summaryrefslogtreecommitdiff
path: root/chromium/content/browser
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2018-12-10 16:19:40 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2018-12-10 16:01:50 +0000
commit51f6c2793adab2d864b3d2b360000ef8db1d3e92 (patch)
tree835b3b4446b012c75e80177cef9fbe6972cc7dbe /chromium/content/browser
parent6036726eb981b6c4b42047513b9d3f4ac865daac (diff)
downloadqtwebengine-chromium-51f6c2793adab2d864b3d2b360000ef8db1d3e92.tar.gz
BASELINE: Update Chromium to 71.0.3578.93
Change-Id: I6a32086c33670e1b033f8b10e6bf1fd4da1d105d Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Diffstat (limited to 'chromium/content/browser')
-rw-r--r--chromium/content/browser/BUILD.gn73
-rw-r--r--chromium/content/browser/DEPS5
-rw-r--r--chromium/content/browser/accessibility/accessibility_action_browsertest.cc38
-rw-r--r--chromium/content/browser/accessibility/accessibility_event_recorder.cc14
-rw-r--r--chromium/content/browser/accessibility/accessibility_event_recorder.h17
-rw-r--r--chromium/content/browser/accessibility/accessibility_event_recorder_auralinux.cc401
-rw-r--r--chromium/content/browser/accessibility/accessibility_event_recorder_mac.mm25
-rw-r--r--chromium/content/browser/accessibility/accessibility_event_recorder_win.cc83
-rw-r--r--chromium/content/browser/accessibility/accessibility_mode_browsertest.cc2
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter.h6
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter_auralinux.cc192
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter_blink.cc5
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter_browser.cc7
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter_browser.h3
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter_mac.mm134
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter_utils_auralinux.cc238
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter_utils_auralinux.h19
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter_win.cc11
-rw-r--r--chromium/content/browser/accessibility/accessibility_win_browsertest.cc426
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility.cc79
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility.h5
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_android.cc4
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_android.h2
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_auralinux_unittest.cc155
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_cocoa.mm13
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_com_win.cc8
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_mac.h5
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_mac.mm15
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager.cc44
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager.h9
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_android.cc1
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_auralinux.cc82
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_auralinux.h6
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_mac.mm7
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_win.cc42
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_win.h8
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_position.cc6
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_position.h2
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_state_impl.cc10
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_state_impl.h3
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_state_impl_mac.mm2
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_state_impl_win.cc56
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_unittest.cc66
-rw-r--r--chromium/content/browser/accessibility/dump_accessibility_browsertest_base.cc12
-rw-r--r--chromium/content/browser/accessibility/dump_accessibility_browsertest_base.h6
-rw-r--r--chromium/content/browser/accessibility/dump_accessibility_events_browsertest.cc60
-rw-r--r--chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc31
-rw-r--r--chromium/content/browser/android/app_web_message_port.cc2
-rw-r--r--chromium/content/browser/android/app_web_message_port.h2
-rw-r--r--chromium/content/browser/android/background_sync_network_observer_android.cc28
-rw-r--r--chromium/content/browser/android/background_sync_network_observer_android.h15
-rw-r--r--chromium/content/browser/android/content_url_loader_factory.cc261
-rw-r--r--chromium/content/browser/android/content_url_loader_factory.h47
-rw-r--r--chromium/content/browser/android/dialog_overlay_impl.cc39
-rw-r--r--chromium/content/browser/android/dialog_overlay_impl.h19
-rw-r--r--chromium/content/browser/android/gesture_listener_manager.cc2
-rw-r--r--chromium/content/browser/android/ime_adapter_android.cc7
-rw-r--r--chromium/content/browser/android/java/gin_java_bridge_dispatcher_host.h9
-rw-r--r--chromium/content/browser/android/java/gin_java_bridge_message_filter.cc17
-rw-r--r--chromium/content/browser/android/java/gin_java_bridge_message_filter.h11
-rw-r--r--chromium/content/browser/android/java/jni_reflect.cc63
-rw-r--r--chromium/content/browser/android/java/jni_reflect.h55
-rw-r--r--chromium/content/browser/android/scoped_surface_request_manager.cc6
-rw-r--r--chromium/content/browser/android/select_popup.cc2
-rw-r--r--chromium/content/browser/android/synchronous_compositor_host.cc6
-rw-r--r--chromium/content/browser/android/synchronous_compositor_sync_call_bridge.cc8
-rw-r--r--chromium/content/browser/android/synchronous_compositor_sync_call_bridge.h14
-rw-r--r--chromium/content/browser/android/text_suggestion_host_android.cc33
-rw-r--r--chromium/content/browser/android/text_suggestion_host_android.h7
-rw-r--r--chromium/content/browser/android/url_request_content_job.h3
-rw-r--r--chromium/content/browser/android/web_contents_observer_proxy.cc15
-rw-r--r--chromium/content/browser/android/web_contents_observer_proxy.h1
-rw-r--r--chromium/content/browser/appcache/appcache.cc4
-rw-r--r--chromium/content/browser/appcache/appcache_database.cc126
-rw-r--r--chromium/content/browser/appcache/appcache_database.h9
-rw-r--r--chromium/content/browser/appcache/appcache_database_unittest.cc475
-rw-r--r--chromium/content/browser/appcache/appcache_disk_cache.cc239
-rw-r--r--chromium/content/browser/appcache/appcache_disk_cache.h115
-rw-r--r--chromium/content/browser/appcache/appcache_disk_cache_unittest.cc14
-rw-r--r--chromium/content/browser/appcache/appcache_frontend_proxy.cc6
-rw-r--r--chromium/content/browser/appcache/appcache_group.cc6
-rw-r--r--chromium/content/browser/appcache/appcache_host.cc4
-rw-r--r--chromium/content/browser/appcache/appcache_internals_ui.cc55
-rw-r--r--chromium/content/browser/appcache/appcache_job.cc23
-rw-r--r--chromium/content/browser/appcache/appcache_job.h34
-rw-r--r--chromium/content/browser/appcache/appcache_manifest_parser.cc574
-rw-r--r--chromium/content/browser/appcache/appcache_manifest_parser.h11
-rw-r--r--chromium/content/browser/appcache/appcache_manifest_parser_unittest.cc3
-rw-r--r--chromium/content/browser/appcache/appcache_navigation_handle.cc6
-rw-r--r--chromium/content/browser/appcache/appcache_request_handler.cc5
-rw-r--r--chromium/content/browser/appcache/appcache_request_handler.h3
-rw-r--r--chromium/content/browser/appcache/appcache_request_handler_unittest.cc5
-rw-r--r--chromium/content/browser/appcache/appcache_response.cc43
-rw-r--r--chromium/content/browser/appcache/appcache_response.h65
-rw-r--r--chromium/content/browser/appcache/appcache_response_unittest.cc74
-rw-r--r--chromium/content/browser/appcache/appcache_service_impl.cc6
-rw-r--r--chromium/content/browser/appcache/appcache_service_unittest.cc3
-rw-r--r--chromium/content/browser/appcache/appcache_storage.cc2
-rw-r--r--chromium/content/browser/appcache/appcache_storage.h11
-rw-r--r--chromium/content/browser/appcache/appcache_storage_impl.cc91
-rw-r--r--chromium/content/browser/appcache/appcache_storage_impl.h10
-rw-r--r--chromium/content/browser/appcache/appcache_storage_impl_unittest.cc2
-rw-r--r--chromium/content/browser/appcache/appcache_update_job.cc36
-rw-r--r--chromium/content/browser/appcache/appcache_update_job.h3
-rw-r--r--chromium/content/browser/appcache/appcache_update_job_unittest.cc173
-rw-r--r--chromium/content/browser/appcache/appcache_update_url_fetcher.cc2
-rw-r--r--chromium/content/browser/appcache/appcache_update_url_request.cc2
-rw-r--r--chromium/content/browser/appcache/appcache_url_loader_job.cc16
-rw-r--r--chromium/content/browser/appcache/appcache_url_request_job.cc20
-rw-r--r--chromium/content/browser/appcache/appcache_url_request_job_unittest.cc21
-rw-r--r--chromium/content/browser/appcache/chrome_appcache_service_unittest.cc6
-rw-r--r--chromium/content/browser/appcache/mock_appcache_storage.cc32
-rw-r--r--chromium/content/browser/appcache/mock_appcache_storage.h9
-rw-r--r--chromium/content/browser/background_fetch/background_fetch.proto6
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_context.cc299
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_context.h58
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_cross_origin_filter.cc2
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_data_manager.cc32
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_data_manager.h16
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_data_manager_observer.h8
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_data_manager_unittest.cc398
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_delegate_proxy.cc97
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_delegate_proxy.h8
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_delegate_proxy_unittest.cc38
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_embedded_worker_test_helper.cc16
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_event_dispatcher_unittest.cc26
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_job_controller.cc110
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_job_controller.h45
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_job_controller_unittest.cc103
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_metrics.cc50
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_metrics.h17
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_registration_notifier.cc38
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_registration_notifier.h22
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_registration_notifier_unittest.cc113
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_request_info.cc25
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_request_info.h12
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_scheduler.cc50
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_scheduler.h21
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_scheduler_unittest.cc22
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_service_impl.cc17
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_service_impl.h1
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_service_unittest.cc21
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_test_base.cc15
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_test_base.h6
-rw-r--r--chromium/content/browser/background_fetch/mock_background_fetch_delegate.cc22
-rw-r--r--chromium/content/browser/background_fetch/storage/create_metadata_task.cc132
-rw-r--r--chromium/content/browser/background_fetch/storage/create_metadata_task.h4
-rw-r--r--chromium/content/browser/background_fetch/storage/database_helpers.cc14
-rw-r--r--chromium/content/browser/background_fetch/storage/database_helpers.h3
-rw-r--r--chromium/content/browser/background_fetch/storage/get_settled_fetches_task.cc28
-rw-r--r--chromium/content/browser/background_fetch/storage/get_settled_fetches_task.h5
-rw-r--r--chromium/content/browser/background_fetch/storage/mark_registration_for_deletion_task.cc10
-rw-r--r--chromium/content/browser/background_fetch/storage/mark_request_complete_task.cc38
-rw-r--r--chromium/content/browser/background_fetch/storage/mark_request_complete_task.h7
-rw-r--r--chromium/content/browser/background_fetch/storage/start_next_pending_request_task.cc61
-rw-r--r--chromium/content/browser/background_fetch/storage/start_next_pending_request_task.h11
-rw-r--r--chromium/content/browser/background_sync/background_sync_browsertest.cc14
-rw-r--r--chromium/content/browser/background_sync/background_sync_context.cc16
-rw-r--r--chromium/content/browser/background_sync/background_sync_manager.cc26
-rw-r--r--chromium/content/browser/background_sync/background_sync_manager_unittest.cc48
-rw-r--r--chromium/content/browser/background_sync/background_sync_network_observer.cc81
-rw-r--r--chromium/content/browser/background_sync/background_sync_network_observer.h54
-rw-r--r--chromium/content/browser/background_sync/background_sync_network_observer_unittest.cc84
-rw-r--r--chromium/content/browser/background_sync/background_sync_service_impl_unittest.cc13
-rw-r--r--chromium/content/browser/bad_message.cc8
-rw-r--r--chromium/content/browser/blob_storage/blob_registry_wrapper.cc6
-rw-r--r--chromium/content/browser/blob_storage/blob_storage_browsertest.cc13
-rw-r--r--chromium/content/browser/blob_storage/blob_url_browsertest.cc10
-rw-r--r--chromium/content/browser/blob_storage/blob_url_unittest.cc5
-rw-r--r--chromium/content/browser/blob_storage/chrome_blob_storage_context.cc20
-rw-r--r--chromium/content/browser/bluetooth/bluetooth_allowed_devices_map.cc2
-rw-r--r--chromium/content/browser/bluetooth/bluetooth_device_chooser_controller.cc4
-rw-r--r--chromium/content/browser/browser_associated_interface_unittest.cc7
-rw-r--r--chromium/content/browser/browser_child_process_host_impl.cc33
-rw-r--r--chromium/content/browser/browser_context.cc114
-rw-r--r--chromium/content/browser/browser_ipc_logging.cc7
-rw-r--r--chromium/content/browser/browser_main_loop.cc190
-rw-r--r--chromium/content/browser/browser_main_loop.h16
-rw-r--r--chromium/content/browser/browser_main_loop_unittest.cc11
-rw-r--r--chromium/content/browser/browser_main_runner_impl.cc8
-rw-r--r--chromium/content/browser/browser_main_runner_impl.h7
-rw-r--r--chromium/content/browser/browser_plugin/browser_plugin_guest.cc30
-rw-r--r--chromium/content/browser/browser_plugin/browser_plugin_guest.h6
-rw-r--r--chromium/content/browser/browser_process_sub_thread.cc3
-rw-r--r--chromium/content/browser/browser_thread_impl.cc242
-rw-r--r--chromium/content/browser/browser_thread_impl.h9
-rw-r--r--chromium/content/browser/browser_thread_unittest.cc49
-rw-r--r--chromium/content/browser/browsing_data/OWNERS1
-rw-r--r--chromium/content/browser/browsing_data/browsing_data_filter_builder_impl.cc2
-rw-r--r--chromium/content/browser/browsing_data/browsing_data_remover_impl.cc6
-rw-r--r--chromium/content/browser/browsing_data/browsing_data_remover_impl_unittest.cc10
-rw-r--r--chromium/content/browser/browsing_data/clear_site_data_handler.cc2
-rw-r--r--chromium/content/browser/browsing_data/clear_site_data_handler_browsertest.cc21
-rw-r--r--chromium/content/browser/browsing_data/clear_site_data_throttle.cc14
-rw-r--r--chromium/content/browser/browsing_data/clear_site_data_throttle_unittest.cc5
-rw-r--r--chromium/content/browser/browsing_data/conditional_cache_deletion_helper_browsertest.cc10
-rw-r--r--chromium/content/browser/browsing_data/storage_partition_http_cache_data_remover.cc53
-rw-r--r--chromium/content/browser/browsing_data/storage_partition_http_cache_data_remover.h3
-rw-r--r--chromium/content/browser/browsing_instance.cc31
-rw-r--r--chromium/content/browser/browsing_instance.h8
-rw-r--r--chromium/content/browser/byte_stream.h4
-rw-r--r--chromium/content/browser/byte_stream_unittest.cc66
-rw-r--r--chromium/content/browser/cache_storage/cache_storage.cc16
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_blob_to_disk_cache.cc14
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_blob_to_disk_cache.h1
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_blob_to_disk_cache_unittest.cc5
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_cache.cc168
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_cache.h10
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_cache_unittest.cc108
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_context_impl.cc13
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_dispatcher_host.cc9
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_histogram_utils.cc14
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_histogram_utils.h (renamed from chromium/content/browser/cache_storage/cache_storage_histogram_macros.h)37
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_manager.cc2
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_manager_unittest.cc4
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_operation.cc2
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_scheduler.cc2
-rw-r--r--chromium/content/browser/child_process_launcher_helper.cc5
-rw-r--r--chromium/content/browser/child_process_launcher_helper_android.cc6
-rw-r--r--chromium/content/browser/child_process_launcher_helper_mac.cc40
-rw-r--r--chromium/content/browser/child_process_security_policy_browsertest.cc33
-rw-r--r--chromium/content/browser/child_process_security_policy_impl.cc211
-rw-r--r--chromium/content/browser/child_process_security_policy_impl.h57
-rw-r--r--chromium/content/browser/child_process_security_policy_unittest.cc86
-rw-r--r--chromium/content/browser/cocoa/system_hotkey_helper_mac.mm9
-rw-r--r--chromium/content/browser/code_cache/generated_code_cache.cc76
-rw-r--r--chromium/content/browser/code_cache/generated_code_cache.h23
-rw-r--r--chromium/content/browser/code_cache/generated_code_cache_context.cc23
-rw-r--r--chromium/content/browser/code_cache/generated_code_cache_context.h9
-rw-r--r--chromium/content/browser/code_cache/generated_code_cache_unittest.cc66
-rw-r--r--chromium/content/browser/compositor/gpu_process_transport_factory.cc46
-rw-r--r--chromium/content/browser/compositor/gpu_process_transport_factory.h2
-rw-r--r--chromium/content/browser/compositor/reflector_impl_unittest.cc7
-rw-r--r--chromium/content/browser/compositor/viz_process_transport_factory.cc26
-rw-r--r--chromium/content/browser/compositor/viz_process_transport_factory.h4
-rw-r--r--chromium/content/browser/content_service_browsertest.cc96
-rw-r--r--chromium/content/browser/content_service_delegate_impl.cc59
-rw-r--r--chromium/content/browser/content_service_delegate_impl.h1
-rw-r--r--chromium/content/browser/cookie_store/cookie_store_context.cc16
-rw-r--r--chromium/content/browser/cookie_store/cookie_store_manager_unittest.cc2
-rw-r--r--chromium/content/browser/devtools/browser_devtools_agent_host.cc4
-rw-r--r--chromium/content/browser/devtools/devtools_agent_host_impl.cc45
-rw-r--r--chromium/content/browser/devtools/devtools_agent_host_impl.h28
-rw-r--r--chromium/content/browser/devtools/devtools_http_handler.cc35
-rw-r--r--chromium/content/browser/devtools/devtools_http_handler_unittest.cc7
-rw-r--r--chromium/content/browser/devtools/devtools_interceptor_controller.cc22
-rw-r--r--chromium/content/browser/devtools/devtools_network_interceptor.cc9
-rw-r--r--chromium/content/browser/devtools/devtools_network_interceptor.h5
-rw-r--r--chromium/content/browser/devtools/devtools_pipe_handler.cc9
-rw-r--r--chromium/content/browser/devtools/devtools_renderer_channel.cc57
-rw-r--r--chromium/content/browser/devtools/devtools_renderer_channel.h55
-rw-r--r--chromium/content/browser/devtools/devtools_session.cc30
-rw-r--r--chromium/content/browser/devtools/devtools_session.h44
-rw-r--r--chromium/content/browser/devtools/devtools_stream_blob.cc39
-rw-r--r--chromium/content/browser/devtools/devtools_stream_file.cc9
-rw-r--r--chromium/content/browser/devtools/devtools_url_interceptor_request_job.cc86
-rw-r--r--chromium/content/browser/devtools/devtools_url_interceptor_request_job.h1
-rw-r--r--chromium/content/browser/devtools/devtools_url_loader_interceptor.cc97
-rw-r--r--chromium/content/browser/devtools/devtools_url_request_interceptor.cc22
-rw-r--r--chromium/content/browser/devtools/devtools_video_consumer.cc4
-rw-r--r--chromium/content/browser/devtools/devtools_video_consumer_unittest.cc9
-rw-r--r--chromium/content/browser/devtools/forwarding_agent_host.cc3
-rw-r--r--chromium/content/browser/devtools/forwarding_agent_host.h2
-rw-r--r--chromium/content/browser/devtools/protocol/browser_handler.cc5
-rw-r--r--chromium/content/browser/devtools/protocol/browser_handler.h2
-rw-r--r--chromium/content/browser/devtools/protocol/devtools_download_manager_delegate.cc7
-rw-r--r--chromium/content/browser/devtools/protocol/devtools_protocol_browsertest.cc43
-rw-r--r--chromium/content/browser/devtools/protocol/devtools_protocol_test_support.cc2
-rw-r--r--chromium/content/browser/devtools/protocol/devtools_protocol_test_support.h12
-rw-r--r--chromium/content/browser/devtools/protocol/emulation_handler.cc26
-rw-r--r--chromium/content/browser/devtools/protocol/input_handler.cc5
-rw-r--r--chromium/content/browser/devtools/protocol/inspector_handler.cc6
-rw-r--r--chromium/content/browser/devtools/protocol/memory_handler.cc2
-rw-r--r--chromium/content/browser/devtools/protocol/network_handler.cc129
-rw-r--r--chromium/content/browser/devtools/protocol/page_handler.cc39
-rw-r--r--chromium/content/browser/devtools/protocol/page_handler.h3
-rw-r--r--chromium/content/browser/devtools/protocol/security_handler.cc5
-rw-r--r--chromium/content/browser/devtools/protocol/service_worker_handler.cc24
-rw-r--r--chromium/content/browser/devtools/protocol/storage_handler.cc44
-rw-r--r--chromium/content/browser/devtools/protocol/system_info_handler.cc10
-rw-r--r--chromium/content/browser/devtools/protocol/target_handler.cc112
-rw-r--r--chromium/content/browser/devtools/protocol/target_handler.h14
-rw-r--r--chromium/content/browser/devtools/protocol/tethering_handler.cc28
-rw-r--r--chromium/content/browser/devtools/protocol/tracing_handler.cc38
-rw-r--r--chromium/content/browser/devtools/protocol_config.json2
-rw-r--r--chromium/content/browser/devtools/render_frame_devtools_agent_host.cc99
-rw-r--r--chromium/content/browser/devtools/render_frame_devtools_agent_host.h8
-rw-r--r--chromium/content/browser/devtools/service_worker_devtools_agent_host.cc60
-rw-r--r--chromium/content/browser/devtools/service_worker_devtools_agent_host.h13
-rw-r--r--chromium/content/browser/devtools/service_worker_devtools_manager.cc10
-rw-r--r--chromium/content/browser/devtools/service_worker_devtools_manager.h1
-rw-r--r--chromium/content/browser/devtools/shared_worker_devtools_agent_host.cc41
-rw-r--r--chromium/content/browser/devtools/shared_worker_devtools_agent_host.h14
-rw-r--r--chromium/content/browser/do_not_track_browsertest.cc165
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_area_unittest.cc4
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_context_impl.cc6
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_context_impl_unittest.cc4
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_context_wrapper.cc28
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_context_wrapper.h7
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_database.cc2
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_database_unittest.cc2
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_namespace.cc6
-rw-r--r--chromium/content/browser/dom_storage/session_storage_context_mojo.cc3
-rw-r--r--chromium/content/browser/dom_storage/session_storage_database.cc4
-rw-r--r--chromium/content/browser/dom_storage/session_storage_database.h9
-rw-r--r--chromium/content/browser/dom_storage/session_storage_database_unittest.cc3
-rw-r--r--chromium/content/browser/dom_storage/session_storage_metadata.cc8
-rw-r--r--chromium/content/browser/dom_storage/session_storage_namespace_impl.cc12
-rw-r--r--chromium/content/browser/dom_storage/session_storage_namespace_impl_mojo_unittest.cc5
-rw-r--r--chromium/content/browser/dom_storage/storage_area_impl.cc4
-rw-r--r--chromium/content/browser/download/download_browsertest.cc100
-rw-r--r--chromium/content/browser/download/download_manager_impl.cc43
-rw-r--r--chromium/content/browser/download/download_manager_impl_unittest.cc3
-rw-r--r--chromium/content/browser/download/download_request_core.cc9
-rw-r--r--chromium/content/browser/download/download_request_core.h7
-rw-r--r--chromium/content/browser/download/download_request_core_unittest.cc11
-rw-r--r--chromium/content/browser/download/download_request_handle.cc14
-rw-r--r--chromium/content/browser/download/download_request_utils.cc6
-rw-r--r--chromium/content/browser/download/download_resource_handler.cc28
-rw-r--r--chromium/content/browser/download/download_utils.cc11
-rw-r--r--chromium/content/browser/download/download_utils.h10
-rw-r--r--chromium/content/browser/download/drag_download_file.cc16
-rw-r--r--chromium/content/browser/download/drag_download_file_browsertest.cc6
-rw-r--r--chromium/content/browser/download/drag_download_util.cc12
-rw-r--r--chromium/content/browser/download/mhtml_generation_browsertest.cc19
-rw-r--r--chromium/content/browser/download/save_file_manager.cc24
-rw-r--r--chromium/content/browser/download/save_package.cc4
-rw-r--r--chromium/content/browser/download/url_downloader.cc10
-rw-r--r--chromium/content/browser/download/url_downloader_factory.cc5
-rw-r--r--chromium/content/browser/download/url_downloader_factory.h8
-rw-r--r--chromium/content/browser/download/web_ui_download_url_loader_factory_getter.cc4
-rw-r--r--chromium/content/browser/file_url_loader_factory.cc40
-rw-r--r--chromium/content/browser/fileapi/README.md23
-rw-r--r--chromium/content/browser/fileapi/browser_file_system_helper.cc5
-rw-r--r--chromium/content/browser/fileapi/file_system_browsertest.cc6
-rw-r--r--chromium/content/browser/fileapi/file_system_chooser.cc164
-rw-r--r--chromium/content/browser/fileapi/file_system_chooser.h17
-rw-r--r--chromium/content/browser/fileapi/file_system_chooser_browsertest.cc195
-rw-r--r--chromium/content/browser/fileapi/file_system_chooser_test_helpers.cc126
-rw-r--r--chromium/content/browser/fileapi/file_system_chooser_test_helpers.h60
-rw-r--r--chromium/content/browser/fileapi/file_system_chooser_unittest.cc168
-rw-r--r--chromium/content/browser/fileapi/file_system_manager_impl.cc31
-rw-r--r--chromium/content/browser/fileapi/file_system_manager_impl.h13
-rw-r--r--chromium/content/browser/fileapi/file_system_url_loader_factory.cc6
-rw-r--r--chromium/content/browser/fileapi/file_system_url_loader_factory_browsertest.cc6
-rw-r--r--chromium/content/browser/find_request_manager.cc86
-rw-r--r--chromium/content/browser/find_request_manager.h15
-rw-r--r--chromium/content/browser/find_request_manager_browsertest.cc166
-rw-r--r--chromium/content/browser/font_unique_name_lookup/font_unique_name_browsertest.cc58
-rw-r--r--chromium/content/browser/font_unique_name_lookup/font_unique_name_lookup_service.cc10
-rw-r--r--chromium/content/browser/frame_host/cross_process_frame_connector.cc136
-rw-r--r--chromium/content/browser/frame_host/cross_process_frame_connector.h38
-rw-r--r--chromium/content/browser/frame_host/debug_urls.cc15
-rw-r--r--chromium/content/browser/frame_host/form_submission_throttle.cc14
-rw-r--r--chromium/content/browser/frame_host/form_submission_throttle.h2
-rw-r--r--chromium/content/browser/frame_host/frame_tree.cc27
-rw-r--r--chromium/content/browser/frame_host/frame_tree.h17
-rw-r--r--chromium/content/browser/frame_host/frame_tree_browsertest.cc24
-rw-r--r--chromium/content/browser/frame_host/frame_tree_node.cc96
-rw-r--r--chromium/content/browser/frame_host/frame_tree_node.h34
-rw-r--r--chromium/content/browser/frame_host/interstitial_page_impl.cc12
-rw-r--r--chromium/content/browser/frame_host/interstitial_page_impl.h3
-rw-r--r--chromium/content/browser/frame_host/interstitial_page_navigator_impl.cc10
-rw-r--r--chromium/content/browser/frame_host/interstitial_page_navigator_impl.h5
-rw-r--r--chromium/content/browser/frame_host/keep_alive_handle_factory.cc6
-rw-r--r--chromium/content/browser/frame_host/mixed_content_navigation_throttle.cc25
-rw-r--r--chromium/content/browser/frame_host/mixed_content_navigation_throttle.h4
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_impl.cc38
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_impl.h5
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_impl_browsertest.cc100
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_impl_unittest.cc46
-rw-r--r--chromium/content/browser/frame_host/navigation_entry_impl.cc13
-rw-r--r--chromium/content/browser/frame_host/navigation_entry_impl.h3
-rw-r--r--chromium/content/browser/frame_host/navigation_handle_impl.cc132
-rw-r--r--chromium/content/browser/frame_host/navigation_handle_impl.h36
-rw-r--r--chromium/content/browser/frame_host/navigation_handle_impl_browsertest.cc53
-rw-r--r--chromium/content/browser/frame_host/navigation_handle_impl_unittest.cc16
-rw-r--r--chromium/content/browser/frame_host/navigation_request.cc163
-rw-r--r--chromium/content/browser/frame_host/navigation_request.h18
-rw-r--r--chromium/content/browser/frame_host/navigator.cc3
-rw-r--r--chromium/content/browser/frame_host/navigator.h10
-rw-r--r--chromium/content/browser/frame_host/navigator_impl.cc57
-rw-r--r--chromium/content/browser/frame_host/navigator_impl.h8
-rw-r--r--chromium/content/browser/frame_host/navigator_impl_unittest.cc2
-rw-r--r--chromium/content/browser/frame_host/origin_policy_throttle.cc62
-rw-r--r--chromium/content/browser/frame_host/origin_policy_throttle.h17
-rw-r--r--chromium/content/browser/frame_host/origin_policy_throttle_unittest.cc4
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_delegate.cc8
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_delegate.h21
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_factory.cc11
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_factory.h3
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_impl.cc602
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_impl.h121
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_impl_browsertest.cc118
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_manager.cc141
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_manager.h22
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_manager_browsertest.cc25
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_manager_unittest.cc12
-rw-r--r--chromium/content/browser/frame_host/render_frame_message_filter.cc134
-rw-r--r--chromium/content/browser/frame_host/render_frame_message_filter.h6
-rw-r--r--chromium/content/browser/frame_host/render_frame_message_filter_browsertest.cc6
-rw-r--r--chromium/content/browser/frame_host/render_frame_proxy_host.cc8
-rw-r--r--chromium/content/browser/frame_host/render_widget_host_view_guest.cc17
-rw-r--r--chromium/content/browser/frame_host/render_widget_host_view_guest.h4
-rw-r--r--chromium/content/browser/frame_host/render_widget_host_view_guest_unittest.cc51
-rw-r--r--chromium/content/browser/frame_host/webui_navigation_browsertest.cc49
-rw-r--r--chromium/content/browser/gpu/browser_gpu_channel_host_factory.cc37
-rw-r--r--chromium/content/browser/gpu/browser_gpu_channel_host_factory.h5
-rw-r--r--chromium/content/browser/gpu/browser_gpu_client_delegate.cc59
-rw-r--r--chromium/content/browser/gpu/browser_gpu_client_delegate.h5
-rw-r--r--chromium/content/browser/gpu/ca_transaction_gpu_coordinator.cc10
-rw-r--r--chromium/content/browser/gpu/compositor_util.cc10
-rw-r--r--chromium/content/browser/gpu/compositor_util.h3
-rw-r--r--chromium/content/browser/gpu/delegate_to_browser_gpu_service_accelerator_factory.cc16
-rw-r--r--chromium/content/browser/gpu/gpu_data_manager_impl.cc18
-rw-r--r--chromium/content/browser/gpu/gpu_data_manager_impl.h34
-rw-r--r--chromium/content/browser/gpu/gpu_data_manager_impl_private.cc180
-rw-r--r--chromium/content/browser/gpu/gpu_data_manager_impl_private.h32
-rw-r--r--chromium/content/browser/gpu/gpu_data_manager_impl_private_unittest.cc71
-rw-r--r--chromium/content/browser/gpu/gpu_internals_ui.cc9
-rw-r--r--chromium/content/browser/gpu/gpu_ipc_browsertests.cc6
-rw-r--r--chromium/content/browser/gpu/gpu_memory_buffer_manager_singleton.cc8
-rw-r--r--chromium/content/browser/gpu/gpu_process_host.cc222
-rw-r--r--chromium/content/browser/gpu/gpu_process_host.h37
-rw-r--r--chromium/content/browser/gpu/in_process_gpu_thread_browsertests.cc8
-rw-r--r--chromium/content/browser/gpu/video_capture_dependencies.cc (renamed from chromium/content/browser/renderer_host/media/video_capture_dependencies.cc)13
-rw-r--r--chromium/content/browser/gpu/video_capture_dependencies.h (renamed from chromium/content/browser/renderer_host/media/video_capture_dependencies.h)9
-rw-r--r--chromium/content/browser/gpu_interface_provider.cc96
-rw-r--r--chromium/content/browser/gpu_interface_provider.h40
-rw-r--r--chromium/content/browser/histogram_controller.cc14
-rw-r--r--chromium/content/browser/histogram_synchronizer.cc22
-rw-r--r--chromium/content/browser/histogram_synchronizer.h8
-rw-r--r--chromium/content/browser/host_zoom_map_impl.cc10
-rw-r--r--chromium/content/browser/host_zoom_map_impl_unittest.cc9
-rw-r--r--chromium/content/browser/hyphenation/hyphenation_impl.cc18
-rw-r--r--chromium/content/browser/image_capture/image_capture_impl.cc14
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_active_blob_registry.cc6
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_backing_store.cc57
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_backing_store.h19
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_backing_store_unittest.cc33
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_browsertest.cc300
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_callbacks.cc64
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_cleanup_on_io_error_unittest.cc33
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_context_impl.cc57
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_context_impl.h15
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_database_callbacks.cc32
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_dispatcher_host.cc25
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_dispatcher_host.h2
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc42
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_factory.h25
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_factory_impl.cc79
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_factory_impl.h18
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_factory_unittest.cc42
-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.cc17
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_transaction_coordinator.cc4
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_unittest.cc8
-rw-r--r--chromium/content/browser/indexed_db/leveldb/leveldb_database.cc2
-rw-r--r--chromium/content/browser/indexed_db/leveldb/leveldb_transaction.cc2
-rw-r--r--chromium/content/browser/indexed_db/mock_indexed_db_factory.h70
-rw-r--r--chromium/content/browser/initiator_csp_context.cc24
-rw-r--r--chromium/content/browser/initiator_csp_context.h10
-rw-r--r--chromium/content/browser/interface_provider_filtering.cc6
-rw-r--r--chromium/content/browser/isolated_origin_browsertest.cc36
-rw-r--r--chromium/content/browser/isolated_origin_util.cc2
-rw-r--r--chromium/content/browser/loader/cors_file_origin_browsertest.cc175
-rw-r--r--chromium/content/browser/loader/cors_origin_access_list_browsertest.cc285
-rw-r--r--chromium/content/browser/loader/cross_site_document_blocking_browsertest.cc153
-rw-r--r--chromium/content/browser/loader/cross_site_document_resource_handler.cc36
-rw-r--r--chromium/content/browser/loader/cross_site_document_resource_handler_unittest.cc158
-rw-r--r--chromium/content/browser/loader/data_pipe_to_source_stream.cc2
-rw-r--r--chromium/content/browser/loader/data_pipe_to_source_stream_unittest.cc3
-rw-r--r--chromium/content/browser/loader/detachable_resource_handler.cc8
-rw-r--r--chromium/content/browser/loader/intercepting_resource_handler.cc4
-rw-r--r--chromium/content/browser/loader/intercepting_resource_handler.h2
-rw-r--r--chromium/content/browser/loader/loader_browsertest.cc36
-rw-r--r--chromium/content/browser/loader/loader_io_thread_notifier.cc6
-rw-r--r--chromium/content/browser/loader/merkle_integrity_source_stream_unittest.cc2
-rw-r--r--chromium/content/browser/loader/mime_sniffing_resource_handler.cc4
-rw-r--r--chromium/content/browser/loader/mime_sniffing_resource_handler.h17
-rw-r--r--chromium/content/browser/loader/mime_sniffing_resource_handler_unittest.cc17
-rw-r--r--chromium/content/browser/loader/mojo_async_resource_handler.cc3
-rw-r--r--chromium/content/browser/loader/mojo_async_resource_handler_unittest.cc3
-rw-r--r--chromium/content/browser/loader/navigation_loader_interceptor.cc3
-rw-r--r--chromium/content/browser/loader/navigation_loader_interceptor.h8
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_impl.cc337
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_impl_unittest.cc9
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_unittest.cc3
-rw-r--r--chromium/content/browser/loader/prefetch_browsertest.cc39
-rw-r--r--chromium/content/browser/loader/prefetch_url_loader.cc54
-rw-r--r--chromium/content/browser/loader/prefetch_url_loader.h10
-rw-r--r--chromium/content/browser/loader/prefetch_url_loader_service.cc20
-rw-r--r--chromium/content/browser/loader/prefetch_url_loader_service.h17
-rw-r--r--chromium/content/browser/loader/resource_dispatcher_host_impl.cc75
-rw-r--r--chromium/content/browser/loader/resource_dispatcher_host_impl.h14
-rw-r--r--chromium/content/browser/loader/resource_dispatcher_host_unittest.cc169
-rw-r--r--chromium/content/browser/loader/resource_hints_impl.cc109
-rw-r--r--chromium/content/browser/loader/resource_message_filter.cc6
-rw-r--r--chromium/content/browser/loader/resource_message_filter.h6
-rw-r--r--chromium/content/browser/loader/resource_request_info_impl.cc27
-rw-r--r--chromium/content/browser/loader/resource_request_info_impl.h12
-rw-r--r--chromium/content/browser/loader/shared_cors_origin_access_list_impl.cc51
-rw-r--r--chromium/content/browser/loader/shared_cors_origin_access_list_impl.h43
-rw-r--r--chromium/content/browser/loader/stream_writer.cc2
-rw-r--r--chromium/content/browser/loader/test_resource_handler.cc2
-rw-r--r--chromium/content/browser/loader/throttling_resource_handler_unittest.cc8
-rw-r--r--chromium/content/browser/loader/upload_data_stream_builder_unittest.cc8
-rw-r--r--chromium/content/browser/loader/url_loader_factory_impl_unittest.cc7
-rw-r--r--chromium/content/browser/mach_broker_mac.mm6
-rw-r--r--chromium/content/browser/manifest/manifest_icon_downloader.cc10
-rw-r--r--chromium/content/browser/media/android/browser_gpu_video_accelerator_factories.cc210
-rw-r--r--chromium/content/browser/media/android/browser_gpu_video_accelerator_factories.h76
-rw-r--r--chromium/content/browser/media/android/media_player_renderer.cc6
-rw-r--r--chromium/content/browser/media/android/media_resource_getter_impl.cc14
-rw-r--r--chromium/content/browser/media/audio_input_stream_broker.cc92
-rw-r--r--chromium/content/browser/media/audio_input_stream_broker.h6
-rw-r--r--chromium/content/browser/media/audio_input_stream_broker_unittest.cc4
-rw-r--r--chromium/content/browser/media/audio_loopback_stream_broker.cc91
-rw-r--r--chromium/content/browser/media/audio_loopback_stream_broker.h24
-rw-r--r--chromium/content/browser/media/audio_loopback_stream_broker_unittest.cc60
-rw-r--r--chromium/content/browser/media/audio_output_stream_broker.cc116
-rw-r--r--chromium/content/browser/media/audio_output_stream_broker.h15
-rw-r--r--chromium/content/browser/media/audio_stream_broker.cc47
-rw-r--r--chromium/content/browser/media/audio_stream_broker.h78
-rw-r--r--chromium/content/browser/media/audio_stream_monitor.cc14
-rw-r--r--chromium/content/browser/media/capture/audio_mirroring_manager.cc8
-rw-r--r--chromium/content/browser/media/capture/audio_mirroring_manager_unittest.cc13
-rw-r--r--chromium/content/browser/media/capture/aura_window_video_capture_device.cc10
-rw-r--r--chromium/content/browser/media/capture/aura_window_video_capture_device_browsertest.cc14
-rw-r--r--chromium/content/browser/media/capture/desktop_capture_device.cc6
-rw-r--r--chromium/content/browser/media/capture/desktop_capture_device_unittest.cc19
-rw-r--r--chromium/content/browser/media/capture/desktop_streams_registry_impl.cc8
-rw-r--r--chromium/content/browser/media/capture/fake_video_capture_stack.cc2
-rw-r--r--chromium/content/browser/media/capture/frame_sink_video_capture_device.cc18
-rw-r--r--chromium/content/browser/media/capture/frame_sink_video_capture_device_unittest.cc13
-rw-r--r--chromium/content/browser/media/capture/lame_window_capturer_chromeos.cc8
-rw-r--r--chromium/content/browser/media/capture/lame_window_capturer_chromeos.h2
-rw-r--r--chromium/content/browser/media/capture/mouse_cursor_overlay_controller_browsertest.cc7
-rw-r--r--chromium/content/browser/media/capture/screen_capture_device_android_unittest.cc17
-rw-r--r--chromium/content/browser/media/capture/web_contents_audio_input_stream.cc35
-rw-r--r--chromium/content/browser/media/capture/web_contents_audio_input_stream_unittest.cc6
-rw-r--r--chromium/content/browser/media/capture/web_contents_audio_muter.cc14
-rw-r--r--chromium/content/browser/media/capture/web_contents_tracker.cc13
-rw-r--r--chromium/content/browser/media/capture/web_contents_video_capture_device.cc14
-rw-r--r--chromium/content/browser/media/capture/web_contents_video_capture_device_browsertest.cc14
-rw-r--r--chromium/content/browser/media/cdm_storage_impl.cc2
-rw-r--r--chromium/content/browser/media/encrypted_media_browsertest.cc42
-rw-r--r--chromium/content/browser/media/forwarding_audio_stream_factory.cc344
-rw-r--r--chromium/content/browser/media/forwarding_audio_stream_factory.h246
-rw-r--r--chromium/content/browser/media/forwarding_audio_stream_factory_unittest.cc272
-rw-r--r--chromium/content/browser/media/in_process_audio_loopback_stream_creator.cc113
-rw-r--r--chromium/content/browser/media/media_browsertest.cc3
-rw-r--r--chromium/content/browser/media/media_browsertest.h4
-rw-r--r--chromium/content/browser/media/media_color_browsertest.cc5
-rw-r--r--chromium/content/browser/media/media_devices_permission_checker.cc10
-rw-r--r--chromium/content/browser/media/media_devices_util.cc6
-rw-r--r--chromium/content/browser/media/media_internals.cc171
-rw-r--r--chromium/content/browser/media/media_internals.h24
-rw-r--r--chromium/content/browser/media/media_internals_proxy.cc14
-rw-r--r--chromium/content/browser/media/media_internals_unittest.cc138
-rw-r--r--chromium/content/browser/media/media_source_browsertest.cc12
-rw-r--r--chromium/content/browser/media/media_suspend_browsertest.cc6
-rw-r--r--chromium/content/browser/media/media_web_contents_observer.cc21
-rw-r--r--chromium/content/browser/media/media_web_contents_observer.h6
-rw-r--r--chromium/content/browser/media/midi_host_unittest.cc7
-rw-r--r--chromium/content/browser/media/session/audio_focus_delegate.h23
-rw-r--r--chromium/content/browser/media/session/audio_focus_delegate_android.cc13
-rw-r--r--chromium/content/browser/media/session/audio_focus_delegate_android.h9
-rw-r--r--chromium/content/browser/media/session/audio_focus_delegate_default.cc131
-rw-r--r--chromium/content/browser/media/session/audio_focus_delegate_default_browsertest.cc162
-rw-r--r--chromium/content/browser/media/session/audio_focus_manager.cc173
-rw-r--r--chromium/content/browser/media/session/audio_focus_manager.h76
-rw-r--r--chromium/content/browser/media/session/audio_focus_manager_unittest.cc550
-rw-r--r--chromium/content/browser/media/session/audio_focus_observer.cc43
-rw-r--r--chromium/content/browser/media/session/audio_focus_observer.h9
-rw-r--r--chromium/content/browser/media/session/media_session_android.cc6
-rw-r--r--chromium/content/browser/media/session/media_session_browsertest.cc18
-rw-r--r--chromium/content/browser/media/session/media_session_controllers_manager_unittest.cc5
-rw-r--r--chromium/content/browser/media/session/media_session_impl.cc269
-rw-r--r--chromium/content/browser/media/session/media_session_impl.h145
-rw-r--r--chromium/content/browser/media/session/media_session_impl_browsertest.cc624
-rw-r--r--chromium/content/browser/media/session/media_session_impl_uma_unittest.cc22
-rw-r--r--chromium/content/browser/media/session/media_session_impl_unittest.cc427
-rw-r--r--chromium/content/browser/media/webaudio/audio_context_manager_browsertest.cc65
-rw-r--r--chromium/content/browser/media/webaudio/audio_context_manager_impl.cc60
-rw-r--r--chromium/content/browser/media/webaudio/audio_context_manager_impl.h22
-rw-r--r--chromium/content/browser/media/webaudio/audio_context_manager_impl_unittest.cc102
-rw-r--r--chromium/content/browser/memory/memory_coordinator_impl_browsertest.cc6
-rw-r--r--chromium/content/browser/memory/memory_monitor_android.cc25
-rw-r--r--chromium/content/browser/memory/memory_monitor_android.h4
-rw-r--r--chromium/content/browser/memory/memory_monitor_win.cc6
-rw-r--r--chromium/content/browser/message_port_provider.cc2
-rw-r--r--chromium/content/browser/mojo_sandbox_browsertest.cc10
-rw-r--r--chromium/content/browser/navigation_browsertest.cc (renamed from chromium/content/browser/browser_side_navigation_browsertest.cc)252
-rw-r--r--chromium/content/browser/net/network_quality_observer_impl.cc179
-rw-r--r--chromium/content/browser/net/network_quality_observer_impl.h36
-rw-r--r--chromium/content/browser/net/network_quality_observer_impl_unittest.cc23
-rw-r--r--chromium/content/browser/net/quota_policy_cookie_store.cc5
-rw-r--r--chromium/content/browser/net_info_browsertest.cc202
-rw-r--r--chromium/content/browser/network_service_browsertest.cc116
-rw-r--r--chromium/content/browser/network_service_client.cc105
-rw-r--r--chromium/content/browser/network_service_client.h15
-rw-r--r--chromium/content/browser/network_service_instance.cc131
-rw-r--r--chromium/content/browser/network_service_restart_browsertest.cc394
-rw-r--r--chromium/content/browser/notification_service_impl.cc3
-rw-r--r--chromium/content/browser/notifications/blink_notification_service_impl.cc83
-rw-r--r--chromium/content/browser/notifications/blink_notification_service_impl.h32
-rw-r--r--chromium/content/browser/notifications/blink_notification_service_impl_unittest.cc196
-rw-r--r--chromium/content/browser/notifications/notification_database.cc10
-rw-r--r--chromium/content/browser/notifications/notification_database_data.proto6
-rw-r--r--chromium/content/browser/notifications/notification_database_data_conversions.cc32
-rw-r--r--chromium/content/browser/notifications/notification_database_data_unittest.cc38
-rw-r--r--chromium/content/browser/notifications/notification_database_unittest.cc8
-rw-r--r--chromium/content/browser/notifications/notification_event_dispatcher_impl.cc20
-rw-r--r--chromium/content/browser/notifications/notification_id_generator.cc2
-rw-r--r--chromium/content/browser/notifications/platform_notification_context_impl.cc59
-rw-r--r--chromium/content/browser/notifications/platform_notification_context_unittest.cc6
-rw-r--r--chromium/content/browser/ns_view_bridge_factory_host.mm51
-rw-r--r--chromium/content/browser/ns_view_bridge_factory_impl.mm63
-rw-r--r--chromium/content/browser/oop_browsertest.cc10
-rw-r--r--chromium/content/browser/payments/payment_app_content_unittest_base.cc5
-rw-r--r--chromium/content/browser/payments/payment_app_context_impl.cc14
-rw-r--r--chromium/content/browser/payments/payment_app_info_fetcher.cc13
-rw-r--r--chromium/content/browser/payments/payment_app_installer.cc30
-rw-r--r--chromium/content/browser/payments/payment_app_provider_impl.cc70
-rw-r--r--chromium/content/browser/payments/payment_instrument_icon_fetcher.cc19
-rw-r--r--chromium/content/browser/permissions/permission_service_impl.cc3
-rw-r--r--chromium/content/browser/picture_in_picture/picture_in_picture_window_controller_impl.cc28
-rw-r--r--chromium/content/browser/picture_in_picture/picture_in_picture_window_controller_impl.h5
-rw-r--r--chromium/content/browser/plugin_data_remover_impl.cc14
-rw-r--r--chromium/content/browser/plugin_private_storage_helper.cc17
-rw-r--r--chromium/content/browser/plugin_service_impl.cc10
-rw-r--r--chromium/content/browser/plugin_service_impl_browsertest.cc6
-rw-r--r--chromium/content/browser/pointer_lock_browsertest.cc49
-rw-r--r--chromium/content/browser/portal/portal.cc32
-rw-r--r--chromium/content/browser/portal/portal.h2
-rw-r--r--chromium/content/browser/portal/portal_browsertest.cc139
-rw-r--r--chromium/content/browser/power_monitor_browsertest.cc10
-rw-r--r--chromium/content/browser/ppapi_plugin_process_host.cc30
-rw-r--r--chromium/content/browser/presentation/presentation_service_impl_unittest.cc6
-rw-r--r--chromium/content/browser/process_internals/BUILD.gn4
-rw-r--r--chromium/content/browser/process_internals/process_internals.mojom35
-rw-r--r--chromium/content/browser/process_internals/process_internals_handler_impl.cc64
-rw-r--r--chromium/content/browser/process_internals/process_internals_handler_impl.h3
-rw-r--r--chromium/content/browser/process_internals/process_internals_ui.cc14
-rw-r--r--chromium/content/browser/process_internals/process_internals_ui.h5
-rw-r--r--chromium/content/browser/push_messaging/push_messaging_manager.cc60
-rw-r--r--chromium/content/browser/push_messaging/push_messaging_router.cc10
-rw-r--r--chromium/content/browser/quota_dispatcher_host.cc20
-rw-r--r--chromium/content/browser/renderer_host/browser_compositor_view_mac.h1
-rw-r--r--chromium/content/browser/renderer_host/browser_compositor_view_mac.mm4
-rw-r--r--chromium/content/browser/renderer_host/clipboard_host_impl.cc22
-rw-r--r--chromium/content/browser/renderer_host/clipboard_host_impl.h6
-rw-r--r--chromium/content/browser/renderer_host/clipboard_host_impl_unittest.cc65
-rw-r--r--chromium/content/browser/renderer_host/code_cache_host_impl.cc239
-rw-r--r--chromium/content/browser/renderer_host/code_cache_host_impl.h104
-rw-r--r--chromium/content/browser/renderer_host/compositor_impl_android.cc212
-rw-r--r--chromium/content/browser/renderer_host/compositor_impl_android.h18
-rw-r--r--chromium/content/browser/renderer_host/compositor_impl_android_browsertest.cc2
-rw-r--r--chromium/content/browser/renderer_host/delegated_frame_host.cc124
-rw-r--r--chromium/content/browser/renderer_host/delegated_frame_host.h17
-rw-r--r--chromium/content/browser/renderer_host/delegated_frame_host_client_aura.cc4
-rw-r--r--chromium/content/browser/renderer_host/delegated_frame_host_client_aura.h1
-rw-r--r--chromium/content/browser/renderer_host/dwrite_font_proxy_message_filter_win_unittest.cc22
-rw-r--r--chromium/content/browser/renderer_host/embedded_frame_sink_provider_impl_unittest.cc4
-rw-r--r--chromium/content/browser/renderer_host/hit_test_debug_key_event_observer.cc76
-rw-r--r--chromium/content/browser/renderer_host/hit_test_debug_key_event_observer.h40
-rw-r--r--chromium/content/browser/renderer_host/input/OWNERS1
-rw-r--r--chromium/content/browser/renderer_host/input/autoscroll_browsertest.cc163
-rw-r--r--chromium/content/browser/renderer_host/input/compositor_event_ack_browsertest.cc22
-rw-r--r--chromium/content/browser/renderer_host/input/fling_browsertest.cc32
-rw-r--r--chromium/content/browser/renderer_host/input/fling_controller.cc9
-rw-r--r--chromium/content/browser/renderer_host/input/fling_controller.h5
-rw-r--r--chromium/content/browser/renderer_host/input/fling_controller_unittest.cc173
-rw-r--r--chromium/content/browser/renderer_host/input/input_router_impl.cc42
-rw-r--r--chromium/content/browser/renderer_host/input/input_router_impl.h3
-rw-r--r--chromium/content/browser/renderer_host/input/input_router_impl_unittest.cc97
-rw-r--r--chromium/content/browser/renderer_host/input/main_thread_event_queue_browsertest.cc24
-rw-r--r--chromium/content/browser/renderer_host/input/mouse_latency_browsertest.cc3
-rw-r--r--chromium/content/browser/renderer_host/input/mouse_wheel_event_queue.cc21
-rw-r--r--chromium/content/browser/renderer_host/input/passthrough_touch_event_queue_unittest.cc5
-rw-r--r--chromium/content/browser/renderer_host/input/scroll_latency_browsertest.cc3
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_gesture.cc4
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_gesture.h6
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_gesture_controller.cc9
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_gesture_controller.h2
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc65
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_mouse_driver.cc14
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_pointer_action.cc16
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_pointer_action.h1
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_pointer_action_unittest.cc123
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_tap_gesture.cc4
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_tap_gesture.h1
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_touch_driver.cc53
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_touch_driver.h6
-rw-r--r--chromium/content/browser/renderer_host/input/touch_action_browsertest.cc84
-rw-r--r--chromium/content/browser/renderer_host/input/touch_action_filter.cc88
-rw-r--r--chromium/content/browser/renderer_host/input/touch_action_filter.h13
-rw-r--r--chromium/content/browser/renderer_host/input/touch_action_filter_unittest.cc114
-rw-r--r--chromium/content/browser/renderer_host/input/touch_emulator.cc8
-rw-r--r--chromium/content/browser/renderer_host/input/touch_emulator.h9
-rw-r--r--chromium/content/browser/renderer_host/input/touch_input_browsertest.cc9
-rw-r--r--chromium/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc106
-rw-r--r--chromium/content/browser/renderer_host/input/touch_selection_controller_client_child_frame.cc8
-rw-r--r--chromium/content/browser/renderer_host/input/touch_selection_controller_client_manager_android.cc51
-rw-r--r--chromium/content/browser/renderer_host/input/touch_selection_controller_client_manager_android.h3
-rw-r--r--chromium/content/browser/renderer_host/input/web_input_event_builders_mac_unittest.mm4
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_delegate_impl.cc24
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_device_manager.cc21
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_stream_handle_unittest.cc4
-rw-r--r--chromium/content/browser/renderer_host/media/audio_output_authorization_handler.cc10
-rw-r--r--chromium/content/browser/renderer_host/media/audio_output_authorization_handler_unittest.cc59
-rw-r--r--chromium/content/browser/renderer_host/media/audio_output_delegate_impl.cc18
-rw-r--r--chromium/content/browser/renderer_host/media/audio_output_delegate_impl_unittest.cc77
-rw-r--r--chromium/content/browser/renderer_host/media/in_process_video_capture_device_launcher.cc10
-rw-r--r--chromium/content/browser/renderer_host/media/media_capture_devices_impl.cc22
-rw-r--r--chromium/content/browser/renderer_host/media/media_devices_dispatcher_host.cc22
-rw-r--r--chromium/content/browser/renderer_host/media/media_devices_manager.cc25
-rw-r--r--chromium/content/browser/renderer_host/media/media_devices_manager.h2
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_dispatcher_host.cc12
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc2
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_manager.cc88
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_manager_unittest.cc1
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_track_metrics_host.cc4
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_ui_proxy.cc26
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc21
-rw-r--r--chromium/content/browser/renderer_host/media/old_render_frame_audio_input_stream_factory.cc14
-rw-r--r--chromium/content/browser/renderer_host/media/old_render_frame_audio_output_stream_factory.cc6
-rw-r--r--chromium/content/browser/renderer_host/media/peer_connection_tracker_host.cc22
-rw-r--r--chromium/content/browser/renderer_host/media/render_frame_audio_input_stream_factory.cc338
-rw-r--r--chromium/content/browser/renderer_host/media/render_frame_audio_input_stream_factory.h62
-rw-r--r--chromium/content/browser/renderer_host/media/render_frame_audio_input_stream_factory_unittest.cc33
-rw-r--r--chromium/content/browser/renderer_host/media/render_frame_audio_output_stream_factory.cc260
-rw-r--r--chromium/content/browser/renderer_host/media/render_frame_audio_output_stream_factory.h86
-rw-r--r--chromium/content/browser/renderer_host/media/render_frame_audio_output_stream_factory_unittest.cc15
-rw-r--r--chromium/content/browser/renderer_host/media/service_video_capture_device_launcher.cc6
-rw-r--r--chromium/content/browser/renderer_host/media/service_video_capture_device_launcher_unittest.cc47
-rw-r--r--chromium/content/browser/renderer_host/media/service_video_capture_provider.cc15
-rw-r--r--chromium/content/browser/renderer_host/media/service_video_capture_provider_unittest.cc65
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_browsertest.cc18
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_buffer_pool_unittest.cc145
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_controller.cc85
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_controller_event_handler.h1
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_controller_unittest.cc175
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_host.cc19
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_host.h1
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_manager.cc64
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_manager.h18
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_manager_unittest.cc119
-rw-r--r--chromium/content/browser/renderer_host/overscroll_controller.cc10
-rw-r--r--chromium/content/browser/renderer_host/overscroll_controller_unittest.cc216
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.cc3
-rw-r--r--chromium/content/browser/renderer_host/pepper/browser_ppapi_host_impl.cc3
-rw-r--r--chromium/content/browser/renderer_host/pepper/browser_ppapi_host_impl.h7
-rw-r--r--chromium/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.cc14
-rw-r--r--chromium/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.h8
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_file_io_host.cc31
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_file_system_browser_host.cc33
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_host_resolver_message_filter.cc8
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_network_monitor_host.cc39
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_network_monitor_host.h13
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_network_proxy_host.cc6
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_print_settings_manager.cc6
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_proxy_lookup_helper.cc6
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_proxy_lookup_helper_unittest.cc10
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.cc303
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.h62
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.cc1434
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.h263
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.cc12
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_vpn_provider_message_filter_chromeos.cc4
-rw-r--r--chromium/content/browser/renderer_host/pepper/quota_reservation.cc17
-rw-r--r--chromium/content/browser/renderer_host/pepper/quota_reservation_unittest.cc5
-rw-r--r--chromium/content/browser/renderer_host/pepper/ssl_context_helper.cc42
-rw-r--r--chromium/content/browser/renderer_host/pepper/ssl_context_helper.h59
-rw-r--r--chromium/content/browser/renderer_host/popup_window_mac.h3
-rw-r--r--chromium/content/browser/renderer_host/popup_window_mac.mm4
-rw-r--r--chromium/content/browser/renderer_host/render_frame_metadata_provider_impl.cc11
-rw-r--r--chromium/content/browser/renderer_host/render_frame_metadata_provider_impl.h2
-rw-r--r--chromium/content/browser/renderer_host/render_message_filter.cc171
-rw-r--r--chromium/content/browser/renderer_host/render_message_filter.h45
-rw-r--r--chromium/content/browser/renderer_host/render_process_host_browsertest.cc14
-rw-r--r--chromium/content/browser/renderer_host/render_process_host_impl.cc279
-rw-r--r--chromium/content/browser/renderer_host/render_process_host_impl.h32
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_delegate.h15
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_delegate_view.cc2
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_delegate_view.h4
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_impl.cc165
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_impl.h17
-rw-r--r--chromium/content/browser/renderer_host/render_widget_helper.cc26
-rw-r--r--chromium/content/browser/renderer_host/render_widget_helper.h6
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_browsertest.cc158
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_delegate.cc8
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_delegate.h9
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_impl.cc249
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_impl.h37
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_input_event_router.cc327
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_input_event_router.h18
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_ns_view_bridge_local.h43
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_ns_view_bridge_local.mm55
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_ns_view_client_helper.h (renamed from chromium/content/browser/renderer_host/render_widget_host_ns_view_client.h)24
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_ns_view_client_helper.mm100
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_owner_delegate.h5
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_unittest.cc95
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_android.cc42
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_android.h11
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_aura.cc152
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_aura.h9
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc356
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_base.cc166
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_base.h66
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_child_frame.cc45
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_child_frame_browsertest.cc2
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc12
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_cocoa.h16
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_cocoa.mm170
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_event_handler.cc55
-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.h28
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_mac.mm111
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm4
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm22
-rw-r--r--chromium/content/browser/renderer_host/render_widget_targeter.cc217
-rw-r--r--chromium/content/browser/renderer_host/render_widget_targeter.h63
-rw-r--r--chromium/content/browser/renderer_host/text_input_manager.cc4
-rw-r--r--chromium/content/browser/renderer_host/text_input_manager.h7
-rw-r--r--chromium/content/browser/renderer_host/ui_events_helper.cc5
-rw-r--r--chromium/content/browser/renderer_host/web_database_host_impl.cc8
-rw-r--r--chromium/content/browser/renderer_interface_binders.cc12
-rw-r--r--chromium/content/browser/resources/gpu/info_view.js1
-rw-r--r--chromium/content/browser/resources/media/client_renderer.js97
-rw-r--r--chromium/content/browser/resources/media/main.js4
-rw-r--r--chromium/content/browser/resources/media/manager.js19
-rw-r--r--chromium/content/browser/resources/media/media_internals.html12
-rw-r--r--chromium/content/browser/resources/media/stats_graph_helper.js4
-rw-r--r--chromium/content/browser/resources/media/util.js12
-rw-r--r--chromium/content/browser/resources/process/process_internals.css86
-rw-r--r--chromium/content/browser/resources/process/process_internals.html43
-rw-r--r--chromium/content/browser/resources/process/process_internals.js173
-rw-r--r--chromium/content/browser/scheduler/OWNERS4
-rw-r--r--chromium/content/browser/scheduler/browser_task_executor.cc153
-rw-r--r--chromium/content/browser/scheduler/browser_task_executor.h74
-rw-r--r--chromium/content/browser/scheduler/browser_task_executor_unittest.cc51
-rw-r--r--chromium/content/browser/scheduler/responsiveness/README2
-rw-r--r--chromium/content/browser/scheduler/responsiveness/native_event_observer.cc49
-rw-r--r--chromium/content/browser/scheduler/responsiveness/native_event_observer.h23
-rw-r--r--chromium/content/browser/scheduler/responsiveness/watcher.cc44
-rw-r--r--chromium/content/browser/scheduler/responsiveness/watcher.h10
-rw-r--r--chromium/content/browser/scheduler/responsiveness/watcher_unittest.cc26
-rw-r--r--chromium/content/browser/screen_orientation/screen_orientation_browsertest.cc2
-rw-r--r--chromium/content/browser/screenlock_monitor/OWNERS1
-rw-r--r--chromium/content/browser/screenlock_monitor/screenlock_monitor.cc56
-rw-r--r--chromium/content/browser/screenlock_monitor/screenlock_monitor.h53
-rw-r--r--chromium/content/browser/screenlock_monitor/screenlock_monitor_device_source.cc21
-rw-r--r--chromium/content/browser/screenlock_monitor/screenlock_monitor_device_source.h89
-rw-r--r--chromium/content/browser/screenlock_monitor/screenlock_monitor_device_source_chromeos.cc35
-rw-r--r--chromium/content/browser/screenlock_monitor/screenlock_monitor_device_source_mac.mm52
-rw-r--r--chromium/content/browser/screenlock_monitor/screenlock_monitor_device_source_win.cc70
-rw-r--r--chromium/content/browser/screenlock_monitor/screenlock_monitor_source.cc31
-rw-r--r--chromium/content/browser/screenlock_monitor/screenlock_monitor_source.h31
-rw-r--r--chromium/content/browser/screenlock_monitor/screenlock_monitor_unittest.cc89
-rw-r--r--chromium/content/browser/security_exploit_browsertest.cc324
-rw-r--r--chromium/content/browser/service_manager/common_browser_interfaces.cc5
-rw-r--r--chromium/content/browser/service_manager/service_manager_context.cc20
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_instance.cc195
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_instance.h10
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_instance_unittest.cc4
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_registry.cc6
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_test_helper.cc51
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_test_helper.h16
-rw-r--r--chromium/content/browser/service_worker/payment_handler_support.cc14
-rw-r--r--chromium/content/browser/service_worker/service_worker_browsertest.cc567
-rw-r--r--chromium/content/browser/service_worker/service_worker_cache_writer.cc70
-rw-r--r--chromium/content/browser/service_worker/service_worker_cache_writer.h26
-rw-r--r--chromium/content/browser/service_worker/service_worker_cache_writer_unittest.cc516
-rw-r--r--chromium/content/browser/service_worker/service_worker_client_utils.cc53
-rw-r--r--chromium/content/browser/service_worker/service_worker_content_settings_proxy_impl.cc2
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_core.cc13
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_request_handler.cc11
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_request_handler_unittest.cc15
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_unittest.cc20
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_watcher.cc34
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_wrapper.cc137
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_wrapper.h8
-rw-r--r--chromium/content/browser/service_worker/service_worker_controllee_request_handler.cc96
-rw-r--r--chromium/content/browser/service_worker/service_worker_controllee_request_handler.h8
-rw-r--r--chromium/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc9
-rw-r--r--chromium/content/browser/service_worker/service_worker_data_pipe_reader_unittest.cc19
-rw-r--r--chromium/content/browser/service_worker/service_worker_database.cc22
-rw-r--r--chromium/content/browser/service_worker/service_worker_database.h1
-rw-r--r--chromium/content/browser/service_worker/service_worker_database.proto5
-rw-r--r--chromium/content/browser/service_worker/service_worker_database_unittest.cc161
-rw-r--r--chromium/content/browser/service_worker/service_worker_disk_cache.cc10
-rw-r--r--chromium/content/browser/service_worker/service_worker_disk_cache.h13
-rw-r--r--chromium/content/browser/service_worker/service_worker_dispatcher_host.cc6
-rw-r--r--chromium/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc9
-rw-r--r--chromium/content/browser/service_worker/service_worker_fetch_dispatcher.cc44
-rw-r--r--chromium/content/browser/service_worker/service_worker_fetch_dispatcher.h9
-rw-r--r--chromium/content/browser/service_worker/service_worker_installed_script_reader.cc38
-rw-r--r--chromium/content/browser/service_worker/service_worker_installed_scripts_sender_unittest.cc7
-rw-r--r--chromium/content/browser/service_worker/service_worker_internals_ui.cc34
-rw-r--r--chromium/content/browser/service_worker/service_worker_job_unittest.cc157
-rw-r--r--chromium/content/browser/service_worker/service_worker_metrics.cc15
-rw-r--r--chromium/content/browser/service_worker/service_worker_metrics.h9
-rw-r--r--chromium/content/browser/service_worker/service_worker_navigation_handle_core.cc6
-rw-r--r--chromium/content/browser/service_worker/service_worker_navigation_loader.cc192
-rw-r--r--chromium/content/browser/service_worker/service_worker_navigation_loader.h34
-rw-r--r--chromium/content/browser/service_worker/service_worker_navigation_loader_unittest.cc241
-rw-r--r--chromium/content/browser/service_worker/service_worker_new_script_loader.cc15
-rw-r--r--chromium/content/browser/service_worker/service_worker_new_script_loader_unittest.cc5
-rw-r--r--chromium/content/browser/service_worker/service_worker_object_host.cc4
-rw-r--r--chromium/content/browser/service_worker/service_worker_object_host_unittest.cc10
-rw-r--r--chromium/content/browser/service_worker/service_worker_provider_host.cc103
-rw-r--r--chromium/content/browser/service_worker/service_worker_provider_host.h39
-rw-r--r--chromium/content/browser/service_worker/service_worker_provider_host_unittest.cc114
-rw-r--r--chromium/content/browser/service_worker/service_worker_read_from_cache_job_unittest.cc12
-rw-r--r--chromium/content/browser/service_worker/service_worker_register_job.cc70
-rw-r--r--chromium/content/browser/service_worker/service_worker_register_job.h21
-rw-r--r--chromium/content/browser/service_worker/service_worker_registration.cc84
-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.cc48
-rw-r--r--chromium/content/browser/service_worker/service_worker_registration_object_host.h11
-rw-r--r--chromium/content/browser/service_worker/service_worker_registration_unittest.cc356
-rw-r--r--chromium/content/browser/service_worker/service_worker_request_handler.cc34
-rw-r--r--chromium/content/browser/service_worker/service_worker_request_handler.h11
-rw-r--r--chromium/content/browser/service_worker/service_worker_request_handler_unittest.cc18
-rw-r--r--chromium/content/browser/service_worker/service_worker_script_cache_map.cc9
-rw-r--r--chromium/content/browser/service_worker/service_worker_script_loader_factory.cc13
-rw-r--r--chromium/content/browser/service_worker/service_worker_script_loader_factory.h3
-rw-r--r--chromium/content/browser/service_worker/service_worker_script_loader_factory_unittest.cc3
-rw-r--r--chromium/content/browser/service_worker/service_worker_single_script_update_checker.cc385
-rw-r--r--chromium/content/browser/service_worker/service_worker_single_script_update_checker.h141
-rw-r--r--chromium/content/browser/service_worker/service_worker_single_script_update_checker_unittest.cc288
-rw-r--r--chromium/content/browser/service_worker/service_worker_storage.cc12
-rw-r--r--chromium/content/browser/service_worker/service_worker_storage_unittest.cc33
-rw-r--r--chromium/content/browser/service_worker/service_worker_test_utils.cc171
-rw-r--r--chromium/content/browser/service_worker/service_worker_test_utils.h164
-rw-r--r--chromium/content/browser/service_worker/service_worker_tls_browsertest.cc146
-rw-r--r--chromium/content/browser/service_worker/service_worker_update_checker.cc74
-rw-r--r--chromium/content/browser/service_worker/service_worker_update_checker.h56
-rw-r--r--chromium/content/browser/service_worker/service_worker_url_job_wrapper.cc8
-rw-r--r--chromium/content/browser/service_worker/service_worker_url_job_wrapper.h6
-rw-r--r--chromium/content/browser/service_worker/service_worker_url_request_job.cc20
-rw-r--r--chromium/content/browser/service_worker/service_worker_url_request_job.h10
-rw-r--r--chromium/content/browser/service_worker/service_worker_url_request_job_unittest.cc50
-rw-r--r--chromium/content/browser/service_worker/service_worker_version.cc128
-rw-r--r--chromium/content/browser/service_worker/service_worker_version.h81
-rw-r--r--chromium/content/browser/service_worker/service_worker_version_unittest.cc53
-rw-r--r--chromium/content/browser/service_worker/service_worker_write_to_cache_job.cc37
-rw-r--r--chromium/content/browser/service_worker/service_worker_write_to_cache_job.h4
-rw-r--r--chromium/content/browser/service_worker/service_worker_write_to_cache_job_unittest.cc17
-rw-r--r--chromium/content/browser/shareable_file_reference_unittest.cc4
-rw-r--r--chromium/content/browser/shared_worker/mock_shared_worker.cc7
-rw-r--r--chromium/content/browser/shared_worker/mock_shared_worker.h9
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_connector_impl.cc2
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_content_settings_proxy_impl.cc4
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_host.cc151
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_host.h31
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_host_unittest.cc126
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_script_fetcher.cc205
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_script_fetcher.h97
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_script_loader.cc45
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_script_loader.h23
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_script_loader_factory.cc41
-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.cc321
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_service_impl.h39
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_service_impl_unittest.cc2
-rw-r--r--chromium/content/browser/shared_worker/worker_browsertest.cc5
-rw-r--r--chromium/content/browser/site_instance_impl.cc91
-rw-r--r--chromium/content/browser/site_instance_impl.h42
-rw-r--r--chromium/content/browser/site_instance_impl_unittest.cc122
-rw-r--r--chromium/content/browser/site_per_process_browsertest.cc328
-rw-r--r--chromium/content/browser/site_per_process_hit_test_browsertest.cc768
-rw-r--r--chromium/content/browser/site_per_process_mac_browsertest.mm6
-rw-r--r--chromium/content/browser/speech/speech_recognition_browsertest.cc10
-rw-r--r--chromium/content/browser/speech/speech_recognition_dispatcher_host.cc12
-rw-r--r--chromium/content/browser/speech/speech_recognition_engine_unittest.cc11
-rw-r--r--chromium/content/browser/speech/speech_recognition_manager_impl.cc8
-rw-r--r--chromium/content/browser/speech/speech_recognizer_impl.cc41
-rw-r--r--chromium/content/browser/speech/speech_recognizer_impl_android.cc46
-rw-r--r--chromium/content/browser/ssl/ssl_client_auth_handler.cc18
-rw-r--r--chromium/content/browser/ssl/ssl_error_handler.cc18
-rw-r--r--chromium/content/browser/ssl/ssl_manager.cc71
-rw-r--r--chromium/content/browser/startup_helper.cc110
-rw-r--r--chromium/content/browser/startup_helper.h23
-rw-r--r--chromium/content/browser/startup_task_runner.cc4
-rw-r--r--chromium/content/browser/storage_partition_impl.cc168
-rw-r--r--chromium/content/browser/storage_partition_impl_map.cc32
-rw-r--r--chromium/content/browser/storage_partition_impl_unittest.cc473
-rw-r--r--chromium/content/browser/streams/stream.cc3
-rw-r--r--chromium/content/browser/streams/stream_context.cc6
-rw-r--r--chromium/content/browser/streams/stream_registry.cc4
-rw-r--r--chromium/content/browser/streams/stream_unittest.cc12
-rw-r--r--chromium/content/browser/streams/stream_url_request_job_unittest.cc24
-rw-r--r--chromium/content/browser/top_document_isolation_browsertest.cc616
-rw-r--r--chromium/content/browser/tracing/background_startup_tracing_observer.cc6
-rw-r--r--chromium/content/browser/tracing/background_tracing_config_unittest.cc7
-rw-r--r--chromium/content/browser/tracing/background_tracing_manager_browsertest.cc25
-rw-r--r--chromium/content/browser/tracing/background_tracing_manager_impl.cc25
-rw-r--r--chromium/content/browser/tracing/background_tracing_rule.cc10
-rw-r--r--chromium/content/browser/tracing/etw_tracing_agent_win.cc8
-rw-r--r--chromium/content/browser/tracing/trace_message_filter.cc12
-rw-r--r--chromium/content/browser/tracing/tracing_controller_browsertest.cc8
-rw-r--r--chromium/content/browser/tracing/tracing_controller_impl.cc47
-rw-r--r--chromium/content/browser/tracing/tracing_controller_impl.h7
-rw-r--r--chromium/content/browser/tracing/tracing_controller_impl_data_endpoint.cc9
-rw-r--r--chromium/content/browser/tracing/tracing_ui.cc3
-rw-r--r--chromium/content/browser/url_loader_factory_getter.cc14
-rw-r--r--chromium/content/browser/url_loader_factory_getter.h13
-rw-r--r--chromium/content/browser/utility_process_host.cc74
-rw-r--r--chromium/content/browser/utility_process_host_browsertest.cc23
-rw-r--r--chromium/content/browser/web_contents/aura/overscroll_navigation_overlay.cc4
-rw-r--r--chromium/content/browser/web_contents/web_contents_android.cc16
-rw-r--r--chromium/content/browser/web_contents/web_contents_android.h3
-rw-r--r--chromium/content/browser/web_contents/web_contents_getter_registry.cc51
-rw-r--r--chromium/content/browser/web_contents/web_contents_getter_registry.h49
-rw-r--r--chromium/content/browser/web_contents/web_contents_impl.cc473
-rw-r--r--chromium/content/browser/web_contents/web_contents_impl.h68
-rw-r--r--chromium/content/browser/web_contents/web_contents_impl_browsertest.cc153
-rw-r--r--chromium/content/browser/web_contents/web_contents_impl_unittest.cc93
-rw-r--r--chromium/content/browser/web_contents/web_contents_ns_view_bridge.h54
-rw-r--r--chromium/content/browser/web_contents/web_contents_ns_view_bridge.mm65
-rw-r--r--chromium/content/browser/web_contents/web_contents_view.h12
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_android.cc7
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_android.h4
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_aura.cc16
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_aura.h2
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_child_frame.cc13
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_child_frame.h4
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_guest.cc20
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_guest.h4
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_mac.h51
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_mac.mm130
-rw-r--r--chromium/content/browser/web_contents/web_drag_source_mac.mm11
-rw-r--r--chromium/content/browser/web_package/mock_signed_exchange_handler.cc13
-rw-r--r--chromium/content/browser/web_package/mock_signed_exchange_handler.h11
-rw-r--r--chromium/content/browser/web_package/origins_list.cc82
-rw-r--r--chromium/content/browser/web_package/origins_list.h52
-rw-r--r--chromium/content/browser/web_package/origins_list_unittest.cc77
-rw-r--r--chromium/content/browser/web_package/signed_exchange_cert_fetcher.cc12
-rw-r--r--chromium/content/browser/web_package/signed_exchange_cert_fetcher.h4
-rw-r--r--chromium/content/browser/web_package/signed_exchange_cert_fetcher_unittest.cc29
-rw-r--r--chromium/content/browser/web_package/signed_exchange_certificate_chain.h1
-rw-r--r--chromium/content/browser/web_package/signed_exchange_consts.h2
-rw-r--r--chromium/content/browser/web_package/signed_exchange_devtools_proxy.cc22
-rw-r--r--chromium/content/browser/web_package/signed_exchange_envelope.cc49
-rw-r--r--chromium/content/browser/web_package/signed_exchange_envelope.h2
-rw-r--r--chromium/content/browser/web_package/signed_exchange_envelope_unittest.cc11
-rw-r--r--chromium/content/browser/web_package/signed_exchange_error.h31
-rw-r--r--chromium/content/browser/web_package/signed_exchange_handler.cc221
-rw-r--r--chromium/content/browser/web_package/signed_exchange_handler.h31
-rw-r--r--chromium/content/browser/web_package/signed_exchange_handler_unittest.cc99
-rw-r--r--chromium/content/browser/web_package/signed_exchange_loader.cc28
-rw-r--r--chromium/content/browser/web_package/signed_exchange_loader.h7
-rw-r--r--chromium/content/browser/web_package/signed_exchange_prefetch_handler.cc18
-rw-r--r--chromium/content/browser/web_package/signed_exchange_prefetch_handler.h6
-rw-r--r--chromium/content/browser/web_package/signed_exchange_prefetch_metric_recorder.cc23
-rw-r--r--chromium/content/browser/web_package/signed_exchange_prefetch_metric_recorder.h35
-rw-r--r--chromium/content/browser/web_package/signed_exchange_request_handler.cc16
-rw-r--r--chromium/content/browser/web_package/signed_exchange_request_handler.h8
-rw-r--r--chromium/content/browser/web_package/signed_exchange_request_handler_browsertest.cc896
-rw-r--r--chromium/content/browser/web_package/signed_exchange_signature_header_field.cc22
-rw-r--r--chromium/content/browser/web_package/signed_exchange_signature_header_field.h11
-rw-r--r--chromium/content/browser/web_package/signed_exchange_signature_header_field_unittest.cc56
-rw-r--r--chromium/content/browser/web_package/signed_exchange_signature_verifier.cc140
-rw-r--r--chromium/content/browser/web_package/signed_exchange_signature_verifier.h35
-rw-r--r--chromium/content/browser/web_package/signed_exchange_signature_verifier_unittest.cc176
-rw-r--r--chromium/content/browser/web_package/signed_exchange_utils.cc94
-rw-r--r--chromium/content/browser/web_package/signed_exchange_utils.h26
-rw-r--r--chromium/content/browser/web_package/signed_exchange_utils_unittest.cc97
-rw-r--r--chromium/content/browser/webauth/authenticator_impl.cc186
-rw-r--r--chromium/content/browser/webauth/authenticator_impl.h3
-rw-r--r--chromium/content/browser/webauth/authenticator_impl_unittest.cc63
-rw-r--r--chromium/content/browser/webauth/authenticator_type_converters.cc19
-rw-r--r--chromium/content/browser/webauth/authenticator_type_converters.h7
-rw-r--r--chromium/content/browser/webauth/scoped_virtual_authenticator_environment.cc2
-rw-r--r--chromium/content/browser/webauth/scoped_virtual_authenticator_environment.h4
-rw-r--r--chromium/content/browser/webauth/virtual_discovery.cc8
-rw-r--r--chromium/content/browser/webauth/virtual_discovery.h11
-rw-r--r--chromium/content/browser/webauth/webauth_browsertest.cc12
-rw-r--r--chromium/content/browser/webrtc/webrtc_audio_browsertest.cc86
-rw-r--r--chromium/content/browser/webrtc/webrtc_browsertest.cc9
-rw-r--r--chromium/content/browser/webrtc/webrtc_content_browsertest_base.cc3
-rw-r--r--chromium/content/browser/webrtc/webrtc_depth_capture_browsertest.cc11
-rw-r--r--chromium/content/browser/webrtc/webrtc_getusermedia_browsertest.cc79
-rw-r--r--chromium/content/browser/webrtc/webrtc_internals.cc6
-rw-r--r--chromium/content/browser/webrtc/webrtc_internals_unittest.cc8
-rw-r--r--chromium/content/browser/webrtc/webrtc_video_capture_browsertest.cc2
-rw-r--r--chromium/content/browser/webrtc/webrtc_video_capture_service_browsertest.cc149
-rw-r--r--chromium/content/browser/webrtc/webrtc_video_capture_service_enumeration_browsertest.cc160
-rw-r--r--chromium/content/browser/webrtc/webrtc_webcam_browsertest.cc5
-rw-r--r--chromium/content/browser/websockets/websocket_manager.cc10
-rw-r--r--chromium/content/browser/webui/shared_resources_data_source.cc80
-rw-r--r--chromium/content/browser/webui/url_data_manager.cc24
-rw-r--r--chromium/content/browser/webui/url_data_manager_backend.cc23
-rw-r--r--chromium/content/browser/webui/url_data_source_impl.cc6
-rw-r--r--chromium/content/browser/webui/web_ui_message_handler_unittest.cc37
-rw-r--r--chromium/content/browser/webui/web_ui_mojo_browsertest.cc25
-rw-r--r--chromium/content/browser/webui/web_ui_url_loader_factory.cc9
1100 files changed, 36568 insertions, 19199 deletions
diff --git a/chromium/content/browser/BUILD.gn b/chromium/content/browser/BUILD.gn
index 02d6ebe936c..cf4d96c6856 100644
--- a/chromium/content/browser/BUILD.gn
+++ b/chromium/content/browser/BUILD.gn
@@ -138,6 +138,7 @@ jumbo_source_set("browser") {
"//services/device/public/mojom:generic_sensor",
"//services/file:lib",
"//services/file/public/mojom",
+ "//services/media_session:lib",
"//services/media_session/public/cpp",
"//services/media_session/public/mojom",
"//services/metrics",
@@ -318,6 +319,8 @@ jumbo_source_set("browser") {
"android/content_protocol_handler_impl.h",
"android/content_startup_flags.cc",
"android/content_startup_flags.h",
+ "android/content_url_loader_factory.cc",
+ "android/content_url_loader_factory.h",
"android/devtools_auth.cc",
"android/dialog_overlay_impl.cc",
"android/dialog_overlay_impl.h",
@@ -556,7 +559,8 @@ jumbo_source_set("browser") {
"cache_storage/cache_storage_context_impl.h",
"cache_storage/cache_storage_dispatcher_host.cc",
"cache_storage/cache_storage_dispatcher_host.h",
- "cache_storage/cache_storage_histogram_macros.h",
+ "cache_storage/cache_storage_histogram_utils.cc",
+ "cache_storage/cache_storage_histogram_utils.h",
"cache_storage/cache_storage_index.cc",
"cache_storage/cache_storage_index.h",
"cache_storage/cache_storage_manager.cc",
@@ -588,6 +592,8 @@ jumbo_source_set("browser") {
"code_cache/generated_code_cache_context.h",
"startup_data_impl.cc",
"startup_data_impl.h",
+ "startup_helper.cc",
+ "startup_helper.h",
# NOTE: These files are here instead of in compositor_browser_sources
# because the latter is not built on Android, whereas these files are
@@ -625,6 +631,8 @@ jumbo_source_set("browser") {
"devtools/devtools_network_transaction_factory.cc",
"devtools/devtools_pipe_handler.cc",
"devtools/devtools_pipe_handler.h",
+ "devtools/devtools_renderer_channel.cc",
+ "devtools/devtools_renderer_channel.h",
"devtools/devtools_session.cc",
"devtools/devtools_session.h",
"devtools/devtools_stream_blob.cc",
@@ -886,6 +894,7 @@ jumbo_source_set("browser") {
"gpu/browser_gpu_client_delegate.h",
"gpu/compositor_util.cc",
"gpu/compositor_util.h",
+ "gpu/delegate_to_browser_gpu_service_accelerator_factory.cc",
"gpu/gpu_client.cc",
"gpu/gpu_data_manager_impl.cc",
"gpu/gpu_data_manager_impl.h",
@@ -903,6 +912,8 @@ jumbo_source_set("browser") {
"gpu/gpu_process_host.h",
"gpu/shader_cache_factory.cc",
"gpu/shader_cache_factory.h",
+ "gpu/video_capture_dependencies.cc",
+ "gpu/video_capture_dependencies.h",
"histogram_controller.cc",
"histogram_controller.h",
"histogram_subscriber.h",
@@ -1047,7 +1058,6 @@ jumbo_source_set("browser") {
"loader/resource_dispatcher_host_impl.h",
"loader/resource_handler.cc",
"loader/resource_handler.h",
- "loader/resource_hints_impl.cc",
"loader/resource_loader.cc",
"loader/resource_loader.h",
"loader/resource_loader_delegate.h",
@@ -1059,6 +1069,8 @@ jumbo_source_set("browser") {
"loader/resource_requester_info.h",
"loader/resource_scheduler_filter.cc",
"loader/resource_scheduler_filter.h",
+ "loader/shared_cors_origin_access_list_impl.cc",
+ "loader/shared_cors_origin_access_list_impl.h",
"loader/source_stream_to_data_pipe.cc",
"loader/source_stream_to_data_pipe.h",
"loader/stream_resource_handler.cc",
@@ -1080,6 +1092,8 @@ jumbo_source_set("browser") {
"manifest/manifest_icon_downloader.cc",
"manifest/manifest_manager_host.cc",
"manifest/manifest_manager_host.h",
+ "media/android/browser_gpu_video_accelerator_factories.cc",
+ "media/android/browser_gpu_video_accelerator_factories.h",
"media/android/browser_media_player_manager.cc",
"media/android/browser_media_player_manager.h",
"media/android/media_player_renderer.cc",
@@ -1148,8 +1162,6 @@ jumbo_source_set("browser") {
"media/session/audio_focus_delegate_android.cc",
"media/session/audio_focus_delegate_android.h",
"media/session/audio_focus_delegate_default.cc",
- "media/session/audio_focus_manager.cc",
- "media/session/audio_focus_manager.h",
"media/session/audio_focus_observer.cc",
"media/session/audio_focus_observer.h",
"media/session/media_metadata_sanitizer.cc",
@@ -1269,6 +1281,8 @@ jumbo_source_set("browser") {
"renderer_host/clipboard_host_impl.cc",
"renderer_host/clipboard_host_impl.h",
"renderer_host/clipboard_host_impl_mac.mm",
+ "renderer_host/code_cache_host_impl.cc",
+ "renderer_host/code_cache_host_impl.h",
"renderer_host/cursor_manager.cc",
"renderer_host/cursor_manager.h",
"renderer_host/dip_util.cc",
@@ -1292,6 +1306,8 @@ jumbo_source_set("browser") {
"renderer_host/frame_sink_provider_impl.h",
"renderer_host/frame_token_message_queue.cc",
"renderer_host/frame_token_message_queue.h",
+ "renderer_host/hit_test_debug_key_event_observer.cc",
+ "renderer_host/hit_test_debug_key_event_observer.h",
"renderer_host/input/fling_controller.cc",
"renderer_host/input/fling_controller.h",
"renderer_host/input/fling_scheduler.cc",
@@ -1445,8 +1461,6 @@ jumbo_source_set("browser") {
"renderer_host/media/video_capture_controller.cc",
"renderer_host/media/video_capture_controller.h",
"renderer_host/media/video_capture_controller_event_handler.h",
- "renderer_host/media/video_capture_dependencies.cc",
- "renderer_host/media/video_capture_dependencies.h",
"renderer_host/media/video_capture_device_launch_observer.h",
"renderer_host/media/video_capture_factory_delegate.cc",
"renderer_host/media/video_capture_factory_delegate.h",
@@ -1528,6 +1542,8 @@ jumbo_source_set("browser") {
"sandbox_ipc_linux.h",
"sandbox_parameters_mac.h",
"sandbox_parameters_mac.mm",
+ "scheduler/browser_task_executor.cc",
+ "scheduler/browser_task_executor.h",
"scheduler/responsiveness/calculator.cc",
"scheduler/responsiveness/calculator.h",
"scheduler/responsiveness/message_loop_observer.cc",
@@ -1541,6 +1557,15 @@ jumbo_source_set("browser") {
"scoped_active_url.h",
"screen_orientation/screen_orientation_provider.cc",
"screen_orientation/screen_orientation_provider.h",
+ "screenlock_monitor/screenlock_monitor.cc",
+ "screenlock_monitor/screenlock_monitor.h",
+ "screenlock_monitor/screenlock_monitor_device_source.cc",
+ "screenlock_monitor/screenlock_monitor_device_source.h",
+ "screenlock_monitor/screenlock_monitor_device_source_chromeos.cc",
+ "screenlock_monitor/screenlock_monitor_device_source_mac.mm",
+ "screenlock_monitor/screenlock_monitor_device_source_win.cc",
+ "screenlock_monitor/screenlock_monitor_source.cc",
+ "screenlock_monitor/screenlock_monitor_source.h",
"service_manager/common_browser_interfaces.cc",
"service_manager/common_browser_interfaces.h",
"service_manager/service_manager_context.cc",
@@ -1638,12 +1663,16 @@ jumbo_source_set("browser") {
"service_worker/service_worker_script_cache_map.h",
"service_worker/service_worker_script_loader_factory.cc",
"service_worker/service_worker_script_loader_factory.h",
+ "service_worker/service_worker_single_script_update_checker.cc",
+ "service_worker/service_worker_single_script_update_checker.h",
"service_worker/service_worker_storage.cc",
"service_worker/service_worker_storage.h",
"service_worker/service_worker_type_converters.cc",
"service_worker/service_worker_type_converters.h",
"service_worker/service_worker_unregister_job.cc",
"service_worker/service_worker_unregister_job.h",
+ "service_worker/service_worker_update_checker.cc",
+ "service_worker/service_worker_update_checker.h",
"service_worker/service_worker_url_job_wrapper.cc",
"service_worker/service_worker_url_job_wrapper.h",
"service_worker/service_worker_url_request_job.cc",
@@ -1660,6 +1689,8 @@ jumbo_source_set("browser") {
"shared_worker/shared_worker_host.h",
"shared_worker/shared_worker_instance.cc",
"shared_worker/shared_worker_instance.h",
+ "shared_worker/shared_worker_script_fetcher.cc",
+ "shared_worker/shared_worker_script_fetcher.h",
"shared_worker/shared_worker_script_loader.cc",
"shared_worker/shared_worker_script_loader.h",
"shared_worker/shared_worker_script_loader_factory.cc",
@@ -1743,6 +1774,8 @@ jumbo_source_set("browser") {
"web_contents/aura/shadow_layer_delegate.h",
"web_contents/aura/types.cc",
"web_contents/aura/types.h",
+ "web_contents/web_contents_getter_registry.cc",
+ "web_contents/web_contents_getter_registry.h",
"web_contents/web_contents_impl.cc",
"web_contents/web_contents_impl.h",
"web_contents/web_contents_view.h",
@@ -1760,6 +1793,8 @@ jumbo_source_set("browser") {
"web_contents/web_drag_source_mac.mm",
"web_contents/web_drag_utils_win.cc",
"web_contents/web_drag_utils_win.h",
+ "web_package/origins_list.cc",
+ "web_package/origins_list.h",
"web_package/signed_exchange_cert_fetcher.cc",
"web_package/signed_exchange_cert_fetcher.h",
"web_package/signed_exchange_cert_fetcher_factory.cc",
@@ -1779,6 +1814,8 @@ jumbo_source_set("browser") {
"web_package/signed_exchange_loader.h",
"web_package/signed_exchange_prefetch_handler.cc",
"web_package/signed_exchange_prefetch_handler.h",
+ "web_package/signed_exchange_prefetch_metric_recorder.cc",
+ "web_package/signed_exchange_prefetch_metric_recorder.h",
"web_package/signed_exchange_prologue.cc",
"web_package/signed_exchange_prologue.h",
"web_package/signed_exchange_request_handler.cc",
@@ -1851,6 +1888,7 @@ jumbo_source_set("browser") {
"tracing/cros_tracing_agent.cc",
"tracing/cros_tracing_agent.h",
]
+ deps += [ "//chromeos/resources" ]
} else {
sources += [
"memory/memory_monitor_linux.cc",
@@ -1895,6 +1933,8 @@ jumbo_source_set("browser") {
sources += [
"gpu/ca_transaction_gpu_coordinator.cc",
"gpu/ca_transaction_gpu_coordinator.h",
+ "web_contents/web_contents_ns_view_bridge.h",
+ "web_contents/web_contents_ns_view_bridge.mm",
]
deps += [ "//ui/events:dom_keyboard_layout" ]
}
@@ -1967,6 +2007,7 @@ jumbo_source_set("browser") {
"imm32.lib",
"oleacc.lib",
"portabledeviceguids.lib",
+ "wtsapi32.lib",
]
}
@@ -2057,8 +2098,6 @@ jumbo_source_set("browser") {
"renderer_host/pepper/pepper_vpn_provider_message_filter_chromeos.h",
"renderer_host/pepper/quota_reservation.cc",
"renderer_host/pepper/quota_reservation.h",
- "renderer_host/pepper/ssl_context_helper.cc",
- "renderer_host/pepper/ssl_context_helper.h",
"renderer_host/plugin_registry_impl.cc",
"renderer_host/plugin_registry_impl.h",
]
@@ -2093,13 +2132,18 @@ jumbo_source_set("browser") {
if (use_atk) {
sources += [
"accessibility/accessibility_tree_formatter_auralinux.cc",
+ "accessibility/accessibility_tree_formatter_utils_auralinux.cc",
+ "accessibility/accessibility_tree_formatter_utils_auralinux.h",
"accessibility/browser_accessibility_auralinux.cc",
"accessibility/browser_accessibility_auralinux.h",
"accessibility/browser_accessibility_manager_auralinux.cc",
"accessibility/browser_accessibility_manager_auralinux.h",
]
- configs += [ "//build/config/linux/atk" ]
+ configs += [
+ "//build/config/linux/atk",
+ "//build/config/linux:atspi2",
+ ]
if (use_glib) {
configs += [ "//build/config/linux:glib" ]
@@ -2232,8 +2276,6 @@ jumbo_source_set("browser") {
sources -= [
"browser_ipc_logging.cc",
"media/session/audio_focus_delegate_default.cc",
- "media/session/audio_focus_manager.cc",
- "media/session/audio_focus_manager.h",
"tracing/tracing_ui.cc",
"tracing/tracing_ui.h",
]
@@ -2319,11 +2361,14 @@ jumbo_source_set("browser") {
"IOSurface.framework",
]
sources += [
+ "ns_view_bridge_factory_host.mm",
+ "ns_view_bridge_factory_impl.mm",
"renderer_host/popup_window_mac.h",
"renderer_host/popup_window_mac.mm",
"renderer_host/render_widget_host_ns_view_bridge_local.h",
"renderer_host/render_widget_host_ns_view_bridge_local.mm",
- "renderer_host/render_widget_host_ns_view_client.h",
+ "renderer_host/render_widget_host_ns_view_client_helper.h",
+ "renderer_host/render_widget_host_ns_view_client_helper.mm",
"renderer_host/render_widget_host_view_cocoa.h",
"renderer_host/render_widget_host_view_cocoa.mm",
]
@@ -2334,6 +2379,7 @@ jumbo_source_set("browser") {
"//chromeos",
"//chromeos:power_manager_proto",
"//chromeos/assistant:buildflags",
+ "//components/session_manager/core",
]
}
@@ -2344,6 +2390,7 @@ jumbo_source_set("browser") {
if (use_aura) {
deps += [
"//services/ws/public/cpp",
+ "//services/ws/public/cpp/host",
"//services/ws/public/mojom",
"//ui/aura",
"//ui/aura_extra",
@@ -2352,6 +2399,8 @@ jumbo_source_set("browser") {
"//ui/wm/public",
]
sources += [
+ "gpu_interface_provider.cc",
+ "gpu_interface_provider.h",
"renderer_host/delegated_frame_host_client_aura.cc",
"renderer_host/delegated_frame_host_client_aura.h",
"renderer_host/render_widget_host_view_event_handler.cc",
diff --git a/chromium/content/browser/DEPS b/chromium/content/browser/DEPS
index a065eb289c4..7d8808294ea 100644
--- a/chromium/content/browser/DEPS
+++ b/chromium/content/browser/DEPS
@@ -2,6 +2,7 @@ include_rules = [
# Allow inclusion of specific components that we depend on.
# See comment in content/DEPS for which components are allowed.
"+components/discardable_memory/common",
+ "+components/discardable_memory/public",
"+components/discardable_memory/service",
"+components/download/database",
"+components/download/public/common",
@@ -11,6 +12,7 @@ include_rules = [
"+components/services/filesystem",
"+components/services/font/ppapi_fontconfig_matching.h",
"+components/services/leveldb",
+ "+components/session_manager/core",
"+components/link_header_util",
"+components/metrics",
"+components/metrics:single_sample_metrics",
@@ -106,19 +108,18 @@ include_rules = [
"+third_party/blink/public/platform/modules/locks/lock_manager.mojom.h",
"+third_party/blink/public/platform/modules/notifications/web_notification_constants.h",
"+third_party/blink/public/platform/modules/service_worker/web_service_worker_error.h",
+ "+third_party/blink/public/platform/modules/fetch/fetch_api_request.mojom.h",
"+third_party/blink/public/public_buildflags.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",
"+third_party/blink/public/web/web_plugin_action.h",
- "+third_party/blink/public/web/web_popup_type.h",
"+third_party/blink/public/web/web_serialized_script_value_version.h",
"+third_party/blink/public/web/WebSharedWorkerCreationContextType.h",
"+third_party/blink/public/web/WebSharedWorkerCreationErrors.h",
diff --git a/chromium/content/browser/accessibility/accessibility_action_browsertest.cc b/chromium/content/browser/accessibility/accessibility_action_browsertest.cc
index cad16f8da69..2a074451b5b 100644
--- a/chromium/content/browser/accessibility/accessibility_action_browsertest.cc
+++ b/chromium/content/browser/accessibility/accessibility_action_browsertest.cc
@@ -150,6 +150,44 @@ IN_PROC_BROWSER_TEST_F(AccessibilityActionBrowserTest,
ax::mojom::FloatAttribute::kValueForRange));
}
+IN_PROC_BROWSER_TEST_F(AccessibilityActionBrowserTest, Scroll) {
+ NavigateToURL(shell(), GURL(url::kAboutBlankURL));
+
+ AccessibilityNotificationWaiter waiter(shell()->web_contents(),
+ ui::kAXModeComplete,
+ ax::mojom::Event::kLoadComplete);
+ GURL url(
+ "data:text/html,"
+ "<div style='width:100; height:50; overflow:scroll' "
+ "aria-label='shakespeare'>"
+ "To be or not to be, that is the question."
+ "</div>");
+
+ NavigateToURL(shell(), url);
+ waiter.WaitForNotification();
+
+ BrowserAccessibility* target =
+ FindNode(ax::mojom::Role::kGenericContainer, "shakespeare");
+ EXPECT_NE(target, nullptr);
+
+ int y_before = target->GetIntAttribute(ax::mojom::IntAttribute::kScrollY);
+
+ AccessibilityNotificationWaiter waiter2(
+ shell()->web_contents(), ui::kAXModeComplete,
+ ax::mojom::Event::kScrollPositionChanged);
+
+ ui::AXActionData data;
+ data.action = ax::mojom::Action::kScrollDown;
+ data.target_node_id = target->GetId();
+
+ target->manager()->delegate()->AccessibilityPerformAction(data);
+ waiter2.WaitForNotification();
+
+ int y_after = target->GetIntAttribute(ax::mojom::IntAttribute::kScrollY);
+
+ EXPECT_GT(y_after, y_before);
+}
+
IN_PROC_BROWSER_TEST_F(AccessibilityActionBrowserTest, CanvasGetImage) {
NavigateToURL(shell(), GURL(url::kAboutBlankURL));
diff --git a/chromium/content/browser/accessibility/accessibility_event_recorder.cc b/chromium/content/browser/accessibility/accessibility_event_recorder.cc
index a2de95e816a..e558d871725 100644
--- a/chromium/content/browser/accessibility/accessibility_event_recorder.cc
+++ b/chromium/content/browser/accessibility/accessibility_event_recorder.cc
@@ -5,24 +5,24 @@
#include "content/browser/accessibility/accessibility_event_recorder.h"
#include "build/build_config.h"
+#include "content/browser/accessibility/accessibility_buildflags.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
namespace content {
AccessibilityEventRecorder::AccessibilityEventRecorder(
- BrowserAccessibilityManager* manager,
- base::ProcessId pid)
+ BrowserAccessibilityManager* manager)
: manager_(manager) {}
AccessibilityEventRecorder::~AccessibilityEventRecorder() = default;
-#if !defined(OS_WIN) && !defined(OS_MACOSX)
+#if !defined(OS_WIN) && !defined(OS_MACOSX) && !BUILDFLAG(USE_ATK)
// static
-AccessibilityEventRecorder& AccessibilityEventRecorder::GetInstance(
+std::unique_ptr<AccessibilityEventRecorder> AccessibilityEventRecorder::Create(
BrowserAccessibilityManager* manager,
- base::ProcessId pid) {
- static base::NoDestructor<AccessibilityEventRecorder> instance(manager, pid);
- return *instance;
+ base::ProcessId pid,
+ const base::StringPiece& application_name_match_pattern) {
+ return std::make_unique<AccessibilityEventRecorder>(manager);
}
#endif
diff --git a/chromium/content/browser/accessibility/accessibility_event_recorder.h b/chromium/content/browser/accessibility/accessibility_event_recorder.h
index 4d03a1dbc01..c6276b801e4 100644
--- a/chromium/content/browser/accessibility/accessibility_event_recorder.h
+++ b/chromium/content/browser/accessibility/accessibility_event_recorder.h
@@ -5,12 +5,12 @@
#ifndef CONTENT_BROWSER_ACCESSIBILITY_ACCESSIBILITY_EVENT_RECORDER_H_
#define CONTENT_BROWSER_ACCESSIBILITY_ACCESSIBILITY_EVENT_RECORDER_H_
+#include <memory>
#include <string>
#include <vector>
#include "base/callback.h"
#include "base/macros.h"
-#include "base/no_destructor.h"
#include "base/process/process_handle.h"
namespace content {
@@ -37,10 +37,14 @@ class BrowserAccessibilityManager;
// As currently designed, there should only be one instance of this class.
class AccessibilityEventRecorder {
public:
- // Get the right platform-specific subclass.
- static AccessibilityEventRecorder& GetInstance(
+ // Construct the right platform-specific subclass.
+ static std::unique_ptr<AccessibilityEventRecorder> Create(
BrowserAccessibilityManager* manager = nullptr,
- base::ProcessId pid = 0);
+ base::ProcessId pid = 0,
+ const base::StringPiece& application_name_match_pattern =
+ base::StringPiece());
+
+ AccessibilityEventRecorder(BrowserAccessibilityManager* manager);
virtual ~AccessibilityEventRecorder();
void set_only_web_events(bool only_web_events) {
@@ -55,16 +59,11 @@ class AccessibilityEventRecorder {
const std::vector<std::string>& event_logs() { return event_logs_; }
protected:
- AccessibilityEventRecorder(BrowserAccessibilityManager* manager,
- base::ProcessId pid);
-
void OnEvent(const std::string& event);
BrowserAccessibilityManager* const manager_;
bool only_web_events_ = false;
- friend class base::NoDestructor<AccessibilityEventRecorder>;
-
private:
std::vector<std::string> event_logs_;
AccessibilityEventCallback callback_;
diff --git a/chromium/content/browser/accessibility/accessibility_event_recorder_auralinux.cc b/chromium/content/browser/accessibility/accessibility_event_recorder_auralinux.cc
new file mode 100644
index 00000000000..203e2da5d4a
--- /dev/null
+++ b/chromium/content/browser/accessibility/accessibility_event_recorder_auralinux.cc
@@ -0,0 +1,401 @@
+// 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/accessibility/accessibility_event_recorder.h"
+
+#include <atk/atk.h>
+#include <atk/atkutil.h>
+#include <atspi/atspi.h>
+
+#include "base/process/process_handle.h"
+#include "base/stl_util.h"
+#include "base/strings/pattern.h"
+#include "base/strings/stringprintf.h"
+#include "content/browser/accessibility/accessibility_tree_formatter_utils_auralinux.h"
+#include "content/browser/accessibility/browser_accessibility_auralinux.h"
+#include "content/browser/accessibility/browser_accessibility_manager.h"
+
+#if defined(ATK_CHECK_VERSION) && ATK_CHECK_VERSION(2, 16, 0)
+#define ATK_216
+#endif
+
+namespace content {
+
+// This class has two distinct event recording code paths. When we are
+// recording events in-process (typically this is used for
+// DumpAccessibilityEvents tests), we use ATK's global event handlers. Since
+// ATK doesn't support intercepting events from other processes, if we have a
+// non-zero PID or an accessibility application name pattern, we use AT-SPI2
+// directly to intercept events. Since AT-SPI2 should be capable of
+// intercepting events in-process as well, eventually it would be nice to
+// remove the ATK code path entirely.
+class AccessibilityEventRecorderAuraLinux : public AccessibilityEventRecorder {
+ public:
+ explicit AccessibilityEventRecorderAuraLinux(
+ BrowserAccessibilityManager* manager,
+ base::ProcessId pid,
+ const base::StringPiece& application_name_match_pattern);
+ ~AccessibilityEventRecorderAuraLinux() override;
+
+ void ProcessATKEvent(const char* event,
+ unsigned int n_params,
+ const GValue* params);
+ void ProcessATSPIEvent(const AtspiEvent* event);
+
+ static gboolean OnATKEventReceived(GSignalInvocationHint* hint,
+ unsigned int n_params,
+ const GValue* params,
+ gpointer data);
+
+ private:
+ bool ShouldUseATSPI();
+
+ void AddATKEventListener(const char* event_name);
+ void AddATKEventListeners();
+ void RemoveATKEventListeners();
+ bool IncludeState(AtkStateType state_type);
+
+ void AddATSPIEventListeners();
+ void RemoveATSPIEventListeners();
+
+ AtspiEventListener* atspi_event_listener_ = nullptr;
+ base::ProcessId pid_;
+ base::StringPiece application_name_match_pattern_;
+ std::vector<unsigned int> atk_listener_ids_;
+ static AccessibilityEventRecorderAuraLinux* instance_;
+
+ DISALLOW_COPY_AND_ASSIGN(AccessibilityEventRecorderAuraLinux);
+};
+
+// static
+AccessibilityEventRecorderAuraLinux*
+ AccessibilityEventRecorderAuraLinux::instance_ = nullptr;
+
+// static
+gboolean AccessibilityEventRecorderAuraLinux::OnATKEventReceived(
+ GSignalInvocationHint* hint,
+ unsigned int n_params,
+ const GValue* params,
+ gpointer data) {
+ GSignalQuery query;
+ g_signal_query(hint->signal_id, &query);
+
+ if (instance_) {
+ instance_->ProcessATKEvent(query.signal_name, n_params, params);
+ }
+
+ return true;
+}
+
+// static
+std::unique_ptr<AccessibilityEventRecorder> AccessibilityEventRecorder::Create(
+ BrowserAccessibilityManager* manager,
+ base::ProcessId pid,
+ const base::StringPiece& application_name_match_pattern) {
+ return std::make_unique<AccessibilityEventRecorderAuraLinux>(
+ manager, pid, application_name_match_pattern);
+}
+
+bool AccessibilityEventRecorderAuraLinux::ShouldUseATSPI() {
+ return pid_ != base::GetCurrentProcId() ||
+ !application_name_match_pattern_.empty();
+}
+
+AccessibilityEventRecorderAuraLinux::AccessibilityEventRecorderAuraLinux(
+ BrowserAccessibilityManager* manager,
+ base::ProcessId pid,
+ const base::StringPiece& application_name_match_pattern)
+ : AccessibilityEventRecorder(manager),
+ pid_(pid),
+ application_name_match_pattern_(application_name_match_pattern) {
+ CHECK(!instance_) << "There can be only one instance of"
+ << " AccessibilityEventRecorder at a time.";
+
+ if (ShouldUseATSPI()) {
+ AddATSPIEventListeners();
+ } else {
+ AddATKEventListeners();
+ }
+
+ instance_ = this;
+}
+
+AccessibilityEventRecorderAuraLinux::~AccessibilityEventRecorderAuraLinux() {
+ RemoveATSPIEventListeners();
+ instance_ = nullptr;
+}
+
+void AccessibilityEventRecorderAuraLinux::AddATKEventListener(
+ const char* event_name) {
+ unsigned id = atk_add_global_event_listener(OnATKEventReceived, event_name);
+ if (!id)
+ LOG(FATAL) << "atk_add_global_event_listener failed for " << event_name;
+
+ atk_listener_ids_.push_back(id);
+}
+
+void AccessibilityEventRecorderAuraLinux::AddATKEventListeners() {
+ GObject* gobject = G_OBJECT(g_object_new(G_TYPE_OBJECT, nullptr, nullptr));
+ g_object_unref(atk_no_op_object_new(gobject));
+ g_object_unref(gobject);
+
+ AddATKEventListener("ATK:AtkObject:state-change");
+ AddATKEventListener("ATK:AtkObject:focus-event");
+ AddATKEventListener("ATK:AtkObject:property-change");
+}
+
+void AccessibilityEventRecorderAuraLinux::RemoveATKEventListeners() {
+ for (const auto& id : atk_listener_ids_)
+ atk_remove_global_event_listener(id);
+
+ atk_listener_ids_.clear();
+}
+
+// Pruning states which are not supported on older bots makes it possible to
+// run the events tests in more environments.
+bool AccessibilityEventRecorderAuraLinux::IncludeState(
+ AtkStateType state_type) {
+ switch (state_type) {
+#if defined(ATK_216)
+ case ATK_STATE_CHECKABLE:
+ case ATK_STATE_HAS_POPUP:
+ case ATK_STATE_READ_ONLY:
+ return false;
+#endif
+ case ATK_STATE_LAST_DEFINED:
+ return false;
+ default:
+ return true;
+ }
+}
+
+void AccessibilityEventRecorderAuraLinux::ProcessATKEvent(
+ const char* event,
+ unsigned int n_params,
+ const GValue* params) {
+ // If we don't have a root object, it means the tree is being destroyed.
+ if (!manager_->GetRoot()) {
+ RemoveATKEventListeners();
+ return;
+ }
+
+ std::string log;
+ if (std::string(event).find("property-change") != std::string::npos) {
+ DCHECK_GE(n_params, 2u);
+ AtkPropertyValues* property_values =
+ static_cast<AtkPropertyValues*>(g_value_get_pointer(&params[1]));
+
+ if (g_strcmp0(property_values->property_name, "accessible-value"))
+ return;
+
+ log += "VALUE-CHANGED:";
+ log +=
+ base::NumberToString(g_value_get_double(&property_values->new_value));
+ } else {
+ log += base::ToUpperASCII(event);
+ if (std::string(event).find("state-change") != std::string::npos) {
+ log += ":" + base::ToUpperASCII(g_value_get_string(&params[1]));
+ log += base::StringPrintf(":%s", g_strdup_value_contents(&params[2]));
+ }
+ }
+
+ AtkObject* obj = ATK_OBJECT(g_value_get_object(&params[0]));
+ std::string role = atk_role_get_name(atk_object_get_role(obj));
+ base::ReplaceChars(role, " ", "_", &role);
+ log += base::StringPrintf(" role=ROLE_%s", base::ToUpperASCII(role).c_str());
+ log += base::StringPrintf(" name='%s'", atk_object_get_name(obj));
+
+ std::string states = "";
+ AtkStateSet* state_set = atk_object_ref_state_set(obj);
+ for (int i = ATK_STATE_INVALID; i < ATK_STATE_LAST_DEFINED; i++) {
+ AtkStateType state_type = static_cast<AtkStateType>(i);
+ if (atk_state_set_contains_state(state_set, state_type) &&
+ IncludeState(state_type)) {
+ states += " " + base::ToUpperASCII(atk_state_type_get_name(state_type));
+ }
+ }
+ states = base::CollapseWhitespaceASCII(states, false);
+ base::ReplaceChars(states, " ", ",", &states);
+ log += base::StringPrintf(" %s", states.c_str());
+
+ OnEvent(log);
+}
+
+// This list is composed of the sorted event names taken from the list provided
+// in the libatspi documentation at:
+// https://developer.gnome.org/libatspi/stable/AtspiEventListener.html#atspi-event-listener-register
+const char* const kEventNames[] = {
+ "object:active-descendant-changed",
+ "object:children-changed",
+ "object:column-deleted",
+ "object:column-inserted",
+ "object:column-reordered",
+ "object:model-changed",
+ "object:property-change",
+ "object:property-change:accessible-description",
+ "object:property-change:accessible-name",
+ "object:property-change:accessible-parent",
+ "object:property-change:accessible-role",
+ "object:property-change:accessible-table-caption",
+ "object:property-change:accessible-table-column-description",
+ "object:property-change:accessible-table-column-header",
+ "object:property-change:accessible-table-row-description",
+ "object:property-change:accessible-table-row-header",
+ "object:property-change:accessible-table-summary",
+ "object:property-change:accessible-value",
+ "object:row-deleted",
+ "object:row-inserted",
+ "object:row-reordered",
+ "object:selection-changed",
+ "object:state-changed",
+ "object:text-caret-moved",
+ "object:text-changed",
+ "object:text-selection-changed",
+ "object:visible-data-changed",
+ "window:activate",
+ "window:close",
+ "window:create",
+ "window:deactivate",
+ "window:desktop-create",
+ "window:desktop-destroy",
+ "window:lower",
+ "window:maximize",
+ "window:minimize",
+ "window:move",
+ "window:raise",
+ "window:reparent",
+ "window:resize",
+ "window:restore",
+ "window:restyle",
+ "window:shade",
+ "window:unshade",
+};
+
+static void OnATSPIEventReceived(AtspiEvent* event, void* data) {
+ static_cast<AccessibilityEventRecorderAuraLinux*>(data)->ProcessATSPIEvent(
+ event);
+ g_boxed_free(ATSPI_TYPE_EVENT, static_cast<void*>(event));
+}
+
+void AccessibilityEventRecorderAuraLinux::AddATSPIEventListeners() {
+ atspi_init();
+ atspi_event_listener_ =
+ atspi_event_listener_new(OnATSPIEventReceived, this, nullptr);
+
+ GError* error = nullptr;
+ for (size_t i = 0; i < base::size(kEventNames); i++) {
+ atspi_event_listener_register(atspi_event_listener_, kEventNames[i],
+ &error);
+ if (error) {
+ LOG(ERROR) << "Could not register event listener for " << kEventNames[i];
+ g_clear_error(&error);
+ }
+ }
+}
+
+void AccessibilityEventRecorderAuraLinux::RemoveATSPIEventListeners() {
+ if (!atspi_event_listener_)
+ return;
+
+ GError* error = nullptr;
+ for (size_t i = 0; i < base::size(kEventNames); i++) {
+ atspi_event_listener_deregister(atspi_event_listener_, kEventNames[i],
+ nullptr);
+ if (error) {
+ LOG(ERROR) << "Could not deregister event listener for "
+ << kEventNames[i];
+ g_clear_error(&error);
+ }
+ }
+
+ g_object_unref(atspi_event_listener_);
+ atspi_event_listener_ = nullptr;
+}
+
+void AccessibilityEventRecorderAuraLinux::ProcessATSPIEvent(
+ const AtspiEvent* event) {
+ GError* error = nullptr;
+
+ if (!application_name_match_pattern_.empty()) {
+ AtspiAccessible* application =
+ atspi_accessible_get_application(event->source, &error);
+ if (error || !application)
+ return;
+
+ char* application_name = atspi_accessible_get_name(application, &error);
+ g_object_unref(application);
+ if (error || !application_name) {
+ g_clear_error(&error);
+ return;
+ }
+
+ if (!base::MatchPattern(application_name,
+ application_name_match_pattern_)) {
+ return;
+ }
+ free(application_name);
+ }
+
+ if (pid_) {
+ int pid = atspi_accessible_get_process_id(event->source, &error);
+ if (!error && pid != pid_)
+ return;
+ g_clear_error(&error);
+ }
+
+ std::stringstream output;
+ output << event->type << " ";
+
+ GHashTable* attributes =
+ atspi_accessible_get_attributes(event->source, &error);
+ std::string html_tag, html_class, html_id;
+ if (!error && attributes) {
+ if (char* tag = static_cast<char*>(g_hash_table_lookup(attributes, "tag")))
+ html_tag = tag;
+ if (char* id = static_cast<char*>(g_hash_table_lookup(attributes, "id")))
+ html_id = id;
+ if (char* class_chars =
+ static_cast<char*>(g_hash_table_lookup(attributes, "class")))
+ html_class = std::string(".") + class_chars;
+ g_hash_table_unref(attributes);
+ }
+ g_clear_error(&error);
+
+ if (!html_tag.empty())
+ output << "<" << html_tag << html_id << html_class << ">";
+
+ AtspiRole role = atspi_accessible_get_role(event->source, &error);
+ output << "role=";
+ if (!error)
+ output << ATSPIRoleToString(role);
+ else
+ output << "#error";
+ g_clear_error(&error);
+
+ char* name = atspi_accessible_get_name(event->source, &error);
+ output << " name=";
+ if (!error && name)
+ output << name;
+ else
+ output << "#error";
+ g_clear_error(&error);
+ free(name);
+
+ AtspiStateSet* atspi_states = atspi_accessible_get_state_set(event->source);
+ GArray* state_array = atspi_state_set_get_states(atspi_states);
+ std::vector<std::string> states;
+ for (unsigned i = 0; i < state_array->len; i++) {
+ AtspiStateType state_type = g_array_index(state_array, AtspiStateType, i);
+ states.push_back(ATSPIStateToString(state_type));
+ }
+ g_array_free(state_array, TRUE);
+ g_object_unref(atspi_states);
+ output << " ";
+ std::copy(states.begin(), states.end(),
+ std::ostream_iterator<std::string>(output, ", "));
+
+ OnEvent(output.str());
+}
+
+} // namespace content
diff --git a/chromium/content/browser/accessibility/accessibility_event_recorder_mac.mm b/chromium/content/browser/accessibility/accessibility_event_recorder_mac.mm
index 0245a037230..9b037b4b368 100644
--- a/chromium/content/browser/accessibility/accessibility_event_recorder_mac.mm
+++ b/chromium/content/browser/accessibility/accessibility_event_recorder_mac.mm
@@ -8,6 +8,7 @@
#include <string>
+#include "base/logging.h"
#include "base/mac/foundation_util.h"
#include "base/mac/scoped_cftyperef.h"
#include "base/strings/stringprintf.h"
@@ -20,15 +21,14 @@ namespace content {
// watch for NSAccessibility events.
class AccessibilityEventRecorderMac : public AccessibilityEventRecorder {
public:
+ AccessibilityEventRecorderMac(BrowserAccessibilityManager* manager,
+ base::ProcessId pid);
~AccessibilityEventRecorderMac() override;
// Callback executed every time we receive an event notification.
void EventReceived(AXUIElementRef element, CFStringRef notification);
private:
- AccessibilityEventRecorderMac(BrowserAccessibilityManager* manager,
- base::ProcessId pid);
-
// Add one notification to the list of notifications monitored by our
// observer.
void AddNotification(NSString* notification);
@@ -45,7 +45,6 @@ class AccessibilityEventRecorderMac : public AccessibilityEventRecorder {
base::ScopedCFTypeRef<AXObserverRef> observer_ref_;
CFRunLoopSourceRef observer_run_loop_source_;
- friend class base::NoDestructor<AccessibilityEventRecorderMac>;
DISALLOW_COPY_AND_ASSIGN(AccessibilityEventRecorderMac);
};
@@ -61,19 +60,23 @@ static void EventReceivedThunk(
}
// static
-AccessibilityEventRecorder& AccessibilityEventRecorder::GetInstance(
+std::unique_ptr<AccessibilityEventRecorder> AccessibilityEventRecorder::Create(
BrowserAccessibilityManager* manager,
- base::ProcessId pid) {
- static base::NoDestructor<AccessibilityEventRecorderMac> instance(manager,
- pid);
- return *instance;
+ base::ProcessId pid,
+ const base::StringPiece& application_name_match_pattern) {
+ if (!application_name_match_pattern.empty()) {
+ LOG(ERROR) << "Recording accessibility events from an application name "
+ "match pattern not supported on this platform yet.";
+ NOTREACHED();
+ }
+
+ return std::make_unique<AccessibilityEventRecorderMac>(manager, pid);
}
AccessibilityEventRecorderMac::AccessibilityEventRecorderMac(
BrowserAccessibilityManager* manager,
base::ProcessId pid)
- : AccessibilityEventRecorder(manager, pid),
- observer_run_loop_source_(NULL) {
+ : AccessibilityEventRecorder(manager), observer_run_loop_source_(NULL) {
if (kAXErrorSuccess != AXObserverCreate(pid, EventReceivedThunk,
observer_ref_.InitializeInto())) {
LOG(FATAL) << "Failed to create AXObserverRef";
diff --git a/chromium/content/browser/accessibility/accessibility_event_recorder_win.cc b/chromium/content/browser/accessibility/accessibility_event_recorder_win.cc
index 07c26adb4c0..0f1c7120a37 100644
--- a/chromium/content/browser/accessibility/accessibility_event_recorder_win.cc
+++ b/chromium/content/browser/accessibility/accessibility_event_recorder_win.cc
@@ -75,6 +75,10 @@ std::string AccessibilityEventToStringUTF8(int32_t event_id) {
class AccessibilityEventRecorderWin : public AccessibilityEventRecorder {
public:
+ AccessibilityEventRecorderWin(
+ BrowserAccessibilityManager* manager,
+ base::ProcessId pid,
+ const base::StringPiece& application_name_match_pattern);
~AccessibilityEventRecorderWin() override;
// Callback registered by SetWinEventHook. Just calls OnWinEventHook.
@@ -87,9 +91,6 @@ class AccessibilityEventRecorderWin : public AccessibilityEventRecorder {
DWORD event_time);
private:
- AccessibilityEventRecorderWin(BrowserAccessibilityManager* manager,
- base::ProcessId pid);
-
// Called by the thunk registered by SetWinEventHook. Retrieves accessibility
// info about the node the event was fired on and appends a string to
// the event log.
@@ -107,18 +108,27 @@ class AccessibilityEventRecorderWin : public AccessibilityEventRecorder {
HWND hwnd, DWORD dwId, REFIID riid, void **ppvObject);
HWINEVENTHOOK win_event_hook_handle_;
+ static AccessibilityEventRecorderWin* instance_;
- friend class base::NoDestructor<AccessibilityEventRecorderWin>;
DISALLOW_COPY_AND_ASSIGN(AccessibilityEventRecorderWin);
};
// static
-AccessibilityEventRecorder& AccessibilityEventRecorder::GetInstance(
+AccessibilityEventRecorderWin* AccessibilityEventRecorderWin::instance_ =
+ nullptr;
+
+// static
+std::unique_ptr<AccessibilityEventRecorder> AccessibilityEventRecorder::Create(
BrowserAccessibilityManager* manager,
- base::ProcessId pid) {
- static base::NoDestructor<AccessibilityEventRecorderWin> instance(manager,
- pid);
- return *instance;
+ base::ProcessId pid,
+ const base::StringPiece& application_name_match_pattern) {
+ if (!application_name_match_pattern.empty()) {
+ LOG(FATAL) << "Recording accessibility events from an application name "
+ "match pattern not supported on this platform yet.";
+ }
+
+ return std::make_unique<AccessibilityEventRecorderWin>(
+ manager, pid, application_name_match_pattern);
}
// static
@@ -130,15 +140,19 @@ CALLBACK void AccessibilityEventRecorderWin::WinEventHookThunk(
LONG child_id,
DWORD event_thread,
DWORD event_time) {
- static_cast<AccessibilityEventRecorderWin&>(GetInstance())
- .OnWinEventHook(handle, event, hwnd, obj_id, child_id, event_thread,
- event_time);
+ if (instance_) {
+ instance_->OnWinEventHook(handle, event, hwnd, obj_id, child_id,
+ event_thread, event_time);
+ }
}
AccessibilityEventRecorderWin::AccessibilityEventRecorderWin(
BrowserAccessibilityManager* manager,
- base::ProcessId pid)
- : AccessibilityEventRecorder(manager, pid) {
+ base::ProcessId pid,
+ const base::StringPiece& application_name_match_pattern)
+ : AccessibilityEventRecorder(manager) {
+ CHECK(!instance_) << "There can be only one instance of"
+ << " AccessibilityEventRecorder at a time.";
// For now, just use out of context events when running as a utility to watch
// events (no BrowserAccessibilityManager), because otherwise Chrome events
// are not getting reported. Being in context is better so that for
@@ -151,10 +165,12 @@ AccessibilityEventRecorderWin::AccessibilityEventRecorderWin(
0, // Hook all threads
context);
CHECK(win_event_hook_handle_);
+ instance_ = this;
}
AccessibilityEventRecorderWin::~AccessibilityEventRecorderWin() {
UnhookWinEvent(win_event_hook_handle_);
+ instance_ = nullptr;
}
void AccessibilityEventRecorderWin::OnWinEventHook(
@@ -194,8 +210,33 @@ void AccessibilityEventRecorderWin::OnWinEventHook(
return;
}
+ std::string event_str = AccessibilityEventToStringUTF8(event);
+ if (event_str.empty()) {
+ VLOG(1) << "Ignoring event " << event;
+ return;
+ }
+
+ base::win::ScopedVariant childid_self(CHILDID_SELF);
+ base::win::ScopedVariant role;
+ iaccessible->get_accRole(childid_self, role.Receive());
+ base::win::ScopedVariant state;
+ iaccessible->get_accState(childid_self, state.Receive());
+ int ia_state = V_I4(state.ptr());
+ std::string hwnd_class_name = base::UTF16ToUTF8(gfx::GetClassName(hwnd));
+
+ // Caret is special:
+ // Log all caret events that occur, with their window class, so that we can
+ // test to make sure they are only occurring on the desired window class.
+ if (ROLE_SYSTEM_CARET == V_I4(role.ptr())) {
+ base::string16 state_str = IAccessibleStateToString(ia_state);
+ std::string log = base::StringPrintf(
+ "%s role=ROLE_SYSTEM_CARET %ls window_class=%s", event_str.c_str(),
+ state_str.c_str(), hwnd_class_name.c_str());
+ OnEvent(log);
+ return;
+ }
+
if (only_web_events_) {
- std::string hwnd_class_name = base::UTF16ToUTF8(gfx::GetClassName(hwnd));
if (hwnd_class_name != "Chrome_RenderWidgetHostHWND")
return;
@@ -211,22 +252,10 @@ void AccessibilityEventRecorderWin::OnWinEventHook(
return;
}
- std::string event_str = AccessibilityEventToStringUTF8(event);
- if (event_str.empty()) {
- VLOG(1) << "Ignoring event " << event;
- return;
- }
-
- base::win::ScopedVariant childid_self(CHILDID_SELF);
- base::win::ScopedVariant role;
- iaccessible->get_accRole(childid_self, role.Receive());
base::win::ScopedBstr name_bstr;
iaccessible->get_accName(childid_self, name_bstr.Receive());
base::win::ScopedBstr value_bstr;
iaccessible->get_accValue(childid_self, value_bstr.Receive());
- base::win::ScopedVariant state;
- iaccessible->get_accState(childid_self, state.Receive());
- int ia_state = V_I4(state.ptr());
// Avoid flakiness. Events fired on a WINDOW are out of the control
// of a test.
diff --git a/chromium/content/browser/accessibility/accessibility_mode_browsertest.cc b/chromium/content/browser/accessibility/accessibility_mode_browsertest.cc
index 8bbb7346b01..c68ecf5396a 100644
--- a/chromium/content/browser/accessibility/accessibility_mode_browsertest.cc
+++ b/chromium/content/browser/accessibility/accessibility_mode_browsertest.cc
@@ -18,7 +18,7 @@
#include "content/shell/browser/shell.h"
#include "content/test/accessibility_browser_test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/accessibility/ax_modes.h"
+#include "ui/accessibility/ax_mode.h"
namespace content {
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter.h b/chromium/content/browser/accessibility/accessibility_tree_formatter.h
index 51b8bc52c6a..7dc41adf79c 100644
--- a/chromium/content/browser/accessibility/accessibility_tree_formatter.h
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter.h
@@ -13,6 +13,7 @@
#include "base/macros.h"
#include "base/process/process_handle.h"
#include "base/strings/string16.h"
+#include "base/strings/string_piece.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "content/browser/accessibility/browser_accessibility.h"
@@ -89,6 +90,11 @@ class CONTENT_EXPORT AccessibilityTreeFormatter {
virtual std::unique_ptr<base::DictionaryValue>
BuildAccessibilityTreeForWindow(gfx::AcceleratedWidget widget) = 0;
+ // Build an accessibility tree for an application with a name matching the
+ // given pattern.
+ virtual std::unique_ptr<base::DictionaryValue>
+ BuildAccessibilityTreeForPattern(const base::StringPiece& pattern) = 0;
+
// Returns a filtered accesibility tree using the current filters.
std::unique_ptr<base::DictionaryValue> FilterAccessibilityTree(
const base::DictionaryValue& dict);
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter_auralinux.cc b/chromium/content/browser/accessibility/accessibility_tree_formatter_auralinux.cc
index 596b7d7ebc6..91baaa6c28a 100644
--- a/chromium/content/browser/accessibility/accessibility_tree_formatter_auralinux.cc
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter_auralinux.cc
@@ -4,23 +4,31 @@
#include "content/browser/accessibility/accessibility_tree_formatter_browser.h"
+#include <atspi/atspi.h>
+#include <dbus/dbus.h>
+
+#include <iostream>
#include <utility>
#include "base/logging.h"
+#include "base/strings/pattern.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
+#include "content/browser/accessibility/accessibility_tree_formatter_utils_auralinux.h"
#include "content/browser/accessibility/browser_accessibility_auralinux.h"
#include "ui/accessibility/platform/ax_platform_node_auralinux.h"
+#include "ui/base/x/x11_util.h"
+#include "ui/gfx/x/x11.h"
namespace content {
class AccessibilityTreeFormatterAuraLinux
: public AccessibilityTreeFormatterBrowser {
public:
- explicit AccessibilityTreeFormatterAuraLinux();
+ AccessibilityTreeFormatterAuraLinux();
~AccessibilityTreeFormatterAuraLinux() override;
private:
@@ -30,9 +38,24 @@ class AccessibilityTreeFormatterAuraLinux
const std::string GetDenyString() override;
void AddProperties(const BrowserAccessibility& node,
base::DictionaryValue* dict) override;
+
base::string16 ProcessTreeForOutput(
const base::DictionaryValue& node,
base::DictionaryValue* filtered_dict_result = nullptr) override;
+
+ std::unique_ptr<base::DictionaryValue> BuildAccessibilityTreeForProcess(
+ base::ProcessId pid) override;
+ std::unique_ptr<base::DictionaryValue> BuildAccessibilityTreeForWindow(
+ gfx::AcceleratedWidget hwnd) override;
+ std::unique_ptr<base::DictionaryValue> BuildAccessibilityTreeForPattern(
+ const base::StringPiece& pattern) override;
+ std::unique_ptr<base::DictionaryValue> BuildAccessibilityTreeWithNode(
+ AtspiAccessible* node);
+
+ void RecursiveBuildAccessibilityTree(AtspiAccessible* node,
+ base::DictionaryValue* dict);
+ virtual void AddProperties(AtspiAccessible* node,
+ base::DictionaryValue* dict);
};
// static
@@ -46,16 +69,176 @@ AccessibilityTreeFormatterAuraLinux::AccessibilityTreeFormatterAuraLinux() {
AccessibilityTreeFormatterAuraLinux::~AccessibilityTreeFormatterAuraLinux() {
}
+std::unique_ptr<base::DictionaryValue>
+AccessibilityTreeFormatterAuraLinux::BuildAccessibilityTreeForPattern(
+ const base::StringPiece& pattern) {
+ // AT-SPI2 always expects the first parameter to this call to be zero.
+ AtspiAccessible* desktop = atspi_get_desktop(0);
+ CHECK(desktop);
+
+ GError* error = nullptr;
+ int child_count = atspi_accessible_get_child_count(desktop, &error);
+ if (error) {
+ LOG(ERROR) << "Failed to get children of root accessible object"
+ << error->message;
+ g_clear_error(&error);
+ return nullptr;
+ }
+
+ std::vector<std::pair<std::string, AtspiAccessible*>> matched_children;
+ for (int i = 0; i < child_count; i++) {
+ AtspiAccessible* child =
+ atspi_accessible_get_child_at_index(desktop, i, &error);
+ if (error) {
+ g_clear_error(&error);
+ continue;
+ }
+
+ char* name = atspi_accessible_get_name(child, &error);
+ if (!error && name && base::MatchPattern(name, pattern)) {
+ matched_children.push_back(std::make_pair(name, child));
+ }
+
+ free(name);
+ }
+
+ if (matched_children.size() == 1) {
+ return BuildAccessibilityTreeWithNode(matched_children[0].second);
+ }
+
+ if (matched_children.size()) {
+ LOG(ERROR) << "Matched more than one application. "
+ << "Try to make a more specific pattern.";
+ for (auto& match : matched_children) {
+ LOG(ERROR) << " * " << match.first;
+ }
+ }
+
+ return nullptr;
+}
+
+std::unique_ptr<base::DictionaryValue>
+AccessibilityTreeFormatterAuraLinux::BuildAccessibilityTreeForProcess(
+ base::ProcessId pid) {
+ LOG(ERROR) << "Aura Linux does not yet support building trees for processes";
+ NOTIMPLEMENTED();
+ return nullptr;
+}
+
+std::unique_ptr<base::DictionaryValue>
+AccessibilityTreeFormatterAuraLinux::BuildAccessibilityTreeForWindow(
+ gfx::AcceleratedWidget window) {
+ LOG(ERROR) << "Aura Linux does not yet support building trees for window ids";
+ NOTIMPLEMENTED();
+ return nullptr;
+}
+
+std::unique_ptr<base::DictionaryValue>
+AccessibilityTreeFormatterAuraLinux::BuildAccessibilityTreeWithNode(
+ AtspiAccessible* node) {
+ CHECK(node);
+
+ std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
+ RecursiveBuildAccessibilityTree(node, dict.get());
+
+ return dict;
+}
+
+void AccessibilityTreeFormatterAuraLinux::RecursiveBuildAccessibilityTree(
+ AtspiAccessible* node,
+ base::DictionaryValue* dict) {
+ AddProperties(node, dict);
+
+ GError* error = nullptr;
+ int child_count = atspi_accessible_get_child_count(node, &error);
+ if (error) {
+ g_clear_error(&error);
+ return;
+ }
+
+ if (child_count <= 0)
+ return;
+
+ auto children = std::make_unique<base::ListValue>();
+ for (int i = 0; i < child_count; i++) {
+ std::unique_ptr<base::DictionaryValue> child_dict(
+ new base::DictionaryValue);
+
+ AtspiAccessible* child =
+ atspi_accessible_get_child_at_index(node, i, &error);
+ if (error) {
+ child_dict->SetString("error", "[Error retrieving child]");
+ g_clear_error(&error);
+ continue;
+ }
+
+ CHECK(child);
+ RecursiveBuildAccessibilityTree(child, child_dict.get());
+ children->Append(std::move(child_dict));
+ }
+
+ dict->Set(kChildrenDictAttr, std::move(children));
+}
+
void AccessibilityTreeFormatterAuraLinux::AddProperties(
const BrowserAccessibility& node,
base::DictionaryValue* dict) {
dict->SetInteger("id", node.GetId());
BrowserAccessibilityAuraLinux* acc_obj =
ToBrowserAccessibilityAuraLinux(const_cast<BrowserAccessibility*>(&node));
-
acc_obj->GetNode()->AddAccessibilityTreeProperties(dict);
}
+void AccessibilityTreeFormatterAuraLinux::AddProperties(
+ AtspiAccessible* node,
+ base::DictionaryValue* dict) {
+ GError* error = nullptr;
+ char* role_name = atspi_accessible_get_role_name(node, &error);
+ if (!error)
+ dict->SetString("role", role_name);
+ g_clear_error(&error);
+ free(role_name);
+
+ char* name = atspi_accessible_get_name(node, &error);
+ if (!error)
+ dict->SetString("name", name);
+ g_clear_error(&error);
+ free(name);
+
+ error = nullptr;
+ char* description = atspi_accessible_get_description(node, &error);
+ if (!error)
+ dict->SetString("description", description);
+ g_clear_error(&error);
+ free(description);
+
+ error = nullptr;
+ GHashTable* attributes = atspi_accessible_get_attributes(node, &error);
+ if (!error) {
+ GHashTableIter i;
+ void* key = nullptr;
+ void* value = nullptr;
+
+ g_hash_table_iter_init(&i, attributes);
+ while (g_hash_table_iter_next(&i, &key, &value)) {
+ dict->SetString(static_cast<char*>(key), static_cast<char*>(value));
+ }
+ }
+ g_clear_error(&error);
+ g_hash_table_unref(attributes);
+
+ AtspiStateSet* atspi_states = atspi_accessible_get_state_set(node);
+ GArray* state_array = atspi_state_set_get_states(atspi_states);
+ auto states = std::make_unique<base::ListValue>();
+ for (unsigned i = 0; i < state_array->len; i++) {
+ AtspiStateType state_type = g_array_index(state_array, AtspiStateType, i);
+ states->AppendString(ATSPIStateToString(state_type));
+ }
+ dict->Set("states", std::move(states));
+ g_array_free(state_array, TRUE);
+ g_object_unref(atspi_states);
+}
+
const char* const ATK_OBJECT_ATTRIBUTES[] = {
"atomic",
"autocomplete",
@@ -120,8 +303,7 @@ base::string16 AccessibilityTreeFormatterAuraLinux::ProcessTreeForOutput(
const base::ListValue* states_value;
node.GetList("states", &states_value);
- for (base::ListValue::const_iterator it = states_value->begin();
- it != states_value->end(); ++it) {
+ for (auto it = states_value->begin(); it != states_value->end(); ++it) {
std::string state_value;
if (it->GetAsString(&state_value))
WriteAttribute(false, state_value, &line);
@@ -161,4 +343,4 @@ const std::string AccessibilityTreeFormatterAuraLinux::GetDenyString() {
return "@AURALINUX-DENY:";
}
-}
+} // namespace content
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter_blink.cc b/chromium/content/browser/accessibility/accessibility_tree_formatter_blink.cc
index 50f1d01015b..69d5f617bae 100644
--- a/chromium/content/browser/accessibility/accessibility_tree_formatter_blink.cc
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter_blink.cc
@@ -35,7 +35,7 @@ const char* STATE_OFFSCREEN = "offscreen";
uint32_t AccessibilityTreeFormatterBlink::ChildCount(
const BrowserAccessibility& node) const {
- if (node.HasIntAttribute(ax::mojom::IntAttribute::kChildTreeId))
+ if (node.HasStringAttribute(ax::mojom::StringAttribute::kChildTreeId))
return node.PlatformChildCount();
else
return node.InternalChildCount();
@@ -44,7 +44,7 @@ uint32_t AccessibilityTreeFormatterBlink::ChildCount(
BrowserAccessibility* AccessibilityTreeFormatterBlink::GetChild(
const BrowserAccessibility& node,
uint32_t i) const {
- if (node.HasIntAttribute(ax::mojom::IntAttribute::kChildTreeId))
+ if (node.HasStringAttribute(ax::mojom::StringAttribute::kChildTreeId))
return node.PlatformGetChild(i);
else
return node.InternalGetChild(i);
@@ -92,7 +92,6 @@ std::string AccessibilityTreeFormatterBlink::IntAttrToString(
case ax::mojom::IntAttribute::kAriaColumnCount:
case ax::mojom::IntAttribute::kAriaRowCount:
case ax::mojom::IntAttribute::kBackgroundColor:
- case ax::mojom::IntAttribute::kChildTreeId:
case ax::mojom::IntAttribute::kColor:
case ax::mojom::IntAttribute::kColorValue:
case ax::mojom::IntAttribute::kDetailsId:
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter_browser.cc b/chromium/content/browser/accessibility/accessibility_tree_formatter_browser.cc
index fa5142f04df..3157cc7050b 100644
--- a/chromium/content/browser/accessibility/accessibility_tree_formatter_browser.cc
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter_browser.cc
@@ -30,6 +30,13 @@ AccessibilityTreeFormatterBrowser::BuildAccessibilityTreeForWindow(
return nullptr;
}
+std::unique_ptr<base::DictionaryValue>
+AccessibilityTreeFormatterBrowser::BuildAccessibilityTreeForPattern(
+ const base::StringPiece& pattern) {
+ NOTREACHED();
+ return nullptr;
+}
+
void AccessibilityTreeFormatterBrowser::RecursiveBuildAccessibilityTree(
const BrowserAccessibility& node,
base::DictionaryValue* dict) {
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter_browser.h b/chromium/content/browser/accessibility/accessibility_tree_formatter_browser.h
index b91c9debdc3..c5713fd3367 100644
--- a/chromium/content/browser/accessibility/accessibility_tree_formatter_browser.h
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter_browser.h
@@ -31,6 +31,9 @@ class CONTENT_EXPORT AccessibilityTreeFormatterBrowser
std::unique_ptr<base::DictionaryValue> BuildAccessibilityTreeForWindow(
gfx::AcceleratedWidget widget) override;
+ std::unique_ptr<base::DictionaryValue> BuildAccessibilityTreeForPattern(
+ const base::StringPiece& pattern) override;
+
protected:
void RecursiveBuildAccessibilityTree(const BrowserAccessibility& node,
base::DictionaryValue* dict);
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter_mac.mm b/chromium/content/browser/accessibility/accessibility_tree_formatter_mac.mm
index a63ae0b7b07..72b0c9164e8 100644
--- a/chromium/content/browser/accessibility/accessibility_tree_formatter_mac.mm
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter_mac.mm
@@ -143,72 +143,68 @@ std::unique_ptr<base::Value> PopulateObject(id value) {
SysNSStringToUTF16([NSString stringWithFormat:@"%@", value])));
}
-NSArray* BuildAllAttributesArray() {
- // Note: clang-format tries to put multiple attributes on one line,
- // but we prefer to have one per line for readability.
- // clang-format off
- NSArray* array = [NSArray arrayWithObjects:
- NSAccessibilityRoleDescriptionAttribute,
- NSAccessibilityTitleAttribute,
- NSAccessibilityValueAttribute,
- NSAccessibilityMinValueAttribute,
- NSAccessibilityMaxValueAttribute,
- NSAccessibilityValueDescriptionAttribute,
- NSAccessibilityDescriptionAttribute,
- NSAccessibilityHelpAttribute,
- @"AXInvalid",
- NSAccessibilityDisclosingAttribute,
- NSAccessibilityDisclosureLevelAttribute,
- @"AXAccessKey",
- @"AXARIAAtomic",
- @"AXARIABusy",
- @"AXARIAColumnCount",
- @"AXARIAColumnIndex",
- @"AXARIALive",
- @"AXARIARelevant",
- @"AXARIARowCount",
- @"AXARIARowIndex",
- @"AXARIASetSize",
- @"AXARIAPosInSet",
- @"AXAutocomplete",
- @"AXAutocompleteValue",
- NSAccessibilityColumnHeaderUIElementsAttribute,
- NSAccessibilityColumnIndexRangeAttribute,
- @"AXDOMIdentifier",
- @"AXDropEffects",
- @"AXEditableAncestor",
- NSAccessibilityEnabledAttribute,
- NSAccessibilityExpandedAttribute,
- @"AXFocusableAncestor",
- NSAccessibilityFocusedAttribute,
- @"AXGrabbed",
- NSAccessibilityHeaderAttribute,
- @"AXHasPopup",
- @"AXHasPopupValue",
- @"AXHighestEditableAncestor",
- NSAccessibilityIndexAttribute,
- @"AXLanguage",
- @"AXLoaded",
- @"AXLoadingProcess",
- NSAccessibilityNumberOfCharactersAttribute,
- NSAccessibilitySortDirectionAttribute,
- NSAccessibilityOrientationAttribute,
- NSAccessibilityPlaceholderValueAttribute,
- @"AXRequired",
- NSAccessibilityRowHeaderUIElementsAttribute,
- NSAccessibilityRowIndexRangeAttribute,
- NSAccessibilitySelectedAttribute,
- NSAccessibilitySelectedChildrenAttribute,
- NSAccessibilityTitleUIElementAttribute,
- NSAccessibilityURLAttribute,
- NSAccessibilityVisibleCharacterRangeAttribute,
- NSAccessibilityVisibleChildrenAttribute,
- @"AXVisited",
- @"AXLinkedUIElements",
- nil];
- // clang-format off
-
- return [array retain];
+NSArray* AllAttributesArray() {
+ static NSArray* all_attributes = [@[
+ NSAccessibilityRoleDescriptionAttribute,
+ NSAccessibilityTitleAttribute,
+ NSAccessibilityValueAttribute,
+ NSAccessibilityMinValueAttribute,
+ NSAccessibilityMaxValueAttribute,
+ NSAccessibilityValueDescriptionAttribute,
+ NSAccessibilityDescriptionAttribute,
+ NSAccessibilityHelpAttribute,
+ @"AXInvalid",
+ NSAccessibilityDisclosingAttribute,
+ NSAccessibilityDisclosureLevelAttribute,
+ @"AXAccessKey",
+ @"AXARIAAtomic",
+ @"AXARIABusy",
+ @"AXARIAColumnCount",
+ @"AXARIAColumnIndex",
+ @"AXARIALive",
+ @"AXARIARelevant",
+ @"AXARIARowCount",
+ @"AXARIARowIndex",
+ @"AXARIASetSize",
+ @"AXARIAPosInSet",
+ @"AXAutocomplete",
+ @"AXAutocompleteValue",
+ NSAccessibilityColumnHeaderUIElementsAttribute,
+ NSAccessibilityColumnIndexRangeAttribute,
+ @"AXDOMIdentifier",
+ @"AXDropEffects",
+ @"AXEditableAncestor",
+ NSAccessibilityEnabledAttribute,
+ NSAccessibilityExpandedAttribute,
+ @"AXFocusableAncestor",
+ NSAccessibilityFocusedAttribute,
+ @"AXGrabbed",
+ NSAccessibilityHeaderAttribute,
+ @"AXHasPopup",
+ @"AXHasPopupValue",
+ @"AXHighestEditableAncestor",
+ NSAccessibilityIndexAttribute,
+ @"AXLanguage",
+ @"AXLoaded",
+ @"AXLoadingProcess",
+ NSAccessibilityNumberOfCharactersAttribute,
+ NSAccessibilitySortDirectionAttribute,
+ NSAccessibilityOrientationAttribute,
+ NSAccessibilityPlaceholderValueAttribute,
+ @"AXRequired",
+ NSAccessibilityRowHeaderUIElementsAttribute,
+ NSAccessibilityRowIndexRangeAttribute,
+ NSAccessibilitySelectedAttribute,
+ NSAccessibilitySelectedChildrenAttribute,
+ NSAccessibilityTitleUIElementAttribute,
+ NSAccessibilityURLAttribute,
+ NSAccessibilityVisibleCharacterRangeAttribute,
+ NSAccessibilityVisibleChildrenAttribute,
+ @"AXVisited",
+ @"AXLinkedUIElements"
+ ] retain];
+
+ return all_attributes;
}
} // namespace
@@ -259,8 +255,7 @@ void AccessibilityTreeFormatterMac::AddProperties(
SysNSStringToUTF8(subrole));
}
- CR_DEFINE_STATIC_LOCAL(NSArray*, all_attributes, (BuildAllAttributesArray()));
- for (NSString* requestedAttribute in all_attributes) {
+ for (NSString* requestedAttribute in AllAttributesArray()) {
if (![supportedAttributes containsObject:requestedAttribute])
continue;
id value = [cocoa_node accessibilityAttributeValue:requestedAttribute];
@@ -307,8 +302,7 @@ base::string16 AccessibilityTreeFormatterMac::ProcessTreeForOutput(
&line);
}
- CR_DEFINE_STATIC_LOCAL(NSArray*, all_attributes, (BuildAllAttributesArray()));
- for (NSString* requestedAttribute in all_attributes) {
+ for (NSString* requestedAttribute in AllAttributesArray()) {
string requestedAttributeUTF8 = SysNSStringToUTF8(requestedAttribute);
if (dict.GetString(requestedAttributeUTF8, &s_value)) {
WriteAttribute([defaultAttributes containsObject:requestedAttribute],
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter_utils_auralinux.cc b/chromium/content/browser/accessibility/accessibility_tree_formatter_utils_auralinux.cc
new file mode 100644
index 00000000000..976c1f8d26b
--- /dev/null
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter_utils_auralinux.cc
@@ -0,0 +1,238 @@
+// 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/browser/accessibility/accessibility_tree_formatter_utils_auralinux.h"
+
+#include "base/stl_util.h"
+
+namespace content {
+namespace {
+struct PlatformConstantToNameEntry {
+ int32_t value;
+ const char* name;
+};
+
+const char* GetNameForPlatformConstant(
+ const PlatformConstantToNameEntry table[],
+ size_t table_size,
+ int32_t value) {
+ for (size_t i = 0; i < table_size; ++i) {
+ auto& entry = table[i];
+ if (entry.value == value)
+ return entry.name;
+ }
+ return "<unknown>";
+}
+} // namespace
+
+#define QUOTE(X) \
+ { X, #X }
+
+#define ATSPI_CHECK_VERSION(major, minor, micro) \
+ (major) < ATSPI_MAJOR_VERSION || \
+ ((major) == ATSPI_MAJOR_VERSION && (minor) < ATSPI_MINOR_VERSION) || \
+ ((major) == ATSPI_MAJOR_VERSION && (minor) == ATSPI_MINOR_VERSION && \
+ (micro) <= ATSPI_MICRO_VERSION)
+
+CONTENT_EXPORT const char* ATSPIStateToString(AtspiStateType state) {
+ // These roles are listed in the order they are defined in the enum so that
+ // we can more easily discard ones that are too new for the version of
+ // atspi2 that we are compiling against.
+ static const PlatformConstantToNameEntry state_table[] = {
+ QUOTE(ATSPI_STATE_INVALID),
+ QUOTE(ATSPI_STATE_ACTIVE),
+ QUOTE(ATSPI_STATE_ARMED),
+ QUOTE(ATSPI_STATE_BUSY),
+ QUOTE(ATSPI_STATE_CHECKED),
+ QUOTE(ATSPI_STATE_COLLAPSED),
+ QUOTE(ATSPI_STATE_DEFUNCT),
+ QUOTE(ATSPI_STATE_EDITABLE),
+ QUOTE(ATSPI_STATE_ENABLED),
+ QUOTE(ATSPI_STATE_EXPANDABLE),
+ QUOTE(ATSPI_STATE_EXPANDED),
+ QUOTE(ATSPI_STATE_FOCUSABLE),
+ QUOTE(ATSPI_STATE_FOCUSED),
+ QUOTE(ATSPI_STATE_HAS_TOOLTIP),
+ QUOTE(ATSPI_STATE_HORIZONTAL),
+ QUOTE(ATSPI_STATE_ICONIFIED),
+ QUOTE(ATSPI_STATE_MODAL),
+ QUOTE(ATSPI_STATE_MULTI_LINE),
+ QUOTE(ATSPI_STATE_MULTISELECTABLE),
+ QUOTE(ATSPI_STATE_OPAQUE),
+ QUOTE(ATSPI_STATE_PRESSED),
+ QUOTE(ATSPI_STATE_RESIZABLE),
+ QUOTE(ATSPI_STATE_SELECTABLE),
+ QUOTE(ATSPI_STATE_SELECTED),
+ QUOTE(ATSPI_STATE_SENSITIVE),
+ QUOTE(ATSPI_STATE_SHOWING),
+ QUOTE(ATSPI_STATE_SINGLE_LINE),
+ QUOTE(ATSPI_STATE_STALE),
+ QUOTE(ATSPI_STATE_TRANSIENT),
+ QUOTE(ATSPI_STATE_VERTICAL),
+ QUOTE(ATSPI_STATE_VISIBLE),
+ QUOTE(ATSPI_STATE_MANAGES_DESCENDANTS),
+ QUOTE(ATSPI_STATE_INDETERMINATE),
+ QUOTE(ATSPI_STATE_REQUIRED),
+ QUOTE(ATSPI_STATE_TRUNCATED),
+ QUOTE(ATSPI_STATE_ANIMATED),
+ QUOTE(ATSPI_STATE_INVALID_ENTRY),
+ QUOTE(ATSPI_STATE_SUPPORTS_AUTOCOMPLETION),
+ QUOTE(ATSPI_STATE_SELECTABLE_TEXT),
+ QUOTE(ATSPI_STATE_IS_DEFAULT),
+ QUOTE(ATSPI_STATE_VISITED),
+#if ATSPI_CHECK_VERSION(2, 12, 0)
+ QUOTE(ATSPI_STATE_CHECKABLE),
+ QUOTE(ATSPI_STATE_HAS_POPUP),
+#endif
+#if ATSPI_CHECK_VERSION(2, 16, 0)
+ QUOTE(ATSPI_STATE_READ_ONLY),
+#endif
+ };
+
+ return GetNameForPlatformConstant(state_table, base::size(state_table),
+ state);
+}
+
+CONTENT_EXPORT const char* ATSPIRoleToString(AtspiRole role) {
+ // These roles are listed in the order they are defined in the enum so that
+ // we can more easily discard ones that are too new for the version of
+ // atspi2 that we are compiling against.
+ static const PlatformConstantToNameEntry role_table[] = {
+ QUOTE(ATSPI_ROLE_INVALID),
+ QUOTE(ATSPI_ROLE_ACCELERATOR_LABEL),
+ QUOTE(ATSPI_ROLE_ALERT),
+ QUOTE(ATSPI_ROLE_ANIMATION),
+ QUOTE(ATSPI_ROLE_ARROW),
+ QUOTE(ATSPI_ROLE_CALENDAR),
+ QUOTE(ATSPI_ROLE_CANVAS),
+ QUOTE(ATSPI_ROLE_CHECK_BOX),
+ QUOTE(ATSPI_ROLE_CHECK_MENU_ITEM),
+ QUOTE(ATSPI_ROLE_COLOR_CHOOSER),
+ QUOTE(ATSPI_ROLE_COLUMN_HEADER),
+ QUOTE(ATSPI_ROLE_COMBO_BOX),
+ QUOTE(ATSPI_ROLE_DATE_EDITOR),
+ QUOTE(ATSPI_ROLE_DESKTOP_ICON),
+ QUOTE(ATSPI_ROLE_DESKTOP_FRAME),
+ QUOTE(ATSPI_ROLE_DIAL),
+ QUOTE(ATSPI_ROLE_DIALOG),
+ QUOTE(ATSPI_ROLE_DIRECTORY_PANE),
+ QUOTE(ATSPI_ROLE_DRAWING_AREA),
+ QUOTE(ATSPI_ROLE_FILE_CHOOSER),
+ QUOTE(ATSPI_ROLE_FILLER),
+ QUOTE(ATSPI_ROLE_FOCUS_TRAVERSABLE),
+ QUOTE(ATSPI_ROLE_FONT_CHOOSER),
+ QUOTE(ATSPI_ROLE_FRAME),
+ QUOTE(ATSPI_ROLE_GLASS_PANE),
+ QUOTE(ATSPI_ROLE_HTML_CONTAINER),
+ QUOTE(ATSPI_ROLE_ICON),
+ QUOTE(ATSPI_ROLE_IMAGE),
+ QUOTE(ATSPI_ROLE_INTERNAL_FRAME),
+ QUOTE(ATSPI_ROLE_LABEL),
+ QUOTE(ATSPI_ROLE_LAYERED_PANE),
+ QUOTE(ATSPI_ROLE_LIST),
+ QUOTE(ATSPI_ROLE_LIST_ITEM),
+ QUOTE(ATSPI_ROLE_MENU),
+ QUOTE(ATSPI_ROLE_MENU_BAR),
+ QUOTE(ATSPI_ROLE_MENU_ITEM),
+ QUOTE(ATSPI_ROLE_OPTION_PANE),
+ QUOTE(ATSPI_ROLE_PAGE_TAB),
+ QUOTE(ATSPI_ROLE_PAGE_TAB_LIST),
+ QUOTE(ATSPI_ROLE_PANEL),
+ QUOTE(ATSPI_ROLE_PASSWORD_TEXT),
+ QUOTE(ATSPI_ROLE_POPUP_MENU),
+ QUOTE(ATSPI_ROLE_PROGRESS_BAR),
+ QUOTE(ATSPI_ROLE_PUSH_BUTTON),
+ QUOTE(ATSPI_ROLE_RADIO_BUTTON),
+ QUOTE(ATSPI_ROLE_RADIO_MENU_ITEM),
+ QUOTE(ATSPI_ROLE_ROOT_PANE),
+ QUOTE(ATSPI_ROLE_ROW_HEADER),
+ QUOTE(ATSPI_ROLE_SCROLL_BAR),
+ QUOTE(ATSPI_ROLE_SCROLL_PANE),
+ QUOTE(ATSPI_ROLE_SEPARATOR),
+ QUOTE(ATSPI_ROLE_SLIDER),
+ QUOTE(ATSPI_ROLE_SPIN_BUTTON),
+ QUOTE(ATSPI_ROLE_SPLIT_PANE),
+ QUOTE(ATSPI_ROLE_STATUS_BAR),
+ QUOTE(ATSPI_ROLE_TABLE),
+ QUOTE(ATSPI_ROLE_TABLE_CELL),
+ QUOTE(ATSPI_ROLE_TABLE_COLUMN_HEADER),
+ QUOTE(ATSPI_ROLE_TABLE_ROW_HEADER),
+ QUOTE(ATSPI_ROLE_TEAROFF_MENU_ITEM),
+ QUOTE(ATSPI_ROLE_TERMINAL),
+ QUOTE(ATSPI_ROLE_TEXT),
+ QUOTE(ATSPI_ROLE_TOGGLE_BUTTON),
+ QUOTE(ATSPI_ROLE_TOOL_BAR),
+ QUOTE(ATSPI_ROLE_TOOL_TIP),
+ QUOTE(ATSPI_ROLE_TREE),
+ QUOTE(ATSPI_ROLE_TREE_TABLE),
+ QUOTE(ATSPI_ROLE_UNKNOWN),
+ QUOTE(ATSPI_ROLE_VIEWPORT),
+ QUOTE(ATSPI_ROLE_WINDOW),
+ QUOTE(ATSPI_ROLE_EXTENDED),
+ QUOTE(ATSPI_ROLE_HEADER),
+ QUOTE(ATSPI_ROLE_FOOTER),
+ QUOTE(ATSPI_ROLE_PARAGRAPH),
+ QUOTE(ATSPI_ROLE_RULER),
+ QUOTE(ATSPI_ROLE_APPLICATION),
+ QUOTE(ATSPI_ROLE_AUTOCOMPLETE),
+ QUOTE(ATSPI_ROLE_EDITBAR),
+ QUOTE(ATSPI_ROLE_EMBEDDED),
+ QUOTE(ATSPI_ROLE_ENTRY),
+ QUOTE(ATSPI_ROLE_CHART),
+ QUOTE(ATSPI_ROLE_CAPTION),
+ QUOTE(ATSPI_ROLE_DOCUMENT_FRAME),
+ QUOTE(ATSPI_ROLE_HEADING),
+ QUOTE(ATSPI_ROLE_PAGE),
+ QUOTE(ATSPI_ROLE_SECTION),
+ QUOTE(ATSPI_ROLE_REDUNDANT_OBJECT),
+ QUOTE(ATSPI_ROLE_FORM),
+ QUOTE(ATSPI_ROLE_LINK),
+ QUOTE(ATSPI_ROLE_INPUT_METHOD_WINDOW),
+ QUOTE(ATSPI_ROLE_TABLE_ROW),
+ QUOTE(ATSPI_ROLE_TREE_ITEM),
+ QUOTE(ATSPI_ROLE_DOCUMENT_SPREADSHEET),
+ QUOTE(ATSPI_ROLE_DOCUMENT_PRESENTATION),
+ QUOTE(ATSPI_ROLE_DOCUMENT_TEXT),
+ QUOTE(ATSPI_ROLE_DOCUMENT_WEB),
+ QUOTE(ATSPI_ROLE_DOCUMENT_EMAIL),
+ QUOTE(ATSPI_ROLE_COMMENT),
+ QUOTE(ATSPI_ROLE_LIST_BOX),
+ QUOTE(ATSPI_ROLE_GROUPING),
+ QUOTE(ATSPI_ROLE_IMAGE_MAP),
+ QUOTE(ATSPI_ROLE_NOTIFICATION),
+ QUOTE(ATSPI_ROLE_INFO_BAR),
+ QUOTE(ATSPI_ROLE_LEVEL_BAR),
+#if ATSPI_CHECK_VERSION(2, 12, 0)
+ QUOTE(ATSPI_ROLE_TITLE_BAR),
+ QUOTE(ATSPI_ROLE_BLOCK_QUOTE),
+ QUOTE(ATSPI_ROLE_AUDIO),
+ QUOTE(ATSPI_ROLE_VIDEO),
+ QUOTE(ATSPI_ROLE_DEFINITION),
+ QUOTE(ATSPI_ROLE_ARTICLE),
+ QUOTE(ATSPI_ROLE_LANDMARK),
+ QUOTE(ATSPI_ROLE_LOG),
+ QUOTE(ATSPI_ROLE_MARQUEE),
+ QUOTE(ATSPI_ROLE_MATH),
+ QUOTE(ATSPI_ROLE_RATING),
+ QUOTE(ATSPI_ROLE_TIMER),
+#endif
+#if ATSPI_CHECK_VERSION(2, 16, 0)
+ QUOTE(ATSPI_ROLE_STATIC),
+ QUOTE(ATSPI_ROLE_MATH_FRACTION),
+ QUOTE(ATSPI_ROLE_MATH_ROOT),
+ QUOTE(ATSPI_ROLE_SUBSCRIPT),
+ QUOTE(ATSPI_ROLE_SUPERSCRIPT),
+#endif
+#if ATSPI_CHECK_VERSION(2, 26, 0)
+ QUOTE(ATSPI_ROLE_DESCRIPTION_LIST),
+ QUOTE(ATSPI_ROLE_DESCRIPTION_TERM),
+ QUOTE(ATSPI_ROLE_DESCRIPTION_VALUE),
+ QUOTE(ATSPI_ROLE_FOOTNOTE),
+#endif
+ };
+
+ return GetNameForPlatformConstant(role_table, base::size(role_table), role);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter_utils_auralinux.h b/chromium/content/browser/accessibility/accessibility_tree_formatter_utils_auralinux.h
new file mode 100644
index 00000000000..29dad1d2fea
--- /dev/null
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter_utils_auralinux.h
@@ -0,0 +1,19 @@
+// 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_ACCESSIBILITY_ACCESSIBILITY_TREE_FORMATTER_UTILS_AURALINUX_H_
+#define CONTENT_BROWSER_ACCESSIBILITY_ACCESSIBILITY_TREE_FORMATTER_UTILS_AURALINUX_H_
+
+#include <atspi/atspi.h>
+
+#include "content/common/content_export.h"
+
+namespace content {
+
+CONTENT_EXPORT const char* ATSPIStateToString(AtspiStateType state);
+CONTENT_EXPORT const char* ATSPIRoleToString(AtspiRole role);
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_ACCESSIBILITY_ACCESSIBILITY_TREE_FORMATTER_UTILS_AURALINUX_H_
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter_win.cc b/chromium/content/browser/accessibility/accessibility_tree_formatter_win.cc
index 20fd3b776fc..edcd636a3c3 100644
--- a/chromium/content/browser/accessibility/accessibility_tree_formatter_win.cc
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter_win.cc
@@ -10,6 +10,7 @@
#include <stdint.h>
#include <wrl/client.h>
+#include <iostream>
#include <string>
#include <utility>
@@ -70,6 +71,8 @@ class AccessibilityTreeFormatterWin : public AccessibilityTreeFormatter {
gfx::AcceleratedWidget hwnd) override;
std::unique_ptr<base::DictionaryValue> BuildAccessibilityTreeForProcess(
base::ProcessId pid) override;
+ std::unique_ptr<base::DictionaryValue> BuildAccessibilityTreeForPattern(
+ const base::StringPiece& pattern) override;
std::unique_ptr<base::DictionaryValue> BuildAccessibilityTree(
Microsoft::WRL::ComPtr<IAccessible> start,
LONG window_x = 0,
@@ -281,6 +284,14 @@ AccessibilityTreeFormatterWin::BuildAccessibilityTreeForProcess(
return BuildAccessibilityTreeForWindow(hwnd);
}
+std::unique_ptr<base::DictionaryValue>
+AccessibilityTreeFormatterWin::BuildAccessibilityTreeForPattern(
+ const base::StringPiece& pattern) {
+ LOG(ERROR) << "Windows does not yet support building accessibility trees for "
+ "patterns";
+ return nullptr;
+}
+
void AccessibilityTreeFormatterWin::RecursiveBuildAccessibilityTree(
const Microsoft::WRL::ComPtr<IAccessible> node,
base::DictionaryValue* dict,
diff --git a/chromium/content/browser/accessibility/accessibility_win_browsertest.cc b/chromium/content/browser/accessibility/accessibility_win_browsertest.cc
index 9bb5760cfdb..1813c91433c 100644
--- a/chromium/content/browser/accessibility/accessibility_win_browsertest.cc
+++ b/chromium/content/browser/accessibility/accessibility_win_browsertest.cc
@@ -76,6 +76,16 @@ class AccessibilityWinBrowserTest : public ContentBrowserTest {
void SetUpInputField(Microsoft::WRL::ComPtr<IAccessibleText>* input_text);
void SetUpScrollableInputField(
Microsoft::WRL::ComPtr<IAccessibleText>* input_text);
+ void SetUpSingleCharInputField(
+ Microsoft::WRL::ComPtr<IAccessibleText>* input_text);
+ void SetUpSingleCharInputFieldWithPlaceholder(
+ Microsoft::WRL::ComPtr<IAccessibleText>* input_text);
+ void SetUpSingleCharTextarea(
+ Microsoft::WRL::ComPtr<IAccessibleText>* input_text);
+ void SetUpSingleCharContenteditable(
+ Microsoft::WRL::ComPtr<IAccessibleText>* input_text);
+ void SetUpSingleCharRtlInputField(
+ Microsoft::WRL::ComPtr<IAccessibleText>* input_text);
void SetUpTextareaField(
Microsoft::WRL::ComPtr<IAccessibleText>* textarea_text);
void SetUpSampleParagraph(
@@ -201,6 +211,71 @@ void AccessibilityWinBrowserTest::SetUpScrollableInputField(
SetUpInputFieldHelper(input_text);
}
+// Loads a page with an input text field and places a single character in it.
+// Also tests with padding, in order to ensure character extent of empty field
+// does not erroneously include padding.
+void AccessibilityWinBrowserTest::SetUpSingleCharInputField(
+ Microsoft::WRL::ComPtr<IAccessibleText>* input_text) {
+ ASSERT_NE(nullptr, input_text);
+ LoadInitialAccessibilityTreeFromHtml(std::string(
+ R"HTML(<!DOCTYPE html>
+ <html>
+ <body>
+ <form>
+ <input type="text" value="x" style="padding:3px">
+ </form>
+ </body>
+ </html>)HTML"));
+ SetUpInputFieldHelper(input_text);
+}
+
+void AccessibilityWinBrowserTest::SetUpSingleCharInputFieldWithPlaceholder(
+ Microsoft::WRL::ComPtr<IAccessibleText>* input_text) {
+ ASSERT_NE(nullptr, input_text);
+ LoadInitialAccessibilityTreeFromHtml(std::string(
+ R"HTML(<!DOCTYPE html>
+ <html>
+ <body>
+ <form>
+ <input type="text" value="x" placeholder="placeholder">
+ </form>
+ </body>
+ </html>)HTML"));
+ SetUpInputFieldHelper(input_text);
+}
+
+void AccessibilityWinBrowserTest::SetUpSingleCharTextarea(
+ Microsoft::WRL::ComPtr<IAccessibleText>* input_text) {
+ ASSERT_NE(nullptr, input_text);
+ LoadInitialAccessibilityTreeFromHtml(std::string(
+ R"HTML(<!DOCTYPE html>
+ <html>
+ <body>
+ <form>
+ <textarea rows="3" cols="10">x</textarea>
+ </form>
+ </body>
+ </html>)HTML"));
+ SetUpInputFieldHelper(input_text);
+}
+
+// Loads a page with a right-to-left input text field and places a single
+// character in it.
+void AccessibilityWinBrowserTest::SetUpSingleCharRtlInputField(
+ Microsoft::WRL::ComPtr<IAccessibleText>* input_text) {
+ ASSERT_NE(nullptr, input_text);
+ LoadInitialAccessibilityTreeFromHtml(std::string(
+ R"HTML(<!DOCTYPE html>
+ <html>
+ <body>
+ <form>
+ <input type="text" id="textField" name="name" dir="rtl" value="x">
+ </form>
+ </body>
+ </html>)HTML"));
+ SetUpInputFieldHelper(input_text);
+}
+
void AccessibilityWinBrowserTest::SetUpInputFieldHelper(
Microsoft::WRL::ComPtr<IAccessibleText>* input_text) {
Microsoft::WRL::ComPtr<IAccessible> document(GetRendererAccessible());
@@ -237,12 +312,13 @@ void AccessibilityWinBrowserTest::SetUpInputFieldHelper(
ax::mojom::Event::kTextSelectionChanged);
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");"
- L"textField.scrollLeft = 1000;");
+ ExecuteScript(
+ std::wstring(L"let textField = document.querySelector('input,textarea');"
+ L"textField.focus();"
+ L"textField.setSelectionRange(") +
+ caret_offset + L"," + caret_offset +
+ L");"
+ L"textField.scrollLeft = 1000;");
waiter.WaitForNotification();
}
@@ -330,8 +406,9 @@ void AccessibilityWinBrowserTest::SetUpSampleParagraphInScrollableDocument(
LoadInitialAccessibilityTreeFromHtml(
R"HTML(<!DOCTYPE html>
<html>
- <body style="overflow: scroll; margin-top: 100vh">
- <p><b>Game theory</b> is "the study of
+ <body>
+ <p style="margin-top:50vh; margin-bottom:200vh">
+ <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."
@@ -771,10 +848,10 @@ class NativeWinEventWaiter {
NativeWinEventWaiter(BrowserAccessibilityManager* manager,
const std::string& match_pattern)
: event_recorder_(
- AccessibilityEventRecorder::GetInstance(manager,
- base::GetCurrentProcId())),
+ AccessibilityEventRecorder::Create(manager,
+ base::GetCurrentProcId())),
match_pattern_(match_pattern) {
- event_recorder_.ListenToEvents(base::BindRepeating(
+ event_recorder_->ListenToEvents(base::BindRepeating(
&NativeWinEventWaiter::OnEvent, base::Unretained(this)));
}
@@ -787,7 +864,7 @@ class NativeWinEventWaiter {
void Wait() { run_loop_.Run(); }
private:
- AccessibilityEventRecorder& event_recorder_;
+ std::unique_ptr<AccessibilityEventRecorder> event_recorder_;
std::string match_pattern_;
base::RunLoop run_loop_;
};
@@ -1244,6 +1321,15 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
EXPECT_LT(1, width) << "at offset " << offset;
EXPECT_EQ(previous_height, height) << "at offset " << offset;
}
+
+ // Past end of text.
+ EXPECT_HRESULT_SUCCEEDED(paragraph_text->get_characterExtents(
+ n_characters, coordinate_type, &x, &y, &width, &height));
+ EXPECT_LT(previous_x, x) << "at final offset " << n_characters;
+ EXPECT_EQ(previous_y, y) << "at final offset " << n_characters;
+ // Last character width past end should be 1, the width of a caret.
+ EXPECT_EQ(1, width) << "at final offset " << n_characters;
+ EXPECT_EQ(previous_height, height) << "at final offset " << n_characters;
}
}
@@ -1375,6 +1461,272 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
EXPECT_LT(1, width) << "at offset " << offset;
EXPECT_EQ(previous_height, height) << "at offset " << offset;
}
+ // Past end of text.
+ EXPECT_HRESULT_SUCCEEDED(input_text->get_characterExtents(
+ n_characters, coordinate_type, &x, &y, &width, &height));
+ EXPECT_LT(previous_x, x) << "at final offset " << n_characters;
+ EXPECT_EQ(previous_y, y) << "at final offset " << n_characters;
+ // Last character width past end should be 1, the width of a caret.
+ EXPECT_EQ(1, width) << "at final offset " << n_characters;
+ EXPECT_EQ(previous_height, height) << "at final offset " << n_characters;
+ }
+}
+
+IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
+ TestCharacterExtentsInEmptyInputField) {
+ Microsoft::WRL::ComPtr<IAccessibleText> input_text;
+ SetUpSingleCharInputField(&input_text);
+
+ LONG n_characters;
+ ASSERT_HRESULT_SUCCEEDED(input_text->get_nCharacters(&n_characters));
+ ASSERT_EQ(1, n_characters);
+
+ // Get the rect for the only character.
+ LONG prev_x, prev_y, prev_width, prev_height;
+ EXPECT_HRESULT_SUCCEEDED(input_text->get_characterExtents(
+ 0, IA2_COORDTYPE_SCREEN_RELATIVE, &prev_x, &prev_y, &prev_width,
+ &prev_height));
+
+ EXPECT_LT(1, prev_width);
+ EXPECT_LT(1, prev_height);
+
+ base::win::ScopedBstr text0;
+ ASSERT_HRESULT_SUCCEEDED(input_text->get_text(0, -1, text0.Receive()));
+
+ // Delete the character in the input field.
+ AccessibilityNotificationWaiter waiter(
+ shell()->web_contents(), ui::kAXModeComplete,
+ ax::mojom::Event::kTextSelectionChanged);
+ ExecuteScript(std::wstring(L"document.querySelector('input').value='';"));
+ waiter.WaitForNotification();
+
+ ASSERT_HRESULT_SUCCEEDED(input_text->get_nCharacters(&n_characters));
+ ASSERT_EQ(0, n_characters);
+ LONG caret_offset;
+ ASSERT_HRESULT_SUCCEEDED(input_text->get_caretOffset(&caret_offset));
+ ASSERT_EQ(0, caret_offset);
+
+ base::win::ScopedBstr text;
+ ASSERT_HRESULT_SUCCEEDED(input_text->get_text(0, -1, text.Receive()));
+
+ // Now that input is completely empty, the position of the caret should be
+ // returned for character 0. The x,y position and height should be the same as
+ // it was as when there was single character, but the width should now be 1.
+ LONG x, y, width, height;
+ for (int offset = IA2_TEXT_OFFSET_CARET; offset <= 0; ++offset) {
+ EXPECT_HRESULT_SUCCEEDED(input_text->get_characterExtents(
+ offset, IA2_COORDTYPE_SCREEN_RELATIVE, &x, &y, &width, &height));
+ EXPECT_EQ(prev_x, x);
+ EXPECT_EQ(prev_y, y);
+ EXPECT_EQ(1, width);
+ EXPECT_EQ(prev_height, height);
+ }
+}
+
+IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
+ TestCharacterExtentsInEmptyInputFieldWithPlaceholder) {
+ Microsoft::WRL::ComPtr<IAccessibleText> input_text;
+ SetUpSingleCharInputFieldWithPlaceholder(&input_text);
+
+ LONG n_characters;
+ ASSERT_HRESULT_SUCCEEDED(input_text->get_nCharacters(&n_characters));
+ ASSERT_EQ(1, n_characters);
+
+ // Get the rect for the only character.
+ LONG prev_x, prev_y, prev_width, prev_height;
+ EXPECT_HRESULT_SUCCEEDED(input_text->get_characterExtents(
+ 0, IA2_COORDTYPE_SCREEN_RELATIVE, &prev_x, &prev_y, &prev_width,
+ &prev_height));
+
+ EXPECT_LT(1, prev_width);
+ EXPECT_LT(1, prev_height);
+
+ base::win::ScopedBstr text0;
+ ASSERT_HRESULT_SUCCEEDED(input_text->get_text(0, -1, text0.Receive()));
+
+ // Delete the character in the input field.
+ AccessibilityNotificationWaiter waiter(
+ shell()->web_contents(), ui::kAXModeComplete,
+ ax::mojom::Event::kTextSelectionChanged);
+ ExecuteScript(std::wstring(L"document.querySelector('input').value='';"));
+ waiter.WaitForNotification();
+
+ ASSERT_HRESULT_SUCCEEDED(input_text->get_nCharacters(&n_characters));
+ ASSERT_EQ(0, n_characters);
+ LONG caret_offset;
+ ASSERT_HRESULT_SUCCEEDED(input_text->get_caretOffset(&caret_offset));
+ ASSERT_EQ(0, caret_offset);
+
+ base::win::ScopedBstr text;
+ ASSERT_HRESULT_SUCCEEDED(input_text->get_text(0, -1, text.Receive()));
+
+ // Now that input is completely empty, the position of the caret should be
+ // returned for character 0. The x,y position and height should be the same as
+ // it was as when there was single character, but the width should now be 1.
+ LONG x, y, width, height;
+ for (int offset = IA2_TEXT_OFFSET_CARET; offset <= 0; ++offset) {
+ EXPECT_HRESULT_SUCCEEDED(input_text->get_characterExtents(
+ offset, IA2_COORDTYPE_SCREEN_RELATIVE, &x, &y, &width, &height));
+ EXPECT_EQ(prev_x, x);
+ EXPECT_EQ(prev_y, y);
+ EXPECT_EQ(1, width);
+ EXPECT_EQ(prev_height, height);
+ }
+}
+
+// TODO(accessibility) empty contenteditable gets height of entire
+// contenteditable instead of just 1 line. May be able to use the following
+// in Blink to get the height of a line -- it's at least close:
+// layout_object->Style()->GetFont().PrimaryFont()->GetFontMetrics().Height()
+IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
+ DISABLED_TestCharacterExtentsInEmptyContenteditable) {
+ Microsoft::WRL::ComPtr<IAccessibleText> input_text;
+ SetUpSampleParagraphInScrollableEditable(&input_text);
+
+ LONG n_characters;
+ ASSERT_HRESULT_SUCCEEDED(input_text->get_nCharacters(&n_characters));
+ ASSERT_LT(0, n_characters);
+
+ // Get the rect for the only character.
+ LONG prev_x, prev_y, prev_width, prev_height;
+ EXPECT_HRESULT_SUCCEEDED(input_text->get_characterExtents(
+ 0, IA2_COORDTYPE_SCREEN_RELATIVE, &prev_x, &prev_y, &prev_width,
+ &prev_height));
+
+ EXPECT_LT(1, prev_width);
+ EXPECT_LT(1, prev_height);
+
+ base::win::ScopedBstr text0;
+ ASSERT_HRESULT_SUCCEEDED(input_text->get_text(0, -1, text0.Receive()));
+
+ // Delete the character in the input field.
+ AccessibilityNotificationWaiter waiter(shell()->web_contents(),
+ ui::kAXModeComplete,
+ ax::mojom::Event::kChildrenChanged);
+ ExecuteScript(std::wstring(
+ L"document.querySelector('[contenteditable]').innerText='';"));
+ waiter.WaitForNotification();
+
+ ASSERT_HRESULT_SUCCEEDED(input_text->get_nCharacters(&n_characters));
+ ASSERT_EQ(0, n_characters);
+ LONG caret_offset;
+ ASSERT_HRESULT_SUCCEEDED(input_text->get_caretOffset(&caret_offset));
+ ASSERT_EQ(0, caret_offset);
+
+ base::win::ScopedBstr text;
+ ASSERT_HRESULT_SUCCEEDED(input_text->get_text(0, -1, text.Receive()));
+
+ // Now that input is completely empty, the position of the caret should be
+ // returned for character 0. The x,y position and height should be the same as
+ // it was as when there was single character, but the width should now be 1.
+ LONG x, y, width, height;
+ for (int offset = IA2_TEXT_OFFSET_CARET; offset <= 0; ++offset) {
+ EXPECT_HRESULT_SUCCEEDED(input_text->get_characterExtents(
+ offset, IA2_COORDTYPE_SCREEN_RELATIVE, &x, &y, &width, &height));
+ EXPECT_EQ(prev_x, x);
+ EXPECT_EQ(prev_y, y);
+ EXPECT_EQ(1, width);
+ EXPECT_EQ(prev_height, height);
+ }
+}
+
+IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
+ TestCharacterExtentsInEmptyTextarea) {
+ Microsoft::WRL::ComPtr<IAccessibleText> input_text;
+ SetUpSingleCharTextarea(&input_text);
+
+ LONG n_characters;
+ ASSERT_HRESULT_SUCCEEDED(input_text->get_nCharacters(&n_characters));
+ ASSERT_EQ(1, n_characters);
+
+ // Get the rect for the only character.
+ LONG prev_x, prev_y, prev_width, prev_height;
+ EXPECT_HRESULT_SUCCEEDED(input_text->get_characterExtents(
+ 0, IA2_COORDTYPE_SCREEN_RELATIVE, &prev_x, &prev_y, &prev_width,
+ &prev_height));
+
+ EXPECT_LT(1, prev_width);
+ EXPECT_LT(1, prev_height);
+
+ base::win::ScopedBstr text0;
+ ASSERT_HRESULT_SUCCEEDED(input_text->get_text(0, -1, text0.Receive()));
+
+ // Delete the character in the input field.
+ AccessibilityNotificationWaiter waiter(
+ shell()->web_contents(), ui::kAXModeComplete,
+ ax::mojom::Event::kTextSelectionChanged);
+ ExecuteScript(
+ std::wstring(L"document.querySelector('textarea').innerText='';"));
+ waiter.WaitForNotification();
+
+ ASSERT_HRESULT_SUCCEEDED(input_text->get_nCharacters(&n_characters));
+ ASSERT_EQ(0, n_characters);
+ LONG caret_offset;
+ ASSERT_HRESULT_SUCCEEDED(input_text->get_caretOffset(&caret_offset));
+ ASSERT_EQ(0, caret_offset);
+
+ base::win::ScopedBstr text;
+ ASSERT_HRESULT_SUCCEEDED(input_text->get_text(0, -1, text.Receive()));
+
+ // Now that input is completely empty, the position of the caret should be
+ // returned for character 0. The x,y position and height should be the same as
+ // it was as when there was single character, but the width should now be 1.
+ LONG x, y, width, height;
+ for (int offset = IA2_TEXT_OFFSET_CARET; offset <= 0; ++offset) {
+ EXPECT_HRESULT_SUCCEEDED(input_text->get_characterExtents(
+ offset, IA2_COORDTYPE_SCREEN_RELATIVE, &x, &y, &width, &height));
+ EXPECT_EQ(prev_x, x);
+ EXPECT_EQ(prev_y, y);
+ EXPECT_EQ(1, width);
+ EXPECT_EQ(prev_height, height);
+ }
+}
+
+IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
+ TestCharacterExtentsInEmptyRtlInputField) {
+ Microsoft::WRL::ComPtr<IAccessibleText> input_text;
+ SetUpSingleCharRtlInputField(&input_text);
+
+ LONG n_characters;
+ ASSERT_HRESULT_SUCCEEDED(input_text->get_nCharacters(&n_characters));
+ ASSERT_EQ(1, n_characters);
+
+ // Get the rect for the only character.
+ LONG prev_x, prev_y, prev_width, prev_height;
+ EXPECT_HRESULT_SUCCEEDED(input_text->get_characterExtents(
+ 0, IA2_COORDTYPE_SCREEN_RELATIVE, &prev_x, &prev_y, &prev_width,
+ &prev_height));
+
+ EXPECT_LT(1, prev_width);
+ EXPECT_LT(1, prev_height);
+
+ // Delete the character in the input field.
+ AccessibilityNotificationWaiter waiter(
+ shell()->web_contents(), ui::kAXModeComplete,
+ ax::mojom::Event::kTextSelectionChanged);
+ ExecuteScript(
+ std::wstring(L"const input = document.querySelector('input');"
+ "input.value='';"));
+ waiter.WaitForNotification();
+
+ ASSERT_HRESULT_SUCCEEDED(input_text->get_nCharacters(&n_characters));
+ ASSERT_EQ(0, n_characters);
+ LONG caret_offset;
+ ASSERT_HRESULT_SUCCEEDED(input_text->get_caretOffset(&caret_offset));
+ ASSERT_EQ(0, caret_offset);
+
+ // Now that input is completely empty, the position of the caret should be
+ // returned for character 0. The x,y position and height should be the same as
+ // it was as when there was single character, but the width should now be 1.
+ LONG x, y, width, height;
+ for (int offset = IA2_TEXT_OFFSET_CARET; offset <= 0; ++offset) {
+ EXPECT_HRESULT_SUCCEEDED(input_text->get_characterExtents(
+ offset, IA2_COORDTYPE_SCREEN_RELATIVE, &x, &y, &width, &height));
+ // TODO(accessibility) Why do results keep changing on each run?
+ EXPECT_GE(prev_x + prev_width - 1, x);
+ EXPECT_EQ(prev_y, y);
+ EXPECT_EQ(1, width);
+ EXPECT_EQ(prev_height, height);
}
}
@@ -1433,15 +1785,55 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, TestScrollToPoint) {
EXPECT_EQ(prev_x, x);
EXPECT_GT(prev_y, y);
- prev_x = x;
- prev_y = y;
+ constexpr int kScrollToY = 0;
EXPECT_HRESULT_SUCCEEDED(
- paragraph->scrollToPoint(IA2_COORDTYPE_SCREEN_RELATIVE, 0, 0));
+ paragraph->scrollToPoint(IA2_COORDTYPE_SCREEN_RELATIVE, 0, kScrollToY));
location_changed_waiter.WaitForNotification();
ASSERT_HRESULT_SUCCEEDED(
paragraph->accLocation(&x, &y, &width, &height, childid_self));
- EXPECT_EQ(prev_x, x);
- EXPECT_EQ(prev_y, y);
+ EXPECT_EQ(kScrollToY, y);
+
+ constexpr int kScrollToY_2 = 243;
+ EXPECT_HRESULT_SUCCEEDED(
+ paragraph->scrollToPoint(IA2_COORDTYPE_SCREEN_RELATIVE, 0, kScrollToY_2));
+ location_changed_waiter.WaitForNotification();
+ ASSERT_HRESULT_SUCCEEDED(
+ paragraph->accLocation(&x, &y, &width, &height, childid_self));
+ EXPECT_EQ(kScrollToY_2, y);
+}
+
+IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
+ TestScrollSubstringToPoint) {
+ Microsoft::WRL::ComPtr<IAccessibleText> paragraph_text;
+ SetUpSampleParagraphInScrollableDocument(&paragraph_text);
+ Microsoft::WRL::ComPtr<IAccessible2> paragraph;
+ ASSERT_HRESULT_SUCCEEDED(paragraph_text.CopyTo(IID_PPV_ARGS(&paragraph)));
+
+ LONG x, y, width, height;
+ base::win::ScopedVariant childid_self(CHILDID_SELF);
+ AccessibilityNotificationWaiter location_changed_waiter(
+ shell()->web_contents(), ui::kAXModeComplete,
+ ax::mojom::Event::kLocationChanged);
+
+ constexpr int kScrollToY = 187;
+ constexpr int kCharOffset = 10;
+ EXPECT_HRESULT_SUCCEEDED(paragraph_text->scrollSubstringToPoint(
+ kCharOffset, kCharOffset + 1, IA2_COORDTYPE_SCREEN_RELATIVE, 0,
+ kScrollToY));
+ location_changed_waiter.WaitForNotification();
+ ASSERT_HRESULT_SUCCEEDED(paragraph_text->get_characterExtents(
+ kCharOffset, IA2_COORDTYPE_SCREEN_RELATIVE, &x, &y, &width, &height));
+ EXPECT_EQ(kScrollToY, y);
+
+ constexpr int kScrollToY_2 = -133;
+ constexpr int kCharOffset_2 = 30;
+ EXPECT_HRESULT_SUCCEEDED(paragraph_text->scrollSubstringToPoint(
+ kCharOffset_2, kCharOffset_2 + 1, IA2_COORDTYPE_SCREEN_RELATIVE, 0,
+ kScrollToY_2));
+ location_changed_waiter.WaitForNotification();
+ ASSERT_HRESULT_SUCCEEDED(paragraph_text->get_characterExtents(
+ kCharOffset_2, IA2_COORDTYPE_SCREEN_RELATIVE, &x, &y, &width, &height));
+ EXPECT_EQ(kScrollToY_2, y);
}
IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, TestSetCaretOffset) {
diff --git a/chromium/content/browser/accessibility/browser_accessibility.cc b/chromium/content/browser/accessibility/browser_accessibility.cc
index 10485315e69..d8c0af5afcf 100644
--- a/chromium/content/browser/accessibility/browser_accessibility.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility.cc
@@ -10,6 +10,7 @@
#include <iterator>
#include "base/logging.h"
+#include "base/no_destructor.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
@@ -73,11 +74,17 @@ bool BrowserAccessibility::PlatformIsLeaf() const {
}
}
+bool BrowserAccessibility::CanFireEvents() const {
+ // Allow events unless this object would be trimmed away.
+ return !PlatformIsChildOfLeaf();
+}
+
uint32_t BrowserAccessibility::PlatformChildCount() const {
- if (HasIntAttribute(ax::mojom::IntAttribute::kChildTreeId)) {
+ if (HasStringAttribute(ax::mojom::StringAttribute::kChildTreeId)) {
+ AXTreeID child_tree_id = AXTreeID::FromString(
+ GetStringAttribute(ax::mojom::StringAttribute::kChildTreeId));
BrowserAccessibilityManager* child_manager =
- BrowserAccessibilityManager::FromID(
- GetIntAttribute(ax::mojom::IntAttribute::kChildTreeId));
+ BrowserAccessibilityManager::FromID(child_tree_id);
if (child_manager && child_manager->GetRoot()->PlatformGetParent() == this)
return 1;
@@ -127,10 +134,11 @@ BrowserAccessibility* BrowserAccessibility::PlatformGetChild(
BrowserAccessibility* result = nullptr;
if (child_index == 0 &&
- HasIntAttribute(ax::mojom::IntAttribute::kChildTreeId)) {
+ HasStringAttribute(ax::mojom::StringAttribute::kChildTreeId)) {
+ AXTreeID child_tree_id = AXTreeID::FromString(
+ GetStringAttribute(ax::mojom::StringAttribute::kChildTreeId));
BrowserAccessibilityManager* child_manager =
- BrowserAccessibilityManager::FromID(
- GetIntAttribute(ax::mojom::IntAttribute::kChildTreeId));
+ BrowserAccessibilityManager::FromID(child_tree_id);
if (child_manager && child_manager->GetRoot()->PlatformGetParent() == this)
result = child_manager->GetRoot();
} else {
@@ -380,7 +388,9 @@ gfx::Rect BrowserAccessibility::GetPageBoundsForRange(int start,
else
start = 0;
}
- return bounds;
+ // When past the end of text, the area will be 0.
+ // In this case, use bounds provided for the caret.
+ return bounds.IsEmpty() ? GetPageBoundsPastEndOfText() : bounds;
}
int end = start + len;
@@ -492,6 +502,53 @@ gfx::Rect BrowserAccessibility::GetScreenBoundsForRange(int start,
return bounds;
}
+// Get a rect for a 1-width character past the end of text. This is what ATs
+// expect when getting the character extents past the last character in a line,
+// and equals what the caret bounds would be when past the end of the text.
+gfx::Rect BrowserAccessibility::GetPageBoundsPastEndOfText() const {
+ // Step 1: get approximate caret bounds. The thickness may not yet be correct.
+ gfx::Rect bounds;
+ if (InternalChildCount() > 0) {
+ // When past the end of text, use bounds provided by a last child if
+ // available, and then correct for thickness of caret.
+ BrowserAccessibility* child = InternalGetChild(InternalChildCount() - 1);
+ int child_text_len = child->GetText().size();
+ bounds = child->GetPageBoundsForRange(child_text_len, child_text_len);
+ if (bounds.width() == 0 && bounds.height() == 0)
+ return bounds; // Inline text boxes info not yet available.
+ } else {
+ // Compute bounds of where caret would be, based on bounds of object.
+ bounds = GetPageBoundsRect();
+ }
+
+ // Step 2: correct for the thickness of the caret.
+ auto text_direction = static_cast<ax::mojom::TextDirection>(
+ GetIntAttribute(ax::mojom::IntAttribute::kTextDirection));
+ constexpr int kCaretThickness = 1;
+ switch (text_direction) {
+ case ax::mojom::TextDirection::kNone:
+ case ax::mojom::TextDirection::kLtr: {
+ bounds.set_width(kCaretThickness);
+ break;
+ }
+ case ax::mojom::TextDirection::kRtl: {
+ bounds.set_x(bounds.right() - kCaretThickness);
+ bounds.set_width(kCaretThickness);
+ break;
+ }
+ case ax::mojom::TextDirection::kTtb: {
+ bounds.set_height(kCaretThickness);
+ break;
+ }
+ case ax::mojom::TextDirection::kBtt: {
+ bounds.set_y(bounds.bottom() - kCaretThickness);
+ bounds.set_height(kCaretThickness);
+ break;
+ }
+ }
+ return bounds;
+}
+
base::string16 BrowserAccessibility::GetValue() const {
base::string16 value =
GetString16Attribute(ax::mojom::StringAttribute::kValue);
@@ -886,19 +943,19 @@ gfx::NativeViewAccessible BrowserAccessibility::GetNativeViewAccessible() {
// AXPlatformNodeDelegate.
//
const ui::AXNodeData& BrowserAccessibility::GetData() const {
- CR_DEFINE_STATIC_LOCAL(ui::AXNodeData, empty_data, ());
+ static base::NoDestructor<ui::AXNodeData> empty_data;
if (node_)
return node_->data();
else
- return empty_data;
+ return *empty_data;
}
const ui::AXTreeData& BrowserAccessibility::GetTreeData() const {
- CR_DEFINE_STATIC_LOCAL(ui::AXTreeData, empty_data, ());
+ static base::NoDestructor<ui::AXTreeData> empty_data;
if (manager())
return manager()->GetTreeData();
else
- return empty_data;
+ return *empty_data;
}
gfx::NativeWindow BrowserAccessibility::GetTopLevelWidget() {
diff --git a/chromium/content/browser/accessibility/browser_accessibility.h b/chromium/content/browser/accessibility/browser_accessibility.h
index b66d5e86384..89034481f8b 100644
--- a/chromium/content/browser/accessibility/browser_accessibility.h
+++ b/chromium/content/browser/accessibility/browser_accessibility.h
@@ -114,6 +114,9 @@ class CONTENT_EXPORT BrowserAccessibility : public ui::AXPlatformNodeDelegate {
// that might send notifications.
virtual bool PlatformIsLeaf() const;
+ // Returns true if this object can fire events.
+ virtual bool CanFireEvents() const;
+
// Returns the number of children of this object, or 0 if PlatformIsLeaf()
// returns true.
virtual uint32_t PlatformChildCount() const;
@@ -392,6 +395,8 @@ class CONTENT_EXPORT BrowserAccessibility : public ui::AXPlatformNodeDelegate {
// text, depending on the platform.
base::string16 GetInnerText() const;
+ gfx::Rect GetPageBoundsPastEndOfText() const;
+
// A unique ID, since node IDs are frame-local.
ui::AXUniqueId unique_id_;
diff --git a/chromium/content/browser/accessibility/browser_accessibility_android.cc b/chromium/content/browser/accessibility/browser_accessibility_android.cc
index 95b60d9f0d0..7cc43690a3a 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_android.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_android.cc
@@ -163,6 +163,10 @@ bool BrowserAccessibilityAndroid::PlatformIsLeaf() const {
return false;
}
+bool BrowserAccessibilityAndroid::CanFireEvents() const {
+ return true;
+}
+
bool BrowserAccessibilityAndroid::IsCheckable() const {
return HasIntAttribute(ax::mojom::IntAttribute::kCheckedState);
}
diff --git a/chromium/content/browser/accessibility/browser_accessibility_android.h b/chromium/content/browser/accessibility/browser_accessibility_android.h
index a2c8b6cb973..e87b171f578 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_android.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_android.h
@@ -27,6 +27,8 @@ class CONTENT_EXPORT BrowserAccessibilityAndroid : public BrowserAccessibility {
base::string16 GetValue() const override;
bool PlatformIsLeaf() const override;
+ // Android needs events even on objects that are trimmed away.
+ bool CanFireEvents() const override;
bool IsCheckable() const;
bool IsChecked() const;
diff --git a/chromium/content/browser/accessibility/browser_accessibility_auralinux_unittest.cc b/chromium/content/browser/accessibility/browser_accessibility_auralinux_unittest.cc
index 3d31036acac..40acf2141b1 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_auralinux_unittest.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_auralinux_unittest.cc
@@ -113,6 +113,161 @@ TEST_F(BrowserAccessibilityAuraLinuxTest, TestCompositeAtkText) {
EXPECT_STREQ((text1_name + text2_name).c_str(), text);
g_free(text);
+ ASSERT_TRUE(ATK_IS_HYPERTEXT(root_atk_object));
+ AtkHypertext* atk_hypertext = ATK_HYPERTEXT(root_atk_object);
+
+ // There should be no hyperlinks in the node and trying to get one should
+ // always return -1.
+ EXPECT_EQ(0, atk_hypertext_get_n_links(atk_hypertext));
+ EXPECT_EQ(-1, atk_hypertext_get_link_index(atk_hypertext, 0));
+ EXPECT_EQ(-1, atk_hypertext_get_link_index(atk_hypertext, -1));
+ EXPECT_EQ(-1, atk_hypertext_get_link_index(atk_hypertext, 1));
+
+ g_object_unref(root_atk_object);
+
+ manager.reset();
+}
+
+TEST_F(BrowserAccessibilityAuraLinuxTest, TestComplexHypertext) {
+ const std::string text1_name = "One two three.";
+ const std::string combo_box_name = "City:";
+ const std::string combo_box_value = "Happyland";
+ const std::string text2_name = " Four five six.";
+ const std::string check_box_name = "I agree";
+ const std::string check_box_value = "Checked";
+ const std::string button_text_name = "Red";
+ const std::string link_text_name = "Blue";
+ // Each control (combo / check box, button and link) will be represented by an
+ // embedded object character.
+ const base::string16 string16_embed(
+ 1, ui::AXPlatformNodeAuraLinux::kEmbeddedCharacter);
+ const std::string embed = base::UTF16ToUTF8(string16_embed);
+ const std::string root_hypertext =
+ text1_name + embed + text2_name + embed + embed + embed;
+
+ ui::AXNodeData text1;
+ text1.id = 11;
+ text1.role = ax::mojom::Role::kStaticText;
+ text1.SetName(text1_name);
+
+ ui::AXNodeData combo_box;
+ combo_box.id = 12;
+ combo_box.role = ax::mojom::Role::kTextFieldWithComboBox;
+ combo_box.AddState(ax::mojom::State::kEditable);
+ combo_box.SetName(combo_box_name);
+ combo_box.SetValue(combo_box_value);
+
+ ui::AXNodeData text2;
+ text2.id = 13;
+ text2.role = ax::mojom::Role::kStaticText;
+ text2.SetName(text2_name);
+
+ ui::AXNodeData check_box;
+ check_box.id = 14;
+ check_box.role = ax::mojom::Role::kCheckBox;
+ check_box.SetCheckedState(ax::mojom::CheckedState::kTrue);
+ check_box.SetName(check_box_name);
+ check_box.SetValue(check_box_value);
+
+ ui::AXNodeData button, button_text;
+ button.id = 15;
+ button_text.id = 17;
+ button_text.SetName(button_text_name);
+ button.role = ax::mojom::Role::kButton;
+ button_text.role = ax::mojom::Role::kStaticText;
+ button.child_ids.push_back(button_text.id);
+
+ ui::AXNodeData link, link_text;
+ link.id = 16;
+ link_text.id = 18;
+ link_text.SetName(link_text_name);
+ link.role = ax::mojom::Role::kLink;
+ link_text.role = ax::mojom::Role::kStaticText;
+ link.child_ids.push_back(link_text.id);
+
+ ui::AXNodeData root;
+ root.id = 1;
+ root.role = ax::mojom::Role::kRootWebArea;
+ root.child_ids.push_back(text1.id);
+ root.child_ids.push_back(combo_box.id);
+ root.child_ids.push_back(text2.id);
+ root.child_ids.push_back(check_box.id);
+ root.child_ids.push_back(button.id);
+ root.child_ids.push_back(link.id);
+
+ std::unique_ptr<BrowserAccessibilityManager> manager(
+ BrowserAccessibilityManager::Create(
+ MakeAXTreeUpdate(root, text1, combo_box, text2, check_box, button,
+ button_text, link, link_text),
+ nullptr, new BrowserAccessibilityFactory()));
+
+ ui::AXPlatformNodeAuraLinux* root_obj =
+ ToBrowserAccessibilityAuraLinux(manager->GetRoot())->GetNode();
+ AtkObject* root_atk_object(root_obj->GetNativeViewAccessible());
+
+ ASSERT_TRUE(ATK_IS_OBJECT(root_atk_object));
+ ASSERT_TRUE(ATK_IS_TEXT(root_atk_object));
+ g_object_ref(root_atk_object);
+ AtkText* atk_text = ATK_TEXT(root_atk_object);
+
+ EXPECT_EQ(g_utf8_strlen(root_hypertext.c_str(), -1),
+ atk_text_get_character_count(atk_text));
+
+ gchar* text = atk_text_get_text(atk_text, 0, -1);
+ EXPECT_STREQ(root_hypertext.c_str(), text);
+ g_free(text);
+
+ ASSERT_TRUE(ATK_IS_HYPERTEXT(root_atk_object));
+ AtkHypertext* atk_hypertext = ATK_HYPERTEXT(root_atk_object);
+
+ EXPECT_EQ(4, atk_hypertext_get_n_links(atk_hypertext));
+
+ auto verify_atk_link_text = [&](const char* expected_text, int link_index,
+ int expected_start_index) {
+ AtkHyperlink* link = atk_hypertext_get_link(atk_hypertext, link_index);
+ ASSERT_NE(nullptr, link);
+ ASSERT_TRUE(ATK_IS_HYPERLINK(link));
+
+ ASSERT_EQ(atk_hyperlink_get_start_index(link), expected_start_index);
+ ASSERT_EQ(atk_hyperlink_get_end_index(link), expected_start_index + 1);
+
+ AtkObject* object = atk_hyperlink_get_object(link, 0);
+ ASSERT_TRUE(ATK_IS_TEXT(object));
+
+ char* text = atk_text_get_text(ATK_TEXT(object), 0, -1);
+ EXPECT_STREQ(expected_text, text);
+ g_free(text);
+ };
+
+ AtkHyperlink* combo_box_link = atk_hypertext_get_link(atk_hypertext, 0);
+ ASSERT_NE(nullptr, combo_box_link);
+ ASSERT_TRUE(ATK_IS_HYPERLINK(combo_box_link));
+
+ // Get the text of the combo box. It should be its value.
+ verify_atk_link_text(combo_box_value.c_str(), 0, 14);
+
+ // Get the text of the check box. It should be its name.
+ verify_atk_link_text(check_box_name.c_str(), 1, 30);
+
+ // Get the text of the button.
+ verify_atk_link_text(button_text_name.c_str(), 2, 31);
+
+ // Get the text of the link.
+ verify_atk_link_text(link_text_name.c_str(), 3, 32);
+
+ // Now test that all the object indices map back to the correct link indices.
+ EXPECT_EQ(-1, atk_hypertext_get_link_index(atk_hypertext, -1));
+ EXPECT_EQ(-1, atk_hypertext_get_link_index(atk_hypertext, 0));
+ EXPECT_EQ(-1, atk_hypertext_get_link_index(atk_hypertext, 1));
+ EXPECT_EQ(-1, atk_hypertext_get_link_index(atk_hypertext, 5));
+ EXPECT_EQ(-1, atk_hypertext_get_link_index(atk_hypertext, 13));
+ EXPECT_EQ(0, atk_hypertext_get_link_index(atk_hypertext, 14));
+ EXPECT_EQ(1, atk_hypertext_get_link_index(atk_hypertext, 30));
+ EXPECT_EQ(2, atk_hypertext_get_link_index(atk_hypertext, 31));
+ EXPECT_EQ(3, atk_hypertext_get_link_index(atk_hypertext, 32));
+ EXPECT_EQ(-1, atk_hypertext_get_link_index(atk_hypertext, 33));
+ EXPECT_EQ(-1, atk_hypertext_get_link_index(atk_hypertext, 34));
+
g_object_unref(root_atk_object);
manager.reset();
diff --git a/chromium/content/browser/accessibility/browser_accessibility_cocoa.mm b/chromium/content/browser/accessibility/browser_accessibility_cocoa.mm
index 06db282cd74..ec60dd6b8f2 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_cocoa.mm
+++ b/chromium/content/browser/accessibility/browser_accessibility_cocoa.mm
@@ -985,7 +985,8 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
// Group, radiogroup etc.
if ([self shouldExposeNameInDescription]) {
return base::SysUTF8ToNSString(name);
- } else if (nameFrom == ax::mojom::NameFrom::kContents ||
+ } else if (nameFrom == ax::mojom::NameFrom::kCaption ||
+ nameFrom == ax::mojom::NameFrom::kContents ||
nameFrom == ax::mojom::NameFrom::kRelatedElement ||
nameFrom == ax::mojom::NameFrom::kValue) {
return @"";
@@ -1568,7 +1569,8 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
ax::mojom::NameFrom nameFrom = static_cast<ax::mojom::NameFrom>(
owner_->GetIntAttribute(ax::mojom::IntAttribute::kNameFrom));
- if (nameFrom != ax::mojom::NameFrom::kRelatedElement)
+ if (nameFrom != ax::mojom::NameFrom::kCaption &&
+ nameFrom != ax::mojom::NameFrom::kRelatedElement)
return false;
std::vector<int32_t> labelledby_ids =
@@ -2173,7 +2175,8 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
// On Mac OS X, the accessible name of an object is exposed as its
// title if it comes from visible text, and as its description
// otherwise, but never both.
- if (nameFrom == ax::mojom::NameFrom::kContents ||
+ if (nameFrom == ax::mojom::NameFrom::kCaption ||
+ nameFrom == ax::mojom::NameFrom::kContents ||
nameFrom == ax::mojom::NameFrom::kRelatedElement ||
nameFrom == ax::mojom::NameFrom::kValue) {
return NSStringForStringAttribute(owner_,
@@ -2193,7 +2196,8 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
owner_->GetIntListAttribute(ax::mojom::IntListAttribute::kLabelledbyIds);
ax::mojom::NameFrom nameFrom = static_cast<ax::mojom::NameFrom>(
owner_->GetIntAttribute(ax::mojom::IntAttribute::kNameFrom));
- if (nameFrom == ax::mojom::NameFrom::kRelatedElement &&
+ if ((nameFrom == ax::mojom::NameFrom::kCaption ||
+ nameFrom == ax::mojom::NameFrom::kRelatedElement) &&
labelledby_ids.size() == 1) {
BrowserAccessibility* titleElement =
owner_->manager()->GetFromID(labelledby_ids[0]);
@@ -2239,6 +2243,7 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
return @"";
} else if (owner_->HasIntAttribute(ax::mojom::IntAttribute::kCheckedState) ||
[role isEqualToString:NSAccessibilityRadioButtonRole]) {
+ // On Mac, tabs are exposed as radio buttons, and are treated as checkable.
int value;
const auto checkedState = static_cast<ax::mojom::CheckedState>(
owner_->GetIntAttribute(ax::mojom::IntAttribute::kCheckedState));
diff --git a/chromium/content/browser/accessibility/browser_accessibility_com_win.cc b/chromium/content/browser/accessibility/browser_accessibility_com_win.cc
index c874c05dd94..edcd56cc1ba 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_com_win.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_com_win.cc
@@ -20,7 +20,7 @@
#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_modes.h"
+#include "ui/accessibility/ax_mode.h"
#include "ui/accessibility/ax_role_properties.h"
#include "ui/accessibility/ax_text_utils.h"
#include "ui/base/win/accessibility_ids_win.h"
@@ -95,7 +95,8 @@ IFACEMETHODIMP BrowserAccessibilityComWin::get_appName(BSTR* app_name) {
std::vector<std::string> product_components =
base::SplitString(GetContentClient()->GetProduct(), "/",
base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
- DCHECK_EQ(2U, product_components.size());
+ // |GetProduct| will return an empty string if we are running the content
+ // shell instead of Chrome.
if (product_components.size() != 2)
return E_FAIL;
*app_name = SysAllocString(base::UTF8ToUTF16(product_components[0]).c_str());
@@ -114,7 +115,8 @@ IFACEMETHODIMP BrowserAccessibilityComWin::get_appVersion(BSTR* app_version) {
std::vector<std::string> product_components =
base::SplitString(GetContentClient()->GetProduct(), "/",
base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
- DCHECK_EQ(2U, product_components.size());
+ // |GetProduct| will return an empty string if we are running the content
+ // shell instead of Chrome.
if (product_components.size() != 2)
return E_FAIL;
*app_version =
diff --git a/chromium/content/browser/accessibility/browser_accessibility_mac.h b/chromium/content/browser/accessibility/browser_accessibility_mac.h
index d2cc8d75974..0e00dbdf874 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_mac.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_mac.h
@@ -38,11 +38,6 @@ class BrowserAccessibilityMac : public BrowserAccessibility {
return browser_accessibility_cocoa_;
}
- // Detach the BrowserAccessibilityCocoa object and then recreate it.
- // This is only used to work around VoiceOver bugs by forcing VoiceOver
- // to rebuild its internal state.
- void RecreateNativeObject();
-
private:
// This gives BrowserAccessibility::Create access to the class constructor.
friend class BrowserAccessibility;
diff --git a/chromium/content/browser/accessibility/browser_accessibility_mac.mm b/chromium/content/browser/accessibility/browser_accessibility_mac.mm
index 1c5d9171a4f..ca5da8d26c8 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_mac.mm
+++ b/chromium/content/browser/accessibility/browser_accessibility_mac.mm
@@ -82,21 +82,6 @@ BrowserAccessibility* BrowserAccessibilityMac::PlatformGetChild(
return nullptr;
}
-void BrowserAccessibilityMac::RecreateNativeObject() {
- if (!browser_accessibility_cocoa_)
- return;
-
- // Preserve the children so that recreating the native object doesn't
- // end up recreating the whole subtree.
- base::scoped_nsobject<NSMutableArray> children;
- [browser_accessibility_cocoa_ swapChildren:&children];
- [browser_accessibility_cocoa_ detach];
- [browser_accessibility_cocoa_ release];
- browser_accessibility_cocoa_ = [[BrowserAccessibilityCocoa alloc]
- initWithObject:this];
- [browser_accessibility_cocoa_ swapChildren:&children];
-}
-
const BrowserAccessibilityCocoa*
ToBrowserAccessibilityCocoa(const BrowserAccessibility* obj) {
DCHECK(obj);
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager.cc b/chromium/content/browser/accessibility/browser_accessibility_manager.cc
index 3ab440e85ad..568883f0915 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager.cc
@@ -5,10 +5,12 @@
#include "content/browser/accessibility/browser_accessibility_manager.h"
#include <stddef.h>
+#include <map>
#include <utility>
#include "base/debug/crash_logging.h"
#include "base/logging.h"
+#include "base/no_destructor.h"
#include "build/build_config.h"
#include "content/browser/accessibility/browser_accessibility.h"
#include "content/common/accessibility_messages.h"
@@ -21,8 +23,7 @@ namespace content {
namespace {
// Map from AXTreeID to BrowserAccessibilityManager
-using AXTreeIDMap = base::hash_map<ui::AXTreeIDRegistry::AXTreeID,
- BrowserAccessibilityManager*>;
+using AXTreeIDMap = std::map<ui::AXTreeID, BrowserAccessibilityManager*>;
base::LazyInstance<AXTreeIDMap>::Leaky g_ax_tree_id_map =
LAZY_INSTANCE_INITIALIZER;
@@ -45,13 +46,13 @@ ui::AXTreeUpdate MakeAXTreeUpdate(
const ui::AXNodeData& node10 /* = ui::AXNodeData() */,
const ui::AXNodeData& node11 /* = ui::AXNodeData() */,
const ui::AXNodeData& node12 /* = ui::AXNodeData() */) {
- CR_DEFINE_STATIC_LOCAL(ui::AXNodeData, empty_data, ());
- int32_t no_id = empty_data.id;
+ static base::NoDestructor<ui::AXNodeData> empty_data;
+ int32_t no_id = empty_data->id;
ui::AXTreeUpdate update;
ui::AXTreeData tree_data;
- tree_data.tree_id = 1;
- tree_data.focused_tree_id = 1;
+ tree_data.tree_id = ui::AXTreeID::FromString("1");
+ tree_data.focused_tree_id = ui::AXTreeID::FromString("1");
update.tree_data = tree_data;
update.has_tree_data = true;
update.root_id = node1.id;
@@ -106,7 +107,7 @@ BrowserAccessibilityManager* BrowserAccessibilityManager::Create(
// static
BrowserAccessibilityManager* BrowserAccessibilityManager::FromID(
- ui::AXTreeIDRegistry::AXTreeID ax_tree_id) {
+ ui::AXTreeID ax_tree_id) {
AXTreeIDMap* ax_tree_id_map = g_ax_tree_id_map.Pointer();
auto iter = ax_tree_id_map->find(ax_tree_id);
return iter == ax_tree_id_map->end() ? nullptr : iter->second;
@@ -123,7 +124,7 @@ BrowserAccessibilityManager::BrowserAccessibilityManager(
last_focused_node_(nullptr),
last_focused_manager_(nullptr),
connected_to_parent_tree_node_(false),
- ax_tree_id_(ui::AXTreeIDRegistry::kNoAXTreeID),
+ ax_tree_id_(ui::AXTreeIDUnknown()),
device_scale_factor_(1.0f),
use_custom_device_scale_factor_for_testing_(false) {
SetTree(tree_.get());
@@ -140,7 +141,7 @@ BrowserAccessibilityManager::BrowserAccessibilityManager(
user_is_navigating_away_(false),
last_focused_node_(nullptr),
last_focused_manager_(nullptr),
- ax_tree_id_(ui::AXTreeIDRegistry::kNoAXTreeID),
+ ax_tree_id_(ui::AXTreeIDUnknown()),
device_scale_factor_(1.0f),
use_custom_device_scale_factor_for_testing_(false) {
SetTree(tree_.get());
@@ -257,7 +258,7 @@ BrowserAccessibilityManager::GetParentNodeFromParentTree() {
if (!GetRoot())
return nullptr;
- int parent_tree_id = GetTreeData().parent_tree_id;
+ ui::AXTreeID parent_tree_id = GetTreeData().parent_tree_id;
BrowserAccessibilityManager* parent_manager =
BrowserAccessibilityManager::FromID(parent_tree_id);
if (!parent_manager)
@@ -274,8 +275,9 @@ BrowserAccessibilityManager::GetParentNodeFromParentTree() {
for (int32_t host_node_id : host_node_ids) {
BrowserAccessibility* parent_node = parent_manager->GetFromID(host_node_id);
if (parent_node) {
- DCHECK_EQ(ax_tree_id_, parent_node->GetIntAttribute(
- ax::mojom::IntAttribute::kChildTreeId));
+ DCHECK_EQ(ax_tree_id_,
+ AXTreeID::FromString(parent_node->GetStringAttribute(
+ ax::mojom::StringAttribute::kChildTreeId)));
return parent_node;
}
}
@@ -374,7 +376,7 @@ void BrowserAccessibilityManager::OnAccessibilityEvents(
// Fire any events related to changes to the tree.
for (auto targeted_event : *this) {
BrowserAccessibility* event_target = GetFromAXNode(targeted_event.node);
- if (!event_target)
+ if (!event_target || !event_target->CanFireEvents())
continue;
FireGeneratedEvent(targeted_event.event_params.event, event_target);
@@ -387,7 +389,7 @@ void BrowserAccessibilityManager::OnAccessibilityEvents(
// Fire the native event.
BrowserAccessibility* event_target = GetFromID(event.id);
- if (!event_target)
+ if (!event_target || !event_target->CanFireEvents())
return;
if (event.event_type == ax::mojom::Event::kHover)
@@ -499,10 +501,10 @@ BrowserAccessibility* BrowserAccessibilityManager::GetFocus() {
BrowserAccessibilityManager* root_manager = GetRootManager();
if (!root_manager)
root_manager = this;
- int32_t focused_tree_id = root_manager->GetTreeData().focused_tree_id;
+ ui::AXTreeID focused_tree_id = root_manager->GetTreeData().focused_tree_id;
BrowserAccessibilityManager* focused_manager = nullptr;
- if (focused_tree_id)
+ if (focused_tree_id != ui::AXTreeIDUnknown())
focused_manager = BrowserAccessibilityManager::FromID(focused_tree_id);
// BrowserAccessibilityManager::FromID(focused_tree_id) may return nullptr
@@ -520,10 +522,11 @@ BrowserAccessibilityManager::GetFocusFromThisOrDescendantFrame() {
if (!obj)
return GetRoot();
- if (obj->HasIntAttribute(ax::mojom::IntAttribute::kChildTreeId)) {
+ if (obj->HasStringAttribute(ax::mojom::StringAttribute::kChildTreeId)) {
+ AXTreeID child_tree_id = AXTreeID::FromString(
+ obj->GetStringAttribute(ax::mojom::StringAttribute::kChildTreeId));
BrowserAccessibilityManager* child_manager =
- BrowserAccessibilityManager::FromID(
- obj->GetIntAttribute(ax::mojom::IntAttribute::kChildTreeId));
+ BrowserAccessibilityManager::FromID(child_tree_id);
if (child_manager)
return child_manager->GetFocusFromThisOrDescendantFrame();
}
@@ -1115,7 +1118,8 @@ void BrowserAccessibilityManager::OnAtomicUpdateFinished(
const std::vector<ui::AXTreeDelegate::Change>& changes) {
AXEventGenerator::OnAtomicUpdateFinished(tree, root_changed, changes);
bool ax_tree_id_changed = false;
- if (GetTreeData().tree_id != -1 && GetTreeData().tree_id != ax_tree_id_) {
+ if (GetTreeData().tree_id != ui::AXTreeIDUnknown() &&
+ GetTreeData().tree_id != ax_tree_id_) {
g_ax_tree_id_map.Get().erase(ax_tree_id_);
ax_tree_id_ = GetTreeData().tree_id;
g_ax_tree_id_map.Get().insert(std::make_pair(ax_tree_id_, this));
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager.h b/chromium/content/browser/accessibility/browser_accessibility_manager.h
index 397df50cb4b..76aec4cef74 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager.h
@@ -120,8 +120,7 @@ class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXEventGenerator {
BrowserAccessibilityDelegate* delegate,
BrowserAccessibilityFactory* factory = new BrowserAccessibilityFactory());
- static BrowserAccessibilityManager* FromID(
- ui::AXTreeIDRegistry::AXTreeID ax_tree_id);
+ static BrowserAccessibilityManager* FromID(ui::AXTreeID ax_tree_id);
~BrowserAccessibilityManager() override;
@@ -340,7 +339,7 @@ class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXEventGenerator {
int end_offset);
// Accessors.
- ui::AXTreeIDRegistry::AXTreeID ax_tree_id() const { return ax_tree_id_; }
+ ui::AXTreeID ax_tree_id() const { return ax_tree_id_; }
float device_scale_factor() const { return device_scale_factor_; }
ui::AXTree* ax_tree() const { return tree_.get(); }
@@ -441,7 +440,7 @@ class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXEventGenerator {
// last object found by an asynchronous hit test. Subsequent hit test
// requests that remain within this object's bounds will return the same
// object, but will also trigger a new asynchronous hit test request.
- int last_hover_ax_tree_id_;
+ ui::AXTreeID last_hover_ax_tree_id_;
int last_hover_node_id_;
gfx::Rect last_hover_bounds_;
@@ -451,7 +450,7 @@ class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXEventGenerator {
bool connected_to_parent_tree_node_;
// The global ID of this accessibility tree.
- ui::AXTreeIDRegistry::AXTreeID ax_tree_id_;
+ ui::AXTreeID ax_tree_id_;
// The device scale factor for the view associated with this frame,
// cached each time there's any update to the accessibility tree.
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_android.cc b/chromium/content/browser/accessibility/browser_accessibility_manager_android.cc
index f1ba43ffb36..ed8b663a4d7 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_android.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_android.cc
@@ -205,6 +205,7 @@ void BrowserAccessibilityManagerAndroid::FireGeneratedEvent(
case Event::INVALID_STATUS_CHANGED:
case Event::LIVE_REGION_CHANGED:
case Event::LIVE_REGION_CREATED:
+ case Event::LOAD_START:
case Event::MENU_ITEM_SELECTED:
case Event::NAME_CHANGED:
case Event::OTHER_ATTRIBUTE_CHANGED:
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_auralinux.cc b/chromium/content/browser/accessibility/browser_accessibility_manager_auralinux.cc
index 1caa0621b77..74d1bd60af5 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_auralinux.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_auralinux.cc
@@ -54,10 +54,55 @@ ui::AXTreeUpdate
void BrowserAccessibilityManagerAuraLinux::FireFocusEvent(
BrowserAccessibility* node) {
BrowserAccessibilityManager::FireFocusEvent(node);
- if (node->IsNative()) {
- ToBrowserAccessibilityAuraLinux(node)->GetNode()->NotifyAccessibilityEvent(
- ax::mojom::Event::kFocus);
- }
+ FireEvent(node, ax::mojom::Event::kFocus);
+}
+
+void BrowserAccessibilityManagerAuraLinux::FireSelectedEvent(
+ BrowserAccessibility* node) {
+ // Some browser UI widgets, such as the omnibox popup, only send notifications
+ // when they become selected. In contrast elements in a page, such as options
+ // in the select element, also send notifications when they become unselected.
+ // Since AXPlatformNodeAuraLinux must handle firing a platform event for the
+ // unselected case, we can safely ignore the unselected case for rendered
+ // elements.
+ if (!node->GetBoolAttribute(ax::mojom::BoolAttribute::kSelected))
+ return;
+
+ FireEvent(node, ax::mojom::Event::kSelection);
+}
+
+void BrowserAccessibilityManagerAuraLinux::FireLoadingEvent(
+ BrowserAccessibility* node,
+ bool is_loading) {
+ if (!node->IsNative())
+ return;
+
+ gfx::NativeViewAccessible obj = node->GetNativeViewAccessible();
+ if (!ATK_IS_OBJECT(obj))
+ return;
+
+ atk_object_notify_state_change(obj, ATK_STATE_BUSY, is_loading);
+ if (!is_loading)
+ g_signal_emit_by_name(obj, "load_complete");
+}
+
+void BrowserAccessibilityManagerAuraLinux::FireExpandedEvent(
+ BrowserAccessibility* node,
+ bool is_expanded) {
+ if (!node->IsNative())
+ return;
+
+ ToBrowserAccessibilityAuraLinux(node)->GetNode()->OnExpandedStateChanged(
+ is_expanded);
+}
+
+void BrowserAccessibilityManagerAuraLinux::FireEvent(BrowserAccessibility* node,
+ ax::mojom::Event event) {
+ if (!node->IsNative())
+ return;
+
+ ToBrowserAccessibilityAuraLinux(node)->GetNode()->NotifyAccessibilityEvent(
+ event);
}
void BrowserAccessibilityManagerAuraLinux::FireBlinkEvent(
@@ -71,7 +116,34 @@ void BrowserAccessibilityManagerAuraLinux::FireGeneratedEvent(
AXEventGenerator::Event event_type,
BrowserAccessibility* node) {
BrowserAccessibilityManager::FireGeneratedEvent(event_type, node);
- // Need to implement.
+
+ switch (event_type) {
+ case Event::CHECKED_STATE_CHANGED:
+ FireEvent(node, ax::mojom::Event::kCheckedStateChanged);
+ break;
+ case Event::COLLAPSED:
+ FireExpandedEvent(node, false);
+ break;
+ case Event::EXPANDED:
+ FireExpandedEvent(node, true);
+ break;
+ case Event::LOAD_COMPLETE:
+ FireLoadingEvent(node, false);
+ break;
+ case Event::LOAD_START:
+ FireLoadingEvent(node, true);
+ break;
+ case Event::MENU_ITEM_SELECTED:
+ case Event::SELECTED_CHANGED:
+ FireSelectedEvent(node);
+ break;
+ case Event::VALUE_CHANGED:
+ FireEvent(node, ax::mojom::Event::kValueChanged);
+ break;
+ default:
+ // Need to implement.
+ break;
+ }
}
void BrowserAccessibilityManagerAuraLinux::OnAtomicUpdateFinished(
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_auralinux.h b/chromium/content/browser/accessibility/browser_accessibility_manager_auralinux.h
index 7de682076c4..a6e857981fc 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_auralinux.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_auralinux.h
@@ -34,6 +34,10 @@ class CONTENT_EXPORT BrowserAccessibilityManagerAuraLinux
void FireGeneratedEvent(AXEventGenerator::Event event_type,
BrowserAccessibility* node) override;
+ void FireSelectedEvent(BrowserAccessibility* node);
+ void FireExpandedEvent(BrowserAccessibility* node, bool is_expanded);
+ void FireLoadingEvent(BrowserAccessibility* node, bool is_loading);
+
AtkObject* parent_object() { return parent_object_; }
protected:
@@ -44,6 +48,8 @@ class CONTENT_EXPORT BrowserAccessibilityManagerAuraLinux
const std::vector<ui::AXTreeDelegate::Change>& changes) override;
private:
+ void FireEvent(BrowserAccessibility* node, ax::mojom::Event event);
+
AtkObject* parent_object_;
// Give BrowserAccessibilityManager::Create access to our constructor.
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_mac.mm b/chromium/content/browser/accessibility/browser_accessibility_manager_mac.mm
index 09cb7f8a55d..ace4792b686 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_mac.mm
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_mac.mm
@@ -12,10 +12,12 @@
#import "base/mac/sdk_forward_declarations.h"
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/task/post_task.h"
#include "base/time/time.h"
#import "content/browser/accessibility/browser_accessibility_cocoa.h"
#import "content/browser/accessibility/browser_accessibility_mac.h"
#include "content/common/accessibility_messages.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "ui/accelerated_widget_mac/accelerated_widget_mac.h"
#include "ui/accessibility/ax_role_properties.h"
@@ -337,8 +339,8 @@ void BrowserAccessibilityManagerMac::FireGeneratedEvent(
// Use native VoiceOver support for live regions.
base::scoped_nsobject<BrowserAccessibilityCocoa> retained_node(
[native_node retain]);
- BrowserThread::PostDelayedTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostDelayedTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::Bind(
[](base::scoped_nsobject<BrowserAccessibilityCocoa> node) {
if (node && [node instanceActive]) {
@@ -376,6 +378,7 @@ void BrowserAccessibilityManagerMac::FireGeneratedEvent(
case Event::DESCRIPTION_CHANGED:
case Event::DOCUMENT_TITLE_CHANGED:
case Event::LIVE_REGION_NODE_CHANGED:
+ case Event::LOAD_START:
case Event::NAME_CHANGED:
case Event::OTHER_ATTRIBUTE_CHANGED:
case Event::RELATED_NODE_CHANGED:
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_win.cc b/chromium/content/browser/accessibility/browser_accessibility_manager_win.cc
index 1a3eecf5de2..166426aed7e 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_win.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_win.cc
@@ -19,10 +19,6 @@
namespace content {
-// See OnScreenReaderHoneyPotQueried, below.
-bool g_screen_reader_honeypot_queried = false;
-bool g_acc_name_called = false;
-
// static
BrowserAccessibilityManager* BrowserAccessibilityManager::Create(
const ui::AXTreeUpdate& initial_tree,
@@ -44,7 +40,6 @@ BrowserAccessibilityManagerWin::BrowserAccessibilityManagerWin(
load_complete_pending_(false) {
ui::win::CreateATLModuleIfNeeded();
Initialize(initial_tree);
- ui::GetIAccessible2UsageObserverList().AddObserver(this);
}
BrowserAccessibilityManagerWin::~BrowserAccessibilityManagerWin() {
@@ -52,7 +47,6 @@ BrowserAccessibilityManagerWin::~BrowserAccessibilityManagerWin() {
// destructor, otherwise our overrides of functions like
// OnNodeWillBeDeleted won't be called.
tree_.reset(NULL);
- ui::GetIAccessible2UsageObserverList().RemoveObserver(this);
}
// static
@@ -76,38 +70,6 @@ HWND BrowserAccessibilityManagerWin::GetParentHWND() {
return delegate->AccessibilityGetAcceleratedWidget();
}
-void BrowserAccessibilityManagerWin::OnIAccessible2Used() {
- // When IAccessible2 APIs have been used elsewhere in the codebase,
- // enable basic web accessibility support. (Full screen reader support is
- // detected later when specific more advanced APIs are accessed.)
- BrowserAccessibilityStateImpl::GetInstance()->AddAccessibilityModeFlags(
- ui::AXMode::kNativeAPIs | ui::AXMode::kWebContents);
-}
-
-void BrowserAccessibilityManagerWin::OnScreenReaderHoneyPotQueried() {
- // We used to trust this as a signal that a screen reader is running,
- // but it's been abused. Now only enable accessibility if we also
- // detect a call to get_accName.
- if (g_screen_reader_honeypot_queried)
- return;
- g_screen_reader_honeypot_queried = true;
- if (g_acc_name_called) {
- BrowserAccessibilityStateImpl::GetInstance()->AddAccessibilityModeFlags(
- ui::AXMode::kNativeAPIs | ui::AXMode::kWebContents);
- }
-}
-
-void BrowserAccessibilityManagerWin::OnAccNameCalled() {
- // See OnScreenReaderHoneyPotQueried, above.
- if (g_acc_name_called)
- return;
- g_acc_name_called = true;
- if (g_screen_reader_honeypot_queried) {
- BrowserAccessibilityStateImpl::GetInstance()->AddAccessibilityModeFlags(
- ui::AXMode::kNativeAPIs | ui::AXMode::kWebContents);
- }
-}
-
void BrowserAccessibilityManagerWin::UserIsReloading() {
if (GetRoot())
FireWinAccessibilityEvent(IA2_EVENT_DOCUMENT_RELOAD, GetRoot());
@@ -217,6 +179,7 @@ void BrowserAccessibilityManagerWin::FireGeneratedEvent(
case Event::INVALID_STATUS_CHANGED:
case Event::LIVE_REGION_CREATED:
case Event::LIVE_REGION_NODE_CHANGED:
+ case Event::LOAD_START:
case Event::MENU_ITEM_SELECTED:
case Event::NAME_CHANGED:
case Event::OTHER_ATTRIBUTE_CHANGED:
@@ -235,6 +198,9 @@ void BrowserAccessibilityManagerWin::FireGeneratedEvent(
void BrowserAccessibilityManagerWin::FireWinAccessibilityEvent(
LONG win_event_type,
BrowserAccessibility* node) {
+ if (!node->CanFireEvents())
+ return;
+
// If there's no root delegate, this may be a new frame that hasn't
// yet been swapped in or added to the frame tree. Suppress firing events
// until then.
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_win.h b/chromium/content/browser/accessibility/browser_accessibility_manager_win.h
index 76d343421cc..88fd18b431d 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_win.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_win.h
@@ -18,8 +18,7 @@ class BrowserAccessibilityWin;
// Manages a tree of BrowserAccessibilityWin objects.
class CONTENT_EXPORT BrowserAccessibilityManagerWin
- : public BrowserAccessibilityManager,
- public ui::IAccessible2UsageObserver {
+ : public BrowserAccessibilityManager {
public:
BrowserAccessibilityManagerWin(
const ui::AXTreeUpdate& initial_tree,
@@ -33,11 +32,6 @@ class CONTENT_EXPORT BrowserAccessibilityManagerWin
// Get the closest containing HWND.
HWND GetParentHWND();
- // IAccessible2UsageObserver
- void OnIAccessible2Used() override;
- void OnScreenReaderHoneyPotQueried() override;
- void OnAccNameCalled() override;
-
// BrowserAccessibilityManager methods
void UserIsReloading() override;
BrowserAccessibility* GetFocus() override;
diff --git a/chromium/content/browser/accessibility/browser_accessibility_position.cc b/chromium/content/browser/accessibility/browser_accessibility_position.cc
index 74ba6636e49..8d11df28630 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_position.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_position.cc
@@ -36,7 +36,7 @@ void BrowserAccessibilityPosition::AnchorChild(int child_index,
DCHECK(child_id);
if (!GetAnchor() || child_index < 0 || child_index >= AnchorChildCount()) {
- *tree_id = INVALID_TREE_ID;
+ *tree_id = ui::AXTreeIDUnknown();
*child_id = INVALID_ANCHOR_ID;
return;
}
@@ -74,7 +74,7 @@ void BrowserAccessibilityPosition::AnchorParent(AXTreeID* tree_id,
DCHECK(parent_id);
if (!GetAnchor() || !GetAnchor()->PlatformGetParent()) {
- *tree_id = AXPosition::INVALID_TREE_ID;
+ *tree_id = ui::AXTreeIDUnknown();
*parent_id = AXPosition::INVALID_ANCHOR_ID;
return;
}
@@ -87,7 +87,7 @@ void BrowserAccessibilityPosition::AnchorParent(AXTreeID* tree_id,
BrowserAccessibility* BrowserAccessibilityPosition::GetNodeInTree(
AXTreeID tree_id,
int32_t node_id) const {
- if (tree_id == AXPosition::INVALID_TREE_ID ||
+ if (tree_id == ui::AXTreeIDUnknown() ||
node_id == AXPosition::INVALID_ANCHOR_ID) {
return nullptr;
}
diff --git a/chromium/content/browser/accessibility/browser_accessibility_position.h b/chromium/content/browser/accessibility/browser_accessibility_position.h
index 89ea6d8e407..d5a7a684dab 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_position.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_position.h
@@ -17,7 +17,7 @@ namespace content {
class BrowserAccessibility;
-using AXTreeID = ui::AXTreeIDRegistry::AXTreeID;
+using AXTreeID = ui::AXTreeID;
class BrowserAccessibilityPosition
: public ui::AXPosition<BrowserAccessibilityPosition,
diff --git a/chromium/content/browser/accessibility/browser_accessibility_state_impl.cc b/chromium/content/browser/accessibility/browser_accessibility_state_impl.cc
index 15faf68df8a..2c185d0ad17 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_state_impl.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_state_impl.cc
@@ -12,6 +12,7 @@
#include "build/build_config.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_switches.h"
#include "ui/accessibility/platform/ax_platform_node.h"
@@ -67,6 +68,9 @@ BrowserAccessibilityStateImpl::BrowserAccessibilityStateImpl()
// Hook ourselves up to observe ax mode changes.
ui::AXPlatformNode::AddAXModeObserver(this);
+ // Let each platform do its own initialization.
+ PlatformInitialize();
+
#if defined(OS_WIN)
// The delay is necessary because assistive technology sometimes isn't
// detected until after the user interacts in some way, so a reasonable delay
@@ -78,8 +82,8 @@ BrowserAccessibilityStateImpl::BrowserAccessibilityStateImpl()
#else
// On all other platforms, UpdateHistograms should be called on the UI
// thread because it needs to be able to access PrefService.
- BrowserThread::PostDelayedTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostDelayedTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&BrowserAccessibilityStateImpl::UpdateHistograms, this),
base::TimeDelta::FromSeconds(ACCESSIBILITY_HISTOGRAM_DELAY_SECS));
#endif
@@ -167,6 +171,8 @@ ui::AXMode BrowserAccessibilityStateImpl::GetAccessibilityMode() const {
}
#if !defined(OS_WIN) && !defined(OS_MACOSX)
+void BrowserAccessibilityStateImpl::PlatformInitialize() {}
+
void BrowserAccessibilityStateImpl::UpdatePlatformSpecificHistograms() {
}
#endif
diff --git a/chromium/content/browser/accessibility/browser_accessibility_state_impl.h b/chromium/content/browser/accessibility/browser_accessibility_state_impl.h
index 9b57bbd68d8..1b592367cb8 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_state_impl.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_state_impl.h
@@ -11,8 +11,8 @@
#include "base/macros.h"
#include "base/memory/singleton.h"
#include "content/public/browser/browser_accessibility_state.h"
+#include "ui/accessibility/ax_mode.h"
#include "ui/accessibility/ax_mode_observer.h"
-#include "ui/accessibility/ax_modes.h"
namespace content {
@@ -84,6 +84,7 @@ class CONTENT_EXPORT BrowserAccessibilityStateImpl
// Leaky singleton, destructor generally won't be called.
~BrowserAccessibilityStateImpl() override;
+ void PlatformInitialize();
void UpdatePlatformSpecificHistograms();
ui::AXMode accessibility_mode_;
diff --git a/chromium/content/browser/accessibility/browser_accessibility_state_impl_mac.mm b/chromium/content/browser/accessibility/browser_accessibility_state_impl_mac.mm
index e3a743e11a9..262083f1234 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_state_impl_mac.mm
+++ b/chromium/content/browser/accessibility/browser_accessibility_state_impl_mac.mm
@@ -18,6 +18,8 @@
namespace content {
+void BrowserAccessibilityStateImpl::PlatformInitialize() {}
+
void BrowserAccessibilityStateImpl::UpdatePlatformSpecificHistograms() {
// NOTE: This function is running on the file thread.
NSWorkspace* workspace = [NSWorkspace sharedWorkspace];
diff --git a/chromium/content/browser/accessibility/browser_accessibility_state_impl_win.cc b/chromium/content/browser/accessibility/browser_accessibility_state_impl_win.cc
index df3b54be3ca..16314d71645 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_state_impl_win.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_state_impl_win.cc
@@ -15,9 +15,65 @@
#include "base/macros.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_util.h"
+#include "ui/accessibility/platform/ax_platform_node_win.h"
namespace content {
+namespace {
+
+// Enables accessibility based on three possible clues that indicate
+// accessibility API usage.
+//
+// TODO(dmazzoni): Rename IAccessible2UsageObserver to something more general.
+class WindowsAccessibilityEnabler : public ui::IAccessible2UsageObserver {
+ public:
+ WindowsAccessibilityEnabler() {}
+
+ private:
+ // IAccessible2UsageObserver
+ void OnIAccessible2Used() override {
+ // When IAccessible2 APIs have been used elsewhere in the codebase,
+ // enable basic web accessibility support. (Full screen reader support is
+ // detected later when specific more advanced APIs are accessed.)
+ BrowserAccessibilityStateImpl::GetInstance()->AddAccessibilityModeFlags(
+ ui::AXMode::kNativeAPIs | ui::AXMode::kWebContents);
+ }
+
+ void OnScreenReaderHoneyPotQueried() override {
+ // We used to trust this as a signal that a screen reader is running,
+ // but it's been abused. Now only enable accessibility if we also
+ // detect a call to get_accName.
+ if (screen_reader_honeypot_queried_)
+ return;
+ screen_reader_honeypot_queried_ = true;
+ if (acc_name_called_) {
+ BrowserAccessibilityStateImpl::GetInstance()->AddAccessibilityModeFlags(
+ ui::AXMode::kNativeAPIs | ui::AXMode::kWebContents);
+ }
+ }
+
+ void OnAccNameCalled() override {
+ // See OnScreenReaderHoneyPotQueried, above.
+ if (acc_name_called_)
+ return;
+ acc_name_called_ = true;
+ if (screen_reader_honeypot_queried_) {
+ BrowserAccessibilityStateImpl::GetInstance()->AddAccessibilityModeFlags(
+ ui::AXMode::kNativeAPIs | ui::AXMode::kWebContents);
+ }
+ }
+
+ bool screen_reader_honeypot_queried_ = false;
+ bool acc_name_called_ = false;
+};
+
+} // namespace
+
+void BrowserAccessibilityStateImpl::PlatformInitialize() {
+ ui::GetIAccessible2UsageObserverList().AddObserver(
+ new WindowsAccessibilityEnabler());
+}
+
void BrowserAccessibilityStateImpl::UpdatePlatformSpecificHistograms() {
// NOTE: this method is run from the file thread to reduce jank, since
// there's no guarantee these system calls will return quickly. Be careful
diff --git a/chromium/content/browser/accessibility/browser_accessibility_unittest.cc b/chromium/content/browser/accessibility/browser_accessibility_unittest.cc
new file mode 100644
index 00000000000..af607ed106c
--- /dev/null
+++ b/chromium/content/browser/accessibility/browser_accessibility_unittest.cc
@@ -0,0 +1,66 @@
+// 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/browser/accessibility/browser_accessibility.h"
+
+#include "build/build_config.h"
+#include "content/browser/accessibility/browser_accessibility_manager.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+class BrowserAccessibilityTest : public testing::Test {
+ public:
+ BrowserAccessibilityTest();
+ ~BrowserAccessibilityTest() override;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(BrowserAccessibilityTest);
+};
+
+BrowserAccessibilityTest::BrowserAccessibilityTest() {}
+
+BrowserAccessibilityTest::~BrowserAccessibilityTest() {}
+
+TEST_F(BrowserAccessibilityTest, TestCanFireEvents) {
+ ui::AXNodeData text1;
+ text1.id = 111;
+ text1.role = ax::mojom::Role::kStaticText;
+ text1.SetName("One two three.");
+
+ ui::AXNodeData para1;
+ para1.id = 11;
+ para1.role = ax::mojom::Role::kParagraph;
+ para1.child_ids.push_back(text1.id);
+
+ ui::AXNodeData root;
+ root.id = 1;
+ root.role = ax::mojom::Role::kRootWebArea;
+ root.child_ids.push_back(para1.id);
+
+ std::unique_ptr<BrowserAccessibilityManager> manager(
+ BrowserAccessibilityManager::Create(MakeAXTreeUpdate(root, para1, text1),
+ nullptr,
+ new BrowserAccessibilityFactory()));
+
+ BrowserAccessibility* root_obj = manager->GetRoot();
+ EXPECT_FALSE(root_obj->PlatformIsLeaf());
+ EXPECT_TRUE(root_obj->CanFireEvents());
+
+ BrowserAccessibility* para_obj = root_obj->PlatformGetChild(0);
+ EXPECT_TRUE(para_obj->CanFireEvents());
+#if defined(OS_ANDROID)
+ EXPECT_TRUE(para_obj->PlatformIsLeaf());
+#else
+ EXPECT_FALSE(para_obj->PlatformIsLeaf());
+#endif
+
+ BrowserAccessibility* text_obj = manager->GetFromID(111);
+ EXPECT_TRUE(text_obj->PlatformIsLeaf());
+ EXPECT_TRUE(text_obj->CanFireEvents());
+
+ manager.reset();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/accessibility/dump_accessibility_browsertest_base.cc b/chromium/content/browser/accessibility/dump_accessibility_browsertest_base.cc
index 76f0ccee205..77b9831fee4 100644
--- a/chromium/content/browser/accessibility/dump_accessibility_browsertest_base.cc
+++ b/chromium/content/browser/accessibility/dump_accessibility_browsertest_base.cc
@@ -142,7 +142,8 @@ std::vector<int> DumpAccessibilityTestBase::DiffLines(
void DumpAccessibilityTestBase::ParseHtmlForExtraDirectives(
const std::string& test_html,
std::vector<Filter>* filters,
- std::vector<std::string>* wait_for) {
+ std::vector<std::string>* wait_for,
+ std::vector<std::string>* run_until) {
for (const std::string& line :
base::SplitString(test_html, "\n", base::TRIM_WHITESPACE,
base::SPLIT_WANT_ALL)) {
@@ -150,6 +151,7 @@ void DumpAccessibilityTestBase::ParseHtmlForExtraDirectives(
const std::string& allow_str = formatter_->GetAllowString();
const std::string& deny_str = formatter_->GetDenyString();
const std::string& wait_str = "@WAIT-FOR:";
+ const std::string& until_str = "@RUN-UNTIL-EVENT:";
if (base::StartsWith(line, allow_empty_str,
base::CompareCase::SENSITIVE)) {
filters->push_back(
@@ -168,6 +170,9 @@ void DumpAccessibilityTestBase::ParseHtmlForExtraDirectives(
} else if (base::StartsWith(line, wait_str,
base::CompareCase::SENSITIVE)) {
wait_for->push_back(line.substr(wait_str.size()));
+ } else if (base::StartsWith(line, until_str,
+ base::CompareCase::SENSITIVE)) {
+ run_until->push_back(line.substr(until_str.size()));
}
}
}
@@ -254,9 +259,10 @@ void DumpAccessibilityTestBase::RunTestForPlatform(
// Parse filters and other directives in the test file.
std::vector<std::string> wait_for;
+ std::vector<std::string> run_until;
filters_.clear();
AddDefaultFilters(&filters_);
- ParseHtmlForExtraDirectives(html_contents, &filters_, &wait_for);
+ ParseHtmlForExtraDirectives(html_contents, &filters_, &wait_for, &run_until);
// Get the test URL.
GURL url(embedded_test_server()->GetURL(
@@ -354,7 +360,7 @@ void DumpAccessibilityTestBase::RunTestForPlatform(
}
// Call the subclass to dump the output.
- std::vector<std::string> actual_lines = Dump();
+ std::vector<std::string> actual_lines = Dump(run_until);
std::string actual_contents_for_output =
base::JoinString(actual_lines, "\n") + "\n";
diff --git a/chromium/content/browser/accessibility/dump_accessibility_browsertest_base.h b/chromium/content/browser/accessibility/dump_accessibility_browsertest_base.h
index 0dfb953b1a4..35a8e57b8be 100644
--- a/chromium/content/browser/accessibility/dump_accessibility_browsertest_base.h
+++ b/chromium/content/browser/accessibility/dump_accessibility_browsertest_base.h
@@ -47,7 +47,8 @@ class DumpAccessibilityTestBase : public ContentBrowserTest {
// including the load complete accessibility event. The subclass should
// dump whatever that specific test wants to dump, returning the result
// as a sequence of strings.
- virtual std::vector<std::string> Dump() = 0;
+ virtual std::vector<std::string> Dump(
+ std::vector<std::string>& run_until) = 0;
// Add the default filters that are applied to all tests.
virtual void AddDefaultFilters(
@@ -92,7 +93,8 @@ class DumpAccessibilityTestBase : public ContentBrowserTest {
void ParseHtmlForExtraDirectives(
const std::string& test_html,
std::vector<AccessibilityTreeFormatter::Filter>* filters,
- std::vector<std::string>* wait_for);
+ std::vector<std::string>* wait_for,
+ std::vector<std::string>* run_until);
// Create the right AccessibilityTreeFormatter subclass.
AccessibilityTreeFormatter* CreateAccessibilityTreeFormatter();
diff --git a/chromium/content/browser/accessibility/dump_accessibility_events_browsertest.cc b/chromium/content/browser/accessibility/dump_accessibility_events_browsertest.cc
index b914cec0d63..b5d3af0d4b5 100644
--- a/chromium/content/browser/accessibility/dump_accessibility_events_browsertest.cc
+++ b/chromium/content/browser/accessibility/dump_accessibility_events_browsertest.cc
@@ -69,7 +69,7 @@ class DumpAccessibilityEventsTest : public DumpAccessibilityTestBase {
base::ASCIIToUTF16("EVENT_OBJECT_FOCUS*DOCUMENT*"), Filter::DENY));
}
- std::vector<std::string> Dump() override;
+ std::vector<std::string> Dump(std::vector<std::string>& run_until) override;
void OnDiffFailed() override;
void RunEventTest(const base::FilePath::CharType* file_path);
@@ -79,13 +79,31 @@ class DumpAccessibilityEventsTest : public DumpAccessibilityTestBase {
base::string16 final_tree_;
};
-std::vector<std::string> DumpAccessibilityEventsTest::Dump() {
+bool IsRecordingComplete(AccessibilityEventRecorder& event_recorder,
+ std::vector<std::string>& run_until) {
+ // If no @RUN-UNTIL-EVENT directives, then having any events is enough.
+ if (run_until.empty())
+ return true;
+
+ std::vector<std::string> event_logs = event_recorder.event_logs();
+
+ for (size_t i = 0; i < event_logs.size(); ++i)
+ for (size_t j = 0; j < run_until.size(); ++j)
+ if (event_logs[i].find(run_until[j]) != std::string::npos)
+ return true;
+
+ return false;
+}
+
+std::vector<std::string> DumpAccessibilityEventsTest::Dump(
+ std::vector<std::string>& run_until) {
WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(
shell()->web_contents());
base::ProcessId pid = base::GetCurrentProcId();
- auto& event_recorder = AccessibilityEventRecorder::GetInstance(
- web_contents->GetRootBrowserAccessibilityManager(), pid);
- event_recorder.set_only_web_events(true);
+ std::unique_ptr<AccessibilityEventRecorder> event_recorder(
+ AccessibilityEventRecorder::Create(
+ web_contents->GetRootBrowserAccessibilityManager(), pid));
+ event_recorder->set_only_web_events(true);
// Save a copy of the accessibility tree (as a text dump); we'll
// log this for the user later if the test fails.
@@ -102,9 +120,11 @@ std::vector<std::string> DumpAccessibilityEventsTest::Dump() {
web_contents->GetMainFrame()->ExecuteJavaScriptForTests(
base::ASCIIToUTF16("go()"));
- // Wait for at least one accessibility event generated in response to
- // that function.
- waiter->WaitForNotification();
+ for (;;) {
+ waiter->WaitForNotification(); // Run at least once.
+ if (IsRecordingComplete(*event_recorder, run_until))
+ break;
+ }
// More than one accessibility event could have been generated.
// To make sure we've received all accessibility events, add a
@@ -123,7 +143,7 @@ std::vector<std::string> DumpAccessibilityEventsTest::Dump() {
// Dump the event logs, running them through any filters specified
// in the HTML file.
- std::vector<std::string> event_logs = event_recorder.event_logs();
+ std::vector<std::string> event_logs = event_recorder->event_logs();
std::vector<std::string> result;
for (size_t i = 0; i < event_logs.size(); ++i) {
if (AccessibilityTreeFormatter::MatchesFilters(
@@ -268,6 +288,18 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest,
RunEventTest(FILE_PATH_LITERAL("checked-state-changed.html"));
}
+// http:/crbug.com/889013
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest,
+ DISABLED_AccessibilityEventsCaretHide) {
+ RunEventTest(FILE_PATH_LITERAL("caret-hide.html"));
+}
+
+// http:/crbug.com/889013
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest,
+ DISABLED_AccessibilityEventsCaretMove) {
+ RunEventTest(FILE_PATH_LITERAL("caret-move.html"));
+}
+
IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest,
AccessibilityEventsCSSDisplay) {
RunEventTest(FILE_PATH_LITERAL("css-display.html"));
@@ -423,4 +455,14 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest,
RunEventTest(FILE_PATH_LITERAL("text-changed.html"));
}
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest,
+ AccessibilityEventsAriaCheckedChanged) {
+ RunEventTest(FILE_PATH_LITERAL("aria-checked-changed.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest,
+ AccessibilityEventsAriaPressedChanged) {
+ RunEventTest(FILE_PATH_LITERAL("aria-pressed-changed.html"));
+}
+
} // namespace content
diff --git a/chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc b/chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
index 6de78219107..10e4d014626 100644
--- a/chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
+++ b/chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
@@ -125,7 +125,7 @@ class DumpAccessibilityTreeTest : public DumpAccessibilityTestBase {
RunTest(test_file, "accessibility/regression");
}
- std::vector<std::string> Dump() override {
+ std::vector<std::string> Dump(std::vector<std::string>& unused) override {
std::unique_ptr<AccessibilityTreeFormatter> formatter(
CreateAccessibilityTreeFormatter());
formatter->SetFilters(filters_);
@@ -514,6 +514,10 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaDropEffect) {
RunAriaTest(FILE_PATH_LITERAL("aria-dropeffect.html"));
}
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaEditable) {
+ RunAriaTest(FILE_PATH_LITERAL("aria-editable.html"));
+}
+
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
AccessibilityAriaErrorMessage) {
RunAriaTest(FILE_PATH_LITERAL("aria-errormessage.html"));
@@ -967,6 +971,11 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
RunAriaTest(FILE_PATH_LITERAL("table-column-hidden.html"));
}
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
+ AccessibilityLabelWithSelectedAriaOption) {
+ RunAriaTest(FILE_PATH_LITERAL("label-with-selected-option.html"));
+}
+
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityArticle) {
RunHtmlTest(FILE_PATH_LITERAL("article.html"));
}
@@ -1835,6 +1844,26 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
RunHtmlTest(FILE_PATH_LITERAL("window-crops-items.html"));
}
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
+ AccessibilityInputInsideLabel) {
+ RunHtmlTest(FILE_PATH_LITERAL("input-inside-label.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
+ AccessibilityInputImageWithTitle) {
+ RunHtmlTest(FILE_PATH_LITERAL("input-image-with-title.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
+ AccessibilityLabelWithSelectedOption) {
+ RunHtmlTest(FILE_PATH_LITERAL("label-with-selected-option.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
+ AccessibilityLabelWithPresentationalChild) {
+ RunHtmlTest(FILE_PATH_LITERAL("label-with-presentational-child.html"));
+}
+
//
// Regression tests. These don't test a specific web platform feature,
// they test a specific web page that crashed or had some bad behavior
diff --git a/chromium/content/browser/android/app_web_message_port.cc b/chromium/content/browser/android/app_web_message_port.cc
index ec7b9ba9fdf..ac0b990d8fd 100644
--- a/chromium/content/browser/android/app_web_message_port.cc
+++ b/chromium/content/browser/android/app_web_message_port.cc
@@ -10,7 +10,7 @@
#include "base/bind.h"
#include "base/threading/thread_task_runner_handle.h"
#include "jni/AppWebMessagePort_jni.h"
-#include "third_party/blink/public/common/message_port/string_message_codec.h"
+#include "third_party/blink/public/common/messaging/string_message_codec.h"
using blink::MessagePortChannel;
diff --git a/chromium/content/browser/android/app_web_message_port.h b/chromium/content/browser/android/app_web_message_port.h
index 2dd94028094..2d1f3a4d712 100644
--- a/chromium/content/browser/android/app_web_message_port.h
+++ b/chromium/content/browser/android/app_web_message_port.h
@@ -6,7 +6,7 @@
#define CONTENT_BROWSER_ANDROID_APP_WEB_MESSAGE_PORT_H_
#include "base/android/jni_weak_ref.h"
-#include "third_party/blink/public/common/message_port/message_port_channel.h"
+#include "third_party/blink/public/common/messaging/message_port_channel.h"
namespace content {
diff --git a/chromium/content/browser/android/background_sync_network_observer_android.cc b/chromium/content/browser/android/background_sync_network_observer_android.cc
index c1c514c7f4b..77844478b8d 100644
--- a/chromium/content/browser/android/background_sync_network_observer_android.cc
+++ b/chromium/content/browser/android/background_sync_network_observer_android.cc
@@ -4,6 +4,8 @@
#include "content/browser/android/background_sync_network_observer_android.h"
+#include "base/task/post_task.h"
+#include "content/public/browser/browser_task_traits.h"
#include "jni/BackgroundSyncNetworkObserver_jni.h"
using base::android::JavaParamRef;
@@ -13,12 +15,12 @@ namespace content {
// static
scoped_refptr<BackgroundSyncNetworkObserverAndroid::Observer>
BackgroundSyncNetworkObserverAndroid::Observer::Create(
- base::Callback<void(net::NetworkChangeNotifier::ConnectionType)> callback) {
+ base::Callback<void(network::mojom::ConnectionType)> callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
scoped_refptr<BackgroundSyncNetworkObserverAndroid::Observer> observer(
new BackgroundSyncNetworkObserverAndroid::Observer(callback));
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::Bind(&BackgroundSyncNetworkObserverAndroid::Observer::Init,
observer));
return observer;
@@ -48,15 +50,14 @@ void BackgroundSyncNetworkObserverAndroid::Observer::
const JavaParamRef<jobject>& jcaller,
jint new_connection_type) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::Bind(callback_,
- static_cast<net::NetworkChangeNotifier::ConnectionType>(
- new_connection_type)));
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
+ base::Bind(callback_, static_cast<network::mojom::ConnectionType>(
+ new_connection_type)));
}
BackgroundSyncNetworkObserverAndroid::Observer::Observer(
- base::Callback<void(net::NetworkChangeNotifier::ConnectionType)> callback)
+ base::Callback<void(network::mojom::ConnectionType)> callback)
: callback_(callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
}
@@ -67,15 +68,16 @@ BackgroundSyncNetworkObserverAndroid::BackgroundSyncNetworkObserverAndroid(
weak_ptr_factory_(this) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- // Remove the observer attached by the NetworkObserver constructor
- net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
-
observer_ = Observer::Create(
- base::Bind(&BackgroundSyncNetworkObserverAndroid::OnNetworkChanged,
+ base::Bind(&BackgroundSyncNetworkObserverAndroid::OnConnectionChanged,
weak_ptr_factory_.GetWeakPtr()));
}
BackgroundSyncNetworkObserverAndroid::~BackgroundSyncNetworkObserverAndroid() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
}
+
+void BackgroundSyncNetworkObserverAndroid::RegisterWithNetworkConnectionTracker(
+ network::NetworkConnectionTracker* network_connection_tracker) {}
+
} // namespace content
diff --git a/chromium/content/browser/android/background_sync_network_observer_android.h b/chromium/content/browser/android/background_sync_network_observer_android.h
index ace3b9b4f17..85f93c2d603 100644
--- a/chromium/content/browser/android/background_sync_network_observer_android.h
+++ b/chromium/content/browser/android/background_sync_network_observer_android.h
@@ -15,9 +15,9 @@
namespace content {
// BackgroundSyncNetworkObserverAndroid is a specialized
-// BackgroundSyncNetworkObserver which is backed by a NetworkChangeNotifier
+// BackgroundSyncNetworkObserver which is backed by a NetworkConnectionTracker
// that listens for network events even when the browser is paused, unlike the
-// standard NetworkChangeNotifier. This ensures that sync events can be fired
+// standard NetworkConnectionTracker. This ensures that sync events can be fired
// even when the browser is backgrounded, and other network observers are
// disabled.
class BackgroundSyncNetworkObserverAndroid
@@ -38,8 +38,7 @@ class BackgroundSyncNetworkObserverAndroid
content::BrowserThread::DeleteOnUIThread> {
public:
static scoped_refptr<BackgroundSyncNetworkObserverAndroid::Observer> Create(
- base::Callback<void(net::NetworkChangeNotifier::ConnectionType)>
- callback);
+ base::Callback<void(network::mojom::ConnectionType)> callback);
// Called from BackgroundSyncNetworkObserver.java over JNI whenever the
// connection type changes. This updates the current connection type seen by
@@ -55,20 +54,22 @@ class BackgroundSyncNetworkObserverAndroid
friend class base::DeleteHelper<
BackgroundSyncNetworkObserverAndroid::Observer>;
- Observer(base::Callback<void(net::NetworkChangeNotifier::ConnectionType)>
- callback);
+ Observer(base::Callback<void(network::mojom::ConnectionType)> callback);
void Init();
~Observer();
// This callback is to be run on the IO thread whenever the connection type
// changes.
- base::Callback<void(net::NetworkChangeNotifier::ConnectionType)> callback_;
+ base::Callback<void(network::mojom::ConnectionType)> callback_;
base::android::ScopedJavaGlobalRef<jobject> j_observer_;
DISALLOW_COPY_AND_ASSIGN(Observer);
};
private:
+ void RegisterWithNetworkConnectionTracker(
+ network::NetworkConnectionTracker* network_connection_tracker) override;
+
// Accessed on UI Thread
scoped_refptr<Observer> observer_;
diff --git a/chromium/content/browser/android/content_url_loader_factory.cc b/chromium/content/browser/android/content_url_loader_factory.cc
new file mode 100644
index 00000000000..25cc7e7006a
--- /dev/null
+++ b/chromium/content/browser/android/content_url_loader_factory.cc
@@ -0,0 +1,261 @@
+// 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_url_loader_factory.h"
+
+#include <string>
+#include <vector>
+
+#include "base/android/content_uri_utils.h"
+#include "base/bind.h"
+#include "base/files/file.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/macros.h"
+#include "base/time/time.h"
+#include "content/public/browser/content_browser_client.h"
+#include "content/public/browser/file_url_loader.h"
+#include "content/public/common/content_client.h"
+#include "mojo/public/cpp/system/data_pipe.h"
+#include "mojo/public/cpp/system/file_data_pipe_producer.h"
+#include "net/base/net_errors.h"
+#include "net/http/http_byte_range.h"
+#include "net/http/http_util.h"
+#include "services/network/public/cpp/resource_request.h"
+#include "services/network/public/mojom/url_loader.mojom.h"
+
+// TODO(eroman): Add unit-tests for "X-Chrome-intent-type"
+// (see url_request_content_job_unittest.cc).
+// TODO(eroman): Remove duplication with file_url_loader_factory.cc (notably
+// Range header parsing).
+
+namespace content {
+namespace {
+
+constexpr size_t kDefaultContentUrlPipeSize = 65536;
+
+// Assigns the byte range that has been requested based on the Range header.
+// This assumes the simplest form of the Range header using a single range.
+// If no byte range was specified, the output range will cover the entire file.
+bool GetRequestedByteRange(const network::ResourceRequest& request,
+ size_t content_size,
+ size_t* first_byte_to_send,
+ size_t* total_bytes_to_send) {
+ *first_byte_to_send = 0;
+ *total_bytes_to_send = content_size;
+
+ std::string range_header;
+ std::vector<net::HttpByteRange> ranges;
+
+ if (!request.headers.GetHeader(net::HttpRequestHeaders::kRange,
+ &range_header) ||
+ !net::HttpUtil::ParseRangeHeader(range_header, &ranges)) {
+ return true;
+ }
+
+ // Only handle a simple Range header for a single range.
+ net::HttpByteRange byte_range = ranges[0];
+ if (ranges.size() != 1 || !byte_range.ComputeBounds(content_size))
+ return false;
+
+ *first_byte_to_send = static_cast<size_t>(byte_range.first_byte_position());
+ *total_bytes_to_send = static_cast<size_t>(byte_range.last_byte_position()) -
+ *first_byte_to_send + 1;
+ return true;
+}
+
+// Gets the mimetype for |content_path| either by asking the content provider,
+// or by using the special Chrome request header X-Chrome-intent-type.
+void GetMimeType(const network::ResourceRequest& request,
+ const base::FilePath& content_path,
+ std::string* out_mime_type) {
+ out_mime_type->clear();
+
+ std::string intent_type_header;
+ if ((request.resource_type == content::RESOURCE_TYPE_MAIN_FRAME) &&
+ request.headers.GetHeader("X-Chrome-intent-type", &intent_type_header)) {
+ *out_mime_type = intent_type_header;
+ }
+
+ if (out_mime_type->empty())
+ *out_mime_type = base::GetContentUriMimeType(content_path);
+}
+
+class ContentURLLoader : public network::mojom::URLLoader {
+ public:
+ static void CreateAndStart(
+ const network::ResourceRequest& request,
+ network::mojom::URLLoaderRequest loader,
+ network::mojom::URLLoaderClientPtrInfo client_info) {
+ // 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* content_url_loader = new ContentURLLoader;
+ content_url_loader->Start(request, std::move(loader),
+ std::move(client_info));
+ }
+
+ // network::mojom::URLLoader:
+ void FollowRedirect(const base::Optional<std::vector<std::string>>&
+ to_be_removed_request_headers,
+ 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 {}
+
+ private:
+ ContentURLLoader() : binding_(this) {}
+ ~ContentURLLoader() override = default;
+
+ void Start(const network::ResourceRequest& request,
+ network::mojom::URLLoaderRequest loader,
+ network::mojom::URLLoaderClientPtrInfo client_info) {
+ network::ResourceResponseHead head;
+ head.request_start = head.response_start = base::TimeTicks::Now();
+ binding_.Bind(std::move(loader));
+ binding_.set_connection_error_handler(base::BindOnce(
+ &ContentURLLoader::OnConnectionError, base::Unretained(this)));
+
+ network::mojom::URLLoaderClientPtr client;
+ client.Bind(std::move(client_info));
+
+ DCHECK(request.url.SchemeIs("content"));
+ base::FilePath path = base::FilePath(request.url.spec());
+
+ // Get the file length.
+ base::File::Info info;
+ if (!base::GetFileInfo(path, &info))
+ return CompleteWithFailure(std::move(client), net::ERR_FILE_NOT_FOUND);
+
+ size_t first_byte_to_send;
+ size_t total_bytes_to_send;
+ if (!GetRequestedByteRange(request, info.size, &first_byte_to_send,
+ &total_bytes_to_send)) {
+ return CompleteWithFailure(std::move(client),
+ net::ERR_REQUEST_RANGE_NOT_SATISFIABLE);
+ }
+
+ mojo::DataPipe pipe(kDefaultContentUrlPipeSize);
+ if (!pipe.consumer_handle.is_valid()) {
+ return CompleteWithFailure(std::move(client), net::ERR_FAILED);
+ }
+
+ base::File file = base::OpenContentUriForRead(path);
+ if (!file.IsValid()) {
+ return CompleteWithFailure(
+ std::move(client), net::FileErrorToNetError(file.error_details()));
+ return;
+ }
+
+ total_bytes_written_ = total_bytes_to_send;
+ head.content_length = base::saturated_cast<int64_t>(total_bytes_to_send);
+
+ // Set the mimetype of the response.
+ GetMimeType(request, path, &head.mime_type);
+ if (!head.mime_type.empty() && head.headers) {
+ head.headers = base::MakeRefCounted<net::HttpResponseHeaders>("");
+ head.headers->AddHeader(
+ base::StringPrintf("%s: %s", net::HttpRequestHeaders::kContentType,
+ head.mime_type.c_str()));
+ }
+
+ client->OnReceiveResponse(head);
+ client->OnStartLoadingResponseBody(std::move(pipe.consumer_handle));
+ client_ = std::move(client);
+
+ if (total_bytes_to_send == 0) {
+ // There's no more data, so we're already done.
+ OnFileWritten(MOJO_RESULT_OK);
+ return;
+ }
+
+ // In case of a range request, seek to the appropriate position before
+ // sending the remaining bytes asynchronously. Under normal conditions
+ // (i.e., no range request) this Seek is effectively a no-op.
+ file.Seek(base::File::FROM_BEGIN, static_cast<int64_t>(first_byte_to_send));
+
+ data_producer_ = std::make_unique<mojo::FileDataPipeProducer>(
+ std::move(pipe.producer_handle), /*observer=*/nullptr);
+ data_producer_->WriteFromFile(
+ std::move(file), total_bytes_to_send,
+ base::BindOnce(&ContentURLLoader::OnFileWritten,
+ base::Unretained(this)));
+ }
+
+ void CompleteWithFailure(network::mojom::URLLoaderClientPtr client,
+ net::Error net_error) {
+ client->OnComplete(network::URLLoaderCompletionStatus(net_error));
+ MaybeDeleteSelf();
+ }
+
+ void OnConnectionError() {
+ binding_.Close();
+ MaybeDeleteSelf();
+ }
+
+ void MaybeDeleteSelf() {
+ if (!binding_.is_bound() && !client_.is_bound())
+ delete this;
+ }
+
+ 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();
+
+ if (result == MOJO_RESULT_OK) {
+ network::URLLoaderCompletionStatus status(net::OK);
+ status.encoded_data_length = total_bytes_written_;
+ status.encoded_body_length = total_bytes_written_;
+ status.decoded_body_length = total_bytes_written_;
+ client_->OnComplete(status);
+ } else {
+ client_->OnComplete(network::URLLoaderCompletionStatus(net::ERR_FAILED));
+ }
+ client_.reset();
+ MaybeDeleteSelf();
+ }
+
+ std::unique_ptr<mojo::FileDataPipeProducer> data_producer_;
+ mojo::Binding<network::mojom::URLLoader> binding_;
+ network::mojom::URLLoaderClientPtr client_;
+
+ // In case of successful loads, this holds the total of bytes written.
+ // It is used to set some of the URLLoaderCompletionStatus data passed back
+ // to the URLLoaderClients (eg SimpleURLLoader).
+ size_t total_bytes_written_ = 0;
+
+ DISALLOW_COPY_AND_ASSIGN(ContentURLLoader);
+};
+
+} // namespace
+
+ContentURLLoaderFactory::ContentURLLoaderFactory(
+ scoped_refptr<base::SequencedTaskRunner> task_runner)
+ : task_runner_(std::move(task_runner)) {}
+
+ContentURLLoaderFactory::~ContentURLLoaderFactory() = default;
+
+void ContentURLLoaderFactory::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) {
+ task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&ContentURLLoader::CreateAndStart, request,
+ std::move(loader), client.PassInterface()));
+}
+
+void ContentURLLoaderFactory::Clone(
+ network::mojom::URLLoaderFactoryRequest loader) {
+ bindings_.AddBinding(this, std::move(loader));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/android/content_url_loader_factory.h b/chromium/content/browser/android/content_url_loader_factory.h
new file mode 100644
index 00000000000..8cbe8c63054
--- /dev/null
+++ b/chromium/content/browser/android/content_url_loader_factory.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_BROWSER_ANDROID_CONTENT_URL_LOADER_FACTORY_H_
+#define CONTENT_BROWSER_ANDROID_CONTENT_URL_LOADER_FACTORY_H_
+
+#include "base/macros.h"
+#include "base/sequenced_task_runner.h"
+#include "content/common/content_export.h"
+#include "mojo/public/cpp/bindings/binding_set.h"
+#include "services/network/public/mojom/url_loader_factory.mojom.h"
+
+namespace content {
+
+// A URLLoaderFactory used for the content:// scheme used when Network Service
+// is enabled.
+class CONTENT_EXPORT ContentURLLoaderFactory
+ : public network::mojom::URLLoaderFactory {
+ public:
+ // SequencedTaskRunner must be allowed to block and should have background
+ // priority since it will be used to schedule synchronous file I/O tasks.
+ explicit ContentURLLoaderFactory(
+ scoped_refptr<base::SequencedTaskRunner> task_runner);
+ ~ContentURLLoaderFactory() override;
+
+ private:
+ // network::mojom::URLLoaderFactory:
+ 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;
+ void Clone(network::mojom::URLLoaderFactoryRequest loader) override;
+
+ const scoped_refptr<base::SequencedTaskRunner> task_runner_;
+ mojo::BindingSet<network::mojom::URLLoaderFactory> bindings_;
+
+ DISALLOW_COPY_AND_ASSIGN(ContentURLLoaderFactory);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_ANDROID_CONTENT_URL_LOADER_FACTORY_H_
diff --git a/chromium/content/browser/android/dialog_overlay_impl.cc b/chromium/content/browser/android/dialog_overlay_impl.cc
index 70457ba7490..a6a952bd31f 100644
--- a/chromium/content/browser/android/dialog_overlay_impl.cc
+++ b/chromium/content/browser/android/dialog_overlay_impl.cc
@@ -71,7 +71,8 @@ DialogOverlayImpl::DialogOverlayImpl(const JavaParamRef<jobject>& obj,
bool power_efficient)
: WebContentsObserver(web_contents),
rfhi_(rfhi),
- power_efficient_(power_efficient) {
+ power_efficient_(power_efficient),
+ observed_window_android_(false) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(rfhi_);
@@ -105,9 +106,11 @@ void DialogOverlayImpl::CompleteInit(JNIEnv* env,
// Send the initial token, if there is one. The observer will notify us about
// changes only.
if (auto* window = web_contents()->GetNativeView()->GetWindowAndroid()) {
+ RegisterWindowObserverIfNeeded(window);
ScopedJavaLocalRef<jobject> token = window->GetWindowToken();
- if (!token.is_null())
+ if (!token.is_null()) {
Java_DialogOverlayImpl_onWindowToken(env, obj, token);
+ }
// else we will send one if we get a callback from ViewAndroid.
}
}
@@ -117,7 +120,7 @@ DialogOverlayImpl::~DialogOverlayImpl() {
}
void DialogOverlayImpl::Stop() {
- UnregisterForTokensIfNeeded();
+ UnregisterCallbacksIfNeeded();
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj = obj_.get(env);
@@ -129,7 +132,7 @@ void DialogOverlayImpl::Stop() {
void DialogOverlayImpl::Destroy(JNIEnv* env, const JavaParamRef<jobject>& obj) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- UnregisterForTokensIfNeeded();
+ UnregisterCallbacksIfNeeded();
// We delete soon since this might be part of an onDismissed callback.
BrowserThread::DeleteSoon(BrowserThread::UI, FROM_HERE, this);
}
@@ -145,7 +148,7 @@ void DialogOverlayImpl::GetCompositorOffset(
point.y());
}
-void DialogOverlayImpl::UnregisterForTokensIfNeeded() {
+void DialogOverlayImpl::UnregisterCallbacksIfNeeded() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (!rfhi_)
@@ -157,7 +160,12 @@ void DialogOverlayImpl::UnregisterForTokensIfNeeded() {
WebContentsDelegate* delegate = web_contents()->GetDelegate();
if (delegate)
delegate->SetOverlayMode(false);
-
+ if (observed_window_android_) {
+ auto* window_android = web_contents()->GetNativeView()->GetWindowAndroid();
+ if (window_android)
+ window_android->RemoveObserver(this);
+ observed_window_android_ = false;
+ }
web_contents()->GetNativeView()->RemoveObserver(this);
rfhi_ = nullptr;
}
@@ -187,6 +195,11 @@ void DialogOverlayImpl::OnVisibilityChanged(content::Visibility visibility) {
Stop();
}
+void DialogOverlayImpl::OnRootWindowVisibilityChanged(bool visible) {
+ if (!visible)
+ Stop();
+}
+
void DialogOverlayImpl::WebContentsDestroyed() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
Stop();
@@ -213,9 +226,10 @@ void DialogOverlayImpl::OnAttachedToWindow() {
ScopedJavaLocalRef<jobject> token;
- if (auto* window = web_contents()->GetNativeView()->GetWindowAndroid())
+ if (auto* window = web_contents()->GetNativeView()->GetWindowAndroid()) {
+ RegisterWindowObserverIfNeeded(window);
token = window->GetWindowToken();
-
+ }
ScopedJavaLocalRef<jobject> obj = obj_.get(env);
if (!obj.is_null())
Java_DialogOverlayImpl_onWindowToken(env, obj, token);
@@ -226,6 +240,15 @@ void DialogOverlayImpl::OnDetachedFromWindow() {
ScopedJavaLocalRef<jobject> obj = obj_.get(env);
if (!obj.is_null())
Java_DialogOverlayImpl_onWindowToken(env, obj, nullptr);
+ Stop();
+}
+
+void DialogOverlayImpl::RegisterWindowObserverIfNeeded(
+ ui::WindowAndroid* window) {
+ if (!observed_window_android_) {
+ observed_window_android_ = true;
+ window->AddObserver(this);
+ }
}
static jint JNI_DialogOverlayImpl_RegisterSurface(
diff --git a/chromium/content/browser/android/dialog_overlay_impl.h b/chromium/content/browser/android/dialog_overlay_impl.h
index 4cb4cbef524..1e955a8c085 100644
--- a/chromium/content/browser/android/dialog_overlay_impl.h
+++ b/chromium/content/browser/android/dialog_overlay_impl.h
@@ -12,6 +12,8 @@
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/public/browser/web_contents_observer.h"
#include "ui/android/view_android_observer.h"
+#include "ui/android/window_android.h"
+#include "ui/android/window_android_observer.h"
namespace content {
@@ -20,6 +22,7 @@ namespace content {
// detached from a WindowAndroid, we get the Android window token and notify the
// java side.
class DialogOverlayImpl : public ui::ViewAndroidObserver,
+ public ui::WindowAndroidObserver,
public WebContentsObserver {
public:
// This may not call back into |obj| directly, but must post. This is because
@@ -59,12 +62,21 @@ class DialogOverlayImpl : public ui::ViewAndroidObserver,
void RenderFrameHostChanged(RenderFrameHost* old_host,
RenderFrameHost* new_host) override;
- // Unregister for tokens if we're registered.
- void UnregisterForTokensIfNeeded();
+ // Unregister callbacks if previously registered.
+ void UnregisterCallbacksIfNeeded();
+
+ // WindowAndroidObserver
+ void OnRootWindowVisibilityChanged(bool visible) override;
+ void OnCompositingDidCommit() override {}
+ void OnAttachCompositor() override {}
+ void OnDetachCompositor() override {}
+ void OnActivityStopped() override {}
+ void OnActivityStarted() override {}
private:
// Signals the overlay should be cleaned up and no longer used.
void Stop();
+ void RegisterWindowObserverIfNeeded(ui::WindowAndroid* window);
// Java object that owns us.
JavaObjectWeakGlobalRef obj_;
@@ -74,6 +86,9 @@ class DialogOverlayImpl : public ui::ViewAndroidObserver,
// Do we care about power efficiency?
bool power_efficient_;
+
+ // Whether we added ourselves as an observer through WindowAndroid.
+ bool observed_window_android_;
};
} // namespace content
diff --git a/chromium/content/browser/android/gesture_listener_manager.cc b/chromium/content/browser/android/gesture_listener_manager.cc
index 676329795a4..4d03f78eec8 100644
--- a/chromium/content/browser/android/gesture_listener_manager.cc
+++ b/chromium/content/browser/android/gesture_listener_manager.cc
@@ -111,7 +111,7 @@ GestureListenerManager::~GestureListenerManager() {
ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
if (j_obj.is_null())
return;
- Java_GestureListenerManagerImpl_onDestroy(env, j_obj);
+ Java_GestureListenerManagerImpl_onNativeDestroyed(env, j_obj);
}
void GestureListenerManager::ResetGestureDetection(
diff --git a/chromium/content/browser/android/ime_adapter_android.cc b/chromium/content/browser/android/ime_adapter_android.cc
index 6bb9735fc5b..cdc5d3255cb 100644
--- a/chromium/content/browser/android/ime_adapter_android.cc
+++ b/chromium/content/browser/android/ime_adapter_android.cc
@@ -14,6 +14,7 @@
#include "base/android/scoped_java_ref.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
+#include "content/browser/android/text_suggestion_host_android.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/renderer_host/render_view_host_delegate.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
@@ -144,13 +145,17 @@ ImeAdapterAndroid::ImeAdapterAndroid(JNIEnv* env,
WebContents* web_contents)
: RenderWidgetHostConnector(web_contents), rwhva_(nullptr) {
java_ime_adapter_ = JavaObjectWeakGlobalRef(env, obj);
+
+ // Set up mojo client for TextSuggestionHost in advance. Java side is
+ // initialized lazily right before showing the menu first time.
+ TextSuggestionHostAndroid::Create(env, web_contents);
}
ImeAdapterAndroid::~ImeAdapterAndroid() {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj = java_ime_adapter_.get(env);
if (!obj.is_null())
- Java_ImeAdapterImpl_destroy(env, obj);
+ Java_ImeAdapterImpl_onNativeDestroyed(env, obj);
}
void ImeAdapterAndroid::UpdateRenderProcessConnection(
diff --git a/chromium/content/browser/android/java/gin_java_bridge_dispatcher_host.h b/chromium/content/browser/android/java/gin_java_bridge_dispatcher_host.h
index 8e55c6434e9..db327b40960 100644
--- a/chromium/content/browser/android/java/gin_java_bridge_dispatcher_host.h
+++ b/chromium/content/browser/android/java/gin_java_bridge_dispatcher_host.h
@@ -15,6 +15,7 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/synchronization/lock.h"
+#include "base/thread_annotations.h"
#include "content/browser/android/java/gin_java_bound_object.h"
#include "content/browser/android/java/gin_java_method_invocation_helper.h"
#include "content/public/browser/web_contents_observer.h"
@@ -95,9 +96,9 @@ class GinJavaBridgeDispatcherHost
bool FindObjectId(const base::android::JavaRef<jobject>& object,
GinJavaBoundObject::ObjectID* object_id);
void RemoveFromRetainedObjectSetLocked(const JavaObjectWeakGlobalRef& ref);
- JavaObjectWeakGlobalRef RemoveHolderLocked(
- int32_t holder,
- ObjectMap::iterator* iter_ptr);
+ JavaObjectWeakGlobalRef RemoveHolderLocked(int32_t holder,
+ ObjectMap::iterator* iter_ptr)
+ EXCLUSIVE_LOCKS_REQUIRED(objects_lock_);
// The following objects are used only on the UI thread.
@@ -116,7 +117,7 @@ class GinJavaBridgeDispatcherHost
JavaObjectWeakGlobalRef retained_object_set_;
// Note that retained_object_set_ does not need to be consistent
// with objects_.
- ObjectMap objects_;
+ ObjectMap objects_ GUARDED_BY(objects_lock_);
base::Lock objects_lock_;
// The following objects are only used on the background thread.
diff --git a/chromium/content/browser/android/java/gin_java_bridge_message_filter.cc b/chromium/content/browser/android/java/gin_java_bridge_message_filter.cc
index 9c2feb1a847..2a3872237b2 100644
--- a/chromium/content/browser/android/java/gin_java_bridge_message_filter.cc
+++ b/chromium/content/browser/android/java/gin_java_bridge_message_filter.cc
@@ -84,6 +84,21 @@ void GinJavaBridgeMessageFilter::RemoveHost(GinJavaBridgeDispatcherHost* host) {
}
}
+void GinJavaBridgeMessageFilter::RenderProcessExited(
+ RenderProcessHost* rph,
+ const ChildProcessTerminationInfo& info) {
+#if DCHECK_IS_ON()
+ {
+ scoped_refptr<GinJavaBridgeMessageFilter> filter =
+ base::UserDataAdapter<GinJavaBridgeMessageFilter>::Get(
+ rph, kGinJavaBridgeMessageFilterKey);
+ DCHECK_EQ(this, filter.get());
+ }
+#endif
+ rph->RemoveObserver(this);
+ rph->RemoveUserData(kGinJavaBridgeMessageFilterKey);
+}
+
// static
scoped_refptr<GinJavaBridgeMessageFilter> GinJavaBridgeMessageFilter::FromHost(
GinJavaBridgeDispatcherHost* host, bool create_if_not_exists) {
@@ -94,6 +109,8 @@ scoped_refptr<GinJavaBridgeMessageFilter> GinJavaBridgeMessageFilter::FromHost(
if (!filter && create_if_not_exists) {
filter = new GinJavaBridgeMessageFilter();
rph->AddFilter(filter.get());
+ rph->AddObserver(filter.get());
+
rph->SetUserData(
kGinJavaBridgeMessageFilterKey,
std::make_unique<base::UserDataAdapter<GinJavaBridgeMessageFilter>>(
diff --git a/chromium/content/browser/android/java/gin_java_bridge_message_filter.h b/chromium/content/browser/android/java/gin_java_bridge_message_filter.h
index b117d2d5d53..c15bc707920 100644
--- a/chromium/content/browser/android/java/gin_java_bridge_message_filter.h
+++ b/chromium/content/browser/android/java/gin_java_bridge_message_filter.h
@@ -12,9 +12,11 @@
#include "base/memory/ref_counted.h"
#include "base/synchronization/lock.h"
+#include "base/thread_annotations.h"
#include "content/browser/android/java/gin_java_bound_object.h"
#include "content/common/android/gin_java_bridge_errors.h"
#include "content/public/browser/browser_message_filter.h"
+#include "content/public/browser/render_process_host_observer.h"
namespace base {
class ListValue;
@@ -29,7 +31,8 @@ namespace content {
class GinJavaBridgeDispatcherHost;
class RenderFrameHost;
-class GinJavaBridgeMessageFilter : public BrowserMessageFilter {
+class GinJavaBridgeMessageFilter : public BrowserMessageFilter,
+ public RenderProcessHostObserver {
public:
// BrowserMessageFilter
void OnDestruct() const override;
@@ -37,6 +40,10 @@ class GinJavaBridgeMessageFilter : public BrowserMessageFilter {
base::TaskRunner* OverrideTaskRunnerForMessage(
const IPC::Message& message) override;
+ // RenderProcessHostObserver
+ void RenderProcessExited(RenderProcessHost* rph,
+ const ChildProcessTerminationInfo& info) override;
+
// Called on the UI thread.
void AddRoutingIdForHost(GinJavaBridgeDispatcherHost* host,
RenderFrameHost* render_frame_host);
@@ -81,7 +88,7 @@ class GinJavaBridgeMessageFilter : public BrowserMessageFilter {
void OnObjectWrapperDeleted(GinJavaBoundObject::ObjectID object_id);
// Accessed both from UI and background threads.
- HostMap hosts_;
+ HostMap hosts_ GUARDED_BY(hosts_lock_);
base::Lock hosts_lock_;
// The routing id of the RenderFrameHost whose request we are processing.
diff --git a/chromium/content/browser/android/java/jni_reflect.cc b/chromium/content/browser/android/java/jni_reflect.cc
new file mode 100644
index 00000000000..cc2ef8b6cde
--- /dev/null
+++ b/chromium/content/browser/android/java/jni_reflect.cc
@@ -0,0 +1,63 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/android/java/jni_reflect.h"
+
+#include "base/android/jni_android.h"
+#include "base/android/jni_string.h"
+
+#include "jni/AccessibleObject_jni.h"
+#include "jni/Class_jni.h"
+#include "jni/Method_jni.h"
+#include "jni/Modifier_jni.h"
+
+using base::android::ConvertJavaStringToUTF8;
+using base::android::JavaRef;
+using base::android::ScopedJavaLocalRef;
+
+namespace content {
+
+std::string GetClassName(JNIEnv* env, const JavaRef<jclass>& clazz) {
+ return ConvertJavaStringToUTF8(JNI_Class::Java_Class_getName(env, clazz));
+}
+
+ScopedJavaLocalRef<jobjectArray> GetClassMethods(JNIEnv* env,
+ const JavaRef<jclass>& clazz) {
+ return JNI_Class::Java_Class_getMethods(env, clazz);
+}
+
+std::string GetMethodName(JNIEnv* env, const JavaRef<jobject>& method) {
+ return ConvertJavaStringToUTF8(JNI_Method::Java_Method_getName(env, method));
+}
+
+ScopedJavaLocalRef<jobjectArray> GetMethodParameterTypes(
+ JNIEnv* env,
+ const JavaRef<jobject>& method) {
+ return JNI_Method::Java_Method_getParameterTypes(env, method);
+}
+
+ScopedJavaLocalRef<jclass> GetMethodReturnType(JNIEnv* env,
+ const JavaRef<jobject>& method) {
+ return JNI_Method::Java_Method_getReturnType(env, method);
+}
+
+ScopedJavaLocalRef<jclass> GetMethodDeclaringClass(
+ JNIEnv* env,
+ const JavaRef<jobject>& method) {
+ return JNI_Method::Java_Method_getDeclaringClass(env, method);
+}
+
+bool IsMethodStatic(JNIEnv* env, const JavaRef<jobject>& method) {
+ jint modifiers = JNI_Method::Java_Method_getModifiers(env, method);
+ return JNI_Modifier::Java_Modifier_isStatic(env, modifiers);
+}
+
+bool IsAnnotationPresent(JNIEnv* env,
+ const JavaRef<jobject>& obj,
+ const JavaRef<jclass>& annotation_clazz) {
+ return JNI_AccessibleObject::Java_AccessibleObject_isAnnotationPresent(
+ env, obj, annotation_clazz);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/android/java/jni_reflect.h b/chromium/content/browser/android/java/jni_reflect.h
new file mode 100644
index 00000000000..b7455fd4dcd
--- /dev/null
+++ b/chromium/content/browser/android/java/jni_reflect.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_ANDROID_JAVA_JNI_REFLECT_H_
+#define CONTENT_BROWSER_ANDROID_JAVA_JNI_REFLECT_H_
+
+#include <jni.h>
+#include <string>
+
+#include "base/android/scoped_java_ref.h"
+
+namespace content {
+
+// Return the class's name.
+std::string GetClassName(JNIEnv* env,
+ const base::android::JavaRef<jclass>& clazz);
+
+// Return an array of Method objects for the public methods of clazz.
+base::android::ScopedJavaLocalRef<jobjectArray> GetClassMethods(
+ JNIEnv* env,
+ const base::android::JavaRef<jclass>& clazz);
+
+// Return the method's name.
+std::string GetMethodName(JNIEnv* env,
+ const base::android::JavaRef<jobject>& method);
+
+// Return an array listing the method's parameter types.
+base::android::ScopedJavaLocalRef<jobjectArray> GetMethodParameterTypes(
+ JNIEnv* env,
+ const base::android::JavaRef<jobject>& method);
+
+// Return the method's return type.
+base::android::ScopedJavaLocalRef<jclass> GetMethodReturnType(
+ JNIEnv* env,
+ const base::android::JavaRef<jobject>& method);
+
+// Return the method's declaring class.
+base::android::ScopedJavaLocalRef<jclass> GetMethodDeclaringClass(
+ JNIEnv* env,
+ const base::android::JavaRef<jobject>& method);
+
+// Check if the method is static.
+bool IsMethodStatic(JNIEnv* env, const base::android::JavaRef<jobject>& method);
+
+// Check if the annotation identified by annotation_clazz is present on the
+// object obj.
+bool IsAnnotationPresent(
+ JNIEnv* env,
+ const base::android::JavaRef<jobject>& obj,
+ const base::android::JavaRef<jclass>& annotation_clazz);
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_ANDROID_JAVA_JNI_REFLECT_H_
diff --git a/chromium/content/browser/android/scoped_surface_request_manager.cc b/chromium/content/browser/android/scoped_surface_request_manager.cc
index 6d67c9f810d..d37d66eb3e7 100644
--- a/chromium/content/browser/android/scoped_surface_request_manager.cc
+++ b/chromium/content/browser/android/scoped_surface_request_manager.cc
@@ -4,6 +4,8 @@
#include "content/browser/android/scoped_surface_request_manager.h"
+#include "base/task/post_task.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
namespace content {
@@ -64,8 +66,8 @@ void ScopedSurfaceRequestManager::FulfillScopedSurfaceRequest(
gl::ScopedJavaSurface surface) {
// base::Unretained is safe because the lifetime of this object is tied to
// the lifetime of the browser process.
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::Bind(&ScopedSurfaceRequestManager::CompleteRequestOnUiThread,
base::Unretained(this), request_token,
base::Passed(&surface)));
diff --git a/chromium/content/browser/android/select_popup.cc b/chromium/content/browser/android/select_popup.cc
index 44d187ced2e..404e2194a4a 100644
--- a/chromium/content/browser/android/select_popup.cc
+++ b/chromium/content/browser/android/select_popup.cc
@@ -53,7 +53,7 @@ SelectPopup::~SelectPopup() {
ScopedJavaLocalRef<jobject> j_obj = java_obj_.get(env);
if (j_obj.is_null())
return;
- Java_SelectPopup_destroy(env, j_obj);
+ Java_SelectPopup_onNativeDestroyed(env, j_obj);
}
void SelectPopup::ShowMenu(RenderFrameHost* frame,
diff --git a/chromium/content/browser/android/synchronous_compositor_host.cc b/chromium/content/browser/android/synchronous_compositor_host.cc
index 58d7822c4aa..ff49053fcc2 100644
--- a/chromium/content/browser/android/synchronous_compositor_host.cc
+++ b/chromium/content/browser/android/synchronous_compositor_host.cc
@@ -11,6 +11,7 @@
#include "base/containers/hash_tables.h"
#include "base/memory/ptr_util.h"
#include "base/memory/shared_memory.h"
+#include "base/task/post_task.h"
#include "base/threading/thread_restrictions.h"
#include "base/trace_event/trace_event_argument.h"
#include "content/browser/android/synchronous_compositor_sync_call_bridge.h"
@@ -20,6 +21,7 @@
#include "content/common/android/sync_compositor_statics.h"
#include "content/common/input/sync_compositor_messages.h"
#include "content/public/browser/android/synchronous_compositor_client.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/common/content_features.h"
@@ -53,8 +55,8 @@ class SynchronousCompositorControlHost
scoped_refptr<SynchronousCompositorSyncCallBridge> bridge,
int process_id) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&CreateOnIOThread, std::move(request), std::move(bridge),
process_id));
}
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 1f560661134..5a312ae3381 100644
--- a/chromium/content/browser/android/synchronous_compositor_sync_call_bridge.cc
+++ b/chromium/content/browser/android/synchronous_compositor_sync_call_bridge.cc
@@ -4,8 +4,10 @@
#include "content/browser/android/synchronous_compositor_sync_call_bridge.h"
+#include "base/task/post_task.h"
#include "content/browser/android/synchronous_compositor_host.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_features.h"
#include "ui/android/window_android.h"
@@ -54,8 +56,8 @@ bool SynchronousCompositorSyncCallBridge::ReceiveFrameOnIOThread(
frame_futures_.pop_front();
if (compositor_frame) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&SynchronousCompositorSyncCallBridge::
ProcessFrameMetadataOnUIThread,
this, metadata_version,
@@ -85,7 +87,7 @@ bool SynchronousCompositorSyncCallBridge::WaitAfterVSyncOnUIThread(
base::AutoLock lock(lock_);
if (remote_state_ != RemoteState::READY)
return false;
- DCHECK(!begin_frame_response_valid_);
+ CHECK(!begin_frame_response_valid_);
if (window_android_in_vsync_) {
DCHECK_EQ(window_android_in_vsync_, window_android);
return true;
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 36dc19df4ad..1b833f9b6e4 100644
--- a/chromium/content/browser/android/synchronous_compositor_sync_call_bridge.h
+++ b/chromium/content/browser/android/synchronous_compositor_sync_call_bridge.h
@@ -8,6 +8,7 @@
#include "base/containers/circular_deque.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "base/thread_annotations.h"
#include "components/viz/common/quads/compositor_frame.h"
#include "content/common/input/sync_compositor_messages.h"
#include "content/public/browser/android/synchronous_compositor.h"
@@ -114,7 +115,8 @@ class SynchronousCompositorSyncCallBridge
viz::CompositorFrameMetadata metadata);
// Signal all waiters for closure. Callee must host a lock to |lock_|.
- void SignalRemoteClosedToAllWaitersOnIOThread();
+ void SignalRemoteClosedToAllWaitersOnIOThread()
+ EXCLUSIVE_LOCKS_REQUIRED(lock_);
using FrameFutureQueue =
base::circular_deque<scoped_refptr<SynchronousCompositor::FrameFuture>>;
@@ -129,11 +131,11 @@ class SynchronousCompositorSyncCallBridge
// Shared variables between the IO thread and UI thread.
base::Lock lock_;
- FrameFutureQueue frame_futures_;
- bool begin_frame_response_valid_ = false;
- SyncCompositorCommonRendererParams last_render_params_;
- base::ConditionVariable begin_frame_condition_;
- RemoteState remote_state_ = RemoteState::INIT;
+ FrameFutureQueue frame_futures_ GUARDED_BY(lock_);
+ bool begin_frame_response_valid_ GUARDED_BY(lock_) = false;
+ SyncCompositorCommonRendererParams last_render_params_ GUARDED_BY(lock_);
+ base::ConditionVariable begin_frame_condition_ GUARDED_BY(lock_);
+ RemoteState remote_state_ GUARDED_BY(lock_) = RemoteState::INIT;
DISALLOW_COPY_AND_ASSIGN(SynchronousCompositorSyncCallBridge);
};
diff --git a/chromium/content/browser/android/text_suggestion_host_android.cc b/chromium/content/browser/android/text_suggestion_host_android.cc
index ac308472dda..c571a952c47 100644
--- a/chromium/content/browser/android/text_suggestion_host_android.cc
+++ b/chromium/content/browser/android/text_suggestion_host_android.cc
@@ -34,25 +34,17 @@ const size_t kMaxNumberOfSuggestions = 5;
} // namespace
-jlong JNI_TextSuggestionHost_Init(JNIEnv* env,
- const JavaParamRef<jobject>& obj,
- const JavaParamRef<jobject>& jweb_contents) {
- WebContents* web_contents = WebContents::FromJavaWebContents(jweb_contents);
- DCHECK(web_contents);
- auto* text_suggestion_host =
- new TextSuggestionHostAndroid(env, obj, web_contents);
+void TextSuggestionHostAndroid::Create(JNIEnv* env, WebContents* web_contents) {
+ auto* text_suggestion_host = new TextSuggestionHostAndroid(env, web_contents);
text_suggestion_host->Initialize();
- return reinterpret_cast<intptr_t>(text_suggestion_host);
}
TextSuggestionHostAndroid::TextSuggestionHostAndroid(
JNIEnv* env,
- const JavaParamRef<jobject>& obj,
WebContents* web_contents)
: RenderWidgetHostConnector(web_contents),
WebContentsObserver(web_contents),
rwhva_(nullptr),
- java_text_suggestion_host_(JavaObjectWeakGlobalRef(env, obj)),
suggestion_menu_timeout_(
base::Bind(&TextSuggestionHostAndroid::OnSuggestionMenuTimeout,
base::Unretained(this))) {
@@ -64,7 +56,7 @@ TextSuggestionHostAndroid::~TextSuggestionHostAndroid() {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj = java_text_suggestion_host_.get(env);
if (!obj.is_null())
- Java_TextSuggestionHost_destroy(env, obj);
+ Java_TextSuggestionHost_onNativeDestroyed(env, obj);
}
void TextSuggestionHostAndroid::UpdateRenderProcessConnection(
@@ -144,6 +136,19 @@ double TextSuggestionHostAndroid::DpToPxIfNeeded(double value) {
return value;
}
+ScopedJavaLocalRef<jobject>
+TextSuggestionHostAndroid::GetJavaTextSuggestionHost() {
+ JNIEnv* env = AttachCurrentThread();
+ ScopedJavaLocalRef<jobject> obj = java_text_suggestion_host_.get(env);
+ if (obj.is_null()) {
+ obj = Java_TextSuggestionHost_create(
+ env, WebContentsObserver::web_contents()->GetJavaWebContents(),
+ reinterpret_cast<intptr_t>(this));
+ java_text_suggestion_host_ = JavaObjectWeakGlobalRef(env, obj);
+ }
+ return obj;
+}
+
void TextSuggestionHostAndroid::ShowSpellCheckSuggestionMenu(
double caret_x,
double caret_y,
@@ -155,7 +160,7 @@ void TextSuggestionHostAndroid::ShowSpellCheckSuggestionMenu(
for (size_t i = 0; i < suggestions.size() && i < kMaxNumberOfSuggestions; ++i)
suggestion_strings.push_back(suggestions[i]->suggestion);
JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jobject> obj = java_text_suggestion_host_.get(env);
+ ScopedJavaLocalRef<jobject> obj = GetJavaTextSuggestionHost();
if (obj.is_null())
return;
@@ -173,7 +178,9 @@ void TextSuggestionHostAndroid::ShowTextSuggestionMenu(
const std::string& marked_text,
const std::vector<blink::mojom::TextSuggestionPtr>& suggestions) {
JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jobject> obj = java_text_suggestion_host_.get(env);
+ ScopedJavaLocalRef<jobject> obj = GetJavaTextSuggestionHost();
+ if (obj.is_null())
+ return;
// Enforce kMaxNumberOfSuggestions here in case the renderer is hijacked and
// tries to send bad input.
diff --git a/chromium/content/browser/android/text_suggestion_host_android.h b/chromium/content/browser/android/text_suggestion_host_android.h
index af220c331ff..e2b690a252f 100644
--- a/chromium/content/browser/android/text_suggestion_host_android.h
+++ b/chromium/content/browser/android/text_suggestion_host_android.h
@@ -18,13 +18,13 @@ namespace content {
// misspelled word. This class creates the Android implementation of
// mojom::TextSuggestionHost, which is used to communicate back-and-forth with
// Blink side code (these are separate classes due to lifecycle considerations;
-// this class needs to be constructed from Java code, but Mojo code wants to
-// take ownership of mojom::TextSuggestionHost).
+// this class is created by ImeAdapterAndroid ctor and destroyed together with
+// WebContents. Mojo code takes ownership of mojom::TextSuggestionHost).
class TextSuggestionHostAndroid : public RenderWidgetHostConnector,
public WebContentsObserver {
public:
+ static void Create(JNIEnv* env, WebContents* web_contents);
TextSuggestionHostAndroid(JNIEnv* env,
- const base::android::JavaParamRef<jobject>& obj,
WebContents* web_contents);
~TextSuggestionHostAndroid() override;
@@ -95,6 +95,7 @@ class TextSuggestionHostAndroid : public RenderWidgetHostConnector,
private:
RenderFrameHost* GetFocusedFrame();
+ base::android::ScopedJavaLocalRef<jobject> GetJavaTextSuggestionHost();
const blink::mojom::TextSuggestionBackendPtr& GetTextSuggestionBackend();
// Used by the spell check menu timer to notify Blink that the timer has
// expired.
diff --git a/chromium/content/browser/android/url_request_content_job.h b/chromium/content/browser/android/url_request_content_job.h
index 40a97470a83..e389fdd3073 100644
--- a/chromium/content/browser/android/url_request_content_job.h
+++ b/chromium/content/browser/android/url_request_content_job.h
@@ -31,6 +31,9 @@ class FileStream;
namespace content {
// A request job that handles reading content URIs
+//
+// Note that when the Network Service is enabled, ContentUrlLoaderFactory is
+// used instead.
class CONTENT_EXPORT URLRequestContentJob : public net::URLRequestJob {
public:
URLRequestContentJob(
diff --git a/chromium/content/browser/android/web_contents_observer_proxy.cc b/chromium/content/browser/android/web_contents_observer_proxy.cc
index 988ede89422..84b5241b810 100644
--- a/chromium/content/browser/android/web_contents_observer_proxy.cc
+++ b/chromium/content/browser/android/web_contents_observer_proxy.cc
@@ -138,8 +138,13 @@ void WebContentsObserverProxy::DidStartNavigation(
void WebContentsObserverProxy::DidFinishNavigation(
NavigationHandle* navigation_handle) {
JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jstring> jstring_url(
- ConvertUTF8ToJavaString(env, navigation_handle->GetURL().spec()));
+ // Matches logic in
+ // components/navigation_interception/navigation_params_android.cc
+ ScopedJavaLocalRef<jstring> jstring_url(ConvertUTF8ToJavaString(
+ env,
+ navigation_handle->GetBaseURLForDataURL().is_empty()
+ ? navigation_handle->GetURL().spec()
+ : navigation_handle->GetBaseURLForDataURL().possibly_invalid_spec()));
bool is_fragment_navigation = navigation_handle->IsSameDocument();
@@ -161,6 +166,7 @@ void WebContentsObserverProxy::DidFinishNavigation(
env, java_observer_, jstring_url, navigation_handle->IsInMainFrame(),
navigation_handle->IsErrorPage(), navigation_handle->HasCommitted(),
navigation_handle->IsSameDocument(), is_fragment_navigation,
+ navigation_handle->IsRendererInitiated(), navigation_handle->IsDownload(),
navigation_handle->HasCommitted() ? navigation_handle->GetPageTransition()
: -1,
navigation_handle->GetNetErrorCode(), jerror_description,
@@ -277,4 +283,9 @@ void WebContentsObserverProxy::ViewportFitChanged(
env, java_observer_, as_jint(static_cast<int>(value)));
}
+void WebContentsObserverProxy::DidReloadLoFiImages() {
+ JNIEnv* env = AttachCurrentThread();
+ Java_WebContentsObserverProxy_didReloadLoFiImages(env, java_observer_);
+}
+
} // namespace content
diff --git a/chromium/content/browser/android/web_contents_observer_proxy.h b/chromium/content/browser/android/web_contents_observer_proxy.h
index e79ad3edb59..ccc54e0a776 100644
--- a/chromium/content/browser/android/web_contents_observer_proxy.h
+++ b/chromium/content/browser/android/web_contents_observer_proxy.h
@@ -59,6 +59,7 @@ class WebContentsObserverProxy : public WebContentsObserver {
void MediaEffectivelyFullscreenChanged(bool is_fullscreen) override;
void SetToBaseURLForDataURLIfNeeded(std::string* url);
void ViewportFitChanged(blink::mojom::ViewportFit value) override;
+ void DidReloadLoFiImages() override;
base::android::ScopedJavaGlobalRef<jobject> java_observer_;
GURL base_url_of_last_started_data_url_;
diff --git a/chromium/content/browser/appcache/appcache.cc b/chromium/content/browser/appcache/appcache.cc
index 5390894d2ed..0dc8369a996 100644
--- a/chromium/content/browser/appcache/appcache.cc
+++ b/chromium/content/browser/appcache/appcache.cc
@@ -61,14 +61,14 @@ bool AppCache::AddOrModifyEntry(const GURL& url, const AppCacheEntry& entry) {
}
void AppCache::RemoveEntry(const GURL& url) {
- EntryMap::iterator found = entries_.find(url);
+ auto found = entries_.find(url);
DCHECK(found != entries_.end());
cache_size_ -= found->second.response_size();
entries_.erase(found);
}
AppCacheEntry* AppCache::GetEntry(const GURL& url) {
- EntryMap::iterator it = entries_.find(url);
+ auto it = entries_.find(url);
return (it != entries_.end()) ? &(it->second) : nullptr;
}
diff --git a/chromium/content/browser/appcache/appcache_database.cc b/chromium/content/browser/appcache/appcache_database.cc
index e3d373be53a..96ae9e4c8d4 100644
--- a/chromium/content/browser/appcache/appcache_database.cc
+++ b/chromium/content/browser/appcache/appcache_database.cc
@@ -24,6 +24,20 @@ namespace content {
// Schema -------------------------------------------------------------------
namespace {
+// Version number of the database.
+//
+// We support migrating the database schema from versions that are at most 2
+// years old. Older versions are unsupported, and will cause the database to get
+// nuked.
+//
+// Version 0 - 2009-12-28 - https://crrev.com/501033 (unsupported)
+// Version 1 - 2010-01-20 - https://crrev.com/554008 (unsupported)
+// Version 2 - 2010-02-23 - https://crrev.com/630009 (unsupported)
+// Version 3 - 2010-03-17 - https://crrev.com/886003 (unsupported)
+// Version 4 - 2011-12-12 - https://crrev.com/8396013 (unsupported)
+// Version 5 - 2013-03-29 - https://crrev.com/12628006 (unsupported)
+// Version 6 - 2013-09-20 - https://crrev.com/23503069 (unsupported)
+// Version 7 - 2015-07-09 - https://crrev.com/879393002
const int kCurrentVersion = 7;
const int kCompatibleVersion = 7;
const bool kCreateIfNeeded = true;
@@ -1141,117 +1155,7 @@ bool AppCacheDatabase::CreateSchema() {
}
bool AppCacheDatabase::UpgradeSchema() {
-#if defined(APPCACHE_USE_SIMPLE_CACHE)
- if (meta_table_->GetVersionNumber() < 6)
- return DeleteExistingAndCreateNewDatabase();
-#endif
- if (meta_table_->GetVersionNumber() == 3) {
- // version 3 was pre 12/17/2011
- DCHECK_EQ(strcmp(kNamespacesTable, kTables[3].table_name), 0);
- DCHECK_EQ(strcmp(kNamespacesTable, kIndexes[6].table_name), 0);
- DCHECK_EQ(strcmp(kNamespacesTable, kIndexes[7].table_name), 0);
- DCHECK_EQ(strcmp(kNamespacesTable, kIndexes[8].table_name), 0);
-
- const TableInfo kNamespaceTable_v4 = {
- kNamespacesTable,
- "(cache_id INTEGER,"
- " origin TEXT," // intentionally not normalized
- " type INTEGER,"
- " namespace_url TEXT,"
- " target_url TEXT)"
- };
-
- // Migrate from the old FallbackNameSpaces to the newer Namespaces table,
- // but without the is_pattern column added in v5.
- sql::Transaction transaction(db_.get());
- if (!transaction.Begin() ||
- !CreateTable(db_.get(), kNamespaceTable_v4)) {
- return false;
- }
-
- // Move data from the old table to the new table, setting the
- // 'type' for all current records to the value for
- // APPCACHE_FALLBACK_NAMESPACE.
- DCHECK_EQ(0, static_cast<int>(APPCACHE_FALLBACK_NAMESPACE));
- if (!db_->Execute(
- "INSERT INTO Namespaces"
- " SELECT cache_id, origin, 0, namespace_url, fallback_entry_url"
- " FROM FallbackNameSpaces")) {
- return false;
- }
-
- // Drop the old table, indexes on that table are also removed by this.
- if (!db_->Execute("DROP TABLE FallbackNameSpaces"))
- return false;
-
- // Create new indexes.
- if (!CreateIndex(db_.get(), kIndexes[6]) ||
- !CreateIndex(db_.get(), kIndexes[7]) ||
- !CreateIndex(db_.get(), kIndexes[8])) {
- return false;
- }
-
- meta_table_->SetVersionNumber(4);
- meta_table_->SetCompatibleVersionNumber(4);
- if (!transaction.Commit())
- return false;
- }
-
- if (meta_table_->GetVersionNumber() == 4) {
- // version 4 pre 3/30/2013
- // Add the is_pattern column to the Namespaces and OnlineWhitelists tables.
- DCHECK_EQ(strcmp(kNamespacesTable, "Namespaces"), 0);
- sql::Transaction transaction(db_.get());
- if (!transaction.Begin())
- return false;
- if (!db_->Execute(
- "ALTER TABLE Namespaces ADD COLUMN"
- " is_pattern INTEGER CHECK(is_pattern IN (0, 1))")) {
- return false;
- }
- if (!db_->Execute(
- "ALTER TABLE OnlineWhitelists ADD COLUMN"
- " is_pattern INTEGER CHECK(is_pattern IN (0, 1))")) {
- return false;
- }
- meta_table_->SetVersionNumber(5);
- meta_table_->SetCompatibleVersionNumber(5);
- if (!transaction.Commit())
- return false;
- }
-
-#if defined(APPCACHE_USE_SIMPLE_CACHE)
- // The schema version number was increased to 6 when we switched to the
- // SimpleCache for Android, but the SQL part of the schema is identical
- // to v5 on desktop chrome.
- if (meta_table_->GetVersionNumber() == 6) {
-#else
- if (meta_table_->GetVersionNumber() == 5) {
-#endif
- // Versions 5 and 6 were pre-July 2015.
- // Version 7 adds support for expiring caches that are failing to update.
- sql::Transaction transaction(db_.get());
- if (!transaction.Begin() ||
- !db_->Execute(
- "ALTER TABLE Groups ADD COLUMN"
- " last_full_update_check_time INTEGER") ||
- !db_->Execute(
- "ALTER TABLE Groups ADD COLUMN"
- " first_evictable_error_time INTEGER") ||
- !db_->Execute(
- "UPDATE Groups"
- " SET last_full_update_check_time ="
- " (SELECT update_time FROM Caches"
- " WHERE Caches.group_id = Groups.group_id)")) {
- return false;
- }
- meta_table_->SetVersionNumber(7);
- meta_table_->SetCompatibleVersionNumber(7);
- return transaction.Commit();
- }
-
- // If there is no upgrade path for the version on disk to the current
- // version, nuke everything and start over.
+ // The version on disk is deprecated.
return DeleteExistingAndCreateNewDatabase();
}
diff --git a/chromium/content/browser/appcache/appcache_database.h b/chromium/content/browser/appcache/appcache_database.h
index fe3e144e8ca..5aecf70ec3f 100644
--- a/chromium/content/browser/appcache/appcache_database.h
+++ b/chromium/content/browser/appcache/appcache_database.h
@@ -41,9 +41,7 @@ FORWARD_DECLARE_TEST(AppCacheDatabaseTest, OnlineWhiteListRecords);
FORWARD_DECLARE_TEST(AppCacheDatabaseTest, ReCreate);
FORWARD_DECLARE_TEST(AppCacheDatabaseTest, DeletableResponseIds);
FORWARD_DECLARE_TEST(AppCacheDatabaseTest, OriginUsage);
-FORWARD_DECLARE_TEST(AppCacheDatabaseTest, UpgradeSchema3to7);
-FORWARD_DECLARE_TEST(AppCacheDatabaseTest, UpgradeSchema4to7);
-FORWARD_DECLARE_TEST(AppCacheDatabaseTest, UpgradeSchema5or6to7);
+FORWARD_DECLARE_TEST(AppCacheDatabaseTest, UpgradeSchemaNukesDeprecatedVersion);
FORWARD_DECLARE_TEST(AppCacheDatabaseTest, WasCorrutionDetected);
class AppCacheDatabaseTest;
class AppCacheStorageImplTest;
@@ -258,9 +256,8 @@ class CONTENT_EXPORT AppCacheDatabase {
FRIEND_TEST_ALL_PREFIXES(content::AppCacheDatabaseTest, ReCreate);
FRIEND_TEST_ALL_PREFIXES(content::AppCacheDatabaseTest, DeletableResponseIds);
FRIEND_TEST_ALL_PREFIXES(content::AppCacheDatabaseTest, OriginUsage);
- FRIEND_TEST_ALL_PREFIXES(content::AppCacheDatabaseTest, UpgradeSchema3to7);
- FRIEND_TEST_ALL_PREFIXES(content::AppCacheDatabaseTest, UpgradeSchema4to7);
- FRIEND_TEST_ALL_PREFIXES(content::AppCacheDatabaseTest, UpgradeSchema5or6to7);
+ FRIEND_TEST_ALL_PREFIXES(content::AppCacheDatabaseTest,
+ UpgradeSchemaNukesDeprecatedVersion);
FRIEND_TEST_ALL_PREFIXES(content::AppCacheDatabaseTest, WasCorrutionDetected);
DISALLOW_COPY_AND_ASSIGN(AppCacheDatabase);
diff --git a/chromium/content/browser/appcache/appcache_database_unittest.cc b/chromium/content/browser/appcache/appcache_database_unittest.cc
index 53b5e2e317f..4145ded8318 100644
--- a/chromium/content/browser/appcache/appcache_database_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_database_unittest.cc
@@ -826,481 +826,38 @@ TEST(AppCacheDatabaseTest, OriginUsage) {
EXPECT_EQ(5000, usage_map[kOtherOrigin]);
}
-#if defined(APPCACHE_USE_SIMPLE_CACHE)
-// There is no such upgrade path in this case.
-#else
-TEST(AppCacheDatabaseTest, UpgradeSchema4to7) {
+TEST(AppCacheDatabaseTest, UpgradeSchemaNukesDeprecatedVersion) {
// Real file on disk for this test.
base::ScopedTempDir temp_dir;
ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
- const base::FilePath kDbFile = temp_dir.GetPath().AppendASCII("upgrade4.db");
-
- const GURL kMockOrigin("http://mockorigin/");
- const char kNamespaceUrlFormat[] = "namespace%d";
- const char kWhitelistUrlFormat[] = "whitelist%d";
- const char kTargetUrlFormat[] = "target%d";
- const int kNumNamespaces = 10;
- const int kWhitelistCacheId = 1;
+ const base::FilePath kDbFile =
+ temp_dir.GetPath().AppendASCII("deprecated.db");
- // Create a v4 schema based database containing some fallback records.
+ // Create a database with a table name that does not show up in the AppCache
+ // schema. This table would not be touched by any migration, so its existence
+ // indicates that the database was not nuked.
{
- const int kVersion4 = 4;
- const char kGroupsTable[] = "Groups";
- const char kCachesTable[] = "Caches";
- const char kEntriesTable[] = "Entries";
- const char kNamespacesTable[] = "Namespaces";
- const char kOnlineWhiteListsTable[] = "OnlineWhiteLists";
- const char kDeletableResponseIdsTable[] = "DeletableResponseIds";
-
- struct TableInfo {
- const char* table_name;
- const char* columns;
- };
-
- struct IndexInfo {
- const char* index_name;
- const char* table_name;
- const char* columns;
- bool unique;
- };
-
- const TableInfo kTables4[] = {
- { kGroupsTable,
- "(group_id INTEGER PRIMARY KEY,"
- " origin TEXT,"
- " manifest_url TEXT,"
- " creation_time INTEGER,"
- " last_access_time INTEGER)" },
-
- { kCachesTable,
- "(cache_id INTEGER PRIMARY KEY,"
- " group_id INTEGER,"
- " online_wildcard INTEGER CHECK(online_wildcard IN (0, 1)),"
- " update_time INTEGER,"
- " cache_size INTEGER)" }, // intentionally not normalized
-
- { kEntriesTable,
- "(cache_id INTEGER,"
- " url TEXT,"
- " flags INTEGER,"
- " response_id INTEGER,"
- " response_size INTEGER)" },
-
- { kNamespacesTable,
- "(cache_id INTEGER,"
- " origin TEXT," // intentionally not normalized
- " type INTEGER,"
- " namespace_url TEXT,"
- " target_url TEXT)" },
-
- { kOnlineWhiteListsTable,
- "(cache_id INTEGER,"
- " namespace_url TEXT)" },
-
- { kDeletableResponseIdsTable,
- "(response_id INTEGER NOT NULL)" },
- };
-
- const IndexInfo kIndexes4[] = {
- { "GroupsOriginIndex",
- kGroupsTable,
- "(origin)",
- false },
-
- { "GroupsManifestIndex",
- kGroupsTable,
- "(manifest_url)",
- true },
-
- { "CachesGroupIndex",
- kCachesTable,
- "(group_id)",
- false },
-
- { "EntriesCacheIndex",
- kEntriesTable,
- "(cache_id)",
- false },
-
- { "EntriesCacheAndUrlIndex",
- kEntriesTable,
- "(cache_id, url)",
- true },
-
- { "EntriesResponseIdIndex",
- kEntriesTable,
- "(response_id)",
- true },
-
- { "NamespacesCacheIndex",
- kNamespacesTable,
- "(cache_id)",
- false },
-
- { "NamespacesOriginIndex",
- kNamespacesTable,
- "(origin)",
- false },
-
- { "NamespacesCacheAndUrlIndex",
- kNamespacesTable,
- "(cache_id, namespace_url)",
- true },
-
- { "OnlineWhiteListCacheIndex",
- kOnlineWhiteListsTable,
- "(cache_id)",
- false },
-
- { "DeletableResponsesIdIndex",
- kDeletableResponseIdsTable,
- "(response_id)",
- true },
- };
-
- const int kTableCount4 = arraysize(kTables4);
- const int kIndexCount4 = arraysize(kIndexes4);
-
- sql::Database connection;
- EXPECT_TRUE(connection.Open(kDbFile));
-
- sql::Transaction transaction(&connection);
- EXPECT_TRUE(transaction.Begin());
+ sql::Database db;
+ EXPECT_TRUE(db.Open(kDbFile));
sql::MetaTable meta_table;
- EXPECT_TRUE(meta_table.Init(&connection, kVersion4, kVersion4));
-
- for (int i = 0; i < kTableCount4; ++i) {
- std::string sql("CREATE TABLE ");
- sql += kTables4[i].table_name;
- sql += kTables4[i].columns;
- EXPECT_TRUE(connection.Execute(sql.c_str()));
- }
-
- for (int i = 0; i < kIndexCount4; ++i) {
- std::string sql;
- if (kIndexes4[i].unique)
- sql += "CREATE UNIQUE INDEX ";
- else
- sql += "CREATE INDEX ";
- sql += kIndexes4[i].index_name;
- sql += " ON ";
- sql += kIndexes4[i].table_name;
- sql += kIndexes4[i].columns;
- EXPECT_TRUE(connection.Execute(sql.c_str()));
- }
-
- const char* kNamespacesSql =
- "INSERT INTO Namespaces"
- " (cache_id, origin, type, namespace_url, target_url)"
- " VALUES (?, ?, ?, ?, ?)";
- sql::Statement statement;
- statement.Assign(connection.GetUniqueStatement(kNamespacesSql));
- EXPECT_TRUE(statement.is_valid());
- for (int i = 0; i < kNumNamespaces; ++i) {
- GURL namespace_url(
- kMockOrigin.Resolve(base::StringPrintf(kNamespaceUrlFormat, i)));
- GURL target_url(
- kMockOrigin.Resolve(base::StringPrintf(kTargetUrlFormat, i)));
- statement.BindInt64(0, i);
- statement.BindString(1, kMockOrigin.spec().c_str());
- statement.BindInt(2, APPCACHE_FALLBACK_NAMESPACE);
- statement.BindString(3, namespace_url.spec().c_str());
- statement.BindString(4, target_url.spec().c_str());
- ASSERT_TRUE(statement.Run());
- statement.Reset(true);
- }
-
- const char* kWhitelistsSql =
- "INSERT INTO OnlineWhiteLists"
- " (cache_id, namespace_url)"
- " VALUES (?, ?)";
- statement.Assign(connection.GetUniqueStatement(kWhitelistsSql));
- EXPECT_TRUE(statement.is_valid());
- for (int i = 0; i < kNumNamespaces; ++i) {
- GURL namespace_url(
- kMockOrigin.Resolve(base::StringPrintf(kWhitelistUrlFormat, i)));
- statement.BindInt64(0, kWhitelistCacheId);
- statement.BindString(1, namespace_url.spec().c_str());
- ASSERT_TRUE(statement.Run());
- statement.Reset(true);
- }
-
- EXPECT_TRUE(transaction.Commit());
- }
+ EXPECT_TRUE(meta_table.Init(&db, 6, 6));
- // Open that database and verify that it got upgraded to v7.
- AppCacheDatabase db(kDbFile);
- EXPECT_TRUE(db.LazyOpen(true));
- EXPECT_TRUE(db.db_->DoesColumnExist("Namespaces", "is_pattern"));
- EXPECT_TRUE(db.db_->DoesColumnExist("OnlineWhiteLists", "is_pattern"));
- EXPECT_TRUE(db.db_->DoesColumnExist("Groups",
- "last_full_update_check_time"));
- EXPECT_TRUE(db.db_->DoesColumnExist("Groups",
- "first_evictable_error_time"));
- EXPECT_EQ(7, db.meta_table_->GetVersionNumber());
- EXPECT_EQ(7, db.meta_table_->GetCompatibleVersionNumber());
+ static const char kSchemaSql[] =
+ "CREATE TABLE Unused(id INTEGER PRIMARY KEY)";
+ EXPECT_TRUE(db.Execute(kSchemaSql));
- std::vector<AppCacheDatabase::NamespaceRecord> intercepts;
- std::vector<AppCacheDatabase::NamespaceRecord> fallbacks;
- EXPECT_TRUE(db.FindNamespacesForOrigin(url::Origin::Create(kMockOrigin),
- &intercepts, &fallbacks));
- EXPECT_TRUE(intercepts.empty());
- EXPECT_EQ(kNumNamespaces, static_cast<int>(fallbacks.size()));
-
- std::vector<AppCacheDatabase::OnlineWhiteListRecord> whitelists;
- EXPECT_TRUE(db.FindOnlineWhiteListForCache(kWhitelistCacheId, &whitelists));
- EXPECT_EQ(kNumNamespaces, static_cast<int>(whitelists.size()));
-
- for (int i = 0; i < kNumNamespaces; ++i) {
- GURL expected_namespace_url(
- kMockOrigin.Resolve(base::StringPrintf(kNamespaceUrlFormat, i)));
- GURL expected_target_url(
- kMockOrigin.Resolve(base::StringPrintf(kTargetUrlFormat, i)));
- GURL expected_whitelist_url(
- kMockOrigin.Resolve(base::StringPrintf(kWhitelistUrlFormat, i)));
-
- EXPECT_EQ(i, fallbacks[i].cache_id);
- EXPECT_EQ(APPCACHE_FALLBACK_NAMESPACE, fallbacks[i].namespace_.type);
- EXPECT_EQ(url::Origin::Create(kMockOrigin), fallbacks[i].origin);
- EXPECT_EQ(expected_namespace_url, fallbacks[i].namespace_.namespace_url);
- EXPECT_EQ(expected_target_url, fallbacks[i].namespace_.target_url);
- EXPECT_FALSE(fallbacks[i].namespace_.is_pattern);
- EXPECT_EQ(expected_whitelist_url, whitelists[i].namespace_url);
- EXPECT_FALSE(whitelists[i].is_pattern);
+ EXPECT_TRUE(db.DoesColumnExist("Unused", "id"));
}
-}
-#endif // !APPCACHE_USE_SIMPLE_CACHE
-// Verify last_full_update_check_time and first_evictable_error_time.
-TEST(AppCacheDatabaseTest, UpgradeSchema5or6to7) {
- // Real file on disk for this test.
- base::ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
- const base::FilePath kDbFile =
- temp_dir.GetPath().AppendASCII("upgrade5or6to7.db");
-
- const GURL kMockOrigin("http://mockorigin/");
- const base::Time kMockTime = base::Time::Now();
-
- // Create a v5or6 schema based database containing two groups, one
- // that has an associated cache as expected, and one which erroneously
- // is missing its cache record.
- {
- // The SQL schema is the same in these two cases.
-#if defined(APPCACHE_USE_SIMPLE_CACHE)
- const int kVersionN = 6;
-#else
- const int kVersionN = 5;
-#endif // !APPCACHE_USE_SIMPLE_CACHE
-
- const char kGroupsTable[] = "Groups";
- const char kCachesTable[] = "Caches";
- const char kEntriesTable[] = "Entries";
- const char kNamespacesTable[] = "Namespaces";
- const char kOnlineWhiteListsTable[] = "OnlineWhiteLists";
- const char kDeletableResponseIdsTable[] = "DeletableResponseIds";
-
- struct TableInfo {
- const char* table_name;
- const char* columns;
- };
-
- struct IndexInfo {
- const char* index_name;
- const char* table_name;
- const char* columns;
- bool unique;
- };
-
- const TableInfo kTables5[] = {
- { kGroupsTable,
- "(group_id INTEGER PRIMARY KEY,"
- " origin TEXT,"
- " manifest_url TEXT,"
- " creation_time INTEGER,"
- " last_access_time INTEGER)" },
-
- { kCachesTable,
- "(cache_id INTEGER PRIMARY KEY,"
- " group_id INTEGER,"
- " online_wildcard INTEGER CHECK(online_wildcard IN (0, 1)),"
- " update_time INTEGER,"
- " cache_size INTEGER)" }, // intentionally not normalized
-
- { kEntriesTable,
- "(cache_id INTEGER,"
- " url TEXT,"
- " flags INTEGER,"
- " response_id INTEGER,"
- " response_size INTEGER)" },
-
- { kNamespacesTable,
- "(cache_id INTEGER,"
- " origin TEXT," // intentionally not normalized
- " type INTEGER,"
- " namespace_url TEXT,"
- " target_url TEXT,"
- " is_pattern INTEGER CHECK(is_pattern IN (0, 1)))" },
-
- { kOnlineWhiteListsTable,
- "(cache_id INTEGER,"
- " namespace_url TEXT,"
- " is_pattern INTEGER CHECK(is_pattern IN (0, 1)))" },
-
- { kDeletableResponseIdsTable,
- "(response_id INTEGER NOT NULL)" },
- };
-
- const IndexInfo kIndexes5[] = {
- { "GroupsOriginIndex",
- kGroupsTable,
- "(origin)",
- false },
-
- { "GroupsManifestIndex",
- kGroupsTable,
- "(manifest_url)",
- true },
-
- { "CachesGroupIndex",
- kCachesTable,
- "(group_id)",
- false },
-
- { "EntriesCacheIndex",
- kEntriesTable,
- "(cache_id)",
- false },
-
- { "EntriesCacheAndUrlIndex",
- kEntriesTable,
- "(cache_id, url)",
- true },
-
- { "EntriesResponseIdIndex",
- kEntriesTable,
- "(response_id)",
- true },
-
- { "NamespacesCacheIndex",
- kNamespacesTable,
- "(cache_id)",
- false },
-
- { "NamespacesOriginIndex",
- kNamespacesTable,
- "(origin)",
- false },
-
- { "NamespacesCacheAndUrlIndex",
- kNamespacesTable,
- "(cache_id, namespace_url)",
- true },
-
- { "OnlineWhiteListCacheIndex",
- kOnlineWhiteListsTable,
- "(cache_id)",
- false },
-
- { "DeletableResponsesIdIndex",
- kDeletableResponseIdsTable,
- "(response_id)",
- true },
- };
-
- const int kTableCount5 = arraysize(kTables5);
- const int kIndexCount5 = arraysize(kIndexes5);
-
- sql::Database connection;
- EXPECT_TRUE(connection.Open(kDbFile));
-
- sql::Transaction transaction(&connection);
- EXPECT_TRUE(transaction.Begin());
-
- sql::MetaTable meta_table;
- EXPECT_TRUE(meta_table.Init(&connection, kVersionN, kVersionN));
-
- for (int i = 0; i < kTableCount5; ++i) {
- std::string sql("CREATE TABLE ");
- sql += kTables5[i].table_name;
- sql += kTables5[i].columns;
- EXPECT_TRUE(connection.Execute(sql.c_str()));
- }
-
- for (int i = 0; i < kIndexCount5; ++i) {
- std::string sql;
- if (kIndexes5[i].unique)
- sql += "CREATE UNIQUE INDEX ";
- else
- sql += "CREATE INDEX ";
- sql += kIndexes5[i].index_name;
- sql += " ON ";
- sql += kIndexes5[i].table_name;
- sql += kIndexes5[i].columns;
- EXPECT_TRUE(connection.Execute(sql.c_str()));
- }
-
- sql::Statement statement;
-
- const GURL kMockManifestUrl(kMockOrigin.Resolve("mockmanifest"));
- const GURL kMockManifest2Url(kMockOrigin.Resolve("mockmanifest2"));
-
- const char* kInsertGroup =
- "INSERT INTO Groups"
- " (group_id, origin, manifest_url, creation_time, last_access_time)"
- " VALUES (?, ?, ?, ?, ?)";
- statement.Assign(connection.GetUniqueStatement(kInsertGroup));
- EXPECT_TRUE(statement.is_valid());
- statement.BindInt64(0, 1);
- statement.BindString(1, kMockOrigin.spec().c_str());
- statement.BindString(2, kMockManifestUrl.spec().c_str());
- statement.BindInt64(3, kMockTime.ToInternalValue());
- statement.BindInt64(4, kMockTime.ToInternalValue());
- ASSERT_TRUE(statement.Run());
- statement.Reset(true);
- statement.BindInt64(0, 2);
- statement.BindString(1, kMockOrigin.spec().c_str());
- statement.BindString(2, kMockManifest2Url.spec().c_str());
- statement.BindInt64(3, kMockTime.ToInternalValue());
- statement.BindInt64(4, kMockTime.ToInternalValue());
- ASSERT_TRUE(statement.Run());
- statement.Reset(true);
-
- const char* kInsertCache =
- "INSERT INTO Caches"
- " (cache_id, group_id, online_wildcard, update_time, cache_size)"
- " VALUES (?, ?, ?, ?, ?)";
- statement.Assign(connection.GetUniqueStatement(kInsertCache));
- EXPECT_TRUE(statement.is_valid());
- statement.BindInt64(0, 1);
- statement.BindInt64(1, 1);
- statement.BindInt(2, 0);
- statement.BindInt64(3, kMockTime.ToInternalValue());
- statement.BindInt64(4, 1000);
- ASSERT_TRUE(statement.Run());
- statement.Reset(true);
-
- EXPECT_TRUE(transaction.Commit());
- }
-
- // Open that database and verify that it got upgraded to v7.
+ // Open that database and verify that it got nuked.
AppCacheDatabase db(kDbFile);
- EXPECT_TRUE(db.LazyOpen(true));
+ EXPECT_TRUE(db.LazyOpen(/*create_if_needed=*/false));
+ EXPECT_FALSE(db.db_->DoesColumnExist("Unused", "id"));
EXPECT_TRUE(db.db_->DoesColumnExist("Groups",
"last_full_update_check_time"));
- EXPECT_TRUE(db.db_->DoesColumnExist("Groups",
- "first_evictable_error_time"));
EXPECT_EQ(7, db.meta_table_->GetVersionNumber());
EXPECT_EQ(7, db.meta_table_->GetCompatibleVersionNumber());
-
- AppCacheDatabase::GroupRecord group;
- EXPECT_TRUE(db.FindGroup(1, &group));
- EXPECT_EQ(kMockTime, group.last_full_update_check_time);
- EXPECT_EQ(kZeroTime, group.first_evictable_error_time);
- EXPECT_TRUE(db.FindGroup(2, &group));
- EXPECT_EQ(kZeroTime, group.last_full_update_check_time);
- EXPECT_EQ(kZeroTime, group.first_evictable_error_time);
}
} // namespace content
diff --git a/chromium/content/browser/appcache/appcache_disk_cache.cc b/chromium/content/browser/appcache/appcache_disk_cache.cc
index c7018934cb2..242bf8c88f1 100644
--- a/chromium/content/browser/appcache/appcache_disk_cache.cc
+++ b/chromium/content/browser/appcache/appcache_disk_cache.cc
@@ -34,9 +34,9 @@ class AppCacheDiskCache::CreateBackendCallbackShim
void Cancel() { appcache_diskcache_ = nullptr; }
- void Callback(int rv) {
+ void Callback(int return_value) {
if (appcache_diskcache_)
- appcache_diskcache_->OnCreateBackendComplete(rv);
+ appcache_diskcache_->OnCreateBackendComplete(return_value);
}
std::unique_ptr<disk_cache::Backend> backend_ptr_; // Accessed directly.
@@ -50,118 +50,108 @@ class AppCacheDiskCache::CreateBackendCallbackShim
AppCacheDiskCache* appcache_diskcache_; // Unowned pointer.
};
-// An implementation of AppCacheDiskCacheInterface::Entry that's a thin
-// wrapper around disk_cache::Entry.
-class AppCacheDiskCache::EntryImpl : public Entry {
- public:
- EntryImpl(disk_cache::Entry* disk_cache_entry,
- AppCacheDiskCache* owner)
- : disk_cache_entry_(disk_cache_entry), owner_(owner) {
- DCHECK(disk_cache_entry);
- DCHECK(owner);
- owner_->AddOpenEntry(this);
- }
+AppCacheDiskCacheEntry::AppCacheDiskCacheEntry(
+ disk_cache::Entry* disk_cache_entry,
+ AppCacheDiskCache* cache)
+ : disk_cache_entry_(disk_cache_entry), cache_(cache) {
+ DCHECK(disk_cache_entry);
+ DCHECK(cache);
+ cache_->AddOpenEntry(this);
+}
- // Entry implementation.
- int Read(int index,
- int64_t offset,
- net::IOBuffer* buf,
- int buf_len,
- net::CompletionOnceCallback callback) override {
- if (offset < 0 || offset > std::numeric_limits<int32_t>::max())
- return net::ERR_INVALID_ARGUMENT;
- if (!disk_cache_entry_)
- return net::ERR_ABORTED;
- return disk_cache_entry_->ReadData(index, static_cast<int>(offset), buf,
- buf_len, std::move(callback));
- }
+AppCacheDiskCacheEntry::~AppCacheDiskCacheEntry() {
+ if (cache_)
+ cache_->RemoveOpenEntry(this);
+}
- int Write(int index,
- int64_t offset,
- net::IOBuffer* buf,
- int buf_len,
- net::CompletionOnceCallback callback) override {
- if (offset < 0 || offset > std::numeric_limits<int32_t>::max())
- return net::ERR_INVALID_ARGUMENT;
- if (!disk_cache_entry_)
- return net::ERR_ABORTED;
- const bool kTruncate = true;
- return disk_cache_entry_->WriteData(index, static_cast<int>(offset), buf,
- buf_len, std::move(callback),
- kTruncate);
- }
+int AppCacheDiskCacheEntry::Read(int index,
+ int64_t offset,
+ net::IOBuffer* buf,
+ int buf_len,
+ net::CompletionOnceCallback callback) {
+ if (offset < 0 || offset > std::numeric_limits<int32_t>::max())
+ return net::ERR_INVALID_ARGUMENT;
+ if (!disk_cache_entry_)
+ return net::ERR_ABORTED;
+ return disk_cache_entry_->ReadData(index, static_cast<int>(offset), buf,
+ buf_len, std::move(callback));
+}
- int64_t GetSize(int index) override {
- return disk_cache_entry_ ? disk_cache_entry_->GetDataSize(index) : 0L;
- }
+int AppCacheDiskCacheEntry::Write(int index,
+ int64_t offset,
+ net::IOBuffer* buf,
+ int buf_len,
+ net::CompletionOnceCallback callback) {
+ if (offset < 0 || offset > std::numeric_limits<int32_t>::max())
+ return net::ERR_INVALID_ARGUMENT;
+ if (!disk_cache_entry_)
+ return net::ERR_ABORTED;
+ const bool kTruncate = true;
+ return disk_cache_entry_->WriteData(index, static_cast<int>(offset), buf,
+ buf_len, std::move(callback), kTruncate);
+}
- void Close() override {
- if (disk_cache_entry_)
- disk_cache_entry_->Close();
- delete this;
- }
+int64_t AppCacheDiskCacheEntry::GetSize(int index) {
+ return disk_cache_entry_ ? disk_cache_entry_->GetDataSize(index) : 0L;
+}
- void Abandon() {
- owner_ = nullptr;
+void AppCacheDiskCacheEntry::Close() {
+ if (disk_cache_entry_)
disk_cache_entry_->Close();
- disk_cache_entry_ = nullptr;
- }
-
- private:
- ~EntryImpl() override {
- if (owner_)
- owner_->RemoveOpenEntry(this);
- }
+ delete this;
+}
- disk_cache::Entry* disk_cache_entry_;
- AppCacheDiskCache* owner_;
-};
+void AppCacheDiskCacheEntry::Abandon() {
+ cache_ = nullptr;
+ disk_cache_entry_->Close();
+ disk_cache_entry_ = nullptr;
+}
// Separate object to hold state for each Create, Delete, or Doom call
// while the call is in-flight and to produce an EntryImpl upon completion.
class AppCacheDiskCache::ActiveCall
: public base::RefCounted<AppCacheDiskCache::ActiveCall> {
public:
- static int CreateEntry(const base::WeakPtr<AppCacheDiskCache>& owner,
- int64_t key,
- Entry** entry,
- net::CompletionOnceCallback callback) {
+ static net::Error CreateEntry(const base::WeakPtr<AppCacheDiskCache>& owner,
+ int64_t key,
+ AppCacheDiskCacheEntry** entry,
+ net::CompletionOnceCallback callback) {
scoped_refptr<ActiveCall> active_call(
new ActiveCall(owner, entry, std::move(callback)));
- int rv = owner->disk_cache()->CreateEntry(
+ net::Error return_value = owner->disk_cache()->CreateEntry(
base::Int64ToString(key), net::HIGHEST, &active_call->entry_ptr_,
base::BindOnce(&ActiveCall::OnAsyncCompletion, active_call));
- return active_call->HandleImmediateReturnValue(rv);
+ return active_call->HandleImmediateReturnValue(return_value);
}
- static int OpenEntry(const base::WeakPtr<AppCacheDiskCache>& owner,
- int64_t key,
- Entry** entry,
- net::CompletionOnceCallback callback) {
+ static net::Error OpenEntry(const base::WeakPtr<AppCacheDiskCache>& owner,
+ int64_t key,
+ AppCacheDiskCacheEntry** entry,
+ net::CompletionOnceCallback callback) {
scoped_refptr<ActiveCall> active_call(
new ActiveCall(owner, entry, std::move(callback)));
- int rv = owner->disk_cache()->OpenEntry(
+ net::Error return_value = owner->disk_cache()->OpenEntry(
base::Int64ToString(key), net::HIGHEST, &active_call->entry_ptr_,
base::BindOnce(&ActiveCall::OnAsyncCompletion, active_call));
- return active_call->HandleImmediateReturnValue(rv);
+ return active_call->HandleImmediateReturnValue(return_value);
}
- static int DoomEntry(const base::WeakPtr<AppCacheDiskCache>& owner,
- int64_t key,
- net::CompletionOnceCallback callback) {
+ static net::Error DoomEntry(const base::WeakPtr<AppCacheDiskCache>& owner,
+ int64_t key,
+ net::CompletionOnceCallback callback) {
scoped_refptr<ActiveCall> active_call(
new ActiveCall(owner, nullptr, std::move(callback)));
- int rv = owner->disk_cache()->DoomEntry(
+ net::Error return_value = owner->disk_cache()->DoomEntry(
base::Int64ToString(key), net::HIGHEST,
base::BindOnce(&ActiveCall::OnAsyncCompletion, active_call));
- return active_call->HandleImmediateReturnValue(rv);
+ return active_call->HandleImmediateReturnValue(return_value);
}
private:
friend class base::RefCounted<AppCacheDiskCache::ActiveCall>;
ActiveCall(const base::WeakPtr<AppCacheDiskCache>& owner,
- Entry** entry,
+ AppCacheDiskCacheEntry** entry,
net::CompletionOnceCallback callback)
: owner_(owner),
entry_(entry),
@@ -172,7 +162,7 @@ class AppCacheDiskCache::ActiveCall
~ActiveCall() {}
- int HandleImmediateReturnValue(int rv) {
+ net::Error HandleImmediateReturnValue(net::Error rv) {
if (rv == net::ERR_IO_PENDING) {
// OnAsyncCompletion will be called later.
return rv;
@@ -180,7 +170,7 @@ class AppCacheDiskCache::ActiveCall
if (rv == net::OK && entry_) {
DCHECK(entry_ptr_);
- *entry_ = new EntryImpl(entry_ptr_, owner_.get());
+ *entry_ = new AppCacheDiskCacheEntry(entry_ptr_, owner_.get());
}
return rv;
}
@@ -189,7 +179,7 @@ class AppCacheDiskCache::ActiveCall
if (rv == net::OK && entry_) {
DCHECK(entry_ptr_);
if (owner_) {
- *entry_ = new EntryImpl(entry_ptr_, owner_.get());
+ *entry_ = new AppCacheDiskCacheEntry(entry_ptr_, owner_.get());
} else {
entry_ptr_->Close();
rv = net::ERR_ABORTED;
@@ -199,16 +189,16 @@ class AppCacheDiskCache::ActiveCall
}
base::WeakPtr<AppCacheDiskCache> owner_;
- Entry** entry_;
+ AppCacheDiskCacheEntry** entry_;
net::CompletionOnceCallback callback_;
disk_cache::Entry* entry_ptr_;
};
AppCacheDiskCache::AppCacheDiskCache()
#if defined(APPCACHE_USE_SIMPLE_CACHE)
- : AppCacheDiskCache(true)
+ : AppCacheDiskCache("DiskCache.AppCache", true)
#else
- : AppCacheDiskCache(false)
+ : AppCacheDiskCache("DiskCache.AppCache", false)
#endif
{
}
@@ -217,7 +207,7 @@ AppCacheDiskCache::~AppCacheDiskCache() {
Disable();
}
-int AppCacheDiskCache::InitWithDiskBackend(
+net::Error AppCacheDiskCache::InitWithDiskBackend(
const base::FilePath& disk_cache_directory,
int disk_cache_size,
bool force,
@@ -227,7 +217,7 @@ int AppCacheDiskCache::InitWithDiskBackend(
std::move(post_cleanup_callback), std::move(callback));
}
-int AppCacheDiskCache::InitWithMemBackend(
+net::Error AppCacheDiskCache::InitWithMemBackend(
int mem_cache_size,
net::CompletionOnceCallback callback) {
return Init(net::MEMORY_CACHE, base::FilePath(), mem_cache_size, false,
@@ -249,16 +239,17 @@ void AppCacheDiskCache::Disable() {
// We need to close open file handles in order to reinitalize the
// appcache system on the fly. File handles held in both entries and in
// the main disk_cache::Backend class need to be released.
- for (EntryImpl* entry : open_entries_) {
+ for (AppCacheDiskCacheEntry* entry : open_entries_) {
entry->Abandon();
}
open_entries_.clear();
disk_cache_.reset();
}
-int AppCacheDiskCache::CreateEntry(int64_t key,
- Entry** entry,
- net::CompletionOnceCallback callback) {
+net::Error AppCacheDiskCache::CreateEntry(
+ int64_t key,
+ AppCacheDiskCacheEntry** entry,
+ net::CompletionOnceCallback callback) {
DCHECK(entry);
DCHECK(!callback.is_null());
if (is_disabled_)
@@ -277,9 +268,9 @@ int AppCacheDiskCache::CreateEntry(int64_t key,
std::move(callback));
}
-int AppCacheDiskCache::OpenEntry(int64_t key,
- Entry** entry,
- net::CompletionOnceCallback callback) {
+net::Error AppCacheDiskCache::OpenEntry(int64_t key,
+ AppCacheDiskCacheEntry** entry,
+ net::CompletionOnceCallback callback) {
DCHECK(entry);
DCHECK(!callback.is_null());
if (is_disabled_)
@@ -298,8 +289,8 @@ int AppCacheDiskCache::OpenEntry(int64_t key,
std::move(callback));
}
-int AppCacheDiskCache::DoomEntry(int64_t key,
- net::CompletionOnceCallback callback) {
+net::Error AppCacheDiskCache::DoomEntry(int64_t key,
+ net::CompletionOnceCallback callback) {
DCHECK(!callback.is_null());
if (is_disabled_)
return net::ERR_ABORTED;
@@ -317,11 +308,16 @@ int AppCacheDiskCache::DoomEntry(int64_t key,
std::move(callback));
}
-AppCacheDiskCache::AppCacheDiskCache(bool use_simple_cache)
- : AppCacheDiskCacheInterface("DiskCache.AppCache"),
- use_simple_cache_(use_simple_cache),
+base::WeakPtr<AppCacheDiskCache> AppCacheDiskCache::GetWeakPtr() {
+ return weak_factory_.GetWeakPtr();
+}
+
+AppCacheDiskCache::AppCacheDiskCache(const char* uma_name,
+ bool use_simple_cache)
+ : use_simple_cache_(use_simple_cache),
is_disabled_(false),
is_waiting_to_initialize_(false),
+ uma_name_(uma_name),
weak_factory_(this) {}
AppCacheDiskCache::PendingCall::PendingCall()
@@ -330,7 +326,7 @@ AppCacheDiskCache::PendingCall::PendingCall()
AppCacheDiskCache::PendingCall::PendingCall(
PendingCallType call_type,
int64_t key,
- Entry** entry,
+ AppCacheDiskCacheEntry** entry,
net::CompletionOnceCallback callback)
: call_type(call_type),
key(key),
@@ -339,19 +335,19 @@ AppCacheDiskCache::PendingCall::PendingCall(
AppCacheDiskCache::PendingCall::PendingCall(PendingCall&& other) = default;
-AppCacheDiskCache::PendingCall::~PendingCall() {}
+AppCacheDiskCache::PendingCall::~PendingCall() = default;
-int AppCacheDiskCache::Init(net::CacheType cache_type,
- const base::FilePath& cache_directory,
- int cache_size,
- bool force,
- base::OnceClosure post_cleanup_callback,
- net::CompletionOnceCallback callback) {
+net::Error AppCacheDiskCache::Init(net::CacheType cache_type,
+ const base::FilePath& cache_directory,
+ int cache_size,
+ bool force,
+ base::OnceClosure post_cleanup_callback,
+ net::CompletionOnceCallback callback) {
DCHECK(!is_initializing_or_waiting_to_initialize() && !disk_cache_.get());
is_disabled_ = false;
create_backend_callback_ = new CreateBackendCallbackShim(this);
- int rv = disk_cache::CreateCacheBackend(
+ net::Error return_value = disk_cache::CreateCacheBackend(
cache_type,
use_simple_cache_ ? net::CACHE_BACKEND_SIMPLE
: net::CACHE_BACKEND_DEFAULT,
@@ -360,22 +356,22 @@ int AppCacheDiskCache::Init(net::CacheType cache_type,
std::move(post_cleanup_callback),
base::BindOnce(&CreateBackendCallbackShim::Callback,
create_backend_callback_));
- if (rv == net::ERR_IO_PENDING)
+ if (return_value == net::ERR_IO_PENDING)
init_callback_ = std::move(callback);
else
- OnCreateBackendComplete(rv);
- return rv;
+ OnCreateBackendComplete(return_value);
+ return return_value;
}
-void AppCacheDiskCache::OnCreateBackendComplete(int rv) {
- if (rv == net::OK) {
+void AppCacheDiskCache::OnCreateBackendComplete(int return_value) {
+ if (return_value == net::OK) {
disk_cache_ = std::move(create_backend_callback_->backend_ptr_);
}
create_backend_callback_ = nullptr;
// Invoke our clients callback function.
if (!init_callback_.is_null()) {
- std::move(init_callback_).Run(rv);
+ std::move(init_callback_).Run(return_value);
}
// Service pending calls that were queued up while we were initializing.
@@ -383,23 +379,20 @@ void AppCacheDiskCache::OnCreateBackendComplete(int rv) {
// This is safe, because the callback will only be called once.
net::CompletionRepeatingCallback copyable_callback =
base::AdaptCallbackForRepeating(std::move(call.callback));
- rv = net::ERR_FAILED;
+ return_value = net::ERR_FAILED;
switch (call.call_type) {
case CREATE:
- rv = CreateEntry(call.key, call.entry, copyable_callback);
+ return_value = CreateEntry(call.key, call.entry, copyable_callback);
break;
case OPEN:
- rv = OpenEntry(call.key, call.entry, copyable_callback);
+ return_value = OpenEntry(call.key, call.entry, copyable_callback);
break;
case DOOM:
- rv = DoomEntry(call.key, copyable_callback);
- break;
- default:
- NOTREACHED();
+ return_value = DoomEntry(call.key, copyable_callback);
break;
}
- if (rv != net::ERR_IO_PENDING)
- copyable_callback.Run(rv);
+ if (return_value != net::ERR_IO_PENDING)
+ copyable_callback.Run(return_value);
}
pending_calls_.clear();
}
diff --git a/chromium/content/browser/appcache/appcache_disk_cache.h b/chromium/content/browser/appcache/appcache_disk_cache.h
index 73bccf9d2f9..82309a1502f 100644
--- a/chromium/content/browser/appcache/appcache_disk_cache.h
+++ b/chromium/content/browser/appcache/appcache_disk_cache.h
@@ -13,55 +13,96 @@
#include "base/callback_forward.h"
#include "base/memory/ref_counted.h"
-#include "content/browser/appcache/appcache_response.h"
#include "content/common/content_export.h"
#include "net/base/completion_once_callback.h"
#include "net/disk_cache/disk_cache.h"
namespace content {
-// An implementation of AppCacheDiskCacheInterface that
+class AppCacheDiskCache;
+
+// Thin wrapper around disk_cache::Entry.
+class CONTENT_EXPORT AppCacheDiskCacheEntry {
+ public:
+ // The newly created entry takes ownership of |disk_cache_entry| and closes it
+ // on destruction. |cache| must outlive the newly created entry.
+ AppCacheDiskCacheEntry(disk_cache::Entry* disk_cache_entry,
+ AppCacheDiskCache* cache);
+
+ int Read(int index,
+ int64_t offset,
+ net::IOBuffer* buf,
+ int buf_len,
+ net::CompletionOnceCallback callback);
+
+ int Write(int index,
+ int64_t offset,
+ net::IOBuffer* buf,
+ int buf_len,
+ net::CompletionOnceCallback callback);
+ int64_t GetSize(int index);
+ void Close();
+
+ // Should only be called by AppCacheDiskCache.
+ void Abandon();
+
+ private:
+ // Call Close() instead of calling this directly.
+ ~AppCacheDiskCacheEntry();
+
+ // The disk_cache::Entry is owned by this entry and closed on destruction.
+ disk_cache::Entry* disk_cache_entry_;
+
+ // The cache that this entry belongs to.
+ AppCacheDiskCache* cache_;
+};
+
+// An implementation of AppCacheDiskCache that
// uses net::DiskCache as the backing store.
-class CONTENT_EXPORT AppCacheDiskCache
- : public AppCacheDiskCacheInterface {
+class CONTENT_EXPORT AppCacheDiskCache {
public:
AppCacheDiskCache();
- ~AppCacheDiskCache() override;
+ virtual ~AppCacheDiskCache();
// Initializes the object to use disk backed storage.
- int InitWithDiskBackend(const base::FilePath& disk_cache_directory,
- int disk_cache_size,
- bool force,
- base::OnceClosure post_cleanup_callback,
- net::CompletionOnceCallback callback);
+ net::Error InitWithDiskBackend(const base::FilePath& disk_cache_directory,
+ int disk_cache_size,
+ bool force,
+ base::OnceClosure post_cleanup_callback,
+ net::CompletionOnceCallback callback);
// Initializes the object to use memory only storage.
// This is used for Chrome's incognito browsing.
- int InitWithMemBackend(int disk_cache_size,
- net::CompletionOnceCallback callback);
+ net::Error InitWithMemBackend(int disk_cache_size,
+ net::CompletionOnceCallback callback);
void Disable();
bool is_disabled() const { return is_disabled_; }
- int CreateEntry(int64_t key,
- Entry** entry,
- net::CompletionOnceCallback callback) override;
- int OpenEntry(int64_t key,
- Entry** entry,
- net::CompletionOnceCallback callback) override;
- int DoomEntry(int64_t key, net::CompletionOnceCallback callback) override;
+ net::Error CreateEntry(int64_t key,
+ AppCacheDiskCacheEntry** entry,
+ net::CompletionOnceCallback callback);
+ net::Error OpenEntry(int64_t key,
+ AppCacheDiskCacheEntry** entry,
+ net::CompletionOnceCallback callback);
+ net::Error DoomEntry(int64_t key, net::CompletionOnceCallback callback);
+
+ base::WeakPtr<AppCacheDiskCache> GetWeakPtr();
void set_is_waiting_to_initialize(bool is_waiting_to_initialize) {
is_waiting_to_initialize_ = is_waiting_to_initialize;
}
+ const char* uma_name() { return uma_name_; }
+
protected:
- explicit AppCacheDiskCache(bool use_simple_cache);
+ // |uma_name| must remain valid for the life of the object.
+ explicit AppCacheDiskCache(const char* uma_name, bool use_simple_cache);
disk_cache::Backend* disk_cache() { return disk_cache_.get(); }
private:
class CreateBackendCallbackShim;
- class EntryImpl;
+ friend class AppCacheDiskCacheEntry;
// PendingCalls allow CreateEntry, OpenEntry, and DoomEntry to be called
// immediately after construction, without waiting for the
@@ -77,7 +118,7 @@ class CONTENT_EXPORT AppCacheDiskCache
PendingCall();
PendingCall(PendingCallType call_type,
int64_t key,
- Entry** entry,
+ AppCacheDiskCacheEntry** entry,
net::CompletionOnceCallback callback);
PendingCall(PendingCall&& other);
@@ -85,28 +126,35 @@ class CONTENT_EXPORT AppCacheDiskCache
PendingCallType call_type;
int64_t key;
- Entry** entry;
+ AppCacheDiskCacheEntry** entry;
net::CompletionOnceCallback callback;
};
using PendingCalls = std::vector<PendingCall>;
class ActiveCall;
using ActiveCalls = std::set<ActiveCall*>;
- using OpenEntries = std::set<EntryImpl*>;
+ using OpenEntries = std::set<AppCacheDiskCacheEntry*>;
bool is_initializing_or_waiting_to_initialize() const {
return create_backend_callback_.get() != NULL || is_waiting_to_initialize_;
}
- int Init(net::CacheType cache_type,
- const base::FilePath& directory,
- int cache_size,
- bool force,
- base::OnceClosure post_cleanup_callback,
- net::CompletionOnceCallback callback);
- void OnCreateBackendComplete(int rv);
- void AddOpenEntry(EntryImpl* entry) { open_entries_.insert(entry); }
- void RemoveOpenEntry(EntryImpl* entry) { open_entries_.erase(entry); }
+ net::Error Init(net::CacheType cache_type,
+ const base::FilePath& directory,
+ int cache_size,
+ bool force,
+ base::OnceClosure post_cleanup_callback,
+ net::CompletionOnceCallback callback);
+ void OnCreateBackendComplete(int return_value);
+
+ // Called by AppCacheDiskCacheEntry constructor.
+ void AddOpenEntry(AppCacheDiskCacheEntry* entry) {
+ open_entries_.insert(entry);
+ }
+ // Called by AppCacheDiskCacheEntry destructor.
+ void RemoveOpenEntry(AppCacheDiskCacheEntry* entry) {
+ open_entries_.erase(entry);
+ }
bool use_simple_cache_;
bool is_disabled_;
@@ -116,6 +164,7 @@ class CONTENT_EXPORT AppCacheDiskCache
PendingCalls pending_calls_;
OpenEntries open_entries_;
std::unique_ptr<disk_cache::Backend> disk_cache_;
+ const char* const uma_name_;
base::WeakPtrFactory<AppCacheDiskCache> weak_factory_;
};
diff --git a/chromium/content/browser/appcache/appcache_disk_cache_unittest.cc b/chromium/content/browser/appcache/appcache_disk_cache_unittest.cc
index f6e4cf492d9..8f382da2538 100644
--- a/chromium/content/browser/appcache/appcache_disk_cache_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_disk_cache_unittest.cc
@@ -49,7 +49,7 @@ class AppCacheDiskCacheTest : public testing::Test {
};
TEST_F(AppCacheDiskCacheTest, DisablePriorToInitCompletion) {
- AppCacheDiskCache::Entry* entry = nullptr;
+ AppCacheDiskCacheEntry* entry = nullptr;
// Create an instance and start it initializing, queue up
// one of each kind of "entry" function.
@@ -103,7 +103,7 @@ TEST_F(AppCacheDiskCacheTest, DisableAfterInitted) {
// Methods should return immediately when disabled and not invoke
// the callback at all.
- AppCacheDiskCache::Entry* entry = nullptr;
+ AppCacheDiskCacheEntry* entry = nullptr;
completion_results_.clear();
EXPECT_EQ(net::ERR_ABORTED,
disk_cache->CreateEntry(1, &entry, completion_callback_));
@@ -135,8 +135,8 @@ TEST_F(AppCacheDiskCacheTest, DISABLED_DisableWithEntriesOpen) {
// and we do have expectations about that.
// Create/open some entries.
- AppCacheDiskCache::Entry* entry1 = nullptr;
- AppCacheDiskCache::Entry* entry2 = nullptr;
+ AppCacheDiskCacheEntry* entry1 = nullptr;
+ AppCacheDiskCacheEntry* entry2 = nullptr;
disk_cache->CreateEntry(1, &entry1, completion_callback_);
disk_cache->CreateEntry(2, &entry2, completion_callback_);
FlushCacheTasks();
@@ -146,12 +146,14 @@ TEST_F(AppCacheDiskCacheTest, DISABLED_DisableWithEntriesOpen) {
// Write something to one of the entries and flush it.
const char* kData = "Hello";
const int kDataLen = strlen(kData) + 1;
- scoped_refptr<net::IOBuffer> write_buf(new net::WrappedIOBuffer(kData));
+ scoped_refptr<net::IOBuffer> write_buf =
+ base::MakeRefCounted<net::WrappedIOBuffer>(kData);
entry1->Write(0, 0, write_buf.get(), kDataLen, completion_callback_);
FlushCacheTasks();
// Queue up a read and a write.
- scoped_refptr<net::IOBuffer> read_buf = new net::IOBuffer(kDataLen);
+ scoped_refptr<net::IOBuffer> read_buf =
+ base::MakeRefCounted<net::IOBuffer>(kDataLen);
entry1->Read(0, 0, read_buf.get(), kDataLen, completion_callback_);
entry2->Write(0, 0, write_buf.get(), kDataLen, completion_callback_);
diff --git a/chromium/content/browser/appcache/appcache_frontend_proxy.cc b/chromium/content/browser/appcache/appcache_frontend_proxy.cc
index 47b80b9ace4..d9eb816c963 100644
--- a/chromium/content/browser/appcache/appcache_frontend_proxy.cc
+++ b/chromium/content/browser/appcache/appcache_frontend_proxy.cc
@@ -4,7 +4,9 @@
#include "content/browser/appcache/appcache_frontend_proxy.h"
+#include "base/task/post_task.h"
#include "content/common/appcache.mojom.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/common/bind_interface_helpers.h"
@@ -26,8 +28,8 @@ void BindOnUIThread(int process_id, mojom::AppCacheFrontendRequest request) {
mojom::AppCacheFrontend* AppCacheFrontendProxy::GetAppCacheFrontend() {
if (!app_cache_renderer_ptr_) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&BindOnUIThread, process_id_,
mojo::MakeRequest(&app_cache_renderer_ptr_)));
}
diff --git a/chromium/content/browser/appcache/appcache_group.cc b/chromium/content/browser/appcache/appcache_group.cc
index 6a83480f298..42a94cca7d5 100644
--- a/chromium/content/browser/appcache/appcache_group.cc
+++ b/chromium/content/browser/appcache/appcache_group.cc
@@ -100,8 +100,7 @@ void AppCacheGroup::AddCache(AppCache* complete_cache) {
// Update hosts of older caches to add a reference to the newest cache.
// (This loop mutates |old_caches_| so a range-based for-loop cannot be
// used, because it caches the end iterator.)
- for (Caches::iterator it = old_caches_.begin(); it != old_caches_.end();
- ++it) {
+ for (auto it = old_caches_.begin(); it != old_caches_.end(); ++it) {
AppCache* cache = *it;
for (AppCacheHost* host : cache->associated_hosts())
host->SetSwappableCache(this);
@@ -121,8 +120,7 @@ void AppCacheGroup::RemoveCache(AppCache* cache) {
} else {
scoped_refptr<AppCacheGroup> protect(this);
- Caches::iterator it =
- std::find(old_caches_.begin(), old_caches_.end(), cache);
+ auto it = std::find(old_caches_.begin(), old_caches_.end(), cache);
if (it != old_caches_.end()) {
AppCache* tmp_cache = *it;
old_caches_.erase(it);
diff --git a/chromium/content/browser/appcache/appcache_host.cc b/chromium/content/browser/appcache/appcache_host.cc
index f82d1f76585..bbc891b3d8b 100644
--- a/chromium/content/browser/appcache/appcache_host.cc
+++ b/chromium/content/browser/appcache/appcache_host.cc
@@ -83,7 +83,7 @@ AppCacheHost::~AppCacheHost() {
if (group_being_updated_.get())
group_being_updated_->RemoveUpdateObserver(this);
storage()->CancelDelegateCallbacks(this);
- if (service()->quota_manager_proxy() && !origin_in_use_.unique())
+ if (service()->quota_manager_proxy() && !origin_in_use_.opaque())
service()->quota_manager_proxy()->NotifyOriginNoLongerInUse(origin_in_use_);
}
@@ -113,7 +113,7 @@ bool AppCacheHost::SelectCache(const GURL& document_url,
}
origin_in_use_ = url::Origin::Create(document_url);
- if (service()->quota_manager_proxy() && !origin_in_use_.unique())
+ if (service()->quota_manager_proxy() && !origin_in_use_.opaque())
service()->quota_manager_proxy()->NotifyOriginInUse(origin_in_use_);
if (main_resource_blocked_)
diff --git a/chromium/content/browser/appcache/appcache_internals_ui.cc b/chromium/content/browser/appcache/appcache_internals_ui.cc
index d95dcaf3494..6256cd8b4f9 100644
--- a/chromium/content/browser/appcache/appcache_internals_ui.cc
+++ b/chromium/content/browser/appcache/appcache_internals_ui.cc
@@ -13,6 +13,7 @@
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/task/post_task.h"
#include "base/threading/platform_thread.h"
#include "base/values.h"
#include "content/browser/appcache/appcache.h"
@@ -20,6 +21,7 @@
#include "content/browser/storage_partition_impl.h"
#include "content/grit/content_resources.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/web_ui.h"
#include "content/public/browser/web_ui_data_source.h"
@@ -145,8 +147,8 @@ AppCacheInternalsUI::Proxy::Proxy(
void AppCacheInternalsUI::Proxy::Initialize(
const scoped_refptr<ChromeAppCacheService>& chrome_appcache_service) {
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&Proxy::Initialize, this, chrome_appcache_service));
return;
}
@@ -161,8 +163,8 @@ AppCacheInternalsUI::Proxy::~Proxy() {
void AppCacheInternalsUI::Proxy::Shutdown() {
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::BindOnce(&Proxy::Shutdown, this));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(&Proxy::Shutdown, this));
return;
}
shutdown_called_ = true;
@@ -175,8 +177,8 @@ void AppCacheInternalsUI::Proxy::Shutdown() {
void AppCacheInternalsUI::Proxy::RequestAllAppCacheInfo() {
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&Proxy::RequestAllAppCacheInfo, this));
return;
}
@@ -192,8 +194,8 @@ void AppCacheInternalsUI::Proxy::RequestAllAppCacheInfo() {
void AppCacheInternalsUI::Proxy::OnAllAppCacheInfoReady(
scoped_refptr<AppCacheInfoCollection> collection,
int net_result_code) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&AppCacheInternalsUI::OnAllAppCacheInfoReady,
appcache_internals_ui_, collection, partition_path_));
}
@@ -201,8 +203,8 @@ void AppCacheInternalsUI::Proxy::OnAllAppCacheInfoReady(
void AppCacheInternalsUI::Proxy::DeleteAppCache(
const std::string& manifest_url) {
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&Proxy::DeleteAppCache, this, manifest_url));
return;
}
@@ -216,8 +218,8 @@ void AppCacheInternalsUI::Proxy::DeleteAppCache(
void AppCacheInternalsUI::Proxy::OnAppCacheInfoDeleted(
const std::string& manifest_url,
int net_result_code) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&AppCacheInternalsUI::OnAppCacheInfoDeleted,
appcache_internals_ui_, partition_path_, manifest_url,
net_result_code == net::OK));
@@ -226,8 +228,8 @@ void AppCacheInternalsUI::Proxy::OnAppCacheInfoDeleted(
void AppCacheInternalsUI::Proxy::RequestAppCacheDetails(
const std::string& manifest_url) {
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&Proxy::RequestAppCacheDetails, this, manifest_url));
return;
}
@@ -246,8 +248,8 @@ void AppCacheInternalsUI::Proxy::OnGroupLoaded(AppCacheGroup* appcache_group,
std::sort(resource_info_vector->begin(), resource_info_vector->end(),
SortByResourceUrl);
}
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&AppCacheInternalsUI::OnAppCacheDetailsReady,
appcache_internals_ui_, partition_path_,
manifest_gurl.spec(), std::move(resource_info_vector)));
@@ -256,8 +258,8 @@ void AppCacheInternalsUI::Proxy::OnGroupLoaded(AppCacheGroup* appcache_group,
void AppCacheInternalsUI::Proxy::RequestFileDetails(
const ResponseEnquiry& response_enquiry) {
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&Proxy::RequestFileDetails, this, response_enquiry));
return;
}
@@ -289,11 +291,12 @@ void AppCacheInternalsUI::Proxy::OnResponseInfoLoaded(
const int64_t kLimit = 100 * 1000;
int64_t amount_to_read =
std::min(kLimit, response_info->response_data_size());
- scoped_refptr<net::IOBuffer> response_data(
- new net::IOBuffer(base::checked_cast<size_t>(amount_to_read)));
- std::unique_ptr<AppCacheResponseReader> reader(
+ scoped_refptr<net::IOBuffer> response_data =
+ base::MakeRefCounted<net::IOBuffer>(
+ base::checked_cast<size_t>(amount_to_read));
+ std::unique_ptr<AppCacheResponseReader> reader =
appcache_service_->storage()->CreateResponseReader(
- GURL(response_enquiry.manifest_url), response_enquiry.response_id));
+ GURL(response_enquiry.manifest_url), response_enquiry.response_id);
reader->ReadData(response_data.get(), amount_to_read,
base::BindOnce(&Proxy::OnResponseDataReadComplete, this,
@@ -313,14 +316,14 @@ void AppCacheInternalsUI::Proxy::OnResponseDataReadComplete(
if (shutdown_called_)
return;
if (!response_info || net_result_code < 0) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&AppCacheInternalsUI::OnFileDetailsFailed,
appcache_internals_ui_, response_enquiry,
net_result_code));
} else {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&AppCacheInternalsUI::OnFileDetailsReady,
appcache_internals_ui_, response_enquiry, response_info,
response_data, net_result_code));
diff --git a/chromium/content/browser/appcache/appcache_job.cc b/chromium/content/browser/appcache/appcache_job.cc
index 20fcaed3a65..e5575b2bc5c 100644
--- a/chromium/content/browser/appcache/appcache_job.cc
+++ b/chromium/content/browser/appcache/appcache_job.cc
@@ -20,26 +20,6 @@ AppCacheJob::~AppCacheJob() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
}
-bool AppCacheJob::IsWaiting() const {
- return delivery_type_ == AWAITING_DELIVERY_ORDERS;
-}
-
-bool AppCacheJob::IsDeliveringAppCacheResponse() const {
- return delivery_type_ == APPCACHED_DELIVERY;
-}
-
-bool AppCacheJob::IsDeliveringNetworkResponse() const {
- return delivery_type_ == NETWORK_DELIVERY;
-}
-
-bool AppCacheJob::IsDeliveringErrorResponse() const {
- return delivery_type_ == ERROR_DELIVERY;
-}
-
-bool AppCacheJob::IsCacheEntryNotFound() const {
- return cache_entry_not_found_;
-}
-
AppCacheURLRequestJob* AppCacheJob::AsURLRequestJob() {
return nullptr;
}
@@ -49,7 +29,8 @@ AppCacheURLLoaderJob* AppCacheJob::AsURLLoaderJob() {
}
AppCacheJob::AppCacheJob()
- : cache_entry_not_found_(false), delivery_type_(AWAITING_DELIVERY_ORDERS) {}
+ : cache_entry_not_found_(false),
+ delivery_type_(DeliveryType::kAwaitingDeliverCall) {}
void AppCacheJob::InitializeRangeRequestInfo(
const net::HttpRequestHeaders& headers) {
diff --git a/chromium/content/browser/appcache/appcache_job.h b/chromium/content/browser/appcache/appcache_job.h
index 47d80378f29..cf18a72fcc7 100644
--- a/chromium/content/browser/appcache/appcache_job.h
+++ b/chromium/content/browser/appcache/appcache_job.h
@@ -36,32 +36,40 @@ class AppCacheURLRequestJob;
// of the AppCache code.
class CONTENT_EXPORT AppCacheJob {
public:
- enum DeliveryType {
- AWAITING_DELIVERY_ORDERS,
- APPCACHED_DELIVERY,
- NETWORK_DELIVERY,
- ERROR_DELIVERY
+ enum class DeliveryType {
+ kAwaitingDeliverCall,
+ kAppCached,
+ kNetwork,
+ kError,
};
virtual ~AppCacheJob();
- // Returns true if the job was started.
+ // True if the job was started.
virtual bool IsStarted() const = 0;
- // Returns true if the job is waiting for instructions.
- virtual bool IsWaiting() const;
+ // True if the job is waiting for instructions.
+ bool IsWaiting() const {
+ return delivery_type_ == DeliveryType::kAwaitingDeliverCall;
+ }
- // Returns true if the job is delivering a response from the cache.
- virtual bool IsDeliveringAppCacheResponse() const;
+ // True if the job is delivering a response from the cache.
+ bool IsDeliveringAppCacheResponse() const {
+ return delivery_type_ == DeliveryType::kAppCached;
+ }
// Returns true if the job is delivering a response from the network.
- virtual bool IsDeliveringNetworkResponse() const;
+ bool IsDeliveringNetworkResponse() const {
+ return delivery_type_ == DeliveryType::kNetwork;
+ }
// Returns true if the job is delivering an error response.
- virtual bool IsDeliveringErrorResponse() const;
+ bool IsDeliveringErrorResponse() const {
+ return delivery_type_ == DeliveryType::kError;
+ }
// Returns true if the cache entry was not found in the cache.
- virtual bool IsCacheEntryNotFound() const;
+ bool IsCacheEntryNotFound() const { return cache_entry_not_found_; }
// Informs the job of what response it should deliver. Only one of these
// methods should be called, and only once per job. A job will sit idle and
diff --git a/chromium/content/browser/appcache/appcache_manifest_parser.cc b/chromium/content/browser/appcache/appcache_manifest_parser.cc
index 88ab907592f..d07cabf28fb 100644
--- a/chromium/content/browser/appcache/appcache_manifest_parser.cc
+++ b/chromium/content/browser/appcache/appcache_manifest_parser.cc
@@ -33,11 +33,11 @@
#include <stddef.h>
-#include "base/command_line.h"
-#include "base/i18n/icu_string_conversions.h"
+#include <tuple>
+#include <utility>
+
#include "base/logging.h"
-#include "base/macros.h"
-#include "base/strings/string_util.h"
+#include "base/strings/string_piece.h"
#include "base/strings/utf_string_conversions.h"
#include "url/gurl.h"
@@ -45,17 +45,176 @@ namespace content {
namespace {
-// Helper function used to identify 'isPattern' annotations.
-bool HasPatternMatchingAnnotation(const wchar_t* line_p,
- const wchar_t* line_end) {
- // Skip whitespace separating the resource url from the annotation.
- // Note: trailing whitespace has already been trimmed from the line.
- while (line_p < line_end && (*line_p == '\t' || *line_p == ' '))
- ++line_p;
- if (line_p == line_end)
+// Values for the mode in the AppCache manifest parsing algorithm specification.
+enum class Mode {
+ kExplicit, // In the CACHE: section.
+ kIntercept, // In the CHROMIUM-INTERCEPT: section. (non-standard)
+ kFallback, // In the FALLBACK: section.
+ kOnlineSafelist, // In the NETWORK: section.
+ kUnknown, // Sections that are not covered by the spec.
+};
+
+// AppCache defines whitespace as CR / LF / space (0x20) / tab (0x09).
+constexpr bool IsWhiteSpace(char character) {
+ return (character == ' ') || (character == '\t') || (character == '\n') ||
+ (character == '\r');
+}
+
+// AppCache defines newline characters as CR or LF.
+constexpr bool IsNewLine(char character) {
+ return (character == '\n') || (character == '\r');
+}
+
+// AppCache defines token separators as space (0x20) or tab (0x09).
+constexpr bool IsTokenSeparator(char character) {
+ return (character == ' ') || (character == '\t');
+}
+
+// Removes the characters at the beginning of the string up to a newline.
+base::StringPiece TrimToFirstNewLine(base::StringPiece data) {
+ size_t skip = 0;
+ while (skip < data.length() && !IsNewLine(data[skip]))
+ ++skip;
+ return data.substr(skip);
+}
+
+// Removes whitespace characters at the beginning of the string.
+base::StringPiece TrimStartingWhiteSpace(base::StringPiece data) {
+ size_t skip = 0;
+ while (skip < data.length() && IsWhiteSpace(data[skip]))
+ ++skip;
+ return data.substr(skip);
+}
+
+// Removes whitespace characters at the end of the string.
+base::StringPiece TrimTrailingWhiteSpace(base::StringPiece data) {
+ size_t length = data.size();
+
+ while (length != 0) {
+ --length;
+ if (!IsWhiteSpace(data[length])) {
+ ++length;
+ break;
+ }
+ }
+ return data.substr(0, length);
+}
+
+// Splits a string at the first occurrence of a newline.
+//
+// Returns the first line, which is guaranteed not to include a newline, and the
+// rest of the string, which may be empty.
+std::pair<base::StringPiece, base::StringPiece> SplitOnNewLine(
+ base::StringPiece data) {
+ size_t split = 0;
+ while (split < data.length() && !IsNewLine(data[split]))
+ ++split;
+ return {data.substr(0, split), data.substr(split)};
+}
+
+// True if the string does not contain any newline character.
+bool IsSingleLine(base::StringPiece maybe_line) {
+ return !std::any_of(maybe_line.begin(), maybe_line.end(), &IsNewLine);
+}
+
+// Splits a token out of a manifest line.
+//
+// Tokens are separated by space (0x20) or tab (0x09) characters.
+//
+// The line must not start with a whitespace character.
+//
+// Returns the token and the rest of the line. Consumes the whitespace after the
+// returned token -- the rest of the line will not start with whitespace.
+std::pair<base::StringPiece, base::StringPiece> SplitLineToken(
+ base::StringPiece line) {
+ DCHECK(IsSingleLine(line));
+ DCHECK(line.empty() || !IsWhiteSpace(line[0]));
+
+ size_t token_end = 0;
+ while (token_end < line.length() && !IsTokenSeparator(line[token_end]))
+ ++token_end;
+
+ size_t split = token_end;
+ while (split < line.length() && IsTokenSeparator(line[split]))
+ ++split;
+
+ return {line.substr(0, token_end), line.substr(split)};
+}
+
+// True if the given line is a mode-setting line.
+//
+// In the AppCache parsing algorithm, the mode only changes when processing a
+// line that ends with ':' (colon) after whitespace removal.
+//
+// The given string must have had whitespace stripped at both ends.
+bool IsModeSettingLine(base::StringPiece line) {
+ DCHECK(IsSingleLine(line));
+
+ if (line.empty())
return false;
- std::wstring annotation(line_p, line_end - line_p);
- return annotation == L"isPattern";
+
+ DCHECK(!IsWhiteSpace(line[0])) << "line starts with whitespace";
+
+ const auto last_character = line[line.length() - 1];
+ DCHECK(!IsWhiteSpace(last_character)) << "line ends with whitespace";
+
+ return last_character == ':';
+}
+
+// The mode that the AppCache parsing algorithm will be switched to.
+//
+// The given string must be a mode-setting line.
+Mode ParseModeSettingLine(base::StringPiece line) {
+ DCHECK(IsModeSettingLine(line));
+
+ static constexpr base::StringPiece kCacheLine("CACHE:");
+ if (line == kCacheLine)
+ return Mode::kExplicit;
+
+ static constexpr base::StringPiece kFallbackLine("FALLBACK:");
+ if (line == kFallbackLine)
+ return Mode::kFallback;
+
+ static constexpr base::StringPiece kNetworkLine("NETWORK:");
+ if (line == kNetworkLine)
+ return Mode::kOnlineSafelist;
+
+ static constexpr base::StringPiece kInterceptLine("CHROMIUM-INTERCEPT:");
+ if (line == kInterceptLine)
+ return Mode::kIntercept;
+
+ return Mode::kUnknown;
+}
+
+// True if the next token in the manifest line is the pattern indicator flag.
+//
+// Pattern URLs are a non-standard feature.
+bool NextTokenIsPatternMatchingFlag(base::StringPiece line) {
+ base::StringPiece is_pattern_token;
+ std::tie(is_pattern_token, line) = SplitLineToken(line);
+
+ static constexpr base::StringPiece kPatternFlag("isPattern");
+ return is_pattern_token == kPatternFlag;
+}
+
+// Parses a URL token in an AppCache manifest.
+//
+// The returned URL may not be valid, if the token does not represent a valid
+// URL.
+//
+// Per the AppCache specification, the URL is resolved relative to the manifest
+// URL, and stripped of any fragment.
+GURL ParseUrlToken(base::StringPiece url_token, const GURL& manifest_url) {
+ GURL url = manifest_url.Resolve(url_token);
+ if (!url.is_valid())
+ return url;
+
+ if (url.has_ref()) {
+ GURL::Replacements replacements;
+ replacements.ClearRef();
+ url = url.ReplaceComponents(replacements);
+ }
+ return url;
}
bool ScopeMatches(const GURL& manifest_url, const GURL& namespace_url) {
@@ -66,37 +225,17 @@ bool ScopeMatches(const GURL& manifest_url, const GURL& namespace_url) {
} // namespace
-enum Mode {
- EXPLICIT,
- INTERCEPT,
- FALLBACK,
- ONLINE_WHITELIST,
- UNKNOWN_MODE,
-};
-
-enum InterceptVerb {
- RETURN,
- EXECUTE,
- UNKNOWN_VERB,
-};
-
-AppCacheManifest::AppCacheManifest() {}
-
-AppCacheManifest::~AppCacheManifest() {}
+AppCacheManifest::AppCacheManifest() = default;
-bool ParseManifest(const GURL& manifest_url, const char* data, int length,
- ParseMode parse_mode, AppCacheManifest& manifest) {
- // This is an implementation of the parsing algorithm specified in
- // the HTML5 offline web application docs:
- // http://www.w3.org/TR/html5/offline.html
- // Do not modify it without consulting those docs.
- // Though you might be tempted to convert these wstrings to UTF-8 or
- // base::string16, this implementation seems simpler given the constraints.
+AppCacheManifest::~AppCacheManifest() = default;
- const wchar_t kSignature[] = L"CACHE MANIFEST";
- const size_t kSignatureLength = arraysize(kSignature) - 1;
- const wchar_t kChromiumSignature[] = L"CHROMIUM CACHE MANIFEST";
- const size_t kChromiumSignatureLength = arraysize(kChromiumSignature) - 1;
+bool ParseManifest(const GURL& manifest_url,
+ const char* manifest_bytes,
+ int manifest_size,
+ ParseMode parse_mode,
+ AppCacheManifest& manifest) {
+ // The parsing algorithm is specified at
+ // https://html.spec.whatwg.org/multipage/offline.html
DCHECK(manifest.explicit_urls.empty());
DCHECK(manifest.fallback_namespaces.empty());
@@ -105,233 +244,168 @@ bool ParseManifest(const GURL& manifest_url, const char* data, int length,
DCHECK(!manifest.did_ignore_intercept_namespaces);
DCHECK(!manifest.did_ignore_fallback_namespaces);
- Mode mode = EXPLICIT;
-
- std::wstring data_string;
- base::UTF8ToWide(data, length, &data_string);
- const wchar_t* p = data_string.c_str();
- const wchar_t* end = p + data_string.length();
-
- // Look for the magic signature: "^\xFEFF?CACHE MANIFEST[ \t]?"
- // Example: "CACHE MANIFEST #comment" is a valid signature.
- // Example: "CACHE MANIFEST;V2" is not.
-
- // When the input data starts with a UTF-8 Byte-Order-Mark
- // (0xEF, 0xBB, 0xBF), the UTF8ToWide() function converts it to a
- // Unicode BOM (U+FEFF). Skip a converted Unicode BOM if it exists.
- int bom_offset = 0;
- if (!data_string.empty() && data_string[0] == 0xFEFF) {
- bom_offset = 1;
- ++p;
- }
-
- if (p >= end)
- return false;
-
- // Check for a supported signature and skip p past it.
- if (0 == data_string.compare(bom_offset, kSignatureLength,
- kSignature)) {
- p += kSignatureLength;
- } else if (0 == data_string.compare(bom_offset, kChromiumSignatureLength,
- kChromiumSignature)) {
- p += kChromiumSignatureLength;
+ Mode mode = Mode::kExplicit;
+
+ // The specification requires UTF-8-decoding the manifest, which replaces
+ // invalid UTF-8 characters with placeholders. It would be nice if
+ // utf_string_conversions included a UTF-8 to UTF-8 conversion for this
+ // purpose, but AppCache isn't important enough to add conversion code just
+ // to accelerate manifest decoding.
+ DCHECK_GE(manifest_size, 0);
+ base::string16 wide_manifest_bytes =
+ base::UTF8ToUTF16(base::StringPiece(manifest_bytes, manifest_size));
+ std::string decoded_manifest_bytes = base::UTF16ToUTF8(wide_manifest_bytes);
+
+ // The bytes of the manifest that haven't been consumed yet.
+ base::StringPiece data(decoded_manifest_bytes);
+
+ // Discard a leading UTF-8 Byte-Order-Mark (BOM) (0xEF, 0xBB, 0xBF);
+ static constexpr base::StringPiece kUtf8Bom("\xEF\xBB\xBF");
+ if (data.starts_with(kUtf8Bom))
+ data = data.substr(kUtf8Bom.length());
+
+ // The manifest has to start with a well-defined signature.
+ static constexpr base::StringPiece kSignature("CACHE MANIFEST");
+ static constexpr base::StringPiece kChromiumSignature(
+ "CHROMIUM CACHE MANIFEST");
+ if (data.starts_with(kSignature)) {
+ data = data.substr(kSignature.length());
+ } else if (data.starts_with(kChromiumSignature)) {
+ // Chrome recognizes a separate signature, CHROMIUM CACHE MANIFEST. This was
+ // built so that manifests that use the Chrome-only feature
+ // CHROMIUM-INTERCEPT will be ignored by other browsers.
+ // See https://crbug.com/101565
+
+ // TODO(pwnall): Add a UMA metric to see if we can remove support for this
+ // non-standard signature.
+ data = data.substr(kChromiumSignature.length());
} else {
return false;
}
- // Character after "CACHE MANIFEST" must be whitespace.
- if (p < end && *p != ' ' && *p != '\t' && *p != '\n' && *p != '\r')
+ // The character after "CACHE MANIFEST" must be a whitespace character.
+ if (!data.empty() && !IsWhiteSpace(data[0]))
return false;
- // Skip to the end of the line.
- while (p < end && *p != '\r' && *p != '\n')
- ++p;
+ // The spec requires ignoring any characters on the first line after the
+ // signature and its following whitespace.
+ data = TrimToFirstNewLine(data);
- while (1) {
- // Skip whitespace
- while (p < end && (*p == '\n' || *p == '\r' || *p == ' ' || *p == '\t'))
- ++p;
-
- if (p == end)
+ while (true) {
+ data = TrimStartingWhiteSpace(data);
+ if (data.empty())
break;
- const wchar_t* line_start = p;
+ base::StringPiece line;
+ std::tie(line, data) = SplitOnNewLine(data);
- // Find the end of the line
- while (p < end && *p != '\r' && *p != '\n')
- ++p;
+ // The checks above guarantee that the input to SplitOnNewLine() starts with
+ // a non-whitespace character.
+ DCHECK(!line.empty());
- // Check if we have a comment
- if (*line_start == '#')
+ if (line[0] == '#') // Lines starting with # are comments.
continue;
- // Get rid of trailing whitespace
- const wchar_t* tmp = p - 1;
- while (tmp > line_start && (*tmp == ' ' || *tmp == '\t'))
- --tmp;
-
- std::wstring line(line_start, tmp - line_start + 1);
-
- if (line == L"CACHE:") {
- mode = EXPLICIT;
- } else if (line == L"FALLBACK:") {
- mode = FALLBACK;
- } else if (line == L"NETWORK:") {
- mode = ONLINE_WHITELIST;
- } else if (line == L"CHROMIUM-INTERCEPT:") {
- mode = INTERCEPT;
- } else if (*(line.end() - 1) == ':') {
- mode = UNKNOWN_MODE;
- } else if (mode == UNKNOWN_MODE) {
+ line = TrimTrailingWhiteSpace(line);
+
+ // Handle all the steps checking for lines that end with ":".
+ if (IsModeSettingLine(line)) {
+ mode = ParseModeSettingLine(line);
+ continue;
+ }
+
+ if (mode == Mode::kUnknown)
continue;
- } else if (line == L"*" && mode == ONLINE_WHITELIST) {
+
+ static constexpr base::StringPiece kOnlineSafelistWildcard("*");
+ if (mode == Mode::kOnlineSafelist && line == kOnlineSafelistWildcard) {
manifest.online_whitelist_all = true;
continue;
- } else if (mode == EXPLICIT || mode == ONLINE_WHITELIST) {
- const wchar_t *line_p = line.c_str();
- const wchar_t *line_end = line_p + line.length();
-
- // Look for whitespace separating the URL from subsequent ignored tokens.
- while (line_p < line_end && *line_p != '\t' && *line_p != ' ')
- ++line_p;
-
- base::string16 url16;
- base::WideToUTF16(line.c_str(), line_p - line.c_str(), &url16);
- GURL url = manifest_url.Resolve(url16);
- if (!url.is_valid())
- continue;
- if (url.has_ref()) {
- GURL::Replacements replacements;
- replacements.ClearRef();
- url = url.ReplaceComponents(replacements);
- }
+ }
+
+ // Chrome does not implement the SETTINGS: section. If we ever decided to do
+ // so, the implementation would go here.
+
+ // Common code for the following sections: explicit (CACHE:),
+ // fallback (FALLBACK:), online safelist (NETWORK:) and intercept
+ // (CHROMIUM-INTERCEPT:). All these sections start by parsing a URL token.
+ base::StringPiece namespace_url_token;
+ std::tie(namespace_url_token, line) = SplitLineToken(line);
+ GURL namespace_url = ParseUrlToken(namespace_url_token, manifest_url);
+ if (!namespace_url.is_valid())
+ continue;
+ if (mode == Mode::kExplicit || mode == Mode::kOnlineSafelist) {
// Scheme component must be the same as the manifest URL's.
- if (url.scheme() != manifest_url.scheme()) {
+ if (namespace_url.scheme() != manifest_url.scheme()) {
continue;
}
- // See http://code.google.com/p/chromium/issues/detail?id=69594
- // We willfully violate the HTML5 spec at this point in order
- // to support the appcaching of cross-origin HTTPS resources.
- // Per the spec, EXPLICIT cross-origin HTTS resources should be
- // ignored here. We've opted for a milder constraint and allow
- // caching unless the resource has a "no-store" header. That
- // condition is enforced in AppCacheUpdateJob.
+ // Deviate from the HTML5 spec by supporting the caching of cross-origin
+ // HTTPS resources. See https://crbug.com/69594
+ //
+ // Per the spec, explicit (CACHE:) cross-origin HTTPS resources should be
+ // ignored here. We've opted for a milder constraint and allow caching
+ // unless the resource has a "no-store" header. That condition is enforced
+ // in AppCacheUpdateJob.
- if (mode == EXPLICIT) {
- manifest.explicit_urls.insert(url.spec());
+ if (mode == Mode::kExplicit) {
+ manifest.explicit_urls.insert(namespace_url.spec());
} else {
- bool is_pattern = HasPatternMatchingAnnotation(line_p, line_end);
- manifest.online_whitelist_namespaces.push_back(
- AppCacheNamespace(APPCACHE_NETWORK_NAMESPACE, url, GURL(),
- is_pattern));
+ // Chrome supports URL patterns in manifests. This is not standardized.
+ // An URL record followed by the "isPattern" token is considered a
+ // pattern.
+
+ // TODO(pwnall): Add a UMA metric to see if we can remove this feature.
+ bool is_pattern = NextTokenIsPatternMatchingFlag(line);
+ manifest.online_whitelist_namespaces.emplace_back(AppCacheNamespace(
+ APPCACHE_NETWORK_NAMESPACE, namespace_url, GURL(), is_pattern));
}
- } else if (mode == INTERCEPT) {
- if (parse_mode != PARSE_MANIFEST_ALLOWING_DANGEROUS_FEATURES) {
- manifest.did_ignore_intercept_namespaces = true;
- continue;
- }
-
- // Lines of the form,
- // <urlnamespace> <intercept_type> <targeturl>
- const wchar_t* line_p = line.c_str();
- const wchar_t* line_end = line_p + line.length();
-
- // Look for first whitespace separating the url namespace from
- // the intercept type.
- while (line_p < line_end && *line_p != '\t' && *line_p != ' ')
- ++line_p;
+ continue;
+ }
- if (line_p == line_end)
- continue; // There was no whitespace separating the URLs.
+ if (mode == Mode::kIntercept) {
+ // Chrome supports a CHROMIUM-INTERCEPT section. https://crbug.com/101565
+ //
+ // This section consists of entries of the form:
+ // namespace_url verb url_target
- base::string16 namespace_url16;
- base::WideToUTF16(line.c_str(), line_p - line.c_str(), &namespace_url16);
- GURL namespace_url = manifest_url.Resolve(namespace_url16);
- if (!namespace_url.is_valid())
+ if (parse_mode != PARSE_MANIFEST_ALLOWING_DANGEROUS_FEATURES) {
+ manifest.did_ignore_intercept_namespaces = true;
continue;
- if (namespace_url.has_ref()) {
- GURL::Replacements replacements;
- replacements.ClearRef();
- namespace_url = namespace_url.ReplaceComponents(replacements);
}
- // The namespace URL must have the same scheme, host and port
- // as the manifest's URL.
if (manifest_url.GetOrigin() != namespace_url.GetOrigin())
continue;
- // Skip whitespace separating namespace from the type.
- while (line_p < line_end && (*line_p == '\t' || *line_p == ' '))
- ++line_p;
-
- // Look for whitespace separating the type from the target url.
- const wchar_t* type_start = line_p;
- while (line_p < line_end && *line_p != '\t' && *line_p != ' ')
- ++line_p;
-
- // Look for a type value we understand, otherwise skip the line.
- std::wstring type(type_start, line_p - type_start);
- if (type != L"return")
+ // The only supported verb is "return".
+ base::StringPiece verb_token;
+ std::tie(verb_token, line) = SplitLineToken(line);
+ static constexpr base::StringPiece kReturnVerb("return");
+ if (verb_token != kReturnVerb)
continue;
- // Skip whitespace separating type from the target_url.
- while (line_p < line_end && (*line_p == '\t' || *line_p == ' '))
- ++line_p;
-
- // Look for whitespace separating the URL from subsequent ignored tokens.
- const wchar_t* target_url_start = line_p;
- while (line_p < line_end && *line_p != '\t' && *line_p != ' ')
- ++line_p;
-
- base::string16 target_url16;
- base::WideToUTF16(target_url_start, line_p - target_url_start,
- &target_url16);
- GURL target_url = manifest_url.Resolve(target_url16);
+ base::StringPiece target_url_token;
+ std::tie(target_url_token, line) = SplitLineToken(line);
+ if (target_url_token.empty())
+ continue;
+ GURL target_url = ParseUrlToken(target_url_token, manifest_url);
if (!target_url.is_valid())
continue;
- if (target_url.has_ref()) {
- GURL::Replacements replacements;
- replacements.ClearRef();
- target_url = target_url.ReplaceComponents(replacements);
- }
if (manifest_url.GetOrigin() != target_url.GetOrigin())
continue;
- bool is_pattern = HasPatternMatchingAnnotation(line_p, line_end);
- manifest.intercept_namespaces.push_back(AppCacheNamespace(
- APPCACHE_INTERCEPT_NAMESPACE, namespace_url, target_url, is_pattern));
- } else if (mode == FALLBACK) {
- const wchar_t* line_p = line.c_str();
- const wchar_t* line_end = line_p + line.length();
-
- // Look for whitespace separating the two URLs
- while (line_p < line_end && *line_p != '\t' && *line_p != ' ')
- ++line_p;
-
- if (line_p == line_end) {
- // There was no whitespace separating the URLs.
- continue;
- }
-
- base::string16 namespace_url16;
- base::WideToUTF16(line.c_str(), line_p - line.c_str(), &namespace_url16);
- GURL namespace_url = manifest_url.Resolve(namespace_url16);
- if (!namespace_url.is_valid())
- continue;
- if (namespace_url.has_ref()) {
- GURL::Replacements replacements;
- replacements.ClearRef();
- namespace_url = namespace_url.ReplaceComponents(replacements);
- }
+ // TODO(pwnall): Add a UMA metric to see if we can remove this feature.
+ bool is_pattern = NextTokenIsPatternMatchingFlag(line);
+ manifest.intercept_namespaces.emplace_back(
+ APPCACHE_INTERCEPT_NAMESPACE, namespace_url, target_url, is_pattern);
+ continue;
+ }
- // Fallback namespace URL must have the same scheme, host and port
- // as the manifest's URL.
- if (manifest_url.GetOrigin() != namespace_url.GetOrigin()) {
+ if (mode == Mode::kFallback) {
+ if (manifest_url.GetOrigin() != namespace_url.GetOrigin())
continue;
- }
if (parse_mode != PARSE_MANIFEST_ALLOWING_DANGEROUS_FEATURES) {
if (!ScopeMatches(manifest_url, namespace_url)) {
@@ -340,43 +414,29 @@ bool ParseManifest(const GURL& manifest_url, const char* data, int length,
}
}
- // Skip whitespace separating fallback namespace from URL.
- while (line_p < line_end && (*line_p == '\t' || *line_p == ' '))
- ++line_p;
-
- // Look for whitespace separating the URL from subsequent ignored tokens.
- const wchar_t* fallback_start = line_p;
- while (line_p < line_end && *line_p != '\t' && *line_p != ' ')
- ++line_p;
-
- base::string16 fallback_url16;
- base::WideToUTF16(fallback_start, line_p - fallback_start,
- &fallback_url16);
- GURL fallback_url = manifest_url.Resolve(fallback_url16);
+ base::StringPiece fallback_url_token;
+ std::tie(fallback_url_token, line) = SplitLineToken(line);
+ if (fallback_url_token.empty())
+ continue;
+ GURL fallback_url = ParseUrlToken(fallback_url_token, manifest_url);
if (!fallback_url.is_valid())
continue;
- if (fallback_url.has_ref()) {
- GURL::Replacements replacements;
- replacements.ClearRef();
- fallback_url = fallback_url.ReplaceComponents(replacements);
- }
- // Fallback entry URL must have the same scheme, host and port
- // as the manifest's URL.
- if (manifest_url.GetOrigin() != fallback_url.GetOrigin()) {
+ if (manifest_url.GetOrigin() != fallback_url.GetOrigin())
continue;
- }
- bool is_pattern = HasPatternMatchingAnnotation(line_p, line_end);
+ // TODO(pwnall): Add a UMA metric to see if we can remove this feature.
+ bool is_pattern = NextTokenIsPatternMatchingFlag(line);
- // Store regardless of duplicate namespace URL. Only first match
- // will ever be used.
- manifest.fallback_namespaces.push_back(
+ // Store regardless of duplicate namespace URL. Only the first match will
+ // ever be used.
+ manifest.fallback_namespaces.emplace_back(
AppCacheNamespace(APPCACHE_FALLBACK_NAMESPACE, namespace_url,
- fallback_url, is_pattern));
- } else {
- NOTREACHED();
+ fallback_url, is_pattern));
+ continue;
}
+
+ NOTREACHED() << "Unimplemented AppCache manifest parser mode";
}
return true;
diff --git a/chromium/content/browser/appcache/appcache_manifest_parser.h b/chromium/content/browser/appcache/appcache_manifest_parser.h
index 016655b25e9..6312d4fa08d 100644
--- a/chromium/content/browser/appcache/appcache_manifest_parser.h
+++ b/chromium/content/browser/appcache/appcache_manifest_parser.h
@@ -61,12 +61,11 @@ enum ParseMode {
PARSE_MANIFEST_ALLOWING_DANGEROUS_FEATURES
};
-CONTENT_EXPORT bool ParseManifest(
- const GURL& manifest_url,
- const char* data,
- int length,
- ParseMode parse_mode,
- AppCacheManifest& manifest);
+CONTENT_EXPORT bool ParseManifest(const GURL& manifest_url,
+ const char* manifest_bytes,
+ int manifest_size,
+ ParseMode parse_mode,
+ AppCacheManifest& manifest);
} // namespace content
diff --git a/chromium/content/browser/appcache/appcache_manifest_parser_unittest.cc b/chromium/content/browser/appcache/appcache_manifest_parser_unittest.cc
index 5ca2d3ac9e1..07f005be838 100644
--- a/chromium/content/browser/appcache/appcache_manifest_parser_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_manifest_parser_unittest.cc
@@ -447,7 +447,8 @@ TEST(AppCacheManifestParserTest, UnusualUtf8) {
PARSE_MANIFEST_ALLOWING_DANGEROUS_FEATURES,
manifest));
base::hash_set<std::string> urls = manifest.explicit_urls;
- EXPECT_TRUE(urls.find("http://bad.com/%EF%BF%BDinvalidutf8") != urls.end());
+ EXPECT_TRUE(urls.find("http://bad.com/%EF%BF%BDinvalidutf8") != urls.end())
+ << "manifest byte stream was passed through, not UTF-8-decoded";
EXPECT_TRUE(urls.find("http://bad.com/nonbmp%F1%84%AB%BC") != urls.end());
}
diff --git a/chromium/content/browser/appcache/appcache_navigation_handle.cc b/chromium/content/browser/appcache/appcache_navigation_handle.cc
index b6bf5de3d8f..005f258bb32 100644
--- a/chromium/content/browser/appcache/appcache_navigation_handle.cc
+++ b/chromium/content/browser/appcache/appcache_navigation_handle.cc
@@ -5,8 +5,10 @@
#include "content/browser/appcache/appcache_navigation_handle.h"
#include "base/bind.h"
+#include "base/task/post_task.h"
#include "content/browser/appcache/appcache_navigation_handle_core.h"
#include "content/browser/appcache/chrome_appcache_service.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
namespace {
@@ -23,8 +25,8 @@ AppCacheNavigationHandle::AppCacheNavigationHandle(
core_(std::make_unique<AppCacheNavigationHandleCore>(appcache_service,
appcache_host_id_)) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&AppCacheNavigationHandleCore::Initialize,
base::Unretained(core_.get())));
}
diff --git a/chromium/content/browser/appcache/appcache_request_handler.cc b/chromium/content/browser/appcache/appcache_request_handler.cc
index 459c79ab482..42578121c1d 100644
--- a/chromium/content/browser/appcache/appcache_request_handler.cc
+++ b/chromium/content/browser/appcache/appcache_request_handler.cc
@@ -573,7 +573,8 @@ bool AppCacheRequestHandler::MaybeCreateLoaderForResponse(
const network::ResourceResponseHead& response,
network::mojom::URLLoaderPtr* loader,
network::mojom::URLLoaderClientRequest* client_request,
- ThrottlingURLLoader* url_loader) {
+ ThrottlingURLLoader* url_loader,
+ bool* skip_other_interceptors) {
// The sync interface of this method is inherited from the
// NavigationLoaderInterceptor class. The LoaderCallback created here is
// invoked synchronously in fallback cases, and only when there really is
@@ -600,6 +601,8 @@ bool AppCacheRequestHandler::MaybeCreateLoaderForResponse(
return false;
}
DCHECK(was_called);
+ if (IsMainResourceType(resource_type_))
+ should_create_subresource_loader_ = true;
return true;
}
diff --git a/chromium/content/browser/appcache/appcache_request_handler.h b/chromium/content/browser/appcache/appcache_request_handler.h
index 57362f43c43..40249b7ee04 100644
--- a/chromium/content/browser/appcache/appcache_request_handler.h
+++ b/chromium/content/browser/appcache/appcache_request_handler.h
@@ -84,7 +84,8 @@ class CONTENT_EXPORT AppCacheRequestHandler
const network::ResourceResponseHead& response,
network::mojom::URLLoaderPtr* loader,
network::mojom::URLLoaderClientRequest* client_request,
- ThrottlingURLLoader* url_loader) override;
+ ThrottlingURLLoader* url_loader,
+ bool* skip_other_interceptors) override;
base::Optional<SubresourceLoaderParams> MaybeCreateSubresourceLoaderParams()
override;
diff --git a/chromium/content/browser/appcache/appcache_request_handler_unittest.cc b/chromium/content/browser/appcache/appcache_request_handler_unittest.cc
index bd3494c4aa9..0ed52f25f1a 100644
--- a/chromium/content/browser/appcache/appcache_request_handler_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_request_handler_unittest.cc
@@ -21,6 +21,7 @@
#include "base/single_thread_task_runner.h"
#include "base/strings/stringprintf.h"
#include "base/synchronization/waitable_event.h"
+#include "base/task/post_task.h"
#include "base/test/scoped_feature_list.h"
#include "base/threading/thread.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -33,6 +34,7 @@
#include "content/browser/appcache/appcache_url_request_job.h"
#include "content/browser/appcache/mock_appcache_policy.h"
#include "content/browser/appcache/mock_appcache_service.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "net/base/net_errors.h"
#include "net/base/request_priority.h"
@@ -204,7 +206,8 @@ class AppCacheRequestHandlerTest
static void SetUpTestCase() {
thread_bundle_.reset(
new TestBrowserThreadBundle(TestBrowserThreadBundle::REAL_IO_THREAD));
- io_task_runner_ = BrowserThread::GetTaskRunnerForThread(BrowserThread::IO);
+ io_task_runner_ =
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO});
}
static void TearDownTestCase() {
diff --git a/chromium/content/browser/appcache/appcache_response.cc b/chromium/content/browser/appcache/appcache_response.cc
index 15bb71504fb..04515fc6118 100644
--- a/chromium/content/browser/appcache/appcache_response.cc
+++ b/chromium/content/browser/appcache/appcache_response.cc
@@ -18,6 +18,7 @@
#include "base/single_thread_task_runner.h"
#include "base/strings/string_util.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "content/browser/appcache/appcache_disk_cache.h"
#include "content/browser/appcache/appcache_storage.h"
#include "net/base/completion_once_callback.h"
#include "net/base/io_buffer.h"
@@ -82,23 +83,11 @@ HttpResponseInfoIOBuffer::HttpResponseInfoIOBuffer(
HttpResponseInfoIOBuffer::~HttpResponseInfoIOBuffer() = default;
-// AppCacheDiskCacheInterface ----------------------------------------
-
-AppCacheDiskCacheInterface::AppCacheDiskCacheInterface(const char* uma_name)
- : uma_name_(uma_name), weak_factory_(this) {}
-
-base::WeakPtr<AppCacheDiskCacheInterface>
-AppCacheDiskCacheInterface::GetWeakPtr() {
- return weak_factory_.GetWeakPtr();
-}
-
-AppCacheDiskCacheInterface::~AppCacheDiskCacheInterface() {}
-
// AppCacheResponseIO ----------------------------------------------
AppCacheResponseIO::AppCacheResponseIO(
int64_t response_id,
- base::WeakPtr<AppCacheDiskCacheInterface> disk_cache)
+ base::WeakPtr<AppCacheDiskCache> disk_cache)
: response_id_(response_id),
disk_cache_(std::move(disk_cache)),
entry_(nullptr),
@@ -152,13 +141,13 @@ void AppCacheResponseIO::OnRawIOComplete(int result) {
void AppCacheResponseIO::OpenEntryIfNeeded() {
int rv;
- AppCacheDiskCacheInterface::Entry** entry_ptr = nullptr;
+ AppCacheDiskCacheEntry** entry_ptr = nullptr;
if (entry_) {
rv = net::OK;
} else if (!disk_cache_) {
rv = net::ERR_FAILED;
} else {
- entry_ptr = new AppCacheDiskCacheInterface::Entry*;
+ entry_ptr = new AppCacheDiskCacheEntry*;
rv = disk_cache_->OpenEntry(
response_id_, entry_ptr,
base::BindOnce(&AppCacheResponseIO::OpenEntryCallback, GetWeakPtr(),
@@ -172,7 +161,7 @@ void AppCacheResponseIO::OpenEntryIfNeeded() {
// static
void AppCacheResponseIO::OpenEntryCallback(
base::WeakPtr<AppCacheResponseIO> response,
- AppCacheDiskCacheInterface::Entry** entry,
+ AppCacheDiskCacheEntry** entry,
int rv) {
if (!response) {
delete entry;
@@ -194,7 +183,7 @@ void AppCacheResponseIO::OpenEntryCallback(
AppCacheResponseReader::AppCacheResponseReader(
int64_t response_id,
- base::WeakPtr<AppCacheDiskCacheInterface> disk_cache)
+ base::WeakPtr<AppCacheDiskCache> disk_cache)
: AppCacheResponseIO(response_id, std::move(disk_cache)),
range_offset_(0),
range_length_(std::numeric_limits<int32_t>::max()),
@@ -225,7 +214,7 @@ void AppCacheResponseReader::ContinueReadInfo() {
return;
}
- buffer_ = new net::IOBuffer(size);
+ buffer_ = base::MakeRefCounted<net::IOBuffer>(size);
ReadRaw(kResponseInfoIndex, 0, buffer_.get(), size);
}
@@ -290,8 +279,9 @@ void AppCacheResponseReader::OnIOComplete(int result) {
int64_t metadata_size = entry_->GetSize(kResponseMetadataIndex);
if (metadata_size > 0) {
reading_metadata_size_ = metadata_size;
- info_buffer_->http_info->metadata = new net::IOBufferWithSize(
- base::checked_cast<size_t>(metadata_size));
+ info_buffer_->http_info->metadata =
+ base::MakeRefCounted<net::IOBufferWithSize>(
+ base::checked_cast<size_t>(metadata_size));
ReadRaw(kResponseMetadataIndex, 0,
info_buffer_->http_info->metadata.get(), metadata_size);
return;
@@ -325,7 +315,7 @@ base::WeakPtr<AppCacheResponseIO> AppCacheResponseReader::GetWeakPtr() {
AppCacheResponseWriter::AppCacheResponseWriter(
int64_t response_id,
- base::WeakPtr<AppCacheDiskCacheInterface> disk_cache)
+ base::WeakPtr<AppCacheDiskCache> disk_cache)
: AppCacheResponseIO(response_id, std::move(disk_cache)),
info_size_(0),
write_position_(0),
@@ -407,7 +397,7 @@ void AppCacheResponseWriter::OnIOComplete(int result) {
void AppCacheResponseWriter::CreateEntryIfNeededAndContinue() {
int rv;
- AppCacheDiskCacheInterface::Entry** entry_ptr = nullptr;
+ AppCacheDiskCacheEntry** entry_ptr = nullptr;
if (entry_) {
creation_phase_ = NO_ATTEMPT;
rv = net::OK;
@@ -416,7 +406,7 @@ void AppCacheResponseWriter::CreateEntryIfNeededAndContinue() {
rv = net::ERR_FAILED;
} else {
creation_phase_ = INITIAL_ATTEMPT;
- entry_ptr = new AppCacheDiskCacheInterface::Entry*;
+ entry_ptr = new AppCacheDiskCacheEntry*;
rv = disk_cache_->CreateEntry(
response_id_, entry_ptr,
base::BindOnce(&AppCacheResponseWriter::OnCreateEntryComplete,
@@ -429,7 +419,7 @@ void AppCacheResponseWriter::CreateEntryIfNeededAndContinue() {
// static
void AppCacheResponseWriter::OnCreateEntryComplete(
base::WeakPtr<AppCacheResponseWriter> writer,
- AppCacheDiskCacheInterface::Entry** entry,
+ AppCacheDiskCacheEntry** entry,
int rv) {
if (!writer) {
if (entry) {
@@ -462,8 +452,7 @@ void AppCacheResponseWriter::OnCreateEntryComplete(
} else if (writer->creation_phase_ == DOOM_EXISTING) {
DCHECK_EQ(nullptr, entry);
writer->creation_phase_ = SECOND_ATTEMPT;
- AppCacheDiskCacheInterface::Entry** entry_ptr =
- new AppCacheDiskCacheInterface::Entry*;
+ AppCacheDiskCacheEntry** entry_ptr = new AppCacheDiskCacheEntry*;
rv = writer->disk_cache_->CreateEntry(
writer->response_id_, entry_ptr,
base::BindOnce(&AppCacheResponseWriter::OnCreateEntryComplete, writer,
@@ -494,7 +483,7 @@ base::WeakPtr<AppCacheResponseIO> AppCacheResponseWriter::GetWeakPtr() {
AppCacheResponseMetadataWriter::AppCacheResponseMetadataWriter(
int64_t response_id,
- base::WeakPtr<AppCacheDiskCacheInterface> disk_cache)
+ base::WeakPtr<AppCacheDiskCache> disk_cache)
: AppCacheResponseIO(response_id, std::move(disk_cache)),
write_amount_(0),
weak_factory_(this) {}
diff --git a/chromium/content/browser/appcache/appcache_response.h b/chromium/content/browser/appcache/appcache_response.h
index de0663e162e..3f22f716a64 100644
--- a/chromium/content/browser/appcache/appcache_response.h
+++ b/chromium/content/browser/appcache/appcache_response.h
@@ -23,6 +23,8 @@ class IOBuffer;
}
namespace content {
+class AppCacheDiskCache;
+class AppCacheDiskCacheEntry;
class AppCacheStorage;
class MockAppCacheStorage;
@@ -75,48 +77,6 @@ struct CONTENT_EXPORT HttpResponseInfoIOBuffer
~HttpResponseInfoIOBuffer();
};
-// Low level storage API used by the response reader and writer.
-class CONTENT_EXPORT AppCacheDiskCacheInterface {
- public:
- class Entry {
- public:
- virtual int Read(int index,
- int64_t offset,
- net::IOBuffer* buf,
- int buf_len,
- net::CompletionOnceCallback callback) = 0;
- virtual int Write(int index,
- int64_t offset,
- net::IOBuffer* buf,
- int buf_len,
- net::CompletionOnceCallback callback) = 0;
- virtual int64_t GetSize(int index) = 0;
- virtual void Close() = 0;
- protected:
- virtual ~Entry() = default;
- };
-
- // The uma_name pointer must remain valid for the life of the object.
- AppCacheDiskCacheInterface(const char* uma_name);
-
- virtual int CreateEntry(int64_t key,
- Entry** entry,
- net::CompletionOnceCallback callback) = 0;
- virtual int OpenEntry(int64_t key,
- Entry** entry,
- net::CompletionOnceCallback callback) = 0;
- virtual int DoomEntry(int64_t key, net::CompletionOnceCallback callback) = 0;
-
- const char* uma_name() const { return uma_name_; }
- base::WeakPtr<AppCacheDiskCacheInterface> GetWeakPtr();
-
- protected:
- virtual ~AppCacheDiskCacheInterface();
-
- const char* uma_name_;
- base::WeakPtrFactory<AppCacheDiskCacheInterface> weak_factory_;
-};
-
// Common base class for response reader and writer.
class CONTENT_EXPORT AppCacheResponseIO {
public:
@@ -125,7 +85,7 @@ class CONTENT_EXPORT AppCacheResponseIO {
protected:
AppCacheResponseIO(int64_t response_id,
- base::WeakPtr<AppCacheDiskCacheInterface> disk_cache);
+ base::WeakPtr<AppCacheDiskCache> disk_cache);
virtual void OnIOComplete(int result) = 0;
virtual void OnOpenEntryComplete() {}
@@ -142,8 +102,8 @@ class CONTENT_EXPORT AppCacheResponseIO {
virtual base::WeakPtr<AppCacheResponseIO> GetWeakPtr() = 0;
const int64_t response_id_;
- base::WeakPtr<AppCacheDiskCacheInterface> disk_cache_;
- AppCacheDiskCacheInterface::Entry* entry_;
+ base::WeakPtr<AppCacheDiskCache> disk_cache_;
+ AppCacheDiskCacheEntry* entry_;
scoped_refptr<HttpResponseInfoIOBuffer> info_buffer_;
scoped_refptr<net::IOBuffer> buffer_;
int buffer_len_;
@@ -153,7 +113,7 @@ class CONTENT_EXPORT AppCacheResponseIO {
private:
void OnRawIOComplete(int result);
static void OpenEntryCallback(base::WeakPtr<AppCacheResponseIO> response,
- AppCacheDiskCacheInterface::Entry** entry,
+ AppCacheDiskCacheEntry** entry,
int rv);
};
@@ -202,9 +162,9 @@ class CONTENT_EXPORT AppCacheResponseReader : public AppCacheResponseIO {
friend class AppCacheStorageImpl;
friend class content::MockAppCacheStorage;
- // Should only be constructed by the storage class and derivatives.
+ // Use AppCacheStorage::CreateResponse() instead of calling directly.
AppCacheResponseReader(int64_t response_id,
- base::WeakPtr<AppCacheDiskCacheInterface> disk_cache);
+ base::WeakPtr<AppCacheDiskCache> disk_cache);
void OnIOComplete(int result) override;
void OnOpenEntryComplete() override;
@@ -262,7 +222,7 @@ class CONTENT_EXPORT AppCacheResponseWriter : public AppCacheResponseIO {
protected:
// Should only be constructed by the storage class and derivatives.
AppCacheResponseWriter(int64_t response_id,
- base::WeakPtr<AppCacheDiskCacheInterface> disk_cache);
+ base::WeakPtr<AppCacheDiskCache> disk_cache);
private:
friend class AppCacheStorageImpl;
@@ -283,7 +243,7 @@ class CONTENT_EXPORT AppCacheResponseWriter : public AppCacheResponseIO {
void CreateEntryIfNeededAndContinue();
static void OnCreateEntryComplete(
base::WeakPtr<AppCacheResponseWriter> writer,
- AppCacheDiskCacheInterface::Entry** entry,
+ AppCacheDiskCacheEntry** entry,
int rv);
int info_size_;
@@ -323,9 +283,8 @@ class CONTENT_EXPORT AppCacheResponseMetadataWriter
friend class content::MockAppCacheStorage;
// Should only be constructed by the storage class and derivatives.
- AppCacheResponseMetadataWriter(
- int64_t response_id,
- base::WeakPtr<AppCacheDiskCacheInterface> disk_cache);
+ AppCacheResponseMetadataWriter(int64_t response_id,
+ base::WeakPtr<AppCacheDiskCache> disk_cache);
private:
void OnIOComplete(int result) override;
diff --git a/chromium/content/browser/appcache/appcache_response_unittest.cc b/chromium/content/browser/appcache/appcache_response_unittest.cc
index 799c9133b52..5cde7376907 100644
--- a/chromium/content/browser/appcache/appcache_response_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_response_unittest.cc
@@ -169,7 +169,8 @@ class AppCacheResponseTest : public testing::Test {
static const char kHttpHeaders[] =
"HTTP/1.0 200 OK\0Content-Length: 5\0\0";
static const char kHttpBody[] = "Hello";
- scoped_refptr<IOBuffer> body(new WrappedIOBuffer(kHttpBody));
+ scoped_refptr<IOBuffer> body =
+ base::MakeRefCounted<WrappedIOBuffer>(kHttpBody);
std::string raw_headers(kHttpHeaders, arraysize(kHttpHeaders));
WriteResponse(
MakeHttpResponseInfo(raw_headers), body.get(), strlen(kHttpBody));
@@ -326,8 +327,8 @@ class AppCacheResponseTest : public testing::Test {
// 1. Attempt to ReadInfo
// 2. Attempt to ReadData
- reader_.reset(
- service_->storage()->CreateResponseReader(GURL(), kNoSuchResponseId));
+ reader_ =
+ service_->storage()->CreateResponseReader(GURL(), kNoSuchResponseId);
// Push tasks in reverse order
PushNextTask(base::BindOnce(&AppCacheResponseTest::ReadNonExistentData,
@@ -349,7 +350,7 @@ class AppCacheResponseTest : public testing::Test {
void ReadNonExistentData() {
EXPECT_FALSE(reader_->IsReadPending());
- read_buffer_ = new IOBuffer(kBlockSize);
+ read_buffer_ = base::MakeRefCounted<IOBuffer>(kBlockSize);
reader_->ReadData(read_buffer_.get(), kBlockSize,
base::BindOnce(&AppCacheResponseTest::OnReadComplete,
base::Unretained(this)));
@@ -382,7 +383,7 @@ class AppCacheResponseTest : public testing::Test {
PushNextTask(
base::BindOnce(&AppCacheResponseTest::LoadResponseInfo_Hit_Step2,
base::Unretained(this)));
- writer_.reset(service_->storage()->CreateResponseWriter(GURL()));
+ writer_ = service_->storage()->CreateResponseWriter(GURL());
written_response_id_ = writer_->response_id();
WriteBasicResponse();
}
@@ -444,7 +445,7 @@ class AppCacheResponseTest : public testing::Test {
base::Unretained(this), "Metadata First"));
PushNextTask(base::BindOnce(&AppCacheResponseTest::Metadata_ResetWriter,
base::Unretained(this)));
- writer_.reset(service_->storage()->CreateResponseWriter(GURL()));
+ writer_ = service_->storage()->CreateResponseWriter(GURL());
written_response_id_ = writer_->response_id();
WriteBasicResponse();
}
@@ -455,9 +456,10 @@ class AppCacheResponseTest : public testing::Test {
}
void Metadata_WriteMetadata(const char* metadata) {
- metadata_writer_.reset(service_->storage()->CreateResponseMetadataWriter(
- written_response_id_));
- scoped_refptr<IOBuffer> buffer(new WrappedIOBuffer(metadata));
+ metadata_writer_ =
+ service_->storage()->CreateResponseMetadataWriter(written_response_id_);
+ scoped_refptr<IOBuffer> buffer =
+ base::MakeRefCounted<WrappedIOBuffer>(metadata);
WriteResponseMetadata(buffer.get(), strlen(metadata));
}
@@ -510,7 +512,7 @@ class AppCacheResponseTest : public testing::Test {
PushNextTask(base::BindOnce(&AppCacheResponseTest::WriteResponseHead,
base::Unretained(this), std::move(head)));
- writer_.reset(service_->storage()->CreateResponseWriter(GURL()));
+ writer_ = service_->storage()->CreateResponseWriter(GURL());
written_response_id_ = writer_->response_id();
ScheduleNextTask();
}
@@ -557,7 +559,7 @@ class AppCacheResponseTest : public testing::Test {
}
void WriteOutBlocks() {
- writer_.reset(service_->storage()->CreateResponseWriter(GURL()));
+ writer_ = service_->storage()->CreateResponseWriter(GURL());
written_response_id_ = writer_->response_id();
for (int i = 0; i < kNumBlocks; ++i) {
PushNextTask(base::BindOnce(&AppCacheResponseTest::WriteOneBlock,
@@ -567,16 +569,16 @@ class AppCacheResponseTest : public testing::Test {
}
void WriteOneBlock(int block_number) {
- scoped_refptr<IOBuffer> io_buffer(
- new IOBuffer(kBlockSize));
+ scoped_refptr<IOBuffer> io_buffer =
+ base::MakeRefCounted<IOBuffer>(kBlockSize);
FillData(block_number, io_buffer->data(), kBlockSize);
WriteResponseBody(io_buffer, kBlockSize);
}
void ReadInBlocks() {
writer_.reset();
- reader_.reset(service_->storage()->CreateResponseReader(
- GURL(), written_response_id_));
+ reader_ =
+ service_->storage()->CreateResponseReader(GURL(), written_response_id_);
for (int i = 0; i < kNumBlocks; ++i) {
PushNextTask(base::BindOnce(&AppCacheResponseTest::ReadOneBlock,
base::Unretained(this), kNumBlocks - i));
@@ -587,7 +589,7 @@ class AppCacheResponseTest : public testing::Test {
void ReadOneBlock(int block_number) {
PushNextTask(base::BindOnce(&AppCacheResponseTest::VerifyOneBlock,
base::Unretained(this), block_number));
- ReadResponseBody(new IOBuffer(kBlockSize), kBlockSize);
+ ReadResponseBody(base::MakeRefCounted<IOBuffer>(kBlockSize), kBlockSize);
}
void VerifyOneBlock(int block_number) {
@@ -598,10 +600,10 @@ class AppCacheResponseTest : public testing::Test {
void ReadAllAtOnce() {
PushNextTask(base::BindOnce(&AppCacheResponseTest::VerifyAllAtOnce,
base::Unretained(this)));
- reader_.reset(service_->storage()->CreateResponseReader(
- GURL(), written_response_id_));
+ reader_ =
+ service_->storage()->CreateResponseReader(GURL(), written_response_id_);
int big_size = kNumBlocks * kBlockSize;
- ReadResponseBody(new IOBuffer(big_size), big_size);
+ ReadResponseBody(base::MakeRefCounted<IOBuffer>(big_size), big_size);
}
void VerifyAllAtOnce() {
@@ -613,7 +615,7 @@ class AppCacheResponseTest : public testing::Test {
void ReadPastEOF() {
EXPECT_FALSE(reader_->IsReadPending());
- read_buffer_ = new IOBuffer(kBlockSize);
+ read_buffer_ = base::MakeRefCounted<IOBuffer>(kBlockSize);
expected_read_result_ = 0;
reader_->ReadData(read_buffer_.get(), kBlockSize,
base::BindOnce(&AppCacheResponseTest::OnReadComplete,
@@ -623,10 +625,10 @@ class AppCacheResponseTest : public testing::Test {
void ReadRange() {
PushNextTask(base::BindOnce(&AppCacheResponseTest::VerifyRange,
base::Unretained(this)));
- reader_.reset(service_->storage()->CreateResponseReader(
- GURL(), written_response_id_));
+ reader_ =
+ service_->storage()->CreateResponseReader(GURL(), written_response_id_);
reader_->SetReadRange(kBlockSize, kBlockSize);
- ReadResponseBody(new IOBuffer(kBlockSize), kBlockSize);
+ ReadResponseBody(base::MakeRefCounted<IOBuffer>(kBlockSize), kBlockSize);
}
void VerifyRange() {
@@ -637,10 +639,10 @@ class AppCacheResponseTest : public testing::Test {
void ReadRangePartiallyBeyondEOF() {
PushNextTask(base::BindOnce(&AppCacheResponseTest::VerifyRangeBeyondEOF,
base::Unretained(this)));
- reader_.reset(service_->storage()->CreateResponseReader(
- GURL(), written_response_id_));
+ reader_ =
+ service_->storage()->CreateResponseReader(GURL(), written_response_id_);
reader_->SetReadRange(kBlockSize, kNumBlocks * kBlockSize);
- ReadResponseBody(new IOBuffer(kNumBlocks * kBlockSize),
+ ReadResponseBody(base::MakeRefCounted<IOBuffer>(kNumBlocks * kBlockSize),
kNumBlocks * kBlockSize);
expected_read_result_ = (kNumBlocks - 1) * kBlockSize;
}
@@ -651,10 +653,10 @@ class AppCacheResponseTest : public testing::Test {
}
void ReadRangeFullyBeyondEOF() {
- reader_.reset(service_->storage()->CreateResponseReader(
- GURL(), written_response_id_));
+ reader_ =
+ service_->storage()->CreateResponseReader(GURL(), written_response_id_);
reader_->SetReadRange((kNumBlocks * kBlockSize) + 1, kBlockSize);
- ReadResponseBody(new IOBuffer(kBlockSize), kBlockSize);
+ ReadResponseBody(base::MakeRefCounted<IOBuffer>(kBlockSize), kBlockSize);
expected_read_result_ = 0;
}
@@ -677,7 +679,7 @@ class AppCacheResponseTest : public testing::Test {
}
void WriteOutBlocksImmediately() {
- writer_.reset(service_->storage()->CreateResponseWriter(GURL()));
+ writer_ = service_->storage()->CreateResponseWriter(GURL());
written_response_id_ = writer_->response_id();
for (int i = 0; i < kNumBlocks; ++i) {
PushNextTaskAsImmediate(
@@ -689,8 +691,8 @@ class AppCacheResponseTest : public testing::Test {
void ReadInBlocksImmediately() {
writer_.reset();
- reader_.reset(service_->storage()->CreateResponseReader(
- GURL(), written_response_id_));
+ reader_ =
+ service_->storage()->CreateResponseReader(GURL(), written_response_id_);
for (int i = 0; i < kNumBlocks; ++i) {
PushNextTaskAsImmediate(
base::BindOnce(&AppCacheResponseTest::ReadOneBlockImmediately,
@@ -703,7 +705,7 @@ class AppCacheResponseTest : public testing::Test {
PushNextTaskAsImmediate(
base::BindOnce(&AppCacheResponseTest::VerifyOneBlock,
base::Unretained(this), block_number));
- ReadResponseBody(new IOBuffer(kBlockSize), kBlockSize);
+ ReadResponseBody(base::MakeRefCounted<IOBuffer>(kBlockSize), kBlockSize);
}
// DeleteWithinCallbacks -------------------------------------------
@@ -749,9 +751,9 @@ class AppCacheResponseTest : public testing::Test {
void ReadThenDelete() {
read_callback_was_called_ = false;
- reader_.reset(service_->storage()->CreateResponseReader(
- GURL(), written_response_id_));
- ReadResponseBody(new IOBuffer(kBlockSize), kBlockSize);
+ reader_ =
+ service_->storage()->CreateResponseReader(GURL(), written_response_id_);
+ ReadResponseBody(base::MakeRefCounted<IOBuffer>(kBlockSize), kBlockSize);
EXPECT_TRUE(reader_->IsReadPending());
reader_.reset();
diff --git a/chromium/content/browser/appcache/appcache_service_impl.cc b/chromium/content/browser/appcache/appcache_service_impl.cc
index 513eef22af8..b95cb20d688 100644
--- a/chromium/content/browser/appcache/appcache_service_impl.cc
+++ b/chromium/content/browser/appcache/appcache_service_impl.cc
@@ -321,8 +321,8 @@ void AppCacheServiceImpl::CheckResponseHelper::OnGroupLoaded(
// Verify that we can read the response info and data.
expected_total_size_ = entry->response_size();
- response_reader_.reset(
- service_->storage()->CreateResponseReader(manifest_url_, response_id_));
+ response_reader_ =
+ service_->storage()->CreateResponseReader(manifest_url_, response_id_);
info_buffer_ = new HttpResponseInfoIOBuffer();
response_reader_->ReadInfo(
info_buffer_.get(),
@@ -341,7 +341,7 @@ void AppCacheServiceImpl::CheckResponseHelper::OnReadInfoComplete(int result) {
amount_headers_read_ = result;
// Start reading the data.
- data_buffer_ = new net::IOBuffer(kIOBufferSize);
+ data_buffer_ = base::MakeRefCounted<net::IOBuffer>(kIOBufferSize);
response_reader_->ReadData(
data_buffer_.get(), kIOBufferSize,
base::BindOnce(&CheckResponseHelper::OnReadDataComplete,
diff --git a/chromium/content/browser/appcache/appcache_service_unittest.cc b/chromium/content/browser/appcache/appcache_service_unittest.cc
index 50a7421ae9c..a50ce5ca7fc 100644
--- a/chromium/content/browser/appcache/appcache_service_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_service_unittest.cc
@@ -43,8 +43,7 @@ class MockResponseReader : public AppCacheResponseReader {
int info_size,
const char* data,
int data_size)
- : AppCacheResponseReader(response_id,
- base::WeakPtr<AppCacheDiskCacheInterface>()),
+ : AppCacheResponseReader(response_id, /*disk_cache=*/nullptr),
info_(info),
info_size_(info_size),
data_(data),
diff --git a/chromium/content/browser/appcache/appcache_storage.cc b/chromium/content/browser/appcache/appcache_storage.cc
index 3be839ed241..c927a8f5d7c 100644
--- a/chromium/content/browser/appcache/appcache_storage.cc
+++ b/chromium/content/browser/appcache/appcache_storage.cc
@@ -60,7 +60,7 @@ AppCacheStorage::ResponseInfoLoadTask::~ResponseInfoLoadTask() {
void AppCacheStorage::ResponseInfoLoadTask::StartIfNeeded() {
if (reader_)
return;
- reader_.reset(storage_->CreateResponseReader(manifest_url_, response_id_));
+ reader_ = storage_->CreateResponseReader(manifest_url_, response_id_);
reader_->ReadInfo(info_buffer_.get(),
base::BindOnce(&ResponseInfoLoadTask::OnReadComplete,
base::Unretained(this)));
diff --git a/chromium/content/browser/appcache/appcache_storage.h b/chromium/content/browser/appcache/appcache_storage.h
index 5e49a2760a2..79da21bb9e6 100644
--- a/chromium/content/browser/appcache/appcache_storage.h
+++ b/chromium/content/browser/appcache/appcache_storage.h
@@ -176,17 +176,18 @@ class CONTENT_EXPORT AppCacheStorage {
}
// Creates a reader to read a response from storage.
- virtual AppCacheResponseReader* CreateResponseReader(const GURL& manifest_url,
- int64_t response_id) = 0;
+ virtual std::unique_ptr<AppCacheResponseReader> CreateResponseReader(
+ const GURL& manifest_url,
+ int64_t response_id) = 0;
// Creates a writer to write a new response to storage. This call
// establishes a new response id.
- virtual AppCacheResponseWriter* CreateResponseWriter(
+ virtual std::unique_ptr<AppCacheResponseWriter> CreateResponseWriter(
const GURL& manifest_url) = 0;
// Creates a metadata writer to write metadata of response to storage.
- virtual AppCacheResponseMetadataWriter* CreateResponseMetadataWriter(
- int64_t response_id) = 0;
+ virtual std::unique_ptr<AppCacheResponseMetadataWriter>
+ CreateResponseMetadataWriter(int64_t response_id) = 0;
// Schedules the lazy deletion of responses and saves the ids
// persistently such that the responses will be deleted upon restart
diff --git a/chromium/content/browser/appcache/appcache_storage_impl.cc b/chromium/content/browser/appcache/appcache_storage_impl.cc
index 7ca367b82d4..35e3764b735 100644
--- a/chromium/content/browser/appcache/appcache_storage_impl.cc
+++ b/chromium/content/browser/appcache/appcache_storage_impl.cc
@@ -14,13 +14,11 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
-#include "base/command_line.h"
#include "base/files/file_util.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/single_thread_task_runner.h"
#include "base/stl_util.h"
-#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/trace_event/trace_event.h"
@@ -32,7 +30,6 @@
#include "content/browser/appcache/appcache_quota_client.h"
#include "content/browser/appcache/appcache_response.h"
#include "content/browser/appcache/appcache_service_impl.h"
-#include "content/public/common/content_switches.h"
#include "net/base/cache_type.h"
#include "net/base/net_errors.h"
#include "sql/database.h"
@@ -46,13 +43,11 @@ namespace content {
namespace {
-constexpr const int kMB = 1024 * 1024;
-
// Hard coded default when not using quota management.
-constexpr const int kDefaultQuota = 5 * kMB;
+constexpr const int kDefaultQuota = 5 * 1024 * 1024;
-constexpr const int kMaxAppCacheDiskCacheSize = 250 * kMB;
-constexpr const int kMaxAppCacheMemDiskCacheSize = 10 * kMB;
+constexpr const int kMaxAppCacheDiskCacheSize = 250 * 1024 * 1024;
+constexpr const int kMaxAppCacheMemDiskCacheSize = 10 * 1024 * 1024;
constexpr base::FilePath::CharType kDiskCacheDirectoryName[] =
FILE_PATH_LITERAL("Cache");
@@ -620,22 +615,14 @@ class AppCacheStorageImpl::StoreGroupAndCacheTask : public StoreOrLoadTask {
bool would_exceed_quota_;
int64_t space_available_;
int64_t new_origin_usage_;
- int64_t max_appcache_origin_cache_size_;
std::vector<int64_t> newly_deletable_response_ids_;
};
AppCacheStorageImpl::StoreGroupAndCacheTask::StoreGroupAndCacheTask(
- AppCacheStorageImpl* storage,
- AppCacheGroup* group,
- AppCache* newest_cache)
- : StoreOrLoadTask(storage),
- group_(group),
- cache_(newest_cache),
- success_(false),
- would_exceed_quota_(false),
- space_available_(-1),
- new_origin_usage_(-1),
- max_appcache_origin_cache_size_(kDefaultQuota) {
+ AppCacheStorageImpl* storage, AppCacheGroup* group, AppCache* newest_cache)
+ : StoreOrLoadTask(storage), group_(group), cache_(newest_cache),
+ success_(false), would_exceed_quota_(false),
+ space_available_(-1), new_origin_usage_(-1) {
group_record_.group_id = group->group_id();
group_record_.manifest_url = group->manifest_url();
group_record_.origin = url::Origin::Create(group_record_.manifest_url);
@@ -649,15 +636,6 @@ AppCacheStorageImpl::StoreGroupAndCacheTask::StoreGroupAndCacheTask(
&intercept_namespace_records_,
&fallback_namespace_records_,
&online_whitelist_records_);
-
- base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess();
- if (command_line.HasSwitch(switches::kMaxAppCacheOriginCacheSizeMb)) {
- if (base::StringToInt64(command_line.GetSwitchValueASCII(
- switches::kMaxAppCacheOriginCacheSizeMb),
- &max_appcache_origin_cache_size_)) {
- max_appcache_origin_cache_size_ *= kMB;
- }
- }
}
void AppCacheStorageImpl::StoreGroupAndCacheTask::GetQuotaThenSchedule() {
@@ -684,7 +662,7 @@ void AppCacheStorageImpl::StoreGroupAndCacheTask::GetQuotaThenSchedule() {
// We have to ask the quota manager for the value.
storage_->pending_quota_queries_.insert(this);
quota_manager->GetUsageAndQuota(
- group_record_.origin.GetURL(), blink::mojom::StorageType::kTemporary,
+ group_record_.origin, blink::mojom::StorageType::kTemporary,
base::BindOnce(&StoreGroupAndCacheTask::OnQuotaCallback, this));
}
@@ -779,10 +757,9 @@ void AppCacheStorageImpl::StoreGroupAndCacheTask::Run() {
return;
}
- // Use a user defined value or a simple hard-coded value when not using quota
- // management.
+ // Use a simple hard-coded value when not using quota management.
if (space_available_ == -1) {
- if (new_origin_usage_ > max_appcache_origin_cache_size_) {
+ if (new_origin_usage_ > kDefaultQuota) {
would_exceed_quota_ = true;
success_ = false;
return;
@@ -1567,8 +1544,7 @@ void AppCacheStorageImpl::FindResponseForMainRequest(
working_set()->GetGroupsInOrigin(origin);
if (groups_in_use) {
if (!preferred_manifest_url.is_empty()) {
- AppCacheWorkingSet::GroupMap::const_iterator found =
- groups_in_use->find(preferred_manifest_url);
+ auto found = groups_in_use->find(preferred_manifest_url);
if (found != groups_in_use->end() &&
FindResponseForMainRequestInGroup(
found->second, *url_ptr, delegate)) {
@@ -1710,23 +1686,26 @@ void AppCacheStorageImpl::StoreEvictionTimes(AppCacheGroup* group) {
task->Schedule();
}
-AppCacheResponseReader* AppCacheStorageImpl::CreateResponseReader(
- const GURL& manifest_url,
- int64_t response_id) {
- return new AppCacheResponseReader(
- response_id, is_disabled_ ? nullptr : disk_cache()->GetWeakPtr());
+std::unique_ptr<AppCacheResponseReader>
+AppCacheStorageImpl::CreateResponseReader(const GURL& manifest_url,
+ int64_t response_id) {
+ // base::WrapUnique needed due to non-public constructor.
+ return base::WrapUnique(new AppCacheResponseReader(
+ response_id, is_disabled_ ? nullptr : disk_cache()->GetWeakPtr()));
}
-AppCacheResponseWriter* AppCacheStorageImpl::CreateResponseWriter(
- const GURL& manifest_url) {
- return new AppCacheResponseWriter(
- NewResponseId(), is_disabled_ ? nullptr : disk_cache()->GetWeakPtr());
+std::unique_ptr<AppCacheResponseWriter>
+AppCacheStorageImpl::CreateResponseWriter(const GURL& manifest_url) {
+ // base::WrapUnique needed due to non-public constructor.
+ return base::WrapUnique(new AppCacheResponseWriter(
+ NewResponseId(), is_disabled_ ? nullptr : disk_cache()->GetWeakPtr()));
}
-AppCacheResponseMetadataWriter*
+std::unique_ptr<AppCacheResponseMetadataWriter>
AppCacheStorageImpl::CreateResponseMetadataWriter(int64_t response_id) {
- return new AppCacheResponseMetadataWriter(
- response_id, is_disabled_ ? nullptr : disk_cache()->GetWeakPtr());
+ // base::WrapUnique needed due to non-public constructor.
+ return base::WrapUnique(new AppCacheResponseMetadataWriter(
+ response_id, is_disabled_ ? nullptr : disk_cache()->GetWeakPtr()));
}
void AppCacheStorageImpl::DoomResponses(
@@ -1843,7 +1822,7 @@ void AppCacheStorageImpl::OnDeletedOneResponse(int rv) {
AppCacheStorageImpl::CacheLoadTask*
AppCacheStorageImpl::GetPendingCacheLoadTask(int64_t cache_id) {
- PendingCacheLoads::iterator found = pending_cache_loads_.find(cache_id);
+ auto found = pending_cache_loads_.find(cache_id);
if (found != pending_cache_loads_.end())
return found->second;
return nullptr;
@@ -1851,7 +1830,7 @@ AppCacheStorageImpl::GetPendingCacheLoadTask(int64_t cache_id) {
AppCacheStorageImpl::GroupLoadTask*
AppCacheStorageImpl::GetPendingGroupLoadTask(const GURL& manifest_url) {
- PendingGroupLoads::iterator found = pending_group_loads_.find(manifest_url);
+ auto found = pending_group_loads_.find(manifest_url);
if (found != pending_group_loads_.end())
return found->second;
return nullptr;
@@ -1895,21 +1874,9 @@ AppCacheDiskCache* AppCacheStorageImpl::disk_cache() {
base::Unretained(this)));
} else {
expecting_cleanup_complete_on_disable_ = true;
-
- const base::CommandLine& command_line =
- *base::CommandLine::ForCurrentProcess();
- unsigned int max_appcache_disk_cache_size = kMaxAppCacheDiskCacheSize;
- if (command_line.HasSwitch(switches::kMaxAppCacheDiskCacheSizeMb)) {
- if (base::StringToUint(command_line.GetSwitchValueASCII(
- switches::kMaxAppCacheDiskCacheSizeMb),
- &max_appcache_disk_cache_size)) {
- max_appcache_disk_cache_size *= kMB;
- }
- }
-
rv = disk_cache_->InitWithDiskBackend(
cache_directory_.Append(kDiskCacheDirectoryName),
- max_appcache_disk_cache_size, false,
+ kMaxAppCacheDiskCacheSize, false,
base::BindOnce(&AppCacheStorageImpl::OnDiskCacheCleanupComplete,
weak_factory_.GetWeakPtr()),
base::Bind(&AppCacheStorageImpl::OnDiskCacheInitialized,
diff --git a/chromium/content/browser/appcache/appcache_storage_impl.h b/chromium/content/browser/appcache/appcache_storage_impl.h
index 51b0bb1c093..c7b389b1932 100644
--- a/chromium/content/browser/appcache/appcache_storage_impl.h
+++ b/chromium/content/browser/appcache/appcache_storage_impl.h
@@ -8,6 +8,7 @@
#include <stdint.h>
#include <map>
+#include <memory>
#include <set>
#include <utility>
#include <vector>
@@ -63,11 +64,12 @@ class AppCacheStorageImpl : public AppCacheStorage {
Delegate* delegate,
int response_code) override;
void StoreEvictionTimes(AppCacheGroup* group) override;
- AppCacheResponseReader* CreateResponseReader(const GURL& manifest_url,
- int64_t response_id) override;
- AppCacheResponseWriter* CreateResponseWriter(
+ std::unique_ptr<AppCacheResponseReader> CreateResponseReader(
+ const GURL& manifest_url,
+ int64_t response_id) override;
+ std::unique_ptr<AppCacheResponseWriter> CreateResponseWriter(
const GURL& manifest_url) override;
- AppCacheResponseMetadataWriter* CreateResponseMetadataWriter(
+ std::unique_ptr<AppCacheResponseMetadataWriter> CreateResponseMetadataWriter(
int64_t response_id) override;
void DoomResponses(const GURL& manifest_url,
const std::vector<int64_t>& response_ids) override;
diff --git a/chromium/content/browser/appcache/appcache_storage_impl_unittest.cc b/chromium/content/browser/appcache/appcache_storage_impl_unittest.cc
index 03237c227d3..8fe734648c3 100644
--- a/chromium/content/browser/appcache/appcache_storage_impl_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_storage_impl_unittest.cc
@@ -254,7 +254,7 @@ class AppCacheStorageImplTest : public testing::Test {
storage::GetQuotaSettingsFunc()),
async_(false) {}
- void GetUsageAndQuota(const GURL& origin,
+ void GetUsageAndQuota(const url::Origin& /* origin */,
StorageType type,
UsageAndQuotaCallback callback) override {
EXPECT_EQ(StorageType::kTemporary, type);
diff --git a/chromium/content/browser/appcache/appcache_update_job.cc b/chromium/content/browser/appcache/appcache_update_job.cc
index 32be530befe..46f01ad46d2 100644
--- a/chromium/content/browser/appcache/appcache_update_job.cc
+++ b/chromium/content/browser/appcache/appcache_update_job.cc
@@ -271,8 +271,9 @@ void AppCacheUpdateJob::StartUpdate(AppCacheHost* host,
weak_factory_.GetWeakPtr(), true));
}
-AppCacheResponseWriter* AppCacheUpdateJob::CreateResponseWriter() {
- AppCacheResponseWriter* writer =
+std::unique_ptr<AppCacheResponseWriter>
+AppCacheUpdateJob::CreateResponseWriter() {
+ std::unique_ptr<AppCacheResponseWriter> writer =
storage_->CreateResponseWriter(manifest_url_);
stored_response_ids_.push_back(writer->response_id());
return writer;
@@ -598,7 +599,7 @@ void AppCacheUpdateJob::HandleMasterEntryFetchCompleted(URLFetcher* fetcher,
int response_code = net_error == net::OK ? request->GetResponseCode() : -1;
- PendingMasters::iterator found = pending_master_entries_.find(url);
+ auto found = pending_master_entries_.find(url);
DCHECK(found != pending_master_entries_.end());
PendingHosts& hosts = found->second;
@@ -687,7 +688,7 @@ void AppCacheUpdateJob::HandleManifestRefetchCompleted(URLFetcher* fetcher,
entry->add_types(AppCacheEntry::MANIFEST);
StoreGroupAndCache();
} else {
- manifest_response_writer_.reset(CreateResponseWriter());
+ manifest_response_writer_ = CreateResponseWriter();
scoped_refptr<HttpResponseInfoIOBuffer> io_buffer =
base::MakeRefCounted<HttpResponseInfoIOBuffer>(
std::move(manifest_response_info_));
@@ -721,8 +722,8 @@ void AppCacheUpdateJob::HandleManifestRefetchCompleted(URLFetcher* fetcher,
void AppCacheUpdateJob::OnManifestInfoWriteComplete(int result) {
if (result > 0) {
- scoped_refptr<net::StringIOBuffer> io_buffer(
- new net::StringIOBuffer(manifest_data_));
+ scoped_refptr<net::StringIOBuffer> io_buffer =
+ base::MakeRefCounted<net::StringIOBuffer>(manifest_data_);
manifest_response_writer_->WriteData(
io_buffer.get(), manifest_data_.length(),
base::BindOnce(&AppCacheUpdateJob::OnManifestDataWriteComplete,
@@ -860,11 +861,10 @@ void AppCacheUpdateJob::AddAllAssociatedHostsToNotifier(
void AppCacheUpdateJob::OnDestructionImminent(AppCacheHost* host) {
// The host is about to be deleted; remove from our collection.
- PendingMasters::iterator found =
- pending_master_entries_.find(host->pending_master_entry_url());
+ auto found = pending_master_entries_.find(host->pending_master_entry_url());
CHECK(found != pending_master_entries_.end());
PendingHosts& hosts = found->second;
- PendingHosts::iterator it = std::find(hosts.begin(), hosts.end(), host);
+ auto it = std::find(hosts.begin(), hosts.end(), host);
CHECK(it != hosts.end());
hosts.erase(it);
}
@@ -901,10 +901,10 @@ void AppCacheUpdateJob::CheckIfManifestChanged() {
}
// Load manifest data from storage to compare against fetched manifest.
- manifest_response_reader_.reset(
- storage_->CreateResponseReader(manifest_url_,
- entry->response_id()));
- read_manifest_buffer_ = new net::IOBuffer(kAppCacheFetchBufferSize);
+ manifest_response_reader_ =
+ storage_->CreateResponseReader(manifest_url_, entry->response_id());
+ read_manifest_buffer_ =
+ base::MakeRefCounted<net::IOBuffer>(kAppCacheFetchBufferSize);
manifest_response_reader_->ReadData(
read_manifest_buffer_.get(), kAppCacheFetchBufferSize,
base::BindOnce(&AppCacheUpdateJob::OnManifestDataReadComplete,
@@ -967,7 +967,7 @@ void AppCacheUpdateJob::FetchUrls() {
UrlToFetch url_to_fetch = urls_to_fetch_.front();
urls_to_fetch_.pop_front();
- AppCache::EntryMap::iterator it = url_file_list_.find(url_to_fetch.url);
+ auto it = url_file_list_.find(url_to_fetch.url);
DCHECK(it != url_file_list_.end());
AppCacheEntry& entry = it->second;
if (ShouldSkipUrlFetch(entry)) {
@@ -1093,7 +1093,7 @@ void AppCacheUpdateJob::FetchMasterEntries() {
// TODO(michaeln): defer until the updated cache has been stored.
DCHECK(!inprogress_cache_.get());
AppCache* cache = group_->newest_complete_cache();
- PendingMasters::iterator found = pending_master_entries_.find(url);
+ auto found = pending_master_entries_.find(url);
DCHECK(found != pending_master_entries_.end());
PendingHosts& hosts = found->second;
for (AppCacheHost* host : hosts)
@@ -1132,7 +1132,7 @@ void AppCacheUpdateJob::CancelAllMasterEntryFetches(
HostNotifier host_notifier;
while (!master_entries_to_fetch_.empty()) {
const GURL& url = *master_entries_to_fetch_.begin();
- PendingMasters::iterator found = pending_master_entries_.find(url);
+ auto found = pending_master_entries_.find(url);
DCHECK(found != pending_master_entries_.end());
PendingHosts& hosts = found->second;
for (AppCacheHost* host : hosts) {
@@ -1180,7 +1180,7 @@ void AppCacheUpdateJob::OnResponseInfoLoaded(
return;
}
- LoadingResponses::iterator found = loading_responses_.find(response_id);
+ auto found = loading_responses_.find(response_id);
DCHECK(found != loading_responses_.end());
const GURL& url = found->second;
@@ -1194,7 +1194,7 @@ void AppCacheUpdateJob::OnResponseInfoLoaded(
DCHECK(copy_me);
DCHECK_EQ(copy_me->response_id(), response_id);
- AppCache::EntryMap::iterator it = url_file_list_.find(url);
+ auto it = url_file_list_.find(url);
DCHECK(it != url_file_list_.end());
AppCacheEntry& entry = it->second;
entry.set_response_id(response_id);
diff --git a/chromium/content/browser/appcache/appcache_update_job.h b/chromium/content/browser/appcache/appcache_update_job.h
index 79eabef47b1..5a5f05c4860 100644
--- a/chromium/content/browser/appcache/appcache_update_job.h
+++ b/chromium/content/browser/appcache/appcache_update_job.h
@@ -9,6 +9,7 @@
#include <stdint.h>
#include <map>
+#include <memory>
#include <set>
#include <string>
#include <vector>
@@ -116,7 +117,7 @@ class CONTENT_EXPORT AppCacheUpdateJob
scoped_refptr<AppCacheResponseInfo> existing_response_info;
};
- AppCacheResponseWriter* CreateResponseWriter();
+ std::unique_ptr<AppCacheResponseWriter> CreateResponseWriter();
// Methods for AppCacheStorage::Delegate.
void OnResponseInfoLoaded(AppCacheResponseInfo* response_info,
diff --git a/chromium/content/browser/appcache/appcache_update_job_unittest.cc b/chromium/content/browser/appcache/appcache_update_job_unittest.cc
index 6cb4ce06c35..53aecac2c24 100644
--- a/chromium/content/browser/appcache/appcache_update_job_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_update_job_unittest.cc
@@ -20,6 +20,7 @@
#include "base/stl_util.h"
#include "base/strings/stringprintf.h"
#include "base/synchronization/waitable_event.h"
+#include "base/task/post_task.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/scoped_task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -29,6 +30,7 @@
#include "content/browser/appcache/appcache_update_url_loader_request.h"
#include "content/browser/appcache/mock_appcache_service.h"
#include "content/browser/url_loader_factory_getter.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/system/data_pipe.h"
@@ -705,15 +707,15 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
tested_manifest_path_override_(nullptr),
request_handler_type_(GetParam()),
thread_bundle_(content::TestBrowserThreadBundle::REAL_IO_THREAD) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&IOThread::Init, base::Unretained(io_thread_.get())));
if (request_handler_type_ == URLLOADER) {
loader_factory_getter_ = new URLLoaderFactoryGetter();
feature_list_.InitAndEnableFeature(network::features::kNetworkService);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&AppCacheUpdateJobTest::InitializeFactory,
base::Unretained(this)));
}
@@ -724,8 +726,8 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
// The TestBrowserThreadBundle dtor guarantees that all posted tasks are
// executed before the IO thread shuts down. It is safe to use the
// Unretained pointer here.
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&IOThread::CleanUp, base::Unretained(io_thread_.get())));
}
@@ -737,8 +739,8 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
base::WaitableEvent::ResetPolicy::AUTOMATIC,
base::WaitableEvent::InitialState::NOT_SIGNALED));
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::BindOnce(method, base::Unretained(this)));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(method, base::Unretained(this)));
// Wait until task is done before exiting the test.
event_->Wait();
@@ -752,7 +754,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
}
void StartCacheAttemptTest() {
- ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
+ ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
MakeService();
group_ = new AppCacheGroup(service_->storage(), GURL("http://failme"),
@@ -787,7 +789,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
}
void StartUpgradeAttemptTest() {
- ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
+ ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
{
MakeService();
@@ -853,7 +855,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
}
void CacheAttemptFetchManifestFailTest() {
- ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
+ ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
MakeService();
group_ = new AppCacheGroup(service_->storage(), GURL("http://failme"),
@@ -877,7 +879,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
}
void UpgradeFetchManifestFailTest() {
- ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
+ ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
MakeService();
group_ = new AppCacheGroup(service_->storage(),
@@ -918,7 +920,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
}
void ManifestRedirectTest() {
- ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
+ ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
if (request_handler_type_ == URLREQUEST) {
net::URLRequestJobFactoryImpl* new_factory(
@@ -950,7 +952,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
}
void ManifestMissingMimeTypeTest() {
- ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
+ ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
MakeService();
group_ = new AppCacheGroup(
@@ -990,7 +992,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
}
void ManifestNotFoundTest() {
- ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
+ ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
MakeService();
group_ = new AppCacheGroup(
@@ -1026,7 +1028,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
}
void ManifestGoneTest() {
- ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
+ ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
MakeService();
group_ = new AppCacheGroup(
@@ -1051,7 +1053,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
}
void CacheAttemptNotModifiedTest() {
- ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
+ ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
MakeService();
group_ = new AppCacheGroup(
@@ -1076,7 +1078,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
}
void UpgradeNotModifiedTest() {
- ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
+ ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
MakeService();
group_ = new AppCacheGroup(
@@ -1120,7 +1122,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
}
void UpgradeManifestDataUnchangedTest() {
- ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
+ ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
MakeService();
group_ = new AppCacheGroup(
@@ -1131,8 +1133,8 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
group_->update_job_ = update;
// Create response writer to get a response id.
- response_writer_.reset(
- service_->storage()->CreateResponseWriter(group_->manifest_url()));
+ response_writer_ =
+ service_->storage()->CreateResponseWriter(group_->manifest_url());
AppCache* cache = MakeCacheForGroup(1, response_writer_->response_id());
MockFrontend* frontend1 = MakeMockFrontend();
@@ -1158,8 +1160,8 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
// Seed storage with expected manifest data.
const std::string seed_data(kManifest1Contents);
- scoped_refptr<net::StringIOBuffer> io_buffer(
- new net::StringIOBuffer(seed_data));
+ scoped_refptr<net::StringIOBuffer> io_buffer =
+ base::MakeRefCounted<net::StringIOBuffer>(seed_data);
response_writer_->WriteData(
io_buffer.get(), seed_data.length(),
base::BindOnce(
@@ -1171,7 +1173,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
// See http://code.google.com/p/chromium/issues/detail?id=95101
void Bug95101Test() {
- ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
+ ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
MakeService();
group_ = new AppCacheGroup(
@@ -1215,7 +1217,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
}
void BasicCacheAttemptSuccessTest() {
- ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
+ ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
GURL manifest_url = MockHttpServer::GetMockUrl("files/manifest1");
@@ -1246,7 +1248,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
void DownloadInterceptEntriesTest() {
// Ensures we download intercept entries too.
- ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
+ ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
GURL manifest_url =
MockHttpServer::GetMockUrl("files/manifest-with-intercept");
MakeService();
@@ -1273,7 +1275,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
}
void BasicUpgradeSuccessTest() {
- ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
+ ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
MakeService();
group_ = new AppCacheGroup(
@@ -1284,8 +1286,8 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
group_->update_job_ = update;
// Create a response writer to get a response id.
- response_writer_.reset(
- service_->storage()->CreateResponseWriter(group_->manifest_url()));
+ response_writer_ =
+ service_->storage()->CreateResponseWriter(group_->manifest_url());
AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(),
response_writer_->response_id());
@@ -1330,8 +1332,8 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
// Seed storage with expected manifest data different from manifest1.
const std::string seed_data("different");
- scoped_refptr<net::StringIOBuffer> io_buffer(
- new net::StringIOBuffer(seed_data));
+ scoped_refptr<net::StringIOBuffer> io_buffer =
+ base::MakeRefCounted<net::StringIOBuffer>(seed_data);
response_writer_->WriteData(
io_buffer.get(), seed_data.length(),
base::BindOnce(
@@ -1342,7 +1344,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
}
void UpgradeLoadFromNewestCacheTest() {
- ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
+ ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
MakeService();
group_ = new AppCacheGroup(
@@ -1358,8 +1360,8 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
host->AssociateCompleteCache(cache);
// Give the newest cache an entry that is in storage.
- response_writer_.reset(
- service_->storage()->CreateResponseWriter(group_->manifest_url()));
+ response_writer_ =
+ service_->storage()->CreateResponseWriter(group_->manifest_url());
cache->AddEntry(MockHttpServer::GetMockUrl("files/explicit1"),
AppCacheEntry(AppCacheEntry::EXPLICIT,
response_writer_->response_id()));
@@ -1410,7 +1412,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
}
void UpgradeNoLoadFromNewestCacheTest() {
- ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
+ ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
MakeService();
group_ = new AppCacheGroup(
@@ -1426,8 +1428,8 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
host->AssociateCompleteCache(cache);
// Give the newest cache an entry that is in storage.
- response_writer_.reset(
- service_->storage()->CreateResponseWriter(group_->manifest_url()));
+ response_writer_ =
+ service_->storage()->CreateResponseWriter(group_->manifest_url());
cache->AddEntry(MockHttpServer::GetMockUrl("files/explicit1"),
AppCacheEntry(AppCacheEntry::EXPLICIT,
response_writer_->response_id()));
@@ -1476,7 +1478,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
}
void UpgradeLoadFromNewestCacheVaryHeaderTest() {
- ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
+ ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
MakeService();
group_ = new AppCacheGroup(
@@ -1492,8 +1494,8 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
host->AssociateCompleteCache(cache);
// Give the newest cache an entry that is in storage.
- response_writer_.reset(
- service_->storage()->CreateResponseWriter(group_->manifest_url()));
+ response_writer_ =
+ service_->storage()->CreateResponseWriter(group_->manifest_url());
cache->AddEntry(MockHttpServer::GetMockUrl("files/explicit1"),
AppCacheEntry(AppCacheEntry::EXPLICIT,
response_writer_->response_id()));
@@ -1542,7 +1544,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
}
void UpgradeLoadFromNewestCacheReuseVaryHeaderTest() {
- ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
+ ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
MakeService();
group_ = new AppCacheGroup(service_->storage(),
@@ -1558,8 +1560,8 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
host->AssociateCompleteCache(cache);
// Give the newest cache an entry that is in storage.
- response_writer_.reset(
- service_->storage()->CreateResponseWriter(group_->manifest_url()));
+ response_writer_ =
+ service_->storage()->CreateResponseWriter(group_->manifest_url());
cache->AddEntry(MockHttpServer::GetMockUrl("files/explicit1"),
AppCacheEntry(AppCacheEntry::EXPLICIT,
response_writer_->response_id()));
@@ -1612,7 +1614,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
}
void UpgradeSuccessMergedTypesTest() {
- ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
+ ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
MakeService();
group_ = new AppCacheGroup(service_->storage(),
@@ -1670,7 +1672,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
}
void CacheAttemptFailUrlFetchTest() {
- ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
+ ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
MakeService();
group_ = new AppCacheGroup(service_->storage(),
@@ -1695,7 +1697,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
}
void UpgradeFailUrlFetchTest() {
- ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
+ ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
MakeService();
group_ = new AppCacheGroup(service_->storage(),
@@ -1740,7 +1742,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
}
void UpgradeFailMasterUrlFetchTest() {
- ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
+ ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
tested_manifest_path_override_ = "files/manifest1-with-notmodified";
@@ -1853,7 +1855,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
}
void EmptyManifestTest() {
- ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
+ ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
MakeService();
group_ = new AppCacheGroup(
@@ -1902,7 +1904,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
}
void EmptyFileTest() {
- ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
+ ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
MakeService();
group_ = new AppCacheGroup(service_->storage(),
@@ -1939,7 +1941,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
}
void RetryRequestTest() {
- ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
+ ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
// Set some large number of times to return retry.
// Expect 1 manifest fetch and 3 retries.
@@ -1976,7 +1978,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
}
void RetryNoRetryAfterTest() {
- ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
+ ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
// Set some large number of times to return retry.
// Expect 1 manifest fetch and 0 retries.
@@ -2013,7 +2015,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
}
void RetryNonzeroRetryAfterTest() {
- ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
+ ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
// Set some large number of times to return retry.
// Expect 1 request and 0 retry attempts.
@@ -2051,7 +2053,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
}
void RetrySuccessTest() {
- ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
+ ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
// Set 2 as the retry limit (does not exceed the max).
// Expect 1 manifest fetch, 2 retries, 1 url fetch, 1 manifest refetch.
@@ -2088,7 +2090,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
}
void RetryUrlTest() {
- ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
+ ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
// Set 1 as the retry limit (does not exceed the max).
// Expect 1 manifest fetch, 1 url fetch, 1 url retry, 1 manifest refetch.
@@ -2125,7 +2127,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
}
void FailStoreNewestCacheTest() {
- ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
+ ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
MakeService();
MockAppCacheStorage* storage =
@@ -2154,7 +2156,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
}
void UpgradeFailStoreNewestCacheTest() {
- ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
+ ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
MakeService();
MockAppCacheStorage* storage =
@@ -2202,7 +2204,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
}
void MasterEntryFailStoreNewestCacheTest() {
- ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
+ ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
MakeService();
MockAppCacheStorage* storage =
@@ -2252,7 +2254,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
}
void UpgradeFailMakeGroupObsoleteTest() {
- ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
+ ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
MakeService();
MockAppCacheStorage* storage =
@@ -2292,7 +2294,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
}
void MasterEntryFetchManifestFailTest() {
- ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
+ ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
MakeService();
group_ = new AppCacheGroup(service_->storage(), GURL("http://failme"), 111);
@@ -2317,7 +2319,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
}
void MasterEntryBadManifestTest() {
- ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
+ ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
MakeService();
group_ = new AppCacheGroup(service_->storage(),
@@ -2343,7 +2345,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
}
void MasterEntryManifestNotFoundTest() {
- ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
+ ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
MakeService();
group_ = new AppCacheGroup(
@@ -2372,7 +2374,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
}
void MasterEntryFailUrlFetchTest() {
- ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
+ ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
MakeService();
group_ = new AppCacheGroup(service_->storage(),
@@ -2403,7 +2405,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
}
void MasterEntryAllFailTest() {
- ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
+ ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
MakeService();
group_ = new AppCacheGroup(
@@ -2447,7 +2449,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
}
void UpgradeMasterEntryAllFailTest() {
- ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
+ ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
MakeService();
group_ = new AppCacheGroup(
@@ -2507,7 +2509,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
}
void MasterEntrySomeFailTest() {
- ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
+ ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
MakeService();
group_ = new AppCacheGroup(
@@ -2558,7 +2560,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
}
void UpgradeMasterEntrySomeFailTest() {
- ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
+ ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
MakeService();
group_ = new AppCacheGroup(
@@ -2625,7 +2627,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
}
void MasterEntryNoUpdateTest() {
- ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
+ ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
MakeService();
group_ = new AppCacheGroup(service_->storage(),
@@ -2681,7 +2683,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
}
void StartUpdateMidCacheAttemptTest() {
- ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
+ ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
MakeService();
group_ = new AppCacheGroup(
@@ -2776,7 +2778,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
}
void StartUpdateMidNoUpdateTest() {
- ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
+ ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
MakeService();
group_ = new AppCacheGroup(
@@ -2861,7 +2863,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
}
void StartUpdateMidDownloadTest() {
- ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
+ ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
MakeService();
group_ = new AppCacheGroup(
@@ -2960,7 +2962,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
}
void QueueMasterEntryTest() {
- ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
+ ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
MakeService();
group_ = new AppCacheGroup(
@@ -3018,7 +3020,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
}
void IfModifiedSinceTestCache() {
- ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
+ ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
if (request_handler_type_ == URLREQUEST) {
net::URLRequestJobFactoryImpl* new_factory(
@@ -3059,7 +3061,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
}
void IfModifiedTestRefetch() {
- ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
+ ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
if (request_handler_type_ == URLREQUEST) {
net::URLRequestJobFactoryImpl* new_factory(
@@ -3110,7 +3112,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
}
void IfModifiedTestLastModified() {
- ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
+ ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
if (request_handler_type_ == URLREQUEST) {
net::URLRequestJobFactoryImpl* new_factory(
@@ -3162,7 +3164,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
}
void IfModifiedSinceUpgradeTest() {
- ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
+ ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
HttpHeadersRequestTestJob::Initialize("Sat, 29 Oct 1994 19:43:31 GMT",
std::string());
@@ -3185,8 +3187,8 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
group_->update_job_ = update;
// Give the newest cache a manifest enry that is in storage.
- response_writer_.reset(
- service_->storage()->CreateResponseWriter(group_->manifest_url()));
+ response_writer_ =
+ service_->storage()->CreateResponseWriter(group_->manifest_url());
AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(),
response_writer_->response_id());
@@ -3236,7 +3238,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
}
void IfNoneMatchUpgradeTest() {
- ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
+ ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
HttpHeadersRequestTestJob::Initialize(std::string(), "\"LadeDade\"");
@@ -3258,8 +3260,8 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
group_->update_job_ = update;
// Give the newest cache a manifest enry that is in storage.
- response_writer_.reset(
- service_->storage()->CreateResponseWriter(group_->manifest_url()));
+ response_writer_ =
+ service_->storage()->CreateResponseWriter(group_->manifest_url());
AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(),
response_writer_->response_id());
@@ -3309,7 +3311,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
}
void IfNoneMatchRefetchTest() {
- ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
+ ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
HttpHeadersRequestTestJob::Initialize(std::string(), "\"LadeDade\"");
@@ -3360,7 +3362,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
}
void MultipleHeadersRefetchTest() {
- ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
+ ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
// Verify that code is correct when building multiple extra headers.
HttpHeadersRequestTestJob::Initialize(
@@ -3414,7 +3416,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
}
void CrossOriginHttpsSuccessTest() {
- ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
+ ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
GURL manifest_url = MockHttpServer::GetMockHttpsUrl(
"files/valid_cross_origin_https_manifest");
@@ -3443,7 +3445,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
}
void CrossOriginHttpsDeniedTest() {
- ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
+ ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
GURL manifest_url = MockHttpServer::GetMockHttpsUrl(
"files/invalid_cross_origin_https_manifest");
@@ -3628,8 +3630,7 @@ class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
// Check that any copied entries have the expected response id
// and that entries that are not copied have a different response id.
- std::map<GURL, int64_t>::iterator found =
- expect_response_ids_.find(pair.first);
+ auto found = expect_response_ids_.find(pair.first);
if (found != expect_response_ids_.end()) {
EXPECT_EQ(found->second, pair.second.response_id());
} else if (expect_old_cache_) {
diff --git a/chromium/content/browser/appcache/appcache_update_url_fetcher.cc b/chromium/content/browser/appcache/appcache_update_url_fetcher.cc
index e9652f899a3..924a76cd237 100644
--- a/chromium/content/browser/appcache/appcache_update_url_fetcher.cc
+++ b/chromium/content/browser/appcache/appcache_update_url_fetcher.cc
@@ -106,7 +106,7 @@ void AppCacheUpdateJob::URLFetcher::OnResponseStarted(int net_error) {
// Write response info to storage for URL fetches. Wait for async write
// completion before reading any response data.
if (fetch_type_ == URL_FETCH || fetch_type_ == MASTER_ENTRY_FETCH) {
- response_writer_.reset(job_->CreateResponseWriter());
+ response_writer_ = job_->CreateResponseWriter();
scoped_refptr<HttpResponseInfoIOBuffer> io_buffer =
base::MakeRefCounted<HttpResponseInfoIOBuffer>(
std::make_unique<net::HttpResponseInfo>(
diff --git a/chromium/content/browser/appcache/appcache_update_url_request.cc b/chromium/content/browser/appcache/appcache_update_url_request.cc
index d2c28d702af..7448503af5b 100644
--- a/chromium/content/browser/appcache/appcache_update_url_request.cc
+++ b/chromium/content/browser/appcache/appcache_update_url_request.cc
@@ -119,7 +119,7 @@ AppCacheUpdateJob::UpdateURLRequest::UpdateURLRequest(
this,
GetTrafficAnnotation())),
fetcher_(fetcher),
- buffer_(new net::IOBuffer(buffer_size)),
+ buffer_(base::MakeRefCounted<net::IOBuffer>(buffer_size)),
buffer_size_(buffer_size),
weak_factory_(this) {}
diff --git a/chromium/content/browser/appcache/appcache_url_loader_job.cc b/chromium/content/browser/appcache/appcache_url_loader_job.cc
index e4245c4861f..43c10be404f 100644
--- a/chromium/content/browser/appcache/appcache_url_loader_job.cc
+++ b/chromium/content/browser/appcache/appcache_url_loader_job.cc
@@ -22,8 +22,8 @@ AppCacheURLLoaderJob::~AppCacheURLLoaderJob() {
}
bool AppCacheURLLoaderJob::IsStarted() const {
- return delivery_type_ != AWAITING_DELIVERY_ORDERS &&
- delivery_type_ != NETWORK_DELIVERY;
+ return delivery_type_ != DeliveryType::kAwaitingDeliverCall &&
+ delivery_type_ != DeliveryType::kNetwork;
}
void AppCacheURLLoaderJob::DeliverAppCachedResponse(const GURL& manifest_url,
@@ -35,7 +35,7 @@ void AppCacheURLLoaderJob::DeliverAppCachedResponse(const GURL& manifest_url,
return;
}
- delivery_type_ = APPCACHED_DELIVERY;
+ delivery_type_ = DeliveryType::kAppCached;
// In tests we only care about the delivery_type_ state.
if (AppCacheRequestHandler::IsRunningInTests())
@@ -57,7 +57,7 @@ void AppCacheURLLoaderJob::DeliverAppCachedResponse(const GURL& manifest_url,
}
void AppCacheURLLoaderJob::DeliverNetworkResponse() {
- delivery_type_ = NETWORK_DELIVERY;
+ delivery_type_ = DeliveryType::kNetwork;
// In tests we only care about the delivery_type_ state.
if (AppCacheRequestHandler::IsRunningInTests())
@@ -71,7 +71,7 @@ void AppCacheURLLoaderJob::DeliverNetworkResponse() {
}
void AppCacheURLLoaderJob::DeliverErrorResponse() {
- delivery_type_ = ERROR_DELIVERY;
+ delivery_type_ = DeliveryType::kError;
// In tests we only care about the delivery_type_ state.
if (AppCacheRequestHandler::IsRunningInTests())
@@ -190,8 +190,8 @@ void AppCacheURLLoaderJob::OnResponseInfoLoaded(
}
info_ = response_info;
- reader_.reset(
- storage_->CreateResponseReader(manifest_url_, entry_.response_id()));
+ reader_ =
+ storage_->CreateResponseReader(manifest_url_, entry_.response_id());
if (is_range_request())
SetupRangeResponse();
@@ -353,7 +353,7 @@ void AppCacheURLLoaderJob::NotifyCompleted(int error_code) {
}
client_->OnComplete(status);
- if (delivery_type_ == APPCACHED_DELIVERY) {
+ if (delivery_type_ == DeliveryType::kAppCached) {
AppCacheHistograms::CountResponseRetrieval(
error_code == 0, is_main_resource_load_,
url::Origin::Create(manifest_url_));
diff --git a/chromium/content/browser/appcache/appcache_url_request_job.cc b/chromium/content/browser/appcache/appcache_url_request_job.cc
index d0c16f3b250..cd1ab22e37f 100644
--- a/chromium/content/browser/appcache/appcache_url_request_job.cc
+++ b/chromium/content/browser/appcache/appcache_url_request_job.cc
@@ -65,7 +65,7 @@ void AppCacheURLRequestJob::DeliverAppCachedResponse(const GURL& manifest_url,
bool is_fallback) {
DCHECK(!has_delivery_orders());
DCHECK(entry.has_response_id());
- delivery_type_ = APPCACHED_DELIVERY;
+ delivery_type_ = DeliveryType::kAppCached;
manifest_url_ = manifest_url;
cache_id_ = cache_id;
entry_ = entry;
@@ -75,14 +75,14 @@ void AppCacheURLRequestJob::DeliverAppCachedResponse(const GURL& manifest_url,
void AppCacheURLRequestJob::DeliverNetworkResponse() {
DCHECK(!has_delivery_orders());
- delivery_type_ = NETWORK_DELIVERY;
+ delivery_type_ = DeliveryType::kNetwork;
storage_ = nullptr; // not needed
MaybeBeginDelivery();
}
void AppCacheURLRequestJob::DeliverErrorResponse() {
DCHECK(!has_delivery_orders());
- delivery_type_ = ERROR_DELIVERY;
+ delivery_type_ = DeliveryType::kError;
storage_ = nullptr; // not needed
MaybeBeginDelivery();
}
@@ -137,7 +137,7 @@ void AppCacheURLRequestJob::BeginDelivery() {
return;
switch (delivery_type_) {
- case NETWORK_DELIVERY:
+ case DeliveryType::kNetwork:
// To fallthru to the network, we restart the request which will
// cause a new job to be created to retrieve the resource from the
// network. Our caller is responsible for arranging to not re-intercept
@@ -145,14 +145,14 @@ void AppCacheURLRequestJob::BeginDelivery() {
NotifyRestartRequired();
break;
- case ERROR_DELIVERY:
+ case DeliveryType::kError:
request()->net_log().AddEvent(
net::NetLogEventType::APPCACHE_DELIVERING_ERROR_RESPONSE);
NotifyStartError(net::URLRequestStatus(net::URLRequestStatus::FAILED,
net::ERR_FAILED));
break;
- case APPCACHED_DELIVERY:
+ case DeliveryType::kAppCached:
request()->net_log().AddEvent(
is_fallback_
? net::NetLogEventType::APPCACHE_DELIVERING_FALLBACK_RESPONSE
@@ -170,7 +170,7 @@ void AppCacheURLRequestJob::BeginErrorDelivery(const char* message) {
if (host_)
host_->frontend()->OnLogMessage(host_->host_id(), APPCACHE_LOG_ERROR,
message);
- delivery_type_ = ERROR_DELIVERY;
+ delivery_type_ = DeliveryType::kError;
storage_ = nullptr;
BeginDelivery();
}
@@ -181,8 +181,8 @@ void AppCacheURLRequestJob::OnResponseInfoLoaded(
DCHECK(IsDeliveringAppCacheResponse());
if (response_info) {
info_ = response_info;
- reader_.reset(
- storage_->CreateResponseReader(manifest_url_, entry_.response_id()));
+ reader_ =
+ storage_->CreateResponseReader(manifest_url_, entry_.response_id());
if (is_range_request())
SetupRangeResponse();
@@ -249,7 +249,7 @@ net::LoadState AppCacheURLRequestJob::GetLoadState() const {
return net::LOAD_STATE_IDLE;
if (!has_delivery_orders())
return net::LOAD_STATE_WAITING_FOR_APPCACHE;
- if (delivery_type_ != APPCACHED_DELIVERY)
+ if (delivery_type_ != DeliveryType::kAppCached)
return net::LOAD_STATE_IDLE;
if (!info_.get())
return net::LOAD_STATE_WAITING_FOR_APPCACHE;
diff --git a/chromium/content/browser/appcache/appcache_url_request_job_unittest.cc b/chromium/content/browser/appcache/appcache_url_request_job_unittest.cc
index 266c8173551..a373b78fac1 100644
--- a/chromium/content/browser/appcache/appcache_url_request_job_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_url_request_job_unittest.cc
@@ -147,7 +147,8 @@ class AppCacheURLRequestJobTest : public testing::Test {
public:
explicit MockURLRequestDelegate(AppCacheURLRequestJobTest* test)
: test_(test),
- received_data_(new net::IOBuffer(kNumBlocks * kBlockSize)),
+ received_data_(
+ base::MakeRefCounted<net::IOBuffer>(kNumBlocks * kBlockSize)),
did_receive_headers_(false),
amount_received_(0),
kill_after_amount_received_(0),
@@ -197,8 +198,9 @@ class AppCacheURLRequestJobTest : public testing::Test {
void ReadSome(net::URLRequest* request) {
DCHECK(amount_received_ + kBlockSize <= kNumBlocks * kBlockSize);
- scoped_refptr<IOBuffer> wrapped_buffer(
- new net::WrappedIOBuffer(received_data_->data() + amount_received_));
+ scoped_refptr<IOBuffer> wrapped_buffer =
+ base::MakeRefCounted<net::WrappedIOBuffer>(received_data_->data() +
+ amount_received_);
EXPECT_EQ(net::ERR_IO_PENDING,
request->Read(wrapped_buffer.get(), kBlockSize));
}
@@ -620,7 +622,7 @@ class AppCacheURLRequestJobTest : public testing::Test {
base::BindOnce(&AppCacheURLRequestJobTest::RequestAppCachedResource,
base::Unretained(this), false));
- writer_.reset(service_->storage()->CreateResponseWriter(GURL()));
+ writer_ = service_->storage()->CreateResponseWriter(GURL());
written_response_id_ = writer_->response_id();
WriteBasicResponse();
// Continues async
@@ -692,7 +694,7 @@ class AppCacheURLRequestJobTest : public testing::Test {
base::BindOnce(&AppCacheURLRequestJobTest::RequestAppCachedResource,
base::Unretained(this), true));
- writer_.reset(service_->storage()->CreateResponseWriter(GURL()));
+ writer_ = service_->storage()->CreateResponseWriter(GURL());
written_response_id_ = writer_->response_id();
WriteLargeResponse();
// Continues async
@@ -702,7 +704,8 @@ class AppCacheURLRequestJobTest : public testing::Test {
// 3, 1k blocks
static const char kHttpHeaders[] =
"HTTP/1.0 200 OK\0Content-Length: 3072\0\0";
- scoped_refptr<IOBuffer> body(new IOBuffer(kBlockSize * 3));
+ scoped_refptr<IOBuffer> body =
+ base::MakeRefCounted<IOBuffer>(kBlockSize * 3);
char* p = body->data();
for (int i = 0; i < 3; ++i, p += kBlockSize)
FillData(i + 1, p, kBlockSize);
@@ -734,7 +737,7 @@ class AppCacheURLRequestJobTest : public testing::Test {
base::Unretained(this)));
PushNextTask(base::BindOnce(&AppCacheURLRequestJobTest::MakeRangeRequest,
base::Unretained(this)));
- writer_.reset(service_->storage()->CreateResponseWriter(GURL()));
+ writer_ = service_->storage()->CreateResponseWriter(GURL());
written_response_id_ = writer_->response_id();
WriteBasicResponse();
// Continues async
@@ -801,7 +804,7 @@ class AppCacheURLRequestJobTest : public testing::Test {
base::BindOnce(&AppCacheURLRequestJobTest::RequestAppCachedResource,
base::Unretained(this), true));
- writer_.reset(service_->storage()->CreateResponseWriter(GURL()));
+ writer_ = service_->storage()->CreateResponseWriter(GURL());
written_response_id_ = writer_->response_id();
WriteLargeResponse();
@@ -829,7 +832,7 @@ class AppCacheURLRequestJobTest : public testing::Test {
base::BindOnce(&AppCacheURLRequestJobTest::RequestAppCachedResource,
base::Unretained(this), true));
- writer_.reset(service_->storage()->CreateResponseWriter(GURL()));
+ writer_ = service_->storage()->CreateResponseWriter(GURL());
written_response_id_ = writer_->response_id();
WriteLargeResponse();
diff --git a/chromium/content/browser/appcache/chrome_appcache_service_unittest.cc b/chromium/content/browser/appcache/chrome_appcache_service_unittest.cc
index 1e5688dadd6..9a28416f758 100644
--- a/chromium/content/browser/appcache/chrome_appcache_service_unittest.cc
+++ b/chromium/content/browser/appcache/chrome_appcache_service_unittest.cc
@@ -11,11 +11,13 @@
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
+#include "base/task/post_task.h"
#include "base/test/scoped_task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/appcache/appcache_database.h"
#include "content/browser/appcache/appcache_storage_impl.h"
#include "content/browser/appcache/chrome_appcache_service.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/resource_context.h"
#include "content/public/test/test_browser_context.h"
@@ -103,8 +105,8 @@ ChromeAppCacheServiceTest::CreateAppCacheServiceImpl(
new MockURLRequestContextGetter(
browser_context_.GetResourceContext()->GetRequestContext(),
base::ThreadTaskRunnerHandle::Get());
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&ChromeAppCacheService::InitializeOnIOThread, appcache_service,
appcache_path, browser_context_.GetResourceContext(),
diff --git a/chromium/content/browser/appcache/mock_appcache_storage.cc b/chromium/content/browser/appcache/mock_appcache_storage.cc
index 79bf39b087e..30d7d9a5a5e 100644
--- a/chromium/content/browser/appcache/mock_appcache_storage.cc
+++ b/chromium/content/browser/appcache/mock_appcache_storage.cc
@@ -46,8 +46,7 @@ MockAppCacheStorage::MockAppCacheStorage(AppCacheServiceImpl* service)
last_response_id_ = 0;
}
-MockAppCacheStorage::~MockAppCacheStorage() {
-}
+MockAppCacheStorage::~MockAppCacheStorage() = default;
void MockAppCacheStorage::GetAllInfo(Delegate* delegate) {
ScheduleTask(base::BindOnce(
@@ -160,24 +159,29 @@ void MockAppCacheStorage::StoreEvictionTimes(AppCacheGroup* group) {
group->first_evictable_error_time());
}
-AppCacheResponseReader* MockAppCacheStorage::CreateResponseReader(
- const GURL& manifest_url,
- int64_t response_id) {
+std::unique_ptr<AppCacheResponseReader>
+MockAppCacheStorage::CreateResponseReader(const GURL& manifest_url,
+ int64_t response_id) {
if (simulated_reader_)
- return simulated_reader_.release();
- return new AppCacheResponseReader(response_id, disk_cache()->GetWeakPtr());
+ return std::move(simulated_reader_);
+
+ // base::WrapUnique needed due to non-public constructor.
+ return base::WrapUnique(
+ new AppCacheResponseReader(response_id, disk_cache()->GetWeakPtr()));
}
-AppCacheResponseWriter* MockAppCacheStorage::CreateResponseWriter(
- const GURL& manifest_url) {
- return new AppCacheResponseWriter(NewResponseId(),
- disk_cache()->GetWeakPtr());
+std::unique_ptr<AppCacheResponseWriter>
+MockAppCacheStorage::CreateResponseWriter(const GURL& manifest_url) {
+ // base::WrapUnique needed due to non-public constructor.
+ return base::WrapUnique(
+ new AppCacheResponseWriter(NewResponseId(), disk_cache()->GetWeakPtr()));
}
-AppCacheResponseMetadataWriter*
+std::unique_ptr<AppCacheResponseMetadataWriter>
MockAppCacheStorage::CreateResponseMetadataWriter(int64_t response_id) {
- return new AppCacheResponseMetadataWriter(response_id,
- disk_cache()->GetWeakPtr());
+ // base::WrapUnique needed due to non-public constructor.
+ return base::WrapUnique(new AppCacheResponseMetadataWriter(
+ response_id, disk_cache()->GetWeakPtr()));
}
void MockAppCacheStorage::DoomResponses(
diff --git a/chromium/content/browser/appcache/mock_appcache_storage.h b/chromium/content/browser/appcache/mock_appcache_storage.h
index 4823ff0523f..0a4fcb75cc1 100644
--- a/chromium/content/browser/appcache/mock_appcache_storage.h
+++ b/chromium/content/browser/appcache/mock_appcache_storage.h
@@ -75,11 +75,12 @@ class MockAppCacheStorage : public AppCacheStorage {
Delegate* delegate,
int response_code) override;
void StoreEvictionTimes(AppCacheGroup* group) override;
- AppCacheResponseReader* CreateResponseReader(const GURL& manifest_url,
- int64_t response_id) override;
- AppCacheResponseWriter* CreateResponseWriter(
+ std::unique_ptr<AppCacheResponseReader> CreateResponseReader(
+ const GURL& manifest_url,
+ int64_t response_id) override;
+ std::unique_ptr<AppCacheResponseWriter> CreateResponseWriter(
const GURL& manifest_url) override;
- AppCacheResponseMetadataWriter* CreateResponseMetadataWriter(
+ std::unique_ptr<AppCacheResponseMetadataWriter> CreateResponseMetadataWriter(
int64_t response_id) override;
void DoomResponses(const GURL& manifest_url,
const std::vector<int64_t>& response_ids) override;
diff --git a/chromium/content/browser/background_fetch/background_fetch.proto b/chromium/content/browser/background_fetch/background_fetch.proto
index d1cef4f3bfd..c88966804ed 100644
--- a/chromium/content/browser/background_fetch/background_fetch.proto
+++ b/chromium/content/browser/background_fetch/background_fetch.proto
@@ -13,8 +13,8 @@ package content.proto;
//
// Next Tag: 9
message BackgroundFetchRegistration {
- enum BackgroundFetchState {
- PENDING = 0; // Default value.
+ enum BackgroundFetchResult {
+ UNSET = 0; // Default value.
FAILURE = 1;
SUCCESS = 2;
}
@@ -41,7 +41,7 @@ message BackgroundFetchRegistration {
optional uint64 uploaded = 4;
optional uint64 download_total = 5;
optional uint64 downloaded = 6;
- optional BackgroundFetchState state = 7;
+ optional BackgroundFetchResult result = 7;
optional BackgroundFetchFailureReason failure_reason = 8;
}
diff --git a/chromium/content/browser/background_fetch/background_fetch_context.cc b/chromium/content/browser/background_fetch/background_fetch_context.cc
index 13f6f472b29..340d9d0eb87 100644
--- a/chromium/content/browser/background_fetch/background_fetch_context.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_context.cc
@@ -7,6 +7,7 @@
#include <utility>
#include "base/bind_helpers.h"
+#include "base/task/post_task.h"
#include "content/browser/background_fetch/background_fetch_data_manager.h"
#include "content/browser/background_fetch/background_fetch_job_controller.h"
#include "content/browser/background_fetch/background_fetch_metrics.h"
@@ -17,6 +18,7 @@
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/public/browser/background_fetch_delegate.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
#include "net/url_request/url_request_context_getter.h"
@@ -25,6 +27,8 @@
namespace content {
+using FailureReason = blink::mojom::BackgroundFetchFailureReason;
+
BackgroundFetchContext::BackgroundFetchContext(
BrowserContext* browser_context,
const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context,
@@ -72,15 +76,16 @@ void BackgroundFetchContext::DidGetInitializationData(
blink::mojom::BackgroundFetchError error,
std::vector<background_fetch::BackgroundFetchInitializationData>
initialization_data) {
- if (error != blink::mojom::BackgroundFetchError::NONE) {
- // TODO(crbug.com/780025): Log failures to UMA.
+ if (error != blink::mojom::BackgroundFetchError::NONE)
return;
- }
+
+ background_fetch::RecordRegistrationsOnStartup(initialization_data.size());
for (auto& data : initialization_data) {
CreateController(data.registration_id, data.registration, data.options,
data.icon, data.ui_title, data.num_completed_requests,
- data.num_requests, std::move(data.active_fetch_requests));
+ data.num_requests, std::move(data.active_fetch_requests),
+ /* start_paused = */ false);
}
}
@@ -133,6 +138,7 @@ void BackgroundFetchContext::StartFetch(
const std::vector<ServiceWorkerFetchRequest>& requests,
const BackgroundFetchOptions& options,
const SkBitmap& icon,
+ blink::mojom::BackgroundFetchUkmDataPtr ukm_data,
RenderFrameHost* render_frame_host,
blink::mojom::BackgroundFetchService::FetchCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -143,23 +149,14 @@ void BackgroundFetchContext::StartFetch(
// operator uses.
DCHECK_EQ(0u, fetch_callbacks_.count(registration_id));
fetch_callbacks_[registration_id] = std::move(callback);
-
- // |data_manager| is guaranteed to outlive |this|. |create_registration| is
- // passed to `DidGetPermission`, which is tied to |weak_factory_|. That means
- // that if |create_registration| runs, |this| is still alive, as is
- // |data_manager| (a pointer owned by |this|).
- auto create_registration = base::BindOnce(
- &BackgroundFetchDataManager::CreateRegistration,
- base::Unretained(data_manager_.get()), registration_id, requests, options,
- icon,
- base::BindOnce(&BackgroundFetchContext::DidCreateRegistration,
- weak_factory_.GetWeakPtr(), registration_id));
+ int frame_tree_node_id =
+ render_frame_host ? render_frame_host->GetFrameTreeNodeId() : 0;
GetPermissionForOrigin(
registration_id.origin(), render_frame_host,
base::BindOnce(&BackgroundFetchContext::DidGetPermission,
- weak_factory_.GetWeakPtr(), std::move(create_registration),
- registration_id));
+ weak_factory_.GetWeakPtr(), registration_id, requests,
+ options, icon, std::move(ukm_data), frame_tree_node_id));
}
void BackgroundFetchContext::GetPermissionForOrigin(
@@ -167,7 +164,6 @@ void BackgroundFetchContext::GetPermissionForOrigin(
RenderFrameHost* render_frame_host,
GetPermissionCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
ResourceRequestInfo::WebContentsGetter wc_getter = base::NullCallback();
// Permissions need to go through the DownloadRequestLimiter if the fetch
@@ -182,11 +178,28 @@ void BackgroundFetchContext::GetPermissionForOrigin(
}
void BackgroundFetchContext::DidGetPermission(
- base::OnceClosure permission_closure,
const BackgroundFetchRegistrationId& registration_id,
- bool has_permission) {
- if (has_permission) {
- std::move(permission_closure).Run();
+ const std::vector<ServiceWorkerFetchRequest>& requests,
+ const BackgroundFetchOptions& options,
+ const SkBitmap& icon,
+ blink::mojom::BackgroundFetchUkmDataPtr ukm_data,
+ int frame_tree_node_id,
+ BackgroundFetchPermission permission) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(&background_fetch::RecordBackgroundFetchUkmEvent,
+ registration_id.origin(), requests, options, icon,
+ std::move(ukm_data), frame_tree_node_id, permission));
+
+ if (permission != BackgroundFetchPermission::BLOCKED) {
+ // TODO(crbug.com/886896): Passed paused flag to CreateRegistration.
+ data_manager_->BackgroundFetchDataManager::CreateRegistration(
+ registration_id, requests, options, icon,
+ permission == BackgroundFetchPermission::ASK /* start_paused */,
+ base::BindOnce(&BackgroundFetchContext::DidCreateRegistration,
+ weak_factory_.GetWeakPtr(), registration_id));
return;
}
@@ -201,7 +214,6 @@ void BackgroundFetchContext::DidGetPermission(
void BackgroundFetchContext::GetIconDisplaySize(
blink::mojom::BackgroundFetchService::GetIconDisplaySizeCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
delegate_proxy_.GetIconDisplaySize(std::move(callback));
}
@@ -261,7 +273,7 @@ void BackgroundFetchContext::OnQuotaExceeded(
const BackgroundFetchRegistrationId& registration_id) {
auto job_it = job_controllers_.find(registration_id.unique_id());
if (job_it != job_controllers_.end() && job_it->second)
- job_it->second->Abort(BackgroundFetchReasonToAbort::QUOTA_EXCEEDED);
+ job_it->second->Abort(FailureReason::QUOTA_EXCEEDED);
}
void BackgroundFetchContext::AbandonFetches(
@@ -281,8 +293,7 @@ void BackgroundFetchContext::AbandonFetches(
service_worker_registration_id) {
DCHECK(saved_iter->second);
- saved_iter->second->Abort(
- BackgroundFetchReasonToAbort::SERVICE_WORKER_UNAVAILABLE);
+ saved_iter->second->Abort(FailureReason::SERVICE_WORKER_UNAVAILABLE);
}
}
@@ -307,7 +318,8 @@ void BackgroundFetchContext::OnRegistrationCreated(
const BackgroundFetchRegistration& registration,
const BackgroundFetchOptions& options,
const SkBitmap& icon,
- int num_requests) {
+ int num_requests,
+ bool start_paused) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (hang_registration_creation_for_testing_) {
@@ -322,7 +334,7 @@ void BackgroundFetchContext::OnRegistrationCreated(
CreateController(registration_id, registration, options, icon, options.title,
0u /* num_completed_requests */, num_requests,
- {} /* active_fetch_requests */);
+ {} /* active_fetch_requests */, start_paused);
}
void BackgroundFetchContext::OnUpdatedUI(
@@ -348,6 +360,15 @@ void BackgroundFetchContext::OnStorageWiped() {
AbandonFetches(blink::mojom::kInvalidServiceWorkerRegistrationId);
}
+void BackgroundFetchContext::OnFetchStorageError(
+ const BackgroundFetchRegistrationId& registration_id) {
+ auto controllers_iter = job_controllers_.find(registration_id.unique_id());
+ if (controllers_iter == job_controllers_.end())
+ return;
+
+ controllers_iter->second->Abort(FailureReason::SERVICE_WORKER_UNAVAILABLE);
+}
+
void BackgroundFetchContext::CreateController(
const BackgroundFetchRegistrationId& registration_id,
const BackgroundFetchRegistration& registration,
@@ -357,7 +378,8 @@ void BackgroundFetchContext::CreateController(
size_t num_completed_requests,
size_t num_requests,
std::vector<scoped_refptr<BackgroundFetchRequestInfo>>
- active_fetch_requests) {
+ active_fetch_requests,
+ bool start_paused) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
auto controller = std::make_unique<BackgroundFetchJobController>(
@@ -372,7 +394,7 @@ void BackgroundFetchContext::CreateController(
controller->InitializeRequestStatus(num_completed_requests, num_requests,
std::move(active_fetch_requests),
- ui_title);
+ ui_title, start_paused);
scheduler_->AddJobController(controller.get());
job_controllers_.emplace(registration_id.unique_id(), std::move(controller));
}
@@ -382,28 +404,36 @@ void BackgroundFetchContext::Abort(
blink::mojom::BackgroundFetchService::AbortCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ auto controllers_iter = job_controllers_.find(registration_id.unique_id());
+ if (controllers_iter == job_controllers_.end()) {
+ std::move(callback).Run(blink::mojom::BackgroundFetchError::INVALID_ID);
+ return;
+ }
+
+ controllers_iter->second->Abort(FailureReason::CANCELLED_BY_DEVELOPER);
+
DidFinishJob(std::move(callback), registration_id,
- BackgroundFetchReasonToAbort::ABORTED_BY_DEVELOPER);
+ FailureReason::CANCELLED_BY_DEVELOPER);
}
void BackgroundFetchContext::DidFinishJob(
base::OnceCallback<void(blink::mojom::BackgroundFetchError)> callback,
const BackgroundFetchRegistrationId& registration_id,
- BackgroundFetchReasonToAbort reason_to_abort) {
+ FailureReason failure_reason) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- // If |aborted| is true, this will also propagate the event to any active
- // JobController for the registration, to terminate in-progress requests.
+ // If the registration was aborted, this will also propagate the event to any
+ // active JobController, to terminate in-progress requests.
data_manager_->MarkRegistrationForDeletion(
registration_id,
base::BindOnce(&BackgroundFetchContext::DidMarkForDeletion,
weak_factory_.GetWeakPtr(), registration_id,
- reason_to_abort, std::move(callback)));
+ failure_reason, std::move(callback)));
}
void BackgroundFetchContext::DidMarkForDeletion(
const BackgroundFetchRegistrationId& registration_id,
- BackgroundFetchReasonToAbort reason_to_abort,
+ FailureReason failure_reason,
base::OnceCallback<void(blink::mojom::BackgroundFetchError)> callback,
blink::mojom::BackgroundFetchError error) {
DCHECK(callback);
@@ -412,109 +442,109 @@ void BackgroundFetchContext::DidMarkForDeletion(
// It's normal to get INVALID_ID errors here - it means the registration was
// already inactive (marked for deletion). This happens when an abort (from
// developer or from user) races with the download completing/failing, or even
- // when two aborts race. TODO(johnme): Log STORAGE_ERRORs to UMA though.
+ // when two aborts race.
if (error != blink::mojom::BackgroundFetchError::NONE)
return;
- auto controllers_iter = job_controllers_.find(registration_id.unique_id());
-
- if (reason_to_abort == BackgroundFetchReasonToAbort::ABORTED_BY_DEVELOPER) {
- DCHECK(controllers_iter != job_controllers_.end());
- controllers_iter->second->Abort(reason_to_abort);
+ if (failure_reason == FailureReason::NONE) {
+ // As far as we know the fetch was successful, go over the entries in the
+ // cache and make sure all the responses are there and successful.
+ data_manager_->GetSettledFetchesForRegistration(
+ registration_id, std::make_unique<BackgroundFetchRequestMatchParams>(),
+ base::BindOnce(&BackgroundFetchContext::DidGetSettledFetches,
+ weak_factory_.GetWeakPtr(), registration_id));
+ return;
}
- auto registration = controllers_iter->second->NewRegistration(
- blink::mojom::BackgroundFetchState::FAILURE);
- switch (reason_to_abort) {
- case BackgroundFetchReasonToAbort::ABORTED_BY_DEVELOPER:
- case BackgroundFetchReasonToAbort::CANCELLED_FROM_UI:
- CleanupRegistration(registration_id, {},
- blink::mojom::BackgroundFetchState::FAILURE);
- event_dispatcher_.DispatchBackgroundFetchAbortEvent(
- registration_id, std::move(registration), base::DoNothing());
- return;
- case BackgroundFetchReasonToAbort::TOTAL_DOWNLOAD_SIZE_EXCEEDED:
- case BackgroundFetchReasonToAbort::SERVICE_WORKER_UNAVAILABLE:
- case BackgroundFetchReasonToAbort::QUOTA_EXCEEDED:
- case BackgroundFetchReasonToAbort::NONE:
- // This will send a BackgroundFetchFetched or BackgroundFetchFail event.
- // We still need this to figure out which event to send.
- // TODO(crbug.com/699957, crbug.com/874092): Add a method to only return
- // the information needed to dispatch these events, instead of settled
- // fetches.
- data_manager_->GetSettledFetchesForRegistration(
- registration_id,
- std::make_unique<BackgroundFetchRequestMatchParams>(),
- base::BindOnce(&BackgroundFetchContext::DidGetSettledFetches,
- weak_factory_.GetWeakPtr(), registration_id,
- std::move(registration)));
- return;
- }
+ // The fetch failed, dispatch an appropriate event.
+ auto controllers_iter = job_controllers_.find(registration_id.unique_id());
+ DCHECK(controllers_iter != job_controllers_.end());
+ auto registration = controllers_iter->second->NewRegistration(
+ blink::mojom::BackgroundFetchResult::FAILURE);
+ DispatchCompletionEvent(registration_id, std::move(registration));
}
void BackgroundFetchContext::DidGetSettledFetches(
const BackgroundFetchRegistrationId& registration_id,
- std::unique_ptr<BackgroundFetchRegistration> registration,
blink::mojom::BackgroundFetchError error,
- bool background_fetch_succeeded,
+ FailureReason failure_reason,
std::vector<BackgroundFetchSettledFetch> settled_fetches,
std::vector<std::unique_ptr<storage::BlobDataHandle>> blob_data_handles) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(failure_reason == FailureReason::NONE ||
+ failure_reason == FailureReason::FETCH_ERROR ||
+ failure_reason == FailureReason::SERVICE_WORKER_UNAVAILABLE ||
+ failure_reason == FailureReason::BAD_STATUS);
- if (error != blink::mojom::BackgroundFetchError::NONE) {
- CleanupRegistration(registration_id, {} /* fetches */,
- blink::mojom::BackgroundFetchState::FAILURE,
- true /* preserve_info_to_dispatch_click_event */);
- return;
- }
+ auto controllers_iter = job_controllers_.find(registration_id.unique_id());
+ DCHECK(controllers_iter != job_controllers_.end());
+ failure_reason = controllers_iter->second->MergeFailureReason(failure_reason);
- DCHECK(job_controllers_.count(registration_id.unique_id()));
+ blink::mojom::BackgroundFetchResult result =
+ failure_reason == FailureReason::NONE
+ ? blink::mojom::BackgroundFetchResult::SUCCESS
+ : blink::mojom::BackgroundFetchResult::FAILURE;
- if (job_controllers_[registration_id.unique_id()]->total_downloads() !=
- static_cast<int>(settled_fetches.size())) {
- // Something went wrong, and some information was lost.
- background_fetch_succeeded = false;
- }
+ auto registration = controllers_iter->second->NewRegistration(result);
+ DispatchCompletionEvent(registration_id, std::move(registration));
+}
+
+void BackgroundFetchContext::DispatchCompletionEvent(
+ const BackgroundFetchRegistrationId& registration_id,
+ std::unique_ptr<BackgroundFetchRegistration> registration) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ registration_notifier_->Notify(*registration);
- // The `backgroundfetchsuccess` event will be invoked when all requests in the
- // registration have completed successfully. In all other cases, the
- // `backgroundfetchfail` event will be invoked instead.
- if (background_fetch_succeeded) {
- registration->state = blink::mojom::BackgroundFetchState::SUCCESS;
- event_dispatcher_.DispatchBackgroundFetchSuccessEvent(
- registration_id, std::move(registration),
- base::BindOnce(
- &BackgroundFetchContext::CleanupRegistration,
- weak_factory_.GetWeakPtr(), registration_id,
- // The blob uuid is sent as part of |settled_fetches|. Bind
- // |blob_data_handles| to the callback to keep them alive
- // until the waitUntil event is resolved.
- std::move(blob_data_handles),
- blink::mojom::BackgroundFetchState::SUCCESS,
- true /* preserve_info_to_dispatch_click_event */));
- } else {
- registration->state = blink::mojom::BackgroundFetchState::FAILURE;
- event_dispatcher_.DispatchBackgroundFetchFailEvent(
- registration_id, std::move(registration),
- base::BindOnce(
- &BackgroundFetchContext::CleanupRegistration,
- weak_factory_.GetWeakPtr(), registration_id,
- // The blob uuid is sent as part of |settled_fetches|. Bind
- // |blob_data_handles| to the callback to keep them alive
- // until the waitUntil event is resolved.
- std::move(blob_data_handles),
- blink::mojom::BackgroundFetchState::FAILURE,
- true /* preserve_info_to_dispatch_click_event */));
+ switch (registration->failure_reason) {
+ case FailureReason::NONE:
+ DCHECK_EQ(registration->result,
+ blink::mojom::BackgroundFetchResult::SUCCESS);
+ event_dispatcher_.DispatchBackgroundFetchSuccessEvent(
+ registration_id, std::move(registration),
+ base::BindOnce(&BackgroundFetchContext::CleanupRegistration,
+ weak_factory_.GetWeakPtr(), registration_id,
+ blink::mojom::BackgroundFetchResult::SUCCESS,
+ /* preserve_info_to_dispatch_click_event= */ true));
+ return;
+ case FailureReason::CANCELLED_FROM_UI:
+ case FailureReason::CANCELLED_BY_DEVELOPER:
+ DCHECK_EQ(registration->result,
+ blink::mojom::BackgroundFetchResult::FAILURE);
+ event_dispatcher_.DispatchBackgroundFetchAbortEvent(
+ registration_id, std::move(registration),
+ base::BindOnce(&BackgroundFetchContext::CleanupRegistration,
+ weak_factory_.GetWeakPtr(), registration_id,
+ blink::mojom::BackgroundFetchResult::FAILURE,
+ /* preserve_info_to_dispatch_click_event= */ false));
+ return;
+ case FailureReason::BAD_STATUS:
+ case FailureReason::FETCH_ERROR:
+ case FailureReason::SERVICE_WORKER_UNAVAILABLE:
+ case FailureReason::QUOTA_EXCEEDED:
+ case FailureReason::TOTAL_DOWNLOAD_SIZE_EXCEEDED:
+ DCHECK_EQ(registration->result,
+ blink::mojom::BackgroundFetchResult::FAILURE);
+ event_dispatcher_.DispatchBackgroundFetchFailEvent(
+ registration_id, std::move(registration),
+ base::BindOnce(&BackgroundFetchContext::CleanupRegistration,
+ weak_factory_.GetWeakPtr(), registration_id,
+ blink::mojom::BackgroundFetchResult::FAILURE,
+ /* preserve_info_to_dispatch_click_event= */ true));
+ return;
}
}
void BackgroundFetchContext::CleanupRegistration(
const BackgroundFetchRegistrationId& registration_id,
- const std::vector<std::unique_ptr<storage::BlobDataHandle>>& blob_handles,
- blink::mojom::BackgroundFetchState background_fetch_state,
+ blink::mojom::BackgroundFetchResult background_fetch_result,
bool preserve_info_to_dispatch_click_event) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ // Indicate to the renderer that the records for this fetch are no longer
+ // available.
+ registration_notifier_->NotifyRecordsUnavailable(registration_id.unique_id());
+
// If we had an active JobController, it is no longer necessary, as the
// notification's UI can no longer be updated after the fetch is aborted, or
// after the waitUntil promise of the
@@ -526,22 +556,16 @@ void BackgroundFetchContext::CleanupRegistration(
if (preserve_info_to_dispatch_click_event) {
completed_fetches_[registration_id.unique_id()] = std::make_pair(
registration_id,
- controllers_iter->second->NewRegistration(background_fetch_state));
+ controllers_iter->second->NewRegistration(background_fetch_result));
}
job_controllers_.erase(registration_id.unique_id());
- // At this point, JavaScript can no longer obtain BackgroundFetchRegistration
- // objects for this registration, and those objects are the only thing that
- // requires us to keep the registration's data around. So once the
- // RegistrationNotifier informs us that all existing observers (and hence
- // BackgroundFetchRegistration objects) have been garbage collected, it'll be
- // safe to delete the registration. This callback doesn't run if the browser
- // is shutdown before that happens - BackgroundFetchDataManager::Cleanup acts
- // as a fallback in that case, and deletes the registration on next startup.
- registration_notifier_->AddGarbageCollectionCallback(
- registration_id.unique_id(),
- base::BindOnce(&BackgroundFetchContext::LastObserverGarbageCollected,
- weak_factory_.GetWeakPtr(), registration_id));
+ // Delete the data associated with this fetch. Cache storage will keep the
+ // downloaded data around so long as there are references to it, and delete
+ // it once there is none. We don't need to do that accounting.
+ data_manager_->DeleteRegistration(
+ registration_id,
+ base::BindOnce(&background_fetch::RecordRegistrationDeletedError));
}
void BackgroundFetchContext::DispatchClickEvent(const std::string& unique_id) {
@@ -555,14 +579,12 @@ void BackgroundFetchContext::DispatchClickEvent(const std::string& unique_id) {
return;
}
- // The fetch is active, or has been aborted/cancelled.
+ // The fetch is active.
auto controllers_iter = job_controllers_.find(unique_id);
if (controllers_iter == job_controllers_.end())
return;
- // TODO(crbug.com/873630): Implement a background fetch state manager to
- // keep track of states, and stop hard-coding it here.
auto registration = controllers_iter->second->NewRegistration(
- blink::mojom::BackgroundFetchState::PENDING);
+ blink::mojom::BackgroundFetchResult::UNSET);
event_dispatcher_.DispatchBackgroundFetchClickEvent(
controllers_iter->second->registration_id(), std::move(registration),
base::DoNothing());
@@ -583,7 +605,7 @@ void BackgroundFetchContext::MatchRequests(
void BackgroundFetchContext::DidGetMatchingRequests(
blink::mojom::BackgroundFetchService::MatchRequestsCallback callback,
blink::mojom::BackgroundFetchError error,
- bool background_fetch_succeeded,
+ FailureReason failure_reason,
std::vector<BackgroundFetchSettledFetch> settled_fetches,
std::vector<std::unique_ptr<storage::BlobDataHandle>> blob_data_handles) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -596,20 +618,11 @@ void BackgroundFetchContext::DidGetMatchingRequests(
std::move(callback).Run(std::move(settled_fetches));
}
-void BackgroundFetchContext::LastObserverGarbageCollected(
- const BackgroundFetchRegistrationId& registration_id) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- data_manager_->DeleteRegistration(
- registration_id,
- base::BindOnce(&background_fetch::RecordRegistrationDeletedError));
-}
-
void BackgroundFetchContext::Shutdown() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&BackgroundFetchContext::ShutdownOnIO, this));
}
diff --git a/chromium/content/browser/background_fetch/background_fetch_context.h b/chromium/content/browser/background_fetch/background_fetch_context.h
index e25b9151c53..431e7ef081d 100644
--- a/chromium/content/browser/background_fetch/background_fetch_context.h
+++ b/chromium/content/browser/background_fetch/background_fetch_context.h
@@ -91,6 +91,7 @@ class CONTENT_EXPORT BackgroundFetchContext
const std::vector<ServiceWorkerFetchRequest>& requests,
const BackgroundFetchOptions& options,
const SkBitmap& icon,
+ blink::mojom::BackgroundFetchUkmDataPtr ukm_data,
RenderFrameHost* render_frame_host,
blink::mojom::BackgroundFetchService::FetchCallback callback);
@@ -135,7 +136,8 @@ class CONTENT_EXPORT BackgroundFetchContext
const BackgroundFetchRegistration& registration,
const BackgroundFetchOptions& options,
const SkBitmap& icon,
- int num_requests) override;
+ int num_requests,
+ bool start_paused) override;
void OnUpdatedUI(const BackgroundFetchRegistrationId& registration_id,
const base::Optional<std::string>& title,
const base::Optional<SkBitmap>& icon) override;
@@ -143,6 +145,8 @@ class CONTENT_EXPORT BackgroundFetchContext
int64_t service_worker_registration_id) override;
void OnQuotaExceeded(
const BackgroundFetchRegistrationId& registration_id) override;
+ void OnFetchStorageError(
+ const BackgroundFetchRegistrationId& registration_id) override;
// ServiceWorkerContextCoreObserver implementation.
void OnRegistrationDeleted(int64_t registration_id,
@@ -150,7 +154,8 @@ class CONTENT_EXPORT BackgroundFetchContext
void OnStorageWiped() override;
private:
- using GetPermissionCallback = base::OnceCallback<void(bool)>;
+ using GetPermissionCallback =
+ base::OnceCallback<void(BackgroundFetchPermission)>;
FRIEND_TEST_ALL_PREFIXES(BackgroundFetchServiceTest,
JobsInitializedOnBrowserRestart);
@@ -175,7 +180,8 @@ class CONTENT_EXPORT BackgroundFetchContext
size_t num_completed_requests,
size_t num_requests,
std::vector<scoped_refptr<BackgroundFetchRequestInfo>>
- active_fetch_requests);
+ active_fetch_requests,
+ bool start_paused);
// Called when an existing registration has been retrieved from the data
// manager. If the registration does not exist then |registration| is nullptr.
@@ -195,12 +201,12 @@ class CONTENT_EXPORT BackgroundFetchContext
void DidFinishJob(
base::OnceCallback<void(blink::mojom::BackgroundFetchError)> callback,
const BackgroundFetchRegistrationId& registration_id,
- BackgroundFetchReasonToAbort reason_to_abort);
+ blink::mojom::BackgroundFetchFailureReason failure_reason);
// Called when the data manager finishes marking a registration as deleted.
void DidMarkForDeletion(
const BackgroundFetchRegistrationId& registration_id,
- BackgroundFetchReasonToAbort reason_to_abort,
+ blink::mojom::BackgroundFetchFailureReason failure_reason,
base::OnceCallback<void(blink::mojom::BackgroundFetchError)> callback,
blink::mojom::BackgroundFetchError error);
@@ -208,9 +214,8 @@ class CONTENT_EXPORT BackgroundFetchContext
// retrieved from storage, and the Service Worker event can be invoked.
void DidGetSettledFetches(
const BackgroundFetchRegistrationId& registration_id,
- std::unique_ptr<BackgroundFetchRegistration> registration,
blink::mojom::BackgroundFetchError error,
- bool background_fetch_succeeded,
+ blink::mojom::BackgroundFetchFailureReason failure_reason,
std::vector<BackgroundFetchSettledFetch> settled_fetches,
std::vector<std::unique_ptr<storage::BlobDataHandle>> blob_data_handles);
@@ -220,10 +225,15 @@ class CONTENT_EXPORT BackgroundFetchContext
void DidGetMatchingRequests(
blink::mojom::BackgroundFetchService::MatchRequestsCallback callback,
blink::mojom::BackgroundFetchError error,
- bool background_fetch_succeeded,
+ blink::mojom::BackgroundFetchFailureReason failure_reason,
std::vector<BackgroundFetchSettledFetch> settled_fetches,
std::vector<std::unique_ptr<storage::BlobDataHandle>> blob_data_handles);
+ // Dispatches an appropriate event (success, fail, abort).
+ void DispatchCompletionEvent(
+ const BackgroundFetchRegistrationId& registration_id,
+ std::unique_ptr<BackgroundFetchRegistration> registration);
+
// Called when the notification UI for the background fetch job associated
// with |unique_id| is activated.
void DispatchClickEvent(const std::string& unique_id);
@@ -235,25 +245,17 @@ class CONTENT_EXPORT BackgroundFetchContext
initialization_data);
// Called when all processing for the |registration_id| has been finished and
- // the job is ready to be deleted. |blob_handles| are unused, but some callers
- // use it to keep blobs alive for the right duration.
- // |partial cleanup|, when set, preserves the registration ID, and the state
- // of Fetch when it completed, in |completed_fetches_|. This is not done when
- // fetch is aborted or cancelled. We use this information to propagate
- // BackgroundFetchClicked event to the developer, when the user taps the UI.
+ // the job is ready to be deleted.
+ // |preserve_info_to_dispatch_click_event|, when set, preserves the
+ // registration ID, and the result of the Fetch when it completed, in
+ // |completed_fetches_|. This is not done when fetch is aborted or cancelled.
+ // We use this information to propagate BackgroundFetchClicked event to the
+ // developer, when the user taps the UI.
void CleanupRegistration(
const BackgroundFetchRegistrationId& registration_id,
- const std::vector<std::unique_ptr<storage::BlobDataHandle>>&
- blob_data_handles,
- blink::mojom::BackgroundFetchState background_fetch_state,
+ blink::mojom::BackgroundFetchResult background_fetch_result,
bool preserve_info_to_dispatch_click_event = false);
- // Called when the last JavaScript BackgroundFetchRegistration object has been
- // garbage collected for a registration marked for deletion, and so it is now
- // safe to delete the underlying registration data.
- void LastObserverGarbageCollected(
- const BackgroundFetchRegistrationId& registration_id);
-
// Switches out |data_manager_| with a DataManager configured for testing
// environments. Must be called directly after the constructor.
void SetDataManagerForTesting(
@@ -271,9 +273,13 @@ class CONTENT_EXPORT BackgroundFetchContext
GetPermissionCallback callback);
// Callback for GetPermissionForOrigin.
- void DidGetPermission(base::OnceClosure permission_closure,
- const BackgroundFetchRegistrationId& registration_id,
- bool has_permission);
+ void DidGetPermission(const BackgroundFetchRegistrationId& registration_id,
+ const std::vector<ServiceWorkerFetchRequest>& requests,
+ const BackgroundFetchOptions& options,
+ const SkBitmap& icon,
+ blink::mojom::BackgroundFetchUkmDataPtr ukm_data,
+ int frame_tree_node_id,
+ BackgroundFetchPermission permission);
// |this| is owned, indirectly, by the BrowserContext.
BrowserContext* browser_context_;
diff --git a/chromium/content/browser/background_fetch/background_fetch_cross_origin_filter.cc b/chromium/content/browser/background_fetch/background_fetch_cross_origin_filter.cc
index 120b53c5723..50d79fe6281 100644
--- a/chromium/content/browser/background_fetch/background_fetch_cross_origin_filter.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_cross_origin_filter.cc
@@ -37,7 +37,7 @@ bool ParseOriginListHeader(const std::string& value,
for (const std::string& origin_string : origin_vector) {
url::Origin origin = url::Origin::Create(GURL(origin_string));
- if (origin.unique())
+ if (origin.opaque())
return false;
candidate_origins.insert(origin);
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 1fac2a819f9..1007b8a027a 100644
--- a/chromium/content/browser/background_fetch/background_fetch_data_manager.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_data_manager.cc
@@ -98,11 +98,13 @@ void BackgroundFetchDataManager::CreateRegistration(
const std::vector<ServiceWorkerFetchRequest>& requests,
const BackgroundFetchOptions& options,
const SkBitmap& icon,
+ bool start_paused,
GetRegistrationCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
AddDatabaseTask(std::make_unique<background_fetch::CreateMetadataTask>(
- this, registration_id, requests, options, icon, std::move(callback)));
+ this, registration_id, requests, options, icon, start_paused,
+ std::move(callback)));
}
void BackgroundFetchDataManager::GetRegistration(
@@ -133,41 +135,19 @@ void BackgroundFetchDataManager::PopNextRequest(
NextRequestCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- auto start_next_request = base::BindOnce(
- &BackgroundFetchDataManager::AddStartNextPendingRequestTask,
- weak_ptr_factory_.GetWeakPtr(), registration_id, std::move(callback));
-
- // Get the associated metadata, and add a StartNextPendingRequestTask.
- AddDatabaseTask(std::make_unique<background_fetch::GetRegistrationTask>(
- this, registration_id.service_worker_registration_id(),
- registration_id.origin(), registration_id.developer_id(),
- std::move(start_next_request)));
-}
-
-void BackgroundFetchDataManager::AddStartNextPendingRequestTask(
- const BackgroundFetchRegistrationId& registration_id,
- NextRequestCallback callback,
- blink::mojom::BackgroundFetchError error,
- const BackgroundFetchRegistration& registration) {
- if (error != blink::mojom::BackgroundFetchError::NONE) {
- // Stop giving out requests as registration aborted (or otherwise finished).
- std::move(callback).Run(nullptr /* request */);
- return;
- }
-
AddDatabaseTask(
std::make_unique<background_fetch::StartNextPendingRequestTask>(
- this, registration_id, registration, std::move(callback)));
+ this, registration_id, std::move(callback)));
}
void BackgroundFetchDataManager::MarkRequestAsComplete(
const BackgroundFetchRegistrationId& registration_id,
scoped_refptr<BackgroundFetchRequestInfo> request_info,
- base::OnceClosure closure) {
+ MarkRequestCompleteCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
AddDatabaseTask(std::make_unique<background_fetch::MarkRequestCompleteTask>(
- this, registration_id, std::move(request_info), std::move(closure)));
+ this, registration_id, std::move(request_info), std::move(callback)));
}
void BackgroundFetchDataManager::GetSettledFetchesForRegistration(
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 253831a6deb..2c49a60d665 100644
--- a/chromium/content/browser/background_fetch/background_fetch_data_manager.h
+++ b/chromium/content/browser/background_fetch/background_fetch_data_manager.h
@@ -65,14 +65,17 @@ class CONTENT_EXPORT BackgroundFetchDataManager
std::vector<background_fetch::BackgroundFetchInitializationData>)>;
using SettledFetchesCallback = base::OnceCallback<void(
blink::mojom::BackgroundFetchError,
- bool /* background_fetch_succeeded */,
+ blink::mojom::BackgroundFetchFailureReason,
std::vector<BackgroundFetchSettledFetch>,
std::vector<std::unique_ptr<storage::BlobDataHandle>>)>;
using GetRegistrationCallback =
base::OnceCallback<void(blink::mojom::BackgroundFetchError,
const BackgroundFetchRegistration&)>;
+ using MarkRequestCompleteCallback =
+ base::OnceCallback<void(blink::mojom::BackgroundFetchError)>;
using NextRequestCallback =
- base::OnceCallback<void(scoped_refptr<BackgroundFetchRequestInfo>)>;
+ base::OnceCallback<void(blink::mojom::BackgroundFetchError,
+ scoped_refptr<BackgroundFetchRequestInfo>)>;
BackgroundFetchDataManager(
BrowserContext* browser_context,
@@ -102,6 +105,7 @@ class CONTENT_EXPORT BackgroundFetchDataManager
const std::vector<ServiceWorkerFetchRequest>& requests,
const BackgroundFetchOptions& options,
const SkBitmap& icon,
+ bool start_paused,
GetRegistrationCallback callback);
// Get the BackgroundFetchRegistration.
@@ -166,7 +170,7 @@ class CONTENT_EXPORT BackgroundFetchDataManager
void MarkRequestAsComplete(
const BackgroundFetchRegistrationId& registration_id,
scoped_refptr<BackgroundFetchRequestInfo> request_info,
- base::OnceClosure closure) override;
+ MarkRequestCompleteCallback callback) override;
void ShutdownOnIO();
@@ -193,12 +197,6 @@ class CONTENT_EXPORT BackgroundFetchDataManager
return quota_manager_proxy_.get();
}
- void AddStartNextPendingRequestTask(
- const BackgroundFetchRegistrationId& registration_id,
- NextRequestCallback callback,
- blink::mojom::BackgroundFetchError error,
- const BackgroundFetchRegistration& registration);
-
void AddDatabaseTask(std::unique_ptr<background_fetch::DatabaseTask> task);
// DatabaseTaskHost implementation.
diff --git a/chromium/content/browser/background_fetch/background_fetch_data_manager_observer.h b/chromium/content/browser/background_fetch/background_fetch_data_manager_observer.h
index ab1a9f2aca0..032cc1284ec 100644
--- a/chromium/content/browser/background_fetch/background_fetch_data_manager_observer.h
+++ b/chromium/content/browser/background_fetch/background_fetch_data_manager_observer.h
@@ -28,7 +28,8 @@ class BackgroundFetchDataManagerObserver {
const BackgroundFetchRegistration& registration,
const BackgroundFetchOptions& options,
const SkBitmap& icon,
- int num_requests) = 0;
+ int num_requests,
+ bool start_paused) = 0;
// Called when the UI options for the Background Fetch |registration_id| have
// been updated in the data store.
@@ -44,6 +45,11 @@ class BackgroundFetchDataManagerObserver {
virtual void OnQuotaExceeded(
const BackgroundFetchRegistrationId& registration_id) = 0;
+ // Called if a database task encountered a storage error in the context of a
+ // fetch workflow, such as preparing a request or storing a response.
+ virtual void OnFetchStorageError(
+ const BackgroundFetchRegistrationId& registration_id) = 0;
+
virtual ~BackgroundFetchDataManagerObserver() {}
};
diff --git a/chromium/content/browser/background_fetch/background_fetch_data_manager_unittest.cc b/chromium/content/browser/background_fetch/background_fetch_data_manager_unittest.cc
index 4b2a1074e78..3003797895a 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
@@ -34,6 +34,7 @@
#include "services/network/public/mojom/fetch_api.mojom.h"
#include "storage/browser/blob/blob_data_handle.h"
#include "testing/gmock/include/gmock/gmock.h"
+#include "third_party/blink/public/platform/modules/background_fetch/background_fetch.mojom.h"
#include "third_party/blink/public/platform/modules/cache_storage/cache_storage.mojom.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkColor.h"
@@ -102,21 +103,23 @@ void AnnotateRequestInfoWithFakeDownloadManagerData(
std::string headers =
success ? "HTTP/1.1 200 OK\n" : "HTTP/1.1 404 Not found\n";
- request_info->PopulateWithResponse(std::make_unique<BackgroundFetchResponse>(
+ auto response = std::make_unique<BackgroundFetchResponse>(
std::vector<GURL>(1u, request_info->fetch_request().url),
- base::MakeRefCounted<net::HttpResponseHeaders>(headers)));
+ base::MakeRefCounted<net::HttpResponseHeaders>(headers));
if (!success) {
// Fill |request_info| with a failed result.
request_info->SetResult(std::make_unique<BackgroundFetchResult>(
- base::Time::Now(), BackgroundFetchResult::FailureReason::UNKNOWN));
+ std::move(response), base::Time::Now(),
+ BackgroundFetchResult::FailureReason::FETCH_ERROR));
return;
}
// This is treated as an empty response, but the size is set to
// |kResponseFileSize| for tests that use filesize.
request_info->SetResult(std::make_unique<BackgroundFetchResult>(
- base::Time::Now(), base::FilePath(), base::nullopt /* blob_handle */,
+ std::move(response), base::Time::Now(), base::FilePath(),
+ base::nullopt /* blob_handle */,
over_quota ? kBackgroundFetchMaxQuotaBytes + 1 : kResponseFileSize));
}
@@ -232,7 +235,7 @@ class BackgroundFetchDataManagerTest
base::RunLoop run_loop;
background_fetch_data_manager_->CreateRegistration(
- registration_id, requests, options, icon,
+ registration_id, requests, options, icon, /* start_paused = */ false,
base::BindOnce(&DidCreateRegistration, run_loop.QuitClosure(),
out_error));
run_loop.Run();
@@ -312,7 +315,9 @@ class BackgroundFetchDataManagerTest
// BackgroundFetchDataManager::PopNextRequest().
void PopNextRequest(
const BackgroundFetchRegistrationId& registration_id,
+ blink::mojom::BackgroundFetchError* out_error,
scoped_refptr<BackgroundFetchRequestInfo>* out_request_info) {
+ DCHECK(out_error);
DCHECK(out_request_info);
base::RunLoop run_loop;
@@ -320,7 +325,7 @@ class BackgroundFetchDataManagerTest
registration_id,
base::BindOnce(&BackgroundFetchDataManagerTest::DidPopNextRequest,
base::Unretained(this), run_loop.QuitClosure(),
- out_request_info));
+ out_error, out_request_info));
run_loop.Run();
}
@@ -353,13 +358,16 @@ class BackgroundFetchDataManagerTest
// Synchronous version of BackgroundFetchDataManager::MarkRequestAsComplete().
void MarkRequestAsComplete(
const BackgroundFetchRegistrationId& registration_id,
- BackgroundFetchRequestInfo* request_info) {
+ BackgroundFetchRequestInfo* request_info,
+ blink::mojom::BackgroundFetchError* out_error) {
+ DCHECK(out_error);
+
base::RunLoop run_loop;
background_fetch_data_manager_->MarkRequestAsComplete(
registration_id, request_info,
base::BindOnce(
&BackgroundFetchDataManagerTest::DidMarkRequestAsComplete,
- base::Unretained(this), run_loop.QuitClosure()));
+ base::Unretained(this), run_loop.QuitClosure(), out_error));
run_loop.Run();
}
@@ -371,10 +379,10 @@ class BackgroundFetchDataManagerTest
blink::mojom::QueryParamsPtr cache_query_params,
bool match_all,
blink::mojom::BackgroundFetchError* out_error,
- bool* out_succeeded,
+ blink::mojom::BackgroundFetchFailureReason* out_failure_reason,
std::vector<BackgroundFetchSettledFetch>* out_settled_fetches) {
DCHECK(out_error);
- DCHECK(out_succeeded);
+ DCHECK(out_failure_reason);
DCHECK(out_settled_fetches);
base::RunLoop run_loop;
@@ -385,7 +393,7 @@ class BackgroundFetchDataManagerTest
base::BindOnce(&BackgroundFetchDataManagerTest::
DidGetSettledFetchesForRegistration,
base::Unretained(this), run_loop.QuitClosure(),
- out_error, out_succeeded, out_settled_fetches));
+ out_error, out_failure_reason, out_settled_fetches));
run_loop.Run();
}
@@ -552,12 +560,13 @@ class BackgroundFetchDataManagerTest
}
// BackgroundFetchDataManagerObserver mocks:
- MOCK_METHOD5(OnRegistrationCreated,
+ MOCK_METHOD6(OnRegistrationCreated,
void(const BackgroundFetchRegistrationId& registration_id,
const BackgroundFetchRegistration& registration,
const BackgroundFetchOptions& options,
const SkBitmap& icon,
- int num_requests));
+ int num_requests,
+ bool start_paused));
MOCK_METHOD3(OnUpdatedUI,
void(const BackgroundFetchRegistrationId& registration,
const base::Optional<std::string>& title,
@@ -566,6 +575,8 @@ class BackgroundFetchDataManagerTest
void(int64_t service_worker_registration_id));
MOCK_METHOD1(OnQuotaExceeded,
void(const BackgroundFetchRegistrationId& registration_id));
+ MOCK_METHOD1(OnFetchStorageError,
+ void(const BackgroundFetchRegistrationId& registration_id));
protected:
void DidGetRegistration(base::OnceClosure quit_closure,
@@ -615,27 +626,33 @@ class BackgroundFetchDataManagerTest
void DidPopNextRequest(
base::OnceClosure quit_closure,
+ blink::mojom::BackgroundFetchError* out_error,
scoped_refptr<BackgroundFetchRequestInfo>* out_request_info,
+ blink::mojom::BackgroundFetchError error,
scoped_refptr<BackgroundFetchRequestInfo> request_info) {
+ *out_error = error;
*out_request_info = request_info;
std::move(quit_closure).Run();
}
- void DidMarkRequestAsComplete(base::OnceClosure quit_closure) {
+ void DidMarkRequestAsComplete(base::OnceClosure quit_closure,
+ blink::mojom::BackgroundFetchError* out_error,
+ blink::mojom::BackgroundFetchError error) {
+ *out_error = error;
std::move(quit_closure).Run();
}
void DidGetSettledFetchesForRegistration(
base::OnceClosure quit_closure,
blink::mojom::BackgroundFetchError* out_error,
- bool* out_succeeded,
+ blink::mojom::BackgroundFetchFailureReason* out_failure_reason,
std::vector<BackgroundFetchSettledFetch>* out_settled_fetches,
blink::mojom::BackgroundFetchError error,
- bool succeeded,
+ blink::mojom::BackgroundFetchFailureReason failure_reason,
std::vector<BackgroundFetchSettledFetch> settled_fetches,
std::vector<std::unique_ptr<storage::BlobDataHandle>>) {
*out_error = error;
- *out_succeeded = succeeded;
+ *out_failure_reason = failure_reason;
*out_settled_fetches = std::move(settled_fetches);
std::move(quit_closure).Run();
@@ -707,7 +724,7 @@ TEST_F(BackgroundFetchDataManagerTest, NoDuplicateRegistrations) {
// Creating the initial registration should succeed.
{
- EXPECT_CALL(*this, OnRegistrationCreated(registration_id1, _, _, _, _));
+ EXPECT_CALL(*this, OnRegistrationCreated(registration_id1, _, _, _, _, _));
CreateRegistration(registration_id1, requests, options, SkBitmap(), &error);
ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
@@ -736,7 +753,7 @@ TEST_F(BackgroundFetchDataManagerTest, NoDuplicateRegistrations) {
// is no longer an *active* registration with the same |developer_id|, even
// though the initial registration has not yet been deleted.
{
- EXPECT_CALL(*this, OnRegistrationCreated(registration_id2, _, _, _, _));
+ EXPECT_CALL(*this, OnRegistrationCreated(registration_id2, _, _, _, _, _));
CreateRegistration(registration_id2, requests, options, SkBitmap(), &error);
ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
@@ -764,6 +781,73 @@ TEST_F(BackgroundFetchDataManagerTest, ExceedingQuotaFailsCreation) {
ASSERT_EQ(error, blink::mojom::BackgroundFetchError::QUOTA_EXCEEDED);
}
+TEST_F(BackgroundFetchDataManagerTest, RegistrationLimitIsEnforced) {
+ // Tests that the BackgroundFetchDataManager correctly rejects creating a
+ // registration when an origin exceeds the allowed number of registrations.
+ int64_t swid1 = RegisterServiceWorker();
+ ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, swid1);
+ int64_t swid2 = RegisterServiceWorker();
+ ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, swid2);
+
+ ASSERT_NE(swid1, swid2);
+
+ blink::mojom::BackgroundFetchError error;
+
+ // Create two registrations for every Service Worker.
+ for (int i = 0; i < 2; i++) {
+ // First Service Worker.
+ BackgroundFetchRegistrationId registration_id1(
+ swid1, origin(), kExampleDeveloperId + base::IntToString(i),
+ base::GenerateGUID());
+ CreateRegistration(registration_id1,
+ std::vector<ServiceWorkerFetchRequest>(),
+ BackgroundFetchOptions(), SkBitmap(), &error);
+ ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+
+ // Second service Worker.
+ BackgroundFetchRegistrationId registration_id2(
+ swid2, origin(), kExampleDeveloperId + base::IntToString(i),
+ base::GenerateGUID());
+ CreateRegistration(registration_id2,
+ std::vector<ServiceWorkerFetchRequest>(),
+ BackgroundFetchOptions(), SkBitmap(), &error);
+ ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ }
+
+ // Create another registration in the first Service Worker,
+ // bringing us to the limit.
+ {
+ BackgroundFetchRegistrationId registration_id(
+ swid1, origin(), "developer_id1", base::GenerateGUID());
+ CreateRegistration(registration_id,
+ std::vector<ServiceWorkerFetchRequest>(),
+ BackgroundFetchOptions(), SkBitmap(), &error);
+ ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ }
+
+ // A registration this time should fail.
+ {
+ BackgroundFetchRegistrationId registration_id(
+ swid1, origin(), "developer_id2", base::GenerateGUID());
+ CreateRegistration(registration_id,
+ std::vector<ServiceWorkerFetchRequest>(),
+ BackgroundFetchOptions(), SkBitmap(), &error);
+ ASSERT_EQ(error,
+ blink::mojom::BackgroundFetchError::REGISTRATION_LIMIT_EXCEEDED);
+ }
+
+ // The registration should also fail for the other Service Worker.
+ {
+ BackgroundFetchRegistrationId registration_id(
+ swid2, origin(), "developer_id3", base::GenerateGUID());
+ CreateRegistration(registration_id,
+ std::vector<ServiceWorkerFetchRequest>(),
+ BackgroundFetchOptions(), SkBitmap(), &error);
+ ASSERT_EQ(error,
+ blink::mojom::BackgroundFetchError::REGISTRATION_LIMIT_EXCEEDED);
+ }
+}
+
TEST_F(BackgroundFetchDataManagerTest, GetDeveloperIds) {
int64_t sw_id = RegisterServiceWorker();
ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, sw_id);
@@ -781,7 +865,7 @@ TEST_F(BackgroundFetchDataManagerTest, GetDeveloperIds) {
BackgroundFetchRegistrationId registration_id1(
sw_id, origin(), kExampleDeveloperId, kExampleUniqueId);
{
- EXPECT_CALL(*this, OnRegistrationCreated(registration_id1, _, _, _, _));
+ EXPECT_CALL(*this, OnRegistrationCreated(registration_id1, _, _, _, _, _));
CreateRegistration(registration_id1, requests, options, SkBitmap(), &error);
ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
@@ -803,7 +887,7 @@ TEST_F(BackgroundFetchDataManagerTest, GetDeveloperIds) {
BackgroundFetchRegistrationId registration_id2(
sw_id, origin(), kAlternativeDeveloperId, kAlternativeUniqueId);
{
- EXPECT_CALL(*this, OnRegistrationCreated(registration_id2, _, _, _, _));
+ EXPECT_CALL(*this, OnRegistrationCreated(registration_id2, _, _, _, _, _));
CreateRegistration(registration_id2, requests, options, SkBitmap(), &error);
ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
@@ -835,7 +919,7 @@ TEST_F(BackgroundFetchDataManagerTest, GetRegistration) {
// Create a single registration.
{
- EXPECT_CALL(*this, OnRegistrationCreated(registration_id, _, _, _, _));
+ EXPECT_CALL(*this, OnRegistrationCreated(registration_id, _, _, _, _, _));
CreateRegistration(registration_id, requests, options, SkBitmap(), &error);
ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
@@ -877,7 +961,7 @@ TEST_F(BackgroundFetchDataManagerTest, GetMetadata) {
// Create a single registration.
{
- EXPECT_CALL(*this, OnRegistrationCreated(registration_id, _, _, _, _));
+ EXPECT_CALL(*this, OnRegistrationCreated(registration_id, _, _, _, _, _));
CreateRegistration(registration_id, requests, options, SkBitmap(), &error);
ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
@@ -915,7 +999,7 @@ TEST_F(BackgroundFetchDataManagerTest, LargeIconNotPersisted) {
// Create a single registration.
{
- EXPECT_CALL(*this, OnRegistrationCreated(registration_id, _, _, _, _));
+ EXPECT_CALL(*this, OnRegistrationCreated(registration_id, _, _, _, _, _));
CreateRegistration(registration_id, requests, options, icon, &error);
ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
@@ -947,7 +1031,7 @@ TEST_F(BackgroundFetchDataManagerTest, UpdateRegistrationUI) {
// Create a single registration.
{
- EXPECT_CALL(*this, OnRegistrationCreated(registration_id, _, _, _, _));
+ EXPECT_CALL(*this, OnRegistrationCreated(registration_id, _, _, _, _, _));
CreateRegistration(registration_id, requests, options, CreateTestIcon(),
&error);
@@ -1044,7 +1128,7 @@ TEST_F(BackgroundFetchDataManagerTest, CreateAndDeleteRegistration) {
blink::mojom::BackgroundFetchError error;
{
- EXPECT_CALL(*this, OnRegistrationCreated(registration_id1, _, _, _, _));
+ EXPECT_CALL(*this, OnRegistrationCreated(registration_id1, _, _, _, _, _));
CreateRegistration(registration_id1, requests, options, SkBitmap(), &error);
ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
@@ -1091,7 +1175,7 @@ TEST_F(BackgroundFetchDataManagerTest, CreateAndDeleteRegistration) {
// |developer_id|, even though the initial registration has not yet been
// deleted.
{
- EXPECT_CALL(*this, OnRegistrationCreated(registration_id2, _, _, _, _));
+ EXPECT_CALL(*this, OnRegistrationCreated(registration_id2, _, _, _, _, _));
CreateRegistration(registration_id2, requests, options, SkBitmap(), &error);
ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
@@ -1104,10 +1188,53 @@ TEST_F(BackgroundFetchDataManagerTest, CreateAndDeleteRegistration) {
EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
}
+TEST_F(BackgroundFetchDataManagerTest, MarkRegistrationForDeletion) {
+ int64_t sw_id = RegisterServiceWorker();
+ ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, sw_id);
+
+ BackgroundFetchRegistrationId registration_id1(
+ sw_id, origin(), kExampleDeveloperId, kExampleUniqueId);
+
+ std::vector<ServiceWorkerFetchRequest> requests(2u);
+ BackgroundFetchOptions options;
+ blink::mojom::BackgroundFetchError error;
+
+ CreateRegistration(registration_id1, requests, options, SkBitmap(), &error);
+ ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+
+ // Create a |developer_id| such that the other one is a substring.
+ std::string developer_id2 = std::string(kExampleDeveloperId) + "!";
+ BackgroundFetchRegistrationId registration_id2(sw_id, origin(), developer_id2,
+ kAlternativeUniqueId);
+
+ CreateRegistration(registration_id2, requests, options, SkBitmap(), &error);
+ ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+
+ // Get all active registration mappings.
+ {
+ auto registrations = GetRegistrationUserDataByKeyPrefix(
+ sw_id, background_fetch::ActiveRegistrationUniqueIdKey(""));
+ EXPECT_EQ(registrations.size(), 2u);
+ }
+
+ // Deactivate the first registration.
+ MarkRegistrationForDeletion(registration_id1, &error);
+ EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+
+ // The second registration should still exist.
+ {
+ auto registrations = GetRegistrationUserDataByKeyPrefix(
+ sw_id, background_fetch::ActiveRegistrationUniqueIdKey(""));
+ ASSERT_EQ(registrations.size(), 1u);
+ EXPECT_EQ(registrations[0], kAlternativeUniqueId);
+ }
+}
+
TEST_F(BackgroundFetchDataManagerTest, PopNextRequestAndMarkAsComplete) {
int64_t sw_id = RegisterServiceWorker();
ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, sw_id);
+ blink::mojom::BackgroundFetchError error;
scoped_refptr<BackgroundFetchRequestInfo> request_info;
BackgroundFetchRegistrationId registration_id(
@@ -1115,7 +1242,8 @@ TEST_F(BackgroundFetchDataManagerTest, PopNextRequestAndMarkAsComplete) {
// There registration hasn't been created yet, so there are no pending
// requests.
- PopNextRequest(registration_id, &request_info);
+ PopNextRequest(registration_id, &error, &request_info);
+ EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
EXPECT_FALSE(request_info);
EXPECT_EQ(
GetRequestStats(sw_id),
@@ -1124,10 +1252,9 @@ TEST_F(BackgroundFetchDataManagerTest, PopNextRequestAndMarkAsComplete) {
std::vector<ServiceWorkerFetchRequest> requests(2u);
BackgroundFetchOptions options;
- blink::mojom::BackgroundFetchError error;
{
- EXPECT_CALL(*this, OnRegistrationCreated(registration_id, _, _, _, _));
+ EXPECT_CALL(*this, OnRegistrationCreated(registration_id, _, _, _, _, _));
CreateRegistration(registration_id, requests, options, SkBitmap(), &error);
ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
@@ -1139,7 +1266,8 @@ TEST_F(BackgroundFetchDataManagerTest, PopNextRequestAndMarkAsComplete) {
0 /* completed_requests */}));
// Popping should work now.
- PopNextRequest(registration_id, &request_info);
+ PopNextRequest(registration_id, &error, &request_info);
+ EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
EXPECT_TRUE(request_info);
EXPECT_EQ(request_info->request_index(), 0);
EXPECT_FALSE(request_info->download_guid().empty());
@@ -1150,7 +1278,8 @@ TEST_F(BackgroundFetchDataManagerTest, PopNextRequestAndMarkAsComplete) {
// Mark as complete.
AnnotateRequestInfoWithFakeDownloadManagerData(request_info.get());
- MarkRequestAsComplete(registration_id, request_info.get());
+ MarkRequestAsComplete(registration_id, request_info.get(), &error);
+ EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
ASSERT_EQ(
GetRequestStats(sw_id),
(ResponseStateStats{1 /* pending_requests */, 0 /* active_requests */,
@@ -1158,7 +1287,8 @@ TEST_F(BackgroundFetchDataManagerTest, PopNextRequestAndMarkAsComplete) {
RestartDataManagerFromPersistentStorage();
- PopNextRequest(registration_id, &request_info);
+ PopNextRequest(registration_id, &error, &request_info);
+ EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
EXPECT_TRUE(request_info);
EXPECT_EQ(request_info->request_index(), 1);
EXPECT_FALSE(request_info->download_guid().empty());
@@ -1169,14 +1299,16 @@ TEST_F(BackgroundFetchDataManagerTest, PopNextRequestAndMarkAsComplete) {
// Mark as complete.
AnnotateRequestInfoWithFakeDownloadManagerData(request_info.get());
- MarkRequestAsComplete(registration_id, request_info.get());
+ MarkRequestAsComplete(registration_id, request_info.get(), &error);
+ EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
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);
+ PopNextRequest(registration_id, &error, &request_info);
+ EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
EXPECT_FALSE(request_info);
EXPECT_EQ(
GetRequestStats(sw_id),
@@ -1184,7 +1316,7 @@ TEST_F(BackgroundFetchDataManagerTest, PopNextRequestAndMarkAsComplete) {
2 /* completed_requests */}));
}
-TEST_F(BackgroundFetchDataManagerTest, DownloadTotalUpdated) {
+TEST_F(BackgroundFetchDataManagerTest, DownloadedUpdated) {
int64_t sw_id = RegisterServiceWorker();
ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, sw_id);
@@ -1195,7 +1327,7 @@ TEST_F(BackgroundFetchDataManagerTest, DownloadTotalUpdated) {
BackgroundFetchOptions options;
blink::mojom::BackgroundFetchError error;
{
- EXPECT_CALL(*this, OnRegistrationCreated(registration_id, _, _, _, _));
+ EXPECT_CALL(*this, OnRegistrationCreated(registration_id, _, _, _, _, _));
CreateRegistration(registration_id, requests, options, SkBitmap(), &error);
ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
@@ -1204,36 +1336,42 @@ TEST_F(BackgroundFetchDataManagerTest, DownloadTotalUpdated) {
auto registration =
GetRegistration(sw_id, origin(), kExampleDeveloperId, &error);
ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
- EXPECT_EQ(registration.download_total, 0u);
+ EXPECT_EQ(registration.downloaded, 0u);
scoped_refptr<BackgroundFetchRequestInfo> request_info;
- PopNextRequest(registration_id, &request_info);
+ PopNextRequest(registration_id, &error, &request_info);
+ ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
AnnotateRequestInfoWithFakeDownloadManagerData(request_info.get(),
true /* succeeded */);
- MarkRequestAsComplete(registration_id, request_info.get());
+ MarkRequestAsComplete(registration_id, request_info.get(), &error);
+ EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
registration = GetRegistration(sw_id, origin(), kExampleDeveloperId, &error);
ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
- EXPECT_EQ(registration.download_total, kResponseFileSize);
+ EXPECT_EQ(registration.downloaded, kResponseFileSize);
- PopNextRequest(registration_id, &request_info);
+ PopNextRequest(registration_id, &error, &request_info);
+ ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
AnnotateRequestInfoWithFakeDownloadManagerData(request_info.get(),
true /* succeeded */);
- MarkRequestAsComplete(registration_id, request_info.get());
+ MarkRequestAsComplete(registration_id, request_info.get(), &error);
+ EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
registration = GetRegistration(sw_id, origin(), kExampleDeveloperId, &error);
ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
- EXPECT_EQ(registration.download_total, 2 * kResponseFileSize);
+ EXPECT_EQ(registration.downloaded, 2 * kResponseFileSize);
- PopNextRequest(registration_id, &request_info);
+ PopNextRequest(registration_id, &error, &request_info);
+ ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
AnnotateRequestInfoWithFakeDownloadManagerData(request_info.get(),
false /* succeeded */);
- MarkRequestAsComplete(registration_id, request_info.get());
+ MarkRequestAsComplete(registration_id, request_info.get(), &error);
+ EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
registration = GetRegistration(sw_id, origin(), kExampleDeveloperId, &error);
ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
- // |download_total| is unchanged.
- EXPECT_EQ(registration.download_total, 2 * kResponseFileSize);
+ // |registration.downloaded| is unchanged.
+ EXPECT_EQ(registration.downloaded, 2 * kResponseFileSize);
}
TEST_F(BackgroundFetchDataManagerTest, ExceedingQuotaAbandonsFetch) {
@@ -1247,19 +1385,21 @@ TEST_F(BackgroundFetchDataManagerTest, ExceedingQuotaAbandonsFetch) {
BackgroundFetchOptions options;
blink::mojom::BackgroundFetchError error;
{
- EXPECT_CALL(*this, OnRegistrationCreated(registration_id, _, _, _, _));
+ EXPECT_CALL(*this, OnRegistrationCreated(registration_id, _, _, _, _, _));
CreateRegistration(registration_id, requests, options, SkBitmap(), &error);
ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
}
scoped_refptr<BackgroundFetchRequestInfo> request_info;
- PopNextRequest(registration_id, &request_info);
+ PopNextRequest(registration_id, &error, &request_info);
+ ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
AnnotateRequestInfoWithFakeDownloadManagerData(
request_info.get(), true /* succeeded */, true /* over_quota */);
{
EXPECT_CALL(*this, OnQuotaExceeded(registration_id));
- MarkRequestAsComplete(registration_id, request_info.get());
+ MarkRequestAsComplete(registration_id, request_info.get(), &error);
+ EXPECT_EQ(error, blink::mojom::BackgroundFetchError::QUOTA_EXCEEDED);
}
}
@@ -1274,19 +1414,21 @@ TEST_F(BackgroundFetchDataManagerTest, WriteToCache) {
BackgroundFetchOptions options;
blink::mojom::BackgroundFetchError error;
{
- EXPECT_CALL(*this, OnRegistrationCreated(registration_id, _, _, _, _));
+ EXPECT_CALL(*this, OnRegistrationCreated(registration_id, _, _, _, _, _));
CreateRegistration(registration_id, requests, options, SkBitmap(), &error);
ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
}
scoped_refptr<BackgroundFetchRequestInfo> request_info;
- PopNextRequest(registration_id, &request_info);
+ PopNextRequest(registration_id, &error, &request_info);
+ EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
ASSERT_TRUE(request_info);
AnnotateRequestInfoWithFakeDownloadManagerData(request_info.get(),
true /* success */);
- MarkRequestAsComplete(registration_id, request_info.get());
+ MarkRequestAsComplete(registration_id, request_info.get(), &error);
+ EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
EXPECT_TRUE(HasCache(kExampleUniqueId));
EXPECT_FALSE(HasCache("foo"));
@@ -1294,12 +1436,14 @@ TEST_F(BackgroundFetchDataManagerTest, WriteToCache) {
EXPECT_TRUE(MatchCache(requests[0]));
EXPECT_FALSE(MatchCache(requests[1]));
- PopNextRequest(registration_id, &request_info);
+ PopNextRequest(registration_id, &error, &request_info);
+ EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
ASSERT_TRUE(request_info);
AnnotateRequestInfoWithFakeDownloadManagerData(request_info.get(),
true /* success */);
- MarkRequestAsComplete(registration_id, request_info.get());
+ MarkRequestAsComplete(registration_id, request_info.get(), &error);
+ EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
EXPECT_TRUE(MatchCache(requests[0]));
EXPECT_TRUE(MatchCache(requests[1]));
@@ -1321,19 +1465,21 @@ TEST_F(BackgroundFetchDataManagerTest, CacheDeleted) {
BackgroundFetchOptions options;
blink::mojom::BackgroundFetchError error;
{
- EXPECT_CALL(*this, OnRegistrationCreated(registration_id, _, _, _, _));
+ EXPECT_CALL(*this, OnRegistrationCreated(registration_id, _, _, _, _, _));
CreateRegistration(registration_id, {request}, options, SkBitmap(), &error);
ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
}
scoped_refptr<BackgroundFetchRequestInfo> request_info;
- PopNextRequest(registration_id, &request_info);
+ PopNextRequest(registration_id, &error, &request_info);
+ EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
ASSERT_TRUE(request_info);
AnnotateRequestInfoWithFakeDownloadManagerData(request_info.get(),
true /* success */);
- MarkRequestAsComplete(registration_id, request_info.get());
+ MarkRequestAsComplete(registration_id, request_info.get(), &error);
+ EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
EXPECT_TRUE(HasCache(kExampleUniqueId));
EXPECT_TRUE(MatchCache(request));
@@ -1358,7 +1504,7 @@ TEST_F(BackgroundFetchDataManagerTest, GetSettledFetchesForRegistration) {
sw_id, origin(), kExampleDeveloperId, kExampleUniqueId);
{
- EXPECT_CALL(*this, OnRegistrationCreated(registration_id, _, _, _, _));
+ EXPECT_CALL(*this, OnRegistrationCreated(registration_id, _, _, _, _, _));
CreateRegistration(registration_id, requests, options, SkBitmap(), &error);
ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
@@ -1370,22 +1516,24 @@ TEST_F(BackgroundFetchDataManagerTest, GetSettledFetchesForRegistration) {
0 /* completed_requests */}));
// Nothing is downloaded yet.
- bool succeeded = false;
+ blink::mojom::BackgroundFetchFailureReason failure_reason;
std::vector<BackgroundFetchSettledFetch> settled_fetches;
GetSettledFetchesForRegistration(
registration_id, base::nullopt /* request_to_match */,
nullptr /* cache_query_params */, false /* match_all */, &error,
- &succeeded, &settled_fetches);
+ &failure_reason, &settled_fetches);
EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
- EXPECT_TRUE(succeeded);
+ EXPECT_EQ(failure_reason, blink::mojom::BackgroundFetchFailureReason::NONE);
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);
+ PopNextRequest(registration_id, &error, &request_info);
+ EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
ASSERT_TRUE(request_info);
AnnotateRequestInfoWithFakeDownloadManagerData(request_info.get());
- MarkRequestAsComplete(registration_id, request_info.get());
+ MarkRequestAsComplete(registration_id, request_info.get(), &error);
+ EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
}
RestartDataManagerFromPersistentStorage();
@@ -1398,11 +1546,12 @@ TEST_F(BackgroundFetchDataManagerTest, GetSettledFetchesForRegistration) {
GetSettledFetchesForRegistration(
registration_id, base::nullopt /* request_to_match */,
nullptr /* cache_query_params */, false /* match_all */, &error,
- &succeeded, &settled_fetches);
+ &failure_reason, &settled_fetches);
EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
// We are marking the responses as failed in Download Manager.
- EXPECT_FALSE(succeeded);
+ EXPECT_EQ(failure_reason,
+ blink::mojom::BackgroundFetchFailureReason::BAD_STATUS);
EXPECT_EQ(settled_fetches.size(), requests.size());
}
@@ -1417,50 +1566,54 @@ TEST_F(BackgroundFetchDataManagerTest, GetSettledFetchesFromCache) {
BackgroundFetchOptions options;
blink::mojom::BackgroundFetchError error;
{
- EXPECT_CALL(*this, OnRegistrationCreated(registration_id, _, _, _, _));
+ EXPECT_CALL(*this, OnRegistrationCreated(registration_id, _, _, _, _, _));
CreateRegistration(registration_id, requests, options, SkBitmap(), &error);
ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
}
- bool succeeded = false;
+ blink::mojom::BackgroundFetchFailureReason failure_reason;
std::vector<BackgroundFetchSettledFetch> settled_fetches;
// Nothing is downloaded yet.
GetSettledFetchesForRegistration(
registration_id, base::nullopt /* request_to_match */,
nullptr /* cache_query_params */, false /* match_all */, &error,
- &succeeded, &settled_fetches);
+ &failure_reason, &settled_fetches);
EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
- EXPECT_TRUE(succeeded);
+ EXPECT_EQ(failure_reason, blink::mojom::BackgroundFetchFailureReason::NONE);
EXPECT_EQ(settled_fetches.size(), 0u);
scoped_refptr<BackgroundFetchRequestInfo> request_info;
- PopNextRequest(registration_id, &request_info);
+ PopNextRequest(registration_id, &error, &request_info);
+ EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
ASSERT_TRUE(request_info);
AnnotateRequestInfoWithFakeDownloadManagerData(request_info.get(),
true /* success */);
- MarkRequestAsComplete(registration_id, request_info.get());
+ MarkRequestAsComplete(registration_id, request_info.get(), &error);
+ EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
GetSettledFetchesForRegistration(
registration_id, base::nullopt /* request_to_match */,
nullptr /* cache_query_params */, false /* match_all */, &error,
- &succeeded, &settled_fetches);
+ &failure_reason, &settled_fetches);
EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
- EXPECT_TRUE(succeeded);
+ EXPECT_EQ(failure_reason, blink::mojom::BackgroundFetchFailureReason::NONE);
EXPECT_EQ(settled_fetches.size(), 1u);
- PopNextRequest(registration_id, &request_info);
+ PopNextRequest(registration_id, &error, &request_info);
+ EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
ASSERT_TRUE(request_info);
AnnotateRequestInfoWithFakeDownloadManagerData(request_info.get(),
true /* success */);
- MarkRequestAsComplete(registration_id, request_info.get());
+ MarkRequestAsComplete(registration_id, request_info.get(), &error);
+ EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
GetSettledFetchesForRegistration(
registration_id, base::nullopt /* request_to_match */,
nullptr /* cache_query_params */, false /* match_all */, &error,
- &succeeded, &settled_fetches);
+ &failure_reason, &settled_fetches);
EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
- EXPECT_TRUE(succeeded);
+ EXPECT_EQ(failure_reason, blink::mojom::BackgroundFetchFailureReason::NONE);
ASSERT_EQ(settled_fetches.size(), 2u);
// Sanity check that the responses are written to / read from the cache.
@@ -1476,9 +1629,9 @@ TEST_F(BackgroundFetchDataManagerTest, GetSettledFetchesFromCache) {
GetSettledFetchesForRegistration(
registration_id, base::nullopt /* request_to_match */,
nullptr /* cache_query_params */, false /* match_all */, &error,
- &succeeded, &settled_fetches);
+ &failure_reason, &settled_fetches);
EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
- EXPECT_TRUE(succeeded);
+ EXPECT_EQ(failure_reason, blink::mojom::BackgroundFetchFailureReason::NONE);
EXPECT_EQ(settled_fetches.size(), 2u);
}
@@ -1493,7 +1646,7 @@ TEST_F(BackgroundFetchDataManagerTest, GetSettledFetchesForASpecificRequest) {
sw_id, origin(), kExampleDeveloperId, kExampleUniqueId);
{
- EXPECT_CALL(*this, OnRegistrationCreated(registration_id, _, _, _, _));
+ EXPECT_CALL(*this, OnRegistrationCreated(registration_id, _, _, _, _, _));
CreateRegistration(registration_id, requests, options, SkBitmap(), &error);
ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
@@ -1502,10 +1655,12 @@ TEST_F(BackgroundFetchDataManagerTest, GetSettledFetchesForASpecificRequest) {
for (size_t i = 0; i < requests.size(); i++) {
SCOPED_TRACE(i);
scoped_refptr<BackgroundFetchRequestInfo> request_info;
- PopNextRequest(registration_id, &request_info);
+ PopNextRequest(registration_id, &error, &request_info);
+ EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
ASSERT_TRUE(request_info);
AnnotateRequestInfoWithFakeDownloadManagerData(request_info.get());
- MarkRequestAsComplete(registration_id, request_info.get());
+ MarkRequestAsComplete(registration_id, request_info.get(), &error);
+ EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
}
EXPECT_EQ(
@@ -1513,16 +1668,17 @@ TEST_F(BackgroundFetchDataManagerTest, GetSettledFetchesForASpecificRequest) {
(ResponseStateStats{0 /* pending_requests */, 0 /* active_requests */,
requests.size() /* completed_requests */}));
- bool succeeded = false;
+ blink::mojom::BackgroundFetchFailureReason failure_reason;
std::vector<BackgroundFetchSettledFetch> settled_fetches;
GetSettledFetchesForRegistration(
registration_id, requests[0] /* request_to_match */,
nullptr /* cache_query_params */, false /* match_all */, &error,
- &succeeded, &settled_fetches);
+ &failure_reason, &settled_fetches);
ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
// We are marking the responses as failed in Download Manager.
- EXPECT_FALSE(succeeded);
+ EXPECT_EQ(failure_reason,
+ blink::mojom::BackgroundFetchFailureReason::BAD_STATUS);
EXPECT_EQ(settled_fetches.size(), 1u);
}
@@ -1538,7 +1694,7 @@ TEST_F(BackgroundFetchDataManagerTest,
sw_id, origin(), kExampleDeveloperId, kExampleUniqueId);
{
- EXPECT_CALL(*this, OnRegistrationCreated(registration_id, _, _, _, _));
+ EXPECT_CALL(*this, OnRegistrationCreated(registration_id, _, _, _, _, _));
CreateRegistration(registration_id, requests, options, SkBitmap(), &error);
ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
@@ -1547,10 +1703,12 @@ TEST_F(BackgroundFetchDataManagerTest,
for (size_t i = 0; i < requests.size() - 1; i++) {
SCOPED_TRACE(i);
scoped_refptr<BackgroundFetchRequestInfo> request_info;
- PopNextRequest(registration_id, &request_info);
+ PopNextRequest(registration_id, &error, &request_info);
+ EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
ASSERT_TRUE(request_info);
AnnotateRequestInfoWithFakeDownloadManagerData(request_info.get());
- MarkRequestAsComplete(registration_id, request_info.get());
+ MarkRequestAsComplete(registration_id, request_info.get(), &error);
+ EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
}
EXPECT_EQ(
@@ -1558,12 +1716,12 @@ TEST_F(BackgroundFetchDataManagerTest,
(ResponseStateStats{1 /* pending_requests */, 0 /* active_requests */,
requests.size() - 1 /* completed_requests */}));
- bool succeeded = false;
+ blink::mojom::BackgroundFetchFailureReason failure_reason;
std::vector<BackgroundFetchSettledFetch> settled_fetches;
GetSettledFetchesForRegistration(
registration_id, requests[2] /* request_to_match */,
nullptr /* cache_query_params */, false /* match_all */, &error,
- &succeeded, &settled_fetches);
+ &failure_reason, &settled_fetches);
ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
EXPECT_EQ(settled_fetches.size(), 1u);
EXPECT_EQ(settled_fetches[0].response->response_type,
@@ -1584,7 +1742,7 @@ TEST_F(BackgroundFetchDataManagerTest, IgnoreMethodAndMatchAll) {
sw_id, origin(), kExampleDeveloperId, kExampleUniqueId);
{
- EXPECT_CALL(*this, OnRegistrationCreated(registration_id, _, _, _, _));
+ EXPECT_CALL(*this, OnRegistrationCreated(registration_id, _, _, _, _, _));
CreateRegistration(registration_id, requests, options, SkBitmap(), &error);
ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
@@ -1593,10 +1751,12 @@ TEST_F(BackgroundFetchDataManagerTest, IgnoreMethodAndMatchAll) {
for (size_t i = 0; i < requests.size(); i++) {
SCOPED_TRACE(i);
scoped_refptr<BackgroundFetchRequestInfo> request_info;
- PopNextRequest(registration_id, &request_info);
+ PopNextRequest(registration_id, &error, &request_info);
+ EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
ASSERT_TRUE(request_info);
AnnotateRequestInfoWithFakeDownloadManagerData(request_info.get());
- MarkRequestAsComplete(registration_id, request_info.get());
+ MarkRequestAsComplete(registration_id, request_info.get(), &error);
+ EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
}
EXPECT_EQ(
@@ -1604,19 +1764,20 @@ TEST_F(BackgroundFetchDataManagerTest, IgnoreMethodAndMatchAll) {
(ResponseStateStats{0 /* pending_requests */, 0 /* active_requests */,
requests.size() /* completed_requests */}));
- bool succeeded = false;
+ blink::mojom::BackgroundFetchFailureReason failure_reason;
std::vector<BackgroundFetchSettledFetch> settled_fetches;
blink::mojom::QueryParamsPtr cache_query_params =
blink::mojom::QueryParams::New();
cache_query_params->ignore_method = true;
GetSettledFetchesForRegistration(
registration_id, requests[0] /* request_to_match */,
- std::move(cache_query_params), true /* match_all */, &error, &succeeded,
- &settled_fetches);
+ std::move(cache_query_params), true /* match_all */, &error,
+ &failure_reason, &settled_fetches);
ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
// We are marking the responses as failed in Download Manager.
- EXPECT_FALSE(succeeded);
+ EXPECT_EQ(failure_reason,
+ blink::mojom::BackgroundFetchFailureReason::BAD_STATUS);
// If the ASSERT below fails, the Cache Storage API implementation has likely
// changed to distinguish keys by request data other than just the URL.
// Thank you! Please can you update the 1u below to 2u, or file a bug against
@@ -1642,7 +1803,7 @@ TEST_F(BackgroundFetchDataManagerTest, Cleanup) {
GetRegistrationUserDataByKeyPrefix(sw_id, kUserDataPrefix).size());
// Create a registration.
{
- EXPECT_CALL(*this, OnRegistrationCreated(registration_id, _, _, _, _));
+ EXPECT_CALL(*this, OnRegistrationCreated(registration_id, _, _, _, _, _));
CreateRegistration(registration_id, requests, options, SkBitmap(), &error);
ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
@@ -1660,12 +1821,7 @@ TEST_F(BackgroundFetchDataManagerTest, Cleanup) {
RestartDataManagerFromPersistentStorage();
- // Pending Requests should be deleted after marking a registration for
- // deletion.
- EXPECT_EQ(0u, GetRegistrationUserDataByKeyPrefix(
- sw_id, background_fetch::kPendingRequestKeyPrefix)
- .size());
- EXPECT_EQ(2u, // Metadata proto + title.
+ EXPECT_EQ(4u, // Metadata proto + UI options + remaining pending fetches.
GetRegistrationUserDataByKeyPrefix(sw_id, kUserDataPrefix).size());
// Cleanup should delete the registration.
@@ -1708,7 +1864,7 @@ TEST_F(BackgroundFetchDataManagerTest, GetInitializationData) {
sw_id, origin(), kExampleDeveloperId, kExampleUniqueId);
{
- EXPECT_CALL(*this, OnRegistrationCreated(registration_id, _, _, _, _));
+ EXPECT_CALL(*this, OnRegistrationCreated(registration_id, _, _, _, _, _));
CreateRegistration(registration_id, requests, options, CreateTestIcon(),
&error);
@@ -1738,11 +1894,16 @@ TEST_F(BackgroundFetchDataManagerTest, GetInitializationData) {
// Mark one request as complete and start another.
scoped_refptr<BackgroundFetchRequestInfo> request_info;
- PopNextRequest(registration_id, &request_info);
+ PopNextRequest(registration_id, &error, &request_info);
+ EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
ASSERT_TRUE(request_info);
+
AnnotateRequestInfoWithFakeDownloadManagerData(request_info.get());
- MarkRequestAsComplete(registration_id, request_info.get());
- PopNextRequest(registration_id, &request_info);
+ MarkRequestAsComplete(registration_id, request_info.get(), &error);
+ EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+
+ PopNextRequest(registration_id, &error, &request_info);
+ EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
ASSERT_TRUE(request_info);
{
std::vector<BackgroundFetchInitializationData> data =
@@ -1767,7 +1928,7 @@ TEST_F(BackgroundFetchDataManagerTest, GetInitializationData) {
BackgroundFetchRegistrationId registration_id2(
sw_id, origin(), kAlternativeDeveloperId, kAlternativeUniqueId);
{
- EXPECT_CALL(*this, OnRegistrationCreated(registration_id2, _, _, _, _));
+ EXPECT_CALL(*this, OnRegistrationCreated(registration_id2, _, _, _, _, _));
CreateRegistration(registration_id2, requests, options, SkBitmap(), &error);
ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
@@ -1794,7 +1955,7 @@ TEST_F(BackgroundFetchDataManagerTest, CreateInParallel) {
std::vector<blink::mojom::BackgroundFetchError> errors(5);
// We expect a single successful registration to be created.
- EXPECT_CALL(*this, OnRegistrationCreated(_, _, _, _, _));
+ EXPECT_CALL(*this, OnRegistrationCreated(_, _, _, _, _, _));
const int num_parallel_creates = 5;
@@ -1810,6 +1971,7 @@ TEST_F(BackgroundFetchDataManagerTest, CreateInParallel) {
background_fetch_data_manager_->CreateRegistration(
registration_id, requests, options, SkBitmap(),
+ /* start_paused = */ false,
base::BindOnce(&DidCreateRegistration, quit_once_all_finished_closure,
&errors[i]));
}
@@ -1868,20 +2030,22 @@ TEST_F(BackgroundFetchDataManagerTest, StorageErrorsReported) {
}
scoped_refptr<BackgroundFetchRequestInfo> request_info;
- PopNextRequest(registration_id, &request_info);
+ PopNextRequest(registration_id, &error, &request_info);
+ EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
ASSERT_TRUE(request_info);
AnnotateRequestInfoWithFakeDownloadManagerData(request_info.get(),
true /* success */);
- MarkRequestAsComplete(registration_id, request_info.get());
+ MarkRequestAsComplete(registration_id, request_info.get(), &error);
+ EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
- bool succeeded = false;
+ blink::mojom::BackgroundFetchFailureReason failure_reason;
std::vector<BackgroundFetchSettledFetch> settled_fetches;
{
GetSettledFetchesForRegistration(
registration_id, base::nullopt /* request_to_match */,
nullptr /* cache_query_params */, false /* match_all */, &error,
- &succeeded, &settled_fetches);
+ &failure_reason, &settled_fetches);
ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
}
@@ -1896,7 +2060,7 @@ TEST_F(BackgroundFetchDataManagerTest, StorageErrorsReported) {
GetSettledFetchesForRegistration(
registration_id, base::nullopt /* request_to_match */,
nullptr /* cache_query_params */, false /* match_all */, &error,
- &succeeded, &settled_fetches);
+ &failure_reason, &settled_fetches);
ASSERT_EQ(error, blink::mojom::BackgroundFetchError::STORAGE_ERROR);
histogram_tester.ExpectBucketCount(
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 c8048feda17..79ca6513c22 100644
--- a/chromium/content/browser/background_fetch/background_fetch_delegate_proxy.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_delegate_proxy.cc
@@ -6,11 +6,13 @@
#include <utility>
+#include "base/task/post_task.h"
#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/browser_task_traits.h"
#include "content/public/browser/download_manager.h"
#include "ui/gfx/geometry/size.h"
@@ -43,11 +45,10 @@ class BackgroundFetchDelegateProxy::Core
void ForwardGetPermissionForOriginCallbackToIO(
BackgroundFetchDelegate::GetPermissionForOriginCallback callback,
- bool has_permission) {
+ BackgroundFetchPermission permission) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(std::move(callback), has_permission));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(std::move(callback), permission));
}
void GetPermissionForOrigin(
@@ -60,7 +61,7 @@ class BackgroundFetchDelegateProxy::Core
base::BindOnce(&Core::ForwardGetPermissionForOriginCallbackToIO,
weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
} else {
- std::move(callback).Run(false /* has_permission */);
+ std::move(callback).Run(BackgroundFetchPermission::BLOCKED);
}
}
@@ -68,8 +69,8 @@ class BackgroundFetchDelegateProxy::Core
BackgroundFetchDelegate::GetIconDisplaySizeCallback callback,
const gfx::Size& display_size) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::BindOnce(std::move(callback), display_size));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(std::move(callback), display_size));
}
void GetIconDisplaySize(
@@ -81,8 +82,8 @@ class BackgroundFetchDelegateProxy::Core
base::BindOnce(&Core::ForwardGetIconDisplaySizeCallbackToIO,
weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
} else {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(std::move(callback), gfx::Size(0, 0)));
}
}
@@ -91,6 +92,13 @@ class BackgroundFetchDelegateProxy::Core
std::unique_ptr<BackgroundFetchDescription> fetch_description) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ // If there are multiple clients created we might have registered the wrong
+ // one with the delegate by overwriting it. This check makes sure that we
+ // register the correct client until multiple clients are supported.
+ // TODO(crbug.com/907075): Support multiple clients.
+ if (delegate_ && delegate_->client().get() != this)
+ delegate_->SetDelegateClient(GetWeakPtrOnUI());
+
if (delegate_)
delegate_->CreateDownloadJob(std::move(fetch_description));
}
@@ -176,8 +184,9 @@ class BackgroundFetchDelegateProxy::Core
}
// BackgroundFetchDelegate::Client implementation:
- void OnJobCancelled(const std::string& job_unique_id,
- BackgroundFetchReasonToAbort reason_to_abort) override;
+ void OnJobCancelled(
+ const std::string& job_unique_id,
+ blink::mojom::BackgroundFetchFailureReason reason_to_abort) override;
void OnDownloadUpdated(const std::string& job_unique_id,
const std::string& guid,
uint64_t bytes_downloaded) override;
@@ -207,10 +216,10 @@ class BackgroundFetchDelegateProxy::Core
void BackgroundFetchDelegateProxy::Core::OnJobCancelled(
const std::string& job_unique_id,
- BackgroundFetchReasonToAbort reason_to_abort) {
+ blink::mojom::BackgroundFetchFailureReason reason_to_abort) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&BackgroundFetchDelegateProxy::OnJobCancelled, io_parent_,
job_unique_id, reason_to_abort));
}
@@ -220,8 +229,8 @@ void BackgroundFetchDelegateProxy::Core::OnDownloadUpdated(
const std::string& guid,
uint64_t bytes_downloaded) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&BackgroundFetchDelegateProxy::OnDownloadUpdated,
io_parent_, job_unique_id, guid, bytes_downloaded));
}
@@ -231,8 +240,8 @@ void BackgroundFetchDelegateProxy::Core::OnDownloadComplete(
const std::string& guid,
std::unique_ptr<BackgroundFetchResult> result) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&BackgroundFetchDelegateProxy::OnDownloadComplete,
io_parent_, job_unique_id, guid, std::move(result)));
}
@@ -243,8 +252,8 @@ void BackgroundFetchDelegateProxy::Core::OnDownloadStarted(
std::unique_ptr<content::BackgroundFetchResponse> response) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&BackgroundFetchDelegateProxy::DidStartRequest, io_parent_,
job_unique_id, guid, std::move(response)));
}
@@ -253,8 +262,8 @@ void BackgroundFetchDelegateProxy::Core::OnUIActivated(
const std::string& job_unique_id) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&BackgroundFetchDelegateProxy::DidActivateUI, io_parent_,
job_unique_id));
}
@@ -307,9 +316,9 @@ void BackgroundFetchDelegateProxy::SetClickEventDispatcher(
void BackgroundFetchDelegateProxy::GetIconDisplaySize(
BackgroundFetchDelegate::GetIconDisplaySizeCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(&Core::GetIconDisplaySize,
- ui_core_ptr_, std::move(callback)));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(&Core::GetIconDisplaySize,
+ ui_core_ptr_, std::move(callback)));
}
void BackgroundFetchDelegateProxy::GetPermissionForOrigin(
@@ -317,8 +326,8 @@ void BackgroundFetchDelegateProxy::GetPermissionForOrigin(
const ResourceRequestInfo::WebContentsGetter& wc_getter,
BackgroundFetchDelegate::GetPermissionForOriginCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&Core::GetPermissionForOrigin, ui_core_ptr_, origin,
wc_getter, std::move(callback)));
}
@@ -335,9 +344,10 @@ void BackgroundFetchDelegateProxy::CreateDownloadJob(
fetch_description->job_unique_id,
JobDetails(controller, std::move(active_fetch_requests)));
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(&Core::CreateDownloadJob, ui_core_ptr_,
- std::move(fetch_description)));
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(&Core::CreateDownloadJob, ui_core_ptr_,
+ std::move(fetch_description)));
}
void BackgroundFetchDelegateProxy::StartRequest(
@@ -355,9 +365,9 @@ void BackgroundFetchDelegateProxy::StartRequest(
job_details.current_request_map[download_guid] = request;
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(&Core::StartRequest, ui_core_ptr_,
- job_unique_id, origin, request));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(&Core::StartRequest, ui_core_ptr_,
+ job_unique_id, origin, request));
}
void BackgroundFetchDelegateProxy::UpdateUI(
@@ -366,16 +376,16 @@ void BackgroundFetchDelegateProxy::UpdateUI(
const base::Optional<SkBitmap>& icon) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(&Core::UpdateUI, ui_core_ptr_,
- job_unique_id, title, icon));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(&Core::UpdateUI, ui_core_ptr_,
+ job_unique_id, title, icon));
}
void BackgroundFetchDelegateProxy::Abort(const std::string& job_unique_id) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&Core::Abort, ui_core_ptr_, job_unique_id));
job_details_map_.erase(job_unique_id);
@@ -383,11 +393,12 @@ void BackgroundFetchDelegateProxy::Abort(const std::string& job_unique_id) {
void BackgroundFetchDelegateProxy::OnJobCancelled(
const std::string& job_unique_id,
- BackgroundFetchReasonToAbort reason_to_abort) {
+ blink::mojom::BackgroundFetchFailureReason reason_to_abort) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(reason_to_abort == BackgroundFetchReasonToAbort::CANCELLED_FROM_UI ||
- reason_to_abort ==
- BackgroundFetchReasonToAbort::TOTAL_DOWNLOAD_SIZE_EXCEEDED);
+ DCHECK(reason_to_abort ==
+ blink::mojom::BackgroundFetchFailureReason::CANCELLED_FROM_UI ||
+ reason_to_abort == blink::mojom::BackgroundFetchFailureReason::
+ TOTAL_DOWNLOAD_SIZE_EXCEEDED);
// TODO(delphick): The controller may not exist as persistence is not yet
// implemented.
@@ -419,8 +430,6 @@ void BackgroundFetchDelegateProxy::DidStartRequest(
DCHECK(request_info);
DCHECK_EQ(guid, request_info->download_guid());
- request_info->PopulateWithResponse(std::move(response));
-
if (job_details.controller)
job_details.controller->DidStartRequest(request_info);
}
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 d393db41cfc..e877ab60cfe 100644
--- a/chromium/content/browser/background_fetch/background_fetch_delegate_proxy.h
+++ b/chromium/content/browser/background_fetch/background_fetch_delegate_proxy.h
@@ -20,6 +20,7 @@
#include "content/public/browser/background_fetch_description.h"
#include "content/public/browser/background_fetch_response.h"
#include "content/public/browser/browser_thread.h"
+#include "third_party/blink/public/platform/modules/background_fetch/background_fetch.mojom.h"
namespace content {
@@ -48,7 +49,7 @@ class CONTENT_EXPORT BackgroundFetchDelegateProxy {
const scoped_refptr<BackgroundFetchRequestInfo>& request) = 0;
// Called when the delegate aborts a Background Fetch registration.
- virtual void Abort(BackgroundFetchReasonToAbort) = 0;
+ virtual void Abort(blink::mojom::BackgroundFetchFailureReason) = 0;
virtual ~Controller() {}
};
@@ -114,8 +115,9 @@ 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,
- BackgroundFetchReasonToAbort reason_to_abort);
+ void OnJobCancelled(
+ const std::string& job_unique_id,
+ blink::mojom::BackgroundFetchFailureReason 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 8d142789922..b5b5e2e94bf 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
@@ -9,12 +9,15 @@
#include "base/memory/weak_ptr.h"
#include "base/run_loop.h"
+#include "base/task/post_task.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_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/platform/modules/background_fetch/background_fetch.mojom.h"
namespace content {
@@ -37,7 +40,7 @@ class FakeBackgroundFetchDelegate : public BackgroundFetchDelegate {
const url::Origin& origin,
const ResourceRequestInfo::WebContentsGetter& wc_getter,
GetPermissionForOriginCallback callback) override {
- std::move(callback).Run(true /* has_permission */);
+ std::move(callback).Run(BackgroundFetchPermission::ALLOWED);
}
void CreateDownloadJob(
std::unique_ptr<BackgroundFetchDescription> fetch_description) override {}
@@ -51,6 +54,7 @@ class FakeBackgroundFetchDelegate : public BackgroundFetchDelegate {
return;
download_guid_to_job_id_map_[guid] = job_unique_id;
+ download_guid_to_url_map_[guid] = url;
auto response = std::make_unique<BackgroundFetchResponse>(
std::vector<GURL>({url}),
@@ -58,8 +62,8 @@ class FakeBackgroundFetchDelegate : public BackgroundFetchDelegate {
client()->OnDownloadStarted(job_unique_id, guid, std::move(response));
if (complete_downloads_) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&FakeBackgroundFetchDelegate::CompleteDownload,
base::Unretained(this), job_unique_id, guid));
}
@@ -89,14 +93,21 @@ class FakeBackgroundFetchDelegate : public BackgroundFetchDelegate {
if (aborted_jobs_.count(download_guid_to_job_id_map_[guid]))
return;
- client()->OnDownloadComplete(job_unique_id, guid,
- std::make_unique<BackgroundFetchResult>(
- base::Time::Now(), base::FilePath(),
- base::nullopt /* blob_handle */, 10u));
+ auto response = std::make_unique<BackgroundFetchResponse>(
+ std::vector<GURL>({download_guid_to_url_map_[guid]}),
+ base::MakeRefCounted<net::HttpResponseHeaders>("200 OK"));
+
+ client()->OnDownloadComplete(
+ job_unique_id, guid,
+ std::make_unique<BackgroundFetchResult>(
+ std::move(response), base::Time::Now(), base::FilePath(),
+ base::nullopt /* blob_handle */, 10u));
+ download_guid_to_url_map_.erase(guid);
}
std::set<std::string> aborted_jobs_;
std::map<std::string, std::string> download_guid_to_job_id_map_;
+ std::map<std::string, GURL> download_guid_to_url_map_;
bool complete_downloads_ = true;
};
@@ -118,7 +129,8 @@ class FakeController : public BackgroundFetchDelegateProxy::Controller {
request_completed_ = true;
}
- void Abort(BackgroundFetchReasonToAbort reason_to_abort) override {}
+ void Abort(
+ blink::mojom::BackgroundFetchFailureReason reason_to_abort) override {}
bool request_started_ = false;
bool request_completed_ = false;
@@ -168,7 +180,7 @@ TEST_F(BackgroundFetchDelegateProxyTest, StartRequest) {
kExampleUniqueId, "Job 1", url::Origin(), SkBitmap(),
0 /* completed_parts */, 1 /* total_parts */,
0 /* completed_parts_size */, 0 /* total_parts_size */,
- std::vector<std::string>());
+ std::vector<std::string>(), /* start_paused = */ false);
delegate_proxy_.CreateDownloadJob(controller.weak_ptr_factory_.GetWeakPtr(),
std::move(fetch_description),
{} /* active_fetch_requests */);
@@ -193,7 +205,7 @@ TEST_F(BackgroundFetchDelegateProxyTest, StartRequest_NotCompleted) {
kExampleUniqueId, "Job 1", url::Origin(), SkBitmap(),
0 /* completed_parts */, 1 /* total_parts */,
0 /* completed_parts_size */, 0 /* total_parts_size */,
- std::vector<std::string>());
+ std::vector<std::string>(), /* start_paused = */ false);
delegate_proxy_.CreateDownloadJob(controller.weak_ptr_factory_.GetWeakPtr(),
std::move(fetch_description),
{} /* active_fetch_requests */);
@@ -222,7 +234,7 @@ TEST_F(BackgroundFetchDelegateProxyTest, Abort) {
kExampleUniqueId, "Job 1", url::Origin(), SkBitmap(),
0 /* completed_parts */, 1 /* total_parts */,
0 /* completed_parts_size */, 0 /* total_parts_size */,
- std::vector<std::string>());
+ std::vector<std::string>(), /* start_paused = */ false);
delegate_proxy_.CreateDownloadJob(controller.weak_ptr_factory_.GetWeakPtr(),
std::move(fetch_description1),
{} /* active_fetch_requests */);
@@ -231,7 +243,7 @@ TEST_F(BackgroundFetchDelegateProxyTest, Abort) {
kExampleUniqueId2, "Job 2", url::Origin(), SkBitmap(),
0 /* completed_parts */, 1 /* total_parts */,
0 /* completed_parts_size */, 0 /* total_parts_size */,
- std::vector<std::string>());
+ std::vector<std::string>(), /* start_paused = */ false);
delegate_proxy_.CreateDownloadJob(controller2.weak_ptr_factory_.GetWeakPtr(),
std::move(fetch_description2),
{} /* active_fetch_requests */);
@@ -267,7 +279,7 @@ TEST_F(BackgroundFetchDelegateProxyTest, UpdateUI) {
kExampleUniqueId, "Job 1 Started.", url::Origin(), SkBitmap(),
0 /* completed_parts */, 1 /* total_parts */,
0 /* completed_parts_size */, 0 /* total_parts_size */,
- std::vector<std::string>());
+ std::vector<std::string>(), /* start_paused = */ false);
delegate_proxy_.CreateDownloadJob(controller.weak_ptr_factory_.GetWeakPtr(),
std::move(fetch_description),
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 b1ba4db1748..48338d12f0b 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
@@ -25,10 +25,10 @@ void BackgroundFetchEmbeddedWorkerTestHelper::OnBackgroundFetchAbortEvent(
if (fail_abort_event_) {
std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::REJECTED,
- base::Time::Now());
+ base::TimeTicks::Now());
} else {
std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
- base::Time::Now());
+ base::TimeTicks::Now());
}
if (abort_event_closure_)
@@ -42,10 +42,10 @@ void BackgroundFetchEmbeddedWorkerTestHelper::OnBackgroundFetchClickEvent(
if (fail_click_event_) {
std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::REJECTED,
- base::Time::Now());
+ base::TimeTicks::Now());
} else {
std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
- base::Time::Now());
+ base::TimeTicks::Now());
}
if (click_event_closure_)
@@ -59,10 +59,10 @@ void BackgroundFetchEmbeddedWorkerTestHelper::OnBackgroundFetchFailEvent(
if (fail_fetch_fail_event_) {
std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::REJECTED,
- base::Time::Now());
+ base::TimeTicks::Now());
} else {
std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
- base::Time::Now());
+ base::TimeTicks::Now());
}
if (fetch_fail_event_closure_)
@@ -77,10 +77,10 @@ void BackgroundFetchEmbeddedWorkerTestHelper::OnBackgroundFetchSuccessEvent(
if (fail_fetched_event_) {
std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::REJECTED,
- base::Time::Now());
+ base::TimeTicks::Now());
} else {
std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
- base::Time::Now());
+ base::TimeTicks::Now());
}
if (fetched_event_closure_)
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 415e48ebf61..d897cb81851 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
@@ -48,7 +48,7 @@ TEST_F(BackgroundFetchEventDispatcherTest, DispatchInvalidRegistration) {
auto registration = CreateBackgroundFetchRegistration(
invalid_registration_id.developer_id(),
invalid_registration_id.unique_id(),
- blink::mojom::BackgroundFetchState::FAILURE,
+ blink::mojom::BackgroundFetchResult::FAILURE,
blink::mojom::BackgroundFetchFailureReason::QUOTA_EXCEEDED);
event_dispatcher_.DispatchBackgroundFetchAbortEvent(
invalid_registration_id, std::move(registration), run_loop.QuitClosure());
@@ -79,7 +79,7 @@ TEST_F(BackgroundFetchEventDispatcherTest, DispatchAbortEvent) {
base::RunLoop run_loop;
auto registration = CreateBackgroundFetchRegistration(
kExampleDeveloperId, kExampleUniqueId,
- blink::mojom::BackgroundFetchState::FAILURE,
+ blink::mojom::BackgroundFetchResult::FAILURE,
blink::mojom::BackgroundFetchFailureReason::CANCELLED_FROM_UI);
event_dispatcher_.DispatchBackgroundFetchAbortEvent(
registration_id, std::move(registration), run_loop.QuitClosure());
@@ -109,7 +109,7 @@ TEST_F(BackgroundFetchEventDispatcherTest, DispatchAbortEvent) {
base::RunLoop run_loop;
auto registration = CreateBackgroundFetchRegistration(
kExampleDeveloperId2, kExampleUniqueId2,
- blink::mojom::BackgroundFetchState::FAILURE,
+ blink::mojom::BackgroundFetchResult::FAILURE,
blink::mojom::BackgroundFetchFailureReason::QUOTA_EXCEEDED);
event_dispatcher_.DispatchBackgroundFetchAbortEvent(second_registration_id,
std::move(registration),
@@ -148,7 +148,7 @@ TEST_F(BackgroundFetchEventDispatcherTest, DispatchClickEvent) {
base::RunLoop run_loop;
auto registration = CreateBackgroundFetchRegistration(
kExampleDeveloperId, kExampleUniqueId,
- blink::mojom::BackgroundFetchState::PENDING,
+ blink::mojom::BackgroundFetchResult::UNSET,
blink::mojom::BackgroundFetchFailureReason::NONE);
event_dispatcher_.DispatchBackgroundFetchClickEvent(
registration_id, std::move(registration), run_loop.QuitClosure());
@@ -159,8 +159,8 @@ TEST_F(BackgroundFetchEventDispatcherTest, DispatchClickEvent) {
ASSERT_TRUE(embedded_worker_test_helper()->last_registration().has_value());
EXPECT_EQ(kExampleDeveloperId,
embedded_worker_test_helper()->last_registration()->developer_id);
- EXPECT_EQ(blink::mojom::BackgroundFetchState::PENDING,
- embedded_worker_test_helper()->last_registration()->state);
+ EXPECT_EQ(blink::mojom::BackgroundFetchResult::UNSET,
+ embedded_worker_test_helper()->last_registration()->result);
histogram_tester_.ExpectUniqueSample(
"BackgroundFetch.EventDispatchResult.ClickEvent",
@@ -176,7 +176,7 @@ TEST_F(BackgroundFetchEventDispatcherTest, DispatchClickEvent) {
base::RunLoop run_loop;
auto registration = CreateBackgroundFetchRegistration(
kExampleDeveloperId2, kExampleUniqueId2,
- blink::mojom::BackgroundFetchState::FAILURE,
+ blink::mojom::BackgroundFetchResult::FAILURE,
blink::mojom::BackgroundFetchFailureReason::QUOTA_EXCEEDED);
event_dispatcher_.DispatchBackgroundFetchClickEvent(second_registration_id,
std::move(registration),
@@ -188,8 +188,8 @@ TEST_F(BackgroundFetchEventDispatcherTest, DispatchClickEvent) {
ASSERT_TRUE(embedded_worker_test_helper()->last_registration().has_value());
EXPECT_EQ(kExampleDeveloperId2,
embedded_worker_test_helper()->last_registration()->developer_id);
- EXPECT_EQ(blink::mojom::BackgroundFetchState::FAILURE,
- embedded_worker_test_helper()->last_registration()->state);
+ EXPECT_EQ(blink::mojom::BackgroundFetchResult::FAILURE,
+ embedded_worker_test_helper()->last_registration()->result);
histogram_tester_.ExpectBucketCount(
"BackgroundFetch.EventDispatchResult.ClickEvent",
@@ -215,7 +215,7 @@ TEST_F(BackgroundFetchEventDispatcherTest, DispatchFailEvent) {
base::RunLoop run_loop;
auto registration = CreateBackgroundFetchRegistration(
kExampleDeveloperId, kExampleUniqueId,
- blink::mojom::BackgroundFetchState::FAILURE,
+ blink::mojom::BackgroundFetchResult::FAILURE,
blink::mojom::BackgroundFetchFailureReason::QUOTA_EXCEEDED);
event_dispatcher_.DispatchBackgroundFetchFailEvent(
registration_id, std::move(registration), run_loop.QuitClosure());
@@ -241,7 +241,7 @@ TEST_F(BackgroundFetchEventDispatcherTest, DispatchFailEvent) {
base::RunLoop run_loop;
auto registration = CreateBackgroundFetchRegistration(
kExampleDeveloperId2, kExampleUniqueId2,
- blink::mojom::BackgroundFetchState::FAILURE,
+ blink::mojom::BackgroundFetchResult::FAILURE,
blink::mojom::BackgroundFetchFailureReason::QUOTA_EXCEEDED);
event_dispatcher_.DispatchBackgroundFetchFailEvent(second_registration_id,
std::move(registration),
@@ -277,7 +277,7 @@ TEST_F(BackgroundFetchEventDispatcherTest, DispatchFetchSuccessEvent) {
base::RunLoop run_loop;
auto registration = CreateBackgroundFetchRegistration(
kExampleDeveloperId, kExampleUniqueId,
- blink::mojom::BackgroundFetchState::SUCCESS,
+ blink::mojom::BackgroundFetchResult::SUCCESS,
blink::mojom::BackgroundFetchFailureReason::NONE);
event_dispatcher_.DispatchBackgroundFetchSuccessEvent(
registration_id, std::move(registration), run_loop.QuitClosure());
@@ -306,7 +306,7 @@ TEST_F(BackgroundFetchEventDispatcherTest, DispatchFetchSuccessEvent) {
base::RunLoop run_loop;
auto registration = CreateBackgroundFetchRegistration(
kExampleDeveloperId2, kExampleUniqueId2,
- blink::mojom::BackgroundFetchState::SUCCESS,
+ blink::mojom::BackgroundFetchResult::SUCCESS,
blink::mojom::BackgroundFetchFailureReason::NONE);
event_dispatcher_.DispatchBackgroundFetchSuccessEvent(
second_registration_id, std::move(registration),
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 a2e82ba7bdd..a0e07e425fa 100644
--- a/chromium/content/browser/background_fetch/background_fetch_job_controller.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_job_controller.cc
@@ -3,6 +3,8 @@
// found in the LICENSE file.
#include "content/browser/background_fetch/background_fetch_job_controller.h"
+#include "content/public/common/origin_util.h"
+#include "services/network/public/cpp/cors/cors.h"
#include "third_party/blink/public/platform/modules/background_fetch/background_fetch.mojom.h"
#include <utility>
@@ -11,6 +13,8 @@
namespace content {
+using blink::mojom::BackgroundFetchFailureReason;
+
BackgroundFetchJobController::BackgroundFetchJobController(
BackgroundFetchDelegateProxy* delegate_proxy,
BackgroundFetchScheduler* scheduler,
@@ -37,13 +41,15 @@ void BackgroundFetchJobController::InitializeRequestStatus(
int total_downloads,
std::vector<scoped_refptr<BackgroundFetchRequestInfo>>
active_fetch_requests,
- const std::string& ui_title) {
+ const std::string& ui_title,
+ bool start_paused) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
// Don't allow double initialization.
DCHECK_GT(total_downloads, 0);
DCHECK_EQ(total_downloads_, 0);
+ outstanding_requests_ = active_fetch_requests;
completed_downloads_ = completed_downloads;
total_downloads_ = total_downloads;
@@ -59,7 +65,7 @@ void BackgroundFetchJobController::InitializeRequestStatus(
registration_id().unique_id(), ui_title, registration_id().origin(),
icon_, completed_downloads, total_downloads,
complete_requests_downloaded_bytes_cache_, total_downloads_size_,
- std::move(active_guids));
+ std::move(active_guids), start_paused);
delegate_proxy_->CreateDownloadJob(GetWeakPtr(), std::move(fetch_description),
std::move(active_fetch_requests));
@@ -73,6 +79,41 @@ bool BackgroundFetchJobController::HasMoreRequests() {
return completed_downloads_ < total_downloads_;
}
+bool BackgroundFetchJobController::IsMixedContent(
+ const BackgroundFetchRequestInfo& request) {
+ // Empty request is valid, it shouldn't fail the mixed content check.
+ if (request.fetch_request().url.is_empty())
+ return false;
+
+ return !IsOriginSecure(request.fetch_request().url);
+}
+
+bool BackgroundFetchJobController::RequiresCORSPreflight(
+ const BackgroundFetchRequestInfo& request) {
+ auto fetch_request = request.fetch_request();
+
+ // Same origin requests don't require a CORS preflight.
+ // https://fetch.spec.whatwg.org/#main-fetch
+ // TODO(crbug.com/711354): Make sure that cross-origin redirects are disabled.
+ if (url::IsSameOriginWith(registration_id().origin().GetURL(),
+ fetch_request.url)) {
+ return false;
+ }
+
+ // Requests that are more involved than what is possible with HTML's form
+ // element require a CORS-preflight request.
+ // https://fetch.spec.whatwg.org/#main-fetch
+ if (!fetch_request.method.empty() &&
+ !network::cors::IsCORSSafelistedMethod(fetch_request.method)) {
+ return true;
+ }
+
+ net::HttpRequestHeaders::HeaderVector headers;
+ for (const auto& header : fetch_request.headers)
+ headers.emplace_back(header.first, header.second);
+ return !network::cors::CORSUnsafeRequestHeaderNames(headers).empty();
+}
+
void BackgroundFetchJobController::StartRequest(
scoped_refptr<BackgroundFetchRequestInfo> request,
RequestFinishedCallback request_finished_callback) {
@@ -84,15 +125,29 @@ void BackgroundFetchJobController::StartRequest(
active_request_downloaded_bytes_ = 0;
active_request_finished_callback_ = std::move(request_finished_callback);
+ if (IsMixedContent(*request.get()) || RequiresCORSPreflight(*request.get())) {
+ request->SetEmptyResultWithFailureReason(
+ BackgroundFetchResult::FailureReason::FETCH_ERROR);
+
+ ++completed_downloads_;
+ std::move(active_request_finished_callback_).Run(request);
+ return;
+ }
+
delegate_proxy_->StartRequest(registration_id().unique_id(),
registration_id().origin(), request);
}
+std::vector<scoped_refptr<BackgroundFetchRequestInfo>>
+BackgroundFetchJobController::TakeOutstandingRequests() {
+ return std::move(outstanding_requests_);
+}
+
void BackgroundFetchJobController::DidStartRequest(
const scoped_refptr<BackgroundFetchRequestInfo>& request) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- // TODO(delphick): Either add CORS check here or remove this function and do
- // the CORS check in BackgroundFetchDelegateImpl (since
+ // TODO(crbug.com/884672): Either add CORS check here or remove this function
+ // and do the CORS check in BackgroundFetchDelegateImpl (since
// download::Client::OnDownloadStarted returns a value that can abort the
// download).
}
@@ -107,9 +162,10 @@ void BackgroundFetchJobController::DidUpdateRequest(
active_request_downloaded_bytes_ = bytes_downloaded;
- progress_callback_.Run(registration_id().unique_id(), options_.download_total,
- complete_requests_downloaded_bytes_cache_ +
- GetInProgressDownloadedBytes());
+ auto registration =
+ NewRegistration(blink::mojom::BackgroundFetchResult::UNSET);
+ registration->downloaded += GetInProgressDownloadedBytes();
+ progress_callback_.Run(*registration);
}
void BackgroundFetchJobController::DidCompleteRequest(
@@ -140,43 +196,20 @@ void BackgroundFetchJobController::UpdateUI(
std::unique_ptr<BackgroundFetchRegistration>
BackgroundFetchJobController::NewRegistration(
- blink::mojom::BackgroundFetchState state) const {
+ blink::mojom::BackgroundFetchResult result) const {
return std::make_unique<BackgroundFetchRegistration>(
registration_id().developer_id(), registration_id().unique_id(),
0 /* upload_total */, 0 /* uploaded */, total_downloads_size_,
- complete_requests_downloaded_bytes_cache_, state, MojoFailureReason());
+ complete_requests_downloaded_bytes_cache_, result, failure_reason_);
}
uint64_t BackgroundFetchJobController::GetInProgressDownloadedBytes() {
return active_request_downloaded_bytes_;
}
-// TODO(crbug.com/876691): Get rid of BackgroundFetchReasonToAbort and remove
-// this method.
-blink::mojom::BackgroundFetchFailureReason
-BackgroundFetchJobController::MojoFailureReason() const {
- switch (reason_to_abort_) {
- case BackgroundFetchReasonToAbort::NONE:
- return blink::mojom::BackgroundFetchFailureReason::NONE;
- case BackgroundFetchReasonToAbort::CANCELLED_FROM_UI:
- return blink::mojom::BackgroundFetchFailureReason::CANCELLED_FROM_UI;
- case BackgroundFetchReasonToAbort::ABORTED_BY_DEVELOPER:
- return blink::mojom::BackgroundFetchFailureReason::CANCELLED_BY_DEVELOPER;
- case BackgroundFetchReasonToAbort::TOTAL_DOWNLOAD_SIZE_EXCEEDED:
- return blink::mojom::BackgroundFetchFailureReason::
- TOTAL_DOWNLOAD_SIZE_EXCEEDED;
- case BackgroundFetchReasonToAbort::SERVICE_WORKER_UNAVAILABLE:
- return blink::mojom::BackgroundFetchFailureReason::
- SERVICE_WORKER_UNAVAILABLE;
- case BackgroundFetchReasonToAbort::QUOTA_EXCEEDED:
- return blink::mojom::BackgroundFetchFailureReason::QUOTA_EXCEEDED;
- }
- NOTREACHED();
-}
-
void BackgroundFetchJobController::Abort(
- BackgroundFetchReasonToAbort reason_to_abort) {
- reason_to_abort_ = reason_to_abort;
+ BackgroundFetchFailureReason failure_reason) {
+ failure_reason_ = failure_reason;
// Stop propagating any in-flight events to the scheduler.
active_request_finished_callback_.Reset();
@@ -184,7 +217,14 @@ void BackgroundFetchJobController::Abort(
// Cancel any in-flight downloads and UI through the BGFetchDelegate.
delegate_proxy_->Abort(registration_id().unique_id());
- Finish(reason_to_abort);
+ Finish(failure_reason_);
+}
+
+BackgroundFetchFailureReason BackgroundFetchJobController::MergeFailureReason(
+ BackgroundFetchFailureReason failure_reason) {
+ if (failure_reason_ == BackgroundFetchFailureReason::NONE)
+ failure_reason_ = failure_reason;
+ return failure_reason_;
}
} // 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 7bc8b2fbf9e..ab829c87170 100644
--- a/chromium/content/browser/background_fetch/background_fetch_job_controller.h
+++ b/chromium/content/browser/background_fetch/background_fetch_job_controller.h
@@ -41,11 +41,9 @@ class CONTENT_EXPORT BackgroundFetchJobController final
public:
using FinishedCallback =
base::OnceCallback<void(const BackgroundFetchRegistrationId&,
- BackgroundFetchReasonToAbort)>;
+ blink::mojom::BackgroundFetchFailureReason)>;
using ProgressCallback =
- base::RepeatingCallback<void(const std::string& /* unique_id */,
- uint64_t /* download_total */,
- uint64_t /* downloaded */)>;
+ base::RepeatingCallback<void(const BackgroundFetchRegistration&)>;
BackgroundFetchJobController(
BackgroundFetchDelegateProxy* delegate_proxy,
@@ -66,7 +64,8 @@ class CONTENT_EXPORT BackgroundFetchJobController final
int total_downloads,
std::vector<scoped_refptr<BackgroundFetchRequestInfo>>
active_fetch_requests,
- const std::string& ui_title);
+ const std::string& ui_title,
+ bool start_paused);
// Gets the number of bytes downloaded for jobs that are currently running.
uint64_t GetInProgressDownloadedBytes();
@@ -79,7 +78,7 @@ class CONTENT_EXPORT BackgroundFetchJobController final
// Returns a unique_ptr to a BackgroundFetchRegistration object
// created with member fields.
std::unique_ptr<BackgroundFetchRegistration> NewRegistration(
- blink::mojom::BackgroundFetchState state) const;
+ blink::mojom::BackgroundFetchResult result) const;
// Returns the options with which this job is fetching data.
const BackgroundFetchOptions& options() const { return options_; }
@@ -93,6 +92,11 @@ class CONTENT_EXPORT BackgroundFetchJobController final
// Returns the number of requests that comprise the whole job.
int total_downloads() const { return total_downloads_; }
+ // If |failure_reason_| is none, overwrites it with |failure_reason|, and
+ // returns the new value.
+ blink::mojom::BackgroundFetchFailureReason MergeFailureReason(
+ blink::mojom::BackgroundFetchFailureReason failure_reason);
+
base::WeakPtr<BackgroundFetchJobController> GetWeakPtr() {
return weak_ptr_factory_.GetWeakPtr();
}
@@ -110,13 +114,24 @@ class CONTENT_EXPORT BackgroundFetchJobController final
bool HasMoreRequests() override;
void StartRequest(scoped_refptr<BackgroundFetchRequestInfo> request,
RequestFinishedCallback request_finished_callback) override;
- void Abort(BackgroundFetchReasonToAbort reason_to_abort) override;
+ std::vector<scoped_refptr<BackgroundFetchRequestInfo>>
+ TakeOutstandingRequests() override;
+ void Abort(
+ blink::mojom::BackgroundFetchFailureReason failure_reason) override;
private:
- // Returns reason_to_abort_ as blink::mojom::BackgroundFetchFailureReason.
- // TODO(crbug.com/876691): Get rid of BackgroundFetchReasonToAbort and remove
- // this converter.
- blink::mojom::BackgroundFetchFailureReason MojoFailureReason() const;
+ // Performs mixed content checks on the |request| for Background Fetch.
+ // Background Fetch depends on Service Workers, which are restricted for use
+ // on secure origins. We can therefore assume that the registration's origin
+ // is secure. This test ensures that the origin for the url of every
+ // request is also secure.
+ bool IsMixedContent(const BackgroundFetchRequestInfo& request);
+
+ // Whether the |request| needs CORS preflight.
+ // Requests that require CORS preflights are temporarily blocked, because the
+ // browser side of Background Fetch doesn't yet support performing CORS
+ // checks. TODO(crbug.com/711354): Remove this temporary block.
+ bool RequiresCORSPreflight(const BackgroundFetchRequestInfo& request);
// Options for the represented background fetch registration.
BackgroundFetchOptions options_;
@@ -124,6 +139,10 @@ class CONTENT_EXPORT BackgroundFetchJobController final
// Icon for the represented background fetch registration.
SkBitmap icon_;
+ // The list of requests for this fetch that started in a previous session
+ // and did not finish.
+ std::vector<scoped_refptr<BackgroundFetchRequestInfo>> outstanding_requests_;
+
// Number of bytes downloaded for the active request.
uint64_t active_request_downloaded_bytes_ = 0;
@@ -151,8 +170,8 @@ class CONTENT_EXPORT BackgroundFetchJobController final
int completed_downloads_ = 0;
// The reason background fetch was aborted.
- BackgroundFetchReasonToAbort reason_to_abort_ =
- BackgroundFetchReasonToAbort::NONE;
+ blink::mojom::BackgroundFetchFailureReason failure_reason_ =
+ blink::mojom::BackgroundFetchFailureReason::NONE;
base::WeakPtrFactory<BackgroundFetchJobController> weak_ptr_factory_;
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 b231b85f93f..259b466300b 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
@@ -29,6 +29,7 @@
#include "content/public/test/fake_download_item.h"
#include "content/public/test/mock_download_manager.h"
#include "testing/gmock/include/gmock/gmock.h"
+#include "third_party/blink/public/platform/modules/background_fetch/background_fetch.mojom.h"
using testing::_;
@@ -55,7 +56,7 @@ class BackgroundFetchJobControllerTest : public BackgroundFetchTestBase {
const BackgroundFetchRegistrationId& registration_id) {
if (finished_requests_.count(registration_id)) {
DCHECK_NE(finished_requests_[registration_id],
- BackgroundFetchReasonToAbort::NONE);
+ blink::mojom::BackgroundFetchFailureReason::NONE);
return JobCompletionStatus::kAborted;
}
@@ -77,6 +78,20 @@ class BackgroundFetchJobControllerTest : public BackgroundFetchTestBase {
pending_requests_counts_[registration_id]--;
}
+ // To be called when a request for |registration_id| has finished.
+ // Moves |request_info| to |out_request_info|.
+ void GetRequestInfoOnRequestFinished(
+ const BackgroundFetchRegistrationId& registration_id,
+ scoped_refptr<content::BackgroundFetchRequestInfo>* out_request_info,
+ scoped_refptr<content::BackgroundFetchRequestInfo> request_info) {
+ DCHECK(pending_requests_counts_.count(registration_id));
+ DCHECK(out_request_info);
+
+ EXPECT_GE(pending_requests_counts_[registration_id], 1);
+ pending_requests_counts_[registration_id]--;
+ *out_request_info = request_info;
+ }
+
// Creates a new Background Fetch registration, whose id will be stored in the
// |*registration_id|, and registers it with the DataManager for the included
// |request_data|. If |auto_complete_requests| is true, the request will
@@ -140,7 +155,8 @@ class BackgroundFetchJobControllerTest : public BackgroundFetchTestBase {
base::Unretained(this)));
controller->InitializeRequestStatus(
- 0, total_downloads, {} /* outstanding_guids */, "" /* ui_title */);
+ 0, total_downloads, {} /* outstanding_guids */, "" /* ui_title */,
+ /* start_paused = */ false);
return controller;
}
@@ -179,7 +195,8 @@ class BackgroundFetchJobControllerTest : public BackgroundFetchTestBase {
uint64_t last_downloaded_ = 0;
std::map<BackgroundFetchRegistrationId, int> pending_requests_counts_;
- std::map<BackgroundFetchRegistrationId, BackgroundFetchReasonToAbort>
+ std::map<BackgroundFetchRegistrationId,
+ blink::mojom::BackgroundFetchFailureReason>
finished_requests_;
// Closure that will be invoked every time the JobController receives a
@@ -190,17 +207,16 @@ class BackgroundFetchJobControllerTest : public BackgroundFetchTestBase {
BackgroundFetchDelegate* delegate_;
private:
- void DidUpdateProgress(const std::string& unique_id,
- uint64_t download_total,
- uint64_t downloaded) {
- last_downloaded_ = downloaded;
+ void DidUpdateProgress(const BackgroundFetchRegistration& registration) {
+ last_downloaded_ = registration.downloaded;
if (job_progress_closure_)
job_progress_closure_.Run();
}
- void DidFinishJob(const BackgroundFetchRegistrationId& registration_id,
- BackgroundFetchReasonToAbort reason_to_abort) {
+ void DidFinishJob(
+ const BackgroundFetchRegistrationId& registration_id,
+ blink::mojom::BackgroundFetchFailureReason reason_to_abort) {
auto iter = pending_requests_counts_.find(registration_id);
DCHECK(iter != pending_requests_counts_.end());
@@ -235,6 +251,32 @@ TEST_F(BackgroundFetchJobControllerTest, SingleRequestJob) {
GetCompletionStatus(registration_id));
}
+TEST_F(BackgroundFetchJobControllerTest, SingleRequestJobWithInsecureOrigin) {
+ BackgroundFetchRegistrationId registration_id;
+
+ auto requests = CreateRegistrationForRequests(
+ &registration_id, {{GURL("http://example.com/funny_cat.png"), "GET"}},
+ true /* auto_complete_requests */);
+
+ EXPECT_EQ(JobCompletionStatus::kRunning,
+ GetCompletionStatus(registration_id));
+
+ std::unique_ptr<BackgroundFetchJobController> controller =
+ CreateJobController(registration_id, requests.size());
+
+ controller->StartRequest(
+ requests[0],
+ base::BindOnce(
+ &BackgroundFetchJobControllerTest::GetRequestInfoOnRequestFinished,
+ base::Unretained(this), registration_id, &requests[0]));
+
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(JobCompletionStatus::kCompleted,
+ GetCompletionStatus(registration_id));
+ EXPECT_FALSE(requests[0]->IsResultSuccess());
+}
+
TEST_F(BackgroundFetchJobControllerTest, MultipleRequestJob) {
BackgroundFetchRegistrationId registration_id;
@@ -282,6 +324,46 @@ TEST_F(BackgroundFetchJobControllerTest, MultipleRequestJob) {
GetCompletionStatus(registration_id));
}
+TEST_F(BackgroundFetchJobControllerTest, MultipleRequestsJobWithMixedContent) {
+ BackgroundFetchRegistrationId registration_id;
+
+ auto requests = CreateRegistrationForRequests(
+ &registration_id,
+ {{GURL("http://example.com/funny_cat.png"), "GET"},
+ {GURL("https://example.com/scary_cat.png"), "GET"}},
+ true /* auto_complete_requests */);
+
+ EXPECT_EQ(JobCompletionStatus::kRunning,
+ GetCompletionStatus(registration_id));
+
+ std::unique_ptr<BackgroundFetchJobController> controller =
+ CreateJobController(registration_id, requests.size());
+
+ controller->StartRequest(
+ requests[0],
+ base::BindOnce(
+ &BackgroundFetchJobControllerTest::GetRequestInfoOnRequestFinished,
+ base::Unretained(this), registration_id, &requests[0]));
+
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(JobCompletionStatus::kRunning,
+ GetCompletionStatus(registration_id));
+ EXPECT_FALSE(requests[0]->IsResultSuccess());
+
+ controller->StartRequest(
+ requests[1],
+ base::BindOnce(
+ &BackgroundFetchJobControllerTest::GetRequestInfoOnRequestFinished,
+ base::Unretained(this), registration_id, &requests[1]));
+
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(JobCompletionStatus::kCompleted,
+ GetCompletionStatus(registration_id));
+ EXPECT_TRUE(requests[1]->IsResultSuccess());
+}
+
TEST_F(BackgroundFetchJobControllerTest, Abort) {
BackgroundFetchRegistrationId registration_id;
@@ -300,7 +382,8 @@ TEST_F(BackgroundFetchJobControllerTest, Abort) {
base::BindOnce(&BackgroundFetchJobControllerTest::OnRequestFinished,
base::Unretained(this), registration_id));
- controller->Abort(BackgroundFetchReasonToAbort::CANCELLED_FROM_UI);
+ controller->Abort(
+ blink::mojom::BackgroundFetchFailureReason::CANCELLED_FROM_UI);
base::RunLoop().RunUntilIdle();
diff --git a/chromium/content/browser/background_fetch/background_fetch_metrics.cc b/chromium/content/browser/background_fetch/background_fetch_metrics.cc
index ec5979b21d1..430b46f0486 100644
--- a/chromium/content/browser/background_fetch/background_fetch_metrics.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_metrics.cc
@@ -5,11 +5,20 @@
#include "content/browser/background_fetch/background_fetch_metrics.h"
#include "base/metrics/histogram_macros.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/web_contents.h"
+#include "services/metrics/public/cpp/metrics_utils.h"
+#include "services/metrics/public/cpp/ukm_builders.h"
+#include "services/metrics/public/cpp/ukm_recorder.h"
namespace content {
namespace background_fetch {
+// Exponential bucket spacing for UKM event data.
+const double kUkmEventDataBucketSpacing = 2.0;
+
void RecordSchedulerFinishedError(blink::mojom::BackgroundFetchError error) {
UMA_HISTOGRAM_ENUMERATION("BackgroundFetch.SchedulerFinishedError", error);
}
@@ -22,6 +31,47 @@ void RecordRegistrationDeletedError(blink::mojom::BackgroundFetchError error) {
UMA_HISTOGRAM_ENUMERATION("BackgroundFetch.RegistrationDeletedError", error);
}
+void RecordRegistrationsOnStartup(int num_registrations) {
+ UMA_HISTOGRAM_COUNTS_100("BackgroundFetch.IncompleteFetchesOnStartup",
+ num_registrations);
+}
+
+void RecordBackgroundFetchUkmEvent(
+ const url::Origin& origin,
+ const std::vector<ServiceWorkerFetchRequest>& requests,
+ const BackgroundFetchOptions& options,
+ const SkBitmap& icon,
+ blink::mojom::BackgroundFetchUkmDataPtr ukm_data,
+ int frame_tree_node_id,
+ BackgroundFetchPermission permission) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ // Only record UKM data if there's a frame associated.
+ auto* web_contents = WebContents::FromFrameTreeNodeId(frame_tree_node_id);
+ if (!web_contents)
+ return;
+
+ // Only record UKM data if the origin of the page currently being displayed
+ // is the same as the one the background fetch was started with.
+ auto displayed_origin = web_contents->GetLastCommittedURL().GetOrigin();
+ if (!origin.IsSameOriginWith(url::Origin::Create(displayed_origin)))
+ return;
+ ukm::SourceId source_id = static_cast<WebContentsImpl*>(web_contents)
+ ->GetUkmSourceIdForLastCommittedSource();
+
+ ukm::builders::BackgroundFetch(source_id)
+ .SetHasTitle(!options.title.empty())
+ .SetNumIcons(options.icons.size())
+ .SetRatioOfIdealToChosenIconSize(ukm_data->ideal_to_chosen_icon_size)
+ .SetDownloadTotal(ukm::GetExponentialBucketMin(
+ options.download_total, kUkmEventDataBucketSpacing))
+ .SetNumRequestsInFetch(ukm::GetExponentialBucketMin(
+ requests.size(), kUkmEventDataBucketSpacing))
+ .SetDeniedDueToPermissions(permission ==
+ BackgroundFetchPermission::BLOCKED)
+ .Record(ukm::UkmRecorder::Get());
+}
+
} // 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
index 977b33bc687..27f65916507 100644
--- a/chromium/content/browser/background_fetch/background_fetch_metrics.h
+++ b/chromium/content/browser/background_fetch/background_fetch_metrics.h
@@ -5,6 +5,7 @@
#ifndef CONTENT_BROWSER_BACKGROUND_FETCH_BACKGROUND_FETCH_METRICS_H_
#define CONTENT_BROWSER_BACKGROUND_FETCH_BACKGROUND_FETCH_METRICS_H_
+#include "content/public/browser/background_fetch_delegate.h"
#include "third_party/blink/public/platform/modules/background_fetch/background_fetch.mojom.h"
namespace content {
@@ -24,6 +25,22 @@ void RecordRegistrationCreatedError(blink::mojom::BackgroundFetchError error);
// associated with a registration has been completely deleted.
void RecordRegistrationDeletedError(blink::mojom::BackgroundFetchError error);
+// Records the number of registrations that have unfinished fetches found on
+// start-up.
+void RecordRegistrationsOnStartup(int num_registrations);
+
+// Records the BackgroundFetch UKM event. Must be called before a Background
+// Fetch registration has been created. Will be a no-op if |frame_tree_node_id|
+// does not identify a valid, live frame.
+void RecordBackgroundFetchUkmEvent(
+ const url::Origin& origin,
+ const std::vector<ServiceWorkerFetchRequest>& requests,
+ const BackgroundFetchOptions& options,
+ const SkBitmap& icon,
+ blink::mojom::BackgroundFetchUkmDataPtr ukm_data,
+ int frame_tree_node_id,
+ BackgroundFetchPermission permission);
+
} // namespace background_fetch
} // namespace content
diff --git a/chromium/content/browser/background_fetch/background_fetch_registration_notifier.cc b/chromium/content/browser/background_fetch/background_fetch_registration_notifier.cc
index 4590bb371e7..e5dfc98ca08 100644
--- a/chromium/content/browser/background_fetch/background_fetch_registration_notifier.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_registration_notifier.cc
@@ -5,7 +5,6 @@
#include "content/browser/background_fetch/background_fetch_registration_notifier.h"
#include "base/bind.h"
-#include "base/stl_util.h"
namespace content {
@@ -29,24 +28,30 @@ void BackgroundFetchRegistrationNotifier::AddObserver(
observers_.emplace(unique_id, std::move(observer));
}
-void BackgroundFetchRegistrationNotifier::Notify(const std::string& unique_id,
- uint64_t download_total,
- uint64_t downloaded) {
- auto range = observers_.equal_range(unique_id);
+void BackgroundFetchRegistrationNotifier::Notify(
+ const BackgroundFetchRegistration& registration) {
+ auto range = observers_.equal_range(registration.unique_id);
for (auto it = range.first; it != range.second; ++it) {
// TODO(crbug.com/774054): Uploads are not yet supported.
it->second->OnProgress(0 /* upload_total */, 0 /* uploaded */,
- download_total, downloaded);
+ registration.download_total, registration.downloaded,
+ registration.result, registration.failure_reason);
}
}
-void BackgroundFetchRegistrationNotifier::AddGarbageCollectionCallback(
- const std::string& unique_id,
- base::OnceClosure callback) {
- if (!observers_.count(unique_id))
- std::move(callback).Run();
- else
- garbage_collection_callbacks_.emplace(unique_id, std::move(callback));
+void BackgroundFetchRegistrationNotifier::NotifyRecordsUnavailable(
+ const std::string& unique_id) {
+ for (auto it = observers_.begin(); it != observers_.end();) {
+ if (it->first != unique_id) {
+ it++;
+ continue;
+ }
+
+ it->second->OnRecordsUnavailable();
+
+ // No more notifications will be sent to the observers from this point.
+ it = observers_.erase(it);
+ }
}
void BackgroundFetchRegistrationNotifier::OnConnectionError(
@@ -57,13 +62,6 @@ void BackgroundFetchRegistrationNotifier::OnConnectionError(
[observer](const auto& unique_id_observer_ptr_pair) {
return unique_id_observer_ptr_pair.second.get() == observer;
});
-
- auto callback_iter = garbage_collection_callbacks_.find(unique_id);
- if (callback_iter != garbage_collection_callbacks_.end() &&
- !observers_.count(unique_id)) {
- std::move(callback_iter->second).Run();
- garbage_collection_callbacks_.erase(callback_iter);
- }
}
} // namespace content
diff --git a/chromium/content/browser/background_fetch/background_fetch_registration_notifier.h b/chromium/content/browser/background_fetch/background_fetch_registration_notifier.h
index 80abea1ece9..0632473515f 100644
--- a/chromium/content/browser/background_fetch/background_fetch_registration_notifier.h
+++ b/chromium/content/browser/background_fetch/background_fetch_registration_notifier.h
@@ -30,18 +30,14 @@ class CONTENT_EXPORT BackgroundFetchRegistrationNotifier {
const std::string& unique_id,
blink::mojom::BackgroundFetchRegistrationObserverPtr observer);
- // Notifies any registered observers for the registration identified by the
- // |unique_id| of the progress. This will cause JavaScript events to fire.
- // Successful fetches must also call Notify with the final state.
- void Notify(const std::string& unique_id,
- uint64_t download_total,
- uint64_t downloaded);
+ // Notifies any registered observers for the |registration| of the progress.
+ // This will cause JavaScript events to fire.
+ // Completed fetches must also call Notify with the final state.
+ void Notify(const BackgroundFetchRegistration& registration);
- // Runs |callback| when the last observer for |unique_id| is removed, or
- // immediately if there are already no observers. Callback will never be run
- // if the browser is shutdown before the last observer is removed.
- void AddGarbageCollectionCallback(const std::string& unique_id,
- base::OnceClosure callback);
+ // Notifies any registered observers for the registration identifier by
+ // |unique_id| that the records for the fetch are no longer available.
+ void NotifyRecordsUnavailable(const std::string& unique_id);
base::WeakPtr<BackgroundFetchRegistrationNotifier> GetWeakPtr() {
return weak_factory_.GetWeakPtr();
@@ -59,10 +55,6 @@ class CONTENT_EXPORT BackgroundFetchRegistrationNotifier {
blink::mojom::BackgroundFetchRegistrationObserverPtr>
observers_;
- // Map from registration |unique_id| to callback to run when last observer is
- // removed.
- std::map<std::string, base::OnceClosure> garbage_collection_callbacks_;
-
base::WeakPtrFactory<BackgroundFetchRegistrationNotifier> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(BackgroundFetchRegistrationNotifier);
diff --git a/chromium/content/browser/background_fetch/background_fetch_registration_notifier_unittest.cc b/chromium/content/browser/background_fetch/background_fetch_registration_notifier_unittest.cc
index 9be34593da1..cd9eee1f13c 100644
--- a/chromium/content/browser/background_fetch/background_fetch_registration_notifier_unittest.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_registration_notifier_unittest.cc
@@ -19,6 +19,7 @@
namespace content {
namespace {
+const char kDeveloperId[] = "my-fetch";
const char kPrimaryUniqueId[] = "7e57ab1e-c0de-a150-ca75-1e75f005ba11";
const char kSecondaryUniqueId[] = "bb48a9fb-c21f-4c2d-a9ae-58bd48a9fb53";
@@ -32,16 +33,24 @@ class TestRegistrationObserver
ProgressUpdate(uint64_t upload_total,
uint64_t uploaded,
uint64_t download_total,
- uint64_t downloaded)
+ uint64_t downloaded,
+ blink::mojom::BackgroundFetchResult result,
+ blink::mojom::BackgroundFetchFailureReason failure_reason)
: upload_total(upload_total),
uploaded(uploaded),
download_total(download_total),
- downloaded(downloaded) {}
+ downloaded(downloaded),
+ result(result),
+ failure_reason(failure_reason) {}
uint64_t upload_total = 0;
uint64_t uploaded = 0;
uint64_t download_total = 0;
uint64_t downloaded = 0;
+ blink::mojom::BackgroundFetchResult result =
+ blink::mojom::BackgroundFetchResult::UNSET;
+ blink::mojom::BackgroundFetchFailureReason failure_reason =
+ blink::mojom::BackgroundFetchFailureReason::NONE;
};
TestRegistrationObserver() : binding_(this) {}
@@ -62,18 +71,26 @@ class TestRegistrationObserver
return progress_updates_;
}
+ bool records_available() const { return records_available_; }
+
// blink::mojom::BackgroundFetchRegistrationObserver implementation.
- void OnProgress(uint64_t upload_total,
- uint64_t uploaded,
- uint64_t download_total,
- uint64_t downloaded) override {
+ void OnProgress(
+ uint64_t upload_total,
+ uint64_t uploaded,
+ uint64_t download_total,
+ uint64_t downloaded,
+ blink::mojom::BackgroundFetchResult result,
+ blink::mojom::BackgroundFetchFailureReason failure_reason) override {
progress_updates_.emplace_back(upload_total, uploaded, download_total,
- downloaded);
+ downloaded, result, failure_reason);
}
+ void OnRecordsUnavailable() override { records_available_ = false; }
+
private:
std::vector<ProgressUpdate> progress_updates_;
mojo::Binding<blink::mojom::BackgroundFetchRegistrationObserver> binding_;
+ bool records_available_ = true;
DISALLOW_COPY_AND_ASSIGN(TestRegistrationObserver);
};
@@ -89,14 +106,15 @@ class BackgroundFetchRegistrationNotifierTest : public ::testing::Test {
// Notifies all observers for the |unique_id| of the made progress, and waits
// until the task runner managing the Mojo connection has finished.
- void Notify(const std::string& unique_id,
- uint64_t download_total,
- uint64_t downloaded) {
- notifier_->Notify(unique_id, download_total, downloaded);
+ void Notify(const BackgroundFetchRegistration& registration) {
+ notifier_->Notify(registration);
task_runner_->RunUntilIdle();
}
- void CollectGarbage() { garbage_collected_ = true; }
+ void NotifyRecordsUnavailable(const std::string& unique_id) {
+ notifier_->NotifyRecordsUnavailable(unique_id);
+ task_runner_->RunUntilIdle();
+ }
protected:
scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
@@ -104,8 +122,6 @@ class BackgroundFetchRegistrationNotifierTest : public ::testing::Test {
std::unique_ptr<BackgroundFetchRegistrationNotifier> notifier_;
- bool garbage_collected_ = false;
-
private:
DISALLOW_COPY_AND_ASSIGN(BackgroundFetchRegistrationNotifierTest);
};
@@ -116,7 +132,11 @@ TEST_F(BackgroundFetchRegistrationNotifierTest, NotifySingleObserver) {
notifier_->AddObserver(kPrimaryUniqueId, observer->GetPtr());
ASSERT_EQ(observer->progress_updates().size(), 0u);
- Notify(kPrimaryUniqueId, kDownloadTotal, kDownloaded);
+ Notify(BackgroundFetchRegistration(
+ kDeveloperId, kPrimaryUniqueId,
+ /* upload_total*/ 0, /* uploaded*/ 0, kDownloadTotal, kDownloaded,
+ blink::mojom::BackgroundFetchResult::UNSET,
+ blink::mojom::BackgroundFetchFailureReason::NONE));
ASSERT_EQ(observer->progress_updates().size(), 1u);
@@ -126,6 +146,9 @@ TEST_F(BackgroundFetchRegistrationNotifierTest, NotifySingleObserver) {
EXPECT_EQ(update.uploaded, 0u);
EXPECT_EQ(update.download_total, kDownloadTotal);
EXPECT_EQ(update.downloaded, kDownloaded);
+ EXPECT_EQ(update.result, blink::mojom::BackgroundFetchResult::UNSET);
+ EXPECT_EQ(update.failure_reason,
+ blink::mojom::BackgroundFetchFailureReason::NONE);
}
TEST_F(BackgroundFetchRegistrationNotifierTest, NotifyMultipleObservers) {
@@ -145,7 +168,11 @@ TEST_F(BackgroundFetchRegistrationNotifierTest, NotifyMultipleObservers) {
ASSERT_EQ(secondary_observer->progress_updates().size(), 0u);
// Notify the |kPrimaryUniqueId|.
- Notify(kPrimaryUniqueId, kDownloadTotal, kDownloaded);
+ Notify(BackgroundFetchRegistration(
+ kDeveloperId, kPrimaryUniqueId,
+ /* upload_total*/ 0, /* uploaded*/ 0, kDownloadTotal, kDownloaded,
+ blink::mojom::BackgroundFetchResult::UNSET,
+ blink::mojom::BackgroundFetchFailureReason::NONE));
for (auto& observer : primary_observers) {
ASSERT_EQ(observer->progress_updates().size(), 1u);
@@ -156,6 +183,9 @@ TEST_F(BackgroundFetchRegistrationNotifierTest, NotifyMultipleObservers) {
EXPECT_EQ(update.uploaded, 0u);
EXPECT_EQ(update.download_total, kDownloadTotal);
EXPECT_EQ(update.downloaded, kDownloaded);
+ EXPECT_EQ(update.result, blink::mojom::BackgroundFetchResult::UNSET);
+ EXPECT_EQ(update.failure_reason,
+ blink::mojom::BackgroundFetchFailureReason::NONE);
}
// The observer for |kSecondaryUniqueId| should not have been notified.
@@ -169,14 +199,22 @@ TEST_F(BackgroundFetchRegistrationNotifierTest,
notifier_->AddObserver(kPrimaryUniqueId, observer->GetPtr());
ASSERT_EQ(observer->progress_updates().size(), 0u);
- Notify(kPrimaryUniqueId, kDownloadTotal, kDownloaded);
+ Notify(BackgroundFetchRegistration(
+ kDeveloperId, kPrimaryUniqueId,
+ /* upload_total*/ 0, /* uploaded*/ 0, kDownloadTotal, kDownloaded,
+ blink::mojom::BackgroundFetchResult::UNSET,
+ blink::mojom::BackgroundFetchFailureReason::NONE));
ASSERT_EQ(observer->progress_updates().size(), 1u);
// Closes the binding as would be done from the renderer process.
observer->Close();
- Notify(kPrimaryUniqueId, kDownloadTotal, kDownloaded);
+ Notify(BackgroundFetchRegistration(
+ kDeveloperId, kPrimaryUniqueId,
+ /* upload_total*/ 0, /* uploaded*/ 0, kDownloadTotal, kDownloaded,
+ blink::mojom::BackgroundFetchResult::UNSET,
+ blink::mojom::BackgroundFetchFailureReason::NONE));
// The observers for |kPrimaryUniqueId| were removed, so no second update
// should have been received by the |observer|.
@@ -189,44 +227,25 @@ TEST_F(BackgroundFetchRegistrationNotifierTest, NotifyWithoutObservers) {
notifier_->AddObserver(kPrimaryUniqueId, observer->GetPtr());
ASSERT_EQ(observer->progress_updates().size(), 0u);
- Notify(kSecondaryUniqueId, kDownloadTotal, kDownloaded);
+ Notify(BackgroundFetchRegistration(
+ kDeveloperId, kSecondaryUniqueId,
+ /* upload_total*/ 0, /* uploaded*/ 0, kDownloadTotal, kDownloaded,
+ blink::mojom::BackgroundFetchResult::UNSET,
+ blink::mojom::BackgroundFetchFailureReason::NONE));
// Because the notification was for |kSecondaryUniqueId|, no progress updates
// should be received by the |observer|.
EXPECT_EQ(observer->progress_updates().size(), 0u);
}
-TEST_F(BackgroundFetchRegistrationNotifierTest,
- AddGarbageCollectionCallback_NoObservers) {
- notifier_->AddGarbageCollectionCallback(
- kPrimaryUniqueId,
- base::BindOnce(&BackgroundFetchRegistrationNotifierTest::CollectGarbage,
- base::Unretained(this)));
-
- ASSERT_TRUE(garbage_collected_)
- << "Garbage should be collected when there are no observers";
-}
-
-TEST_F(BackgroundFetchRegistrationNotifierTest,
- AddGarbageCollectionCallback_OneObserver) {
+TEST_F(BackgroundFetchRegistrationNotifierTest, NotifyRecordsUnavailable) {
auto observer = std::make_unique<TestRegistrationObserver>();
- auto foo = observer->GetPtr();
- notifier_->AddObserver(kPrimaryUniqueId, std::move(foo));
- notifier_->AddGarbageCollectionCallback(
- kPrimaryUniqueId,
- base::BindOnce(&BackgroundFetchRegistrationNotifierTest::CollectGarbage,
- base::Unretained(this)));
-
- ASSERT_FALSE(garbage_collected_)
- << "Garbage should not be collected when there is an observer";
-
- observer->Close();
+ notifier_->AddObserver(kPrimaryUniqueId, observer->GetPtr());
+ ASSERT_TRUE(observer->records_available());
- // TODO(crbug.com/777764): Add this back when non-exceptional binding closures
- // are detected properly.
- // ASSERT_TRUE(garbage_collected_) << "Garbage should be collected when the
- // "observer is closed.";
+ NotifyRecordsUnavailable(kPrimaryUniqueId);
+ ASSERT_FALSE(observer->records_available());
}
} // namespace
diff --git a/chromium/content/browser/background_fetch/background_fetch_request_info.cc b/chromium/content/browser/background_fetch/background_fetch_request_info.cc
index e13df709f2f..d2103e65700 100644
--- a/chromium/content/browser/background_fetch/background_fetch_request_info.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_request_info.cc
@@ -42,9 +42,27 @@ void BackgroundFetchRequestInfo::SetDownloadGuid(
download_guid_ = download_guid;
}
+void BackgroundFetchRequestInfo::SetResult(
+ std::unique_ptr<BackgroundFetchResult> result) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(result);
+
+ result_ = std::move(result);
+ PopulateWithResponse(std::move(result_->response));
+}
+
+void BackgroundFetchRequestInfo::SetEmptyResultWithFailureReason(
+ BackgroundFetchResult::FailureReason failure_reason) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ result_ = std::make_unique<BackgroundFetchResult>(
+ nullptr /* response */, base::Time::Now(), failure_reason);
+}
+
void BackgroundFetchRequestInfo::PopulateWithResponse(
std::unique_ptr<BackgroundFetchResponse> response) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(response);
url_chain_ = response->url_chain;
@@ -63,13 +81,6 @@ void BackgroundFetchRequestInfo::PopulateWithResponse(
response_headers_[base::ToLowerASCII(name)] = value;
}
-void BackgroundFetchRequestInfo::SetResult(
- std::unique_ptr<BackgroundFetchResult> result) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
- result_ = std::move(result);
-}
-
int BackgroundFetchRequestInfo::GetResponseCode() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return response_code_;
diff --git a/chromium/content/browser/background_fetch/background_fetch_request_info.h b/chromium/content/browser/background_fetch/background_fetch_request_info.h
index 1a796748e4e..3b359aa5d7b 100644
--- a/chromium/content/browser/background_fetch/background_fetch_request_info.h
+++ b/chromium/content/browser/background_fetch/background_fetch_request_info.h
@@ -20,6 +20,7 @@
#include "content/browser/background_fetch/background_fetch_constants.h"
#include "content/common/content_export.h"
#include "content/common/service_worker/service_worker_types.h"
+#include "content/public/browser/background_fetch_response.h"
#include "url/gurl.h"
namespace storage {
@@ -48,11 +49,13 @@ class CONTENT_EXPORT BackgroundFetchRequestInfo
// retrieved from storage). Can only be used if no GUID is already set.
void SetDownloadGuid(const std::string& download_guid);
- // Populates the cached state for the in-progress download.
- void PopulateWithResponse(std::unique_ptr<BackgroundFetchResponse> response);
-
void SetResult(std::unique_ptr<BackgroundFetchResult> result);
+ // Creates an empty result, with no response, and assigns |failure_reason|
+ // as its failure_reason.
+ void SetEmptyResultWithFailureReason(
+ BackgroundFetchResult::FailureReason failure_reason);
+
// Returns the index of this request within a Background Fetch registration.
int request_index() const { return request_index_; }
@@ -101,6 +104,9 @@ class CONTENT_EXPORT BackgroundFetchRequestInfo
friend class base::DeleteHelper<BackgroundFetchRequestInfo>;
friend class BackgroundFetchCrossOriginFilterTest;
+ // Extracts the headers and the status code.
+ void PopulateWithResponse(std::unique_ptr<BackgroundFetchResponse> response);
+
~BackgroundFetchRequestInfo();
// ---- Data associated with the request -------------------------------------
diff --git a/chromium/content/browser/background_fetch/background_fetch_scheduler.cc b/chromium/content/browser/background_fetch/background_fetch_scheduler.cc
index 4fe7cf3fbaf..6038067c002 100644
--- a/chromium/content/browser/background_fetch/background_fetch_scheduler.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_scheduler.cc
@@ -23,16 +23,18 @@ BackgroundFetchScheduler::Controller::Controller(
BackgroundFetchScheduler::Controller::~Controller() = default;
void BackgroundFetchScheduler::Controller::Finish(
- BackgroundFetchReasonToAbort reason_to_abort) {
- DCHECK(reason_to_abort != BackgroundFetchReasonToAbort::NONE ||
+ blink::mojom::BackgroundFetchFailureReason reason_to_abort) {
+ DCHECK(reason_to_abort != blink::mojom::BackgroundFetchFailureReason::NONE ||
!HasMoreRequests());
scheduler_->RemoveJobController(this);
// Developer-initiated abortions will have already marked the registration for
// deletion, so make sure that we don't execute the same code-path twice.
- if (reason_to_abort == BackgroundFetchReasonToAbort::ABORTED_BY_DEVELOPER)
+ if (reason_to_abort ==
+ blink::mojom::BackgroundFetchFailureReason::CANCELLED_BY_DEVELOPER) {
return;
+ }
// Race conditions make it possible for a controller to finish twice. This
// should be removed when the scheduler starts owning the controllers.
@@ -50,9 +52,26 @@ BackgroundFetchScheduler::~BackgroundFetchScheduler() = default;
void BackgroundFetchScheduler::AddJobController(Controller* controller) {
DCHECK(controller);
-
controller_queue_.push_back(controller);
+ std::vector<scoped_refptr<content::BackgroundFetchRequestInfo>>
+ outstanding_requests = controller->TakeOutstandingRequests();
+ // There are active downloads from the previous session.
+ if (!outstanding_requests.empty()) {
+ // The current assumption is that there can be at most one active fetch
+ // at any given time.
+ DCHECK(!active_controller_);
+ DCHECK_EQ(outstanding_requests.size(), 1u);
+
+ active_controller_ = controller;
+ for (auto& request_info : outstanding_requests) {
+ active_controller_->StartRequest(
+ std::move(request_info),
+ base::BindOnce(&BackgroundFetchScheduler::MarkRequestAsComplete,
+ weak_ptr_factory_.GetWeakPtr()));
+ }
+ }
+
if (!active_controller_)
ScheduleDownload();
}
@@ -88,6 +107,7 @@ void BackgroundFetchScheduler::ScheduleDownload() {
}
void BackgroundFetchScheduler::DidPopNextRequest(
+ blink::mojom::BackgroundFetchError error,
scoped_refptr<BackgroundFetchRequestInfo> request_info) {
// It's possible for the |active_controller_| to have been aborted while the
// next request was being retrieved. Bail out when that happens.
@@ -96,16 +116,13 @@ void BackgroundFetchScheduler::DidPopNextRequest(
return;
}
- // There might've been a storage error when |request_info| could not be loaded
- // from the database. Bail out in this case as well.
- if (!request_info) {
- // TODO(peter): Should we abort the |active_controller_| in this case?
- active_controller_ = nullptr;
-
- ScheduleDownload();
+ if (error != blink::mojom::BackgroundFetchError::NONE) {
+ // This fetch is being abandoned, after which something will be scheduled.
return;
}
+ DCHECK(request_info);
+
// Otherwise start the |request_info| through the live Job Controller.
active_controller_->StartRequest(
std::move(request_info),
@@ -126,12 +143,19 @@ void BackgroundFetchScheduler::MarkRequestAsComplete(
weak_ptr_factory_.GetWeakPtr()));
}
-void BackgroundFetchScheduler::DidMarkRequestAsComplete() {
+void BackgroundFetchScheduler::DidMarkRequestAsComplete(
+ blink::mojom::BackgroundFetchError error) {
// It's possible for the |active_controller_| to have been aborted while the
// request was being marked as completed. Bail out in that case.
if (!active_controller_)
return;
+ if (error != blink::mojom::BackgroundFetchError::NONE) {
+ // This fetch is being abandoned, after which something will be scheduled.
+ DCHECK_EQ(error, blink::mojom::BackgroundFetchError::STORAGE_ERROR);
+ return;
+ }
+
// Continue with the |active_controller_| while there are files pending.
if (active_controller_->HasMoreRequests()) {
request_provider_->PopNextRequest(
@@ -141,7 +165,7 @@ void BackgroundFetchScheduler::DidMarkRequestAsComplete() {
return;
}
- active_controller_->Finish(BackgroundFetchReasonToAbort::NONE);
+ active_controller_->Finish(blink::mojom::BackgroundFetchFailureReason::NONE);
}
} // namespace content
diff --git a/chromium/content/browser/background_fetch/background_fetch_scheduler.h b/chromium/content/browser/background_fetch/background_fetch_scheduler.h
index 449ea6699f8..314f2184ec5 100644
--- a/chromium/content/browser/background_fetch/background_fetch_scheduler.h
+++ b/chromium/content/browser/background_fetch/background_fetch_scheduler.h
@@ -16,12 +16,12 @@
#include "base/memory/weak_ptr.h"
#include "content/browser/background_fetch/background_fetch_registration_id.h"
#include "content/common/content_export.h"
+#include "third_party/blink/public/platform/modules/background_fetch/background_fetch.mojom.h"
namespace content {
class BackgroundFetchRegistrationId;
class BackgroundFetchRequestInfo;
-enum class BackgroundFetchReasonToAbort;
// Maintains a list of Controllers and chooses which ones should launch new
// downloads.
@@ -29,7 +29,7 @@ class CONTENT_EXPORT BackgroundFetchScheduler {
public:
using FinishedCallback =
base::OnceCallback<void(const BackgroundFetchRegistrationId&,
- BackgroundFetchReasonToAbort)>;
+ blink::mojom::BackgroundFetchFailureReason)>;
// Interface for download job controllers.
class CONTENT_EXPORT Controller {
@@ -46,7 +46,12 @@ class CONTENT_EXPORT BackgroundFetchScheduler {
virtual void StartRequest(scoped_refptr<BackgroundFetchRequestInfo> request,
RequestFinishedCallback callback) = 0;
- void Finish(BackgroundFetchReasonToAbort reason_to_abort);
+ // Returns a list of requests that started in a previous session and did not
+ // complete. Clears the list of outstanding GUIDs in the controller.
+ virtual std::vector<scoped_refptr<BackgroundFetchRequestInfo>>
+ TakeOutstandingRequests() = 0;
+
+ void Finish(blink::mojom::BackgroundFetchFailureReason reason_to_abort);
const BackgroundFetchRegistrationId& registration_id() const {
return registration_id_;
@@ -66,8 +71,11 @@ class CONTENT_EXPORT BackgroundFetchScheduler {
FinishedCallback finished_callback_;
};
+ using MarkRequestCompleteCallback =
+ base::OnceCallback<void(blink::mojom::BackgroundFetchError)>;
using NextRequestCallback =
- base::OnceCallback<void(scoped_refptr<BackgroundFetchRequestInfo>)>;
+ base::OnceCallback<void(blink::mojom::BackgroundFetchError,
+ scoped_refptr<BackgroundFetchRequestInfo>)>;
class CONTENT_EXPORT RequestProvider {
public:
@@ -83,7 +91,7 @@ class CONTENT_EXPORT BackgroundFetchScheduler {
virtual void MarkRequestAsComplete(
const BackgroundFetchRegistrationId& registration_id,
scoped_refptr<BackgroundFetchRequestInfo> request_info,
- base::OnceClosure closure) = 0;
+ MarkRequestCompleteCallback callback) = 0;
};
explicit BackgroundFetchScheduler(RequestProvider* request_provider);
@@ -101,11 +109,12 @@ class CONTENT_EXPORT BackgroundFetchScheduler {
void ScheduleDownload();
void DidPopNextRequest(
+ blink::mojom::BackgroundFetchError error,
scoped_refptr<BackgroundFetchRequestInfo> request_info);
void MarkRequestAsComplete(
scoped_refptr<BackgroundFetchRequestInfo> request_info);
- void DidMarkRequestAsComplete();
+ void DidMarkRequestAsComplete(blink::mojom::BackgroundFetchError error);
RequestProvider* request_provider_;
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 156d262cdaf..ad18e4d5e4d 100644
--- a/chromium/content/browser/background_fetch/background_fetch_scheduler_unittest.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_scheduler_unittest.cc
@@ -8,8 +8,10 @@
#include "base/guid.h"
#include "base/strings/string_number_conversions.h"
+#include "base/task/post_task.h"
#include "content/browser/background_fetch/background_fetch_request_info.h"
#include "content/browser/background_fetch/background_fetch_test_base.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -49,11 +51,16 @@ class FakeController : public BackgroundFetchScheduler::Controller {
controller_sequence_list_->push_back(name_ +
base::IntToString(jobs_started_));
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(std::move(callback), std::move(request)));
}
+ std::vector<scoped_refptr<BackgroundFetchRequestInfo>>
+ TakeOutstandingRequests() override {
+ return {};
+ }
+
private:
int jobs_started_ = 0;
std::vector<std::string>* controller_sequence_list_;
@@ -76,8 +83,8 @@ class BackgroundFetchSchedulerTest
return;
}
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&BackgroundFetchSchedulerTest::PostQuitAfterRepeatingBarriers,
base::Unretained(this), std::move(quit_closure),
@@ -94,14 +101,15 @@ class BackgroundFetchSchedulerTest
0 /* request_count */, fetch_request);
request->InitializeDownloadGuid();
- std::move(callback).Run(std::move(request));
+ std::move(callback).Run(blink::mojom::BackgroundFetchError::NONE,
+ std::move(request));
}
void MarkRequestAsComplete(
const BackgroundFetchRegistrationId& registration_id,
scoped_refptr<BackgroundFetchRequestInfo> request_info,
- base::OnceClosure closure) override {
- std::move(closure).Run();
+ BackgroundFetchScheduler::MarkRequestCompleteCallback closure) override {
+ std::move(closure).Run(blink::mojom::BackgroundFetchError::NONE);
}
protected:
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 f116ff5aad3..edfea31c08a 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 "base/optional.h"
+#include "base/task/post_task.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"
@@ -15,6 +16,7 @@
#include "content/browser/bad_message.h"
#include "content/browser/storage_partition_impl.h"
#include "content/common/service_worker/service_worker_types.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
@@ -38,8 +40,8 @@ void BackgroundFetchServiceImpl::CreateForWorker(
const url::Origin& origin) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
BackgroundFetchServiceImpl::CreateOnIoThread,
WrapRefCounted(static_cast<StoragePartitionImpl*>(
@@ -60,8 +62,8 @@ void BackgroundFetchServiceImpl::CreateForFrame(
RenderFrameHost::FromID(render_process_host->GetID(), render_frame_id);
DCHECK(render_frame_host);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
BackgroundFetchServiceImpl::CreateOnIoThread,
WrapRefCounted(static_cast<StoragePartitionImpl*>(
@@ -105,6 +107,7 @@ void BackgroundFetchServiceImpl::Fetch(
const std::vector<ServiceWorkerFetchRequest>& requests,
const BackgroundFetchOptions& options,
const SkBitmap& icon,
+ blink::mojom::BackgroundFetchUkmDataPtr ukm_data,
FetchCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (!ValidateDeveloperId(developer_id) || !ValidateRequests(requests)) {
@@ -122,9 +125,9 @@ void BackgroundFetchServiceImpl::Fetch(
origin_, developer_id,
base::GenerateGUID());
- background_fetch_context_->StartFetch(registration_id, requests, options,
- icon, render_frame_host_,
- std::move(callback));
+ background_fetch_context_->StartFetch(
+ registration_id, requests, options, icon, std::move(ukm_data),
+ render_frame_host_, std::move(callback));
}
void BackgroundFetchServiceImpl::GetIconDisplaySize(
diff --git a/chromium/content/browser/background_fetch/background_fetch_service_impl.h b/chromium/content/browser/background_fetch/background_fetch_service_impl.h
index 5abcc9b3b18..68f68503b06 100644
--- a/chromium/content/browser/background_fetch/background_fetch_service_impl.h
+++ b/chromium/content/browser/background_fetch/background_fetch_service_impl.h
@@ -50,6 +50,7 @@ class CONTENT_EXPORT BackgroundFetchServiceImpl
const std::vector<ServiceWorkerFetchRequest>& requests,
const BackgroundFetchOptions& options,
const SkBitmap& icon,
+ blink::mojom::BackgroundFetchUkmDataPtr ukm_data,
FetchCallback callback) override;
void GetIconDisplaySize(GetIconDisplaySizeCallback callback) override;
void MatchRequests(
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 7ae027d417c..90dc6495006 100644
--- a/chromium/content/browser/background_fetch/background_fetch_service_unittest.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_service_unittest.cc
@@ -124,6 +124,7 @@ class BackgroundFetchServiceTest : public BackgroundFetchTestBase {
base::RunLoop run_loop;
service_->Fetch(
service_worker_registration_id, developer_id, requests, options, icon,
+ blink::mojom::BackgroundFetchUkmData::New(),
base::BindOnce(&BackgroundFetchServiceTest::DidGetRegistration,
base::Unretained(this), run_loop.QuitClosure(),
out_error, out_registration));
@@ -154,7 +155,7 @@ class BackgroundFetchServiceTest : public BackgroundFetchTestBase {
base::RunLoop run_loop;
context_->data_manager_->CreateRegistration(
- registration_id, requests, options, icon,
+ registration_id, requests, options, icon, /* start_paused = */ false,
base::BindOnce(&BackgroundFetchServiceTest::DidStartFetch,
base::Unretained(this), run_loop.QuitClosure()));
run_loop.Run();
@@ -179,10 +180,11 @@ class BackgroundFetchServiceTest : public BackgroundFetchTestBase {
base::RunLoop run_loop;
service_->Fetch(
service_worker_registration_id, developer_id, requests, options, icon,
+ blink::mojom::BackgroundFetchUkmData::New(),
base::BindOnce(&BackgroundFetchServiceTest::DidGetRegistration,
base::Unretained(this), run_loop.QuitClosure(),
out_error, out_registration));
- UnregisterServiceWorker();
+ UnregisterServiceWorker(service_worker_registration_id);
run_loop.Run();
}
@@ -213,7 +215,7 @@ class BackgroundFetchServiceTest : public BackgroundFetchTestBase {
DCHECK(out_error);
base::RunLoop run_loop;
- service_->UpdateUI(service_worker_registration_id, unique_id, developer_id,
+ service_->UpdateUI(service_worker_registration_id, developer_id, unique_id,
title, SkBitmap(),
base::BindOnce(&BackgroundFetchServiceTest::DidGetError,
base::Unretained(this),
@@ -237,10 +239,11 @@ class BackgroundFetchServiceTest : public BackgroundFetchTestBase {
run_loop.Run();
+ // Allow all the DatabaseTasks resulting from Abort to complete.
+ thread_bundle_.RunUntilIdle();
+
// We only delete the registration if we successfully abort.
if (*out_error == blink::mojom::BackgroundFetchError::NONE) {
- // TODO(crbug.com/850894): The Abort callback is being resolved early.
- base::RunLoop().RunUntilIdle();
// The error passed to the histogram counter is not related to this
// |*out_error|, but the result of
// BackgroundFetchDataManager::DeleteRegistration. For the purposes these
@@ -727,7 +730,7 @@ TEST_F(BackgroundFetchServiceTest, UpdateUI) {
// Immediately update the title. This should succeed.
UpdateUI(registration_id.service_worker_registration_id(),
- registration_id.unique_id(), registration_id.developer_id(),
+ registration_id.developer_id(), registration_id.unique_id(),
second_title, &error);
EXPECT_EQ(blink::mojom::BackgroundFetchError::NONE, error);
@@ -929,8 +932,8 @@ TEST_F(BackgroundFetchServiceTest, UniqueId) {
// title of the second registration only.
std::string updated_second_registration_title = "Foo";
UpdateUI(second_registration_id.service_worker_registration_id(),
- second_registration_id.unique_id(),
second_registration_id.developer_id(),
+ second_registration_id.unique_id(),
updated_second_registration_title, &error);
EXPECT_EQ(blink::mojom::BackgroundFetchError::NONE, error);
@@ -939,8 +942,8 @@ TEST_F(BackgroundFetchServiceTest, UniqueId) {
// backgroundfetchsuccess or backgroundfetchfail event, both of which should
// work even though that registration is no longer active).
UpdateUI(aborted_registration_id.service_worker_registration_id(),
- aborted_registration_id.unique_id(),
- aborted_registration_id.developer_id(), "Bar", &error);
+ aborted_registration_id.developer_id(),
+ aborted_registration_id.unique_id(), "Bar", &error);
EXPECT_EQ(blink::mojom::BackgroundFetchError::INVALID_ID, error);
// Verify that the second registration's title was indeed updated, and that it
diff --git a/chromium/content/browser/background_fetch/background_fetch_test_base.cc b/chromium/content/browser/background_fetch/background_fetch_test_base.cc
index ef6f354e99c..f09f7a36dda 100644
--- a/chromium/content/browser/background_fetch/background_fetch_test_base.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_test_base.cc
@@ -67,6 +67,10 @@ void DidUnregisterServiceWorker(base::Closure quit_closure,
std::move(quit_closure).Run();
}
+GURL GetPatternForId(int64_t id) {
+ return GURL(kTestOrigin + base::IntToString(id));
+}
+
} // namespace
BackgroundFetchTestBase::BackgroundFetchTestBase()
@@ -99,7 +103,7 @@ int64_t BackgroundFetchTestBase::RegisterServiceWorker() {
{
blink::mojom::ServiceWorkerRegistrationOptions options;
- options.scope = origin_.GetURL();
+ options.scope = GetPatternForId(next_pattern_id_++);
base::RunLoop run_loop;
embedded_worker_test_helper_.context()->RegisterServiceWorker(
script_url, options,
@@ -142,10 +146,11 @@ int64_t BackgroundFetchTestBase::RegisterServiceWorker() {
return service_worker_registration_id;
}
-void BackgroundFetchTestBase::UnregisterServiceWorker() {
+void BackgroundFetchTestBase::UnregisterServiceWorker(
+ int64_t service_worker_registration_id) {
base::RunLoop run_loop;
embedded_worker_test_helper_.context()->UnregisterServiceWorker(
- origin_.GetURL(),
+ GetPatternForId(service_worker_registration_id),
base::BindOnce(&DidUnregisterServiceWorker, run_loop.QuitClosure()));
run_loop.Run();
}
@@ -167,11 +172,11 @@ std::unique_ptr<BackgroundFetchRegistration>
BackgroundFetchTestBase::CreateBackgroundFetchRegistration(
const std::string& developer_id,
const std::string& unique_id,
- blink::mojom::BackgroundFetchState state,
+ blink::mojom::BackgroundFetchResult result,
blink::mojom::BackgroundFetchFailureReason failure_reason) {
auto registration = std::make_unique<BackgroundFetchRegistration>(
developer_id, unique_id, 0 /* upload_total */, 0 /* uploaded */,
- 0 /* download_total */, 0 /* downloaded */, state, failure_reason);
+ 0 /* download_total */, 0 /* downloaded */, result, failure_reason);
return registration;
}
diff --git a/chromium/content/browser/background_fetch/background_fetch_test_base.h b/chromium/content/browser/background_fetch/background_fetch_test_base.h
index 9bb6f0b09c9..4244b015be8 100644
--- a/chromium/content/browser/background_fetch/background_fetch_test_base.h
+++ b/chromium/content/browser/background_fetch/background_fetch_test_base.h
@@ -47,7 +47,7 @@ class BackgroundFetchTestBase : public ::testing::Test {
// Unregisters the test Service Worker and verifies that the unregistration
// succeeded.
- void UnregisterServiceWorker();
+ void UnregisterServiceWorker(int64_t service_worker_registration_id);
// Creates a ServiceWorkerFetchRequest instance for the given details and
// provides a faked |response|.
@@ -61,7 +61,7 @@ class BackgroundFetchTestBase : public ::testing::Test {
CreateBackgroundFetchRegistration(
const std::string& developer_id,
const std::string& unique_id,
- blink::mojom::BackgroundFetchState state,
+ blink::mojom::BackgroundFetchResult result,
blink::mojom::BackgroundFetchFailureReason failure_reason);
// Returns the embedded worker test helper instance, which can be used to
@@ -93,6 +93,8 @@ class BackgroundFetchTestBase : public ::testing::Test {
StoragePartition* storage_partition_;
+ int next_pattern_id_ = 0;
+
// Vector of ServiceWorkerRegistration instances that have to be kept alive
// for the lifetime of this test.
std::vector<scoped_refptr<ServiceWorkerRegistration>>
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 3655aae7eb8..5a165cf5a9d 100644
--- a/chromium/content/browser/background_fetch/mock_background_fetch_delegate.cc
+++ b/chromium/content/browser/background_fetch/mock_background_fetch_delegate.cc
@@ -63,7 +63,7 @@ void MockBackgroundFetchDelegate::GetPermissionForOrigin(
GetPermissionForOriginCallback callback) {
base::SequencedTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
- base::BindOnce(std::move(callback), true /* has_permission */));
+ base::BindOnce(std::move(callback), BackgroundFetchPermission::ALLOWED));
}
void MockBackgroundFetchDelegate::GetIconDisplaySize(
@@ -95,14 +95,12 @@ void MockBackgroundFetchDelegate::DownloadUrl(
std::unique_ptr<TestResponse> test_response = std::move(url_iter->second);
url_responses_.erase(url_iter);
- std::unique_ptr<BackgroundFetchResponse> response =
- std::make_unique<BackgroundFetchResponse>(std::vector<GURL>({url}),
- test_response->headers);
-
PostAbortCheckingTask(
job_unique_id,
base::BindOnce(&BackgroundFetchDelegate::Client::OnDownloadStarted,
- client(), job_unique_id, guid, std::move(response)));
+ client(), job_unique_id, guid,
+ std::make_unique<BackgroundFetchResponse>(
+ std::vector<GURL>({url}), test_response->headers)));
if (test_response->data.size()) {
// Report progress at 50% complete.
@@ -140,16 +138,20 @@ void MockBackgroundFetchDelegate::DownloadUrl(
&BackgroundFetchDelegate::Client::OnDownloadComplete, client(),
job_unique_id, guid,
std::make_unique<BackgroundFetchResult>(
+ std::make_unique<BackgroundFetchResponse>(
+ std::vector<GURL>({url}), test_response->headers),
base::Time::Now(), response_path,
base::nullopt /* blob_handle */, test_response->data.size())));
} else {
+ auto response = std::make_unique<BackgroundFetchResponse>(
+ std::vector<GURL>({url}), test_response->headers);
+ auto result = std::make_unique<BackgroundFetchResult>(
+ std::move(response), base::Time::Now(),
+ BackgroundFetchResult::FailureReason::FETCH_ERROR);
PostAbortCheckingTask(
job_unique_id,
base::BindOnce(&BackgroundFetchDelegate::Client::OnDownloadComplete,
- client(), job_unique_id, guid,
- std::make_unique<BackgroundFetchResult>(
- base::Time::Now(),
- BackgroundFetchResult::FailureReason::UNKNOWN)));
+ client(), job_unique_id, guid, std::move(result)));
}
seen_guids_.insert(guid);
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 17665e2b145..93c37d4d2cd 100644
--- a/chromium/content/browser/background_fetch/storage/create_metadata_task.cc
+++ b/chromium/content/browser/background_fetch/storage/create_metadata_task.cc
@@ -4,8 +4,10 @@
#include "content/browser/background_fetch/storage/create_metadata_task.h"
+#include <set>
#include <utility>
+#include "base/barrier_closure.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "content/browser/background_fetch/background_fetch_data_manager.h"
@@ -19,24 +21,148 @@ namespace content {
namespace background_fetch {
+namespace {
+
+// TODO(crbug.com/889401): Consider making this configurable by finch.
+constexpr size_t kRegistrationLimitPerOrigin = 5u;
+
+// Finds the number of active registrations associated with the provided origin,
+// and compares it with the limit to determine whether this registration can go
+// through.
+class CanCreateRegistrationTask : public DatabaseTask {
+ public:
+ using CanCreateRegistrationCallback =
+ base::OnceCallback<void(blink::mojom::BackgroundFetchError, bool)>;
+
+ CanCreateRegistrationTask(DatabaseTaskHost* host,
+ const url::Origin& origin,
+ CanCreateRegistrationCallback callback)
+ : DatabaseTask(host),
+ origin_(origin),
+ callback_(std::move(callback)),
+ weak_factory_(this) {}
+
+ ~CanCreateRegistrationTask() override = default;
+
+ void Start() override {
+ service_worker_context()->GetRegistrationsForOrigin(
+ origin_,
+ base::BindOnce(&CanCreateRegistrationTask::DidGetRegistrationsForOrigin,
+ weak_factory_.GetWeakPtr()));
+ }
+
+ private:
+ void DidGetRegistrationsForOrigin(
+ blink::ServiceWorkerStatusCode status,
+ const std::vector<scoped_refptr<ServiceWorkerRegistration>>&
+ registrations) {
+ switch (ToDatabaseStatus(status)) {
+ case DatabaseStatus::kOk:
+ break;
+ case DatabaseStatus::kNotFound:
+ FinishWithError(blink::mojom::BackgroundFetchError::NONE);
+ return;
+ case DatabaseStatus::kFailed:
+ FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
+ return;
+ }
+
+ std::set<int64_t> registration_ids;
+ for (const auto& registration : registrations)
+ registration_ids.insert(registration->id());
+
+ base::RepeatingClosure barrier_closure = base::BarrierClosure(
+ registration_ids.size(),
+ base::BindOnce(&CanCreateRegistrationTask::FinishWithError,
+ weak_factory_.GetWeakPtr(),
+ blink::mojom::BackgroundFetchError::NONE));
+
+ for (int64_t registration_id : registration_ids) {
+ service_worker_context()->GetRegistrationUserDataByKeyPrefix(
+ registration_id, kActiveRegistrationUniqueIdKeyPrefix,
+ base::BindOnce(&CanCreateRegistrationTask::DidGetActiveRegistrations,
+ weak_factory_.GetWeakPtr(), barrier_closure));
+ }
+ }
+
+ void DidGetActiveRegistrations(base::OnceClosure done_closure,
+ const std::vector<std::string>& data,
+ blink::ServiceWorkerStatusCode status) {
+ switch (ToDatabaseStatus(status)) {
+ case DatabaseStatus::kNotFound:
+ std::move(done_closure).Run();
+ return;
+ case DatabaseStatus::kOk:
+ num_active_registrations_ += data.size();
+ std::move(done_closure).Run();
+ return;
+ case DatabaseStatus::kFailed:
+ FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
+ return;
+ }
+ }
+
+ void FinishWithError(blink::mojom::BackgroundFetchError error) override {
+ std::move(callback_).Run(
+ error, num_active_registrations_ < kRegistrationLimitPerOrigin);
+ Finished(); // Destroys |this|.
+ }
+
+ url::Origin origin_;
+ CanCreateRegistrationCallback callback_;
+
+ // The number of existing registrations found for |origin_|.
+ size_t num_active_registrations_ = 0u;
+
+ base::WeakPtrFactory<CanCreateRegistrationTask>
+ weak_factory_; // Keep as last.
+};
+
+} // namespace
+
CreateMetadataTask::CreateMetadataTask(
DatabaseTaskHost* host,
const BackgroundFetchRegistrationId& registration_id,
const std::vector<ServiceWorkerFetchRequest>& requests,
const BackgroundFetchOptions& options,
const SkBitmap& icon,
+ bool start_paused,
CreateMetadataCallback callback)
: DatabaseTask(host),
registration_id_(registration_id),
requests_(requests),
options_(options),
icon_(icon),
+ start_paused_(start_paused),
callback_(std::move(callback)),
weak_factory_(this) {}
CreateMetadataTask::~CreateMetadataTask() = default;
void CreateMetadataTask::Start() {
+ // Check if the registration can be created.
+ AddSubTask(std::make_unique<CanCreateRegistrationTask>(
+ this, registration_id_.origin(),
+ base::BindOnce(&CreateMetadataTask::DidGetCanCreateRegistration,
+ weak_factory_.GetWeakPtr())));
+}
+
+void CreateMetadataTask::DidGetCanCreateRegistration(
+ blink::mojom::BackgroundFetchError error,
+ bool can_create) {
+ if (error == blink::mojom::BackgroundFetchError::STORAGE_ERROR) {
+ SetStorageErrorAndFinish(
+ BackgroundFetchStorageError::kServiceWorkerStorageError);
+ return;
+ }
+
+ DCHECK_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ if (!can_create) {
+ FinishWithError(
+ blink::mojom::BackgroundFetchError::REGISTRATION_LIMIT_EXCEEDED);
+ return;
+ }
+
// Check if there is enough quota to download the data first.
if (options_.download_total > 0) {
IsQuotaAvailable(registration_id_.origin(), options_.download_total,
@@ -101,8 +227,8 @@ void CreateMetadataTask::InitializeMetadataProto() {
registration_proto->set_unique_id(registration_id_.unique_id());
registration_proto->set_developer_id(registration_id_.developer_id());
registration_proto->set_download_total(options_.download_total);
- registration_proto->set_state(
- proto::BackgroundFetchRegistration_BackgroundFetchState_PENDING);
+ registration_proto->set_result(
+ proto::BackgroundFetchRegistration_BackgroundFetchResult_UNSET);
registration_proto->set_failure_reason(
proto::BackgroundFetchRegistration_BackgroundFetchFailureReason_NONE);
@@ -236,7 +362,7 @@ void CreateMetadataTask::FinishWithError(
for (auto& observer : data_manager()->observers()) {
observer.OnRegistrationCreated(registration_id_, registration, options_,
- icon_, requests_.size());
+ icon_, requests_.size(), start_paused_);
}
}
diff --git a/chromium/content/browser/background_fetch/storage/create_metadata_task.h b/chromium/content/browser/background_fetch/storage/create_metadata_task.h
index 33307624820..e7eedc65eb0 100644
--- a/chromium/content/browser/background_fetch/storage/create_metadata_task.h
+++ b/chromium/content/browser/background_fetch/storage/create_metadata_task.h
@@ -33,6 +33,7 @@ class CreateMetadataTask : public DatabaseTask {
const std::vector<ServiceWorkerFetchRequest>& requests,
const BackgroundFetchOptions& options,
const SkBitmap& icon,
+ bool start_paused,
CreateMetadataCallback callback);
~CreateMetadataTask() override;
@@ -40,6 +41,8 @@ class CreateMetadataTask : public DatabaseTask {
void Start() override;
private:
+ void DidGetCanCreateRegistration(blink::mojom::BackgroundFetchError error,
+ bool can_create);
void DidGetIsQuotaAvailable(bool is_available);
void GetRegistrationUniqueId();
@@ -64,6 +67,7 @@ class CreateMetadataTask : public DatabaseTask {
std::vector<ServiceWorkerFetchRequest> requests_;
BackgroundFetchOptions options_;
SkBitmap icon_;
+ bool start_paused_;
CreateMetadataCallback callback_;
std::unique_ptr<proto::BackgroundFetchMetadata> metadata_proto_;
diff --git a/chromium/content/browser/background_fetch/storage/database_helpers.cc b/chromium/content/browser/background_fetch/storage/database_helpers.cc
index 691e721e6ad..caac11bb7fc 100644
--- a/chromium/content/browser/background_fetch/storage/database_helpers.cc
+++ b/chromium/content/browser/background_fetch/storage/database_helpers.cc
@@ -101,15 +101,15 @@ bool ToBackgroundFetchRegistration(
registration->uploaded = registration_proto.uploaded();
registration->download_total = registration_proto.download_total();
registration->downloaded = registration_proto.downloaded();
- switch (registration_proto.state()) {
- case proto::BackgroundFetchRegistration_BackgroundFetchState_PENDING:
- registration->state = blink::mojom::BackgroundFetchState::PENDING;
+ switch (registration_proto.result()) {
+ case proto::BackgroundFetchRegistration_BackgroundFetchResult_UNSET:
+ registration->result = blink::mojom::BackgroundFetchResult::UNSET;
break;
- case proto::BackgroundFetchRegistration_BackgroundFetchState_FAILURE:
- registration->state = blink::mojom::BackgroundFetchState::FAILURE;
+ case proto::BackgroundFetchRegistration_BackgroundFetchResult_FAILURE:
+ registration->result = blink::mojom::BackgroundFetchResult::FAILURE;
break;
- case proto::BackgroundFetchRegistration_BackgroundFetchState_SUCCESS:
- registration->state = blink::mojom::BackgroundFetchState::SUCCESS;
+ case proto::BackgroundFetchRegistration_BackgroundFetchResult_SUCCESS:
+ registration->result = blink::mojom::BackgroundFetchResult::SUCCESS;
break;
default:
NOTREACHED();
diff --git a/chromium/content/browser/background_fetch/storage/database_helpers.h b/chromium/content/browser/background_fetch/storage/database_helpers.h
index bca77cdc83d..82ea96e1dab 100644
--- a/chromium/content/browser/background_fetch/storage/database_helpers.h
+++ b/chromium/content/browser/background_fetch/storage/database_helpers.h
@@ -34,7 +34,8 @@ const char kActiveRequestKeyPrefix[] = "bgfetch_active_request_";
const char kCompletedRequestKeyPrefix[] = "bgfetch_completed_request_";
// Database Keys.
-std::string ActiveRegistrationUniqueIdKey(const std::string& developer_id);
+CONTENT_EXPORT std::string ActiveRegistrationUniqueIdKey(
+ const std::string& developer_id);
CONTENT_EXPORT std::string RegistrationKey(const std::string& unique_id);
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
index 1d9a170a594..ee60d40d93d 100644
--- a/chromium/content/browser/background_fetch/storage/get_settled_fetches_task.cc
+++ b/chromium/content/browser/background_fetch/storage/get_settled_fetches_task.cc
@@ -9,6 +9,7 @@
#include "content/browser/background_fetch/storage/database_helpers.h"
#include "content/browser/cache_storage/cache_storage_manager.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
+#include "services/network/public/cpp/cors/cors.h"
namespace content {
@@ -69,7 +70,7 @@ void GetSettledFetchesTask::DidGetCompletedRequests(
SetStorageError(BackgroundFetchStorageError::kServiceWorkerStorageError);
break;
case DatabaseStatus::kNotFound:
- background_fetch_succeeded_ = false;
+ failure_reason_ = blink::mojom::BackgroundFetchFailureReason::FETCH_ERROR;
error_ = blink::mojom::BackgroundFetchError::INVALID_ID;
break;
}
@@ -81,12 +82,11 @@ void GetSettledFetchesTask::DidGetCompletedRequests(
serialized_completed_request)) {
// Service worker database has been corrupted. Abandon fetches.
SetStorageError(BackgroundFetchStorageError::kServiceWorkerStorageError);
- background_fetch_succeeded_ = false;
+ failure_reason_ = blink::mojom::BackgroundFetchFailureReason::
+ SERVICE_WORKER_UNAVAILABLE;
AbandonFetches(registration_id_.service_worker_registration_id());
break;
}
- if (!completed_requests_.back().succeeded())
- background_fetch_succeeded_ = false;
}
std::move(done_closure).Run();
}
@@ -235,7 +235,7 @@ void GetSettledFetchesTask::DidMatchAllResponsesForRequest(
void GetSettledFetchesTask::FillUncachedResponse(
BackgroundFetchSettledFetch* settled_fetch,
base::OnceClosure callback) {
- background_fetch_succeeded_ = false;
+ failure_reason_ = blink::mojom::BackgroundFetchFailureReason::FETCH_ERROR;
// TODO(rayankans): Fill unmatched response with error reports.
DCHECK(!settled_fetch->response);
@@ -252,8 +252,24 @@ void GetSettledFetchesTask::FinishWithError(
if (HasStorageError())
error = blink::mojom::BackgroundFetchError::STORAGE_ERROR;
ReportStorageError();
+
+ if (error == blink::mojom::BackgroundFetchError::NONE) {
+ for (const auto& settled_fetch : settled_fetches_) {
+ if (!settled_fetch.response->status_code) {
+ // A status_code of 0 means no headers were returned.
+ failure_reason_ =
+ blink::mojom::BackgroundFetchFailureReason::FETCH_ERROR;
+ break;
+ }
+ if (!network::cors::IsOkStatus(settled_fetch.response->status_code)) {
+ failure_reason_ =
+ blink::mojom::BackgroundFetchFailureReason::BAD_STATUS;
+ break;
+ }
+ }
+ }
std::move(settled_fetches_callback_)
- .Run(error, background_fetch_succeeded_, std::move(settled_fetches_),
+ .Run(error, failure_reason_, std::move(settled_fetches_),
{} /* blob_data_handles */);
Finished(); // Destroys |this|.
}
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
index 2b5183a09b5..15417204b74 100644
--- a/chromium/content/browser/background_fetch/storage/get_settled_fetches_task.h
+++ b/chromium/content/browser/background_fetch/storage/get_settled_fetches_task.h
@@ -25,7 +25,7 @@ class GetSettledFetchesTask : public DatabaseTask {
// TODO(nator): Remove BlobDataHandle since we're not using them.
using SettledFetchesCallback = base::OnceCallback<void(
blink::mojom::BackgroundFetchError,
- bool,
+ blink::mojom::BackgroundFetchFailureReason,
std::vector<BackgroundFetchSettledFetch>,
std::vector<std::unique_ptr<storage::BlobDataHandle>>)>;
@@ -81,7 +81,8 @@ class GetSettledFetchesTask : public DatabaseTask {
// SettledFetchesCallback params.
std::vector<BackgroundFetchSettledFetch> settled_fetches_;
- bool background_fetch_succeeded_ = true;
+ blink::mojom::BackgroundFetchFailureReason failure_reason_ =
+ blink::mojom::BackgroundFetchFailureReason::NONE;
// Storage params.
CacheStorageCacheHandle handle_;
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 6007fb6b929..68c9de01889 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
@@ -63,14 +63,10 @@ void MarkRegistrationForDeletionTask::DidGetActiveUniqueId(
proto::BackgroundFetchMetadata metadata_proto;
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
- // keys are not required by GetRegistration.
- service_worker_context()->ClearRegistrationUserDataByKeyPrefixes(
+ // Mark registration as no longer active.
+ service_worker_context()->ClearRegistrationUserData(
registration_id_.service_worker_registration_id(),
- {ActiveRegistrationUniqueIdKey(registration_id_.developer_id()),
- PendingRequestKeyPrefix(registration_id_.unique_id())},
+ {ActiveRegistrationUniqueIdKey(registration_id_.developer_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
index a6c9de6c61a..a941ac21a08 100644
--- a/chromium/content/browser/background_fetch/storage/mark_request_complete_task.cc
+++ b/chromium/content/browser/background_fetch/storage/mark_request_complete_task.cc
@@ -40,11 +40,11 @@ MarkRequestCompleteTask::MarkRequestCompleteTask(
DatabaseTaskHost* host,
BackgroundFetchRegistrationId registration_id,
scoped_refptr<BackgroundFetchRequestInfo> request_info,
- base::OnceClosure closure)
+ MarkRequestCompleteCallback callback)
: DatabaseTask(host),
registration_id_(registration_id),
request_info_(std::move(request_info)),
- closure_(std::move(closure)),
+ callback_(std::move(callback)),
weak_factory_(this) {}
MarkRequestCompleteTask::~MarkRequestCompleteTask() = default;
@@ -62,17 +62,23 @@ void MarkRequestCompleteTask::Start() {
void MarkRequestCompleteTask::StoreResponse(base::OnceClosure done_closure) {
auto response = blink::mojom::FetchAPIResponse::New();
response->url_list = request_info_->GetURLChain();
- // TODO(crbug.com/838837): fill error and cors_exposed_header_names in
- // response.
response->response_type = network::mojom::FetchResponseType::kDefault;
response->response_time = request_info_->GetResponseTime();
- BackgroundFetchCrossOriginFilter filter(registration_id_.origin(),
- *request_info_);
- if (filter.CanPopulateBody())
- PopulateResponseBody(response.get());
- else
+ if (request_info_->GetURLChain().empty()) {
+ // The URL chain was not provided, so this is a failed response.
+ DCHECK(!request_info_->IsResultSuccess());
is_response_successful_ = false;
+ } else {
+ // TODO(crbug.com/884672): Move cross origin checks to when the response
+ // headers are available.
+ BackgroundFetchCrossOriginFilter filter(registration_id_.origin(),
+ *request_info_);
+ if (filter.CanPopulateBody())
+ PopulateResponseBody(response.get());
+ else
+ is_response_successful_ = false;
+ }
if (!IsOK(*request_info_))
is_response_successful_ = false;
@@ -277,8 +283,8 @@ void MarkRequestCompleteTask::DidGetMetadata(
return;
}
- metadata->mutable_registration()->set_download_total(
- metadata->registration().download_total() + request_info_->GetFileSize());
+ metadata->mutable_registration()->set_downloaded(
+ metadata->registration().downloaded() + request_info_->GetFileSize());
service_worker_context()->StoreRegistrationUserData(
registration_id_.service_worker_registration_id(),
@@ -292,15 +298,21 @@ void MarkRequestCompleteTask::DidGetMetadata(
void MarkRequestCompleteTask::DidStoreMetadata(
base::OnceClosure done_closure,
blink::ServiceWorkerStatusCode status) {
- SetStorageError(BackgroundFetchStorageError::kServiceWorkerStorageError);
+ if (ToDatabaseStatus(status) != DatabaseStatus::kOk)
+ SetStorageError(BackgroundFetchStorageError::kServiceWorkerStorageError);
std::move(done_closure).Run();
}
void MarkRequestCompleteTask::FinishWithError(
blink::mojom::BackgroundFetchError error) {
+ if (HasStorageError()) {
+ error = blink::mojom::BackgroundFetchError::STORAGE_ERROR;
+ for (auto& observer : data_manager()->observers())
+ observer.OnFetchStorageError(registration_id_);
+ }
ReportStorageError();
- std::move(closure_).Run();
+ std::move(callback_).Run(error);
Finished();
}
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
index 09e11561eb4..870f781255b 100644
--- a/chromium/content/browser/background_fetch/storage/mark_request_complete_task.h
+++ b/chromium/content/browser/background_fetch/storage/mark_request_complete_task.h
@@ -21,11 +21,14 @@ namespace background_fetch {
// download response in cache storage.
class MarkRequestCompleteTask : public DatabaseTask {
public:
+ using MarkRequestCompleteCallback =
+ base::OnceCallback<void(blink::mojom::BackgroundFetchError)>;
+
MarkRequestCompleteTask(
DatabaseTaskHost* host,
BackgroundFetchRegistrationId registration_id,
scoped_refptr<BackgroundFetchRequestInfo> request_info,
- base::OnceClosure closure);
+ MarkRequestCompleteCallback callback);
~MarkRequestCompleteTask() override;
@@ -73,7 +76,7 @@ class MarkRequestCompleteTask : public DatabaseTask {
BackgroundFetchRegistrationId registration_id_;
scoped_refptr<BackgroundFetchRequestInfo> request_info_;
- base::OnceClosure closure_;
+ MarkRequestCompleteCallback callback_;
proto::BackgroundFetchCompletedRequest completed_request_;
bool is_response_successful_ = true;
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
index acccbe39878..a28ed8a65e7 100644
--- 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
@@ -6,6 +6,7 @@
#include "base/guid.h"
#include "content/browser/background_fetch/background_fetch_data_manager.h"
+#include "content/browser/background_fetch/background_fetch_data_manager_observer.h"
#include "content/browser/background_fetch/storage/database_helpers.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
@@ -16,11 +17,9 @@ namespace background_fetch {
StartNextPendingRequestTask::StartNextPendingRequestTask(
DatabaseTaskHost* host,
const BackgroundFetchRegistrationId& registration_id,
- const BackgroundFetchRegistration& registration,
NextRequestCallback callback)
: DatabaseTask(host),
registration_id_(registration_id),
- registration_(registration),
callback_(std::move(callback)),
weak_factory_(this) {
DCHECK(!registration_id_.is_null());
@@ -35,7 +34,7 @@ void StartNextPendingRequestTask::Start() {
void StartNextPendingRequestTask::GetPendingRequests() {
service_worker_context()->GetRegistrationUserDataByKeyPrefix(
registration_id_.service_worker_registration_id(),
- PendingRequestKeyPrefix(registration_.unique_id),
+ PendingRequestKeyPrefix(registration_id_.unique_id()),
base::BindOnce(&StartNextPendingRequestTask::DidGetPendingRequests,
weak_factory_.GetWeakPtr()));
}
@@ -65,43 +64,7 @@ void StartNextPendingRequestTask::DidGetPendingRequests(
return;
}
- // Make sure there isn't already an Active Request.
- // This might happen if the browser is killed in-between writes.
- service_worker_context()->GetRegistrationUserData(
- registration_id_.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,
- blink::ServiceWorkerStatusCode status) {
- switch (ToDatabaseStatus(status)) {
- case DatabaseStatus::kFailed:
- SetStorageErrorAndFinish(
- BackgroundFetchStorageError::kServiceWorkerStorageError);
- return;
- case DatabaseStatus::kNotFound:
- CreateAndStoreActiveRequest();
- return;
- case DatabaseStatus::kOk:
- // We already stored the active request.
- if (!active_request_.ParseFromString(data.front())) {
- // Service worker database has been corrupted. Abandon fetches.
- AbandonFetches(registration_id_.service_worker_registration_id());
- SetStorageErrorAndFinish(
- BackgroundFetchStorageError::kServiceWorkerStorageError);
- return;
- }
- StartDownload();
- return;
- }
- NOTREACHED();
-}
-
-void StartNextPendingRequestTask::CreateAndStoreActiveRequest() {
+ // Create an active request.
proto::BackgroundFetchActiveRequest active_request;
active_request_.set_download_guid(base::GenerateGUID());
@@ -132,19 +95,12 @@ void StartNextPendingRequestTask::DidStoreActiveRequest(
BackgroundFetchStorageError::kServiceWorkerStorageError);
return;
}
- StartDownload();
-}
-void StartNextPendingRequestTask::StartDownload() {
- DCHECK(!active_request_.download_guid().empty());
-
- auto next_request = base::MakeRefCounted<BackgroundFetchRequestInfo>(
+ 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);
+ next_request_->SetDownloadGuid(active_request_.download_guid());
// Delete the pending request.
service_worker_context()->ClearRegistrationUserData(
@@ -167,10 +123,13 @@ void StartNextPendingRequestTask::DidDeletePendingRequest(
void StartNextPendingRequestTask::FinishWithError(
blink::mojom::BackgroundFetchError error) {
+ if (HasStorageError()) {
+ for (auto& observer : data_manager()->observers())
+ observer.OnFetchStorageError(registration_id_);
+ }
ReportStorageError();
- if (callback_)
- std::move(callback_).Run(nullptr /* request */);
+ std::move(callback_).Run(error, std::move(next_request_));
Finished(); // Destroys |this|.
}
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
index 5faaeb00e5f..48be7080d15 100644
--- 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
@@ -21,12 +21,12 @@ namespace background_fetch {
class StartNextPendingRequestTask : public DatabaseTask {
public:
using NextRequestCallback =
- base::OnceCallback<void(scoped_refptr<BackgroundFetchRequestInfo>)>;
+ base::OnceCallback<void(blink::mojom::BackgroundFetchError,
+ scoped_refptr<BackgroundFetchRequestInfo>)>;
StartNextPendingRequestTask(
DatabaseTaskHost* host,
const BackgroundFetchRegistrationId& registration_id,
- const BackgroundFetchRegistration& registration,
NextRequestCallback callback);
~StartNextPendingRequestTask() override;
@@ -43,12 +43,8 @@ class StartNextPendingRequestTask : public DatabaseTask {
void DidFindActiveRequest(const std::vector<std::string>& data,
blink::ServiceWorkerStatusCode status);
- void CreateAndStoreActiveRequest();
-
void DidStoreActiveRequest(blink::ServiceWorkerStatusCode status);
- void StartDownload();
-
void DidDeletePendingRequest(blink::ServiceWorkerStatusCode status);
void FinishWithError(blink::mojom::BackgroundFetchError error) override;
@@ -56,7 +52,6 @@ class StartNextPendingRequestTask : public DatabaseTask {
std::string HistogramName() const override;
BackgroundFetchRegistrationId registration_id_;
- BackgroundFetchRegistration registration_;
NextRequestCallback callback_;
// protos don't support move semantics, so these class members will be used
@@ -64,6 +59,8 @@ class StartNextPendingRequestTask : public DatabaseTask {
proto::BackgroundFetchPendingRequest pending_request_;
proto::BackgroundFetchActiveRequest active_request_;
+ scoped_refptr<BackgroundFetchRequestInfo> next_request_;
+
base::WeakPtrFactory<StartNextPendingRequestTask>
weak_factory_; // Keep as last.
diff --git a/chromium/content/browser/background_sync/background_sync_browsertest.cc b/chromium/content/browser/background_sync/background_sync_browsertest.cc
index 678766f9341..3c4f3d499b0 100644
--- a/chromium/content/browser/background_sync/background_sync_browsertest.cc
+++ b/chromium/content/browser/background_sync/background_sync_browsertest.cc
@@ -14,6 +14,7 @@
#include "base/run_loop.h"
#include "base/strings/string_split.h"
#include "base/strings/stringprintf.h"
+#include "base/task/post_task.h"
#include "base/task_runner_util.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/background_sync/background_sync_context.h"
@@ -24,6 +25,7 @@
#include "content/browser/service_worker/service_worker_registration.h"
#include "content/browser/storage_partition_impl.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_switches.h"
@@ -131,13 +133,15 @@ class BackgroundSyncBrowserTest : public ContentBrowserTest {
~BackgroundSyncBrowserTest() override {}
void SetUp() override {
- background_sync_test_util::SetIgnoreNetworkChangeNotifier(true);
+ background_sync_test_util::SetIgnoreNetworkChanges(true);
ContentBrowserTest::SetUp();
}
void SetIncognitoMode(bool incognito) {
shell_ = incognito ? CreateOffTheRecordBrowser() : shell();
+ // Let any async shell creation logic finish.
+ base::RunLoop().RunUntilIdle();
}
StoragePartitionImpl* GetStorage() {
@@ -233,8 +237,8 @@ bool BackgroundSyncBrowserTest::RegistrationPending(const std::string& tag) {
base::BindOnce(&RegistrationPendingCallback, run_loop.QuitClosure(),
base::ThreadTaskRunnerHandle::Get(), &is_pending);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&RegistrationPendingOnIOThread, base::WrapRefCounted(sync_context),
base::WrapRefCounted(service_worker_context), tag,
@@ -251,8 +255,8 @@ void BackgroundSyncBrowserTest::SetMaxSyncAttempts(int max_sync_attempts) {
StoragePartitionImpl* storage = GetStorage();
BackgroundSyncContext* sync_context = storage->GetBackgroundSyncContext();
- BrowserThread::PostTaskAndReply(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraitsAndReply(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&SetMaxSyncAttemptsOnIOThread,
base::WrapRefCounted(sync_context), max_sync_attempts),
run_loop.QuitClosure());
diff --git a/chromium/content/browser/background_sync/background_sync_context.cc b/chromium/content/browser/background_sync/background_sync_context.cc
index d460b065966..82e1cac6f54 100644
--- a/chromium/content/browser/background_sync/background_sync_context.cc
+++ b/chromium/content/browser/background_sync/background_sync_context.cc
@@ -8,16 +8,18 @@
#include "base/bind.h"
#include "base/stl_util.h"
+#include "base/task/post_task.h"
#include "content/browser/background_sync/background_sync_manager.h"
#include "content/browser/background_sync/background_sync_service_impl.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
namespace content {
BackgroundSyncContext::BackgroundSyncContext()
: base::RefCountedDeleteOnSequence<BackgroundSyncContext>(
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)) {}
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO})) {}
BackgroundSyncContext::~BackgroundSyncContext() {
// The destructor must run on the IO thread because it implicitly accesses
@@ -32,24 +34,24 @@ void BackgroundSyncContext::Init(
const scoped_refptr<ServiceWorkerContextWrapper>& context) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&BackgroundSyncContext::CreateBackgroundSyncManager, this,
context));
}
void BackgroundSyncContext::Shutdown() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&BackgroundSyncContext::ShutdownOnIO, this));
}
void BackgroundSyncContext::CreateService(
blink::mojom::BackgroundSyncServiceRequest request) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&BackgroundSyncContext::CreateServiceOnIOThread, this,
std::move(request)));
}
diff --git a/chromium/content/browser/background_sync/background_sync_manager.cc b/chromium/content/browser/background_sync/background_sync_manager.cc
index 0b5b90e9d39..73d01cfc92d 100644
--- a/chromium/content/browser/background_sync/background_sync_manager.cc
+++ b/chromium/content/browser/background_sync/background_sync_manager.cc
@@ -11,6 +11,7 @@
#include "base/location.h"
#include "base/memory/ptr_util.h"
#include "base/single_thread_task_runner.h"
+#include "base/task/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/default_clock.h"
#include "base/time/time.h"
@@ -26,6 +27,7 @@
#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/browser/background_sync_controller.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/permission_controller.h"
#include "content/public/browser/permission_type.h"
@@ -149,7 +151,7 @@ void OnSyncEventFinished(scoped_refptr<ServiceWorkerVersion> active_version,
int request_id,
ServiceWorkerVersion::StatusCallback callback,
blink::mojom::ServiceWorkerEventStatus status,
- base::Time dispatch_event_time) {
+ base::TimeTicks dispatch_event_time) {
if (!active_version->FinishRequest(
request_id,
status == blink::mojom::ServiceWorkerEventStatus::COMPLETED,
@@ -344,8 +346,8 @@ void BackgroundSyncManager::InitImpl(base::OnceClosure callback) {
return;
}
- BrowserThread::PostTaskAndReplyWithResult(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraitsAndReplyWithResult(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&GetControllerParameters, service_worker_context_,
std::make_unique<BackgroundSyncParameters>(*parameters_)),
base::BindOnce(&BackgroundSyncManager::InitDidGetControllerParameters,
@@ -494,8 +496,8 @@ void BackgroundSyncManager::RegisterImpl(
return;
}
- BrowserThread::PostTaskAndReplyWithResult(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraitsAndReplyWithResult(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&GetBackgroundSyncPermissionOnUIThread,
service_worker_context_,
sw_registration->pattern().GetOrigin()),
@@ -527,8 +529,8 @@ void BackgroundSyncManager::RegisterDidAskForPermission(
return;
}
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&NotifyBackgroundSyncRegisteredOnUIThread,
service_worker_context_,
sw_registration->pattern().GetOrigin()));
@@ -638,8 +640,7 @@ BackgroundSyncRegistration* BackgroundSyncManager::LookupActiveRegistration(
const std::string& tag) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- SWIdToRegistrationsMap::iterator it =
- active_registrations_.find(sw_registration_id);
+ auto it = active_registrations_.find(sw_registration_id);
if (it == active_registrations_.end())
return nullptr;
@@ -836,8 +837,7 @@ void BackgroundSyncManager::GetRegistrationsImpl(
return;
}
- SWIdToRegistrationsMap::iterator it =
- active_registrations_.find(sw_registration_id);
+ auto it = active_registrations_.find(sw_registration_id);
if (it != active_registrations_.end()) {
const BackgroundSyncRegistrations& registrations = it->second;
@@ -917,8 +917,8 @@ void BackgroundSyncManager::RunInBackgroundIfNecessary() {
// In case the browser closes (or to prevent it from closing), call
// RunInBackground to either wake up the browser at the wakeup delta or to
// keep the browser running.
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(
RunInBackgroundOnUIThread, service_worker_context_,
!soonest_wakeup_delta.is_max() /* should run in background */,
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 077a39c679d..f700acafc4e 100644
--- a/chromium/content/browser/background_sync/background_sync_manager_unittest.cc
+++ b/chromium/content/browser/background_sync/background_sync_manager_unittest.cc
@@ -37,7 +37,7 @@
#include "content/public/test/test_utils.h"
#include "content/test/mock_background_sync_controller.h"
#include "content/test/test_background_sync_manager.h"
-#include "net/base/network_change_notifier.h"
+#include "services/network/test/test_network_connection_tracker.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
@@ -86,8 +86,7 @@ void UnregisterServiceWorkerCallback(bool* called,
class BackgroundSyncManagerTest : public testing::Test {
public:
BackgroundSyncManagerTest()
- : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP),
- network_change_notifier_(net::NetworkChangeNotifier::CreateMock()) {
+ : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {
sync_options_1_.tag = "foo";
sync_options_1_.network_state = NETWORK_STATE_ONLINE;
@@ -97,7 +96,7 @@ class BackgroundSyncManagerTest : public testing::Test {
void SetUp() override {
// Don't let the tests be confused by the real-world device connectivity
- background_sync_test_util::SetIgnoreNetworkChangeNotifier(true);
+ background_sync_test_util::SetIgnoreNetworkChanges(true);
// TODO(jkarlin): Create a new object with all of the necessary SW calls
// so that we can inject test versions instead of bringing up all of this
@@ -129,7 +128,7 @@ class BackgroundSyncManagerTest : public testing::Test {
void TearDown() override {
// Restore the network observer functionality for subsequent tests
- background_sync_test_util::SetIgnoreNetworkChangeNotifier(false);
+ background_sync_test_util::SetIgnoreNetworkChanges(false);
}
void RegisterServiceWorkers() {
@@ -168,13 +167,13 @@ class BackgroundSyncManagerTest : public testing::Test {
EXPECT_TRUE(sw_registration_2_);
}
- void SetNetwork(net::NetworkChangeNotifier::ConnectionType connection_type) {
- net::NetworkChangeNotifier::NotifyObserversOfNetworkChangeForTests(
+ void SetNetwork(network::mojom::ConnectionType connection_type) {
+ network::TestNetworkConnectionTracker::GetInstance()->SetConnectionType(
connection_type);
if (test_background_sync_manager_) {
BackgroundSyncNetworkObserver* network_observer =
test_background_sync_manager_->GetNetworkObserverForTesting();
- network_observer->NotifyManagerIfNetworkChangedForTesting(
+ network_observer->NotifyManagerIfConnectionChangedForTesting(
connection_type);
base::RunLoop().RunUntilIdle();
}
@@ -216,7 +215,7 @@ class BackgroundSyncManagerTest : public testing::Test {
// the sync event fires by manipulating the network state as needed.
// NOTE: The setup of the network connection must happen after the
// BackgroundSyncManager has been created.
- SetNetwork(net::NetworkChangeNotifier::CONNECTION_NONE);
+ SetNetwork(network::mojom::ConnectionType::CONNECTION_NONE);
}
void InitBackgroundSyncManager() {
@@ -346,7 +345,7 @@ class BackgroundSyncManagerTest : public testing::Test {
void SetupForSyncEvent(
const TestBackgroundSyncManager::DispatchSyncCallback& callback) {
test_background_sync_manager_->set_dispatch_sync_callback(callback);
- SetNetwork(net::NetworkChangeNotifier::CONNECTION_WIFI);
+ SetNetwork(network::mojom::ConnectionType::CONNECTION_WIFI);
}
void DispatchSyncStatusCallback(
@@ -411,7 +410,6 @@ class BackgroundSyncManagerTest : public testing::Test {
}
TestBrowserThreadBundle browser_thread_bundle_;
- std::unique_ptr<net::NetworkChangeNotifier> network_change_notifier_;
std::unique_ptr<EmbeddedWorkerTestHelper> helper_;
std::unique_ptr<BackgroundSyncManager> background_sync_manager_;
std::unique_ptr<StoragePartitionImpl> storage_partition_impl_;
@@ -853,7 +851,7 @@ TEST_F(BackgroundSyncManagerTest, OverwritePendingRegistration) {
InitFailedSyncEventTest();
// Prevent the first sync from running so that it stays in a pending state.
- SetNetwork(net::NetworkChangeNotifier::CONNECTION_NONE);
+ SetNetwork(network::mojom::ConnectionType::CONNECTION_NONE);
EXPECT_TRUE(Register(sync_options_1_));
EXPECT_TRUE(GetRegistration(sync_options_1_));
@@ -862,7 +860,7 @@ TEST_F(BackgroundSyncManagerTest, OverwritePendingRegistration) {
EXPECT_TRUE(GetRegistration(sync_options_1_));
// Verify that it only gets to run once.
- SetNetwork(net::NetworkChangeNotifier::CONNECTION_WIFI);
+ SetNetwork(network::mojom::ConnectionType::CONNECTION_WIFI);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(1, sync_events_called_);
EXPECT_FALSE(GetRegistration(sync_options_1_));
@@ -870,7 +868,7 @@ TEST_F(BackgroundSyncManagerTest, OverwritePendingRegistration) {
TEST_F(BackgroundSyncManagerTest, DisableWhilePending) {
InitDelayedSyncEventTest();
- SetNetwork(net::NetworkChangeNotifier::CONNECTION_NONE);
+ SetNetwork(network::mojom::ConnectionType::CONNECTION_NONE);
EXPECT_TRUE(Register(sync_options_1_));
// Corrupting the backend should result in the manager disabling itself on the
@@ -879,7 +877,7 @@ TEST_F(BackgroundSyncManagerTest, DisableWhilePending) {
EXPECT_FALSE(Register(sync_options_2_));
test_background_sync_manager_->set_corrupt_backend(false);
- SetNetwork(net::NetworkChangeNotifier::CONNECTION_WIFI);
+ SetNetwork(network::mojom::ConnectionType::CONNECTION_WIFI);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(0, sync_events_called_);
}
@@ -906,12 +904,12 @@ TEST_F(BackgroundSyncManagerTest, DisableWhileFiring) {
TEST_F(BackgroundSyncManagerTest, FiresOnNetworkChange) {
InitSyncEventTest();
- SetNetwork(net::NetworkChangeNotifier::CONNECTION_NONE);
+ SetNetwork(network::mojom::ConnectionType::CONNECTION_NONE);
EXPECT_TRUE(Register(sync_options_1_));
EXPECT_EQ(0, sync_events_called_);
EXPECT_TRUE(GetRegistration(sync_options_1_));
- SetNetwork(net::NetworkChangeNotifier::CONNECTION_WIFI);
+ SetNetwork(network::mojom::ConnectionType::CONNECTION_WIFI);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(1, sync_events_called_);
EXPECT_FALSE(GetRegistration(sync_options_1_));
@@ -920,14 +918,14 @@ TEST_F(BackgroundSyncManagerTest, FiresOnNetworkChange) {
TEST_F(BackgroundSyncManagerTest, MultipleRegistrationsFireOnNetworkChange) {
InitSyncEventTest();
- SetNetwork(net::NetworkChangeNotifier::CONNECTION_NONE);
+ SetNetwork(network::mojom::ConnectionType::CONNECTION_NONE);
EXPECT_TRUE(Register(sync_options_1_));
EXPECT_TRUE(Register(sync_options_2_));
EXPECT_EQ(0, sync_events_called_);
EXPECT_TRUE(GetRegistration(sync_options_1_));
EXPECT_TRUE(GetRegistration(sync_options_2_));
- SetNetwork(net::NetworkChangeNotifier::CONNECTION_WIFI);
+ SetNetwork(network::mojom::ConnectionType::CONNECTION_WIFI);
EXPECT_EQ(2, sync_events_called_);
EXPECT_FALSE(GetRegistration(sync_options_1_));
@@ -938,7 +936,7 @@ TEST_F(BackgroundSyncManagerTest, FiresOnManagerRestart) {
InitSyncEventTest();
// Initially the event won't run because there is no network.
- SetNetwork(net::NetworkChangeNotifier::CONNECTION_NONE);
+ SetNetwork(network::mojom::ConnectionType::CONNECTION_NONE);
EXPECT_TRUE(Register(sync_options_1_));
EXPECT_EQ(0, sync_events_called_);
EXPECT_TRUE(GetRegistration(sync_options_1_));
@@ -947,7 +945,7 @@ TEST_F(BackgroundSyncManagerTest, FiresOnManagerRestart) {
DeleteBackgroundSyncManager();
// The next time the manager is started, the network is good.
- SetNetwork(net::NetworkChangeNotifier::CONNECTION_WIFI);
+ SetNetwork(network::mojom::ConnectionType::CONNECTION_WIFI);
SetupBackgroundSyncManager();
InitSyncEventTest();
@@ -1138,7 +1136,7 @@ TEST_F(BackgroundSyncManagerTest, WakeBrowserCalled) {
EXPECT_LT(0, GetController()->run_in_background_count());
EXPECT_FALSE(GetController()->run_in_background_enabled());
- SetNetwork(net::NetworkChangeNotifier::CONNECTION_NONE);
+ SetNetwork(network::mojom::ConnectionType::CONNECTION_NONE);
EXPECT_FALSE(GetController()->run_in_background_enabled());
// Register a one-shot but it can't fire due to lack of network, wake up is
@@ -1148,7 +1146,7 @@ TEST_F(BackgroundSyncManagerTest, WakeBrowserCalled) {
// Start the event but it will pause mid-sync due to
// InitDelayedSyncEventTest() above.
- SetNetwork(net::NetworkChangeNotifier::CONNECTION_WIFI);
+ SetNetwork(network::mojom::ConnectionType::CONNECTION_WIFI);
EXPECT_TRUE(GetController()->run_in_background_enabled());
EXPECT_EQ(test_background_sync_manager_->background_sync_parameters()
->min_sync_recovery_time,
@@ -1435,7 +1433,7 @@ TEST_F(BackgroundSyncManagerTest, EmulateDispatchSyncEvent) {
background_sync_manager_->EmulateServiceWorkerOffline(sw_registration_id_1_,
false);
- SetNetwork(net::NetworkChangeNotifier::CONNECTION_NONE);
+ SetNetwork(network::mojom::ConnectionType::CONNECTION_NONE);
was_called = false;
code = blink::ServiceWorkerStatusCode::kOk;
background_sync_manager_->EmulateDispatchSyncEvent(
@@ -1445,7 +1443,7 @@ TEST_F(BackgroundSyncManagerTest, EmulateDispatchSyncEvent) {
EXPECT_TRUE(was_called);
EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNetwork, code);
- SetNetwork(net::NetworkChangeNotifier::CONNECTION_WIFI);
+ SetNetwork(network::mojom::ConnectionType::CONNECTION_WIFI);
was_called = false;
background_sync_manager_->EmulateDispatchSyncEvent(
"emulated_tag", sw_registration_1_->active_version(), false,
diff --git a/chromium/content/browser/background_sync/background_sync_network_observer.cc b/chromium/content/browser/background_sync/background_sync_network_observer.cc
index 0746401e1d9..496b401f206 100644
--- a/chromium/content/browser/background_sync/background_sync_network_observer.cc
+++ b/chromium/content/browser/background_sync/background_sync_network_observer.cc
@@ -6,33 +6,65 @@
#include "base/location.h"
#include "base/single_thread_task_runner.h"
+#include "base/task/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/network_service_instance.h"
namespace content {
// static
-bool BackgroundSyncNetworkObserver::ignore_network_change_notifier_ = false;
+bool BackgroundSyncNetworkObserver::ignore_network_changes_ = false;
// static
-void BackgroundSyncNetworkObserver::SetIgnoreNetworkChangeNotifierForTests(
+void BackgroundSyncNetworkObserver::SetIgnoreNetworkChangesForTests(
bool ignore) {
- ignore_network_change_notifier_ = ignore;
+ ignore_network_changes_ = ignore;
}
BackgroundSyncNetworkObserver::BackgroundSyncNetworkObserver(
- const base::RepeatingClosure& network_changed_callback)
- : connection_type_(net::NetworkChangeNotifier::GetConnectionType()),
- network_changed_callback_(network_changed_callback) {
+ const base::RepeatingClosure& connection_changed_callback)
+ : network_connection_tracker_(nullptr),
+ connection_type_(network::mojom::ConnectionType::CONNECTION_UNKNOWN),
+ connection_changed_callback_(connection_changed_callback),
+ weak_ptr_factory_(this) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
+ base::PostTaskWithTraitsAndReplyWithResult(
+ FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(&GetNetworkConnectionTracker),
+ base::BindOnce(
+ &BackgroundSyncNetworkObserver::RegisterWithNetworkConnectionTracker,
+ weak_ptr_factory_.GetWeakPtr()));
}
BackgroundSyncNetworkObserver::~BackgroundSyncNetworkObserver() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
+ if (network_connection_tracker_)
+ network_connection_tracker_->RemoveNetworkConnectionObserver(this);
+}
+
+void BackgroundSyncNetworkObserver::RegisterWithNetworkConnectionTracker(
+ network::NetworkConnectionTracker* network_connection_tracker) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(network_connection_tracker);
+ network_connection_tracker_ = network_connection_tracker;
+ network_connection_tracker_->AddNetworkConnectionObserver(this);
+
+ UpdateConnectionType();
+}
+
+void BackgroundSyncNetworkObserver::UpdateConnectionType() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ network::mojom::ConnectionType connection_type;
+ bool synchronous_return = network_connection_tracker_->GetConnectionType(
+ &connection_type,
+ base::BindOnce(&BackgroundSyncNetworkObserver::OnConnectionChanged,
+ weak_ptr_factory_.GetWeakPtr()));
+ if (synchronous_return)
+ OnConnectionChanged(connection_type);
}
bool BackgroundSyncNetworkObserver::NetworkSufficient(
@@ -45,46 +77,47 @@ bool BackgroundSyncNetworkObserver::NetworkSufficient(
case NETWORK_STATE_AVOID_CELLULAR:
// Note that this returns true for CONNECTION_UNKNOWN to avoid never
// firing.
- return connection_type_ != net::NetworkChangeNotifier::CONNECTION_NONE &&
- !net::NetworkChangeNotifier::IsConnectionCellular(
+ return connection_type_ !=
+ network::mojom::ConnectionType::CONNECTION_NONE &&
+ !network::NetworkConnectionTracker::IsConnectionCellular(
connection_type_);
case NETWORK_STATE_ONLINE:
- return connection_type_ != net::NetworkChangeNotifier::CONNECTION_NONE;
+ return connection_type_ !=
+ network::mojom::ConnectionType::CONNECTION_NONE;
}
NOTREACHED();
return false;
}
-void BackgroundSyncNetworkObserver::OnNetworkChanged(
- net::NetworkChangeNotifier::ConnectionType connection_type) {
+void BackgroundSyncNetworkObserver::OnConnectionChanged(
+ network::mojom::ConnectionType connection_type) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- if (ignore_network_change_notifier_)
+ if (ignore_network_changes_)
return;
- NotifyManagerIfNetworkChanged(connection_type);
+ NotifyManagerIfConnectionChanged(connection_type);
}
-void BackgroundSyncNetworkObserver::NotifyManagerIfNetworkChangedForTesting(
- net::NetworkChangeNotifier::ConnectionType connection_type) {
- NotifyManagerIfNetworkChanged(connection_type);
+void BackgroundSyncNetworkObserver::NotifyManagerIfConnectionChangedForTesting(
+ network::mojom::ConnectionType connection_type) {
+ NotifyManagerIfConnectionChanged(connection_type);
}
-void BackgroundSyncNetworkObserver::NotifyManagerIfNetworkChanged(
- net::NetworkChangeNotifier::ConnectionType connection_type) {
+void BackgroundSyncNetworkObserver::NotifyManagerIfConnectionChanged(
+ network::mojom::ConnectionType connection_type) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (connection_type == connection_type_)
return;
connection_type_ = connection_type;
- NotifyNetworkChanged();
+ NotifyConnectionChanged();
}
-void BackgroundSyncNetworkObserver::NotifyNetworkChanged() {
+void BackgroundSyncNetworkObserver::NotifyConnectionChanged() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- network_changed_callback_);
+ connection_changed_callback_);
}
} // namespace content
diff --git a/chromium/content/browser/background_sync/background_sync_network_observer.h b/chromium/content/browser/background_sync/background_sync_network_observer.h
index c52dbe5c527..8e587d01d12 100644
--- a/chromium/content/browser/background_sync/background_sync_network_observer.h
+++ b/chromium/content/browser/background_sync/background_sync_network_observer.h
@@ -7,14 +7,15 @@
#include "base/bind.h"
#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
#include "content/browser/background_sync/background_sync.pb.h"
#include "content/common/content_export.h"
-#include "net/base/network_change_notifier.h"
+#include "services/network/public/cpp/network_connection_tracker.h"
namespace content {
class CONTENT_EXPORT BackgroundSyncNetworkObserver
- : public net::NetworkChangeNotifier::NetworkChangeObserver {
+ : public network::NetworkConnectionTracker::NetworkConnectionObserver {
public:
// Creates a BackgroundSyncNetworkObserver. |network_changed_callback| is
// called when the network connection changes asynchronously via PostMessage.
@@ -23,37 +24,50 @@ class CONTENT_EXPORT BackgroundSyncNetworkObserver
~BackgroundSyncNetworkObserver() override;
- // Enable or disable notifications coming from the NetworkChangeNotifier. (For
- // preventing flakes in tests)
- static void SetIgnoreNetworkChangeNotifierForTests(bool ignore);
+ // Enable or disable notifications coming from the NetworkConnectionTracker.
+ // (For preventing flakes in tests)
+ static void SetIgnoreNetworkChangesForTests(bool ignore);
// Returns true if the state of the network meets the needs of
// |network_state|.
bool NetworkSufficient(SyncNetworkState network_state);
- // NetworkChangeObserver overrides
- void OnNetworkChanged(
- net::NetworkChangeNotifier::ConnectionType connection_type) override;
+ // NetworkConnectionObserver overrides
+ void OnConnectionChanged(
+ network::mojom::ConnectionType connection_type) override;
- // Allow tests to call NotifyManagerIfNetworkChanged.
- void NotifyManagerIfNetworkChangedForTesting(
- net::NetworkChangeNotifier::ConnectionType connection_type);
+ // Allow tests to call NotifyManagerIfConnectionChanged.
+ void NotifyManagerIfConnectionChangedForTesting(
+ network::mojom::ConnectionType connection_type);
private:
- // Calls NotifyNetworkChanged if the connection type has changed.
- void NotifyManagerIfNetworkChanged(
- net::NetworkChangeNotifier::ConnectionType connection_type);
+ // Finishes setup once we get the NetworkConnectionTracker from the UI thread.
+ virtual void RegisterWithNetworkConnectionTracker(
+ network::NetworkConnectionTracker* network_connection_tracker);
- void NotifyNetworkChanged();
+ // Update the current connection type from the NetworkConnectionTracker.
+ void UpdateConnectionType();
- net::NetworkChangeNotifier::ConnectionType connection_type_;
+ // Calls NotifyConnectionChanged if the connection type has changed.
+ void NotifyManagerIfConnectionChanged(
+ network::mojom::ConnectionType connection_type);
- // The callback to run when the network changes.
- base::RepeatingClosure network_changed_callback_;
+ void NotifyConnectionChanged();
- // Set true to ignore notifications coming from the NetworkChangeNotifier
+ // NetworkConnectionTracker is a global singleton which will outlive this
+ // object.
+ network::NetworkConnectionTracker* network_connection_tracker_;
+
+ network::mojom::ConnectionType connection_type_;
+
+ // The callback to run when the connection changes.
+ base::RepeatingClosure connection_changed_callback_;
+
+ // Set true to ignore notifications coming from the NetworkConnectionTracker
// (to prevent flakes in tests).
- static bool ignore_network_change_notifier_;
+ static bool ignore_network_changes_;
+
+ base::WeakPtrFactory<BackgroundSyncNetworkObserver> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(BackgroundSyncNetworkObserver);
};
diff --git a/chromium/content/browser/background_sync/background_sync_network_observer_unittest.cc b/chromium/content/browser/background_sync/background_sync_network_observer_unittest.cc
index ed81a611987..9ab8e094051 100644
--- a/chromium/content/browser/background_sync/background_sync_network_observer_unittest.cc
+++ b/chromium/content/browser/background_sync/background_sync_network_observer_unittest.cc
@@ -6,103 +6,121 @@
#include "base/run_loop.h"
#include "content/public/test/test_browser_thread_bundle.h"
-#include "net/base/network_change_notifier.h"
+#include "services/network/test/test_network_connection_tracker.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
class BackgroundSyncNetworkObserverTest : public testing::Test {
- protected:
- BackgroundSyncNetworkObserverTest()
- : network_change_notifier(net::NetworkChangeNotifier::CreateMock()),
- network_observer_(new BackgroundSyncNetworkObserver(base::BindRepeating(
- &BackgroundSyncNetworkObserverTest::OnNetworkChanged,
- base::Unretained(this)))),
- network_changed_count_(0) {}
-
- void SetNetwork(net::NetworkChangeNotifier::ConnectionType connection_type) {
- net::NetworkChangeNotifier::NotifyObserversOfNetworkChangeForTests(
+ public:
+ BackgroundSyncNetworkObserverTest() : network_changed_count_(0) {
+ network_observer_ =
+ std::make_unique<BackgroundSyncNetworkObserver>(base::BindRepeating(
+ &BackgroundSyncNetworkObserverTest::OnConnectionChanged,
+ base::Unretained(this)));
+ }
+
+ void SetNetwork(network::mojom::ConnectionType connection_type) {
+ network::TestNetworkConnectionTracker::GetInstance()->SetConnectionType(
connection_type);
base::RunLoop().RunUntilIdle();
}
- void OnNetworkChanged() { network_changed_count_++; }
+ void OnConnectionChanged() { network_changed_count_++; }
+ protected:
TestBrowserThreadBundle browser_thread_bundle_;
- std::unique_ptr<net::NetworkChangeNotifier> network_change_notifier;
std::unique_ptr<BackgroundSyncNetworkObserver> network_observer_;
int network_changed_count_;
};
TEST_F(BackgroundSyncNetworkObserverTest, NetworkChangeInvokesCallback) {
- SetNetwork(net::NetworkChangeNotifier::CONNECTION_NONE);
+ SetNetwork(network::mojom::ConnectionType::CONNECTION_NONE);
network_changed_count_ = 0;
- SetNetwork(net::NetworkChangeNotifier::CONNECTION_WIFI);
+ SetNetwork(network::mojom::ConnectionType::CONNECTION_WIFI);
EXPECT_EQ(1, network_changed_count_);
- SetNetwork(net::NetworkChangeNotifier::CONNECTION_3G);
+ SetNetwork(network::mojom::ConnectionType::CONNECTION_3G);
EXPECT_EQ(2, network_changed_count_);
- SetNetwork(net::NetworkChangeNotifier::CONNECTION_UNKNOWN);
+ SetNetwork(network::mojom::ConnectionType::CONNECTION_UNKNOWN);
EXPECT_EQ(3, network_changed_count_);
- SetNetwork(net::NetworkChangeNotifier::CONNECTION_NONE);
+ SetNetwork(network::mojom::ConnectionType::CONNECTION_NONE);
EXPECT_EQ(4, network_changed_count_);
- SetNetwork(net::NetworkChangeNotifier::CONNECTION_NONE);
+ SetNetwork(network::mojom::ConnectionType::CONNECTION_NONE);
EXPECT_EQ(4, network_changed_count_);
}
TEST_F(BackgroundSyncNetworkObserverTest, NetworkSufficientAnyNetwork) {
- SetNetwork(net::NetworkChangeNotifier::CONNECTION_WIFI);
+ SetNetwork(network::mojom::ConnectionType::CONNECTION_WIFI);
EXPECT_TRUE(network_observer_->NetworkSufficient(NETWORK_STATE_ANY));
- SetNetwork(net::NetworkChangeNotifier::CONNECTION_3G);
+ SetNetwork(network::mojom::ConnectionType::CONNECTION_3G);
EXPECT_TRUE(network_observer_->NetworkSufficient(NETWORK_STATE_ANY));
- SetNetwork(net::NetworkChangeNotifier::CONNECTION_UNKNOWN);
+ SetNetwork(network::mojom::ConnectionType::CONNECTION_UNKNOWN);
EXPECT_TRUE(network_observer_->NetworkSufficient(NETWORK_STATE_ANY));
- SetNetwork(net::NetworkChangeNotifier::CONNECTION_NONE);
+ SetNetwork(network::mojom::ConnectionType::CONNECTION_NONE);
EXPECT_TRUE(network_observer_->NetworkSufficient(NETWORK_STATE_ANY));
}
TEST_F(BackgroundSyncNetworkObserverTest, NetworkSufficientAvoidCellular) {
- SetNetwork(net::NetworkChangeNotifier::CONNECTION_WIFI);
+ SetNetwork(network::mojom::ConnectionType::CONNECTION_WIFI);
EXPECT_TRUE(
network_observer_->NetworkSufficient(NETWORK_STATE_AVOID_CELLULAR));
- SetNetwork(net::NetworkChangeNotifier::CONNECTION_UNKNOWN);
+ SetNetwork(network::mojom::ConnectionType::CONNECTION_UNKNOWN);
EXPECT_TRUE(
network_observer_->NetworkSufficient(NETWORK_STATE_AVOID_CELLULAR));
- SetNetwork(net::NetworkChangeNotifier::CONNECTION_2G);
+ SetNetwork(network::mojom::ConnectionType::CONNECTION_2G);
EXPECT_FALSE(
network_observer_->NetworkSufficient(NETWORK_STATE_AVOID_CELLULAR));
- SetNetwork(net::NetworkChangeNotifier::CONNECTION_3G);
+ SetNetwork(network::mojom::ConnectionType::CONNECTION_3G);
EXPECT_FALSE(
network_observer_->NetworkSufficient(NETWORK_STATE_AVOID_CELLULAR));
- SetNetwork(net::NetworkChangeNotifier::CONNECTION_4G);
+ SetNetwork(network::mojom::ConnectionType::CONNECTION_4G);
EXPECT_FALSE(
network_observer_->NetworkSufficient(NETWORK_STATE_AVOID_CELLULAR));
- SetNetwork(net::NetworkChangeNotifier::CONNECTION_NONE);
+ SetNetwork(network::mojom::ConnectionType::CONNECTION_NONE);
EXPECT_FALSE(
network_observer_->NetworkSufficient(NETWORK_STATE_AVOID_CELLULAR));
}
TEST_F(BackgroundSyncNetworkObserverTest, ConditionsMetOnline) {
- SetNetwork(net::NetworkChangeNotifier::CONNECTION_WIFI);
+ SetNetwork(network::mojom::ConnectionType::CONNECTION_WIFI);
EXPECT_TRUE(network_observer_->NetworkSufficient(NETWORK_STATE_ONLINE));
- SetNetwork(net::NetworkChangeNotifier::CONNECTION_3G);
+ SetNetwork(network::mojom::ConnectionType::CONNECTION_3G);
EXPECT_TRUE(network_observer_->NetworkSufficient(NETWORK_STATE_ONLINE));
- SetNetwork(net::NetworkChangeNotifier::CONNECTION_UNKNOWN);
+ SetNetwork(network::mojom::ConnectionType::CONNECTION_UNKNOWN);
EXPECT_TRUE(network_observer_->NetworkSufficient(NETWORK_STATE_ONLINE));
- SetNetwork(net::NetworkChangeNotifier::CONNECTION_NONE);
+ SetNetwork(network::mojom::ConnectionType::CONNECTION_NONE);
EXPECT_FALSE(network_observer_->NetworkSufficient(NETWORK_STATE_ONLINE));
}
+TEST_F(BackgroundSyncNetworkObserverTest, GetNetworkOnConstruction) {
+ // We need to emulate being disconnected before creating the network observer.
+ network_observer_.reset();
+ SetNetwork(network::mojom::ConnectionType::CONNECTION_NONE);
+
+ auto observer =
+ std::make_unique<BackgroundSyncNetworkObserver>(base::BindRepeating(
+ &BackgroundSyncNetworkObserverTest::OnConnectionChanged,
+ base::Unretained(this)));
+
+ base::RunLoop().RunUntilIdle();
+
+ // The network observer should have learned that the current network is not
+ // the default (UNKNOWN) but is in fact NONE.
+ EXPECT_EQ(1, network_changed_count_);
+ EXPECT_FALSE(observer->NetworkSufficient(NETWORK_STATE_ONLINE));
+}
+
} // 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 4f6d1aa3caf..a1dd3ef2121 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
@@ -25,7 +25,6 @@
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/test/test_background_sync_context.h"
#include "mojo/public/cpp/bindings/interface_ptr.h"
-#include "net/base/network_change_notifier.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
@@ -90,14 +89,13 @@ class BackgroundSyncServiceImplTest : public testing::Test {
public:
BackgroundSyncServiceImplTest()
: thread_bundle_(
- new TestBrowserThreadBundle(TestBrowserThreadBundle::IO_MAINLOOP)),
- network_change_notifier_(net::NetworkChangeNotifier::CreateMock()) {
+ new TestBrowserThreadBundle(TestBrowserThreadBundle::IO_MAINLOOP)) {
default_sync_registration_ = blink::mojom::SyncRegistration::New();
}
void SetUp() override {
// Don't let the tests be confused by the real-world device connectivity
- background_sync_test_util::SetIgnoreNetworkChangeNotifier(true);
+ background_sync_test_util::SetIgnoreNetworkChanges(true);
CreateTestHelper();
CreateStoragePartition();
@@ -115,7 +113,7 @@ class BackgroundSyncServiceImplTest : public testing::Test {
background_sync_context_ = nullptr;
// Restore the network observer functionality for subsequent tests
- background_sync_test_util::SetIgnoreNetworkChangeNotifier(false);
+ background_sync_test_util::SetIgnoreNetworkChanges(false);
}
// SetUp helper methods
@@ -158,8 +156,8 @@ class BackgroundSyncServiceImplTest : public testing::Test {
BackgroundSyncNetworkObserver* network_observer =
background_sync_context_->background_sync_manager()
->GetNetworkObserverForTesting();
- network_observer->NotifyManagerIfNetworkChangedForTesting(
- net::NetworkChangeNotifier::CONNECTION_NONE);
+ network_observer->NotifyManagerIfConnectionChangedForTesting(
+ network::mojom::ConnectionType::CONNECTION_NONE);
base::RunLoop().RunUntilIdle();
}
@@ -211,7 +209,6 @@ class BackgroundSyncServiceImplTest : public testing::Test {
}
std::unique_ptr<TestBrowserThreadBundle> thread_bundle_;
- std::unique_ptr<net::NetworkChangeNotifier> network_change_notifier_;
std::unique_ptr<EmbeddedWorkerTestHelper> embedded_worker_helper_;
std::unique_ptr<StoragePartitionImpl> storage_partition_impl_;
scoped_refptr<BackgroundSyncContext> background_sync_context_;
diff --git a/chromium/content/browser/bad_message.cc b/chromium/content/browser/bad_message.cc
index ab82b3354a8..e0a02d18085 100644
--- a/chromium/content/browser/bad_message.cc
+++ b/chromium/content/browser/bad_message.cc
@@ -9,7 +9,9 @@
#include "base/logging.h"
#include "base/metrics/histogram_functions.h"
#include "base/strings/string_number_conversions.h"
+#include "base/task/post_task.h"
#include "content/public/browser/browser_message_filter.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
@@ -54,9 +56,9 @@ void ReceivedBadMessage(int render_process_id, BadMessageReason reason) {
base::debug::DumpWithoutCrashing();
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(&ReceivedBadMessageOnUIThread,
- render_process_id, reason));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(&ReceivedBadMessageOnUIThread,
+ render_process_id, reason));
return;
}
ReceivedBadMessageOnUIThread(render_process_id, reason);
diff --git a/chromium/content/browser/blob_storage/blob_registry_wrapper.cc b/chromium/content/browser/blob_storage/blob_registry_wrapper.cc
index 9188ea19669..de1add337d0 100644
--- a/chromium/content/browser/blob_storage/blob_registry_wrapper.cc
+++ b/chromium/content/browser/blob_storage/blob_registry_wrapper.cc
@@ -4,8 +4,10 @@
#include "content/browser/blob_storage/blob_registry_wrapper.h"
+#include "base/task/post_task.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
#include "content/browser/child_process_security_policy_impl.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/common/content_features.h"
#include "storage/browser/blob/blob_registry_impl.h"
#include "storage/browser/blob/blob_storage_context.h"
@@ -47,8 +49,8 @@ scoped_refptr<BlobRegistryWrapper> BlobRegistryWrapper::Create(
scoped_refptr<ChromeBlobStorageContext> blob_storage_context,
scoped_refptr<storage::FileSystemContext> file_system_context) {
scoped_refptr<BlobRegistryWrapper> result(new BlobRegistryWrapper());
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&BlobRegistryWrapper::InitializeOnIOThread, result,
std::move(blob_storage_context),
std::move(file_system_context)));
diff --git a/chromium/content/browser/blob_storage/blob_storage_browsertest.cc b/chromium/content/browser/blob_storage/blob_storage_browsertest.cc
index 6b248d9d661..9a5d9f99605 100644
--- a/chromium/content/browser/blob_storage/blob_storage_browsertest.cc
+++ b/chromium/content/browser/blob_storage/blob_storage_browsertest.cc
@@ -3,9 +3,11 @@
// found in the LICENSE file.
#include "base/run_loop.h"
+#include "base/task/post_task.h"
#include "base/test/bind_test_util.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/browser_test_utils.h"
@@ -57,9 +59,10 @@ class BlobStorageBrowserTest : public ContentBrowserTest {
}
void SetBlobLimits() {
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::BindOnce(&SetBlobLimitsOnIO, GetBlobContext(),
- base::ConstRef(limits_)));
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(&SetBlobLimitsOnIO, GetBlobContext(),
+ base::ConstRef(limits_)));
}
void SimpleTest(const GURL& test_url, bool incognito = false) {
@@ -95,8 +98,8 @@ IN_PROC_BROWSER_TEST_F(BlobStorageBrowserTest, BlobCombinations) {
auto blob_context = GetBlobContext();
base::RunLoop loop;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE, base::BindLambdaForTesting([&]() {
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO}, base::BindLambdaForTesting([&]() {
const storage::BlobMemoryController& memory_controller =
blob_context->context()->memory_controller();
// Our exact usages depend on IPC message ordering & garbage collection.
diff --git a/chromium/content/browser/blob_storage/blob_url_browsertest.cc b/chromium/content/browser/blob_storage/blob_url_browsertest.cc
index dfb724f3c95..3932fcaa062 100644
--- a/chromium/content/browser/blob_storage/blob_url_browsertest.cc
+++ b/chromium/content/browser/blob_storage/blob_url_browsertest.cc
@@ -74,7 +74,7 @@ IN_PROC_BROWSER_TEST_P(BlobUrlBrowserTest, LinkToUniqueOriginBlob) {
EXPECT_TRUE(ExecuteScriptAndExtractString(
new_contents,
"domAutomationController.send("
- " document.origin + ' ' + document.body.innerText);",
+ " self.origin + ' ' + document.body.innerText);",
&page_content));
EXPECT_EQ("null potato", page_content);
}
@@ -105,7 +105,7 @@ IN_PROC_BROWSER_TEST_P(BlobUrlBrowserTest, LinkToSameOriginBlob) {
EXPECT_TRUE(ExecuteScriptAndExtractString(
new_contents,
"domAutomationController.send("
- " document.origin + ' ' + document.body.innerText);",
+ " self.origin + ' ' + document.body.innerText);",
&page_content));
EXPECT_EQ(origin.Serialize() + " potato", page_content);
}
@@ -143,7 +143,7 @@ IN_PROC_BROWSER_TEST_P(BlobUrlBrowserTest, LinkToSameOriginBlobWithAuthority) {
EXPECT_TRUE(ExecuteScriptAndExtractString(
new_contents,
"domAutomationController.send("
- " document.origin + ' ' + document.body.innerText);",
+ " self.origin + ' ' + document.body.innerText);",
&page_content));
EXPECT_EQ(origin.Serialize() + " ", page_content); // no potato
}
@@ -160,7 +160,7 @@ IN_PROC_BROWSER_TEST_P(BlobUrlBrowserTest, ReplaceStateToAddAuthorityToBlob) {
EXPECT_TRUE(ExecuteScript(
shell(),
"var spoof_fn = function () {\n"
- " host_port = document.origin.split('://')[1];\n"
+ " host_port = self.origin.split('://')[1];\n"
" spoof_url = 'blob:http://spoof.com@' + host_port + '/abcd';\n"
" window.history.replaceState({}, '', spoof_url);\n"
"};\n"
@@ -183,7 +183,7 @@ IN_PROC_BROWSER_TEST_P(BlobUrlBrowserTest, ReplaceStateToAddAuthorityToBlob) {
EXPECT_TRUE(ExecuteScriptAndExtractString(
new_contents,
"domAutomationController.send("
- " document.origin + ' ' + document.body.innerText);",
+ " self.origin + ' ' + document.body.innerText);",
&page_content));
EXPECT_EQ(origin.Serialize() + " potato", page_content);
diff --git a/chromium/content/browser/blob_storage/blob_url_unittest.cc b/chromium/content/browser/blob_storage/blob_url_unittest.cc
index 702da3728bd..283ded19bba 100644
--- a/chromium/content/browser/blob_storage/blob_url_unittest.cc
+++ b/chromium/content/browser/blob_storage/blob_url_unittest.cc
@@ -107,7 +107,8 @@ disk_cache::ScopedEntryPtr CreateDiskCacheEntry(disk_cache::Backend* cache,
return nullptr;
disk_cache::ScopedEntryPtr entry(temp_entry);
- scoped_refptr<net::StringIOBuffer> iobuffer = new net::StringIOBuffer(data);
+ scoped_refptr<net::StringIOBuffer> iobuffer =
+ base::MakeRefCounted<net::StringIOBuffer>(data);
rv = entry->WriteData(kTestDiskCacheStreamIndex, 0, iobuffer.get(),
iobuffer->size(), callback.callback(), false);
EXPECT_EQ(static_cast<int>(data.size()), callback.GetResult(rv));
@@ -121,7 +122,7 @@ disk_cache::ScopedEntryPtr CreateDiskCacheEntryWithSideData(
const std::string& side_data) {
disk_cache::ScopedEntryPtr entry = CreateDiskCacheEntry(cache, key, data);
scoped_refptr<net::StringIOBuffer> iobuffer =
- new net::StringIOBuffer(side_data);
+ base::MakeRefCounted<net::StringIOBuffer>(side_data);
net::TestCompletionCallback callback;
int rv = entry->WriteData(kTestDiskCacheSideStreamIndex, 0, iobuffer.get(),
iobuffer->size(), callback.callback(), false);
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 203e9c7e94a..31bad2ca4cc 100644
--- a/chromium/content/browser/blob_storage/chrome_blob_storage_context.cc
+++ b/chromium/content/browser/blob_storage/chrome_blob_storage_context.cc
@@ -21,6 +21,7 @@
#include "content/browser/resource_context_impl.h"
#include "content/public/browser/blob_handle.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_features.h"
#include "services/network/public/cpp/resource_request_body.h"
@@ -127,8 +128,8 @@ ChromeBlobStorageContext* ChromeBlobStorageContext::GetFor(
}
if (io_thread_valid) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&ChromeBlobStorageContext::InitializeOnIOThread, blob,
std::move(blob_storage_dir),
std::move(file_task_runner)));
@@ -148,7 +149,8 @@ void ChromeBlobStorageContext::InitializeOnIOThread(
// Signal the BlobMemoryController when it's appropriate to calculate its
// storage limits.
BrowserThread::PostAfterStartupTask(
- FROM_HERE, BrowserThread::GetTaskRunnerForThread(BrowserThread::IO),
+ FROM_HERE,
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO}),
base::BindOnce(&storage::BlobMemoryController::CalculateBlobStorageLimits,
context_->mutable_memory_controller()->GetWeakPtr()));
}
@@ -181,8 +183,8 @@ ChromeBlobStorageContext::URLLoaderFactoryForToken(
blink::mojom::BlobURLTokenPtr token) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
network::mojom::URLLoaderFactoryPtr blob_url_loader_factory_ptr;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
[](scoped_refptr<ChromeBlobStorageContext> context,
network::mojom::URLLoaderFactoryRequest request,
@@ -204,8 +206,8 @@ ChromeBlobStorageContext::URLLoaderFactoryForUrl(
const GURL& url) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
network::mojom::URLLoaderFactoryPtr blob_url_loader_factory_ptr;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
[](scoped_refptr<ChromeBlobStorageContext> context,
network::mojom::URLLoaderFactoryRequest request, const GURL& url) {
@@ -226,8 +228,8 @@ blink::mojom::BlobPtr ChromeBlobStorageContext::GetBlobPtr(
const std::string& uuid) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
blink::mojom::BlobPtr blob_ptr;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
[](scoped_refptr<ChromeBlobStorageContext> context,
blink::mojom::BlobRequest request, const std::string& uuid) {
diff --git a/chromium/content/browser/bluetooth/bluetooth_allowed_devices_map.cc b/chromium/content/browser/bluetooth/bluetooth_allowed_devices_map.cc
index 4b4ce9a95a9..1c275f34260 100644
--- a/chromium/content/browser/bluetooth/bluetooth_allowed_devices_map.cc
+++ b/chromium/content/browser/bluetooth/bluetooth_allowed_devices_map.cc
@@ -19,7 +19,7 @@ BluetoothAllowedDevicesMap::GetOrCreateAllowedDevices(
const url::Origin& origin) {
// "Unique" Origins generate the same key in maps, therefore are not
// supported.
- CHECK(!origin.unique());
+ CHECK(!origin.opaque());
auto iter = origin_to_allowed_devices_map_.find(origin);
if (iter == origin_to_allowed_devices_map_.end()) {
iter = origin_to_allowed_devices_map_.insert(
diff --git a/chromium/content/browser/bluetooth/bluetooth_device_chooser_controller.cc b/chromium/content/browser/bluetooth/bluetooth_device_chooser_controller.cc
index bea76778640..b561ce31363 100644
--- a/chromium/content/browser/bluetooth/bluetooth_device_chooser_controller.cc
+++ b/chromium/content/browser/bluetooth/bluetooth_device_chooser_controller.cc
@@ -344,9 +344,9 @@ void BluetoothDeviceChooserController::GetDevice(
REQUEST_DEVICE_FROM_CROSS_ORIGIN_IFRAME);
return;
}
- // The above also excludes unique origins, which are not even same-origin with
+ // The above also excludes opaque origins, which are not even same-origin with
// themselves.
- DCHECK(!requesting_origin.unique());
+ DCHECK(!requesting_origin.opaque());
if (!adapter_->IsPresent()) {
DVLOG(1) << "Bluetooth Adapter not present. Can't serve requestDevice.";
diff --git a/chromium/content/browser/browser_associated_interface_unittest.cc b/chromium/content/browser/browser_associated_interface_unittest.cc
index 8e3a8041c0c..2ddc8c2091b 100644
--- a/chromium/content/browser/browser_associated_interface_unittest.cc
+++ b/chromium/content/browser/browser_associated_interface_unittest.cc
@@ -12,9 +12,11 @@
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/stringprintf.h"
+#include "base/task/post_task.h"
#include "base/threading/thread.h"
#include "content/public/browser/browser_associated_interface.h"
#include "content/public/browser/browser_message_filter.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/test/test_browser_associated_interfaces.mojom.h"
@@ -164,8 +166,9 @@ class TestClientRunner {
TEST_F(BrowserAssociatedInterfaceTest, Basic) {
TestBrowserThreadBundle browser_threads_;
mojo::MessagePipe pipe;
- ProxyRunner proxy(std::move(pipe.handle0), true,
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO));
+ ProxyRunner proxy(
+ std::move(pipe.handle0), true,
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO}));
AddFilterToChannel(new TestDriverMessageFilter, proxy.channel());
TestClientRunner client(std::move(pipe.handle1));
diff --git a/chromium/content/browser/browser_child_process_host_impl.cc b/chromium/content/browser/browser_child_process_host_impl.cc
index 993ba401697..0d338c22edc 100644
--- a/chromium/content/browser/browser_child_process_host_impl.cc
+++ b/chromium/content/browser/browser_child_process_host_impl.cc
@@ -23,6 +23,7 @@
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/synchronization/waitable_event.h"
+#include "base/task/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "components/tracing/common/trace_startup_config.h"
@@ -37,6 +38,7 @@
#include "content/common/service_manager/child_connection.h"
#include "content/public/browser/browser_child_process_host_delegate.h"
#include "content/public/browser/browser_child_process_observer.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/child_process_data.h"
#include "content/public/browser/content_browser_client.h"
@@ -184,8 +186,8 @@ BrowserChildProcessHostImpl::~BrowserChildProcessHostImpl() {
g_child_process_list.Get().remove(this);
if (notify_child_disconnected_) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&NotifyProcessHostDisconnected, data_.Duplicate()));
}
}
@@ -196,8 +198,7 @@ void BrowserChildProcessHostImpl::TerminateAll() {
// Make a copy since the BrowserChildProcessHost dtor mutates the original
// list.
BrowserChildProcessList copy = g_child_process_list.Get();
- for (BrowserChildProcessList::iterator it = copy.begin();
- it != copy.end(); ++it) {
+ for (auto it = copy.begin(); it != copy.end(); ++it) {
delete (*it)->delegate(); // ~*HostDelegate deletes *HostImpl.
}
}
@@ -383,15 +384,15 @@ void BrowserChildProcessHostImpl::OnChannelConnected(int32_t peer_pid) {
early_exit_watcher_.StopWatching();
#endif
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&NotifyProcessHostConnected, data_.Duplicate()));
delegate_->OnChannelConnected(peer_pid);
if (IsProcessLaunched()) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&NotifyProcessLaunchedAndConnected, data_.Duplicate()));
}
}
@@ -442,16 +443,16 @@ void BrowserChildProcessHostImpl::OnChildDisconnected() {
GetTerminationInfo(true /* known_dead */);
#if defined(OS_ANDROID)
delegate_->OnProcessCrashed(info.exit_code);
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&NotifyProcessKilled, data_.Duplicate(), info));
#else // OS_ANDROID
switch (info.status) {
case base::TERMINATION_STATUS_PROCESS_CRASHED:
case base::TERMINATION_STATUS_ABNORMAL_TERMINATION: {
delegate_->OnProcessCrashed(info.exit_code);
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&NotifyProcessCrashed, data_.Duplicate(), info));
UMA_HISTOGRAM_ENUMERATION("ChildProcess.Crashed2",
static_cast<ProcessType>(data_.process_type),
@@ -463,8 +464,8 @@ void BrowserChildProcessHostImpl::OnChildDisconnected() {
#endif
case base::TERMINATION_STATUS_PROCESS_WAS_KILLED: {
delegate_->OnProcessCrashed(info.exit_code);
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&NotifyProcessKilled, data_.Duplicate(), info));
// Report that this child process was killed.
UMA_HISTOGRAM_ENUMERATION("ChildProcess.Killed2",
@@ -608,8 +609,8 @@ void BrowserChildProcessHostImpl::OnProcessLaunched() {
delegate_->OnProcessLaunched();
if (is_channel_connected_) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&NotifyProcessLaunchedAndConnected, data_.Duplicate()));
}
}
diff --git a/chromium/content/browser/browser_context.cc b/chromium/content/browser/browser_context.cc
index 840cafc185f..9797767f88e 100644
--- a/chromium/content/browser/browser_context.cc
+++ b/chromium/content/browser/browser_context.cc
@@ -14,7 +14,9 @@
#include <vector>
#include "base/base64.h"
+#include "base/bind.h"
#include "base/command_line.h"
+#include "base/feature_list.h"
#include "base/files/file_path.h"
#include "base/guid.h"
#include "base/lazy_instance.h"
@@ -22,6 +24,7 @@
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/rand_util.h"
+#include "base/supports_user_data.h"
#include "base/task/post_task.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -33,12 +36,14 @@
#include "content/browser/download/download_manager_impl.h"
#include "content/browser/indexed_db/indexed_db_context_impl.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
+#include "content/browser/loader/shared_cors_origin_access_list_impl.h"
#include "content/browser/permissions/permission_controller_impl.h"
#include "content/browser/push_messaging/push_messaging_router.h"
#include "content/browser/service_manager/common_browser_interfaces.h"
#include "content/browser/storage_partition_impl_map.h"
#include "content/common/child_process_host_impl.h"
#include "content/public/browser/blob_handle.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/render_process_host.h"
@@ -58,13 +63,13 @@
#include "services/file/file_service.h"
#include "services/file/public/mojom/constants.mojom.h"
#include "services/file/user_id_map.h"
+#include "services/network/public/cpp/features.h"
#include "services/service_manager/public/cpp/connector.h"
#include "services/service_manager/public/mojom/service.mojom.h"
#include "storage/browser/blob/blob_storage_context.h"
#include "storage/browser/database/database_tracker.h"
#include "storage/browser/fileapi/external_mount_points.h"
-
using base::UserDataAdapter;
namespace content {
@@ -102,14 +107,61 @@ class ContentServiceDelegateHolder : public base::SupportsUserData::Data {
DISALLOW_COPY_AND_ASSIGN(ContentServiceDelegateHolder);
};
+// A class used to make an asynchronous Mojo call with cloned patterns for each
+// StoragePartition iteration. |this| instance will be destructed when all
+// existing asynchronous Mojo calls made in SetLists() are done, and |closure|
+// will be invoked on destructing |this|.
+class CorsOriginPatternSetter
+ : public base::RefCounted<CorsOriginPatternSetter> {
+ public:
+ CorsOriginPatternSetter(
+ const url::Origin& source_origin,
+ std::vector<network::mojom::CorsOriginPatternPtr> allow_patterns,
+ std::vector<network::mojom::CorsOriginPatternPtr> block_patterns,
+ base::OnceClosure closure)
+ : source_origin_(source_origin),
+ allow_patterns_(std::move(allow_patterns)),
+ block_patterns_(std::move(block_patterns)),
+ closure_(std::move(closure)) {}
+
+ void SetLists(StoragePartition* partition) {
+ partition->GetNetworkContext()->SetCorsOriginAccessListsForOrigin(
+ source_origin_, ClonePatterns(allow_patterns_),
+ ClonePatterns(block_patterns_),
+ base::BindOnce([](scoped_refptr<CorsOriginPatternSetter> setter) {},
+ base::RetainedRef(this)));
+ }
+
+ private:
+ friend class base::RefCounted<CorsOriginPatternSetter>;
+
+ static std::vector<network::mojom::CorsOriginPatternPtr> ClonePatterns(
+ const std::vector<network::mojom::CorsOriginPatternPtr>& patterns) {
+ std::vector<network::mojom::CorsOriginPatternPtr> cloned_patterns;
+ cloned_patterns.reserve(patterns.size());
+ for (const auto& item : patterns)
+ cloned_patterns.push_back(item.Clone());
+ return cloned_patterns;
+ }
+
+ ~CorsOriginPatternSetter() { std::move(closure_).Run(); }
+
+ const url::Origin source_origin_;
+ const std::vector<network::mojom::CorsOriginPatternPtr> allow_patterns_;
+ const std::vector<network::mojom::CorsOriginPatternPtr> block_patterns_;
+
+ base::OnceClosure closure_;
+};
+
// Key names on BrowserContext.
const char kBrowsingDataRemoverKey[] = "browsing-data-remover";
const char kContentServiceDelegateKey[] = "content-service-delegate";
-const char kPermissionControllerKey[] = "permission-controller";
const char kDownloadManagerKeyName[] = "download_manager";
const char kMojoWasInitialized[] = "mojo-was-initialized";
+const char kPermissionControllerKey[] = "permission-controller";
const char kServiceManagerConnection[] = "service-manager-connection";
const char kServiceUserId[] = "service-user-id";
+const char kSharedCorsOriginAccessListKey[] = "shared-cors-origin-access-list";
const char kStoragePartitionMapKeyName[] = "content_storage_partition_map";
const char kVideoDecodePerfHistoryId[] = "video-decode-perf-history";
@@ -195,7 +247,8 @@ class BrowserContextServiceManagerConnectionHolder
service_manager::mojom::ServiceRequest request)
: service_manager_connection_(ServiceManagerConnection::Create(
std::move(request),
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO))) {}
+ base::CreateSingleThreadTaskRunnerWithTraits(
+ {BrowserThread::IO}))) {}
~BrowserContextServiceManagerConnectionHolder() override {}
ServiceManagerConnection* service_manager_connection() {
@@ -364,8 +417,8 @@ void BrowserContext::CreateMemoryBackedBlob(BrowserContext* browser_context,
ChromeBlobStorageContext* blob_context =
ChromeBlobStorageContext::GetFor(browser_context);
- BrowserThread::PostTaskAndReplyWithResult(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraitsAndReplyWithResult(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&ChromeBlobStorageContext::CreateMemoryBackedBlob,
base::WrapRefCounted(blob_context), data, length,
content_type),
@@ -463,8 +516,8 @@ void BrowserContext::SaveSessionState(BrowserContext* browser_context) {
base::WrapRefCounted(database_tracker)));
if (BrowserThread::IsThreadInitialized(BrowserThread::IO)) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&SaveSessionStateOnIOThread,
base::WrapRefCounted(storage_partition->GetURLRequestContext()),
@@ -626,8 +679,41 @@ ServiceManagerConnection* BrowserContext::GetServiceManagerConnectionFor(
: nullptr;
}
+// static
+const SharedCorsOriginAccessList* BrowserContext::GetSharedCorsOriginAccessList(
+ BrowserContext* browser_context) {
+ return UserDataAdapter<SharedCorsOriginAccessList>::Get(
+ browser_context, kSharedCorsOriginAccessListKey);
+}
+
+// static
+void BrowserContext::SetCorsOriginAccessListsForOrigin(
+ BrowserContext* browser_context,
+ const url::Origin& source_origin,
+ std::vector<network::mojom::CorsOriginPatternPtr> allow_patterns,
+ std::vector<network::mojom::CorsOriginPatternPtr> block_patterns,
+ base::OnceClosure closure) {
+ if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+ UserDataAdapter<SharedCorsOriginAccessList>::Get(
+ browser_context, kSharedCorsOriginAccessListKey)
+ ->SetForOrigin(source_origin, std::move(allow_patterns),
+ std::move(block_patterns), std::move(closure));
+ } else {
+ auto setter = base::MakeRefCounted<CorsOriginPatternSetter>(
+ source_origin, std::move(allow_patterns), std::move(block_patterns),
+ std::move(closure));
+ ForEachStoragePartition(
+ browser_context, base::BindRepeating(&CorsOriginPatternSetter::SetLists,
+ base::RetainedRef(setter.get())));
+ }
+}
+
BrowserContext::BrowserContext()
- : unique_id_(base::UnguessableToken::Create().ToString()) {}
+ : unique_id_(base::UnguessableToken::Create().ToString()) {
+ SetUserData(kSharedCorsOriginAccessListKey,
+ std::make_unique<UserDataAdapter<SharedCorsOriginAccessList>>(
+ new SharedCorsOriginAccessListImpl()));
+}
BrowserContext::~BrowserContext() {
CHECK(GetUserData(kMojoWasInitialized))
@@ -672,10 +758,14 @@ media::VideoDecodePerfHistory* BrowserContext::GetVideoDecodePerfHistory() {
// occurs later upon first VideoDecodePerfHistory API request that requires DB
// access. DB operations will not block the UI thread.
if (!decode_history) {
- auto db_factory = std::make_unique<media::VideoDecodeStatsDBImplFactory>(
- GetPath().Append(FILE_PATH_LITERAL("VideoDecodeStats")));
- decode_history = new media::VideoDecodePerfHistory(std::move(db_factory));
- SetUserData(kVideoDecodePerfHistoryId, base::WrapUnique(decode_history));
+ std::unique_ptr<media::VideoDecodeStatsDBImpl> stats_db =
+ media::VideoDecodeStatsDBImpl::Create(
+ GetPath().Append(FILE_PATH_LITERAL("VideoDecodeStats")));
+ auto new_decode_history =
+ std::make_unique<media::VideoDecodePerfHistory>(std::move(stats_db));
+ decode_history = new_decode_history.get();
+
+ SetUserData(kVideoDecodePerfHistoryId, std::move(new_decode_history));
}
return decode_history;
diff --git a/chromium/content/browser/browser_ipc_logging.cc b/chromium/content/browser/browser_ipc_logging.cc
index ea431e0d338..07958a939f0 100644
--- a/chromium/content/browser/browser_ipc_logging.cc
+++ b/chromium/content/browser/browser_ipc_logging.cc
@@ -5,8 +5,10 @@
#include "content/public/browser/browser_ipc_logging.h"
#include "base/bind.h"
+#include "base/task/post_task.h"
#include "content/common/child_control.mojom.h"
#include "content/public/browser/browser_child_process_host_iterator.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/common/bind_interface_helpers.h"
@@ -38,9 +40,8 @@ void EnableIPCLogging(bool enable) {
// Now tell subprocesses. Messages to ChildProcess-derived
// processes must be done on the IO thread.
- BrowserThread::PostTask(
- BrowserThread::IO,
- FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::Bind(EnableIPCLoggingForChildProcesses, enable));
// Finally, tell the renderers which don't derive from ChildProcess.
diff --git a/chromium/content/browser/browser_main_loop.cc b/chromium/content/browser/browser_main_loop.cc
index 5cea69cfba0..20471ef5cca 100644
--- a/chromium/content/browser/browser_main_loop.cc
+++ b/chromium/content/browser/browser_main_loop.cc
@@ -37,7 +37,8 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/synchronization/waitable_event.h"
-#include "base/system_monitor/system_monitor.h"
+#include "base/system/system_monitor.h"
+#include "base/task/post_task.h"
#include "base/task/task_scheduler/initialization_util.h"
#include "base/threading/thread.h"
#include "base/threading/thread_restrictions.h"
@@ -85,6 +86,8 @@
#include "content/browser/renderer_host/media/media_stream_manager.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/scheduler/responsiveness/watcher.h"
+#include "content/browser/screenlock_monitor/screenlock_monitor.h"
+#include "content/browser/screenlock_monitor/screenlock_monitor_device_source.h"
#include "content/browser/service_manager/service_manager_context.h"
#include "content/browser/speech/speech_recognition_manager_impl.h"
#include "content/browser/startup_data_impl.h"
@@ -99,6 +102,7 @@
#include "content/common/service_manager/service_manager_connection_impl.h"
#include "content/common/task_scheduler.h"
#include "content/public/browser/browser_main_parts.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/gpu_data_manager_observer.h"
@@ -188,7 +192,6 @@
#include "base/memory/memory_pressure_monitor_win.h"
#include "net/base/winsock_init.h"
#include "services/service_manager/sandbox/win/sandbox_win.h"
-#include "ui/base/l10n/l10n_util_win.h"
#include "ui/display/win/screen_win.h"
#endif
@@ -343,46 +346,6 @@ enum WorkerPoolType : size_t {
WORKER_POOL_COUNT // Always last.
};
-std::unique_ptr<base::TaskScheduler::InitParams>
-GetDefaultTaskSchedulerInitParams() {
-#if defined(OS_ANDROID)
- // Mobile config, for iOS see ios/web/app/web_main_loop.cc.
- return std::make_unique<base::TaskScheduler::InitParams>(
- base::SchedulerWorkerPoolParams(
- base::RecommendedMaxNumberOfThreadsInPool(2, 8, 0.1, 0),
- base::TimeDelta::FromSeconds(30)),
- base::SchedulerWorkerPoolParams(
- base::RecommendedMaxNumberOfThreadsInPool(2, 8, 0.1, 0),
- base::TimeDelta::FromSeconds(30)),
- base::SchedulerWorkerPoolParams(
- base::RecommendedMaxNumberOfThreadsInPool(3, 8, 0.3, 0),
- base::TimeDelta::FromSeconds(30)),
- base::SchedulerWorkerPoolParams(
- base::RecommendedMaxNumberOfThreadsInPool(3, 8, 0.3, 0),
- base::TimeDelta::FromSeconds(60)));
-#else
- // Desktop config.
- return std::make_unique<base::TaskScheduler::InitParams>(
- base::SchedulerWorkerPoolParams(
- base::RecommendedMaxNumberOfThreadsInPool(3, 8, 0.1, 0),
- base::TimeDelta::FromSeconds(30)),
- base::SchedulerWorkerPoolParams(
- base::RecommendedMaxNumberOfThreadsInPool(3, 8, 0.1, 0),
- base::TimeDelta::FromSeconds(40)),
- base::SchedulerWorkerPoolParams(
- base::RecommendedMaxNumberOfThreadsInPool(8, 32, 0.3, 0),
- base::TimeDelta::FromSeconds(30)),
- base::SchedulerWorkerPoolParams(
- base::RecommendedMaxNumberOfThreadsInPool(8, 32, 0.3, 0),
- base::TimeDelta::FromSeconds(60))
-#if defined(OS_WIN)
- ,
- base::TaskScheduler::InitParams::SharedWorkerPoolEnvironment::COM_MTA
-#endif // defined(OS_WIN)
- );
-#endif
-}
-
#if !defined(OS_FUCHSIA)
// Time between updating and recording swap rates.
constexpr base::TimeDelta kSwapMetricsInterval =
@@ -437,6 +400,31 @@ void SetFileUrlPathAliasForIpcFuzzer() {
const base::Feature kBrowserResponsivenessCalculator{
"BrowserResponsivenessCalculator", base::FEATURE_DISABLED_BY_DEFAULT};
+std::unique_ptr<base::MemoryPressureMonitor> CreateMemoryPressureMonitor(
+ const base::CommandLine& command_line) {
+ // Behavior of browser tests should not depend on things outside of their
+ // control (like the amount of memory on the system running the tests).
+ if (command_line.HasSwitch(switches::kBrowserTest))
+ return nullptr;
+
+// TODO(chrisha): Simplify this code once MemoryPressureMonitor is made a
+// concrete class.
+#if defined(OS_CHROMEOS)
+ if (chromeos::switches::MemoryPressureHandlingEnabled()) {
+ return std::make_unique<base::chromeos::MemoryPressureMonitor>(
+ chromeos::switches::GetMemoryPressureThresholds());
+ }
+ return nullptr;
+#elif defined(OS_MACOSX)
+ return std::make_unique<base::mac::MemoryPressureMonitor>();
+#elif defined(OS_WIN)
+ return CreateWinMemoryPressureMonitor(command_line);
+#else
+ // No memory monitor on other platforms...
+ return nullptr;
+#endif
+}
+
} // namespace
#if defined(USE_X11)
@@ -493,8 +481,8 @@ class HDRProxy {
static void RequestHDRStatus() {
// The request must be sent to the GPU process from the IO thread.
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::BindOnce(&HDRProxy::RequestOnIOThread));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(&HDRProxy::RequestOnIOThread));
}
private:
@@ -511,8 +499,8 @@ class HDRProxy {
}
}
static void GotResultOnIOThread(bool hdr_enabled) {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(&HDRProxy::GotResult, hdr_enabled));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(&HDRProxy::GotResult, hdr_enabled));
}
static void GotResult(bool hdr_enabled) {
display::win::ScreenWin::SetHDREnabled(hdr_enabled);
@@ -541,12 +529,18 @@ media::AudioManager* BrowserMainLoop::GetAudioManager() {
return g_current_browser_main_loop->audio_manager();
}
-BrowserMainLoop::BrowserMainLoop(const MainFunctionParams& parameters)
+BrowserMainLoop::BrowserMainLoop(
+ const MainFunctionParams& parameters,
+ std::unique_ptr<base::TaskScheduler::ScopedExecutionFence>
+ scoped_execution_fence)
: parameters_(parameters),
parsed_command_line_(parameters.command_line),
result_code_(service_manager::RESULT_CODE_NORMAL_EXIT),
- created_threads_(false) {
+ created_threads_(false),
+ scoped_execution_fence_(std::move(scoped_execution_fence)) {
DCHECK(!g_current_browser_main_loop);
+ DCHECK(scoped_execution_fence_)
+ << "TaskScheduler must be halted before kicking off content.";
g_current_browser_main_loop = this;
if (GetContentClient()->browser()->ShouldCreateTaskScheduler()) {
@@ -617,29 +611,11 @@ int BrowserMainLoop::EarlyInitialization() {
#endif // defined(USE_GLIB)
if (parts_) {
-#if defined(OS_WIN)
- // If we're running tests (ui_task is non-null), then the ResourceBundle
- // has already been initialized.
- if (!parameters_.ui_task) {
- // Override the configured locale with the user's preferred UI language.
- l10n_util::OverrideLocaleWithUILanguageList();
- }
-#endif
const int pre_early_init_error_code = parts_->PreEarlyInitialization();
if (pre_early_init_error_code != service_manager::RESULT_CODE_NORMAL_EXIT)
return pre_early_init_error_code;
}
- if (!parts_ || parts_->ShouldContentCreateFeatureList()) {
- // Note that we do not initialize a new FeatureList when calling this for
- // the second time.
- const base::CommandLine* command_line =
- base::CommandLine::ForCurrentProcess();
- base::FeatureList::InitializeInstance(
- command_line->GetSwitchValueASCII(switches::kEnableFeatures),
- command_line->GetSwitchValueASCII(switches::kDisableFeatures));
- }
-
#if defined(OS_ANDROID) || defined(OS_CHROMEOS)
// Up the priority of the UI thread unless it was already high (since recent
// versions of Android (O+) do this automatically).
@@ -732,6 +708,13 @@ void BrowserMainLoop::PostMainMessageLoopStart() {
network_change_notifier_.reset(net::NetworkChangeNotifier::Create());
}
{
+ TRACE_EVENT0("startup", "BrowserMainLoop::Subsystem:ScreenlockMonitor");
+ std::unique_ptr<ScreenlockMonitorSource> screenlock_monitor_source =
+ std::make_unique<ScreenlockMonitorDeviceSource>();
+ screenlock_monitor_ = std::make_unique<ScreenlockMonitor>(
+ std::move(screenlock_monitor_source));
+ }
+ {
TRACE_EVENT0("startup", "BrowserMainLoop::Subsystem:MediaFeatures");
media::InitializeMediaLibrary();
}
@@ -755,7 +738,7 @@ void BrowserMainLoop::PostMainMessageLoopStart() {
{
base::SetRecordActionTaskRunner(
- BrowserThread::GetTaskRunnerForThread(BrowserThread::UI));
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::UI}));
}
if (!features::IsMultiProcessMash()) {
@@ -960,31 +943,8 @@ void BrowserMainLoop::SynchronouslyFlushStartupTasks() {
int BrowserMainLoop::CreateThreads() {
TRACE_EVENT0("startup,rail", "BrowserMainLoop::CreateThreads");
- {
- auto task_scheduler_init_params =
- GetContentClient()->browser()->GetTaskSchedulerInitParams();
- if (!task_scheduler_init_params)
- task_scheduler_init_params = GetDefaultTaskSchedulerInitParams();
- DCHECK(task_scheduler_init_params);
-
- // If a renderer lives in the browser process, adjust the number of threads
- // in the foreground pool.
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kSingleProcess)) {
- const base::SchedulerWorkerPoolParams&
- current_foreground_worker_pool_params(
- task_scheduler_init_params->foreground_worker_pool_params);
- task_scheduler_init_params->foreground_worker_pool_params =
- base::SchedulerWorkerPoolParams(
- std::max(GetMinThreadsInRendererTaskSchedulerForegroundPool(),
- current_foreground_worker_pool_params.max_tasks()),
- current_foreground_worker_pool_params.suggested_reclaim_time(),
- current_foreground_worker_pool_params.backward_compatibility());
- }
-
- base::TaskScheduler::GetInstance()->Start(
- *task_scheduler_init_params.get());
- }
+ // Release the TaskScheduler's threads.
+ scoped_execution_fence_.reset();
// 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
@@ -1023,9 +983,8 @@ int BrowserMainLoop::PreMainMessageLoopRun() {
}
// If the UI thread blocks, the whole UI is unresponsive.
- // Do not allow disk IO from the UI thread.
- base::ThreadRestrictions::SetIOAllowed(false);
- base::ThreadRestrictions::DisallowWaiting();
+ // Do not allow unresponsive tasks from the UI thread.
+ base::DisallowUnresponsiveTasks();
return result_code_;
}
@@ -1054,8 +1013,8 @@ void BrowserMainLoop::ShutdownThreadsAndCleanUp() {
// Teardown may start in PostMainMessageLoopRun, and during teardown we
// need to be able to perform IO.
base::ThreadRestrictions::SetIOAllowed(true);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
base::IgnoreResult(&base::ThreadRestrictions::SetIOAllowed), true));
@@ -1211,7 +1170,7 @@ void BrowserMainLoop::GetCompositingModeReporter(
// CompositingModeReporter.
return;
#else
- if (features::IsUsingWindowService()) {
+ if (features::IsMultiProcessMash()) {
// Mash == ChromeOS, which doesn't support software compositing, so no need
// to report compositing mode.
return;
@@ -1270,12 +1229,12 @@ int BrowserMainLoop::BrowserThreadsStarted() {
// BrowserGpuChannelHostFactory below, since that depends on an initialized
// ShaderCacheFactory.
InitShaderCacheFactorySingleton(
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO));
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO}));
// Initialize the FontRenderParams on IO thread. This needs to be initialized
// before gpu process initialization below.
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&viz::GpuHostImpl::InitFontRenderParams,
gfx::GetFontRenderParams(gfx::FontRenderParamsQuery(), nullptr)));
@@ -1392,7 +1351,7 @@ int BrowserMainLoop::BrowserThreadsStarted() {
// network service.
resource_dispatcher_host_.reset(new ResourceDispatcherHostImpl(
base::Bind(&DownloadResourceHandler::Create),
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO),
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO}),
!parsed_command_line_.HasSwitch(switches::kDisableResourceScheduler)));
GetContentClient()->browser()->ResourceDispatcherHostCreated();
@@ -1458,8 +1417,8 @@ int BrowserMainLoop::BrowserThreadsStarted() {
!established_gpu_channel && always_uses_gpu && browser_is_viz_host) {
TRACE_EVENT_INSTANT0("gpu", "Post task to launch GPU process",
TRACE_EVENT_SCOPE_THREAD);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(base::IgnoreResult(&GpuProcessHost::Get),
GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
true /* force_create */));
@@ -1498,21 +1457,7 @@ bool BrowserMainLoop::UsingInProcessGpu() const {
}
void BrowserMainLoop::InitializeMemoryManagementComponent() {
- // TODO(chrisha): Abstract away this construction mess to a helper function,
- // once MemoryPressureMonitor is made a concrete class.
-#if defined(OS_CHROMEOS)
- if (chromeos::switches::MemoryPressureHandlingEnabled()) {
- memory_pressure_monitor_ =
- std::make_unique<base::chromeos::MemoryPressureMonitor>(
- chromeos::switches::GetMemoryPressureThresholds());
- }
-#elif defined(OS_MACOSX)
- memory_pressure_monitor_ =
- std::make_unique<base::mac::MemoryPressureMonitor>();
-#elif defined(OS_WIN)
- memory_pressure_monitor_ =
- CreateWinMemoryPressureMonitor(parsed_command_line_);
-#endif
+ memory_pressure_monitor_ = CreateMemoryPressureMonitor(parsed_command_line_);
if (base::FeatureList::IsEnabled(features::kMemoryCoordinator))
MemoryCoordinatorImpl::GetInstance()->Start();
@@ -1575,7 +1520,7 @@ void BrowserMainLoop::MainMessageLoopRun() {
// Android's main message loop is the Java message loop.
NOTREACHED();
#else
- DCHECK(base::MessageLoopForUI::IsCurrent());
+ DCHECK(base::MessageLoopCurrentForUI::IsSet());
if (parameters_.ui_task) {
base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
*parameters_.ui_task);
@@ -1596,7 +1541,7 @@ void BrowserMainLoop::InitializeMojo() {
}
mojo_ipc_support_.reset(new mojo::core::ScopedIPCSupport(
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO),
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO}),
mojo::core::ScopedIPCSupport::ShutdownPolicy::FAST));
service_manager_context_.reset(
@@ -1729,7 +1674,8 @@ void BrowserMainLoop::InitializeAudio() {
if (base::FeatureList::IsEnabled(features::kAudioServiceLaunchOnStartup)) {
// Schedule the audio service startup on the main thread.
BrowserThread::PostAfterStartupTask(
- FROM_HERE, BrowserThread::GetTaskRunnerForThread(BrowserThread::UI),
+ FROM_HERE,
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::UI}),
base::BindOnce([]() {
TRACE_EVENT0("audio", "Starting audio service");
ServiceManagerConnection* connection =
diff --git a/chromium/content/browser/browser_main_loop.h b/chromium/content/browser/browser_main_loop.h
index feebf19dc5f..f9118502d31 100644
--- a/chromium/content/browser/browser_main_loop.h
+++ b/chromium/content/browser/browser_main_loop.h
@@ -11,6 +11,7 @@
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "base/task/task_scheduler/task_scheduler.h"
#include "base/timer/timer.h"
#include "build/build_config.h"
#include "content/browser/browser_process_sub_thread.h"
@@ -95,6 +96,7 @@ class LoaderDelegateImpl;
class MediaStreamManager;
class ResourceDispatcherHostImpl;
class SaveFileManager;
+class ScreenlockMonitor;
class ServiceManagerContext;
class SpeechRecognitionManagerImpl;
class StartupTaskRunner;
@@ -128,7 +130,9 @@ class CONTENT_EXPORT BrowserMainLoop {
// The TaskScheduler instance must exist but not to be started when building
// BrowserMainLoop.
- explicit BrowserMainLoop(const MainFunctionParams& parameters);
+ explicit BrowserMainLoop(
+ const MainFunctionParams& parameters,
+ std::unique_ptr<base::TaskScheduler::ScopedExecutionFence> fence);
virtual ~BrowserMainLoop();
void Init();
@@ -284,6 +288,15 @@ class CONTENT_EXPORT BrowserMainLoop {
const base::CommandLine& parsed_command_line_;
int result_code_;
bool created_threads_; // True if the non-UI threads were created.
+ // //content must be initialized single-threaded until
+ // BrowserMainLoop::CreateThreads() as things initialized before it require an
+ // initialize-once happens-before relationship with all eventual content tasks
+ // running on other threads. This ScopedExecutionFence ensures that no tasks
+ // posted to TaskScheduler gets to run before CreateThreads(); satisfying this
+ // requirement even though the TaskScheduler is created and started before
+ // content is entered.
+ std::unique_ptr<base::TaskScheduler::ScopedExecutionFence>
+ scoped_execution_fence_;
// Members initialized in |MainMessageLoopStart()| ---------------------------
std::unique_ptr<base::MessageLoop> main_message_loop_;
@@ -294,6 +307,7 @@ class CONTENT_EXPORT BrowserMainLoop {
std::unique_ptr<base::PowerMonitor> power_monitor_;
std::unique_ptr<base::HighResolutionTimerManager> hi_res_timer_manager_;
std::unique_ptr<net::NetworkChangeNotifier> network_change_notifier_;
+ std::unique_ptr<ScreenlockMonitor> screenlock_monitor_;
// Per-process listener for online state changes.
std::unique_ptr<BrowserOnlineStateObserver> online_state_observer_;
diff --git a/chromium/content/browser/browser_main_loop_unittest.cc b/chromium/content/browser/browser_main_loop_unittest.cc
index a4bebc6547d..b5d345fc2d0 100644
--- a/chromium/content/browser/browser_main_loop_unittest.cc
+++ b/chromium/content/browser/browser_main_loop_unittest.cc
@@ -10,6 +10,8 @@
#include "base/task/task_scheduler/task_scheduler.h"
#include "base/test/scoped_command_line.h"
#include "content/browser/browser_thread_impl.h"
+#include "content/browser/scheduler/browser_task_executor.h"
+#include "content/browser/startup_helper.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/main_function_params.h"
@@ -21,13 +23,17 @@ namespace content {
// the number of cores in its foreground pool.
TEST(BrowserMainLoopTest, CreateThreadsInSingleProcess) {
{
- base::TaskScheduler::Create("Browser");
base::test::ScopedCommandLine scoped_command_line;
scoped_command_line.GetProcessCommandLine()->AppendSwitch(
switches::kSingleProcess);
+ base::TaskScheduler::Create("Browser");
+ StartBrowserTaskScheduler();
+ BrowserTaskExecutor::Create();
MainFunctionParams main_function_params(
*scoped_command_line.GetProcessCommandLine());
- BrowserMainLoop browser_main_loop(main_function_params);
+ BrowserMainLoop browser_main_loop(
+ main_function_params,
+ std::make_unique<base::TaskScheduler::ScopedExecutionFence>());
browser_main_loop.MainMessageLoopStart();
browser_main_loop.Init();
browser_main_loop.CreateThreads();
@@ -37,6 +43,7 @@ TEST(BrowserMainLoopTest, CreateThreadsInSingleProcess) {
base::SysInfo::NumberOfProcessors() - 1);
browser_main_loop.ShutdownThreadsAndCleanUp();
}
+ BrowserTaskExecutor::ResetForTesting();
for (int id = BrowserThread::UI; id < BrowserThread::ID_COUNT; ++id) {
BrowserThreadImpl::ResetGlobalsForTesting(
static_cast<BrowserThread::ID>(id));
diff --git a/chromium/content/browser/browser_main_runner_impl.cc b/chromium/content/browser/browser_main_runner_impl.cc
index 94dc07ff40b..f779462715e 100644
--- a/chromium/content/browser/browser_main_runner_impl.cc
+++ b/chromium/content/browser/browser_main_runner_impl.cc
@@ -54,7 +54,10 @@ BrowserMainRunnerImpl* BrowserMainRunnerImpl::Create() {
}
BrowserMainRunnerImpl::BrowserMainRunnerImpl()
- : initialization_started_(false), is_shutdown_(false) {}
+ : initialization_started_(false),
+ is_shutdown_(false),
+ scoped_execution_fence_(
+ std::make_unique<base::TaskScheduler::ScopedExecutionFence>()) {}
BrowserMainRunnerImpl::~BrowserMainRunnerImpl() {
if (initialization_started_ && !is_shutdown_)
@@ -107,7 +110,8 @@ int BrowserMainRunnerImpl::Initialize(const MainFunctionParams& parameters) {
gfx::win::MaybeInitializeDirectWrite();
#endif // OS_WIN
- main_loop_.reset(new BrowserMainLoop(parameters));
+ main_loop_.reset(
+ new BrowserMainLoop(parameters, std::move(scoped_execution_fence_)));
main_loop_->Init();
diff --git a/chromium/content/browser/browser_main_runner_impl.h b/chromium/content/browser/browser_main_runner_impl.h
index 08e959ff7aa..7ab5d1c11e9 100644
--- a/chromium/content/browser/browser_main_runner_impl.h
+++ b/chromium/content/browser/browser_main_runner_impl.h
@@ -8,6 +8,7 @@
#include <memory>
#include "base/macros.h"
+#include "base/task/task_scheduler/task_scheduler.h"
#include "build/build_config.h"
#include "content/public/browser/browser_main_runner.h"
@@ -44,6 +45,12 @@ class BrowserMainRunnerImpl : public BrowserMainRunner {
// True if the runner has been shut down.
bool is_shutdown_;
+ // Prevents execution of TaskScheduler tasks from the moment content is
+ // entered. Handed off to |main_loop_| later so it can decide when to release
+ // worker threads again.
+ std::unique_ptr<base::TaskScheduler::ScopedExecutionFence>
+ scoped_execution_fence_;
+
std::unique_ptr<NotificationServiceImpl> notification_service_;
std::unique_ptr<BrowserMainLoop> main_loop_;
#if defined(OS_WIN)
diff --git a/chromium/content/browser/browser_plugin/browser_plugin_guest.cc b/chromium/content/browser/browser_plugin/browser_plugin_guest.cc
index e5f885ab4bc..2c585e36dff 100644
--- a/chromium/content/browser/browser_plugin/browser_plugin_guest.cc
+++ b/chromium/content/browser/browser_plugin/browser_plugin_guest.cc
@@ -40,6 +40,7 @@
#include "content/common/input/ime_text_span_conversions.h"
#include "content/common/text_input_state.h"
#include "content/common/view_messages.h"
+#include "content/common/widget_messages.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_plugin_guest_manager.h"
#include "content/public/browser/content_browser_client.h"
@@ -407,16 +408,6 @@ void BrowserPluginGuest::PointerLockPermissionResponse(bool allow) {
browser_plugin_instance_id(), allow));
}
-void BrowserPluginGuest::FirstSurfaceActivation(
- const viz::SurfaceInfo& surface_info) {
- if (!features::IsUsingWindowService() &&
- !features::IsSurfaceSynchronizationEnabled()) {
- SendMessageToEmbedder(
- std::make_unique<BrowserPluginMsg_FirstSurfaceActivation>(
- browser_plugin_instance_id(), surface_info));
- }
-}
-
void BrowserPluginGuest::ResendEventToEmbedder(
const blink::WebInputEvent& event) {
if (!attached() || !owner_web_contents_)
@@ -667,7 +658,7 @@ void BrowserPluginGuest::RenderViewReady() {
// In case we've created a new guest render process after a crash, let the
// associated BrowserPlugin know. We only need to send this if we're attached,
// as guest_crashed_ is cleared automatically on attach anyways.
- if (attached() && !features::IsUsingWindowService()) {
+ if (attached() && !features::IsMultiProcessMash()) {
RenderWidgetHostViewGuest* rwhv = static_cast<RenderWidgetHostViewGuest*>(
web_contents()->GetRenderWidgetHostView());
if (rwhv) {
@@ -726,12 +717,12 @@ bool BrowserPluginGuest::OnMessageReceived(const IPC::Message& message) {
IPC_BEGIN_MESSAGE_MAP(BrowserPluginGuest, message)
IPC_MESSAGE_HANDLER(ViewHostMsg_HasTouchEventHandlers,
OnHasTouchEventHandlers)
- IPC_MESSAGE_HANDLER(ViewHostMsg_LockMouse, OnLockMouse)
+ IPC_MESSAGE_HANDLER(WidgetHostMsg_LockMouse, OnLockMouse)
IPC_MESSAGE_HANDLER(ViewHostMsg_ShowWidget, OnShowWidget)
IPC_MESSAGE_HANDLER(ViewHostMsg_TakeFocus, OnTakeFocus)
- IPC_MESSAGE_HANDLER(ViewHostMsg_TextInputStateChanged,
+ IPC_MESSAGE_HANDLER(WidgetHostMsg_TextInputStateChanged,
OnTextInputStateChanged)
- IPC_MESSAGE_HANDLER(ViewHostMsg_UnlockMouse, OnUnlockMouse)
+ IPC_MESSAGE_HANDLER(WidgetHostMsg_UnlockMouse, OnUnlockMouse)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
@@ -955,7 +946,7 @@ void BrowserPluginGuest::OnLockMouse(bool user_gesture,
RenderWidgetHost* widget_host =
web_contents()->GetRenderViewHost()->GetWidget();
widget_host->Send(
- new ViewMsg_LockMouse_ACK(widget_host->GetRoutingID(), false));
+ new WidgetMsg_LockMouse_ACK(widget_host->GetRoutingID(), false));
return;
}
@@ -976,7 +967,7 @@ void BrowserPluginGuest::OnLockMouseAck(int browser_plugin_instance_id,
RenderWidgetHost* widget_host =
web_contents()->GetRenderViewHost()->GetWidget();
widget_host->Send(
- new ViewMsg_LockMouse_ACK(widget_host->GetRoutingID(), succeeded));
+ new WidgetMsg_LockMouse_ACK(widget_host->GetRoutingID(), succeeded));
pending_lock_request_ = false;
if (succeeded)
mouse_locked_ = true;
@@ -1030,7 +1021,7 @@ void BrowserPluginGuest::OnUnlockMouseAck(int browser_plugin_instance_id) {
if (mouse_locked_) {
RenderWidgetHost* widget_host =
web_contents()->GetRenderViewHost()->GetWidget();
- widget_host->Send(new ViewMsg_MouseLockLost(widget_host->GetRoutingID()));
+ widget_host->Send(new WidgetMsg_MouseLockLost(widget_host->GetRoutingID()));
}
mouse_locked_ = false;
}
@@ -1116,10 +1107,11 @@ void BrowserPluginGuest::OnShowPopup(
}
#endif
-void BrowserPluginGuest::OnShowWidget(int route_id,
+void BrowserPluginGuest::OnShowWidget(int widget_route_id,
const gfx::Rect& initial_rect) {
int process_id = GetWebContents()->GetMainFrame()->GetProcess()->GetID();
- GetWebContents()->ShowCreatedWidget(process_id, route_id, initial_rect);
+ GetWebContents()->ShowCreatedWidget(process_id, widget_route_id,
+ initial_rect);
}
void BrowserPluginGuest::OnTakeFocus(bool reverse) {
diff --git a/chromium/content/browser/browser_plugin/browser_plugin_guest.h b/chromium/content/browser/browser_plugin/browser_plugin_guest.h
index aab107192d0..c788a84e377 100644
--- a/chromium/content/browser/browser_plugin/browser_plugin_guest.h
+++ b/chromium/content/browser/browser_plugin/browser_plugin_guest.h
@@ -63,7 +63,6 @@ class RenderFrameMetadata;
namespace viz {
class LocalSurfaceId;
-class SurfaceInfo;
} // namespace viz
namespace content {
@@ -243,9 +242,6 @@ class CONTENT_EXPORT BrowserPluginGuest : public GuestHost,
void PointerLockPermissionResponse(bool allow);
- // The next function is virtual for test purposes.
- virtual void FirstSurfaceActivation(const viz::SurfaceInfo& surface_info);
-
void ResendEventToEmbedder(const blink::WebInputEvent& event);
// TODO(ekaramad): Remove this once https://crbug.com/642826 is resolved.
@@ -355,7 +351,7 @@ class CONTENT_EXPORT BrowserPluginGuest : public GuestHost,
void OnShowPopup(RenderFrameHost* render_frame_host,
const FrameHostMsg_ShowPopup_Params& params);
#endif
- void OnShowWidget(int route_id, const gfx::Rect& initial_rect);
+ void OnShowWidget(int widget_route_id, const gfx::Rect& initial_rect);
void OnTakeFocus(bool reverse);
void OnUpdateFrameName(int frame_id,
bool is_top_level,
diff --git a/chromium/content/browser/browser_process_sub_thread.cc b/chromium/content/browser/browser_process_sub_thread.cc
index 9172012c111..074fbfa8098 100644
--- a/chromium/content/browser/browser_process_sub_thread.cc
+++ b/chromium/content/browser/browser_process_sub_thread.cc
@@ -100,8 +100,7 @@ void BrowserProcessSubThread::Init() {
#endif
if (!is_blocking_allowed_for_testing_) {
- base::DisallowBlocking();
- base::DisallowBaseSyncPrimitives();
+ base::DisallowUnresponsiveTasks();
}
}
diff --git a/chromium/content/browser/browser_thread_impl.cc b/chromium/content/browser/browser_thread_impl.cc
index d90d84982a4..43c361db748 100644
--- a/chromium/content/browser/browser_thread_impl.cc
+++ b/chromium/content/browser/browser_thread_impl.cc
@@ -11,73 +11,20 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/compiler_specific.h"
-#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/macros.h"
+#include "base/no_destructor.h"
#include "base/sequence_checker.h"
#include "base/task/task_executor.h"
#include "base/threading/platform_thread.h"
#include "base/time/time.h"
#include "build/build_config.h"
-#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/content_browser_client.h"
namespace content {
namespace {
-// An implementation of SingleThreadTaskRunner to be used in conjunction
-// with BrowserThread.
-// TODO(gab): Consider replacing this with |g_globals->task_runners| -- only
-// works if none are requested before starting the threads.
-class BrowserThreadTaskRunner : public base::SingleThreadTaskRunner {
- public:
- explicit BrowserThreadTaskRunner(BrowserThread::ID identifier)
- : id_(identifier) {}
-
- // SingleThreadTaskRunner implementation.
- bool PostDelayedTask(const base::Location& from_here,
- base::OnceClosure task,
- base::TimeDelta delay) override {
- return BrowserThread::PostDelayedTask(id_, from_here, std::move(task),
- delay);
- }
-
- bool PostNonNestableDelayedTask(const base::Location& from_here,
- base::OnceClosure task,
- base::TimeDelta delay) override {
- return BrowserThread::PostNonNestableDelayedTask(id_, from_here,
- std::move(task), delay);
- }
-
- bool RunsTasksInCurrentSequence() const override {
- return BrowserThread::CurrentlyOn(id_);
- }
-
- protected:
- ~BrowserThreadTaskRunner() override {}
-
- private:
- BrowserThread::ID id_;
- DISALLOW_COPY_AND_ASSIGN(BrowserThreadTaskRunner);
-};
-
-// A separate helper is used just for the task runners, in order to avoid
-// needing to initialize the globals to create a task runner.
-struct BrowserThreadTaskRunners {
- BrowserThreadTaskRunners() {
- for (int i = 0; i < BrowserThread::ID_COUNT; ++i) {
- proxies[i] =
- new BrowserThreadTaskRunner(static_cast<BrowserThread::ID>(i));
- }
- }
-
- scoped_refptr<base::SingleThreadTaskRunner> proxies[BrowserThread::ID_COUNT];
-};
-
-base::LazyInstance<BrowserThreadTaskRunners>::Leaky g_task_runners =
- LAZY_INSTANCE_INITIALIZER;
-
// State of a given BrowserThread::ID in chronological order throughout the
// browser process' lifetime.
enum BrowserThreadState {
@@ -126,105 +73,11 @@ struct BrowserThreadGlobals {
base::subtle::Atomic32 states[BrowserThread::ID_COUNT] = {};
};
-base::LazyInstance<BrowserThreadGlobals>::Leaky
- g_globals = LAZY_INSTANCE_INITIALIZER;
-
-bool PostTaskHelper(BrowserThread::ID identifier,
- const base::Location& from_here,
- base::OnceClosure task,
- base::TimeDelta delay,
- bool nestable) {
- DCHECK_GE(identifier, 0);
- DCHECK_LT(identifier, BrowserThread::ID_COUNT);
-
- BrowserThreadGlobals& globals = g_globals.Get();
-
- // Tasks should always be posted while the BrowserThread is in a RUNNING or
- // SHUTDOWN state (will return false if SHUTDOWN).
- //
- // Posting tasks before BrowserThreads are initialized is incorrect as it
- // would silently no-op. If you need to support posting early, gate it on
- // BrowserThread::IsThreadInitialized(). If you hit this check in unittests,
- // you most likely posted a task outside the scope of a
- // TestBrowserThreadBundle (which also completely resets the state after
- // shutdown in ~TestBrowserThreadBundle(), ref. ResetGlobalsForTesting(),
- // making sure TestBrowserThreadBundle is the first member of your test
- // fixture and thus outlives everything is usually the right solution).
- DCHECK_GE(base::subtle::NoBarrier_Load(&globals.states[identifier]),
- BrowserThreadState::RUNNING);
- DCHECK(globals.task_runners[identifier]);
-
- if (nestable) {
- return globals.task_runners[identifier]->PostDelayedTask(
- from_here, std::move(task), delay);
- } else {
- return globals.task_runners[identifier]->PostNonNestableDelayedTask(
- from_here, std::move(task), delay);
- }
+BrowserThreadGlobals& GetBrowserThreadGlobals() {
+ static base::NoDestructor<BrowserThreadGlobals> globals;
+ return *globals;
}
-class BrowserThreadTaskExecutor : public base::TaskExecutor {
- public:
- BrowserThreadTaskExecutor() {}
- ~BrowserThreadTaskExecutor() override {}
-
- // base::TaskExecutor implementation.
- bool PostDelayedTaskWithTraits(const base::Location& from_here,
- const base::TaskTraits& traits,
- base::OnceClosure task,
- base::TimeDelta delay) override {
- return PostTaskHelper(
- GetBrowserThreadIdentifier(traits), from_here, std::move(task), delay,
- traits.GetExtension<BrowserTaskTraitsExtension>().nestable());
- }
-
- scoped_refptr<base::TaskRunner> CreateTaskRunnerWithTraits(
- const base::TaskTraits& traits) override {
- return GetTaskRunnerForThread(GetBrowserThreadIdentifier(traits));
- }
-
- scoped_refptr<base::SequencedTaskRunner> CreateSequencedTaskRunnerWithTraits(
- const base::TaskTraits& traits) override {
- return GetTaskRunnerForThread(GetBrowserThreadIdentifier(traits));
- }
-
- scoped_refptr<base::SingleThreadTaskRunner>
- CreateSingleThreadTaskRunnerWithTraits(
- const base::TaskTraits& traits,
- base::SingleThreadTaskRunnerThreadMode thread_mode) override {
- // It's not possible to request DEDICATED access to a BrowserThread.
- DCHECK_EQ(thread_mode, base::SingleThreadTaskRunnerThreadMode::SHARED);
- return GetTaskRunnerForThread(GetBrowserThreadIdentifier(traits));
- }
-
-#if defined(OS_WIN)
- scoped_refptr<base::SingleThreadTaskRunner> CreateCOMSTATaskRunnerWithTraits(
- const base::TaskTraits& traits,
- base::SingleThreadTaskRunnerThreadMode thread_mode) override {
- // Only the UI thread supports COM.
- DCHECK_EQ(GetBrowserThreadIdentifier(traits), BrowserThread::UI);
- return CreateSingleThreadTaskRunnerWithTraits(traits, thread_mode);
- }
-#endif // defined(OS_WIN)
-
- private:
- BrowserThread::ID GetBrowserThreadIdentifier(const base::TaskTraits& traits) {
- DCHECK_EQ(traits.extension_id(), BrowserTaskTraitsExtension::kExtensionId);
- BrowserThread::ID id =
- traits.GetExtension<BrowserTaskTraitsExtension>().browser_thread();
- DCHECK_LT(id, BrowserThread::ID_COUNT);
- return id;
- }
-
- scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunnerForThread(
- BrowserThread::ID identifier) {
- return g_task_runners.Get().proxies[identifier];
- }
-};
-
-// |g_browser_thread_task_executor| is intentionally leaked on shutdown.
-BrowserThreadTaskExecutor* g_browser_thread_task_executor = nullptr;
-
} // namespace
BrowserThreadImpl::BrowserThreadImpl(
@@ -235,7 +88,7 @@ BrowserThreadImpl::BrowserThreadImpl(
DCHECK_LT(identifier_, ID_COUNT);
DCHECK(task_runner);
- BrowserThreadGlobals& globals = g_globals.Get();
+ BrowserThreadGlobals& globals = GetBrowserThreadGlobals();
DCHECK_CALLED_ON_VALID_THREAD(globals.main_thread_checker_);
@@ -249,7 +102,7 @@ BrowserThreadImpl::BrowserThreadImpl(
}
BrowserThreadImpl::~BrowserThreadImpl() {
- BrowserThreadGlobals& globals = g_globals.Get();
+ BrowserThreadGlobals& globals = GetBrowserThreadGlobals();
DCHECK_CALLED_ON_VALID_THREAD(globals.main_thread_checker_);
DCHECK_EQ(base::subtle::NoBarrier_Load(&globals.states[identifier_]),
@@ -265,7 +118,7 @@ BrowserThreadImpl::~BrowserThreadImpl() {
// static
void BrowserThreadImpl::ResetGlobalsForTesting(BrowserThread::ID identifier) {
- BrowserThreadGlobals& globals = g_globals.Get();
+ BrowserThreadGlobals& globals = GetBrowserThreadGlobals();
DCHECK_CALLED_ON_VALID_THREAD(globals.main_thread_checker_);
DCHECK_EQ(base::subtle::NoBarrier_Load(&globals.states[identifier]),
@@ -304,7 +157,7 @@ bool BrowserThread::IsThreadInitialized(ID identifier) {
DCHECK_GE(identifier, 0);
DCHECK_LT(identifier, ID_COUNT);
- BrowserThreadGlobals& globals = g_globals.Get();
+ BrowserThreadGlobals& globals = GetBrowserThreadGlobals();
return base::subtle::NoBarrier_Load(&globals.states[identifier]) ==
BrowserThreadState::RUNNING;
}
@@ -314,7 +167,7 @@ bool BrowserThread::CurrentlyOn(ID identifier) {
DCHECK_GE(identifier, 0);
DCHECK_LT(identifier, ID_COUNT);
- BrowserThreadGlobals& globals = g_globals.Get();
+ BrowserThreadGlobals& globals = GetBrowserThreadGlobals();
// Thread-safe since |globals.task_runners| is read-only after being
// initialized from main thread (which happens before //content and embedders
@@ -338,49 +191,9 @@ std::string BrowserThread::GetDCheckCurrentlyOnErrorMessage(ID expected) {
return result;
}
-bool BrowserThread::PostTask(ID identifier,
- const base::Location& from_here,
- base::OnceClosure task) {
- return PostTaskHelper(identifier, from_here, std::move(task),
- base::TimeDelta(), true);
-}
-
-// static
-bool BrowserThread::PostDelayedTask(ID identifier,
- const base::Location& from_here,
- base::OnceClosure task,
- base::TimeDelta delay) {
- return PostTaskHelper(identifier, from_here, std::move(task), delay, true);
-}
-
-// static
-bool BrowserThread::PostNonNestableTask(ID identifier,
- const base::Location& from_here,
- base::OnceClosure task) {
- return PostTaskHelper(identifier, from_here, std::move(task),
- base::TimeDelta(), false);
-}
-
-// static
-bool BrowserThread::PostNonNestableDelayedTask(ID identifier,
- const base::Location& from_here,
- base::OnceClosure task,
- base::TimeDelta delay) {
- return PostTaskHelper(identifier, from_here, std::move(task), delay, false);
-}
-
-// static
-bool BrowserThread::PostTaskAndReply(ID identifier,
- const base::Location& from_here,
- base::OnceClosure task,
- base::OnceClosure reply) {
- return GetTaskRunnerForThread(identifier)
- ->PostTaskAndReply(from_here, std::move(task), std::move(reply));
-}
-
// static
bool BrowserThread::GetCurrentThreadIdentifier(ID* identifier) {
- BrowserThreadGlobals& globals = g_globals.Get();
+ BrowserThreadGlobals& globals = GetBrowserThreadGlobals();
// Thread-safe since |globals.task_runners| is read-only after being
// initialized from main thread (which happens before //content and embedders
@@ -400,24 +213,27 @@ bool BrowserThread::GetCurrentThreadIdentifier(ID* identifier) {
// static
scoped_refptr<base::SingleThreadTaskRunner>
BrowserThread::GetTaskRunnerForThread(ID identifier) {
- return g_task_runners.Get().proxies[identifier];
-}
+ DCHECK_GE(identifier, 0);
+ DCHECK_LT(identifier, ID_COUNT);
-// static
-void BrowserThreadImpl::CreateTaskExecutor() {
- DCHECK(!g_browser_thread_task_executor);
- g_browser_thread_task_executor = new BrowserThreadTaskExecutor();
- base::RegisterTaskExecutor(BrowserTaskTraitsExtension::kExtensionId,
- g_browser_thread_task_executor);
-}
+ BrowserThreadGlobals& globals = GetBrowserThreadGlobals();
-// static
-void BrowserThreadImpl::ResetTaskExecutorForTesting() {
- DCHECK(g_browser_thread_task_executor);
- base::UnregisterTaskExecutorForTesting(
- BrowserTaskTraitsExtension::kExtensionId);
- delete g_browser_thread_task_executor;
- g_browser_thread_task_executor = nullptr;
+ // Tasks should always be posted while the BrowserThread is in a RUNNING or
+ // SHUTDOWN state (will return false if SHUTDOWN).
+ //
+ // Posting tasks before BrowserThreads are initialized is incorrect as it
+ // would silently no-op. If you need to support posting early, gate it on
+ // BrowserThread::IsThreadInitialized(). If you hit this check in unittests,
+ // you most likely posted a task outside the scope of a
+ // TestBrowserThreadBundle (which also completely resets the state after
+ // shutdown in ~TestBrowserThreadBundle(), ref. ResetGlobalsForTesting(),
+ // making sure TestBrowserThreadBundle is the first member of your test
+ // fixture and thus outlives everything is usually the right solution).
+ DCHECK_GE(base::subtle::NoBarrier_Load(&globals.states[identifier]),
+ BrowserThreadState::RUNNING);
+ DCHECK(globals.task_runners[identifier]);
+
+ return globals.task_runners[identifier];
}
} // namespace content
diff --git a/chromium/content/browser/browser_thread_impl.h b/chromium/content/browser/browser_thread_impl.h
index 5789a29e1c5..a09d5832607 100644
--- a/chromium/content/browser/browser_thread_impl.h
+++ b/chromium/content/browser/browser_thread_impl.h
@@ -39,12 +39,9 @@ class CONTENT_EXPORT BrowserThreadImpl : public BrowserThread {
// |identifier|.
static void ResetGlobalsForTesting(BrowserThread::ID identifier);
- // Creates and registers a TaskExecutor that facilitates posting tasks to a
- // BrowserThread via //base/task/post_task.h.
- static void CreateTaskExecutor();
-
- // Unregister and delete the TaskExecutor after a test.
- static void ResetTaskExecutorForTesting();
+ // Exposed for BrowserTaskExecutor. Other code should use
+ // base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::UI/IO}).
+ using BrowserThread::GetTaskRunnerForThread;
private:
// Restrict instantiation to BrowserProcessSubThread as it performs important
diff --git a/chromium/content/browser/browser_thread_unittest.cc b/chromium/content/browser/browser_thread_unittest.cc
index f27b5b97f7f..377f0cbf866 100644
--- a/chromium/content/browser/browser_thread_unittest.cc
+++ b/chromium/content/browser/browser_thread_unittest.cc
@@ -18,6 +18,7 @@
#include "build/build_config.h"
#include "content/browser/browser_process_sub_thread.h"
#include "content/browser/browser_thread_impl.h"
+#include "content/browser/scheduler/browser_task_executor.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/test/test_browser_thread.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -37,7 +38,7 @@ class BrowserThreadTest : public testing::Test {
protected:
void SetUp() override {
- BrowserThreadImpl::CreateTaskExecutor();
+ BrowserTaskExecutor::Create();
ui_thread_ = std::make_unique<BrowserProcessSubThread>(BrowserThread::UI);
ui_thread_->Start();
@@ -57,7 +58,7 @@ class BrowserThreadTest : public testing::Test {
BrowserThreadImpl::ResetGlobalsForTesting(BrowserThread::UI);
BrowserThreadImpl::ResetGlobalsForTesting(BrowserThread::IO);
- BrowserThreadImpl::ResetTaskExecutorForTesting();
+ BrowserTaskExecutor::ResetForTesting();
}
// Prepares this BrowserThreadTest for Release() to be invoked. |on_release|
@@ -110,10 +111,9 @@ class UIThreadDestructionObserver
: callback_task_runner_(base::ThreadTaskRunnerHandle::Get()),
callback_(callback),
ui_task_runner_(
- BrowserThread::GetTaskRunnerForThread(BrowserThread::UI)),
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::UI})),
did_shutdown_(did_shutdown) {
- BrowserThread::GetTaskRunnerForThread(BrowserThread::UI)
- ->PostTask(FROM_HERE, base::BindOnce(&Watch, this));
+ ui_task_runner_->PostTask(FROM_HERE, base::BindOnce(&Watch, this));
}
private:
@@ -140,15 +140,6 @@ class UIThreadDestructionObserver
bool* did_shutdown_;
};
-TEST_F(BrowserThreadTest, PostTask) {
- base::RunLoop run_loop;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&BasicFunction, run_loop.QuitWhenIdleClosure(),
- BrowserThread::IO));
- run_loop.Run();
-}
-
TEST_F(BrowserThreadTest, PostTaskWithTraits) {
base::RunLoop run_loop;
EXPECT_TRUE(base::PostTaskWithTraits(
@@ -174,16 +165,6 @@ TEST_F(BrowserThreadTest, ReleasedOnCorrectThread) {
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, run_loop.QuitWhenIdleClosure(),
- BrowserThread::IO));
- run_loop.Run();
-}
-
TEST_F(BrowserThreadTest, PostTaskViaTaskRunnerWithTraits) {
scoped_refptr<base::TaskRunner> task_runner =
base::CreateTaskRunnerWithTraits({BrowserThread::IO});
@@ -226,16 +207,6 @@ TEST_F(BrowserThreadTest, PostTaskViaCOMSTATaskRunnerWithTraits) {
}
#endif // defined(OS_WIN)
-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);
- run_loop.Run();
-}
-
TEST_F(BrowserThreadTest, ReleaseViaTaskRunnerWithTraits) {
scoped_refptr<base::SingleThreadTaskRunner> task_runner =
base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::UI});
@@ -245,16 +216,6 @@ TEST_F(BrowserThreadTest, ReleaseViaTaskRunnerWithTraits) {
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.
- base::RunLoop run_loop;
- ASSERT_TRUE(BrowserThread::PostTaskAndReply(BrowserThread::IO, FROM_HERE,
- base::DoNothing(),
- run_loop.QuitWhenIdleClosure()));
- run_loop.Run();
-}
-
TEST_F(BrowserThreadTest, PostTaskAndReplyWithTraits) {
// Most of the heavy testing for PostTaskAndReply() is done inside the
// task runner test. This just makes sure we get piped through at all.
diff --git a/chromium/content/browser/browsing_data/OWNERS b/chromium/content/browser/browsing_data/OWNERS
index 4b224ec6732..24085194c54 100644
--- a/chromium/content/browser/browsing_data/OWNERS
+++ b/chromium/content/browser/browsing_data/OWNERS
@@ -1,4 +1,3 @@
-bauerb@chromium.org
dullweber@chromium.org
markusheintz@chromium.org
jsbell@chromium.org
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 e569410d369..b06695ab36a 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
@@ -100,7 +100,7 @@ void BrowsingDataFilterBuilderImpl::AddOrigin(const url::Origin& origin) {
// This means that std::set::find() will use the same semantics for
// origin comparison as Origin::IsSameOriginWith(). Furthermore, this
// means that two filters are equal iff they are equal element-wise.
- DCHECK(!origin.unique()) << "Invalid origin passed into OriginFilter.";
+ DCHECK(!origin.opaque()) << "Invalid origin passed into OriginFilter.";
// TODO(msramek): All urls with file scheme currently map to the same
// origin. This is currently not a problem, but if it becomes one,
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 5d0afd56593..cf3cedd6053 100644
--- a/chromium/content/browser/browsing_data/browsing_data_remover_impl.cc
+++ b/chromium/content/browser/browsing_data/browsing_data_remover_impl.cc
@@ -17,8 +17,10 @@
#include "base/metrics/histogram_macros.h"
#include "base/metrics/user_metrics.h"
#include "base/stl_util.h"
+#include "base/task/post_task.h"
#include "content/browser/browsing_data/storage_partition_http_cache_data_remover.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/browsing_data_filter_builder.h"
#include "content/public/browser/browsing_data_remover_delegate.h"
@@ -580,8 +582,8 @@ void BrowsingDataRemoverImpl::Notify() {
// Yield to the UI thread before executing the next removal task.
// TODO(msramek): Consider also adding a backoff if too many tasks
// are scheduled.
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&BrowsingDataRemoverImpl::RunNextTask, GetWeakPtr()));
}
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 a82100fd443..973d3d451b4 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
@@ -24,10 +24,12 @@
#include "base/single_thread_task_runner.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/cancelable_task_tracker.h"
+#include "base/task/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "content/browser/browsing_data/browsing_data_remover_impl.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browsing_data_filter_builder.h"
#include "content/public/browser/browsing_data_remover.h"
#include "content/public/browser/cookie_store_factory.h"
@@ -174,8 +176,8 @@ class StoragePartitionRemovalTestStoragePartition
storage_partition_removal_data_.remove_end = end;
storage_partition_removal_data_.origin_matcher = origin_matcher;
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(
&StoragePartitionRemovalTestStoragePartition::AsyncRunCallback,
base::Unretained(this), std::move(callback)));
@@ -198,8 +200,8 @@ class StoragePartitionRemovalTestStoragePartition
storage_partition_removal_data_.cookie_deletion_filter =
std::move(cookie_deletion_filter);
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(
&StoragePartitionRemovalTestStoragePartition::AsyncRunCallback,
base::Unretained(this), std::move(callback)));
diff --git a/chromium/content/browser/browsing_data/clear_site_data_handler.cc b/chromium/content/browser/browsing_data/clear_site_data_handler.cc
index fc99ea9a22b..902c6b64ebc 100644
--- a/chromium/content/browser/browsing_data/clear_site_data_handler.cc
+++ b/chromium/content/browser/browsing_data/clear_site_data_handler.cc
@@ -290,7 +290,7 @@ bool ClearSiteDataHandler::Run() {
}
url::Origin origin = url::Origin::Create(url_);
- if (origin.unique()) {
+ if (origin.opaque()) {
delegate_->AddMessage(url_, "Not supported for unique origins.",
CONSOLE_MESSAGE_LEVEL_ERROR);
return false;
diff --git a/chromium/content/browser/browsing_data/clear_site_data_handler_browsertest.cc b/chromium/content/browser/browsing_data/clear_site_data_handler_browsertest.cc
index 0bf7f3c6adc..58b7e32758a 100644
--- a/chromium/content/browser/browsing_data/clear_site_data_handler_browsertest.cc
+++ b/chromium/content/browser/browsing_data/clear_site_data_handler_browsertest.cc
@@ -12,12 +12,14 @@
#include "base/scoped_observer.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/task/post_task.h"
#include "build/build_config.h"
#include "components/network_session_configurator/common/network_switches.h"
#include "content/browser/browsing_data/browsing_data_filter_builder_impl.h"
#include "content/browser/service_worker/service_worker_context_core_observer.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/browsing_data_remover.h"
#include "content/public/browser/content_browser_client.h"
@@ -206,8 +208,8 @@ class ClearSiteDataHandlerBrowserTest : public ContentBrowserTest {
// Initialize the cookie store pointer on the IO thread.
base::RunLoop run_loop;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&ClearSiteDataHandlerBrowserTest::InitializeCookieStore,
base::Unretained(this),
@@ -275,9 +277,10 @@ class ClearSiteDataHandlerBrowserTest : public ContentBrowserTest {
// Register the worker.
blink::mojom::ServiceWorkerRegistrationOptions options(
- scope_url, blink::mojom::ServiceWorkerUpdateViaCache::kImports);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ scope_url, blink::mojom::ScriptType::kClassic,
+ blink::mojom::ServiceWorkerUpdateViaCache::kImports);
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&ServiceWorkerContextWrapper::RegisterServiceWorker,
base::Unretained(service_worker_context), js_url, options,
@@ -287,8 +290,8 @@ class ClearSiteDataHandlerBrowserTest : public ContentBrowserTest {
// Wait for its activation.
base::RunLoop run_loop;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&ServiceWorkerActivationObserver::SignalActivation,
base::Unretained(service_worker_context),
run_loop.QuitClosure()));
@@ -306,8 +309,8 @@ class ClearSiteDataHandlerBrowserTest : public ContentBrowserTest {
std::vector<ServiceWorkerUsageInfo> service_workers;
base::RunLoop run_loop;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&ServiceWorkerContextWrapper::GetAllOriginsInfo,
base::Unretained(service_worker_context),
diff --git a/chromium/content/browser/browsing_data/clear_site_data_throttle.cc b/chromium/content/browser/browsing_data/clear_site_data_throttle.cc
index ba0a6e39c53..d1a6df336c5 100644
--- a/chromium/content/browser/browsing_data/clear_site_data_throttle.cc
+++ b/chromium/content/browser/browsing_data/clear_site_data_throttle.cc
@@ -11,9 +11,11 @@
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
+#include "base/task/post_task.h"
#include "base/values.h"
#include "content/browser/service_worker/service_worker_response_info.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/browsing_data_filter_builder.h"
#include "content/public/browser/browsing_data_remover.h"
@@ -72,7 +74,7 @@ int ParametersMask2(bool clear_cookies, bool clear_storage, bool clear_cache) {
// the UI thread.
void JumpFromUIToIOThread(base::OnceClosure callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, std::move(callback));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO}, std::move(callback));
}
// Finds the BrowserContext associated with the request and requests
@@ -256,8 +258,8 @@ void ClearSiteDataThrottle::ConsoleMessagesDelegate::OutputMessages(
return;
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&OutputMessagesOnUIThread, web_contents_getter,
std::move(messages_), output_formatted_message_function_));
@@ -367,7 +369,7 @@ bool ClearSiteDataThrottle::HandleHeader() {
}
url::Origin origin = url::Origin::Create(GetCurrentURL());
- if (origin.unique()) {
+ if (origin.opaque()) {
delegate_->AddMessage(GetCurrentURL(), "Not supported for unique origins.",
CONSOLE_MESSAGE_LEVEL_ERROR);
return false;
@@ -523,8 +525,8 @@ void ClearSiteDataThrottle::ExecuteClearingTask(const url::Origin& origin,
bool clear_cache,
base::OnceClosure callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&UIThreadSiteDataClearer::Run,
ResourceRequestInfo::ForRequest(request_)
->GetWebContentsGetterForRequest(),
diff --git a/chromium/content/browser/browsing_data/clear_site_data_throttle_unittest.cc b/chromium/content/browser/browsing_data/clear_site_data_throttle_unittest.cc
index 5af116cf2f6..4630b9cff5d 100644
--- a/chromium/content/browser/browsing_data/clear_site_data_throttle_unittest.cc
+++ b/chromium/content/browser/browsing_data/clear_site_data_throttle_unittest.cc
@@ -9,8 +9,10 @@
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
+#include "base/task/post_task.h"
#include "base/test/scoped_command_line.h"
#include "base/test/scoped_task_environment.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/resource_request_info.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/test_browser_thread.h"
@@ -38,7 +40,8 @@ const char kClearCookiesHeader[] = "Clear-Site-Data: \"cookies\"";
void WaitForUIThread() {
base::RunLoop run_loop;
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, run_loop.QuitClosure());
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ run_loop.QuitClosure());
run_loop.Run();
}
diff --git a/chromium/content/browser/browsing_data/conditional_cache_deletion_helper_browsertest.cc b/chromium/content/browser/browsing_data/conditional_cache_deletion_helper_browsertest.cc
index 3d4ecc58671..9857560d855 100644
--- a/chromium/content/browser/browsing_data/conditional_cache_deletion_helper_browsertest.cc
+++ b/chromium/content/browser/browsing_data/conditional_cache_deletion_helper_browsertest.cc
@@ -10,10 +10,12 @@
#include "base/strings/string_number_conversions.h"
#include "base/synchronization/waitable_event.h"
+#include "base/task/post_task.h"
#include "base/test/test_timeouts.h"
#include "base/threading/platform_thread.h"
#include "content/browser/browsing_data/conditional_cache_deletion_helper.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents.h"
@@ -103,8 +105,8 @@ IN_PROC_BROWSER_TEST_F(ConditionalCacheDeletionHelperBrowserTest, Condition) {
GetCacheTestUtil()->CreateCacheEntries(keys);
// Delete the entries whose keys are even numbers.
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&ConditionalCacheDeletionHelperBrowserTest::DeleteEntries,
base::Unretained(this), base::Bind(&KeyIsEven)));
WaitForTasksOnIOThread();
@@ -163,8 +165,8 @@ IN_PROC_BROWSER_TEST_F(ConditionalCacheDeletionHelperBrowserTest,
base::Bind(&HasHttpsExampleOrigin), now, base::Time::Max());
// Delete the entries.
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&ConditionalCacheDeletionHelperBrowserTest::DeleteEntries,
base::Unretained(this), std::move(condition)));
WaitForTasksOnIOThread();
diff --git a/chromium/content/browser/browsing_data/storage_partition_http_cache_data_remover.cc b/chromium/content/browser/browsing_data/storage_partition_http_cache_data_remover.cc
index a6551a0c099..1f0e36632e8 100644
--- a/chromium/content/browser/browsing_data/storage_partition_http_cache_data_remover.cc
+++ b/chromium/content/browser/browsing_data/storage_partition_http_cache_data_remover.cc
@@ -7,10 +7,12 @@
#include "base/location.h"
#include "base/sequenced_task_runner_helpers.h"
#include "base/single_thread_task_runner.h"
+#include "base/task/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/browsing_data/conditional_cache_deletion_helper.h"
#include "content/browser/code_cache/generated_code_cache.h"
#include "content/browser/code_cache/generated_code_cache_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/common/content_features.h"
@@ -73,8 +75,8 @@ void StoragePartitionHttpCacheDataRemover::Remove(
DCHECK(!done_callback.is_null());
done_callback_ = std::move(done_callback);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&StoragePartitionHttpCacheDataRemover::ClearHttpCacheOnIOThread,
base::Unretained(this)));
@@ -97,8 +99,8 @@ void StoragePartitionHttpCacheDataRemover::ClearedHttpCache() {
// The expected state sequence is CacheState::NONE --> CacheState::CREATE_MAIN
// --> CacheState::DELETE_MAIN --> CacheState::CREATE_MEDIA -->
-// CacheState::DELETE_MEDIA --> CacheState::DELETE_CODE --> CacheState::DONE,
-// and any errors are ignored.
+// CacheState::DELETE_MEDIA --> CacheState::DELETE_CODE_JS --> DELETE_CODE_WASM
+// -> CacheState::DONE, and any errors are ignored.
void StoragePartitionHttpCacheDataRemover::DoClearCache(int rv) {
DCHECK_NE(CacheState::NONE, next_cache_state_);
@@ -116,7 +118,7 @@ void StoragePartitionHttpCacheDataRemover::DoClearCache(int rv) {
if (!getter) {
next_cache_state_ = (next_cache_state_ == CacheState::CREATE_MAIN)
? CacheState::CREATE_MEDIA
- : CacheState::DELETE_CODE;
+ : CacheState::DELETE_CODE_JS;
break;
}
@@ -143,7 +145,7 @@ void StoragePartitionHttpCacheDataRemover::DoClearCache(int rv) {
case CacheState::DELETE_MEDIA: {
next_cache_state_ = (next_cache_state_ == CacheState::DELETE_MAIN)
? CacheState::CREATE_MEDIA
- : CacheState::DELETE_CODE;
+ : CacheState::DELETE_CODE_JS;
// |cache_| can be null if it cannot be initialized.
if (cache_) {
@@ -170,21 +172,28 @@ void StoragePartitionHttpCacheDataRemover::DoClearCache(int rv) {
}
break;
}
- case CacheState::DELETE_CODE: {
+ case CacheState::DELETE_CODE_JS: {
+ next_cache_state_ = CacheState::DELETE_CODE_WASM;
+ // TODO(crbug.com/866419): Currently we just clear entire caches.
+ // Change it to conditionally clear entries based on the filters.
+ // Likewise for DELETE_CODE_WASM.
+ if (generated_code_cache_context_ &&
+ generated_code_cache_context_->generated_js_code_cache()) {
+ rv = generated_code_cache_context_->generated_js_code_cache()
+ ->ClearCache(base::BindRepeating(
+ &StoragePartitionHttpCacheDataRemover::DoClearCache,
+ base::Unretained(this)));
+ }
+ break;
+ }
+ case CacheState::DELETE_CODE_WASM: {
next_cache_state_ = CacheState::DONE;
- if (base::FeatureList::IsEnabled(features::kIsolatedCodeCache)) {
- DCHECK(generated_code_cache_context_);
- GeneratedCodeCache* code_cache =
- generated_code_cache_context_->generated_code_cache();
- if (code_cache) {
- auto callback = base::BindRepeating(
- &StoragePartitionHttpCacheDataRemover::DoClearCache,
- base::Unretained(this));
- // TODO(crbug.com/866419): Currently we just clear the entire cache.
- // Change it to conditionally clear the entries based on the
- // filters.
- rv = code_cache->ClearCache(callback);
- }
+ if (generated_code_cache_context_ &&
+ generated_code_cache_context_->generated_wasm_code_cache()) {
+ rv = generated_code_cache_context_->generated_wasm_code_cache()
+ ->ClearCache(base::BindRepeating(
+ &StoragePartitionHttpCacheDataRemover::DoClearCache,
+ base::Unretained(this)));
}
break;
}
@@ -193,8 +202,8 @@ void StoragePartitionHttpCacheDataRemover::DoClearCache(int rv) {
next_cache_state_ = CacheState::NONE;
// Notify the UI thread that we are done.
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(
&StoragePartitionHttpCacheDataRemover::ClearedHttpCache,
base::Unretained(this)));
diff --git a/chromium/content/browser/browsing_data/storage_partition_http_cache_data_remover.h b/chromium/content/browser/browsing_data/storage_partition_http_cache_data_remover.h
index 665a8f4e6b8..e9bf114541a 100644
--- a/chromium/content/browser/browsing_data/storage_partition_http_cache_data_remover.h
+++ b/chromium/content/browser/browsing_data/storage_partition_http_cache_data_remover.h
@@ -57,7 +57,8 @@ class StoragePartitionHttpCacheDataRemover {
CREATE_MEDIA,
DELETE_MAIN,
DELETE_MEDIA,
- DELETE_CODE,
+ DELETE_CODE_JS,
+ DELETE_CODE_WASM,
DONE
};
diff --git a/chromium/content/browser/browsing_instance.cc b/chromium/content/browser/browsing_instance.cc
index 9b24ae580a6..2b6c41a4b80 100644
--- a/chromium/content/browser/browsing_instance.cc
+++ b/chromium/content/browser/browsing_instance.cc
@@ -32,7 +32,7 @@ scoped_refptr<SiteInstanceImpl> BrowsingInstance::GetSiteInstanceForURL(
std::string site = SiteInstance::GetSiteForURL(browser_context_, url)
.possibly_invalid_spec();
- SiteInstanceMap::iterator i = site_instance_map_.find(site);
+ auto i = site_instance_map_.find(site);
if (i != site_instance_map_.end())
return i->second;
@@ -44,33 +44,10 @@ scoped_refptr<SiteInstanceImpl> BrowsingInstance::GetSiteInstanceForURL(
return instance;
}
-scoped_refptr<SiteInstanceImpl>
-BrowsingInstance::GetDefaultSubframeSiteInstance() {
- // This should only be used for --top-document-isolation mode.
- CHECK(SiteIsolationPolicy::IsTopDocumentIsolationEnabled());
- if (!default_subframe_site_instance_) {
- SiteInstanceImpl* instance = new SiteInstanceImpl(this);
- instance->set_process_reuse_policy(
- SiteInstanceImpl::ProcessReusePolicy::USE_DEFAULT_SUBFRAME_PROCESS);
-
- // TODO(nick): This is a hack for now.
- instance->SetSite(GURL("http://web-subframes.invalid"));
-
- default_subframe_site_instance_ = instance;
- }
-
- return base::WrapRefCounted(default_subframe_site_instance_);
-}
-
void BrowsingInstance::RegisterSiteInstance(SiteInstanceImpl* site_instance) {
DCHECK(site_instance->browsing_instance_.get() == this);
DCHECK(site_instance->HasSite());
- // Don't register the default subframe SiteInstance, to prevent it from being
- // returned by GetSiteInstanceForURL.
- if (default_subframe_site_instance_ == site_instance)
- return;
-
std::string site = site_instance->GetSiteURL().possibly_invalid_spec();
// Only register if we don't have a SiteInstance for this site already.
@@ -78,7 +55,7 @@ void BrowsingInstance::RegisterSiteInstance(SiteInstanceImpl* site_instance) {
// tabs are navigated there at the same time. (We don't call SetSite or
// register them until DidNavigate.) If there is a previously existing
// SiteInstance for this site, we just won't register the new one.
- SiteInstanceMap::iterator i = site_instance_map_.find(site);
+ auto i = site_instance_map_.find(site);
if (i == site_instance_map_.end()) {
// Not previously registered, so register it.
site_instance_map_[site] = site_instance;
@@ -93,13 +70,11 @@ void BrowsingInstance::UnregisterSiteInstance(SiteInstanceImpl* site_instance) {
// Only unregister the SiteInstance if it is the same one that is registered
// for the site. (It might have been an unregistered SiteInstance. See the
// comments in RegisterSiteInstance.)
- SiteInstanceMap::iterator i = site_instance_map_.find(site);
+ auto i = site_instance_map_.find(site);
if (i != site_instance_map_.end() && i->second == site_instance) {
// Matches, so erase it.
site_instance_map_.erase(i);
}
- if (default_subframe_site_instance_ == site_instance)
- default_subframe_site_instance_ = nullptr;
}
BrowsingInstance::~BrowsingInstance() {
diff --git a/chromium/content/browser/browsing_instance.h b/chromium/content/browser/browsing_instance.h
index 2e17bf8d5c5..118f1781b30 100644
--- a/chromium/content/browser/browsing_instance.h
+++ b/chromium/content/browser/browsing_instance.h
@@ -87,12 +87,6 @@ class CONTENT_EXPORT BrowsingInstance final
// SiteInstance per site.
scoped_refptr<SiteInstanceImpl> GetSiteInstanceForURL(const GURL& url);
- // Returns a SiteInstance that should be used for subframes when an oopif is
- // required, but a dedicated process is not. This SiteInstance will be created
- // if it doesn't already exist. There is at most one of these per
- // BrowsingInstance.
- scoped_refptr<SiteInstanceImpl> GetDefaultSubframeSiteInstance();
-
// Adds the given SiteInstance to our map, to ensure that we do not create
// another SiteInstance for the same site.
void RegisterSiteInstance(SiteInstanceImpl* site_instance);
@@ -131,8 +125,6 @@ class CONTENT_EXPORT BrowsingInstance final
// Number of WebContentses currently using this BrowsingInstance.
size_t active_contents_count_;
- SiteInstanceImpl* default_subframe_site_instance_ = nullptr;
-
DISALLOW_COPY_AND_ASSIGN(BrowsingInstance);
};
diff --git a/chromium/content/browser/byte_stream.h b/chromium/content/browser/byte_stream.h
index 784bc67cc13..6e3719f0198 100644
--- a/chromium/content/browser/byte_stream.h
+++ b/chromium/content/browser/byte_stream.h
@@ -11,7 +11,9 @@
#include "base/callback.h"
#include "base/memory/ref_counted.h"
+#include "base/task/post_task.h"
#include "content/common/content_export.h"
+#include "content/public/browser/browser_task_traits.h"
#include "net/base/io_buffer.h"
namespace base {
@@ -66,7 +68,7 @@ namespace content {
// std::unique_ptr<ByteStreamWriter> writer;
// std::unique_ptr<ByteStreamReader> reader;
// CreateByteStream(
-// BrowserThread::GetTaskRunnerForThread(BrowserThread::IO),
+// base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO}),
// base::CreateSequencedTaskRunnerWithTraits({base::MayBlock, ...}),
// kStreamBufferSize /* e.g. 10240. */,
// &writer,
diff --git a/chromium/content/browser/byte_stream_unittest.cc b/chromium/content/browser/byte_stream_unittest.cc
index 7335cf2f717..0d617d3b1fe 100644
--- a/chromium/content/browser/byte_stream_unittest.cc
+++ b/chromium/content/browser/byte_stream_unittest.cc
@@ -12,9 +12,10 @@
#include "base/callback.h"
#include "base/containers/circular_deque.h"
#include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop.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 "net/base/io_buffer.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -35,7 +36,8 @@ class ByteStreamTest : public testing::Test {
// contents of the created buffer will be kept, and can be validated
// by ValidateIOBuffer.
scoped_refptr<net::IOBuffer> NewIOBuffer(size_t buffer_size) {
- scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(buffer_size));
+ scoped_refptr<net::IOBuffer> buffer =
+ base::MakeRefCounted<net::IOBuffer>(buffer_size);
char *bufferp = buffer->data();
for (size_t i = 0; i < buffer_size; i++)
bufferp[i] = (i + producing_seed_key_) % (1 << sizeof(char));
@@ -89,7 +91,7 @@ class ByteStreamTest : public testing::Test {
}
protected:
- base::MessageLoop message_loop_;
+ base::test::ScopedTaskEnvironment task_environment_;
private:
int producing_seed_key_;
@@ -107,8 +109,9 @@ ByteStreamTest::ByteStreamTest()
TEST_F(ByteStreamTest, ByteStream_PushBack) {
std::unique_ptr<ByteStreamWriter> byte_stream_input;
std::unique_ptr<ByteStreamReader> byte_stream_output;
- CreateByteStream(message_loop_.task_runner(), message_loop_.task_runner(),
- 3 * 1024, &byte_stream_input, &byte_stream_output);
+ CreateByteStream(base::ThreadTaskRunnerHandle::Get(),
+ base::ThreadTaskRunnerHandle::Get(), 3 * 1024,
+ &byte_stream_input, &byte_stream_output);
// Push a series of IO buffers on; test pushback happening and
// that it's advisory.
@@ -161,8 +164,9 @@ TEST_F(ByteStreamTest, ByteStream_PushBack) {
TEST_F(ByteStreamTest, ByteStream_Flush) {
std::unique_ptr<ByteStreamWriter> byte_stream_input;
std::unique_ptr<ByteStreamReader> byte_stream_output;
- CreateByteStream(message_loop_.task_runner(), message_loop_.task_runner(),
- 1024, &byte_stream_input, &byte_stream_output);
+ CreateByteStream(base::ThreadTaskRunnerHandle::Get(),
+ base::ThreadTaskRunnerHandle::Get(), 1024,
+ &byte_stream_input, &byte_stream_output);
EXPECT_TRUE(Write(byte_stream_input.get(), 1));
base::RunLoop().RunUntilIdle();
@@ -200,8 +204,9 @@ TEST_F(ByteStreamTest, ByteStream_Flush) {
TEST_F(ByteStreamTest, ByteStream_PushBackSplit) {
std::unique_ptr<ByteStreamWriter> byte_stream_input;
std::unique_ptr<ByteStreamReader> byte_stream_output;
- CreateByteStream(message_loop_.task_runner(), message_loop_.task_runner(),
- 9 * 1024, &byte_stream_input, &byte_stream_output);
+ CreateByteStream(base::ThreadTaskRunnerHandle::Get(),
+ base::ThreadTaskRunnerHandle::Get(), 9 * 1024,
+ &byte_stream_input, &byte_stream_output);
// Push a series of IO buffers on; test pushback happening and
// that it's advisory.
@@ -254,8 +259,9 @@ TEST_F(ByteStreamTest, ByteStream_CompleteTransmits) {
size_t output_length;
// Empty stream, non-error case.
- CreateByteStream(message_loop_.task_runner(), message_loop_.task_runner(),
- 3 * 1024, &byte_stream_input, &byte_stream_output);
+ CreateByteStream(base::ThreadTaskRunnerHandle::Get(),
+ base::ThreadTaskRunnerHandle::Get(), 3 * 1024,
+ &byte_stream_input, &byte_stream_output);
EXPECT_EQ(ByteStreamReader::STREAM_EMPTY,
byte_stream_output->Read(&output_io_buffer, &output_length));
byte_stream_input->Close(0);
@@ -265,8 +271,9 @@ TEST_F(ByteStreamTest, ByteStream_CompleteTransmits) {
EXPECT_EQ(0, byte_stream_output->GetStatus());
// Non-empty stream, non-error case.
- CreateByteStream(message_loop_.task_runner(), message_loop_.task_runner(),
- 3 * 1024, &byte_stream_input, &byte_stream_output);
+ CreateByteStream(base::ThreadTaskRunnerHandle::Get(),
+ base::ThreadTaskRunnerHandle::Get(), 3 * 1024,
+ &byte_stream_input, &byte_stream_output);
EXPECT_EQ(ByteStreamReader::STREAM_EMPTY,
byte_stream_output->Read(&output_io_buffer, &output_length));
EXPECT_TRUE(Write(byte_stream_input.get(), 1024));
@@ -282,8 +289,9 @@ TEST_F(ByteStreamTest, ByteStream_CompleteTransmits) {
const int kFakeErrorCode = 22;
// Empty stream, error case.
- CreateByteStream(message_loop_.task_runner(), message_loop_.task_runner(),
- 3 * 1024, &byte_stream_input, &byte_stream_output);
+ CreateByteStream(base::ThreadTaskRunnerHandle::Get(),
+ base::ThreadTaskRunnerHandle::Get(), 3 * 1024,
+ &byte_stream_input, &byte_stream_output);
EXPECT_EQ(ByteStreamReader::STREAM_EMPTY,
byte_stream_output->Read(&output_io_buffer, &output_length));
byte_stream_input->Close(kFakeErrorCode);
@@ -293,8 +301,9 @@ TEST_F(ByteStreamTest, ByteStream_CompleteTransmits) {
EXPECT_EQ(kFakeErrorCode, byte_stream_output->GetStatus());
// Non-empty stream, error case.
- CreateByteStream(message_loop_.task_runner(), message_loop_.task_runner(),
- 3 * 1024, &byte_stream_input, &byte_stream_output);
+ CreateByteStream(base::ThreadTaskRunnerHandle::Get(),
+ base::ThreadTaskRunnerHandle::Get(), 3 * 1024,
+ &byte_stream_input, &byte_stream_output);
EXPECT_EQ(ByteStreamReader::STREAM_EMPTY,
byte_stream_output->Read(&output_io_buffer, &output_length));
EXPECT_TRUE(Write(byte_stream_input.get(), 1024));
@@ -315,7 +324,7 @@ TEST_F(ByteStreamTest, ByteStream_SinkCallback) {
std::unique_ptr<ByteStreamWriter> byte_stream_input;
std::unique_ptr<ByteStreamReader> byte_stream_output;
- CreateByteStream(message_loop_.task_runner(), task_runner, 10000,
+ CreateByteStream(base::ThreadTaskRunnerHandle::Get(), task_runner, 10000,
&byte_stream_input, &byte_stream_output);
scoped_refptr<net::IOBuffer> output_io_buffer;
@@ -366,7 +375,7 @@ TEST_F(ByteStreamTest, ByteStream_SourceCallback) {
std::unique_ptr<ByteStreamWriter> byte_stream_input;
std::unique_ptr<ByteStreamReader> byte_stream_output;
- CreateByteStream(task_runner, message_loop_.task_runner(), 10000,
+ CreateByteStream(task_runner, base::ThreadTaskRunnerHandle::Get(), 10000,
&byte_stream_input, &byte_stream_output);
scoped_refptr<net::IOBuffer> output_io_buffer;
@@ -427,7 +436,7 @@ TEST_F(ByteStreamTest, ByteStream_SinkInterrupt) {
std::unique_ptr<ByteStreamWriter> byte_stream_input;
std::unique_ptr<ByteStreamReader> byte_stream_output;
- CreateByteStream(message_loop_.task_runner(), task_runner, 10000,
+ CreateByteStream(base::ThreadTaskRunnerHandle::Get(), task_runner, 10000,
&byte_stream_input, &byte_stream_output);
scoped_refptr<net::IOBuffer> output_io_buffer;
@@ -473,7 +482,7 @@ TEST_F(ByteStreamTest, ByteStream_SourceInterrupt) {
std::unique_ptr<ByteStreamWriter> byte_stream_input;
std::unique_ptr<ByteStreamReader> byte_stream_output;
- CreateByteStream(task_runner, message_loop_.task_runner(), 10000,
+ CreateByteStream(task_runner, base::ThreadTaskRunnerHandle::Get(), 10000,
&byte_stream_input, &byte_stream_output);
scoped_refptr<net::IOBuffer> output_io_buffer;
@@ -524,7 +533,7 @@ TEST_F(ByteStreamTest, ByteStream_ZeroCallback) {
std::unique_ptr<ByteStreamWriter> byte_stream_input;
std::unique_ptr<ByteStreamReader> byte_stream_output;
- CreateByteStream(message_loop_.task_runner(), task_runner, 10000,
+ CreateByteStream(base::ThreadTaskRunnerHandle::Get(), task_runner, 10000,
&byte_stream_input, &byte_stream_output);
base::Closure intermediate_callback;
@@ -543,8 +552,9 @@ TEST_F(ByteStreamTest, ByteStream_ZeroCallback) {
TEST_F(ByteStreamTest, ByteStream_CloseWithoutAnyWrite) {
std::unique_ptr<ByteStreamWriter> byte_stream_input;
std::unique_ptr<ByteStreamReader> byte_stream_output;
- CreateByteStream(message_loop_.task_runner(), message_loop_.task_runner(),
- 3 * 1024, &byte_stream_input, &byte_stream_output);
+ CreateByteStream(base::ThreadTaskRunnerHandle::Get(),
+ base::ThreadTaskRunnerHandle::Get(), 3 * 1024,
+ &byte_stream_input, &byte_stream_output);
byte_stream_input->Close(0);
base::RunLoop().RunUntilIdle();
@@ -558,8 +568,9 @@ TEST_F(ByteStreamTest, ByteStream_CloseWithoutAnyWrite) {
TEST_F(ByteStreamTest, ByteStream_FlushWithoutAnyWrite) {
std::unique_ptr<ByteStreamWriter> byte_stream_input;
std::unique_ptr<ByteStreamReader> byte_stream_output;
- CreateByteStream(message_loop_.task_runner(), message_loop_.task_runner(),
- 3 * 1024, &byte_stream_input, &byte_stream_output);
+ CreateByteStream(base::ThreadTaskRunnerHandle::Get(),
+ base::ThreadTaskRunnerHandle::Get(), 3 * 1024,
+ &byte_stream_input, &byte_stream_output);
byte_stream_input->Flush();
base::RunLoop().RunUntilIdle();
@@ -579,7 +590,8 @@ TEST_F(ByteStreamTest, ByteStream_FlushWithoutAnyWrite) {
TEST_F(ByteStreamTest, ByteStream_WriteOverflow) {
std::unique_ptr<ByteStreamWriter> byte_stream_input;
std::unique_ptr<ByteStreamReader> byte_stream_output;
- CreateByteStream(message_loop_.task_runner(), message_loop_.task_runner(),
+ CreateByteStream(base::ThreadTaskRunnerHandle::Get(),
+ base::ThreadTaskRunnerHandle::Get(),
std::numeric_limits<size_t>::max(), &byte_stream_input,
&byte_stream_output);
diff --git a/chromium/content/browser/cache_storage/cache_storage.cc b/chromium/content/browser/cache_storage/cache_storage.cc
index 78508c8b6f1..5371daf3c55 100644
--- a/chromium/content/browser/cache_storage/cache_storage.cc
+++ b/chromium/content/browser/cache_storage/cache_storage.cc
@@ -30,6 +30,7 @@
#include "content/browser/cache_storage/cache_storage.pb.h"
#include "content/browser/cache_storage/cache_storage_cache.h"
#include "content/browser/cache_storage/cache_storage_cache_handle.h"
+#include "content/browser/cache_storage/cache_storage_histogram_utils.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"
@@ -132,7 +133,7 @@ class CacheStorage::CacheLoader {
cache_storage_(cache_storage),
origin_(origin),
owner_(owner) {
- DCHECK(!origin_.unique());
+ DCHECK(!origin_.opaque());
}
virtual ~CacheLoader() {}
@@ -895,8 +896,9 @@ void CacheStorage::CreateCacheDidCreateCache(
static_cast<bool>(cache));
if (!cache) {
- std::move(callback).Run(CacheStorageCacheHandle(),
- CacheStorageError::kErrorStorage);
+ std::move(callback).Run(
+ CacheStorageCacheHandle(),
+ MakeErrorStorage(ErrorStorageType::kDidCreateNullCache));
return;
}
@@ -966,14 +968,14 @@ void CacheStorage::DeleteCacheDidWriteIndex(
// Undo any changes if the index couldn't be written to disk.
cache_index_->RestoreDoomedCache();
cache_handle.value()->SetObserver(this);
- std::move(callback).Run(CacheStorageError::kErrorStorage);
+ std::move(callback).Run(
+ MakeErrorStorage(ErrorStorageType::kDeleteCacheFailed));
return;
}
cache_index_->FinalizeDoomedCache();
- CacheMap::iterator map_iter =
- cache_map_.find(cache_handle.value()->cache_name());
+ auto map_iter = cache_map_.find(cache_handle.value()->cache_name());
DCHECK(map_iter != cache_map_.end());
doomed_caches_.insert(
@@ -1159,7 +1161,7 @@ CacheStorageCacheHandle CacheStorage::GetLoadedCache(
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(initialized_);
- CacheMap::iterator map_iter = cache_map_.find(cache_name);
+ auto map_iter = cache_map_.find(cache_name);
if (map_iter == cache_map_.end())
return CacheStorageCacheHandle();
diff --git a/chromium/content/browser/cache_storage/cache_storage_blob_to_disk_cache.cc b/chromium/content/browser/cache_storage/cache_storage_blob_to_disk_cache.cc
index ad208e12186..dbfaccfc03e 100644
--- a/chromium/content/browser/cache_storage/cache_storage_blob_to_disk_cache.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_blob_to_disk_cache.cc
@@ -13,6 +13,7 @@
#include "storage/browser/blob/blob_data_handle.h"
#include "storage/browser/blob/blob_url_request_job_factory.h"
#include "storage/common/storage_histograms.h"
+#include "third_party/blink/public/common/blob/blob_utils.h"
namespace content {
@@ -31,6 +32,7 @@ void CacheStorageBlobToDiskCache::StreamBlobToCache(
disk_cache::ScopedEntryPtr entry,
int disk_cache_body_index,
blink::mojom::BlobPtr blob,
+ uint64_t blob_size,
EntryAndBoolCallback callback) {
DCHECK(entry);
DCHECK_LE(0, disk_cache_body_index);
@@ -38,10 +40,16 @@ void CacheStorageBlobToDiskCache::StreamBlobToCache(
DCHECK(!consumer_handle_.is_valid());
DCHECK(!pending_read_);
+ MojoCreateDataPipeOptions options;
+ options.struct_size = sizeof(MojoCreateDataPipeOptions);
+ options.flags = MOJO_CREATE_DATA_PIPE_FLAG_NONE;
+ options.element_num_bytes = 1;
+ options.capacity_num_bytes = blink::BlobUtils::GetDataPipeCapacity(blob_size);
+
mojo::ScopedDataPipeProducerHandle producer_handle;
- MojoResult result =
- CreateDataPipe(nullptr, &producer_handle, &consumer_handle_);
- if (result != MOJO_RESULT_OK) {
+ MojoResult rv =
+ mojo::CreateDataPipe(&options, &producer_handle, &consumer_handle_);
+ if (rv != MOJO_RESULT_OK) {
std::move(callback).Run(std::move(entry), false /* success */);
return;
}
diff --git a/chromium/content/browser/cache_storage/cache_storage_blob_to_disk_cache.h b/chromium/content/browser/cache_storage/cache_storage_blob_to_disk_cache.h
index dbaf77d581a..efcfc5d5319 100644
--- a/chromium/content/browser/cache_storage/cache_storage_blob_to_disk_cache.h
+++ b/chromium/content/browser/cache_storage/cache_storage_blob_to_disk_cache.h
@@ -38,6 +38,7 @@ class CONTENT_EXPORT CacheStorageBlobToDiskCache
void StreamBlobToCache(disk_cache::ScopedEntryPtr entry,
int disk_cache_body_index,
blink::mojom::BlobPtr blob,
+ uint64_t blob_size,
EntryAndBoolCallback callback);
// BlobReaderClient:
diff --git a/chromium/content/browser/cache_storage/cache_storage_blob_to_disk_cache_unittest.cc b/chromium/content/browser/cache_storage/cache_storage_blob_to_disk_cache_unittest.cc
index 103f821e3f8..c4f1c0216af 100644
--- a/chromium/content/browser/cache_storage/cache_storage_blob_to_disk_cache_unittest.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_blob_to_disk_cache_unittest.cc
@@ -152,8 +152,8 @@ class CacheStorageBlobToDiskCacheTest : public testing::Test {
std::string ReadCacheContent() {
int bytes_to_read = disk_cache_entry_->GetDataSize(kCacheEntryIndex);
- scoped_refptr<net::IOBufferWithSize> buffer(
- new net::IOBufferWithSize(bytes_to_read));
+ scoped_refptr<net::IOBufferWithSize> buffer =
+ base::MakeRefCounted<net::IOBufferWithSize>(bytes_to_read);
int rv = disk_cache_entry_->ReadData(kCacheEntryIndex, 0 /* offset */,
buffer.get(), buffer->size(),
@@ -170,6 +170,7 @@ class CacheStorageBlobToDiskCacheTest : public testing::Test {
cache_storage_blob_to_disk_cache_->StreamBlobToCache(
std::move(disk_cache_entry_), kCacheEntryIndex, std::move(blob_ptr),
+ blob_handle_->size(),
base::BindOnce(&CacheStorageBlobToDiskCacheTest::StreamCallback,
base::Unretained(this)));
diff --git a/chromium/content/browser/cache_storage/cache_storage_cache.cc b/chromium/content/browser/cache_storage/cache_storage_cache.cc
index a4e3aa14d58..72f27bb164f 100644
--- a/chromium/content/browser/cache_storage/cache_storage_cache.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_cache.cc
@@ -29,6 +29,8 @@
#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_histogram_utils.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"
@@ -50,6 +52,7 @@
#include "storage/browser/quota/quota_manager_proxy.h"
#include "storage/common/blob_storage/blob_handle.h"
#include "storage/common/storage_histograms.h"
+#include "third_party/blink/public/common/blob/blob_utils.h"
#include "third_party/blink/public/common/cache_storage/cache_storage_utils.h"
#include "third_party/blink/public/mojom/quota/quota_types.mojom.h"
@@ -83,10 +86,6 @@ const int32_t kCachePaddingAlgorithmVersion = 2;
using MetadataCallback =
base::OnceCallback<void(std::unique_ptr<proto::CacheMetadata>)>;
-// The maximum size of each cache. Ultimately, cache size
-// is controlled per-origin by the QuotaManager.
-const int kMaxCacheBytes = std::numeric_limits<int>::max();
-
network::mojom::FetchResponseType ProtoResponseTypeToFetchResponseType(
proto::CacheResponse::ResponseType response_type) {
switch (response_type) {
@@ -152,9 +151,8 @@ bool VaryMatches(const ServiceWorkerHeaderMap& request,
if (trimmed == "*")
return false;
- ServiceWorkerHeaderMap::const_iterator request_iter = request.find(trimmed);
- ServiceWorkerHeaderMap::const_iterator cached_request_iter =
- cached_request.find(trimmed);
+ auto request_iter = request.find(trimmed);
+ auto cached_request_iter = cached_request.find(trimmed);
// If the header exists in one but not the other, no match.
if ((request_iter == request.end()) !=
@@ -258,8 +256,9 @@ GURL RemoveQueryParam(const GURL& url) {
void ReadMetadata(disk_cache::Entry* entry, MetadataCallback callback) {
DCHECK(entry);
- scoped_refptr<net::IOBufferWithSize> buffer(new net::IOBufferWithSize(
- entry->GetDataSize(CacheStorageCache::INDEX_HEADERS)));
+ scoped_refptr<net::IOBufferWithSize> buffer =
+ base::MakeRefCounted<net::IOBufferWithSize>(
+ entry->GetDataSize(CacheStorageCache::INDEX_HEADERS));
net::CompletionCallback read_header_callback =
base::AdaptCallbackForRepeating(base::BindOnce(
@@ -446,19 +445,25 @@ struct CacheStorageCache::PutContext {
PutContext(std::unique_ptr<ServiceWorkerFetchRequest> request,
blink::mojom::FetchAPIResponsePtr response,
blink::mojom::BlobPtr blob,
+ uint64_t blob_size,
blink::mojom::BlobPtr side_data_blob,
+ uint64_t side_data_blob_size,
CacheStorageCache::ErrorCallback callback)
: request(std::move(request)),
response(std::move(response)),
blob(std::move(blob)),
+ blob_size(blob_size),
side_data_blob(std::move(side_data_blob)),
+ side_data_blob_size(side_data_blob_size),
callback(std::move(callback)) {}
// Input parameters to the Put function.
std::unique_ptr<ServiceWorkerFetchRequest> request;
blink::mojom::FetchAPIResponsePtr response;
blink::mojom::BlobPtr blob;
+ uint64_t blob_size;
blink::mojom::BlobPtr side_data_blob;
+ uint64_t side_data_blob_size;
CacheStorageCache::ErrorCallback callback;
disk_cache::ScopedEntryPtr cache_entry;
@@ -566,7 +571,8 @@ void CacheStorageCache::Match(
blink::mojom::QueryParamsPtr match_params,
ResponseCallback callback) {
if (backend_state_ == BACKEND_CLOSED) {
- std::move(callback).Run(CacheStorageError::kErrorStorage, nullptr);
+ std::move(callback).Run(
+ MakeErrorStorage(ErrorStorageType::kMatchBackendClosed), nullptr);
return;
}
@@ -581,8 +587,9 @@ void CacheStorageCache::MatchAll(
blink::mojom::QueryParamsPtr match_params,
ResponsesCallback callback) {
if (backend_state_ == BACKEND_CLOSED) {
- std::move(callback).Run(CacheStorageError::kErrorStorage,
- std::vector<blink::mojom::FetchAPIResponsePtr>());
+ std::move(callback).Run(
+ MakeErrorStorage(ErrorStorageType::kMatchAllBackendClosed),
+ std::vector<blink::mojom::FetchAPIResponsePtr>());
return;
}
@@ -600,7 +607,9 @@ void CacheStorageCache::WriteSideData(ErrorCallback callback,
if (backend_state_ == BACKEND_CLOSED) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
- base::BindOnce(std::move(callback), CacheStorageError::kErrorStorage));
+ base::BindOnce(
+ std::move(callback),
+ MakeErrorStorage(ErrorStorageType::kWriteSideDataBackendClosed)));
return;
}
@@ -626,10 +635,12 @@ void CacheStorageCache::BatchOperation(
if (backend_state_ == BACKEND_CLOSED) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(std::move(callback),
- CacheStorageVerboseError::New(
- CacheStorageError::kErrorStorage,
- std::move(message))));
+ FROM_HERE,
+ base::BindOnce(
+ std::move(callback),
+ CacheStorageVerboseError::New(
+ MakeErrorStorage(ErrorStorageType::kBatchBackendClosed),
+ std::move(message))));
return;
}
@@ -689,10 +700,12 @@ void CacheStorageCache::BatchOperation(
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, std::move(bad_message_callback));
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(std::move(callback),
- CacheStorageVerboseError::New(
- CacheStorageError::kErrorStorage,
- std::move(message))));
+ FROM_HERE,
+ base::BindOnce(
+ std::move(callback),
+ CacheStorageVerboseError::New(
+ MakeErrorStorage(ErrorStorageType::kBatchInvalidSpace),
+ std::move(message))));
return;
}
uint64_t space_required = safe_space_required.ValueOrDie();
@@ -739,10 +752,13 @@ void CacheStorageCache::BatchDidGetUsageAndQuota(
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, std::move(bad_message_callback));
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(std::move(callback),
- CacheStorageVerboseError::New(
- CacheStorageError::kErrorStorage,
- std::move(message))));
+ FROM_HERE,
+ base::BindOnce(
+ std::move(callback),
+ CacheStorageVerboseError::New(
+ MakeErrorStorage(
+ ErrorStorageType::kBatchDidGetUsageAndQuotaInvalidSpace),
+ std::move(message))));
return;
}
if (status_code != blink::mojom::QuotaStatusCode::kOk ||
@@ -793,7 +809,8 @@ void CacheStorageCache::BatchDidGetUsageAndQuota(
NOTREACHED();
// TODO(nhiroki): This should return "TypeError".
// http://crbug.com/425505
- completion_callback.Run(CacheStorageError::kErrorStorage);
+ completion_callback.Run(MakeErrorStorage(
+ ErrorStorageType::kBatchDidGetUsageAndQuotaUndefinedOp));
break;
}
}
@@ -827,7 +844,8 @@ void CacheStorageCache::Keys(std::unique_ptr<ServiceWorkerFetchRequest> request,
blink::mojom::QueryParamsPtr options,
RequestsCallback callback) {
if (backend_state_ == BACKEND_CLOSED) {
- std::move(callback).Run(CacheStorageError::kErrorStorage, nullptr);
+ std::move(callback).Run(
+ MakeErrorStorage(ErrorStorageType::kKeysBackendClosed), nullptr);
return;
}
@@ -911,7 +929,7 @@ CacheStorageCache::CacheStorageCache(
cache_observer_(nullptr),
memory_only_(path.empty()),
weak_ptr_factory_(this) {
- DCHECK(!origin_.unique());
+ DCHECK(!origin_.opaque());
DCHECK(quota_manager_proxy_.get());
DCHECK(cache_padding_key_.get());
@@ -933,11 +951,13 @@ void CacheStorageCache::QueryCache(
QUERY_CACHE_ENTRIES | QUERY_CACHE_RESPONSES_WITH_BODIES,
query_types & (QUERY_CACHE_ENTRIES | QUERY_CACHE_RESPONSES_WITH_BODIES));
if (backend_state_ == BACKEND_CLOSED) {
- std::move(callback).Run(CacheStorageError::kErrorStorage, nullptr);
+ std::move(callback).Run(
+ MakeErrorStorage(ErrorStorageType::kQueryCacheBackendClosed), nullptr);
return;
}
- if ((!options || !options->ignore_method) && request &&
+ if (owner_ != CacheStorageOwner::kBackgroundFetch &&
+ (!options || !options->ignore_method) && request &&
!request->method.empty() && request->method != "GET") {
std::move(callback).Run(CacheStorageError::kSuccess,
std::make_unique<QueryCacheResults>());
@@ -1025,7 +1045,7 @@ void CacheStorageCache::QueryCacheFilterEntry(
if (rv < 0) {
std::move(query_cache_context->callback)
- .Run(CacheStorageError::kErrorStorage,
+ .Run(MakeErrorStorage(ErrorStorageType::kQueryCacheFilterEntryFailed),
std::move(query_cache_context->matches));
return;
}
@@ -1127,7 +1147,9 @@ void CacheStorageCache::QueryCacheDidReadMetadata(
if (!blob_storage_context_) {
std::move(query_cache_context->callback)
- .Run(CacheStorageError::kErrorStorage, nullptr);
+ .Run(MakeErrorStorage(
+ ErrorStorageType::kQueryCacheDidReadMetadataNullBlobContext),
+ nullptr);
return;
}
@@ -1214,8 +1236,9 @@ void CacheStorageCache::MatchAllImpl(
ResponsesCallback callback) {
DCHECK_NE(BACKEND_UNINITIALIZED, backend_state_);
if (backend_state_ != BACKEND_OPEN) {
- std::move(callback).Run(CacheStorageError::kErrorStorage,
- std::vector<blink::mojom::FetchAPIResponsePtr>());
+ std::move(callback).Run(
+ MakeErrorStorage(ErrorStorageType::kStorageMatchAllBackendClosed),
+ std::vector<blink::mojom::FetchAPIResponsePtr>());
return;
}
@@ -1277,7 +1300,8 @@ void CacheStorageCache::WriteSideDataImpl(ErrorCallback callback,
int buf_len) {
DCHECK_NE(BACKEND_UNINITIALIZED, backend_state_);
if (backend_state_ != BACKEND_OPEN) {
- std::move(callback).Run(CacheStorageError::kErrorStorage);
+ std::move(callback).Run(
+ MakeErrorStorage(ErrorStorageType::kWriteSideDataImplBackendClosed));
return;
}
@@ -1405,19 +1429,25 @@ void CacheStorageCache::Put(std::unique_ptr<ServiceWorkerFetchRequest> request,
DCHECK(BACKEND_OPEN == backend_state_ || initializing_);
blink::mojom::BlobPtr blob;
+ uint64_t blob_size = blink::BlobUtils::kUnknownSize;
blink::mojom::BlobPtr side_data_blob;
+ uint64_t side_data_blob_size = blink::BlobUtils::kUnknownSize;
- if (response->blob)
+ if (response->blob) {
blob.Bind(std::move(response->blob->blob));
- if (response->side_data_blob)
+ blob_size = response->blob->size;
+ }
+ if (response->side_data_blob) {
side_data_blob.Bind(std::move(response->side_data_blob->blob));
+ side_data_blob_size = response->side_data_blob->size;
+ }
UMA_HISTOGRAM_ENUMERATION("ServiceWorkerCache.Cache.AllWritesResponseType",
response->response_type);
auto put_context = std::make_unique<PutContext>(
- std::move(request), std::move(response), std::move(blob),
- std::move(side_data_blob),
+ std::move(request), std::move(response), std::move(blob), blob_size,
+ std::move(side_data_blob), side_data_blob_size,
scheduler_->WrapCallbackToRunNext(std::move(callback)));
scheduler_->ScheduleOperation(base::BindOnce(&CacheStorageCache::PutImpl,
@@ -1428,7 +1458,8 @@ void CacheStorageCache::Put(std::unique_ptr<ServiceWorkerFetchRequest> request,
void CacheStorageCache::PutImpl(std::unique_ptr<PutContext> put_context) {
DCHECK_NE(BACKEND_UNINITIALIZED, backend_state_);
if (backend_state_ != BACKEND_OPEN) {
- std::move(put_context->callback).Run(CacheStorageError::kErrorStorage);
+ std::move(put_context->callback)
+ .Run(MakeErrorStorage(ErrorStorageType::kPutImplBackendClosed));
return;
}
@@ -1454,7 +1485,9 @@ void CacheStorageCache::PutDidDeleteEntry(
std::unique_ptr<PutContext> put_context,
CacheStorageError error) {
if (backend_state_ != BACKEND_OPEN) {
- std::move(put_context->callback).Run(CacheStorageError::kErrorStorage);
+ std::move(put_context->callback)
+ .Run(MakeErrorStorage(
+ ErrorStorageType::kPutDidDeleteEntryBackendClosed));
return;
}
@@ -1530,12 +1563,13 @@ void CacheStorageCache::PutDidCreateEntry(
std::unique_ptr<std::string> serialized(new std::string());
if (!metadata.SerializeToString(serialized.get())) {
- std::move(put_context->callback).Run(CacheStorageError::kErrorStorage);
+ std::move(put_context->callback)
+ .Run(MakeErrorStorage(ErrorStorageType::kMetadataSerializationFailed));
return;
}
- scoped_refptr<net::StringIOBuffer> buffer(
- new net::StringIOBuffer(std::move(serialized)));
+ scoped_refptr<net::StringIOBuffer> buffer =
+ base::MakeRefCounted<net::StringIOBuffer>(std::move(serialized));
// Get a temporary copy of the entry pointer before passing it in base::Bind.
disk_cache::Entry* temp_entry_ptr = put_context->cache_entry.get();
@@ -1560,7 +1594,8 @@ void CacheStorageCache::PutDidWriteHeaders(
int rv) {
if (rv != expected_bytes) {
put_context->cache_entry->Doom();
- std::move(put_context->callback).Run(CacheStorageError::kErrorStorage);
+ std::move(put_context->callback)
+ .Run(MakeErrorStorage(ErrorStorageType::kPutDidWriteHeadersWrongBytes));
return;
}
@@ -1594,6 +1629,10 @@ void CacheStorageCache::PutWriteBlobToCache(
: std::move(put_context->side_data_blob);
DCHECK(blob);
+ int64_t blob_size = disk_cache_body_index == INDEX_RESPONSE_BODY
+ ? put_context->blob_size
+ : put_context->side_data_blob_size;
+
disk_cache::ScopedEntryPtr entry(std::move(put_context->cache_entry));
put_context->cache_entry = nullptr;
@@ -1603,7 +1642,7 @@ void CacheStorageCache::PutWriteBlobToCache(
active_blob_to_disk_cache_writers_.Add(std::move(blob_to_cache));
blob_to_cache_raw->StreamBlobToCache(
- std::move(entry), disk_cache_body_index, std::move(blob),
+ std::move(entry), disk_cache_body_index, std::move(blob), blob_size,
base::BindOnce(&CacheStorageCache::PutDidWriteBlobToCache,
weak_ptr_factory_.GetWeakPtr(), std::move(put_context),
blob_to_cache_key));
@@ -1621,7 +1660,8 @@ void CacheStorageCache::PutDidWriteBlobToCache(
if (!success) {
put_context->cache_entry->Doom();
- std::move(put_context->callback).Run(CacheStorageError::kErrorStorage);
+ std::move(put_context->callback)
+ .Run(MakeErrorStorage(ErrorStorageType::kPutDidWriteBlobToCacheFailed));
return;
}
@@ -1636,19 +1676,19 @@ void CacheStorageCache::PutDidWriteBlobToCache(
void CacheStorageCache::CalculateCacheSizePadding(
SizePaddingCallback got_sizes_callback) {
- net::CompletionCallback got_size_callback =
+ net::Int64CompletionCallback got_size_callback =
base::AdaptCallbackForRepeating(base::BindOnce(
&CacheStorageCache::CalculateCacheSizePaddingGotSize,
weak_ptr_factory_.GetWeakPtr(), std::move(got_sizes_callback)));
- int rv = backend_->CalculateSizeOfAllEntries(got_size_callback);
+ int64_t rv = backend_->CalculateSizeOfAllEntries(got_size_callback);
if (rv != net::ERR_IO_PENDING)
std::move(got_size_callback).Run(rv);
}
void CacheStorageCache::CalculateCacheSizePaddingGotSize(
SizePaddingCallback callback,
- int cache_size) {
+ int64_t cache_size) {
// Enumerating entries is only done during cache initialization and only if
// necessary.
DCHECK_EQ(backend_state_, BACKEND_UNINITIALIZED);
@@ -1664,7 +1704,7 @@ void CacheStorageCache::CalculateCacheSizePaddingGotSize(
void CacheStorageCache::PaddingDidQueryCache(
SizePaddingCallback callback,
- int cache_size,
+ int64_t cache_size,
CacheStorageError error,
std::unique_ptr<QueryCacheResults> query_cache_results) {
int64_t cache_padding = 0;
@@ -1683,8 +1723,8 @@ void CacheStorageCache::PaddingDidQueryCache(
}
void CacheStorageCache::CalculateCacheSize(
- const net::CompletionCallback& callback) {
- int rv = backend_->CalculateSizeOfAllEntries(callback);
+ const net::Int64CompletionCallback& callback) {
+ int64_t rv = backend_->CalculateSizeOfAllEntries(callback);
if (rv != net::ERR_IO_PENDING)
callback.Run(rv);
}
@@ -1705,7 +1745,7 @@ void CacheStorageCache::UpdateCacheSize(base::OnceClosure callback) {
void CacheStorageCache::UpdateCacheSizeGotSize(
CacheStorageCacheHandle cache_handle,
base::OnceClosure callback,
- int current_cache_size) {
+ int64_t current_cache_size) {
DCHECK_NE(current_cache_size, CacheStorage::kSizeUnknown);
cache_size_ = current_cache_size;
int64_t size_delta = PaddedCacheSize() - last_reported_size_;
@@ -1747,7 +1787,8 @@ void CacheStorageCache::DeleteImpl(
ErrorCallback callback) {
DCHECK_NE(BACKEND_UNINITIALIZED, backend_state_);
if (backend_state_ != BACKEND_OPEN) {
- std::move(callback).Run(CacheStorageError::kErrorStorage);
+ std::move(callback).Run(
+ MakeErrorStorage(ErrorStorageType::kDeleteImplBackendClosed));
return;
}
@@ -1792,7 +1833,8 @@ void CacheStorageCache::KeysImpl(
RequestsCallback callback) {
DCHECK_NE(BACKEND_UNINITIALIZED, backend_state_);
if (backend_state_ != BACKEND_OPEN) {
- std::move(callback).Run(CacheStorageError::kErrorStorage, nullptr);
+ std::move(callback).Run(
+ MakeErrorStorage(ErrorStorageType::kKeysImplBackendClosed), nullptr);
return;
}
@@ -1862,6 +1904,11 @@ void CacheStorageCache::CreateBackend(ErrorCallback callback) {
// Use APP_CACHE as opposed to DISK_CACHE to prevent cache eviction.
net::CacheType cache_type = memory_only_ ? net::MEMORY_CACHE : net::APP_CACHE;
+ // The maximum size of each cache. Ultimately, cache size
+ // is controlled per-origin by the QuotaManager.
+ uint64_t max_bytes = memory_only_ ? std::numeric_limits<int>::max()
+ : std::numeric_limits<int64_t>::max();
+
std::unique_ptr<ScopedBackendPtr> backend_ptr(new ScopedBackendPtr());
// Temporary pointer so that backend_ptr can be Pass()'d in Bind below.
@@ -1874,7 +1921,7 @@ void CacheStorageCache::CreateBackend(ErrorCallback callback) {
std::move(backend_ptr)));
int rv = disk_cache::CreateCacheBackend(
- cache_type, net::CACHE_BACKEND_SIMPLE, path_, kMaxCacheBytes,
+ cache_type, net::CACHE_BACKEND_SIMPLE, path_, max_bytes,
false, /* force */
nullptr, backend,
base::BindOnce(&CacheStorageCache::DeleteBackendCompletedIO,
@@ -1889,7 +1936,8 @@ void CacheStorageCache::CreateBackendDidCreate(
std::unique_ptr<ScopedBackendPtr> backend_ptr,
int rv) {
if (rv != net::OK) {
- std::move(callback).Run(CacheStorageError::kErrorStorage);
+ std::move(callback).Run(
+ MakeErrorStorage(ErrorStorageType::kCreateBackendDidCreateFailed));
return;
}
@@ -1921,7 +1969,7 @@ void CacheStorageCache::InitDidCreateBackend(
auto calculate_size_callback =
base::AdaptCallbackForRepeating(std::move(callback));
- int rv = backend_->CalculateSizeOfAllEntries(base::BindOnce(
+ int64_t rv = backend_->CalculateSizeOfAllEntries(base::BindOnce(
&CacheStorageCache::InitGotCacheSize, weak_ptr_factory_.GetWeakPtr(),
calculate_size_callback, cache_create_error));
@@ -1932,7 +1980,7 @@ void CacheStorageCache::InitDidCreateBackend(
void CacheStorageCache::InitGotCacheSize(base::OnceClosure callback,
CacheStorageError cache_create_error,
- int cache_size) {
+ int64_t cache_size) {
if (cache_create_error != CacheStorageError::kSuccess) {
InitGotCacheSizeAndPadding(std::move(callback), cache_create_error, 0, 0);
return;
diff --git a/chromium/content/browser/cache_storage/cache_storage_cache.h b/chromium/content/browser/cache_storage/cache_storage_cache.h
index d0ab8ce63db..efcdca43ac1 100644
--- a/chromium/content/browser/cache_storage/cache_storage_cache.h
+++ b/chromium/content/browser/cache_storage/cache_storage_cache.h
@@ -391,7 +391,7 @@ class CONTENT_EXPORT CacheStorageCache {
void UpdateCacheSize(base::OnceClosure callback);
void UpdateCacheSizeGotSize(CacheStorageCacheHandle,
base::OnceClosure callback,
- int current_cache_size);
+ int64_t current_cache_size);
// Returns ERROR_NOT_FOUND if not found. Otherwise deletes and returns OK.
void Delete(blink::mojom::BatchOperationPtr operation,
@@ -429,22 +429,22 @@ class CONTENT_EXPORT CacheStorageCache {
// Calculate the size and padding of the cache.
void CalculateCacheSizePadding(SizePaddingCallback callback);
void CalculateCacheSizePaddingGotSize(SizePaddingCallback callback,
- int cache_size);
+ int64_t cache_size);
void PaddingDidQueryCache(
SizePaddingCallback callback,
- int cache_size,
+ int64_t cache_size,
blink::mojom::CacheStorageError error,
std::unique_ptr<QueryCacheResults> query_cache_results);
// Calculate the size (but not padding) of the cache.
- void CalculateCacheSize(const net::CompletionCallback& callback);
+ void CalculateCacheSize(const net::Int64CompletionCallback& callback);
void InitBackend();
void InitDidCreateBackend(base::OnceClosure callback,
blink::mojom::CacheStorageError cache_create_error);
void InitGotCacheSize(base::OnceClosure callback,
blink::mojom::CacheStorageError cache_create_error,
- int cache_size);
+ int64_t cache_size);
void InitGotCacheSizeAndPadding(
base::OnceClosure callback,
blink::mojom::CacheStorageError cache_create_error,
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 5578dd58900..55b20bc194e 100644
--- a/chromium/content/browser/cache_storage/cache_storage_cache_unittest.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_cache_unittest.cc
@@ -20,9 +20,11 @@
#include "base/run_loop.h"
#include "base/strings/string_split.h"
#include "base/test/bind_test_util.h"
+#include "base/test/metrics/histogram_tester.h"
#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/browser/cache_storage/cache_storage_histogram_utils.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"
@@ -60,7 +62,8 @@ namespace content {
namespace cache_storage_cache_unittest {
const char kTestData[] = "Hello World";
-const char kOrigin[] = "http://example.com";
+// TODO(crbug.com/889590): Use helper for url::Origin creation from string.
+const url::Origin kOrigin = url::Origin::Create(GURL("http://example.com"));
const char kCacheName[] = "test_cache";
const GURL kBodyUrl("http://example.com/body.html");
const GURL kBodyUrlWithQuery("http://example.com/body.html?query=test");
@@ -96,10 +99,10 @@ class DelayableBackend : public disk_cache::Backend {
return backend_->GetCacheType();
}
int32_t GetEntryCount() const override { return backend_->GetEntryCount(); }
- int OpenEntry(const std::string& key,
- net::RequestPriority request_priority,
- disk_cache::Entry** entry,
- CompletionOnceCallback callback) override {
+ net::Error OpenEntry(const std::string& key,
+ net::RequestPriority request_priority,
+ disk_cache::Entry** entry,
+ CompletionOnceCallback callback) override {
if (delay_open_entry_ && open_entry_callback_.is_null()) {
open_entry_callback_ = base::BindOnce(
&DelayableBackend::OpenEntryDelayedImpl, base::Unretained(this), key,
@@ -110,32 +113,33 @@ class DelayableBackend : public disk_cache::Backend {
std::move(callback));
}
- int CreateEntry(const std::string& key,
- net::RequestPriority request_priority,
- disk_cache::Entry** entry,
- CompletionOnceCallback callback) override {
+ net::Error CreateEntry(const std::string& key,
+ net::RequestPriority request_priority,
+ disk_cache::Entry** entry,
+ CompletionOnceCallback callback) override {
return backend_->CreateEntry(key, request_priority, entry,
std::move(callback));
}
- int DoomEntry(const std::string& key,
- net::RequestPriority request_priority,
- CompletionOnceCallback callback) override {
+ net::Error DoomEntry(const std::string& key,
+ net::RequestPriority request_priority,
+ CompletionOnceCallback callback) override {
return backend_->DoomEntry(key, request_priority, std::move(callback));
}
- int DoomAllEntries(CompletionOnceCallback callback) override {
+ net::Error DoomAllEntries(CompletionOnceCallback callback) override {
return backend_->DoomAllEntries(std::move(callback));
}
- int DoomEntriesBetween(base::Time initial_time,
- base::Time end_time,
- CompletionOnceCallback callback) override {
+ net::Error DoomEntriesBetween(base::Time initial_time,
+ base::Time end_time,
+ CompletionOnceCallback callback) override {
return backend_->DoomEntriesBetween(initial_time, end_time,
std::move(callback));
}
- int DoomEntriesSince(base::Time initial_time,
- CompletionOnceCallback callback) override {
+ net::Error DoomEntriesSince(base::Time initial_time,
+ CompletionOnceCallback callback) override {
return backend_->DoomEntriesSince(initial_time, std::move(callback));
}
- int CalculateSizeOfAllEntries(CompletionOnceCallback callback) override {
+ int64_t CalculateSizeOfAllEntries(
+ Int64CompletionOnceCallback callback) override {
return backend_->CalculateSizeOfAllEntries(std::move(callback));
}
std::unique_ptr<Iterator> CreateIterator() override {
@@ -384,9 +388,8 @@ class CacheStorageCacheTest : public testing::Test {
mock_quota_manager_ = new MockQuotaManager(
is_incognito, temp_dir_path, base::ThreadTaskRunnerHandle::Get().get(),
quota_policy_.get());
- mock_quota_manager_->SetQuota(GURL(kOrigin),
- blink::mojom::StorageType::kTemporary,
- 1024 * 1024 * 100);
+ mock_quota_manager_->SetQuota(
+ kOrigin, blink::mojom::StorageType::kTemporary, 1024 * 1024 * 100);
quota_manager_proxy_ = new MockQuotaManagerProxy(
mock_quota_manager_.get(), base::ThreadTaskRunnerHandle::Get().get());
@@ -412,8 +415,7 @@ class CacheStorageCacheTest : public testing::Test {
MakeRequest(&blob_ptr_));
cache_ = std::make_unique<TestCacheStorageCache>(
- url::Origin::Create(GURL(kOrigin)), kCacheName, temp_dir_path,
- nullptr /* CacheStorage */,
+ kOrigin, kCacheName, temp_dir_path, nullptr /* CacheStorage */,
BrowserContext::GetDefaultStoragePartition(&browser_context_)
->GetURLRequestContext(),
quota_manager_proxy_, blob_storage_context->context()->AsWeakPtr());
@@ -920,6 +922,8 @@ TEST_P(CacheStorageCacheTestP, PutBodyDropBlobRef) {
}
TEST_P(CacheStorageCacheTestP, PutBadMessage) {
+ base::HistogramTester histogram_tester;
+
// Two unique puts that will collectively overflow unit64_t size of the
// batch operation.
blink::mojom::BatchOperationPtr operation1 =
@@ -938,6 +942,8 @@ TEST_P(CacheStorageCacheTestP, PutBadMessage) {
operations.push_back(std::move(operation2));
EXPECT_EQ(CacheStorageError::kErrorStorage,
BatchOperation(std::move(operations)));
+ histogram_tester.ExpectBucketCount("ServiceWorkerCache.ErrorStorageType",
+ ErrorStorageType::kBatchInvalidSpace, 1);
EXPECT_EQ("CSDH_UNEXPECTED_OPERATION", bad_message_reason_);
EXPECT_FALSE(Match(body_request_));
@@ -1532,8 +1538,7 @@ TEST_P(CacheStorageCacheTestP, PutWithSideData) {
}
TEST_P(CacheStorageCacheTestP, PutWithSideData_QuotaExceeded) {
- mock_quota_manager_->SetQuota(GURL(kOrigin),
- blink::mojom::StorageType::kTemporary,
+ mock_quota_manager_->SetQuota(kOrigin, blink::mojom::StorageType::kTemporary,
expected_blob_data_.size() - 1);
blink::mojom::FetchAPIResponsePtr response = CreateBlobBodyResponse();
const std::string expected_side_data = "SideData";
@@ -1548,8 +1553,7 @@ TEST_P(CacheStorageCacheTestP, PutWithSideData_QuotaExceeded) {
}
TEST_P(CacheStorageCacheTestP, PutWithSideData_QuotaExceededSkipSideData) {
- mock_quota_manager_->SetQuota(GURL(kOrigin),
- blink::mojom::StorageType::kTemporary,
+ mock_quota_manager_->SetQuota(kOrigin, blink::mojom::StorageType::kTemporary,
expected_blob_data_.size());
blink::mojom::FetchAPIResponsePtr response = CreateBlobBodyResponse();
const std::string expected_side_data = "SideData";
@@ -1570,6 +1574,7 @@ TEST_P(CacheStorageCacheTestP, PutWithSideData_QuotaExceededSkipSideData) {
}
TEST_P(CacheStorageCacheTestP, PutWithSideData_BadMessage) {
+ base::HistogramTester histogram_tester;
blink::mojom::FetchAPIResponsePtr response = CreateBlobBodyResponse();
const std::string expected_side_data = "SideData";
@@ -1589,6 +1594,9 @@ TEST_P(CacheStorageCacheTestP, PutWithSideData_BadMessage) {
operations.emplace_back(std::move(operation));
EXPECT_EQ(CacheStorageError::kErrorStorage,
BatchOperation(std::move(operations)));
+ histogram_tester.ExpectBucketCount(
+ "ServiceWorkerCache.ErrorStorageType",
+ ErrorStorageType::kBatchDidGetUsageAndQuotaInvalidSpace, 1);
EXPECT_EQ("CSDH_UNEXPECTED_OPERATION", bad_message_reason_);
EXPECT_FALSE(Match(body_request_));
@@ -1601,8 +1609,8 @@ TEST_P(CacheStorageCacheTestP, WriteSideData) {
EXPECT_TRUE(Put(body_request_, std::move(response)));
const std::string expected_side_data1 = "SideDataSample";
- scoped_refptr<net::IOBuffer> buffer1(
- new net::StringIOBuffer(expected_side_data1));
+ scoped_refptr<net::IOBuffer> buffer1 =
+ base::MakeRefCounted<net::StringIOBuffer>(expected_side_data1);
EXPECT_TRUE(WriteSideData(body_request_.url, response_time, buffer1,
expected_side_data1.length()));
@@ -1613,8 +1621,8 @@ TEST_P(CacheStorageCacheTestP, WriteSideData) {
EXPECT_TRUE(ResponseSideDataEqual(expected_side_data1, blob1.get()));
const std::string expected_side_data2 = "New data";
- scoped_refptr<net::IOBuffer> buffer2(
- new net::StringIOBuffer(expected_side_data2));
+ scoped_refptr<net::IOBuffer> buffer2 =
+ base::MakeRefCounted<net::StringIOBuffer>(expected_side_data2);
EXPECT_TRUE(WriteSideData(body_request_.url, response_time, buffer2,
expected_side_data2.length()));
EXPECT_TRUE(Match(body_request_));
@@ -1627,15 +1635,16 @@ TEST_P(CacheStorageCacheTestP, WriteSideData) {
}
TEST_P(CacheStorageCacheTestP, WriteSideData_QuotaExceeded) {
- mock_quota_manager_->SetQuota(
- GURL(kOrigin), blink::mojom::StorageType::kTemporary, 1024 * 1023);
+ mock_quota_manager_->SetQuota(kOrigin, blink::mojom::StorageType::kTemporary,
+ 1024 * 1023);
base::Time response_time(base::Time::Now());
blink::mojom::FetchAPIResponsePtr response(CreateNoBodyResponse());
response->response_time = response_time;
EXPECT_TRUE(Put(no_body_request_, std::move(response)));
const size_t kSize = 1024 * 1024;
- scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize));
+ scoped_refptr<net::IOBuffer> buffer =
+ base::MakeRefCounted<net::IOBuffer>(kSize);
memset(buffer->data(), 0, kSize);
EXPECT_FALSE(
WriteSideData(no_body_request_.url, response_time, buffer, kSize));
@@ -1655,7 +1664,8 @@ TEST_P(CacheStorageCacheTestP, WriteSideData_QuotaManagerModified) {
EXPECT_EQ(1, quota_manager_proxy_->notify_storage_modified_count());
const size_t kSize = 10;
- scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize));
+ scoped_refptr<net::IOBuffer> buffer =
+ base::MakeRefCounted<net::IOBuffer>(kSize);
memset(buffer->data(), 0, kSize);
EXPECT_TRUE(
WriteSideData(no_body_request_.url, response_time, buffer, kSize));
@@ -1671,7 +1681,8 @@ TEST_P(CacheStorageCacheTestP, WriteSideData_DifferentTimeStamp) {
EXPECT_TRUE(Put(no_body_request_, std::move(response)));
const size_t kSize = 10;
- scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize));
+ scoped_refptr<net::IOBuffer> buffer =
+ base::MakeRefCounted<net::IOBuffer>(kSize);
memset(buffer->data(), 0, kSize);
EXPECT_FALSE(WriteSideData(no_body_request_.url,
response_time + base::TimeDelta::FromSeconds(1),
@@ -1682,7 +1693,8 @@ TEST_P(CacheStorageCacheTestP, WriteSideData_DifferentTimeStamp) {
TEST_P(CacheStorageCacheTestP, WriteSideData_NotFound) {
const size_t kSize = 10;
- scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize));
+ scoped_refptr<net::IOBuffer> buffer =
+ base::MakeRefCounted<net::IOBuffer>(kSize);
memset(buffer->data(), 0, kSize);
EXPECT_FALSE(WriteSideData(GURL("http://www.example.com/not_exist"),
base::Time::Now(), buffer, kSize));
@@ -1731,8 +1743,8 @@ TEST_P(CacheStorageCacheTestP, QuotaManagerModified) {
}
TEST_P(CacheStorageCacheTestP, PutObeysQuotaLimits) {
- mock_quota_manager_->SetQuota(GURL(kOrigin),
- blink::mojom::StorageType::kTemporary, 0);
+ mock_quota_manager_->SetQuota(kOrigin, blink::mojom::StorageType::kTemporary,
+ 0);
EXPECT_FALSE(Put(body_request_, CreateBlobBodyResponse()));
EXPECT_EQ(CacheStorageError::kErrorQuotaExceeded, callback_error_);
}
@@ -1769,8 +1781,8 @@ TEST_F(CacheStorageCacheTest, VerifyOpaqueSizePadding) {
// Now write some side data to that cache.
const std::string expected_side_data(2048, 'X');
- scoped_refptr<net::IOBuffer> side_data_buffer(
- new net::StringIOBuffer(expected_side_data));
+ scoped_refptr<net::IOBuffer> side_data_buffer =
+ base::MakeRefCounted<net::StringIOBuffer>(expected_side_data);
EXPECT_TRUE(WriteSideData(non_opaque_request.url, response_time,
side_data_buffer, expected_side_data.length()));
int64_t unpadded_total_resource_size = Size();
@@ -1813,8 +1825,8 @@ TEST_F(CacheStorageCacheTest, VerifyOpaqueSizePadding) {
// Now reset opaque side data back to zero.
const std::string expected_side_data2 = "";
- scoped_refptr<net::IOBuffer> buffer2(
- new net::StringIOBuffer(expected_side_data2));
+ scoped_refptr<net::IOBuffer> buffer2 =
+ base::MakeRefCounted<net::StringIOBuffer>(expected_side_data2);
EXPECT_TRUE(WriteSideData(opaque_request.url, response_time, buffer2,
expected_side_data2.length()));
EXPECT_EQ(size_after_opaque_put, Size());
@@ -1835,8 +1847,8 @@ TEST_F(CacheStorageCacheTest, TestDifferentOpaqueSideDataSizes) {
int64_t opaque_cache_size_no_side_data = Size();
const std::string small_side_data(1024, 'X');
- scoped_refptr<net::IOBuffer> buffer1(
- new net::StringIOBuffer(small_side_data));
+ scoped_refptr<net::IOBuffer> buffer1 =
+ base::MakeRefCounted<net::StringIOBuffer>(small_side_data);
EXPECT_TRUE(WriteSideData(request.url, response_time, buffer1,
small_side_data.length()));
int64_t opaque_cache_size_with_side_data = Size();
@@ -1846,8 +1858,8 @@ TEST_F(CacheStorageCacheTest, TestDifferentOpaqueSideDataSizes) {
// at all.
const std::string large_side_data(2048, 'X');
EXPECT_NE(large_side_data.length(), small_side_data.length());
- scoped_refptr<net::IOBuffer> buffer2(
- new net::StringIOBuffer(large_side_data));
+ scoped_refptr<net::IOBuffer> buffer2 =
+ base::MakeRefCounted<net::StringIOBuffer>(large_side_data);
EXPECT_TRUE(WriteSideData(request.url, response_time, buffer2,
large_side_data.length()));
int side_data_delta = large_side_data.length() - small_side_data.length();
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 c61cf8c1d81..ffc6bc04f4b 100644
--- a/chromium/content/browser/cache_storage/cache_storage_context_impl.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_context_impl.cc
@@ -11,6 +11,7 @@
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
#include "content/browser/cache_storage/cache_storage_manager.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "net/url_request/url_request_context_getter.h"
#include "storage/browser/blob/blob_storage_context.h"
@@ -49,8 +50,8 @@ void CacheStorageContextImpl::Init(
return;
}
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&CacheStorageContextImpl::CreateCacheStorageManager, this,
user_data_directory, cache_task_runner,
std::move(quota_manager_proxy)));
@@ -59,8 +60,8 @@ void CacheStorageContextImpl::Init(
void CacheStorageContextImpl::Shutdown() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&CacheStorageContextImpl::ShutdownOnIO, this));
}
@@ -85,8 +86,8 @@ void CacheStorageContextImpl::GetAllOriginsInfo(
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (!cache_manager_) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(callback, std::vector<CacheStorageUsageInfo>()));
return;
}
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 5f50ea600d4..9394792d4bb 100644
--- a/chromium/content/browser/cache_storage/cache_storage_dispatcher_host.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_dispatcher_host.cc
@@ -13,6 +13,7 @@
#include "base/optional.h"
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/task/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
@@ -20,6 +21,7 @@
#include "content/browser/cache_storage/cache_storage_cache_handle.h"
#include "content/browser/cache_storage/cache_storage_context_impl.h"
#include "content/browser/cache_storage/cache_storage_manager.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/common/origin_util.h"
@@ -28,7 +30,6 @@
#include "url/gurl.h"
#include "url/origin.h"
-
namespace content {
namespace {
@@ -40,7 +41,7 @@ const int32_t kCachePreservationSeconds = 5;
// TODO(lucmult): Check this before binding.
bool OriginCanAccessCacheStorage(const url::Origin& origin) {
- return !origin.unique() && IsOriginSecure(origin.GetURL());
+ return !origin.opaque() && IsOriginSecure(origin.GetURL());
}
void StopPreservingCache(CacheStorageCacheHandle cache_handle) {}
@@ -211,8 +212,8 @@ CacheStorageDispatcherHost::~CacheStorageDispatcherHost() = default;
void CacheStorageDispatcherHost::Init(CacheStorageContextImpl* context) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&CacheStorageDispatcherHost::CreateCacheListener,
base::RetainedRef(this), base::RetainedRef(context)));
}
diff --git a/chromium/content/browser/cache_storage/cache_storage_histogram_utils.cc b/chromium/content/browser/cache_storage/cache_storage_histogram_utils.cc
new file mode 100644
index 00000000000..89d8aae6792
--- /dev/null
+++ b/chromium/content/browser/cache_storage/cache_storage_histogram_utils.cc
@@ -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.
+
+#include "content/browser/cache_storage/cache_storage_histogram_utils.h"
+
+namespace content {
+
+blink::mojom::CacheStorageError MakeErrorStorage(ErrorStorageType type) {
+ UMA_HISTOGRAM_ENUMERATION("ServiceWorkerCache.ErrorStorageType", type);
+ return blink::mojom::CacheStorageError::kErrorStorage;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/cache_storage/cache_storage_histogram_macros.h b/chromium/content/browser/cache_storage/cache_storage_histogram_utils.h
index 92b0d87e03b..3743d0d3e35 100644
--- a/chromium/content/browser/cache_storage/cache_storage_histogram_macros.h
+++ b/chromium/content/browser/cache_storage/cache_storage_histogram_utils.h
@@ -2,14 +2,45 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_BROWSER_CACHE_STORAGE_CACHE_STORAGE_HISTOGRAM_MACROS_H_
-#define CONTENT_BROWSER_CACHE_STORAGE_CACHE_STORAGE_HISTOGRAM_MACROS_H_
+#ifndef CONTENT_BROWSER_CACHE_STORAGE_CACHE_STORAGE_HISTOGRAM_UTILS_H_
+#define CONTENT_BROWSER_CACHE_STORAGE_CACHE_STORAGE_HISTOGRAM_UTILS_H_
#include "base/metrics/histogram_macros.h"
#include "content/browser/cache_storage/cache_storage_scheduler_client.h"
+#include "third_party/blink/public/platform/modules/cache_storage/cache_storage.mojom.h"
namespace content {
+// This enum gets recorded as a histogram. Do not renumber the values.
+enum class ErrorStorageType {
+ kDidCreateNullCache = 0,
+ kDeleteCacheFailed = 1,
+ kMatchBackendClosed = 2,
+ kMatchAllBackendClosed = 3,
+ kWriteSideDataBackendClosed = 4,
+ kBatchBackendClosed = 5,
+ kBatchInvalidSpace = 6,
+ kBatchDidGetUsageAndQuotaInvalidSpace = 7,
+ kBatchDidGetUsageAndQuotaUndefinedOp = 8,
+ kKeysBackendClosed = 9,
+ kQueryCacheBackendClosed = 10,
+ kQueryCacheFilterEntryFailed = 11,
+ kQueryCacheDidReadMetadataNullBlobContext = 12,
+ kStorageMatchAllBackendClosed = 13,
+ kWriteSideDataImplBackendClosed = 14,
+ kPutImplBackendClosed = 15,
+ kPutDidDeleteEntryBackendClosed = 16,
+ kMetadataSerializationFailed = 17,
+ kPutDidWriteHeadersWrongBytes = 18,
+ kPutDidWriteBlobToCacheFailed = 19,
+ kDeleteImplBackendClosed = 20,
+ kKeysImplBackendClosed = 21,
+ kCreateBackendDidCreateFailed = 22,
+ kMaxValue = kCreateBackendDidCreateFailed,
+};
+
+blink::mojom::CacheStorageError MakeErrorStorage(ErrorStorageType type);
+
// Metrics to make it easier to write histograms for several clients.
#define CACHE_STORAGE_SCHEDULER_UMA_THUNK(uma_type, args) \
UMA_HISTOGRAM_##uma_type args
@@ -40,4 +71,4 @@ namespace content {
} // namespace content
-#endif // CONTENT_BROWSER_CACHE_STORAGE_CACHE_STORAGE_HISTOGRAM_MACROS_H_
+#endif // CONTENT_BROWSER_CACHE_STORAGE_CACHE_STORAGE_HISTOGRAM_UTILS_H_
diff --git a/chromium/content/browser/cache_storage/cache_storage_manager.cc b/chromium/content/browser/cache_storage/cache_storage_manager.cc
index 6eab90f4d1e..2b5c01e2362 100644
--- a/chromium/content/browser/cache_storage/cache_storage_manager.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_manager.cc
@@ -431,7 +431,7 @@ void CacheStorageManager::DeleteOriginData(
// Create the CacheStorage for the origin if it hasn't been loaded yet.
FindOrCreateCacheStorage(origin, owner);
- CacheStorageMap::iterator it = cache_storage_map_.find({origin, owner});
+ auto it = cache_storage_map_.find({origin, owner});
DCHECK(it != cache_storage_map_.end());
CacheStorage* cache_storage = it->second.release();
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 c9aa9486f41..9c9f451e123 100644
--- a/chromium/content/browser/cache_storage/cache_storage_manager_unittest.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_manager_unittest.cc
@@ -259,9 +259,9 @@ class CacheStorageManagerTest : public testing::Test {
mock_quota_manager_ = new MockQuotaManager(
MemoryOnly(), temp_dir_path, base::ThreadTaskRunnerHandle::Get().get(),
quota_policy_.get());
- mock_quota_manager_->SetQuota(origin1_.GetURL(), StorageType::kTemporary,
+ mock_quota_manager_->SetQuota(origin1_, StorageType::kTemporary,
1024 * 1024 * 100);
- mock_quota_manager_->SetQuota(origin2_.GetURL(), StorageType::kTemporary,
+ mock_quota_manager_->SetQuota(origin2_, StorageType::kTemporary,
1024 * 1024 * 100);
quota_manager_proxy_ = new MockCacheStorageQuotaManagerProxy(
diff --git a/chromium/content/browser/cache_storage/cache_storage_operation.cc b/chromium/content/browser/cache_storage/cache_storage_operation.cc
index 89502144f0b..38ea200db9e 100644
--- a/chromium/content/browser/cache_storage/cache_storage_operation.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_operation.cc
@@ -4,7 +4,7 @@
#include "content/browser/cache_storage/cache_storage_operation.h"
-#include "content/browser/cache_storage/cache_storage_histogram_macros.h"
+#include "content/browser/cache_storage/cache_storage_histogram_utils.h"
namespace content {
diff --git a/chromium/content/browser/cache_storage/cache_storage_scheduler.cc b/chromium/content/browser/cache_storage/cache_storage_scheduler.cc
index d28492ff53d..28215800d27 100644
--- a/chromium/content/browser/cache_storage/cache_storage_scheduler.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_scheduler.cc
@@ -12,7 +12,7 @@
#include "base/metrics/histogram_macros.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
-#include "content/browser/cache_storage/cache_storage_histogram_macros.h"
+#include "content/browser/cache_storage/cache_storage_histogram_utils.h"
#include "content/browser/cache_storage/cache_storage_operation.h"
namespace content {
diff --git a/chromium/content/browser/child_process_launcher_helper.cc b/chromium/content/browser/child_process_launcher_helper.cc
index 6e0eebe2361..2f75fff5eed 100644
--- a/chromium/content/browser/child_process_launcher_helper.cc
+++ b/chromium/content/browser/child_process_launcher_helper.cc
@@ -13,6 +13,7 @@
#include "base/task/single_thread_task_runner_thread_mode.h"
#include "base/task/task_traits.h"
#include "content/browser/child_process_launcher.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/child_process_launcher_utils.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/sandboxed_process_launcher_delegate.h"
@@ -151,8 +152,8 @@ void ChildProcessLauncherHelper::PostLaunchOnLauncherThread(
}
}
- BrowserThread::PostTask(
- client_thread_id_, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {client_thread_id_},
base::BindOnce(&ChildProcessLauncherHelper::PostLaunchOnClientThread,
this, std::move(process), launch_result));
}
diff --git a/chromium/content/browser/child_process_launcher_helper_android.cc b/chromium/content/browser/child_process_launcher_helper_android.cc
index 83be7e6bbb4..5118e3622aa 100644
--- a/chromium/content/browser/child_process_launcher_helper_android.cc
+++ b/chromium/content/browser/child_process_launcher_helper_android.cc
@@ -10,11 +10,13 @@
#include "base/i18n/icu_util.h"
#include "base/logging.h"
#include "base/metrics/field_trial.h"
+#include "base/task/post_task.h"
#include "content/browser/child_process_launcher.h"
#include "content/browser/child_process_launcher_helper.h"
#include "content/browser/child_process_launcher_helper_posix.h"
#include "content/browser/posix_file_descriptor_info_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/child_process_launcher_utils.h"
#include "content/public/browser/render_process_host.h"
@@ -134,8 +136,8 @@ ChildProcessLauncherHelper::LaunchProcessOnLauncherThread(
java_peer_.Reset(Java_ChildProcessLauncherHelperImpl_createAndStart(
env, reinterpret_cast<intptr_t>(this), j_argv, j_file_infos));
AddRef(); // Balanced by OnChildProcessStarted.
- BrowserThread::PostTask(
- client_thread_id_, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {client_thread_id_},
base::Bind(
&ChildProcessLauncherHelper::set_java_peer_available_on_client_thread,
this));
diff --git a/chromium/content/browser/child_process_launcher_helper_mac.cc b/chromium/content/browser/child_process_launcher_helper_mac.cc
index c1b02ef4855..60a5a647015 100644
--- a/chromium/content/browser/child_process_launcher_helper_mac.cc
+++ b/chromium/content/browser/child_process_launcher_helper_mac.cc
@@ -73,34 +73,8 @@ bool ChildProcessLauncherHelper::BeforeLaunchOnLauncherThread(
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 use_v2 = base::FeatureList::IsEnabled(features::kMacV2Sandbox);
-
- switch (sandbox_type) {
- case service_manager::SANDBOX_TYPE_NO_SANDBOX:
- break;
- case service_manager::SANDBOX_TYPE_CDM:
- case service_manager::SANDBOX_TYPE_PPAPI:
- case service_manager::SANDBOX_TYPE_RENDERER:
- case service_manager::SANDBOX_TYPE_UTILITY:
- case service_manager::SANDBOX_TYPE_NACL_LOADER:
- case service_manager::SANDBOX_TYPE_PDF_COMPOSITOR:
- case service_manager::SANDBOX_TYPE_PROFILING:
- // If the feature experiment is enabled and this process type supports
- // the v2 sandbox, use it.
- use_v2 &= true;
- break;
- case service_manager::SANDBOX_TYPE_AUDIO:
- // The audio service only exists with the v2 sandbox.
- use_v2 |= true;
- break;
- default:
- // This is a 'break' because the V2 sandbox is not enabled for all
- // processes yet, and so there are sandbox types like NETWORK that
- // should not be run under the V2 sandbox.
- use_v2 = false;
- break;
- }
+ bool use_v2 =
+ !no_sandbox && (sandbox_type != service_manager::SANDBOX_TYPE_GPU);
if (use_v2 && !no_sandbox) {
// Generate the profile string.
@@ -133,8 +107,16 @@ bool ChildProcessLauncherHelper::BeforeLaunchOnLauncherThread(
case service_manager::SANDBOX_TYPE_PROFILING:
profile += service_manager::kSeatbeltPolicyString_utility;
break;
- default:
+ case service_manager::SANDBOX_TYPE_NETWORK:
+ // Put a separate CHECK() for the network sandbox so that crash reports
+ // will show which invalid case was hit.
CHECK(false);
+ break;
+ case service_manager::SANDBOX_TYPE_INVALID:
+ case service_manager::SANDBOX_TYPE_FIRST_TYPE:
+ case service_manager::SANDBOX_TYPE_AFTER_LAST_TYPE:
+ CHECK(false);
+ break;
}
// Disable os logging to com.apple.diagnosticd which is a performance
diff --git a/chromium/content/browser/child_process_security_policy_browsertest.cc b/chromium/content/browser/child_process_security_policy_browsertest.cc
index a308f42cdee..810e975b253 100644
--- a/chromium/content/browser/child_process_security_policy_browsertest.cc
+++ b/chromium/content/browser/child_process_security_policy_browsertest.cc
@@ -24,16 +24,20 @@ class ChildProcessSecurityPolicyInProcessBrowserTest
: public ContentBrowserTest {
public:
void SetUp() override {
- EXPECT_EQ(
- ChildProcessSecurityPolicyImpl::GetInstance()->security_state_.size(),
- 0U);
+ auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
+ {
+ base::AutoLock lock(policy->lock_);
+ EXPECT_EQ(0u, policy->security_state_.size());
+ }
ContentBrowserTest::SetUp();
}
void TearDown() override {
- EXPECT_EQ(
- ChildProcessSecurityPolicyImpl::GetInstance()->security_state_.size(),
- 0U);
+ auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
+ {
+ base::AutoLock lock(policy->lock_);
+ EXPECT_EQ(0u, policy->security_state_.size());
+ }
ContentBrowserTest::TearDown();
}
};
@@ -44,11 +48,14 @@ IN_PROC_BROWSER_TEST_F(ChildProcessSecurityPolicyInProcessBrowserTest, DISABLED_
IN_PROC_BROWSER_TEST_F(ChildProcessSecurityPolicyInProcessBrowserTest, NoLeak) {
#endif
GURL url = GetTestUrl("", "simple_page.html");
+ auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
NavigateToURL(shell(), url);
- EXPECT_EQ(
- RenderProcessHostImpl::IsSpareProcessKeptAtAllTimes() ? 2u : 1u,
- ChildProcessSecurityPolicyImpl::GetInstance()->security_state_.size());
+ {
+ base::AutoLock lock(policy->lock_);
+ EXPECT_EQ(RenderProcessHostImpl::IsSpareProcessKeptAtAllTimes() ? 2u : 1u,
+ policy->security_state_.size());
+ }
WebContents* web_contents = shell()->web_contents();
content::RenderProcessHostWatcher exit_observer(
@@ -58,9 +65,11 @@ IN_PROC_BROWSER_TEST_F(ChildProcessSecurityPolicyInProcessBrowserTest, NoLeak) {
exit_observer.Wait();
web_contents->GetController().Reload(ReloadType::NORMAL, true);
- EXPECT_EQ(
- RenderProcessHostImpl::IsSpareProcessKeptAtAllTimes() ? 2u : 1u,
- ChildProcessSecurityPolicyImpl::GetInstance()->security_state_.size());
+ {
+ base::AutoLock lock(policy->lock_);
+ EXPECT_EQ(RenderProcessHostImpl::IsSpareProcessKeptAtAllTimes() ? 2u : 1u,
+ policy->security_state_.size());
+ }
}
} // namespace content
diff --git a/chromium/content/browser/child_process_security_policy_impl.cc b/chromium/content/browser/child_process_security_policy_impl.cc
index bd757e4fdef..323f85836c3 100644
--- a/chromium/content/browser/child_process_security_policy_impl.cc
+++ b/chromium/content/browser/child_process_security_policy_impl.cc
@@ -108,24 +108,24 @@ class ChildProcessSecurityPolicyImpl::SecurityState {
~SecurityState() {
storage::IsolatedContext* isolated_context =
storage::IsolatedContext::GetInstance();
- for (FileSystemMap::iterator iter = filesystem_permissions_.begin();
- iter != filesystem_permissions_.end();
- ++iter) {
+ for (auto iter = filesystem_permissions_.begin();
+ iter != filesystem_permissions_.end(); ++iter) {
isolated_context->RemoveReference(iter->first);
}
- UMA_HISTOGRAM_COUNTS("ChildProcessSecurityPolicy.PerChildFilePermissions",
- file_permissions_.size());
+ UMA_HISTOGRAM_COUNTS_1M(
+ "ChildProcessSecurityPolicy.PerChildFilePermissions",
+ file_permissions_.size());
}
// Grant permission to request and commit URLs with the specified origin.
void GrantCommitOrigin(const url::Origin& origin) {
- if (origin.unique())
+ if (origin.opaque())
return;
origin_map_[origin] = CommitRequestPolicy::kCommitAndRequest;
}
void GrantRequestOrigin(const url::Origin& origin) {
- if (origin.unique())
+ if (origin.opaque())
return;
// Anything already in |origin_map_| must have at least request permission
// already. In that case, the emplace() below will be a no-op.
@@ -146,8 +146,9 @@ class ChildProcessSecurityPolicyImpl::SecurityState {
void GrantPermissionsForFile(const base::FilePath& file, int permissions) {
base::FilePath stripped = file.StripTrailingSeparators();
file_permissions_[stripped] |= permissions;
- UMA_HISTOGRAM_COUNTS("ChildProcessSecurityPolicy.FilePermissionPathLength",
- stripped.value().size());
+ UMA_HISTOGRAM_COUNTS_1M(
+ "ChildProcessSecurityPolicy.FilePermissionPathLength",
+ stripped.value().size());
}
// Grant navigation to a file but not the file:// scheme in general.
@@ -508,7 +509,7 @@ void ChildProcessSecurityPolicyImpl::GrantCommitURL(int child_id,
// TODO(dcheng): In the future, URLs with opaque origins would ideally carry
// around an origin with them, so we wouldn't need to grant commit access to
// the entire scheme.
- if (!origin.unique())
+ if (!origin.opaque())
GrantCommitOrigin(child_id, origin);
// The scheme has already been whitelisted for every child process, so no need
@@ -522,7 +523,7 @@ void ChildProcessSecurityPolicyImpl::GrantCommitURL(int child_id,
if (state == security_state_.end())
return;
- if (origin.unique()) {
+ if (origin.opaque()) {
// If it's impossible to grant commit rights to just the origin (among other
// things, URLs with non-standard schemes will be treated as opaque
// origins), then grant access to commit all URLs of that scheme.
@@ -542,7 +543,7 @@ void ChildProcessSecurityPolicyImpl::GrantRequestSpecificFileURL(
{
base::AutoLock lock(lock_);
- SecurityStateMap::iterator state = security_state_.find(child_id);
+ auto state = security_state_.find(child_id);
if (state == security_state_.end())
return;
@@ -578,7 +579,7 @@ void ChildProcessSecurityPolicyImpl::GrantPermissionsForFile(
int child_id, const base::FilePath& file, int permissions) {
base::AutoLock lock(lock_);
- SecurityStateMap::iterator state = security_state_.find(child_id);
+ auto state = security_state_.find(child_id);
if (state == security_state_.end())
return;
@@ -589,7 +590,7 @@ void ChildProcessSecurityPolicyImpl::RevokeAllPermissionsForFile(
int child_id, const base::FilePath& file) {
base::AutoLock lock(lock_);
- SecurityStateMap::iterator state = security_state_.find(child_id);
+ auto state = security_state_.find(child_id);
if (state == security_state_.end())
return;
@@ -630,7 +631,7 @@ void ChildProcessSecurityPolicyImpl::GrantDeleteFromFileSystem(
void ChildProcessSecurityPolicyImpl::GrantSendMidiSysExMessage(int child_id) {
base::AutoLock lock(lock_);
- SecurityStateMap::iterator state = security_state_.find(child_id);
+ auto state = security_state_.find(child_id);
if (state == security_state_.end())
return;
@@ -642,7 +643,7 @@ void ChildProcessSecurityPolicyImpl::GrantCommitOrigin(
const url::Origin& origin) {
base::AutoLock lock(lock_);
- SecurityStateMap::iterator state = security_state_.find(child_id);
+ auto state = security_state_.find(child_id);
if (state == security_state_.end())
return;
@@ -654,7 +655,7 @@ void ChildProcessSecurityPolicyImpl::GrantRequestOrigin(
const url::Origin& origin) {
base::AutoLock lock(lock_);
- SecurityStateMap::iterator state = security_state_.find(child_id);
+ auto state = security_state_.find(child_id);
if (state == security_state_.end())
return;
@@ -681,7 +682,7 @@ void ChildProcessSecurityPolicyImpl::GrantWebUIBindings(int child_id,
base::AutoLock lock(lock_);
- SecurityStateMap::iterator state = security_state_.find(child_id);
+ auto state = security_state_.find(child_id);
if (state == security_state_.end())
return;
@@ -697,7 +698,7 @@ void ChildProcessSecurityPolicyImpl::GrantWebUIBindings(int child_id,
void ChildProcessSecurityPolicyImpl::GrantReadRawCookies(int child_id) {
base::AutoLock lock(lock_);
- SecurityStateMap::iterator state = security_state_.find(child_id);
+ auto state = security_state_.find(child_id);
if (state == security_state_.end())
return;
@@ -707,7 +708,7 @@ void ChildProcessSecurityPolicyImpl::GrantReadRawCookies(int child_id) {
void ChildProcessSecurityPolicyImpl::RevokeReadRawCookies(int child_id) {
base::AutoLock lock(lock_);
- SecurityStateMap::iterator state = security_state_.find(child_id);
+ auto state = security_state_.find(child_id);
if (state == security_state_.end())
return;
@@ -740,7 +741,7 @@ bool ChildProcessSecurityPolicyImpl::CanRequestURL(
return false;
url::Origin origin = url::Origin::Create(url);
- return origin.unique() || CanRequestURL(child_id, GURL(origin.Serialize()));
+ return origin.opaque() || CanRequestURL(child_id, GURL(origin.Serialize()));
}
if (IsWebSafeScheme(scheme))
@@ -749,7 +750,7 @@ bool ChildProcessSecurityPolicyImpl::CanRequestURL(
{
base::AutoLock lock(lock_);
- SecurityStateMap::iterator state = security_state_.find(child_id);
+ auto state = security_state_.find(child_id);
if (state == security_state_.end())
return false;
@@ -793,7 +794,8 @@ bool ChildProcessSecurityPolicyImpl::CanRedirectToURL(const GURL& url) {
}
bool ChildProcessSecurityPolicyImpl::CanCommitURL(int child_id,
- const GURL& url) {
+ const GURL& url,
+ bool check_origin_locks) {
if (!url.is_valid())
return false; // Can't commit invalid URLs.
@@ -811,9 +813,19 @@ bool ChildProcessSecurityPolicyImpl::CanCommitURL(int child_id,
return false;
url::Origin origin = url::Origin::Create(url);
- return origin.unique() || CanCommitURL(child_id, GURL(origin.Serialize()));
+ return origin.opaque() ||
+ CanCommitURL(child_id, GURL(origin.Serialize()), check_origin_locks);
}
+ // With site isolation, a URL from a site may only be committed in a process
+ // dedicated to that site. This check will ensure that |url| can't commit if
+ // the process is locked to a different site. Note that this check is only
+ // effective for processes that are locked to a site, but even with strict
+ // site isolation, currently not all processes are locked (e.g., extensions
+ // or <webview> tags - see ShouldLockToOrigin()).
+ if (check_origin_locks && !CanAccessDataForOrigin(child_id, url))
+ return false;
+
{
base::AutoLock lock(lock_);
@@ -821,17 +833,12 @@ bool ChildProcessSecurityPolicyImpl::CanCommitURL(int child_id,
// schemes_okay_to_commit_in_any_process_ here, which is stricter than
// IsWebSafeScheme().
//
- // TODO(creis, nick): https://crbug.com/515309: in generalized Site
- // Isolation and/or --site-per-process, there will be no such thing as a
- // scheme that is okay to commit in any process. Instead, an URL from a site
- // that is isolated may only be committed in a process dedicated to that
- // site, so CanCommitURL will need to rely on explicit, per-process grants.
- // Note how today, even with extension isolation, the line below does not
+ // TODO(creis, nick): https://crbug.com/515309: The line below does not
// enforce that http pages cannot commit in an extension process.
if (base::ContainsKey(schemes_okay_to_commit_in_any_process_, scheme))
return true;
- SecurityStateMap::iterator state = security_state_.find(child_id);
+ auto state = security_state_.find(child_id);
if (state == security_state_.end())
return false;
@@ -841,6 +848,11 @@ bool ChildProcessSecurityPolicyImpl::CanCommitURL(int child_id,
}
}
+bool ChildProcessSecurityPolicyImpl::CanCommitURL(int child_id,
+ const GURL& url) {
+ return CanCommitURL(child_id, url, true /* check_origin_lock */);
+}
+
bool ChildProcessSecurityPolicyImpl::CanSetAsOriginHeader(int child_id,
const GURL& url) {
if (!url.is_valid())
@@ -852,7 +864,12 @@ bool ChildProcessSecurityPolicyImpl::CanSetAsOriginHeader(int child_id,
// If this process can commit |url|, it can use |url| as an origin for
// outbound requests.
- if (CanCommitURL(child_id, url))
+ //
+ // TODO(alexmos): This should eventually also check the origin lock, but
+ // currently this is not done due to certain corner cases involving HTML
+ // imports and layout tests that simulate requests from isolated worlds. See
+ // https://crbug.com/515309.
+ if (CanCommitURL(child_id, url, false /* check_origin_lock */))
return true;
// Allow schemes which may come from scripts executing in isolated worlds;
@@ -971,7 +988,7 @@ bool ChildProcessSecurityPolicyImpl::HasPermissionsForFile(
if (!result) {
// If this is a worker thread that has no access to a given file,
// let's check that its renderer process has access to that file instead.
- WorkerToMainProcessMap::iterator iter = worker_map_.find(child_id);
+ auto iter = worker_map_.find(child_id);
if (iter != worker_map_.end() && iter->second != 0) {
result = ChildProcessHasPermissionsForFile(iter->second,
file,
@@ -1013,20 +1030,27 @@ bool ChildProcessSecurityPolicyImpl::HasPermissionsForFileSystemFile(
return false;
}
- FileSystemPermissionPolicyMap::iterator found =
- file_system_policy_map_.find(filesystem_url.type());
- if (found == file_system_policy_map_.end())
- return false;
+ int found_permissions = 0;
+ {
+ base::AutoLock lock(lock_);
+ auto found = file_system_policy_map_.find(filesystem_url.type());
+ if (found == file_system_policy_map_.end())
+ return false;
+ found_permissions = found->second;
+ }
- if ((found->second & storage::FILE_PERMISSION_READ_ONLY) &&
+ if ((found_permissions & storage::FILE_PERMISSION_READ_ONLY) &&
permissions & ~READ_FILE_GRANT) {
return false;
}
- if (found->second & storage::FILE_PERMISSION_USE_FILE_PERMISSION)
+ // Note that HasPermissionsForFile (called below) will internally acquire the
+ // |lock_|, therefore the |lock_| has to be released before the call (since
+ // base::Lock is not reentrant).
+ if (found_permissions & storage::FILE_PERMISSION_USE_FILE_PERMISSION)
return HasPermissionsForFile(child_id, filesystem_url.path(), permissions);
- if (found->second & storage::FILE_PERMISSION_SANDBOX)
+ if (found_permissions & storage::FILE_PERMISSION_SANDBOX)
return true;
return false;
@@ -1077,7 +1101,7 @@ bool ChildProcessSecurityPolicyImpl::CanDeleteFileSystemFile(
bool ChildProcessSecurityPolicyImpl::HasWebUIBindings(int child_id) {
base::AutoLock lock(lock_);
- SecurityStateMap::iterator state = security_state_.find(child_id);
+ auto state = security_state_.find(child_id);
if (state == security_state_.end())
return false;
@@ -1087,7 +1111,7 @@ bool ChildProcessSecurityPolicyImpl::HasWebUIBindings(int child_id) {
bool ChildProcessSecurityPolicyImpl::CanReadRawCookies(int child_id) {
base::AutoLock lock(lock_);
- SecurityStateMap::iterator state = security_state_.find(child_id);
+ auto state = security_state_.find(child_id);
if (state == security_state_.end())
return false;
@@ -1105,7 +1129,7 @@ void ChildProcessSecurityPolicyImpl::AddChild(int child_id) {
bool ChildProcessSecurityPolicyImpl::ChildProcessHasPermissionsForFile(
int child_id, const base::FilePath& file, int permissions) {
- SecurityStateMap::iterator state = security_state_.find(child_id);
+ auto state = security_state_.find(child_id);
if (state == security_state_.end())
return false;
return state->second->HasPermissionsForFile(file, permissions);
@@ -1113,28 +1137,26 @@ bool ChildProcessSecurityPolicyImpl::ChildProcessHasPermissionsForFile(
bool ChildProcessSecurityPolicyImpl::CanAccessDataForOrigin(int child_id,
const GURL& url) {
- // It's important to call GetSiteForURL before acquiring |lock_|, since
- // GetSiteForURL consults IsIsolatedOrigin, which needs to grab the same
- // lock.
- //
- // TODO(creis): We must pass the valid browser_context to convert hosted apps
- // URLs. Currently, hosted apps cannot set cookies in this mode. See
- // http://crbug.com/160576.
- GURL site_url = SiteInstance::GetSiteForURL(nullptr, url);
+ // It's important to call DetermineProcessLockURL before
+ // acquiring |lock_|, since DetermineProcessLockURL consults
+ // IsIsolatedOrigin, which needs to grab the same lock.
+ GURL expected_process_lock =
+ SiteInstanceImpl::DetermineProcessLockURL(nullptr, url);
base::AutoLock lock(lock_);
- SecurityStateMap::iterator state = security_state_.find(child_id);
+ auto state = security_state_.find(child_id);
if (state == security_state_.end()) {
// TODO(nick): Returning true instead of false here is a temporary
// workaround for https://crbug.com/600441
return true;
}
- bool can_access = state->second->CanAccessDataForOrigin(site_url);
+ bool can_access =
+ state->second->CanAccessDataForOrigin(expected_process_lock);
if (!can_access) {
// Returning false here will result in a renderer kill. Set some crash
// keys that will help understand the circumstances of that kill.
base::debug::SetCrashKeyString(bad_message::GetRequestedSiteURLKey(),
- site_url.spec());
+ expected_process_lock.spec());
base::debug::SetCrashKeyString(bad_message::GetKilledProcessOriginLockKey(),
state->second->origin_lock().spec());
@@ -1155,7 +1177,7 @@ void ChildProcessSecurityPolicyImpl::LockToOrigin(int child_id,
// "gurl" can be currently empty in some cases, such as file://blah.
DCHECK_EQ(SiteInstanceImpl::DetermineProcessLockURL(nullptr, gurl), gurl);
base::AutoLock lock(lock_);
- SecurityStateMap::iterator state = security_state_.find(child_id);
+ auto state = security_state_.find(child_id);
DCHECK(state != security_state_.end());
state->second->LockToOrigin(gurl);
}
@@ -1164,7 +1186,7 @@ ChildProcessSecurityPolicyImpl::CheckOriginLockResult
ChildProcessSecurityPolicyImpl::CheckOriginLock(int child_id,
const GURL& site_url) {
base::AutoLock lock(lock_);
- SecurityStateMap::iterator state = security_state_.find(child_id);
+ auto state = security_state_.find(child_id);
if (state == security_state_.end())
return ChildProcessSecurityPolicyImpl::CheckOriginLockResult::NO_LOCK;
return state->second->CheckOriginLock(site_url);
@@ -1172,7 +1194,7 @@ ChildProcessSecurityPolicyImpl::CheckOriginLock(int child_id,
GURL ChildProcessSecurityPolicyImpl::GetOriginLock(int child_id) {
base::AutoLock lock(lock_);
- SecurityStateMap::iterator state = security_state_.find(child_id);
+ auto state = security_state_.find(child_id);
if (state == security_state_.end())
return GURL();
return state->second->origin_lock();
@@ -1184,7 +1206,7 @@ void ChildProcessSecurityPolicyImpl::GrantPermissionsForFileSystem(
int permission) {
base::AutoLock lock(lock_);
- SecurityStateMap::iterator state = security_state_.find(child_id);
+ auto state = security_state_.find(child_id);
if (state == security_state_.end())
return;
state->second->GrantPermissionsForFileSystem(filesystem_id, permission);
@@ -1196,7 +1218,7 @@ bool ChildProcessSecurityPolicyImpl::HasPermissionsForFileSystem(
int permission) {
base::AutoLock lock(lock_);
- SecurityStateMap::iterator state = security_state_.find(child_id);
+ auto state = security_state_.find(child_id);
if (state == security_state_.end())
return false;
return state->second->HasPermissionsForFileSystem(filesystem_id, permission);
@@ -1212,7 +1234,7 @@ void ChildProcessSecurityPolicyImpl::RegisterFileSystemPermissionPolicy(
bool ChildProcessSecurityPolicyImpl::CanSendMidiSysExMessage(int child_id) {
base::AutoLock lock(lock_);
- SecurityStateMap::iterator state = security_state_.find(child_id);
+ auto state = security_state_.find(child_id);
if (state == security_state_.end())
return false;
@@ -1230,10 +1252,18 @@ void ChildProcessSecurityPolicyImpl::AddIsolatedOrigins(
return true; // Remove.
});
- // Taking the lock once and doing a batch insertion via base::flat_set::insert
- // is important because of performance characteristics of base::flat_set.
base::AutoLock lock(lock_);
- isolated_origins_.insert(origins_to_add.begin(), origins_to_add.end());
+ for (const url::Origin& origin : origins_to_add) {
+ // GetSiteForOrigin() is used to look up the site URL of |origin| to speed
+ // up the isolated origin lookup. This only performs a straightforward
+ // translation of an origin to eTLD+1; it does *not* take into account
+ // effective URLs, isolated origins, and other logic that's not needed
+ // here, but *is* typically needed for making process model decisions. Be
+ // very careful about using GetSiteForOrigin() elsewhere, and consider
+ // whether you should be using GetSiteForURL() instead.
+ GURL key(SiteInstanceImpl::GetSiteForOrigin(origin));
+ isolated_origins_[key].insert(origin);
+ }
}
bool ChildProcessSecurityPolicyImpl::IsIsolatedOrigin(
@@ -1245,20 +1275,54 @@ bool ChildProcessSecurityPolicyImpl::IsIsolatedOrigin(
bool ChildProcessSecurityPolicyImpl::GetMatchingIsolatedOrigin(
const url::Origin& origin,
url::Origin* result) {
+ // GetSiteForOrigin() is used to look up the site URL of |origin| to speed
+ // up the isolated origin lookup. This only performs a straightforward
+ // translation of an origin to eTLD+1; it does *not* take into account
+ // effective URLs, isolated origins, and other logic that's not needed
+ // here, but *is* typically needed for making process model decisions. Be
+ // very careful about using GetSiteForOrigin() elsewhere, and consider
+ // whether you should be using GetSiteForURL() instead.
+ return GetMatchingIsolatedOrigin(
+ origin, SiteInstanceImpl::GetSiteForOrigin(origin), result);
+}
+
+bool ChildProcessSecurityPolicyImpl::GetMatchingIsolatedOrigin(
+ const url::Origin& origin,
+ const GURL& site_url,
+ url::Origin* result) {
*result = url::Origin();
base::AutoLock lock(lock_);
+ // Look up the list of origins corresponding to |origin|'s site.
+ auto it = isolated_origins_.find(site_url);
+
+ // Subtle corner case: if the site's host ends with a dot, do the lookup
+ // without it. A trailing dot shouldn't be able to bypass isolated origins:
+ // if "https://foo.com" is an isolated origin, "https://foo.com." should
+ // match it.
+ if (it == isolated_origins_.end() && site_url.has_host() &&
+ site_url.host_piece().back() == '.') {
+ GURL::Replacements replacements;
+ base::StringPiece host(site_url.host_piece());
+ host.remove_suffix(1);
+ replacements.SetHostStr(host);
+ it = isolated_origins_.find(site_url.ReplaceComponents(replacements));
+ }
+
// If multiple isolated origins are registered with a common domain suffix,
// return the most specific one. For example, if foo.isolated.com and
- // isolated.com are both isolated origins, bar.foo.isolated.com should return
- // foo.isolated.com.
+ // isolated.com are both isolated origins, bar.foo.isolated.com should
+ // return foo.isolated.com.
bool found = false;
- for (auto isolated_origin : isolated_origins_) {
- if (IsolatedOriginUtil::DoesOriginMatchIsolatedOrigin(origin,
- isolated_origin)) {
- if (!found || result->host().length() < isolated_origin.host().length()) {
- *result = isolated_origin;
- found = true;
+ if (it != isolated_origins_.end()) {
+ for (const url::Origin& isolated_origin : it->second) {
+ if (IsolatedOriginUtil::DoesOriginMatchIsolatedOrigin(origin,
+ isolated_origin)) {
+ if (!found ||
+ result->host().length() < isolated_origin.host().length()) {
+ *result = isolated_origin;
+ found = true;
+ }
}
}
}
@@ -1268,8 +1332,11 @@ bool ChildProcessSecurityPolicyImpl::GetMatchingIsolatedOrigin(
void ChildProcessSecurityPolicyImpl::RemoveIsolatedOriginForTesting(
const url::Origin& origin) {
+ GURL key(SiteInstanceImpl::GetSiteForOrigin(origin));
base::AutoLock lock(lock_);
- isolated_origins_.erase(origin);
+ isolated_origins_[key].erase(origin);
+ if (isolated_origins_[key].empty())
+ isolated_origins_.erase(key);
}
} // namespace content
diff --git a/chromium/content/browser/child_process_security_policy_impl.h b/chromium/content/browser/child_process_security_policy_impl.h
index a82411ecdce..9dbc29b83e7 100644
--- a/chromium/content/browser/child_process_security_policy_impl.h
+++ b/chromium/content/browser/child_process_security_policy_impl.h
@@ -12,12 +12,14 @@
#include <vector>
#include "base/compiler_specific.h"
+#include "base/containers/flat_map.h"
#include "base/containers/flat_set.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/singleton.h"
#include "base/synchronization/lock.h"
+#include "base/thread_annotations.h"
#include "content/public/browser/child_process_security_policy.h"
#include "content/public/common/resource_type.h"
#include "storage/common/fileapi/file_system_types.h"
@@ -97,6 +99,15 @@ class CONTENT_EXPORT ChildProcessSecurityPolicyImpl
bool GetMatchingIsolatedOrigin(const url::Origin& origin,
url::Origin* result) override;
+ // A version of GetMatchingIsolatedOrigin that takes in both the |origin| and
+ // the |site_url| that |origin| corresponds to. |site_url| is the key by
+ // which |origin| will be looked up in |isolated_origins_|; this function
+ // allows it to be passed in when it is already known to avoid recomputing it
+ // internally.
+ bool GetMatchingIsolatedOrigin(const url::Origin& origin,
+ const GURL& site_url,
+ url::Origin* result);
+
// Returns if |child_id| can read all of the |files|.
bool CanReadAllFiles(int child_id, const std::vector<base::FilePath>& files);
@@ -160,6 +171,20 @@ class CONTENT_EXPORT ChildProcessSecurityPolicyImpl
// Revoke read raw cookies permission.
void RevokeReadRawCookies(int child_id);
+ // A version of the public ChildProcessSecurityPolicy::CanCommitURL() which
+ // takes an additional bool |check_origin_lock|, specifying whether to
+ // reject |url| if it does not match the origin lock on process |child_id|.
+ // Passing true for |check_origin_lock| provides stronger enforcement with
+ // strict site isolation; it is only set to false by features (e.g., Origin
+ // header validation) that aren't yet ready for this enforcement. This
+ // function should *not* be used by new features; use the public
+ // ChildProcessSecurityPolicy::CanCommitURL() instead, which internally calls
+ // this with |check_origin_lock| being true.
+ //
+ // TODO(alexmos): Remove |check_origin_lock| and check origin locks
+ // unconditionally once https://crbug.com/515309 is fixed.
+ bool CanCommitURL(int child_id, const GURL& url, bool check_origin_lock);
+
// Whether the given origin is valid for an origin header. Valid origin
// headers are commitable URLs.
bool CanSetAsOriginHeader(int child_id, const GURL& url);
@@ -286,13 +311,14 @@ class CONTENT_EXPORT ChildProcessSecurityPolicyImpl
friend struct base::DefaultSingletonTraits<ChildProcessSecurityPolicyImpl>;
// Adds child process during registration.
- void AddChild(int child_id);
+ void AddChild(int child_id) EXCLUSIVE_LOCKS_REQUIRED(lock_);
// Determines if certain permissions were granted for a file to given child
// process. |permissions| is an internally defined bit-set.
bool ChildProcessHasPermissionsForFile(int child_id,
const base::FilePath& file,
- int permissions);
+ int permissions)
+ EXCLUSIVE_LOCKS_REQUIRED(lock_);
// Grant a particular permission set for a file. |permissions| is an
// internally defined bit-set.
@@ -336,32 +362,43 @@ class CONTENT_EXPORT ChildProcessSecurityPolicyImpl
// These schemes are white-listed for all child processes in various contexts.
// These sets are protected by |lock_|.
- SchemeSet schemes_okay_to_commit_in_any_process_;
- SchemeSet schemes_okay_to_request_in_any_process_;
- SchemeSet schemes_okay_to_appear_as_origin_headers_;
+ SchemeSet schemes_okay_to_commit_in_any_process_ GUARDED_BY(lock_);
+ SchemeSet schemes_okay_to_request_in_any_process_ GUARDED_BY(lock_);
+ SchemeSet schemes_okay_to_appear_as_origin_headers_ GUARDED_BY(lock_);
// These schemes do not actually represent retrievable URLs. For example,
// the the URLs in the "about" scheme are aliases to other URLs. This set is
// protected by |lock_|.
- SchemeSet pseudo_schemes_;
+ SchemeSet pseudo_schemes_ GUARDED_BY(lock_);
// This map holds a SecurityState for each child process. The key for the
// map is the ID of the ChildProcessHost. The SecurityState objects are
// owned by this object and are protected by |lock_|. References to them must
// not escape this class.
- SecurityStateMap security_state_;
+ SecurityStateMap security_state_ GUARDED_BY(lock_);
// This maps keeps the record of which js worker thread child process
// corresponds to which main js thread child process.
- WorkerToMainProcessMap worker_map_;
+ WorkerToMainProcessMap worker_map_ GUARDED_BY(lock_);
- FileSystemPermissionPolicyMap file_system_policy_map_;
+ FileSystemPermissionPolicyMap file_system_policy_map_ GUARDED_BY(lock_);
// Tracks origins for which the entire origin should be treated as a site
// when making process model decisions, rather than the origin's scheme and
// eTLD+1. Each of these origins requires a dedicated process. This set is
// protected by |lock_|.
- base::flat_set<url::Origin> isolated_origins_;
+ //
+ // The origins are stored in a map indexed by a site URL computed for each
+ // origin. For example, adding https://foo.com, https://bar.foo.com, and
+ // https://www.bar.com would result in the following structure:
+ // https://foo.com -> { https://foo.com, https://bar.foo.com }
+ // https://bar.com -> { https://www.bar.com }
+ // This organization speeds up lookups of isolated origins. The site can be
+ // found in O(log n) time, and the corresponding list of origins to search
+ // using the expensive DoesOriginMatchIsolatedOrigin() comparison is
+ // typically small.
+ base::flat_map<GURL, base::flat_set<url::Origin>> isolated_origins_
+ GUARDED_BY(lock_);
DISALLOW_COPY_AND_ASSIGN(ChildProcessSecurityPolicyImpl);
};
diff --git a/chromium/content/browser/child_process_security_policy_unittest.cc b/chromium/content/browser/child_process_security_policy_unittest.cc
index 57bc04c9d8c..d571d8e9883 100644
--- a/chromium/content/browser/child_process_security_policy_unittest.cc
+++ b/chromium/content/browser/child_process_security_policy_unittest.cc
@@ -9,6 +9,7 @@
#include "base/logging.h"
#include "base/test/mock_log.h"
#include "content/browser/child_process_security_policy_impl.h"
+#include "content/browser/site_instance_impl.h"
#include "content/public/common/bindings_policy.h"
#include "content/public/common/url_constants.h"
#include "content/test/test_content_browser_client.h"
@@ -497,8 +498,8 @@ TEST_F(ChildProcessSecurityPolicyTest, GrantCommitURLToNonStandardScheme) {
const GURL url("httpxml://awesome");
const GURL url2("httpxml://also-awesome");
- ASSERT_TRUE(url::Origin::Create(url).unique());
- ASSERT_TRUE(url::Origin::Create(url2).unique());
+ ASSERT_TRUE(url::Origin::Create(url).opaque());
+ ASSERT_TRUE(url::Origin::Create(url2).opaque());
RegisterTestScheme("httpxml");
p->Add(kRendererID);
@@ -1086,12 +1087,38 @@ TEST_F(ChildProcessSecurityPolicyTest, OriginGranting) {
p->Remove(kRendererID);
}
+
+namespace {
+
+// Helpers to construct (key, value) entries used to validate the
+// isolated_origins_ map.
+auto IsolatedOriginEntry(const url::Origin& origin) {
+ return std::pair<GURL, base::flat_set<url::Origin>>(
+ SiteInstanceImpl::GetSiteForOrigin(origin), {origin});
+}
+
+auto IsolatedOriginEntry(const url::Origin& origin1,
+ const url::Origin& origin2) {
+ EXPECT_EQ(SiteInstanceImpl::GetSiteForOrigin(origin1),
+ SiteInstanceImpl::GetSiteForOrigin(origin2));
+ return std::pair<GURL, base::flat_set<url::Origin>>(
+ SiteInstanceImpl::GetSiteForOrigin(origin1), {origin1, origin2});
+}
+
+} // namespace
+
+#define LOCKED_EXPECT_THAT(lock, value, matcher) \
+ do { \
+ base::AutoLock auto_lock(lock); \
+ EXPECT_THAT(value, matcher); \
+ } while (0);
+
// Verifies ChildProcessSecurityPolicyImpl::AddIsolatedOrigins method.
TEST_F(ChildProcessSecurityPolicyTest, AddIsolatedOrigins) {
url::Origin foo = url::Origin::Create(GURL("https://foo.com/"));
url::Origin bar = url::Origin::Create(GURL("https://bar.com/"));
url::Origin baz = url::Origin::Create(GURL("https://baz.com/"));
- url::Origin foobar = url::Origin::Create(GURL("https://foobar.com/"));
+ url::Origin quxfoo = url::Origin::Create(GURL("https://qux.foo.com/"));
url::Origin baz_http_8000 = url::Origin::Create(GURL("http://baz.com:8000/"));
url::Origin baz_https_8000 =
url::Origin::Create(GURL("https://baz.com:8000/"));
@@ -1100,32 +1127,43 @@ TEST_F(ChildProcessSecurityPolicyTest, AddIsolatedOrigins) {
ChildProcessSecurityPolicyImpl::GetInstance();
// Initially there should be no isolated origins.
- EXPECT_THAT(p->isolated_origins_, testing::IsEmpty());
+ LOCKED_EXPECT_THAT(p->lock_, p->isolated_origins_, testing::IsEmpty());
// Verify deduplication of the argument.
p->AddIsolatedOrigins({foo, bar, bar});
- EXPECT_THAT(p->isolated_origins_, testing::UnorderedElementsAre(foo, bar));
+ LOCKED_EXPECT_THAT(p->lock_, p->isolated_origins_,
+ testing::UnorderedElementsAre(IsolatedOriginEntry(foo),
+ IsolatedOriginEntry(bar)));
// Verify that the old set is extended (not replaced).
p->AddIsolatedOrigins({baz});
- EXPECT_THAT(p->isolated_origins_,
- testing::UnorderedElementsAre(foo, bar, baz));
+ LOCKED_EXPECT_THAT(p->lock_, p->isolated_origins_,
+ testing::UnorderedElementsAre(IsolatedOriginEntry(foo),
+ IsolatedOriginEntry(bar),
+ IsolatedOriginEntry(baz)));
// Verify deduplication against the old set.
p->AddIsolatedOrigins({foo});
- EXPECT_THAT(p->isolated_origins_,
- testing::UnorderedElementsAre(foo, bar, baz));
+ LOCKED_EXPECT_THAT(p->lock_, p->isolated_origins_,
+ testing::UnorderedElementsAre(IsolatedOriginEntry(foo),
+ IsolatedOriginEntry(bar),
+ IsolatedOriginEntry(baz)));
- // Verify deduplication considers scheme and port differences.
+ // Verify deduplication considers scheme and port differences. Note that
+ // origins that differ only in ports map to the same key.
p->AddIsolatedOrigins({baz, baz_http_8000, baz_https_8000});
- EXPECT_THAT(p->isolated_origins_,
- testing::UnorderedElementsAre(foo, bar, baz, baz_http_8000,
- baz_https_8000));
+ LOCKED_EXPECT_THAT(p->lock_, p->isolated_origins_,
+ testing::UnorderedElementsAre(
+ IsolatedOriginEntry(foo), IsolatedOriginEntry(bar),
+ IsolatedOriginEntry(baz, baz_https_8000),
+ IsolatedOriginEntry(baz_http_8000)));
// Verify that adding an origin that is invalid for isolation will 1) log a
// warning and 2) won't CHECK or crash the browser process, 3) will not add
// the invalid origin, but will add the remaining origins passed to
- // AddIsolatedOrigins.
+ // AddIsolatedOrigins. Note that the new |quxfoo| origin should map to the
+ // same key (i.e., the https://foo.com/ site URL) as the existing |foo|
+ // origin.
{
base::test::MockLog mock_log;
EXPECT_CALL(mock_log,
@@ -1134,11 +1172,23 @@ TEST_F(ChildProcessSecurityPolicyTest, AddIsolatedOrigins) {
.Times(1);
mock_log.StartCapturingLogs();
- p->AddIsolatedOrigins({foobar, invalid_etld});
- EXPECT_THAT(p->isolated_origins_,
- testing::UnorderedElementsAre(foo, bar, baz, baz_http_8000,
- baz_https_8000, foobar));
+ p->AddIsolatedOrigins({quxfoo, invalid_etld});
+ LOCKED_EXPECT_THAT(
+ p->lock_, p->isolated_origins_,
+ testing::UnorderedElementsAre(IsolatedOriginEntry(foo, quxfoo),
+ IsolatedOriginEntry(bar),
+ IsolatedOriginEntry(baz, baz_https_8000),
+ IsolatedOriginEntry(baz_http_8000)));
}
}
+// Check that an unsuccessful isolated origin lookup for a URL with an empty
+// host doesn't crash. See https://crbug.com/882686.
+TEST_F(ChildProcessSecurityPolicyTest, IsIsolatedOriginWithEmptyHost) {
+ ChildProcessSecurityPolicyImpl* p =
+ ChildProcessSecurityPolicyImpl::GetInstance();
+ EXPECT_FALSE(p->IsIsolatedOrigin(url::Origin::Create(GURL())));
+ EXPECT_FALSE(p->IsIsolatedOrigin(url::Origin::Create(GURL("file:///foo"))));
+}
+
} // namespace content
diff --git a/chromium/content/browser/cocoa/system_hotkey_helper_mac.mm b/chromium/content/browser/cocoa/system_hotkey_helper_mac.mm
index 0a26a48fd62..27b8fae73bc 100644
--- a/chromium/content/browser/cocoa/system_hotkey_helper_mac.mm
+++ b/chromium/content/browser/cocoa/system_hotkey_helper_mac.mm
@@ -12,6 +12,7 @@
#include "base/task/task_traits.h"
#include "base/threading/scoped_blocking_call.h"
#include "content/browser/cocoa/system_hotkey_map.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
namespace {
@@ -62,11 +63,9 @@ void SystemHotkeyHelperMac::LoadSystemHotkeys() {
// will destroy the object.
NSDictionary* dictionary = [SystemHotkeyMap::DictionaryFromData(data) retain];
- BrowserThread::PostTask(BrowserThread::UI,
- FROM_HERE,
- base::Bind(&SystemHotkeyHelperMac::FileDidLoad,
- base::Unretained(this),
- dictionary));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ base::Bind(&SystemHotkeyHelperMac::FileDidLoad,
+ base::Unretained(this), dictionary));
}
void SystemHotkeyHelperMac::FileDidLoad(NSDictionary* dictionary) {
diff --git a/chromium/content/browser/code_cache/generated_code_cache.cc b/chromium/content/browser/code_cache/generated_code_cache.cc
index f1f3ec32393..90028a32b48 100644
--- a/chromium/content/browser/code_cache/generated_code_cache.cc
+++ b/chromium/content/browser/code_cache/generated_code_cache.cc
@@ -4,6 +4,7 @@
#include "content/browser/code_cache/generated_code_cache.h"
#include "base/memory/ptr_util.h"
+#include "base/metrics/histogram_macros.h"
#include "net/base/completion_callback.h"
#include "net/base/completion_once_callback.h"
#include "net/http/http_util.h"
@@ -24,7 +25,7 @@ bool IsAllowedToCache(const GURL& resource_url,
// Don't cache the code corresponding to unique origins. The same-origin
// checks should always fail for unique origins but the serialized value of
// unique origins does not ensure this.
- if (requesting_origin.unique())
+ if (requesting_origin.opaque())
return false;
// If the resource url or requesting url is invalid don't cache the code.
@@ -39,7 +40,7 @@ bool IsAllowedToCache(const GURL& resource_url,
// serialized url and origin with a separator in between.
std::string GetCacheKey(const GURL& resource_url,
const url::Origin& requesting_origin) {
- DCHECK(!requesting_origin.unique());
+ DCHECK(!requesting_origin.opaque());
DCHECK(resource_url.is_valid());
// Add a prefix _ so it can't be parsed as a valid URL.
std::string key = "_key";
@@ -54,6 +55,18 @@ std::string GetCacheKey(const GURL& resource_url,
}
} // namespace
+void GeneratedCodeCache::CollectStatistics(
+ GeneratedCodeCache::CacheEntryStatus status) {
+ switch (cache_type_) {
+ case GeneratedCodeCache::CodeCacheType::kJavaScript:
+ UMA_HISTOGRAM_ENUMERATION("SiteIsolatedCodeCache.JS.Behaviour", status);
+ break;
+ case GeneratedCodeCache::CodeCacheType::kWebAssembly:
+ UMA_HISTOGRAM_ENUMERATION("SiteIsolatedCodeCache.WASM.Behaviour", status);
+ break;
+ }
+}
+
// Stores the information about a pending request while disk backend is
// being initialized.
class GeneratedCodeCache::PendingOperation {
@@ -141,10 +154,12 @@ GeneratedCodeCache::PendingOperation::PendingOperation(
GeneratedCodeCache::PendingOperation::~PendingOperation() = default;
GeneratedCodeCache::GeneratedCodeCache(const base::FilePath& path,
- int max_size_bytes)
+ int max_size_bytes,
+ CodeCacheType cache_type)
: backend_state_(kUnInitialized),
path_(path),
max_size_bytes_(max_size_bytes),
+ cache_type_(cache_type),
weak_ptr_factory_(this) {
CreateBackend();
}
@@ -156,18 +171,23 @@ void GeneratedCodeCache::WriteData(const GURL& url,
const base::Time& response_time,
const std::vector<uint8_t>& data) {
// Silently ignore the requests.
- if (backend_state_ == kFailed)
+ if (backend_state_ == kFailed) {
+ CollectStatistics(CacheEntryStatus::kError);
return;
+ }
// If the url is invalid or if it is from a unique origin, we should not
// cache the code.
- if (!IsAllowedToCache(url, origin))
+ if (!IsAllowedToCache(url, origin)) {
+ CollectStatistics(CacheEntryStatus::kError);
return;
+ }
// Append the response time to the metadata. Code caches store
// response_time + generated code as a single entry.
- scoped_refptr<net::IOBufferWithSize> buffer(
- new net::IOBufferWithSize(data.size() + kResponseTimeSizeInBytes));
+ scoped_refptr<net::IOBufferWithSize> buffer =
+ base::MakeRefCounted<net::IOBufferWithSize>(data.size() +
+ kResponseTimeSizeInBytes);
int64_t serialized_time =
response_time.ToDeltaSinceWindowsEpoch().InMicroseconds();
memcpy(buffer->data(), &serialized_time, kResponseTimeSizeInBytes);
@@ -192,6 +212,7 @@ void GeneratedCodeCache::FetchEntry(const GURL& url,
const url::Origin& origin,
ReadDataCallback read_data_callback) {
if (backend_state_ == kFailed) {
+ CollectStatistics(CacheEntryStatus::kError);
// Silently ignore the requests.
std::move(read_data_callback).Run(base::Time(), std::vector<uint8_t>());
return;
@@ -200,6 +221,7 @@ void GeneratedCodeCache::FetchEntry(const GURL& url,
// If the url is invalid or if it is from a unique origin, we should not
// cache the code.
if (!IsAllowedToCache(url, origin)) {
+ CollectStatistics(CacheEntryStatus::kError);
std::move(read_data_callback).Run(base::Time(), std::vector<uint8_t>());
return;
}
@@ -220,13 +242,17 @@ void GeneratedCodeCache::FetchEntry(const GURL& url,
void GeneratedCodeCache::DeleteEntry(const GURL& url,
const url::Origin& origin) {
// Silently ignore the requests.
- if (backend_state_ == kFailed)
+ if (backend_state_ == kFailed) {
+ CollectStatistics(CacheEntryStatus::kError);
return;
+ }
// If the url is invalid or if it is from a unique origin, we should not
// cache the code.
- if (!IsAllowedToCache(url, origin))
+ if (!IsAllowedToCache(url, origin)) {
+ CollectStatistics(CacheEntryStatus::kError);
return;
+ }
std::string key = GetCacheKey(url, origin);
if (backend_state_ != kInitialized) {
@@ -355,6 +381,7 @@ void GeneratedCodeCache::OpenCompleteForWriteData(
DCHECK(entry->data);
disk_cache::ScopedEntryPtr disk_entry(entry->data);
+ CollectStatistics(CacheEntryStatus::kUpdate);
// This call will truncate the data. This is safe to do since we read the
// entire data at the same time currently. If we want to read in parts we have
// to doom the entry first.
@@ -366,11 +393,14 @@ void GeneratedCodeCache::CreateCompleteForWriteData(
scoped_refptr<net::IOBufferWithSize> buffer,
scoped_refptr<base::RefCountedData<disk_cache::Entry*>> entry,
int rv) {
- if (rv != net::OK)
+ if (rv != net::OK) {
+ CollectStatistics(CacheEntryStatus::kError);
return;
+ }
DCHECK(entry->data);
disk_cache::ScopedEntryPtr disk_entry(entry->data);
+ CollectStatistics(CacheEntryStatus::kCreate);
disk_entry->WriteData(kDataIndex, 0, buffer.get(), buffer->size(),
net::CompletionOnceCallback(), true);
}
@@ -402,6 +432,7 @@ void GeneratedCodeCache::OpenCompleteForReadData(
scoped_refptr<base::RefCountedData<disk_cache::Entry*>> entry,
int rv) {
if (rv != net::OK) {
+ CollectStatistics(CacheEntryStatus::kMiss);
std::move(read_data_callback).Run(base::Time(), std::vector<uint8_t>());
return;
}
@@ -411,7 +442,8 @@ void GeneratedCodeCache::OpenCompleteForReadData(
disk_cache::ScopedEntryPtr disk_entry(entry->data);
int size = disk_entry->GetDataSize(kDataIndex);
- scoped_refptr<net::IOBufferWithSize> buffer(new net::IOBufferWithSize(size));
+ scoped_refptr<net::IOBufferWithSize> buffer =
+ base::MakeRefCounted<net::IOBufferWithSize>(size);
net::CompletionOnceCallback callback = base::BindOnce(
&GeneratedCodeCache::ReadDataComplete, weak_ptr_factory_.GetWeakPtr(),
read_data_callback, buffer);
@@ -427,13 +459,30 @@ void GeneratedCodeCache::ReadDataComplete(
scoped_refptr<net::IOBufferWithSize> buffer,
int rv) {
if (rv != buffer->size()) {
+ CollectStatistics(CacheEntryStatus::kMiss);
+ std::move(callback).Run(base::Time(), std::vector<uint8_t>());
+ } else if (buffer->size() < kResponseTimeSizeInBytes) {
+ // TODO(crbug.com/886892): Change the implementation, so serialize requests
+ // for the same key here. When we do that, this case should not arise.
+ // We might be reading an entry before the write was completed. This can
+ // happen if we have a write and read operation for the same key almost at
+ // the same time and they interleave as:
+ // W(Create) -> R(Open) -> R(Read) -> W(Write).
+ CollectStatistics(CacheEntryStatus::kIncompleteEntry);
std::move(callback).Run(base::Time(), std::vector<uint8_t>());
} else {
+ // DiskCache ensures that the operations that are queued for an entry
+ // go in order. Hence, we would either read an empty data or read the full
+ // data. Please look at comment in else to see why we read empty data.
+ CollectStatistics(CacheEntryStatus::kHit);
int64_t raw_response_time = *(reinterpret_cast<int64_t*>(buffer->data()));
base::Time response_time = base::Time::FromDeltaSinceWindowsEpoch(
base::TimeDelta::FromMicroseconds(raw_response_time));
- std::vector<uint8_t> data(buffer->data() + kResponseTimeSizeInBytes,
- buffer->data() + buffer->size());
+ std::vector<uint8_t> data;
+ if (buffer->size() > kResponseTimeSizeInBytes) {
+ data = std::vector<uint8_t>(buffer->data() + kResponseTimeSizeInBytes,
+ buffer->data() + buffer->size());
+ }
std::move(callback).Run(response_time, data);
}
}
@@ -442,6 +491,7 @@ void GeneratedCodeCache::DeleteEntryImpl(const std::string& key) {
if (backend_state_ != kInitialized)
return;
+ CollectStatistics(CacheEntryStatus::kClear);
backend_->DoomEntry(key, net::LOWEST, net::CompletionOnceCallback());
}
diff --git a/chromium/content/browser/code_cache/generated_code_cache.h b/chromium/content/browser/code_cache/generated_code_cache.h
index 58e735b447d..2ad53ff0329 100644
--- a/chromium/content/browser/code_cache/generated_code_cache.h
+++ b/chromium/content/browser/code_cache/generated_code_cache.h
@@ -36,10 +36,28 @@ class CONTENT_EXPORT GeneratedCodeCache {
const std::vector<uint8_t>&)>;
static const int kResponseTimeSizeInBytes = sizeof(int64_t);
+ // Cache type. Used for collecting statistics for JS and Wasm in separate
+ // buckets.
+ enum CodeCacheType { kJavaScript, kWebAssembly };
+
+ // Used for collecting statistics about cache behaviour.
+ enum CacheEntryStatus {
+ kHit,
+ kMiss,
+ kClear,
+ kUpdate,
+ kCreate,
+ kError,
+ kIncompleteEntry,
+ kMaxValue = kIncompleteEntry
+ };
+
// Creates a GeneratedCodeCache with the specified path and the maximum size.
// If |max_size_bytes| is 0, then disk_cache picks a default size based on
// some heuristics.
- GeneratedCodeCache(const base::FilePath& path, int max_size_bytes);
+ GeneratedCodeCache(const base::FilePath& path,
+ int max_size_bytes,
+ CodeCacheType cache_type);
~GeneratedCodeCache();
@@ -120,6 +138,8 @@ class CONTENT_EXPORT GeneratedCodeCache {
void DoPendingClearCache(net::CompletionCallback callback);
void PendingClearComplete(net::CompletionCallback callback, int rv);
+ void CollectStatistics(GeneratedCodeCache::CacheEntryStatus status);
+
std::unique_ptr<disk_cache::Backend> backend_;
BackendState backend_state_;
@@ -127,6 +147,7 @@ class CONTENT_EXPORT GeneratedCodeCache {
base::FilePath path_;
int max_size_bytes_;
+ CodeCacheType cache_type_;
base::WeakPtrFactory<GeneratedCodeCache> weak_ptr_factory_;
diff --git a/chromium/content/browser/code_cache/generated_code_cache_context.cc b/chromium/content/browser/code_cache/generated_code_cache_context.cc
index 9aa1621fce3..b119832b8d4 100644
--- a/chromium/content/browser/code_cache/generated_code_cache_context.cc
+++ b/chromium/content/browser/code_cache/generated_code_cache_context.cc
@@ -3,7 +3,9 @@
// found in the LICENSE file.
#include "content/browser/code_cache/generated_code_cache_context.h"
#include "base/files/file_path.h"
+#include "base/task/post_task.h"
#include "content/browser/code_cache/generated_code_cache.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
namespace content {
@@ -16,20 +18,31 @@ void GeneratedCodeCacheContext::Initialize(const base::FilePath& path,
int max_bytes) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&GeneratedCodeCacheContext::InitializeOnIO, this, path,
max_bytes));
}
void GeneratedCodeCacheContext::InitializeOnIO(const base::FilePath& path,
int max_bytes) {
- generated_code_cache_.reset(new GeneratedCodeCache(path, max_bytes));
+ generated_js_code_cache_.reset(
+ new GeneratedCodeCache(path.AppendASCII("js"), max_bytes,
+ GeneratedCodeCache::CodeCacheType::kJavaScript));
+ generated_wasm_code_cache_.reset(
+ new GeneratedCodeCache(path.AppendASCII("wasm"), max_bytes,
+ GeneratedCodeCache::CodeCacheType::kWebAssembly));
}
-GeneratedCodeCache* GeneratedCodeCacheContext::generated_code_cache() const {
+GeneratedCodeCache* GeneratedCodeCacheContext::generated_js_code_cache() const {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- return generated_code_cache_.get();
+ return generated_js_code_cache_.get();
+}
+
+GeneratedCodeCache* GeneratedCodeCacheContext::generated_wasm_code_cache()
+ const {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ return generated_wasm_code_cache_.get();
}
GeneratedCodeCacheContext::~GeneratedCodeCacheContext() = default;
diff --git a/chromium/content/browser/code_cache/generated_code_cache_context.h b/chromium/content/browser/code_cache/generated_code_cache_context.h
index 4a42bebef7b..7e26e3269ee 100644
--- a/chromium/content/browser/code_cache/generated_code_cache_context.h
+++ b/chromium/content/browser/code_cache/generated_code_cache_context.h
@@ -30,8 +30,9 @@ class CONTENT_EXPORT GeneratedCodeCacheContext
// being setup.
void Initialize(const base::FilePath& path, int max_bytes);
- // Call on the IO thread to get the code cache instance.
- GeneratedCodeCache* generated_code_cache() const;
+ // Call on the IO thread to get the code cache instances.
+ GeneratedCodeCache* generated_js_code_cache() const;
+ GeneratedCodeCache* generated_wasm_code_cache() const;
private:
friend class base::RefCountedThreadSafe<GeneratedCodeCacheContext>;
@@ -41,7 +42,9 @@ class CONTENT_EXPORT GeneratedCodeCacheContext
// Created, used and deleted on the IO thread.
std::unique_ptr<GeneratedCodeCache, BrowserThread::DeleteOnIOThread>
- generated_code_cache_;
+ generated_js_code_cache_;
+ std::unique_ptr<GeneratedCodeCache, BrowserThread::DeleteOnIOThread>
+ generated_wasm_code_cache_;
DISALLOW_COPY_AND_ASSIGN(GeneratedCodeCacheContext);
};
diff --git a/chromium/content/browser/code_cache/generated_code_cache_unittest.cc b/chromium/content/browser/code_cache/generated_code_cache_unittest.cc
index 4f005c89c9a..3a2e4ca7fc5 100644
--- a/chromium/content/browser/code_cache/generated_code_cache_unittest.cc
+++ b/chromium/content/browser/code_cache/generated_code_cache_unittest.cc
@@ -25,8 +25,6 @@ class GeneratedCodeCacheTest : public testing::Test {
void SetUp() override {
ASSERT_TRUE(cache_dir_.CreateUniqueTempDir());
cache_path_ = cache_dir_.GetPath();
- generated_code_cache_ =
- std::make_unique<GeneratedCodeCache>(cache_path_, kMaxSizeInBytes);
}
void TearDown() override {
@@ -36,7 +34,11 @@ class GeneratedCodeCacheTest : public testing::Test {
// This function initializes the cache and waits till the transaction is
// finished. When this function returns, the backend is already initialized.
- void InitializeCache() {
+ void InitializeCache(GeneratedCodeCache::CodeCacheType cache_type) {
+ // Create code cache
+ generated_code_cache_ = std::make_unique<GeneratedCodeCache>(
+ cache_path_, kMaxSizeInBytes, cache_type);
+
GURL url(kInitialUrl);
url::Origin origin = url::Origin::Create(GURL(kInitialOrigin));
WriteToCache(url, origin, kInitialData, base::Time::Now());
@@ -46,10 +48,10 @@ class GeneratedCodeCacheTest : public testing::Test {
// This function initializes the cache and reopens it. When this function
// returns, the backend initialization is not complete yet. This is used
// to test the pending operaions path.
- void InitializeCacheAndReOpen() {
- InitializeCache();
+ void InitializeCacheAndReOpen(GeneratedCodeCache::CodeCacheType cache_type) {
+ InitializeCache(cache_type);
generated_code_cache_.reset(
- new GeneratedCodeCache(cache_path_, kMaxSizeInBytes));
+ new GeneratedCodeCache(cache_path_, kMaxSizeInBytes, cache_type));
}
void WriteToCache(const GURL& url,
@@ -113,6 +115,7 @@ TEST_F(GeneratedCodeCacheTest, CheckResponseTime) {
GURL url(kInitialUrl);
url::Origin origin = url::Origin::Create(GURL(kInitialOrigin));
+ InitializeCache(GeneratedCodeCache::CodeCacheType::kJavaScript);
std::string data = "SerializedCodeForScript";
base::Time response_time = base::Time::Now();
WriteToCache(url, origin, data, response_time);
@@ -129,7 +132,7 @@ TEST_F(GeneratedCodeCacheTest, FetchEntry) {
GURL url(kInitialUrl);
url::Origin origin = url::Origin::Create(GURL(kInitialOrigin));
- InitializeCache();
+ InitializeCache(GeneratedCodeCache::CodeCacheType::kJavaScript);
FetchFromCache(url, origin);
scoped_task_environment_.RunUntilIdle();
@@ -141,7 +144,7 @@ TEST_F(GeneratedCodeCacheTest, WriteEntry) {
GURL new_url("http://example1.com/script.js");
url::Origin origin = url::Origin::Create(GURL(kInitialOrigin));
- InitializeCache();
+ InitializeCache(GeneratedCodeCache::CodeCacheType::kJavaScript);
std::string data = "SerializedCodeForScript";
base::Time response_time = base::Time::Now();
WriteToCache(new_url, origin, data, response_time);
@@ -158,7 +161,7 @@ TEST_F(GeneratedCodeCacheTest, DeleteEntry) {
GURL url(kInitialUrl);
url::Origin origin = url::Origin::Create(GURL(kInitialOrigin));
- InitializeCache();
+ InitializeCache(GeneratedCodeCache::CodeCacheType::kJavaScript);
DeleteFromCache(url, origin);
FetchFromCache(url, origin);
scoped_task_environment_.RunUntilIdle();
@@ -167,11 +170,27 @@ TEST_F(GeneratedCodeCacheTest, DeleteEntry) {
ASSERT_TRUE(received_null_);
}
+TEST_F(GeneratedCodeCacheTest, WriteEntryWithEmptyData) {
+ GURL url(kInitialUrl);
+ url::Origin origin = url::Origin::Create(GURL(kInitialOrigin));
+
+ InitializeCache(GeneratedCodeCache::CodeCacheType::kJavaScript);
+ base::Time response_time = base::Time::Now();
+ WriteToCache(url, origin, std::string(), response_time);
+ scoped_task_environment_.RunUntilIdle();
+ FetchFromCache(url, origin);
+ scoped_task_environment_.RunUntilIdle();
+
+ ASSERT_TRUE(received_);
+ ASSERT_TRUE(received_null_);
+ EXPECT_EQ(response_time, received_response_time_);
+}
+
TEST_F(GeneratedCodeCacheTest, FetchEntryPendingOp) {
GURL url(kInitialUrl);
url::Origin origin = url::Origin::Create(GURL(kInitialOrigin));
- InitializeCacheAndReOpen();
+ InitializeCacheAndReOpen(GeneratedCodeCache::CodeCacheType::kJavaScript);
FetchFromCache(url, origin);
scoped_task_environment_.RunUntilIdle();
@@ -183,7 +202,7 @@ TEST_F(GeneratedCodeCacheTest, WriteEntryPendingOp) {
GURL new_url("http://example1.com/script1.js");
url::Origin origin = url::Origin::Create(GURL(kInitialOrigin));
- InitializeCache();
+ InitializeCache(GeneratedCodeCache::CodeCacheType::kJavaScript);
std::string data = "SerializedCodeForScript";
base::Time response_time = base::Time::Now();
WriteToCache(new_url, origin, data, response_time);
@@ -200,7 +219,7 @@ TEST_F(GeneratedCodeCacheTest, DeleteEntryPendingOp) {
GURL url(kInitialUrl);
url::Origin origin = url::Origin::Create(GURL(kInitialOrigin));
- InitializeCacheAndReOpen();
+ InitializeCacheAndReOpen(GeneratedCodeCache::CodeCacheType::kJavaScript);
DeleteFromCache(url, origin);
FetchFromCache(url, origin);
scoped_task_environment_.RunUntilIdle();
@@ -213,7 +232,7 @@ TEST_F(GeneratedCodeCacheTest, UpdateDataOfExistingEntry) {
GURL url(kInitialUrl);
url::Origin origin = url::Origin::Create(GURL(kInitialOrigin));
- InitializeCache();
+ InitializeCache(GeneratedCodeCache::CodeCacheType::kJavaScript);
std::string new_data = "SerializedCodeForScriptOverwrite";
base::Time response_time = base::Time::Now();
WriteToCache(url, origin, new_data, response_time);
@@ -227,7 +246,7 @@ TEST_F(GeneratedCodeCacheTest, UpdateDataOfExistingEntry) {
}
TEST_F(GeneratedCodeCacheTest, FetchFailsForNonexistingOrigin) {
- InitializeCache();
+ InitializeCache(GeneratedCodeCache::CodeCacheType::kJavaScript);
url::Origin new_origin = url::Origin::Create(GURL("http://not-example.com"));
FetchFromCache(GURL(kInitialUrl), new_origin);
scoped_task_environment_.RunUntilIdle();
@@ -241,6 +260,7 @@ TEST_F(GeneratedCodeCacheTest, FetchEntriesFromSameOrigin) {
GURL second_url("http://script.com/one.js");
url::Origin origin = url::Origin::Create(GURL(kInitialOrigin));
+ InitializeCache(GeneratedCodeCache::CodeCacheType::kJavaScript);
std::string data_first_resource = "SerializedCodeForFirstResource";
WriteToCache(url, origin, data_first_resource, base::Time());
@@ -264,6 +284,7 @@ TEST_F(GeneratedCodeCacheTest, FetchSucceedsFromDifferentOrigins) {
url::Origin origin = url::Origin::Create(GURL("http://example.com"));
url::Origin origin1 = url::Origin::Create(GURL("http://example1.com"));
+ InitializeCache(GeneratedCodeCache::CodeCacheType::kJavaScript);
std::string data_origin = "SerializedCodeForFirstOrigin";
WriteToCache(url, origin, data_origin, base::Time());
@@ -287,6 +308,7 @@ TEST_F(GeneratedCodeCacheTest, FetchFailsForUniqueOrigin) {
url::Origin origin =
url::Origin::Create(GURL("data:text/html,<script></script>"));
+ InitializeCache(GeneratedCodeCache::CodeCacheType::kJavaScript);
std::string data = "SerializedCodeForUniqueOrigin";
WriteToCache(url, origin, data, base::Time());
scoped_task_environment_.RunUntilIdle();
@@ -301,6 +323,7 @@ TEST_F(GeneratedCodeCacheTest, FetchFailsForInvalidOrigin) {
GURL url("http://example.com/script.js");
url::Origin origin = url::Origin::Create(GURL("invalidURL"));
+ InitializeCache(GeneratedCodeCache::CodeCacheType::kJavaScript);
std::string data = "SerializedCodeForInvalidOrigin";
WriteToCache(url, origin, data, base::Time());
scoped_task_environment_.RunUntilIdle();
@@ -316,6 +339,7 @@ TEST_F(GeneratedCodeCacheTest, FetchFailsForInvalidURL) {
GURL url("InvalidURL");
url::Origin origin = url::Origin::Create(GURL("http://example.com"));
+ InitializeCache(GeneratedCodeCache::CodeCacheType::kJavaScript);
std::string data = "SerializedCodeForInvalidURL";
WriteToCache(url, origin, data, base::Time());
scoped_task_environment_.RunUntilIdle();
@@ -330,7 +354,7 @@ TEST_F(GeneratedCodeCacheTest, ClearCache) {
GURL url("http://example.com/script.js");
url::Origin origin = url::Origin::Create(GURL("http://example.com"));
- InitializeCache();
+ InitializeCache(GeneratedCodeCache::CodeCacheType::kJavaScript);
ClearCache();
scoped_task_environment_.RunUntilIdle();
FetchFromCache(url, origin);
@@ -339,4 +363,16 @@ TEST_F(GeneratedCodeCacheTest, ClearCache) {
ASSERT_TRUE(received_);
ASSERT_TRUE(received_null_);
}
+
+TEST_F(GeneratedCodeCacheTest, WasmCache) {
+ GURL url(kInitialUrl);
+ url::Origin origin = url::Origin::Create(GURL(kInitialOrigin));
+
+ InitializeCache(GeneratedCodeCache::CodeCacheType::kWebAssembly);
+ FetchFromCache(url, origin);
+ scoped_task_environment_.RunUntilIdle();
+
+ ASSERT_TRUE(received_);
+ EXPECT_EQ(kInitialData, received_data_);
+}
} // namespace content
diff --git a/chromium/content/browser/compositor/gpu_process_transport_factory.cc b/chromium/content/browser/compositor/gpu_process_transport_factory.cc
index 642fff3b436..e8741caf69a 100644
--- a/chromium/content/browser/compositor/gpu_process_transport_factory.cc
+++ b/chromium/content/browser/compositor/gpu_process_transport_factory.cc
@@ -48,9 +48,9 @@
#include "content/browser/gpu/compositor_util.h"
#include "content/browser/gpu/gpu_data_manager_impl.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
-#include "content/common/gpu_stream_constants.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_switches.h"
+#include "content/public/common/gpu_stream_constants.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu/command_buffer/client/raster_interface.h"
@@ -217,7 +217,7 @@ GpuProcessTransportFactory::CreateSoftwareOutputDevice(
return base::WrapUnique(new viz::SoftwareOutputDevice);
#if defined(USE_AURA)
- if (features::IsUsingWindowService()) {
+ if (features::IsMultiProcessMash()) {
NOTREACHED();
return nullptr;
}
@@ -344,8 +344,7 @@ void GpuProcessTransportFactory::EstablishedGpuChannel(
use_gpu_compositing = false;
// The widget might have been released in the meantime.
- PerCompositorDataMap::iterator it =
- per_compositor_data_.find(compositor.get());
+ auto it = per_compositor_data_.find(compositor.get());
if (it == per_compositor_data_.end())
return;
@@ -404,7 +403,7 @@ void GpuProcessTransportFactory::EstablishedGpuChannel(
auto result = shared_worker_context_provider_->BindToCurrentThread();
if (result != gpu::ContextResult::kSuccess) {
shared_worker_context_provider_ = nullptr;
- if (result == gpu::ContextResult::kFatalFailure)
+ if (gpu::IsFatalOrSurfaceFailure(result))
use_gpu_compositing = false;
}
}
@@ -434,7 +433,7 @@ void GpuProcessTransportFactory::EstablishedGpuChannel(
auto result = context_provider->BindToCurrentThread();
if (result != gpu::ContextResult::kSuccess) {
context_provider = nullptr;
- if (result == gpu::ContextResult::kFatalFailure)
+ if (gpu::IsFatalOrSurfaceFailure(result))
use_gpu_compositing = false;
}
}
@@ -708,7 +707,7 @@ void GpuProcessTransportFactory::RemoveReflector(ui::Reflector* reflector) {
}
void GpuProcessTransportFactory::RemoveCompositor(ui::Compositor* compositor) {
- PerCompositorDataMap::iterator it = per_compositor_data_.find(compositor);
+ auto it = per_compositor_data_.find(compositor);
if (it == per_compositor_data_.end())
return;
PerCompositorData* data = it->second.get();
@@ -780,7 +779,7 @@ GpuProcessTransportFactory::GetHostFrameSinkManager() {
void GpuProcessTransportFactory::SetDisplayVisible(ui::Compositor* compositor,
bool visible) {
- PerCompositorDataMap::iterator it = per_compositor_data_.find(compositor);
+ auto it = per_compositor_data_.find(compositor);
if (it == per_compositor_data_.end())
return;
PerCompositorData* data = it->second.get();
@@ -793,7 +792,7 @@ void GpuProcessTransportFactory::SetDisplayVisible(ui::Compositor* compositor,
void GpuProcessTransportFactory::ResizeDisplay(ui::Compositor* compositor,
const gfx::Size& size) {
- PerCompositorDataMap::iterator it = per_compositor_data_.find(compositor);
+ auto it = per_compositor_data_.find(compositor);
if (it == per_compositor_data_.end())
return;
PerCompositorData* data = it->second.get();
@@ -804,7 +803,7 @@ void GpuProcessTransportFactory::ResizeDisplay(ui::Compositor* compositor,
void GpuProcessTransportFactory::DisableSwapUntilResize(
ui::Compositor* compositor) {
- PerCompositorDataMap::iterator it = per_compositor_data_.find(compositor);
+ auto it = per_compositor_data_.find(compositor);
if (it == per_compositor_data_.end())
return;
PerCompositorData* data = it->second.get();
@@ -816,7 +815,7 @@ void GpuProcessTransportFactory::DisableSwapUntilResize(
void GpuProcessTransportFactory::SetDisplayColorMatrix(
ui::Compositor* compositor,
const SkMatrix44& matrix) {
- PerCompositorDataMap::iterator it = per_compositor_data_.find(compositor);
+ auto it = per_compositor_data_.find(compositor);
if (it == per_compositor_data_.end())
return;
PerCompositorData* data = it->second.get();
@@ -830,7 +829,7 @@ void GpuProcessTransportFactory::SetDisplayColorSpace(
ui::Compositor* compositor,
const gfx::ColorSpace& blending_color_space,
const gfx::ColorSpace& output_color_space) {
- PerCompositorDataMap::iterator it = per_compositor_data_.find(compositor);
+ auto it = per_compositor_data_.find(compositor);
if (it == per_compositor_data_.end())
return;
PerCompositorData* data = it->second.get();
@@ -841,23 +840,11 @@ void GpuProcessTransportFactory::SetDisplayColorSpace(
data->display->SetColorSpace(blending_color_space, output_color_space);
}
-void GpuProcessTransportFactory::SetAuthoritativeVSyncInterval(
- ui::Compositor* compositor,
- base::TimeDelta interval) {
- PerCompositorDataMap::iterator it = per_compositor_data_.find(compositor);
- if (it == per_compositor_data_.end())
- return;
- PerCompositorData* data = it->second.get();
- DCHECK(data);
- if (data->synthetic_begin_frame_source)
- data->synthetic_begin_frame_source->SetAuthoritativeVSyncInterval(interval);
-}
-
void GpuProcessTransportFactory::SetDisplayVSyncParameters(
ui::Compositor* compositor,
base::TimeTicks timebase,
base::TimeDelta interval) {
- PerCompositorDataMap::iterator it = per_compositor_data_.find(compositor);
+ auto it = per_compositor_data_.find(compositor);
if (it == per_compositor_data_.end())
return;
PerCompositorData* data = it->second.get();
@@ -871,7 +858,7 @@ void GpuProcessTransportFactory::SetDisplayVSyncParameters(
void GpuProcessTransportFactory::IssueExternalBeginFrame(
ui::Compositor* compositor,
const viz::BeginFrameArgs& args) {
- PerCompositorDataMap::iterator it = per_compositor_data_.find(compositor);
+ auto it = per_compositor_data_.find(compositor);
if (it == per_compositor_data_.end())
return;
PerCompositorData* data = it->second.get();
@@ -882,7 +869,7 @@ void GpuProcessTransportFactory::IssueExternalBeginFrame(
void GpuProcessTransportFactory::SetOutputIsSecure(ui::Compositor* compositor,
bool secure) {
- PerCompositorDataMap::iterator it = per_compositor_data_.find(compositor);
+ auto it = per_compositor_data_.find(compositor);
if (it == per_compositor_data_.end())
return;
PerCompositorData* data = it->second.get();
@@ -1071,13 +1058,16 @@ GpuProcessTransportFactory::CreateContextCommon(
attributes.enable_gles2_interface = support_gles2_interface;
attributes.enable_raster_interface = support_raster_interface;
+ gpu::SharedMemoryLimits memory_limits =
+ gpu::SharedMemoryLimits::ForDisplayCompositor();
+
constexpr bool automatic_flushes = false;
GURL url("chrome://gpu/GpuProcessTransportFactory::CreateContextCommon");
return base::MakeRefCounted<ws::ContextProviderCommandBuffer>(
std::move(gpu_channel_host), GetGpuMemoryBufferManager(), stream_id,
stream_priority, surface_handle, url, automatic_flushes, support_locking,
- support_grcontext, gpu::SharedMemoryLimits(), attributes, type);
+ support_grcontext, memory_limits, 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 08384de8696..b9f2cf332cd 100644
--- a/chromium/content/browser/compositor/gpu_process_transport_factory.h
+++ b/chromium/content/browser/compositor/gpu_process_transport_factory.h
@@ -96,8 +96,6 @@ class GpuProcessTransportFactory : public ui::ContextFactory,
void SetDisplayColorSpace(ui::Compositor* compositor,
const gfx::ColorSpace& blending_color_space,
const gfx::ColorSpace& output_color_space) override;
- void SetAuthoritativeVSyncInterval(ui::Compositor* compositor,
- base::TimeDelta interval) override;
void SetDisplayVSyncParameters(ui::Compositor* compositor,
base::TimeTicks timebase,
base::TimeDelta interval) override;
diff --git a/chromium/content/browser/compositor/reflector_impl_unittest.cc b/chromium/content/browser/compositor/reflector_impl_unittest.cc
index 40a83a865a1..21319bfc09d 100644
--- a/chromium/content/browser/compositor/reflector_impl_unittest.cc
+++ b/chromium/content/browser/compositor/reflector_impl_unittest.cc
@@ -6,9 +6,9 @@
#include "base/callback.h"
#include "base/feature_list.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"
#include "build/build_config.h"
#include "components/viz/common/features.h"
#include "components/viz/common/frame_sinks/begin_frame_source.h"
@@ -134,12 +134,11 @@ class ReflectorImplTest : public testing::Test {
ui::ContextFactory* context_factory = nullptr;
ui::ContextFactoryPrivate* context_factory_private = nullptr;
- message_loop_ = std::make_unique<base::MessageLoop>();
ui::InitializeContextFactoryForTests(enable_pixel_output, &context_factory,
&context_factory_private);
ImageTransportFactory::SetFactory(
std::make_unique<TestImageTransportFactory>());
- task_runner_ = message_loop_->task_runner();
+ task_runner_ = base::ThreadTaskRunnerHandle::Get();
compositor_task_runner_ = new FakeTaskRunner();
begin_frame_source_ = std::make_unique<viz::DelayBasedBeginFrameSource>(
std::make_unique<viz::DelayBasedTimeSource>(
@@ -193,7 +192,7 @@ class ReflectorImplTest : public testing::Test {
protected:
scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner_;
std::unique_ptr<viz::SyntheticBeginFrameSource> begin_frame_source_;
- std::unique_ptr<base::MessageLoop> message_loop_;
+ base::test::ScopedTaskEnvironment task_environment_;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
std::unique_ptr<ui::Compositor> compositor_;
std::unique_ptr<ui::Layer> root_layer_;
diff --git a/chromium/content/browser/compositor/viz_process_transport_factory.cc b/chromium/content/browser/compositor/viz_process_transport_factory.cc
index 07fe6eeaf90..8ae1f00fdbc 100644
--- a/chromium/content/browser/compositor/viz_process_transport_factory.cc
+++ b/chromium/content/browser/compositor/viz_process_transport_factory.cc
@@ -10,6 +10,7 @@
#include "base/command_line.h"
#include "base/debug/dump_without_crashing.h"
#include "base/single_thread_task_runner.h"
+#include "base/task/post_task.h"
#include "cc/mojo_embedder/async_layer_tree_frame_sink.h"
#include "cc/raster/single_thread_task_graph_runner.h"
#include "components/viz/client/hit_test_data_provider_draw_quad.h"
@@ -25,10 +26,11 @@
#include "content/browser/gpu/compositor_util.h"
#include "content/browser/gpu/gpu_data_manager_impl.h"
#include "content/browser/gpu/gpu_process_host.h"
-#include "content/common/gpu_stream_constants.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
+#include "content/public/common/gpu_stream_constants.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu/command_buffer/client/raster_interface.h"
#include "gpu/ipc/client/gpu_channel_host.h"
@@ -69,12 +71,15 @@ scoped_refptr<ws::ContextProviderCommandBuffer> CreateContextProviderImpl(
attributes.enable_gles2_interface = support_gles2_interface;
attributes.enable_raster_interface = support_raster_interface;
+ gpu::SharedMemoryLimits memory_limits =
+ gpu::SharedMemoryLimits::ForDisplayCompositor();
+
GURL url("chrome://gpu/VizProcessTransportFactory::CreateContextProvider");
return base::MakeRefCounted<ws::ContextProviderCommandBuffer>(
std::move(gpu_channel_host), gpu_memory_buffer_manager,
kGpuStreamIdDefault, kGpuStreamPriorityUI, gpu::kNullSurfaceHandle,
std::move(url), kAutomaticFlushes, support_locking, support_grcontext,
- gpu::SharedMemoryLimits(), attributes, type);
+ memory_limits, attributes, type);
}
bool IsContextLost(viz::ContextProvider* context_provider) {
@@ -170,8 +175,8 @@ void VizProcessTransportFactory::ConnectHostFrameSinkManager() {
std::move(request), std::move(client));
}
};
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(connect_on_io_thread,
std::move(frame_sink_manager_request),
frame_sink_manager_client.PassInterface()));
@@ -204,6 +209,10 @@ void VizProcessTransportFactory::CreateLayerTreeFrameSink(
compositor->widget());
#endif
+ // Create the data map entry so that we can set properties like output secure
+ // while we are waiting for the GpuChannel to be established.
+ AddCompositor(compositor.get());
+
if (is_gpu_compositing_disabled() ||
compositor->force_software_compositor()) {
OnEstablishedGpuChannel(compositor, nullptr);
@@ -225,10 +234,11 @@ VizProcessTransportFactory::SharedMainThreadContextProvider() {
context_result = TryCreateContextsForGpuCompositing(
gpu_channel_establish_factory_->EstablishGpuChannelSync());
- if (context_result == gpu::ContextResult::kFatalFailure)
+ if (gpu::IsFatalOrSurfaceFailure(context_result))
DisableGpuCompositing(nullptr);
}
- // On kFatalFailure |main_context_provider_| will be null.
+ // On kFatalFailure or kSurfaceFailure, |main_context_provider_| will be
+ // null.
}
return main_context_provider_;
@@ -367,7 +377,7 @@ void VizProcessTransportFactory::OnEstablishedGpuChannel(
base::BindOnce(&VizProcessTransportFactory::OnEstablishedGpuChannel,
weak_ptr_factory_.GetWeakPtr(), compositor_weak_ptr));
return;
- } else if (context_result == gpu::ContextResult::kFatalFailure) {
+ } else if (gpu::IsFatalOrSurfaceFailure(context_result)) {
DisableGpuCompositing(compositor);
gpu_compositing = false;
}
@@ -380,7 +390,7 @@ void VizProcessTransportFactory::OnEstablishedGpuChannel(
compositor_context = main_context_provider_;
worker_context = worker_context_provider_;
}
- ConfigureCompositor(compositor_weak_ptr, std::move(compositor_context),
+ ConfigureCompositor(compositor, std::move(compositor_context),
std::move(worker_context));
}
diff --git a/chromium/content/browser/compositor/viz_process_transport_factory.h b/chromium/content/browser/compositor/viz_process_transport_factory.h
index 41619afe58d..5823501edca 100644
--- a/chromium/content/browser/compositor/viz_process_transport_factory.h
+++ b/chromium/content/browser/compositor/viz_process_transport_factory.h
@@ -104,8 +104,8 @@ class VizProcessTransportFactory : public ui::ContextFactory,
// blacklisted.
//
// Returns kSuccess if caller can use GPU compositing, kTransientFailure if
- // caller should try again or kFatalFailure if caller should fallback to
- // software compositing.
+ // caller should try again or kFatalFailure/kSurfaceFailure if caller should
+ // fallback to software compositing.
gpu::ContextResult TryCreateContextsForGpuCompositing(
scoped_refptr<gpu::GpuChannelHost> gpu_channel_host);
diff --git a/chromium/content/browser/content_service_browsertest.cc b/chromium/content/browser/content_service_browsertest.cc
index 633ff83f863..8c45554d59a 100644
--- a/chromium/content/browser/content_service_browsertest.cc
+++ b/chromium/content/browser/content_service_browsertest.cc
@@ -34,25 +34,107 @@ class ContentServiceBrowserTest : public ContentBrowserTest {
CHECK(embedded_test_server()->Start());
}
+ protected:
+ content::mojom::NavigableContentsFactory* GetFactory() {
+ if (!factory_) {
+ auto* connector = BrowserContext::GetConnectorFor(
+ shell()->web_contents()->GetBrowserContext());
+ connector->BindInterface(content::mojom::kServiceName, &factory_);
+ }
+ return factory_.get();
+ }
+
private:
+ content::mojom::NavigableContentsFactoryPtr factory_;
+
DISALLOW_COPY_AND_ASSIGN(ContentServiceBrowserTest);
};
+class StopLoadingObserver : public content::NavigableContentsObserver {
+ public:
+ StopLoadingObserver() {}
+ ~StopLoadingObserver() override {}
+
+ void CallOnNextStopLoading(base::OnceClosure callback) {
+ callback_ = std::move(callback);
+ }
+
+ private:
+ // content::NavigableContentsObserver:
+ void DidStopLoading() override {
+ if (callback_)
+ std::move(callback_).Run();
+ }
+
+ base::OnceClosure callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(StopLoadingObserver);
+};
+
+class NavigationObserver : public content::NavigableContentsObserver {
+ public:
+ NavigationObserver() {}
+ ~NavigationObserver() override {}
+
+ void CallOnNextNavigation(base::OnceClosure callback) {
+ callback_ = std::move(callback);
+ }
+
+ size_t navigations_finished() const { return navigations_finished_; }
+ const GURL& last_url() const { return last_url_; }
+
+ private:
+ void DidFinishNavigation(
+ const GURL& url,
+ bool is_main_frame,
+ bool is_error_page,
+ const net::HttpResponseHeaders* response_headers) override {
+ ++navigations_finished_;
+ last_url_ = url;
+ if (callback_)
+ std::move(callback_).Run();
+ }
+
+ base::OnceClosure callback_;
+ size_t navigations_finished_ = 0;
+ GURL last_url_;
+
+ DISALLOW_COPY_AND_ASSIGN(NavigationObserver);
+};
+
// Verifies that the embedded Content Service is reachable. Does a basic
// end-to-end sanity check to also verify that a NavigableContents is backed by
// a WebContents instance in the browser.
IN_PROC_BROWSER_TEST_F(ContentServiceBrowserTest, EmbeddedContentService) {
- auto* browser_context = shell()->web_contents()->GetBrowserContext();
- auto* connector = BrowserContext::GetConnectorFor(browser_context);
+ auto contents = std::make_unique<NavigableContents>(GetFactory());
- content::mojom::NavigableContentsFactoryPtr factory;
- connector->BindInterface(content::mojom::kServiceName, &factory);
- auto contents = std::make_unique<content::NavigableContents>(factory.get());
+ const GURL kTestUrl = embedded_test_server()->GetURL("/hello.html");
+ StopLoadingObserver observer;
+ base::RunLoop loop;
+ observer.CallOnNextStopLoading(loop.QuitClosure());
+ contents->AddObserver(&observer);
+ contents->Navigate(kTestUrl);
+ loop.Run();
+ contents->RemoveObserver(&observer);
+}
+
+IN_PROC_BROWSER_TEST_F(ContentServiceBrowserTest, DidFinishNavigation) {
+ auto contents = std::make_unique<NavigableContents>(GetFactory());
+ const GURL kTestUrl = embedded_test_server()->GetURL("/hello.html");
+ NavigationObserver observer;
base::RunLoop loop;
- contents->set_did_stop_loading_callback_for_testing(loop.QuitClosure());
- contents->Navigate(embedded_test_server()->GetURL("/hello.html"));
+ observer.CallOnNextNavigation(loop.QuitClosure());
+ contents->AddObserver(&observer);
+ contents->Navigate(kTestUrl);
+
+ EXPECT_EQ(0u, observer.navigations_finished());
+
loop.Run();
+ contents->RemoveObserver(&observer);
+
+ EXPECT_EQ(1u, observer.navigations_finished());
+ EXPECT_EQ(kTestUrl, observer.last_url());
}
} // namespace
diff --git a/chromium/content/browser/content_service_delegate_impl.cc b/chromium/content/browser/content_service_delegate_impl.cc
index 40eb806f117..7c7f3f38d33 100644
--- a/chromium/content/browser/content_service_delegate_impl.cc
+++ b/chromium/content/browser/content_service_delegate_impl.cc
@@ -5,7 +5,10 @@
#include "content/browser/content_service_delegate_impl.h"
#include "base/macros.h"
+#include "content/public/browser/navigation_handle.h"
+#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_delegate.h"
#include "content/public/browser/web_contents_observer.h"
#include "services/content/navigable_contents_delegate.h"
#include "services/content/service.h"
@@ -17,14 +20,19 @@ namespace {
// Bridge between Content Service navigable contents delegation API and a
// WebContentsImpl.
class NavigableContentsDelegateImpl : public content::NavigableContentsDelegate,
+ public WebContentsDelegate,
public WebContentsObserver {
public:
- explicit NavigableContentsDelegateImpl(BrowserContext* browser_context,
- mojom::NavigableContentsClient* client)
- : client_(client) {
- WebContents::CreateParams params(browser_context);
- web_contents_ = WebContents::Create(params);
+ explicit NavigableContentsDelegateImpl(
+ BrowserContext* browser_context,
+ const mojom::NavigableContentsParams& params,
+ mojom::NavigableContentsClient* client)
+ : client_(client),
+ enable_view_auto_resize_(params.enable_view_auto_resize) {
+ WebContents::CreateParams create_params(browser_context);
+ web_contents_ = WebContents::Create(create_params);
WebContentsObserver::Observe(web_contents_.get());
+ web_contents_->SetDelegate(this);
}
~NavigableContentsDelegateImpl() override {
@@ -37,18 +45,48 @@ class NavigableContentsDelegateImpl : public content::NavigableContentsDelegate,
return web_contents_->GetNativeView();
}
- void Navigate(const GURL& url) override {
- NavigationController::LoadURLParams params(url);
- params.transition_type = ui::PAGE_TRANSITION_AUTO_TOPLEVEL;
- web_contents_->GetController().LoadURLWithParams(params);
+ void Navigate(const GURL& url,
+ content::mojom::NavigateParamsPtr params) override {
+ NavigationController::LoadURLParams load_url_params(url);
+ load_url_params.transition_type = ui::PAGE_TRANSITION_AUTO_TOPLEVEL;
+ load_url_params.should_clear_history_list =
+ params->should_clear_session_history;
+ web_contents_->GetController().LoadURLWithParams(load_url_params);
+ }
+
+ // WebContentsDelegate:
+ void ResizeDueToAutoResize(WebContents* web_contents,
+ const gfx::Size& new_size) override {
+ DCHECK_EQ(web_contents, web_contents_.get());
+ client_->DidAutoResizeView(new_size);
}
// WebContentsObserver:
+ void RenderViewHostChanged(RenderViewHost* old_host,
+ RenderViewHost* new_host) override {
+ if (enable_view_auto_resize_ && web_contents_->GetRenderWidgetHostView()) {
+ web_contents_->GetRenderWidgetHostView()->EnableAutoResize(
+ gfx::Size(1, 1), gfx::Size(INT_MAX, INT_MAX));
+ }
+ }
+
+ void DidFinishNavigation(NavigationHandle* navigation_handle) override {
+ client_->DidFinishNavigation(
+ navigation_handle->GetURL(), navigation_handle->IsInMainFrame(),
+ navigation_handle->IsErrorPage(),
+ navigation_handle->GetResponseHeaders()
+ ? base::MakeRefCounted<net::HttpResponseHeaders>(
+ navigation_handle->GetResponseHeaders()->raw_headers())
+ : nullptr);
+ }
+
void DidStopLoading() override { client_->DidStopLoading(); }
std::unique_ptr<WebContents> web_contents_;
mojom::NavigableContentsClient* const client_;
+ const bool enable_view_auto_resize_;
+
DISALLOW_COPY_AND_ASSIGN(NavigableContentsDelegateImpl);
};
@@ -82,9 +120,10 @@ void ContentServiceDelegateImpl::WillDestroyServiceInstance(
std::unique_ptr<content::NavigableContentsDelegate>
ContentServiceDelegateImpl::CreateNavigableContentsDelegate(
+ const mojom::NavigableContentsParams& params,
mojom::NavigableContentsClient* client) {
return std::make_unique<NavigableContentsDelegateImpl>(browser_context_,
- client);
+ params, client);
}
} // namespace content
diff --git a/chromium/content/browser/content_service_delegate_impl.h b/chromium/content/browser/content_service_delegate_impl.h
index 70b2295f950..4515c7f44aa 100644
--- a/chromium/content/browser/content_service_delegate_impl.h
+++ b/chromium/content/browser/content_service_delegate_impl.h
@@ -37,6 +37,7 @@ class ContentServiceDelegateImpl : public content::ServiceDelegate {
// content::ContentServiceDelegate:
void WillDestroyServiceInstance(content::Service* service) override;
std::unique_ptr<NavigableContentsDelegate> CreateNavigableContentsDelegate(
+ const mojom::NavigableContentsParams& params,
mojom::NavigableContentsClient* client) override;
BrowserContext* const browser_context_;
diff --git a/chromium/content/browser/cookie_store/cookie_store_context.cc b/chromium/content/browser/cookie_store/cookie_store_context.cc
index eeea0d01a97..84be95782e2 100644
--- a/chromium/content/browser/cookie_store/cookie_store_context.cc
+++ b/chromium/content/browser/cookie_store/cookie_store_context.cc
@@ -4,7 +4,9 @@
#include "content/browser/cookie_store/cookie_store_context.h"
+#include "base/task/post_task.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/storage_partition.h"
@@ -12,7 +14,7 @@ namespace content {
CookieStoreContext::CookieStoreContext()
: base::RefCountedDeleteOnSequence<CookieStoreContext>(
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)) {}
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO})) {}
CookieStoreContext::~CookieStoreContext() {
// The destructor must be called on the IO thread, because it runs
@@ -30,8 +32,8 @@ void CookieStoreContext::Initialize(
initialize_called_ = true;
#endif // DCHECK_IS_ON()
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&CookieStoreContext::InitializeOnIOThread, this,
std::move(service_worker_context),
@@ -56,8 +58,8 @@ void CookieStoreContext::ListenToCookieChanges(
network_context->GetCookieManager(
mojo::MakeRequest(&cookie_manager_ptr_info));
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&CookieStoreContext::ListenToCookieChangesOnIOThread, this,
std::move(cookie_manager_ptr_info),
@@ -77,8 +79,8 @@ void CookieStoreContext::CreateService(blink::mojom::CookieStoreRequest request,
DCHECK(initialize_called_) << __func__ << " called before Initialize()";
#endif // DCHECK_IS_ON()
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&CookieStoreContext::CreateServiceOnIOThread, this,
std::move(request), origin));
}
diff --git a/chromium/content/browser/cookie_store/cookie_store_manager_unittest.cc b/chromium/content/browser/cookie_store/cookie_store_manager_unittest.cc
index b74748e9a2a..0cd0a1336a7 100644
--- a/chromium/content/browser/cookie_store/cookie_store_manager_unittest.cc
+++ b/chromium/content/browser/cookie_store/cookie_store_manager_unittest.cc
@@ -167,7 +167,7 @@ class CookieStoreWorkerTestHelper : public EmbeddedWorkerTestHelper {
override {
changes_.emplace_back(cookie, cause);
std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
- base::Time::Now());
+ base::TimeTicks::Now());
}
private:
diff --git a/chromium/content/browser/devtools/browser_devtools_agent_host.cc b/chromium/content/browser/devtools/browser_devtools_agent_host.cc
index a83315a158b..bf38edb2d2c 100644
--- a/chromium/content/browser/devtools/browser_devtools_agent_host.cc
+++ b/chromium/content/browser/devtools/browser_devtools_agent_host.cc
@@ -52,7 +52,7 @@ BrowserDevToolsAgentHost::~BrowserDevToolsAgentHost() {
bool BrowserDevToolsAgentHost::AttachSession(DevToolsSession* session,
TargetRegistry* parent_registry) {
- if (session->restricted())
+ if (!session->client()->MayAttachToBrowser())
return false;
TargetRegistry* registry = parent_registry;
@@ -63,7 +63,7 @@ bool BrowserDevToolsAgentHost::AttachSession(DevToolsSession* session,
}
session->SetBrowserOnly(true);
session->AddHandler(std::make_unique<protocol::TargetHandler>(
- true /* browser_only */, GetId(), registry));
+ protocol::TargetHandler::AccessMode::kBrowser, GetId(), registry));
if (only_discovery_)
return true;
diff --git a/chromium/content/browser/devtools/devtools_agent_host_impl.cc b/chromium/content/browser/devtools/devtools_agent_host_impl.cc
index d32bd45d916..32d7899b635 100644
--- a/chromium/content/browser/devtools/devtools_agent_host_impl.cc
+++ b/chromium/content/browser/devtools/devtools_agent_host_impl.cc
@@ -13,7 +13,6 @@
#include "base/lazy_instance.h"
#include "base/observer_list.h"
#include "content/browser/devtools/devtools_manager.h"
-#include "content/browser/devtools/devtools_session.h"
#include "content/browser/devtools/forwarding_agent_host.h"
#include "content/browser/devtools/protocol/page.h"
#include "content/browser/devtools/protocol/security_handler.h"
@@ -115,7 +114,8 @@ DevToolsAgentHost::List DevToolsAgentHost::GetOrCreateAll() {
return result;
}
-DevToolsAgentHostImpl::DevToolsAgentHostImpl(const std::string& id) : id_(id) {
+DevToolsAgentHostImpl::DevToolsAgentHostImpl(const std::string& id)
+ : id_(id), renderer_channel_(this) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
}
@@ -129,7 +129,7 @@ scoped_refptr<DevToolsAgentHost> DevToolsAgentHost::GetForId(
const std::string& id) {
if (!g_devtools_instances.IsCreated())
return nullptr;
- DevToolsMap::iterator it = g_devtools_instances.Get().find(id);
+ auto it = g_devtools_instances.Get().find(id);
if (it == g_devtools_instances.Get().end())
return nullptr;
return it->second;
@@ -177,18 +177,14 @@ DevToolsSession* DevToolsAgentHostImpl::SessionByClient(
}
bool DevToolsAgentHostImpl::InnerAttachClient(DevToolsAgentHostClient* client,
- TargetRegistry* registry,
- bool restricted) {
+ TargetRegistry* registry) {
scoped_refptr<DevToolsAgentHostImpl> protect(this);
- DevToolsSession* session = new DevToolsSession(this, client, restricted);
- sessions_.insert(session);
- session_by_client_[client].reset(session);
- if (!AttachSession(session, registry)) {
- sessions_.erase(session);
- session_by_client_.erase(client);
+ auto session = std::make_unique<DevToolsSession>(this, client);
+ if (!AttachSession(session.get(), registry))
return false;
- }
-
+ renderer_channel_.AttachSession(session.get());
+ sessions_.insert(session.get());
+ session_by_client_[client] = std::move(session);
if (sessions_.size() == 1)
NotifyAttached();
DevToolsManager* manager = DevToolsManager::GetInstance();
@@ -197,10 +193,10 @@ bool DevToolsAgentHostImpl::InnerAttachClient(DevToolsAgentHostClient* client,
return true;
}
-void DevToolsAgentHostImpl::AttachClient(DevToolsAgentHostClient* client) {
+bool DevToolsAgentHostImpl::AttachClient(DevToolsAgentHostClient* client) {
if (SessionByClient(client))
- return;
- InnerAttachClient(client, nullptr, false /* restricted */);
+ return false;
+ return InnerAttachClient(client, nullptr);
}
void DevToolsAgentHostImpl::AttachSubtargetClient(
@@ -208,14 +204,7 @@ void DevToolsAgentHostImpl::AttachSubtargetClient(
TargetRegistry* registry) {
if (SessionByClient(client))
return;
- InnerAttachClient(client, registry, false /* restricted */);
-}
-
-bool DevToolsAgentHostImpl::AttachRestrictedClient(
- DevToolsAgentHostClient* client) {
- if (SessionByClient(client))
- return false;
- return InnerAttachClient(client, nullptr, true /* restricted */);
+ InnerAttachClient(client, registry);
}
bool DevToolsAgentHostImpl::DetachClient(DevToolsAgentHostClient* client) {
@@ -349,6 +338,8 @@ bool DevToolsAgentHostImpl::AttachSession(DevToolsSession* session,
void DevToolsAgentHostImpl::DetachSession(DevToolsSession* session) {}
+void DevToolsAgentHostImpl::UpdateRendererChannel(bool force) {}
+
// static
void DevToolsAgentHost::DetachAllClients() {
if (!g_devtools_instances.IsCreated())
@@ -357,12 +348,10 @@ void DevToolsAgentHost::DetachAllClients() {
// Make a copy, since detaching may lead to agent destruction, which
// removes it from the instances.
std::vector<scoped_refptr<DevToolsAgentHostImpl>> copy;
- for (DevToolsMap::iterator it(g_devtools_instances.Get().begin());
+ for (auto it(g_devtools_instances.Get().begin());
it != g_devtools_instances.Get().end(); ++it)
copy.push_back(it->second);
- for (std::vector<scoped_refptr<DevToolsAgentHostImpl>>::iterator it(
- copy.begin());
- it != copy.end(); ++it)
+ for (auto it(copy.begin()); it != copy.end(); ++it)
it->get()->ForceDetachAllSessions();
}
diff --git a/chromium/content/browser/devtools/devtools_agent_host_impl.h b/chromium/content/browser/devtools/devtools_agent_host_impl.h
index 0910548167e..1db750429e3 100644
--- a/chromium/content/browser/devtools/devtools_agent_host_impl.h
+++ b/chromium/content/browser/devtools/devtools_agent_host_impl.h
@@ -14,6 +14,8 @@
#include "base/containers/flat_set.h"
#include "base/process/kill.h"
#include "content/browser/devtools/devtools_io_context.h"
+#include "content/browser/devtools/devtools_renderer_channel.h"
+#include "content/browser/devtools/devtools_session.h"
#include "content/common/content_export.h"
#include "content/public/browser/certificate_request_result_type.h"
#include "content/public/browser/devtools_agent_host.h"
@@ -22,7 +24,6 @@
namespace content {
class BrowserContext;
-class DevToolsSession;
class TargetRegistry;
// Describes interface for managing devtools agents from the browser process.
@@ -38,8 +39,7 @@ class CONTENT_EXPORT DevToolsAgentHostImpl : public DevToolsAgentHost {
CertErrorCallback callback);
// DevToolsAgentHost implementation.
- void AttachClient(DevToolsAgentHostClient* client) override;
- bool AttachRestrictedClient(DevToolsAgentHostClient* client) override;
+ bool AttachClient(DevToolsAgentHostClient* client) override;
bool DetachClient(DevToolsAgentHostClient* client) override;
bool DispatchProtocolMessage(DevToolsAgentHostClient* client,
const std::string& message) override;
@@ -59,6 +59,19 @@ class CONTENT_EXPORT DevToolsAgentHostImpl : public DevToolsAgentHost {
bool Inspect();
+ template <typename Handler>
+ std::vector<Handler*> HandlersByName(const std::string& name) {
+ std::vector<Handler*> result;
+ if (sessions_.empty())
+ return result;
+ for (DevToolsSession* session : sessions_) {
+ auto it = session->handlers().find(name);
+ if (it != session->handlers().end())
+ result.push_back(static_cast<Handler*>(it->second.get()));
+ }
+ return result;
+ }
+
protected:
DevToolsAgentHostImpl(const std::string& id);
~DevToolsAgentHostImpl() override;
@@ -69,11 +82,11 @@ class CONTENT_EXPORT DevToolsAgentHostImpl : public DevToolsAgentHost {
virtual bool AttachSession(DevToolsSession* session,
TargetRegistry* registry);
virtual void DetachSession(DevToolsSession* session);
-
virtual bool DispatchProtocolMessage(
DevToolsAgentHostClient* client,
const std::string& message,
std::unique_ptr<base::DictionaryValue> parsed_message);
+ virtual void UpdateRendererChannel(bool force);
void NotifyCreated();
void NotifyNavigated();
@@ -82,17 +95,17 @@ class CONTENT_EXPORT DevToolsAgentHostImpl : public DevToolsAgentHost {
void ForceDetachRestrictedSessions(
const std::vector<DevToolsSession*>& restricted_sessions);
DevToolsIOContext* GetIOContext() { return &io_context_; }
+ DevToolsRendererChannel* GetRendererChannel() { return &renderer_channel_; }
base::flat_set<DevToolsSession*>& sessions() { return sessions_; }
private:
friend class DevToolsAgentHost; // for static methods
- friend class DevToolsSession;
friend class TargetRegistry; // for subtarget management
+ friend class DevToolsRendererChannel;
bool InnerAttachClient(DevToolsAgentHostClient* client,
- TargetRegistry* registry,
- bool restricted);
+ TargetRegistry* registry);
void InnerDetachClient(DevToolsAgentHostClient* client);
void NotifyAttached();
void NotifyDetached();
@@ -108,6 +121,7 @@ class CONTENT_EXPORT DevToolsAgentHostImpl : public DevToolsAgentHost {
base::flat_map<DevToolsAgentHostClient*, std::unique_ptr<DevToolsSession>>
session_by_client_;
DevToolsIOContext io_context_;
+ DevToolsRendererChannel renderer_channel_;
static int s_force_creation_count_;
};
diff --git a/chromium/content/browser/devtools/devtools_http_handler.cc b/chromium/content/browser/devtools/devtools_http_handler.cc
index a0ce6d621d8..baa7d79aec2 100644
--- a/chromium/content/browser/devtools/devtools_http_handler.cc
+++ b/chromium/content/browser/devtools/devtools_http_handler.cc
@@ -29,6 +29,7 @@
#include "content/browser/devtools/devtools_http_handler.h"
#include "content/browser/devtools/devtools_manager.h"
#include "content/browser/devtools/grit/devtools_resources.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/devtools_external_agent_proxy_delegate.h"
#include "content/public/browser/devtools_frontend_host.h"
@@ -295,8 +296,8 @@ void StartServerOnHandlerThread(
#endif
}
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&ServerStartedOnUI, std::move(handler), thread.release(),
server_wrapper.release(), socket_factory.release(),
std::move(ip_address)));
@@ -316,6 +317,7 @@ class DevToolsAgentHostClientImpl : public DevToolsAgentHostClient {
connection_id_(connection_id),
agent_host_(agent_host) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ // TODO(dgozman): handle return value of AttachClient.
agent_host_->AttachClient(this);
}
@@ -426,16 +428,16 @@ void ServerWrapper::OnHttpRequest(int connection_id,
server_->SetSendBufferSize(connection_id, kSendBufferSizeForDevTools);
if (base::StartsWith(info.path, "/json", base::CompareCase::SENSITIVE)) {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(&DevToolsHttpHandler::OnJsonRequest,
- handler_, connection_id, info));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(&DevToolsHttpHandler::OnJsonRequest,
+ handler_, connection_id, info));
return;
}
if (info.path.empty() || info.path == "/") {
// Discovery page request.
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&DevToolsHttpHandler::OnDiscoveryPageRequest, handler_,
connection_id));
return;
@@ -460,8 +462,8 @@ void ServerWrapper::OnHttpRequest(int connection_id,
}
if (bundles_resources_) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&DevToolsHttpHandler::OnFrontendResourceRequest,
handler_, connection_id, filename));
return;
@@ -472,23 +474,23 @@ void ServerWrapper::OnHttpRequest(int connection_id,
void ServerWrapper::OnWebSocketRequest(
int connection_id,
const net::HttpServerRequestInfo& request) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&DevToolsHttpHandler::OnWebSocketRequest, handler_,
connection_id, request));
}
void ServerWrapper::OnWebSocketMessage(int connection_id,
const std::string& data) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&DevToolsHttpHandler::OnWebSocketMessage, handler_,
connection_id, data));
}
void ServerWrapper::OnClose(int connection_id) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&DevToolsHttpHandler::OnClose, handler_, connection_id));
}
@@ -763,8 +765,7 @@ void DevToolsHttpHandler::OnWebSocketRequest(
void DevToolsHttpHandler::OnWebSocketMessage(
int connection_id,
const std::string& data) {
- ConnectionToClientMap::iterator it =
- connection_to_client_.find(connection_id);
+ auto it = connection_to_client_.find(connection_id);
if (it != connection_to_client_.end())
it->second->OnMessage(data);
}
diff --git a/chromium/content/browser/devtools/devtools_http_handler_unittest.cc b/chromium/content/browser/devtools/devtools_http_handler_unittest.cc
index 97ac6d57e1d..3e47c6c4b6b 100644
--- a/chromium/content/browser/devtools/devtools_http_handler_unittest.cc
+++ b/chromium/content/browser/devtools/devtools_http_handler_unittest.cc
@@ -17,8 +17,10 @@
#include "base/single_thread_task_runner.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
+#include "base/task/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/values.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/devtools_manager_delegate.h"
#include "content/public/browser/devtools_socket_factory.h"
@@ -59,7 +61,7 @@ class DummyServerSocket : public net::ServerSocket {
};
void QuitFromHandlerThread(const base::Closure& quit_closure) {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, quit_closure);
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI}, quit_closure);
}
class DummyServerSocketFactory : public DevToolsSocketFactory {
@@ -70,8 +72,7 @@ class DummyServerSocketFactory : public DevToolsSocketFactory {
quit_closure_2_(quit_closure_2) {}
~DummyServerSocketFactory() override {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE, quit_closure_2_);
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI}, quit_closure_2_);
}
protected:
diff --git a/chromium/content/browser/devtools/devtools_interceptor_controller.cc b/chromium/content/browser/devtools/devtools_interceptor_controller.cc
index a2c27cba5df..4ba252da7a4 100644
--- a/chromium/content/browser/devtools/devtools_interceptor_controller.cc
+++ b/chromium/content/browser/devtools/devtools_interceptor_controller.cc
@@ -5,9 +5,11 @@
#include "content/browser/devtools/devtools_interceptor_controller.h"
#include "base/supports_user_data.h"
+#include "base/task/post_task.h"
#include "content/browser/frame_host/frame_tree_node.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
namespace content {
@@ -34,8 +36,8 @@ DevToolsInterceptorController::StartInterceptingRequests(
std::unique_ptr<InterceptionHandle> handle(new InterceptionHandle(
std::move(registration_handle), interceptor_, filter_entry.get()));
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&DevToolsNetworkInterceptor::AddFilterEntry, interceptor_,
std::move(filter_entry)));
return handle;
@@ -47,8 +49,8 @@ void DevToolsInterceptorController::ContinueInterceptedRequest(
std::unique_ptr<ContinueInterceptedRequestCallback> callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&DevToolsNetworkInterceptor::ContinueInterceptedRequest,
interceptor_, interception_id, std::move(modifications),
std::move(callback)));
@@ -68,8 +70,8 @@ void DevToolsInterceptorController::GetResponseBody(
std::string interception_id,
std::unique_ptr<GetResponseBodyForInterceptionCallback> callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&DevToolsNetworkInterceptor::GetResponseBody, interceptor_,
std::move(interception_id), std::move(callback)));
}
@@ -116,16 +118,16 @@ InterceptionHandle::InterceptionHandle(
entry_(entry) {}
InterceptionHandle::~InterceptionHandle() {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&DevToolsNetworkInterceptor::RemoveFilterEntry,
interceptor_, entry_));
}
void InterceptionHandle::UpdatePatterns(
std::vector<DevToolsNetworkInterceptor::Pattern> patterns) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&DevToolsNetworkInterceptor::UpdatePatterns, interceptor_,
base::Unretained(entry_), std::move(patterns)));
}
diff --git a/chromium/content/browser/devtools/devtools_network_interceptor.cc b/chromium/content/browser/devtools/devtools_network_interceptor.cc
index e4206b1f0bd..7554d6ff982 100644
--- a/chromium/content/browser/devtools/devtools_network_interceptor.cc
+++ b/chromium/content/browser/devtools/devtools_network_interceptor.cc
@@ -25,8 +25,7 @@ DevToolsNetworkInterceptor::FilterEntry::FilterEntry(
DevToolsNetworkInterceptor::FilterEntry::FilterEntry(FilterEntry&&) {}
DevToolsNetworkInterceptor::FilterEntry::~FilterEntry() {}
-DevToolsNetworkInterceptor::Modifications::Modifications()
- : mark_as_canceled(false) {}
+DevToolsNetworkInterceptor::Modifications::Modifications() = default;
DevToolsNetworkInterceptor::Modifications::Modifications(
base::Optional<net::Error> error_reason,
@@ -36,16 +35,14 @@ DevToolsNetworkInterceptor::Modifications::Modifications(
protocol::Maybe<std::string> modified_post_data,
protocol::Maybe<protocol::Network::Headers> modified_headers,
protocol::Maybe<protocol::Network::AuthChallengeResponse>
- auth_challenge_response,
- bool mark_as_canceled)
+ auth_challenge_response)
: error_reason(std::move(error_reason)),
raw_response(std::move(raw_response)),
modified_url(std::move(modified_url)),
modified_method(std::move(modified_method)),
modified_post_data(std::move(modified_post_data)),
modified_headers(std::move(modified_headers)),
- auth_challenge_response(std::move(auth_challenge_response)),
- mark_as_canceled(mark_as_canceled) {}
+ auth_challenge_response(std::move(auth_challenge_response)) {}
DevToolsNetworkInterceptor::Modifications::~Modifications() {}
diff --git a/chromium/content/browser/devtools/devtools_network_interceptor.h b/chromium/content/browser/devtools/devtools_network_interceptor.h
index 43dbf902448..9d89ad6d55f 100644
--- a/chromium/content/browser/devtools/devtools_network_interceptor.h
+++ b/chromium/content/browser/devtools/devtools_network_interceptor.h
@@ -59,8 +59,7 @@ class DevToolsNetworkInterceptor {
protocol::Maybe<std::string> modified_post_data,
protocol::Maybe<protocol::Network::Headers> modified_headers,
protocol::Maybe<protocol::Network::AuthChallengeResponse>
- auth_challenge_response,
- bool mark_as_canceled);
+ auth_challenge_response);
~Modifications();
// If none of the following are set then the request will be allowed to
@@ -77,8 +76,6 @@ class DevToolsNetworkInterceptor {
// AuthChallengeResponse is mutually exclusive with the above.
protocol::Maybe<protocol::Network::AuthChallengeResponse>
auth_challenge_response;
-
- bool mark_as_canceled;
};
enum InterceptionStage {
diff --git a/chromium/content/browser/devtools/devtools_pipe_handler.cc b/chromium/content/browser/devtools/devtools_pipe_handler.cc
index 8552cf21711..ea1c61db746 100644
--- a/chromium/content/browser/devtools/devtools_pipe_handler.cc
+++ b/chromium/content/browser/devtools/devtools_pipe_handler.cc
@@ -23,6 +23,7 @@
#include "base/task/post_task.h"
#include "base/threading/thread.h"
#include "build/build_config.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/devtools_agent_host.h"
#include "net/server/http_connection.h"
@@ -152,8 +153,8 @@ bool PipeReader::HandleReadResult(int result) {
if (read_buffer_->StartOfBuffer()[i] == '\0') {
std::string str(read_buffer_->StartOfBuffer() + offset, i - offset);
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&DevToolsPipeHandler::HandleMessage, devtools_handler_,
std::move(str)));
offset = i + 1;
@@ -165,8 +166,8 @@ bool PipeReader::HandleReadResult(int result) {
}
void PipeReader::ConnectionClosed() {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&DevToolsPipeHandler::Shutdown, devtools_handler_));
}
diff --git a/chromium/content/browser/devtools/devtools_renderer_channel.cc b/chromium/content/browser/devtools/devtools_renderer_channel.cc
new file mode 100644
index 00000000000..bd09fc1e7bb
--- /dev/null
+++ b/chromium/content/browser/devtools/devtools_renderer_channel.cc
@@ -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.
+
+#include "content/browser/devtools/devtools_renderer_channel.h"
+
+#include "content/browser/devtools/devtools_agent_host_impl.h"
+#include "content/browser/devtools/devtools_session.h"
+#include "content/browser/devtools/protocol/devtools_domain_handler.h"
+#include "content/public/common/child_process_host.h"
+#include "ui/gfx/geometry/point.h"
+
+namespace content {
+
+DevToolsRendererChannel::DevToolsRendererChannel(DevToolsAgentHostImpl* owner)
+ : owner_(owner),
+ binding_(this),
+ process_id_(ChildProcessHost::kInvalidUniqueID) {}
+
+DevToolsRendererChannel::~DevToolsRendererChannel() = default;
+
+void DevToolsRendererChannel::SetRenderer(
+ blink::mojom::DevToolsAgentAssociatedPtr agent_ptr,
+ blink::mojom::DevToolsAgentHostAssociatedRequest host_request,
+ int process_id,
+ RenderFrameHostImpl* frame_host) {
+ binding_.Close();
+ if (host_request)
+ binding_.Bind(std::move(host_request));
+ agent_ptr_ = std::move(agent_ptr);
+ process_id_ = process_id;
+ frame_host_ = frame_host;
+ for (DevToolsSession* session : owner_->sessions()) {
+ for (auto& pair : session->handlers())
+ pair.second->SetRenderer(process_id_, frame_host_);
+ session->AttachToAgent(agent_ptr_.get());
+ }
+}
+
+void DevToolsRendererChannel::AttachSession(DevToolsSession* session) {
+ if (!agent_ptr_)
+ owner_->UpdateRendererChannel(true /* force */);
+ for (auto& pair : session->handlers())
+ pair.second->SetRenderer(process_id_, frame_host_);
+ session->AttachToAgent(agent_ptr_.get());
+}
+
+void DevToolsRendererChannel::InspectElement(const gfx::Point& point) {
+ if (!agent_ptr_)
+ owner_->UpdateRendererChannel(true /* force */);
+ // Previous call might update |agent_ptr_|
+ // via SetRenderer(), so we should check it again.
+ if (agent_ptr_)
+ agent_ptr_->InspectElement(point);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/devtools/devtools_renderer_channel.h b/chromium/content/browser/devtools/devtools_renderer_channel.h
new file mode 100644
index 00000000000..1e390457bac
--- /dev/null
+++ b/chromium/content/browser/devtools/devtools_renderer_channel.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_RENDERER_CHANNEL_H_
+#define CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_RENDERER_CHANNEL_H_
+
+#include "base/macros.h"
+#include "content/common/content_export.h"
+#include "mojo/public/cpp/bindings/associated_binding.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "third_party/blink/public/web/devtools_agent.mojom.h"
+
+namespace gfx {
+class Point;
+}
+
+namespace content {
+
+class DevToolsAgentHostImpl;
+class DevToolsSession;
+class RenderFrameHostImpl;
+
+// This class encapsulates a connection to blink::mojom::DevToolsAgent
+// in the renderer.
+// When the renderer changes, different DevToolsAgentHostImpl subclasses
+// retrieve a new blink::mojom::DevToolsAgent pointer, and this channel
+// starts using it for all existing and future sessions.
+class CONTENT_EXPORT DevToolsRendererChannel
+ : public blink::mojom::DevToolsAgentHost {
+ public:
+ explicit DevToolsRendererChannel(DevToolsAgentHostImpl* owner);
+ ~DevToolsRendererChannel() override;
+
+ void SetRenderer(
+ blink::mojom::DevToolsAgentAssociatedPtr agent_ptr,
+ blink::mojom::DevToolsAgentHostAssociatedRequest host_request,
+ int process_id,
+ RenderFrameHostImpl* frame_host);
+ void AttachSession(DevToolsSession* session);
+ void InspectElement(const gfx::Point& point);
+
+ private:
+ DevToolsAgentHostImpl* owner_;
+ mojo::AssociatedBinding<blink::mojom::DevToolsAgentHost> binding_;
+ blink::mojom::DevToolsAgentAssociatedPtr agent_ptr_;
+ int process_id_;
+ RenderFrameHostImpl* frame_host_ = nullptr;
+
+ DISALLOW_COPY_AND_ASSIGN(DevToolsRendererChannel);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_RENDERER_CHANNEL_H_
diff --git a/chromium/content/browser/devtools/devtools_session.cc b/chromium/content/browser/devtools/devtools_session.cc
index 0d91850d5e7..fa29cf6a41f 100644
--- a/chromium/content/browser/devtools/devtools_session.cc
+++ b/chromium/content/browser/devtools/devtools_session.cc
@@ -7,11 +7,11 @@
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
#include "content/browser/devtools/devtools_manager.h"
+#include "content/browser/devtools/protocol/devtools_domain_handler.h"
#include "content/browser/devtools/protocol/protocol.h"
#include "content/browser/devtools/render_frame_devtools_agent_host.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/public/browser/devtools_manager_delegate.h"
-#include "content/public/common/child_process_host.h"
namespace content {
@@ -32,17 +32,12 @@ bool ShouldSendOnIO(const std::string& method) {
} // namespace
DevToolsSession::DevToolsSession(DevToolsAgentHostImpl* agent_host,
- DevToolsAgentHostClient* client,
- bool restricted)
+ DevToolsAgentHostClient* client)
: binding_(this),
agent_host_(agent_host),
client_(client),
- restricted_(restricted),
- process_host_id_(ChildProcessHost::kInvalidUniqueID),
- host_(nullptr),
dispatcher_(new protocol::UberDispatcher(this)),
- weak_factory_(this) {
-}
+ weak_factory_(this) {}
DevToolsSession::~DevToolsSession() {
// It is Ok for session to be deleted without the dispose -
@@ -61,24 +56,21 @@ void DevToolsSession::Dispose() {
void DevToolsSession::AddHandler(
std::unique_ptr<protocol::DevToolsDomainHandler> handler) {
handler->Wire(dispatcher_.get());
- handler->SetRenderer(process_host_id_, host_);
handlers_[handler->name()] = std::move(handler);
}
-void DevToolsSession::SetRenderer(int process_host_id,
- RenderFrameHostImpl* frame_host) {
- process_host_id_ = process_host_id;
- host_ = frame_host;
- for (auto& pair : handlers_)
- pair.second->SetRenderer(process_host_id_, host_);
-}
-
void DevToolsSession::SetBrowserOnly(bool browser_only) {
browser_only_ = browser_only;
}
-void DevToolsSession::AttachToAgent(
- const blink::mojom::DevToolsAgentAssociatedPtr& agent) {
+void DevToolsSession::AttachToAgent(blink::mojom::DevToolsAgent* agent) {
+ if (!agent) {
+ binding_.Close();
+ session_ptr_.reset();
+ io_session_ptr_.reset();
+ return;
+ }
+
blink::mojom::DevToolsSessionHostAssociatedPtrInfo host_ptr_info;
binding_.Bind(mojo::MakeRequest(&host_ptr_info));
agent->AttachDevToolsSession(
diff --git a/chromium/content/browser/devtools/devtools_session.h b/chromium/content/browser/devtools/devtools_session.h
index 467edb43869..b845a54446a 100644
--- a/chromium/content/browser/devtools/devtools_session.h
+++ b/chromium/content/browser/devtools/devtools_session.h
@@ -11,58 +11,46 @@
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "base/values.h"
-#include "content/browser/devtools/devtools_agent_host_impl.h"
-#include "content/browser/devtools/protocol/devtools_domain_handler.h"
+#include "content/browser/devtools/protocol/forward.h"
#include "mojo/public/cpp/bindings/associated_binding.h"
#include "third_party/blink/public/web/devtools_agent.mojom.h"
namespace content {
class DevToolsAgentHostClient;
-class RenderFrameHostImpl;
+class DevToolsAgentHostImpl;
+
+namespace protocol {
+class DevToolsDomainHandler;
+}
class DevToolsSession : public protocol::FrontendChannel,
public blink::mojom::DevToolsSessionHost {
public:
DevToolsSession(DevToolsAgentHostImpl* agent_host,
- DevToolsAgentHostClient* client,
- bool restricted);
+ DevToolsAgentHostClient* client);
~DevToolsSession() override;
void Dispose();
- bool restricted() { return restricted_; }
- DevToolsAgentHost* agent_host() { return agent_host_; };
+ DevToolsAgentHostImpl* agent_host() { return agent_host_; };
DevToolsAgentHostClient* client() { return client_; };
// Browser-only sessions do not talk to mojom::DevToolsAgent, but instead
// handle all protocol messages locally in the browser process.
void SetBrowserOnly(bool browser_only);
-
void AddHandler(std::unique_ptr<protocol::DevToolsDomainHandler> handler);
- // TODO(dgozman): maybe combine this with AttachToAgent?
- void SetRenderer(int process_host_id, RenderFrameHostImpl* frame_host);
- void AttachToAgent(const blink::mojom::DevToolsAgentAssociatedPtr& agent);
+ void AttachToAgent(blink::mojom::DevToolsAgent* agent);
void DispatchProtocolMessage(
const std::string& message,
std::unique_ptr<base::DictionaryValue> parsed_message);
void SuspendSendingMessagesToAgent();
void ResumeSendingMessagesToAgent();
- template <typename Handler>
- static std::vector<Handler*> HandlersForAgentHost(
- DevToolsAgentHostImpl* agent_host,
- const std::string& name) {
- std::vector<Handler*> result;
- if (agent_host->sessions().empty())
- return result;
- for (DevToolsSession* session : agent_host->sessions()) {
- auto it = session->handlers_.find(name);
- if (it != session->handlers_.end())
- result.push_back(static_cast<Handler*>(it->second.get()));
- }
- return result;
- }
+ using HandlersMap =
+ base::flat_map<std::string,
+ std::unique_ptr<protocol::DevToolsDomainHandler>>;
+ HandlersMap& handlers() { return handlers_; }
private:
void SendResponse(std::unique_ptr<base::DictionaryValue> response);
@@ -101,12 +89,8 @@ class DevToolsSession : public protocol::FrontendChannel,
blink::mojom::DevToolsSessionPtr io_session_ptr_;
DevToolsAgentHostImpl* agent_host_;
DevToolsAgentHostClient* client_;
- bool restricted_;
bool browser_only_ = false;
- base::flat_map<std::string, std::unique_ptr<protocol::DevToolsDomainHandler>>
- handlers_;
- int process_host_id_;
- RenderFrameHostImpl* host_;
+ HandlersMap handlers_;
std::unique_ptr<protocol::UberDispatcher> dispatcher_;
// These messages were queued after suspending, not sent to the agent,
diff --git a/chromium/content/browser/devtools/devtools_stream_blob.cc b/chromium/content/browser/devtools/devtools_stream_blob.cc
index 2dca3fb2bfb..27135840da1 100644
--- a/chromium/content/browser/devtools/devtools_stream_blob.cc
+++ b/chromium/content/browser/devtools/devtools_stream_blob.cc
@@ -7,7 +7,9 @@
#include "base/base64.h"
#include "base/bind.h"
#include "base/strings/string_piece.h"
+#include "base/task/post_task.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/storage_partition.h"
#include "net/base/io_buffer.h"
@@ -29,7 +31,7 @@ DevToolsStreamBlob::ReadRequest::~ReadRequest() = default;
DevToolsStreamBlob::DevToolsStreamBlob()
: DevToolsIOContext::Stream(
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)),
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO})),
last_read_pos_(0),
failed_(false),
is_binary_(false) {}
@@ -64,18 +66,19 @@ scoped_refptr<DevToolsIOContext::Stream> DevToolsStreamBlob::Create(
}
void DevToolsStreamBlob::ReadRequest::Fail() {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(std::move(callback), nullptr, false,
- Stream::StatusFailure));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ 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)));
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(&DevToolsStreamBlob::OpenOnIO, this, context, handle,
+ std::move(callback)));
}
void DevToolsStreamBlob::Read(off_t position,
@@ -83,8 +86,8 @@ void DevToolsStreamBlob::Read(off_t position,
ReadCallback callback) {
std::unique_ptr<ReadRequest> request(
new ReadRequest(position, max_size, std::move(callback)));
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&DevToolsStreamBlob::ReadOnIO, this, std::move(request)));
}
@@ -115,8 +118,8 @@ void DevToolsStreamBlob::OnBlobConstructionComplete(
FailOnIO(std::move(open_callback_));
return;
}
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(std::move(open_callback_), true));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(std::move(open_callback_), true));
if (!pending_reads_.empty())
StartReadRequest();
}
@@ -141,8 +144,8 @@ void DevToolsStreamBlob::FailOnIO() {
}
void DevToolsStreamBlob::FailOnIO(OpenCallback callback) {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(std::move(callback), false));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(std::move(callback), false));
FailOnIO();
}
@@ -166,7 +169,7 @@ 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);
+ io_buf_ = base::MakeRefCounted<net::IOBufferWithSize>(request.max_size);
int bytes_read;
BlobReader::Status status = blob_reader_->Read(
io_buf_.get(), request.max_size, &bytes_read,
@@ -178,8 +181,8 @@ void DevToolsStreamBlob::BeginRead() {
bytes_read = blob_reader_->net_error();
DCHECK_LT(0, bytes_read);
}
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&DevToolsStreamBlob::OnReadComplete, this, bytes_read));
}
@@ -207,8 +210,8 @@ void DevToolsStreamBlob::OnReadComplete(int bytes_read) {
*data = std::string(io_buf_->data(), bytes_read);
}
}
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(std::move(request->callback), std::move(data),
base64_encoded, status));
if (!pending_reads_.empty())
diff --git a/chromium/content/browser/devtools/devtools_stream_file.cc b/chromium/content/browser/devtools/devtools_stream_file.cc
index 1e0aa6b6bd3..a258da32b6e 100644
--- a/chromium/content/browser/devtools/devtools_stream_file.cc
+++ b/chromium/content/browser/devtools/devtools_stream_file.cc
@@ -12,7 +12,7 @@
#include "base/task/lazy_task_runner.h"
#include "base/task/post_task.h"
#include "base/third_party/icu/icu_utf.h"
-#include "base/threading/thread_restrictions.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "storage/browser/fileapi/file_system_context.h"
@@ -46,7 +46,6 @@ DevToolsStreamFile::~DevToolsStreamFile() {
bool DevToolsStreamFile::InitOnFileSequenceIfNeeded() {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
- base::AssertBlockingAllowed();
if (had_errors_)
return false;
if (file_.IsValid())
@@ -122,9 +121,9 @@ void DevToolsStreamFile::ReadOnFileSequence(off_t position,
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));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(std::move(callback), std::move(data),
+ base64_encoded, status));
}
void DevToolsStreamFile::AppendOnFileSequence(
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 d07eca5061f..4e6a637f824 100644
--- a/chromium/content/browser/devtools/devtools_url_interceptor_request_job.cc
+++ b/chromium/content/browser/devtools/devtools_url_interceptor_request_job.cc
@@ -7,10 +7,12 @@
#include "base/base64.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/task/post_task.h"
#include "content/browser/devtools/protocol/network_handler.h"
#include "content/browser/devtools/protocol/page.h"
#include "content/browser/loader/download_utils_impl.h"
#include "content/browser/loader/resource_request_info_impl.h"
+#include "content/public/browser/browser_task_traits.h"
#include "ipc/ipc_channel.h"
#include "net/base/completion_once_callback.h"
#include "net/base/elements_upload_data_stream.h"
@@ -142,6 +144,7 @@ DevToolsURLInterceptorRequestJob::SubRequest::SubRequest(
resource_request_info->GetRequestID(),
resource_request_info->GetRenderFrameID(),
resource_request_info->IsMainFrame(),
+ resource_request_info->fetch_window_id(),
resource_request_info->GetResourceType(),
resource_request_info->GetPageTransition(),
resource_request_info->IsDownload(), resource_request_info->is_stream(),
@@ -273,7 +276,7 @@ DevToolsURLInterceptorRequestJob::InterceptedRequest::InterceptedRequest(
: SubRequest(request_details,
devtools_interceptor_request_job,
interceptor),
- response_buffer_(new net::GrowableIOBuffer()),
+ response_buffer_(base::MakeRefCounted<net::GrowableIOBuffer>()),
read_response_result_(0),
read_started_(false) {}
@@ -456,8 +459,6 @@ int DevToolsURLInterceptorRequestJob::MockResponseDetails::ReadRawData(
namespace {
-using DevToolsStatus = ResourceRequestInfoImpl::DevToolsStatus;
-
void SendPendingBodyRequestsOnUiThread(
std::vector<std::unique_ptr<
protocol::Network::Backend::GetResponseBodyForInterceptionCallback>>
@@ -532,14 +533,6 @@ std::unique_ptr<net::UploadDataStream> GetUploadData(net::URLRequest* request) {
std::move(proxy_readers), 0);
}
-void SetDevToolsStatus(net::URLRequest* request,
- DevToolsStatus devtools_status) {
- ResourceRequestInfoImpl* resource_request_info =
- ResourceRequestInfoImpl::ForRequest(request);
- DCHECK(resource_request_info);
- 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.
@@ -644,8 +637,8 @@ void DevToolsURLInterceptorRequestJob::StartWithCookies(
DCHECK(stage_to_intercept_ == InterceptionStage::REQUEST ||
stage_to_intercept_ == InterceptionStage::BOTH);
waiting_for_user_response_ = WaitingForUserResponse::WAITING_FOR_REQUEST_ACK;
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(callback_, BuildRequestInfo()));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(callback_, BuildRequestInfo()));
}
void DevToolsURLInterceptorRequestJob::Kill() {
@@ -771,8 +764,8 @@ void DevToolsURLInterceptorRequestJob::OnSubRequestAuthRequired(
.SetScheme(auth_info->scheme)
.SetRealm(auth_info->realm)
.Build();
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(callback_, std::move(request_info)));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(callback_, std::move(request_info)));
}
void DevToolsURLInterceptorRequestJob::OnSubRequestResponseStarted(
@@ -794,8 +787,6 @@ void DevToolsURLInterceptorRequestJob::OnSubRequestRedirectReceived(
bool* defer_redirect) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(sub_request_);
- SetDevToolsStatus(sub_request_->request(),
- DevToolsStatus::kCanceledAsRedirect);
// If we're not intercepting results or are a response then cancel this
// redirect and tell the parent request it was redirected through |redirect_|.
@@ -829,8 +820,8 @@ void DevToolsURLInterceptorRequestJob::OnSubRequestRedirectReceived(
protocol::Object::fromValue(headers_dict.get(), nullptr);
request_info->http_response_status_code = redirectinfo.status_code;
request_info->redirect_url = redirectinfo.new_url.spec();
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(callback_, std::move(request_info)));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(callback_, std::move(request_info)));
sub_request_.reset();
}
@@ -865,8 +856,8 @@ void DevToolsURLInterceptorRequestJob::OnInterceptedRequestResponseStarted(
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)));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(callback_, std::move(request_info)));
}
// If result is < 0 it means error.
@@ -876,8 +867,8 @@ void DevToolsURLInterceptorRequestJob::OnInterceptedRequestResponseReady(
DCHECK(sub_request_);
if (result < 0) {
sub_request_->Cancel();
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(
&SendPendingBodyRequestsWithErrorOnUiThread,
std::move(pending_body_requests_),
@@ -885,10 +876,10 @@ void DevToolsURLInterceptorRequestJob::OnInterceptedRequestResponseReady(
"Could not get response body because of error code: %d",
result))));
} else {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(&SendPendingBodyRequestsOnUiThread,
- std::move(pending_body_requests_),
- std::string(buf.data(), result)));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(&SendPendingBodyRequestsOnUiThread,
+ std::move(pending_body_requests_),
+ std::string(buf.data(), result)));
}
if (request_->status().status() == net::URLRequestStatus::CANCELED ||
waiting_for_user_response_ != WaitingForUserResponse::NOT_WAITING) {
@@ -920,8 +911,7 @@ void DevToolsURLInterceptorRequestJob::StopIntercepting() {
base::nullopt, base::nullopt, protocol::Maybe<std::string>(),
protocol::Maybe<std::string>(), protocol::Maybe<std::string>(),
protocol::Maybe<protocol::Network::Headers>(),
- protocol::Maybe<protocol::Network::AuthChallengeResponse>(),
- false));
+ protocol::Maybe<protocol::Network::AuthChallengeResponse>()));
return;
case WaitingForUserResponse::WAITING_FOR_AUTH_ACK: {
std::unique_ptr<protocol::Network::AuthChallengeResponse> auth_response =
@@ -934,7 +924,7 @@ void DevToolsURLInterceptorRequestJob::StopIntercepting() {
base::nullopt, base::nullopt, protocol::Maybe<std::string>(),
protocol::Maybe<std::string>(), protocol::Maybe<std::string>(),
protocol::Maybe<protocol::Network::Headers>(),
- std::move(auth_response), false));
+ std::move(auth_response)));
return;
}
@@ -950,8 +940,8 @@ void DevToolsURLInterceptorRequestJob::ContinueInterceptedRequest(
DCHECK_CURRENTLY_ON(BrowserThread::IO);
switch (waiting_for_user_response_) {
case WaitingForUserResponse::NOT_WAITING:
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&ContinueInterceptedRequestCallback::sendFailure,
std::move(callback),
protocol::Response::InvalidParams(
@@ -962,8 +952,8 @@ void DevToolsURLInterceptorRequestJob::ContinueInterceptedRequest(
// Fallthough.
case WaitingForUserResponse::WAITING_FOR_REQUEST_ACK:
if (modifications->auth_challenge_response.isJust()) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&ContinueInterceptedRequestCallback::sendFailure,
std::move(callback),
protocol::Response::InvalidParams(
@@ -971,16 +961,16 @@ void DevToolsURLInterceptorRequestJob::ContinueInterceptedRequest(
break;
}
ProcessInterceptionResponse(std::move(modifications));
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&ContinueInterceptedRequestCallback::sendSuccess,
std::move(callback)));
break;
case WaitingForUserResponse::WAITING_FOR_AUTH_ACK:
if (!modifications->auth_challenge_response.isJust()) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&ContinueInterceptedRequestCallback::sendFailure,
std::move(callback),
protocol::Response::InvalidParams(
@@ -988,13 +978,13 @@ void DevToolsURLInterceptorRequestJob::ContinueInterceptedRequest(
break;
}
if (ProcessAuthResponse(std::move(modifications))) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&ContinueInterceptedRequestCallback::sendSuccess,
std::move(callback)));
} else {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&ContinueInterceptedRequestCallback::sendFailure,
std::move(callback),
protocol::Response::InvalidParams(
@@ -1040,8 +1030,8 @@ void DevToolsURLInterceptorRequestJob::GetResponseBody(
"received.";
}
if (error_reason.size()) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(
&GetResponseBodyForInterceptionCallback::sendFailure,
std::move(callback),
@@ -1073,9 +1063,6 @@ void DevToolsURLInterceptorRequestJob::ProcessInterceptionResponse(
WaitingForUserResponse::WAITING_FOR_RESPONSE_ACK;
waiting_for_user_response_ = WaitingForUserResponse::NOT_WAITING;
- if (modifications->mark_as_canceled)
- SetDevToolsStatus(request(), DevToolsStatus::kCanceled);
-
if (modifications->error_reason) {
if (sub_request_) {
sub_request_->Cancel();
@@ -1248,6 +1235,11 @@ void DevToolsURLInterceptorRequestJob::SetResponseHeadersCallback(
response_headers_callback_ = std::move(callback);
}
+void DevToolsURLInterceptorRequestJob::ContinueDespiteLastError() {
+ if (sub_request_)
+ sub_request_->request()->ContinueDespiteLastError();
+}
+
DevToolsURLInterceptorRequestJob::RequestDetails::RequestDetails(
const GURL& url,
const std::string& method,
diff --git a/chromium/content/browser/devtools/devtools_url_interceptor_request_job.h b/chromium/content/browser/devtools/devtools_url_interceptor_request_job.h
index ac37f7204ff..0dc53c267fd 100644
--- a/chromium/content/browser/devtools/devtools_url_interceptor_request_job.h
+++ b/chromium/content/browser/devtools/devtools_url_interceptor_request_job.h
@@ -61,6 +61,7 @@ class DevToolsURLInterceptorRequestJob : public net::URLRequestJob {
void SetRequestHeadersCallback(net::RequestHeadersCallback callback) override;
void SetResponseHeadersCallback(
net::ResponseHeadersCallback callback) override;
+ void ContinueDespiteLastError() override;
// Must be called on IO thread.
void StopIntercepting();
diff --git a/chromium/content/browser/devtools/devtools_url_loader_interceptor.cc b/chromium/content/browser/devtools/devtools_url_loader_interceptor.cc
index 99e8fd164e5..af405769294 100644
--- a/chromium/content/browser/devtools/devtools_url_loader_interceptor.cc
+++ b/chromium/content/browser/devtools/devtools_url_loader_interceptor.cc
@@ -6,11 +6,13 @@
#include "base/base64.h"
#include "base/no_destructor.h"
#include "base/strings/stringprintf.h"
+#include "base/task/post_task.h"
#include "base/time/time.h"
#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/download_utils_impl.h"
+#include "content/public/browser/browser_task_traits.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"
@@ -70,8 +72,8 @@ class BodyReader : public mojo::DataPipeDrainer::Client {
callbacks_.push_back(std::move(callback));
if (data_complete_) {
DCHECK_EQ(1UL, callbacks_.size());
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&BodyReader::DispatchBodyOnUI, std::move(callbacks_),
encoded_body_));
}
@@ -81,8 +83,8 @@ class BodyReader : public mojo::DataPipeDrainer::Client {
const std::string& body() const { return body_; }
void CancelWithError(std::string error) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&BodyReader::DispatchErrorOnUI, std::move(callbacks_),
std::move(error)));
}
@@ -124,9 +126,10 @@ void BodyReader::OnDataComplete() {
body_pipe_drainer_.reset();
// TODO(caseq): only encode if necessary.
base::Base64Encode(body_, &encoded_body_);
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(&BodyReader::DispatchBodyOnUI,
- std::move(callbacks_), encoded_body_));
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(&BodyReader::DispatchBodyOnUI, std::move(callbacks_),
+ encoded_body_));
std::move(download_complete_callback_).Run();
}
@@ -204,7 +207,7 @@ class InterceptionJob : public network::mojom::URLLoaderClient,
Response InnerContinueRequest(std::unique_ptr<Modifications> modifications);
Response ProcessAuthResponse(AuthChallengeResponse* auth_challenge_response);
Response ProcessResponseOverride(const std::string& response);
- Response ProcessRedirectByClient(const std::string& location);
+ Response ProcessRedirectByClient(const GURL& redirect_url);
void SendResponse(const base::StringPiece& body);
void ApplyModificationsToRequest(
std::unique_ptr<Modifications> modifications);
@@ -387,8 +390,8 @@ class DevToolsURLLoaderInterceptor::Impl
auto it = jobs_.find(id);
if (it != jobs_.end())
return it->second;
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(
&Callback::sendFailure, std::move(*callback),
protocol::Response::InvalidParams("Invalid InterceptionId.")));
@@ -458,8 +461,8 @@ DevToolsURLLoaderFactoryProxy::DevToolsURLLoaderFactoryProxy(
is_download_(is_download),
interceptor_(std::move(interceptor)) {
DETACH_FROM_SEQUENCE(sequence_checker_);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&DevToolsURLLoaderFactoryProxy::StartOnIO,
base::Unretained(this), std::move(loader_request),
std::move(target_factory_info)));
@@ -543,7 +546,8 @@ DevToolsURLLoaderInterceptor::DevToolsURLLoaderInterceptor(
enabled_(false),
impl_(new DevToolsURLLoaderInterceptor::Impl(std::move(callback)),
base::OnTaskRunnerDeleter(
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO))),
+ base::CreateSingleThreadTaskRunnerWithTraits(
+ {BrowserThread::IO}))),
weak_impl_(impl_->AsWeakPtr()) {}
DevToolsURLLoaderInterceptor::~DevToolsURLLoaderInterceptor() {
@@ -571,8 +575,8 @@ void DevToolsURLLoaderInterceptor::SetPatterns(
enabled_ = !!patterns.size();
UpdateSubresourceLoaderFactories();
}
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&Impl::SetPatterns, base::Unretained(impl_.get()),
std::move(patterns)));
}
@@ -580,8 +584,8 @@ void DevToolsURLLoaderInterceptor::SetPatterns(
void DevToolsURLLoaderInterceptor::GetResponseBody(
const std::string& interception_id,
std::unique_ptr<GetResponseBodyForInterceptionCallback> callback) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&Impl::GetResponseBody, base::Unretained(impl_.get()),
interception_id, std::move(callback)));
}
@@ -589,8 +593,8 @@ void DevToolsURLLoaderInterceptor::GetResponseBody(
void DevToolsURLLoaderInterceptor::TakeResponseBodyPipe(
const std::string& interception_id,
DevToolsNetworkInterceptor::TakeResponseBodyPipeCallback callback) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&Impl::TakeResponseBodyPipe, base::Unretained(impl_.get()),
interception_id, std::move(callback)));
}
@@ -599,8 +603,8 @@ void DevToolsURLLoaderInterceptor::ContinueInterceptedRequest(
const std::string& interception_id,
std::unique_ptr<Modifications> modifications,
std::unique_ptr<ContinueInterceptedRequestCallback> callback) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&Impl::ContinueInterceptedRequest,
base::Unretained(impl_.get()), interception_id,
std::move(modifications), std::move(callback)));
@@ -699,8 +703,8 @@ void InterceptionJob::GetResponseBody(
std::unique_ptr<GetResponseBodyForInterceptionCallback> callback) {
std::string error_reason;
if (!CanGetResponseBody(&error_reason)) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&GetResponseBodyForInterceptionCallback::sendFailure,
std::move(callback),
Response::Error(std::move(error_reason))));
@@ -719,8 +723,8 @@ void InterceptionJob::TakeResponseBodyPipe(
TakeResponseBodyPipeCallback callback) {
std::string error_reason;
if (!CanGetResponseBody(&error_reason)) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(std::move(callback),
Response::Error(std::move(error_reason)),
mojo::ScopedDataPipeConsumerHandle(), std::string()));
@@ -745,7 +749,7 @@ void InterceptionJob::ContinueInterceptedRequest(
std::move(callback))
: base::BindOnce(&ContinueInterceptedRequestCallback::sendFailure,
std::move(callback), std::move(response));
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, std::move(task));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI}, std::move(task));
}
void InterceptionJob::Detach() {
@@ -777,12 +781,9 @@ Response InterceptionJob::InnerContinueRequest(
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
- ? *modifications->error_reason
- : (modifications->mark_as_canceled ? net::ERR_ABORTED
- : net::ERR_FAILED);
- network::URLLoaderCompletionStatus status(error);
+ if (modifications->error_reason) {
+ network::URLLoaderCompletionStatus status(
+ modifications->error_reason.value());
status.completion_time = base::TimeTicks::Now();
if (modifications->error_reason == net::ERR_BLOCKED_BY_CLIENT) {
// So we know that these modifications originated from devtools
@@ -820,7 +821,8 @@ Response InterceptionJob::InnerContinueRequest(
auto* headers = response_metadata_->head.headers.get();
headers->RemoveHeader("location");
headers->AddHeader("location: " + location);
- return ProcessRedirectByClient(location);
+ return ProcessRedirectByClient(
+ create_loader_params_->request.url.Resolve(location));
}
client_->OnReceiveRedirect(*response_metadata_->redirect_info,
response_metadata_->head);
@@ -940,7 +942,9 @@ Response InterceptionJob::ProcessResponseOverride(const std::string& response) {
head->headers = new net::HttpResponseHeaders(std::move(raw_headers));
head->headers->GetMimeTypeAndCharset(&head->mime_type, &head->charset);
if (head->mime_type.empty()) {
- net::SniffMimeType(response.data() + header_size, body_size,
+ size_t bytes_to_sniff =
+ std::min(body_size, static_cast<size_t>(net::kMaxBytesToSniff));
+ net::SniffMimeType(response.data() + header_size, bytes_to_sniff,
create_loader_params_->request.url, "",
net::ForceSniffFileUrlsForHtml::kDisabled,
&head->mime_type);
@@ -952,9 +956,12 @@ Response InterceptionJob::ProcessResponseOverride(const std::string& response) {
head->request_start = start_ticks_;
head->response_start = base::TimeTicks::Now();
- std::string location_url;
- if (head->headers->IsRedirect(&location_url))
- return ProcessRedirectByClient(location_url);
+ std::string location;
+ if (head->headers->IsRedirect(&location)) {
+ GURL redirect_url = create_loader_params_->request.url.Resolve(location);
+ if (redirect_url.is_valid())
+ return ProcessRedirectByClient(redirect_url);
+ }
response_metadata_->transfer_size = body_size;
@@ -967,9 +974,7 @@ Response InterceptionJob::ProcessResponseOverride(const std::string& response) {
return Response::OK();
}
-Response InterceptionJob::ProcessRedirectByClient(const std::string& location) {
- GURL redirect_url = create_loader_params_->request.url.Resolve(location);
-
+Response InterceptionJob::ProcessRedirectByClient(const GURL& redirect_url) {
if (!redirect_url.is_valid())
return Response::Error("Invalid redirect URL in overriden headers");
@@ -987,8 +992,8 @@ Response InterceptionJob::ProcessRedirectByClient(const std::string& location) {
request.method, request.url, request.site_for_cookies,
first_party_url_policy, request.referrer_policy,
request.referrer.spec(), &headers, headers.response_code(),
- redirect_url, false /* token_binding_negotiated */,
- false /* insecure_scheme_was_upgraded */, false /* copy_fragment */));
+ redirect_url, false /* insecure_scheme_was_upgraded */,
+ true /* copy_fragment */));
client_->OnReceiveRedirect(*response_metadata_->redirect_info,
response_metadata_->head);
@@ -1097,8 +1102,8 @@ std::unique_ptr<InterceptedRequestInfo> InterceptionJob::BuildRequestInfo(
void InterceptionJob::NotifyClient(
std::unique_ptr<InterceptedRequestInfo> request_info) {
waiting_for_resolution_ = true;
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(interceptor_->request_intercepted_callback_,
std::move(request_info)));
}
@@ -1250,8 +1255,8 @@ void InterceptionJob::OnStartLoadingResponseBody(
if (pending_response_body_pipe_callback_) {
DCHECK_EQ(State::kResponseTaken, state_);
DCHECK(!body_reader_);
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(std::move(pending_response_body_pipe_callback_),
Response::OK(), std::move(body),
response_metadata_->head.mime_type));
diff --git a/chromium/content/browser/devtools/devtools_url_request_interceptor.cc b/chromium/content/browser/devtools/devtools_url_request_interceptor.cc
index e6bf677b05b..870cb80ec79 100644
--- a/chromium/content/browser/devtools/devtools_url_request_interceptor.cc
+++ b/chromium/content/browser/devtools/devtools_url_request_interceptor.cc
@@ -6,9 +6,11 @@
#include "base/strings/pattern.h"
#include "base/strings/stringprintf.h"
+#include "base/task/post_task.h"
#include "content/browser/devtools/devtools_interceptor_controller.h"
#include "content/browser/devtools/devtools_url_interceptor_request_job.h"
#include "content/browser/devtools/protocol/network_handler.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/resource_request_info.h"
#include "net/url_request/url_request.h"
@@ -27,8 +29,8 @@ DevToolsURLRequestInterceptor::DevToolsURLRequestInterceptor(
: next_id_(0), weak_factory_(this) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
auto target_registry = std::make_unique<DevToolsTargetRegistry>(
- content::BrowserThread::GetTaskRunnerForThread(
- content::BrowserThread::IO));
+ base::CreateSingleThreadTaskRunnerWithTraits(
+ {content::BrowserThread::IO}));
target_resolver_ = target_registry->CreateResolver();
// Controller lifetime is managed by the browser context.
auto* controller = new DevToolsInterceptorController(
@@ -58,8 +60,8 @@ void DevToolsURLRequestInterceptor::ContinueInterceptedRequest(
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DevToolsURLInterceptorRequestJob* job = GetJob(interception_id);
if (!job) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(
&ContinueInterceptedRequestCallback::sendFailure,
std::move(callback),
@@ -97,8 +99,8 @@ void DevToolsURLRequestInterceptor::GetResponseBody(
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DevToolsURLInterceptorRequestJob* job = GetJob(interception_id);
if (!job) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(
&GetResponseBodyForInterceptionCallback::sendFailure,
std::move(callback),
@@ -144,8 +146,8 @@ net::URLRequestJob* DevToolsURLRequestInterceptor::InnerMaybeInterceptRequest(
std::string interception_id = base::StringPrintf("id-%zu", ++next_id_);
if (IsNavigationRequest(resource_type)) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&DevToolsInterceptorController::NavigationStarted,
controller_, interception_id,
resource_request_info->GetGlobalRequestID()));
@@ -275,8 +277,8 @@ void DevToolsURLRequestInterceptor::JobFinished(
interception_id_to_job_map_.erase(interception_id);
if (!is_navigation)
return;
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&DevToolsInterceptorController::NavigationFinished,
controller_, interception_id));
}
diff --git a/chromium/content/browser/devtools/devtools_video_consumer.cc b/chromium/content/browser/devtools/devtools_video_consumer.cc
index e6316a8681c..e7bbf3843a7 100644
--- a/chromium/content/browser/devtools/devtools_video_consumer.cc
+++ b/chromium/content/browser/devtools/devtools_video_consumer.cc
@@ -57,7 +57,7 @@ SkBitmap DevToolsVideoConsumer::GetSkBitmapFromFrame(
skbitmap.allocN32Pixels(frame->visible_rect().width(),
frame->visible_rect().height());
cc::SkiaPaintCanvas canvas(skbitmap);
- renderer.Copy(frame, &canvas, media::Context3D());
+ renderer.Copy(frame, &canvas, media::Context3D(), nullptr);
return skbitmap;
}
@@ -171,6 +171,8 @@ void DevToolsVideoConsumer::OnFrameCaptured(
viz::mojom::FrameSinkVideoConsumerFrameCallbacksPtr callbacks) {},
std::move(mapping), std::move(callbacks)));
frame->metadata()->MergeInternalValuesFrom(info->metadata);
+ if (info->color_space.has_value())
+ frame->set_color_space(info->color_space.value());
callback_.Run(std::move(frame));
}
diff --git a/chromium/content/browser/devtools/devtools_video_consumer_unittest.cc b/chromium/content/browser/devtools/devtools_video_consumer_unittest.cc
index 6aefd60ca68..496a3e8b057 100644
--- a/chromium/content/browser/devtools/devtools_video_consumer_unittest.cc
+++ b/chromium/content/browser/devtools/devtools_video_consumer_unittest.cc
@@ -6,7 +6,7 @@
#include <vector>
#include "base/memory/read_only_shared_memory_region.h"
-#include "base/message_loop/message_loop.h"
+#include "base/test/scoped_task_environment.h"
#include "content/browser/devtools/devtools_video_consumer.h"
#include "content/public/test/test_utils.h"
#include "media/base/limits.h"
@@ -50,7 +50,7 @@ class MockFrameSinkVideoCapturer : public viz::mojom::FrameSinkVideoCapturer {
// This is never called.
MOCK_METHOD2(SetFormat,
void(media::VideoPixelFormat format,
- media::ColorSpace color_space));
+ const gfx::ColorSpace& color_space));
void SetMinCapturePeriod(base::TimeDelta min_capture_period) final {
min_capture_period_ = min_capture_period;
MockSetMinCapturePeriod(min_capture_period_);
@@ -181,7 +181,8 @@ class DevToolsVideoConsumerTest : public testing::Test {
media::mojom::VideoFrameInfoPtr info = media::mojom::VideoFrameInfo::New(
base::TimeDelta(), base::Value(base::Value::Type::DICTIONARY), kFormat,
- kResolution, gfx::Rect(kResolution));
+ kResolution, gfx::Rect(kResolution), gfx::ColorSpace::CreateREC709(),
+ nullptr);
consumer_->OnFrameCaptured(std::move(data), std::move(info),
gfx::Rect(kResolution), gfx::Rect(kResolution),
@@ -230,7 +231,7 @@ class DevToolsVideoConsumerTest : public testing::Test {
weak_factory_.GetWeakPtr()));
}
- base::MessageLoop message_loop_;
+ base::test::ScopedTaskEnvironment task_environment_;
base::WeakPtrFactory<DevToolsVideoConsumerTest> weak_factory_;
};
diff --git a/chromium/content/browser/devtools/forwarding_agent_host.cc b/chromium/content/browser/devtools/forwarding_agent_host.cc
index 1682f1cc880..44970981ede 100644
--- a/chromium/content/browser/devtools/forwarding_agent_host.cc
+++ b/chromium/content/browser/devtools/forwarding_agent_host.cc
@@ -51,8 +51,9 @@ ForwardingAgentHost::ForwardingAgentHost(
ForwardingAgentHost::~ForwardingAgentHost() {
}
-void ForwardingAgentHost::AttachClient(DevToolsAgentHostClient* client) {
+bool ForwardingAgentHost::AttachClient(DevToolsAgentHostClient* client) {
session_proxies_[client].reset(new SessionProxy(this, client));
+ return true;
}
bool ForwardingAgentHost::DetachClient(DevToolsAgentHostClient* client) {
diff --git a/chromium/content/browser/devtools/forwarding_agent_host.h b/chromium/content/browser/devtools/forwarding_agent_host.h
index 3368c916f36..e3aec78e772 100644
--- a/chromium/content/browser/devtools/forwarding_agent_host.h
+++ b/chromium/content/browser/devtools/forwarding_agent_host.h
@@ -27,7 +27,7 @@ class ForwardingAgentHost : public DevToolsAgentHostImpl {
~ForwardingAgentHost() override;
// DevToolsAgentHost implementation
- void AttachClient(DevToolsAgentHostClient* client) override;
+ bool AttachClient(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/browser_handler.cc b/chromium/content/browser/devtools/protocol/browser_handler.cc
index 2c57058886f..193dcdbd454 100644
--- a/chromium/content/browser/devtools/protocol/browser_handler.cc
+++ b/chromium/content/browser/devtools/protocol/browser_handler.cc
@@ -268,5 +268,10 @@ Response BrowserHandler::GetBrowserCommandLine(
}
}
+Response BrowserHandler::Crash() {
+ CHECK(false);
+ return Response::OK();
+}
+
} // namespace protocol
} // namespace content
diff --git a/chromium/content/browser/devtools/protocol/browser_handler.h b/chromium/content/browser/devtools/protocol/browser_handler.h
index 5175b0ffb41..3b8515a9ea0 100644
--- a/chromium/content/browser/devtools/protocol/browser_handler.h
+++ b/chromium/content/browser/devtools/protocol/browser_handler.h
@@ -53,6 +53,8 @@ class BrowserHandler : public DevToolsDomainHandler, public Browser::Backend {
Response ResetPermissions(Maybe<std::string> browser_context_id) override;
+ Response Crash() override;
+
private:
Response FindBrowserContext(const Maybe<std::string>& browser_context_id,
BrowserContext** browser_context);
diff --git a/chromium/content/browser/devtools/protocol/devtools_download_manager_delegate.cc b/chromium/content/browser/devtools/protocol/devtools_download_manager_delegate.cc
index bfaa525d37e..3ef417e6211 100644
--- a/chromium/content/browser/devtools/protocol/devtools_download_manager_delegate.cc
+++ b/chromium/content/browser/devtools/protocol/devtools_download_manager_delegate.cc
@@ -7,9 +7,9 @@
#include "base/bind.h"
#include "base/files/file_util.h"
#include "base/task/post_task.h"
-#include "base/threading/thread_restrictions.h"
#include "content/browser/devtools/protocol/devtools_download_manager_helper.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/download_item_utils.h"
#include "content/public/browser/download_manager.h"
@@ -159,7 +159,6 @@ void DevToolsDownloadManagerDelegate::GenerateFilename(
const std::string& mime_type,
const base::FilePath& suggested_directory,
const FilenameDeterminedCallback& callback) {
- base::AssertBlockingAllowed();
base::FilePath generated_name =
net::GenerateFileName(url, content_disposition, std::string(),
suggested_filename, mime_type, "download");
@@ -168,8 +167,8 @@ void DevToolsDownloadManagerDelegate::GenerateFilename(
base::CreateDirectory(suggested_directory);
base::FilePath suggested_path(suggested_directory.Append(generated_name));
- content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
- base::BindOnce(callback, suggested_path));
+ base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI},
+ base::BindOnce(callback, suggested_path));
}
void DevToolsDownloadManagerDelegate::OnDownloadPathGenerated(
diff --git a/chromium/content/browser/devtools/protocol/devtools_protocol_browsertest.cc b/chromium/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
index c66b3c9454a..57a749755b9 100644
--- a/chromium/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
+++ b/chromium/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
@@ -11,6 +11,7 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/command_line.h"
+#include "base/json/json_reader.h"
#include "base/logging.h"
#include "base/strings/stringprintf.h"
#include "base/sys_info.h"
@@ -1356,6 +1357,48 @@ IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, CertificateError) {
->GetURL());
}
+IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest,
+ CertificateErrorRequestInterception) {
+ net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
+ https_server.SetSSLConfig(net::EmbeddedTestServer::CERT_EXPIRED);
+ https_server.ServeFilesFromSourceDirectory("content/test/data");
+ ASSERT_TRUE(https_server.Start());
+ GURL test_url = https_server.GetURL("/devtools/navigation.html");
+
+ shell()->LoadURL(GURL("about:blank"));
+ WaitForLoadStop(shell()->web_contents());
+
+ Attach();
+ SendCommand("Network.enable", nullptr, true);
+ SendCommand("Security.enable", nullptr, false);
+ SendCommand(
+ "Network.setRequestInterception",
+ base::JSONReader::Read("{\"patterns\": [{\"urlPattern\": \"*\"}]}"),
+ true);
+
+ SendCommand("Security.setIgnoreCertificateErrors",
+ base::JSONReader::Read("{\"ignore\": true}"), true);
+
+ SendCommand("Network.clearBrowserCache", nullptr, true);
+ SendCommand("Network.clearBrowserCookies", nullptr, true);
+ TestNavigationObserver continue_observer(shell()->web_contents(), 1);
+ shell()->LoadURL(test_url);
+ std::unique_ptr<base::DictionaryValue> params =
+ WaitForNotification("Network.requestIntercepted", false);
+ std::string interceptionId;
+ EXPECT_TRUE(params->GetString("interceptionId", &interceptionId));
+ SendCommand("Network.continueInterceptedRequest",
+ base::JSONReader::Read("{\"interceptionId\": \"" +
+ interceptionId + "\"}"),
+ false);
+ continue_observer.Wait();
+ EXPECT_EQ(test_url, shell()
+ ->web_contents()
+ ->GetController()
+ .GetLastCommittedEntry()
+ ->GetURL());
+}
+
IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, CertificateErrorBrowserTarget) {
net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
https_server.SetSSLConfig(net::EmbeddedTestServer::CERT_EXPIRED);
diff --git a/chromium/content/browser/devtools/protocol/devtools_protocol_test_support.cc b/chromium/content/browser/devtools/protocol/devtools_protocol_test_support.cc
index 41ba4bc6448..14d94c8a26b 100644
--- a/chromium/content/browser/devtools/protocol/devtools_protocol_test_support.cc
+++ b/chromium/content/browser/devtools/protocol/devtools_protocol_test_support.cc
@@ -47,7 +47,7 @@ bool DevToolsProtocolTest::DidAddMessageToConsole(
base::DictionaryValue* DevToolsProtocolTest::SendCommand(
const std::string& method,
- std::unique_ptr<base::DictionaryValue> params,
+ std::unique_ptr<base::Value> params,
bool wait) {
in_dispatch_ = true;
base::DictionaryValue command;
diff --git a/chromium/content/browser/devtools/protocol/devtools_protocol_test_support.h b/chromium/content/browser/devtools/protocol/devtools_protocol_test_support.h
index 15e5d23afce..cb8a49967f9 100644
--- a/chromium/content/browser/devtools/protocol/devtools_protocol_test_support.h
+++ b/chromium/content/browser/devtools/protocol/devtools_protocol_test_support.h
@@ -40,16 +40,14 @@ class DevToolsProtocolTest : public ContentBrowserTest,
content::WebContents* web_contents,
content::SecurityStyleExplanations* security_style_explanations) override;
- base::DictionaryValue* SendCommand(
- const std::string& method,
- std::unique_ptr<base::DictionaryValue> params) {
+ base::DictionaryValue* SendCommand(const std::string& method,
+ std::unique_ptr<base::Value> params) {
return SendCommand(method, std::move(params), true);
}
- base::DictionaryValue* SendCommand(
- const std::string& method,
- std::unique_ptr<base::DictionaryValue> params,
- bool wait);
+ base::DictionaryValue* SendCommand(const std::string& method,
+ std::unique_ptr<base::Value> params,
+ bool wait);
void WaitForResponse();
diff --git a/chromium/content/browser/devtools/protocol/emulation_handler.cc b/chromium/content/browser/devtools/protocol/emulation_handler.cc
index af6d9a2b197..8df358c3af9 100644
--- a/chromium/content/browser/devtools/protocol/emulation_handler.cc
+++ b/chromium/content/browser/devtools/protocol/emulation_handler.cc
@@ -8,12 +8,12 @@
#include "base/strings/string_number_conversions.h"
#include "build/build_config.h"
-#include "content/browser/devtools/devtools_session.h"
+#include "content/browser/devtools/devtools_agent_host_impl.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/renderer_host/input/touch_emulator.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
-#include "content/common/view_messages.h"
+#include "content/common/widget_messages.h"
#include "content/public/common/url_constants.h"
#include "net/http/http_util.h"
#include "services/device/public/cpp/geolocation/geoposition.h"
@@ -69,19 +69,19 @@ EmulationHandler::~EmulationHandler() {
// static
std::vector<EmulationHandler*> EmulationHandler::ForAgentHost(
DevToolsAgentHostImpl* host) {
- return DevToolsSession::HandlersForAgentHost<EmulationHandler>(
- host, Emulation::Metainfo::domainName);
+ return host->HandlersByName<EmulationHandler>(
+ Emulation::Metainfo::domainName);
}
void EmulationHandler::SetRenderer(int process_host_id,
RenderFrameHostImpl* frame_host) {
if (host_ == frame_host)
return;
-
host_ = frame_host;
if (touch_emulation_enabled_)
UpdateTouchEventEmulationState();
- UpdateDeviceEmulationState();
+ if (device_emulation_enabled_)
+ UpdateDeviceEmulationState();
}
void EmulationHandler::Wire(UberDispatcher* dispatcher) {
@@ -94,8 +94,10 @@ Response EmulationHandler::Disable() {
UpdateTouchEventEmulationState();
}
user_agent_ = std::string();
- device_emulation_enabled_ = false;
- UpdateDeviceEmulationState();
+ if (device_emulation_enabled_) {
+ device_emulation_enabled_ = false;
+ UpdateDeviceEmulationState();
+ }
return Response::OK();
}
@@ -387,14 +389,14 @@ void EmulationHandler::UpdateDeviceEmulationState() {
// emulation params were applied. That way, we can avoid having to handle
// Set/ClearDeviceMetricsOverride in the renderer. With the old IPC system,
// this is tricky since we'd have to track the DevTools message id with the
- // ViewMsg and acknowledgment, as well as plump the acknowledgment back to the
- // EmulationHandler somehow. Mojo callbacks should make this much simpler.
+ // WidgetMsg and acknowledgment, as well as plump the acknowledgment back to
+ // the EmulationHandler somehow. Mojo callbacks should make this much simpler.
if (device_emulation_enabled_) {
- host_->GetRenderWidgetHost()->Send(new ViewMsg_EnableDeviceEmulation(
+ host_->GetRenderWidgetHost()->Send(new WidgetMsg_EnableDeviceEmulation(
host_->GetRenderWidgetHost()->GetRoutingID(),
device_emulation_params_));
} else {
- host_->GetRenderWidgetHost()->Send(new ViewMsg_DisableDeviceEmulation(
+ host_->GetRenderWidgetHost()->Send(new WidgetMsg_DisableDeviceEmulation(
host_->GetRenderWidgetHost()->GetRoutingID()));
}
}
diff --git a/chromium/content/browser/devtools/protocol/input_handler.cc b/chromium/content/browser/devtools/protocol/input_handler.cc
index d89856b04b3..d6fbc0110f4 100644
--- a/chromium/content/browser/devtools/protocol/input_handler.cc
+++ b/chromium/content/browser/devtools/protocol/input_handler.cc
@@ -10,7 +10,7 @@
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/trace_event.h"
-#include "content/browser/devtools/devtools_session.h"
+#include "content/browser/devtools/devtools_agent_host_impl.h"
#include "content/browser/devtools/protocol/native_input_event_builder.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/renderer_host/input/touch_emulator.h"
@@ -414,8 +414,7 @@ InputHandler::~InputHandler() {
// static
std::vector<InputHandler*> InputHandler::ForAgentHost(
DevToolsAgentHostImpl* host) {
- return DevToolsSession::HandlersForAgentHost<InputHandler>(
- host, Input::Metainfo::domainName);
+ return host->HandlersByName<InputHandler>(Input::Metainfo::domainName);
}
void InputHandler::SetRenderer(int process_host_id,
diff --git a/chromium/content/browser/devtools/protocol/inspector_handler.cc b/chromium/content/browser/devtools/protocol/inspector_handler.cc
index ae8e11f7472..31eb6d428f7 100644
--- a/chromium/content/browser/devtools/protocol/inspector_handler.cc
+++ b/chromium/content/browser/devtools/protocol/inspector_handler.cc
@@ -4,7 +4,7 @@
#include "content/browser/devtools/protocol/inspector_handler.h"
-#include "content/browser/devtools/devtools_session.h"
+#include "content/browser/devtools/devtools_agent_host_impl.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
namespace content {
@@ -21,8 +21,8 @@ InspectorHandler::~InspectorHandler() {
// static
std::vector<InspectorHandler*> InspectorHandler::ForAgentHost(
DevToolsAgentHostImpl* host) {
- return DevToolsSession::HandlersForAgentHost<InspectorHandler>(
- host, Inspector::Metainfo::domainName);
+ return host->HandlersByName<InspectorHandler>(
+ Inspector::Metainfo::domainName);
}
void InspectorHandler::Wire(UberDispatcher* dispatcher) {
diff --git a/chromium/content/browser/devtools/protocol/memory_handler.cc b/chromium/content/browser/devtools/protocol/memory_handler.cc
index 328ecd8aeea..49e5453ac31 100644
--- a/chromium/content/browser/devtools/protocol/memory_handler.cc
+++ b/chromium/content/browser/devtools/protocol/memory_handler.cc
@@ -61,7 +61,7 @@ Response MemoryHandler::GetBrowserSamplingProfile(
for (const auto* module : module_cache.GetModules()) {
modules->addItem(Memory::Module::Create()
.SetName(base::StringPrintf(
- "%" PRIsFP, module->filename.value().c_str()))
+ "%" PRFilePath, module->filename.value().c_str()))
.SetUuid(module->id)
.SetBaseAddress(base::StringPrintf(
"0x%" PRIxPTR, module->base_address))
diff --git a/chromium/content/browser/devtools/protocol/network_handler.cc b/chromium/content/browser/devtools/protocol/network_handler.cc
index 905fe910beb..1ba2c3016bf 100644
--- a/chromium/content/browser/devtools/protocol/network_handler.cc
+++ b/chromium/content/browser/devtools/protocol/network_handler.cc
@@ -16,11 +16,12 @@
#include "base/process/process_handle.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
+#include "base/task/post_task.h"
#include "base/time/time.h"
#include "content/browser/background_sync/background_sync_manager.h"
+#include "content/browser/devtools/devtools_agent_host_impl.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"
@@ -35,6 +36,7 @@
#include "content/browser/web_package/signed_exchange_error.h"
#include "content/common/navigation_params.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/browsing_data_remover.h"
#include "content/public/browser/content_browser_client.h"
@@ -100,7 +102,7 @@ Network::CertificateTransparencyCompliance SerializeCTPolicyCompliance(
case net::ct::CTPolicyCompliance::
CT_POLICY_COMPLIANCE_DETAILS_NOT_AVAILABLE:
return Network::CertificateTransparencyComplianceEnum::Unknown;
- case net::ct::CTPolicyCompliance::CT_POLICY_MAX:
+ case net::ct::CTPolicyCompliance::CT_POLICY_COUNT:
NOTREACHED();
return Network::CertificateTransparencyComplianceEnum::Unknown;
}
@@ -208,8 +210,8 @@ class CookieRetriever : public base::RefCountedThreadSafe<CookieRetriever> {
for (const auto& pair : cookies_)
master_cookie_list.push_back(pair.second);
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&CookieRetriever::SendCookiesResponseOnUI, this,
master_cookie_list));
}
@@ -286,8 +288,8 @@ void ClearedCookiesOnIO(std::unique_ptr<ClearBrowserCookiesCallback> callback,
uint32_t num_deleted) {
DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&ClearBrowserCookiesCallback::sendSuccess,
std::move(callback)));
}
@@ -304,7 +306,7 @@ void ClearCookiesOnIO(net::URLRequestContextGetter* context_getter,
void DeletedCookiesOnIO(base::OnceClosure callback, uint32_t num_deleted) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, std::move(callback));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI}, std::move(callback));
}
std::vector<net::CanonicalCookie> FilterCookies(
@@ -368,9 +370,9 @@ void DeleteCookiesOnIO(net::URLRequestContextGetter* context_getter,
void CookieSetOnIO(std::unique_ptr<SetCookieCallback> callback, bool success) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(&SetCookieCallback::sendSuccess,
- std::move(callback), success));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(&SetCookieCallback::sendSuccess,
+ std::move(callback), success));
}
void DeleteFilteredCookies(network::mojom::CookieManager* cookie_manager,
@@ -455,8 +457,8 @@ void SetCookieOnIO(net::URLRequestContextGetter* context_getter,
void CookiesSetOnIO(std::unique_ptr<SetCookiesCallback> callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&SetCookiesCallback::sendSuccess, std::move(callback)));
}
@@ -663,48 +665,49 @@ String NetErrorToString(int net_error) {
bool AddInterceptedResourceType(
const std::string& resource_type,
base::flat_set<ResourceType>* intercepted_resource_types) {
- if (resource_type == protocol::Page::ResourceTypeEnum::Document) {
+ if (resource_type == protocol::Network::ResourceTypeEnum::Document) {
intercepted_resource_types->insert(RESOURCE_TYPE_MAIN_FRAME);
intercepted_resource_types->insert(RESOURCE_TYPE_SUB_FRAME);
return true;
}
- if (resource_type == protocol::Page::ResourceTypeEnum::Stylesheet) {
+ if (resource_type == protocol::Network::ResourceTypeEnum::Stylesheet) {
intercepted_resource_types->insert(RESOURCE_TYPE_STYLESHEET);
return true;
}
- if (resource_type == protocol::Page::ResourceTypeEnum::Image) {
+ if (resource_type == protocol::Network::ResourceTypeEnum::Image) {
intercepted_resource_types->insert(RESOURCE_TYPE_IMAGE);
return true;
}
- if (resource_type == protocol::Page::ResourceTypeEnum::Media) {
+ if (resource_type == protocol::Network::ResourceTypeEnum::Media) {
intercepted_resource_types->insert(RESOURCE_TYPE_MEDIA);
return true;
}
- if (resource_type == protocol::Page::ResourceTypeEnum::Font) {
+ if (resource_type == protocol::Network::ResourceTypeEnum::Font) {
intercepted_resource_types->insert(RESOURCE_TYPE_FONT_RESOURCE);
return true;
}
- if (resource_type == protocol::Page::ResourceTypeEnum::Script) {
+ if (resource_type == protocol::Network::ResourceTypeEnum::Script) {
intercepted_resource_types->insert(RESOURCE_TYPE_SCRIPT);
return true;
}
- if (resource_type == protocol::Page::ResourceTypeEnum::XHR) {
+ if (resource_type == protocol::Network::ResourceTypeEnum::XHR) {
intercepted_resource_types->insert(RESOURCE_TYPE_XHR);
return true;
}
- if (resource_type == protocol::Page::ResourceTypeEnum::Fetch) {
+ if (resource_type == protocol::Network::ResourceTypeEnum::Fetch) {
intercepted_resource_types->insert(RESOURCE_TYPE_PREFETCH);
return true;
}
- if (resource_type == protocol::Page::ResourceTypeEnum::CSPViolationReport) {
+ if (resource_type ==
+ protocol::Network::ResourceTypeEnum::CSPViolationReport) {
intercepted_resource_types->insert(RESOURCE_TYPE_CSP_REPORT);
return true;
}
- if (resource_type == protocol::Page::ResourceTypeEnum::Ping) {
+ if (resource_type == protocol::Network::ResourceTypeEnum::Ping) {
intercepted_resource_types->insert(RESOURCE_TYPE_PING);
return true;
}
- if (resource_type == protocol::Page::ResourceTypeEnum::Other) {
+ if (resource_type == protocol::Network::ResourceTypeEnum::Other) {
intercepted_resource_types->insert(RESOURCE_TYPE_SUB_RESOURCE);
intercepted_resource_types->insert(RESOURCE_TYPE_OBJECT);
intercepted_resource_types->insert(RESOURCE_TYPE_WORKER);
@@ -773,7 +776,7 @@ String GetProtocol(const GURL& url, const network::ResourceResponseInfo& info) {
std::string protocol = info.alpn_negotiated_protocol;
if (protocol.empty() || protocol == "unknown") {
if (info.was_fetched_via_spdy) {
- protocol = "spdy";
+ protocol = "h2";
} else if (url.SchemeIsHTTPOrHTTPS()) {
protocol = "http";
if (info.headers->GetHttpVersion() == net::HttpVersion(0, 9))
@@ -929,8 +932,8 @@ class BackgroundSyncRestorer {
scoped_refptr<BackgroundSyncContext> sync_context =
static_cast<StoragePartitionImpl*>(storage_partition_)
->GetBackgroundSyncContext();
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&SetServiceWorkerOfflineOnIO, sync_context,
base::RetainedRef(static_cast<ServiceWorkerContextWrapper*>(
@@ -984,8 +987,7 @@ NetworkHandler::~NetworkHandler() {
// static
std::vector<NetworkHandler*> NetworkHandler::ForAgentHost(
DevToolsAgentHostImpl* host) {
- return DevToolsSession::HandlersForAgentHost<NetworkHandler>(
- host, Network::Metainfo::domainName);
+ return host->HandlersByName<NetworkHandler>(Network::Metainfo::domainName);
}
void NetworkHandler::Wire(UberDispatcher* dispatcher) {
@@ -1075,8 +1077,8 @@ void NetworkHandler::ClearBrowserCookies(
}
if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&ClearCookiesOnIO,
base::Unretained(storage_partition_->GetURLRequestContext()),
@@ -1103,8 +1105,8 @@ void NetworkHandler::GetCookies(Maybe<Array<String>> protocol_urls,
scoped_refptr<CookieRetriever> retriever =
new CookieRetriever(std::move(callback));
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&CookieRetriever::RetrieveCookiesOnIO, retriever,
base::Unretained(storage_partition_->GetURLRequestContext()),
@@ -1127,8 +1129,8 @@ void NetworkHandler::GetAllCookies(
scoped_refptr<CookieRetriever> retriever =
new CookieRetriever(std::move(callback));
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&CookieRetriever::RetrieveAllCookiesOnIO, retriever,
base::Unretained(storage_partition_->GetURLRequestContext())));
@@ -1177,8 +1179,8 @@ void NetworkHandler::SetCookie(const std::string& name,
}
if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&SetCookieOnIO,
base::Unretained(storage_partition_->GetURLRequestContext()),
@@ -1217,8 +1219,8 @@ void NetworkHandler::SetCookies(
}
if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&SetCookiesOnIO,
base::Unretained(storage_partition_->GetURLRequestContext()),
@@ -1269,8 +1271,8 @@ void NetworkHandler::DeleteCookies(
}
if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&DeleteCookiesOnIO,
base::Unretained(storage_partition_->GetURLRequestContext()), name,
@@ -1602,7 +1604,7 @@ void NetworkHandler::NavigationRequestWillBeSent(
frontend_->RequestWillBeSent(
id, id, url_without_fragment, std::move(request), current_ticks,
current_wall_time, std::move(initiator), std::move(redirect_response),
- std::string(Page::ResourceTypeEnum::Document), std::move(frame_token),
+ std::string(Network::ResourceTypeEnum::Document), std::move(frame_token),
common_params.has_user_gesture);
}
@@ -1639,7 +1641,7 @@ void NetworkHandler::RequestSent(const std::string& request_id,
static_cast<double>(base::Time::kMicrosecondsPerSecond),
base::Time::Now().ToDoubleT(), std::move(initiator),
std::unique_ptr<Network::Response>(),
- std::string(Page::ResourceTypeEnum::Other),
+ std::string(Network::ResourceTypeEnum::Other),
Maybe<std::string>() /* frame_id */, request.has_user_gesture);
}
@@ -1839,7 +1841,6 @@ void NetworkHandler::ContinueInterceptedRequest(
}
base::Optional<net::Error> error;
- bool mark_as_canceled = false;
if (error_reason.isJust()) {
bool ok;
error = NetErrorFromString(error_reason.fromJust(), &ok);
@@ -1847,15 +1848,13 @@ void NetworkHandler::ContinueInterceptedRequest(
callback->sendFailure(Response::InvalidParams("Invalid errorReason."));
return;
}
-
- mark_as_canceled = true;
}
auto modifications =
std::make_unique<DevToolsNetworkInterceptor::Modifications>(
std::move(error), std::move(raw_response), std::move(url),
std::move(method), std::move(post_data), std::move(headers),
- std::move(auth_challenge_response), mark_as_canceled);
+ std::move(auth_challenge_response));
if (url_loader_interceptor_) {
url_loader_interceptor_->ContinueInterceptedRequest(
@@ -2040,43 +2039,43 @@ namespace {
const char* ResourceTypeToString(ResourceType resource_type) {
switch (resource_type) {
case RESOURCE_TYPE_MAIN_FRAME:
- return protocol::Page::ResourceTypeEnum::Document;
+ return protocol::Network::ResourceTypeEnum::Document;
case RESOURCE_TYPE_SUB_FRAME:
- return protocol::Page::ResourceTypeEnum::Document;
+ return protocol::Network::ResourceTypeEnum::Document;
case RESOURCE_TYPE_STYLESHEET:
- return protocol::Page::ResourceTypeEnum::Stylesheet;
+ return protocol::Network::ResourceTypeEnum::Stylesheet;
case RESOURCE_TYPE_SCRIPT:
- return protocol::Page::ResourceTypeEnum::Script;
+ return protocol::Network::ResourceTypeEnum::Script;
case RESOURCE_TYPE_IMAGE:
- return protocol::Page::ResourceTypeEnum::Image;
+ return protocol::Network::ResourceTypeEnum::Image;
case RESOURCE_TYPE_FONT_RESOURCE:
- return protocol::Page::ResourceTypeEnum::Font;
+ return protocol::Network::ResourceTypeEnum::Font;
case RESOURCE_TYPE_SUB_RESOURCE:
- return protocol::Page::ResourceTypeEnum::Other;
+ return protocol::Network::ResourceTypeEnum::Other;
case RESOURCE_TYPE_OBJECT:
- return protocol::Page::ResourceTypeEnum::Other;
+ return protocol::Network::ResourceTypeEnum::Other;
case RESOURCE_TYPE_MEDIA:
- return protocol::Page::ResourceTypeEnum::Media;
+ return protocol::Network::ResourceTypeEnum::Media;
case RESOURCE_TYPE_WORKER:
- return protocol::Page::ResourceTypeEnum::Other;
+ return protocol::Network::ResourceTypeEnum::Other;
case RESOURCE_TYPE_SHARED_WORKER:
- return protocol::Page::ResourceTypeEnum::Other;
+ return protocol::Network::ResourceTypeEnum::Other;
case RESOURCE_TYPE_PREFETCH:
- return protocol::Page::ResourceTypeEnum::Fetch;
+ return protocol::Network::ResourceTypeEnum::Fetch;
case RESOURCE_TYPE_FAVICON:
- return protocol::Page::ResourceTypeEnum::Other;
+ return protocol::Network::ResourceTypeEnum::Other;
case RESOURCE_TYPE_XHR:
- return protocol::Page::ResourceTypeEnum::XHR;
+ return protocol::Network::ResourceTypeEnum::XHR;
case RESOURCE_TYPE_PING:
- return protocol::Page::ResourceTypeEnum::Ping;
+ return protocol::Network::ResourceTypeEnum::Ping;
case RESOURCE_TYPE_SERVICE_WORKER:
- return protocol::Page::ResourceTypeEnum::Other;
+ return protocol::Network::ResourceTypeEnum::Other;
case RESOURCE_TYPE_CSP_REPORT:
- return protocol::Page::ResourceTypeEnum::CSPViolationReport;
+ return protocol::Network::ResourceTypeEnum::CSPViolationReport;
case RESOURCE_TYPE_PLUGIN_RESOURCE:
- return protocol::Page::ResourceTypeEnum::Other;
+ return protocol::Network::ResourceTypeEnum::Other;
default:
- return protocol::Page::ResourceTypeEnum::Other;
+ return protocol::Network::ResourceTypeEnum::Other;
}
}
diff --git a/chromium/content/browser/devtools/protocol/page_handler.cc b/chromium/content/browser/devtools/protocol/page_handler.cc
index 92d78224bbe..2f0ea698213 100644
--- a/chromium/content/browser/devtools/protocol/page_handler.cc
+++ b/chromium/content/browser/devtools/protocol/page_handler.cc
@@ -23,7 +23,7 @@
#include "base/task/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
-#include "content/browser/devtools/devtools_session.h"
+#include "content/browser/devtools/devtools_agent_host_impl.h"
#include "content/browser/devtools/protocol/devtools_download_manager_delegate.h"
#include "content/browser/devtools/protocol/devtools_download_manager_helper.h"
#include "content/browser/devtools/protocol/emulation_handler.h"
@@ -34,7 +34,7 @@
#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/browser/web_contents/web_contents_view.h"
-#include "content/common/view_messages.h"
+#include "content/common/widget_messages.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/download_manager.h"
@@ -175,16 +175,11 @@ void GetMetadataFromFrame(const media::VideoFrame& frame,
media::VideoFrameMetadata::ROOT_SCROLL_OFFSET_X, &root_scroll_offset_x);
success &= frame.metadata()->GetDouble(
media::VideoFrameMetadata::ROOT_SCROLL_OFFSET_Y, &root_scroll_offset_y);
-#if defined(OS_ANDROID)
success &= frame.metadata()->GetDouble(
media::VideoFrameMetadata::TOP_CONTROLS_HEIGHT, top_controls_height);
success &= frame.metadata()->GetDouble(
media::VideoFrameMetadata::TOP_CONTROLS_SHOWN_RATIO,
top_controls_shown_ratio);
-#else
- *top_controls_height = 0.;
- *top_controls_shown_ratio = 0.;
-#endif // defined(OS_ANDROID)
DCHECK(success);
root_scroll_offset->set_x(root_scroll_offset_x);
@@ -193,7 +188,8 @@ void GetMetadataFromFrame(const media::VideoFrame& frame,
} // namespace
-PageHandler::PageHandler(EmulationHandler* emulation_handler)
+PageHandler::PageHandler(EmulationHandler* emulation_handler,
+ bool allow_set_download_behavior)
: DevToolsDomainHandler(Page::Metainfo::domainName),
enabled_(false),
screencast_enabled_(false),
@@ -210,6 +206,7 @@ PageHandler::PageHandler(EmulationHandler* emulation_handler)
last_surface_size_(gfx::Size()),
host_(nullptr),
emulation_handler_(emulation_handler),
+ allow_set_download_behavior_(allow_set_download_behavior),
observer_(this),
weak_factory_(this) {
bool create_video_consumer = true;
@@ -247,8 +244,7 @@ std::vector<PageHandler*> PageHandler::EnabledForWebContents(
// static
std::vector<PageHandler*> PageHandler::ForAgentHost(
DevToolsAgentHostImpl* host) {
- return DevToolsSession::HandlersForAgentHost<PageHandler>(
- host, Page::Metainfo::domainName);
+ return host->HandlersByName<PageHandler>(Page::Metainfo::domainName);
}
void PageHandler::SetRenderer(int process_host_id,
@@ -404,7 +400,7 @@ Response PageHandler::Close() {
WebContentsImpl* web_contents = GetWebContents();
if (!web_contents)
return Response::Error("Not attached to a page");
- web_contents->DispatchBeforeUnload();
+ web_contents->DispatchBeforeUnload(false /* auto_cancel */);
return Response::OK();
}
@@ -448,6 +444,8 @@ void PageHandler::Navigate(const std::string& url,
type = ui::PAGE_TRANSITION_LINK;
else if (transition_type == Page::TransitionTypeEnum::Typed)
type = ui::PAGE_TRANSITION_TYPED;
+ else if (transition_type == Page::TransitionTypeEnum::Address_bar)
+ type = ui::PAGE_TRANSITION_FROM_ADDRESS_BAR;
else if (transition_type == Page::TransitionTypeEnum::Auto_bookmark)
type = ui::PAGE_TRANSITION_AUTO_BOOKMARK;
else if (transition_type == Page::TransitionTypeEnum::Auto_subframe)
@@ -605,7 +603,8 @@ void PageHandler::CaptureScreenshot(
Maybe<Page::Viewport> clip,
Maybe<bool> from_surface,
std::unique_ptr<CaptureScreenshotCallback> callback) {
- if (!host_ || !host_->GetRenderWidgetHost()) {
+ if (!host_ || !host_->GetRenderWidgetHost() ||
+ !host_->GetRenderWidgetHost()->GetView()) {
callback->sendFailure(Response::InternalError());
return;
}
@@ -791,7 +790,8 @@ Response PageHandler::StartScreencast(Maybe<std::string> format,
if (has_compositor_frame_metadata_) {
InnerSwapCompositorFrame();
} else {
- widget_host->Send(new ViewMsg_ForceRedraw(widget_host->GetRoutingID(), 0));
+ widget_host->Send(
+ new WidgetMsg_ForceRedraw(widget_host->GetRoutingID(), 0));
}
return Response::FallThrough();
}
@@ -857,6 +857,9 @@ Response PageHandler::BringToFront() {
Response PageHandler::SetDownloadBehavior(const std::string& behavior,
Maybe<std::string> download_path) {
+ if (!allow_set_download_behavior_)
+ return Response::Error("Not allowed.");
+
WebContentsImpl* web_contents = GetWebContents();
if (!web_contents)
return Response::InternalError();
@@ -945,13 +948,11 @@ void PageHandler::InnerSwapCompositorFrame() {
if (snapshot_size.IsEmpty())
return;
- double top_controls_height = 0.;
- double top_controls_shown_ratio = 0.;
-#if defined(OS_ANDROID)
- top_controls_height = last_compositor_frame_metadata_.top_controls_height;
- top_controls_shown_ratio =
+ double top_controls_height =
+ last_compositor_frame_metadata_.top_controls_height;
+ double top_controls_shown_ratio =
last_compositor_frame_metadata_.top_controls_shown_ratio;
-#endif
+
std::unique_ptr<Page::ScreencastFrameMetadata> page_metadata =
BuildScreencastFrameMetadata(
surface_size, last_compositor_frame_metadata_.device_scale_factor,
diff --git a/chromium/content/browser/devtools/protocol/page_handler.h b/chromium/content/browser/devtools/protocol/page_handler.h
index ea8e3b17f31..ba523ccc282 100644
--- a/chromium/content/browser/devtools/protocol/page_handler.h
+++ b/chromium/content/browser/devtools/protocol/page_handler.h
@@ -58,7 +58,7 @@ class PageHandler : public DevToolsDomainHandler,
public Page::Backend,
public RenderWidgetHostObserver {
public:
- explicit PageHandler(EmulationHandler* handler);
+ PageHandler(EmulationHandler* handler, bool allow_set_download_behavior);
~PageHandler() override;
static std::vector<PageHandler*> EnabledForWebContents(
@@ -212,6 +212,7 @@ class PageHandler : public DevToolsDomainHandler,
RenderFrameHostImpl* host_;
EmulationHandler* emulation_handler_;
+ bool allow_set_download_behavior_;
std::unique_ptr<Page::Frontend> frontend_;
ScopedObserver<RenderWidgetHost, RenderWidgetHostObserver> observer_;
JavaScriptDialogCallback pending_dialog_;
diff --git a/chromium/content/browser/devtools/protocol/security_handler.cc b/chromium/content/browser/devtools/protocol/security_handler.cc
index bdc3c63acb8..29e074d4c76 100644
--- a/chromium/content/browser/devtools/protocol/security_handler.cc
+++ b/chromium/content/browser/devtools/protocol/security_handler.cc
@@ -10,7 +10,7 @@
#include <vector>
#include "base/base64.h"
-#include "content/browser/devtools/devtools_session.h"
+#include "content/browser/devtools/devtools_agent_host_impl.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_entry.h"
@@ -104,8 +104,7 @@ void AddExplanations(
// static
std::vector<SecurityHandler*> SecurityHandler::ForAgentHost(
DevToolsAgentHostImpl* host) {
- return DevToolsSession::HandlersForAgentHost<SecurityHandler>(
- host, Security::Metainfo::domainName);
+ return host->HandlersByName<SecurityHandler>(Security::Metainfo::domainName);
}
SecurityHandler::SecurityHandler()
diff --git a/chromium/content/browser/devtools/protocol/service_worker_handler.cc b/chromium/content/browser/devtools/protocol/service_worker_handler.cc
index 06c7cf436fd..0164e28d6f4 100644
--- a/chromium/content/browser/devtools/protocol/service_worker_handler.cc
+++ b/chromium/content/browser/devtools/protocol/service_worker_handler.cc
@@ -8,6 +8,7 @@
#include "base/containers/flat_set.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/task/post_task.h"
#include "content/browser/background_sync/background_sync_context.h"
#include "content/browser/background_sync/background_sync_manager.h"
#include "content/browser/devtools/service_worker_devtools_agent_host.h"
@@ -22,6 +23,7 @@
#include "content/browser/storage_partition_impl_map.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/devtools_agent_host.h"
#include "content/public/browser/render_process_host.h"
@@ -89,8 +91,8 @@ void GetDevToolsRouteInfoOnIO(
const base::Callback<void(int, int)>& callback) {
if (content::ServiceWorkerVersion* version =
context->GetLiveVersion(version_id)) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(
callback, version->embedded_worker()->process_id(),
version->embedded_worker()->worker_devtools_agent_route_id()));
@@ -173,6 +175,7 @@ void ServiceWorkerHandler::SetRenderer(int process_host_id,
storage_partition_ =
static_cast<StoragePartitionImpl*>(process_host->GetStoragePartition());
DCHECK(storage_partition_);
+ browser_context_ = process_host->GetBrowserContext();
context_ = static_cast<ServiceWorkerContextWrapper*>(
storage_partition_->GetServiceWorkerContext());
}
@@ -243,8 +246,9 @@ Response ServiceWorkerHandler::StopWorker(const std::string& version_id) {
int64_t id = 0;
if (!base::StringToInt64(version_id, &id))
return CreateInvalidVersionIdErrorResponse();
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::BindOnce(&StopServiceWorkerOnIO, context_, id));
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(&StopServiceWorkerOnIO, context_, id));
return Response::OK();
}
@@ -281,8 +285,8 @@ Response ServiceWorkerHandler::InspectWorker(const std::string& version_id) {
int64_t id = blink::mojom::kInvalidServiceWorkerVersionId;
if (!base::StringToInt64(version_id, &id))
return CreateInvalidVersionIdErrorResponse();
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&GetDevToolsRouteInfoOnIO, context_, id,
base::Bind(&ServiceWorkerHandler::OpenNewDevToolsWindow,
weak_factory_.GetWeakPtr())));
@@ -334,10 +338,10 @@ Response ServiceWorkerHandler::DispatchSyncEvent(
BackgroundSyncContext* sync_context =
storage_partition_->GetBackgroundSyncContext();
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::BindOnce(&DispatchSyncEventOnIO, context_,
- base::WrapRefCounted(sync_context),
- GURL(origin), id, tag, last_chance));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(&DispatchSyncEventOnIO, context_,
+ base::WrapRefCounted(sync_context),
+ GURL(origin), id, tag, last_chance));
return Response::OK();
}
diff --git a/chromium/content/browser/devtools/protocol/storage_handler.cc b/chromium/content/browser/devtools/protocol/storage_handler.cc
index ad5bb6d37ed..436be9bb7ff 100644
--- a/chromium/content/browser/devtools/protocol/storage_handler.cc
+++ b/chromium/content/browser/devtools/protocol/storage_handler.cc
@@ -10,8 +10,10 @@
#include <vector>
#include "base/strings/string_split.h"
+#include "base/task/post_task.h"
#include "content/browser/cache_storage/cache_storage_context_impl.h"
#include "content/browser/indexed_db/indexed_db_context_impl.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/storage_partition.h"
@@ -76,19 +78,19 @@ void GotUsageAndQuotaDataCallback(
int64_t quota,
base::flat_map<storage::QuotaClient::ID, int64_t> usage_breakdown) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(ReportUsageAndQuotaDataOnUIThread, std::move(callback),
code, usage, quota, std::move(usage_breakdown)));
}
void GetUsageAndQuotaOnIOThread(
storage::QuotaManager* manager,
- const GURL& url,
+ const url::Origin& origin,
std::unique_ptr<StorageHandler::GetUsageAndQuotaCallback> callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
manager->GetUsageAndQuotaWithBreakdown(
- url, blink::mojom::StorageType::kTemporary,
+ origin, blink::mojom::StorageType::kTemporary,
base::BindOnce(&GotUsageAndQuotaDataCallback, std::move(callback)));
}
} // namespace
@@ -103,8 +105,8 @@ class StorageHandler::CacheStorageObserver : CacheStorageContextImpl::Observer {
CacheStorageObserver(base::WeakPtr<StorageHandler> owner_storage_handler,
CacheStorageContextImpl* cache_storage_context)
: owner_(owner_storage_handler), context_(cache_storage_context) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&CacheStorageObserver::AddObserverOnIOThread,
base::Unretained(this)));
}
@@ -130,8 +132,8 @@ class StorageHandler::CacheStorageObserver : CacheStorageContextImpl::Observer {
auto found = origins_.find(origin);
if (found == origins_.end())
return;
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&StorageHandler::NotifyCacheStorageListChanged, owner_,
origin.Serialize()));
}
@@ -140,8 +142,8 @@ class StorageHandler::CacheStorageObserver : CacheStorageContextImpl::Observer {
const std::string& cache_name) override {
if (origins_.find(origin) == origins_.end())
return;
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&StorageHandler::NotifyCacheStorageContentChanged,
owner_, origin.Serialize(), cache_name));
}
@@ -198,8 +200,8 @@ class StorageHandler::IndexedDBObserver : IndexedDBContextImpl::Observer {
auto found = origins_.find(origin);
if (found == origins_.end())
return;
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&StorageHandler::NotifyIndexedDBListChanged, owner_,
origin.Serialize()));
}
@@ -211,8 +213,8 @@ class StorageHandler::IndexedDBObserver : IndexedDBContextImpl::Observer {
auto found = origins_.find(origin);
if (found == origins_.end())
return;
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&StorageHandler::NotifyIndexedDBContentChanged, owner_,
origin.Serialize(), database_name, object_store_name));
}
@@ -330,10 +332,10 @@ void StorageHandler::GetUsageAndQuota(
}
storage::QuotaManager* manager = storage_partition_->GetQuotaManager();
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&GetUsageAndQuotaOnIOThread, base::RetainedRef(manager),
- origin_url, std::move(callback)));
+ url::Origin::Create(origin_url), std::move(callback)));
}
Response StorageHandler::TrackCacheStorageForOrigin(const std::string& origin) {
@@ -344,8 +346,8 @@ Response StorageHandler::TrackCacheStorageForOrigin(const std::string& origin) {
if (!origin_url.is_valid())
return Response::InvalidParams(origin + " is not a valid URL");
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&CacheStorageObserver::TrackOriginOnIOThread,
base::Unretained(GetCacheStorageObserver()),
url::Origin::Create(origin_url)));
@@ -361,8 +363,8 @@ Response StorageHandler::UntrackCacheStorageForOrigin(
if (!origin_url.is_valid())
return Response::InvalidParams(origin + " is not a valid URL");
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&CacheStorageObserver::UntrackOriginOnIOThread,
base::Unretained(GetCacheStorageObserver()),
url::Origin::Create(origin_url)));
diff --git a/chromium/content/browser/devtools/protocol/system_info_handler.cc b/chromium/content/browser/devtools/protocol/system_info_handler.cc
index c0c84ef83f8..def5f6bf0ee 100644
--- a/chromium/content/browser/devtools/protocol/system_info_handler.cc
+++ b/chromium/content/browser/devtools/protocol/system_info_handler.cc
@@ -11,10 +11,12 @@
#include "base/bind.h"
#include "base/command_line.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/task/post_task.h"
#include "build/build_config.h"
#include "content/browser/gpu/compositor_util.h"
#include "content/browser/gpu/gpu_data_manager_impl.h"
#include "content/browser/gpu/gpu_process_host.h"
+#include "content/public/browser/browser_task_traits.h"
#include "gpu/config/gpu_feature_type.h"
#include "gpu/config/gpu_info.h"
#include "gpu/config/gpu_switches.h"
@@ -88,6 +90,10 @@ class AuxGPUInfoEnumerator : public gpu::GPUInfo::Enumerator {
void EndOverlayCapability() override {}
+ void BeginDx12VulkanVersionInfo() override {}
+
+ void EndDx12VulkanVersionInfo() override {}
+
void BeginAuxAttributes() override {
in_aux_attributes_ = true;
}
@@ -164,8 +170,8 @@ class SystemInfoHandlerGpuObserver : public content::GpuDataManagerObserver {
std::unique_ptr<GetInfoCallback> callback)
: callback_(std::move(callback)),
weak_factory_(this) {
- BrowserThread::PostDelayedTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostDelayedTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&SystemInfoHandlerGpuObserver::ObserverWatchdogCallback,
weak_factory_.GetWeakPtr()),
base::TimeDelta::FromMilliseconds(kGPUInfoWatchdogTimeoutMs));
diff --git a/chromium/content/browser/devtools/protocol/target_handler.cc b/chromium/content/browser/devtools/protocol/target_handler.cc
index f24ac4f28e2..3e03ef9164e 100644
--- a/chromium/content/browser/devtools/protocol/target_handler.cc
+++ b/chromium/content/browser/devtools/protocol/target_handler.cc
@@ -13,8 +13,8 @@
#include "base/values.h"
#include "build/build_config.h"
#include "content/browser/devtools/browser_devtools_agent_host.h"
+#include "content/browser/devtools/devtools_agent_host_impl.h"
#include "content/browser/devtools/devtools_manager.h"
-#include "content/browser/devtools/devtools_session.h"
#include "content/browser/devtools/target_registry.h"
#include "content/browser/frame_host/navigation_handle_impl.h"
#include "content/public/browser/browser_context.h"
@@ -27,6 +27,8 @@ namespace protocol {
namespace {
+const char kNotAllowedError[] = "Not allowed.";
+
static const char kInitializerScript[] = R"(
(function() {
const bindingName = "%s";
@@ -99,14 +101,37 @@ base::LazyInstance<base::flat_map<DevToolsAgentHost*,
std::unique_ptr<BrowserToPageConnector>>>::
Leaky g_browser_to_page_connectors;
-class BrowserToPageConnector : public DevToolsAgentHostClient {
+class BrowserToPageConnector {
public:
+ class BrowserConnectorHostClient : public DevToolsAgentHostClient {
+ public:
+ BrowserConnectorHostClient(BrowserToPageConnector* connector,
+ DevToolsAgentHost* host)
+ : connector_(connector) {
+ // TODO(dgozman): handle return value of AttachClient.
+ host->AttachClient(this);
+ }
+ void DispatchProtocolMessage(DevToolsAgentHost* agent_host,
+ const std::string& message) override {
+ connector_->DispatchProtocolMessage(agent_host, message);
+ }
+ void AgentHostClosed(DevToolsAgentHost* agent_host) override {
+ connector_->AgentHostClosed(agent_host);
+ }
+
+ private:
+ BrowserToPageConnector* connector_;
+ DISALLOW_COPY_AND_ASSIGN(BrowserConnectorHostClient);
+ };
+
BrowserToPageConnector(const std::string& binding_name,
DevToolsAgentHost* page_host)
: binding_name_(binding_name), page_host_(page_host) {
browser_host_ = BrowserDevToolsAgentHost::CreateForDiscovery();
- browser_host_->AttachClient(this);
- page_host_->AttachClient(this);
+ browser_host_client_ =
+ std::make_unique<BrowserConnectorHostClient>(this, browser_host_.get());
+ page_host_client_ =
+ std::make_unique<BrowserConnectorHostClient>(this, page_host_.get());
SendProtocolMessageToPage("Page.enable", std::make_unique<base::Value>());
SendProtocolMessageToPage("Runtime.enable",
@@ -143,11 +168,11 @@ class BrowserToPageConnector : public DevToolsAgentHostClient {
message.Set("params", std::move(params));
std::string json_message;
base::JSONWriter::Write(message, &json_message);
- page_host_->DispatchProtocolMessage(this, json_message);
+ page_host_->DispatchProtocolMessage(page_host_client_.get(), json_message);
}
void DispatchProtocolMessage(DevToolsAgentHost* agent_host,
- const std::string& message) override {
+ const std::string& message) {
if (agent_host == page_host_.get()) {
std::unique_ptr<base::Value> value = base::JSONReader::Read(message);
if (!value || !value->is_dict())
@@ -166,7 +191,8 @@ class BrowserToPageConnector : public DevToolsAgentHostClient {
base::Value* payload = params->FindKey("payload");
if (!payload || !payload->is_string())
return;
- browser_host_->DispatchProtocolMessage(this, payload->GetString());
+ browser_host_->DispatchProtocolMessage(browser_host_client_.get(),
+ payload->GetString());
return;
}
DCHECK(agent_host == browser_host_.get());
@@ -185,12 +211,12 @@ class BrowserToPageConnector : public DevToolsAgentHostClient {
SendProtocolMessageToPage("Runtime.evaluate", std::move(params));
}
- void AgentHostClosed(DevToolsAgentHost* agent_host) override {
+ void AgentHostClosed(DevToolsAgentHost* agent_host) {
if (agent_host == browser_host_.get()) {
- page_host_->DetachClient(this);
+ page_host_->DetachClient(page_host_client_.get());
} else {
DCHECK(agent_host == page_host_.get());
- browser_host_->DetachClient(this);
+ browser_host_->DetachClient(browser_host_client_.get());
}
g_browser_to_page_connectors.Get().erase(page_host_.get());
}
@@ -198,6 +224,8 @@ class BrowserToPageConnector : public DevToolsAgentHostClient {
std::string binding_name_;
scoped_refptr<DevToolsAgentHost> browser_host_;
scoped_refptr<DevToolsAgentHost> page_host_;
+ std::unique_ptr<BrowserConnectorHostClient> browser_host_client_;
+ std::unique_ptr<BrowserConnectorHostClient> page_host_client_;
int page_message_id_ = 0;
DISALLOW_COPY_AND_ASSIGN(BrowserToPageConnector);
@@ -391,7 +419,7 @@ void TargetHandler::Throttle::Clear() {
}
}
-TargetHandler::TargetHandler(bool browser_only,
+TargetHandler::TargetHandler(AccessMode access_mode,
const std::string& owner_target_id,
TargetRegistry* target_registry)
: DevToolsDomainHandler(Target::Metainfo::domainName),
@@ -399,7 +427,7 @@ TargetHandler::TargetHandler(bool browser_only,
base::Bind(&TargetHandler::AutoAttach, base::Unretained(this)),
base::Bind(&TargetHandler::AutoDetach, base::Unretained(this))),
discover_(false),
- browser_only_(browser_only),
+ access_mode_(access_mode),
owner_target_id_(owner_target_id),
target_registry_(target_registry),
weak_factory_(this) {}
@@ -410,8 +438,7 @@ TargetHandler::~TargetHandler() {
// static
std::vector<TargetHandler*> TargetHandler::ForAgentHost(
DevToolsAgentHostImpl* host) {
- return DevToolsSession::HandlersForAgentHost<TargetHandler>(
- host, Target::Metainfo::domainName);
+ return host->HandlersByName<TargetHandler>(Target::Metainfo::domainName);
}
void TargetHandler::Wire(UberDispatcher* dispatcher) {
@@ -470,7 +497,7 @@ Response TargetHandler::FindSession(Maybe<std::string> session_id,
Session** session,
bool fall_through) {
*session = nullptr;
- fall_through &= !browser_only_;
+ fall_through &= access_mode_ != AccessMode::kBrowser;
if (session_id.isJust()) {
auto it = attached_sessions_.find(session_id.fromJust());
if (it == attached_sessions_.end()) {
@@ -504,6 +531,8 @@ Response TargetHandler::FindSession(Maybe<std::string> session_id,
// ----------------- Protocol ----------------------
Response TargetHandler::SetDiscoverTargets(bool discover) {
+ if (access_mode_ == AccessMode::kAutoAttachOnly)
+ return Response::Error(kNotAllowedError);
if (discover_ == discover)
return Response::OK();
discover_ = discover;
@@ -519,11 +548,16 @@ Response TargetHandler::SetDiscoverTargets(bool discover) {
Response TargetHandler::SetAutoAttach(bool auto_attach,
bool wait_for_debugger_on_start,
Maybe<bool> flatten) {
+ if (flatten.fromMaybe(false) && !target_registry_) {
+ return Response::InvalidParams(
+ "Will only provide flatten access for browser endpoint");
+ }
flatten_auto_attach_ = flatten.fromMaybe(false);
auto_attacher_.SetAutoAttach(auto_attach, wait_for_debugger_on_start);
if (!auto_attacher_.ShouldThrottleFramesNavigation())
ClearThrottles();
- return browser_only_ ? Response::OK() : Response::FallThrough();
+ return access_mode_ == AccessMode::kBrowser ? Response::OK()
+ : Response::FallThrough();
}
Response TargetHandler::SetRemoteLocations(
@@ -534,6 +568,8 @@ Response TargetHandler::SetRemoteLocations(
Response TargetHandler::AttachToTarget(const std::string& target_id,
Maybe<bool> flatten,
std::string* out_session_id) {
+ if (access_mode_ == AccessMode::kAutoAttachOnly)
+ return Response::Error(kNotAllowedError);
// TODO(dgozman): only allow reported hosts.
scoped_refptr<DevToolsAgentHost> agent_host =
DevToolsAgentHost::GetForId(target_id);
@@ -549,6 +585,8 @@ Response TargetHandler::AttachToTarget(const std::string& target_id,
}
Response TargetHandler::AttachToBrowserTarget(std::string* out_session_id) {
+ if (access_mode_ != AccessMode::kBrowser)
+ return Response::Error(kNotAllowedError);
scoped_refptr<DevToolsAgentHost> agent_host =
DevToolsAgentHost::CreateForBrowser(
nullptr, DevToolsAgentHost::CreateServerSocketCallback());
@@ -558,6 +596,8 @@ Response TargetHandler::AttachToBrowserTarget(std::string* out_session_id) {
Response TargetHandler::DetachFromTarget(Maybe<std::string> session_id,
Maybe<std::string> target_id) {
+ if (access_mode_ == AccessMode::kAutoAttachOnly)
+ return Response::Error(kNotAllowedError);
Session* session = nullptr;
Response response =
FindSession(std::move(session_id), std::move(target_id), &session, false);
@@ -587,6 +627,8 @@ Response TargetHandler::SendMessageToTarget(const std::string& message,
Response TargetHandler::GetTargetInfo(
Maybe<std::string> maybe_target_id,
std::unique_ptr<Target::TargetInfo>* target_info) {
+ if (access_mode_ == AccessMode::kAutoAttachOnly)
+ return Response::Error(kNotAllowedError);
const std::string& target_id =
maybe_target_id.isJust() ? maybe_target_id.fromJust() : owner_target_id_;
// TODO(dgozman): only allow reported hosts.
@@ -599,6 +641,8 @@ Response TargetHandler::GetTargetInfo(
}
Response TargetHandler::ActivateTarget(const std::string& target_id) {
+ if (access_mode_ == AccessMode::kAutoAttachOnly)
+ return Response::Error(kNotAllowedError);
// TODO(dgozman): only allow reported hosts.
scoped_refptr<DevToolsAgentHost> agent_host(
DevToolsAgentHost::GetForId(target_id));
@@ -610,6 +654,8 @@ Response TargetHandler::ActivateTarget(const std::string& target_id) {
Response TargetHandler::CloseTarget(const std::string& target_id,
bool* out_success) {
+ if (access_mode_ == AccessMode::kAutoAttachOnly)
+ return Response::Error(kNotAllowedError);
scoped_refptr<DevToolsAgentHost> agent_host =
DevToolsAgentHost::GetForId(target_id);
if (!agent_host)
@@ -621,10 +667,8 @@ Response TargetHandler::CloseTarget(const std::string& target_id,
Response TargetHandler::ExposeDevToolsProtocol(
const std::string& target_id,
Maybe<std::string> binding_name) {
- if (!browser_only_) {
- return Response::InvalidParams(
- "Cannot grant remote debugging capability from non-browser session.");
- }
+ if (access_mode_ != AccessMode::kBrowser)
+ return Response::InvalidParams(kNotAllowedError);
scoped_refptr<DevToolsAgentHost> agent_host =
DevToolsAgentHost::GetForId(target_id);
if (!agent_host)
@@ -650,6 +694,8 @@ Response TargetHandler::CreateTarget(const std::string& url,
Maybe<std::string> context_id,
Maybe<bool> enable_begin_frame_control,
std::string* out_target_id) {
+ if (access_mode_ == AccessMode::kAutoAttachOnly)
+ return Response::Error(kNotAllowedError);
DevToolsManagerDelegate* delegate =
DevToolsManager::GetInstance()->delegate();
if (!delegate)
@@ -664,6 +710,8 @@ Response TargetHandler::CreateTarget(const std::string& url,
Response TargetHandler::GetTargets(
std::unique_ptr<protocol::Array<Target::TargetInfo>>* target_infos) {
+ if (access_mode_ == AccessMode::kAutoAttachOnly)
+ return Response::Error(kNotAllowedError);
*target_infos = protocol::Array<Target::TargetInfo>::create();
for (const auto& host : DevToolsAgentHost::GetOrCreateAll())
(*target_infos)->addItem(CreateInfo(host.get()));
@@ -720,8 +768,12 @@ void TargetHandler::DevToolsAgentHostCrashed(DevToolsAgentHost* host,
: 0);
}
+// ----------------- More protocol methods -------------------
+
protocol::Response TargetHandler::CreateBrowserContext(
std::string* out_context_id) {
+ if (access_mode_ != AccessMode::kBrowser)
+ return Response::Error(kNotAllowedError);
DevToolsManagerDelegate* delegate =
DevToolsManager::GetInstance()->delegate();
if (!delegate)
@@ -730,11 +782,13 @@ protocol::Response TargetHandler::CreateBrowserContext(
if (!context)
return Response::Error("Failed to create browser context.");
*out_context_id = context->UniqueId();
- return protocol::Response::OK();
+ return Response::OK();
}
protocol::Response TargetHandler::GetBrowserContexts(
std::unique_ptr<protocol::Array<protocol::String>>* browser_context_ids) {
+ if (access_mode_ != AccessMode::kBrowser)
+ return Response::Error(kNotAllowedError);
DevToolsManagerDelegate* delegate =
DevToolsManager::GetInstance()->delegate();
if (!delegate)
@@ -744,17 +798,21 @@ protocol::Response TargetHandler::GetBrowserContexts(
*browser_context_ids = std::make_unique<protocol::Array<protocol::String>>();
for (auto* context : contexts)
(*browser_context_ids)->addItem(context->UniqueId());
- return protocol::Response::OK();
+ return Response::OK();
}
void TargetHandler::DisposeBrowserContext(
const std::string& context_id,
std::unique_ptr<DisposeBrowserContextCallback> callback) {
+ if (access_mode_ != AccessMode::kBrowser) {
+ callback->sendFailure(Response::Error(kNotAllowedError));
+ return;
+ }
DevToolsManagerDelegate* delegate =
DevToolsManager::GetInstance()->delegate();
if (!delegate) {
- callback->sendFailure(protocol::Response::Error(
- "Browser context management is not supported."));
+ callback->sendFailure(
+ Response::Error("Browser context management is not supported."));
return;
}
std::vector<content::BrowserContext*> contexts =
@@ -765,8 +823,8 @@ void TargetHandler::DisposeBrowserContext(
return context->UniqueId() == context_id;
});
if (context_it == contexts.end()) {
- callback->sendFailure(protocol::Response::Error(
- "Failed to find context with id " + context_id));
+ callback->sendFailure(
+ Response::Error("Failed to find context with id " + context_id));
return;
}
delegate->DisposeBrowserContext(
@@ -777,7 +835,7 @@ void TargetHandler::DisposeBrowserContext(
if (success)
callback->sendSuccess();
else
- callback->sendFailure(protocol::Response::Error(error));
+ callback->sendFailure(Response::Error(error));
},
std::move(callback)));
}
diff --git a/chromium/content/browser/devtools/protocol/target_handler.h b/chromium/content/browser/devtools/protocol/target_handler.h
index 06a9bbb9ca5..d7e449411c4 100644
--- a/chromium/content/browser/devtools/protocol/target_handler.h
+++ b/chromium/content/browser/devtools/protocol/target_handler.h
@@ -29,7 +29,17 @@ class TargetHandler : public DevToolsDomainHandler,
public Target::Backend,
public DevToolsAgentHostObserver {
public:
- TargetHandler(bool browser_only,
+ enum class AccessMode {
+ // Only setAutoAttach is supported. Any non-related target are not
+ // accessible.
+ kAutoAttachOnly,
+ // Standard mode of operation: both auto-attach and discovery.
+ kRegular,
+ // This mode also allows advanced method like Target.exposeDevToolsProtocol,
+ // which should not be exposed on a non-browser-wide connection.
+ kBrowser
+ };
+ TargetHandler(AccessMode access_mode,
const std::string& owner_target_id,
TargetRegistry* target_registry);
~TargetHandler() override;
@@ -115,7 +125,7 @@ class TargetHandler : public DevToolsDomainHandler,
std::map<std::string, std::unique_ptr<Session>> attached_sessions_;
std::map<DevToolsAgentHost*, Session*> auto_attached_sessions_;
std::set<DevToolsAgentHost*> reported_hosts_;
- bool browser_only_;
+ AccessMode access_mode_;
std::string owner_target_id_;
TargetRegistry* target_registry_;
base::flat_set<Throttle*> throttles_;
diff --git a/chromium/content/browser/devtools/protocol/tethering_handler.cc b/chromium/content/browser/devtools/protocol/tethering_handler.cc
index 4640abe9ff0..66f0dac1f6b 100644
--- a/chromium/content/browser/devtools/protocol/tethering_handler.cc
+++ b/chromium/content/browser/devtools/protocol/tethering_handler.cc
@@ -6,6 +6,8 @@
#include <map>
+#include "base/task/post_task.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "net/base/io_buffer.h"
#include "net/base/ip_address.h"
@@ -105,7 +107,7 @@ class SocketPump {
void Pump(net::StreamSocket* from, net::StreamSocket* to) {
scoped_refptr<net::IOBuffer> buffer =
- new net::IOBuffer(kSocketPumpBufferSize);
+ base::MakeRefCounted<net::IOBuffer>(kSocketPumpBufferSize);
int result =
from->Read(buffer.get(), kSocketPumpBufferSize,
base::BindOnce(&SocketPump::OnRead, base::Unretained(this),
@@ -285,8 +287,8 @@ TetheringHandler::TetheringImpl::~TetheringImpl() = default;
void TetheringHandler::TetheringImpl::Bind(
uint16_t port, std::unique_ptr<BindCallback> callback) {
if (bound_sockets_.find(port) != bound_sockets_.end()) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&BindCallback::sendFailure, std::move(callback),
Response::Error("Port already bound")));
return;
@@ -297,16 +299,16 @@ void TetheringHandler::TetheringImpl::Bind(
std::unique_ptr<BoundSocket> bound_socket =
std::make_unique<BoundSocket>(std::move(accepted), socket_callback_);
if (!bound_socket->Listen(port)) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&BindCallback::sendFailure, std::move(callback),
Response::Error("Could not bind port")));
return;
}
bound_sockets_[port] = std::move(bound_socket);
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&BindCallback::sendSuccess, std::move(callback)));
}
@@ -314,23 +316,23 @@ void TetheringHandler::TetheringImpl::Unbind(
uint16_t port, std::unique_ptr<UnbindCallback> callback) {
auto it = bound_sockets_.find(port);
if (it == bound_sockets_.end()) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&UnbindCallback::sendFailure, std::move(callback),
Response::InvalidParams("Port is not bound")));
return;
}
bound_sockets_.erase(it);
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&UnbindCallback::sendSuccess, std::move(callback)));
}
void TetheringHandler::TetheringImpl::Accepted(uint16_t port,
const std::string& name) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&TetheringHandler::Accepted, handler_, port, name));
}
diff --git a/chromium/content/browser/devtools/protocol/tracing_handler.cc b/chromium/content/browser/devtools/protocol/tracing_handler.cc
index a93a43faa7c..fd1dcd82417 100644
--- a/chromium/content/browser/devtools/protocol/tracing_handler.cc
+++ b/chromium/content/browser/devtools/protocol/tracing_handler.cc
@@ -18,15 +18,16 @@
#include "base/memory/ref_counted_memory.h"
#include "base/strings/string_split.h"
#include "base/strings/stringprintf.h"
+#include "base/task/post_task.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#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_startup_config.h"
+#include "content/browser/devtools/devtools_agent_host_impl.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"
@@ -37,6 +38,7 @@
#include "content/browser/gpu/gpu_process_host.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/tracing/tracing_controller_impl.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h"
#include "services/tracing/public/mojom/constants.mojom.h"
@@ -134,8 +136,8 @@ class DevToolsStreamEndpoint : public TracingController::TraceDataEndpoint {
void ReceiveTraceChunk(std::unique_ptr<std::string> chunk) override {
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&DevToolsStreamEndpoint::ReceiveTraceChunk, this,
std::move(chunk)));
return;
@@ -147,8 +149,8 @@ class DevToolsStreamEndpoint : public TracingController::TraceDataEndpoint {
void ReceiveTraceFinalContents(
std::unique_ptr<const base::DictionaryValue> metadata) override {
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&DevToolsStreamEndpoint::ReceiveTraceFinalContents,
this, std::move(metadata)));
return;
@@ -235,8 +237,7 @@ TracingHandler::~TracingHandler() = default;
// static
std::vector<TracingHandler*> TracingHandler::ForAgentHost(
DevToolsAgentHostImpl* host) {
- return DevToolsSession::HandlersForAgentHost<TracingHandler>(
- host, Tracing::Metainfo::domainName);
+ return host->HandlersByName<TracingHandler>(Tracing::Metainfo::domainName);
}
void TracingHandler::SetRenderer(int process_host_id,
@@ -406,8 +407,8 @@ void TracingHandler::Start(Maybe<std::string> categories,
}
// GPU process id can only be retrieved on IO thread. Do some thread hopping.
- BrowserThread::PostTaskAndReplyWithResult(
- BrowserThread::IO, FROM_HERE, base::BindOnce([]() {
+ base::PostTaskWithTraitsAndReplyWithResult(
+ FROM_HERE, {BrowserThread::IO}, base::BindOnce([]() {
GpuProcessHost* gpu_process_host =
GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
/* force_create */ false);
@@ -431,9 +432,9 @@ void TracingHandler::StartTracingWithGpuPid(
SetupProcessFilter(gpu_pid, nullptr);
TracingController::GetInstance()->StartTracing(
- trace_config_, base::BindRepeating(&TracingHandler::OnRecordingEnabled,
- weak_factory_.GetWeakPtr(),
- base::Passed(std::move(callback))));
+ trace_config_,
+ base::BindOnce(&TracingHandler::OnRecordingEnabled,
+ weak_factory_.GetWeakPtr(), std::move(callback)));
}
void TracingHandler::SetupProcessFilter(
@@ -484,7 +485,7 @@ void TracingHandler::OnProcessReady(RenderProcessHost* process_host) {
base::trace_event::TraceConfig::ProcessFilterConfig(
included_process_ids));
TracingController::GetInstance()->StartTracing(
- trace_config_, base::RepeatingCallback<void()>());
+ trace_config_, TracingController::StartTracingDoneCallback());
}
Response TracingHandler::End() {
@@ -518,9 +519,8 @@ Response TracingHandler::End() {
void TracingHandler::GetCategories(
std::unique_ptr<GetCategoriesCallback> callback) {
TracingController::GetInstance()->GetCategories(
- base::Bind(&TracingHandler::OnCategoriesReceived,
- weak_factory_.GetWeakPtr(),
- base::Passed(std::move(callback))));
+ base::BindOnce(&TracingHandler::OnCategoriesReceived,
+ weak_factory_.GetWeakPtr(), std::move(callback)));
}
void TracingHandler::OnRecordingEnabled(
@@ -573,8 +573,8 @@ void TracingHandler::RequestMemoryDump(
}
auto on_memory_dump_finished =
- base::Bind(&TracingHandler::OnMemoryDumpFinished,
- weak_factory_.GetWeakPtr(), base::Passed(std::move(callback)));
+ base::BindOnce(&TracingHandler::OnMemoryDumpFinished,
+ weak_factory_.GetWeakPtr(), std::move(callback));
memory_instrumentation::MemoryInstrumentation::GetInstance()
->RequestGlobalDumpAndAppendToTrace(
base::trace_event::MemoryDumpType::EXPLICITLY_TRIGGERED,
@@ -684,7 +684,7 @@ void TracingHandler::ReadyToCommitNavigation(
SetupProcessFilter(base::kNullProcessId,
navigation_handle->GetRenderFrameHost());
TracingController::GetInstance()->StartTracing(
- trace_config_, base::RepeatingCallback<void()>());
+ trace_config_, TracingController::StartTracingDoneCallback());
}
void TracingHandler::FrameDeleted(RenderFrameHostImpl* frame_host) {
diff --git a/chromium/content/browser/devtools/protocol_config.json b/chromium/content/browser/devtools/protocol_config.json
index 1c779296c95..98c9cee7ec0 100644
--- a/chromium/content/browser/devtools/protocol_config.json
+++ b/chromium/content/browser/devtools/protocol_config.json
@@ -11,7 +11,7 @@
"options": [
{
"domain": "Browser",
- "include": ["getVersion", "getHistograms", "getHistogram", "getBrowserCommandLine", "grantPermissions", "resetPermissions"]
+ "include": ["getVersion", "getHistograms", "getHistogram", "getBrowserCommandLine", "grantPermissions", "resetPermissions", "crash"]
},
{
"domain": "DOM",
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 f80fb077ae0..7c9bfca5847 100644
--- a/chromium/content/browser/devtools/render_frame_devtools_agent_host.cc
+++ b/chromium/content/browser/devtools/render_frame_devtools_agent_host.cc
@@ -11,11 +11,13 @@
#include "base/lazy_instance.h"
#include "base/memory/ptr_util.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/task/post_task.h"
#include "build/build_config.h"
#include "content/browser/bad_message.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/devtools/devtools_frame_trace_recorder.h"
#include "content/browser/devtools/devtools_manager.h"
+#include "content/browser/devtools/devtools_renderer_channel.h"
#include "content/browser/devtools/devtools_session.h"
#include "content/browser/devtools/protocol/browser_handler.h"
#include "content/browser/devtools/protocol/dom_handler.h"
@@ -43,6 +45,7 @@
#include "content/browser/web_package/signed_exchange_envelope.h"
#include "content/common/view_messages.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/navigation_handle.h"
@@ -56,6 +59,7 @@
#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"
+#include "third_party/blink/public/web/devtools_agent.mojom.h"
#if defined(OS_ANDROID)
#include "content/browser/renderer_host/compositor_impl_android.h"
@@ -209,7 +213,7 @@ void RenderFrameDevToolsAgentHost::OnNavigationResponseReceived(
std::string frame_id = ftn->devtools_frame_token().ToString();
GURL url = nav_request.common_params().url;
DispatchToAgents(ftn, &protocol::NetworkHandler::ResponseReceived, id, id,
- url, protocol::Page::ResourceTypeEnum::Document,
+ url, protocol::Network::ResourceTypeEnum::Document,
response.head, frame_id);
}
@@ -220,7 +224,7 @@ void RenderFrameDevToolsAgentHost::OnNavigationRequestFailed(
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, status);
+ protocol::Network::ResourceTypeEnum::Document, status);
}
// static
@@ -261,7 +265,7 @@ void RenderFrameDevToolsAgentHost::OnSignedExchangeCertificateResponseReceived(
const network::ResourceResponseHead& head) {
DispatchToAgents(frame_tree_node, &protocol::NetworkHandler::ResponseReceived,
request_id.ToString(), loader_id.ToString(), url,
- protocol::Page::ResourceTypeEnum::Other, head,
+ protocol::Network::ResourceTypeEnum::Other, head,
protocol::Maybe<std::string>());
}
@@ -272,7 +276,7 @@ void RenderFrameDevToolsAgentHost::OnSignedExchangeCertificateRequestCompleted(
const network::URLLoaderCompletionStatus& status) {
DispatchToAgents(frame_tree_node, &protocol::NetworkHandler::LoadingComplete,
request_id.ToString(),
- protocol::Page::ResourceTypeEnum::Other, status);
+ protocol::Network::ResourceTypeEnum::Other, status);
}
// static
@@ -427,13 +431,9 @@ WebContents* RenderFrameDevToolsAgentHost::GetWebContents() {
bool RenderFrameDevToolsAgentHost::AttachSession(DevToolsSession* session,
TargetRegistry* registry) {
- if (!ShouldAllowSession(session, frame_host_))
+ if (!ShouldAllowSession(session))
return false;
- session->SetRenderer(frame_host_ ? frame_host_->GetProcess()->GetID()
- : ChildProcessHost::kInvalidUniqueID,
- frame_host_);
-
protocol::EmulationHandler* emulation_handler =
new protocol::EmulationHandler();
session->AddHandler(base::WrapUnique(new protocol::BrowserHandler()));
@@ -452,22 +452,20 @@ bool RenderFrameDevToolsAgentHost::AttachSession(DevToolsSession* session,
session->AddHandler(base::WrapUnique(new protocol::SchemaHandler()));
session->AddHandler(base::WrapUnique(new protocol::ServiceWorkerHandler()));
session->AddHandler(base::WrapUnique(new protocol::StorageHandler()));
- if (!session->restricted()) {
- session->AddHandler(base::WrapUnique(new protocol::TargetHandler(
- false /* browser_only */, GetId(), registry)));
- }
- session->AddHandler(
- base::WrapUnique(new protocol::PageHandler(emulation_handler)));
+ session->AddHandler(base::WrapUnique(new protocol::TargetHandler(
+ session->client()->MayDiscoverTargets()
+ ? protocol::TargetHandler::AccessMode::kRegular
+ : protocol::TargetHandler::AccessMode::kAutoAttachOnly,
+ GetId(), registry)));
+ session->AddHandler(base::WrapUnique(new protocol::PageHandler(
+ emulation_handler, session->client()->MayAffectLocalFiles())));
session->AddHandler(base::WrapUnique(new protocol::SecurityHandler()));
if (!frame_tree_node_ || !frame_tree_node_->parent()) {
session->AddHandler(base::WrapUnique(
new protocol::TracingHandler(frame_tree_node_, GetIOContext())));
}
- if (EnsureAgent())
- session->AttachToAgent(agent_ptr_);
-
- if (sessions().size() == 1) {
+ if (sessions().empty()) {
bool use_video_capture_api = true;
#ifdef OS_ANDROID
// Video capture API cannot be used on Android WebView.
@@ -515,9 +513,7 @@ void RenderFrameDevToolsAgentHost::InspectElement(RenderFrameHost* frame_host,
view->TransformRootPointToViewCoordSpace(gfx::PointF(point)));
}
}
-
- if (host->EnsureAgent())
- host->agent_ptr_->InspectElement(point);
+ host->GetRendererChannel()->InspectElement(point);
}
RenderFrameDevToolsAgentHost::~RenderFrameDevToolsAgentHost() {
@@ -574,7 +570,7 @@ void RenderFrameDevToolsAgentHost::UpdateFrameHost(
render_frame_alive_ = true;
for (auto* inspector : protocol::InspectorHandler::ForAgentHost(this))
inspector->TargetReloadedAfterCrash();
- MaybeReattachToRenderFrame();
+ UpdateRendererChannel(IsAttached());
}
return;
}
@@ -589,11 +585,10 @@ void RenderFrameDevToolsAgentHost::UpdateFrameHost(
RevokePolicy();
frame_host_ = frame_host;
- agent_ptr_.reset();
std::vector<DevToolsSession*> restricted_sessions;
for (DevToolsSession* session : sessions()) {
- if (!ShouldAllowSession(session, frame_host))
+ if (!ShouldAllowSession(session))
restricted_sessions.push_back(session);
}
if (!restricted_sessions.empty())
@@ -605,21 +600,9 @@ void RenderFrameDevToolsAgentHost::UpdateFrameHost(
inspector->TargetReloadedAfterCrash();
}
- if (IsAttached()) {
+ if (IsAttached())
GrantPolicy();
- for (DevToolsSession* session : sessions()) {
- session->SetRenderer(frame_host ? frame_host->GetProcess()->GetID() : -1,
- frame_host);
- }
- MaybeReattachToRenderFrame();
- }
-}
-
-void RenderFrameDevToolsAgentHost::MaybeReattachToRenderFrame() {
- if (!EnsureAgent())
- return;
- for (DevToolsSession* session : sessions())
- session->AttachToAgent(agent_ptr_);
+ UpdateRendererChannel(IsAttached());
}
void RenderFrameDevToolsAgentHost::GrantPolicy() {
@@ -693,7 +676,7 @@ void RenderFrameDevToolsAgentHost::FrameDeleted(RenderFrameHost* rfh) {
void RenderFrameDevToolsAgentHost::RenderFrameDeleted(RenderFrameHost* rfh) {
if (rfh == frame_host_) {
render_frame_alive_ = false;
- agent_ptr_.reset();
+ UpdateRendererChannel(IsAttached());
}
}
@@ -703,7 +686,7 @@ void RenderFrameDevToolsAgentHost::DestroyOnRenderFrameGone() {
RevokePolicy();
ForceDetachAllSessions();
frame_host_ = nullptr;
- agent_ptr_.reset();
+ UpdateRendererChannel(IsAttached());
SetFrameTreeNode(nullptr);
Release();
}
@@ -912,8 +895,8 @@ void RenderFrameDevToolsAgentHost::SignalSynchronousSwapCompositorFrame(
static_cast<RenderFrameHostImpl*>(frame_host)->frame_tree_node()));
if (dtah) {
// Unblock the compositor.
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(
&RenderFrameDevToolsAgentHost::SynchronousSwapCompositorFrame,
dtah.get(), std::move(frame_metadata)));
@@ -936,12 +919,19 @@ void RenderFrameDevToolsAgentHost::SynchronousSwapCompositorFrame(
}
}
-bool RenderFrameDevToolsAgentHost::EnsureAgent() {
- if (!frame_host_ || !render_frame_alive_)
- return false;
- if (!agent_ptr_)
- frame_host_->GetRemoteAssociatedInterfaces()->GetInterface(&agent_ptr_);
- return true;
+void RenderFrameDevToolsAgentHost::UpdateRendererChannel(bool force) {
+ blink::mojom::DevToolsAgentAssociatedPtr agent_ptr;
+ blink::mojom::DevToolsAgentHostAssociatedRequest host_request;
+ if (frame_host_ && render_frame_alive_ && force) {
+ blink::mojom::DevToolsAgentHostAssociatedPtrInfo host_ptr_info;
+ host_request = mojo::MakeRequest(&host_ptr_info);
+ frame_host_->BindDevToolsAgent(std::move(host_ptr_info),
+ mojo::MakeRequest(&agent_ptr));
+ }
+ int process_id = frame_host_ ? frame_host_->GetProcess()->GetID()
+ : ChildProcessHost::kInvalidUniqueID;
+ GetRendererChannel()->SetRenderer(
+ std::move(agent_ptr), std::move(host_request), process_id, frame_host_);
}
bool RenderFrameDevToolsAgentHost::IsChildFrame() {
@@ -949,16 +939,15 @@ bool RenderFrameDevToolsAgentHost::IsChildFrame() {
}
bool RenderFrameDevToolsAgentHost::ShouldAllowSession(
- DevToolsSession* session,
- RenderFrameHostImpl* frame_host) {
+ DevToolsSession* session) {
DevToolsManager* manager = DevToolsManager::GetInstance();
- if (manager->delegate() && frame_host) {
- if (!manager->delegate()->AllowInspectingRenderFrameHost(frame_host))
+ if (manager->delegate() && frame_host_) {
+ if (!manager->delegate()->AllowInspectingRenderFrameHost(frame_host_))
return false;
}
const bool is_webui =
- frame_host && (frame_host->web_ui() || frame_host->pending_web_ui());
- if (!session->client()->MayAttachToRenderer(frame_host, is_webui))
+ frame_host_ && (frame_host_->web_ui() || frame_host_->pending_web_ui());
+ if (!session->client()->MayAttachToRenderer(frame_host_, is_webui))
return false;
return true;
}
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 37f0c8d1e77..42907088fe1 100644
--- a/chromium/content/browser/devtools/render_frame_devtools_agent_host.h
+++ b/chromium/content/browser/devtools/render_frame_devtools_agent_host.h
@@ -21,7 +21,6 @@
#include "content/public/browser/web_contents_observer.h"
#include "net/base/net_errors.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
-#include "third_party/blink/public/web/devtools_agent.mojom.h"
#if defined(OS_ANDROID)
#include "services/device/public/mojom/wake_lock.mojom.h"
@@ -165,6 +164,7 @@ class CONTENT_EXPORT RenderFrameDevToolsAgentHost
TargetRegistry* registry) override;
void DetachSession(DevToolsSession* session) override;
void InspectElement(RenderFrameHost* frame_host, int x, int y) override;
+ void UpdateRendererChannel(bool force) override;
// WebContentsObserver overrides.
void DidStartNavigation(NavigationHandle* navigation_handle) override;
@@ -185,13 +185,11 @@ class CONTENT_EXPORT RenderFrameDevToolsAgentHost
void OnSwapCompositorFrame(const IPC::Message& message);
void DestroyOnRenderFrameGone();
void UpdateFrameHost(RenderFrameHostImpl* frame_host);
- void MaybeReattachToRenderFrame();
void GrantPolicy();
void RevokePolicy();
void SetFrameTreeNode(FrameTreeNode* frame_tree_node);
- bool ShouldAllowSession(DevToolsSession* session,
- RenderFrameHostImpl* frame_host);
+ bool ShouldAllowSession(DevToolsSession* session);
#if defined(OS_ANDROID)
device::mojom::WakeLock* GetWakeLock();
@@ -199,7 +197,6 @@ class CONTENT_EXPORT RenderFrameDevToolsAgentHost
void SynchronousSwapCompositorFrame(
viz::CompositorFrameMetadata frame_metadata);
- bool EnsureAgent();
std::unique_ptr<DevToolsFrameTraceRecorder> frame_trace_recorder_;
#if defined(OS_ANDROID)
@@ -208,7 +205,6 @@ class CONTENT_EXPORT RenderFrameDevToolsAgentHost
// The active host we are talking to.
RenderFrameHostImpl* frame_host_ = nullptr;
- blink::mojom::DevToolsAgentAssociatedPtr agent_ptr_;
base::flat_set<NavigationHandleImpl*> navigation_handles_;
bool render_frame_alive_ = false;
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 32f191e75cc..c610a3730b2 100644
--- a/chromium/content/browser/devtools/service_worker_devtools_agent_host.cc
+++ b/chromium/content/browser/devtools/service_worker_devtools_agent_host.cc
@@ -5,6 +5,8 @@
#include "content/browser/devtools/service_worker_devtools_agent_host.h"
#include "base/strings/stringprintf.h"
+#include "base/task/post_task.h"
+#include "content/browser/devtools/devtools_renderer_channel.h"
#include "content/browser/devtools/devtools_session.h"
#include "content/browser/devtools/protocol/inspector_handler.h"
#include "content/browser/devtools/protocol/network_handler.h"
@@ -13,6 +15,7 @@
#include "content/browser/devtools/service_worker_devtools_manager.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_version.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
@@ -91,8 +94,8 @@ void ServiceWorkerDevToolsAgentHost::Reload() {
}
bool ServiceWorkerDevToolsAgentHost::Close() {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&TerminateServiceWorkerOnIO, context_weak_, version_id_));
return true;
}
@@ -117,46 +120,33 @@ ServiceWorkerDevToolsAgentHost::~ServiceWorkerDevToolsAgentHost() {
bool ServiceWorkerDevToolsAgentHost::AttachSession(DevToolsSession* session,
TargetRegistry* registry) {
- if (state_ == WORKER_READY) {
- if (sessions().size() == 1) {
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::BindOnce(&SetDevToolsAttachedOnIO,
- context_weak_, version_id_, true));
- }
- session->SetRenderer(worker_process_id_, nullptr);
- session->AttachToAgent(agent_ptr_);
- }
session->AddHandler(base::WrapUnique(new protocol::InspectorHandler()));
session->AddHandler(base::WrapUnique(new protocol::NetworkHandler(
GetId(), devtools_worker_token_, GetIOContext())));
session->AddHandler(base::WrapUnique(new protocol::SchemaHandler()));
+ if (state_ == WORKER_READY && sessions().empty())
+ UpdateIsAttached(true);
return true;
}
void ServiceWorkerDevToolsAgentHost::DetachSession(DevToolsSession* session) {
// Destroying session automatically detaches in renderer.
- if (state_ == WORKER_READY && sessions().empty()) {
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::BindOnce(&SetDevToolsAttachedOnIO,
- context_weak_, version_id_, false));
- }
+ if (state_ == WORKER_READY && sessions().empty())
+ UpdateIsAttached(false);
}
void ServiceWorkerDevToolsAgentHost::WorkerReadyForInspection(
+ blink::mojom::DevToolsAgentHostAssociatedRequest host_request,
blink::mojom::DevToolsAgentAssociatedPtrInfo devtools_agent_ptr_info) {
DCHECK_EQ(WORKER_NOT_READY, state_);
state_ = WORKER_READY;
- agent_ptr_.Bind(std::move(devtools_agent_ptr_info));
- if (!sessions().empty()) {
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::BindOnce(&SetDevToolsAttachedOnIO,
- context_weak_, version_id_, true));
- }
-
- for (DevToolsSession* session : sessions()) {
- session->SetRenderer(worker_process_id_, nullptr);
- session->AttachToAgent(agent_ptr_);
- }
+ blink::mojom::DevToolsAgentAssociatedPtr agent_ptr;
+ agent_ptr.Bind(std::move(devtools_agent_ptr_info));
+ GetRendererChannel()->SetRenderer(std::move(agent_ptr),
+ std::move(host_request), worker_process_id_,
+ nullptr);
+ if (!sessions().empty())
+ UpdateIsAttached(true);
}
void ServiceWorkerDevToolsAgentHost::WorkerRestarted(int worker_process_id,
@@ -167,18 +157,24 @@ void ServiceWorkerDevToolsAgentHost::WorkerRestarted(int worker_process_id,
worker_route_id_ = worker_route_id;
for (auto* inspector : protocol::InspectorHandler::ForAgentHost(this))
inspector->TargetReloadedAfterCrash();
- for (DevToolsSession* session : sessions())
- session->SetRenderer(worker_process_id_, nullptr);
}
void ServiceWorkerDevToolsAgentHost::WorkerDestroyed() {
DCHECK_NE(WORKER_TERMINATED, state_);
state_ = WORKER_TERMINATED;
- agent_ptr_.reset();
for (auto* inspector : protocol::InspectorHandler::ForAgentHost(this))
inspector->TargetCrashed();
- for (DevToolsSession* session : sessions())
- session->SetRenderer(-1, nullptr);
+ GetRendererChannel()->SetRenderer(
+ nullptr, nullptr, ChildProcessHost::kInvalidUniqueID, nullptr);
+ if (!sessions().empty())
+ UpdateIsAttached(false);
+}
+
+void ServiceWorkerDevToolsAgentHost::UpdateIsAttached(bool attached) {
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(&SetDevToolsAttachedOnIO, context_weak_, version_id_,
+ attached));
}
} // namespace content
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 b2612093058..0b0d0a2bbef 100644
--- a/chromium/content/browser/devtools/service_worker_devtools_agent_host.h
+++ b/chromium/content/browser/devtools/service_worker_devtools_agent_host.h
@@ -46,13 +46,9 @@ class ServiceWorkerDevToolsAgentHost : public DevToolsAgentHostImpl {
void Reload() override;
bool Close() override;
- // DevToolsAgentHostImpl overrides.
- bool AttachSession(DevToolsSession* session,
- TargetRegistry* registry) override;
- void DetachSession(DevToolsSession* session) override;
-
void WorkerRestarted(int worker_process_id, int worker_route_id);
void WorkerReadyForInspection(
+ blink::mojom::DevToolsAgentHostAssociatedRequest host_request,
blink::mojom::DevToolsAgentAssociatedPtrInfo devtools_agent_ptr_info);
void WorkerDestroyed();
void WorkerVersionInstalled();
@@ -77,6 +73,12 @@ class ServiceWorkerDevToolsAgentHost : public DevToolsAgentHostImpl {
private:
~ServiceWorkerDevToolsAgentHost() override;
+ void UpdateIsAttached(bool attached);
+
+ // DevToolsAgentHostImpl overrides.
+ bool AttachSession(DevToolsSession* session,
+ TargetRegistry* registry) override;
+ void DetachSession(DevToolsSession* session) override;
enum WorkerState {
WORKER_NOT_READY,
@@ -94,7 +96,6 @@ class ServiceWorkerDevToolsAgentHost : public DevToolsAgentHostImpl {
GURL scope_;
base::Time version_installed_time_;
base::Time version_doomed_time_;
- blink::mojom::DevToolsAgentAssociatedPtr agent_ptr_;
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerDevToolsAgentHost);
};
diff --git a/chromium/content/browser/devtools/service_worker_devtools_manager.cc b/chromium/content/browser/devtools/service_worker_devtools_manager.cc
index 60007e08358..a91474c696a 100644
--- a/chromium/content/browser/devtools/service_worker_devtools_manager.cc
+++ b/chromium/content/browser/devtools/service_worker_devtools_manager.cc
@@ -91,6 +91,7 @@ void ServiceWorkerDevToolsManager::WorkerCreated(
void ServiceWorkerDevToolsManager::WorkerReadyForInspection(
int worker_process_id,
int worker_route_id,
+ blink::mojom::DevToolsAgentHostAssociatedRequest host_request,
blink::mojom::DevToolsAgentAssociatedPtrInfo devtools_agent_ptr_info) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
const WorkerId worker_id(worker_process_id, worker_route_id);
@@ -98,7 +99,8 @@ void ServiceWorkerDevToolsManager::WorkerReadyForInspection(
if (it == live_hosts_.end())
return;
scoped_refptr<ServiceWorkerDevToolsAgentHost> host = it->second;
- host->WorkerReadyForInspection(std::move(devtools_agent_ptr_info));
+ host->WorkerReadyForInspection(std::move(host_request),
+ std::move(devtools_agent_ptr_info));
// Bring up UI for the ones not picked by other clients.
if (debug_service_worker_on_start_ && !host->IsAttached())
host->Inspect();
@@ -205,7 +207,7 @@ void ServiceWorkerDevToolsManager::NavigationPreloadResponseReceived(
return;
for (auto* network : protocol::NetworkHandler::ForAgentHost(it->second.get()))
network->ResponseReceived(request_id, std::string(), url,
- protocol::Page::ResourceTypeEnum::Other, head,
+ protocol::Network::ResourceTypeEnum::Other, head,
protocol::Maybe<std::string>());
}
@@ -219,8 +221,8 @@ void ServiceWorkerDevToolsManager::NavigationPreloadCompleted(
if (it == live_hosts_.end())
return;
for (auto* network : protocol::NetworkHandler::ForAgentHost(it->second.get()))
- network->LoadingComplete(request_id,
- protocol::Page::ResourceTypeEnum::Other, status);
+ network->LoadingComplete(
+ request_id, protocol::Network::ResourceTypeEnum::Other, status);
}
} // namespace content
diff --git a/chromium/content/browser/devtools/service_worker_devtools_manager.h b/chromium/content/browser/devtools/service_worker_devtools_manager.h
index 0153f487adb..6745d910ccc 100644
--- a/chromium/content/browser/devtools/service_worker_devtools_manager.h
+++ b/chromium/content/browser/devtools/service_worker_devtools_manager.h
@@ -71,6 +71,7 @@ class CONTENT_EXPORT ServiceWorkerDevToolsManager {
void WorkerReadyForInspection(
int worker_process_id,
int worker_route_id,
+ blink::mojom::DevToolsAgentHostAssociatedRequest host_request,
blink::mojom::DevToolsAgentAssociatedPtrInfo devtools_agent_ptr_info);
void WorkerVersionInstalled(int worker_process_id, int worker_route_id);
void WorkerVersionDoomed(int worker_process_id, int worker_route_id);
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 c09e04a0717..9d4dd11b83d 100644
--- a/chromium/content/browser/devtools/shared_worker_devtools_agent_host.cc
+++ b/chromium/content/browser/devtools/shared_worker_devtools_agent_host.cc
@@ -4,6 +4,7 @@
#include "content/browser/devtools/shared_worker_devtools_agent_host.h"
+#include "content/browser/devtools/devtools_renderer_channel.h"
#include "content/browser/devtools/devtools_session.h"
#include "content/browser/devtools/protocol/inspector_handler.h"
#include "content/browser/devtools/protocol/network_handler.h"
@@ -15,6 +16,7 @@
#include "content/browser/shared_worker/shared_worker_service_impl.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
+#include "third_party/blink/public/web/devtools_agent.mojom.h"
namespace content {
@@ -72,9 +74,6 @@ bool SharedWorkerDevToolsAgentHost::AttachSession(DevToolsSession* session,
session->AddHandler(std::make_unique<protocol::NetworkHandler>(
GetId(), devtools_worker_token_, GetIOContext()));
session->AddHandler(std::make_unique<protocol::SchemaHandler>());
- session->SetRenderer(worker_host_ ? worker_host_->process_id() : -1, nullptr);
- if (state_ == WORKER_READY)
- session->AttachToAgent(EnsureAgent());
return true;
}
@@ -90,8 +89,7 @@ void SharedWorkerDevToolsAgentHost::WorkerReadyForInspection() {
DCHECK_EQ(WORKER_NOT_READY, state_);
DCHECK(worker_host_);
state_ = WORKER_READY;
- for (DevToolsSession* session : sessions())
- session->AttachToAgent(EnsureAgent());
+ UpdateRendererChannel(IsAttached());
}
void SharedWorkerDevToolsAgentHost::WorkerRestarted(
@@ -102,8 +100,7 @@ void SharedWorkerDevToolsAgentHost::WorkerRestarted(
worker_host_ = worker_host;
for (auto* inspector : protocol::InspectorHandler::ForAgentHost(this))
inspector->TargetReloadedAfterCrash();
- for (DevToolsSession* session : sessions())
- session->SetRenderer(worker_host_->process_id(), nullptr);
+ UpdateRendererChannel(IsAttached());
}
void SharedWorkerDevToolsAgentHost::WorkerDestroyed() {
@@ -112,19 +109,25 @@ void SharedWorkerDevToolsAgentHost::WorkerDestroyed() {
state_ = WORKER_TERMINATED;
for (auto* inspector : protocol::InspectorHandler::ForAgentHost(this))
inspector->TargetCrashed();
- for (DevToolsSession* session : sessions())
- session->SetRenderer(-1, nullptr);
worker_host_ = nullptr;
- agent_ptr_.reset();
-}
-
-const blink::mojom::DevToolsAgentAssociatedPtr&
-SharedWorkerDevToolsAgentHost::EnsureAgent() {
- DCHECK_EQ(WORKER_READY, state_);
- DCHECK(worker_host_);
- if (!agent_ptr_)
- worker_host_->BindDevToolsAgent(mojo::MakeRequest(&agent_ptr_));
- return agent_ptr_;
+ UpdateRendererChannel(IsAttached());
+}
+
+void SharedWorkerDevToolsAgentHost::UpdateRendererChannel(bool force) {
+ if (state_ == WORKER_READY && force) {
+ blink::mojom::DevToolsAgentHostAssociatedPtrInfo host_ptr_info;
+ blink::mojom::DevToolsAgentHostAssociatedRequest host_request =
+ mojo::MakeRequest(&host_ptr_info);
+ blink::mojom::DevToolsAgentAssociatedPtr agent_ptr;
+ worker_host_->BindDevToolsAgent(std::move(host_ptr_info),
+ mojo::MakeRequest(&agent_ptr));
+ GetRendererChannel()->SetRenderer(std::move(agent_ptr),
+ std::move(host_request),
+ worker_host_->process_id(), nullptr);
+ } else {
+ GetRendererChannel()->SetRenderer(
+ nullptr, nullptr, ChildProcessHost::kInvalidUniqueID, nullptr);
+ }
}
} // namespace content
diff --git a/chromium/content/browser/devtools/shared_worker_devtools_agent_host.h b/chromium/content/browser/devtools/shared_worker_devtools_agent_host.h
index c0a867de030..09a66d806c2 100644
--- a/chromium/content/browser/devtools/shared_worker_devtools_agent_host.h
+++ b/chromium/content/browser/devtools/shared_worker_devtools_agent_host.h
@@ -8,7 +8,6 @@
#include "base/macros.h"
#include "base/unguessable_token.h"
#include "content/browser/devtools/devtools_agent_host_impl.h"
-#include "third_party/blink/public/web/devtools_agent.mojom.h"
namespace content {
@@ -32,11 +31,6 @@ class SharedWorkerDevToolsAgentHost : public DevToolsAgentHostImpl {
void Reload() override;
bool Close() override;
- // DevToolsAgentHostImpl overrides.
- bool AttachSession(DevToolsSession* session,
- TargetRegistry* registry) override;
- void DetachSession(DevToolsSession* session) override;
-
bool Matches(SharedWorkerHost* worker_host);
void WorkerReadyForInspection();
void WorkerRestarted(SharedWorkerHost* worker_host);
@@ -48,7 +42,12 @@ class SharedWorkerDevToolsAgentHost : public DevToolsAgentHostImpl {
private:
~SharedWorkerDevToolsAgentHost() override;
- const blink::mojom::DevToolsAgentAssociatedPtr& EnsureAgent();
+
+ // DevToolsAgentHostImpl overrides.
+ bool AttachSession(DevToolsSession* session,
+ TargetRegistry* registry) override;
+ void DetachSession(DevToolsSession* session) override;
+ void UpdateRendererChannel(bool force) override;
enum WorkerState {
WORKER_NOT_READY,
@@ -57,7 +56,6 @@ class SharedWorkerDevToolsAgentHost : public DevToolsAgentHostImpl {
};
WorkerState state_;
SharedWorkerHost* worker_host_;
- blink::mojom::DevToolsAgentAssociatedPtr agent_ptr_;
base::UnguessableToken devtools_worker_token_;
std::unique_ptr<SharedWorkerInstance> instance_;
diff --git a/chromium/content/browser/do_not_track_browsertest.cc b/chromium/content/browser/do_not_track_browsertest.cc
index 1aa00dc5b57..f6bfed9f741 100644
--- a/chromium/content/browser/do_not_track_browsertest.cc
+++ b/chromium/content/browser/do_not_track_browsertest.cc
@@ -79,6 +79,10 @@ class DoNotTrackTest : public ContentBrowserTest {
return value;
}
+ GURL GetURL(std::string relative_url) {
+ return embedded_test_server()->GetURL(relative_url);
+ }
+
private:
ContentBrowserClient* original_client_ = nullptr;
MockContentBrowserClient client_;
@@ -101,8 +105,7 @@ std::unique_ptr<net::test_server::HttpResponse> CaptureHeaderHandler(
// Checks that the DNT header is not sent by default.
IN_PROC_BROWSER_TEST_F(DoNotTrackTest, NotEnabled) {
ASSERT_TRUE(embedded_test_server()->Start());
- GURL url = embedded_test_server()->GetURL("/echoheader?DNT");
- EXPECT_TRUE(NavigateToURL(shell(), url));
+ EXPECT_TRUE(NavigateToURL(shell(), GetURL("/echoheader?DNT")));
ExpectPageTextEq("None");
// And the DOM property is not set.
EXPECT_EQ("", GetDOMDoNotTrackProperty());
@@ -113,17 +116,15 @@ IN_PROC_BROWSER_TEST_F(DoNotTrackTest, Simple) {
ASSERT_TRUE(embedded_test_server()->Start());
if (!EnableDoNotTrack())
return;
- GURL url = embedded_test_server()->GetURL("/echoheader?DNT");
- EXPECT_TRUE(NavigateToURL(shell(), url));
+ EXPECT_TRUE(NavigateToURL(shell(), GetURL("/echoheader?DNT")));
ExpectPageTextEq("1");
}
// Checks that the DNT header is preserved during redirects.
IN_PROC_BROWSER_TEST_F(DoNotTrackTest, Redirect) {
ASSERT_TRUE(embedded_test_server()->Start());
- GURL final_url = embedded_test_server()->GetURL("/echoheader?DNT");
- GURL url = embedded_test_server()->GetURL(std::string("/server-redirect?") +
- final_url.spec());
+ GURL final_url = GetURL("/echoheader?DNT");
+ GURL url = GetURL("/server-redirect?" + final_url.spec());
if (!EnableDoNotTrack())
return;
// We don't check the result NavigateToURL as it returns true only if the
@@ -135,10 +136,9 @@ IN_PROC_BROWSER_TEST_F(DoNotTrackTest, Redirect) {
// Checks that the DOM property is set when the corresponding preference is set.
IN_PROC_BROWSER_TEST_F(DoNotTrackTest, DOMProperty) {
ASSERT_TRUE(embedded_test_server()->Start());
- GURL url = embedded_test_server()->GetURL("/echo");
if (!EnableDoNotTrack())
return;
- EXPECT_TRUE(NavigateToURL(shell(), url));
+ EXPECT_TRUE(NavigateToURL(shell(), GetURL("/echo")));
EXPECT_EQ("1", GetDOMDoNotTrackProperty());
}
@@ -152,9 +152,8 @@ IN_PROC_BROWSER_TEST_F(DoNotTrackTest, Worker) {
ASSERT_TRUE(embedded_test_server()->Start());
if (!EnableDoNotTrack())
return;
- const GURL url = embedded_test_server()->GetURL(
- std::string("/workers/create_worker.html?worker_url=/capture"));
- NavigateToURL(shell(), url);
+ NavigateToURL(shell(),
+ GetURL("/workers/create_worker.html?worker_url=/capture"));
loop.Run();
EXPECT_TRUE(header_map.find("DNT") != header_map.end());
@@ -177,9 +176,9 @@ IN_PROC_BROWSER_TEST_F(DoNotTrackTest, MAYBE_SharedWorker) {
ASSERT_TRUE(embedded_test_server()->Start());
if (!EnableDoNotTrack())
return;
- const GURL url = embedded_test_server()->GetURL(
- std::string("/workers/create_shared_worker.html?worker_url=/capture"));
- NavigateToURL(shell(), url);
+ NavigateToURL(
+ shell(),
+ GetURL("/workers/create_shared_worker.html?worker_url=/capture"));
loop.Run();
EXPECT_TRUE(header_map.find("DNT") != header_map.end());
@@ -196,9 +195,10 @@ IN_PROC_BROWSER_TEST_F(DoNotTrackTest, ServiceWorker) {
ASSERT_TRUE(embedded_test_server()->Start());
if (!EnableDoNotTrack())
return;
- const GURL url = embedded_test_server()->GetURL(std::string(
- "/service_worker/create_service_worker.html?worker_url=/capture"));
- NavigateToURL(shell(), url);
+ NavigateToURL(shell(), GetURL("/service_worker/create_service_worker.html"));
+ // We only verify the request for the worker script so we don't check the
+ // result of register().
+ EXPECT_TRUE(ExecJs(shell(), "register('/capture');"));
loop.Run();
EXPECT_TRUE(header_map.find("DNT") != header_map.end());
@@ -211,16 +211,8 @@ IN_PROC_BROWSER_TEST_F(DoNotTrackTest, FetchFromWorker) {
ASSERT_TRUE(embedded_test_server()->Start());
if (!EnableDoNotTrack())
return;
- const GURL fetch_url = embedded_test_server()->GetURL("/echoheader?DNT");
- const GURL url = embedded_test_server()->GetURL(
- std::string("/workers/fetch_from_worker.html?url=") + fetch_url.spec());
- NavigateToURL(shell(), url);
-
- const base::string16 title = base::ASCIIToUTF16("DONE");
- TitleWatcher watcher(shell()->web_contents(), title);
- EXPECT_EQ(title, watcher.WaitAndGetTitle());
-
- ExpectPageTextEq("1");
+ NavigateToURL(shell(), GetURL("/workers/fetch_from_worker.html"));
+ EXPECT_EQ("1", EvalJs(shell(), "fetch_from_worker('/echoheader?DNT');"));
}
// Checks that the DNT header is preserved when fetching from a shared worker.
@@ -236,17 +228,10 @@ IN_PROC_BROWSER_TEST_F(DoNotTrackTest, MAYBE_FetchFromSharedWorker) {
ASSERT_TRUE(embedded_test_server()->Start());
if (!EnableDoNotTrack())
return;
- const GURL fetch_url = embedded_test_server()->GetURL("/echoheader?DNT");
- const GURL url = embedded_test_server()->GetURL(
- std::string("/workers/fetch_from_shared_worker.html?url=") +
- fetch_url.spec());
- NavigateToURL(shell(), url);
-
- const base::string16 title = base::ASCIIToUTF16("DONE");
- TitleWatcher watcher(shell()->web_contents(), title);
- EXPECT_EQ(title, watcher.WaitAndGetTitle());
+ NavigateToURL(shell(), GetURL("/workers/fetch_from_shared_worker.html"));
- ExpectPageTextEq("1");
+ EXPECT_EQ("1",
+ EvalJs(shell(), "fetch_from_shared_worker('/echoheader?DNT');"));
}
// Checks that the DNT header is preserved when fetching from a service worker.
@@ -254,17 +239,12 @@ IN_PROC_BROWSER_TEST_F(DoNotTrackTest, FetchFromServiceWorker) {
ASSERT_TRUE(embedded_test_server()->Start());
if (!EnableDoNotTrack())
return;
- const GURL fetch_url = embedded_test_server()->GetURL("/echoheader?DNT");
- const GURL url = embedded_test_server()->GetURL(
- std::string("/service_worker/fetch_from_service_worker.html?url=") +
- fetch_url.spec());
- NavigateToURL(shell(), url);
-
- const base::string16 title = base::ASCIIToUTF16("DONE");
- TitleWatcher watcher(shell()->web_contents(), title);
- EXPECT_EQ(title, watcher.WaitAndGetTitle());
+ NavigateToURL(shell(),
+ GetURL("/service_worker/fetch_from_service_worker.html"));
- ExpectPageTextEq("1");
+ EXPECT_EQ("ready", EvalJs(shell(), "setup();"));
+ EXPECT_EQ("1",
+ EvalJs(shell(), "fetch_from_service_worker('/echoheader?DNT');"));
}
// Checks that the DNT header is preserved when fetching from a page controlled
@@ -276,28 +256,15 @@ IN_PROC_BROWSER_TEST_F(DoNotTrackTest,
if (!EnableDoNotTrack())
return;
- {
- // Register a service worker which controls /service_worker.
- const GURL url = embedded_test_server()->GetURL(
- "/service_worker/create_service_worker.html?"
- "worker_url=/service_worker/empty.js");
- EXPECT_TRUE(NavigateToURL(shell(), url));
- const base::string16 title = base::ASCIIToUTF16("DONE");
- TitleWatcher watcher(shell()->web_contents(), title);
- EXPECT_EQ(title, watcher.WaitAndGetTitle());
- }
-
- {
- // Issue a request from a controlled page.
- const GURL url = embedded_test_server()->GetURL(
- "/service_worker/fetch_from_page.html?url=/echoheader?DNT");
- EXPECT_TRUE(NavigateToURL(shell(), url));
- const base::string16 title = base::ASCIIToUTF16("DONE");
- TitleWatcher watcher(shell()->web_contents(), title);
- EXPECT_EQ(title, watcher.WaitAndGetTitle());
- }
+ // Register a service worker which controls /service_worker.
+ EXPECT_TRUE(NavigateToURL(
+ shell(), GetURL("/service_worker/create_service_worker.html")));
+ EXPECT_EQ("DONE", EvalJs(shell(), "register('empty.js');"));
- ExpectPageTextEq("1");
+ // Issue a request from a controlled page.
+ EXPECT_TRUE(
+ NavigateToURL(shell(), GetURL("/service_worker/fetch_from_page.html")));
+ EXPECT_EQ("1", EvalJs(shell(), "fetch_from_page('/echoheader?DNT');"));
}
// Checks that the DNT header is preserved when fetching from a page controlled
@@ -308,28 +275,16 @@ IN_PROC_BROWSER_TEST_F(DoNotTrackTest,
if (!EnableDoNotTrack())
return;
- {
- // Register a service worker which controls /service_worker.
- const GURL url = embedded_test_server()->GetURL(
- "/service_worker/create_service_worker.html?"
- "worker_url=/service_worker/fetch_event_pass_through.js");
- EXPECT_TRUE(NavigateToURL(shell(), url));
- const base::string16 title = base::ASCIIToUTF16("DONE");
- TitleWatcher watcher(shell()->web_contents(), title);
- EXPECT_EQ(title, watcher.WaitAndGetTitle());
- }
+ // Register a service worker which controls /service_worker.
+ EXPECT_TRUE(NavigateToURL(
+ shell(), GetURL("/service_worker/create_service_worker.html")));
+ EXPECT_EQ("DONE",
+ EvalJs(shell(), "register('fetch_event_pass_through.js');"));
- {
- // Issue a request from a controlled page.
- const GURL url = embedded_test_server()->GetURL(
- "/service_worker/fetch_from_page.html?url=/echoheader?DNT");
- EXPECT_TRUE(NavigateToURL(shell(), url));
- const base::string16 title = base::ASCIIToUTF16("DONE");
- TitleWatcher watcher(shell()->web_contents(), title);
- EXPECT_EQ(title, watcher.WaitAndGetTitle());
- }
-
- ExpectPageTextEq("1");
+ // Issue a request from a controlled page.
+ EXPECT_TRUE(
+ NavigateToURL(shell(), GetURL("/service_worker/fetch_from_page.html")));
+ EXPECT_EQ("1", EvalJs(shell(), "fetch_from_page('/echoheader?DNT');"));
}
// Checks that the DNT header is preserved when fetching from a page controlled
@@ -340,28 +295,16 @@ IN_PROC_BROWSER_TEST_F(DoNotTrackTest,
if (!EnableDoNotTrack())
return;
- {
- // Register a service worker which controls /service_worker.
- const GURL url = embedded_test_server()->GetURL(
- "/service_worker/create_service_worker.html?"
- "worker_url=/service_worker/fetch_event_respond_with_fetch.js");
- EXPECT_TRUE(NavigateToURL(shell(), url));
- const base::string16 title = base::ASCIIToUTF16("DONE");
- TitleWatcher watcher(shell()->web_contents(), title);
- EXPECT_EQ(title, watcher.WaitAndGetTitle());
- }
-
- {
- // Issue a request from a controlled page.
- const GURL url = embedded_test_server()->GetURL(
- "/service_worker/fetch_from_page.html?url=/echoheader?DNT");
- EXPECT_TRUE(NavigateToURL(shell(), url));
- const base::string16 title = base::ASCIIToUTF16("DONE");
- TitleWatcher watcher(shell()->web_contents(), title);
- EXPECT_EQ(title, watcher.WaitAndGetTitle());
- }
+ // Register a service worker which controls /service_worker.
+ EXPECT_TRUE(NavigateToURL(
+ shell(), GetURL("/service_worker/create_service_worker.html")));
+ EXPECT_EQ("DONE",
+ EvalJs(shell(), "register('fetch_event_respond_with_fetch.js');"));
- ExpectPageTextEq("1");
+ // Issue a request from a controlled page.
+ EXPECT_TRUE(
+ NavigateToURL(shell(), GetURL("/service_worker/fetch_from_page.html")));
+ EXPECT_EQ("1", EvalJs(shell(), "fetch_from_page('/echoheader?DNT');"));
}
} // namespace
diff --git a/chromium/content/browser/dom_storage/dom_storage_area_unittest.cc b/chromium/content/browser/dom_storage/dom_storage_area_unittest.cc
index e4520d7c8a4..204d00895d3 100644
--- a/chromium/content/browser/dom_storage/dom_storage_area_unittest.cc
+++ b/chromium/content/browser/dom_storage/dom_storage_area_unittest.cc
@@ -10,10 +10,10 @@
#include "base/files/scoped_temp_dir.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_task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "build/build_config.h"
@@ -74,7 +74,7 @@ class DOMStorageAreaTest : public testing::Test {
}
private:
- base::MessageLoop message_loop_;
+ base::test::ScopedTaskEnvironment task_environment_;
};
class DOMStorageAreaParamTest : public DOMStorageAreaTest,
diff --git a/chromium/content/browser/dom_storage/dom_storage_context_impl.cc b/chromium/content/browser/dom_storage/dom_storage_context_impl.cc
index f8e1b0ec7ad..16c0e2835c5 100644
--- a/chromium/content/browser/dom_storage/dom_storage_context_impl.cc
+++ b/chromium/content/browser/dom_storage/dom_storage_context_impl.cc
@@ -12,7 +12,6 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
-#include "base/files/file_enumerator.h"
#include "base/files/file_util.h"
#include "base/guid.h"
#include "base/location.h"
@@ -28,7 +27,6 @@
#include "content/browser/dom_storage/dom_storage_namespace.h"
#include "content/browser/dom_storage/dom_storage_task_runner.h"
#include "content/browser/dom_storage/session_storage_database.h"
-#include "content/common/dom_storage/dom_storage_namespace_ids.h"
#include "content/common/dom_storage/dom_storage_types.h"
#include "content/public/browser/dom_storage_context.h"
#include "content/public/browser/local_storage_usage_info.h"
@@ -110,7 +108,7 @@ DOMStorageNamespace* DOMStorageContextImpl::GetStorageNamespace(
const std::string& namespace_id) {
if (is_shutdown_)
return nullptr;
- StorageNamespaceMap::iterator found = namespaces_.find(namespace_id);
+ auto found = namespaces_.find(namespace_id);
if (found == namespaces_.end())
return nullptr;
return found->second.get();
@@ -302,7 +300,7 @@ void DOMStorageContextImpl::CloneSessionNamespace(
return;
DCHECK(!existing_id.empty());
DCHECK(!new_id.empty());
- StorageNamespaceMap::iterator found = namespaces_.find(existing_id);
+ auto found = namespaces_.find(existing_id);
if (found != namespaces_.end()) {
namespaces_[new_id] = found->second->Clone(new_id);
return;
diff --git a/chromium/content/browser/dom_storage/dom_storage_context_impl_unittest.cc b/chromium/content/browser/dom_storage/dom_storage_context_impl_unittest.cc
index ffb4fc3abeb..1bdd28675ae 100644
--- a/chromium/content/browser/dom_storage/dom_storage_context_impl_unittest.cc
+++ b/chromium/content/browser/dom_storage/dom_storage_context_impl_unittest.cc
@@ -7,9 +7,9 @@
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/test/scoped_task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "build/build_config.h"
@@ -58,7 +58,7 @@ class DOMStorageContextImplTest : public testing::Test {
}
protected:
- base::MessageLoop message_loop_;
+ base::test::ScopedTaskEnvironment task_environment_;
base::ScopedTempDir temp_dir_;
scoped_refptr<MockSpecialStoragePolicy> storage_policy_;
scoped_refptr<MockDOMStorageTaskRunner> task_runner_;
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 1f5335f00de..ae4d0f92cbb 100644
--- a/chromium/content/browser/dom_storage/dom_storage_context_wrapper.cc
+++ b/chromium/content/browser/dom_storage/dom_storage_context_wrapper.cc
@@ -28,6 +28,7 @@
#include "content/browser/dom_storage/local_storage_context_mojo.h"
#include "content/browser/dom_storage/session_storage_context_mojo.h"
#include "content/browser/dom_storage/session_storage_namespace_impl.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/local_storage_usage_info.h"
@@ -46,7 +47,7 @@ const char kSessionStorageDirectory[] = "Session Storage";
void GetLegacyLocalStorageUsage(
const base::FilePath& directory,
scoped_refptr<base::SingleThreadTaskRunner> reply_task_runner,
- const DOMStorageContext::GetLocalStorageUsageCallback& callback) {
+ DOMStorageContext::GetLocalStorageUsageCallback callback) {
std::vector<LocalStorageUsageInfo> infos;
base::FileEnumerator enumerator(directory, false,
base::FileEnumerator::FILES);
@@ -61,14 +62,14 @@ void GetLegacyLocalStorageUsage(
infos.push_back(info);
}
}
- reply_task_runner->PostTask(FROM_HERE,
- base::BindOnce(callback, std::move(infos)));
+ reply_task_runner->PostTask(
+ FROM_HERE, base::BindOnce(std::move(callback), std::move(infos)));
}
void InvokeLocalStorageUsageCallbackHelper(
- const DOMStorageContext::GetLocalStorageUsageCallback& callback,
+ DOMStorageContext::GetLocalStorageUsageCallback callback,
std::unique_ptr<std::vector<LocalStorageUsageInfo>> infos) {
- callback.Run(*infos);
+ std::move(callback).Run(*infos);
}
void GetSessionStorageUsageHelper(
@@ -83,7 +84,7 @@ void GetSessionStorageUsageHelper(
void CollectLocalStorageUsage(
std::vector<LocalStorageUsageInfo>* out_info,
- base::Closure done_callback,
+ base::OnceClosure done_callback,
const std::vector<LocalStorageUsageInfo>& in_info) {
out_info->insert(out_info->end(), in_info.begin(), in_info.end());
std::move(done_callback).Run();
@@ -97,10 +98,10 @@ void GotMojoDeletionCallback(
void GotMojoLocalStorageUsage(
scoped_refptr<base::SingleThreadTaskRunner> reply_task_runner,
- const DOMStorageContext::GetLocalStorageUsageCallback& callback,
+ DOMStorageContext::GetLocalStorageUsageCallback callback,
std::vector<LocalStorageUsageInfo> usage) {
- reply_task_runner->PostTask(FROM_HERE,
- base::BindOnce(callback, std::move(usage)));
+ reply_task_runner->PostTask(
+ FROM_HERE, base::BindOnce(std::move(callback), std::move(usage)));
}
void GotMojoSessionStorageUsage(
@@ -147,7 +148,8 @@ DOMStorageContextWrapper::DOMStorageContextWrapper(
storage_dir = local_partition_path.AppendASCII(kLocalStorageDirectory);
// TODO(dmurph): Change this to a sequenced task runner after
// https://crbug.com/809255 is fixed.
- mojo_task_runner_ = BrowserThread::GetTaskRunnerForThread(BrowserThread::IO);
+ mojo_task_runner_ =
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO});
mojo_state_ = new LocalStorageContextMojo(
mojo_task_runner_, connector, context_->task_runner(),
legacy_localstorage_path_, storage_dir, special_storage_policy);
@@ -185,13 +187,13 @@ DOMStorageContextWrapper::~DOMStorageContextWrapper() {
}
void DOMStorageContextWrapper::GetLocalStorageUsage(
- const GetLocalStorageUsageCallback& callback) {
+ GetLocalStorageUsageCallback callback) {
DCHECK(context_.get());
auto infos = std::make_unique<std::vector<LocalStorageUsageInfo>>();
auto* infos_ptr = infos.get();
base::RepeatingClosure got_local_storage_usage = base::BarrierClosure(
- 2, base::BindOnce(&InvokeLocalStorageUsageCallbackHelper, callback,
- std::move(infos)));
+ 2, base::BindOnce(&InvokeLocalStorageUsageCallbackHelper,
+ std::move(callback), std::move(infos)));
auto collect_callback = base::BindRepeating(
CollectLocalStorageUsage, infos_ptr, std::move(got_local_storage_usage));
// base::Unretained is safe here, because the mojo_state_ won't be deleted
diff --git a/chromium/content/browser/dom_storage/dom_storage_context_wrapper.h b/chromium/content/browser/dom_storage/dom_storage_context_wrapper.h
index ac7e069f4c7..17a2aa8d815 100644
--- a/chromium/content/browser/dom_storage/dom_storage_context_wrapper.h
+++ b/chromium/content/browser/dom_storage/dom_storage_context_wrapper.h
@@ -14,6 +14,7 @@
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/synchronization/lock.h"
+#include "base/thread_annotations.h"
#include "components/services/leveldb/public/interfaces/leveldb.mojom.h"
#include "content/browser/dom_storage/dom_storage_context_impl.h"
#include "content/common/content_export.h"
@@ -57,8 +58,7 @@ class CONTENT_EXPORT DOMStorageContextWrapper
storage::SpecialStoragePolicy* special_storage_policy);
// DOMStorageContext implementation.
- void GetLocalStorageUsage(
- const GetLocalStorageUsageCallback& callback) override;
+ void GetLocalStorageUsage(GetLocalStorageUsageCallback callback) override;
void GetSessionStorageUsage(GetSessionStorageUsageCallback callback) override;
void DeleteLocalStorage(const GURL& origin,
base::OnceClosure callback) override;
@@ -143,7 +143,8 @@ class CONTENT_EXPORT DOMStorageContextWrapper
// Profile wasn't destructed. This map allows the restored session to re-use
// the SessionStorageNamespaceImpl objects that are still alive thanks to the
// sessions component.
- std::map<std::string, SessionStorageNamespaceImpl*> alive_namespaces_;
+ std::map<std::string, SessionStorageNamespaceImpl*> alive_namespaces_
+ GUARDED_BY(alive_namespaces_lock_);
mutable base::Lock alive_namespaces_lock_;
base::FilePath legacy_localstorage_path_;
diff --git a/chromium/content/browser/dom_storage/dom_storage_database.cc b/chromium/content/browser/dom_storage/dom_storage_database.cc
index 2609b896ee6..376f1ac5ea3 100644
--- a/chromium/content/browser/dom_storage/dom_storage_database.cc
+++ b/chromium/content/browser/dom_storage/dom_storage_database.cc
@@ -81,7 +81,7 @@ bool DOMStorageDatabase::CommitChanges(bool clear_all_first,
bool did_delete = false;
bool did_insert = false;
- DOMStorageValuesMap::const_iterator it = changes.begin();
+ auto it = changes.begin();
for(; it != changes.end(); ++it) {
sql::Statement statement;
base::string16 key = it->first;
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 7c83def70b8..de24b0f790a 100644
--- a/chromium/content/browser/dom_storage/dom_storage_database_unittest.cc
+++ b/chromium/content/browser/dom_storage/dom_storage_database_unittest.cc
@@ -128,7 +128,7 @@ TEST(DOMStorageDatabaseTest, CloseEmptyDatabaseDeletesFile) {
{
DOMStorageDatabase db(file_name);
ASSERT_TRUE(db.CommitChanges(false, storage));
- DOMStorageValuesMap::iterator it = storage.begin();
+ auto it = storage.begin();
for (; it != storage.end(); ++it)
it->second = base::NullableString16();
ASSERT_TRUE(db.CommitChanges(false, storage));
diff --git a/chromium/content/browser/dom_storage/dom_storage_namespace.cc b/chromium/content/browser/dom_storage/dom_storage_namespace.cc
index d78f30fb98e..2f1f8559193 100644
--- a/chromium/content/browser/dom_storage/dom_storage_namespace.cc
+++ b/chromium/content/browser/dom_storage/dom_storage_namespace.cc
@@ -98,7 +98,7 @@ void DOMStorageNamespace::DeleteSessionStorageOrigin(
}
void DOMStorageNamespace::PurgeMemory(bool aggressively) {
- AreaMap::iterator it = areas_.begin();
+ auto it = areas_.begin();
while (it != areas_.end()) {
const AreaHolder& holder = it->second;
@@ -148,7 +148,7 @@ void DOMStorageNamespace::Flush() {
DOMStorageNamespace::UsageStatistics DOMStorageNamespace::GetUsageStatistics()
const {
UsageStatistics stats = {0};
- for (AreaMap::const_iterator it = areas_.begin(); it != areas_.end(); ++it) {
+ for (auto it = areas_.begin(); it != areas_.end(); ++it) {
if (it->second.area_->map_memory_used()) {
stats.total_cache_size += it->second.area_->map_memory_used();
++stats.total_area_count;
@@ -182,7 +182,7 @@ int DOMStorageNamespace::GetAreaOpenCount(const url::Origin& origin) const {
DOMStorageNamespace::AreaHolder* DOMStorageNamespace::GetAreaHolder(
const url::Origin& origin) {
- AreaMap::iterator found = areas_.find(origin);
+ auto found = areas_.find(origin);
if (found == areas_.end())
return nullptr;
return &(found->second);
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 f64bab5bd63..e90a108e005 100644
--- a/chromium/content/browser/dom_storage/session_storage_context_mojo.cc
+++ b/chromium/content/browser/dom_storage/session_storage_context_mojo.cc
@@ -540,8 +540,7 @@ void SessionStorageContextMojo::RegisterShallowClonedNamespace(
}
}
- SessionStorageMetadata::NamespaceEntry namespace_entry =
- metadata_.GetOrCreateNamespaceEntry(new_namespace_id);
+ auto namespace_entry = metadata_.GetOrCreateNamespaceEntry(new_namespace_id);
metadata_.RegisterShallowClonedNamespace(source_namespace_entry,
namespace_entry, &save_operations);
database_->Write(std::move(save_operations),
diff --git a/chromium/content/browser/dom_storage/session_storage_database.cc b/chromium/content/browser/dom_storage/session_storage_database.cc
index 2a8d889e3a4..4c660ab4917 100644
--- a/chromium/content/browser/dom_storage/session_storage_database.cc
+++ b/chromium/content/browser/dom_storage/session_storage_database.cc
@@ -730,9 +730,7 @@ bool SessionStorageDatabase::ReadMap(const std::string& map_id,
void SessionStorageDatabase::WriteValuesToMap(const std::string& map_id,
const DOMStorageValuesMap& values,
leveldb::WriteBatch* batch) {
- for (DOMStorageValuesMap::const_iterator it = values.begin();
- it != values.end();
- ++it) {
+ for (auto it = values.begin(); it != values.end(); ++it) {
base::NullableString16 value = it->second;
std::string key = MapKey(map_id, base::UTF16ToUTF8(it->first));
if (value.is_null()) {
diff --git a/chromium/content/browser/dom_storage/session_storage_database.h b/chromium/content/browser/dom_storage/session_storage_database.h
index e1ec30e83d3..c541d532c8c 100644
--- a/chromium/content/browser/dom_storage/session_storage_database.h
+++ b/chromium/content/browser/dom_storage/session_storage_database.h
@@ -21,6 +21,7 @@
#include "base/sequence_checker.h"
#include "base/sequenced_task_runner.h"
#include "base/synchronization/lock.h"
+#include "base/thread_annotations.h"
#include "content/common/content_export.h"
#include "content/common/dom_storage/dom_storage_types.h"
#include "third_party/leveldatabase/src/include/leveldb/status.h"
@@ -230,16 +231,16 @@ class CONTENT_EXPORT SessionStorageDatabase
base::Lock db_lock_;
// True if a database error has occurred (e.g., cannot read data).
- bool db_error_;
+ bool db_error_ GUARDED_BY(db_lock_);
// True if the database is in an inconsistent state.
- bool is_inconsistent_;
+ bool is_inconsistent_ GUARDED_BY(db_lock_);
// True if the database is in a failed or inconsistent state, and we have
// already deleted it (as an attempt to recover later).
- bool invalid_db_deleted_;
+ bool invalid_db_deleted_ GUARDED_BY(db_lock_);
// The number of database operations in progress. We need this so that we can
// delete an inconsistent database at the right moment.
- int operation_count_;
+ int operation_count_ GUARDED_BY(db_lock_);
// Used to check methods that run on the commit sequence.
SEQUENCE_CHECKER(sequence_checker_);
diff --git a/chromium/content/browser/dom_storage/session_storage_database_unittest.cc b/chromium/content/browser/dom_storage/session_storage_database_unittest.cc
index af7de589318..c8f00281424 100644
--- a/chromium/content/browser/dom_storage/session_storage_database_unittest.cc
+++ b/chromium/content/browser/dom_storage/session_storage_database_unittest.cc
@@ -336,8 +336,7 @@ void SessionStorageDatabaseTest::CompareValuesMaps(
const DOMStorageValuesMap& map1,
const DOMStorageValuesMap& map2) const {
ASSERT_EQ(map2.size(), map1.size());
- for (DOMStorageValuesMap::const_iterator it = map1.begin();
- it != map1.end(); ++it) {
+ for (auto it = map1.begin(); it != map1.end(); ++it) {
base::string16 key = it->first;
ASSERT_TRUE(map2.find(key) != map2.end());
base::NullableString16 val1 = it->second;
diff --git a/chromium/content/browser/dom_storage/session_storage_metadata.cc b/chromium/content/browser/dom_storage/session_storage_metadata.cc
index 515bbac0b12..772fa0de050 100644
--- a/chromium/content/browser/dom_storage/session_storage_metadata.cc
+++ b/chromium/content/browser/dom_storage/session_storage_metadata.cc
@@ -8,7 +8,7 @@
#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 "third_party/blink/public/common/dom_storage/session_storage_namespace_id.h"
#include "url/gurl.h"
namespace content {
@@ -43,7 +43,7 @@ constexpr const size_t kNamespacePrefixLength =
constexpr const uint8_t kNamespaceOriginSeperatorByte = '-';
constexpr const size_t kNamespaceOriginSeperatorLength = 1;
constexpr const size_t kPrefixBeforeOriginLength =
- kNamespacePrefixLength + kSessionStorageNamespaceIdLength +
+ kNamespacePrefixLength + blink::kSessionStorageNamespaceIdLength +
kNamespaceOriginSeperatorLength;
bool ValueToNumber(const std::vector<uint8_t>& value, int64_t* out) {
@@ -169,7 +169,7 @@ bool SessionStorageMetadata::ParseNamespaces(
continue;
base::StringPiece namespace_id = key_as_string.substr(
- kNamespacePrefixLength, kSessionStorageNamespaceIdLength);
+ kNamespacePrefixLength, blink::kSessionStorageNamespaceIdLength);
base::StringPiece origin_str =
key_as_string.substr(kPrefixBeforeOriginLength);
@@ -347,7 +347,7 @@ 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);
+ auto ns_entry = namespace_origin_map_.find(namespace_id);
if (ns_entry == namespace_origin_map_.end())
return;
diff --git a/chromium/content/browser/dom_storage/session_storage_namespace_impl.cc b/chromium/content/browser/dom_storage/session_storage_namespace_impl.cc
index 81c1d91c755..9c22eb557da 100644
--- a/chromium/content/browser/dom_storage/session_storage_namespace_impl.cc
+++ b/chromium/content/browser/dom_storage/session_storage_namespace_impl.cc
@@ -11,13 +11,15 @@
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/sequenced_task_runner.h"
+#include "base/task/post_task.h"
#include "content/browser/dom_storage/dom_storage_context_impl.h"
#include "content/browser/dom_storage/dom_storage_context_wrapper.h"
#include "content/browser/dom_storage/dom_storage_task_runner.h"
#include "content/browser/dom_storage/session_storage_context_mojo.h"
-#include "content/common/dom_storage/dom_storage_namespace_ids.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_features.h"
+#include "third_party/blink/public/common/dom_storage/session_storage_namespace_id.h"
namespace content {
@@ -25,7 +27,7 @@ namespace content {
scoped_refptr<SessionStorageNamespaceImpl> SessionStorageNamespaceImpl::Create(
scoped_refptr<DOMStorageContextWrapper> context) {
return SessionStorageNamespaceImpl::Create(
- std::move(context), AllocateSessionStorageNamespaceId());
+ std::move(context), blink::AllocateSessionStorageNamespaceId());
}
// static
@@ -100,7 +102,7 @@ bool SessionStorageNamespaceImpl::should_persist() const {
scoped_refptr<SessionStorageNamespaceImpl>
SessionStorageNamespaceImpl::Clone() {
- return CloneFrom(context_wrapper_, AllocateSessionStorageNamespaceId(),
+ return CloneFrom(context_wrapper_, blink::AllocateSessionStorageNamespaceId(),
namespace_id_, true);
}
@@ -150,8 +152,8 @@ SessionStorageNamespaceImpl::~SessionStorageNamespaceImpl() {
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
// If this fails to post then that's fine, as the mojo state should
// already be destructed.
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- deleteNamespaceRunner.Release());
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ deleteNamespaceRunner.Release());
}
}
}
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
index 5080467a908..fb9e5c439a5 100644
--- 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
@@ -59,8 +59,7 @@ class SessionStorageNamespaceImplMojoTest
// 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 entry = metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_);
auto map_id =
metadata_.RegisterNewMap(entry, test_origin1_, &save_operations);
DCHECK(map_id->KeyPrefix() == StdStringToUint8Vector("map-0-"));
@@ -130,7 +129,7 @@ class SessionStorageNamespaceImplMojoTest
const SessionStorageNamespaceImplMojo::OriginAreas& areas_to_clone)
override {
std::vector<leveldb::mojom::BatchedOperationPtr> save_operations;
- NamespaceEntry namespace_entry =
+ auto namespace_entry =
metadata_.GetOrCreateNamespaceEntry(destination_namespace);
metadata_.RegisterShallowClonedNamespace(source_namespace, namespace_entry,
&save_operations);
diff --git a/chromium/content/browser/dom_storage/storage_area_impl.cc b/chromium/content/browser/dom_storage/storage_area_impl.cc
index 63930ec6b94..b5cff87bd5f 100644
--- a/chromium/content/browser/dom_storage/storage_area_impl.cc
+++ b/chromium/content/browser/dom_storage/storage_area_impl.cc
@@ -284,7 +284,7 @@ void StorageAreaImpl::Put(
new_item_memory = key.size() + sizeof(size_t);
} else {
DCHECK_EQ(map_state_, MapState::LOADED_KEYS_AND_VALUES);
- ValueMap::iterator found = keys_values_map_.find(key);
+ auto found = keys_values_map_.find(key);
if (found != keys_values_map_.end()) {
if (found->second == value) {
std::move(callback).Run(true); // Key already has this value.
@@ -398,7 +398,7 @@ void StorageAreaImpl::Delete(
commit_batch_->changed_values[key] = std::vector<uint8_t>();
} else {
DCHECK_EQ(map_state_, MapState::LOADED_KEYS_AND_VALUES);
- ValueMap::iterator found = keys_values_map_.find(key);
+ auto found = keys_values_map_.find(key);
if (found == keys_values_map_.end()) {
std::move(callback).Run(true);
return;
diff --git a/chromium/content/browser/download/download_browsertest.cc b/chromium/content/browser/download/download_browsertest.cc
index 3ae60d75623..97421cd8745 100644
--- a/chromium/content/browser/download/download_browsertest.cc
+++ b/chromium/content/browser/download/download_browsertest.cc
@@ -24,6 +24,7 @@
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/task/post_task.h"
#include "base/test/mock_entropy_provider.h"
#include "base/test/scoped_feature_list.h"
#include "base/threading/platform_thread.h"
@@ -39,6 +40,7 @@
#include "content/browser/download/download_manager_impl.h"
#include "content/browser/download/download_resource_handler.h"
#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/download_request_utils.h"
#include "content/public/browser/resource_throttle.h"
@@ -942,6 +944,12 @@ class DownloadContentTest : public ContentBrowserTest {
return inject_error_callback_;
}
+ void RegisterServiceWorker(Shell* shell, const std::string& worker_url) {
+ NavigateToURL(
+ shell, embedded_test_server()->GetURL("/register_service_worker.html"));
+ EXPECT_EQ("DONE", EvalJs(shell, "register('" + worker_url + "')"));
+ }
+
private:
// Location of the downloads directory for these tests
base::ScopedTempDir downloads_directory_;
@@ -1183,6 +1191,7 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, MultiDownload) {
#if BUILDFLAG(ENABLE_PLUGINS)
// Content served with a MIME type of application/octet-stream should be
// downloaded even when a plugin can be found that handles the file type.
+// See https://crbug.com/104331 for the details.
IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadOctetStream) {
const char kTestPluginName[] = "TestPlugin";
const char kTestMimeType[] = "application/x-test-mime-type";
@@ -1197,9 +1206,90 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadOctetStream) {
// The following is served with a Content-Type of application/octet-stream.
NavigateToURLAndWaitForDownload(
- shell(), embedded_test_server()->GetURL("/download/download-test.lib"),
+ shell(), embedded_test_server()->GetURL("/download/octet-stream.abc"),
+ download::DownloadItem::COMPLETE);
+}
+
+// Content served with a MIME type of application/octet-stream should be
+// downloaded even when a plugin can be found that handles the file type.
+// See https://crbug.com/104331 for the details.
+// In this test, the url is in scope of a service worker but the response is
+// served from network.
+// This is regression test for https://crbug.com/896696.
+IN_PROC_BROWSER_TEST_F(DownloadContentTest,
+ DownloadOctetStream_PassThroughServiceWorker) {
+ const char kTestPluginName[] = "TestPlugin";
+ const char kTestMimeType[] = "application/x-test-mime-type";
+ const char kTestFileType[] = "abc";
+
+ RegisterServiceWorker(shell(), "/fetch_event_passthrough.js");
+
+ WebPluginInfo plugin_info;
+ plugin_info.name = base::ASCIIToUTF16(kTestPluginName);
+ plugin_info.mime_types.push_back(
+ WebPluginMimeType(kTestMimeType, kTestFileType, ""));
+ plugin_info.type = WebPluginInfo::PLUGIN_TYPE_PEPPER_IN_PROCESS;
+ PluginServiceImpl::GetInstance()->RegisterInternalPlugin(plugin_info, false);
+
+ // The following is served with a Content-Type of application/octet-stream.
+ NavigateToURLAndWaitForDownload(
+ shell(), embedded_test_server()->GetURL("/download/octet-stream.abc"),
download::DownloadItem::COMPLETE);
}
+
+// Content served with a MIME type of application/octet-stream should be
+// downloaded even when a plugin can be found that handles the file type.
+// See https://crbug.com/104331 for the details.
+// In this test, the response will be served from a service worker.
+// This is regression test for https://crbug.com/896696.
+IN_PROC_BROWSER_TEST_F(DownloadContentTest,
+ DownloadOctetStream_OctetStreamServiceWorker) {
+ const char kTestPluginName[] = "TestPlugin";
+ const char kTestMimeType[] = "application/x-test-mime-type";
+ const char kTestFileType[] = "abc";
+
+ RegisterServiceWorker(shell(), "/fetch_event_octet_stream.js");
+
+ WebPluginInfo plugin_info;
+ plugin_info.name = base::ASCIIToUTF16(kTestPluginName);
+ plugin_info.mime_types.push_back(
+ WebPluginMimeType(kTestMimeType, kTestFileType, ""));
+ plugin_info.type = WebPluginInfo::PLUGIN_TYPE_PEPPER_IN_PROCESS;
+ PluginServiceImpl::GetInstance()->RegisterInternalPlugin(plugin_info, false);
+
+ // The following is served with a Content-Type of application/octet-stream.
+ NavigateToURLAndWaitForDownload(
+ shell(), embedded_test_server()->GetURL("/download/octet-stream.abc"),
+ download::DownloadItem::COMPLETE);
+}
+
+// Content served with a MIME type of application/octet-stream should be
+// downloaded even when a plugin can be found that handles the file type.
+// See https://crbug.com/104331 for the details.
+// In this test, the url is in scope of a service worker and the response is
+// served from the network via service worker.
+// This is regression test for https://crbug.com/896696.
+IN_PROC_BROWSER_TEST_F(DownloadContentTest,
+ DownloadOctetStream_RespondWithFetchServiceWorker) {
+ const char kTestPluginName[] = "TestPlugin";
+ const char kTestMimeType[] = "application/x-test-mime-type";
+ const char kTestFileType[] = "abc";
+
+ RegisterServiceWorker(shell(), "/fetch_event_respond_with_fetch.js");
+
+ WebPluginInfo plugin_info;
+ plugin_info.name = base::ASCIIToUTF16(kTestPluginName);
+ plugin_info.mime_types.push_back(
+ WebPluginMimeType(kTestMimeType, kTestFileType, ""));
+ plugin_info.type = WebPluginInfo::PLUGIN_TYPE_PEPPER_IN_PROCESS;
+ PluginServiceImpl::GetInstance()->RegisterInternalPlugin(plugin_info, false);
+
+ // The following is served with a Content-Type of application/octet-stream.
+ NavigateToURLAndWaitForDownload(
+ shell(), embedded_test_server()->GetURL("/download/octet-stream.abc"),
+ download::DownloadItem::COMPLETE);
+}
+
#endif
// Try to cancel just before we release the download file, by delaying final
@@ -1344,13 +1434,13 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, ShutdownInProgress) {
// a chance to get the second stall onto the IO thread queue after the cancel
// message created by Shutdown and before the notification callback
// created by the IO thread in canceling the request.
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&base::PlatformThread::Sleep,
base::TimeDelta::FromMilliseconds(25)));
DownloadManagerForShell(shell())->Shutdown();
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&base::PlatformThread::Sleep,
base::TimeDelta::FromMilliseconds(25)));
}
diff --git a/chromium/content/browser/download/download_manager_impl.cc b/chromium/content/browser/download/download_manager_impl.cc
index 37cabf2c9ff..a0220133cd2 100644
--- a/chromium/content/browser/download/download_manager_impl.cc
+++ b/chromium/content/browser/download/download_manager_impl.cc
@@ -20,6 +20,7 @@
#include "base/strings/sys_string_conversions.h"
#include "base/supports_user_data.h"
#include "base/synchronization/lock.h"
+#include "base/task/post_task.h"
#include "build/build_config.h"
#include "components/download/database/in_progress/download_entry.h"
#include "components/download/database/in_progress/in_progress_cache_impl.h"
@@ -56,6 +57,7 @@
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/throttling_url_loader.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/download_item_utils.h"
#include "content/public/browser/download_manager_delegate.h"
@@ -139,8 +141,8 @@ void CreateInterruptedDownload(
failed_created_info->url_chain.push_back(params->url());
failed_created_info->result = reason;
std::unique_ptr<ByteStreamReader> empty_byte_stream;
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(
&DownloadManager::StartDownload, download_manager,
std::move(failed_created_info),
@@ -148,11 +150,13 @@ void CreateInterruptedDownload(
nullptr, params->callback()));
}
-void BeginDownload(std::unique_ptr<download::DownloadUrlParameters> params,
- std::unique_ptr<storage::BlobDataHandle> blob_data_handle,
- content::ResourceContext* resource_context,
- bool is_new_download,
- base::WeakPtr<DownloadManagerImpl> download_manager) {
+void BeginDownload(
+ std::unique_ptr<download::DownloadUrlParameters> params,
+ std::unique_ptr<storage::BlobDataHandle> blob_data_handle,
+ content::ResourceContext* resource_context,
+ scoped_refptr<net::URLRequestContextGetter> url_request_context_getter,
+ bool is_new_download,
+ base::WeakPtr<DownloadManagerImpl> download_manager) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
download::UrlDownloadHandler::UniqueUrlDownloadHandlerPtr downloader(
@@ -161,8 +165,8 @@ void BeginDownload(std::unique_ptr<download::DownloadUrlParameters> params,
params->set_blob_storage_context_getter(
base::BindOnce(&BlobStorageContextGetter, resource_context));
std::unique_ptr<net::URLRequest> url_request =
- DownloadRequestCore::CreateRequestOnIOThread(is_new_download,
- params.get());
+ DownloadRequestCore::CreateRequestOnIOThread(
+ is_new_download, params.get(), std::move(url_request_context_getter));
if (blob_data_handle) {
storage::BlobProtocolHandler::SetRequestedBlobDataHandle(
url_request.get(), std::move(blob_data_handle));
@@ -190,8 +194,8 @@ void BeginDownload(std::unique_ptr<download::DownloadUrlParameters> params,
params.get(), false)
.release());
}
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(
&download::UrlDownloadHandler::Delegate::OnUrlDownloadHandlerCreated,
download_manager, std::move(downloader)));
@@ -304,7 +308,7 @@ DownloadManagerImpl::DownloadManagerImpl(BrowserContext* browser_context)
weak_factory_(this) {
DCHECK(browser_context);
download::SetIOTaskRunner(
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO));
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO}));
if (!base::FeatureList::IsEnabled(network::features::kNetworkService))
download::UrlDownloadHandlerFactory::Install(new UrlDownloaderFactory());
@@ -1256,14 +1260,13 @@ void DownloadManagerImpl::BeginDownloadInternal(
} 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),
- std::move(blob_data_handle),
- browser_context_->GetResourceContext(), is_new_download,
- weak_factory_.GetWeakPtr()));
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(
+ &BeginDownload, std::move(params), std::move(blob_data_handle),
+ browser_context_->GetResourceContext(),
+ base::WrapRefCounted(storage_partition->GetURLRequestContext()),
+ is_new_download, weak_factory_.GetWeakPtr()));
}
}
diff --git a/chromium/content/browser/download/download_manager_impl_unittest.cc b/chromium/content/browser/download/download_manager_impl_unittest.cc
index 7df5b5b6539..fa6bd708f10 100644
--- a/chromium/content/browser/download/download_manager_impl_unittest.cc
+++ b/chromium/content/browser/download/download_manager_impl_unittest.cc
@@ -188,8 +188,7 @@ download::MockDownloadItemImpl* MockDownloadItemFactory::PopItem() {
if (items_.empty())
return nullptr;
- std::map<uint32_t, download::MockDownloadItemImpl*>::iterator first_item =
- items_.begin();
+ auto first_item = items_.begin();
download::MockDownloadItemImpl* result = first_item->second;
items_.erase(first_item);
return result;
diff --git a/chromium/content/browser/download/download_request_core.cc b/chromium/content/browser/download/download_request_core.cc
index a4cdc54c64b..2a707e8b7aa 100644
--- a/chromium/content/browser/download/download_request_core.cc
+++ b/chromium/content/browser/download/download_request_core.cc
@@ -40,6 +40,7 @@
#include "net/http/http_request_headers.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_status_code.h"
+#include "net/url_request/url_request_context_getter.h"
#include "services/device/public/mojom/constants.mojom.h"
#include "services/device/public/mojom/wake_lock_provider.mojom.h"
#include "services/service_manager/public/cpp/connector.h"
@@ -126,12 +127,14 @@ const int DownloadRequestCore::kDownloadByteStreamSize = 100 * 1024;
// static
std::unique_ptr<net::URLRequest> DownloadRequestCore::CreateRequestOnIOThread(
bool is_new_download,
- download::DownloadUrlParameters* params) {
+ download::DownloadUrlParameters* params,
+ scoped_refptr<net::URLRequestContextGetter> url_request_context_getter) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(is_new_download || !params->content_initiated())
<< "Content initiated downloads should be a new download";
- std::unique_ptr<net::URLRequest> request = CreateURLRequestOnIOThread(params);
+ std::unique_ptr<net::URLRequest> request =
+ CreateURLRequestOnIOThread(params, std::move(url_request_context_getter));
DownloadRequestData::Attach(request.get(), params, is_new_download);
return request;
@@ -340,7 +343,7 @@ bool DownloadRequestCore::OnWillRead(scoped_refptr<net::IOBuffer>* buf,
DCHECK(!read_buffer_.get());
*buf_size = kReadBufSize;
- read_buffer_ = new net::IOBuffer(*buf_size);
+ read_buffer_ = base::MakeRefCounted<net::IOBuffer>(*buf_size);
*buf = read_buffer_.get();
return true;
}
diff --git a/chromium/content/browser/download/download_request_core.h b/chromium/content/browser/download/download_request_core.h
index 0a4a2db6000..93d43917a25 100644
--- a/chromium/content/browser/download/download_request_core.h
+++ b/chromium/content/browser/download/download_request_core.h
@@ -13,6 +13,7 @@
#include "base/callback.h"
#include "base/macros.h"
+#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "components/download/public/common/download_interrupt_reasons.h"
#include "components/download/public/common/download_save_info.h"
@@ -27,6 +28,7 @@ struct DownloadCreateInfo;
namespace net {
class HttpResponseHeaders;
class URLRequest;
+class URLRequestContextGetter;
class URLRequestStatus;
} // namespace net
@@ -71,7 +73,7 @@ class CONTENT_EXPORT DownloadRequestCore
// redirect to be followed if the return value is true.
bool OnRequestRedirected();
- // Starts a read cycle. Creates a new IOBuffer which can be passed into
+ // Starts a read cycle. Creates an IOBuffer which can be passed into
// URLRequest::Read(). Call OnReadCompleted() when the Read operation
// completes.
bool OnWillRead(scoped_refptr<net::IOBuffer>* buf,
@@ -110,7 +112,8 @@ class CONTENT_EXPORT DownloadRequestCore
static std::unique_ptr<net::URLRequest> CreateRequestOnIOThread(
bool is_new_download,
- download::DownloadUrlParameters* params);
+ download::DownloadUrlParameters* params,
+ scoped_refptr<net::URLRequestContextGetter> url_request_context_getter);
// Size of the buffer used between the DownloadRequestCore and the
// downstream receiver of its output.
diff --git a/chromium/content/browser/download/download_request_core_unittest.cc b/chromium/content/browser/download/download_request_core_unittest.cc
index 5c6fb4e426b..6a07198b9c6 100644
--- a/chromium/content/browser/download/download_request_core_unittest.cc
+++ b/chromium/content/browser/download/download_request_core_unittest.cc
@@ -5,9 +5,11 @@
#include <memory>
#include "base/run_loop.h"
+#include "base/task/post_task.h"
#include "components/download/public/common/download_item.h"
#include "components/download/public/common/download_url_parameters.h"
#include "content/browser/download/download_request_core.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "net/http/http_request_headers.h"
@@ -29,7 +31,7 @@ class DownloadRequestCoreTest : public testing::Test {
const std::string& url) const {
GURL gurl(url);
return std::make_unique<download::DownloadUrlParameters>(
- gurl, request_context_getter_.get(), TRAFFIC_ANNOTATION_FOR_TESTS);
+ gurl, TRAFFIC_ANNOTATION_FOR_TESTS);
}
void CheckRequestHeaders(const std::string& name,
@@ -46,14 +48,15 @@ class DownloadRequestCoreTest : public testing::Test {
}
void CreateRequestOnIOThread(download::DownloadUrlParameters* params) {
- url_request_ = DownloadRequestCore::CreateRequestOnIOThread(true, params);
+ url_request_ = DownloadRequestCore::CreateRequestOnIOThread(
+ true, params, request_context_getter_);
DCHECK(url_request_.get());
}
void SetUp() override {
request_context_getter_ = new net::TestURLRequestContextGetter(
- content::BrowserThread::GetTaskRunnerForThread(
- content::BrowserThread::UI));
+ base::CreateSingleThreadTaskRunnerWithTraits(
+ {content::BrowserThread::UI}));
}
void TearDown() override {
diff --git a/chromium/content/browser/download/download_request_handle.cc b/chromium/content/browser/download/download_request_handle.cc
index b0d903260d0..d0e09f7cf2e 100644
--- a/chromium/content/browser/download/download_request_handle.cc
+++ b/chromium/content/browser/download/download_request_handle.cc
@@ -6,8 +6,10 @@
#include "base/bind.h"
#include "base/strings/stringprintf.h"
+#include "base/task/post_task.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
namespace content {
@@ -31,20 +33,20 @@ WebContents* DownloadRequestHandle::GetWebContents() const {
}
void DownloadRequestHandle::PauseRequest() {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&DownloadResourceHandler::PauseRequest, handler_));
}
void DownloadRequestHandle::ResumeRequest() {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&DownloadResourceHandler::ResumeRequest, handler_));
}
void DownloadRequestHandle::CancelRequest(bool user_cancel) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&DownloadResourceHandler::CancelRequest, handler_));
}
diff --git a/chromium/content/browser/download/download_request_utils.cc b/chromium/content/browser/download/download_request_utils.cc
index 2c2a29228dc..86de66d1a75 100644
--- a/chromium/content/browser/download/download_request_utils.cc
+++ b/chromium/content/browser/download/download_request_utils.cc
@@ -8,7 +8,6 @@
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
-#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents.h"
namespace content {
@@ -20,14 +19,11 @@ DownloadRequestUtils::CreateDownloadForWebContentsMainFrame(
const GURL& url,
const net::NetworkTrafficAnnotationTag& traffic_annotation) {
RenderFrameHost* render_frame_host = web_contents->GetMainFrame();
- StoragePartition* storage_partition = BrowserContext::GetStoragePartition(
- web_contents->GetBrowserContext(), render_frame_host->GetSiteInstance());
return std::unique_ptr<download::DownloadUrlParameters>(
new download::DownloadUrlParameters(
url, render_frame_host->GetProcess()->GetID(),
render_frame_host->GetRenderViewHost()->GetRoutingID(),
- render_frame_host->GetRoutingID(),
- storage_partition->GetURLRequestContext(), traffic_annotation));
+ render_frame_host->GetRoutingID(), traffic_annotation));
}
} // namespace content
diff --git a/chromium/content/browser/download/download_resource_handler.cc b/chromium/content/browser/download/download_resource_handler.cc
index 752cc1af42d..d022b897f75 100644
--- a/chromium/content/browser/download/download_resource_handler.cc
+++ b/chromium/content/browser/download/download_resource_handler.cc
@@ -11,6 +11,7 @@
#include "base/location.h"
#include "base/logging.h"
#include "base/strings/stringprintf.h"
+#include "base/task/post_task.h"
#include "components/download/public/common/download_create_info.h"
#include "components/download/public/common/download_interrupt_reasons.h"
#include "components/download/public/common/download_interrupt_reasons_utils.h"
@@ -25,6 +26,7 @@
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/loader/resource_request_info_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/download_request_utils.h"
#include "content/public/browser/navigation_entry.h"
@@ -57,9 +59,9 @@ static void StartOnUIThread(
RenderFrameHost* frame_host =
RenderFrameHost::FromID(render_process_id, render_frame_id);
- // PlzNavigate: navigations don't have associated RenderFrameHosts. Get the
- // SiteInstance from the FrameTreeNode.
- if (!frame_host && IsBrowserSideNavigationEnabled()) {
+ // Navigations don't have associated RenderFrameHosts. Get the SiteInstance
+ // from the FrameTreeNode.
+ if (!frame_host) {
FrameTreeNode* frame_tree_node =
FrameTreeNode::GloballyFindByID(frame_tree_node_id);
if (frame_tree_node)
@@ -155,8 +157,8 @@ DownloadResourceHandler::DownloadResourceHandler(
// will occur via PostTask() as well, which will serialized behind this
// PostTask()
const ResourceRequestInfoImpl* request_info = GetRequestInfo();
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(
&InitializeDownloadTabInfoOnUIThread,
DownloadRequestHandle(AsWeakPtr(),
@@ -166,8 +168,8 @@ DownloadResourceHandler::DownloadResourceHandler(
DownloadResourceHandler::~DownloadResourceHandler() {
if (tab_info_) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&DeleteOnUIThread, std::move(tab_info_)));
}
}
@@ -200,8 +202,8 @@ void DownloadResourceHandler::OnRequestRedirected(
url::Origin new_origin(url::Origin::Create(redirect_info.new_url));
if (!follow_cross_origin_redirects_ &&
!first_origin_.IsSameOriginWith(new_origin)) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(
&NavigateOnUIThread, redirect_info.new_url, request()->url_chain(),
Referrer(GURL(redirect_info.new_referrer),
@@ -296,8 +298,8 @@ void DownloadResourceHandler::OnStart(
download::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED &&
create_info->is_new_download) {
if (!callback.is_null())
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(callback, nullptr, create_info->result));
return;
}
@@ -313,8 +315,8 @@ void DownloadResourceHandler::OnStart(
int render_frame_id = -1;
request_info->GetAssociatedRenderFrame(&render_process_id, &render_frame_id);
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&StartOnUIThread, std::move(create_info),
std::move(tab_info_), std::move(stream_reader),
render_process_id, render_frame_id,
diff --git a/chromium/content/browser/download/download_utils.cc b/chromium/content/browser/download/download_utils.cc
index 0fd9009103d..89d3af0f95a 100644
--- a/chromium/content/browser/download/download_utils.cc
+++ b/chromium/content/browser/download/download_utils.cc
@@ -28,6 +28,7 @@
#include "net/base/upload_bytes_element_reader.h"
#include "net/http/http_request_headers.h"
#include "net/url_request/url_request_context.h"
+#include "net/url_request/url_request_context_getter.h"
namespace content {
@@ -40,7 +41,8 @@ storage::BlobStorageContext* BlobStorageContextGetter(
}
std::unique_ptr<net::URLRequest> CreateURLRequestOnIOThread(
- download::DownloadUrlParameters* params) {
+ download::DownloadUrlParameters* params,
+ scoped_refptr<net::URLRequestContextGetter> url_request_context_getter) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(params->offset() >= 0);
@@ -49,10 +51,9 @@ std::unique_ptr<net::URLRequest> CreateURLRequestOnIOThread(
// resource_dispatcher_host_impl.h, so we must down cast. RDHI is the only
// subclass of RDH as of 2012 May 4.
std::unique_ptr<net::URLRequest> request(
- params->url_request_context_getter()
- ->GetURLRequestContext()
- ->CreateRequest(params->url(), net::DEFAULT_PRIORITY, nullptr,
- params->GetNetworkTrafficAnnotation()));
+ url_request_context_getter->GetURLRequestContext()->CreateRequest(
+ params->url(), net::DEFAULT_PRIORITY, nullptr,
+ params->GetNetworkTrafficAnnotation()));
request->set_method(params->method());
if (params->post_body()) {
diff --git a/chromium/content/browser/download/download_utils.h b/chromium/content/browser/download/download_utils.h
index df86cad0db7..a0328942793 100644
--- a/chromium/content/browser/download/download_utils.h
+++ b/chromium/content/browser/download/download_utils.h
@@ -7,6 +7,7 @@
#include <memory>
+#include "base/memory/ref_counted.h"
#include "base/optional.h"
#include "content/common/content_export.h"
@@ -16,6 +17,7 @@ class DownloadUrlParameters;
namespace net {
class URLRequest;
+class URLRequestContextGetter;
} // namespace net
namespace storage {
@@ -26,9 +28,11 @@ namespace content {
class ResourceContext;
-// Create a URLRequest from |params|.
-std::unique_ptr<net::URLRequest> CONTENT_EXPORT
-CreateURLRequestOnIOThread(download::DownloadUrlParameters* params);
+// Create a URLRequest from |params| using the specified
+// URLRequestContextGetter.
+std::unique_ptr<net::URLRequest> CONTENT_EXPORT CreateURLRequestOnIOThread(
+ download::DownloadUrlParameters* params,
+ scoped_refptr<net::URLRequestContextGetter> url_request_context_getter);
storage::BlobStorageContext* BlobStorageContextGetter(
ResourceContext* resource_context);
diff --git a/chromium/content/browser/download/drag_download_file.cc b/chromium/content/browser/download/drag_download_file.cc
index 8c6b6c1ff7f..c15e78c9ef1 100644
--- a/chromium/content/browser/download/drag_download_file.cc
+++ b/chromium/content/browser/download/drag_download_file.cc
@@ -11,12 +11,14 @@
#include "base/location.h"
#include "base/macros.h"
#include "base/single_thread_task_runner.h"
+#include "base/task/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "components/download/public/common/download_item.h"
#include "components/download/public/common/download_stats.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/download_request_utils.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
@@ -214,8 +216,8 @@ DragDownloadFile::~DragDownloadFile() {
// the UI thread so that it calls RemoveObserver on the right thread, and so
// that this task will run after the InitiateDownload task runs on the UI
// thread.
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&DragDownloadFileUI::Delete, base::Unretained(drag_ui_)));
drag_ui_ = nullptr;
}
@@ -231,8 +233,8 @@ void DragDownloadFile::Start(ui::DownloadFileObserver* observer) {
observer_ = observer;
DCHECK(observer_.get());
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&DragDownloadFileUI::InitiateDownload,
base::Unretained(drag_ui_), std::move(file_), file_path_));
}
@@ -247,9 +249,9 @@ bool DragDownloadFile::Wait() {
void DragDownloadFile::Stop() {
CheckThread();
if (drag_ui_) {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(&DragDownloadFileUI::Cancel,
- base::Unretained(drag_ui_)));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(&DragDownloadFileUI::Cancel,
+ base::Unretained(drag_ui_)));
}
}
diff --git a/chromium/content/browser/download/drag_download_file_browsertest.cc b/chromium/content/browser/download/drag_download_file_browsertest.cc
index c267b435449..6fbae0942e7 100644
--- a/chromium/content/browser/download/drag_download_file_browsertest.cc
+++ b/chromium/content/browser/download/drag_download_file_browsertest.cc
@@ -8,10 +8,12 @@
#include "base/memory/ref_counted.h"
#include "base/path_service.h"
#include "base/run_loop.h"
+#include "base/task/post_task.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"
#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/common/content_client.h"
@@ -52,8 +54,8 @@ class DragDownloadFileTest : public ContentBrowserTest {
~DragDownloadFileTest() override {}
void Succeed() {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::RunLoop::QuitCurrentWhenIdleClosureDeprecated());
}
diff --git a/chromium/content/browser/download/drag_download_util.cc b/chromium/content/browser/download/drag_download_util.cc
index 0996ac70e2c..a91ec48853c 100644
--- a/chromium/content/browser/download/drag_download_util.cc
+++ b/chromium/content/browser/download/drag_download_util.cc
@@ -15,8 +15,10 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/task/post_task.h"
#include "base/threading/thread_restrictions.h"
#include "build/build_config.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "url/gurl.h"
@@ -96,13 +98,15 @@ PromiseFileFinalizer::PromiseFileFinalizer(
void PromiseFileFinalizer::OnDownloadCompleted(
const base::FilePath& file_path) {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(&PromiseFileFinalizer::Cleanup, this));
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(&PromiseFileFinalizer::Cleanup, this));
}
void PromiseFileFinalizer::OnDownloadAborted() {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(&PromiseFileFinalizer::Cleanup, this));
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(&PromiseFileFinalizer::Cleanup, this));
}
PromiseFileFinalizer::~PromiseFileFinalizer() {}
diff --git a/chromium/content/browser/download/mhtml_generation_browsertest.cc b/chromium/content/browser/download/mhtml_generation_browsertest.cc
index 5d8e517f459..def931d9e8f 100644
--- a/chromium/content/browser/download/mhtml_generation_browsertest.cc
+++ b/chromium/content/browser/download/mhtml_generation_browsertest.cc
@@ -13,11 +13,13 @@
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/task/post_task.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/threading/thread_restrictions.h"
#include "components/download/public/common/download_task_runner.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/common/frame_messages.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/mhtml_extra_parts.h"
#include "content/public/browser/render_frame_host.h"
@@ -34,7 +36,6 @@
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/web/web_find_options.h"
#include "third_party/blink/public/web/web_frame_serializer_cache_control_policy.h"
using testing::ContainsRegex;
@@ -56,12 +57,12 @@ class FindTrackingDelegate : public WebContentsDelegate {
WebContentsDelegate* old_delegate = web_contents->GetDelegate();
web_contents->SetDelegate(this);
- blink::WebFindOptions options;
- options.run_synchronously_for_testing = true;
- options.match_case = false;
+ auto options = blink::mojom::FindOptions::New();
+ options->run_synchronously_for_testing = true;
+ options->match_case = false;
web_contents->Find(global_request_id++, base::UTF8ToUTF16(search_),
- options);
+ std::move(options));
run_loop_.Run();
web_contents->SetDelegate(old_delegate);
@@ -329,8 +330,8 @@ class GenerateMHTMLAndExitRendererMessageFilter : public BrowserMessageFilter {
// execution at (Y?) and (Z?) instead is possible. In practice,
// bouncing off of UI and download sequence does mean (Z) happens
// after (1).
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&GenerateMHTMLAndExitRendererMessageFilter::TaskX,
base::Unretained(this)));
}
@@ -346,8 +347,8 @@ class GenerateMHTMLAndExitRendererMessageFilter : public BrowserMessageFilter {
}
void TaskY() {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&GenerateMHTMLAndExitRendererMessageFilter::TaskZ,
base::Unretained(this)));
}
diff --git a/chromium/content/browser/download/save_file_manager.cc b/chromium/content/browser/download/save_file_manager.cc
index 96c463e4471..685b462e10c 100644
--- a/chromium/content/browser/download/save_file_manager.cc
+++ b/chromium/content/browser/download/save_file_manager.cc
@@ -4,7 +4,9 @@
#include "build/build_config.h"
+#include "base/task/post_task.h"
#include "content/browser/download/save_file_manager.h"
+#include "content/public/browser/browser_task_traits.h"
#include "base/bind.h"
#include "base/files/file_util.h"
@@ -325,9 +327,9 @@ void SaveFileManager::StartSave(std::unique_ptr<SaveFileCreateInfo> info) {
DCHECK(!LookupSaveFile(save_file->save_item_id()));
save_file_map_[save_file->save_item_id()] = std::move(save_file);
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(&SaveFileManager::OnStartSave, this,
- save_file_create_info));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(&SaveFileManager::OnStartSave, this,
+ save_file_create_info));
}
// We do forward an update to the UI thread here, since we do not use timer to
@@ -343,8 +345,8 @@ void SaveFileManager::UpdateSaveProgress(SaveItemId save_item_id,
download::DownloadInterruptReason reason =
save_file->AppendDataToFile(data.data(), data.size());
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&SaveFileManager::OnUpdateSaveProgress, this,
save_file->save_item_id(), save_file->BytesSoFar(),
reason == download::DOWNLOAD_INTERRUPT_REASON_NONE));
@@ -374,8 +376,8 @@ void SaveFileManager::SaveFinished(SaveItemId save_item_id,
save_file->Detach();
}
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&SaveFileManager::OnSaveFinished, this, save_item_id,
bytes_so_far, is_success));
}
@@ -437,8 +439,8 @@ void SaveFileManager::CancelSave(SaveItemId save_item_id) {
base::DeleteFile(save_file->FullPath(), false);
} else if (save_file->save_source() ==
SaveFileCreateInfo::SAVE_FILE_FROM_NET) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&SaveFileManager::ClearURLLoader, this, save_item_id));
}
@@ -486,8 +488,8 @@ void SaveFileManager::RenameAllFiles(const FinalNamesMap& final_names,
}
}
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&SaveFileManager::OnFinishSavePageJob, this,
render_process_id, render_frame_routing_id,
save_package_id));
diff --git a/chromium/content/browser/download/save_package.cc b/chromium/content/browser/download/save_package.cc
index 187d62297d0..cba288ad68e 100644
--- a/chromium/content/browser/download/save_package.cc
+++ b/chromium/content/browser/download/save_package.cc
@@ -441,7 +441,7 @@ bool SavePackage::GenerateFileName(const std::string& disposition,
base::FilePath::StringType file_name = base_name + file_name_ext;
// Check whether we already have same name in a case insensitive manner.
- FileNameSet::const_iterator iter = file_name_set_.find(file_name);
+ auto iter = file_name_set_.find(file_name);
if (iter == file_name_set_.end()) {
DCHECK(!file_name.empty());
file_name_set_.insert(file_name);
@@ -463,7 +463,7 @@ bool SavePackage::GenerateFileName(const std::string& disposition,
// Prepare the new ordinal number.
uint32_t ordinal_number;
- FileNameCountMap::iterator it = file_name_count_map_.find(base_file_name);
+ auto it = file_name_count_map_.find(base_file_name);
if (it == file_name_count_map_.end()) {
// First base-name-conflict resolving, use 1 as initial ordinal number.
file_name_count_map_[base_file_name] = 1;
diff --git a/chromium/content/browser/download/url_downloader.cc b/chromium/content/browser/download/url_downloader.cc
index e44234a31f5..15b46abdb33 100644
--- a/chromium/content/browser/download/url_downloader.cc
+++ b/chromium/content/browser/download/url_downloader.cc
@@ -8,6 +8,7 @@
#include "base/location.h"
#include "base/macros.h"
#include "base/sequenced_task_runner.h"
+#include "base/task/post_task.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "components/download/public/common/download_create_info.h"
#include "components/download/public/common/download_interrupt_reasons.h"
@@ -16,6 +17,7 @@
#include "components/download/public/common/url_download_request_handle.h"
#include "content/browser/byte_stream.h"
#include "content/browser/download/byte_stream_input_stream.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "net/base/io_buffer.h"
#include "net/base/load_flags.h"
@@ -188,8 +190,8 @@ void UrlDownloader::OnStart(
create_info->request_handle.reset(new download::UrlDownloadRequestHandle(
weak_ptr_factory_.GetWeakPtr(), base::SequencedTaskRunnerHandle::Get()));
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(
&download::UrlDownloadHandler::Delegate::OnUrlDownloadStarted,
delegate_, std::move(create_info),
@@ -214,8 +216,8 @@ void UrlDownloader::CancelRequest() {
}
void UrlDownloader::Destroy() {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(
&download::UrlDownloadHandler::Delegate::OnUrlDownloadStopped,
delegate_, this));
diff --git a/chromium/content/browser/download/url_downloader_factory.cc b/chromium/content/browser/download/url_downloader_factory.cc
index 5a66bd2b9fa..c6a915457d2 100644
--- a/chromium/content/browser/download/url_downloader_factory.cc
+++ b/chromium/content/browser/download/url_downloader_factory.cc
@@ -8,6 +8,7 @@
#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"
+#include "net/url_request/url_request_context_getter.h"
namespace content {
@@ -21,9 +22,11 @@ UrlDownloaderFactory::CreateUrlDownloadHandler(
base::WeakPtr<download::UrlDownloadHandler::Delegate> delegate,
scoped_refptr<download::DownloadURLLoaderFactoryGetter>
url_loader_factory_getter,
+ scoped_refptr<net::URLRequestContextGetter> url_request_context_getter,
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) {
std::unique_ptr<net::URLRequest> url_request =
- DownloadRequestCore::CreateRequestOnIOThread(true, params.get());
+ DownloadRequestCore::CreateRequestOnIOThread(
+ true, params.get(), std::move(url_request_context_getter));
return download::UrlDownloadHandler::UniqueUrlDownloadHandlerPtr(
UrlDownloader::BeginDownload(delegate, std::move(url_request),
diff --git a/chromium/content/browser/download/url_downloader_factory.h b/chromium/content/browser/download/url_downloader_factory.h
index ae908ecaeca..bda99732608 100644
--- a/chromium/content/browser/download/url_downloader_factory.h
+++ b/chromium/content/browser/download/url_downloader_factory.h
@@ -5,11 +5,16 @@
#ifndef CONTENT_BROWSER_DOWNLOAD_URL_DOWNLOADER_FACTORY_H_
#define CONTENT_BROWSER_DOWNLOAD_URL_DOWNLOADER_FACTORY_H_
+#include "base/memory/ref_counted.h"
#include "components/download/public/common/url_download_handler_factory.h"
namespace download {
class DownloadURLLoaderFactoryGetter;
-};
+}
+
+namespace net {
+class URLRequestContextGetter;
+}
namespace content {
@@ -27,6 +32,7 @@ class UrlDownloaderFactory : public download::UrlDownloadHandlerFactory {
base::WeakPtr<download::UrlDownloadHandler::Delegate> delegate,
scoped_refptr<download::DownloadURLLoaderFactoryGetter>
shared_url_loader_factory,
+ scoped_refptr<net::URLRequestContextGetter> url_request_context_getter,
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) override;
};
diff --git a/chromium/content/browser/download/web_ui_download_url_loader_factory_getter.cc b/chromium/content/browser/download/web_ui_download_url_loader_factory_getter.cc
index c4873157c81..cbf07e8a6a3 100644
--- a/chromium/content/browser/download/web_ui_download_url_loader_factory_getter.cc
+++ b/chromium/content/browser/download/web_ui_download_url_loader_factory_getter.cc
@@ -4,6 +4,8 @@
#include "content/browser/download/web_ui_download_url_loader_factory_getter.h"
+#include "base/task/post_task.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/web_ui_url_loader_factory.h"
#include "services/network/public/cpp/wrapper_shared_url_loader_factory.h"
@@ -20,7 +22,7 @@ WebUIDownloadURLLoaderFactoryGetter::WebUIDownloadURLLoaderFactoryGetter(
}
WebUIDownloadURLLoaderFactoryGetter::~WebUIDownloadURLLoaderFactoryGetter() {
- BrowserThread::GetTaskRunnerForThread(BrowserThread::UI)
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::UI})
->DeleteSoon(FROM_HERE, std::move(factory_));
}
diff --git a/chromium/content/browser/file_url_loader_factory.cc b/chromium/content/browser/file_url_loader_factory.cc
index ea4d8eee977..389fd1962ae 100644
--- a/chromium/content/browser/file_url_loader_factory.cc
+++ b/chromium/content/browser/file_url_loader_factory.cc
@@ -25,6 +25,7 @@
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/file_url_loader.h"
#include "content/public/common/content_client.h"
+#include "content/public/common/content_switches.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "mojo/public/cpp/system/data_pipe.h"
#include "mojo/public/cpp/system/file_data_pipe_producer.h"
@@ -38,7 +39,9 @@
#include "net/http/http_byte_range.h"
#include "net/http/http_util.h"
#include "net/url_request/redirect_info.h"
+#include "services/network/public/cpp/cors/cors_error_status.h"
#include "services/network/public/cpp/resource_request.h"
+#include "services/network/public/mojom/cors.mojom-shared.h"
#include "services/network/public/mojom/url_loader.mojom.h"
#include "storage/common/fileapi/file_system_util.h"
#include "url/gurl.h"
@@ -93,6 +96,25 @@ GURL AppendUrlSeparator(const GURL& url) {
return url.ReplaceComponents(replacements);
}
+bool ShouldFailRequestDueToCORS(const network::ResourceRequest& request) {
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableWebSecurity)) {
+ return false;
+ }
+
+ const auto mode = request.fetch_request_mode;
+ if (mode == network::mojom::FetchRequestMode::kNavigate ||
+ mode == network::mojom::FetchRequestMode::kNoCORS) {
+ return false;
+ }
+
+ if (!request.request_initiator)
+ return true;
+
+ return !request.request_initiator->IsSameOriginWith(
+ url::Origin::Create(request.url));
+}
+
class FileURLDirectoryLoader
: public network::mojom::URLLoader,
public net::DirectoryLister::DirectoryListerDelegate {
@@ -560,8 +582,6 @@ class FileURLLoader : public network::mojom::URLLoader {
size_t first_byte_to_send = 0;
size_t total_bytes_to_send = static_cast<size_t>(info.size);
- total_bytes_written_ = static_cast<size_t>(info.size);
-
if (byte_range.IsValid()) {
first_byte_to_send =
static_cast<size_t>(byte_range.first_byte_position());
@@ -570,6 +590,8 @@ class FileURLLoader : public network::mojom::URLLoader {
first_byte_to_send + 1;
}
+ total_bytes_written_ = static_cast<size_t>(total_bytes_to_send);
+
head.content_length = base::saturated_cast<int64_t>(total_bytes_to_send);
if (first_byte_to_send < initial_read_size) {
@@ -677,7 +699,9 @@ class FileURLLoader : public network::mojom::URLLoader {
network::mojom::URLLoaderClientPtr client_;
std::unique_ptr<RedirectData> redirect_data_;
- // In case of successful loads, this holds the total of bytes written.
+ // In case of successful loads, this holds the total number of bytes written
+ // to the response (this may be smaller than the total size of the file when
+ // a byte range was requested).
// It is used to set some of the URLLoaderCompletionStatus data passed back
// to the URLLoaderClients (eg SimpleURLLoader).
size_t total_bytes_written_ = 0;
@@ -708,6 +732,16 @@ void FileURLLoaderFactory::CreateLoaderAndStart(
network::URLLoaderCompletionStatus(net::ERR_INVALID_URL));
return;
}
+
+ // FileURLLoader doesn't support CORS and it's not covered by CORSURLLoader,
+ // so we need to reject requests that need CORS manually.
+ if (ShouldFailRequestDueToCORS(request)) {
+ client->OnComplete(
+ network::URLLoaderCompletionStatus(network::CORSErrorStatus(
+ network::mojom::CORSError::kCORSDisabledScheme)));
+ return;
+ }
+
if (file_path.EndsWithSeparator() && file_path.IsAbsolute()) {
task_runner_->PostTask(
FROM_HERE,
diff --git a/chromium/content/browser/fileapi/README.md b/chromium/content/browser/fileapi/README.md
new file mode 100644
index 00000000000..470736189bf
--- /dev/null
+++ b/chromium/content/browser/fileapi/README.md
@@ -0,0 +1,23 @@
+# FileSystem API
+
+This directory contains part of the browser side implementation of various
+filesystem related APIs.
+
+## Related directories
+
+[`//storage/browser/fileapi/`](../../../storage/browser/fileapi) contains the
+rest of the browser side implementation, while
+[`blink/renderer/modules/filesystem`](../../../third_party/blink/renderer/modules/filesystem)
+contains the renderer side implementation and
+[`blink/public/mojom/filesystem`](../../../third_party/blink/public/mojom/filesystem)
+contains the mojom interfaces for these APIs.
+
+## In this directory
+
+[`FileSystemManagerImpl`](file_system_manager_impl.h) is the main entry point
+for calls from the renderer, it mostly redirects incoming mojom calls to a
+`storage::FileSystemContext` instance.
+
+[`FileSystemChooser`](file_system_chooser.h) uses ui::SelectFileDialog to show
+a file or directory picker, and is responsible for granting a process the right
+permissions for actually accessing the files that were selected.
diff --git a/chromium/content/browser/fileapi/browser_file_system_helper.cc b/chromium/content/browser/fileapi/browser_file_system_helper.cc
index 7227c691e73..f3d73489ec9 100644
--- a/chromium/content/browser/fileapi/browser_file_system_helper.cc
+++ b/chromium/content/browser/fileapi/browser_file_system_helper.cc
@@ -15,8 +15,10 @@
#include "base/sequenced_task_runner.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/lazy_task_runner.h"
+#include "base/task/post_task.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/child_process_security_policy.h"
#include "content/public/browser/content_browser_client.h"
@@ -89,7 +91,8 @@ scoped_refptr<storage::FileSystemContext> CreateFileSystemContext(
scoped_refptr<storage::FileSystemContext> file_system_context =
new storage::FileSystemContext(
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO).get(),
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO})
+ .get(),
g_fileapi_task_runner.Get().get(),
BrowserContext::GetMountPoints(browser_context),
browser_context->GetSpecialStoragePolicy(), quota_manager_proxy,
diff --git a/chromium/content/browser/fileapi/file_system_browsertest.cc b/chromium/content/browser/fileapi/file_system_browsertest.cc
index cce4e1155d0..3ff81a5aada 100644
--- a/chromium/content/browser/fileapi/file_system_browsertest.cc
+++ b/chromium/content/browser/fileapi/file_system_browsertest.cc
@@ -10,9 +10,11 @@
#include "base/location.h"
#include "base/memory/ref_counted.h"
#include "base/single_thread_task_runner.h"
+#include "base/task/post_task.h"
#include "base/test/thread_test_helper.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/common/content_switches.h"
@@ -62,8 +64,8 @@ class FileSystemBrowserTestWithLowQuota : public FileSystemBrowserTest {
static void SetLowQuota(scoped_refptr<QuotaManager> qm) {
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&FileSystemBrowserTestWithLowQuota::SetLowQuota, qm));
return;
}
diff --git a/chromium/content/browser/fileapi/file_system_chooser.cc b/chromium/content/browser/fileapi/file_system_chooser.cc
index 0c8ae67d894..e36025673d1 100644
--- a/chromium/content/browser/fileapi/file_system_chooser.cc
+++ b/chromium/content/browser/fileapi/file_system_chooser.cc
@@ -5,6 +5,10 @@
#include "content/browser/fileapi/file_system_chooser.h"
#include "base/bind.h"
+#include "base/files/file_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/task/post_task.h"
+#include "build/build_config.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/child_process_security_policy.h"
#include "content/public/browser/content_browser_client.h"
@@ -15,25 +19,108 @@
namespace content {
+namespace {
+
+bool GetFileTypesFromAcceptsOption(
+ const blink::mojom::ChooseFileSystemEntryAcceptsOption& option,
+ std::vector<base::FilePath::StringType>* extensions,
+ base::string16* description) {
+ std::set<base::FilePath::StringType> extension_set;
+
+ for (const std::string& extension : option.extensions) {
+#if defined(OS_WIN)
+ extension_set.insert(base::UTF8ToWide(extension));
+#else
+ extension_set.insert(extension);
+#endif
+ }
+
+ for (const std::string& mime_type : option.mime_types) {
+ std::vector<base::FilePath::StringType> inner;
+ net::GetExtensionsForMimeType(mime_type, &inner);
+ if (inner.empty())
+ continue;
+ extension_set.insert(inner.begin(), inner.end());
+ }
+
+ extensions->assign(extension_set.begin(), extension_set.end());
+
+ if (extensions->empty())
+ return false;
+
+ *description = option.description;
+ return true;
+}
+
+void ConvertAcceptsToFileTypeInfo(
+ const std::vector<blink::mojom::ChooseFileSystemEntryAcceptsOptionPtr>& accepts,
+ bool include_accepts_all,
+ ui::SelectFileDialog::FileTypeInfo* file_types) {
+ file_types->include_all_files = include_accepts_all;
+
+ for (const auto& option : accepts) {
+ std::vector<base::FilePath::StringType> extensions;
+ base::string16 description;
+
+ if (!GetFileTypesFromAcceptsOption(*option, &extensions, &description))
+ continue; // No extensions were found for this option, skip it.
+
+ file_types->extensions.push_back(extensions);
+ // FileTypeInfo expects each set of extension to have a corresponding
+ // description. A blank description will result in a system generated
+ // description to be used.
+ file_types->extension_description_overrides.push_back(description);
+ }
+
+ if (file_types->extensions.empty())
+ file_types->include_all_files = true;
+}
+
+} // namespace
+
// static
void FileSystemChooser::CreateAndShow(
int render_process_id,
int frame_id,
+ blink::mojom::ChooseFileSystemEntryType type,
+ std::vector<blink::mojom::ChooseFileSystemEntryAcceptsOptionPtr> accepts,
+ bool include_accepts_all,
ResultCallback callback,
scoped_refptr<base::TaskRunner> callback_runner) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
RenderFrameHost* rfh = RenderFrameHost::FromID(render_process_id, frame_id);
WebContents* web_contents = WebContents::FromRenderFrameHost(rfh);
- auto* listener = new FileSystemChooser(render_process_id, std::move(callback),
- std::move(callback_runner));
+ auto* listener = new FileSystemChooser(
+ render_process_id, type, std::move(callback), std::move(callback_runner));
listener->dialog_ = ui::SelectFileDialog::Create(
listener,
GetContentClient()->browser()->CreateSelectFilePolicy(web_contents));
// TODO(https://crbug.com/878581): Better/more specific options to pass to
// SelectFile.
+
+ ui::SelectFileDialog::Type dialog_type = ui::SelectFileDialog::SELECT_NONE;
+ switch (type) {
+ case blink::mojom::ChooseFileSystemEntryType::kOpenFile:
+ dialog_type = ui::SelectFileDialog::SELECT_OPEN_FILE;
+ break;
+ case blink::mojom::ChooseFileSystemEntryType::kOpenMultipleFiles:
+ dialog_type = ui::SelectFileDialog::SELECT_OPEN_MULTI_FILE;
+ break;
+ case blink::mojom::ChooseFileSystemEntryType::kSaveFile:
+ dialog_type = ui::SelectFileDialog::SELECT_SAVEAS_FILE;
+ break;
+ case blink::mojom::ChooseFileSystemEntryType::kOpenDirectory:
+ dialog_type = ui::SelectFileDialog::SELECT_FOLDER;
+ break;
+ }
+ DCHECK_NE(dialog_type, ui::SelectFileDialog::SELECT_NONE);
+
+ ui::SelectFileDialog::FileTypeInfo file_types;
+ ConvertAcceptsToFileTypeInfo(accepts, include_accepts_all, &file_types);
+
listener->dialog_->SelectFile(
- ui::SelectFileDialog::SELECT_OPEN_FILE, /*title=*/base::string16(),
- /*default_path=*/base::FilePath(), /*file_types=*/nullptr,
+ dialog_type, /*title=*/base::string16(),
+ /*default_path=*/base::FilePath(), &file_types,
/*file_type_index=*/0,
/*default_extension=*/base::FilePath::StringType(),
web_contents ? web_contents->GetTopLevelNativeWindow() : nullptr,
@@ -42,11 +129,13 @@ void FileSystemChooser::CreateAndShow(
FileSystemChooser::FileSystemChooser(
int render_process_id,
+ blink::mojom::ChooseFileSystemEntryType type,
ResultCallback callback,
scoped_refptr<base::TaskRunner> callback_runner)
: render_process_id_(render_process_id),
callback_(std::move(callback)),
- callback_runner_(std::move(callback_runner)) {}
+ callback_runner_(std::move(callback_runner)),
+ type_(type) {}
FileSystemChooser::~FileSystemChooser() {
if (dialog_)
@@ -73,21 +162,72 @@ void FileSystemChooser::MultiFilesSelected(
for (const auto& path : files) {
auto entry = blink::mojom::FileSystemEntry::New();
entry->file_system_id = isolated_context->RegisterFileSystemForPath(
- storage::kFileSystemTypeNativeForPlatformApp, std::string(), path,
+ storage::kFileSystemTypeNativeLocal, std::string(), path,
&entry->base_name);
- // TODO(https://crbug.com/878585): Determine if we always want to grant
- // write permission.
security_policy->GrantReadFileSystem(render_process_id_,
entry->file_system_id);
- security_policy->GrantWriteFileSystem(render_process_id_,
- entry->file_system_id);
- security_policy->GrantDeleteFromFileSystem(render_process_id_,
- entry->file_system_id);
+ // TODO(https://crbug.com/878585): Don't grant write/modify permissions
+ // unless a website already has the appropriate permissions.
+ if (type_ == blink::mojom::ChooseFileSystemEntryType::kOpenDirectory) {
+ // Only grant Create permissions if we're opening a directory. And
+ // just granting Create permissions on top of Write and Delete does not
+ // actually grant the same permissions as calling this method.
+ security_policy->GrantCreateReadWriteFileSystem(render_process_id_,
+ entry->file_system_id);
+ } else {
+ security_policy->GrantWriteFileSystem(render_process_id_,
+ entry->file_system_id);
+ security_policy->GrantDeleteFromFileSystem(render_process_id_,
+ entry->file_system_id);
+ }
result.push_back(std::move(entry));
}
+ if (type_ == blink::mojom::ChooseFileSystemEntryType::kSaveFile) {
+ // Create files if they don't yet exist.
+ // TODO(mek): If we change FileSystemFileHandle to be able to represent a
+ // file that doesn't exist on disk, we should be able to get rid of this
+ // step and make the whole API slightly more robust.
+ base::PostTaskWithTraits(
+ FROM_HERE, {base::TaskPriority::USER_BLOCKING, base::MayBlock()},
+ base::BindOnce(
+ [](const std::vector<base::FilePath>& files,
+ std::vector<blink::mojom::FileSystemEntryPtr> result,
+ scoped_refptr<base::TaskRunner> callback_runner,
+ ResultCallback callback) {
+ for (const auto& path : files) {
+ // Checking if a path exists, and then creating it if it doesn't
+ // is of course racy, but external applications could just as
+ // well be deleting the entire directory, or similar problematic
+ // cases, so no matter what we do there are always going to be
+ // race conditions and websites will just have to deal with any
+ // method being able to fail in unexpected ways.
+ if (base::PathExists(path))
+ continue;
+ int creation_flags =
+ base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_READ;
+ base::File file(path, creation_flags);
+
+ if (!file.IsValid()) {
+ callback_runner->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ std::move(callback), base::File::FILE_ERROR_FAILED,
+ std::vector<blink::mojom::FileSystemEntryPtr>()));
+ return;
+ }
+ }
+ callback_runner->PostTask(
+ FROM_HERE,
+ base::BindOnce(std::move(callback), base::File::FILE_OK,
+ std::move(result)));
+ },
+ files, std::move(result), callback_runner_, std::move(callback_)));
+ delete this;
+ return;
+ }
callback_runner_->PostTask(
FROM_HERE, base::BindOnce(std::move(callback_), base::File::FILE_OK,
std::move(result)));
diff --git a/chromium/content/browser/fileapi/file_system_chooser.h b/chromium/content/browser/fileapi/file_system_chooser.h
index 2283a6725e3..56a2498bccc 100644
--- a/chromium/content/browser/fileapi/file_system_chooser.h
+++ b/chromium/content/browser/fileapi/file_system_chooser.h
@@ -7,6 +7,7 @@
#include "base/files/file.h"
#include "base/task_runner.h"
+#include "content/common/content_export.h"
#include "third_party/blink/public/mojom/filesystem/file_system.mojom.h"
#include "ui/shell_dialogs/select_file_dialog.h"
@@ -17,18 +18,23 @@ namespace content {
// a callback on a specific task runner. Furthermore the listener will delete
// itself when any of its listener methods are called.
// All of this class has to be called on the UI thread.
-class FileSystemChooser : public ui::SelectFileDialog::Listener {
+class CONTENT_EXPORT FileSystemChooser : public ui::SelectFileDialog::Listener {
public:
using ResultCallback =
base::OnceCallback<void(base::File::Error,
std::vector<blink::mojom::FileSystemEntryPtr>)>;
- static void CreateAndShow(int render_process_id,
- int frame_id,
- ResultCallback callback,
- scoped_refptr<base::TaskRunner> callback_runner);
+ static void CreateAndShow(
+ int render_process_id,
+ int frame_id,
+ blink::mojom::ChooseFileSystemEntryType type,
+ std::vector<blink::mojom::ChooseFileSystemEntryAcceptsOptionPtr> accepts,
+ bool include_accepts_all,
+ ResultCallback callback,
+ scoped_refptr<base::TaskRunner> callback_runner);
FileSystemChooser(int render_process_id,
+ blink::mojom::ChooseFileSystemEntryType type,
ResultCallback callback,
scoped_refptr<base::TaskRunner> callback_runner);
@@ -46,6 +52,7 @@ class FileSystemChooser : public ui::SelectFileDialog::Listener {
int render_process_id_;
ResultCallback callback_;
scoped_refptr<base::TaskRunner> callback_runner_;
+ blink::mojom::ChooseFileSystemEntryType type_;
scoped_refptr<ui::SelectFileDialog> dialog_;
};
diff --git a/chromium/content/browser/fileapi/file_system_chooser_browsertest.cc b/chromium/content/browser/fileapi/file_system_chooser_browsertest.cc
new file mode 100644
index 00000000000..3c323eeae4d
--- /dev/null
+++ b/chromium/content/browser/fileapi/file_system_chooser_browsertest.cc
@@ -0,0 +1,195 @@
+// 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 "base/strings/utf_string_conversions.h"
+#include "base/test/scoped_feature_list.h"
+#include "base/threading/thread_restrictions.h"
+#include "content/browser/fileapi/file_system_chooser_test_helpers.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 "third_party/blink/public/common/features.h"
+#include "ui/shell_dialogs/select_file_dialog.h"
+#include "ui/shell_dialogs/select_file_dialog_factory.h"
+#include "ui/shell_dialogs/select_file_policy.h"
+
+namespace content {
+
+// This browser test implements end-to-end tests for the chooseFileSystemEntry
+// API.
+class FileSystemChooserBrowserTest : public ContentBrowserTest {
+ public:
+ void SetUp() override {
+ ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+ scoped_feature_list_.InitAndEnableFeature(
+ blink::features::kWritableFilesAPI);
+ ContentBrowserTest::SetUp();
+ }
+
+ void TearDown() override {
+ ContentBrowserTest::TearDown();
+ ASSERT_TRUE(temp_dir_.Delete());
+ ui::SelectFileDialog::SetFactory(nullptr);
+ }
+
+ base::FilePath CreateTestFile(const std::string& contents) {
+ base::ScopedAllowBlockingForTesting allow_blocking;
+ base::FilePath result;
+ EXPECT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.GetPath(), &result));
+ EXPECT_EQ(int{contents.size()},
+ base::WriteFile(result, contents.data(), contents.size()));
+ return result;
+ }
+
+ base::FilePath CreateTestDir() {
+ base::ScopedAllowBlockingForTesting allow_blocking;
+ base::FilePath result;
+ EXPECT_TRUE(base::CreateTemporaryDirInDir(
+ temp_dir_.GetPath(), FILE_PATH_LITERAL("test"), &result));
+ return result;
+ }
+
+ protected:
+ const std::string kBlankHtml = "<!DOCTYPE html><html><body>";
+ const GURL kTestUrl = GURL("https://foobar.com/");
+
+ private:
+ base::test::ScopedFeatureList scoped_feature_list_;
+ base::ScopedTempDir temp_dir_;
+};
+
+IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest, CancelDialog) {
+ ui::SelectFileDialog::SetFactory(new CancellingSelectFileDialogFactory);
+ LoadDataWithBaseURL(shell(), kTestUrl, kBlankHtml, kTestUrl);
+ auto result = EvalJs(shell(), "self.chooseFileSystemEntries()");
+ EXPECT_TRUE(result.error.find("AbortError") != std::string::npos)
+ << result.error;
+}
+
+IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest, OpenFile) {
+ const std::string file_contents = "hello world!";
+ const base::FilePath test_file = CreateTestFile(file_contents);
+ SelectFileDialogParams dialog_params;
+ ui::SelectFileDialog::SetFactory(
+ new FakeSelectFileDialogFactory({test_file}, &dialog_params));
+ LoadDataWithBaseURL(shell(), kTestUrl, kBlankHtml, kTestUrl);
+ EXPECT_EQ(test_file.BaseName().AsUTF8Unsafe(),
+ EvalJs(shell(),
+ "(async () => {"
+ " let e = await self.chooseFileSystemEntries();"
+ " self.selected_entry = e;"
+ " return e.name; })()"));
+ EXPECT_EQ(ui::SelectFileDialog::SELECT_OPEN_FILE, dialog_params.type);
+ EXPECT_EQ(
+ file_contents,
+ EvalJs(shell(),
+ "(async () => { const file = await self.selected_entry.getFile(); "
+ "return await new Response(file).text(); })()"));
+}
+
+IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest, SaveFile) {
+ const std::string file_contents = "file contents to write";
+ const base::FilePath test_file = CreateTestFile("");
+ {
+ // Delete file, since SaveFile should be able to deal with non-existing
+ // files.
+ base::ScopedAllowBlockingForTesting allow_blocking;
+ ASSERT_TRUE(base::DeleteFile(test_file, false));
+ }
+ SelectFileDialogParams dialog_params;
+ ui::SelectFileDialog::SetFactory(
+ new FakeSelectFileDialogFactory({test_file}, &dialog_params));
+ LoadDataWithBaseURL(shell(), kTestUrl, kBlankHtml, kTestUrl);
+ EXPECT_EQ(test_file.BaseName().AsUTF8Unsafe(),
+ EvalJs(shell(),
+ "(async () => {"
+ " let e = await self.chooseFileSystemEntries("
+ " {type: 'saveFile'});"
+ " self.entry = e;"
+ " return e.name; })()"));
+ EXPECT_EQ(ui::SelectFileDialog::SELECT_SAVEAS_FILE, dialog_params.type);
+ EXPECT_EQ(int{file_contents.size()},
+ EvalJs(shell(),
+ JsReplace("(async () => {"
+ " const w = await self.entry.createWriter();"
+ " await w.write(0, new Blob([$1]));"
+ " return (await self.entry.getFile()).size; })()",
+ file_contents)));
+ {
+ base::ScopedAllowBlockingForTesting allow_blocking;
+ std::string read_contents;
+ EXPECT_TRUE(base::ReadFileToString(test_file, &read_contents));
+ EXPECT_EQ(file_contents, read_contents);
+ }
+}
+
+IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest, OpenMultipleFiles) {
+ const base::FilePath test_file1 = CreateTestFile("file1");
+ const base::FilePath test_file2 = CreateTestFile("file2");
+ SelectFileDialogParams dialog_params;
+ ui::SelectFileDialog::SetFactory(new FakeSelectFileDialogFactory(
+ {test_file1, test_file2}, &dialog_params));
+ LoadDataWithBaseURL(shell(), kTestUrl, kBlankHtml, kTestUrl);
+ EXPECT_EQ(ListValueOf(test_file1.BaseName().AsUTF8Unsafe(),
+ test_file2.BaseName().AsUTF8Unsafe()),
+ EvalJs(shell(),
+ "(async () => {"
+ " let e = await self.chooseFileSystemEntries("
+ " {multiple: true});"
+ " return e.map(x => x.name); })()"));
+ EXPECT_EQ(ui::SelectFileDialog::SELECT_OPEN_MULTI_FILE, dialog_params.type);
+}
+
+IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest, OpenDirectory) {
+ base::FilePath test_dir = CreateTestDir();
+ SelectFileDialogParams dialog_params;
+ ui::SelectFileDialog::SetFactory(
+ new FakeSelectFileDialogFactory({test_dir}, &dialog_params));
+ LoadDataWithBaseURL(shell(), kTestUrl, kBlankHtml, kTestUrl);
+ EXPECT_EQ(test_dir.BaseName().AsUTF8Unsafe(),
+ EvalJs(shell(),
+ "(async () => {"
+ " let e = await self.chooseFileSystemEntries("
+ " {type: 'openDirectory'});"
+ " self.selected_entry = e;"
+ " return e.name; })()"));
+ EXPECT_EQ(ui::SelectFileDialog::SELECT_FOLDER, dialog_params.type);
+}
+
+IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest, AcceptsOptions) {
+ SelectFileDialogParams dialog_params;
+ ui::SelectFileDialog::SetFactory(
+ new CancellingSelectFileDialogFactory(&dialog_params));
+ LoadDataWithBaseURL(shell(), kTestUrl, kBlankHtml, kTestUrl);
+ auto result = EvalJs(shell(),
+ "self.chooseFileSystemEntries({accepts: ["
+ " {description: 'no-extensions'},"
+ " {description: 'foo', extensions: ['txt', 'Js']},"
+ " {mimeTypes: ['image/jpeg']}"
+ "]})");
+ EXPECT_TRUE(result.error.find("AbortError") != std::string::npos)
+ << result.error;
+
+ ASSERT_TRUE(dialog_params.file_types);
+ EXPECT_TRUE(dialog_params.file_types->include_all_files);
+ ASSERT_EQ(2u, dialog_params.file_types->extensions.size());
+ ASSERT_EQ(2u, dialog_params.file_types->extensions[0].size());
+ EXPECT_EQ(FILE_PATH_LITERAL("Js"),
+ dialog_params.file_types->extensions[0][0]);
+ EXPECT_EQ(FILE_PATH_LITERAL("txt"),
+ dialog_params.file_types->extensions[0][1]);
+ EXPECT_TRUE(base::ContainsValue(dialog_params.file_types->extensions[1],
+ FILE_PATH_LITERAL("jpg")));
+ EXPECT_TRUE(base::ContainsValue(dialog_params.file_types->extensions[1],
+ FILE_PATH_LITERAL("jpeg")));
+
+ ASSERT_EQ(2u,
+ dialog_params.file_types->extension_description_overrides.size());
+ EXPECT_EQ(base::ASCIIToUTF16("foo"),
+ dialog_params.file_types->extension_description_overrides[0]);
+ EXPECT_EQ(base::ASCIIToUTF16(""),
+ dialog_params.file_types->extension_description_overrides[1]);
+}
+
+} // namespace content \ No newline at end of file
diff --git a/chromium/content/browser/fileapi/file_system_chooser_test_helpers.cc b/chromium/content/browser/fileapi/file_system_chooser_test_helpers.cc
new file mode 100644
index 00000000000..958f652817c
--- /dev/null
+++ b/chromium/content/browser/fileapi/file_system_chooser_test_helpers.cc
@@ -0,0 +1,126 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "file_system_chooser_test_helpers.h"
+
+namespace content {
+
+namespace {
+
+class CancellingSelectFileDialog : public ui::SelectFileDialog {
+ public:
+ CancellingSelectFileDialog(SelectFileDialogParams* out_params,
+ Listener* listener,
+ std::unique_ptr<ui::SelectFilePolicy> policy)
+ : ui::SelectFileDialog(listener, std::move(policy)),
+ out_params_(out_params) {}
+
+ protected:
+ void SelectFileImpl(Type type,
+ const base::string16& title,
+ const base::FilePath& default_path,
+ const FileTypeInfo* file_types,
+ int file_type_index,
+ const base::FilePath::StringType& default_extension,
+ gfx::NativeWindow owning_window,
+ void* params) override {
+ if (out_params_) {
+ out_params_->type = type;
+ if (file_types)
+ out_params_->file_types = *file_types;
+ else
+ out_params_->file_types = base::nullopt;
+ }
+ listener_->FileSelectionCanceled(params);
+ }
+
+ bool IsRunning(gfx::NativeWindow owning_window) const override {
+ return false;
+ }
+ void ListenerDestroyed() override {}
+ bool HasMultipleFileTypeChoicesImpl() override { return false; }
+
+ private:
+ ~CancellingSelectFileDialog() override = default;
+ SelectFileDialogParams* out_params_;
+};
+
+class FakeSelectFileDialog : public ui::SelectFileDialog {
+ public:
+ FakeSelectFileDialog(std::vector<base::FilePath> result,
+ SelectFileDialogParams* out_params,
+ Listener* listener,
+ std::unique_ptr<ui::SelectFilePolicy> policy)
+ : ui::SelectFileDialog(listener, std::move(policy)),
+ result_(std::move(result)),
+ out_params_(out_params) {}
+
+ protected:
+ void SelectFileImpl(Type type,
+ const base::string16& title,
+ const base::FilePath& default_path,
+ const FileTypeInfo* file_types,
+ int file_type_index,
+ const base::FilePath::StringType& default_extension,
+ gfx::NativeWindow owning_window,
+ void* params) override {
+ if (out_params_) {
+ out_params_->type = type;
+ if (file_types)
+ out_params_->file_types = *file_types;
+ else
+ out_params_->file_types = base::nullopt;
+ }
+ if (result_.size() == 1)
+ listener_->FileSelected(result_[0], 0, params);
+ else
+ listener_->MultiFilesSelected(result_, params);
+ }
+
+ bool IsRunning(gfx::NativeWindow owning_window) const override {
+ return false;
+ }
+ void ListenerDestroyed() override {}
+ bool HasMultipleFileTypeChoicesImpl() override { return false; }
+
+ private:
+ ~FakeSelectFileDialog() override = default;
+ std::vector<base::FilePath> result_;
+ SelectFileDialogParams* out_params_;
+};
+
+} // namespace
+
+SelectFileDialogParams::SelectFileDialogParams() = default;
+SelectFileDialogParams::~SelectFileDialogParams() = default;
+
+CancellingSelectFileDialogFactory::CancellingSelectFileDialogFactory(
+ SelectFileDialogParams* out_params)
+ : out_params_(out_params) {}
+
+CancellingSelectFileDialogFactory::~CancellingSelectFileDialogFactory() =
+ default;
+
+ui::SelectFileDialog* CancellingSelectFileDialogFactory::Create(
+ ui::SelectFileDialog::Listener* listener,
+ std::unique_ptr<ui::SelectFilePolicy> policy) {
+ return new CancellingSelectFileDialog(out_params_, listener,
+ std::move(policy));
+}
+
+FakeSelectFileDialogFactory::FakeSelectFileDialogFactory(
+ std::vector<base::FilePath> result,
+ SelectFileDialogParams* out_params)
+ : result_(std::move(result)), out_params_(out_params) {}
+
+FakeSelectFileDialogFactory::~FakeSelectFileDialogFactory() = default;
+
+ui::SelectFileDialog* FakeSelectFileDialogFactory::Create(
+ ui::SelectFileDialog::Listener* listener,
+ std::unique_ptr<ui::SelectFilePolicy> policy) {
+ return new FakeSelectFileDialog(result_, out_params_, listener,
+ std::move(policy));
+}
+
+} // namespace content \ No newline at end of file
diff --git a/chromium/content/browser/fileapi/file_system_chooser_test_helpers.h b/chromium/content/browser/fileapi/file_system_chooser_test_helpers.h
new file mode 100644
index 00000000000..a26fc2d71b7
--- /dev/null
+++ b/chromium/content/browser/fileapi/file_system_chooser_test_helpers.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_FILEAPI_FILE_SYSTEM_CHOOSER_TEST_HELPERS_H_
+#define CONTENT_BROWSER_FILEAPI_FILE_SYSTEM_CHOOSER_TEST_HELPERS_H_
+
+#include "base/optional.h"
+#include "ui/shell_dialogs/select_file_dialog.h"
+#include "ui/shell_dialogs/select_file_dialog_factory.h"
+#include "ui/shell_dialogs/select_file_policy.h"
+
+namespace content {
+
+// Struct used to report what parameters one of the (fake) SelectFileDialog
+// implementations below was created with.
+struct SelectFileDialogParams {
+ SelectFileDialogParams();
+ ~SelectFileDialogParams();
+
+ ui::SelectFileDialog::Type type = ui::SelectFileDialog::SELECT_NONE;
+ base::Optional<ui::SelectFileDialog::FileTypeInfo> file_types;
+};
+
+// A fake ui::SelectFileDialog, which will cancel the file selection instead of
+// selecting a file.
+class CancellingSelectFileDialogFactory : public ui::SelectFileDialogFactory {
+ public:
+ explicit CancellingSelectFileDialogFactory(
+ SelectFileDialogParams* out_params = nullptr);
+ ~CancellingSelectFileDialogFactory() override;
+
+ ui::SelectFileDialog* Create(
+ ui::SelectFileDialog::Listener* listener,
+ std::unique_ptr<ui::SelectFilePolicy> policy) override;
+
+ private:
+ SelectFileDialogParams* out_params_;
+};
+
+// A fake ui::SelectFileDialog, which will select one or more pre-determined
+// files.
+class FakeSelectFileDialogFactory : public ui::SelectFileDialogFactory {
+ public:
+ FakeSelectFileDialogFactory(std::vector<base::FilePath> result,
+ SelectFileDialogParams* out_params = nullptr);
+ ~FakeSelectFileDialogFactory() override;
+
+ ui::SelectFileDialog* Create(
+ ui::SelectFileDialog::Listener* listener,
+ std::unique_ptr<ui::SelectFilePolicy> policy) override;
+
+ private:
+ std::vector<base::FilePath> result_;
+ SelectFileDialogParams* out_params_;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_FILEAPI_FILE_SYSTEM_CHOOSER_TEST_HELPERS_H_ \ No newline at end of file
diff --git a/chromium/content/browser/fileapi/file_system_chooser_unittest.cc b/chromium/content/browser/fileapi/file_system_chooser_unittest.cc
new file mode 100644
index 00000000000..b95cb53404b
--- /dev/null
+++ b/chromium/content/browser/fileapi/file_system_chooser_unittest.cc
@@ -0,0 +1,168 @@
+// 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_chooser.h"
+
+#include "base/run_loop.h"
+#include "base/stl_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/test/bind_test_util.h"
+#include "base/threading/sequenced_task_runner_handle.h"
+#include "content/browser/fileapi/file_system_chooser_test_helpers.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/shell_dialogs/select_file_dialog.h"
+#include "ui/shell_dialogs/select_file_dialog_factory.h"
+#include "ui/shell_dialogs/select_file_policy.h"
+
+namespace content {
+
+class FileSystemChooserTest : public testing::Test {
+ public:
+ void TearDown() override { ui::SelectFileDialog::SetFactory(nullptr); }
+
+ void SyncShowDialog(
+ std::vector<blink::mojom::ChooseFileSystemEntryAcceptsOptionPtr> accepts,
+ bool include_accepts_all) {
+ base::RunLoop loop;
+ FileSystemChooser::CreateAndShow(
+ 0, 0, blink::mojom::ChooseFileSystemEntryType::kOpenFile,
+ std::move(accepts), include_accepts_all,
+ base::BindLambdaForTesting(
+ [&](base::File::Error,
+ std::vector<blink::mojom::FileSystemEntryPtr>) {
+ loop.Quit();
+ }),
+ base::SequencedTaskRunnerHandle::Get());
+ loop.Run();
+ }
+
+ private:
+ content::TestBrowserThreadBundle thread_bundle_;
+};
+
+TEST_F(FileSystemChooserTest, EmptyAccepts) {
+ SelectFileDialogParams dialog_params;
+ ui::SelectFileDialog::SetFactory(
+ new CancellingSelectFileDialogFactory(&dialog_params));
+ SyncShowDialog({}, /*include_accepts_all=*/true);
+
+ ASSERT_TRUE(dialog_params.file_types);
+ EXPECT_TRUE(dialog_params.file_types->include_all_files);
+ EXPECT_EQ(0u, dialog_params.file_types->extensions.size());
+ EXPECT_EQ(0u,
+ dialog_params.file_types->extension_description_overrides.size());
+}
+
+TEST_F(FileSystemChooserTest, EmptyAcceptsIgnoresIncludeAcceptsAll) {
+ SelectFileDialogParams dialog_params;
+ ui::SelectFileDialog::SetFactory(
+ new CancellingSelectFileDialogFactory(&dialog_params));
+ SyncShowDialog({}, /*include_accepts_all=*/false);
+
+ // Should still include_all_files, even though include_accepts_all was false.
+ ASSERT_TRUE(dialog_params.file_types);
+ EXPECT_TRUE(dialog_params.file_types->include_all_files);
+ EXPECT_EQ(0u, dialog_params.file_types->extensions.size());
+ EXPECT_EQ(0u,
+ dialog_params.file_types->extension_description_overrides.size());
+}
+
+TEST_F(FileSystemChooserTest, AcceptsMimeTypes) {
+ SelectFileDialogParams dialog_params;
+ ui::SelectFileDialog::SetFactory(
+ new CancellingSelectFileDialogFactory(&dialog_params));
+ std::vector<blink::mojom::ChooseFileSystemEntryAcceptsOptionPtr> accepts;
+ accepts.emplace_back(blink::mojom::ChooseFileSystemEntryAcceptsOption::New(
+ base::ASCIIToUTF16(""), std::vector<std::string>({"tExt/Plain"}),
+ std::vector<std::string>({})));
+ accepts.emplace_back(blink::mojom::ChooseFileSystemEntryAcceptsOption::New(
+ base::ASCIIToUTF16("Images"), std::vector<std::string>({"image/*"}),
+ std::vector<std::string>({})));
+ SyncShowDialog(std::move(accepts), /*include_accepts_all=*/true);
+
+ ASSERT_TRUE(dialog_params.file_types);
+ EXPECT_TRUE(dialog_params.file_types->include_all_files);
+ ASSERT_EQ(2u, dialog_params.file_types->extensions.size());
+
+ EXPECT_TRUE(base::ContainsValue(dialog_params.file_types->extensions[0],
+ FILE_PATH_LITERAL("text")));
+ EXPECT_TRUE(base::ContainsValue(dialog_params.file_types->extensions[0],
+ FILE_PATH_LITERAL("txt")));
+
+ EXPECT_TRUE(base::ContainsValue(dialog_params.file_types->extensions[1],
+ FILE_PATH_LITERAL("gif")));
+ EXPECT_TRUE(base::ContainsValue(dialog_params.file_types->extensions[1],
+ FILE_PATH_LITERAL("jpg")));
+ EXPECT_TRUE(base::ContainsValue(dialog_params.file_types->extensions[1],
+ FILE_PATH_LITERAL("jpeg")));
+ EXPECT_TRUE(base::ContainsValue(dialog_params.file_types->extensions[1],
+ FILE_PATH_LITERAL("png")));
+ EXPECT_TRUE(base::ContainsValue(dialog_params.file_types->extensions[1],
+ FILE_PATH_LITERAL("tiff")));
+
+ ASSERT_EQ(2u,
+ dialog_params.file_types->extension_description_overrides.size());
+ EXPECT_EQ(base::ASCIIToUTF16(""),
+ dialog_params.file_types->extension_description_overrides[0]);
+ EXPECT_EQ(base::ASCIIToUTF16("Images"),
+ dialog_params.file_types->extension_description_overrides[1]);
+}
+
+TEST_F(FileSystemChooserTest, AcceptsExtensions) {
+ SelectFileDialogParams dialog_params;
+ ui::SelectFileDialog::SetFactory(
+ new CancellingSelectFileDialogFactory(&dialog_params));
+ std::vector<blink::mojom::ChooseFileSystemEntryAcceptsOptionPtr> accepts;
+ accepts.emplace_back(blink::mojom::ChooseFileSystemEntryAcceptsOption::New(
+ base::ASCIIToUTF16(""), std::vector<std::string>({}),
+ std::vector<std::string>({"text", "js", "text"})));
+ SyncShowDialog(std::move(accepts), /*include_accepts_all=*/true);
+
+ ASSERT_TRUE(dialog_params.file_types);
+ EXPECT_TRUE(dialog_params.file_types->include_all_files);
+ ASSERT_EQ(1u, dialog_params.file_types->extensions.size());
+
+ EXPECT_EQ(2u, dialog_params.file_types->extensions[0].size());
+ EXPECT_TRUE(base::ContainsValue(dialog_params.file_types->extensions[0],
+ FILE_PATH_LITERAL("text")));
+ EXPECT_TRUE(base::ContainsValue(dialog_params.file_types->extensions[0],
+ FILE_PATH_LITERAL("js")));
+
+ ASSERT_EQ(1u,
+ dialog_params.file_types->extension_description_overrides.size());
+ EXPECT_EQ(base::ASCIIToUTF16(""),
+ dialog_params.file_types->extension_description_overrides[0]);
+}
+
+TEST_F(FileSystemChooserTest, AcceptsExtensionsAndMimeTypes) {
+ SelectFileDialogParams dialog_params;
+ ui::SelectFileDialog::SetFactory(
+ new CancellingSelectFileDialogFactory(&dialog_params));
+ std::vector<blink::mojom::ChooseFileSystemEntryAcceptsOptionPtr> accepts;
+ accepts.emplace_back(blink::mojom::ChooseFileSystemEntryAcceptsOption::New(
+ base::ASCIIToUTF16(""), std::vector<std::string>({"image/*"}),
+ std::vector<std::string>({"text", "jpg"})));
+ SyncShowDialog(std::move(accepts), /*include_accepts_all=*/false);
+
+ ASSERT_TRUE(dialog_params.file_types);
+ EXPECT_FALSE(dialog_params.file_types->include_all_files);
+ ASSERT_EQ(1u, dialog_params.file_types->extensions.size());
+
+ EXPECT_TRUE(base::ContainsValue(dialog_params.file_types->extensions[0],
+ FILE_PATH_LITERAL("text")));
+ EXPECT_TRUE(base::ContainsValue(dialog_params.file_types->extensions[0],
+ FILE_PATH_LITERAL("gif")));
+ EXPECT_TRUE(base::ContainsValue(dialog_params.file_types->extensions[0],
+ FILE_PATH_LITERAL("jpeg")));
+ EXPECT_EQ(1, base::STLCount(dialog_params.file_types->extensions[0],
+ FILE_PATH_LITERAL("jpg")));
+
+ ASSERT_EQ(1u,
+ dialog_params.file_types->extension_description_overrides.size());
+ EXPECT_EQ(base::ASCIIToUTF16(""),
+ dialog_params.file_types->extension_description_overrides[0]);
+}
+
+} // namespace content \ No newline at end of file
diff --git a/chromium/content/browser/fileapi/file_system_manager_impl.cc b/chromium/content/browser/fileapi/file_system_manager_impl.cc
index e8b7272c921..c11ea6c1905 100644
--- a/chromium/content/browser/fileapi/file_system_manager_impl.cc
+++ b/chromium/content/browser/fileapi/file_system_manager_impl.cc
@@ -16,6 +16,7 @@
#include "base/metrics/user_metrics.h"
#include "base/sequenced_task_runner.h"
#include "base/strings/string_util.h"
+#include "base/task/post_task.h"
#include "base/threading/thread.h"
#include "base/time/time.h"
#include "build/build_config.h"
@@ -26,6 +27,7 @@
#include "content/browser/fileapi/browser_file_system_helper.h"
#include "content/browser/fileapi/file_system_chooser.h"
#include "content/common/fileapi/webblob_messages.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "ipc/ipc_platform_file.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
@@ -121,9 +123,11 @@ struct FileSystemManagerImpl::ReadDirectorySyncCallbackEntry {
FileSystemManagerImpl::FileSystemManagerImpl(
int process_id,
+ int frame_id,
storage::FileSystemContext* file_system_context,
scoped_refptr<ChromeBlobStorageContext> blob_storage_context)
: process_id_(process_id),
+ frame_id_(frame_id),
context_(file_system_context),
security_policy_(ChildProcessSecurityPolicyImpl::GetInstance()),
blob_storage_context_(blob_storage_context),
@@ -588,19 +592,23 @@ void FileSystemManagerImpl::CreateWriter(const GURL& file_path,
std::move(callback).Run(base::File::FILE_OK, std::move(writer));
}
-void FileSystemManagerImpl::ChooseEntry(int32_t render_frame_id,
- ChooseEntryCallback callback) {
+void FileSystemManagerImpl::ChooseEntry(
+ blink::mojom::ChooseFileSystemEntryType type,
+ std::vector<blink::mojom::ChooseFileSystemEntryAcceptsOptionPtr> accepts,
+ bool include_accepts_all,
+ ChooseEntryCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (!base::FeatureList::IsEnabled(blink::features::kWritableFilesAPI)) {
bindings_.ReportBadMessage("FSMI_WRITABLE_FILES_DISABLED");
return;
}
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::BindOnce(&FileSystemChooser::CreateAndShow, process_id_,
- render_frame_id, std::move(callback),
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)));
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(
+ &FileSystemChooser::CreateAndShow, process_id_, frame_id_, type,
+ std::move(accepts), include_accepts_all, std::move(callback),
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO})));
}
void FileSystemManagerImpl::Cancel(
@@ -741,8 +749,11 @@ void FileSystemManagerImpl::DidResolveURL(
type == storage::FileSystemContext::RESOLVED_ENTRY_NOT_FOUND)
result = base::File::FILE_ERROR_NOT_FOUND;
+ base::FilePath normalized_path(
+ storage::VirtualPath::GetNormalizedFilePath(file_path));
std::move(callback).Run(
- mojo::ConvertTo<blink::mojom::FileSystemInfoPtr>(info), file_path,
+ mojo::ConvertTo<blink::mojom::FileSystemInfoPtr>(info),
+ std::move(normalized_path),
type == storage::FileSystemContext::RESOLVED_ENTRY_DIRECTORY, result);
// For ResolveURL we do not create a new operation, so no unregister here.
}
@@ -818,8 +829,8 @@ void FileSystemManagerImpl::GetPlatformPathOnFileThread(
GetPlatformPathCallback callback) {
base::FilePath platform_path;
SyncGetPlatformPath(context, process_id, path, &platform_path);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&FileSystemManagerImpl::DidGetPlatformPath,
file_system_manager, std::move(callback), platform_path));
}
diff --git a/chromium/content/browser/fileapi/file_system_manager_impl.h b/chromium/content/browser/fileapi/file_system_manager_impl.h
index f5e4cbf7f4c..fa0fd86b63a 100644
--- a/chromium/content/browser/fileapi/file_system_manager_impl.h
+++ b/chromium/content/browser/fileapi/file_system_manager_impl.h
@@ -57,9 +57,12 @@ class ChromeBlobStorageContext;
class CONTENT_EXPORT FileSystemManagerImpl
: public blink::mojom::FileSystemManager {
public:
- // Used by the renderer process host on the UI thread.
+ // Constructed and held by the render frame host and render process host on
+ // the UI thread. Used by render frames (via the render frame host), workers
+ // and pepper (via the render process host).
FileSystemManagerImpl(
int process_id,
+ int frame_id,
storage::FileSystemContext* file_system_context,
scoped_refptr<ChromeBlobStorageContext> blob_storage_context);
~FileSystemManagerImpl() override;
@@ -122,8 +125,11 @@ class CONTENT_EXPORT FileSystemManagerImpl
GetPlatformPathCallback callback) override;
void CreateWriter(const GURL& file_path,
CreateWriterCallback callback) override;
- void ChooseEntry(int32_t render_frame_id,
- ChooseEntryCallback callback) override;
+ void ChooseEntry(
+ blink::mojom::ChooseFileSystemEntryType type,
+ std::vector<blink::mojom::ChooseFileSystemEntryAcceptsOptionPtr> accepts,
+ bool include_accepts_all,
+ ChooseEntryCallback callback) override;
private:
class FileSystemCancellableOperationImpl;
@@ -206,6 +212,7 @@ class CONTENT_EXPORT FileSystemManagerImpl
void OnConnectionErrorForOpListeners(OperationListenerID listener_id);
const int process_id_;
+ const int frame_id_;
storage::FileSystemContext* const context_;
ChildProcessSecurityPolicyImpl* const security_policy_;
const scoped_refptr<ChromeBlobStorageContext> blob_storage_context_;
diff --git a/chromium/content/browser/fileapi/file_system_url_loader_factory.cc b/chromium/content/browser/fileapi/file_system_url_loader_factory.cc
index 3e55c0fa785..4357a05be56 100644
--- a/chromium/content/browser/fileapi/file_system_url_loader_factory.cc
+++ b/chromium/content/browser/fileapi/file_system_url_loader_factory.cc
@@ -20,6 +20,7 @@
#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_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
@@ -473,7 +474,8 @@ class FileSystemFileURLLoader : public FileSystemEntryURLLoader {
data_producer_ = std::make_unique<mojo::StringDataPipeProducer>(
std::move(pipe.producer_handle));
- file_data_ = new net::IOBuffer(kDefaultFileSystemUrlPipeSize);
+ file_data_ =
+ base::MakeRefCounted<net::IOBuffer>(kDefaultFileSystemUrlPipeSize);
ReadMoreFileData();
}
@@ -638,7 +640,7 @@ CreateFileSystemURLLoaderFactory(
return std::make_unique<FileSystemURLLoaderFactory>(
std::move(params),
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO));
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO}));
}
} // namespace content
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
index 980fddbef0f..548f4532a64 100644
--- a/chromium/content/browser/fileapi/file_system_url_loader_factory_browsertest.cc
+++ b/chromium/content/browser/fileapi/file_system_url_loader_factory_browsertest.cc
@@ -12,10 +12,12 @@
#include "base/files/scoped_temp_dir.h"
#include "base/i18n/unicodestring.h"
#include "base/rand_util.h"
+#include "base/task/post_task.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/browser/browser_task_traits.h"
#include "content/public/test/content_browser_test.h"
#include "content/shell/browser/shell.h"
#include "net/base/mime_util.h"
@@ -181,8 +183,8 @@ class FileSystemURLLoaderFactoryTest : public ContentBrowserTest {
void TearDownOnMainThread() override {
loader_.reset();
- content::BrowserThread::PostTask(
- content::BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {content::BrowserThread::IO},
base::BindOnce(&ShutdownFileSystemContextOnIOThread,
std::move(file_system_context_)));
special_storage_policy_ = nullptr;
diff --git a/chromium/content/browser/find_request_manager.cc b/chromium/content/browser/find_request_manager.cc
index 9ae22e14473..e650a39d96a 100644
--- a/chromium/content/browser/find_request_manager.cc
+++ b/chromium/content/browser/find_request_manager.cc
@@ -12,7 +12,6 @@
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/frame_messages.h"
#include "content/public/browser/guest_mode.h"
-#include "third_party/blink/public/mojom/frame/find_in_page.mojom.h"
namespace content {
@@ -215,6 +214,29 @@ class FindRequestManager::FrameObserver : public WebContentsObserver {
DISALLOW_COPY_AND_ASSIGN(FrameObserver);
};
+FindRequestManager::FindRequest::FindRequest() {}
+
+FindRequestManager::FindRequest::FindRequest(
+ int id,
+ const base::string16& search_text,
+ blink::mojom::FindOptionsPtr options)
+ : id(id), search_text(search_text), options(std::move(options)) {}
+
+FindRequestManager::FindRequest::FindRequest(const FindRequest& request)
+ : id(request.id),
+ search_text(request.search_text),
+ options(request.options.Clone()) {}
+
+FindRequestManager::FindRequest::~FindRequest() {}
+
+FindRequestManager::FindRequest& FindRequestManager::FindRequest::operator=(
+ const FindRequest& request) {
+ id = request.id;
+ search_text = request.search_text;
+ options = request.options.Clone();
+ return *this;
+}
+
#if defined(OS_ANDROID)
FindRequestManager::ActivateNearestFindResultState::
ActivateNearestFindResultState() = default;
@@ -252,7 +274,7 @@ FindRequestManager::~FindRequestManager() {}
void FindRequestManager::Find(int request_id,
const base::string16& search_text,
- const blink::WebFindOptions& options) {
+ blink::mojom::FindOptionsPtr options) {
// Every find request must have a unique ID, and these IDs must strictly
// increase so that newer requests always have greater IDs than older
// requests.
@@ -260,10 +282,10 @@ void FindRequestManager::Find(int request_id,
DCHECK_GT(request_id, current_session_id_);
// If this is a new find session, clear any queued requests from last session.
- if (!options.find_next)
+ if (!options->find_next)
find_request_queue_ = base::queue<FindRequest>();
- find_request_queue_.emplace(request_id, search_text, options);
+ find_request_queue_.emplace(request_id, search_text, std::move(options));
if (find_request_queue_.size() == 1)
FindInternal(find_request_queue_.front());
}
@@ -306,7 +328,7 @@ void FindRequestManager::HandleFinalUpdateForFrame(RenderFrameHostImpl* rfh,
// This is the final update for all frames for the current find operation.
if (request_id == current_request_.id && request_id != current_session_id_) {
- DCHECK(current_request_.options.find_next);
+ DCHECK(current_request_.options->find_next);
DCHECK_EQ(pending_find_next_reply_, rfh);
pending_find_next_reply_ = nullptr;
}
@@ -546,7 +568,7 @@ void FindRequestManager::FindInternal(const FindRequest& request) {
DCHECK_GT(request.id, current_request_.id);
DCHECK_GT(request.id, current_session_id_);
- if (request.options.find_next) {
+ if (request.options->find_next) {
// This is a find next operation.
// This implies that there is an ongoing find session with the same search
@@ -559,7 +581,7 @@ void FindRequestManager::FindInternal(const FindRequest& request) {
RenderFrameHost* target_rfh =
contents_->GetFocusedWebContents()->GetFocusedFrame();
if (!target_rfh || !CheckFrame(target_rfh))
- target_rfh = GetInitialFrame(request.options.forward);
+ target_rfh = GetInitialFrame(request.options->forward);
SendFindRequest(request, target_rfh);
current_request_ = request;
@@ -593,20 +615,14 @@ void FindRequestManager::SendFindRequest(const FindRequest& request,
DCHECK(CheckFrame(rfh));
DCHECK(rfh->IsRenderFrameLive());
- if (request.options.find_next)
+ if (request.options->find_next)
pending_find_next_reply_ = rfh;
else
pending_initial_replies_.insert(rfh);
- blink::mojom::FindOptionsPtr options(blink::mojom::FindOptions::New());
- options->forward = request.options.forward;
- options->match_case = request.options.match_case;
- options->find_next = request.options.find_next;
- options->force = request.options.force;
- options->run_synchronously_for_testing =
- request.options.run_synchronously_for_testing;
static_cast<RenderFrameHostImpl*>(rfh)->GetFindInPage()->Find(
- request.id, base::UTF16ToUTF8(request.search_text), std::move(options));
+ request.id, base::UTF16ToUTF8(request.search_text),
+ request.options.Clone());
}
void FindRequestManager::NotifyFindReply(int request_id, bool final_update) {
@@ -674,8 +690,8 @@ void FindRequestManager::AddFrame(RenderFrameHost* rfh, bool force) {
FindRequest request = current_request_;
request.id = current_session_id_;
- request.options.find_next = false;
- request.options.force = force;
+ request.options->find_next = false;
+ request.options->force = force;
SendFindRequest(request, rfh);
}
@@ -722,40 +738,42 @@ void FindRequestManager::FinalUpdateReceived(int request_id,
// request must be sent.
RenderFrameHost* target_rfh;
- if (request_id == current_request_.id && current_request_.options.find_next) {
+ if (request_id == current_request_.id &&
+ current_request_.options->find_next) {
// If this was a find next operation, then the active match will be in the
// next frame with matches after this one.
- target_rfh = Traverse(rfh,
- current_request_.options.forward,
- true /* matches_only */,
- true /* wrap */);
+ target_rfh = Traverse(rfh, current_request_.options->forward,
+ true /* matches_only */, true /* wrap */);
} else if ((target_rfh =
contents_->GetFocusedWebContents()->GetFocusedFrame()) !=
nullptr) {
// Otherwise, if there is a focused frame, then the active match will be in
// the next frame with matches after that one.
- target_rfh = Traverse(target_rfh,
- current_request_.options.forward,
- true /* matches_only */,
- true /* wrap */);
+ target_rfh = Traverse(target_rfh, current_request_.options->forward,
+ true /* matches_only */, true /* wrap */);
} else {
// Otherwise, the first frame with matches will have the active match.
- target_rfh = GetInitialFrame(current_request_.options.forward);
+ target_rfh = GetInitialFrame(current_request_.options->forward);
if (!CheckFrame(target_rfh) ||
!find_in_page_clients_[target_rfh]->number_of_matches()) {
- target_rfh = Traverse(target_rfh,
- current_request_.options.forward,
- true /* matches_only */,
- false /* wrap */);
+ target_rfh = Traverse(target_rfh, current_request_.options->forward,
+ true /* matches_only */, false /* wrap */);
}
}
- DCHECK(target_rfh);
+ if (!target_rfh) {
+ // Sometimes when the WebContents is deleted/navigated, we got into this
+ // situation. We don't care about this WebContents anyways so it's ok to
+ // just not ask for the active match and return immediately.
+ // TODO(rakina): Understand what leads to this situation.
+ // See: https://crbug.com/884679.
+ return;
+ }
// Forward the find reply without |final_update| set because the active match
// has not yet been found.
NotifyFindReply(request_id, false /* final_update */);
- current_request_.options.find_next = true;
+ current_request_.options->find_next = true;
SendFindRequest(current_request_, target_rfh);
}
diff --git a/chromium/content/browser/find_request_manager.h b/chromium/content/browser/find_request_manager.h
index 62050f4611a..1031dfe915c 100644
--- a/chromium/content/browser/find_request_manager.h
+++ b/chromium/content/browser/find_request_manager.h
@@ -14,7 +14,7 @@
#include "content/common/content_export.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/stop_find_action.h"
-#include "third_party/blink/public/web/web_find_options.h"
+#include "third_party/blink/public/mojom/frame/find_in_page.mojom.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/rect_f.h"
@@ -40,7 +40,7 @@ class CONTENT_EXPORT FindRequestManager {
// |options|. |request_id| uniquely identifies the find request.
void Find(int request_id,
const base::string16& search_text,
- const blink::WebFindOptions& options);
+ blink::mojom::FindOptionsPtr options);
// Stops the active find session and clears the general highlighting of the
// matches. |action| determines whether the last active match (if any) will be
@@ -116,13 +116,16 @@ class CONTENT_EXPORT FindRequestManager {
base::string16 search_text;
// The set of find options in effect for this find request.
- blink::WebFindOptions options;
+ blink::mojom::FindOptionsPtr options;
- FindRequest() = default;
+ FindRequest();
FindRequest(int id,
const base::string16& search_text,
- const blink::WebFindOptions& options)
- : id(id), search_text(search_text), options(options) {}
+ blink::mojom::FindOptionsPtr options);
+ FindRequest(const FindRequest& request);
+ ~FindRequest();
+
+ FindRequest& operator=(const FindRequest& request);
};
// Resets all of the per-session state for a new find-in-page session.
diff --git a/chromium/content/browser/find_request_manager_browsertest.cc b/chromium/content/browser/find_request_manager_browsertest.cc
index 0217e5ac7d0..e8c0f18a412 100644
--- a/chromium/content/browser/find_request_manager_browsertest.cc
+++ b/chromium/content/browser/find_request_manager_browsertest.cc
@@ -17,7 +17,6 @@
#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test_utils_internal.h"
#include "net/dns/mock_host_resolver.h"
-#include "third_party/blink/public/web/web_find_options.h"
namespace content {
@@ -86,11 +85,10 @@ class FindRequestManagerTest : public ContentBrowserTest,
}
void Find(const std::string& search_text,
- const blink::WebFindOptions& options) {
+ blink::mojom::FindOptionsPtr options) {
delegate()->UpdateLastRequest(++last_request_id_);
- contents()->Find(last_request_id_,
- base::UTF8ToUTF16(search_text),
- options);
+ contents()->Find(last_request_id_, base::UTF8ToUTF16(search_text),
+ std::move(options));
}
WebContentsImpl* contents() const {
@@ -167,9 +165,9 @@ IN_PROC_BROWSER_TEST_P(FindRequestManagerTest, MAYBE(Basic)) {
if (GetParam())
MakeChildFrameCrossProcess();
- blink::WebFindOptions options;
- options.run_synchronously_for_testing = true;
- Find("result", options);
+ auto options = blink::mojom::FindOptions::New();
+ options->run_synchronously_for_testing = true;
+ Find("result", options->Clone());
delegate()->WaitForFinalReply();
FindResults results = delegate()->GetFindResults();
@@ -177,9 +175,9 @@ IN_PROC_BROWSER_TEST_P(FindRequestManagerTest, MAYBE(Basic)) {
EXPECT_EQ(19, results.number_of_matches);
EXPECT_EQ(1, results.active_match_ordinal);
- options.find_next = true;
+ options->find_next = true;
for (int i = 2; i <= 10; ++i) {
- Find("result", options);
+ Find("result", options->Clone());
delegate()->WaitForFinalReply();
results = delegate()->GetFindResults();
@@ -188,9 +186,9 @@ IN_PROC_BROWSER_TEST_P(FindRequestManagerTest, MAYBE(Basic)) {
EXPECT_EQ(i, results.active_match_ordinal);
}
- options.forward = false;
+ options->forward = false;
for (int i = 9; i >= 5; --i) {
- Find("result", options);
+ Find("result", options->Clone());
delegate()->WaitForFinalReply();
results = delegate()->GetFindResults();
@@ -251,9 +249,9 @@ IN_PROC_BROWSER_TEST_P(FindRequestManagerTest, ScrollAndZoomIntoView) {
ASSERT_TRUE(ExecuteScript(root, "window.scrollTo(3500, 1500);"));
// Search for a result further down in the iframe.
- blink::WebFindOptions options;
- options.run_synchronously_for_testing = true;
- Find("result 17", options);
+ auto options = blink::mojom::FindOptions::New();
+ options->run_synchronously_for_testing = true;
+ Find("result 17", options->Clone());
delegate()->WaitForFinalReply();
// gBCR of result box in iframe.
@@ -313,14 +311,14 @@ IN_PROC_BROWSER_TEST_P(FindRequestManagerTest, MAYBE(CharacterByCharacter)) {
if (GetParam())
MakeChildFrameCrossProcess();
- blink::WebFindOptions default_options;
- default_options.run_synchronously_for_testing = true;
- Find("r", default_options);
- Find("re", default_options);
- Find("res", default_options);
- Find("resu", default_options);
- Find("resul", default_options);
- Find("result", default_options);
+ auto default_options = blink::mojom::FindOptions::New();
+ default_options->run_synchronously_for_testing = true;
+ Find("r", default_options->Clone());
+ Find("re", default_options->Clone());
+ Find("res", default_options->Clone());
+ Find("resu", default_options->Clone());
+ Find("resul", default_options->Clone());
+ Find("result", default_options->Clone());
delegate()->WaitForFinalReply();
FindResults results = delegate()->GetFindResults();
@@ -338,13 +336,13 @@ IN_PROC_BROWSER_TEST_P(FindRequestManagerTest, DISABLED_RapidFire) {
if (GetParam())
MakeChildFrameCrossProcess();
- blink::WebFindOptions options;
- options.run_synchronously_for_testing = true;
- Find("result", options);
+ auto options = blink::mojom::FindOptions::New();
+ options->run_synchronously_for_testing = true;
+ Find("result", options.Clone());
- options.find_next = true;
+ options->find_next = true;
for (int i = 2; i <= 1000; ++i)
- Find("result", options);
+ Find("result", options.Clone());
delegate()->WaitForFinalReply();
FindResults results = delegate()->GetFindResults();
@@ -359,17 +357,17 @@ IN_PROC_BROWSER_TEST_P(FindRequestManagerTest, DISABLED_RapidFire) {
IN_PROC_BROWSER_TEST_P(FindRequestManagerTest, DISABLED_RemoveFrame) {
LoadMultiFramePage(2 /* height */, GetParam() /* cross_process */);
- blink::WebFindOptions options;
- options.run_synchronously_for_testing = true;
- Find("result", options);
+ auto options = blink::mojom::FindOptions::New();
+ options->run_synchronously_for_testing = true;
+ Find("result", options->Clone());
delegate()->WaitForFinalReply();
- options.find_next = true;
- options.forward = false;
- Find("result", options);
- Find("result", options);
- Find("result", options);
- Find("result", options);
- Find("result", options);
+ options->find_next = true;
+ options->forward = false;
+ Find("result", options->Clone());
+ Find("result", options->Clone());
+ Find("result", options->Clone());
+ Find("result", options->Clone());
+ Find("result", options->Clone());
delegate()->WaitForFinalReply();
FindResults results = delegate()->GetFindResults();
@@ -379,7 +377,7 @@ IN_PROC_BROWSER_TEST_P(FindRequestManagerTest, DISABLED_RemoveFrame) {
// Remove a frame.
FrameTreeNode* root = contents()->GetFrameTree()->root();
- root->RemoveChild(root->child_at(0));
+ root->current_frame_host()->RemoveChild(root->child_at(0));
// The number of matches and active match ordinal should update automatically
// to exclude the matches from the removed frame.
@@ -393,14 +391,14 @@ IN_PROC_BROWSER_TEST_P(FindRequestManagerTest, DISABLED_RemoveFrame) {
IN_PROC_BROWSER_TEST_P(FindRequestManagerTest, DISABLED_AddFrame) {
LoadMultiFramePage(2 /* height */, GetParam() /* cross_process */);
- blink::WebFindOptions options;
- options.run_synchronously_for_testing = true;
- Find("result", options);
- options.find_next = true;
- Find("result", options);
- Find("result", options);
- Find("result", options);
- Find("result", options);
+ auto options = blink::mojom::FindOptions::New();
+ options->run_synchronously_for_testing = true;
+ Find("result", options.Clone());
+ options->find_next = true;
+ Find("result", options.Clone());
+ Find("result", options.Clone());
+ Find("result", options.Clone());
+ Find("result", options.Clone());
delegate()->WaitForFinalReply();
FindResults results = delegate()->GetFindResults();
@@ -433,9 +431,9 @@ IN_PROC_BROWSER_TEST_F(FindRequestManagerTest, MAYBE(AddFrameAfterNoMatches)) {
NavigateToURL(shell(), GURL("about:blank"));
EXPECT_TRUE(navigation_observer.last_navigation_succeeded());
- blink::WebFindOptions default_options;
- default_options.run_synchronously_for_testing = true;
- Find("result", default_options);
+ auto default_options = blink::mojom::FindOptions::New();
+ default_options->run_synchronously_for_testing = true;
+ Find("result", default_options.Clone());
delegate()->WaitForFinalReply();
// Initially, there are no matches on the page.
@@ -466,14 +464,14 @@ IN_PROC_BROWSER_TEST_F(FindRequestManagerTest, MAYBE(AddFrameAfterNoMatches)) {
IN_PROC_BROWSER_TEST_P(FindRequestManagerTest, MAYBE(NavigateFrame)) {
LoadMultiFramePage(2 /* height */, GetParam() /* cross_process */);
- blink::WebFindOptions options;
- options.run_synchronously_for_testing = true;
- Find("result", options);
- options.find_next = true;
- options.forward = false;
- Find("result", options);
- Find("result", options);
- Find("result", options);
+ auto options = blink::mojom::FindOptions::New();
+ options->run_synchronously_for_testing = true;
+ Find("result", options.Clone());
+ options->find_next = true;
+ options->forward = false;
+ Find("result", options.Clone());
+ Find("result", options.Clone());
+ Find("result", options.Clone());
delegate()->WaitForFinalReply();
FindResults results = delegate()->GetFindResults();
@@ -515,9 +513,9 @@ IN_PROC_BROWSER_TEST_P(FindRequestManagerTest, MAYBE(NavigateFrame)) {
IN_PROC_BROWSER_TEST_F(FindRequestManagerTest, MAYBE(HiddenFrame)) {
LoadAndWait("/find_in_hidden_frame.html");
- blink::WebFindOptions default_options;
- default_options.run_synchronously_for_testing = true;
- Find("hello", default_options);
+ auto default_options = blink::mojom::FindOptions::New();
+ default_options->run_synchronously_for_testing = true;
+ Find("hello", default_options.Clone());
delegate()->WaitForFinalReply();
FindResults results = delegate()->GetFindResults();
@@ -530,12 +528,12 @@ IN_PROC_BROWSER_TEST_F(FindRequestManagerTest, MAYBE(HiddenFrame)) {
IN_PROC_BROWSER_TEST_P(FindRequestManagerTest, MAYBE(FindNewMatches)) {
LoadAndWait("/find_in_dynamic_page.html");
- blink::WebFindOptions options;
- options.run_synchronously_for_testing = true;
- Find("result", options);
- options.find_next = true;
- Find("result", options);
- Find("result", options);
+ auto options = blink::mojom::FindOptions::New();
+ options->run_synchronously_for_testing = true;
+ Find("result", options.Clone());
+ options->find_next = true;
+ Find("result", options.Clone());
+ Find("result", options.Clone());
delegate()->WaitForFinalReply();
FindResults results = delegate()->GetFindResults();
@@ -547,7 +545,7 @@ IN_PROC_BROWSER_TEST_P(FindRequestManagerTest, MAYBE(FindNewMatches)) {
// "result".
ASSERT_TRUE(ExecuteScript(contents()->GetMainFrame(), "addNewText()"));
- Find("result", options);
+ Find("result", options.Clone());
delegate()->WaitForFinalReply();
results = delegate()->GetFindResults();
@@ -568,9 +566,9 @@ IN_PROC_BROWSER_TEST_P(FindRequestManagerTest, MAYBE(FindNewMatches)) {
IN_PROC_BROWSER_TEST_F(FindRequestManagerTest, MAYBE_FindInPage_Issue627799) {
LoadAndWait("/find_in_long_page.html");
- blink::WebFindOptions options;
- options.run_synchronously_for_testing = true;
- Find("42", options);
+ auto options = blink::mojom::FindOptions::New();
+ options->run_synchronously_for_testing = true;
+ Find("42", options.Clone());
delegate()->WaitForFinalReply();
FindResults results = delegate()->GetFindResults();
@@ -579,9 +577,9 @@ IN_PROC_BROWSER_TEST_F(FindRequestManagerTest, MAYBE_FindInPage_Issue627799) {
EXPECT_EQ(1, results.active_match_ordinal);
delegate()->StartReplyRecord();
- options.find_next = true;
- options.forward = false;
- Find("42", options);
+ options->find_next = true;
+ options->forward = false;
+ Find("42", options.Clone());
delegate()->WaitForFinalReply();
// This is the crux of the issue that this test guards against. Searching
@@ -600,9 +598,9 @@ IN_PROC_BROWSER_TEST_F(FindRequestManagerTest, MAYBE(FindInPage_Issue644448)) {
NavigateToURL(shell(), GURL("about:blank"));
EXPECT_TRUE(navigation_observer.last_navigation_succeeded());
- blink::WebFindOptions default_options;
- default_options.run_synchronously_for_testing = true;
- Find("result", default_options);
+ auto default_options = blink::mojom::FindOptions::New();
+ default_options->run_synchronously_for_testing = true;
+ Find("result", default_options.Clone());
delegate()->WaitForFinalReply();
// Initially, there are no matches on the page.
@@ -614,7 +612,7 @@ IN_PROC_BROWSER_TEST_F(FindRequestManagerTest, MAYBE(FindInPage_Issue644448)) {
// Load a page with matches.
LoadAndWait("/find_in_simple_page.html");
- Find("result", default_options);
+ Find("result", default_options.Clone());
delegate()->WaitForFinalReply();
// There should now be matches found. When the bug was present, there were
@@ -629,9 +627,9 @@ IN_PROC_BROWSER_TEST_F(FindRequestManagerTest, MAYBE(FindInPage_Issue644448)) {
IN_PROC_BROWSER_TEST_F(FindRequestManagerTest, MAYBE(FindMatchRects)) {
LoadAndWait("/find_in_page.html");
- blink::WebFindOptions default_options;
- default_options.run_synchronously_for_testing = true;
- Find("result", default_options);
+ auto default_options = blink::mojom::FindOptions::New();
+ default_options->run_synchronously_for_testing = true;
+ Find("result", default_options.Clone());
delegate()->WaitForFinalReply();
EXPECT_EQ(19, delegate()->GetFindResults().number_of_matches);
@@ -712,9 +710,9 @@ IN_PROC_BROWSER_TEST_F(FindRequestManagerTest,
MAYBE(ActivateNearestFindMatch)) {
LoadAndWait("/find_in_page.html");
- blink::WebFindOptions default_options;
- default_options.run_synchronously_for_testing = true;
- Find("result", default_options);
+ auto default_options = blink::mojom::FindOptions::New();
+ default_options->run_synchronously_for_testing = true;
+ Find("result", default_options.Clone());
delegate()->WaitForFinalReply();
EXPECT_EQ(19, delegate()->GetFindResults().number_of_matches);
diff --git a/chromium/content/browser/font_unique_name_lookup/font_unique_name_browsertest.cc b/chromium/content/browser/font_unique_name_lookup/font_unique_name_browsertest.cc
index 4708110a0f7..8e370e5dbab 100644
--- a/chromium/content/browser/font_unique_name_lookup/font_unique_name_browsertest.cc
+++ b/chromium/content/browser/font_unique_name_lookup/font_unique_name_browsertest.cc
@@ -16,6 +16,7 @@
namespace content {
namespace {
+#if defined(OS_ANDROID)
const char* kExpectedFontFamilyNames[] = {"AndroidClock",
"Roboto",
"Droid Sans Mono",
@@ -59,6 +60,45 @@ const char* kExpectedFontFamilyNames[] = {"AndroidClock",
"Roboto Condensed",
"Roboto Condensed",
"Roboto"};
+#elif defined(OS_LINUX)
+const char* kExpectedFontFamilyNames[] = {"Ahem",
+ "Arimo",
+ "Arimo",
+ "Arimo",
+ "Arimo",
+ "Cousine",
+ "Cousine",
+ "Cousine",
+ "Cousine",
+ "DejaVu Sans",
+ "DejaVu Sans",
+ "Garuda",
+ "Gelasio",
+ "Gelasio",
+ "Gelasio",
+ "Gelasio",
+ "Lohit Devanagari",
+ "Lohit Gurmukhi",
+ "Lohit Tamil",
+ "Noto Sans Khmer",
+ "Tinos",
+ "Tinos",
+ "Tinos",
+ "Tinos",
+ "Mukti Narrow",
+ "Tinos"};
+#elif defined(OS_MACOSX)
+const char* kExpectedFontFamilyNames[] = {"American Typewriter",
+ "Arial Narrow",
+ "Baskerville",
+ "Devanagari MT",
+ "DIN Alternate",
+ "Gill Sans",
+ "Iowan Old Style",
+ "Malayalam Sangam MN",
+ "Hiragino Maru Gothic Pro",
+ "Hiragino Kaku Gothic StdN"};
+#endif
} // namespace
@@ -80,13 +120,9 @@ class FontUniqueNameBrowserTest : public DevToolsProtocolTest {
base::test::ScopedFeatureList feature_list_;
};
-#if defined(OS_ANDROID)
-#define MAYBE_ContentLocalFontsMatching ContentLocalFontsMatching
-#else
-#define MAYBE_ContentLocalFontsMatching DISABLED_ContentLocalFontsMatching
-#endif
-IN_PROC_BROWSER_TEST_F(FontUniqueNameBrowserTest,
- MAYBE_ContentLocalFontsMatching) {
+// TODO(drott): Enable this on all platforms.
+#if defined(OS_ANDROID) || defined(OS_LINUX) || defined(OS_MACOSX)
+IN_PROC_BROWSER_TEST_F(FontUniqueNameBrowserTest, ContentLocalFontsMatching) {
LoadAndWait("/font_src_local_matching.html");
Attach();
@@ -125,16 +161,22 @@ IN_PROC_BROWSER_TEST_F(FontUniqueNameBrowserTest,
params->SetInteger("nodeId", nodeId.GetInt());
base::Value* font_info =
SendCommand("CSS.getPlatformFontsForNode", std::move(params));
+ ASSERT_TRUE(font_info);
ASSERT_TRUE(font_info->is_dict());
base::Value* font_list = font_info->FindKey("fonts");
+ ASSERT_TRUE(font_list);
ASSERT_TRUE(font_list->is_list());
- base::Value& first_font_info = font_list->GetList()[0];
+ std::vector<base::Value>& font_info_list = font_list->GetList();
+ ASSERT_TRUE(font_info_list.size());
+ base::Value& first_font_info = font_info_list[0];
ASSERT_TRUE(first_font_info.is_dict());
base::Value* first_font_name = first_font_info.FindKey("familyName");
+ ASSERT_TRUE(first_font_name);
ASSERT_TRUE(first_font_name->is_string());
ASSERT_GT(first_font_name->GetString().size(), 0u);
ASSERT_EQ(first_font_name->GetString(), kExpectedFontFamilyNames[i]);
}
}
+#endif
} // namespace content
diff --git a/chromium/content/browser/font_unique_name_lookup/font_unique_name_lookup_service.cc b/chromium/content/browser/font_unique_name_lookup/font_unique_name_lookup_service.cc
index 79c4fa1ac5e..bd0d45d7166 100644
--- a/chromium/content/browser/font_unique_name_lookup/font_unique_name_lookup_service.cc
+++ b/chromium/content/browser/font_unique_name_lookup/font_unique_name_lookup_service.cc
@@ -8,6 +8,7 @@
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/macros.h"
+#include "base/no_destructor.h"
#include "base/task/post_task.h"
#include "content/browser/font_unique_name_lookup/font_unique_name_lookup.h"
#include "content/public/common/content_features.h"
@@ -32,12 +33,11 @@ void FontUniqueNameLookupService::Create(
// static
scoped_refptr<base::SequencedTaskRunner>
FontUniqueNameLookupService::GetTaskRunner() {
- CR_DEFINE_STATIC_LOCAL(
- scoped_refptr<base::SequencedTaskRunner>, runner,
- (base::CreateSequencedTaskRunnerWithTraits(
+ static base::NoDestructor<scoped_refptr<base::SequencedTaskRunner>> runner(
+ base::CreateSequencedTaskRunnerWithTraits(
{base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN,
- base::TaskPriority::USER_BLOCKING})));
- return runner;
+ base::TaskPriority::USER_BLOCKING}));
+ return *runner;
}
void FontUniqueNameLookupService::GetUniqueNameLookupTable(
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 4bd20a223cd..5cf646286eb 100644
--- a/chromium/content/browser/frame_host/cross_process_frame_connector.cc
+++ b/chromium/content/browser/frame_host/cross_process_frame_connector.cc
@@ -34,6 +34,37 @@
namespace content {
+namespace {
+
+// If |frame| is an iframe or a GuestView, returns its parent, null otherwise.
+RenderFrameHostImpl* ParentRenderFrameHost(RenderFrameHostImpl* frame) {
+ // Find the parent in the FrameTree (iframe).
+ if (frame->GetParent())
+ return frame->GetParent();
+
+ // Find the parent in the WebContentsTree (GuestView).
+ FrameTreeNode* frame_in_embedder =
+ frame->frame_tree_node()->render_manager()->GetOuterDelegateNode();
+ if (frame_in_embedder)
+ return frame_in_embedder->current_frame_host()->GetParent();
+
+ // No parent found.
+ return nullptr;
+}
+
+// Return the root RenderFrameHost in the outermost WebContents.
+RenderFrameHostImpl* RootRenderFrameHost(RenderFrameHostImpl* frame) {
+ RenderFrameHostImpl* current = frame;
+ while (true) {
+ RenderFrameHostImpl* parent = ParentRenderFrameHost(current);
+ if (!parent)
+ return current;
+ current = parent;
+ };
+}
+
+} // namespace
+
CrossProcessFrameConnector::CrossProcessFrameConnector(
RenderFrameProxyHost* frame_proxy_in_parent_renderer)
: FrameConnectorDelegate(IsUseZoomForDSFEnabled()),
@@ -114,12 +145,13 @@ void CrossProcessFrameConnector::SetView(RenderWidgetHostViewChildFrame* view) {
MaybeLogCrash(CrashVisibility::kNeverVisibleAfterCrash);
}
is_crash_already_logged_ = has_crashed_ = false;
+ delegate_was_shown_after_crash_ = false;
view_->SetFrameConnectorDelegate(this);
if (is_hidden_)
OnVisibilityChanged(false);
FrameMsg_ViewChanged_Params params;
- if (!features::IsUsingWindowService())
+ if (!features::IsMultiProcessMash())
params.frame_sink_id = view_->GetFrameSinkId();
frame_proxy_in_parent_renderer_->Send(new FrameMsg_ViewChanged(
frame_proxy_in_parent_renderer_->GetRoutingID(), params));
@@ -341,20 +373,19 @@ void CrossProcessFrameConnector::OnUpdateViewportIntersection(
viewport_intersection, compositor_visible_rect, occluded_or_obscured);
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);
+ // Record metrics if a crashed subframe became visible as a result of this
+ // viewport intersection update. For example, this might happen if a user
+ // scrolls to a crashed subframe.
+ MaybeLogShownCrash(ShownAfterCrashingReason::kViewportIntersection);
}
}
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);
+ // Record metrics if a crashed subframe became visible as a result of this
+ // visibility change.
+ MaybeLogShownCrash(ShownAfterCrashingReason::kVisibility);
}
if (!view_)
return;
@@ -396,40 +427,19 @@ CrossProcessFrameConnector::GetRootRenderWidgetHostView() {
if (!frame_proxy_in_parent_renderer_)
return nullptr;
- RenderFrameHostImpl* top_host = frame_proxy_in_parent_renderer_->
- frame_tree_node()->frame_tree()->root()->current_frame_host();
-
- // This method should return the root RWHV from the top-level WebContents,
- // in the case of nested WebContents.
- while (top_host->frame_tree_node()->render_manager()->ForInnerDelegate()) {
- top_host = top_host->frame_tree_node()->render_manager()->
- GetOuterDelegateNode()->frame_tree()->root()->current_frame_host();
- }
-
- return static_cast<RenderWidgetHostViewBase*>(top_host->GetView());
+ RenderFrameHostImpl* current =
+ frame_proxy_in_parent_renderer_->frame_tree_node()->current_frame_host();
+ RenderFrameHostImpl* root = RootRenderFrameHost(current);
+ return static_cast<RenderWidgetHostViewBase*>(root->GetView());
}
RenderWidgetHostViewBase*
CrossProcessFrameConnector::GetParentRenderWidgetHostView() {
- FrameTreeNode* parent =
- frame_proxy_in_parent_renderer_->frame_tree_node()->parent();
-
- if (!parent &&
- frame_proxy_in_parent_renderer_->frame_tree_node()
- ->render_manager()
- ->GetOuterDelegateNode()) {
- parent = frame_proxy_in_parent_renderer_->frame_tree_node()
- ->render_manager()
- ->GetOuterDelegateNode()
- ->parent();
- }
-
- if (parent) {
- return static_cast<RenderWidgetHostViewBase*>(
- parent->current_frame_host()->GetView());
- }
-
- return nullptr;
+ RenderFrameHostImpl* current =
+ frame_proxy_in_parent_renderer_->frame_tree_node()->current_frame_host();
+ RenderFrameHostImpl* parent = ParentRenderFrameHost(current);
+ return parent ? static_cast<RenderWidgetHostViewBase*>(parent->GetView())
+ : nullptr;
}
void CrossProcessFrameConnector::EnableAutoResize(const gfx::Size& min_size,
@@ -538,27 +548,53 @@ bool CrossProcessFrameConnector::IsSubtreeThrottled() const {
return subtree_throttled_;
}
-void CrossProcessFrameConnector::MaybeLogCrash(CrashVisibility visibility) {
+bool CrossProcessFrameConnector::MaybeLogCrash(CrashVisibility visibility) {
if (!has_crashed_)
- return;
+ return false;
// Only log once per renderer crash.
if (is_crash_already_logged_)
- return;
+ return false;
is_crash_already_logged_ = true;
// Actually log the UMA.
UMA_HISTOGRAM_ENUMERATION("Stability.ChildFrameCrash.Visibility", visibility);
- if (visibility == CrashVisibility::kShownAfterCrashing) {
- auto* rfh = frame_proxy_in_parent_renderer_->frame_tree_node()
- ->current_frame_host();
- if (rfh->GetParent() && rfh->is_local_root()) {
- UMA_HISTOGRAM_BOOLEAN(
- "RenderFrameHostImpl.ReceivedPostMessageFromNonDescendant",
- rfh->received_post_message_from_non_descendant());
- }
+ return true;
+}
+
+void CrossProcessFrameConnector::MaybeLogShownCrash(
+ ShownAfterCrashingReason reason) {
+ if (!MaybeLogCrash(CrashVisibility::kShownAfterCrashing))
+ return;
+
+ // Identify cases where the sad frame was initially in a hidden tab, then the
+ // tab became visible, and finally the sad frame became visible because it
+ // was scrolled into view or its visibility changed. Record these cases
+ // separately, since they might be avoided by reloading the tab when it
+ // becomes visible.
+ if (delegate_was_shown_after_crash_) {
+ if (reason == ShownAfterCrashingReason::kViewportIntersection)
+ reason = ShownAfterCrashingReason::kViewportIntersectionAfterTabWasShown;
+ else if (reason == ShownAfterCrashingReason::kVisibility)
+ reason = ShownAfterCrashingReason::kVisibilityAfterTabWasShown;
+ }
+
+ UMA_HISTOGRAM_ENUMERATION(
+ "Stability.ChildFrameCrash.ShownAfterCrashingReason", reason);
+}
+
+void CrossProcessFrameConnector::DelegateWasShown() {
+ if (IsVisible()) {
+ // MaybeLogShownCrash will check 1) if there was a crash or not and 2) if
+ // the crash might have been already logged earlier as
+ // kCrashedWhileVisible.
+ MaybeLogShownCrash(
+ CrossProcessFrameConnector::ShownAfterCrashingReason::kTabWasShown);
}
+
+ if (has_crashed_)
+ delegate_was_shown_after_crash_ = true;
}
bool CrossProcessFrameConnector::IsVisible() {
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 203b8a42831..d99a64eb7c3 100644
--- a/chromium/content/browser/frame_host/cross_process_frame_connector.h
+++ b/chromium/content/browser/frame_host/cross_process_frame_connector.h
@@ -130,26 +130,35 @@ 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.
+ // These enums back crashed frame histograms - see MaybeLogCrash() and
+ // MaybeLogShownCrash() below. Please do not modify or remove existing enum
+ // values. When adding new values, please also update enums.xml. 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);
+
+ enum class ShownAfterCrashingReason {
+ kTabWasShown = 0,
+ kViewportIntersection = 1,
+ kVisibility = 2,
+ kViewportIntersectionAfterTabWasShown = 3,
+ kVisibilityAfterTabWasShown = 4,
+ kMaxValue = kVisibilityAfterTabWasShown
+ };
// 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();
+ // This function is called by the RenderFrameHostDelegate to signal that it
+ // became visible.
+ void DelegateWasShown();
+
private:
friend class MockCrossProcessFrameConnector;
@@ -157,6 +166,15 @@ class CONTENT_EXPORT CrossProcessFrameConnector
// unguessable surface ID is not reused after a cross-process navigation.
void ResetScreenSpaceRect();
+ // 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. Returns true if this metric was actually logged.
+ bool MaybeLogCrash(CrashVisibility visibility);
+
+ // Check if a crashed child frame has become visible, and if so, log the
+ // Stability.ChildFrameCrash.Visibility.ShownAfterCrashing* metrics.
+ void MaybeLogShownCrash(ShownAfterCrashingReason reason);
+
// Handlers for messages received from the parent frame.
void OnSynchronizeVisualProperties(
const viz::SurfaceId& surface_id,
@@ -195,6 +213,10 @@ class CONTENT_EXPORT CrossProcessFrameConnector
// CrossProcessFrameConnector or when WebContentsImpl::WasShown is called).
bool has_crashed_ = false;
+ // Remembers whether or not the RenderFrameHostDelegate (i.e., tab) was
+ // shown after a crash. This is only used when recording renderer crashes.
+ bool delegate_was_shown_after_crash_ = 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.
diff --git a/chromium/content/browser/frame_host/debug_urls.cc b/chromium/content/browser/frame_host/debug_urls.cc
index 78868e2664b..85db4c8396c 100644
--- a/chromium/content/browser/frame_host/debug_urls.cc
+++ b/chromium/content/browser/frame_host/debug_urls.cc
@@ -11,10 +11,12 @@
#include "base/debug/profiler.h"
#include "base/strings/utf_string_conversions.h"
#include "base/synchronization/waitable_event.h"
+#include "base/task/post_task.h"
#include "base/threading/thread_restrictions.h"
#include "build/build_config.h"
#include "cc/base/switches.h"
#include "content/browser/gpu/gpu_process_host.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_constants.h"
#include "content/public/common/url_constants.h"
@@ -57,8 +59,7 @@ void HandlePpapiFlashDebugURL(const GURL& url) {
std::vector<PpapiPluginProcessHost*> hosts;
PpapiPluginProcessHost::FindByName(
base::UTF8ToUTF16(kFlashPluginName), &hosts);
- for (std::vector<PpapiPluginProcessHost*>::iterator iter = hosts.begin();
- iter != hosts.end(); ++iter) {
+ for (auto iter = hosts.begin(); iter != hosts.end(); ++iter) {
if (crash)
(*iter)->Send(new PpapiMsg_Crash());
else
@@ -162,9 +163,9 @@ bool HandleDebugURL(const GURL& url, ui::PageTransition transition) {
if (url == kChromeUIDelayedBrowserUIHang) {
// Webdriver-safe url to hang the ui thread. Webdriver waits for the onload
// event in javascript which needs a little more time to fire.
- BrowserThread::PostDelayedTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(&HangCurrentThread),
- base::TimeDelta::FromSeconds(2));
+ base::PostDelayedTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(&HangCurrentThread),
+ base::TimeDelta::FromSeconds(2));
return true;
}
@@ -211,8 +212,8 @@ bool HandleDebugURL(const GURL& url, ui::PageTransition transition) {
}
if (url == kChromeUIPpapiFlashCrashURL || url == kChromeUIPpapiFlashHangURL) {
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::BindOnce(&HandlePpapiFlashDebugURL, url));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(&HandlePpapiFlashDebugURL, url));
return true;
}
diff --git a/chromium/content/browser/frame_host/form_submission_throttle.cc b/chromium/content/browser/frame_host/form_submission_throttle.cc
index 893445d5ebe..46c737ac673 100644
--- a/chromium/content/browser/frame_host/form_submission_throttle.cc
+++ b/chromium/content/browser/frame_host/form_submission_throttle.cc
@@ -19,9 +19,6 @@ std::unique_ptr<NavigationThrottle>
FormSubmissionThrottle::MaybeCreateThrottleFor(NavigationHandle* handle) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
- if (!IsBrowserSideNavigationEnabled())
- return nullptr;
-
if (!handle->IsFormSubmission())
return nullptr;
@@ -33,12 +30,12 @@ FormSubmissionThrottle::~FormSubmissionThrottle() {}
NavigationThrottle::ThrottleCheckResult
FormSubmissionThrottle::WillStartRequest() {
- return CheckContentSecurityPolicyFormAction(false /* is_redirect */);
+ return CheckContentSecurityPolicyFormAction(false /* was_server_redirect */);
}
NavigationThrottle::ThrottleCheckResult
FormSubmissionThrottle::WillRedirectRequest() {
- return CheckContentSecurityPolicyFormAction(true /* is_redirect */);
+ return CheckContentSecurityPolicyFormAction(true /* was_server_redirect */);
}
const char* FormSubmissionThrottle::GetNameForLogging() {
@@ -46,7 +43,8 @@ const char* FormSubmissionThrottle::GetNameForLogging() {
}
NavigationThrottle::ThrottleCheckResult
-FormSubmissionThrottle::CheckContentSecurityPolicyFormAction(bool is_redirect) {
+FormSubmissionThrottle::CheckContentSecurityPolicyFormAction(
+ bool was_server_redirect) {
// TODO(arthursonzogni): form-action is enforced on the wrong RenderFrameHost.
// The navigating one is used instead of the one that has initiated the form
// submission. The renderer side checks are still in place and are used for
@@ -62,7 +60,7 @@ FormSubmissionThrottle::CheckContentSecurityPolicyFormAction(bool is_redirect) {
// compromised) renderer being responsible for enforcing the CSP of another
// (victim) renderer. Therefore it is okay to return early and do no further
// browser-side checks.
- if (!is_redirect)
+ if (!was_server_redirect)
return NavigationThrottle::PROCEED;
NavigationHandleImpl* handle =
@@ -83,7 +81,7 @@ FormSubmissionThrottle::CheckContentSecurityPolicyFormAction(bool is_redirect) {
// 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,
+ CSPDirective::FormAction, url, was_server_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.h b/chromium/content/browser/frame_host/form_submission_throttle.h
index 9c11df352a5..eb95c848f07 100644
--- a/chromium/content/browser/frame_host/form_submission_throttle.h
+++ b/chromium/content/browser/frame_host/form_submission_throttle.h
@@ -36,7 +36,7 @@ class CONTENT_EXPORT FormSubmissionThrottle : public NavigationThrottle {
private:
explicit FormSubmissionThrottle(NavigationHandle* handle);
NavigationThrottle::ThrottleCheckResult CheckContentSecurityPolicyFormAction(
- bool is_redirect);
+ bool was_server_redirect);
DISALLOW_COPY_AND_ASSIGN(FormSubmissionThrottle);
};
diff --git a/chromium/content/browser/frame_host/frame_tree.cc b/chromium/content/browser/frame_host/frame_tree.cc
index ed5a3d823ac..d5d00549b91 100644
--- a/chromium/content/browser/frame_host/frame_tree.cc
+++ b/chromium/content/browser/frame_host/frame_tree.cc
@@ -100,9 +100,6 @@ FrameTree::FrameTree(Navigator* navigator,
manager_delegate_(manager_delegate),
root_(new FrameTreeNode(this,
navigator,
- render_frame_delegate,
- render_widget_delegate,
- manager_delegate,
nullptr,
// The top-level frame must always be in a
// document scope.
@@ -195,10 +192,8 @@ bool FrameTree::AddFrame(
return false;
std::unique_ptr<FrameTreeNode> new_node = base::WrapUnique(new FrameTreeNode(
- this, parent->navigator(), render_frame_delegate_,
- render_widget_delegate_, manager_delegate_, parent, scope, frame_name,
- frame_unique_name, is_created_by_script, devtools_frame_token,
- frame_owner_properties));
+ this, parent->navigator(), parent, scope, frame_name, frame_unique_name,
+ is_created_by_script, devtools_frame_token, frame_owner_properties));
// Set sandbox flags and container policy and make them effective immediately,
// since initial sandbox flags and feature policy should apply to the initial
@@ -212,8 +207,8 @@ bool FrameTree::AddFrame(
new_node->set_was_discarded();
// Add the new node to the FrameTree, creating the RenderFrameHost.
- FrameTreeNode* added_node =
- parent->AddChild(std::move(new_node), process_id, new_routing_id);
+ FrameTreeNode* added_node = parent->current_frame_host()->AddChild(
+ std::move(new_node), process_id, new_routing_id);
DCHECK(interface_provider_request.is_pending());
added_node->current_frame_host()->BindInterfaceProviderRequest(
@@ -244,7 +239,7 @@ void FrameTree::RemoveFrame(FrameTreeNode* child) {
return;
}
- parent->RemoveChild(child);
+ parent->current_frame_host()->RemoveChild(child);
}
void FrameTree::CreateProxiesForSiteInstance(
@@ -356,8 +351,7 @@ RenderViewHostImpl* FrameTree::CreateRenderViewHost(
int32_t widget_routing_id,
bool swapped_out,
bool hidden) {
- RenderViewHostMap::iterator iter =
- render_view_host_map_.find(site_instance->GetId());
+ auto iter = render_view_host_map_.find(site_instance->GetId());
if (iter != render_view_host_map_.end())
return iter->second;
@@ -372,8 +366,7 @@ RenderViewHostImpl* FrameTree::CreateRenderViewHost(
}
RenderViewHostImpl* FrameTree::GetRenderViewHost(SiteInstance* site_instance) {
- RenderViewHostMap::iterator iter =
- render_view_host_map_.find(site_instance->GetId());
+ auto iter = render_view_host_map_.find(site_instance->GetId());
if (iter != render_view_host_map_.end())
return iter->second;
@@ -382,8 +375,7 @@ RenderViewHostImpl* FrameTree::GetRenderViewHost(SiteInstance* site_instance) {
void FrameTree::AddRenderViewHostRef(RenderViewHostImpl* render_view_host) {
SiteInstance* site_instance = render_view_host->GetSiteInstance();
- RenderViewHostMap::iterator iter =
- render_view_host_map_.find(site_instance->GetId());
+ auto iter = render_view_host_map_.find(site_instance->GetId());
CHECK(iter != render_view_host_map_.end());
CHECK(iter->second == render_view_host);
@@ -393,8 +385,7 @@ void FrameTree::AddRenderViewHostRef(RenderViewHostImpl* render_view_host) {
void FrameTree::ReleaseRenderViewHostRef(RenderViewHostImpl* render_view_host) {
SiteInstance* site_instance = render_view_host->GetSiteInstance();
int32_t site_instance_id = site_instance->GetId();
- RenderViewHostMap::iterator iter =
- render_view_host_map_.find(site_instance_id);
+ auto iter = render_view_host_map_.find(site_instance_id);
CHECK(iter != render_view_host_map_.end());
CHECK_EQ(iter->second, render_view_host);
diff --git a/chromium/content/browser/frame_host/frame_tree.h b/chromium/content/browser/frame_host/frame_tree.h
index 248489e5aa5..6aa4ee1b318 100644
--- a/chromium/content/browser/frame_host/frame_tree.h
+++ b/chromium/content/browser/frame_host/frame_tree.h
@@ -102,6 +102,23 @@ class CONTENT_EXPORT FrameTree {
FrameTreeNode* root() const { return root_; }
+ // Delegates for RenderFrameHosts, RenderViewHosts, RenderWidgetHosts and
+ // RenderFrameHostManagers. These can be kept centrally on the FrameTree
+ // because they are expected to be the same for all frames on a given
+ // FrameTree.
+ RenderFrameHostDelegate* render_frame_delegate() {
+ return render_frame_delegate_;
+ }
+ RenderViewHostDelegate* render_view_delegate() {
+ return render_view_delegate_;
+ }
+ RenderWidgetHostDelegate* render_widget_delegate() {
+ return render_widget_delegate_;
+ }
+ RenderFrameHostManager::Delegate* manager_delegate() {
+ return manager_delegate_;
+ }
+
// Returns the FrameTreeNode with the given |frame_tree_node_id| if it is part
// of this FrameTree.
FrameTreeNode* FindByID(int frame_tree_node_id);
diff --git a/chromium/content/browser/frame_host/frame_tree_browsertest.cc b/chromium/content/browser/frame_host/frame_tree_browsertest.cc
index e0be5c94511..7159859c470 100644
--- a/chromium/content/browser/frame_host/frame_tree_browsertest.cc
+++ b/chromium/content/browser/frame_host/frame_tree_browsertest.cc
@@ -32,7 +32,7 @@ namespace content {
namespace {
EvalJsResult GetOriginFromRenderer(FrameTreeNode* node) {
- return EvalJs(node, "document.origin");
+ return EvalJs(node, "self.origin");
}
} // namespace
@@ -275,7 +275,7 @@ IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest, OriginSetOnNavigation) {
// Navigating to a data URL should set a unique origin. This is represented
// as "null" per RFC 6454.
EXPECT_EQ("null", root->current_origin().Serialize());
- EXPECT_TRUE(contents->GetMainFrame()->GetLastCommittedOrigin().unique());
+ EXPECT_TRUE(contents->GetMainFrame()->GetLastCommittedOrigin().opaque());
EXPECT_EQ("null", GetOriginFromRenderer(root));
// Re-navigating to a normal URL should update the origin.
@@ -285,7 +285,7 @@ IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest, OriginSetOnNavigation) {
EXPECT_EQ(
main_url.GetOrigin().spec(),
contents->GetMainFrame()->GetLastCommittedOrigin().Serialize() + '/');
- EXPECT_FALSE(contents->GetMainFrame()->GetLastCommittedOrigin().unique());
+ EXPECT_FALSE(contents->GetMainFrame()->GetLastCommittedOrigin().opaque());
EXPECT_EQ(root->current_origin().Serialize(), GetOriginFromRenderer(root));
}
@@ -315,7 +315,7 @@ IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest, NavigateGrandchildToBlob) {
std::string html =
"<html><body><div>This is blob content.</div>"
"<script>"
- "window.parent.parent.postMessage('HI', document.origin);"
+ "window.parent.parent.postMessage('HI', self.origin);"
"</script></body></html>";
std::string script = JsReplace(
"new Promise((resolve) => {"
@@ -334,7 +334,7 @@ IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest, NavigateGrandchildToBlob) {
deleted_observer.WaitUntilDeleted();
EXPECT_EQ(GURL(blob_url_string), target->current_url());
EXPECT_EQ(url::kBlobScheme, target->current_url().scheme());
- EXPECT_FALSE(target->current_origin().unique());
+ EXPECT_FALSE(target->current_origin().opaque());
EXPECT_EQ("a.com", target->current_origin().host());
EXPECT_EQ(url::kHttpScheme, target->current_origin().scheme());
EXPECT_EQ("This is blob content.",
@@ -373,13 +373,13 @@ IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest, NavigateChildToAboutBlank) {
" frames[0].document.write('Hi from ' + document.domain);"
" } catch (e) { return; }"
" clearInterval(intervalID);"
- " resolve(frames[0].document.origin);"
+ " resolve(frames[0].self.origin);"
" }, 16);"
"});");
EXPECT_EQ(target->current_origin(), about_blank_origin);
EXPECT_EQ(GURL(url::kAboutBlankURL), target->current_url());
EXPECT_EQ(url::kAboutScheme, target->current_url().scheme());
- EXPECT_FALSE(target->current_origin().unique());
+ EXPECT_FALSE(target->current_origin().opaque());
EXPECT_EQ("b.com", target->current_origin().host());
EXPECT_EQ(url::kHttpScheme, target->current_origin().scheme());
@@ -421,13 +421,13 @@ IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest,
" frames[0][0].document.write('Hi from ' + document.domain);"
" } catch (e) { return; }"
" clearInterval(intervalID);"
- " resolve(frames[0][0].document.origin);"
+ " resolve(frames[0][0].self.origin);"
" }, 16);"
"});");
EXPECT_EQ(target->current_origin(), about_blank_origin);
EXPECT_EQ(GURL(url::kAboutBlankURL), target->current_url());
EXPECT_EQ(url::kAboutScheme, target->current_url().scheme());
- EXPECT_FALSE(target->current_origin().unique());
+ EXPECT_FALSE(target->current_origin().opaque());
EXPECT_EQ("a.com", target->current_origin().host());
EXPECT_EQ(url::kHttpScheme, target->current_origin().scheme());
@@ -446,7 +446,7 @@ IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest, ChildFrameWithSrcdoc) {
EXPECT_EQ(1U, root->child_count());
FrameTreeNode* child = root->child_at(0);
- std::string frame_origin = EvalJs(child, "document.origin;").ExtractString();
+ std::string frame_origin = EvalJs(child, "self.origin;").ExtractString();
EXPECT_TRUE(
child->current_frame_host()->GetLastCommittedOrigin().IsSameOriginWith(
url::Origin::Create(GURL(frame_origin))));
@@ -466,7 +466,7 @@ IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest, ChildFrameWithSrcdoc) {
observer.Wait();
EXPECT_EQ(GURL(kAboutSrcDocURL), root->child_at(1)->current_url());
- EvalJsResult frame_origin = EvalJs(root->child_at(1), "document.origin");
+ EvalJsResult frame_origin = EvalJs(root->child_at(1), "self.origin");
EXPECT_EQ(root->current_frame_host()->GetLastCommittedURL().GetOrigin(),
GURL(frame_origin.ExtractString()));
EXPECT_NE(child->current_frame_host()->GetLastCommittedURL().GetOrigin(),
@@ -486,7 +486,7 @@ IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest, ChildFrameWithSrcdoc) {
EXPECT_EQ(
url::Origin::Create(root->current_frame_host()->GetLastCommittedURL())
.Serialize(),
- EvalJs(child, "document.origin"));
+ EvalJs(child, "self.origin"));
}
}
diff --git a/chromium/content/browser/frame_host/frame_tree_node.cc b/chromium/content/browser/frame_host/frame_tree_node.cc
index 46e3d2a7678..24f5fbb94a6 100644
--- a/chromium/content/browser/frame_host/frame_tree_node.cc
+++ b/chromium/content/browser/frame_host/frame_tree_node.cc
@@ -82,15 +82,12 @@ int FrameTreeNode::next_frame_tree_node_id_ = 1;
FrameTreeNode* FrameTreeNode::GloballyFindByID(int frame_tree_node_id) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
FrameTreeNodeIdMap* nodes = g_frame_tree_node_id_map.Pointer();
- FrameTreeNodeIdMap::iterator it = nodes->find(frame_tree_node_id);
+ auto it = nodes->find(frame_tree_node_id);
return it == nodes->end() ? nullptr : it->second;
}
FrameTreeNode::FrameTreeNode(FrameTree* frame_tree,
Navigator* navigator,
- RenderFrameHostDelegate* render_frame_delegate,
- RenderWidgetHostDelegate* render_widget_delegate,
- RenderFrameHostManager::Delegate* manager_delegate,
FrameTreeNode* parent,
blink::WebTreeScopeType scope,
const std::string& name,
@@ -100,10 +97,7 @@ FrameTreeNode::FrameTreeNode(FrameTree* frame_tree,
const FrameOwnerProperties& frame_owner_properties)
: frame_tree_(frame_tree),
navigator_(navigator),
- render_manager_(this,
- render_frame_delegate,
- render_widget_delegate,
- manager_delegate),
+ render_manager_(this, frame_tree->manager_delegate()),
frame_tree_node_id_(next_frame_tree_node_id_++),
parent_(parent),
depth_(parent ? parent->depth_ + 1 : 0u),
@@ -136,9 +130,8 @@ FrameTreeNode::FrameTreeNode(FrameTree* frame_tree,
}
FrameTreeNode::~FrameTreeNode() {
- // Remove the children. See https://crbug.com/612450 for explanation why we
- // don't just call the std::vector::clear method.
- std::vector<std::unique_ptr<FrameTreeNode>>().swap(children_);
+ // Remove the children.
+ current_frame_host()->ResetChildren();
// If the removed frame was created by a script, then its history entry will
// never be reused - we can save some memory by removing the history entry.
@@ -183,47 +176,8 @@ bool FrameTreeNode::IsMainFrame() const {
return frame_tree_->root() == this;
}
-FrameTreeNode* FrameTreeNode::AddChild(std::unique_ptr<FrameTreeNode> child,
- int process_id,
- int frame_routing_id) {
- // Child frame must always be created in the same process as the parent.
- CHECK_EQ(process_id, render_manager_.current_host()->GetProcess()->GetID());
-
- // Initialize the RenderFrameHost for the new node. We always create child
- // frames in the same SiteInstance as the current frame, and they can swap to
- // a different one if they navigate away.
- child->render_manager()->Init(
- render_manager_.current_host()->GetSiteInstance(),
- render_manager_.current_host()->GetRoutingID(), frame_routing_id,
- MSG_ROUTING_NONE, false);
-
- // Other renderer processes in this BrowsingInstance may need to find out
- // about the new frame. Create a proxy for the child frame in all
- // SiteInstances that have a proxy for the frame's parent, since all frames
- // in a frame tree should have the same set of proxies.
- render_manager_.CreateProxiesForChildFrame(child.get());
-
- children_.push_back(std::move(child));
- return children_.back().get();
-}
-
-void FrameTreeNode::RemoveChild(FrameTreeNode* child) {
- for (auto iter = children_.begin(); iter != children_.end(); ++iter) {
- if (iter->get() == child) {
- // Subtle: we need to make sure the node is gone from the tree before
- // observers are notified of its deletion.
- std::unique_ptr<FrameTreeNode> node_to_delete(std::move(*iter));
- children_.erase(iter);
- node_to_delete.reset();
- return;
- }
- }
-}
-
void FrameTreeNode::ResetForNewProcess() {
- // Remove child nodes from the tree, then delete them. This destruction
- // operation will notify observers.
- std::vector<std::unique_ptr<FrameTreeNode>>().swap(children_);
+ current_frame_host()->ResetChildren();
}
void FrameTreeNode::ResetForNavigation() {
@@ -359,18 +313,6 @@ void FrameTreeNode::SetPendingFramePolicy(blink::FramePolicy frame_policy) {
}
}
-bool FrameTreeNode::IsDescendantOf(FrameTreeNode* other) const {
- if (!other || !other->child_count())
- return false;
-
- for (FrameTreeNode* node = parent(); node; node = node->parent()) {
- if (node == other)
- return true;
- }
-
- return false;
-}
-
FrameTreeNode* FrameTreeNode::PreviousSibling() const {
return GetSibling(-1);
}
@@ -421,8 +363,6 @@ void FrameTreeNode::TransferNavigationRequestOwnership(
void FrameTreeNode::CreatedNavigationRequest(
std::unique_ptr<NavigationRequest> navigation_request) {
- CHECK(IsBrowserSideNavigationEnabled());
-
// This is never called when navigating to a Javascript URL. For the loading
// state, this matches what Blink is doing: Blink doesn't send throbber
// notifications for Javascript URLS.
@@ -458,7 +398,6 @@ void FrameTreeNode::CreatedNavigationRequest(
void FrameTreeNode::ResetNavigationRequest(bool keep_state,
bool inform_renderer) {
- CHECK(IsBrowserSideNavigationEnabled());
if (!navigation_request_)
return;
@@ -503,6 +442,9 @@ void FrameTreeNode::ResetNavigationRequest(bool keep_state,
void FrameTreeNode::DidStartLoading(bool to_different_document,
bool was_previously_loading) {
+ TRACE_EVENT2("navigation", "FrameTreeNode::DidStartLoading",
+ "frame_tree_node", frame_tree_node_id(), "to different document",
+ to_different_document);
// Any main frame load to a new document should reset the load progress since
// it will replace the current page and any frames. The WebContents will
// be notified when DidChangeLoadProgress is called.
@@ -522,6 +464,8 @@ void FrameTreeNode::DidStartLoading(bool to_different_document,
}
void FrameTreeNode::DidStopLoading() {
+ TRACE_EVENT1("navigation", "FrameTreeNode::DidStopLoading", "frame_tree_node",
+ frame_tree_node_id());
// Set final load progress and update overall progress. This will notify
// the WebContents of the load progress change.
DidChangeLoadProgress(kLoadingProgressDone);
@@ -549,19 +493,17 @@ void FrameTreeNode::DidChangeLoadProgress(double load_progress) {
}
bool FrameTreeNode::StopLoading() {
- if (IsBrowserSideNavigationEnabled()) {
- if (navigation_request_) {
- int expected_pending_nav_entry_id = navigation_request_->nav_entry_id();
- if (navigation_request_->navigation_handle()) {
- navigation_request_->navigation_handle()->set_net_error_code(
- net::ERR_ABORTED);
- expected_pending_nav_entry_id =
- navigation_request_->navigation_handle()->pending_nav_entry_id();
- }
- navigator_->DiscardPendingEntryIfNeeded(expected_pending_nav_entry_id);
+ if (navigation_request_) {
+ int expected_pending_nav_entry_id = navigation_request_->nav_entry_id();
+ if (navigation_request_->navigation_handle()) {
+ navigation_request_->navigation_handle()->set_net_error_code(
+ net::ERR_ABORTED);
+ expected_pending_nav_entry_id =
+ navigation_request_->navigation_handle()->pending_nav_entry_id();
}
- ResetNavigationRequest(false, true);
+ navigator_->DiscardPendingEntryIfNeeded(expected_pending_nav_entry_id);
}
+ ResetNavigationRequest(false, true);
// TODO(nasko): see if child frames should send IPCs in site-per-process
// mode.
diff --git a/chromium/content/browser/frame_host/frame_tree_node.h b/chromium/content/browser/frame_host/frame_tree_node.h
index cee8a19d6dd..5952a070b60 100644
--- a/chromium/content/browser/frame_host/frame_tree_node.h
+++ b/chromium/content/browser/frame_host/frame_tree_node.h
@@ -39,6 +39,14 @@ struct ContentSecurityPolicyHeader;
// of those frames. We are mirroring this tree in the browser process. This
// class represents a node in this tree and is a wrapper for all objects that
// are frame-specific (as opposed to page-specific).
+//
+// Each FrameTreeNode has a current RenderFrameHost, which can change over
+// time as the frame is navigated. Any immediate subframes of the current
+// document are tracked using FrameTreeNodes owned by the current
+// RenderFrameHost, rather than as children of FrameTreeNode itself. This
+// allows subframe FrameTreeNodes to stay alive while a RenderFrameHost is
+// still alive - for example while pending deletion, after a new current
+// RenderFrameHost has replaced it.
class CONTENT_EXPORT FrameTreeNode {
public:
class Observer {
@@ -62,9 +70,6 @@ class CONTENT_EXPORT FrameTreeNode {
// calling the constructor.
FrameTreeNode(FrameTree* frame_tree,
Navigator* navigator,
- RenderFrameHostDelegate* render_frame_delegate,
- RenderWidgetHostDelegate* render_widget_delegate,
- RenderFrameHostManager::Delegate* manager_delegate,
FrameTreeNode* parent,
blink::WebTreeScopeType scope,
const std::string& name,
@@ -80,11 +85,6 @@ class CONTENT_EXPORT FrameTreeNode {
bool IsMainFrame() const;
- FrameTreeNode* AddChild(std::unique_ptr<FrameTreeNode> child,
- int process_id,
- int frame_routing_id);
- void RemoveChild(FrameTreeNode* child);
-
// Clears process specific-state in this node to prepare for a new process.
void ResetForNewProcess();
@@ -124,9 +124,7 @@ class CONTENT_EXPORT FrameTreeNode {
return devtools_frame_token_;
}
- size_t child_count() const {
- return children_.size();
- }
+ size_t child_count() const { return current_frame_host()->child_count(); }
unsigned int depth() const { return depth_; }
@@ -149,7 +147,7 @@ class CONTENT_EXPORT FrameTreeNode {
void SetOriginalOpener(FrameTreeNode* opener);
FrameTreeNode* child_at(size_t index) const {
- return children_[index].get();
+ return current_frame_host()->child_at(index);
}
// Returns the URL of the last committed page in the current frame.
@@ -269,8 +267,6 @@ class CONTENT_EXPORT FrameTreeNode {
return render_manager_.current_frame_host();
}
- bool IsDescendantOf(FrameTreeNode* other) const;
-
// Return the node immediately preceding this node in its parent's
// |children_|, or nullptr if there is no such node.
FrameTreeNode* PreviousSibling() const;
@@ -380,6 +376,12 @@ class CONTENT_EXPORT FrameTreeNode {
return replication_state_.has_received_user_gesture;
}
+ // Returns whether the frame received a user gesture on a previous navigation
+ // on the same eTLD+1.
+ bool has_received_user_gesture_before_nav() const {
+ return replication_state_.has_received_user_gesture_before_nav;
+ }
+
// When a tab is discarded, WebContents sets was_discarded on its
// root FrameTreeNode.
// In addition, when a child frame is created, this bit is passed on from
@@ -387,6 +389,7 @@ class CONTENT_EXPORT FrameTreeNode {
// When a navigation request is created, was_discarded is passed on to the
// request and reset to false in FrameTreeNode.
void set_was_discarded() { was_discarded_ = true; }
+ bool was_discarded() const { return was_discarded_; }
// Returns the sticky bit of the User Activation v2 state of the
// |FrameTreeNode|.
@@ -460,9 +463,6 @@ class CONTENT_EXPORT FrameTreeNode {
// destroyed.
std::unique_ptr<OpenerDestroyedObserver> original_opener_observer_;
- // The immediate children of this specific frame.
- std::vector<std::unique_ptr<FrameTreeNode>> children_;
-
// Whether this frame has committed any real load, replacing its initial
// about:blank page.
bool has_committed_real_load_;
diff --git a/chromium/content/browser/frame_host/interstitial_page_impl.cc b/chromium/content/browser/frame_host/interstitial_page_impl.cc
index 6a26f13d246..f206f1e547a 100644
--- a/chromium/content/browser/frame_host/interstitial_page_impl.cc
+++ b/chromium/content/browser/frame_host/interstitial_page_impl.cc
@@ -92,7 +92,7 @@ class InterstitialPageImpl::InterstitialPageRVHDelegateView
void TakeFocus(bool reverse) override;
int GetTopControlsHeight() const override;
int GetBottomControlsHeight() const override;
- bool DoBrowserControlsShrinkBlinkSize() const override;
+ bool DoBrowserControlsShrinkRendererSize() const override;
virtual void OnFindReply(int request_id,
int number_of_matches,
const gfx::Rect& selection_rect,
@@ -310,8 +310,7 @@ void InterstitialPageImpl::Hide() {
static_cast<WebContentsImpl*>(web_contents_)->DidChangeVisibleSecurityState();
- InterstitialPageMap::iterator iter =
- g_web_contents_to_interstitial_page->find(web_contents_);
+ auto iter = g_web_contents_to_interstitial_page->find(web_contents_);
DCHECK(iter != g_web_contents_to_interstitial_page->end());
if (iter != g_web_contents_to_interstitial_page->end())
g_web_contents_to_interstitial_page->erase(iter);
@@ -805,8 +804,7 @@ Visibility InterstitialPageImpl::GetVisibility() const {
void InterstitialPageImpl::CreateNewWidget(int32_t render_process_id,
int32_t route_id,
- mojom::WidgetPtr widget,
- blink::WebPopupType popup_type) {
+ mojom::WidgetPtr widget) {
NOTREACHED() << "InterstitialPage does not support showing drop-downs.";
}
@@ -1026,14 +1024,14 @@ int InterstitialPageImpl::InterstitialPageRVHDelegateView::
}
bool InterstitialPageImpl::InterstitialPageRVHDelegateView::
- DoBrowserControlsShrinkBlinkSize() const {
+ DoBrowserControlsShrinkRendererSize() 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();
+ return web_contents->GetDelegateView()->DoBrowserControlsShrinkRendererSize();
}
void InterstitialPageImpl::InterstitialPageRVHDelegateView::OnFindReply(
diff --git a/chromium/content/browser/frame_host/interstitial_page_impl.h b/chromium/content/browser/frame_host/interstitial_page_impl.h
index bb4b5f7771d..1bd73270b29 100644
--- a/chromium/content/browser/frame_host/interstitial_page_impl.h
+++ b/chromium/content/browser/frame_host/interstitial_page_impl.h
@@ -155,8 +155,7 @@ class CONTENT_EXPORT InterstitialPageImpl : public InterstitialPage,
BrowserContext* browser_context) const override;
void CreateNewWidget(int32_t render_process_id,
int32_t route_id,
- mojom::WidgetPtr widget,
- blink::WebPopupType popup_type) override;
+ mojom::WidgetPtr widget) override;
void CreateNewFullscreenWidget(int32_t render_process_id,
int32_t route_id,
mojom::WidgetPtr widget) override;
diff --git a/chromium/content/browser/frame_host/interstitial_page_navigator_impl.cc b/chromium/content/browser/frame_host/interstitial_page_navigator_impl.cc
index fb641d2bd68..7f4c7de9e39 100644
--- a/chromium/content/browser/frame_host/interstitial_page_navigator_impl.cc
+++ b/chromium/content/browser/frame_host/interstitial_page_navigator_impl.cc
@@ -28,16 +28,6 @@ NavigationController* InterstitialPageNavigatorImpl::GetController() {
return controller_;
}
-void InterstitialPageNavigatorImpl::DidStartProvisionalLoad(
- RenderFrameHostImpl* render_frame_host,
- const GURL& url,
- const std::vector<GURL>& redirect_chain,
- const base::TimeTicks& navigation_start) {
- // Do not proceed if the interstitial itself has been disabled.
- if (!enabled_)
- return;
-}
-
void InterstitialPageNavigatorImpl::DidNavigate(
RenderFrameHostImpl* render_frame_host,
const FrameHostMsg_DidCommitProvisionalLoad_Params& input_params,
diff --git a/chromium/content/browser/frame_host/interstitial_page_navigator_impl.h b/chromium/content/browser/frame_host/interstitial_page_navigator_impl.h
index e96489eb086..3ed1141c887 100644
--- a/chromium/content/browser/frame_host/interstitial_page_navigator_impl.h
+++ b/chromium/content/browser/frame_host/interstitial_page_navigator_impl.h
@@ -27,11 +27,6 @@ class CONTENT_EXPORT InterstitialPageNavigatorImpl : public Navigator {
// Navigator implementation.
NavigatorDelegate* GetDelegate() override;
NavigationController* GetController() override;
- void DidStartProvisionalLoad(
- RenderFrameHostImpl* render_frame_host,
- const GURL& url,
- const std::vector<GURL>& redirect_chain,
- const base::TimeTicks& navigation_start) override;
void DidNavigate(
RenderFrameHostImpl* render_frame_host,
const FrameHostMsg_DidCommitProvisionalLoad_Params& input_params,
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 068c8ec250d..6edc4562a5c 100644
--- a/chromium/content/browser/frame_host/keep_alive_handle_factory.cc
+++ b/chromium/content/browser/frame_host/keep_alive_handle_factory.cc
@@ -6,6 +6,8 @@
#include "base/metrics/field_trial.h"
#include "base/metrics/field_trial_params.h"
+#include "base/task/post_task.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/common/content_features.h"
@@ -39,8 +41,8 @@ class KeepAliveHandleFactory::Context final : public base::RefCounted<Context> {
void DetachLater(base::TimeDelta timeout) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- BrowserThread::PostDelayedTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostDelayedTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&Context::Detach, AsWeakPtr()), timeout);
}
diff --git a/chromium/content/browser/frame_host/mixed_content_navigation_throttle.cc b/chromium/content/browser/frame_host/mixed_content_navigation_throttle.cc
index 24042867287..218c6f74c53 100644
--- a/chromium/content/browser/frame_host/mixed_content_navigation_throttle.cc
+++ b/chromium/content/browser/frame_host/mixed_content_navigation_throttle.cc
@@ -19,6 +19,7 @@
#include "content/public/common/origin_util.h"
#include "content/public/common/web_preferences.h"
#include "net/base/url_util.h"
+#include "third_party/blink/public/platform/modules/fetch/fetch_api_request.mojom.h"
#include "url/gurl.h"
#include "url/origin.h"
#include "url/url_constants.h"
@@ -94,16 +95,12 @@ void UpdateRendererOnMixedContentFound(NavigationHandleImpl* navigation_handle,
std::unique_ptr<NavigationThrottle>
MixedContentNavigationThrottle::CreateThrottleForNavigation(
NavigationHandle* navigation_handle) {
- if (IsBrowserSideNavigationEnabled())
- return base::WrapUnique(
- new MixedContentNavigationThrottle(navigation_handle));
- return nullptr;
+ return std::make_unique<MixedContentNavigationThrottle>(navigation_handle);
}
MixedContentNavigationThrottle::MixedContentNavigationThrottle(
NavigationHandle* navigation_handle)
: NavigationThrottle(navigation_handle) {
- DCHECK(IsBrowserSideNavigationEnabled());
}
MixedContentNavigationThrottle::~MixedContentNavigationThrottle() {}
@@ -298,7 +295,7 @@ void MixedContentNavigationThrottle::MaybeSendBlinkFeatureUsageReport() {
// Based off of MixedContentChecker::count.
void MixedContentNavigationThrottle::ReportBasicMixedContentFeatures(
- RequestContextType request_context_type,
+ blink::mojom::RequestContextType request_context_type,
blink::WebMixedContentContextType mixed_content_context_type,
const WebPreferences& prefs) {
mixed_content_features_.insert(MIXED_CONTENT_PRESENT);
@@ -315,19 +312,19 @@ void MixedContentNavigationThrottle::ReportBasicMixedContentFeatures(
// ever be found here.
UseCounterFeature feature;
switch (request_context_type) {
- case REQUEST_CONTEXT_TYPE_INTERNAL:
+ case blink::mojom::RequestContextType::INTERNAL:
feature = MIXED_CONTENT_INTERNAL;
break;
- case REQUEST_CONTEXT_TYPE_PREFETCH:
+ case blink::mojom::RequestContextType::PREFETCH:
feature = MIXED_CONTENT_PREFETCH;
break;
- case REQUEST_CONTEXT_TYPE_AUDIO:
- case REQUEST_CONTEXT_TYPE_DOWNLOAD:
- case REQUEST_CONTEXT_TYPE_FAVICON:
- case REQUEST_CONTEXT_TYPE_IMAGE:
- case REQUEST_CONTEXT_TYPE_PLUGIN:
- case REQUEST_CONTEXT_TYPE_VIDEO:
+ case blink::mojom::RequestContextType::AUDIO:
+ case blink::mojom::RequestContextType::DOWNLOAD:
+ case blink::mojom::RequestContextType::FAVICON:
+ case blink::mojom::RequestContextType::IMAGE:
+ case blink::mojom::RequestContextType::PLUGIN:
+ case blink::mojom::RequestContextType::VIDEO:
default:
NOTREACHED() << "RequestContextType has value " << request_context_type
<< " and has WebMixedContentContextType of "
diff --git a/chromium/content/browser/frame_host/mixed_content_navigation_throttle.h b/chromium/content/browser/frame_host/mixed_content_navigation_throttle.h
index 4c884abf890..152ce976eef 100644
--- a/chromium/content/browser/frame_host/mixed_content_navigation_throttle.h
+++ b/chromium/content/browser/frame_host/mixed_content_navigation_throttle.h
@@ -12,7 +12,7 @@
#include "content/common/content_export.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/navigation_throttle.h"
-#include "content/public/common/request_context_type.h"
+#include "third_party/blink/public/platform/modules/fetch/fetch_api_request.mojom.h"
#include "third_party/blink/public/platform/web_mixed_content_context_type.h"
namespace content {
@@ -71,7 +71,7 @@ class MixedContentNavigationThrottle : public NavigationThrottle {
// Records basic mixed content "feature" usage when any kind of mixed content
// is found.
void ReportBasicMixedContentFeatures(
- RequestContextType request_context_type,
+ blink::mojom::RequestContextType request_context_type,
blink::WebMixedContentContextType mixed_content_context_type,
const WebPreferences& prefs);
diff --git a/chromium/content/browser/frame_host/navigation_controller_impl.cc b/chromium/content/browser/frame_host/navigation_controller_impl.cc
index d8aca9e2cbf..bd5221ce36f 100644
--- a/chromium/content/browser/frame_host/navigation_controller_impl.cc
+++ b/chromium/content/browser/frame_host/navigation_controller_impl.cc
@@ -930,7 +930,7 @@ bool NavigationControllerImpl::RendererDidNavigate(
for (size_t i = 0; i < params.redirects.size(); ++i) {
redirect_chain_size += params.redirects[i].spec().length();
}
- UMA_HISTOGRAM_COUNTS("Navigation.RedirectChainSize", redirect_chain_size);
+ UMA_HISTOGRAM_COUNTS_1M("Navigation.RedirectChainSize", redirect_chain_size);
// Once it is committed, we no longer need to track several pieces of state on
// the entry.
@@ -1661,10 +1661,8 @@ void NavigationControllerImpl::CopyStateFrom(const NavigationController& temp,
needs_reload_ = needs_reload;
InsertEntriesFrom(source, source.GetEntryCount());
- for (SessionStorageNamespaceMap::const_iterator it =
- source.session_storage_namespace_map_.begin();
- it != source.session_storage_namespace_map_.end();
- ++it) {
+ for (auto it = source.session_storage_namespace_map_.begin();
+ it != source.session_storage_namespace_map_.end(); ++it) {
SessionStorageNamespaceImpl* source_namespace =
static_cast<SessionStorageNamespaceImpl*>(it->second.get());
session_storage_namespace_map_[it->first] = source_namespace->Clone();
@@ -1840,15 +1838,16 @@ bool NavigationControllerImpl::StartHistoryNavigationInNewSubframe(
const char kFramePathPrefix[] = "<!--framePath ";
if (base::StartsWith(unique_name, kFramePathPrefix,
base::CompareCase::SENSITIVE)) {
- UMA_HISTOGRAM_COUNTS("SessionRestore.RestoreSubframeFramePathLength",
- unique_name.size());
+ UMA_HISTOGRAM_COUNTS_1M("SessionRestore.RestoreSubframeFramePathLength",
+ unique_name.size());
}
}
std::unique_ptr<NavigationRequest> request = CreateNavigationRequest(
render_frame_host->frame_tree_node(), *entry, frame_entry,
ReloadType::NONE, false /* is_same_document_history_load */,
- true /* is_history_navigation_in_new_child */, nullptr, nullptr);
+ true /* is_history_navigation_in_new_child */, nullptr, nullptr,
+ base::TimeTicks() /* input_start */, WasActivatedOption::kUnknown);
if (!request)
return false;
@@ -1938,7 +1937,8 @@ void NavigationControllerImpl::NavigateFromFrameProxy(
std::unique_ptr<NavigationRequest> request = CreateNavigationRequest(
render_frame_host->frame_tree_node(), *entry, frame_entry.get(),
ReloadType::NONE, false /* is_same_document_history_load */,
- false /* is_history_navigation_in_new_child */, post_body, nullptr);
+ false /* is_history_navigation_in_new_child */, post_body, nullptr,
+ base::TimeTicks() /* input_start */, WasActivatedOption::kUnknown);
if (!request)
return;
@@ -2195,7 +2195,8 @@ void NavigationControllerImpl::NavigateToExistingPendingEntry(
CreateNavigationRequest(
root, *pending_entry_, pending_entry_->GetFrameEntry(root),
reload_type, false /* is_same_document_history_load */,
- false /* is_history_navigation_in_new_child */, nullptr, nullptr);
+ false /* is_history_navigation_in_new_child */, nullptr, nullptr,
+ base::TimeTicks() /* input_start */, WasActivatedOption::kUnknown);
if (!navigation_request) {
// This navigation cannot start (e.g. the URL is invalid), delete the
// pending NavigationEntry.
@@ -2271,7 +2272,9 @@ void NavigationControllerImpl::FindFramesToNavigate(
CreateNavigationRequest(
frame, *pending_entry_, new_item, reload_type,
true /* is_same_document_history_load */,
- false /* is_history_navigation_in_new_child */, nullptr, nullptr);
+ false /* is_history_navigation_in_new_child */, nullptr, nullptr,
+ base::TimeTicks() /* input_start */,
+ WasActivatedOption::kUnknown);
if (navigation_request) {
// Only add the request if was properly created. It's possible for the
// creation to fail in certain cases, e.g. when the URL is invalid.
@@ -2297,7 +2300,9 @@ void NavigationControllerImpl::FindFramesToNavigate(
CreateNavigationRequest(
frame, *pending_entry_, new_item, reload_type,
false /* is_same_document_history_load */,
- false /* is_history_navigation_in_new_child */, nullptr, nullptr);
+ false /* is_history_navigation_in_new_child */, nullptr, nullptr,
+ base::TimeTicks() /* input_start */,
+ WasActivatedOption::kUnknown);
if (navigation_request) {
// Only add the request if was properly created. It's possible for the
// creation to fail in certain cases, e.g. when the URL is invalid.
@@ -2381,7 +2386,8 @@ void NavigationControllerImpl::NavigateWithoutEntry(
node, *pending_entry_, pending_entry_->GetFrameEntry(node), reload_type,
false /* is_same_document_history_load */,
false /* is_history_navigation_in_new_child */, nullptr,
- params.navigation_ui_data ? params.navigation_ui_data->Clone() : nullptr);
+ params.navigation_ui_data ? params.navigation_ui_data->Clone() : nullptr,
+ params.input_start, params.was_activated);
// If the navigation couldn't start, return immediately and discard the
// pending NavigationEntry.
@@ -2543,7 +2549,9 @@ NavigationControllerImpl::CreateNavigationRequest(
bool is_same_document_history_load,
bool is_history_navigation_in_new_child,
const scoped_refptr<network::ResourceRequestBody>& post_body,
- std::unique_ptr<NavigationUIData> navigation_ui_data) {
+ std::unique_ptr<NavigationUIData> navigation_ui_data,
+ base::TimeTicks input_start,
+ WasActivatedOption was_activated) {
GURL dest_url = frame_entry->url();
Referrer dest_referrer = frame_entry->referrer();
if (reload_type == ReloadType::ORIGINAL_REQUEST_URL &&
@@ -2616,7 +2624,7 @@ NavigationControllerImpl::CreateNavigationRequest(
frame_tree_node, dest_url, dest_referrer, *frame_entry, entry,
navigation_type, previews_state, is_same_document_history_load,
is_history_navigation_in_new_child, post_body, navigation_start, this,
- std::move(navigation_ui_data));
+ std::move(navigation_ui_data), input_start, was_activated);
}
void NavigationControllerImpl::NotifyNavigationEntryCommitted(
diff --git a/chromium/content/browser/frame_host/navigation_controller_impl.h b/chromium/content/browser/frame_host/navigation_controller_impl.h
index 8b3502ccbc1..b4ef12e86d6 100644
--- a/chromium/content/browser/frame_host/navigation_controller_impl.h
+++ b/chromium/content/browser/frame_host/navigation_controller_impl.h
@@ -26,6 +26,7 @@
struct FrameHostMsg_DidCommitProvisionalLoad_Params;
namespace content {
+enum class WasActivatedOption;
class FrameTreeNode;
class RenderFrameHostImpl;
class NavigationEntryScreenshotManager;
@@ -293,7 +294,9 @@ class CONTENT_EXPORT NavigationControllerImpl : public NavigationController {
bool is_same_document_history_load,
bool is_history_navigation_in_new_child,
const scoped_refptr<network::ResourceRequestBody>& post_body,
- std::unique_ptr<NavigationUIData> navigation_ui_data);
+ std::unique_ptr<NavigationUIData> navigation_ui_data,
+ base::TimeTicks input_start,
+ WasActivatedOption was_activated);
// Returns whether there is a pending NavigationEntry whose unique ID matches
// the given NavigationHandle's pending_nav_entry_id.
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 06e52b458db..6979a2f11f3 100644
--- a/chromium/content/browser/frame_host/navigation_controller_impl_browsertest.cc
+++ b/chromium/content/browser/frame_host/navigation_controller_impl_browsertest.cc
@@ -18,6 +18,7 @@
#include "base/sequenced_task_runner.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/task/post_task.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/threading/thread_restrictions.h"
@@ -28,7 +29,6 @@
#include "content/browser/frame_host/navigation_handle_impl.h"
#include "content/browser/frame_host/navigation_request.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
-#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/renderer_host/display_util.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
@@ -36,6 +36,7 @@
#include "content/common/frame_messages.h"
#include "content/common/page_state_serialization.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/render_view_host.h"
@@ -984,8 +985,8 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
ErrorPageReplacement) {
NavigationController& controller = shell()->web_contents()->GetController();
GURL error_url = embedded_test_server()->GetURL("/close-socket");
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&net::URLRequestFailedJob::AddUrlHandler));
EXPECT_TRUE(NavigateToURL(shell(), GURL(url::kAboutBlankURL)));
@@ -4912,10 +4913,10 @@ void DoReplaceStateWhilePending(Shell* shell,
EXPECT_TRUE(NavigateToURL(shell, start_url));
// Have the user decide to go to a different page which is very slow.
- NavigationStallDelegate stall_delegate(stalled_url);
- ResourceDispatcherHost::Get()->SetDelegate(&stall_delegate);
- controller.LoadURL(
- stalled_url, Referrer(), ui::PAGE_TRANSITION_LINK, std::string());
+ TestNavigationManager stalled_navigation(shell->web_contents(), stalled_url);
+ controller.LoadURL(stalled_url, Referrer(), ui::PAGE_TRANSITION_LINK,
+ std::string());
+ EXPECT_TRUE(stalled_navigation.WaitForRequestStart());
// That should be the pending entry.
NavigationEntryImpl* entry = controller.GetPendingEntry();
@@ -4936,16 +4937,13 @@ void DoReplaceStateWhilePending(Shell* shell,
EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, capturer.navigation_type());
EXPECT_TRUE(capturer.is_same_document());
}
-
- ResourceDispatcherHost::Get()->SetDelegate(nullptr);
}
} // namespace
-// Flaky on Linux TSan: https://crbug.com/847326
IN_PROC_BROWSER_TEST_F(
NavigationControllerBrowserTest,
- DISABLED_NavigationTypeClassification_On1SameDocumentToXWhile2Pending) {
+ NavigationTypeClassification_On1SameDocumentToXWhile2Pending) {
GURL url1(embedded_test_server()->GetURL(
"/navigation_controller/simple_page_1.html"));
GURL url2(embedded_test_server()->GetURL(
@@ -4971,10 +4969,9 @@ IN_PROC_BROWSER_TEST_F(
DoReplaceStateWhilePending(shell(), url, url, "x");
}
-// Flaky on Linux TSan: https://crbug.com/847326
IN_PROC_BROWSER_TEST_F(
NavigationControllerBrowserTest,
- DISABLED_NavigationTypeClassification_On1SameDocumentTo1While1Pending) {
+ NavigationTypeClassification_On1SameDocumentTo1While1Pending) {
GURL url(embedded_test_server()->GetURL(
"/navigation_controller/simple_page_1.html"));
DoReplaceStateWhilePending(shell(), url, url, "simple_page_1.html");
@@ -5003,11 +5000,11 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// Start a cross-process navigation with replacement, which never completes.
GURL foo_url(embedded_test_server()->GetURL(
"foo.com", "/navigation_controller/page_with_links.html"));
- NavigationStallDelegate stall_delegate(foo_url);
- ResourceDispatcherHost::Get()->SetDelegate(&stall_delegate);
+ TestNavigationManager stalled_navigation(shell()->web_contents(), foo_url);
NavigationController::LoadURLParams params(foo_url);
params.should_replace_current_entry = true;
controller.LoadURLWithParams(params);
+ EXPECT_TRUE(stalled_navigation.WaitForRequestStart());
// That should be the pending entry.
NavigationEntryImpl* entry = controller.GetPendingEntry();
@@ -5033,8 +5030,6 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
EXPECT_EQ(entry_count + 1, controller.GetEntryCount());
EXPECT_EQ(push_state_url, controller.GetLastCommittedEntry()->GetURL());
EXPECT_EQ(start_url, controller.GetEntryAtIndex(0)->GetURL());
-
- ResourceDispatcherHost::Get()->SetDelegate(nullptr);
}
// This test ensures that if we go back from a page that has a replaceState()
@@ -5275,7 +5270,7 @@ class FailureWatcher : public WebContentsObserver {
} // namespace
IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
- DISABLED_StopCausesFailureDespiteJavaScriptURL) {
+ StopCausesFailureDespiteJavaScriptURL) {
NavigationControllerImpl& controller =
static_cast<NavigationControllerImpl&>(
shell()->web_contents()->GetController());
@@ -5292,9 +5287,9 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// Have the user decide to go to a different page which will not commit.
GURL url2(embedded_test_server()->GetURL(
"/navigation_controller/simple_page_2.html"));
- NavigationStallDelegate stall_delegate(url2);
- ResourceDispatcherHost::Get()->SetDelegate(&stall_delegate);
+ TestNavigationManager stalled_navigation(shell()->web_contents(), url2);
controller.LoadURL(url2, Referrer(), ui::PAGE_TRANSITION_LINK, std::string());
+ EXPECT_TRUE(stalled_navigation.WaitForResponse());
// That should be the pending entry.
NavigationEntryImpl* entry = controller.GetPendingEntry();
@@ -5306,16 +5301,12 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
FailureWatcher watcher(root);
GURL js("javascript:(function(){})()");
controller.LoadURL(js, Referrer(), ui::PAGE_TRANSITION_LINK, std::string());
- // This LoadURL ends up purging the pending entry, which is why this is
- // tricky.
- EXPECT_EQ(nullptr, controller.GetPendingEntry());
+ EXPECT_EQ(entry, controller.GetPendingEntry());
EXPECT_TRUE(shell()->web_contents()->IsLoading());
shell()->web_contents()->Stop();
watcher.Wait();
EXPECT_FALSE(shell()->web_contents()->IsLoading());
}
-
- ResourceDispatcherHost::Get()->SetDelegate(nullptr);
}
namespace {
@@ -6022,6 +6013,21 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
EXPECT_EQ(0, controller.GetCurrentEntryIndex());
}
+// Make sure that a 304 response to a navigation aborts the navigation.
+IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, NavigateTo304) {
+ // URL that just returns a blank page.
+ GURL initial_url = embedded_test_server()->GetURL("/set-header");
+ // URL that returns a response with a 304 status code.
+ GURL not_modified_url = embedded_test_server()->GetURL("/echo?status=304");
+
+ EXPECT_TRUE(NavigateToURL(shell(), initial_url));
+ EXPECT_EQ(initial_url, shell()->web_contents()->GetVisibleURL());
+
+ // The navigation should be aborted.
+ EXPECT_FALSE(NavigateToURL(shell(), not_modified_url));
+ EXPECT_EQ(initial_url, shell()->web_contents()->GetVisibleURL());
+}
+
// Ensure that we do not corrupt a NavigationEntry's PageState if two forward
// navigations compete in different frames. See https://crbug.com/623319.
IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
@@ -6765,7 +6771,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// Verify the expected origin through JavaScript. It also has the additional
// verification of the process also being still alive.
EXPECT_EQ(url::Origin::Create(start_url).Serialize(),
- EvalJs(web_contents, "document.origin"));
+ EvalJs(web_contents, "self.origin"));
}
// Helper to trigger a history-back navigation in the WebContents after the
@@ -6854,7 +6860,7 @@ IN_PROC_BROWSER_TEST_F(
// Verify the expected origin through JavaScript. It also has the additional
// verification of the process also being still alive.
EXPECT_EQ(url::Origin::Create(start_url).Serialize(),
- EvalJs(web_contents, "document.origin"));
+ EvalJs(web_contents, "self.origin"));
}
// Test that verifies that Referer and Origin http headers are correctly sent
@@ -8206,4 +8212,44 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
}
}
+// history.back() called twice in the renderer process should not make the user
+// navigate back twice.
+// Regression test for https://crbug.com/869710
+IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
+ HistoryBackTwiceFromRendererWithoutUserGesture) {
+ GURL url1(embedded_test_server()->GetURL("a.com", "/title1.html"));
+ GURL url2(embedded_test_server()->GetURL("b.com", "/title2.html"));
+ GURL url3(embedded_test_server()->GetURL("c.com", "/title3.html"));
+
+ EXPECT_TRUE(NavigateToURL(shell(), url1));
+ EXPECT_TRUE(NavigateToURL(shell(), url2));
+ EXPECT_TRUE(NavigateToURL(shell(), url3));
+
+ EXPECT_TRUE(ExecuteScriptWithoutUserGesture(
+ shell(), "history.back(); history.back();"));
+ EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
+
+ EXPECT_EQ(url2, shell()->web_contents()->GetLastCommittedURL());
+}
+
+// history.back() called twice in the renderer process should not make the user
+// navigate back twice. Even with a user gesture.
+// Regression test for https://crbug.com/869710
+IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
+ HistoryBackTwiceFromRendererWithUserGesture) {
+ GURL url1(embedded_test_server()->GetURL("a.com", "/title1.html"));
+ GURL url2(embedded_test_server()->GetURL("b.com", "/title2.html"));
+ GURL url3(embedded_test_server()->GetURL("c.com", "/title3.html"));
+
+ EXPECT_TRUE(NavigateToURL(shell(), url1));
+ EXPECT_TRUE(NavigateToURL(shell(), url2));
+ EXPECT_TRUE(NavigateToURL(shell(), url3));
+
+ EXPECT_TRUE(ExecuteScript(shell(), "history.back(); history.back();"));
+ EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
+
+ // TODO(https://crbug.com/869710): This should be url2.
+ EXPECT_EQ(url1, shell()->web_contents()->GetLastCommittedURL());
+}
+
} // 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 ebff6f11cc9..43af58f9917 100644
--- a/chromium/content/browser/frame_host/navigation_controller_impl_unittest.cc
+++ b/chromium/content/browser/frame_host/navigation_controller_impl_unittest.cc
@@ -455,13 +455,10 @@ TEST_F(NavigationControllerTestWithBrowserSideNavigation,
// entry when url_1 fails.
NavigateAndCommit(initial_url);
- // Set the pending entry as url_1 and receive the DidStartProvisionalLoad
- // message, creating the NavigationHandle.
+ // Set the pending entry as url_1 and create the NavigationHandle.
controller.LoadURL(url_1, Referrer(), ui::PAGE_TRANSITION_TYPED,
std::string());
EXPECT_EQ(url_1, controller.GetVisibleEntry()->GetURL());
- main_test_rfh()->SimulateNavigationStart(url_1);
- EXPECT_EQ(url_1, controller.GetVisibleEntry()->GetURL());
// The navigation fails and needs to show an error page. This resets the
// pending entry.
@@ -2738,7 +2735,7 @@ TEST_F(NavigationControllerTest, ClientRedirectAfterSameDocumentNavigation) {
params.transition = ui::PAGE_TRANSITION_LINK;
params.redirects.push_back(url);
params.should_update_history = true;
- params.gesture = NavigationGestureUnknown;
+ params.gesture = NavigationGestureAuto;
params.method = "GET";
params.page_state = PageState::CreateFromURL(url);
@@ -2763,7 +2760,7 @@ TEST_F(NavigationControllerTest, ClientRedirectAfterSameDocumentNavigation) {
params.redirects.push_back(GURL("http://foo2/#a"));
params.redirects.push_back(url);
params.should_update_history = true;
- params.gesture = NavigationGestureUnknown;
+ params.gesture = NavigationGestureAuto;
params.method = "GET";
params.page_state = PageState::CreateFromURL(url);
@@ -3381,8 +3378,6 @@ TEST_F(NavigationControllerTest, ReloadTransient) {
// See http://crbug.com/266922.
TEST_F(NavigationControllerTest, RendererInitiatedPendingEntries) {
NavigationControllerImpl& controller = controller_impl();
- Navigator* navigator =
- contents()->GetFrameTree()->root()->navigator();
const GURL url1("nonexistent:12121");
const GURL url1_fixed("http://nonexistent:12121/");
@@ -3392,8 +3387,6 @@ TEST_F(NavigationControllerTest, RendererInitiatedPendingEntries) {
// can show them in new tabs when it is safe.
main_test_rfh()->SendRendererInitiatedNavigationRequest(url1, false);
main_test_rfh()->PrepareForCommit();
- navigator->DidStartProvisionalLoad(main_test_rfh(), url1, std::vector<GURL>(),
- base::TimeTicks::Now());
// Simulate what happens if a BrowserURLHandler rewrites the URL, causing
// the virtual URL to differ from the URL.
@@ -3407,8 +3400,6 @@ TEST_F(NavigationControllerTest, RendererInitiatedPendingEntries) {
// If the user clicks another link, we should replace the pending entry.
main_test_rfh()->SendRendererInitiatedNavigationRequest(url2, false);
main_test_rfh()->PrepareForCommit();
- navigator->DidStartProvisionalLoad(main_test_rfh(), url2, std::vector<GURL>(),
- base::TimeTicks::Now());
EXPECT_EQ(url2, controller.GetPendingEntry()->GetURL());
EXPECT_EQ(url2, controller.GetPendingEntry()->GetVirtualURL());
@@ -3417,26 +3408,10 @@ TEST_F(NavigationControllerTest, RendererInitiatedPendingEntries) {
EXPECT_EQ(url2, controller.GetLastCommittedEntry()->GetURL());
EXPECT_EQ(url2, controller.GetLastCommittedEntry()->GetVirtualURL());
- // We should not replace the pending entry for an error URL.
- navigator->DidStartProvisionalLoad(main_test_rfh(), url1, std::vector<GURL>(),
- base::TimeTicks::Now());
- EXPECT_EQ(url1, controller.GetPendingEntry()->GetURL());
- navigator->DidStartProvisionalLoad(
- main_test_rfh(), GURL(kUnreachableWebDataURL), std::vector<GURL>(),
- base::TimeTicks::Now());
- EXPECT_EQ(url1, controller.GetPendingEntry()->GetURL());
-
// We should remember if the pending entry will replace the current one.
// http://crbug.com/308444.
- navigator->DidStartProvisionalLoad(main_test_rfh(), url1, std::vector<GURL>(),
- base::TimeTicks::Now());
- controller.GetPendingEntry()->set_should_replace_entry(true);
-
main_test_rfh()->SendRendererInitiatedNavigationRequest(url2, false);
main_test_rfh()->PrepareForCommit();
- navigator->DidStartProvisionalLoad(main_test_rfh(), url2, std::vector<GURL>(),
- base::TimeTicks::Now());
- EXPECT_TRUE(controller.GetPendingEntry()->should_replace_entry());
main_test_rfh()->SendNavigateWithReplacement(0, false, url2);
EXPECT_EQ(url2, controller.GetLastCommittedEntry()->GetURL());
}
@@ -4029,12 +4004,9 @@ TEST_F(NavigationControllerTest, CopyStateFrom) {
other_controller.GetSessionStorageNamespaceMap();
EXPECT_EQ(session_storage_namespace_map.size(),
other_session_storage_namespace_map.size());
- for (SessionStorageNamespaceMap::const_iterator it =
- session_storage_namespace_map.begin();
- it != session_storage_namespace_map.end();
- ++it) {
- SessionStorageNamespaceMap::const_iterator other =
- other_session_storage_namespace_map.find(it->first);
+ for (auto it = session_storage_namespace_map.begin();
+ it != session_storage_namespace_map.end(); ++it) {
+ auto other = other_session_storage_namespace_map.find(it->first);
EXPECT_TRUE(other != other_session_storage_namespace_map.end());
}
}
@@ -4523,7 +4495,7 @@ TEST_F(NavigationControllerTest, HistoryNavigate) {
process()->sink().ClearMessages();
// Simulate the page calling history.back(). It should create a pending entry.
- contents()->OnGoToEntryAtOffset(test_rvh(), -1);
+ contents()->OnGoToEntryAtOffset(test_rvh(), -1, false);
EXPECT_EQ(0, controller.GetPendingEntryIndex());
// Also make sure we told the page to navigate.
@@ -4533,7 +4505,7 @@ TEST_F(NavigationControllerTest, HistoryNavigate) {
process()->sink().ClearMessages();
// Now test history.forward()
- contents()->OnGoToEntryAtOffset(test_rvh(), 2);
+ contents()->OnGoToEntryAtOffset(test_rvh(), 2, false);
EXPECT_EQ(2, controller.GetPendingEntryIndex());
nav_url = GetLastNavigationURL();
@@ -4544,7 +4516,7 @@ TEST_F(NavigationControllerTest, HistoryNavigate) {
controller.DiscardNonCommittedEntries();
// Make sure an extravagant history.go() doesn't break.
- contents()->OnGoToEntryAtOffset(test_rvh(), 120); // Out of bounds.
+ contents()->OnGoToEntryAtOffset(test_rvh(), 120, false); // Out of bounds.
EXPECT_EQ(-1, controller.GetPendingEntryIndex());
EXPECT_FALSE(HasNavigationRequest());
}
diff --git a/chromium/content/browser/frame_host/navigation_entry_impl.cc b/chromium/content/browser/frame_host/navigation_entry_impl.cc
index aa9c80e2ce7..bece9448ba6 100644
--- a/chromium/content/browser/frame_host/navigation_entry_impl.cc
+++ b/chromium/content/browser/frame_host/navigation_entry_impl.cc
@@ -613,8 +613,7 @@ void NavigationEntryImpl::SetExtraData(const std::string& key,
bool NavigationEntryImpl::GetExtraData(const std::string& key,
base::string16* data) const {
- std::map<std::string, base::string16>::const_iterator iter =
- extra_data_.find(key);
+ auto iter = extra_data_.find(key);
if (iter == extra_data_.end())
return false;
*data = iter->second;
@@ -686,17 +685,15 @@ CommonNavigationParams NavigationEntryImpl::ConstructCommonNavigationParams(
const Referrer& dest_referrer,
FrameMsg_Navigate_Type::Value navigation_type,
PreviewsState previews_state,
- const base::TimeTicks& navigation_start) const {
+ base::TimeTicks navigation_start,
+ base::TimeTicks input_start) const {
return CommonNavigationParams(
dest_url, dest_referrer, GetTransitionType(), navigation_type,
!IsViewSourceMode(), should_replace_entry(), GetBaseURLForDataURL(),
GetHistoryURLForDataURL(), previews_state, navigation_start,
frame_entry.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(),
- std::vector<ContentSecurityPolicy>() /* initiator_csp */,
- CSPSource() /* initiator_self_source */);
+ base::Optional<SourceLocation>(), has_started_from_context_menu(),
+ has_user_gesture(), InitiatorCSPInfo(), input_start);
}
RequestNavigationParams NavigationEntryImpl::ConstructRequestNavigationParams(
diff --git a/chromium/content/browser/frame_host/navigation_entry_impl.h b/chromium/content/browser/frame_host/navigation_entry_impl.h
index 8c398afe158..858d2af410c 100644
--- a/chromium/content/browser/frame_host/navigation_entry_impl.h
+++ b/chromium/content/browser/frame_host/navigation_entry_impl.h
@@ -187,7 +187,8 @@ class CONTENT_EXPORT NavigationEntryImpl : public NavigationEntry {
const Referrer& dest_referrer,
FrameMsg_Navigate_Type::Value navigation_type,
PreviewsState previews_state,
- const base::TimeTicks& navigation_start) const;
+ base::TimeTicks navigation_start,
+ base::TimeTicks input_start) const;
RequestNavigationParams ConstructRequestNavigationParams(
const FrameNavigationEntry& frame_entry,
const GURL& original_url,
diff --git a/chromium/content/browser/frame_host/navigation_handle_impl.cc b/chromium/content/browser/frame_host/navigation_handle_impl.cc
index 6bc8930b7d8..f8a86851d33 100644
--- a/chromium/content/browser/frame_host/navigation_handle_impl.cc
+++ b/chromium/content/browser/frame_host/navigation_handle_impl.cc
@@ -9,6 +9,7 @@
#include "base/bind.h"
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
+#include "base/optional.h"
#include "base/time/time.h"
#include "content/browser/appcache/appcache_navigation_handle.h"
#include "content/browser/appcache/appcache_service_impl.h"
@@ -34,6 +35,7 @@
#include "content/common/frame_messages.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/navigation_ui_data.h"
+#include "content/public/browser/render_process_host.h"
#include "content/public/browser/site_instance.h"
#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/common/content_client.h"
@@ -72,29 +74,49 @@ void UpdateThrottleCheckResult(
*to_update = result;
}
+// LOG_NAVIGATION_TIMING_HISTOGRAM logs |value| for "Navigation.<histogram>" UMA
+// as well as supplementary UMAs (depending on |transition| and |is_background|)
+// for BackForward/Reload/NewNavigation variants.
+//
+// kMaxTime and kBuckets constants are consistent with
+// UMA_HISTOGRAM_MEDIUM_TIMES, but a custom kMinTime is used for high fidelity
+// near the low end of measured values.
+//
// TODO(csharrison,nasko): This macro is incorrect for subframe navigations,
// which will only have subframe-specific transition types. This means that all
// subframes currently are tagged as NewNavigations.
-#define LOG_NAVIGATION_TIMING_HISTOGRAM(histogram, transition, value, \
- max_time) \
- do { \
- const base::TimeDelta kMinTime = base::TimeDelta::FromMilliseconds(1); \
- const int kBuckets = 50; \
- UMA_HISTOGRAM_CUSTOM_TIMES("Navigation." histogram, value, kMinTime, \
- max_time, kBuckets); \
- if (transition & ui::PAGE_TRANSITION_FORWARD_BACK) { \
- UMA_HISTOGRAM_CUSTOM_TIMES("Navigation." histogram ".BackForward", \
- value, kMinTime, max_time, kBuckets); \
- } else if (ui::PageTransitionCoreTypeIs(transition, \
- ui::PAGE_TRANSITION_RELOAD)) { \
- UMA_HISTOGRAM_CUSTOM_TIMES("Navigation." histogram ".Reload", value, \
- kMinTime, max_time, kBuckets); \
- } else if (ui::PageTransitionIsNewNavigation(transition)) { \
- UMA_HISTOGRAM_CUSTOM_TIMES("Navigation." histogram ".NewNavigation", \
- value, kMinTime, max_time, kBuckets); \
- } else { \
- NOTREACHED() << "Invalid page transition: " << transition; \
- } \
+#define LOG_NAVIGATION_TIMING_HISTOGRAM(histogram, transition, is_background, \
+ duration) \
+ do { \
+ const base::TimeDelta kMinTime = base::TimeDelta::FromMilliseconds(1); \
+ const base::TimeDelta kMaxTime = base::TimeDelta::FromMinutes(3); \
+ const int kBuckets = 50; \
+ UMA_HISTOGRAM_CUSTOM_TIMES("Navigation." histogram, duration, kMinTime, \
+ kMaxTime, kBuckets); \
+ if (transition & ui::PAGE_TRANSITION_FORWARD_BACK) { \
+ UMA_HISTOGRAM_CUSTOM_TIMES("Navigation." histogram ".BackForward", \
+ duration, kMinTime, kMaxTime, kBuckets); \
+ } else if (ui::PageTransitionCoreTypeIs(transition, \
+ ui::PAGE_TRANSITION_RELOAD)) { \
+ UMA_HISTOGRAM_CUSTOM_TIMES("Navigation." histogram ".Reload", duration, \
+ kMinTime, kMaxTime, kBuckets); \
+ } else if (ui::PageTransitionIsNewNavigation(transition)) { \
+ UMA_HISTOGRAM_CUSTOM_TIMES("Navigation." histogram ".NewNavigation", \
+ duration, kMinTime, kMaxTime, kBuckets); \
+ } else { \
+ NOTREACHED() << "Invalid page transition: " << transition; \
+ } \
+ if (is_background.has_value()) { \
+ if (is_background.value()) { \
+ UMA_HISTOGRAM_CUSTOM_TIMES("Navigation." histogram \
+ ".BackgroundProcessPriority", \
+ duration, kMinTime, kMaxTime, kBuckets); \
+ } else { \
+ UMA_HISTOGRAM_CUSTOM_TIMES("Navigation." histogram \
+ ".ForegroundProcessPriority", \
+ duration, kMinTime, kMaxTime, kBuckets); \
+ } \
+ } \
} while (0)
void LogIsSameProcess(ui::PageTransition transition, bool is_same_process) {
@@ -140,7 +162,7 @@ std::unique_ptr<NavigationHandleImpl> NavigationHandleImpl::Create(
bool has_user_gesture,
ui::PageTransition transition,
bool is_external_protocol,
- RequestContextType request_context_type,
+ blink::mojom::RequestContextType request_context_type,
blink::WebMixedContentContextType mixed_content_context_type,
base::TimeTicks input_start) {
return std::unique_ptr<NavigationHandleImpl>(new NavigationHandleImpl(
@@ -172,7 +194,7 @@ NavigationHandleImpl::NavigationHandleImpl(
bool has_user_gesture,
ui::PageTransition transition,
bool is_external_protocol,
- RequestContextType request_context_type,
+ blink::mojom::RequestContextType request_context_type,
blink::WebMixedContentContextType mixed_content_context_type,
base::TimeTicks input_start)
: url_(url),
@@ -207,11 +229,11 @@ NavigationHandleImpl::NavigationHandleImpl(
navigation_type_(NAVIGATION_TYPE_UNKNOWN),
should_check_main_world_csp_(should_check_main_world_csp),
expected_render_process_host_id_(ChildProcessHost::kInvalidUniqueID),
- is_transferring_(false),
is_form_submission_(is_form_submission),
should_replace_current_entry_(false),
is_download_(false),
is_stream_(false),
+ is_signed_exchange_inner_response_(false),
started_from_context_menu_(started_from_context_menu),
is_same_process_(true),
weak_factory_(this) {
@@ -537,7 +559,10 @@ NavigationHandleImpl::CallWillProcessResponseForTesting(
WillProcessResponse(static_cast<RenderFrameHostImpl*>(render_frame_host),
headers, net::HttpResponseInfo::CONNECTION_INFO_UNKNOWN,
net::HostPortPair(), net::SSLInfo(), GlobalRequestID(),
- false, false, false,
+ /* should_replace_current_entry=*/false,
+ /* is_download=*/false,
+ /* is_stream=*/false,
+ /* is_signed_exchange_inner_response=*/false,
base::Bind(&UpdateThrottleCheckResult, &result));
// Reset the callback to ensure it will not be called later.
@@ -554,8 +579,6 @@ void NavigationHandleImpl::CallDidCommitNavigationForTesting(const GURL& url) {
params.transition = ui::PAGE_TRANSITION_TYPED;
params.redirects = std::vector<GURL>();
params.should_update_history = false;
- params.searchable_form_url = GURL();
- params.searchable_form_encoding = std::string();
params.did_create_new_entry = false;
params.gesture = NavigationGestureUser;
params.method = "GET";
@@ -629,6 +652,10 @@ bool NavigationHandleImpl::IsFormSubmission() {
return is_form_submission_;
}
+bool NavigationHandleImpl::IsSignedExchangeInnerResponse() {
+ return is_signed_exchange_inner_response_;
+}
+
void NavigationHandleImpl::InitServiceWorkerHandle(
ServiceWorkerContextWrapper* service_worker_context) {
service_worker_handle_.reset(
@@ -790,6 +817,7 @@ void NavigationHandleImpl::WillProcessResponse(
bool should_replace_current_entry,
bool is_download,
bool is_stream,
+ bool is_signed_exchange_inner_response,
const ThrottleChecksFinishedCallback& callback) {
TRACE_EVENT_ASYNC_STEP_INTO0("navigation", "NavigationHandle", this,
"WillProcessResponse");
@@ -802,6 +830,7 @@ void NavigationHandleImpl::WillProcessResponse(
should_replace_current_entry_ = should_replace_current_entry;
is_download_ = is_download;
is_stream_ = is_stream;
+ is_signed_exchange_inner_response_ = is_signed_exchange_inner_response;
state_ = WILL_PROCESS_RESPONSE;
ssl_info_ = ssl_info;
socket_address_ = socket_address;
@@ -857,30 +886,28 @@ void NavigationHandleImpl::ReadyToCommitNavigation(
frame_tree_node_->current_frame_host()->GetProcess()->GetID();
LogIsSameProcess(transition_, is_same_process_);
- // TODO(csharrison,nasko): Increase the max value to 3 minutes in M68 or
- // M69.
+ // Don't log process-priority-specific UMAs for TimeToReadyToCommit metric
+ // (which shouldn't be influenced by renderer priority).
+ constexpr base::Optional<bool> kIsBackground = base::nullopt;
+
base::TimeDelta delta = ready_to_commit_time_ - navigation_start_;
- LOG_NAVIGATION_TIMING_HISTOGRAM("TimeToReadyToCommit", transition_, delta,
- base::TimeDelta::FromSeconds(10));
+ LOG_NAVIGATION_TIMING_HISTOGRAM("TimeToReadyToCommit", transition_,
+ kIsBackground, delta);
if (IsInMainFrame()) {
LOG_NAVIGATION_TIMING_HISTOGRAM("TimeToReadyToCommit.MainFrame",
- transition_, delta,
- base::TimeDelta::FromSeconds(10));
+ transition_, kIsBackground, delta);
} else {
LOG_NAVIGATION_TIMING_HISTOGRAM("TimeToReadyToCommit.Subframe",
- transition_, delta,
- base::TimeDelta::FromSeconds(10));
+ transition_, kIsBackground, delta);
}
if (is_same_process_) {
LOG_NAVIGATION_TIMING_HISTOGRAM("TimeToReadyToCommit.SameProcess",
- transition_, delta,
- base::TimeDelta::FromSeconds(10));
+ transition_, kIsBackground, delta);
} else {
LOG_NAVIGATION_TIMING_HISTOGRAM("TimeToReadyToCommit.CrossProcess",
- transition_, delta,
- base::TimeDelta::FromSeconds(10));
+ transition_, kIsBackground, delta);
}
}
@@ -932,44 +959,43 @@ void NavigationHandleImpl::DidCommitNavigation(
base::TimeTicks now = base::TimeTicks::Now();
base::TimeDelta delta = now - navigation_start_;
ui::PageTransition transition = GetPageTransition();
- // 3 minutes aligns with UMA_HISTOGRAM_MEDIUM_TIMES.
- const base::TimeDelta kMaxTime = base::TimeDelta::FromMinutes(3);
- LOG_NAVIGATION_TIMING_HISTOGRAM("StartToCommit", transition, delta,
- kMaxTime);
+ base::Optional<bool> is_background =
+ render_frame_host->GetProcess()->IsProcessBackgrounded();
+ LOG_NAVIGATION_TIMING_HISTOGRAM("StartToCommit", transition, is_background,
+ delta);
if (IsInMainFrame()) {
LOG_NAVIGATION_TIMING_HISTOGRAM("StartToCommit.MainFrame", transition,
- delta, kMaxTime);
+ is_background, delta);
} else {
LOG_NAVIGATION_TIMING_HISTOGRAM("StartToCommit.Subframe", transition,
- delta, kMaxTime);
+ is_background, delta);
}
if (is_same_process_) {
LOG_NAVIGATION_TIMING_HISTOGRAM("StartToCommit.SameProcess", transition,
- delta, kMaxTime);
+ is_background, delta);
if (IsInMainFrame()) {
LOG_NAVIGATION_TIMING_HISTOGRAM("StartToCommit.SameProcess.MainFrame",
- transition, delta, kMaxTime);
+ transition, is_background, delta);
} else {
LOG_NAVIGATION_TIMING_HISTOGRAM("StartToCommit.SameProcess.Subframe",
- transition, delta, kMaxTime);
+ transition, is_background, delta);
}
} else {
LOG_NAVIGATION_TIMING_HISTOGRAM("StartToCommit.CrossProcess", transition,
- delta, kMaxTime);
+ is_background, delta);
if (IsInMainFrame()) {
LOG_NAVIGATION_TIMING_HISTOGRAM("StartToCommit.CrossProcess.MainFrame",
- transition, delta, kMaxTime);
+ transition, is_background, delta);
} else {
LOG_NAVIGATION_TIMING_HISTOGRAM("StartToCommit.CrossProcess.Subframe",
- transition, delta, kMaxTime);
+ transition, is_background, delta);
}
}
- // 10 seconds aligns with UMA_HISTOGRAM_TIMES.
if (!ready_to_commit_time_.is_null()) {
LOG_NAVIGATION_TIMING_HISTOGRAM("ReadyToCommitUntilCommit", transition_,
- now - ready_to_commit_time_,
- base::TimeDelta::FromSeconds(10));
+ is_background,
+ now - ready_to_commit_time_);
}
}
diff --git a/chromium/content/browser/frame_host/navigation_handle_impl.h b/chromium/content/browser/frame_host/navigation_handle_impl.h
index 22ecf65f214..56cfa2c17a1 100644
--- a/chromium/content/browser/frame_host/navigation_handle_impl.h
+++ b/chromium/content/browser/frame_host/navigation_handle_impl.h
@@ -28,7 +28,7 @@
#include "content/public/browser/navigation_throttle.h"
#include "content/public/browser/navigation_type.h"
#include "content/public/browser/restore_type.h"
-#include "content/public/common/request_context_type.h"
+#include "third_party/blink/public/platform/modules/fetch/fetch_api_request.mojom.h"
#include "third_party/blink/public/platform/web_mixed_content_context_type.h"
#include "url/gurl.h"
@@ -53,10 +53,8 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
public:
// If |redirect_chain| is empty, then the redirect chain will be created to
// start with |url|. Otherwise |redirect_chain| is used as the starting point.
- // |navigation_start| comes from the DidStartProvisionalLoad IPC, which tracks
- // both renderer-initiated and browser-initiated navigation start.
- // PlzNavigate: This value always comes from the CommonNavigationParams
- // associated with this navigation.
+ // |navigation_start| comes from the CommonNavigationParams associated with
+ // this navigation.
static std::unique_ptr<NavigationHandleImpl> Create(
const GURL& url,
const std::vector<GURL>& redirect_chain,
@@ -77,8 +75,8 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
bool has_user_gesture = false,
ui::PageTransition transition = ui::PAGE_TRANSITION_LINK,
bool is_external_protocol = false,
- RequestContextType request_context_type =
- REQUEST_CONTEXT_TYPE_UNSPECIFIED,
+ blink::mojom::RequestContextType request_context_type =
+ blink::mojom::RequestContextType::UNSPECIFIED,
blink::WebMixedContentContextType mixed_content_context_type =
blink::WebMixedContentContextType::kBlockable,
base::TimeTicks input_start = base::TimeTicks());
@@ -164,6 +162,7 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
const GlobalRequestID& GetGlobalRequestID() override;
bool IsDownload() override;
bool IsFormSubmission() override;
+ bool IsSignedExchangeInnerResponse() override;
const std::string& origin_policy() const { return origin_policy_; }
void set_origin_policy(const std::string& origin_policy) {
@@ -197,7 +196,7 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
// expose the NavigationHandle when navigating to an InterstitialPage.
NavigatorDelegate* GetDelegate() const;
- RequestContextType request_context_type() const {
+ blink::mojom::RequestContextType request_context_type() const {
DCHECK_GE(state_, WILL_SEND_REQUEST);
return request_context_type_;
}
@@ -216,15 +215,6 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
net_error_code_ = net_error_code;
}
- // Returns whether the navigation is currently being transferred from one
- // RenderFrameHost to another. In particular, a DidStartProvisionalLoad IPC
- // for the navigation URL, received in the new RenderFrameHost, should not
- // indicate the start of a new navigation in that case.
- bool is_transferring() const { return is_transferring_; }
- void set_is_transferring(bool is_transferring) {
- is_transferring_ = is_transferring;
- }
-
// Updates the RenderFrameHost that is about to commit the navigation. This
// is used during transfer navigations.
void set_render_frame_host(RenderFrameHostImpl* render_frame_host) {
@@ -306,6 +296,7 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
bool should_replace_current_entry,
bool is_download,
bool is_stream,
+ bool is_signed_exchange_inner_response,
const ThrottleChecksFinishedCallback& callback);
// Returns the FrameTreeNode this navigation is happening in.
@@ -408,7 +399,7 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
bool has_user_gesture,
ui::PageTransition transition,
bool is_external_protocol,
- RequestContextType request_context_type,
+ blink::mojom::RequestContextType request_context_type,
blink::WebMixedContentContextType mixed_content_context_type,
base::TimeTicks input_start);
@@ -523,7 +514,7 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
int pending_nav_entry_id_;
// The fetch request context type.
- RequestContextType request_context_type_;
+ blink::mojom::RequestContextType request_context_type_;
// The mixed content context type for potential mixed content checks.
blink::WebMixedContentContextType mixed_content_context_type_;
@@ -593,10 +584,6 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
// The origin policy that applies to this navigation. Empty if none applies.
std::string origin_policy_;
- // 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_;
-
// Whether or not the navigation results from the submission of a form.
bool is_form_submission_;
@@ -607,6 +594,9 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
bool is_download_;
bool is_stream_;
+ // True if the target is an inner response of a signed exchange.
+ bool is_signed_exchange_inner_response_;
+
// False by default unless the navigation started within a context menu.
bool started_from_context_menu_;
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 9cd758fa060..6fb9c83c1d4 100644
--- a/chromium/content/browser/frame_host/navigation_handle_impl_browsertest.cc
+++ b/chromium/content/browser/frame_host/navigation_handle_impl_browsertest.cc
@@ -6,11 +6,13 @@
#include "base/files/scoped_temp_dir.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/stringprintf.h"
+#include "base/task/post_task.h"
#include "base/test/metrics/histogram_tester.h"
#include "content/browser/frame_host/debug_urls.h"
#include "content/browser/frame_host/navigation_handle_impl.h"
#include "content/browser/frame_host/navigation_request.h"
#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/navigation_throttle.h"
#include "content/public/browser/site_isolation_policy.h"
@@ -20,7 +22,6 @@
#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
-#include "content/public/common/request_context_type.h"
#include "content/public/common/url_constants.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
@@ -36,6 +37,7 @@
#include "net/dns/mock_host_resolver.h"
#include "net/test/url_request/url_request_failed_job.h"
#include "testing/gmock/include/gmock/gmock.h"
+#include "third_party/blink/public/platform/modules/fetch/fetch_api_request.mojom.h"
#include "ui/base/page_transition_types.h"
#include "url/url_constants.h"
@@ -78,7 +80,9 @@ class TestNavigationThrottle : public NavigationThrottle {
const char* GetNameForLogging() override { return "TestNavigationThrottle"; }
- RequestContextType request_context_type() { return request_context_type_; }
+ blink::mojom::RequestContextType request_context_type() {
+ return request_context_type_;
+ }
// Expose Resume and Cancel to the installer.
void ResumeNavigation() { Resume(); }
@@ -92,11 +96,12 @@ class TestNavigationThrottle : public NavigationThrottle {
NavigationThrottle::ThrottleCheckResult WillStartRequest() override {
NavigationHandleImpl* navigation_handle_impl =
static_cast<NavigationHandleImpl*>(navigation_handle());
- CHECK_NE(REQUEST_CONTEXT_TYPE_UNSPECIFIED,
+ CHECK_NE(blink::mojom::RequestContextType::UNSPECIFIED,
navigation_handle_impl->request_context_type());
request_context_type_ = navigation_handle_impl->request_context_type();
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, did_call_will_start_);
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ did_call_will_start_);
return will_start_result_;
}
@@ -106,8 +111,8 @@ class TestNavigationThrottle : public NavigationThrottle {
CHECK_EQ(request_context_type_,
navigation_handle_impl->request_context_type());
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- did_call_will_redirect_);
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ did_call_will_redirect_);
return will_redirect_result_;
}
@@ -117,7 +122,8 @@ class TestNavigationThrottle : public NavigationThrottle {
CHECK_EQ(request_context_type_,
navigation_handle_impl->request_context_type());
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, did_call_will_fail_);
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ did_call_will_fail_);
return will_fail_result_;
}
@@ -127,8 +133,8 @@ class TestNavigationThrottle : public NavigationThrottle {
CHECK_EQ(request_context_type_,
navigation_handle_impl->request_context_type());
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- did_call_will_process_);
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ did_call_will_process_);
return will_process_result_;
}
@@ -140,7 +146,8 @@ class TestNavigationThrottle : public NavigationThrottle {
base::Closure did_call_will_redirect_;
base::Closure did_call_will_fail_;
base::Closure did_call_will_process_;
- RequestContextType request_context_type_ = REQUEST_CONTEXT_TYPE_UNSPECIFIED;
+ blink::mojom::RequestContextType request_context_type_ =
+ blink::mojom::RequestContextType::UNSPECIFIED;
};
// Installs a TestNavigationThrottle either on all following requests or on
@@ -1197,7 +1204,7 @@ IN_PROC_BROWSER_TEST_F(NavigationHandleImplBrowserTest,
EXPECT_EQ(main_url, url_recorder.urls().back());
EXPECT_EQ(1ul, url_recorder.urls().size());
// Checks the main frame RequestContextType.
- EXPECT_EQ(REQUEST_CONTEXT_TYPE_LOCATION,
+ EXPECT_EQ(blink::mojom::RequestContextType::LOCATION,
installer.navigation_throttle()->request_context_type());
// Ditto for frame b navigation.
@@ -1206,7 +1213,7 @@ IN_PROC_BROWSER_TEST_F(NavigationHandleImplBrowserTest,
EXPECT_EQ(2, installer.install_count());
EXPECT_EQ(b_url, url_recorder.urls().back());
EXPECT_EQ(2ul, url_recorder.urls().size());
- EXPECT_EQ(REQUEST_CONTEXT_TYPE_LOCATION,
+ EXPECT_EQ(blink::mojom::RequestContextType::LOCATION,
installer.navigation_throttle()->request_context_type());
// Ditto for frame c navigation.
@@ -1215,7 +1222,7 @@ IN_PROC_BROWSER_TEST_F(NavigationHandleImplBrowserTest,
EXPECT_EQ(3, installer.install_count());
EXPECT_EQ(c_url, url_recorder.urls().back());
EXPECT_EQ(3ul, url_recorder.urls().size());
- EXPECT_EQ(REQUEST_CONTEXT_TYPE_LOCATION,
+ EXPECT_EQ(blink::mojom::RequestContextType::LOCATION,
installer.navigation_throttle()->request_context_type());
// Lets the final navigation finish so that we conclude running the
@@ -1253,7 +1260,7 @@ IN_PROC_BROWSER_TEST_F(NavigationHandleImplBrowserTest,
EXPECT_TRUE(link_manager.WaitForRequestStart());
EXPECT_EQ(link_url, url_recorder.urls().back());
EXPECT_EQ(2ul, url_recorder.urls().size());
- EXPECT_EQ(REQUEST_CONTEXT_TYPE_HYPERLINK,
+ EXPECT_EQ(blink::mojom::RequestContextType::HYPERLINK,
installer.navigation_throttle()->request_context_type());
// Finishes the last navigation.
@@ -1287,7 +1294,7 @@ IN_PROC_BROWSER_TEST_F(NavigationHandleImplBrowserTest,
EXPECT_TRUE(post_manager.WaitForRequestStart());
EXPECT_EQ(post_url, url_recorder.urls().back());
EXPECT_EQ(2ul, url_recorder.urls().size());
- EXPECT_EQ(REQUEST_CONTEXT_TYPE_FORM,
+ EXPECT_EQ(blink::mojom::RequestContextType::FORM,
installer.navigation_throttle()->request_context_type());
// Finishes the last navigation.
@@ -1825,8 +1832,8 @@ IN_PROC_BROWSER_TEST_F(PlzNavigateNavigationHandleImplBrowserTest,
GURL start_url(embedded_test_server()->GetURL("foo.com", "/title1.html"));
GURL error_url(embedded_test_server()->GetURL("/close-socket"));
EXPECT_NE(start_url.host(), error_url.host());
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&net::URLRequestFailedJob::AddUrlHandler));
{
@@ -2077,15 +2084,17 @@ IN_PROC_BROWSER_TEST_F(NavigationHandleImplBrowserTest, StartToCommitMetrics) {
// Add the suffix to all existing histogram names, and append the results to
// |names|.
std::vector<std::string> names{"Navigation.StartToCommit"};
- auto add_suffix = [&names](std::string suffix) {
+ auto add_suffix = [&names](std::vector<std::string> suffixes) {
size_t original_size = names.size();
for (size_t i = 0; i < original_size; i++) {
- names.push_back(names[i] + suffix);
+ for (const std::string& suffix : suffixes)
+ names.push_back(names[i] + suffix);
}
};
- add_suffix(kProcessSuffixes.at(process_type));
- add_suffix(kFrameSuffixes.at(frame_type));
- add_suffix(kTransitionSuffixes.at(transition_type));
+ add_suffix({kProcessSuffixes.at(process_type)});
+ add_suffix({kFrameSuffixes.at(frame_type)});
+ add_suffix({kTransitionSuffixes.at(transition_type),
+ ".ForegroundProcessPriority"});
// Check that all generated histogram names are logged exactly once.
for (const auto& name : names) {
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 b09f5c258a7..62d5ec1c1ac 100644
--- a/chromium/content/browser/frame_host/navigation_handle_impl_unittest.cc
+++ b/chromium/content/browser/frame_host/navigation_handle_impl_unittest.cc
@@ -8,7 +8,6 @@
#include "content/public/browser/navigation_throttle.h"
#include "content/public/browser/ssl_status.h"
#include "content/public/common/browser_side_navigation_policy.h"
-#include "content/public/common/request_context_type.h"
#include "content/public/common/url_constants.h"
#include "content/public/test/browser_side_navigation_test_utils.h"
#include "content/public/test/test_navigation_throttle.h"
@@ -16,6 +15,7 @@
#include "content/test/test_render_frame_host.h"
#include "content/test/test_web_contents.h"
#include "net/ssl/ssl_connection_status_flags.h"
+#include "third_party/blink/public/platform/modules/fetch/fetch_api_request.mojom.h"
namespace content {
@@ -167,7 +167,7 @@ class NavigationHandleImplTest : public RenderViewHostImplTestHarness {
test_handle_->WillProcessResponse(
main_test_rfh(), scoped_refptr<net::HttpResponseHeaders>(),
net::HttpResponseInfo::CONNECTION_INFO_QUIC_35, net::HostPortPair(),
- net::SSLInfo(), GlobalRequestID(), false, false, false,
+ net::SSLInfo(), GlobalRequestID(), false, false, false, false,
base::Bind(&NavigationHandleImplTest::UpdateThrottleCheckResult,
base::Unretained(this)));
}
@@ -265,7 +265,7 @@ class NavigationHandleImplTest : public RenderViewHostImplTestHarness {
false, // has_user_gesture
ui::PAGE_TRANSITION_LINK,
false, // is_external_protocol
- REQUEST_CONTEXT_TYPE_LOCATION);
+ blink::mojom::RequestContextType::LOCATION);
}
private:
@@ -343,19 +343,19 @@ TEST_F(NavigationHandleImplThrottleInsertionTest,
// Note: can be extended to cover more internal members.
TEST_F(NavigationHandleImplTest, SimpleDataChecksRedirectAndProcess) {
SimulateWillStartRequest();
- EXPECT_EQ(REQUEST_CONTEXT_TYPE_LOCATION,
+ EXPECT_EQ(blink::mojom::RequestContextType::LOCATION,
test_handle()->request_context_type());
EXPECT_EQ(net::HttpResponseInfo::CONNECTION_INFO_UNKNOWN,
test_handle()->GetConnectionInfo());
SimulateWillRedirectRequest();
- EXPECT_EQ(REQUEST_CONTEXT_TYPE_LOCATION,
+ EXPECT_EQ(blink::mojom::RequestContextType::LOCATION,
test_handle()->request_context_type());
EXPECT_EQ(net::HttpResponseInfo::CONNECTION_INFO_HTTP1_1,
test_handle()->GetConnectionInfo());
SimulateWillProcessResponse();
- EXPECT_EQ(REQUEST_CONTEXT_TYPE_LOCATION,
+ EXPECT_EQ(blink::mojom::RequestContextType::LOCATION,
test_handle()->request_context_type());
EXPECT_EQ(net::HttpResponseInfo::CONNECTION_INFO_QUIC_35,
test_handle()->GetConnectionInfo());
@@ -373,13 +373,13 @@ TEST_F(NavigationHandleImplTest, SimpleDataCheckNoRedirect) {
TEST_F(NavigationHandleImplTest, SimpleDataChecksFailure) {
SimulateWillStartRequest();
- EXPECT_EQ(REQUEST_CONTEXT_TYPE_LOCATION,
+ EXPECT_EQ(blink::mojom::RequestContextType::LOCATION,
test_handle()->request_context_type());
EXPECT_EQ(net::HttpResponseInfo::CONNECTION_INFO_UNKNOWN,
test_handle()->GetConnectionInfo());
SimulateWillFailRequest(net::ERR_CERT_DATE_INVALID);
- EXPECT_EQ(REQUEST_CONTEXT_TYPE_LOCATION,
+ EXPECT_EQ(blink::mojom::RequestContextType::LOCATION,
test_handle()->request_context_type());
EXPECT_EQ(net::ERR_CERT_DATE_INVALID, test_handle()->GetNetErrorCode());
}
diff --git a/chromium/content/browser/frame_host/navigation_request.cc b/chromium/content/browser/frame_host/navigation_request.cc
index 701167c2055..3687817b179 100644
--- a/chromium/content/browser/frame_host/navigation_request.cc
+++ b/chromium/content/browser/frame_host/navigation_request.cc
@@ -10,6 +10,7 @@
#include "base/optional.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
+#include "base/task/post_task.h"
#include "build/build_config.h"
#include "content/browser/appcache/appcache_navigation_handle.h"
#include "content/browser/appcache/chrome_appcache_service.h"
@@ -28,6 +29,7 @@
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/loader/navigation_url_loader.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
+#include "content/browser/renderer_host/render_view_host_delegate.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_navigation_handle.h"
@@ -35,6 +37,7 @@
#include "content/common/appcache_interfaces.h"
#include "content/common/content_constants_internal.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/global_request_id.h"
@@ -52,7 +55,6 @@
#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"
@@ -67,6 +69,8 @@
#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/common/service_worker/service_worker_utils.h"
+#include "third_party/blink/public/platform/modules/fetch/fetch_api_request.mojom.h"
#include "third_party/blink/public/platform/resource_request_blocked_reason.h"
#include "third_party/blink/public/platform/web_mixed_content_context_type.h"
#include "url/url_constants.h"
@@ -287,9 +291,11 @@ std::unique_ptr<NavigationRequest> NavigationRequest::CreateBrowserInitiated(
bool is_same_document_history_load,
bool is_history_navigation_in_new_child,
const scoped_refptr<network::ResourceRequestBody>& post_body,
- const base::TimeTicks& navigation_start,
+ base::TimeTicks navigation_start,
NavigationControllerImpl* controller,
- std::unique_ptr<NavigationUIData> navigation_ui_data) {
+ std::unique_ptr<NavigationUIData> navigation_ui_data,
+ base::TimeTicks input_start,
+ WasActivatedOption was_activated) {
// A form submission happens either because the navigation is a
// renderer-initiated form submission that took the OpenURL path or a
// back/forward/reload navigation the does a form resubmission.
@@ -322,7 +328,7 @@ std::unique_ptr<NavigationRequest> NavigationRequest::CreateBrowserInitiated(
CommonNavigationParams common_params = entry.ConstructCommonNavigationParams(
frame_entry, request_body, dest_url, dest_referrer, navigation_type,
- previews_state, navigation_start);
+ previews_state, navigation_start, input_start);
RequestNavigationParams request_params =
entry.ConstructRequestNavigationParams(
@@ -334,19 +340,21 @@ std::unique_ptr<NavigationRequest> NavigationRequest::CreateBrowserInitiated(
controller->GetLastCommittedEntryIndex(),
controller->GetEntryCount());
request_params.post_content_type = post_content_type;
+ request_params.was_activated = was_activated;
std::unique_ptr<NavigationRequest> navigation_request(new NavigationRequest(
frame_tree_node, common_params,
mojom::BeginNavigationParams::New(
entry.extra_headers(), net::LOAD_NORMAL,
- false /* skip_service_worker */, REQUEST_CONTEXT_TYPE_LOCATION,
+ false /* skip_service_worker */,
+ blink::mojom::RequestContextType::LOCATION,
blink::WebMixedContentContextType::kBlockable, is_form_submission,
GURL() /* searchable_form_url */,
std::string() /* searchable_form_encoding */, initiator,
GURL() /* client_side_redirect_url */,
base::nullopt /* devtools_initiator_info */),
request_params, browser_initiated, false /* from_begin_navigation */,
- &frame_entry, &entry, std::move(navigation_ui_data), nullptr));
+ &frame_entry, &entry, std::move(navigation_ui_data), nullptr, nullptr));
navigation_request->blob_url_loader_factory_ =
frame_entry.blob_url_loader_factory();
return navigation_request;
@@ -362,7 +370,8 @@ std::unique_ptr<NavigationRequest> NavigationRequest::CreateRendererInitiated(
int current_history_list_length,
bool override_user_agent,
scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
- mojom::NavigationClientAssociatedPtrInfo navigation_client) {
+ mojom::NavigationClientAssociatedPtrInfo navigation_client,
+ blink::mojom::NavigationInitiatorPtr navigation_initiator) {
// Only normal navigations to a different document or reloads are expected.
// - Renderer-initiated fragment-navigations never take place in the browser,
// even with PlzNavigate.
@@ -397,7 +406,7 @@ std::unique_ptr<NavigationRequest> NavigationRequest::CreateRendererInitiated(
true, // from_begin_navigation
nullptr, entry,
nullptr, // navigation_ui_data
- std::move(navigation_client)));
+ std::move(navigation_client), std::move(navigation_initiator)));
navigation_request->blob_url_loader_factory_ =
std::move(blob_url_loader_factory);
return navigation_request;
@@ -413,7 +422,8 @@ NavigationRequest::NavigationRequest(
const FrameNavigationEntry* frame_entry,
const NavigationEntryImpl* entry,
std::unique_ptr<NavigationUIData> navigation_ui_data,
- mojom::NavigationClientAssociatedPtrInfo navigation_client)
+ mojom::NavigationClientAssociatedPtrInfo navigation_client,
+ blink::mojom::NavigationInitiatorPtr navigation_initiator)
: frame_tree_node_(frame_tree_node),
common_params_(common_params),
begin_params_(std::move(begin_params)),
@@ -534,7 +544,9 @@ NavigationRequest::NavigationRequest(
begin_params_->headers = headers.ToString();
initiator_csp_context_.reset(new InitiatorCSPContext(
- common_params_.initiator_csp, common_params_.initiator_self_source));
+ common_params_.initiator_csp_info.initiator_csp,
+ common_params_.initiator_csp_info.initiator_self_source,
+ std::move(navigation_initiator)));
}
NavigationRequest::~NavigationRequest() {
@@ -592,8 +604,8 @@ void NavigationRequest::BeginNavigation() {
// otherwise block. Similarly, the NavigationHandle is created afterwards, so
// that it gets the request URL after potentially being modified by CSP.
net::Error net_error = CheckContentSecurityPolicy(
- false /* is redirect */, false /* url_upgraded_after_redirect */,
- false /* is_response_check */);
+ false /* has_followed redirect */,
+ false /* url_upgraded_after_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 OnRequestFailedInternal().
@@ -686,7 +698,7 @@ void NavigationRequest::CreateNavigationHandle() {
common_params_.navigation_type),
common_params_.navigation_start, nav_entry_id_,
common_params_.started_from_context_menu,
- common_params_.should_check_main_world_csp,
+ common_params_.initiator_csp_info.should_check_main_world_csp,
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,
@@ -852,9 +864,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.
- net::Error net_error = CheckContentSecurityPolicy(
- true /* is redirect */, redirect_info.insecure_scheme_was_upgraded,
- false /* is_response_check */);
+ net::Error net_error =
+ CheckContentSecurityPolicy(true /* has_followed_redirect */,
+ redirect_info.insecure_scheme_was_upgraded,
+ false /* is_response_check */);
if (net_error != net::OK) {
OnRequestFailedInternal(
network::URLLoaderCompletionStatus(net_error), false /*skip_throttles*/,
@@ -958,6 +971,16 @@ void NavigationRequest::OnResponseStarted(
? navigation_handle_->appcache_handle()->appcache_host_id()
: kAppCacheNoHostId;
+ // Update fetch start timing. While NavigationRequest updates fetch start
+ // timing for redirects, it's not aware of service worker interception so
+ // fetch start timing could happen earlier than worker start timing. Use
+ // worker ready time if it is greater than the current value to make sure
+ // fetch start timing always comes after worker start timing (if a service
+ // worker intercepted the navigation).
+ request_params_.navigation_timing.fetch_start =
+ std::max(request_params_.navigation_timing.fetch_start,
+ response->head.service_worker_ready_time);
+
// A navigation is user activated if it contains a user gesture or the frame
// received a gesture and the navigation is renderer initiated. If the
// navigation is browser initiated, it has to come from the context menu.
@@ -965,7 +988,7 @@ void NavigationRequest::OnResponseStarted(
// `ShouldPropagateUserActivation` requirements (same eTLD+1).
// There are two different checks:
// 1. if the `frame_tree_node_` has an origin and is following the rules above
- // with the target URL, it is used and the bit is set iif the navigation is
+ // with the target URL, it is used and the bit is set if the navigation is
// renderer initiated and the `frame_tree_node_` had a gesture. This should
// apply to same page navigations and is preferred over using the referrer
// as it can be changed.
@@ -975,23 +998,28 @@ void NavigationRequest::OnResponseStarted(
// context menu. This should apply to pages that open in a new tab and we
// have to follow the referrer. It means that the activation might not be
// transmitted if it should have.
- request_params_.was_activated = false;
- if (navigation_handle_->IsRendererInitiated() &&
- frame_tree_node_->has_received_user_gesture() &&
- ShouldPropagateUserActivation(
- frame_tree_node_->current_origin(),
- url::Origin::Create(navigation_handle_->GetURL()))) {
- request_params_.was_activated = true;
- // TODO(805871): the next check is relying on
- // navigation_handle_->GetReferrer() but should ideally use a more reliable
- // source for the originating URL when the navigation is renderer initiated.
- } else if (((navigation_handle_->HasUserGesture() &&
- navigation_handle_->IsRendererInitiated()) ||
- navigation_handle_->WasStartedFromContextMenu()) &&
- ShouldPropagateUserActivation(
- url::Origin::Create(navigation_handle_->GetReferrer().url),
- url::Origin::Create(navigation_handle_->GetURL()))) {
- request_params_.was_activated = true;
+ if (request_params_.was_activated == WasActivatedOption::kUnknown) {
+ request_params_.was_activated = WasActivatedOption::kNo;
+
+ if (navigation_handle_->IsRendererInitiated() &&
+ (frame_tree_node_->has_received_user_gesture() ||
+ frame_tree_node_->has_received_user_gesture_before_nav()) &&
+ ShouldPropagateUserActivation(
+ frame_tree_node_->current_origin(),
+ url::Origin::Create(navigation_handle_->GetURL()))) {
+ request_params_.was_activated = WasActivatedOption::kYes;
+ // TODO(805871): the next check is relying on
+ // navigation_handle_->GetReferrer() but should ideally use a more
+ // reliable source for the originating URL when the navigation is renderer
+ // initiated.
+ } else if (((navigation_handle_->HasUserGesture() &&
+ navigation_handle_->IsRendererInitiated()) ||
+ navigation_handle_->WasStartedFromContextMenu()) &&
+ ShouldPropagateUserActivation(
+ url::Origin::Create(navigation_handle_->GetReferrer().url),
+ url::Origin::Create(navigation_handle_->GetURL()))) {
+ request_params_.was_activated = WasActivatedOption::kYes;
+ }
}
// Update the previews state of the request.
@@ -1088,7 +1116,7 @@ void NavigationRequest::OnResponseStarted(
// 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(),
+ navigation_handle_->WasServerRedirect() /* has_followed_redirect */,
false /* url_upgraded_after_redirect */, true /* is_response_check */);
if (net_error != net::OK) {
OnRequestFailedInternal(network::URLLoaderCompletionStatus(net_error),
@@ -1106,7 +1134,7 @@ void NavigationRequest::OnResponseStarted(
render_frame_host, response->head.headers.get(),
response->head.connection_info, response->head.socket_address, ssl_info_,
request_id, common_params_.should_replace_current_entry, is_download,
- is_stream,
+ is_stream, response->head.is_signed_exchange_inner_response,
base::Bind(&NavigationRequest::OnWillProcessResponseChecksComplete,
base::Unretained(this)));
}
@@ -1226,12 +1254,6 @@ bool NavigationRequest::ShouldKeepErrorPageInCurrentProcess(int net_error) {
}
void NavigationRequest::OnRequestStarted(base::TimeTicks timestamp) {
- if (frame_tree_node_->IsMainFrame()) {
- TRACE_EVENT_ASYNC_END_WITH_TIMESTAMP0(
- "navigation", "Navigation timeToNetworkStack", navigation_handle_.get(),
- timestamp);
- }
-
frame_tree_node_->navigator()->LogResourceRequestTime(timestamp,
common_params_.url);
}
@@ -1266,8 +1288,8 @@ void NavigationRequest::OnStartChecksComplete(
// is no onbeforeunload handler or if a NavigationThrottle cancelled it,
// then this could cause reentrancy into NavigationController. So use a
// PostTask to avoid that.
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(
&NavigationRequest::OnRequestFailedInternal,
weak_factory_.GetWeakPtr(),
@@ -1343,7 +1365,7 @@ void NavigationRequest::OnStartChecksComplete(
: 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 opaque URL.
+ // not, the |site_for_cookies| is set to an empty URL.
//
// TODO(mkwst): This is incorrect. It ought to use the definition from
// 'Document::SiteForCookies()' in Blink, which special-cases extension
@@ -1363,7 +1385,7 @@ void NavigationRequest::OnStartChecksComplete(
(ancestors_are_same_site || !base_url.is_empty())
? (frame_tree_node_->IsMainFrame() ? common_params_.url
: top_document_url)
- : GURL("data:,");
+ : GURL::EmptyGURL();
bool parent_is_main_frame = !frame_tree_node_->parent()
? false
: frame_tree_node_->parent()->IsMainFrame();
@@ -1493,10 +1515,20 @@ void NavigationRequest::OnWillProcessResponseChecksComplete(
// If the NavigationThrottles allowed the navigation to continue, have the
// processing of the response resume in the network stack.
if (result.action() == NavigationThrottle::PROCEED) {
- // If this is a download, intercept the navigation response and pass it to
- // DownloadManager, and cancel the navigation.
- if (is_download_ &&
- base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+ // NetworkService doesn't use ResourceDispatcherHost.
+ bool served_via_resource_dispatcher_host =
+ !base::FeatureList::IsEnabled(network::features::kNetworkService);
+ // When S13nServiceWorker is on, it doesn't use ResourceDispatcherHost when
+ // a service worker serves the response.
+ served_via_resource_dispatcher_host =
+ served_via_resource_dispatcher_host &&
+ !(blink::ServiceWorkerUtils::IsServicificationEnabled() &&
+ response_->head.was_fetched_via_service_worker);
+
+ // NetworkService or S13nServiceWorker: If this is a download, intercept the
+ // navigation response and pass it to DownloadManager, and cancel the
+ // navigation.
+ if (is_download_ && !served_via_resource_dispatcher_host) {
// TODO(arthursonzogni): Pass the real ResourceRequest. For the moment
// only these 4 parameters will be used, but it may evolve quickly.
auto resource_request = std::make_unique<network::ResourceRequest>();
@@ -1669,7 +1701,7 @@ void NavigationRequest::CommitNavigation() {
bool NavigationRequest::IsAllowedByCSPDirective(
CSPContext* context,
CSPDirective::Name directive,
- bool is_redirect,
+ bool has_followed_redirect,
bool url_upgraded_after_redirect,
bool is_response_check,
CSPContext::CheckCSPDisposition disposition) {
@@ -1686,25 +1718,26 @@ bool NavigationRequest::IsAllowedByCSPDirective(
url = common_params_.url;
}
return context->IsAllowedByCsp(
- directive, url, is_redirect, is_response_check,
+ directive, url, has_followed_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 has_followed_redirect,
bool url_upgraded_after_redirect,
bool is_response_check,
CSPContext::CheckCSPDisposition disposition) {
bool navigate_to_allowed = IsAllowedByCSPDirective(
- initiator_csp_context_.get(), CSPDirective::NavigateTo, is_redirect,
- url_upgraded_after_redirect, is_response_check, disposition);
+ initiator_csp_context_.get(), CSPDirective::NavigateTo,
+ has_followed_redirect, url_upgraded_after_redirect, is_response_check,
+ disposition);
bool frame_src_allowed = true;
if (parent) {
frame_src_allowed = IsAllowedByCSPDirective(
- parent, CSPDirective::FrameSrc, is_redirect,
+ parent, CSPDirective::FrameSrc, has_followed_redirect,
url_upgraded_after_redirect, is_response_check, disposition);
}
@@ -1724,13 +1757,13 @@ net::Error NavigationRequest::CheckCSPDirectives(
}
net::Error NavigationRequest::CheckContentSecurityPolicy(
- bool is_redirect,
+ bool has_followed_redirect,
bool url_upgraded_after_redirect,
bool is_response_check) {
if (common_params_.url.SchemeIs(url::kAboutScheme))
return net::OK;
- if (common_params_.should_check_main_world_csp ==
+ if (common_params_.initiator_csp_info.should_check_main_world_csp ==
CSPDisposition::DO_NOT_CHECK) {
return net::OK;
}
@@ -1756,13 +1789,13 @@ net::Error NavigationRequest::CheckContentSecurityPolicy(
// This sequence of events allows site owners to learn about (via step 1) any
// requests that are upgraded in step 2.
- net::Error report_only_csp_status =
- CheckCSPDirectives(parent, is_redirect, url_upgraded_after_redirect,
- is_response_check, CSPContext::CHECK_REPORT_ONLY_CSP);
+ net::Error report_only_csp_status = CheckCSPDirectives(
+ parent, has_followed_redirect, url_upgraded_after_redirect,
+ is_response_check, CSPContext::CHECK_REPORT_ONLY_CSP);
// upgrade-insecure-requests is handled in the network code for redirects,
// only do the upgrade here if this is not a redirect.
- if (!is_redirect && !frame_tree_node()->IsMainFrame()) {
+ if (!has_followed_redirect && !frame_tree_node()->IsMainFrame()) {
if (parent &&
parent->ShouldModifyRequestUrlForCsp(true /* is subresource */)) {
upgrade_if_insecure_ = true;
@@ -1771,9 +1804,9 @@ net::Error NavigationRequest::CheckContentSecurityPolicy(
}
}
- net::Error enforced_csp_status =
- CheckCSPDirectives(parent, is_redirect, url_upgraded_after_redirect,
- is_response_check, CSPContext::CHECK_ENFORCED_CSP);
+ net::Error enforced_csp_status = CheckCSPDirectives(
+ parent, has_followed_redirect, url_upgraded_after_redirect,
+ is_response_check, CSPContext::CHECK_ENFORCED_CSP);
if (enforced_csp_status != net::OK)
return enforced_csp_status;
return report_only_csp_status;
diff --git a/chromium/content/browser/frame_host/navigation_request.h b/chromium/content/browser/frame_host/navigation_request.h
index 5d4aa5cbeab..7d37652271a 100644
--- a/chromium/content/browser/frame_host/navigation_request.h
+++ b/chromium/content/browser/frame_host/navigation_request.h
@@ -91,9 +91,11 @@ class CONTENT_EXPORT NavigationRequest : public NavigationURLLoaderDelegate {
bool is_same_document_history_load,
bool is_history_navigation_in_new_child,
const scoped_refptr<network::ResourceRequestBody>& post_body,
- const base::TimeTicks& navigation_start,
+ base::TimeTicks navigation_start,
NavigationControllerImpl* controller,
- std::unique_ptr<NavigationUIData> navigation_ui_data);
+ std::unique_ptr<NavigationUIData> navigation_ui_data,
+ base::TimeTicks input_start,
+ WasActivatedOption was_activated);
// Creates a request for a renderer-intiated navigation.
// Note: |body| is sent to the IO thread when calling BeginNavigation, and
@@ -109,7 +111,8 @@ class CONTENT_EXPORT NavigationRequest : public NavigationURLLoaderDelegate {
int current_history_list_length,
bool override_user_agent,
scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
- mojom::NavigationClientAssociatedPtrInfo navigation_client);
+ mojom::NavigationClientAssociatedPtrInfo navigation_client,
+ blink::mojom::NavigationInitiatorPtr navigation_initiator);
~NavigationRequest() override;
@@ -224,7 +227,8 @@ class CONTENT_EXPORT NavigationRequest : public NavigationURLLoaderDelegate {
const FrameNavigationEntry* frame_navigation_entry,
const NavigationEntryImpl* navitation_entry,
std::unique_ptr<NavigationUIData> navigation_ui_data,
- mojom::NavigationClientAssociatedPtrInfo navigation_client);
+ mojom::NavigationClientAssociatedPtrInfo navigation_client,
+ blink::mojom::NavigationInitiatorPtr navigation_initiator);
// NavigationURLLoaderDelegate implementation.
void OnRequestRedirected(
@@ -284,7 +288,7 @@ class CONTENT_EXPORT NavigationRequest : public NavigationURLLoaderDelegate {
// and navigate-to checks.
bool IsAllowedByCSPDirective(CSPContext* context,
CSPDirective::Name directive,
- bool is_redirect,
+ bool has_followed_redirect,
bool url_upgraded_after_redirect,
bool is_response_check,
CSPContext::CheckCSPDisposition disposition);
@@ -294,7 +298,7 @@ class CONTENT_EXPORT NavigationRequest : public NavigationURLLoaderDelegate {
// 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 has_followed_redirect,
bool url_upgraded_after_redirect,
bool is_response_check,
CSPContext::CheckCSPDisposition disposition);
@@ -305,7 +309,7 @@ class CONTENT_EXPORT NavigationRequest : public NavigationURLLoaderDelegate {
// a report will be sent.
// - The navigation request may be upgraded from HTTP to HTTPS if a CSP is
// configured to upgrade insecure requests.
- net::Error CheckContentSecurityPolicy(bool is_redirect,
+ net::Error CheckContentSecurityPolicy(bool has_followed_redirect,
bool url_upgraded_after_redirect,
bool is_response_check);
diff --git a/chromium/content/browser/frame_host/navigator.cc b/chromium/content/browser/frame_host/navigator.cc
index 59cea6fbf74..7cce6d26021 100644
--- a/chromium/content/browser/frame_host/navigator.cc
+++ b/chromium/content/browser/frame_host/navigator.cc
@@ -32,6 +32,7 @@ void Navigator::OnBeginNavigation(
const CommonNavigationParams& common_params,
mojom::BeginNavigationParamsPtr begin_params,
scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
- mojom::NavigationClientAssociatedPtrInfo navigation_client) {}
+ mojom::NavigationClientAssociatedPtrInfo navigation_client,
+ blink::mojom::NavigationInitiatorPtr navigation_initiator) {}
} // namespace content
diff --git a/chromium/content/browser/frame_host/navigator.h b/chromium/content/browser/frame_host/navigator.h
index fe5fe87f06f..a02d2e9fe72 100644
--- a/chromium/content/browser/frame_host/navigator.h
+++ b/chromium/content/browser/frame_host/navigator.h
@@ -52,13 +52,6 @@ class CONTENT_EXPORT Navigator : public base::RefCounted<Navigator> {
// Notifications coming from the RenderFrameHosts ----------------------------
- // The RenderFrameHostImpl started a provisional load.
- virtual void DidStartProvisionalLoad(
- RenderFrameHostImpl* render_frame_host,
- const GURL& url,
- const std::vector<GURL>& redirect_chain,
- const base::TimeTicks& navigation_start) {}
-
// The RenderFrameHostImpl has failed a provisional load.
virtual void DidFailProvisionalLoadWithError(
RenderFrameHostImpl* render_frame_host,
@@ -151,7 +144,8 @@ class CONTENT_EXPORT Navigator : public base::RefCounted<Navigator> {
const CommonNavigationParams& common_params,
mojom::BeginNavigationParamsPtr begin_params,
scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
- mojom::NavigationClientAssociatedPtrInfo navigation_client);
+ mojom::NavigationClientAssociatedPtrInfo navigation_client,
+ blink::mojom::NavigationInitiatorPtr navigation_initiator);
// Used to restart a navigation that was thought to be same-document in
// cross-document mode.
diff --git a/chromium/content/browser/frame_host/navigator_impl.cc b/chromium/content/browser/frame_host/navigator_impl.cc
index f53badc0816..7d7544debb3 100644
--- a/chromium/content/browser/frame_host/navigator_impl.cc
+++ b/chromium/content/browser/frame_host/navigator_impl.cc
@@ -105,35 +105,6 @@ NavigationController* NavigatorImpl::GetController() {
return controller_;
}
-// TODO(clamy): See if we can remove this function now that PlzNavigate has
-// shipped.
-void NavigatorImpl::DidStartProvisionalLoad(
- RenderFrameHostImpl* render_frame_host,
- const GURL& url,
- const std::vector<GURL>& redirect_chain,
- const base::TimeTicks& navigation_start) {
- bool is_main_frame = render_frame_host->frame_tree_node()->IsMainFrame();
- bool is_error_page = (url.spec() == kUnreachableWebDataURL);
- GURL validated_url(url);
- RenderProcessHost* render_process_host = render_frame_host->GetProcess();
- render_process_host->FilterURL(false, &validated_url);
-
- // Do not allow browser plugin guests to navigate to non-web URLs, since they
- // cannot swap processes or grant bindings.
- ChildProcessSecurityPolicyImpl* policy =
- ChildProcessSecurityPolicyImpl::GetInstance();
- if (render_process_host->IsForGuestsOnly() &&
- !policy->IsWebSafeScheme(validated_url.scheme())) {
- validated_url = GURL(url::kAboutBlankURL);
- }
-
- if (is_main_frame && !is_error_page) {
- DidStartMainFrameNavigation(validated_url,
- render_frame_host->GetSiteInstance(),
- render_frame_host->GetNavigationHandle());
- }
-}
-
void NavigatorImpl::DidFailProvisionalLoadWithError(
RenderFrameHostImpl* render_frame_host,
const FrameHostMsg_DidFailProvisionalLoadWithError_Params& params) {
@@ -398,19 +369,6 @@ void NavigatorImpl::Navigate(std::unique_ptr<NavigationRequest> request,
// after this point without null checking it first.
}
- if (frame_tree_node->IsMainFrame() && frame_tree_node->navigation_request()) {
- // For the trace below we're using the navigation handle as the async
- // trace id, |navigation_start| as the timestamp and reporting the
- // FrameTreeNode id as a parameter. For navigations where no network
- // request is made (data URLs, JavaScript URLs, etc) there is no handle
- // and so no tracing is done.
- TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP1(
- "navigation", "Navigation timeToNetworkStack",
- frame_tree_node->navigation_request()->navigation_handle(),
- frame_tree_node->navigation_request()->common_params().navigation_start,
- "FrameTreeNode id", frame_tree_node->frame_tree_node_id());
- }
-
// Make sure no code called via RFH::Navigate clears the pending entry.
if (is_pending_entry)
CHECK_EQ(nav_entry_id, controller_->GetPendingEntry()->GetUniqueID());
@@ -624,7 +582,8 @@ void NavigatorImpl::OnBeginNavigation(
const CommonNavigationParams& common_params,
mojom::BeginNavigationParamsPtr begin_params,
scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
- mojom::NavigationClientAssociatedPtrInfo navigation_client) {
+ mojom::NavigationClientAssociatedPtrInfo navigation_client,
+ blink::mojom::NavigationInitiatorPtr navigation_initiator) {
// TODO(clamy): the url sent by the renderer should be validated with
// FilterURL.
// This is a renderer-initiated navigation.
@@ -687,7 +646,8 @@ void NavigatorImpl::OnBeginNavigation(
frame_tree_node, pending_entry, common_params,
std::move(begin_params), controller_->GetLastCommittedEntryIndex(),
controller_->GetEntryCount(), override_user_agent,
- std::move(blob_url_loader_factory), std::move(navigation_client)));
+ std::move(blob_url_loader_factory), std::move(navigation_client),
+ std::move(navigation_initiator)));
NavigationRequest* navigation_request = frame_tree_node->navigation_request();
// This frame has already run beforeunload before it sent this IPC. See if
@@ -807,9 +767,14 @@ 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).
//
+ // Do not leave the pending entry visible if it has an invalid URL, since this
+ // might be formatted in an unexpected or unsafe way.
+ // TODO(creis): Block navigations to invalid URLs in https://crbug.com/850824.
+ //
// Note: don't touch the transient entry, since an interstitial may exist.
- bool should_preserve_entry = controller_->IsUnmodifiedBlankTab() ||
- delegate_->ShouldPreserveAbortedURLs();
+ bool should_preserve_entry = pending_entry->GetURL().is_valid() &&
+ (controller_->IsUnmodifiedBlankTab() ||
+ delegate_->ShouldPreserveAbortedURLs());
if (pending_entry != controller_->GetVisibleEntry() ||
!should_preserve_entry) {
controller_->DiscardPendingEntry(true);
diff --git a/chromium/content/browser/frame_host/navigator_impl.h b/chromium/content/browser/frame_host/navigator_impl.h
index b97af7081e4..cfc56346eaa 100644
--- a/chromium/content/browser/frame_host/navigator_impl.h
+++ b/chromium/content/browser/frame_host/navigator_impl.h
@@ -40,11 +40,6 @@ class CONTENT_EXPORT NavigatorImpl : public Navigator {
// Navigator implementation.
NavigatorDelegate* GetDelegate() override;
NavigationController* GetController() override;
- void DidStartProvisionalLoad(
- RenderFrameHostImpl* render_frame_host,
- const GURL& url,
- const std::vector<GURL>& redirect_chain,
- const base::TimeTicks& navigation_start) override;
void DidFailProvisionalLoadWithError(
RenderFrameHostImpl* render_frame_host,
const FrameHostMsg_DidFailProvisionalLoadWithError_Params& params)
@@ -95,7 +90,8 @@ class CONTENT_EXPORT NavigatorImpl : public Navigator {
const CommonNavigationParams& common_params,
mojom::BeginNavigationParamsPtr begin_params,
scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
- mojom::NavigationClientAssociatedPtrInfo navigation_client) override;
+ mojom::NavigationClientAssociatedPtrInfo navigation_client,
+ blink::mojom::NavigationInitiatorPtr navigation_initiator) override;
void RestartNavigationAsCrossDocument(
std::unique_ptr<NavigationRequest> navigation_request) override;
void OnAbortNavigation(FrameTreeNode* frame_tree_node) override;
diff --git a/chromium/content/browser/frame_host/navigator_impl_unittest.cc b/chromium/content/browser/frame_host/navigator_impl_unittest.cc
index 7d748abfede..abda7b16451 100644
--- a/chromium/content/browser/frame_host/navigator_impl_unittest.cc
+++ b/chromium/content/browser/frame_host/navigator_impl_unittest.cc
@@ -1301,7 +1301,7 @@ TEST_F(NavigatorTestWithBrowserSideNavigation, FeaturePolicyNewChild) {
blink::FeaturePolicy* subframe_feature_policy =
subframe_rfh->feature_policy();
ASSERT_TRUE(subframe_feature_policy);
- ASSERT_FALSE(subframe_feature_policy->GetOriginForTest().unique());
+ ASSERT_FALSE(subframe_feature_policy->GetOriginForTest().opaque());
}
TEST_F(NavigatorTestWithBrowserSideNavigation, TwoNavigationsRacingCommit) {
diff --git a/chromium/content/browser/frame_host/origin_policy_throttle.cc b/chromium/content/browser/frame_host/origin_policy_throttle.cc
index 5d2904a633b..e315801fd55 100644
--- a/chromium/content/browser/frame_host/origin_policy_throttle.cc
+++ b/chromium/content/browser/frame_host/origin_policy_throttle.cc
@@ -11,6 +11,7 @@
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/navigation_handle.h"
+#include "content/public/browser/origin_policy_error_reason.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
@@ -21,7 +22,7 @@
namespace {
// Constants derived from the spec, https://github.com/WICG/origin-policy
-static const char* kDefaultPolicy = "1";
+static const char* kDefaultPolicy = "0";
static const char* kDeletePolicy = "0";
static const char* kWellKnown = "/.well-known/origin-policy/";
@@ -36,8 +37,12 @@ namespace content {
bool OriginPolicyThrottle::ShouldRequestOriginPolicy(
const GURL& url,
std::string* request_version) {
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
- if (!base::FeatureList::IsEnabled(features::kOriginPolicy))
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ bool origin_policy_enabled =
+ base::FeatureList::IsEnabled(features::kOriginPolicy) ||
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableExperimentalWebPlatformFeatures);
+ if (!origin_policy_enabled)
return false;
if (!url.SchemeIs(url::kHttpsScheme))
@@ -55,7 +60,7 @@ bool OriginPolicyThrottle::ShouldRequestOriginPolicy(
// static
std::unique_ptr<NavigationThrottle>
OriginPolicyThrottle::MaybeCreateThrottleFor(NavigationHandle* handle) {
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(handle);
// We use presence of the origin policy request header to determine
@@ -64,7 +69,11 @@ OriginPolicyThrottle::MaybeCreateThrottleFor(NavigationHandle* handle) {
net::HttpRequestHeaders::kSecOriginPolicy))
return nullptr;
- DCHECK(base::FeatureList::IsEnabled(features::kOriginPolicy));
+ // TODO(vogelheim): Rewrite & hoist up this DCHECK to ensure that ..HasHeader
+ // and ShouldRequestOriginPolicy are always equal on entry to the method.
+ // This depends on https://crbug.com/881234 being fixed.
+ DCHECK(OriginPolicyThrottle::ShouldRequestOriginPolicy(handle->GetURL(),
+ nullptr));
return base::WrapUnique(new OriginPolicyThrottle(handle));
}
@@ -109,9 +118,9 @@ OriginPolicyThrottle::WillProcessResponse() {
url::Origin origin = GetRequestOrigin();
DCHECK(!origin.Serialize().empty());
- DCHECK(!origin.unique());
+ DCHECK(!origin.opaque());
KnownVersionMap& versions = GetKnownVersions();
- KnownVersionMap::iterator iter = versions.find(origin);
+ auto iter = versions.find(origin);
// Process policy deletion first!
if (header_found && response_version == kDeletePolicy) {
@@ -136,7 +145,9 @@ OriginPolicyThrottle::WillProcessResponse() {
FetchCallback done =
base::BindOnce(&OriginPolicyThrottle::OnTheGloriousPolicyHasArrived,
base::Unretained(this));
- FetchPolicy(policy, std::move(done));
+ RedirectCallback redirect = base::BindRepeating(
+ &OriginPolicyThrottle::OnRedirect, base::Unretained(this));
+ FetchPolicy(policy, std::move(done), std::move(redirect));
return NavigationThrottle::DEFER;
}
@@ -163,7 +174,9 @@ const url::Origin OriginPolicyThrottle::GetRequestOrigin() {
return url::Origin::Create(navigation_handle()->GetURL());
}
-void OriginPolicyThrottle::FetchPolicy(const GURL& url, FetchCallback done) {
+void OriginPolicyThrottle::FetchPolicy(const GURL& url,
+ FetchCallback done,
+ RedirectCallback redirect) {
// Create the traffic annotation
net::NetworkTrafficAnnotationTag traffic_annotation =
net::DefineNetworkTrafficAnnotation("origin_policy_loader", R"(
@@ -187,26 +200,22 @@ void OriginPolicyThrottle::FetchPolicy(const GURL& url, FetchCallback done) {
policy_exception_justification:
"Not implemented, considered not useful."})");
- // Create the SimpleURLLoader for the policy.
+ // Create and configure the SimpleURLLoader for the policy.
std::unique_ptr<network::ResourceRequest> policy_request =
std::make_unique<network::ResourceRequest>();
policy_request->url = url;
policy_request->request_initiator = url::Origin::Create(url);
- policy_request->fetch_credentials_mode =
- network::mojom::FetchCredentialsMode::kOmit;
- policy_request->fetch_redirect_mode =
- network::mojom::FetchRedirectMode::kError;
policy_request->load_flags = net::LOAD_DO_NOT_SEND_COOKIES |
net::LOAD_DO_NOT_SAVE_COOKIES |
net::LOAD_DO_NOT_SEND_AUTH_DATA;
url_loader_ = network::SimpleURLLoader::Create(std::move(policy_request),
traffic_annotation);
+ url_loader_->SetOnRedirectCallback(std::move(redirect));
// Obtain the URLLoaderFactory from the NavigationHandle.
SiteInstance* site_instance = navigation_handle()->GetStartingSiteInstance();
- content::StoragePartition* storage_partition =
- BrowserContext::GetStoragePartition(site_instance->GetBrowserContext(),
- site_instance);
+ StoragePartition* storage_partition = BrowserContext::GetStoragePartition(
+ site_instance->GetBrowserContext(), site_instance);
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory =
storage_partition->GetURLLoaderFactoryForBrowserProcess();
@@ -227,7 +236,7 @@ void OriginPolicyThrottle::OnTheGloriousPolicyHasArrived(
// Fail hard if the policy could not be loaded.
if (!policy_content) {
- CancelDeferredNavigation(NavigationThrottle::CANCEL_AND_IGNORE);
+ CancelNavigation(OriginPolicyErrorReason::kCannotLoadPolicy);
return;
}
@@ -239,4 +248,21 @@ void OriginPolicyThrottle::OnTheGloriousPolicyHasArrived(
Resume();
}
+void OriginPolicyThrottle::OnRedirect(
+ const net::RedirectInfo& redirect_info,
+ const network::ResourceResponseHead& response_head,
+ std::vector<std::string>* to_be_removed_headers) {
+ // Fail hard if the policy response follows a redirect.
+ url_loader_.reset(); // Cancel the request while it's ongoing.
+ CancelNavigation(OriginPolicyErrorReason::kPolicyShouldNotRedirect);
+}
+
+void OriginPolicyThrottle::CancelNavigation(OriginPolicyErrorReason reason) {
+ base::Optional<std::string> error_page =
+ GetContentClient()->browser()->GetOriginPolicyErrorPage(
+ reason, GetRequestOrigin(), navigation_handle()->GetURL());
+ CancelDeferredNavigation(NavigationThrottle::ThrottleCheckResult(
+ NavigationThrottle::CANCEL, net::ERR_BLOCKED_BY_CLIENT, error_page));
+}
+
} // namespace content
diff --git a/chromium/content/browser/frame_host/origin_policy_throttle.h b/chromium/content/browser/frame_host/origin_policy_throttle.h
index 320558cce4e..f142dcfbc5f 100644
--- a/chromium/content/browser/frame_host/origin_policy_throttle.h
+++ b/chromium/content/browser/frame_host/origin_policy_throttle.h
@@ -19,12 +19,17 @@ class GURL;
namespace url {
class Origin;
}
+namespace net {
+struct RedirectInfo;
+} // namespace net
namespace network {
+struct ResourceResponseHead;
class SimpleURLLoader;
} // namespace network
namespace content {
class NavigationHandle;
+enum class OriginPolicyErrorReason;
// The OriginPolicyThrottle is responsible for deciding whether an origin
// policy should be fetched, and doing so when that is positive.
@@ -63,15 +68,25 @@ class CONTENT_EXPORT OriginPolicyThrottle : public NavigationThrottle {
private:
using FetchCallback = base::OnceCallback<void(std::unique_ptr<std::string>)>;
+ using RedirectCallback =
+ base::RepeatingCallback<void(const net::RedirectInfo&,
+ const network::ResourceResponseHead&,
+ std::vector<std::string>*)>;
explicit OriginPolicyThrottle(NavigationHandle* handle);
static KnownVersionMap& GetKnownVersions();
const url::Origin GetRequestOrigin();
- void FetchPolicy(const GURL& url, FetchCallback done);
+ void FetchPolicy(const GURL& url,
+ FetchCallback done,
+ RedirectCallback redirect);
void OnTheGloriousPolicyHasArrived(
std::unique_ptr<std::string> policy_content);
+ void OnRedirect(const net::RedirectInfo& redirect_info,
+ const network::ResourceResponseHead& response_head,
+ std::vector<std::string>* to_be_removed_headers);
+ void CancelNavigation(OriginPolicyErrorReason reason);
// We may need the SimpleURLLoader to download the policy. The loader must
// be kept alive while the load is ongoing.
diff --git a/chromium/content/browser/frame_host/origin_policy_throttle_unittest.cc b/chromium/content/browser/frame_host/origin_policy_throttle_unittest.cc
index 859a318dfc7..8dcc643a765 100644
--- a/chromium/content/browser/frame_host/origin_policy_throttle_unittest.cc
+++ b/chromium/content/browser/frame_host/origin_policy_throttle_unittest.cc
@@ -41,7 +41,7 @@ class OriginPolicyThrottleTest : public RenderViewHostTestHarness,
void CreateHandleFor(const GURL& url) {
net::HttpRequestHeaders headers;
if (OriginPolicyThrottle::ShouldRequestOriginPolicy(url, nullptr))
- headers.SetHeader(net::HttpRequestHeaders::kSecOriginPolicy, "1");
+ headers.SetHeader(net::HttpRequestHeaders::kSecOriginPolicy, "0");
// Except for url and headers (which are determined by the test case)
// all parameters below are cargo-culted from
@@ -101,7 +101,7 @@ TEST_P(OriginPolicyThrottleTest, ShouldRequestLastKnownVersion) {
std::string version;
OriginPolicyThrottle::ShouldRequestOriginPolicy(url, &version);
- EXPECT_EQ(version, "1");
+ EXPECT_EQ(version, "0");
OriginPolicyThrottle::GetKnownVersionsForTesting()[url::Origin::Create(url)] =
"abcd";
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 623cd428e20..b77280ef73f 100644
--- a/chromium/content/browser/frame_host/render_frame_host_delegate.cc
+++ b/chromium/content/browser/frame_host/render_frame_host_delegate.cc
@@ -8,6 +8,7 @@
#include "base/strings/string16.h"
#include "build/build_config.h"
#include "content/browser/frame_host/render_frame_host_delegate.h"
+#include "content/public/browser/file_select_listener.h"
#include "ipc/ipc_message.h"
#include "ui/gfx/native_widget_types.h"
#include "url/gurl.h"
@@ -33,6 +34,13 @@ bool RenderFrameHostDelegate::DidAddMessageToConsole(
return false;
}
+void RenderFrameHostDelegate::RunFileChooser(
+ RenderFrameHost* render_frame_host,
+ std::unique_ptr<FileSelectListener> listener,
+ const blink::mojom::FileChooserParams& params) {
+ listener->FileSelectionCanceled();
+}
+
WebContents* RenderFrameHostDelegate::GetAsWebContents() {
return nullptr;
}
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 9ac81d17f61..61b1c295618 100644
--- a/chromium/content/browser/frame_host/render_frame_host_delegate.h
+++ b/chromium/content/browser/frame_host/render_frame_host_delegate.h
@@ -56,9 +56,13 @@ class Origin;
namespace blink {
struct WebFullscreenOptions;
+namespace mojom {
+class FileChooserParams;
+}
}
namespace content {
+class FileSelectListener;
class FrameTreeNode;
class InterstitialPage;
class PageState;
@@ -69,7 +73,6 @@ class WebContents;
struct AXEventNotificationDetails;
struct AXLocationChangeNotificationDetails;
struct ContextMenuParams;
-struct FileChooserParams;
struct GlobalRequestID;
namespace mojom {
@@ -135,8 +138,12 @@ class CONTENT_EXPORT RenderFrameHostDelegate {
IPC::Message* reply_msg) {}
// Called when a file selection is to be done.
- virtual void RunFileChooser(RenderFrameHost* render_frame_host,
- const FileChooserParams& params) {}
+ // Overrides of this function must call either listener->FileSelected() or
+ // listener->FileSelectionCanceled().
+ virtual void RunFileChooser(
+ RenderFrameHost* render_frame_host,
+ std::unique_ptr<content::FileSelectListener> listener,
+ const blink::mojom::FileChooserParams& params);
// The pending page load was canceled, so the address bar should be updated.
virtual void DidCancelLoading() {}
@@ -238,6 +245,14 @@ class CONTENT_EXPORT RenderFrameHostDelegate {
virtual void FullscreenStateChanged(RenderFrameHost* rfh,
bool is_fullscreen) {}
+#if defined(OS_ANDROID)
+ // Updates information to determine whether a user gesture should carryover to
+ // future navigations. This is needed so navigations within a certain
+ // timeframe of a request initiated by a gesture will be treated as if they
+ // were initiated by a gesture too, otherwise the navigation may be blocked.
+ virtual void UpdateUserGestureCarryoverInfo() {}
+#endif
+
// Let the delegate decide whether postMessage should be delivered to
// |target_rfh| from a source frame in the given SiteInstance. This defaults
// to false and overrides the RenderFrameHost's decision if true.
diff --git a/chromium/content/browser/frame_host/render_frame_host_factory.cc b/chromium/content/browser/frame_host/render_frame_host_factory.cc
index 4276b86c21a..5f8784a5a6d 100644
--- a/chromium/content/browser/frame_host/render_frame_host_factory.cc
+++ b/chromium/content/browser/frame_host/render_frame_host_factory.cc
@@ -19,7 +19,6 @@ std::unique_ptr<RenderFrameHostImpl> RenderFrameHostFactory::Create(
SiteInstance* site_instance,
RenderViewHostImpl* render_view_host,
RenderFrameHostDelegate* delegate,
- RenderWidgetHostDelegate* rwh_delegate,
FrameTree* frame_tree,
FrameTreeNode* frame_tree_node,
int32_t routing_id,
@@ -28,14 +27,12 @@ std::unique_ptr<RenderFrameHostImpl> RenderFrameHostFactory::Create(
bool renderer_initiated_creation) {
if (factory_) {
return factory_->CreateRenderFrameHost(
- site_instance, render_view_host, delegate, rwh_delegate, frame_tree,
- frame_tree_node, routing_id, widget_routing_id, hidden,
- renderer_initiated_creation);
+ site_instance, render_view_host, delegate, frame_tree, frame_tree_node,
+ routing_id, widget_routing_id, hidden, renderer_initiated_creation);
}
return base::WrapUnique(new RenderFrameHostImpl(
- site_instance, render_view_host, delegate, rwh_delegate, frame_tree,
- frame_tree_node, routing_id, widget_routing_id, hidden,
- renderer_initiated_creation));
+ site_instance, render_view_host, delegate, frame_tree, frame_tree_node,
+ routing_id, widget_routing_id, hidden, renderer_initiated_creation));
}
// static
diff --git a/chromium/content/browser/frame_host/render_frame_host_factory.h b/chromium/content/browser/frame_host/render_frame_host_factory.h
index 5fd70cb0d36..9b3c548a925 100644
--- a/chromium/content/browser/frame_host/render_frame_host_factory.h
+++ b/chromium/content/browser/frame_host/render_frame_host_factory.h
@@ -19,7 +19,6 @@ class FrameTreeNode;
class RenderFrameHostDelegate;
class RenderFrameHostImpl;
class RenderViewHostImpl;
-class RenderWidgetHostDelegate;
class SiteInstance;
// A factory for creating RenderFrameHosts. There is a global factory function
@@ -33,7 +32,6 @@ class CONTENT_EXPORT RenderFrameHostFactory {
SiteInstance* site_instance,
RenderViewHostImpl* render_view_host,
RenderFrameHostDelegate* delegate,
- RenderWidgetHostDelegate* rwh_delegate,
FrameTree* frame_tree,
FrameTreeNode* frame_tree_node,
int32_t routing_id,
@@ -54,7 +52,6 @@ class CONTENT_EXPORT RenderFrameHostFactory {
SiteInstance* site_instance,
RenderViewHostImpl* render_view_host,
RenderFrameHostDelegate* delegate,
- RenderWidgetHostDelegate* rwh_delegate,
FrameTree* frame_tree,
FrameTreeNode* frame_tree_node,
int32_t routing_id,
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 e67018e0f80..a17ae7ca0c0 100644
--- a/chromium/content/browser/frame_host/render_frame_host_impl.cc
+++ b/chromium/content/browser/frame_host/render_frame_host_impl.cc
@@ -40,6 +40,7 @@
#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_manager_impl.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"
@@ -84,7 +85,6 @@
#include "content/browser/renderer_host/render_view_host_delegate.h"
#include "content/browser/renderer_host/render_view_host_delegate_view.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
-#include "content/browser/renderer_host/render_widget_host_delegate.h"
#include "content/browser/renderer_host/render_widget_host_factory.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
@@ -119,7 +119,9 @@
#include "content/public/browser/browser_accessibility_state.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_plugin_guest_manager.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/content_browser_client.h"
+#include "content/public/browser/file_select_listener.h"
#include "content/public/browser/permission_type.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_widget_host_view.h"
@@ -132,8 +134,6 @@
#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/file_chooser_file_info.h"
-#include "content/public/common/file_chooser_params.h"
#include "content/public/common/isolated_world_ids.h"
#include "content/public/common/service_manager_connection.h"
#include "content/public/common/service_names.mojom.h"
@@ -150,6 +150,7 @@
#include "media/mojo/services/media_metrics_provider.h"
#include "media/mojo/services/video_decode_perf_history.h"
#include "mojo/public/cpp/bindings/associated_interface_ptr.h"
+#include "mojo/public/cpp/bindings/interface_request.h"
#include "mojo/public/cpp/bindings/message.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "mojo/public/cpp/system/data_pipe.h"
@@ -169,6 +170,7 @@
#include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
#include "third_party/blink/public/common/blob/blob_utils.h"
#include "third_party/blink/public/common/feature_policy/feature_policy.h"
+#include "third_party/blink/public/common/features.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"
@@ -183,6 +185,7 @@
#include "url/url_constants.h"
#if defined(OS_ANDROID)
+#include "content/browser/android/content_url_loader_factory.h"
#include "content/browser/android/java_interfaces_impl.h"
#include "content/browser/frame_host/render_frame_host_android.h"
#include "content/public/browser/android/java_interfaces.h"
@@ -354,8 +357,8 @@ void NotifyForEachFrameFromUI(RenderFrameHostImpl* root_frame_host,
if (pending_frame_host)
routing_ids->insert(pending_frame_host->GetGlobalFrameRoutingId());
}
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&NotifyRouteChangesOnIO, frame_callback,
std::move(routing_ids)));
}
@@ -397,8 +400,8 @@ void NotifyResourceSchedulerOfNavigation(
if (!ui::PageTransitionIsMainFrame(params.transition))
return;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&ResourceSchedulerFilter::OnDidCommitMainframeNavigation,
render_process_id, params.render_view_routing_id));
}
@@ -426,6 +429,24 @@ void LogRendererKillCrashKeys(const GURL& site_url) {
base::debug::SetCrashKeyString(site_url_key, site_url.spec());
}
+url::Origin GetOriginForURLLoaderFactory(GURL target_url,
+ SiteInstanceImpl* site_instance) {
+ // Calculate the origin that will be used as a fallback for URLs such as
+ // about:blank and/or data:. If full site isolation is enabled, then
+ // |site_instance|-based origin will be correct. Otherwise, falling back to a
+ // unique/opaque origin should be safe.
+ //
+ // TODO(lukasza, nasko): https://crbug.com/888079: Do not fall back to
+ // |site_instance| - instead the browser process should already know at
+ // ready-to-commit time the origin to be committed.
+ url::Origin fallback_origin =
+ SiteIsolationPolicy::UseDedicatedProcessesForAllSites()
+ ? url::Origin::Create(site_instance->GetSiteURL())
+ : url::Origin();
+
+ return url::Origin::Resolve(target_url, fallback_origin);
+}
+
} // namespace
class RenderFrameHostImpl::DroppedInterfaceRequestLogger
@@ -467,23 +488,120 @@ struct PendingNavigation {
mojom::BeginNavigationParamsPtr begin_navigation_params;
scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory;
mojom::NavigationClientAssociatedPtrInfo navigation_client;
+ blink::mojom::NavigationInitiatorPtr navigation_initiator;
PendingNavigation(
CommonNavigationParams common_params,
mojom::BeginNavigationParamsPtr begin_navigation_params,
scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
- mojom::NavigationClientAssociatedPtrInfo navigation_client);
+ mojom::NavigationClientAssociatedPtrInfo navigation_client,
+ blink::mojom::NavigationInitiatorPtr navigation_initiator);
};
PendingNavigation::PendingNavigation(
CommonNavigationParams common_params,
mojom::BeginNavigationParamsPtr begin_navigation_params,
scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
- mojom::NavigationClientAssociatedPtrInfo navigation_client)
+ mojom::NavigationClientAssociatedPtrInfo navigation_client,
+ blink::mojom::NavigationInitiatorPtr navigation_initiator)
: common_params(common_params),
begin_navigation_params(std::move(begin_navigation_params)),
blob_url_loader_factory(std::move(blob_url_loader_factory)),
- navigation_client(std::move(navigation_client)) {}
+ navigation_client(std::move(navigation_client)),
+ navigation_initiator(std::move(navigation_initiator)) {}
+
+class FileChooserImpl : public content::FileSelectListener,
+ private content::WebContentsObserver {
+ public:
+ FileChooserImpl(RenderFrameHostImpl* render_frame_host)
+ : render_frame_host_(render_frame_host) {
+ Observe(WebContents::FromRenderFrameHost(render_frame_host));
+ }
+
+ ~FileChooserImpl() override {
+#if DCHECK_IS_ON()
+ DCHECK(was_file_select_listener_function_called_)
+ << "Should call either FileSelectListener::FileSelected() or "
+ "FileSelectListener::FileSelectionCanceled()";
+#endif
+ }
+
+ // FileSelectListener overrides:
+
+ void FileSelected(std::vector<blink::mojom::FileChooserFileInfoPtr> files,
+ blink::mojom::FileChooserParams::Mode mode) override {
+#if DCHECK_IS_ON()
+ DCHECK(!was_file_select_listener_function_called_)
+ << "Should not call both of FileSelectListener::FileSelected() and "
+ "FileSelectListener::FileSelectionCanceled()";
+ was_file_select_listener_function_called_ = true;
+#endif
+ if (!render_frame_host_)
+ return;
+ storage::FileSystemContext* file_system_context = nullptr;
+ const int pid = render_frame_host_->GetProcess()->GetID();
+ auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
+ // Grant the security access requested to the given files.
+ for (const auto& file : files) {
+ if (mode == blink::mojom::FileChooserParams::Mode::kSave) {
+ policy->GrantCreateReadWriteFile(pid,
+ file->get_native_file()->file_path);
+ } else {
+ if (file->is_file_system()) {
+ if (!file_system_context) {
+ file_system_context =
+ BrowserContext::GetStoragePartition(
+ render_frame_host_->GetProcess()->GetBrowserContext(),
+ render_frame_host_->GetSiteInstance())
+ ->GetFileSystemContext();
+ }
+ policy->GrantReadFileSystem(
+ pid, file_system_context->CrackURL(file->get_file_system()->url)
+ .mount_filesystem_id());
+ } else {
+ policy->GrantReadFile(pid, file->get_native_file()->file_path);
+ }
+ }
+ }
+ render_frame_host_->Send(new FrameMsg_RunFileChooserResponse(
+ render_frame_host_->routing_id(), files));
+ }
+
+ void FileSelectionCanceled() override {
+#if DCHECK_IS_ON()
+ DCHECK(!was_file_select_listener_function_called_)
+ << "Should not call both of FileSelectListener::FileSelected() and "
+ "FileSelectListener::FileSelectionCanceled()";
+ was_file_select_listener_function_called_ = true;
+#endif
+ if (!render_frame_host_)
+ return;
+ render_frame_host_->Send(new FrameMsg_RunFileChooserResponse(
+ render_frame_host_->routing_id(),
+ std::vector<blink::mojom::FileChooserFileInfoPtr>()));
+ }
+
+ private:
+ // content::WebContentsObserver overrides:
+
+ void RenderFrameHostChanged(RenderFrameHost* old_host,
+ RenderFrameHost* new_host) override {
+ if (old_host == render_frame_host_)
+ render_frame_host_ = nullptr;
+ }
+
+ void RenderFrameDeleted(RenderFrameHost* render_frame_host) override {
+ if (render_frame_host == render_frame_host_)
+ render_frame_host_ = nullptr;
+ }
+
+ void WebContentsDestroyed() override { render_frame_host_ = nullptr; }
+
+ RenderFrameHostImpl* render_frame_host_;
+#if DCHECK_IS_ON()
+ bool was_file_select_listener_function_called_ = false;
+#endif
+};
// static
RenderFrameHost* RenderFrameHost::FromID(int render_process_id,
@@ -503,20 +621,18 @@ RenderFrameHostImpl* RenderFrameHostImpl::FromID(int process_id,
int routing_id) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
RoutingIDFrameMap* frames = g_routing_id_frame_map.Pointer();
- RoutingIDFrameMap::iterator it = frames->find(
- RenderFrameHostID(process_id, routing_id));
+ auto it = frames->find(RenderFrameHostID(process_id, routing_id));
return it == frames->end() ? NULL : it->second;
}
// static
-RenderFrameHost* RenderFrameHost::FromAXTreeID(
- int ax_tree_id) {
+RenderFrameHost* RenderFrameHost::FromAXTreeID(ui::AXTreeID ax_tree_id) {
return RenderFrameHostImpl::FromAXTreeID(ax_tree_id);
}
// static
RenderFrameHostImpl* RenderFrameHostImpl::FromAXTreeID(
- ui::AXTreeIDRegistry::AXTreeID ax_tree_id) {
+ ui::AXTreeID ax_tree_id) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
ui::AXTreeIDRegistry::FrameID frame_id =
ui::AXTreeIDRegistry::GetInstance()->GetFrameID(ax_tree_id);
@@ -547,7 +663,6 @@ void RenderFrameHostImpl::SetNetworkFactoryForTesting(
RenderFrameHostImpl::RenderFrameHostImpl(SiteInstance* site_instance,
RenderViewHostImpl* render_view_host,
RenderFrameHostDelegate* delegate,
- RenderWidgetHostDelegate* rwh_delegate,
FrameTree* frame_tree,
FrameTreeNode* frame_tree_node,
int32_t routing_id,
@@ -566,6 +681,7 @@ RenderFrameHostImpl::RenderFrameHostImpl(SiteInstance* site_instance,
is_waiting_for_swapout_ack_(false),
render_frame_created_(false),
is_waiting_for_beforeunload_ack_(false),
+ beforeunload_dialog_request_cancels_unload_(false),
unload_ack_is_for_navigation_(false),
beforeunload_timeout_delay_(base::TimeDelta::FromMilliseconds(
RenderViewHostImpl::kUnloadTimeoutMS)),
@@ -574,7 +690,7 @@ RenderFrameHostImpl::RenderFrameHostImpl(SiteInstance* site_instance,
nav_entry_id_(0),
accessibility_reset_token_(0),
accessibility_reset_count_(0),
- browser_plugin_embedder_ax_tree_id_(ui::AXTreeIDRegistry::kNoAXTreeID),
+ browser_plugin_embedder_ax_tree_id_(ui::AXTreeIDUnknown()),
no_create_browser_accessibility_manager_for_testing_(false),
web_ui_type_(WebUI::kNoWebUI),
pending_web_ui_type_(WebUI::kNoWebUI),
@@ -643,8 +759,8 @@ RenderFrameHostImpl::RenderFrameHostImpl(SiteInstance* site_instance,
if (!render_widget_host_) {
DCHECK(frame_tree_node->parent());
render_widget_host_ = RenderWidgetHostFactory::Create(
- rwh_delegate, GetProcess(), widget_routing_id, std::move(widget),
- hidden);
+ frame_tree_->render_widget_delegate(), GetProcess(),
+ widget_routing_id, std::move(widget), hidden);
render_widget_host_->set_owned_by_render_frame_host(true);
} else {
DCHECK(!render_widget_host_->owned_by_render_frame_host());
@@ -768,7 +884,7 @@ int RenderFrameHostImpl::GetRoutingID() {
return routing_id_;
}
-ui::AXTreeIDRegistry::AXTreeID RenderFrameHostImpl::GetAXTreeID() {
+ui::AXTreeID RenderFrameHostImpl::GetAXTreeID() {
return ax_tree_id_;
}
@@ -809,6 +925,18 @@ RenderFrameHostImpl* RenderFrameHostImpl::GetParent() {
return parent_;
}
+bool RenderFrameHostImpl::IsDescendantOf(RenderFrameHost* ancestor) {
+ if (!ancestor || !static_cast<RenderFrameHostImpl*>(ancestor)->child_count())
+ return false;
+
+ for (RenderFrameHostImpl* current = GetParent(); current;
+ current = current->GetParent()) {
+ if (current == ancestor)
+ return true;
+ }
+ return false;
+}
+
int RenderFrameHostImpl::GetFrameTreeNodeId() {
return frame_tree_node_->frame_tree_node_id();
}
@@ -867,7 +995,32 @@ void RenderFrameHostImpl::ExecuteMediaPlayerActionAtLocation(
bool RenderFrameHostImpl::CreateNetworkServiceDefaultFactory(
network::mojom::URLLoaderFactoryRequest default_factory_request) {
return CreateNetworkServiceDefaultFactoryInternal(
- last_committed_url_, std::move(default_factory_request));
+ last_committed_origin_, std::move(default_factory_request));
+}
+
+void RenderFrameHostImpl::MarkInitiatorsAsRequiringSeparateURLLoaderFactory(
+ std::vector<url::Origin> request_initiators,
+ bool push_to_renderer_now) {
+ size_t old_size = initiators_requiring_separate_url_loader_factory_.size();
+ initiators_requiring_separate_url_loader_factory_.insert(
+ request_initiators.begin(), request_initiators.end());
+ size_t new_size = initiators_requiring_separate_url_loader_factory_.size();
+ bool insertion_took_place = (old_size != new_size);
+ if (push_to_renderer_now && insertion_took_place)
+ UpdateSubresourceLoaderFactories();
+}
+
+URLLoaderFactoryBundleInfo::OriginMap
+RenderFrameHostImpl::CreateInitiatorSpecificURLLoaderFactories() {
+ URLLoaderFactoryBundleInfo::OriginMap result;
+ for (const url::Origin& initiator :
+ initiators_requiring_separate_url_loader_factory_) {
+ network::mojom::URLLoaderFactoryPtrInfo factory_info;
+ CreateNetworkServiceDefaultFactoryInternal(
+ initiator, mojo::MakeRequest(&factory_info));
+ result[initiator] = std::move(factory_info);
+ }
+ return result;
}
gfx::NativeView RenderFrameHostImpl::GetNativeView() {
@@ -1065,8 +1218,6 @@ bool RenderFrameHostImpl::OnMessageReceived(const IPC::Message &msg) {
OnDidAddMessageToConsole)
IPC_MESSAGE_HANDLER(FrameHostMsg_Detach, OnDetach)
IPC_MESSAGE_HANDLER(FrameHostMsg_FrameFocused, OnFrameFocused)
- IPC_MESSAGE_HANDLER(FrameHostMsg_DidStartProvisionalLoad,
- OnDidStartProvisionalLoad)
IPC_MESSAGE_HANDLER(FrameHostMsg_DidFailProvisionalLoadWithError,
OnDidFailProvisionalLoadWithError)
IPC_MESSAGE_HANDLER(FrameHostMsg_DidFailLoadWithError,
@@ -1117,7 +1268,6 @@ bool RenderFrameHostImpl::OnMessageReceived(const IPC::Message &msg) {
IPC_MESSAGE_HANDLER(FrameHostMsg_ExitFullscreen, OnExitFullscreen)
IPC_MESSAGE_HANDLER(FrameHostMsg_SuddenTerminationDisablerChanged,
OnSuddenTerminationDisablerChanged)
- IPC_MESSAGE_HANDLER(FrameHostMsg_DidStartLoading, OnDidStartLoading)
IPC_MESSAGE_HANDLER(FrameHostMsg_DidStopLoading, OnDidStopLoading)
IPC_MESSAGE_HANDLER(FrameHostMsg_DidChangeLoadProgress,
OnDidChangeLoadProgress)
@@ -1461,7 +1611,8 @@ void RenderFrameHostImpl::Init() {
frame_tree_node(), pending_navigate_->common_params,
std::move(pending_navigate_->begin_navigation_params),
std::move(pending_navigate_->blob_url_loader_factory),
- std::move(pending_navigate_->navigation_client));
+ std::move(pending_navigate_->navigation_client),
+ std::move(pending_navigate_->navigation_initiator));
pending_navigate_.reset();
}
}
@@ -1581,6 +1732,51 @@ void RenderFrameHostImpl::SetLastCommittedOriginForTesting(
SetLastCommittedOrigin(origin);
}
+FrameTreeNode* RenderFrameHostImpl::AddChild(
+ std::unique_ptr<FrameTreeNode> child,
+ int process_id,
+ int frame_routing_id) {
+ // Child frame must always be created in the same process as the parent.
+ CHECK_EQ(process_id, GetProcess()->GetID());
+
+ // Initialize the RenderFrameHost for the new node. We always create child
+ // frames in the same SiteInstance as the current frame, and they can swap to
+ // a different one if they navigate away.
+ child->render_manager()->Init(GetSiteInstance(),
+ render_view_host()->GetRoutingID(),
+ frame_routing_id, MSG_ROUTING_NONE, false);
+
+ // Other renderer processes in this BrowsingInstance may need to find out
+ // about the new frame. Create a proxy for the child frame in all
+ // SiteInstances that have a proxy for the frame's parent, since all frames
+ // in a frame tree should have the same set of proxies.
+ frame_tree_node_->render_manager()->CreateProxiesForChildFrame(child.get());
+
+ children_.push_back(std::move(child));
+
+ return children_.back().get();
+}
+
+void RenderFrameHostImpl::RemoveChild(FrameTreeNode* child) {
+ for (auto iter = children_.begin(); iter != children_.end(); ++iter) {
+ if (iter->get() == child) {
+ // Subtle: we need to make sure the node is gone from the tree before
+ // observers are notified of its deletion.
+ std::unique_ptr<FrameTreeNode> node_to_delete(std::move(*iter));
+ children_.erase(iter);
+ node_to_delete.reset();
+ return;
+ }
+ }
+}
+
+void RenderFrameHostImpl::ResetChildren() {
+ // Remove child nodes from the tree, then delete them. This destruction
+ // operation will notify observers. See https://crbug.com/612450 for
+ // explanation why we don't just call the std::vector::clear method.
+ std::vector<std::unique_ptr<FrameTreeNode>>().swap(children_);
+}
+
void RenderFrameHostImpl::SetLastCommittedUrl(const GURL& url) {
last_committed_url_ = url;
}
@@ -1653,24 +1849,6 @@ void RenderFrameHostImpl::OnDocumentOnLoadCompleted() {
delegate_->DocumentOnLoadCompleted(this);
}
-void RenderFrameHostImpl::OnDidStartProvisionalLoad(
- const GURL& url,
- const std::vector<GURL>& redirect_chain,
- const base::TimeTicks& navigation_start) {
- // TODO(clamy): Check if other navigation methods (OpenURL,
- // DidFailProvisionalLoad, ...) should also be ignored if the RFH is no longer
- // active.
- if (!is_active())
- return;
-
- TRACE_EVENT2("navigation", "RenderFrameHostImpl::OnDidStartProvisionalLoad",
- "frame_tree_node", frame_tree_node_->frame_tree_node_id(), "url",
- url.possibly_invalid_spec());
-
- frame_tree_node_->navigator()->DidStartProvisionalLoad(
- this, url, redirect_chain, navigation_start);
-}
-
void RenderFrameHostImpl::OnDidFailProvisionalLoadWithError(
const FrameHostMsg_DidFailProvisionalLoadWithError_Params& params) {
TRACE_EVENT2("navigation",
@@ -2252,8 +2430,7 @@ void RenderFrameHostImpl::OnJavaScriptExecuteResponse(
return;
}
- std::map<int, JavaScriptResultCallback>::iterator it =
- javascript_callbacks_.find(id);
+ auto it = javascript_callbacks_.find(id);
if (it != javascript_callbacks_.end()) {
it->second.Run(result_value);
javascript_callbacks_.erase(it);
@@ -2325,6 +2502,15 @@ void RenderFrameHostImpl::OnRunBeforeUnloadConfirm(
// Allow at most one attempt to show a beforeunload dialog per navigation.
RenderFrameHostImpl* beforeunload_initiator = GetBeforeUnloadInitiator();
if (beforeunload_initiator) {
+ // If the running beforeunload handler wants to display a dialog and the
+ // before-unload type wants to ignore it, then short-circuit the request and
+ // respond as if the user decided to stay on the page, canceling the unload.
+ if (beforeunload_initiator->beforeunload_dialog_request_cancels_unload_) {
+ SendJavaScriptDialogReply(reply_msg, false /* success */,
+ base::string16());
+ return;
+ }
+
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
@@ -2361,17 +2547,20 @@ void RenderFrameHostImpl::OnRunBeforeUnloadConfirm(
delegate_->RunBeforeUnloadConfirm(this, is_reload, reply_msg);
}
-void RenderFrameHostImpl::OnRunFileChooser(const FileChooserParams& params) {
+void RenderFrameHostImpl::OnRunFileChooser(
+ const blink::mojom::FileChooserParams& params) {
+ auto listener = std::make_unique<FileChooserImpl>(this);
// Do not allow messages with absolute paths in them as this can permit a
// renderer to coerce the browser to perform I/O on a renderer controlled
// path.
if (params.default_file_name != params.default_file_name.BaseName()) {
bad_message::ReceivedBadMessage(GetProcess(),
bad_message::RFH_FILE_CHOOSER_PATH);
+ listener->FileSelectionCanceled();
return;
}
- delegate_->RunFileChooser(this, params);
+ delegate_->RunFileChooser(this, std::move(listener), params);
}
void RenderFrameHostImpl::RequestTextSurroundingSelection(
@@ -2631,6 +2820,12 @@ void RenderFrameHostImpl::FullscreenStateChanged(bool is_fullscreen) {
delegate_->FullscreenStateChanged(this, is_fullscreen);
}
+#if defined(OS_ANDROID)
+void RenderFrameHostImpl::UpdateUserGestureCarryoverInfo() {
+ delegate_->UpdateUserGestureCarryoverInfo();
+}
+#endif
+
void RenderFrameHostImpl::OnDidBlockFramebust(const GURL& url) {
delegate_->OnDidBlockFramebust(url);
}
@@ -2948,29 +3143,6 @@ void RenderFrameHostImpl::OnExitFullscreen() {
render_view_host_->GetWidget()->SynchronizeVisualProperties();
}
-// TODO(clamy): Remove this IPC now that it is only used for same-document
-// navigations.
-void RenderFrameHostImpl::OnDidStartLoading(bool to_different_document) {
- TRACE_EVENT2("navigation", "RenderFrameHostImpl::OnDidStartLoading",
- "frame_tree_node", frame_tree_node_->frame_tree_node_id(),
- "to different document", to_different_document);
-
- if (to_different_document) {
- bad_message::ReceivedBadMessage(GetProcess(),
- bad_message::RFH_UNEXPECTED_LOAD_START);
- return;
- }
- bool was_previously_loading = frame_tree_node_->frame_tree()->IsLoading();
- is_loading_ = true;
-
- // Only inform the FrameTreeNode of a change in load state if the load state
- // of this RenderFrameHost is being tracked.
- if (is_active()) {
- frame_tree_node_->DidStartLoading(to_different_document,
- was_previously_loading);
- }
-}
-
void RenderFrameHostImpl::OnSuddenTerminationDisablerChanged(
bool present,
blink::WebSuddenTerminationDisablerType disabler_type) {
@@ -3252,8 +3424,8 @@ void RenderFrameHostImpl::CreateNewWindow(
rdh->BlockRequestsForRoute(id);
},
GlobalFrameRoutingId(render_process_id, main_frame_route_id));
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- std::move(block_requests_for_route));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO},
+ std::move(block_requests_for_route));
}
}
@@ -3329,7 +3501,8 @@ void RenderFrameHostImpl::BeginNavigation(
const CommonNavigationParams& common_params,
mojom::BeginNavigationParamsPtr begin_params,
blink::mojom::BlobURLTokenPtr blob_url_token,
- mojom::NavigationClientAssociatedPtrInfo navigation_client) {
+ mojom::NavigationClientAssociatedPtrInfo navigation_client,
+ blink::mojom::NavigationInitiatorPtr navigation_initiator) {
if (!is_active())
return;
@@ -3393,13 +3566,15 @@ void RenderFrameHostImpl::BeginNavigation(
if (waiting_for_init_) {
pending_navigate_ = std::make_unique<PendingNavigation>(
validated_params, std::move(begin_params),
- std::move(blob_url_loader_factory), std::move(navigation_client));
+ std::move(blob_url_loader_factory), std::move(navigation_client),
+ std::move(navigation_initiator));
return;
}
frame_tree_node()->navigator()->OnBeginNavigation(
frame_tree_node(), validated_params, std::move(begin_params),
- std::move(blob_url_loader_factory), std::move(navigation_client));
+ std::move(blob_url_loader_factory), std::move(navigation_client),
+ std::move(navigation_initiator));
}
void RenderFrameHostImpl::SubresourceResponseStarted(
@@ -3509,10 +3684,8 @@ void RenderFrameHostImpl::RegisterMojoInterfaces() {
base::BindRepeating(&RenderFrameHostImpl::CreateAudioOutputStreamFactory,
base::Unretained(this)));
- if (resource_coordinator::IsResourceCoordinatorEnabled()) {
- registry_->AddInterface(
- base::Bind(&CreateFrameResourceCoordinator, base::Unretained(this)));
- }
+ registry_->AddInterface(
+ base::Bind(&CreateFrameResourceCoordinator, base::Unretained(this)));
// BrowserMainLoop::GetInstance() may be null on unit tests.
if (BrowserMainLoop::GetInstance()) {
@@ -3524,15 +3697,14 @@ void RenderFrameHostImpl::RegisterMojoInterfaces() {
BrowserMainLoop::GetInstance()->media_stream_manager();
registry_->AddInterface(
base::Bind(&MediaDevicesDispatcherHost::Create, GetProcess()->GetID(),
- GetRoutingID(),
- base::Unretained(media_stream_manager)),
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO));
+ GetRoutingID(), base::Unretained(media_stream_manager)),
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO}));
registry_->AddInterface(
base::BindRepeating(
&RenderFrameHostImpl::CreateMediaStreamDispatcherHost,
base::Unretained(this), base::Unretained(media_stream_manager)),
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO));
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO}));
}
#if BUILDFLAG(ENABLE_MEDIA_REMOTING)
@@ -3599,7 +3771,16 @@ void RenderFrameHostImpl::RegisterMojoInterfaces() {
registry_->AddInterface(
base::BindRepeating(SpeechRecognitionDispatcherHost::Create,
GetProcess()->GetID(), routing_id_),
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO));
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO}));
+
+ file_system_manager_.reset(new FileSystemManagerImpl(
+ GetProcess()->GetID(), routing_id_,
+ GetProcess()->GetStoragePartition()->GetFileSystemContext(),
+ ChromeBlobStorageContext::GetFor(GetProcess()->GetBrowserContext())));
+ registry_->AddInterface(
+ base::BindRepeating(&FileSystemManagerImpl::BindRequest,
+ base::Unretained(file_system_manager_.get())),
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO}));
if (Portal::IsEnabled()) {
registry_->AddInterface(base::BindRepeating(IgnoreResult(&Portal::Create),
@@ -3650,7 +3831,7 @@ bool RenderFrameHostImpl::CanCommitOrigin(
// It is safe to commit into a unique origin, regardless of the URL, as it is
// restricted from accessing other origins.
- if (origin.unique())
+ if (origin.opaque())
return true;
// Standard URLs must match the reported origin.
@@ -3673,13 +3854,10 @@ void RenderFrameHostImpl::NavigateToInterstitialURL(const GURL& data_url) {
DCHECK(data_url.SchemeIs(url::kDataScheme));
CommonNavigationParams common_params(
data_url, Referrer(), ui::PAGE_TRANSITION_LINK,
- FrameMsg_Navigate_Type::DIFFERENT_DOCUMENT, false, false,
- GURL(), GURL(), PREVIEWS_OFF, base::TimeTicks::Now(), "GET", nullptr,
- base::Optional<SourceLocation>(),
- CSPDisposition::CHECK /* should_check_main_world_csp */,
- false /* started_from_context_menu */, false /* has_user_gesture */,
- std::vector<ContentSecurityPolicy>() /* initiator_csp */,
- CSPSource() /* initiator_self_source */);
+ FrameMsg_Navigate_Type::DIFFERENT_DOCUMENT, false, false, GURL(), GURL(),
+ PREVIEWS_OFF, base::TimeTicks::Now(), "GET", nullptr,
+ base::Optional<SourceLocation>(), false /* started_from_context_menu */,
+ false /* has_user_gesture */, InitiatorCSPInfo());
CommitNavigation(0, nullptr, network::mojom::URLLoaderClientEndpointsPtr(),
common_params, RequestNavigationParams(), false,
base::nullopt, base::nullopt /* subresource_overrides */,
@@ -3699,8 +3877,9 @@ void RenderFrameHostImpl::DispatchBeforeUnload(BeforeUnloadType type,
type == BeforeUnloadType::RENDERER_INITIATED_NAVIGATION;
DCHECK(for_navigation || !is_reload);
- // Tab close should only dispatch beforeunload on main frames.
- DCHECK(type != BeforeUnloadType::TAB_CLOSE ||
+ // TAB_CLOSE and DISCARD should only dispatch beforeunload on main frames.
+ DCHECK(type == BeforeUnloadType::BROWSER_INITIATED_NAVIGATION ||
+ type == BeforeUnloadType::RENDERER_INITIATED_NAVIGATION ||
frame_tree_node_->IsMainFrame());
if (!for_navigation) {
@@ -3757,13 +3936,16 @@ void RenderFrameHostImpl::DispatchBeforeUnload(BeforeUnloadType type,
// Start the hang monitor in case the renderer hangs in the beforeunload
// handler.
is_waiting_for_beforeunload_ack_ = true;
+ beforeunload_dialog_request_cancels_unload_ = false;
unload_ack_is_for_navigation_ = for_navigation;
send_before_unload_start_time_ = base::TimeTicks::Now();
if (render_view_host_->GetDelegate()->IsJavaScriptDialogShowing()) {
// If there is a JavaScript dialog up, don't bother sending the renderer
// the unload event because it is known unresponsive, waiting for the
- // reply from the dialog.
- SimulateBeforeUnloadAck();
+ // reply from the dialog. If this incoming request is for a DISCARD be
+ // sure to reply with |proceed = false|, because the presence of a dialog
+ // indicates that the page can't be discarded.
+ SimulateBeforeUnloadAck(type != BeforeUnloadType::DISCARD);
} else {
// Start a timer that will be shared by all frames that need to run
// beforeunload in the current frame's subtree.
@@ -3771,6 +3953,8 @@ void RenderFrameHostImpl::DispatchBeforeUnload(BeforeUnloadType type,
beforeunload_timeout_->Start(beforeunload_timeout_delay_);
beforeunload_pending_replies_.clear();
+ beforeunload_dialog_request_cancels_unload_ =
+ (type == BeforeUnloadType::DISCARD);
// Run beforeunload in this frame and its cross-process descendant
// frames, in parallel.
@@ -3843,8 +4027,7 @@ bool RenderFrameHostImpl::CheckOrDispatchBeforeUnloadForSubtree(
// 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()) &&
+ if (rfh->IsDescendantOf(added_rfh) &&
rfh->GetSiteInstance() == added_rfh->GetSiteInstance()) {
has_same_site_ancestor = true;
break;
@@ -3863,7 +4046,7 @@ bool RenderFrameHostImpl::CheckOrDispatchBeforeUnloadForSubtree(
return found_beforeunload;
}
-void RenderFrameHostImpl::SimulateBeforeUnloadAck() {
+void RenderFrameHostImpl::SimulateBeforeUnloadAck(bool proceed) {
DCHECK(is_waiting_for_beforeunload_ack_);
base::TimeTicks approx_renderer_start_time = send_before_unload_start_time_;
@@ -3871,7 +4054,7 @@ void RenderFrameHostImpl::SimulateBeforeUnloadAck() {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::BindOnce(&RenderFrameHostImpl::ProcessBeforeUnloadACK,
- weak_ptr_factory_.GetWeakPtr(), true /* proceed */,
+ weak_ptr_factory_.GetWeakPtr(), proceed,
true /* treat_as_final_ack */, approx_renderer_start_time,
base::TimeTicks::Now()));
}
@@ -4023,7 +4206,7 @@ void RenderFrameHostImpl::CommitNavigation(
} else {
// This is a webui scheme that doesn't have webui bindings. Give it
// access to the network loader as it might require it.
- subresource_loader_factories->factories_info().emplace(
+ subresource_loader_factories->scheme_specific_factory_infos().emplace(
scheme, factory_for_webui.PassInterface());
}
}
@@ -4034,7 +4217,9 @@ void RenderFrameHostImpl::CommitNavigation(
// appropriate NetworkContext.
bool bypass_redirect_checks =
CreateNetworkServiceDefaultFactoryAndObserve(
- common_params.url, mojo::MakeRequest(&default_factory_info));
+ GetOriginForURLLoaderFactory(common_params.url,
+ GetSiteInstance()),
+ mojo::MakeRequest(&default_factory_info));
subresource_loader_factories->set_bypass_redirect_checks(
bypass_redirect_checks);
}
@@ -4056,6 +4241,18 @@ void RenderFrameHostImpl::CommitNavigation(
std::move(file_factory));
}
+#if defined(OS_ANDROID)
+ if (common_params.url.SchemeIs(url::kContentScheme)) {
+ // Only content:// URLs can load content:// subresources
+ auto content_factory = std::make_unique<ContentURLLoaderFactory>(
+ base::CreateSequencedTaskRunnerWithTraits(
+ {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+ base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}));
+ non_network_url_loader_factories_.emplace(url::kContentScheme,
+ std::move(content_factory));
+ }
+#endif
+
StoragePartition* partition =
BrowserContext::GetStoragePartition(browser_context, GetSiteInstance());
std::string storage_domain;
@@ -4081,16 +4278,20 @@ void RenderFrameHostImpl::CommitNavigation(
network::mojom::URLLoaderFactoryPtrInfo factory_proxy_info;
auto factory_request = mojo::MakeRequest(&factory_proxy_info);
GetContentClient()->browser()->WillCreateURLLoaderFactory(
- browser_context, this, false /* is_navigation */, common_params.url,
- &factory_request);
+ browser_context, this, false /* is_navigation */,
+ GetOriginForURLLoaderFactory(common_params.url, GetSiteInstance()),
+ &factory_request, nullptr /* bypass_redirect_checks */);
// Keep DevTools proxy lasy, i.e. closest to the network.
RenderFrameDevToolsAgentHost::WillCreateURLLoaderFactory(
this, false /* is_navigation */, false /* is_download */,
&factory_request);
factory.second->Clone(std::move(factory_request));
- subresource_loader_factories->factories_info().emplace(
+ subresource_loader_factories->scheme_specific_factory_infos().emplace(
factory.first, std::move(factory_proxy_info));
}
+
+ subresource_loader_factories->initiator_specific_factory_infos() =
+ CreateInitiatorSpecificURLLoaderFactories();
}
// It is imperative that cross-document navigations always provide a set of
@@ -4123,25 +4324,42 @@ void RenderFrameHostImpl::CommitNavigation(
}
}
+ std::unique_ptr<URLLoaderFactoryBundleInfo> factory_bundle_for_prefetch;
network::mojom::URLLoaderFactoryPtr prefetch_loader_factory;
if (subresource_loader_factories) {
SaveSubresourceFactories(std::move(subresource_loader_factories));
+ factory_bundle_for_prefetch = CloneSubresourceFactories();
+ } else if (base::FeatureList::IsEnabled(
+ blink::features::kServiceWorkerServicification) &&
+ (!is_same_document || is_first_navigation)) {
+ DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
+ factory_bundle_for_prefetch =
+ std::make_unique<URLLoaderFactoryBundleInfo>();
+ network::mojom::URLLoaderFactoryPtrInfo factory_info;
+ CreateNetworkServiceDefaultFactoryInternal(
+ url::Origin(), mojo::MakeRequest(&factory_info));
+ factory_bundle_for_prefetch->default_factory_info() =
+ std::move(factory_info);
+ }
+ if (factory_bundle_for_prefetch) {
// Also set-up URLLoaderFactory for prefetch using the same loader
// factories. TODO(kinuko): Consider setting this up only when prefetch
// is used. Currently we have this here to make sure we have non-racy
// situation (https://crbug.com/849929).
- DCHECK(base::FeatureList::IsEnabled(network::features::kNetworkService));
+ DCHECK(base::FeatureList::IsEnabled(network::features::kNetworkService) ||
+ base::FeatureList::IsEnabled(
+ blink::features::kServiceWorkerServicification));
auto* storage_partition = static_cast<StoragePartitionImpl*>(
BrowserContext::GetStoragePartition(
GetSiteInstance()->GetBrowserContext(), GetSiteInstance()));
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&PrefetchURLLoaderService::GetFactory,
storage_partition->GetPrefetchURLLoaderService(),
mojo::MakeRequest(&prefetch_loader_factory),
frame_tree_node_->frame_tree_node_id(),
- CloneSubresourceFactories()));
+ std::move(factory_bundle_for_prefetch)));
}
auto find_request = navigation_requests_.find(navigation_id);
@@ -4175,8 +4393,8 @@ void RenderFrameHostImpl::CommitNavigation(
// it until its request endpoint is sent. Now that the request endpoint was
// sent, it can be used, so add it to ServiceWorkerObjectHost.
if (remote_object.is_valid()) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&ServiceWorkerObjectHost::AddRemoteObjectPtrAndUpdateState,
subresource_loader_params->controller_service_worker_object_host,
@@ -4210,15 +4428,21 @@ void RenderFrameHostImpl::FailedNavigation(
// completing an unload handler.
ResetWaitingState();
+ // Error page will commit in an opaque origin.
+ //
+ // TODO(lukasza): https://crbug.com/888079: Use this origin when committing
+ // later on.
+ url::Origin origin = url::Origin();
+
std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories;
if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
network::mojom::URLLoaderFactoryPtrInfo default_factory_info;
bool bypass_redirect_checks = CreateNetworkServiceDefaultFactoryAndObserve(
- common_params.url, mojo::MakeRequest(&default_factory_info));
+ origin, mojo::MakeRequest(&default_factory_info));
subresource_loader_factories = std::make_unique<URLLoaderFactoryBundleInfo>(
std::move(default_factory_info),
- std::map<std::string, network::mojom::URLLoaderFactoryPtrInfo>(),
- bypass_redirect_checks);
+ URLLoaderFactoryBundleInfo::SchemeMap(),
+ URLLoaderFactoryBundleInfo::OriginMap(), bypass_redirect_checks);
}
SaveSubresourceFactories(std::move(subresource_loader_factories));
@@ -4311,10 +4535,12 @@ void RenderFrameHostImpl::InvalidateMojoConnection() {
}
bool RenderFrameHostImpl::IsFocused() {
- return GetRenderWidgetHost()->is_focused() &&
- frame_tree_->GetFocusedFrame() &&
- (frame_tree_->GetFocusedFrame() == frame_tree_node() ||
- frame_tree_->GetFocusedFrame()->IsDescendantOf(frame_tree_node()));
+ if (!GetRenderWidgetHost()->is_focused() || !frame_tree_->GetFocusedFrame())
+ return false;
+
+ RenderFrameHostImpl* focused_rfh =
+ frame_tree_->GetFocusedFrame()->current_frame_host();
+ return focused_rfh == this || focused_rfh->IsDescendantOf(this);
}
bool RenderFrameHostImpl::UpdatePendingWebUI(const GURL& dest_url,
@@ -4430,22 +4656,15 @@ RenderFrameHostImpl::GetFindInPage() {
resource_coordinator::FrameResourceCoordinator*
RenderFrameHostImpl::GetFrameResourceCoordinator() {
- if (frame_resource_coordinator_)
- return frame_resource_coordinator_.get();
-
- if (!resource_coordinator::IsResourceCoordinatorEnabled()) {
- frame_resource_coordinator_ =
- std::make_unique<resource_coordinator::FrameResourceCoordinator>(
- nullptr);
- } else {
+ if (!frame_resource_coordinator_) {
auto* connection = ServiceManagerConnection::GetForProcess();
frame_resource_coordinator_ =
std::make_unique<resource_coordinator::FrameResourceCoordinator>(
connection ? connection->GetConnector() : nullptr);
- }
- if (parent_) {
- parent_->GetFrameResourceCoordinator()->AddChildFrame(
- *frame_resource_coordinator_);
+ if (parent_) {
+ parent_->GetFrameResourceCoordinator()->AddChildFrame(
+ *frame_resource_coordinator_);
+ }
}
return frame_resource_coordinator_.get();
}
@@ -4529,6 +4748,13 @@ void RenderFrameHostImpl::CancelBlockedRequestsForFrame() {
}
}
+void RenderFrameHostImpl::BindDevToolsAgent(
+ blink::mojom::DevToolsAgentHostAssociatedPtrInfo host,
+ blink::mojom::DevToolsAgentAssociatedRequest request) {
+ GetNavigationControl()->BindDevToolsAgent(std::move(host),
+ std::move(request));
+}
+
bool RenderFrameHostImpl::IsSameSiteInstance(
RenderFrameHostImpl* other_render_frame_host) {
// As a sanity check, make sure the frame belongs to the same BrowserContext.
@@ -4637,33 +4863,6 @@ int RenderFrameHostImpl::GetProxyCount() {
return frame_tree_node_->render_manager()->GetProxyCount();
}
-void RenderFrameHostImpl::FilesSelectedInChooser(
- const std::vector<content::FileChooserFileInfo>& files,
- FileChooserParams::Mode permissions) {
- storage::FileSystemContext* const file_system_context =
- BrowserContext::GetStoragePartition(GetProcess()->GetBrowserContext(),
- GetSiteInstance())
- ->GetFileSystemContext();
- // Grant the security access requested to the given files.
- for (const auto& file : files) {
- if (permissions == FileChooserParams::Save) {
- ChildProcessSecurityPolicyImpl::GetInstance()->GrantCreateReadWriteFile(
- GetProcess()->GetID(), file.file_path);
- } else {
- ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile(
- GetProcess()->GetID(), file.file_path);
- }
- if (file.file_system_url.is_valid()) {
- ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFileSystem(
- GetProcess()->GetID(),
- file_system_context->CrackURL(file.file_system_url)
- .mount_filesystem_id());
- }
- }
-
- Send(new FrameMsg_RunFileChooserResponse(routing_id_, files));
-}
-
bool RenderFrameHostImpl::HasSelection() {
return has_selection_;
}
@@ -4755,13 +4954,13 @@ void RenderFrameHostImpl::UpdateSubresourceLoaderFactories() {
network::mojom::URLLoaderFactoryPtrInfo default_factory_info;
bool bypass_redirect_checks = CreateNetworkServiceDefaultFactoryAndObserve(
- last_committed_url_, mojo::MakeRequest(&default_factory_info));
+ last_committed_origin_, mojo::MakeRequest(&default_factory_info));
std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories =
std::make_unique<URLLoaderFactoryBundleInfo>(
std::move(default_factory_info),
- std::map<std::string, network::mojom::URLLoaderFactoryPtrInfo>(),
- bypass_redirect_checks);
+ URLLoaderFactoryBundleInfo::SchemeMap(),
+ CreateInitiatorSpecificURLLoaderFactories(), bypass_redirect_checks);
SaveSubresourceFactories(std::move(subresource_loader_factories));
GetNavigationControl()->UpdateSubresourceLoaderFactories(
CloneSubresourceFactories());
@@ -4777,10 +4976,10 @@ std::set<int> RenderFrameHostImpl::GetNavigationEntryIdsPendingCommit() {
}
bool RenderFrameHostImpl::CreateNetworkServiceDefaultFactoryAndObserve(
- const GURL& url,
+ const url::Origin& origin,
network::mojom::URLLoaderFactoryRequest default_factory_request) {
bool bypass_redirect_checks = CreateNetworkServiceDefaultFactoryInternal(
- url, std::move(default_factory_request));
+ origin, std::move(default_factory_request));
// Add connection error observer when Network Service is running
// out-of-process.
@@ -4804,43 +5003,35 @@ bool RenderFrameHostImpl::CreateNetworkServiceDefaultFactoryAndObserve(
}
bool RenderFrameHostImpl::CreateNetworkServiceDefaultFactoryInternal(
- const GURL& url,
+ const url::Origin& origin,
network::mojom::URLLoaderFactoryRequest default_factory_request) {
- network::mojom::URLLoaderFactoryParamsPtr params =
- network::mojom::URLLoaderFactoryParams::New();
- params->process_id = GetProcess()->GetID();
- params->disable_web_security =
- base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDisableWebSecurity);
- SiteIsolationPolicy::PopulateURLLoaderFactoryParamsPtrForCORB(params.get());
-
auto* context = GetSiteInstance()->GetBrowserContext();
bool bypass_redirect_checks = false;
if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
- bypass_redirect_checks =
- GetContentClient()->browser()->WillCreateURLLoaderFactory(
- context, this, false /* is_navigation */, url,
- &default_factory_request);
+ GetContentClient()->browser()->WillCreateURLLoaderFactory(
+ context, this, false /* is_navigation */, origin,
+ &default_factory_request, &bypass_redirect_checks);
}
- // Keep DevTools proxy lasy, i.e. closest to the network.
+ // Keep DevTools proxy last, i.e. closest to the network.
RenderFrameDevToolsAgentHost::WillCreateURLLoaderFactory(
this, false /* is_navigation */, false /* is_download */,
&default_factory_request);
- StoragePartitionImpl* storage_partition = static_cast<StoragePartitionImpl*>(
- BrowserContext::GetStoragePartition(context, GetSiteInstance()));
+
+ // Create the URLLoaderFactory - either via ContentBrowserClient or ourselves.
if (g_create_network_factory_callback_for_test.Get().is_null()) {
- storage_partition->GetNetworkContext()->CreateURLLoaderFactory(
- std::move(default_factory_request), std::move(params));
+ GetProcess()->CreateURLLoaderFactory(origin,
+ std::move(default_factory_request));
} else {
network::mojom::URLLoaderFactoryPtr original_factory;
- storage_partition->GetNetworkContext()->CreateURLLoaderFactory(
- mojo::MakeRequest(&original_factory), std::move(params));
+ GetProcess()->CreateURLLoaderFactory(origin,
+ mojo::MakeRequest(&original_factory));
g_create_network_factory_callback_for_test.Get().Run(
std::move(default_factory_request), GetProcess()->GetID(),
original_factory.PassInterface());
}
+
return bypass_redirect_checks;
}
@@ -4884,8 +5075,7 @@ RenderFrameHost* RenderFrameHost::FromPlaceholderId(
return node ? node->current_frame_host() : nullptr;
}
-ui::AXTreeIDRegistry::AXTreeID RenderFrameHostImpl::RoutingIDToAXTreeID(
- int routing_id) {
+ui::AXTreeID RenderFrameHostImpl::RoutingIDToAXTreeID(int routing_id) {
RenderFrameHostImpl* rfh = nullptr;
RenderFrameProxyHost* rfph = nullptr;
LookupRenderFrameHostOrProxy(GetProcess()->GetID(), routing_id, &rfh, &rfph);
@@ -4894,17 +5084,17 @@ ui::AXTreeIDRegistry::AXTreeID RenderFrameHostImpl::RoutingIDToAXTreeID(
}
if (!rfh)
- return ui::AXTreeIDRegistry::kNoAXTreeID;
+ return ui::AXTreeIDUnknown();
return rfh->GetAXTreeID();
}
-ui::AXTreeIDRegistry::AXTreeID
-RenderFrameHostImpl::BrowserPluginInstanceIDToAXTreeID(int instance_id) {
+ui::AXTreeID RenderFrameHostImpl::BrowserPluginInstanceIDToAXTreeID(
+ int instance_id) {
RenderFrameHostImpl* guest = static_cast<RenderFrameHostImpl*>(
delegate()->GetGuestByInstanceID(this, instance_id));
if (!guest)
- return ui::AXTreeIDRegistry::kNoAXTreeID;
+ return ui::AXTreeIDUnknown();
// Create a mapping from the guest to its embedder's AX Tree ID, and
// explicitly update the guest to propagate that mapping immediately.
@@ -4927,12 +5117,13 @@ void RenderFrameHostImpl::AXContentNodeDataToAXNodeData(
int32_t value = iter.second;
switch (attr) {
case AX_CONTENT_ATTR_CHILD_ROUTING_ID:
- dst->int_attributes.push_back(std::make_pair(
- ax::mojom::IntAttribute::kChildTreeId, RoutingIDToAXTreeID(value)));
+ dst->string_attributes.push_back(
+ std::make_pair(ax::mojom::StringAttribute::kChildTreeId,
+ RoutingIDToAXTreeID(value)));
break;
case AX_CONTENT_ATTR_CHILD_BROWSER_PLUGIN_INSTANCE_ID:
- dst->int_attributes.push_back(
- std::make_pair(ax::mojom::IntAttribute::kChildTreeId,
+ dst->string_attributes.push_back(
+ std::make_pair(ax::mojom::StringAttribute::kChildTreeId,
BrowserPluginInstanceIDToAXTreeID(value)));
break;
case AX_CONTENT_INT_ATTRIBUTE_LAST:
@@ -4955,7 +5146,7 @@ void RenderFrameHostImpl::AXContentTreeDataToAXTreeData(
if (src.parent_routing_id != -1)
dst->parent_tree_id = RoutingIDToAXTreeID(src.parent_routing_id);
- if (browser_plugin_embedder_ax_tree_id_ != ui::AXTreeIDRegistry::kNoAXTreeID)
+ if (browser_plugin_embedder_ax_tree_id_ != ui::AXTreeIDUnknown())
dst->parent_tree_id = browser_plugin_embedder_ax_tree_id_;
// If this is not the root frame tree node, we're done.
@@ -5016,10 +5207,9 @@ void RenderFrameHostImpl::CreateAudioInputStreamFactory(
BrowserMainLoop* browser_main_loop = BrowserMainLoop::GetInstance();
DCHECK(browser_main_loop);
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);
+ MediaStreamManager* msm = browser_main_loop->media_stream_manager();
+ audio_service_audio_input_stream_factory_.emplace(std::move(request), msm,
+ this);
} else {
in_content_audio_input_stream_factory_ =
RenderFrameAudioInputStreamFactoryHandle::CreateFactory(
@@ -5284,7 +5474,7 @@ void RenderFrameHostImpl::BeforeUnloadTimeout() {
if (render_view_host_->GetDelegate()->ShouldIgnoreUnresponsiveRenderer())
return;
- SimulateBeforeUnloadAck();
+ SimulateBeforeUnloadAck(true /* proceed */);
}
void RenderFrameHostImpl::SetLastCommittedSiteUrl(const GURL& url) {
@@ -5434,7 +5624,7 @@ bool RenderFrameHostImpl::ValidateDidCommitParams(
// Error pages must commit in a unique origin. Terminate the renderer
// process if this is violated.
- if (!validated_params->origin.unique()) {
+ if (!validated_params->origin.opaque()) {
DEBUG_ALIAS_FOR_ORIGIN(origin_debug_alias, validated_params->origin);
bad_message::ReceivedBadMessage(
process, bad_message::RFH_ERROR_PROCESS_NON_UNIQUE_ORIGIN_COMMIT);
@@ -5452,7 +5642,7 @@ bool RenderFrameHostImpl::ValidateDidCommitParams(
net::ERR_BLOCKED_BY_CLIENT) {
// Since this is known to be an error page commit, verify it happened in
// a unique origin, terminating the renderer process otherwise.
- if (!validated_params->origin.unique()) {
+ if (!validated_params->origin.opaque()) {
DEBUG_ALIAS_FOR_ORIGIN(origin_debug_alias, validated_params->origin);
bad_message::ReceivedBadMessage(
process, bad_message::RFH_ERROR_PROCESS_NON_UNIQUE_ORIGIN_COMMIT);
@@ -5503,11 +5693,10 @@ bool RenderFrameHostImpl::ValidateDidCommitParams(
// be modified to take |validated_params| by const reference.
process->FilterURL(false, &validated_params->url);
process->FilterURL(true, &validated_params->referrer.url);
- for (std::vector<GURL>::iterator it(validated_params->redirects.begin());
+ for (auto it(validated_params->redirects.begin());
it != validated_params->redirects.end(); ++it) {
process->FilterURL(false, &(*it));
}
- process->FilterURL(true, &validated_params->searchable_form_url);
// Without this check, the renderer can trick the browser into using
// filenames it can't access in a future session restore.
@@ -5539,12 +5728,15 @@ bool RenderFrameHostImpl::DidCommitNavigationInternal(
if (!ValidateDidCommitParams(validated_params))
return false;
- // A racy DidStopLoading IPC might have reset the loading state that was set
- // to true in CommitNavigation. Set it to true now.
+ // Set is loading to true now if it has not been set yet. This happens for
+ // renderer-initiated same-document navigations. It can also happen when a
+ // racy DidStopLoading IPC resets the loading state that was set to true in
+ // CommitNavigation.
if (!is_loading()) {
bool was_loading = frame_tree_node()->frame_tree()->IsLoading();
is_loading_ = true;
- frame_tree_node()->DidStartLoading(true, was_loading);
+ frame_tree_node()->DidStartLoading(!is_same_document_navigation,
+ was_loading);
}
if (navigation_request_)
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 d71a3c050e6..a5598daa56c 100644
--- a/chromium/content/browser/frame_host/render_frame_host_impl.h
+++ b/chromium/content/browser/frame_host/render_frame_host_impl.h
@@ -18,6 +18,7 @@
#include "base/callback.h"
#include "base/compiler_specific.h"
+#include "base/containers/flat_set.h"
#include "base/containers/id_map.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
@@ -64,7 +65,9 @@
#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/common/frame/user_activation_update_type.h"
+#include "third_party/blink/public/mojom/choosers/file_chooser.mojom.h"
#include "third_party/blink/public/mojom/frame/find_in_page.mojom.h"
+#include "third_party/blink/public/mojom/frame/navigation_initiator.mojom.h"
#include "third_party/blink/public/mojom/presentation/presentation.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"
@@ -74,9 +77,10 @@
#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/devtools_agent.mojom.h"
#include "third_party/blink/public/web/web_text_direction.h"
#include "third_party/blink/public/web/web_tree_scope_type.h"
-#include "ui/accessibility/ax_modes.h"
+#include "ui/accessibility/ax_mode.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/base/mojo/window_open_disposition.mojom.h"
#include "ui/base/page_transition_types.h"
@@ -138,7 +142,6 @@ class RenderFrameHostDelegate;
class RenderFrameProxyHost;
class RenderProcessHost;
class RenderViewHostImpl;
-class RenderWidgetHostDelegate;
class RenderWidgetHostImpl;
class RenderWidgetHostView;
class RenderWidgetHostViewBase;
@@ -147,7 +150,6 @@ class TimeoutMonitor;
class WebBluetoothServiceImpl;
struct CommonNavigationParams;
struct ContextMenuParams;
-struct FileChooserParams;
struct FrameOwnerProperties;
struct PendingNavigation;
struct RequestNavigationParams;
@@ -174,8 +176,7 @@ class CONTENT_EXPORT RenderFrameHostImpl
static const int kMaxAccessibilityResets = 5;
static RenderFrameHostImpl* FromID(int process_id, int routing_id);
- static RenderFrameHostImpl* FromAXTreeID(
- ui::AXTreeIDRegistry::AXTreeID ax_tree_id);
+ static RenderFrameHostImpl* FromAXTreeID(ui::AXTreeID ax_tree_id);
static RenderFrameHostImpl* FromOverlayRoutingToken(
const base::UnguessableToken& token);
@@ -194,11 +195,12 @@ class CONTENT_EXPORT RenderFrameHostImpl
// RenderFrameHost
int GetRoutingID() override;
- ui::AXTreeIDRegistry::AXTreeID GetAXTreeID() override;
+ ui::AXTreeID GetAXTreeID() override;
SiteInstanceImpl* GetSiteInstance() override;
RenderProcessHost* GetProcess() override;
RenderWidgetHostView* GetView() override;
RenderFrameHostImpl* GetParent() override;
+ bool IsDescendantOf(RenderFrameHost*) override;
int GetFrameTreeNodeId() override;
base::UnguessableToken GetDevToolsFrameToken() override;
const std::string& GetFrameName() override;
@@ -232,8 +234,6 @@ class CONTENT_EXPORT RenderFrameHostImpl
bool IsRenderFrameLive() override;
bool IsCurrent() override;
int GetProxyCount() override;
- void FilesSelectedInChooser(const std::vector<FileChooserFileInfo>& files,
- FileChooserParams::Mode permissions) override;
bool HasSelection() override;
void RequestTextSurroundingSelection(
const TextSurroundingSelectionCallback& callback,
@@ -253,6 +253,9 @@ class CONTENT_EXPORT RenderFrameHostImpl
const blink::WebMediaPlayerAction& action) override;
bool CreateNetworkServiceDefaultFactory(
network::mojom::URLLoaderFactoryRequest default_factory_request) override;
+ void MarkInitiatorsAsRequiringSeparateURLLoaderFactory(
+ std::vector<url::Origin> request_initiators,
+ bool push_to_renderer_now) override;
// IPC::Sender
bool Send(IPC::Message* msg) override;
@@ -343,6 +346,17 @@ class CONTENT_EXPORT RenderFrameHostImpl
RenderFrameHostDelegate* delegate() { return delegate_; }
FrameTreeNode* frame_tree_node() { return frame_tree_node_; }
+ // Methods to add/remove/reset/query child FrameTreeNodes of this frame.
+ // See class-level comment for FrameTreeNode for how the frame tree is
+ // represented.
+ size_t child_count() { return children_.size(); }
+ FrameTreeNode* child_at(size_t index) const { return children_[index].get(); }
+ FrameTreeNode* AddChild(std::unique_ptr<FrameTreeNode> child,
+ int process_id,
+ int frame_routing_id);
+ void RemoveChild(FrameTreeNode* child);
+ void ResetChildren();
+
// Allows FrameTreeNode::SetCurrentURL to update this frame's last committed
// URL. Do not call this directly, since we rely on SetCurrentURL to track
// whether a real load has committed or not.
@@ -458,7 +472,12 @@ class CONTENT_EXPORT RenderFrameHostImpl
enum class BeforeUnloadType {
BROWSER_INITIATED_NAVIGATION,
RENDERER_INITIATED_NAVIGATION,
- TAB_CLOSE
+ TAB_CLOSE,
+ // This reason is used before a tab is discarded in order to free up
+ // resources. When this is used and the handler returns a non-empty string,
+ // the confirmation dialog will not be displayed and the discard will
+ // automatically be canceled.
+ DISCARD,
};
// Runs the beforeunload handler for this frame and its subframes. |type|
@@ -469,7 +488,7 @@ class CONTENT_EXPORT RenderFrameHostImpl
void DispatchBeforeUnload(BeforeUnloadType type, bool is_reload);
// Simulate beforeunload ack on behalf of renderer if it's unrenresponsive.
- void SimulateBeforeUnloadAck();
+ void SimulateBeforeUnloadAck(bool proceed);
// Returns true if a call to DispatchBeforeUnload will actually send the
// BeforeUnload IPC. This can be called on a main frame or subframe. If
@@ -543,8 +562,7 @@ class CONTENT_EXPORT RenderFrameHostImpl
void UpdateAXTreeData();
// Set the AX tree ID of the embedder RFHI, if this is a browser plugin guest.
- void set_browser_plugin_embedder_ax_tree_id(
- ui::AXTreeIDRegistry::AXTreeID ax_tree_id) {
+ void set_browser_plugin_embedder_ax_tree_id(ui::AXTreeID ax_tree_id) {
browser_plugin_embedder_ax_tree_id_ = ax_tree_id;
}
@@ -702,6 +720,10 @@ class CONTENT_EXPORT RenderFrameHostImpl
// Cancels any blocked request for the frame and its subframes.
void CancelBlockedRequestsForFrame();
+ // Binds a DevToolsAgent interface for debugging.
+ void BindDevToolsAgent(blink::mojom::DevToolsAgentHostAssociatedPtrInfo host,
+ blink::mojom::DevToolsAgentAssociatedRequest request);
+
#if defined(OS_ANDROID)
base::android::ScopedJavaLocalRef<jobject> GetJavaRenderFrameHost();
service_manager::InterfaceProvider* GetJavaInterfaces() override;
@@ -763,14 +785,6 @@ class CONTENT_EXPORT RenderFrameHostImpl
// for unload handler processing.
void SetSubframeUnloadTimeoutForTesting(const base::TimeDelta& timeout);
- bool received_post_message_from_non_descendant() const {
- return received_post_message_from_non_descendant_;
- }
-
- void did_receive_post_message_from_non_descendant() {
- received_post_message_from_non_descendant_ = true;
- }
-
// Returns the list of NavigationEntry ids corresponding to NavigationRequests
// waiting to commit in this RenderFrameHost.
std::set<int> GetNavigationEntryIdsPendingCommit();
@@ -799,7 +813,6 @@ class CONTENT_EXPORT RenderFrameHostImpl
RenderFrameHostImpl(SiteInstance* site_instance,
RenderViewHostImpl* render_view_host,
RenderFrameHostDelegate* delegate,
- RenderWidgetHostDelegate* rwh_delegate,
FrameTree* frame_tree,
FrameTreeNode* frame_tree_node,
int32_t routing_id,
@@ -869,10 +882,6 @@ class CONTENT_EXPORT RenderFrameHostImpl
void OnFrameFocused();
void OnOpenURL(const FrameHostMsg_OpenURL_Params& params);
void OnDocumentOnLoadCompleted();
- void OnDidStartProvisionalLoad(
- const GURL& url,
- const std::vector<GURL>& redirect_chain,
- const base::TimeTicks& navigation_start);
void OnDidFailProvisionalLoadWithError(
const FrameHostMsg_DidFailProvisionalLoadWithError_Params& params);
void OnDidFailLoadWithError(const GURL& url,
@@ -893,7 +902,7 @@ class CONTENT_EXPORT RenderFrameHostImpl
JavaScriptDialogType dialog_type,
IPC::Message* reply_msg);
void OnRunBeforeUnloadConfirm(bool is_reload, IPC::Message* reply_msg);
- void OnRunFileChooser(const FileChooserParams& params);
+ void OnRunFileChooser(const blink::mojom::FileChooserParams& params);
void OnTextSurroundingSelectionResponse(const base::string16& content,
uint32_t start_offset,
uint32_t end_offset);
@@ -938,7 +947,6 @@ class CONTENT_EXPORT RenderFrameHostImpl
void OnSuddenTerminationDisablerChanged(
bool present,
blink::WebSuddenTerminationDisablerType disabler_type);
- void OnDidStartLoading(bool to_different_document);
void OnDidStopLoading();
void OnDidChangeLoadProgress(double load_progress);
void OnSerializeAsMHTMLResponse(
@@ -995,7 +1003,8 @@ class CONTENT_EXPORT RenderFrameHostImpl
const CommonNavigationParams& common_params,
mojom::BeginNavigationParamsPtr begin_params,
blink::mojom::BlobURLTokenPtr blob_url_token,
- mojom::NavigationClientAssociatedPtrInfo navigation_client) override;
+ mojom::NavigationClientAssociatedPtrInfo navigation_client,
+ blink::mojom::NavigationInitiatorPtr navigation_initiator) override;
void SubresourceResponseStarted(const GURL& url,
net::CertStatus cert_status) override;
void ResourceLoadComplete(
@@ -1012,6 +1021,9 @@ class CONTENT_EXPORT RenderFrameHostImpl
void UpdateEncoding(const std::string& encoding) override;
void FrameSizeChanged(const gfx::Size& frame_size) override;
void FullscreenStateChanged(bool is_fullscreen) override;
+#if defined(OS_ANDROID)
+ void UpdateUserGestureCarryoverInfo() override;
+#endif
// Registers Mojo interfaces that this frame host makes available.
void RegisterMojoInterfaces();
@@ -1058,16 +1070,19 @@ class CONTENT_EXPORT RenderFrameHostImpl
// |OnNetworkServiceConnectionError()| if the factory is out-of-process. If
// this returns true, any redirect safety checks should be bypassed in
// downstream loaders.
- // |url| is the URL that the RenderFrame is either committing (in the case of
- // navigation) or has last committed (when handling network process crashes).
+ //
+ // |origin| is the origin that the RenderFrame is either committing (in the
+ // case of navigation) or has last committed (when handling network process
+ // crashes).
bool CreateNetworkServiceDefaultFactoryAndObserve(
- const GURL& url,
+ const url::Origin& origin,
network::mojom::URLLoaderFactoryRequest default_factory_request);
- // |url| is the URL that the RenderFrame is either committing (in the case of
- // navigation) or has last committed (when handling network process crashes).
+ // |origin| is the origin that the RenderFrame is either committing (in the
+ // case of navigation) or has last committed (when handling network process
+ // crashes).
bool CreateNetworkServiceDefaultFactoryInternal(
- const GURL& url,
+ const url::Origin& origin,
network::mojom::URLLoaderFactoryRequest default_factory_request);
// Returns true if the ExecuteJavaScript() API can be used on this host.
@@ -1075,12 +1090,11 @@ class CONTENT_EXPORT RenderFrameHostImpl
// Map a routing ID from a frame in the same frame tree to a globally
// unique AXTreeID.
- ui::AXTreeIDRegistry::AXTreeID RoutingIDToAXTreeID(int routing_id);
+ ui::AXTreeID RoutingIDToAXTreeID(int routing_id);
// Map a browser plugin instance ID to the AXTreeID of the plugin's
// main frame.
- ui::AXTreeIDRegistry::AXTreeID BrowserPluginInstanceIDToAXTreeID(
- int routing_id);
+ ui::AXTreeID BrowserPluginInstanceIDToAXTreeID(int routing_id);
// Convert the content-layer-specific AXContentNodeData to a general-purpose
// AXNodeData structure.
@@ -1296,6 +1310,11 @@ class CONTENT_EXPORT RenderFrameHostImpl
std::unique_ptr<base::trace_event::TracedValue> CommitAsTracedValue(
FrameHostMsg_DidCommitProvisionalLoad_Params* validated_params) const;
+ // Creates initiator-specific URLLoaderFactory objects for intiator origins
+ // registered via MarkInitiatorAsRequiringSeparateURLLoaderFactory method.
+ URLLoaderFactoryBundleInfo::OriginMap
+ CreateInitiatorSpecificURLLoaderFactories();
+
// For now, RenderFrameHosts indirectly keep RenderViewHosts alive via a
// refcount that calls Shutdown when it reaches zero. This allows each
// RenderFrameHostManager to just care about RenderFrameHosts, while ensuring
@@ -1327,6 +1346,9 @@ class CONTENT_EXPORT RenderFrameHostImpl
// The FrameTreeNode which this RenderFrameHostImpl is hosted in.
FrameTreeNode* const frame_tree_node_;
+ // The immediate children of this specific frame.
+ std::vector<std::unique_ptr<FrameTreeNode>> children_;
+
// The active parent RenderFrameHost for this frame, if it is a subframe.
// Null for the main frame. This is cached because the parent FrameTreeNode
// may change its current RenderFrameHost while this child is pending
@@ -1384,6 +1406,11 @@ class CONTENT_EXPORT RenderFrameHostImpl
// machine.
bool is_waiting_for_beforeunload_ack_;
+ // Valid only when |is_waiting_for_beforeunload_ack_| is true. This indicates
+ // whether a subsequent request to launch a modal dialog should be honored or
+ // whether it should implicitly cause the unload to be canceled.
+ bool beforeunload_dialog_request_cancels_unload_;
+
// Valid only when is_waiting_for_beforeunload_ack_ or
// IsWaitingForUnloadACK is true. This tells us if the unload request
// is for closing the entire tab ( = false), or only this RenderFrameHost in
@@ -1429,12 +1456,6 @@ class CONTENT_EXPORT RenderFrameHostImpl
// relevant NavigationEntry.
int nav_entry_id_;
- // Tracks if a frame has been influenced by post message from
- // non-descendant frames. Useful for determining if silently reloading a
- // crashed frame is safe. Post messages from descendants to not matter for
- // this decision since they will be reloaded as well.
- bool received_post_message_from_non_descendant_ = false;
-
// Used to swap out or shut down this RFH when the unload event is taking too
// long to execute, depending on the number of active frames in the
// SiteInstance. May be null in tests.
@@ -1469,11 +1490,10 @@ class CONTENT_EXPORT RenderFrameHostImpl
AXContentTreeData ax_content_tree_data_;
// The AX tree ID of this frame.
- ui::AXTreeIDRegistry::AXTreeID ax_tree_id_ =
- ui::AXTreeIDRegistry::kNoAXTreeID;
+ ui::AXTreeID ax_tree_id_ = ui::AXTreeIDUnknown();
// The AX tree ID of the embedder, if this is a browser plugin guest.
- ui::AXTreeIDRegistry::AXTreeID browser_plugin_embedder_ax_tree_id_;
+ ui::AXTreeID browser_plugin_embedder_ax_tree_id_;
// The mapping from callback id to corresponding callback for pending
// accessibility tree snapshot calls created by RequestAXTreeSnapshot.
@@ -1614,6 +1634,10 @@ class CONTENT_EXPORT RenderFrameHostImpl
// Hosts blink::mojom::PresentationService for the RenderFrame.
std::unique_ptr<PresentationServiceImpl> presentation_service_;
+ // Hosts blink::mojom::FileSystemManager for the RenderFrame.
+ std::unique_ptr<FileSystemManagerImpl, BrowserThread::DeleteOnIOThread>
+ file_system_manager_;
+
#if !defined(OS_ANDROID)
std::unique_ptr<AuthenticatorImpl> authenticator_impl_;
#endif
@@ -1708,6 +1732,11 @@ class CONTENT_EXPORT RenderFrameHostImpl
network::mojom::URLLoaderFactoryPtr
network_service_connection_error_handler_holder_;
+ // Set of request-initiator-origins that require a separate URLLoaderFactory
+ // (e.g. for handling requests initiated by extension content scripts that
+ // require relaxed CORS/CORB rules).
+ base::flat_set<url::Origin> initiators_requiring_separate_url_loader_factory_;
+
// Holds the renderer generated ID and global request ID for the main frame
// request.
std::pair<int, GlobalRequestID> main_frame_request_ids_;
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 bea486b54d1..9517e95efbb 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
@@ -9,6 +9,7 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/run_loop.h"
+#include "base/strings/utf_string_conversions.h"
#include "base/test/bind_test_util.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/mock_callback.h"
@@ -202,14 +203,22 @@ class TestJavaScriptDialogManager : public JavaScriptDialogManager,
: message_loop_runner_(new MessageLoopRunner), url_invalidate_count_(0) {}
~TestJavaScriptDialogManager() override {}
+ // This waits until either WCD::BeforeUnloadFired is called (the unload has
+ // been handled) or JSDM::RunJavaScriptDialog/RunBeforeUnloadDialog is called
+ // (a request to display a dialog has been received).
void Wait() {
message_loop_runner_->Run();
message_loop_runner_ = new MessageLoopRunner;
}
- DialogClosedCallback& callback() { return callback_; }
+ // Runs the dialog callback.
+ void Run(bool success, const base::string16& user_input) {
+ std::move(callback_).Run(success, user_input);
+ }
int num_beforeunload_dialogs_seen() { return num_beforeunload_dialogs_seen_; }
+ int num_beforeunload_fired_seen() { return num_beforeunload_fired_seen_; }
+ bool proceed() { return proceed_; }
// WebContentsDelegate
@@ -218,6 +227,14 @@ class TestJavaScriptDialogManager : public JavaScriptDialogManager,
return this;
}
+ void BeforeUnloadFired(WebContents* tab,
+ bool proceed,
+ bool* proceed_to_fire_unload) override {
+ ++num_beforeunload_fired_seen_;
+ proceed_ = proceed;
+ message_loop_runner_->Quit();
+ }
+
// JavaScriptDialogManager
void RunJavaScriptDialog(WebContents* web_contents,
@@ -226,7 +243,10 @@ class TestJavaScriptDialogManager : public JavaScriptDialogManager,
const base::string16& message_text,
const base::string16& default_prompt_text,
DialogClosedCallback callback,
- bool* did_suppress_message) override {}
+ bool* did_suppress_message) override {
+ callback_ = std::move(callback);
+ message_loop_runner_->Quit();
+ }
void RunBeforeUnloadDialog(WebContents* web_contents,
RenderFrameHost* render_frame_host,
@@ -268,6 +288,13 @@ class TestJavaScriptDialogManager : public JavaScriptDialogManager,
// The total number of beforeunload dialogs seen by this dialog manager.
int num_beforeunload_dialogs_seen_ = 0;
+ // The total number of BeforeUnloadFired events witnessed by the
+ // WebContentsDelegate.
+ int num_beforeunload_fired_seen_ = 0;
+
+ // The |proceed| value returned by the last unload event.
+ bool proceed_ = false;
+
DISALLOW_COPY_AND_ASSIGN(TestJavaScriptDialogManager);
};
@@ -339,7 +366,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBrowserTest,
main_frame->GetProcess()->AddFilter(filter.get());
// Answer the dialog.
- std::move(dialog_manager.callback()).Run(true, base::string16());
+ dialog_manager.Run(true, base::string16());
// There will be no beforeunload ACK, so if the beforeunload ACK timer isn't
// functioning then the navigation will hang forever and this test will time
@@ -378,7 +405,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBrowserTest,
dialog_manager.Wait();
// Answer the dialog.
- std::move(dialog_manager.callback()).Run(true, base::string16());
+ dialog_manager.Run(true, base::string16());
EXPECT_TRUE(WaitForLoadStop(wc));
// The reload should have cleared the user gesture bit, so upon leaving again
@@ -409,7 +436,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBrowserTest,
// Cancel the dialog.
dialog_manager.reset_url_invalidate_count();
- std::move(dialog_manager.callback()).Run(false, base::string16());
+ dialog_manager.Run(false, base::string16());
EXPECT_FALSE(wc->IsLoading());
// Verify there are no pending history items after the dialog is cancelled.
@@ -447,13 +474,13 @@ class RenderFrameHostImplBeforeUnloadBrowserTest
}
void CloseDialogAndProceed() {
- std::move(dialog_manager()->callback())
- .Run(true /* navigation should proceed */, base::string16());
+ dialog_manager_->Run(true /* navigation should proceed */,
+ base::string16());
}
void CloseDialogAndCancel() {
- std::move(dialog_manager()->callback())
- .Run(false /* navigation should proceed */, base::string16());
+ dialog_manager_->Run(false /* navigation should proceed */,
+ base::string16());
}
// Installs a beforeunload handler in the given frame.
@@ -953,7 +980,7 @@ class ExecuteScriptBeforeRenderFrameDeletedHelper
//
// Note that if the second WebContents scheduled a call to window.close() to
// close itself after it calls window.open(), the CreateNewWindow sync IPC could
-// be dispatched *before* ViewHostMsg_Close in the browser process, provided
+// be dispatched *before* WidgetHostMsg_Close in the browser process, provided
// that the browser happened to be in IPC::SyncChannel::WaitForReply on the UI
// thread (most likely after sending GpuCommandBufferMsg_* messages), in which
// case incoming sync IPCs to this thread are dispatched, but the message loop
@@ -1874,6 +1901,77 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBrowserTest,
}
IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBrowserTest,
+ BeforeUnloadDialogSuppressedForDiscard) {
+ WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell()->web_contents());
+ TestJavaScriptDialogManager dialog_manager;
+ wc->SetDelegate(&dialog_manager);
+
+ EXPECT_TRUE(NavigateToURL(
+ shell(), GetTestUrl("render_frame_host", "beforeunload.html")));
+ // Disable the hang monitor, otherwise there will be a race between the
+ // beforeunload dialog and the beforeunload hang timer.
+ wc->GetMainFrame()->DisableBeforeUnloadHangMonitorForTesting();
+
+ // Give the page a user gesture so javascript beforeunload works, and then
+ // dispatch a before unload with discard as a reason. This should return
+ // without any dialog being seen.
+ wc->GetMainFrame()->ExecuteJavaScriptWithUserGestureForTests(
+ base::string16());
+ wc->GetMainFrame()->DispatchBeforeUnload(
+ RenderFrameHostImpl::BeforeUnloadType::DISCARD, false);
+ dialog_manager.Wait();
+ EXPECT_EQ(0, dialog_manager.num_beforeunload_dialogs_seen());
+ EXPECT_EQ(1, dialog_manager.num_beforeunload_fired_seen());
+ EXPECT_FALSE(dialog_manager.proceed());
+
+ wc->SetDelegate(nullptr);
+ wc->SetJavaScriptDialogManagerForTesting(nullptr);
+}
+
+IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBrowserTest,
+ PendingDialogMakesDiscardUnloadReturnFalse) {
+ WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell()->web_contents());
+ TestJavaScriptDialogManager dialog_manager;
+ wc->SetDelegate(&dialog_manager);
+
+ EXPECT_TRUE(NavigateToURL(
+ shell(), GetTestUrl("render_frame_host", "beforeunload.html")));
+ // Disable the hang monitor, otherwise there will be a race between the
+ // beforeunload dialog and the beforeunload hang timer.
+ wc->GetMainFrame()->DisableBeforeUnloadHangMonitorForTesting();
+
+ // Give the page a user gesture so javascript beforeunload works, and then
+ // dispatch a before unload with discard as a reason. This should return
+ // without any dialog being seen.
+ wc->GetMainFrame()->ExecuteJavaScriptWithUserGestureForTests(
+ base::string16());
+
+ // Launch an alert javascript dialog. This pending dialog should block a
+ // subsequent discarding before unload request.
+ wc->GetMainFrame()->ExecuteJavaScriptForTests(
+ base::ASCIIToUTF16("setTimeout(function(){alert('hello');}, 10);"));
+ dialog_manager.Wait();
+ EXPECT_EQ(0, dialog_manager.num_beforeunload_dialogs_seen());
+ EXPECT_EQ(0, dialog_manager.num_beforeunload_fired_seen());
+
+ // Dispatch a before unload request while the first is still blocked
+ // on the dialog, and expect it to return false immediately (synchronously).
+ wc->GetMainFrame()->DispatchBeforeUnload(
+ RenderFrameHostImpl::BeforeUnloadType::DISCARD, false);
+ dialog_manager.Wait();
+ EXPECT_EQ(0, dialog_manager.num_beforeunload_dialogs_seen());
+ EXPECT_EQ(1, dialog_manager.num_beforeunload_fired_seen());
+ EXPECT_FALSE(dialog_manager.proceed());
+
+ // Clear the existing javascript dialog so that the associated IPC message
+ // doesn't leak.
+ dialog_manager.Run(true, base::string16());
+
+ wc->SetDelegate(nullptr);
+ wc->SetJavaScriptDialogManagerForTesting(nullptr);
+}
+
+IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBrowserTest,
NotifiesProcessHostOfAudibleAudio) {
const auto RunPostedTasks = []() {
base::RunLoop run_loop;
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 49ad391a313..69913022bb1 100644
--- a/chromium/content/browser/frame_host/render_frame_host_manager.cc
+++ b/chromium/content/browser/frame_host/render_frame_host_manager.cc
@@ -68,15 +68,10 @@ bool IsDataOrAbout(const GURL& url) {
} // namespace
-RenderFrameHostManager::RenderFrameHostManager(
- FrameTreeNode* frame_tree_node,
- RenderFrameHostDelegate* render_frame_delegate,
- RenderWidgetHostDelegate* render_widget_delegate,
- Delegate* delegate)
+RenderFrameHostManager::RenderFrameHostManager(FrameTreeNode* frame_tree_node,
+ Delegate* delegate)
: frame_tree_node_(frame_tree_node),
delegate_(delegate),
- render_frame_delegate_(render_frame_delegate),
- render_widget_delegate_(render_widget_delegate),
weak_factory_(this) {
DCHECK(frame_tree_node_);
}
@@ -213,7 +208,7 @@ void RenderFrameHostManager::SetIsLoading(bool is_loading) {
void RenderFrameHostManager::OnBeforeUnloadACK(
bool proceed,
const base::TimeTicks& proceed_time) {
- bool proceed_to_fire_unload;
+ bool proceed_to_fire_unload = false;
delegate_->BeforeUnloadFiredFromRenderManager(proceed, proceed_time,
&proceed_to_fire_unload);
@@ -451,9 +446,8 @@ void RenderFrameHostManager::DiscardUnusedFrame(
bool RenderFrameHostManager::DeleteFromPendingList(
RenderFrameHostImpl* render_frame_host) {
- for (RFHPendingDeleteList::iterator iter = pending_delete_hosts_.begin();
- iter != pending_delete_hosts_.end();
- iter++) {
+ for (auto iter = pending_delete_hosts_.begin();
+ iter != pending_delete_hosts_.end(); iter++) {
if (iter->get() == render_frame_host) {
pending_delete_hosts_.erase(iter);
return true;
@@ -654,8 +648,10 @@ RenderFrameHostImpl* RenderFrameHostManager::GetFrameHostForNavigation(
// RenderFrameHostManager are completely initialized. This should be
// removed once the process manager moves away from NotificationService.
// See https://crbug.com/462682.
- delegate_->NotifyMainFrameSwappedFromRenderManager(
- nullptr, render_frame_host_.get());
+ if (frame_tree_node_->IsMainFrame()) {
+ delegate_->NotifyMainFrameSwappedFromRenderManager(
+ nullptr, render_frame_host_.get());
+ }
}
}
@@ -1079,8 +1075,16 @@ RenderFrameHostManager::GetSiteInstanceForNavigation(
static_cast<SiteInstanceImpl*>(new_instance.get());
if (!frame_tree_node_->IsMainFrame() && !new_instance_impl->HasProcess() &&
new_instance_impl->RequiresDedicatedProcess()) {
- new_instance_impl->set_process_reuse_policy(
- SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
+ // Also give the embedder a chance to override this decision. Certain
+ // frames have different enough workloads so that it's better to avoid
+ // placing a subframe into an existing process for better performance
+ // isolation. See https://crbug.com/899418.
+ if (GetContentClient()->browser()->ShouldSubframesTryToReuseExistingProcess(
+ frame_tree_node_->frame_tree()->GetMainFrame())) {
+ new_instance_impl->set_process_reuse_policy(
+ SiteInstanceImpl::ProcessReusePolicy::
+ REUSE_PENDING_OR_COMMITTED_SITE);
+ }
}
return new_instance;
@@ -1113,8 +1117,10 @@ void RenderFrameHostManager::InitializeRenderFrameIfNecessary(
// RenderFrameHostManager are completely initialized. This should be
// removed once the process manager moves away from NotificationService.
// See https://crbug.com/462682.
- delegate_->NotifyMainFrameSwappedFromRenderManager(nullptr,
- render_frame_host_.get());
+ if (frame_tree_node_->IsMainFrame()) {
+ delegate_->NotifyMainFrameSwappedFromRenderManager(
+ nullptr, render_frame_host_.get());
+ }
}
RenderFrameHostManager::SiteInstanceDescriptor
@@ -1358,29 +1364,10 @@ RenderFrameHostManager::DetermineSiteInstanceForURL(
return SiteInstanceDescriptor(opener_frame->GetSiteInstance());
}
- if (!frame_tree_node_->IsMainFrame() &&
- SiteIsolationPolicy::IsTopDocumentIsolationEnabled() &&
- !SiteInstanceImpl::DoesSiteRequireDedicatedProcess(browser_context,
- dest_url)) {
- if (GetContentClient()
- ->browser()
- ->ShouldFrameShareParentSiteInstanceDespiteTopDocumentIsolation(
- dest_url, current_instance)) {
- return SiteInstanceDescriptor(render_frame_host_->GetSiteInstance());
- }
-
- // This is a cross-site subframe of a non-isolated origin, so place this
- // frame in the default subframe site instance.
- return SiteInstanceDescriptor(
- browser_context, dest_url,
- SiteInstanceRelation::RELATED_DEFAULT_SUBFRAME);
- }
-
// Keep subframes in the parent's SiteInstance unless a dedicated process is
// required for either the parent or the subframe's destination URL. This
// isn't a strict invariant but rather a heuristic to avoid unnecessary
- // OOPIFs; see https://crbug.com/711006. Note that this shouldn't apply to
- // TopDocumentIsolation, so do this after TDI checks above.
+ // OOPIFs; see https://crbug.com/711006.
//
// TODO(alexmos): Remove this check after fixing https://crbug.com/787576.
if (!frame_tree_node_->IsMainFrame()) {
@@ -1441,21 +1428,23 @@ bool RenderFrameHostManager::IsBrowsingInstanceSwapAllowedForPageTransition(
bool RenderFrameHostManager::IsRendererTransferNeededForNavigation(
RenderFrameHostImpl* rfh,
const GURL& dest_url) {
- // A transfer is not needed if the current SiteInstance doesn't yet have a
- // site. This is the case for tests that use NavigateToURL.
- //
- // One exception is that a siteless SiteInstance may still have a process,
- // which might be unsuitable for |dest_url|. For example, another navigation
- // could share that process (e.g., when over process limit) and lock it to a
- // different origin before this SiteInstance sets its site. Hence, we also
- // check for cases like this. See https://crbug.com/773809.
+ // Always attempt a process transfer if the SiteInstance has a process that's
+ // unsuitable for |dest_url|. For example, this might happen when reloading
+ // a URL for which a hosted app was just installed or uninstalled.
//
- // TODO(alexmos): We should always check HasWrongProcessForURL regardless of
- // HasSite, but currently we cannot do that because of hosted app workarounds
- // (see https://crbug.com/92669). Revisit this once hosted apps swap
- // processes for cross-site web iframes and popups.
+ // This might also happen for a siteless SiteInstance which may have a
+ // process that's unsuitable for |dest_url|. For example, another navigation
+ // could share that process when over process limit and lock it to a
+ // different site before this SiteInstance sets its site. See
+ // https://crbug.com/773809.
+ if (rfh->GetSiteInstance()->HasWrongProcessForURL(dest_url))
+ return true;
+
+ // A transfer is not needed if the current SiteInstance doesn't yet have a
+ // site. For example, this happens when tests use NavigateToURL or when
+ // navigating a blank window in some cases.
if (!rfh->GetSiteInstance()->HasSite())
- return rfh->GetSiteInstance()->HasWrongProcessForURL(dest_url);
+ return false;
// We do not currently swap processes for navigations in webview tag guests.
if (rfh->GetSiteInstance()->GetSiteURL().SchemeIs(kGuestScheme))
@@ -1479,13 +1468,6 @@ bool RenderFrameHostManager::IsRendererTransferNeededForNavigation(
return true;
}
- if (SiteIsolationPolicy::IsTopDocumentIsolationEnabled() &&
- (!frame_tree_node_->IsMainFrame() ||
- rfh->GetSiteInstance()->IsDefaultSubframeSiteInstance())) {
- // Always attempt a transfer in these cases.
- return true;
- }
-
// If the destination URL is not same-site with current RenderFrameHost and
// doesn't require a dedicated process (see above), but it is same-site with
// the opener RenderFrameHost, attempt a transfer so that the destination URL
@@ -1518,9 +1500,6 @@ scoped_refptr<SiteInstance> RenderFrameHostManager::ConvertToSiteInstance(
if (descriptor.relation == SiteInstanceRelation::RELATED)
return current_instance->GetRelatedSiteInstance(descriptor.dest_url);
- if (descriptor.relation == SiteInstanceRelation::RELATED_DEFAULT_SUBFRAME)
- return current_instance->GetDefaultSubframeSiteInstance();
-
// At this point we know an unrelated site instance must be returned. First
// check if the candidate matches.
if (candidate_instance &&
@@ -1597,7 +1576,7 @@ bool RenderFrameHostManager::IsCurrentlySameSite(RenderFrameHostImpl* candidate,
// It is possible that last_successful_url() was a nonstandard scheme (for
// example, "about:blank"). If so, examine the replicated origin to determine
// the site.
- if (!candidate->GetLastCommittedOrigin().unique() &&
+ if (!candidate->GetLastCommittedOrigin().opaque() &&
SiteInstanceImpl::IsSameWebSite(
browser_context,
GURL(candidate->GetLastCommittedOrigin().Serialize()), dest_url,
@@ -1612,7 +1591,7 @@ bool RenderFrameHostManager::IsCurrentlySameSite(RenderFrameHostImpl* candidate,
// tests rely on that behavior. To accomplish this, compare |dest_url|
// against the site URL.
if (candidate->last_successful_url().IsAboutBlank() &&
- candidate->GetLastCommittedOrigin().unique() &&
+ candidate->GetLastCommittedOrigin().opaque() &&
SiteInstanceImpl::IsSameWebSite(
browser_context, candidate->GetSiteInstance()->original_url(),
dest_url, should_compare_effective_urls)) {
@@ -1706,9 +1685,9 @@ RenderFrameHostManager::CreateRenderFrameHost(
}
return RenderFrameHostFactory::Create(
- site_instance, render_view_host, render_frame_delegate_,
- render_widget_delegate_, frame_tree, frame_tree_node_, frame_routing_id,
- widget_routing_id, hidden, renderer_initiated_creation);
+ site_instance, render_view_host, frame_tree->render_frame_delegate(),
+ frame_tree, frame_tree_node_, frame_routing_id, widget_routing_id, hidden,
+ renderer_initiated_creation);
}
bool RenderFrameHostManager::CreateSpeculativeRenderFrameHost(
@@ -1958,9 +1937,19 @@ RenderFrameHostManager::GetSiteInstanceForNavigationRequest(
// navigation should use the current SiteInstance.
SiteInstance* current_site_instance = render_frame_host_->GetSiteInstance();
bool no_renderer_swap_allowed = false;
+ bool should_swap_for_error_isolation = false;
bool was_server_redirect = request.navigation_handle() &&
request.navigation_handle()->WasServerRedirect();
+ // When error page isolation is enabled, each navigation that crosses
+ // from a success to failure and vice versa needs to do a process swap.
+ if (SiteIsolationPolicy::IsErrorPageIsolationEnabled(
+ frame_tree_node_->IsMainFrame())) {
+ should_swap_for_error_isolation =
+ (request.state() == NavigationRequest::FAILED) !=
+ (current_site_instance->GetSiteURL() == GURL(kUnreachableWebDataURL));
+ }
+
if (frame_tree_node_->IsMainFrame()) {
// Renderer-initiated main frame navigations that may require a
// SiteInstance swap are sent to the browser via the OpenURL IPC and are
@@ -1968,16 +1957,12 @@ 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. Main frame navigations resulting in an error are also
- // expected to change process. Check it first.
+ // go cross-process. Check it first.
bool can_renderer_initiate_transfer =
- (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));
+ 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 {
@@ -1988,7 +1973,7 @@ RenderFrameHostManager::GetSiteInstanceForNavigationRequest(
request.dest_site_instance());
}
- if (no_renderer_swap_allowed)
+ if (no_renderer_swap_allowed && !should_swap_for_error_isolation)
return scoped_refptr<SiteInstance>(current_site_instance);
// If the navigation can swap SiteInstances, compute the SiteInstance it
@@ -2169,7 +2154,9 @@ void RenderFrameHostManager::CommitPending() {
// Removing them when they are deleted is too late.
// This needs to be done before updating the frame tree structure, else it
// will have trouble removing the descendants.
- render_frame_delegate_->FullscreenStateChanged(current_frame_host(), false);
+ frame_tree_node_->frame_tree()
+ ->render_frame_delegate()
+ ->FullscreenStateChanged(current_frame_host(), false);
// While the old frame is still current, remove its children from the tree.
frame_tree_node_->ResetForNewProcess();
@@ -2574,7 +2561,7 @@ bool RenderFrameHostManager::CanSubframeSwapProcess(
// If dest_url is a unique origin like about:blank, then the need for a swap
// is determined by the source_instance or dest_instance.
GURL resolved_url = dest_url;
- if (url::Origin::Create(resolved_url).unique()) {
+ if (url::Origin::Create(resolved_url).opaque()) {
if (source_instance) {
resolved_url = source_instance->GetSiteURL();
} else if (dest_instance) {
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 d8cf377f4e2..0ce014d0f9f 100644
--- a/chromium/content/browser/frame_host/render_frame_host_manager.h
+++ b/chromium/content/browser/frame_host/render_frame_host_manager.h
@@ -17,7 +17,6 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
-#include "content/browser/renderer_host/render_view_host_delegate.h"
#include "content/browser/site_instance_impl.h"
#include "content/common/content_export.h"
#include "content/public/browser/global_request_id.h"
@@ -34,12 +33,10 @@ class NavigationControllerImpl;
class NavigationEntry;
class NavigationRequest;
class NavigatorTestWithBrowserSideNavigation;
-class RenderFrameHostDelegate;
class RenderFrameHostManagerTest;
class RenderFrameProxyHost;
class RenderViewHost;
class RenderViewHostImpl;
-class RenderWidgetHostDelegate;
class RenderWidgetHostView;
class TestWebContents;
class WebUIImpl;
@@ -176,17 +173,11 @@ class CONTENT_EXPORT RenderFrameHostManager
virtual ~Delegate() {}
};
- // All three delegate pointers must be non-NULL and are not owned by this
- // class. They must outlive this class. The RenderViewHostDelegate and
- // RenderWidgetHostDelegate are what will be installed into all
- // RenderViewHosts that are created.
+ // The delegate pointer must be non-NULL and is not owned by this class. It
+ // must outlive this class.
//
// You must call Init() before using this class.
- RenderFrameHostManager(
- FrameTreeNode* frame_tree_node,
- RenderFrameHostDelegate* render_frame_delegate,
- RenderWidgetHostDelegate* render_widget_delegate,
- Delegate* delegate);
+ RenderFrameHostManager(FrameTreeNode* frame_tree_node, Delegate* delegate);
~RenderFrameHostManager();
// For arguments, see WebContentsImpl constructor.
@@ -504,8 +495,6 @@ class CONTENT_EXPORT RenderFrameHostManager
UNRELATED,
// A SiteInstance in the same browsing instance as the current.
RELATED,
- // The default subframe SiteInstance for the current browsing instance.
- RELATED_DEFAULT_SUBFRAME,
};
// Stores information regarding a SiteInstance targeted at a specific URL to
@@ -747,11 +736,6 @@ class CONTENT_EXPORT RenderFrameHostManager
// Our delegate, not owned by us. Guaranteed non-NULL.
Delegate* delegate_;
- // Implemented by the owner of this class. These delegates are installed into
- // all the RenderFrameHosts that we create.
- RenderFrameHostDelegate* render_frame_delegate_;
- RenderWidgetHostDelegate* render_widget_delegate_;
-
// Our RenderFrameHost which is responsible for all communication with a child
// RenderFrame instance.
// For now, RenderFrameHost keeps a RenderViewHost in its SiteInstance alive.
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 a6821503c3e..aa292b7a734 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
@@ -37,7 +37,6 @@
#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"
@@ -2372,6 +2371,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, WebUIGetsBindings) {
EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
shell()->web_contents()->GetMainFrame()->GetProcess()->GetID()));
SiteInstance* site_instance1 = shell()->web_contents()->GetSiteInstance();
+ int process1_id = site_instance1->GetProcess()->GetID();
// Open a new tab. Initially it gets a render view in the original tab's
// current site instance.
@@ -2384,9 +2384,14 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, WebUIGetsBindings) {
WebContentsImpl* new_web_contents = static_cast<WebContentsImpl*>(
new_shell->web_contents());
SiteInstance* site_instance2 = new_web_contents->GetSiteInstance();
+ int process2_id = site_instance2->GetProcess()->GetID();
+ // The 2nd WebUI page should swap to a different process (and SiteInstance),
+ // but should stay in the same BrowsingInstance as the 1st WebUI page.
+ EXPECT_NE(process1_id, process2_id);
EXPECT_NE(site_instance2, site_instance1);
EXPECT_TRUE(site_instance2->IsRelatedSiteInstance(site_instance1));
+
RenderViewHost* initial_rvh = new_web_contents->
GetRenderManagerForTesting()->GetSwappedOutRenderViewHost(site_instance1);
ASSERT_TRUE(initial_rvh);
@@ -3009,16 +3014,15 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
// Navigate again to the original site, but to a page that will take a while
// to commit.
GURL same_site_url(embedded_test_server()->GetURL("a.com", "/title3.html"));
- NavigationStallDelegate stall_delegate(same_site_url);
- ResourceDispatcherHost::Get()->SetDelegate(&stall_delegate);
+ TestNavigationManager stalled_navigation(new_shell->web_contents(),
+ same_site_url);
new_shell->LoadURL(same_site_url);
+ EXPECT_TRUE(stalled_navigation.WaitForRequestStart());
// Going back in history should work and the test should not crash.
TestNavigationObserver back_nav_load_observer(new_shell->web_contents());
new_shell->web_contents()->GetController().GoBack();
back_nav_load_observer.Wait();
-
- ResourceDispatcherHost::Get()->SetDelegate(nullptr);
}
// Tests that InputMsg type IPCs are ignored by swapped out RenderViews. It
@@ -3273,9 +3277,10 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
// Start a cross-site navigation to the same site but don't commit.
GURL cross_site_url(embedded_test_server()->GetURL("b.com", "/title1.html"));
- NavigationStallDelegate stall_delegate(cross_site_url);
- ResourceDispatcherHost::Get()->SetDelegate(&stall_delegate);
+ TestNavigationManager stalled_navigation(shell()->web_contents(),
+ cross_site_url);
shell()->LoadURL(cross_site_url);
+ EXPECT_TRUE(stalled_navigation.WaitForResponse());
WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(
shell()->web_contents());
@@ -3295,8 +3300,6 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
EXPECT_EQ(next_rfh, web_contents->GetMainFrame());
EXPECT_FALSE(
web_contents->GetRenderManagerForTesting()->speculative_frame_host());
-
- ResourceDispatcherHost::Get()->SetDelegate(nullptr);
}
// Check that if a sandboxed subframe opens a cross-process popup such that the
@@ -3353,11 +3356,11 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
EXPECT_NE(new_shell->web_contents()->GetSiteInstance(),
shell()->web_contents()->GetSiteInstance());
- // Check that the popup is sandboxed by checking its document.origin, which
+ // Check that the popup is sandboxed by checking its self.origin, which
// should be unique.
std::string origin;
EXPECT_TRUE(ExecuteScriptAndExtractString(
- new_shell, "domAutomationController.send(document.origin)", &origin));
+ new_shell, "domAutomationController.send(self.origin)", &origin));
EXPECT_EQ("null", origin);
};
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 bc5e48e26e0..a5e33ca7eb5 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
@@ -450,7 +450,8 @@ class RenderFrameHostManagerTest : public RenderViewHostImplTestHarness {
manager->frame_tree_node_, frame_entry->url(),
frame_entry->referrer(), *frame_entry, entry, navigate_type,
PREVIEWS_UNSPECIFIED, false, false, nullptr, base::TimeTicks::Now(),
- controller, nullptr);
+ controller, nullptr, base::TimeTicks(),
+ WasActivatedOption::kUnknown);
// Simulates request creation that triggers the 1st internal call to
// GetFrameHostForNavigation.
@@ -2823,7 +2824,8 @@ TEST_F(RenderFrameHostManagerTestWithBrowserSideNavigation,
frame_entry->referrer(), *frame_entry, entry,
FrameMsg_Navigate_Type::DIFFERENT_DOCUMENT, PREVIEWS_UNSPECIFIED,
false, false, nullptr, base::TimeTicks::Now(),
- static_cast<NavigationControllerImpl*>(&controller()), nullptr);
+ static_cast<NavigationControllerImpl*>(&controller()), nullptr,
+ base::TimeTicks(), WasActivatedOption::kUnknown);
manager->DidCreateNavigationRequest(navigation_request.get());
// As the initial RenderFrame was not live, the new RenderFrameHost should be
@@ -2885,7 +2887,8 @@ TEST_F(RenderFrameHostManagerTestWithBrowserSideNavigation,
frame_entry->referrer(), *frame_entry, entry,
FrameMsg_Navigate_Type::DIFFERENT_DOCUMENT, PREVIEWS_UNSPECIFIED,
false, false, nullptr, base::TimeTicks::Now(),
- static_cast<NavigationControllerImpl*>(&controller()), nullptr);
+ static_cast<NavigationControllerImpl*>(&controller()), nullptr,
+ base::TimeTicks(), WasActivatedOption::kUnknown);
manager->DidCreateNavigationRequest(navigation_request.get());
// The current WebUI should still be in place and the pending WebUI should be
@@ -2944,7 +2947,8 @@ TEST_F(RenderFrameHostManagerTestWithBrowserSideNavigation,
frame_entry->referrer(), *frame_entry, entry,
FrameMsg_Navigate_Type::DIFFERENT_DOCUMENT, PREVIEWS_UNSPECIFIED,
false, false, nullptr, base::TimeTicks::Now(),
- static_cast<NavigationControllerImpl*>(&controller()), nullptr);
+ static_cast<NavigationControllerImpl*>(&controller()), nullptr,
+ base::TimeTicks(), WasActivatedOption::kUnknown);
manager->DidCreateNavigationRequest(navigation_request.get());
// The current WebUI should still be in place and there should be a new
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 dfd9bb1aa8c..f1db4db0d67 100644
--- a/chromium/content/browser/frame_host/render_frame_message_filter.cc
+++ b/chromium/content/browser/frame_host/render_frame_message_filter.cc
@@ -14,6 +14,7 @@
#include "base/macros.h"
#include "base/strings/string_util.h"
#include "base/syslog_logging.h"
+#include "base/task/post_task.h"
#include "base/unguessable_token.h"
#include "build/build_config.h"
#include "components/download/public/common/download_url_parameters.h"
@@ -30,6 +31,7 @@
#include "content/common/frame_owner_properties.h"
#include "content/common/view_messages.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/download_manager.h"
#include "content/public/browser/storage_partition.h"
@@ -143,8 +145,8 @@ void DownloadBlobURLFromToken(
blob_handle = context->GetBlobDataFromUUID(uuid);
}
}
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&DownloadUrlOnUIThread, std::move(params),
std::move(blob_handle), nullptr));
}
@@ -280,8 +282,8 @@ RenderFrameMessageFilter::~RenderFrameMessageFilter() {
network::mojom::CookieManagerPtr* RenderFrameMessageFilter::GetCookieManager() {
if (!cookie_manager_ || cookie_manager_.encountered_error()) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&RenderFrameMessageFilter::InitializeCookieManager, this,
mojo::MakeRequest(&cookie_manager_)));
}
@@ -373,9 +375,9 @@ void RenderFrameMessageFilter::DownloadUrl(
}
})");
std::unique_ptr<download::DownloadUrlParameters> parameters(
- new download::DownloadUrlParameters(
- url, render_process_id_, render_view_id, render_frame_id,
- request_context_.get(), traffic_annotation));
+ new download::DownloadUrlParameters(url, render_process_id_,
+ render_view_id, render_frame_id,
+ traffic_annotation));
parameters->set_content_initiated(true);
parameters->set_suggested_name(suggested_name);
parameters->set_prompt(use_prompt);
@@ -416,8 +418,8 @@ void RenderFrameMessageFilter::DownloadUrl(
// through and allow it to be interrupted so that the embedder can deal.
}
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&DownloadUrlOnUIThread, std::move(parameters),
std::move(blob_data_handle), std::move(blob_url_token)));
}
@@ -436,8 +438,8 @@ void RenderFrameMessageFilter::OnCreateChildFrame(
*devtools_frame_token = base::UnguessableToken::Create();
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&CreateChildFrameOnUI, render_process_id_,
params.parent_routing_id, params.scope, params.frame_name,
params.frame_unique_name, params.is_created_by_script,
@@ -464,12 +466,11 @@ void RenderFrameMessageFilter::CheckPolicyForCookies(
const GURL& site_for_cookies,
GetCookiesCallback callback,
const net::CookieList& cookie_list) {
- net::URLRequestContext* context = GetRequestContextForURL(url);
// Check the policy for get cookies, and pass cookie_list to the
// TabSpecificContentSetting for logging purpose.
- if (context && GetContentClient()->browser()->AllowGetCookie(
- url, site_for_cookies, cookie_list, resource_context_,
- render_process_id_, render_frame_id)) {
+ if (GetContentClient()->browser()->AllowGetCookie(
+ url, site_for_cookies, cookie_list, resource_context_,
+ render_process_id_, render_frame_id)) {
std::move(callback).Run(net::CanonicalCookie::BuildCookieLine(cookie_list));
} else {
std::move(callback).Run(std::string());
@@ -531,7 +532,6 @@ void RenderFrameMessageFilter::SetCookie(int32_t render_frame_id,
const GURL& site_for_cookies,
const std::string& cookie_line,
SetCookieCallback callback) {
- std::move(callback).Run();
ChildProcessSecurityPolicyImpl* policy =
ChildProcessSecurityPolicyImpl::GetInstance();
if (!policy->CanAccessDataForOrigin(render_process_id_, url)) {
@@ -540,37 +540,52 @@ void RenderFrameMessageFilter::SetCookie(int32_t render_frame_id,
SYSLOG(WARNING) << "Killing renderer: illegal cookie write. Reason: "
<< reason;
bad_message::ReceivedBadMessage(this, reason);
+ std::move(callback).Run();
return;
}
net::CookieOptions options;
std::unique_ptr<net::CanonicalCookie> cookie = net::CanonicalCookie::Create(
url, cookie_line, base::Time::Now(), options);
- if (!cookie)
+ if (!cookie) {
+ std::move(callback).Run();
return;
+ }
if (!GetContentClient()->browser()->AllowSetCookie(
url, site_for_cookies, *cookie, resource_context_, render_process_id_,
- render_frame_id))
+ render_frame_id)) {
+ std::move(callback).Run();
return;
+ }
- net::URLRequestContext* context = GetRequestContextForURL(url);
- // If the embedder overrides the URLRequestContext then always use it, even if
+ // If the embedder overrides the cookie store then always use it, even if
// the network service is enabled, instead of the CookieManager associated
// this process' StoragePartition.
- if (base::FeatureList::IsEnabled(network::features::kNetworkService) &&
- context == request_context_->GetURLRequestContext()) {
- (*GetCookieManager())
- ->SetCanonicalCookie(*cookie, url.SchemeIsCryptographic(),
- !options.exclude_httponly(),
- net::CookieStore::SetCookiesCallback());
+ net::CookieStore* cookie_store =
+ GetContentClient()->browser()->OverrideCookieStoreForURL(
+ url, resource_context_);
+ if (cookie_store ||
+ !base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+ std::move(callback).Run();
+ if (!cookie_store)
+ cookie_store = request_context_->GetURLRequestContext()->cookie_store();
+
+ // Pass a null callback since we don't care about when the 'set' completes.
+ cookie_store->SetCanonicalCookieAsync(
+ std::move(cookie), url.SchemeIsCryptographic(),
+ !options.exclude_httponly(), net::CookieStore::SetCookiesCallback());
return;
}
- // Pass a null callback since we don't care about when the 'set' completes.
- context->cookie_store()->SetCanonicalCookieAsync(
- std::move(cookie), url.SchemeIsCryptographic(),
- !options.exclude_httponly(), net::CookieStore::SetCookiesCallback());
+ net::CookieStore::SetCookiesCallback net_callback =
+ base::BindOnce([](SetCookieCallback callback,
+ bool success) { std::move(callback).Run(); },
+ std::move(callback));
+ (*GetCookieManager())
+ ->SetCanonicalCookie(*cookie, url.SchemeIsCryptographic(),
+ !options.exclude_httponly(),
+ std::move(net_callback));
}
void RenderFrameMessageFilter::GetCookies(int render_frame_id,
@@ -601,33 +616,35 @@ void RenderFrameMessageFilter::GetCookies(int render_frame_id,
options.set_same_site_cookie_mode(
net::CookieOptions::SameSiteCookieMode::DO_NOT_INCLUDE);
}
-
- net::URLRequestContext* context = GetRequestContextForURL(url);
- // If the embedder overrides the URLRequestContext then always use it, even if
+ // If the embedder overrides the cookie store then always use it, even if
// the network service is enabled, instead of the CookieManager associated
// this process' StoragePartition.
- if (base::FeatureList::IsEnabled(network::features::kNetworkService) &&
- context == request_context_->GetURLRequestContext()) {
- // TODO(jam): modify GetRequestContextForURL to work with network service.
- // Merge this with code path below for non-network service.
- (*GetCookieManager())
- ->GetCookieList(
- url, options,
- base::BindOnce(&RenderFrameMessageFilter::CheckPolicyForCookies,
- this, render_frame_id, url, site_for_cookies,
- std::move(callback)));
+ net::CookieStore* cookie_store =
+ GetContentClient()->browser()->OverrideCookieStoreForURL(
+ url, resource_context_);
+ if (cookie_store ||
+ !base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+ if (!cookie_store)
+ cookie_store = request_context_->GetURLRequestContext()->cookie_store();
+
+ // If we crash here, figure out what URL the renderer was requesting.
+ // http://crbug.com/99242
+ DEBUG_ALIAS_FOR_GURL(url_buf, url);
+
+ cookie_store->GetCookieListWithOptionsAsync(
+ url, options,
+ base::BindOnce(&RenderFrameMessageFilter::CheckPolicyForCookies, this,
+ render_frame_id, url, site_for_cookies,
+ std::move(callback)));
return;
}
- // If we crash here, figure out what URL the renderer was requesting.
- // http://crbug.com/99242
- DEBUG_ALIAS_FOR_GURL(url_buf, url);
-
- context->cookie_store()->GetCookieListWithOptionsAsync(
- url, options,
- base::BindOnce(&RenderFrameMessageFilter::CheckPolicyForCookies, this,
- render_frame_id, url, site_for_cookies,
- std::move(callback)));
+ (*GetCookieManager())
+ ->GetCookieList(
+ url, options,
+ base::BindOnce(&RenderFrameMessageFilter::CheckPolicyForCookies, this,
+ render_frame_id, url, site_for_cookies,
+ std::move(callback)));
}
#if BUILDFLAG(ENABLE_PLUGINS)
@@ -718,17 +735,4 @@ void RenderFrameMessageFilter::OnPluginInstanceThrottleStateChange(
#endif // ENABLE_PLUGINS
-net::URLRequestContext* RenderFrameMessageFilter::GetRequestContextForURL(
- const GURL& url) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- net::URLRequestContext* context =
- GetContentClient()->browser()->OverrideRequestContextForURL(
- url, resource_context_);
- if (!context)
- context = request_context_->GetURLRequestContext();
-
- return context;
-}
-
} // namespace content
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 a661ac52665..91a7d32dbe7 100644
--- a/chromium/content/browser/frame_host/render_frame_message_filter.h
+++ b/chromium/content/browser/frame_host/render_frame_message_filter.h
@@ -35,7 +35,6 @@ class MessagePipeHandle;
}
namespace net {
-class URLRequestContext;
class URLRequestContextGetter;
}
@@ -171,11 +170,6 @@ class CONTENT_EXPORT RenderFrameMessageFilter
bool is_throttled);
#endif // ENABLE_PLUGINS
- // Returns the correct net::URLRequestContext depending on what type of url is
- // given.
- // Only call on the IO thread.
- net::URLRequestContext* GetRequestContextForURL(const GURL& url);
-
#if BUILDFLAG(ENABLE_PLUGINS)
PluginServiceImpl* plugin_service_;
base::FilePath profile_data_directory_;
diff --git a/chromium/content/browser/frame_host/render_frame_message_filter_browsertest.cc b/chromium/content/browser/frame_host/render_frame_message_filter_browsertest.cc
index 6f1ed61980a..01e6a62ce9c 100644
--- a/chromium/content/browser/frame_host/render_frame_message_filter_browsertest.cc
+++ b/chromium/content/browser/frame_host/render_frame_message_filter_browsertest.cc
@@ -8,6 +8,7 @@
#include "base/bind_helpers.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
+#include "base/task/post_task.h"
#include "base/test/metrics/histogram_tester.h"
#include "content/browser/bad_message.h"
#include "content/browser/frame_host/frame_tree.h"
@@ -15,6 +16,7 @@
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/frame_messages.h"
#include "content/common/render_frame_message_filter.mojom.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/common/content_switches.h"
@@ -232,7 +234,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameMessageFilterBrowserTest,
{
RenderProcessHostKillWaiter iframe_kill_waiter(iframe->GetProcess());
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO})
->PostTask(FROM_HERE,
base::BindOnce(
[](RenderFrameHost* frame) {
@@ -262,7 +264,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameMessageFilterBrowserTest,
RenderProcessHostKillWaiter main_frame_kill_waiter(
tab->GetMainFrame()->GetProcess());
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO})
->PostTask(FROM_HERE, base::BindOnce(
[](RenderFrameHost* frame) {
GetFilterForProcess(frame->GetProcess())
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 bad4c9fc4eb..80d51c9baf6 100644
--- a/chromium/content/browser/frame_host/render_frame_proxy_host.cc
+++ b/chromium/content/browser/frame_host/render_frame_proxy_host.cc
@@ -45,8 +45,7 @@ RenderFrameProxyHost* RenderFrameProxyHost::FromID(int process_id,
int routing_id) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
RoutingIDFrameProxyMap* frames = g_routing_id_frame_proxy_map.Pointer();
- RoutingIDFrameProxyMap::iterator it = frames->find(
- RenderFrameProxyHostID(process_id, routing_id));
+ auto it = frames->find(RenderFrameProxyHostID(process_id, routing_id));
return it == frames->end() ? NULL : it->second;
}
@@ -381,11 +380,6 @@ void RenderFrameProxyHost::OnRouteMessageEvent(
->SynchronizeVisualPropertiesIgnoringPendingAck();
}
- if (!source_rfh->frame_tree_node()->IsDescendantOf(
- target_rfh->frame_tree_node())) {
- target_rfh->did_receive_post_message_from_non_descendant();
- }
-
// 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_widget_host_view_guest.cc b/chromium/content/browser/frame_host/render_widget_host_view_guest.cc
index 86c4876e2d4..96c9cd10005 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
@@ -26,7 +26,8 @@
#include "content/common/browser_plugin/browser_plugin_messages.h"
#include "content/common/frame_messages.h"
#include "content/common/input/web_touch_event_traits.h"
-#include "content/common/view_messages.h"
+#include "content/common/text_input_state.h"
+#include "content/common/widget_messages.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/use_zoom_for_dsf_policy.h"
#include "gpu/ipc/common/gpu_messages.h"
@@ -371,12 +372,6 @@ void RenderWidgetHostViewGuest::SetTooltipText(
root_view->GetCursorManager()->SetTooltipTextForView(this, tooltip_text);
}
-void RenderWidgetHostViewGuest::FirstSurfaceActivation(
- const viz::SurfaceInfo& surface_info) {
- if (guest_ && !guest_->is_in_destruction())
- guest_->FirstSurfaceActivation(surface_info);
-}
-
void RenderWidgetHostViewGuest::OnDidUpdateVisualPropertiesComplete(
const cc::RenderFrameMetadata& metadata) {
if (guest_)
@@ -387,7 +382,7 @@ void RenderWidgetHostViewGuest::OnDidUpdateVisualPropertiesComplete(
void RenderWidgetHostViewGuest::OnAttached() {
RegisterFrameSinkId();
#if defined(USE_AURA)
- if (features::IsUsingWindowService()) {
+ if (features::IsMultiProcessMash()) {
aura::Env::GetInstance()->ScheduleEmbed(
GetWindowTreeClientFromRenderer(),
base::BindOnce(&RenderWidgetHostViewGuest::OnGotEmbedToken,
@@ -451,7 +446,7 @@ gfx::NativeViewAccessible RenderWidgetHostViewGuest::GetNativeViewAccessible() {
void RenderWidgetHostViewGuest::UpdateCursor(const WebCursor& cursor) {
// InterstitialPages are not WebContents so we cannot intercept
- // ViewHostMsg_SetCursor for interstitial pages in BrowserPluginGuest.
+ // WidgetHostMsg_SetCursor for interstitial pages in BrowserPluginGuest.
// All guest RenderViewHosts have RenderWidgetHostViewGuests however,
// and so we will always hit this code path.
if (!guest_)
@@ -529,14 +524,14 @@ void RenderWidgetHostViewGuest::SelectionChanged(const base::string16& text,
}
void RenderWidgetHostViewGuest::SelectionBoundsChanged(
- const ViewHostMsg_SelectionBounds_Params& params) {
+ const WidgetHostMsg_SelectionBounds_Params& params) {
if (!guest_)
return;
RenderWidgetHostViewBase* rwhv = GetOwnerRenderWidgetHostView();
if (!rwhv)
return;
- ViewHostMsg_SelectionBounds_Params guest_params(params);
+ WidgetHostMsg_SelectionBounds_Params guest_params(params);
guest_params.anchor_rect.set_origin(
guest_->GetScreenCoordinates(params.anchor_rect.origin()));
guest_params.focus_rect.set_origin(
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 db521ae67fb..dae838fe107 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
@@ -118,7 +118,7 @@ class CONTENT_EXPORT RenderWidgetHostViewGuest
size_t offset,
const gfx::Range& range) override;
void SelectionBoundsChanged(
- const ViewHostMsg_SelectionBounds_Params& params) override;
+ const WidgetHostMsg_SelectionBounds_Params& params) override;
void PreProcessMouseEvent(const blink::WebMouseEvent& event) override;
void PreProcessTouchEvent(const blink::WebTouchEvent& event) override;
@@ -166,8 +166,6 @@ class CONTENT_EXPORT RenderWidgetHostViewGuest
private:
friend class RenderWidgetHostView;
- void FirstSurfaceActivation(const viz::SurfaceInfo& surface_info) override;
-
void OnDidUpdateVisualPropertiesComplete(
const cc::RenderFrameMetadata& metadata);
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 bfa0b5f3cf9..4f12cceb05b 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
@@ -111,17 +111,9 @@ class TestBrowserPluginGuest : public BrowserPluginGuest {
~TestBrowserPluginGuest() override {}
- void ResetTestData() { last_surface_info_ = viz::SurfaceInfo(); }
-
void set_attached(bool attached) {
BrowserPluginGuest::set_attached_for_test(attached);
}
-
- void FirstSurfaceActivation(const viz::SurfaceInfo& surface_info) override {
- last_surface_info_ = surface_info;
- }
-
- viz::SurfaceInfo last_surface_info_;
};
// TODO(wjmaclean): we should restructure RenderWidgetHostViewChildFrameTest to
@@ -197,47 +189,4 @@ class RenderWidgetHostViewGuestSurfaceTest
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewGuestSurfaceTest);
};
-TEST_F(RenderWidgetHostViewGuestSurfaceTest, TestGuestSurface) {
- // Early out because RenderWidgetHostViewChildFrame::SendSurfaceInfoToEmbedder
- // is no-op on mash and the test expects it call into FirstSurfaceActivation
- // of BrowserPluginGuest.
- if (features::IsUsingWindowService())
- return;
-
- gfx::Size view_size(100, 100);
- gfx::Rect view_rect(view_size);
- float scale_factor = 1.f;
- viz::LocalSurfaceId local_surface_id(1, base::UnguessableToken::Create());
- viz::SurfaceId surface_id(view_->GetFrameSinkId(), local_surface_id);
- viz::SurfaceInfo surface_info(surface_id, scale_factor, view_size);
-
- ASSERT_TRUE(browser_plugin_guest_);
-
- view_->SetSize(view_size);
- view_->Show();
-
- browser_plugin_guest_->set_attached(true);
-
- view_->OnFirstSurfaceActivation(surface_info);
-
- EXPECT_EQ(surface_id, GetSurfaceId());
-
- // Surface ID should have been passed to BrowserPluginGuest to
- // be sent to the embedding renderer.
- EXPECT_EQ(surface_info, browser_plugin_guest_->last_surface_info_);
-
- browser_plugin_guest_->ResetTestData();
-
- // The last received SurfaceInfo must be sent to BrowserPluginGuest on
- // attachment.
- view_->OnAttached();
-
- // Surface ID should have been passed to BrowserPluginGuest to
- // be sent to the embedding renderer.
- EXPECT_EQ(surface_info, browser_plugin_guest_->last_surface_info_);
-
- browser_plugin_guest_->set_attached(false);
- browser_plugin_guest_->ResetTestData();
-}
-
} // namespace content
diff --git a/chromium/content/browser/frame_host/webui_navigation_browsertest.cc b/chromium/content/browser/frame_host/webui_navigation_browsertest.cc
index 7add77190dd..fbf93aa4c4c 100644
--- a/chromium/content/browser/frame_host/webui_navigation_browsertest.cc
+++ b/chromium/content/browser/frame_host/webui_navigation_browsertest.cc
@@ -2,12 +2,15 @@
// 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/macros.h"
#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/bindings_policy.h"
#include "content/public/common/browser_side_navigation_policy.h"
+#include "content/public/common/content_switches.h"
#include "content/public/common/url_constants.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
@@ -16,6 +19,7 @@
#include "content/shell/browser/shell.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "url/url_constants.h"
namespace content {
@@ -219,6 +223,11 @@ IN_PROC_BROWSER_TEST_F(WebUINavigationBrowserTest, WebUIMainFrameToWebAllowed) {
EXPECT_EQ(chrome_url, webui_rfh->GetLastCommittedURL());
EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
webui_rfh->GetProcess()->GetID()));
+ EXPECT_EQ(
+ ChildProcessSecurityPolicyImpl::CheckOriginLockResult::HAS_EQUAL_LOCK,
+ ChildProcessSecurityPolicyImpl::GetInstance()->CheckOriginLock(
+ root->current_frame_host()->GetProcess()->GetID(),
+ webui_site_instance->GetSiteURL()));
GURL web_url(embedded_test_server()->GetURL("/title2.html"));
std::string script =
@@ -233,6 +242,13 @@ IN_PROC_BROWSER_TEST_F(WebUINavigationBrowserTest, WebUIMainFrameToWebAllowed) {
EXPECT_NE(webui_site_instance, root->current_frame_host()->GetSiteInstance());
EXPECT_FALSE(webui_site_instance->IsRelatedSiteInstance(
root->current_frame_host()->GetSiteInstance()));
+ EXPECT_FALSE(ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
+ root->current_frame_host()->GetProcess()->GetID()));
+ EXPECT_NE(
+ ChildProcessSecurityPolicyImpl::CheckOriginLockResult::HAS_EQUAL_LOCK,
+ ChildProcessSecurityPolicyImpl::GetInstance()->CheckOriginLock(
+ root->current_frame_host()->GetProcess()->GetID(),
+ webui_site_instance->GetSiteURL()));
}
IN_PROC_BROWSER_TEST_F(WebUINavigationBrowserTest,
@@ -267,4 +283,37 @@ IN_PROC_BROWSER_TEST_F(WebUINavigationBrowserTest,
BINDINGS_POLICY_WEB_UI);
}
+IN_PROC_BROWSER_TEST_F(WebUINavigationBrowserTest,
+ WebUIOriginsRequireDedicatedProcess) {
+ // chrome:// URLs should require a dedicated process.
+ WebContents* web_contents = shell()->web_contents();
+ BrowserContext* browser_context = web_contents->GetBrowserContext();
+ GURL chrome_url = GURL(std::string(kChromeUIScheme) + "://" +
+ std::string(kChromeUIGpuHost));
+ EXPECT_TRUE(SiteInstanceImpl::DoesSiteRequireDedicatedProcess(browser_context,
+ chrome_url));
+
+ // Navigate to a WebUI page.
+ EXPECT_TRUE(NavigateToURL(shell(), chrome_url));
+
+ // Verify that the "hostname" is also part of the site URL.
+ GURL site_url = web_contents->GetMainFrame()->GetSiteInstance()->GetSiteURL();
+ EXPECT_EQ(chrome_url, site_url);
+
+ // Ask the page to create a blob URL and return back the blob URL.
+ const char* kScript = R"(
+ var blob = new Blob(['foo'], {type : 'text/html'});
+ var url = URL.createObjectURL(blob);
+ url;
+ )";
+ GURL blob_url(EvalJs(shell(), kScript).ExtractString());
+ EXPECT_EQ(url::kBlobScheme, blob_url.scheme());
+
+ // Verify that the blob also requires a dedicated process and that it would
+ // use the same site url as the original page.
+ EXPECT_TRUE(SiteInstanceImpl::DoesSiteRequireDedicatedProcess(browser_context,
+ blob_url));
+ EXPECT_EQ(chrome_url, SiteInstance::GetSiteForURL(browser_context, blob_url));
+}
+
} // namespace content
diff --git a/chromium/content/browser/gpu/browser_gpu_channel_host_factory.cc b/chromium/content/browser/gpu/browser_gpu_channel_host_factory.cc
index f141ce1abbd..50ac5ba170f 100644
--- a/chromium/content/browser/gpu/browser_gpu_channel_host_factory.cc
+++ b/chromium/content/browser/gpu/browser_gpu_channel_host_factory.cc
@@ -12,6 +12,7 @@
#include "base/location.h"
#include "base/single_thread_task_runner.h"
#include "base/synchronization/waitable_event.h"
+#include "base/task/post_task.h"
#include "base/threading/thread_restrictions.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/timer/timer.h"
@@ -25,6 +26,7 @@
#include "content/browser/gpu/gpu_process_host.h"
#include "content/browser/gpu/shader_cache_factory.h"
#include "content/common/child_process_host_impl.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/gpu_data_manager.h"
@@ -101,8 +103,8 @@ BrowserGpuChannelHostFactory::EstablishRequest::Create(
scoped_refptr<EstablishRequest> establish_request =
new EstablishRequest(gpu_client_id, gpu_client_tracing_id);
// PostTask outside the constructor to ensure at least one reference exists.
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&BrowserGpuChannelHostFactory::EstablishRequest::EstablishOnIO,
establish_request));
@@ -164,8 +166,8 @@ void BrowserGpuChannelHostFactory::EstablishRequest::OnEstablishedOnIO(
base::BindOnce(
&BrowserGpuChannelHostFactory::EstablishRequest::RestartTimeout,
this));
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&BrowserGpuChannelHostFactory::EstablishRequest::EstablishOnIO,
this));
@@ -265,8 +267,8 @@ BrowserGpuChannelHostFactory::BrowserGpuChannelHostFactory()
base::FilePath cache_dir =
GetContentClient()->browser()->GetShaderDiskCacheDirectory();
if (!cache_dir.empty()) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&BrowserGpuChannelHostFactory::InitializeShaderDiskCacheOnIO,
gpu_client_id_, cache_dir));
@@ -277,8 +279,8 @@ BrowserGpuChannelHostFactory::BrowserGpuChannelHostFactory()
base::FilePath gr_cache_dir =
GetContentClient()->browser()->GetGrShaderDiskCacheDirectory();
if (!gr_cache_dir.empty()) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&BrowserGpuChannelHostFactory::InitializeGrShaderDiskCacheOnIO,
gr_cache_dir));
@@ -349,6 +351,21 @@ BrowserGpuChannelHostFactory::GetGpuMemoryBufferManager() {
return gpu_memory_buffer_manager_.get();
}
+// Ensures that any pending timeout is cancelled when we are backgrounded.
+// Restarts the timeout when we return to the foreground.
+void BrowserGpuChannelHostFactory::SetApplicationVisible(bool is_visible) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ if (is_visible_ == is_visible)
+ return;
+
+ is_visible_ = is_visible;
+ if (is_visible_) {
+ RestartTimeout();
+ } else {
+ timeout_.Stop();
+ }
+}
+
gpu::GpuChannelHost* BrowserGpuChannelHostFactory::GetGpuChannel() {
if (gpu_channel_.get() && !gpu_channel_->IsLost())
return gpu_channel_.get();
@@ -375,7 +392,9 @@ void BrowserGpuChannelHostFactory::RestartTimeout() {
return;
}
- if (!pending_request_)
+ // Don't restart the timeout if we aren't visible. This function will be
+ // re-called when we become visible again.
+ if (!pending_request_ || !is_visible_)
return;
#if defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER) || \
diff --git a/chromium/content/browser/gpu/browser_gpu_channel_host_factory.h b/chromium/content/browser/gpu/browser_gpu_channel_host_factory.h
index 6386420710d..c620a0909f0 100644
--- a/chromium/content/browser/gpu/browser_gpu_channel_host_factory.h
+++ b/chromium/content/browser/gpu/browser_gpu_channel_host_factory.h
@@ -41,6 +41,10 @@ class CONTENT_EXPORT BrowserGpuChannelHostFactory
// thread stops.
void CloseChannel();
+ // Notify the BrowserGpuChannelHostFactory of visibility, used to prevent
+ // timeouts while backgrounded.
+ void SetApplicationVisible(bool is_visible);
+
// Overridden from gpu::GpuChannelEstablishFactory:
// The factory will return a null GpuChannelHost in the callback during
// shutdown.
@@ -69,6 +73,7 @@ class CONTENT_EXPORT BrowserGpuChannelHostFactory
std::unique_ptr<gpu::GpuMemoryBufferManager, BrowserThread::DeleteOnIOThread>
gpu_memory_buffer_manager_;
scoped_refptr<EstablishRequest> pending_request_;
+ bool is_visible_ = true;
base::OneShotTimer timeout_;
diff --git a/chromium/content/browser/gpu/browser_gpu_client_delegate.cc b/chromium/content/browser/gpu/browser_gpu_client_delegate.cc
index 20da7388187..219ca1fa616 100644
--- a/chromium/content/browser/gpu/browser_gpu_client_delegate.cc
+++ b/chromium/content/browser/gpu/browser_gpu_client_delegate.cc
@@ -4,76 +4,21 @@
#include "content/browser/gpu/browser_gpu_client_delegate.h"
-#include <utility>
-
-#include "components/viz/host/gpu_host_impl.h"
#include "content/browser/gpu/gpu_memory_buffer_manager_singleton.h"
#include "content/browser/gpu/gpu_process_host.h"
-#include "gpu/config/gpu_feature_info.h"
-#include "gpu/config/gpu_info.h"
-#include "mojo/public/cpp/system/message_pipe.h"
namespace content {
-namespace {
-
-void OnEstablishGpuChannel(
- viz::GpuClientDelegate::EstablishGpuChannelCallback callback,
- mojo::ScopedMessagePipeHandle channel_handle,
- const gpu::GPUInfo& gpu_info,
- const gpu::GpuFeatureInfo& gpu_feature_info,
- viz::GpuHostImpl::EstablishChannelStatus status) {
- if (!callback)
- return;
-
- viz::GpuClientDelegate::EstablishGpuChannelStatus delegate_status;
- switch (status) {
- case viz::GpuHostImpl::EstablishChannelStatus::kGpuAccessDenied:
- delegate_status =
- viz::GpuClientDelegate::EstablishGpuChannelStatus::kGpuAccessDenied;
- break;
- case viz::GpuHostImpl::EstablishChannelStatus::kGpuHostInvalid:
- delegate_status =
- viz::GpuClientDelegate::EstablishGpuChannelStatus::kGpuHostInvalid;
- break;
- case viz::GpuHostImpl::EstablishChannelStatus::kSuccess:
- delegate_status =
- viz::GpuClientDelegate::EstablishGpuChannelStatus::kSuccess;
- break;
- }
- std::move(callback).Run(std::move(channel_handle), gpu_info, gpu_feature_info,
- delegate_status);
-}
-
-} // namespace
BrowserGpuClientDelegate::BrowserGpuClientDelegate() = default;
BrowserGpuClientDelegate::~BrowserGpuClientDelegate() = default;
-viz::mojom::GpuService* BrowserGpuClientDelegate::EnsureGpuService() {
+viz::GpuHostImpl* BrowserGpuClientDelegate::EnsureGpuHost() {
if (auto* host = GpuProcessHost::Get())
- return host->gpu_service();
+ return host->gpu_host();
return nullptr;
}
-void BrowserGpuClientDelegate::EstablishGpuChannel(
- int client_id,
- uint64_t client_tracing_id,
- EstablishGpuChannelCallback callback) {
- auto* host = GpuProcessHost::Get();
- if (!host) {
- std::move(callback).Run(mojo::ScopedMessagePipeHandle(), gpu::GPUInfo(),
- gpu::GpuFeatureInfo(),
- EstablishGpuChannelStatus::kGpuAccessDenied);
- return;
- }
-
- const bool is_gpu_host = false;
- host->gpu_host()->EstablishGpuChannel(
- client_id, client_tracing_id, is_gpu_host,
- base::BindOnce(&OnEstablishGpuChannel, std::move(callback)));
-}
-
viz::HostGpuMemoryBufferManager*
BrowserGpuClientDelegate::GetGpuMemoryBufferManager() {
return GpuMemoryBufferManagerSingleton::GetInstance();
diff --git a/chromium/content/browser/gpu/browser_gpu_client_delegate.h b/chromium/content/browser/gpu/browser_gpu_client_delegate.h
index 18150dc6e19..ac8c634b854 100644
--- a/chromium/content/browser/gpu/browser_gpu_client_delegate.h
+++ b/chromium/content/browser/gpu/browser_gpu_client_delegate.h
@@ -15,10 +15,7 @@ class BrowserGpuClientDelegate : public viz::GpuClientDelegate {
~BrowserGpuClientDelegate() override;
// GpuClientDelegate:
- viz::mojom::GpuService* EnsureGpuService() override;
- void EstablishGpuChannel(int client_id,
- uint64_t client_tracing_id,
- EstablishGpuChannelCallback callback) override;
+ viz::GpuHostImpl* EnsureGpuHost() override;
viz::HostGpuMemoryBufferManager* GetGpuMemoryBufferManager() override;
private:
diff --git a/chromium/content/browser/gpu/ca_transaction_gpu_coordinator.cc b/chromium/content/browser/gpu/ca_transaction_gpu_coordinator.cc
index 8f3efa6a705..f68d485dfc5 100644
--- a/chromium/content/browser/gpu/ca_transaction_gpu_coordinator.cc
+++ b/chromium/content/browser/gpu/ca_transaction_gpu_coordinator.cc
@@ -5,7 +5,9 @@
#include "content/browser/gpu/ca_transaction_gpu_coordinator.h"
#include "base/cancelable_callback.h"
+#include "base/task/post_task.h"
#include "content/browser/gpu/gpu_process_host.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "services/viz/privileged/interfaces/gl/gpu_service.mojom.h"
#include "ui/accelerated_widget_mac/ca_transaction_observer.h"
@@ -61,8 +63,8 @@ void CATransactionGPUCoordinator::RemovePostCommitObserverOnUIThread() {
void CATransactionGPUCoordinator::OnActivateForTransaction() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&CATransactionGPUCoordinator::OnActivateForTransactionOnIO,
this));
}
@@ -75,8 +77,8 @@ void CATransactionGPUCoordinator::OnEnterPostCommit() {
// (and removed from the list of post-commit observers) soon after.
pending_commit_count_++;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&CATransactionGPUCoordinator::OnEnterPostCommitOnIO,
this));
}
diff --git a/chromium/content/browser/gpu/compositor_util.cc b/chromium/content/browser/gpu/compositor_util.cc
index 9bcf1916304..c4a41532110 100644
--- a/chromium/content/browser/gpu/compositor_util.cc
+++ b/chromium/content/browser/gpu/compositor_util.cc
@@ -177,6 +177,16 @@ const GpuFeatureData GetGpuFeatureData(
"Native GpuMemoryBuffers have been disabled, either via about:flags or "
"command line.",
true, true},
+ {"surface_control",
+ SafeGetFeatureStatus(gpu_feature_info,
+ gpu::GPU_FEATURE_TYPE_ANDROID_SURFACE_CONTROL),
+#if defined(OS_ANDROID)
+ !base::FeatureList::IsEnabled(features::kAndroidSurfaceControl),
+#else
+ false,
+#endif
+ "Surface Control has been disabled by Finch trial or command line.",
+ false, false},
{"surface_synchronization", gpu::kGpuFeatureStatusEnabled,
!features::IsSurfaceSynchronizationEnabled(),
"Surface synchronization has been disabled by Finch trial or command "
diff --git a/chromium/content/browser/gpu/compositor_util.h b/chromium/content/browser/gpu/compositor_util.h
index e9ed20977ea..c7155e6dec9 100644
--- a/chromium/content/browser/gpu/compositor_util.h
+++ b/chromium/content/browser/gpu/compositor_util.h
@@ -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 image animations should run in the compositor.
-CONTENT_EXPORT bool IsCompositorImageAnimationEnabled();
-
CONTENT_EXPORT std::unique_ptr<base::DictionaryValue> GetFeatureStatus();
CONTENT_EXPORT std::unique_ptr<base::ListValue> GetProblems();
CONTENT_EXPORT std::vector<std::string> GetDriverBugWorkarounds();
diff --git a/chromium/content/browser/gpu/delegate_to_browser_gpu_service_accelerator_factory.cc b/chromium/content/browser/gpu/delegate_to_browser_gpu_service_accelerator_factory.cc
new file mode 100644
index 00000000000..1d37054b3ff
--- /dev/null
+++ b/chromium/content/browser/gpu/delegate_to_browser_gpu_service_accelerator_factory.cc
@@ -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.
+
+#include "content/public/browser/delegate_to_browser_gpu_service_accelerator_factory.h"
+
+#include "content/browser/gpu/video_capture_dependencies.h"
+
+namespace content {
+
+void DelegateToBrowserGpuServiceAcceleratorFactory::CreateJpegDecodeAccelerator(
+ media::mojom::JpegDecodeAcceleratorRequest jda_request) {
+ VideoCaptureDependencies::CreateJpegDecodeAccelerator(std::move(jda_request));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/gpu/gpu_data_manager_impl.cc b/chromium/content/browser/gpu/gpu_data_manager_impl.cc
index f6d3d4c18f1..976bfcd0272 100644
--- a/chromium/content/browser/gpu/gpu_data_manager_impl.cc
+++ b/chromium/content/browser/gpu/gpu_data_manager_impl.cc
@@ -102,6 +102,20 @@ void GpuDataManagerImpl::UpdateGpuInfo(
private_->UpdateGpuInfo(gpu_info, gpu_info_for_hardware_gpu);
}
+#if defined(OS_WIN)
+void GpuDataManagerImpl::UpdateDxDiagNode(
+ const gpu::DxDiagNode& dx_diagnostics) {
+ base::AutoLock auto_lock(lock_);
+ private_->UpdateDxDiagNode(dx_diagnostics);
+}
+
+void GpuDataManagerImpl::UpdateDx12VulkanInfo(
+ const gpu::Dx12VulkanVersionInfo& dx12_vulkan_version_info) {
+ base::AutoLock auto_lock(lock_);
+ private_->UpdateDx12VulkanInfo(dx12_vulkan_version_info);
+}
+#endif
+
void GpuDataManagerImpl::UpdateGpuFeatureInfo(
const gpu::GpuFeatureInfo& gpu_feature_info,
const base::Optional<gpu::GpuFeatureInfo>&
@@ -162,8 +176,8 @@ void GpuDataManagerImpl::HandleGpuSwitch() {
private_->HandleGpuSwitch();
}
-void GpuDataManagerImpl::BlockDomainFrom3DAPIs(
- const GURL& url, DomainGuilt guilt) {
+void GpuDataManagerImpl::BlockDomainFrom3DAPIs(const GURL& url,
+ gpu::DomainGuilt guilt) {
base::AutoLock auto_lock(lock_);
private_->BlockDomainFrom3DAPIs(url, guilt);
}
diff --git a/chromium/content/browser/gpu/gpu_data_manager_impl.h b/chromium/content/browser/gpu/gpu_data_manager_impl.h
index d91d77659f3..2a18cf5b40e 100644
--- a/chromium/content/browser/gpu/gpu_data_manager_impl.h
+++ b/chromium/content/browser/gpu/gpu_data_manager_impl.h
@@ -17,11 +17,14 @@
#include "base/no_destructor.h"
#include "base/process/kill.h"
#include "base/synchronization/lock.h"
+#include "base/thread_annotations.h"
#include "base/time/time.h"
#include "base/values.h"
+#include "build/build_config.h"
#include "content/public/browser/gpu_data_manager.h"
#include "content/public/common/three_d_api_types.h"
#include "gpu/config/gpu_control_list.h"
+#include "gpu/config/gpu_domain_guilt.h"
#include "gpu/config/gpu_feature_info.h"
#include "gpu/config/gpu_info.h"
#include "gpu/config/gpu_mode.h"
@@ -43,24 +46,6 @@ class GpuDataManagerImplPrivate;
class CONTENT_EXPORT GpuDataManagerImpl : public GpuDataManager {
public:
- // Indicates the guilt level of a domain which caused a GPU reset.
- // If a domain is 100% known to be guilty of resetting the GPU, then
- // it will generally not cause other domains' use of 3D APIs to be
- // blocked, unless system stability would be compromised.
- enum DomainGuilt {
- DOMAIN_GUILT_KNOWN,
- DOMAIN_GUILT_UNKNOWN
- };
-
- // Indicates the reason that access to a given client API (like
- // WebGL or Pepper 3D) was blocked or not. This state is distinct
- // from blacklisting of an entire feature.
- enum DomainBlockStatus {
- DOMAIN_BLOCK_STATUS_BLOCKED,
- DOMAIN_BLOCK_STATUS_ALL_DOMAINS_BLOCKED,
- DOMAIN_BLOCK_STATUS_NOT_BLOCKED
- };
-
// Getter for the singleton. This will return NULL on failure.
static GpuDataManagerImpl* GetInstance();
@@ -89,12 +74,14 @@ class CONTENT_EXPORT GpuDataManagerImpl : public GpuDataManager {
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,
const base::Optional<gpu::GPUInfo>& gpu_info_for_hardware_gpu);
-
+#if defined(OS_WIN)
+ void UpdateDx12VulkanInfo(
+ const gpu::Dx12VulkanVersionInfo& dx12_vulkan_version_info);
+ void UpdateDxDiagNode(const gpu::DxDiagNode& dx_diagnostics);
+#endif
// 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,
@@ -132,7 +119,7 @@ class CONTENT_EXPORT GpuDataManagerImpl : public GpuDataManager {
//
// The given URL may be a partial URL (including at least the host)
// or a full URL to a page.
- void BlockDomainFrom3DAPIs(const GURL& url, DomainGuilt guilt);
+ void BlockDomainFrom3DAPIs(const GURL& url, gpu::DomainGuilt guilt);
bool Are3DAPIsBlocked(const GURL& top_origin_url,
int render_process_id,
int render_frame_id,
@@ -176,7 +163,8 @@ class CONTENT_EXPORT GpuDataManagerImpl : public GpuDataManager {
~GpuDataManagerImpl() override;
mutable base::Lock lock_;
- std::unique_ptr<GpuDataManagerImplPrivate> private_;
+ std::unique_ptr<GpuDataManagerImplPrivate> private_ GUARDED_BY(lock_)
+ PT_GUARDED_BY(lock_);
DISALLOW_COPY_AND_ASSIGN(GpuDataManagerImpl);
};
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 4541da4f15c..03a570f5d8e 100644
--- a/chromium/content/browser/gpu/gpu_data_manager_impl_private.cc
+++ b/chromium/content/browser/gpu/gpu_data_manager_impl_private.cc
@@ -18,6 +18,7 @@
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
+#include "base/task/post_task.h"
#include "base/trace_event/trace_event.h"
#include "base/version.h"
#include "build/build_config.h"
@@ -25,6 +26,7 @@
#include "components/viz/common/features.h"
#include "content/browser/gpu/gpu_memory_buffer_manager_singleton.h"
#include "content/browser/gpu/gpu_process_host.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/gpu_data_manager_observer.h"
#include "content/public/browser/gpu_utils.h"
@@ -235,8 +237,8 @@ void OnVideoMemoryUsageStats(
const base::Callback<void(const gpu::VideoMemoryUsageStats& stats)>&
callback,
const gpu::VideoMemoryUsageStats& stats) {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(callback, stats));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(callback, stats));
}
void RequestVideoMemoryUsageStats(
@@ -249,21 +251,35 @@ void RequestVideoMemoryUsageStats(
base::BindOnce(&OnVideoMemoryUsageStats, callback));
}
-void UpdateGpuInfoOnIO(const gpu::GPUInfo& gpu_info) {
+#if defined(OS_WIN)
+void UpdateDxDiagNodeOnIO(const gpu::DxDiagNode& dx_diagnostics) {
// This function is called on the IO thread, but GPUInfo on GpuDataManagerImpl
- // should be updated on the UI thread (since it can call into functions that
- // expect to run in the UI thread, e.g. ContentClient::SetGpuInfo()).
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ // should be updated on the UI thread since it can call into functions that
+ // expect to run in the UI thread.
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(
- [](const gpu::GPUInfo& gpu_info) {
- TRACE_EVENT0("test_gpu", "OnGraphicsInfoCollected");
- GpuDataManagerImpl::GetInstance()->UpdateGpuInfo(gpu_info,
- base::nullopt);
+ [](const gpu::DxDiagNode& dx_diagnostics) {
+ GpuDataManagerImpl::GetInstance()->UpdateDxDiagNode(dx_diagnostics);
},
- gpu_info));
+ dx_diagnostics));
}
+void UpdateDx12VulkanInfoOnIO(
+ const gpu::Dx12VulkanVersionInfo& dx12_vulkan_version_info) {
+ // This function is called on the IO thread, but GPUInfo on GpuDataManagerImpl
+ // should be updated on the UI thread since it can call into functions that
+ // expect to run in the UI thread.
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(
+ [](const gpu::Dx12VulkanVersionInfo& dx12_vulkan_version_info) {
+ GpuDataManagerImpl::GetInstance()->UpdateDx12VulkanInfo(
+ dx12_vulkan_version_info);
+ },
+ dx12_vulkan_version_info));
+}
+#endif
} // anonymous namespace
GpuDataManagerImplPrivate::GpuDataManagerImplPrivate(GpuDataManagerImpl* owner)
@@ -335,9 +351,6 @@ bool GpuDataManagerImplPrivate::GpuAccessAllowed(std::string* reason) const {
if (swiftshader_available)
return true;
- if (in_process_gpu_)
- return true;
-
if (card_disabled_) {
if (reason) {
*reason = "GPU access is disabled ";
@@ -373,25 +386,26 @@ void GpuDataManagerImplPrivate::RequestCompleteGpuInfoIfNeeded() {
return;
if (!NeedsCompleteGpuInfoCollection())
return;
+
+#if defined(OS_WIN)
if (!GpuAccessAllowed(nullptr))
return;
if (in_process_gpu_)
return;
-
complete_gpu_info_already_requested_ = true;
-
- GpuProcessHost::CallOnIO(
-#if defined(OS_WIN)
- GpuProcessHost::GPU_PROCESS_KIND_UNSANDBOXED,
+ GpuProcessHost::CallOnIO(GpuProcessHost::GPU_PROCESS_KIND_UNSANDBOXED_NO_GL,
+ true /* force_create */,
+ base::Bind([](GpuProcessHost* host) {
+ if (!host)
+ return;
+ host->gpu_service()->RequestCompleteGpuInfo(
+ base::BindOnce(&UpdateDxDiagNodeOnIO));
+ }));
#else
- GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
+ // NeedsCompleteGpuInfoCollection() always returns false on platforms other
+ // than Windows.
+ NOTREACHED();
#endif
- true /* force_create */, base::Bind([](GpuProcessHost* host) {
- if (!host)
- return;
- host->gpu_service()->RequestCompleteGpuInfo(
- base::BindOnce(&UpdateGpuInfoOnIO));
- }));
}
void GpuDataManagerImplPrivate::RequestGpuSupportedRuntimeVersion() {
@@ -399,16 +413,20 @@ void GpuDataManagerImplPrivate::RequestGpuSupportedRuntimeVersion() {
if (in_process_gpu_)
return;
base::OnceClosure task = base::BindOnce([]() {
- GpuProcessHost* host = GpuProcessHost::Get(
- GpuProcessHost::GPU_PROCESS_KIND_UNSANDBOXED, true /* force_create */);
+ GpuProcessHost* host =
+ GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_UNSANDBOXED_NO_GL,
+ true /* force_create */);
if (!host)
return;
host->gpu_service()->GetGpuSupportedRuntimeVersion(
- base::BindOnce(&UpdateGpuInfoOnIO));
+ base::BindOnce(&UpdateDx12VulkanInfoOnIO));
});
- BrowserThread::PostDelayedTask(BrowserThread::IO, FROM_HERE, std::move(task),
- base::TimeDelta::FromMilliseconds(15000));
+ base::PostDelayedTaskWithTraits(FROM_HERE, {BrowserThread::IO},
+ std::move(task),
+ base::TimeDelta::FromMilliseconds(15000));
+#else
+ NOTREACHED();
#endif
}
@@ -474,47 +492,54 @@ void GpuDataManagerImplPrivate::UnblockDomainFrom3DAPIs(const GURL& url) {
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;
+ // If GPU process crashes and launches again, GPUInfo will be sent back from
+ // the new GPU process again, and may overwrite the DX12, Vulkan, DxDiagNode
+ // info we already collected. This is to make sure it doesn't happen.
+ gpu::DxDiagNode dx_diagnostics = gpu_info_.dx_diagnostics;
+ gpu::Dx12VulkanVersionInfo dx12_vulkan_version_info =
+ gpu_info_.dx12_vulkan_version_info;
#endif
gpu_info_ = gpu_info;
+#if defined(OS_WIN)
+ if (!dx_diagnostics.IsEmpty()) {
+ gpu_info_.dx_diagnostics = dx_diagnostics;
+ }
+ if (!dx12_vulkan_version_info.IsEmpty()) {
+ gpu_info_.dx12_vulkan_version_info = dx12_vulkan_version_info;
+ }
+#endif // OS_WIN
+
if (!gpu_info_for_hardware_gpu_.IsInitialized()) {
- if (!!gpu_info_for_hardware_gpu) {
+ 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;
+ 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
- if (complete_gpu_info_already_requested_ &&
- !NeedsCompleteGpuInfoCollection()) {
+ GetContentClient()->SetGpuInfo(gpu_info_);
+ NotifyGpuInfoUpdate();
+}
+
+#if defined(OS_WIN)
+void GpuDataManagerImplPrivate::UpdateDxDiagNode(
+ const gpu::DxDiagNode& dx_diagnostics) {
+ gpu_info_.dx_diagnostics = dx_diagnostics;
+ if (complete_gpu_info_already_requested_)
complete_gpu_info_already_requested_ = false;
- }
+ // No need to call GetContentClient()->SetGpuInfo().
+ NotifyGpuInfoUpdate();
+}
- GetContentClient()->SetGpuInfo(gpu_info_);
+void GpuDataManagerImplPrivate::UpdateDx12VulkanInfo(
+ const gpu::Dx12VulkanVersionInfo& dx12_vulkan_version_info) {
+ gpu_info_.dx12_vulkan_version_info = dx12_vulkan_version_info;
+ // No need to call GetContentClient()->SetGpuInfo().
NotifyGpuInfoUpdate();
}
+#endif
void GpuDataManagerImplPrivate::UpdateGpuFeatureInfo(
const gpu::GpuFeatureInfo& gpu_feature_info,
@@ -708,8 +733,8 @@ bool GpuDataManagerImplPrivate::UpdateActiveGpu(uint32_t vendor_id,
return true;
}
-void GpuDataManagerImplPrivate::BlockDomainFrom3DAPIs(
- const GURL& url, GpuDataManagerImpl::DomainGuilt guilt) {
+void GpuDataManagerImplPrivate::BlockDomainFrom3DAPIs(const GURL& url,
+ gpu::DomainGuilt guilt) {
BlockDomainFrom3DAPIsAtTime(url, guilt, base::Time::Now());
}
@@ -718,7 +743,7 @@ bool GpuDataManagerImplPrivate::Are3DAPIsBlocked(const GURL& top_origin_url,
int render_frame_id,
ThreeDAPIType requester) {
return Are3DAPIsBlockedAtTime(top_origin_url, base::Time::Now()) !=
- GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_NOT_BLOCKED;
+ DomainBlockStatus::kNotBlocked;
}
void GpuDataManagerImplPrivate::DisableDomainBlockingFor3DAPIsForTesting() {
@@ -758,35 +783,33 @@ std::string GpuDataManagerImplPrivate::GetDomainFromURL(const GURL& url) const {
void GpuDataManagerImplPrivate::BlockDomainFrom3DAPIsAtTime(
const GURL& url,
- GpuDataManagerImpl::DomainGuilt guilt,
+ gpu::DomainGuilt guilt,
base::Time at_time) {
if (!domain_blocking_enabled_)
return;
std::string domain = GetDomainFromURL(url);
- DomainBlockEntry& entry = blocked_domains_[domain];
- entry.last_guilt = guilt;
+ blocked_domains_[domain] = guilt;
timestamps_of_gpu_resets_.push_back(at_time);
}
-GpuDataManagerImpl::DomainBlockStatus
-GpuDataManagerImplPrivate::Are3DAPIsBlockedAtTime(
- const GURL& url, base::Time at_time) const {
+GpuDataManagerImplPrivate::DomainBlockStatus
+GpuDataManagerImplPrivate::Are3DAPIsBlockedAtTime(const GURL& url,
+ base::Time at_time) const {
if (!domain_blocking_enabled_)
- return GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_NOT_BLOCKED;
+ return DomainBlockStatus::kNotBlocked;
// Note: adjusting the policies in this code will almost certainly
// require adjusting the associated unit tests.
std::string domain = GetDomainFromURL(url);
{
- DomainBlockMap::const_iterator iter = blocked_domains_.find(domain);
- if (iter != blocked_domains_.end()) {
+ if (blocked_domains_.find(domain) != blocked_domains_.end()) {
// Err on the side of caution, and assume that if a particular
// domain shows up in the block map, it's there for a good
// reason and don't let its presence there automatically expire.
- return GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_BLOCKED;
+ return DomainBlockStatus::kBlocked;
}
}
@@ -798,7 +821,7 @@ GpuDataManagerImplPrivate::Are3DAPIsBlockedAtTime(
// TODO(kbr): make this pay attention to the TDR thresholds in the
// Windows registry, but make sure it continues to be testable.
{
- std::list<base::Time>::iterator iter = timestamps_of_gpu_resets_.begin();
+ auto iter = timestamps_of_gpu_resets_.begin();
int num_resets_within_timeframe = 0;
while (iter != timestamps_of_gpu_resets_.end()) {
base::Time time = *iter;
@@ -819,7 +842,7 @@ GpuDataManagerImplPrivate::Are3DAPIsBlockedAtTime(
BLOCK_STATUS_ALL_DOMAINS_BLOCKED,
BLOCK_STATUS_MAX);
- return GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_ALL_DOMAINS_BLOCKED;
+ return DomainBlockStatus::kAllDomainsBlocked;
}
}
@@ -827,7 +850,7 @@ GpuDataManagerImplPrivate::Are3DAPIsBlockedAtTime(
BLOCK_STATUS_NOT_BLOCKED,
BLOCK_STATUS_MAX);
- return GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_NOT_BLOCKED;
+ return DomainBlockStatus::kNotBlocked;
}
int64_t GpuDataManagerImplPrivate::GetBlockAllDomainsDurationInMs() const {
@@ -835,11 +858,8 @@ int64_t GpuDataManagerImplPrivate::GetBlockAllDomainsDurationInMs() const {
}
bool GpuDataManagerImplPrivate::NeedsCompleteGpuInfoCollection() const {
-#if defined(OS_MACOSX)
- return gpu_info_.gl_vendor.empty();
-#elif defined(OS_WIN)
- return (gpu_info_.dx_diagnostics.values.empty() &&
- gpu_info_.dx_diagnostics.children.empty());
+#if defined(OS_WIN)
+ return gpu_info_.dx_diagnostics.IsEmpty();
#else
return false;
#endif
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 68fc14b5286..96346d564cc 100644
--- a/chromium/content/browser/gpu/gpu_data_manager_impl_private.h
+++ b/chromium/content/browser/gpu/gpu_data_manager_impl_private.h
@@ -63,6 +63,11 @@ class CONTENT_EXPORT GpuDataManagerImplPrivate {
void UpdateGpuInfo(
const gpu::GPUInfo& gpu_info,
const base::Optional<gpu::GPUInfo>& optional_gpu_info_for_hardware_gpu);
+#if defined(OS_WIN)
+ void UpdateDxDiagNode(const gpu::DxDiagNode& dx_diagnostics);
+ void UpdateDx12VulkanInfo(
+ const gpu::Dx12VulkanVersionInfo& dx12_vulkan_version_info);
+#endif
void UpdateGpuFeatureInfo(const gpu::GpuFeatureInfo& gpu_feature_info,
const base::Optional<gpu::GpuFeatureInfo>&
gpu_feature_info_for_hardware_gpu);
@@ -83,8 +88,7 @@ class CONTENT_EXPORT GpuDataManagerImplPrivate {
void HandleGpuSwitch();
- void BlockDomainFrom3DAPIs(
- const GURL& url, GpuDataManagerImpl::DomainGuilt guilt);
+ void BlockDomainFrom3DAPIs(const GURL& url, gpu::DomainGuilt guilt);
bool Are3DAPIsBlocked(const GURL& top_origin_url,
int render_process_id,
int render_frame_id,
@@ -125,11 +129,16 @@ class CONTENT_EXPORT GpuDataManagerImplPrivate {
FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplPrivateTest,
UnblockThisDomainFrom3DAPIs);
- struct DomainBlockEntry {
- GpuDataManagerImpl::DomainGuilt last_guilt;
+ // Indicates the reason that access to a given client API (like
+ // WebGL or Pepper 3D) was blocked or not. This state is distinct
+ // from blacklisting of an entire feature.
+ enum class DomainBlockStatus {
+ kBlocked,
+ kAllDomainsBlocked,
+ kNotBlocked,
};
- using DomainBlockMap = std::map<std::string, DomainBlockEntry>;
+ using DomainGuiltMap = std::map<std::string, gpu::DomainGuilt>;
using GpuDataManagerObserverList =
base::ObserverListThreadSafe<GpuDataManagerObserver>;
@@ -157,16 +166,15 @@ class CONTENT_EXPORT GpuDataManagerImplPrivate {
// Implementation functions for blocking of 3D graphics APIs, used
// for unit testing.
void BlockDomainFrom3DAPIsAtTime(const GURL& url,
- GpuDataManagerImpl::DomainGuilt guilt,
+ gpu::DomainGuilt guilt,
base::Time at_time);
- GpuDataManagerImpl::DomainBlockStatus Are3DAPIsBlockedAtTime(
- const GURL& url, base::Time at_time) const;
+ DomainBlockStatus Are3DAPIsBlockedAtTime(const GURL& url,
+ base::Time at_time) const;
int64_t GetBlockAllDomainsDurationInMs() const;
// This is platform specific. At the moment:
- // 1) on MacOSX, if GL strings are missing, this returns true;
- // 2) on Windows, if DxDiagnostics are missing, this returns true;
- // 3) all other platforms, this returns false.
+ // 1) on Windows, if DxDiagnostics are missing, this returns true;
+ // 2) all other platforms, this returns false.
bool NeedsCompleteGpuInfoCollection() const;
GpuDataManagerImpl* const owner_;
@@ -197,7 +205,7 @@ class CONTENT_EXPORT GpuDataManagerImplPrivate {
// they cause random failures.
bool update_histograms_ = true;
- DomainBlockMap blocked_domains_;
+ DomainGuiltMap blocked_domains_;
mutable std::list<base::Time> timestamps_of_gpu_resets_;
bool domain_blocking_enabled_ = true;
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 bb1ddc7b334..6dac8e939ee 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
@@ -6,8 +6,8 @@
#include "base/command_line.h"
#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
+#include "base/test/scoped_task_environment.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "content/browser/gpu/gpu_data_manager_impl_private.h"
@@ -84,8 +84,14 @@ class GpuDataManagerImplPrivateTest : public testing::Test {
ScopedGpuDataManagerImplPrivate() { EXPECT_TRUE(impl_.private_.get()); }
~ScopedGpuDataManagerImplPrivate() = default;
- GpuDataManagerImplPrivate* get() { return impl_.private_.get(); }
- GpuDataManagerImplPrivate* operator->() { return impl_.private_.get(); }
+ // NO_THREAD_SAFETY_ANALYSIS should be fine below, because unit tests
+ // pinky-promise to only run single-threaded.
+ GpuDataManagerImplPrivate* get() NO_THREAD_SAFETY_ANALYSIS {
+ return impl_.private_.get();
+ }
+ GpuDataManagerImplPrivate* operator->() NO_THREAD_SAFETY_ANALYSIS {
+ return impl_.private_.get();
+ }
private:
GpuDataManagerImpl impl_;
@@ -94,12 +100,10 @@ class GpuDataManagerImplPrivateTest : public testing::Test {
base::Time JustBeforeExpiration(const GpuDataManagerImplPrivate* manager);
base::Time JustAfterExpiration(const GpuDataManagerImplPrivate* manager);
- void TestBlockingDomainFrom3DAPIs(
- GpuDataManagerImpl::DomainGuilt guilt_level);
- void TestUnblockingDomainFrom3DAPIs(
- GpuDataManagerImpl::DomainGuilt guilt_level);
+ void TestBlockingDomainFrom3DAPIs(gpu::DomainGuilt guilt_level);
+ void TestUnblockingDomainFrom3DAPIs(gpu::DomainGuilt guilt_level);
- base::MessageLoop message_loop_;
+ base::test::ScopedTaskEnvironment task_environment_;
};
// We use new method instead of GetInstance() method because we want
@@ -141,7 +145,7 @@ base::Time GpuDataManagerImplPrivateTest::JustAfterExpiration(
}
void GpuDataManagerImplPrivateTest::TestBlockingDomainFrom3DAPIs(
- GpuDataManagerImpl::DomainGuilt guilt_level) {
+ gpu::DomainGuilt guilt_level) {
ScopedGpuDataManagerImplPrivate manager;
manager->BlockDomainFrom3DAPIsAtTime(GetDomain1ForTesting(),
@@ -149,19 +153,19 @@ void GpuDataManagerImplPrivateTest::TestBlockingDomainFrom3DAPIs(
GetTimeForTesting());
// This domain should be blocked no matter what.
- EXPECT_EQ(GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_BLOCKED,
+ EXPECT_EQ(GpuDataManagerImplPrivate::DomainBlockStatus::kBlocked,
manager->Are3DAPIsBlockedAtTime(GetDomain1ForTesting(),
- GetTimeForTesting()));
- EXPECT_EQ(GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_BLOCKED,
+ GetTimeForTesting()));
+ EXPECT_EQ(GpuDataManagerImplPrivate::DomainBlockStatus::kBlocked,
manager->Are3DAPIsBlockedAtTime(
GetDomain1ForTesting(), JustBeforeExpiration(manager.get())));
- EXPECT_EQ(GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_BLOCKED,
+ EXPECT_EQ(GpuDataManagerImplPrivate::DomainBlockStatus::kBlocked,
manager->Are3DAPIsBlockedAtTime(
GetDomain1ForTesting(), JustAfterExpiration(manager.get())));
}
void GpuDataManagerImplPrivateTest::TestUnblockingDomainFrom3DAPIs(
- GpuDataManagerImpl::DomainGuilt guilt_level) {
+ gpu::DomainGuilt guilt_level) {
ScopedGpuDataManagerImplPrivate manager;
manager->BlockDomainFrom3DAPIsAtTime(GetDomain1ForTesting(),
@@ -170,64 +174,62 @@ void GpuDataManagerImplPrivateTest::TestUnblockingDomainFrom3DAPIs(
// Unblocking the domain should work.
manager->UnblockDomainFrom3DAPIs(GetDomain1ForTesting());
- EXPECT_EQ(GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_NOT_BLOCKED,
+ EXPECT_EQ(GpuDataManagerImplPrivate::DomainBlockStatus::kNotBlocked,
manager->Are3DAPIsBlockedAtTime(GetDomain1ForTesting(),
GetTimeForTesting()));
- EXPECT_EQ(GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_NOT_BLOCKED,
+ EXPECT_EQ(GpuDataManagerImplPrivate::DomainBlockStatus::kNotBlocked,
manager->Are3DAPIsBlockedAtTime(
GetDomain1ForTesting(), JustBeforeExpiration(manager.get())));
- EXPECT_EQ(GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_NOT_BLOCKED,
+ EXPECT_EQ(GpuDataManagerImplPrivate::DomainBlockStatus::kNotBlocked,
manager->Are3DAPIsBlockedAtTime(
GetDomain1ForTesting(), JustAfterExpiration(manager.get())));
}
TEST_F(GpuDataManagerImplPrivateTest, BlockGuiltyDomainFrom3DAPIs) {
- TestBlockingDomainFrom3DAPIs(GpuDataManagerImpl::DOMAIN_GUILT_KNOWN);
+ TestBlockingDomainFrom3DAPIs(gpu::DomainGuilt::kKnown);
}
TEST_F(GpuDataManagerImplPrivateTest, BlockDomainOfUnknownGuiltFrom3DAPIs) {
- TestBlockingDomainFrom3DAPIs(GpuDataManagerImpl::DOMAIN_GUILT_UNKNOWN);
+ TestBlockingDomainFrom3DAPIs(gpu::DomainGuilt::kUnknown);
}
TEST_F(GpuDataManagerImplPrivateTest, BlockAllDomainsFrom3DAPIs) {
ScopedGpuDataManagerImplPrivate manager;
- manager->BlockDomainFrom3DAPIsAtTime(GetDomain1ForTesting(),
- GpuDataManagerImpl::DOMAIN_GUILT_UNKNOWN,
- GetTimeForTesting());
+ manager->BlockDomainFrom3DAPIsAtTime(
+ GetDomain1ForTesting(), gpu::DomainGuilt::kUnknown, GetTimeForTesting());
// Blocking of other domains should expire.
- EXPECT_EQ(GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_ALL_DOMAINS_BLOCKED,
+ EXPECT_EQ(GpuDataManagerImplPrivate::DomainBlockStatus::kAllDomainsBlocked,
manager->Are3DAPIsBlockedAtTime(
GetDomain2ForTesting(), JustBeforeExpiration(manager.get())));
- EXPECT_EQ(GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_NOT_BLOCKED,
+ EXPECT_EQ(GpuDataManagerImplPrivate::DomainBlockStatus::kNotBlocked,
manager->Are3DAPIsBlockedAtTime(
GetDomain2ForTesting(), JustAfterExpiration(manager.get())));
}
TEST_F(GpuDataManagerImplPrivateTest, UnblockGuiltyDomainFrom3DAPIs) {
- TestUnblockingDomainFrom3DAPIs(GpuDataManagerImpl::DOMAIN_GUILT_KNOWN);
+ TestUnblockingDomainFrom3DAPIs(gpu::DomainGuilt::kKnown);
}
TEST_F(GpuDataManagerImplPrivateTest, UnblockDomainOfUnknownGuiltFrom3DAPIs) {
- TestUnblockingDomainFrom3DAPIs(GpuDataManagerImpl::DOMAIN_GUILT_UNKNOWN);
+ TestUnblockingDomainFrom3DAPIs(gpu::DomainGuilt::kUnknown);
}
TEST_F(GpuDataManagerImplPrivateTest, UnblockOtherDomainFrom3DAPIs) {
ScopedGpuDataManagerImplPrivate manager;
- manager->BlockDomainFrom3DAPIsAtTime(GetDomain1ForTesting(),
- GpuDataManagerImpl::DOMAIN_GUILT_UNKNOWN,
- GetTimeForTesting());
+ manager->BlockDomainFrom3DAPIsAtTime(
+ GetDomain1ForTesting(), gpu::DomainGuilt::kUnknown, GetTimeForTesting());
manager->UnblockDomainFrom3DAPIs(GetDomain2ForTesting());
- EXPECT_EQ(GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_NOT_BLOCKED,
+ EXPECT_EQ(GpuDataManagerImplPrivate::DomainBlockStatus::kNotBlocked,
manager->Are3DAPIsBlockedAtTime(
GetDomain2ForTesting(), JustBeforeExpiration(manager.get())));
// The original domain should still be blocked.
- EXPECT_EQ(GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_BLOCKED,
+ EXPECT_EQ(GpuDataManagerImplPrivate::DomainBlockStatus::kBlocked,
manager->Are3DAPIsBlockedAtTime(
GetDomain1ForTesting(), JustBeforeExpiration(manager.get())));
}
@@ -235,15 +237,14 @@ TEST_F(GpuDataManagerImplPrivateTest, UnblockOtherDomainFrom3DAPIs) {
TEST_F(GpuDataManagerImplPrivateTest, UnblockThisDomainFrom3DAPIs) {
ScopedGpuDataManagerImplPrivate manager;
- manager->BlockDomainFrom3DAPIsAtTime(GetDomain1ForTesting(),
- GpuDataManagerImpl::DOMAIN_GUILT_UNKNOWN,
- GetTimeForTesting());
+ manager->BlockDomainFrom3DAPIsAtTime(
+ GetDomain1ForTesting(), gpu::DomainGuilt::kUnknown, GetTimeForTesting());
manager->UnblockDomainFrom3DAPIs(GetDomain1ForTesting());
// This behavior is debatable. Perhaps the GPU reset caused by
// domain 1 should still cause other domains to be blocked.
- EXPECT_EQ(GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_NOT_BLOCKED,
+ EXPECT_EQ(GpuDataManagerImplPrivate::DomainBlockStatus::kNotBlocked,
manager->Are3DAPIsBlockedAtTime(
GetDomain2ForTesting(), JustBeforeExpiration(manager.get())));
}
diff --git a/chromium/content/browser/gpu/gpu_internals_ui.cc b/chromium/content/browser/gpu/gpu_internals_ui.cc
index 02779864950..abfcc0c3c02 100644
--- a/chromium/content/browser/gpu/gpu_internals_ui.cc
+++ b/chromium/content/browser/gpu/gpu_internals_ui.cc
@@ -213,11 +213,12 @@ std::unique_ptr<base::ListValue> BasicGpuInfoAsListValue(
basic_info->Append(NewDescriptionValuePair(
"Driver D3D12 feature level",
- D3dFeaturelevelToString(gpu_info.d3d12_feature_level)));
+ D3dFeaturelevelToString(
+ gpu_info.dx12_vulkan_version_info.d3d12_feature_level)));
- basic_info->Append(
- NewDescriptionValuePair("Driver Vulkan API version",
- VulkanVersionToString(gpu_info.vulkan_version)));
+ basic_info->Append(NewDescriptionValuePair(
+ "Driver Vulkan API version",
+ VulkanVersionToString(gpu_info.dx12_vulkan_version_info.vulkan_version)));
#endif
basic_info->Append(
diff --git a/chromium/content/browser/gpu/gpu_ipc_browsertests.cc b/chromium/content/browser/gpu/gpu_ipc_browsertests.cc
index 5c930b2e7da..02b5dac7d15 100644
--- a/chromium/content/browser/gpu/gpu_ipc_browsertests.cc
+++ b/chromium/content/browser/gpu/gpu_ipc_browsertests.cc
@@ -4,15 +4,17 @@
#include "base/command_line.h"
#include "base/run_loop.h"
+#include "base/task/post_task.h"
#include "build/build_config.h"
#include "components/viz/common/gpu/context_provider.h"
#include "content/browser/browser_main_loop.h"
#include "content/browser/compositor/image_transport_factory.h"
#include "content/browser/gpu/gpu_process_host.h"
-#include "content/common/gpu_stream_constants.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/gpu_data_manager.h"
#include "content/public/browser/gpu_utils.h"
#include "content/public/common/content_switches.h"
+#include "content/public/common/gpu_stream_constants.h"
#include "content/public/test/content_browser_test.h"
#include "content/test/gpu_browsertest_helpers.h"
#include "gpu/ipc/client/command_buffer_proxy_impl.h"
@@ -349,7 +351,7 @@ IN_PROC_BROWSER_TEST_F(BrowserGpuChannelHostFactoryTest, CreateTransferBuffer) {
// channel on the IO thread, which then notifies the main thread about the
// error state.
base::RunLoop wait_for_io_run_loop;
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO})
->PostTask(FROM_HERE, wait_for_io_run_loop.QuitClosure());
// Waits for the IO thread to run.
wait_for_io_run_loop.Run();
diff --git a/chromium/content/browser/gpu/gpu_memory_buffer_manager_singleton.cc b/chromium/content/browser/gpu/gpu_memory_buffer_manager_singleton.cc
index 780450a72bc..bcbf14e38e4 100644
--- a/chromium/content/browser/gpu/gpu_memory_buffer_manager_singleton.cc
+++ b/chromium/content/browser/gpu/gpu_memory_buffer_manager_singleton.cc
@@ -6,7 +6,10 @@
#include "base/bind.h"
#include "base/logging.h"
+#include "base/task/post_task.h"
+#include "components/viz/host/gpu_host_impl.h"
#include "content/browser/gpu/gpu_process_host.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "gpu/ipc/common/gpu_memory_buffer_support.h"
@@ -18,7 +21,8 @@ GpuMemoryBufferManagerSingleton* g_gpu_memory_buffer_manager;
viz::mojom::GpuService* GetGpuService(
base::OnceClosure connection_error_handler) {
if (auto* host = GpuProcessHost::Get()) {
- host->AddConnectionErrorHandler(std::move(connection_error_handler));
+ host->gpu_host()->AddConnectionErrorHandler(
+ std::move(connection_error_handler));
return host->gpu_service();
}
return nullptr;
@@ -31,7 +35,7 @@ GpuMemoryBufferManagerSingleton::GpuMemoryBufferManagerSingleton(int client_id)
base::BindRepeating(&content::GetGpuService),
client_id,
std::make_unique<gpu::GpuMemoryBufferSupport>(),
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)) {
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO})) {
DCHECK(!g_gpu_memory_buffer_manager);
g_gpu_memory_buffer_manager = this;
}
diff --git a/chromium/content/browser/gpu/gpu_process_host.cc b/chromium/content/browser/gpu/gpu_process_host.cc
index 9511100e607..b184eee1b89 100644
--- a/chromium/content/browser/gpu/gpu_process_host.cc
+++ b/chromium/content/browser/gpu/gpu_process_host.cc
@@ -15,7 +15,6 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/command_line.h"
-#include "base/debug/alias.h"
#include "base/feature_list.h"
#include "base/logging.h"
#include "base/macros.h"
@@ -26,6 +25,7 @@
#include "base/metrics/histogram_macros.h"
#include "base/no_destructor.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/task/post_task.h"
#include "base/threading/thread.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/trace_event.h"
@@ -50,6 +50,7 @@
#include "content/common/memory_coordinator.mojom.h"
#include "content/common/service_manager/child_connection.h"
#include "content/common/view_messages.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/gpu_utils.h"
@@ -277,39 +278,6 @@ void RunCallbackOnIO(GpuProcessHost::GpuProcessKind kind,
callback.Run(host);
}
-#if defined(USE_OZONE)
-// The ozone platform use this callback to send IPC messages to the gpu process.
-void SendGpuProcessMessage(base::WeakPtr<GpuProcessHost> host,
- IPC::Message* message) {
- if (host)
- host->Send(message);
- else
- delete message;
-}
-
-// Helper to register Mus/conventional thread bouncers for ozone startup.
-void OzoneRegisterStartupCallbackHelper(
- base::OnceCallback<void(ui::OzonePlatform*)> io_callback) {
- // The callback registered in ozone can be called in any thread. So use an
- // intermediary callback that bounces to the IO thread if needed, before
- // running the callback.
- auto bounce_callback = base::BindOnce(
- [](base::TaskRunner* task_runner,
- base::OnceCallback<void(ui::OzonePlatform*)> callback,
- ui::OzonePlatform* platform) {
- if (task_runner->RunsTasksInCurrentSequence()) {
- std::move(callback).Run(platform);
- } else {
- task_runner->PostTask(FROM_HERE,
- base::BindOnce(std::move(callback), platform));
- }
- },
- base::RetainedRef(base::ThreadTaskRunnerHandle::Get()),
- std::move(io_callback));
- ui::OzonePlatform::RegisterStartupCallback(std::move(bounce_callback));
-}
-#endif // defined(USE_OZONE)
-
void OnGpuProcessHostDestroyedOnUI(int host_id, const std::string& message) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
GpuDataManagerImpl::GetInstance()->AddLogMessage(
@@ -477,8 +445,8 @@ void BindDiscardableMemoryRequestOnUI(
return;
}
#endif
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&BindDiscardableMemoryRequestOnIO, std::move(request),
BrowserMainLoop::GetInstance()->discardable_shared_memory_manager()));
@@ -496,7 +464,8 @@ void CreateMemoryCoordinatorHandleForGpuProcess(
class GpuProcessHost::ConnectionFilterImpl : public ConnectionFilter {
public:
explicit ConnectionFilterImpl(int gpu_process_id) {
- auto task_runner = BrowserThread::GetTaskRunnerForThread(BrowserThread::UI);
+ auto task_runner =
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::UI});
registry_.AddInterface(base::Bind(&FieldTrialRecorder::Create),
task_runner);
#if defined(OS_ANDROID)
@@ -588,8 +557,8 @@ GpuProcessHost* GpuProcessHost::Get(GpuProcessKind kind, bool force_create) {
// static
void GpuProcessHost::GetHasGpuProcess(base::OnceCallback<void(bool)> callback) {
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&GpuProcessHost::GetHasGpuProcess, std::move(callback)));
return;
}
@@ -610,10 +579,10 @@ void GpuProcessHost::CallOnIO(
bool force_create,
const base::Callback<void(GpuProcessHost*)>& callback) {
#if !defined(OS_WIN)
- DCHECK_NE(kind, GpuProcessHost::GPU_PROCESS_KIND_UNSANDBOXED);
+ DCHECK_NE(kind, GpuProcessHost::GPU_PROCESS_KIND_UNSANDBOXED_NO_GL);
#endif
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&RunCallbackOnIO, kind, force_create, callback));
}
@@ -622,18 +591,16 @@ void GpuProcessHost::BindInterface(
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))));
+ BindDiscardableMemoryRequest(
+ discardable_memory::mojom::DiscardableSharedMemoryManagerRequest(
+ std::move(interface_pipe)));
return;
}
process_->child_connection()->BindInterface(interface_name,
std::move(interface_pipe));
}
+#if defined(USE_OZONE)
void GpuProcessHost::TerminateGpuProcess(const std::string& message) {
// At the moment, this path is only used by Ozone/Wayland. Once others start
// to use this, start to distinguish the origin of termination. By default,
@@ -642,6 +609,11 @@ void GpuProcessHost::TerminateGpuProcess(const std::string& message) {
process_->TerminateOnBadMessageReceived(message);
}
+void GpuProcessHost::SendGpuProcessMessage(IPC::Message* message) {
+ Send(message);
+}
+#endif // defined(USE_OZONE)
+
// static
GpuProcessHost* GpuProcessHost::FromID(int host_id) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -799,65 +771,11 @@ GpuProcessHost::~GpuProcessHost() {
if (block_offscreen_contexts && gpu_host_)
gpu_host_->BlockLiveOffscreenContexts();
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&OnGpuProcessHostDestroyedOnUI, host_id_, message));
}
-#if defined(USE_OZONE)
-void GpuProcessHost::InitOzone() {
- // Ozone needs to send the primary DRM device to GPU process as early as
- // possible to ensure the latter always has a valid device. crbug.com/608839
- // When running with mus, the OzonePlatform may not have been created yet. So
- // defer the callback until OzonePlatform instance is created.
- bool using_mojo = true;
-#if defined(OS_CHROMEOS)
- using_mojo = features::IsOzoneDrmMojo();
-#endif
- if (using_mojo) {
- // TODO(rjkroege): Remove the legacy IPC code paths when no longer
- // necessary. https://crbug.com/806092
- auto interface_binder = base::BindRepeating(&GpuProcessHost::BindInterface,
- weak_ptr_factory_.GetWeakPtr());
- auto terminate_cb = base::BindOnce(&GpuProcessHost::TerminateGpuProcess,
- weak_ptr_factory_.GetWeakPtr());
-
- auto io_callback = base::BindOnce(
- [](const base::RepeatingCallback<void(const std::string&,
- mojo::ScopedMessagePipeHandle)>&
- interface_binder,
- base::OnceCallback<void(const std::string&)> terminate_cb,
- ui::OzonePlatform* platform) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- platform->GetGpuPlatformSupportHost()->OnGpuServiceLaunched(
- BrowserThread::GetTaskRunnerForThread(BrowserThread::UI),
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO),
- interface_binder, std::move(terminate_cb));
- },
- interface_binder, std::move(terminate_cb));
-
- OzoneRegisterStartupCallbackHelper(std::move(io_callback));
- } else {
- auto send_callback = base::BindRepeating(&SendGpuProcessMessage,
- weak_ptr_factory_.GetWeakPtr());
- // Create the callback that should run on the current thread (i.e. IO
- // thread).
- auto io_callback = base::BindOnce(
- [](int host_id,
- const base::RepeatingCallback<void(IPC::Message*)>& send_callback,
- ui::OzonePlatform* platform) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- platform->GetGpuPlatformSupportHost()->OnGpuProcessLaunched(
- host_id, BrowserThread::GetTaskRunnerForThread(BrowserThread::UI),
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO),
- send_callback);
- },
- host_id_, send_callback);
- OzoneRegisterStartupCallbackHelper(std::move(io_callback));
- }
-}
-#endif // defined(USE_OZONE)
-
bool GpuProcessHost::Init() {
init_start_time_ = base::TimeTicks::Now();
@@ -900,6 +818,10 @@ bool GpuProcessHost::Init() {
return false;
}
+ viz::mojom::VizMainAssociatedPtr viz_main_ptr;
+ process_->child_channel()
+ ->GetAssociatedInterfaceSupport()
+ ->GetRemoteAssociatedInterface(&viz_main_ptr);
viz::GpuHostImpl::InitParams params;
params.restart_id = host_id_;
params.in_process = in_process_;
@@ -909,12 +831,11 @@ bool GpuProcessHost::Init() {
params.product = GetContentClient()->GetProduct();
params.deadline_to_synchronize_surfaces =
switches::GetDeadlineToSynchronizeSurfaces();
+ params.main_thread_task_runner =
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::UI});
gpu_host_ = std::make_unique<viz::GpuHostImpl>(
- this, process_->child_channel(), std::move(params));
-
-#if defined(USE_OZONE)
- InitOzone();
-#endif // defined(USE_OZONE)
+ this, std::make_unique<viz::VizMainWrapper>(std::move(viz_main_ptr)),
+ std::move(params));
#if defined(OS_MACOSX)
ca_transaction_gpu_coordinator_ = CATransactionGPUCoordinator::Create(this);
@@ -959,17 +880,6 @@ void GpuProcessHost::OnChannelConnected(int32_t peer_pid) {
}
}
-void GpuProcessHost::AddConnectionErrorHandler(base::OnceClosure handler) {
- connection_error_handlers_.push_back(std::move(handler));
-}
-
-#if defined(OS_ANDROID)
-void GpuProcessHost::OnDestroyingVideoSurfaceAck() {
- TRACE_EVENT0("gpu", "GpuProcessHost::OnDestroyingVideoSurfaceAck");
- if (!send_destroying_video_surface_done_cb_.is_null())
- base::ResetAndReturn(&send_destroying_video_surface_done_cb_).Run();
-}
-#endif
void GpuProcessHost::OnProcessLaunched() {
UMA_HISTOGRAM_TIMES("GPU.GPUProcessLaunchTime",
@@ -987,11 +897,6 @@ void GpuProcessHost::OnProcessLaunched() {
}
void GpuProcessHost::OnProcessLaunchFailed(int error_code) {
- // TODO(crbug.com/849639): Ensure |error_code| is included in crash minidumps.
- // This is for debugging and should be removed when bug is closed.
- int process_launch_error_code = error_code;
- base::debug::Alias(&process_launch_error_code);
-
#if defined(OS_WIN)
if (kind_ == GPU_PROCESS_KIND_SANDBOXED)
RecordAppContainerStatus(error_code, crashed_before_);
@@ -1000,11 +905,6 @@ void GpuProcessHost::OnProcessLaunchFailed(int error_code) {
}
void GpuProcessHost::OnProcessCrashed(int exit_code) {
- // TODO(crbug.com/849639): Ensure |exit_code| is included in crash minidumps.
- // This is for debugging and should be removed when bug is closed.
- int process_crash_exit_code = exit_code;
- base::debug::Alias(&process_crash_exit_code);
-
// Record crash before doing anything that could start a new GPU process.
RecordProcessCrash();
@@ -1025,21 +925,24 @@ gpu::GpuFeatureInfo GpuProcessHost::GetGpuFeatureInfo() const {
return GpuDataManagerImpl::GetInstance()->GetGpuFeatureInfo();
}
-void GpuProcessHost::UpdateGpuInfo(
+void GpuProcessHost::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) {
- auto* gpu_data_manager = GpuDataManagerImpl::GetInstance();
- // Update GpuFeatureInfo first, because UpdateGpuInfo() will notify all
- // listeners.
- gpu_data_manager->UpdateGpuFeatureInfo(gpu_feature_info,
- gpu_feature_info_for_hardware_gpu);
- gpu_data_manager->UpdateGpuInfo(gpu_info, gpu_info_for_hardware_gpu);
+ if (kind_ != GPU_PROCESS_KIND_UNSANDBOXED_NO_GL) {
+ auto* gpu_data_manager = GpuDataManagerImpl::GetInstance();
+ // Update GpuFeatureInfo first, because UpdateGpuInfo() will notify all
+ // listeners.
+ gpu_data_manager->UpdateGpuFeatureInfo(gpu_feature_info,
+ gpu_feature_info_for_hardware_gpu);
+ gpu_data_manager->UpdateGpuInfo(gpu_info, gpu_info_for_hardware_gpu);
+ }
}
void GpuProcessHost::DidFailInitialize() {
+ did_fail_initialize_ = true;
if (kind_ == GPU_PROCESS_KIND_SANDBOXED)
GpuDataManagerImpl::GetInstance()->FallBackToNextGpuMode();
}
@@ -1054,17 +957,8 @@ void GpuProcessHost::DidCreateContextSuccessfully() {
}
void GpuProcessHost::BlockDomainFrom3DAPIs(const GURL& url,
- Delegate::DomainGuilt guilt) {
- GpuDataManagerImpl::DomainGuilt gpu_data_manager_guilt;
- switch (guilt) {
- case Delegate::DomainGuilt::kKnown:
- gpu_data_manager_guilt = GpuDataManagerImpl::DOMAIN_GUILT_KNOWN;
- break;
- case Delegate::DomainGuilt::kUnknown:
- gpu_data_manager_guilt = GpuDataManagerImpl::DOMAIN_GUILT_UNKNOWN;
- }
- GpuDataManagerImpl::GetInstance()->BlockDomainFrom3DAPIs(
- url, gpu_data_manager_guilt);
+ gpu::DomainGuilt guilt) {
+ GpuDataManagerImpl::GetInstance()->BlockDomainFrom3DAPIs(url, guilt);
}
bool GpuProcessHost::GpuAccessAllowed() const {
@@ -1075,8 +969,8 @@ void GpuProcessHost::DisableGpuCompositing() {
#if !defined(OS_ANDROID)
// TODO(crbug.com/819474): The switch from GPU to software compositing should
// be handled here instead of by ImageTransportFactory.
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE, base::BindOnce([]() {
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI}, base::BindOnce([]() {
if (auto* factory = ImageTransportFactory::GetInstance())
factory->DisableGpuCompositing();
}));
@@ -1095,8 +989,8 @@ void GpuProcessHost::RecordLogMessage(int32_t severity,
void GpuProcessHost::BindDiscardableMemoryRequest(
discardable_memory::mojom::DiscardableSharedMemoryManagerRequest request) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&BindDiscardableMemoryRequestOnUI, std::move(request)));
}
@@ -1151,8 +1045,11 @@ bool GpuProcessHost::LaunchGpuProcess() {
cmd_line->AppendArg(switches::kPrefetchArgumentGpu);
#endif // defined(OS_WIN)
- if (kind_ == GPU_PROCESS_KIND_UNSANDBOXED)
+ if (kind_ == GPU_PROCESS_KIND_UNSANDBOXED_NO_GL) {
cmd_line->AppendSwitch(service_manager::switches::kDisableGpuSandbox);
+ cmd_line->AppendSwitchASCII(switches::kUseGL,
+ gl::kGLImplementationDisabledName);
+ }
// TODO(penghuang): Replace all GPU related switches with GpuPreferences.
// https://crbug.com/590825
@@ -1217,15 +1114,8 @@ bool GpuProcessHost::LaunchGpuProcess() {
void GpuProcessHost::SendOutstandingReplies() {
valid_ = false;
- for (auto& handler : connection_error_handlers_)
- std::move(handler).Run();
- connection_error_handlers_.clear();
-
if (gpu_host_)
gpu_host_->SendOutstandingReplies();
-
- if (!send_destroying_video_surface_done_cb_.is_null())
- base::ResetAndReturn(&send_destroying_video_surface_done_cb_).Run();
}
void GpuProcessHost::RecordProcessCrash() {
@@ -1276,18 +1166,8 @@ void GpuProcessHost::RecordProcessCrash() {
recent_crash_count = display_compositor_recent_crash_count_;
}
- // TODO(crbug.com/849639): Ensure crash counts are included in crash
- // minidumps. This is for debugging and should be removed when bug is closed.
- int hardware_accelerated_crash_count =
- hardware_accelerated_recent_crash_count_;
- base::debug::Alias(&hardware_accelerated_crash_count);
- int swiftshader_crash_count = swiftshader_recent_crash_count_;
- base::debug::Alias(&swiftshader_crash_count);
- int display_compositor_crash_count = display_compositor_recent_crash_count_;
- base::debug::Alias(&display_compositor_crash_count);
-
// GPU process initialization failed and fallback already happened.
- if (!gpu_host_ || !gpu_host_->initialized())
+ if (did_fail_initialize_)
return;
bool disable_crash_limit = base::CommandLine::ForCurrentProcess()->HasSwitch(
diff --git a/chromium/content/browser/gpu/gpu_process_host.h b/chromium/content/browser/gpu/gpu_process_host.h
index d79907844e1..fdc79781b4d 100644
--- a/chromium/content/browser/gpu/gpu_process_host.h
+++ b/chromium/content/browser/gpu/gpu_process_host.h
@@ -11,7 +11,6 @@
#include <memory>
#include <set>
#include <string>
-#include <vector>
#include "base/atomicops.h"
#include "base/callback.h"
@@ -56,7 +55,7 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
public viz::GpuHostImpl::Delegate {
public:
enum GpuProcessKind {
- GPU_PROCESS_KIND_UNSANDBOXED,
+ GPU_PROCESS_KIND_UNSANDBOXED_NO_GL, // Unsandboxed, no init GL bindings.
GPU_PROCESS_KIND_SANDBOXED,
GPU_PROCESS_KIND_COUNT
};
@@ -85,10 +84,6 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
bool force_create,
const base::Callback<void(GpuProcessHost*)>& callback);
- void BindInterface(const std::string& interface_name,
- mojo::ScopedMessagePipeHandle interface_pipe);
- void TerminateGpuProcess(const std::string& message);
-
// Get the GPU process host for the GPU process with the given ID. Returns
// null if the process no longer exists.
static GpuProcessHost* FromID(int host_id);
@@ -98,9 +93,6 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
// IPC::Sender implementation.
bool Send(IPC::Message* msg) override;
- // Adds a connection error handler for the GpuService.
- void AddConnectionErrorHandler(base::OnceClosure handler);
-
// What kind of GPU process, e.g. sandboxed or unsandboxed.
GpuProcessKind kind();
@@ -134,10 +126,6 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
bool Init();
-#if defined(USE_OZONE)
- void InitOzone();
-#endif // defined(USE_OZONE)
-
// BrowserChildProcessHostDelegate implementation.
bool OnMessageReceived(const IPC::Message& message) override;
void OnChannelConnected(int32_t peer_pid) override;
@@ -148,7 +136,7 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
// viz::GpuHostImpl::Delegate:
gpu::GPUInfo GetGPUInfo() const override;
gpu::GpuFeatureInfo GetGpuFeatureInfo() const override;
- void UpdateGpuInfo(
+ void DidInitialize(
const gpu::GPUInfo& gpu_info,
const gpu::GpuFeatureInfo& gpu_feature_info,
const base::Optional<gpu::GPUInfo>& gpu_info_for_hardware_gpu,
@@ -156,8 +144,7 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
gpu_feature_info_for_hardware_gpu) override;
void DidFailInitialize() override;
void DidCreateContextSuccessfully() override;
- void BlockDomainFrom3DAPIs(const GURL& url,
- Delegate::DomainGuilt guilt) override;
+ void BlockDomainFrom3DAPIs(const GURL& url, gpu::DomainGuilt guilt) override;
void DisableGpuCompositing() override;
bool GpuAccessAllowed() const override;
gpu::ShaderCacheFactory* GetShaderCacheFactory() override;
@@ -167,11 +154,14 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
void BindDiscardableMemoryRequest(
discardable_memory::mojom::DiscardableSharedMemoryManagerRequest request)
override;
+ void BindInterface(const std::string& interface_name,
+ mojo::ScopedMessagePipeHandle interface_pipe) override;
+#if defined(USE_OZONE)
+ void TerminateGpuProcess(const std::string& message) override;
+ void SendGpuProcessMessage(IPC::Message* message) override;
+#endif
// Message handlers.
-#if defined(OS_ANDROID)
- void OnDestroyingVideoSurfaceAck();
-#endif
void OnFieldTrialActivated(const std::string& trial_name);
bool LaunchGpuProcess();
@@ -189,12 +179,6 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
// GPU process id in case GPU is not in-process.
base::ProcessId process_id_ = base::kNullProcessId;
- // List of connection error handlers for the GpuService.
- std::vector<base::OnceClosure> connection_error_handlers_;
-
- // A callback to signal the completion of a SendDestroyingVideoSurface call.
- base::Closure send_destroying_video_surface_done_cb_;
-
// Qeueud messages to send when the process launches.
base::queue<IPC::Message*> queued_messages_;
@@ -218,6 +202,9 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
// Time Init started. Used to log total GPU process startup time to UMA.
base::TimeTicks init_start_time_;
+ // The GPU process reported failure to initialize.
+ bool did_fail_initialize_ = false;
+
// The total number of GPU process crashes.
static base::subtle::Atomic32 gpu_crash_count_;
static bool crashed_before_;
diff --git a/chromium/content/browser/gpu/in_process_gpu_thread_browsertests.cc b/chromium/content/browser/gpu/in_process_gpu_thread_browsertests.cc
index 22cc546f4c4..f3b231e7faf 100644
--- a/chromium/content/browser/gpu/in_process_gpu_thread_browsertests.cc
+++ b/chromium/content/browser/gpu/in_process_gpu_thread_browsertests.cc
@@ -4,9 +4,11 @@
#include "base/command_line.h"
#include "base/run_loop.h"
+#include "base/task/post_task.h"
#include "content/browser/browser_main_loop.h"
#include "content/browser/gpu/gpu_process_host.h"
#include "content/gpu/in_process_gpu_thread.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/content_browser_test.h"
@@ -30,9 +32,9 @@ void CreateGpuProcessHost() {
void WaitUntilGpuProcessHostIsCreated() {
base::RunLoop run_loop;
- content::BrowserThread::PostTaskAndReply(
- content::BrowserThread::IO, FROM_HERE,
- base::BindOnce(&CreateGpuProcessHost), run_loop.QuitClosure());
+ base::PostTaskWithTraitsAndReply(FROM_HERE, {content::BrowserThread::IO},
+ base::BindOnce(&CreateGpuProcessHost),
+ run_loop.QuitClosure());
run_loop.Run();
}
diff --git a/chromium/content/browser/renderer_host/media/video_capture_dependencies.cc b/chromium/content/browser/gpu/video_capture_dependencies.cc
index 26567c6579b..c84be26c82a 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_dependencies.cc
+++ b/chromium/content/browser/gpu/video_capture_dependencies.cc
@@ -2,11 +2,12 @@
// 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/video_capture_dependencies.h"
+#include "content/browser/gpu/video_capture_dependencies.h"
+#include "base/task/post_task.h"
#include "content/browser/gpu/gpu_process_host.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
-#include "mojo/public/cpp/bindings/strong_binding.h"
namespace content {
@@ -14,8 +15,8 @@ namespace content {
void VideoCaptureDependencies::CreateJpegDecodeAccelerator(
media::mojom::JpegDecodeAcceleratorRequest accelerator) {
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&VideoCaptureDependencies::CreateJpegDecodeAccelerator,
std::move(accelerator)));
return;
@@ -34,8 +35,8 @@ void VideoCaptureDependencies::CreateJpegDecodeAccelerator(
void VideoCaptureDependencies::CreateJpegEncodeAccelerator(
media::mojom::JpegEncodeAcceleratorRequest accelerator) {
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&VideoCaptureDependencies::CreateJpegEncodeAccelerator,
std::move(accelerator)));
return;
diff --git a/chromium/content/browser/renderer_host/media/video_capture_dependencies.h b/chromium/content/browser/gpu/video_capture_dependencies.h
index 5804eef9f03..ab169bb1051 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_dependencies.h
+++ b/chromium/content/browser/gpu/video_capture_dependencies.h
@@ -2,16 +2,15 @@
// 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_VIDEO_CAPTURE_DEPENDENCIES_H_
-#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_CAPTURE_DEPENDENCIES_H_
+#ifndef CONTENT_BROWSER_GPU_VIDEO_CAPTURE_DEPENDENCIES_H_
+#define CONTENT_BROWSER_GPU_VIDEO_CAPTURE_DEPENDENCIES_H_
#include "content/common/content_export.h"
-#include "services/video_capture/public/mojom/device_factory.mojom.h"
#include "services/viz/privileged/interfaces/gl/gpu_service.mojom.h"
namespace content {
-// Browser-provided GPU dependencies for video capture.
+// Browser-process-provided GPU dependencies for video capture.
class CONTENT_EXPORT VideoCaptureDependencies {
public:
static void CreateJpegDecodeAccelerator(
@@ -22,4 +21,4 @@ class CONTENT_EXPORT VideoCaptureDependencies {
} // namespace content
-#endif // CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_CAPTURE_DEPENDENCIES_H_
+#endif // CONTENT_BROWSER_GPU_VIDEO_CAPTURE_DEPENDENCIES_H_
diff --git a/chromium/content/browser/gpu_interface_provider.cc b/chromium/content/browser/gpu_interface_provider.cc
new file mode 100644
index 00000000000..f4153c7f5f5
--- /dev/null
+++ b/chromium/content/browser/gpu_interface_provider.cc
@@ -0,0 +1,96 @@
+// 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/gpu_interface_provider.h"
+
+#include "base/containers/unique_ptr_adapters.h"
+#include "base/memory/ref_counted.h"
+#include "base/task/post_task.h"
+#include "components/discardable_memory/public/interfaces/discardable_shared_memory_manager.mojom.h"
+#include "content/public/browser/browser_task_traits.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/gpu_client.h"
+#include "content/public/browser/gpu_interface_provider_factory.h"
+#include "content/public/browser/gpu_service_registry.h"
+#include "services/ws/public/mojom/gpu.mojom.h"
+
+namespace content {
+
+// InterfaceBinderImpl handles the actual binding. The binding has to happen on
+// the IO thread.
+class GpuInterfaceProvider::InterfaceBinderImpl
+ : public base::RefCountedThreadSafe<InterfaceBinderImpl> {
+ public:
+ InterfaceBinderImpl() = default;
+
+ void BindGpuRequestOnGpuTaskRunner(ws::mojom::GpuRequest request) {
+ // The GPU task runner is bound to the IO thread.
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ auto gpu_client = content::CreateGpuClient(
+ std::move(request),
+ base::BindOnce(&InterfaceBinderImpl::OnGpuClientConnectionError, this),
+ base::CreateSingleThreadTaskRunnerWithTraits(
+ {content::BrowserThread::IO}));
+ gpu_clients_.push_back(std::move(gpu_client));
+ }
+
+ void BindDiscardableSharedMemoryManagerOnGpuTaskRunner(
+ discardable_memory::mojom::DiscardableSharedMemoryManagerRequest
+ request) {
+ content::BindInterfaceInGpuProcess(std::move(request));
+ }
+
+ private:
+ friend class base::RefCountedThreadSafe<InterfaceBinderImpl>;
+ ~InterfaceBinderImpl() = default;
+
+ void OnGpuClientConnectionError(viz::GpuClient* client) {
+ base::EraseIf(
+ gpu_clients_,
+ base::UniquePtrMatcher<viz::GpuClient, base::OnTaskRunnerDeleter>(
+ client));
+ }
+
+ std::vector<std::unique_ptr<viz::GpuClient, base::OnTaskRunnerDeleter>>
+ gpu_clients_;
+
+ DISALLOW_COPY_AND_ASSIGN(InterfaceBinderImpl);
+};
+
+GpuInterfaceProvider::GpuInterfaceProvider()
+ : interface_binder_impl_(base::MakeRefCounted<InterfaceBinderImpl>()) {}
+
+GpuInterfaceProvider::~GpuInterfaceProvider() = default;
+
+void GpuInterfaceProvider::RegisterGpuInterfaces(
+ service_manager::BinderRegistry* registry) {
+ scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner =
+ base::CreateSingleThreadTaskRunnerWithTraits(
+ {content::BrowserThread::IO});
+ registry->AddInterface(
+ base::BindRepeating(&InterfaceBinderImpl::
+ BindDiscardableSharedMemoryManagerOnGpuTaskRunner,
+ interface_binder_impl_),
+ gpu_task_runner);
+ registry->AddInterface(
+ base::BindRepeating(&InterfaceBinderImpl::BindGpuRequestOnGpuTaskRunner,
+ interface_binder_impl_),
+ gpu_task_runner);
+}
+
+#if defined(USE_OZONE)
+void GpuInterfaceProvider::RegisterOzoneGpuInterfaces(
+ service_manager::BinderRegistry* registry) {
+ // Registers the gpu-related interfaces needed by Ozone.
+ // TODO(rjkroege): Adjust when Ozone/DRM/Mojo is complete.
+ NOTIMPLEMENTED();
+}
+#endif
+
+// Factory.
+std::unique_ptr<ws::GpuInterfaceProvider> CreateGpuInterfaceProvider() {
+ return std::make_unique<GpuInterfaceProvider>();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/gpu_interface_provider.h b/chromium/content/browser/gpu_interface_provider.h
new file mode 100644
index 00000000000..e256aa05cf3
--- /dev/null
+++ b/chromium/content/browser/gpu_interface_provider.h
@@ -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.
+
+#ifndef CONTENT_BROWSER_GPU_INTERFACE_PROVIDER_H_
+#define CONTENT_BROWSER_GPU_INTERFACE_PROVIDER_H_
+
+#include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
+#include "content/common/content_export.h"
+#include "services/ws/public/cpp/host/gpu_interface_provider.h"
+
+namespace content {
+
+// An implementation of GpuInterfaceProvider that forwards to the Gpu
+// implementation in content.
+class CONTENT_EXPORT GpuInterfaceProvider : public ws::GpuInterfaceProvider {
+ public:
+ GpuInterfaceProvider();
+ ~GpuInterfaceProvider() override;
+
+ // ws::GpuInterfaceProvider:
+ void RegisterGpuInterfaces(
+ service_manager::BinderRegistry* registry) override;
+#if defined(USE_OZONE)
+ void RegisterOzoneGpuInterfaces(
+ service_manager::BinderRegistry* registry) override;
+#endif
+
+ private:
+ class InterfaceBinderImpl;
+
+ scoped_refptr<InterfaceBinderImpl> interface_binder_impl_;
+
+ DISALLOW_COPY_AND_ASSIGN(GpuInterfaceProvider);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_GPU_INTERFACE_PROVIDER_H_
diff --git a/chromium/content/browser/histogram_controller.cc b/chromium/content/browser/histogram_controller.cc
index 7d1c1108bb7..1c52b9e3ec1 100644
--- a/chromium/content/browser/histogram_controller.cc
+++ b/chromium/content/browser/histogram_controller.cc
@@ -7,9 +7,11 @@
#include "base/bind.h"
#include "base/metrics/histogram_macros.h"
#include "base/process/process_handle.h"
+#include "base/task/post_task.h"
#include "content/browser/histogram_subscriber.h"
#include "content/common/histogram_fetcher.mojom.h"
#include "content/public/browser/browser_child_process_host_iterator.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/child_process_data.h"
#include "content/public/browser/render_process_host.h"
@@ -42,8 +44,8 @@ void HistogramController::OnHistogramDataCollected(
int sequence_number,
const std::vector<std::string>& pickled_histograms) {
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&HistogramController::OnHistogramDataCollected,
base::Unretained(this), sequence_number,
pickled_histograms));
@@ -166,8 +168,8 @@ void HistogramController::GetHistogramDataFromChildProcesses(
++pending_processes;
}
}
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&HistogramController::OnPendingProcesses,
base::Unretained(this), sequence_number, pending_processes,
true));
@@ -191,8 +193,8 @@ void HistogramController::GetHistogramData(int sequence_number) {
}
OnPendingProcesses(sequence_number, pending_processes, false);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&HistogramController::GetHistogramDataFromChildProcesses,
base::Unretained(this), sequence_number));
}
diff --git a/chromium/content/browser/histogram_synchronizer.cc b/chromium/content/browser/histogram_synchronizer.cc
index 796c34fbe21..9dc2eedef0c 100644
--- a/chromium/content/browser/histogram_synchronizer.cc
+++ b/chromium/content/browser/histogram_synchronizer.cc
@@ -14,9 +14,11 @@
#include "base/metrics/histogram_macros.h"
#include "base/pickle.h"
#include "base/single_thread_task_runner.h"
+#include "base/task/post_task.h"
#include "base/threading/thread.h"
#include "base/threading/thread_restrictions.h"
#include "content/browser/histogram_controller.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/histogram_fetcher.h"
#include "content/public/common/content_constants.h"
@@ -94,8 +96,7 @@ class HistogramSynchronizer::RequestContext {
static RequestContext* GetRequestContext(int sequence_number) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- RequestContextMap::iterator it =
- outstanding_requests_.Get().find(sequence_number);
+ auto it = outstanding_requests_.Get().find(sequence_number);
if (it == outstanding_requests_.Get().end())
return nullptr;
@@ -110,8 +111,7 @@ class HistogramSynchronizer::RequestContext {
static void Unregister(int sequence_number) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- RequestContextMap::iterator it =
- outstanding_requests_.Get().find(sequence_number);
+ auto it = outstanding_requests_.Get().find(sequence_number);
if (it == outstanding_requests_.Get().end())
return;
@@ -127,15 +127,15 @@ class HistogramSynchronizer::RequestContext {
UMA_HISTOGRAM_BOOLEAN("Histogram.ReceivedProcessGroupCount",
received_process_group_count);
- UMA_HISTOGRAM_COUNTS("Histogram.PendingProcessNotResponding",
- unresponsive_processes);
+ UMA_HISTOGRAM_COUNTS_1M("Histogram.PendingProcessNotResponding",
+ unresponsive_processes);
}
// Delete all the entries in |outstanding_requests_| map.
static void OnShutdown() {
// Just in case we have any pending tasks, clear them out.
while (!outstanding_requests_.Get().empty()) {
- RequestContextMap::iterator it = outstanding_requests_.Get().begin();
+ auto it = outstanding_requests_.Get().begin();
delete it->second;
outstanding_requests_.Get().erase(it);
}
@@ -189,8 +189,8 @@ HistogramSynchronizer* HistogramSynchronizer::GetInstance() {
// static
void HistogramSynchronizer::FetchHistograms() {
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&HistogramSynchronizer::FetchHistograms));
return;
}
@@ -249,8 +249,8 @@ void HistogramSynchronizer::RegisterAndNotifyAllProcesses(
// Post a task that would be called after waiting for wait_time. This acts
// as a watchdog, to cancel the requests for non-responsive processes.
- BrowserThread::PostDelayedTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostDelayedTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&RequestContext::Unregister, sequence_number), wait_time);
}
diff --git a/chromium/content/browser/histogram_synchronizer.h b/chromium/content/browser/histogram_synchronizer.h
index 2e9b79539dc..c037a502c4a 100644
--- a/chromium/content/browser/histogram_synchronizer.h
+++ b/chromium/content/browser/histogram_synchronizer.h
@@ -127,8 +127,8 @@ class HistogramSynchronizer : public HistogramSubscriber {
// When a request is made to asynchronously update the histograms, we store
// the task and TaskRunner we use to post a completion notification in
// |callback_| and |callback_task_runner_|.
- base::Closure callback_;
- scoped_refptr<base::TaskRunner> callback_task_runner_;
+ base::Closure callback_ GUARDED_BY(lock_);
+ scoped_refptr<base::TaskRunner> callback_task_runner_ GUARDED_BY(lock_);
// We don't track the actual processes that are contacted for an update, only
// the count of the number of processes, and we can sometimes time-out and
@@ -138,11 +138,11 @@ class HistogramSynchronizer : public HistogramSubscriber {
// All sequence numbers used are non-negative.
// last_used_sequence_number_ is the most recently used number (used to avoid
// reuse for a long time).
- int last_used_sequence_number_;
+ int last_used_sequence_number_ GUARDED_BY(lock_);
// The sequence number used by the most recent asynchronous update request to
// contact all processes.
- int async_sequence_number_;
+ int async_sequence_number_ GUARDED_BY(lock_);
DISALLOW_COPY_AND_ASSIGN(HistogramSynchronizer);
};
diff --git a/chromium/content/browser/host_zoom_map_impl.cc b/chromium/content/browser/host_zoom_map_impl.cc
index 34775d0204d..b97855ddd80 100644
--- a/chromium/content/browser/host_zoom_map_impl.cc
+++ b/chromium/content/browser/host_zoom_map_impl.cc
@@ -153,8 +153,7 @@ double HostZoomMapImpl::GetZoomLevelForHost(const std::string& host) const {
bool HostZoomMapImpl::HasZoomLevel(const std::string& scheme,
const std::string& host) const {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- SchemeHostZoomLevels::const_iterator scheme_iterator(
- scheme_host_zoom_levels_.find(scheme));
+ auto scheme_iterator(scheme_host_zoom_levels_.find(scheme));
const HostZoomLevels& zoom_levels =
(scheme_iterator != scheme_host_zoom_levels_.end())
@@ -168,10 +167,9 @@ double HostZoomMapImpl::GetZoomLevelForHostAndScheme(
const std::string& scheme,
const std::string& host) const {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- SchemeHostZoomLevels::const_iterator scheme_iterator(
- scheme_host_zoom_levels_.find(scheme));
+ auto scheme_iterator(scheme_host_zoom_levels_.find(scheme));
if (scheme_iterator != scheme_host_zoom_levels_.end()) {
- HostZoomLevels::const_iterator i(scheme_iterator->second.find(host));
+ auto i(scheme_iterator->second.find(host));
if (i != scheme_iterator->second.end())
return i->second.level;
}
@@ -499,7 +497,7 @@ void HostZoomMapImpl::ClearTemporaryZoomLevel(int render_process_id,
int render_view_id) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
RenderViewKey key(render_process_id, render_view_id);
- TemporaryZoomLevels::iterator it = temporary_zoom_levels_.find(key);
+ auto it = temporary_zoom_levels_.find(key);
if (it == temporary_zoom_levels_.end())
return;
diff --git a/chromium/content/browser/host_zoom_map_impl_unittest.cc b/chromium/content/browser/host_zoom_map_impl_unittest.cc
index c6676920158..0e0d2fc630a 100644
--- a/chromium/content/browser/host_zoom_map_impl_unittest.cc
+++ b/chromium/content/browser/host_zoom_map_impl_unittest.cc
@@ -8,7 +8,7 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop.h"
+#include "base/test/scoped_task_environment.h"
#include "base/test/simple_test_clock.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/test/test_browser_thread.h"
@@ -18,11 +18,12 @@ namespace content {
class HostZoomMapTest : public testing::Test {
public:
- HostZoomMapTest() : ui_thread_(BrowserThread::UI, &message_loop_) {
- }
+ HostZoomMapTest()
+ : ui_thread_(BrowserThread::UI,
+ task_environment_.GetMainThreadTaskRunner()) {}
protected:
- base::MessageLoop message_loop_;
+ base::test::ScopedTaskEnvironment task_environment_;
TestBrowserThread ui_thread_;
};
diff --git a/chromium/content/browser/hyphenation/hyphenation_impl.cc b/chromium/content/browser/hyphenation/hyphenation_impl.cc
index 8d2cb168722..aa05d6baae9 100644
--- a/chromium/content/browser/hyphenation/hyphenation_impl.cc
+++ b/chromium/content/browser/hyphenation/hyphenation_impl.cc
@@ -11,6 +11,7 @@
#include "base/files/file.h"
#include "base/files/file_path.h"
#include "base/metrics/histogram_macros.h"
+#include "base/no_destructor.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/task/post_task.h"
@@ -29,12 +30,12 @@ bool IsValidLocale(const std::string& locale) {
base::File GetDictionaryFile(const std::string& locale) {
// Keep Files open in the cache for subsequent calls.
- CR_DEFINE_STATIC_LOCAL(DictionaryFileMap, cache, ());
+ static base::NoDestructor<DictionaryFileMap> cache;
- const auto& it = cache.find(locale);
- if (it != cache.end())
+ const auto& it = cache->find(locale);
+ if (it != cache->end())
return it->second.Duplicate();
- const auto& inserted = cache.insert(std::make_pair(locale, base::File()));
+ const auto& inserted = cache->insert(std::make_pair(locale, base::File()));
base::File& file = inserted.first->second;
DCHECK(!file.IsValid());
@@ -67,12 +68,11 @@ void HyphenationImpl::Create(blink::mojom::HyphenationRequest request) {
// static
scoped_refptr<base::SequencedTaskRunner> HyphenationImpl::GetTaskRunner() {
- CR_DEFINE_STATIC_LOCAL(
- scoped_refptr<base::SequencedTaskRunner>, runner,
- (base::CreateSequencedTaskRunnerWithTraits(
+ static base::NoDestructor<scoped_refptr<base::SequencedTaskRunner>> runner(
+ base::CreateSequencedTaskRunnerWithTraits(
{base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN,
- base::TaskPriority::USER_BLOCKING})));
- return runner;
+ base::TaskPriority::USER_BLOCKING}));
+ return *runner;
}
void HyphenationImpl::OpenDictionary(const std::string& locale,
diff --git a/chromium/content/browser/image_capture/image_capture_impl.cc b/chromium/content/browser/image_capture/image_capture_impl.cc
index 5198e94e456..27ad33e0b6b 100644
--- a/chromium/content/browser/image_capture/image_capture_impl.cc
+++ b/chromium/content/browser/image_capture/image_capture_impl.cc
@@ -7,9 +7,11 @@
#include <utility>
#include "base/bind_helpers.h"
+#include "base/task/post_task.h"
#include "content/browser/browser_main_loop.h"
#include "content/browser/renderer_host/media/media_stream_manager.h"
#include "content/browser/renderer_host/media/video_capture_manager.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_features.h"
#include "content/public/common/media_stream_request.h"
@@ -90,8 +92,8 @@ void ImageCaptureImpl::GetPhotoState(const std::string& source_id,
mojo::WrapCallbackWithDefaultInvokeIfNotRun(
media::BindToCurrentLoop(std::move(callback)),
mojo::CreateEmptyPhotoState());
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&GetPhotoStateOnIOThread, source_id,
BrowserMainLoop::GetInstance()->media_stream_manager(),
std::move(scoped_callback)));
@@ -105,8 +107,8 @@ void ImageCaptureImpl::SetOptions(const std::string& source_id,
SetOptionsCallback scoped_callback =
mojo::WrapCallbackWithDefaultInvokeIfNotRun(
media::BindToCurrentLoop(std::move(callback)), false);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&SetOptionsOnIOThread, source_id,
BrowserMainLoop::GetInstance()->media_stream_manager(),
std::move(settings), std::move(scoped_callback)));
@@ -120,8 +122,8 @@ void ImageCaptureImpl::TakePhoto(const std::string& source_id,
mojo::WrapCallbackWithDefaultInvokeIfNotRun(
media::BindToCurrentLoop(std::move(callback)),
media::mojom::Blob::New());
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&TakePhotoOnIOThread, source_id,
BrowserMainLoop::GetInstance()->media_stream_manager(),
std::move(scoped_callback)));
diff --git a/chromium/content/browser/indexed_db/indexed_db_active_blob_registry.cc b/chromium/content/browser/indexed_db/indexed_db_active_blob_registry.cc
index a3edf627425..370906e2f8a 100644
--- a/chromium/content/browser/indexed_db/indexed_db_active_blob_registry.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_active_blob_registry.cc
@@ -29,7 +29,7 @@ void IndexedDBActiveBlobRegistry::AddBlobRef(int64_t database_id,
DCHECK(!base::ContainsKey(deleted_dbs_, database_id));
bool need_ref = use_tracker_.empty();
SingleDBMap& single_db_map = use_tracker_[database_id];
- SingleDBMap::iterator iter = single_db_map.find(blob_key);
+ auto iter = single_db_map.find(blob_key);
if (iter == single_db_map.end()) {
single_db_map[blob_key] = false;
if (need_ref) {
@@ -54,7 +54,7 @@ void IndexedDBActiveBlobRegistry::ReleaseBlobRef(int64_t database_id,
return;
}
SingleDBMap& single_db = db_pair->second;
- SingleDBMap::iterator blob_pair = single_db.find(blob_key);
+ auto blob_pair = single_db.find(blob_key);
if (blob_pair == single_db.end()) {
NOTREACHED();
return;
@@ -97,7 +97,7 @@ bool IndexedDBActiveBlobRegistry::MarkDeletedCheckIfUsed(int64_t database_id,
}
SingleDBMap& single_db = db_pair->second;
- SingleDBMap::iterator iter = single_db.find(blob_key);
+ auto iter = single_db.find(blob_key);
if (iter == single_db.end())
return false;
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 01c03fae5ce..413adf0d0ce 100644
--- a/chromium/content/browser/indexed_db/indexed_db_backing_store.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_backing_store.cc
@@ -19,6 +19,7 @@
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/task/post_task.h"
#include "base/trace_event/memory_dump_manager.h"
#include "build/build_config.h"
#include "content/browser/child_process_security_policy_impl.h"
@@ -38,6 +39,7 @@
#include "content/browser/indexed_db/leveldb/leveldb_factory.h"
#include "content/browser/indexed_db/leveldb/leveldb_iterator.h"
#include "content/browser/indexed_db/leveldb/leveldb_transaction.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_features.h"
#include "net/base/load_flags.h"
@@ -569,7 +571,6 @@ IndexedDBBackingStore::IndexedDBBackingStore(
IndexedDBFactory* indexed_db_factory,
const Origin& origin,
const FilePath& blob_path,
- scoped_refptr<net::URLRequestContextGetter> request_context_getter,
std::unique_ptr<LevelDBDatabase> db,
std::unique_ptr<LevelDBComparator> comparator,
base::SequencedTaskRunner* task_runner)
@@ -577,7 +578,6 @@ IndexedDBBackingStore::IndexedDBBackingStore(
origin_(origin),
blob_path_(blob_path),
origin_identifier_(ComputeOriginIdentifier(origin)),
- request_context_getter_(request_context_getter),
task_runner_(task_runner),
db_(std::move(db)),
comparator_(std::move(comparator)),
@@ -620,7 +620,6 @@ scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Open(
IndexedDBFactory* indexed_db_factory,
const Origin& origin,
const FilePath& path_base,
- scoped_refptr<net::URLRequestContextGetter> request_context,
IndexedDBDataLossInfo* data_loss_info,
bool* disk_full,
base::SequencedTaskRunner* task_runner,
@@ -628,8 +627,8 @@ scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Open(
Status* status) {
DefaultLevelDBFactory leveldb_factory;
return IndexedDBBackingStore::Open(
- indexed_db_factory, origin, path_base, request_context, data_loss_info,
- disk_full, &leveldb_factory, task_runner, clean_journal, status);
+ indexed_db_factory, origin, path_base, data_loss_info, disk_full,
+ &leveldb_factory, task_runner, clean_journal, status);
}
Status IndexedDBBackingStore::DestroyBackingStore(const FilePath& path_base,
@@ -702,6 +701,34 @@ Status IndexedDBBackingStore::RevertSchemaToV2() {
return s;
}
+V2SchemaCorruptionStatus IndexedDBBackingStore::HasV2SchemaCorruption() {
+ DCHECK(task_runner_->RunsTasksInCurrentSequence());
+ const std::string schema_version_key = SchemaVersionKey::Encode();
+ scoped_refptr<LevelDBTransaction> transaction =
+ IndexedDBClassFactory::Get()->CreateLevelDBTransaction(db_.get());
+
+ int64_t db_schema_version = 0;
+ bool found = false;
+ Status s =
+ GetInt(transaction.get(), schema_version_key, &db_schema_version, &found);
+ if (!s.ok())
+ return V2SchemaCorruptionStatus::kUnknown;
+ if (db_schema_version != 2)
+ return V2SchemaCorruptionStatus::kNo;
+
+ bool has_blobs = false;
+ s = AnyDatabaseContainsBlobs(transaction.get(), &has_blobs);
+ if (!s.ok())
+ return V2SchemaCorruptionStatus::kUnknown;
+ if (!has_blobs)
+ return V2SchemaCorruptionStatus::kNo;
+
+ s = transaction->Commit();
+ if (!s.ok())
+ return V2SchemaCorruptionStatus::kUnknown;
+ return V2SchemaCorruptionStatus::kYes;
+}
+
WARN_UNUSED_RESULT Status IndexedDBBackingStore::SetUpMetadata() {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
@@ -939,7 +966,6 @@ scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Open(
IndexedDBFactory* indexed_db_factory,
const Origin& origin,
const FilePath& path_base,
- scoped_refptr<net::URLRequestContextGetter> request_context_getter,
IndexedDBDataLossInfo* data_loss_info,
bool* is_disk_full,
LevelDBFactory* leveldb_factory,
@@ -1075,8 +1101,8 @@ scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Open(
base::trace_event::MemoryDumpProvider::Options());
scoped_refptr<IndexedDBBackingStore> backing_store =
- Create(indexed_db_factory, origin, blob_path, request_context_getter,
- std::move(db), std::move(comparator), task_runner, status);
+ Create(indexed_db_factory, origin, blob_path, std::move(db),
+ std::move(comparator), task_runner, status);
if (clean_journal && backing_store.get()) {
*status = backing_store->CleanUpBlobJournal(LiveBlobJournalKey::Encode());
@@ -1126,8 +1152,7 @@ scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::OpenInMemory(
base::trace_event::MemoryDumpProvider::Options());
return Create(nullptr /* indexed_db_factory */, origin, FilePath(),
- nullptr /* request_context */, std::move(db),
- std::move(comparator), task_runner, status);
+ std::move(db), std::move(comparator), task_runner, status);
}
// static
@@ -1135,14 +1160,13 @@ scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Create(
IndexedDBFactory* indexed_db_factory,
const Origin& origin,
const FilePath& blob_path,
- scoped_refptr<net::URLRequestContextGetter> request_context,
std::unique_ptr<LevelDBDatabase> db,
std::unique_ptr<LevelDBComparator> comparator,
base::SequencedTaskRunner* task_runner,
Status* status) {
// TODO(jsbell): Handle comparator name changes.
scoped_refptr<IndexedDBBackingStore> backing_store(new IndexedDBBackingStore(
- indexed_db_factory, origin, blob_path, request_context, std::move(db),
+ indexed_db_factory, origin, blob_path, std::move(db),
std::move(comparator), task_runner));
*status = backing_store->SetUpMetadata();
if (!status->ok())
@@ -1822,8 +1846,8 @@ bool IndexedDBBackingStore::WriteBlobFile(
DCHECK(descriptor.blob());
scoped_refptr<LocalWriteClosure> write_closure(
new LocalWriteClosure(chained_blob_writer, task_runner_.get()));
- content::BrowserThread::PostTask(
- content::BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {content::BrowserThread::IO},
base::BindOnce(
&LocalWriteClosure::WriteBlobToFileOnIOThread, write_closure, path,
std::make_unique<storage::BlobDataHandle>(*descriptor.blob()),
@@ -1856,9 +1880,8 @@ void IndexedDBBackingStore::ReportBlobUnused(int64_t database_id,
// matching (database_id, blob_key) tuple, we should move it to the primary
// journal.
BlobJournalType new_live_blob_journal;
- for (BlobJournalType::iterator journal_iter = live_blob_journal.begin();
- journal_iter != live_blob_journal.end();
- ++journal_iter) {
+ for (auto journal_iter = live_blob_journal.begin();
+ journal_iter != live_blob_journal.end(); ++journal_iter) {
int64_t current_database_id = journal_iter->first;
int64_t current_blob_key = journal_iter->second;
bool current_all_blobs =
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 e5540a77658..5da4da7dc57 100644
--- a/chromium/content/browser/indexed_db/indexed_db_backing_store.h
+++ b/chromium/content/browser/indexed_db/indexed_db_backing_store.h
@@ -50,10 +50,6 @@ namespace storage {
class FileWriterDelegate;
}
-namespace net {
-class URLRequestContextGetter;
-}
-
namespace content {
class IndexedDBFactory;
@@ -68,6 +64,12 @@ class IndexedDBBackingStoreTest;
FORWARD_DECLARE_TEST(IndexedDBBackingStoreTest, ReadCorruptionInfo);
} // namespace indexed_db_backing_store_unittest
+enum class V2SchemaCorruptionStatus {
+ kUnknown = 0, // Due to other unknown/critical errors.
+ kNo = 1,
+ kYes = 2,
+};
+
class CONTENT_EXPORT IndexedDBBackingStore
: public base::RefCounted<IndexedDBBackingStore> {
public:
@@ -400,7 +402,6 @@ class CONTENT_EXPORT IndexedDBBackingStore
IndexedDBFactory* indexed_db_factory,
const url::Origin& origin,
const base::FilePath& path_base,
- scoped_refptr<net::URLRequestContextGetter> request_context_getter,
IndexedDBDataLossInfo* data_loss_info,
bool* disk_full,
base::SequencedTaskRunner* task_runner,
@@ -410,7 +411,6 @@ class CONTENT_EXPORT IndexedDBBackingStore
IndexedDBFactory* indexed_db_factory,
const url::Origin& origin,
const base::FilePath& path_base,
- scoped_refptr<net::URLRequestContextGetter> request_context_getter,
IndexedDBDataLossInfo* data_loss_info,
bool* disk_full,
LevelDBFactory* leveldb_factory,
@@ -580,6 +580,10 @@ class CONTENT_EXPORT IndexedDBBackingStore
// Stops the journal_cleaning_timer_ and runs its pending task.
void ForceRunBlobCleanup();
+ // HasV2SchemaCorruption() returns whether the backing store is v2 and
+ // has blob references.
+ V2SchemaCorruptionStatus HasV2SchemaCorruption();
+
// RevertSchemaToV2() updates a backing store state on disk to override its
// metadata version to 2. This allows triggering https://crbug.com/829141 on
// an otherwise healthy backing store.
@@ -592,7 +596,6 @@ class CONTENT_EXPORT IndexedDBBackingStore
IndexedDBFactory* indexed_db_factory,
const url::Origin& origin,
const base::FilePath& blob_path,
- scoped_refptr<net::URLRequestContextGetter> request_context_getter,
std::unique_ptr<LevelDBDatabase> db,
std::unique_ptr<LevelDBComparator> comparator,
base::SequencedTaskRunner* task_runner);
@@ -637,7 +640,6 @@ class CONTENT_EXPORT IndexedDBBackingStore
IndexedDBFactory* indexed_db_factory,
const url::Origin& origin,
const base::FilePath& blob_path,
- scoped_refptr<net::URLRequestContextGetter> request_context_getter,
std::unique_ptr<LevelDBDatabase> db,
std::unique_ptr<LevelDBComparator> comparator,
base::SequencedTaskRunner* task_runner,
@@ -687,7 +689,6 @@ class CONTENT_EXPORT IndexedDBBackingStore
// provides for future flexibility.
const std::string origin_identifier_;
- scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
scoped_refptr<base::SequencedTaskRunner> task_runner_;
std::set<int> child_process_ids_granted_;
std::map<std::string, std::unique_ptr<BlobChangeRecord>> incognito_blob_map_;
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 6eb906e0216..c9d70844af2 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
@@ -17,6 +17,7 @@
#include "base/sequenced_task_runner.h"
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/task/post_task.h"
#include "base/time/default_clock.h"
#include "content/browser/indexed_db/indexed_db_class_factory.h"
#include "content/browser/indexed_db/indexed_db_context_impl.h"
@@ -26,9 +27,9 @@
#include "content/browser/indexed_db/indexed_db_metadata_coding.h"
#include "content/browser/indexed_db/indexed_db_value.h"
#include "content/browser/indexed_db/leveldb/leveldb_factory.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/public/test/test_utils.h"
-#include "net/url_request/url_request_test_util.h"
#include "storage/browser/blob/blob_data_builder.h"
#include "storage/browser/blob/blob_data_handle.h"
#include "storage/browser/blob/blob_storage_context.h"
@@ -93,7 +94,6 @@ class TestableIndexedDBBackingStore : public IndexedDBBackingStore {
IndexedDBFactory* indexed_db_factory,
const Origin& origin,
const base::FilePath& path_base,
- scoped_refptr<net::URLRequestContextGetter> request_context_getter,
LevelDBFactory* leveldb_factory,
base::SequencedTaskRunner* task_runner,
leveldb::Status* status) {
@@ -120,8 +120,8 @@ class TestableIndexedDBBackingStore : public IndexedDBBackingStore {
scoped_refptr<TestableIndexedDBBackingStore> backing_store(
new TestableIndexedDBBackingStore(indexed_db_factory, origin, blob_path,
- request_context_getter, std::move(db),
- std::move(comparator), task_runner));
+ std::move(db), std::move(comparator),
+ task_runner));
*status = backing_store->SetUpMetadata();
if (!status->ok())
@@ -178,14 +178,12 @@ class TestableIndexedDBBackingStore : public IndexedDBBackingStore {
IndexedDBFactory* indexed_db_factory,
const Origin& origin,
const base::FilePath& blob_path,
- scoped_refptr<net::URLRequestContextGetter> request_context_getter,
std::unique_ptr<LevelDBDatabase> db,
std::unique_ptr<LevelDBComparator> comparator,
base::SequencedTaskRunner* task_runner)
: IndexedDBBackingStore(indexed_db_factory,
origin,
blob_path,
- request_context_getter,
std::move(db),
std::move(comparator),
task_runner),
@@ -207,14 +205,12 @@ class TestIDBFactory : public IndexedDBFactoryImpl {
: IndexedDBFactoryImpl(idb_context, base::DefaultClock::GetInstance()) {}
scoped_refptr<TestableIndexedDBBackingStore> OpenBackingStoreForTest(
- const Origin& origin,
- scoped_refptr<net::URLRequestContextGetter> url_request_context_getter) {
+ const Origin& origin) {
IndexedDBDataLossInfo data_loss_info;
bool disk_full;
leveldb::Status status;
scoped_refptr<IndexedDBBackingStore> backing_store = OpenBackingStore(
- origin, context()->data_path(), url_request_context_getter,
- &data_loss_info, &disk_full, &status);
+ origin, context()->data_path(), &data_loss_info, &disk_full, &status);
scoped_refptr<TestableIndexedDBBackingStore> testable_store =
static_cast<TestableIndexedDBBackingStore*>(backing_store.get());
return testable_store;
@@ -226,15 +222,14 @@ class TestIDBFactory : public IndexedDBFactoryImpl {
scoped_refptr<IndexedDBBackingStore> OpenBackingStoreHelper(
const Origin& origin,
const base::FilePath& data_directory,
- scoped_refptr<net::URLRequestContextGetter> request_context_getter,
IndexedDBDataLossInfo* data_loss_info,
bool* disk_full,
bool first_time,
leveldb::Status* status) override {
DefaultLevelDBFactory leveldb_factory;
- return TestableIndexedDBBackingStore::Open(
- this, origin, data_directory, request_context_getter, &leveldb_factory,
- context()->TaskRunner(), status);
+ return TestableIndexedDBBackingStore::Open(this, origin, data_directory,
+ &leveldb_factory,
+ context()->TaskRunner(), status);
}
private:
@@ -244,10 +239,7 @@ class TestIDBFactory : public IndexedDBFactoryImpl {
class IndexedDBBackingStoreTest : public testing::Test {
public:
IndexedDBBackingStoreTest()
- : url_request_context_getter_(
- base::MakeRefCounted<net::TestURLRequestContextGetter>(
- BrowserThread::GetTaskRunnerForThread(BrowserThread::UI))),
- special_storage_policy_(
+ : special_storage_policy_(
base::MakeRefCounted<MockSpecialStoragePolicy>()),
quota_manager_proxy_(
base::MakeRefCounted<MockQuotaManagerProxy>(nullptr, nullptr)) {}
@@ -262,8 +254,7 @@ class IndexedDBBackingStoreTest : public testing::Test {
test->idb_factory_ = base::MakeRefCounted<TestIDBFactory>(
test->idb_context_.get());
test->backing_store_ =
- test->idb_factory_->OpenBackingStoreForTest(
- origin, test->url_request_context_getter_);
+ test->idb_factory_->OpenBackingStoreForTest(origin);
},
base::Unretained(this)));
RunAllTasksUntilIdle();
@@ -316,11 +307,9 @@ class IndexedDBBackingStoreTest : public testing::Test {
IndexedDBValue value2_;
protected:
- // Must be initialized before url_request_context_getter_
TestBrowserThreadBundle thread_bundle_;
base::ScopedTempDir temp_dir_;
- scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
scoped_refptr<MockSpecialStoragePolicy> special_storage_policy_;
scoped_refptr<MockQuotaManagerProxy> quota_manager_proxy_;
scoped_refptr<IndexedDBContextImpl> idb_context_;
diff --git a/chromium/content/browser/indexed_db/indexed_db_browsertest.cc b/chromium/content/browser/indexed_db/indexed_db_browsertest.cc
index e4f3274ff39..1ae750ded15 100644
--- a/chromium/content/browser/indexed_db/indexed_db_browsertest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_browsertest.cc
@@ -19,6 +19,8 @@
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/task/post_task.h"
+#include "base/test/bind_test_util.h"
#include "base/test/thread_test_helper.h"
#include "base/threading/thread_restrictions.h"
#include "build/build_config.h"
@@ -28,6 +30,7 @@
#include "content/browser/indexed_db/mock_browsertest_indexed_db_class_factory.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
@@ -57,12 +60,16 @@ using url::Origin;
namespace content {
+namespace {
+const Origin kFileOrigin = Origin::Create(GURL("file:///"));
+};
+
// This browser test is aimed towards exercising the IndexedDB bindings and
// the actual implementation that lives in the browser side.
class IndexedDBBrowserTest : public ContentBrowserTest,
public ::testing::WithParamInterface<const char*> {
public:
- IndexedDBBrowserTest() : disk_usage_(-1) {}
+ IndexedDBBrowserTest() = default;
void SetUp() override {
GetTestClassFactory()->Reset();
@@ -116,10 +123,11 @@ class IndexedDBBrowserTest : public ContentBrowserTest,
EXPECT_EQ(expected_title16, title_watcher.WaitAndGetTitle());
}
- IndexedDBContextImpl* GetContext() {
- StoragePartition* partition =
- BrowserContext::GetDefaultStoragePartition(
- shell()->web_contents()->GetBrowserContext());
+ IndexedDBContextImpl* GetContext(Shell* browser = nullptr) {
+ if (!browser)
+ browser = shell();
+ StoragePartition* partition = BrowserContext::GetDefaultStoragePartition(
+ browser->web_contents()->GetBrowserContext());
return static_cast<IndexedDBContextImpl*>(partition->GetIndexedDBContext());
}
@@ -133,8 +141,8 @@ class IndexedDBBrowserTest : public ContentBrowserTest,
static void SetTempQuota(int per_host_quota_kilobytes,
scoped_refptr<QuotaManager> qm) {
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&IndexedDBBrowserTest::SetTempQuota,
per_host_quota_kilobytes, qm));
return;
@@ -145,37 +153,70 @@ class IndexedDBBrowserTest : public ContentBrowserTest,
storage::GetHardCodedSettings(per_host_quota_kilobytes * KB));
}
- virtual int64_t RequestDiskUsage() {
- PostTaskAndReplyWithResult(
- GetContext()->TaskRunner(), FROM_HERE,
- base::BindOnce(&IndexedDBContextImpl::GetOriginDiskUsage, GetContext(),
- Origin::Create(GURL("file:///"))),
- base::BindOnce(&IndexedDBBrowserTest::DidGetDiskUsage,
- base::Unretained(this)));
- scoped_refptr<base::ThreadTestHelper> helper(
- new base::ThreadTestHelper(GetContext()->TaskRunner()));
- EXPECT_TRUE(helper->Run());
- // Wait for DidGetDiskUsage to be called.
- base::RunLoop().RunUntilIdle();
- return disk_usage_;
+ void DeleteForOrigin(const Origin& origin, Shell* browser = nullptr) {
+ base::RunLoop loop;
+ IndexedDBContextImpl* context = GetContext();
+ context->TaskRunner()->PostTask(FROM_HERE,
+ base::BindLambdaForTesting([&]() {
+ context->DeleteForOrigin(kFileOrigin);
+ loop.Quit();
+ }));
+ loop.Run();
}
- virtual int RequestBlobFileCount() {
- PostTaskAndReplyWithResult(
- GetContext()->TaskRunner(), FROM_HERE,
- base::BindOnce(&IndexedDBContextImpl::GetOriginBlobFileCount,
- GetContext(), Origin::Create(GURL("file:///"))),
- base::BindOnce(&IndexedDBBrowserTest::DidGetBlobFileCount,
- base::Unretained(this)));
- scoped_refptr<base::ThreadTestHelper> helper(
- new base::ThreadTestHelper(GetContext()->TaskRunner()));
- EXPECT_TRUE(helper->Run());
- // Wait for DidGetBlobFileCount to be called.
- base::RunLoop().RunUntilIdle();
- return blob_file_count_;
+ int64_t RequestUsage(const Origin& origin, Shell* browser = nullptr) {
+ base::RunLoop loop;
+ int64_t size;
+ IndexedDBContextImpl* context = GetContext(browser);
+ context->TaskRunner()->PostTask(
+ FROM_HERE, base::BindLambdaForTesting([&]() {
+ size = context->GetOriginDiskUsage(origin);
+ loop.Quit();
+ }));
+ loop.Run();
+ return size;
}
- private:
+ int RequestBlobFileCount(const Origin& origin) {
+ base::RunLoop loop;
+ int count;
+ IndexedDBContextImpl* context = GetContext();
+ context->TaskRunner()->PostTask(
+ FROM_HERE, base::BindLambdaForTesting([&]() {
+ count = context->GetOriginBlobFileCount(origin);
+ loop.Quit();
+ }));
+ loop.Run();
+ return count;
+ }
+
+ bool RequestSchemaDowngrade(const Origin& origin) {
+ base::RunLoop loop;
+ bool downgraded;
+ IndexedDBContextImpl* context = GetContext();
+ context->TaskRunner()->PostTask(
+ FROM_HERE, base::BindLambdaForTesting([&]() {
+ downgraded = context->ForceSchemaDowngrade(origin);
+ loop.Quit();
+ }));
+ loop.Run();
+ return downgraded;
+ }
+
+ V2SchemaCorruptionStatus RequestHasV2SchemaCorruption(Origin origin) {
+ base::RunLoop loop;
+ V2SchemaCorruptionStatus status;
+ IndexedDBContextImpl* context = GetContext();
+ context->TaskRunner()->PostTask(
+ FROM_HERE, base::BindLambdaForTesting([&]() {
+ status = context->HasV2SchemaCorruption(origin);
+ loop.Quit();
+ }));
+ loop.Run();
+ return status;
+ }
+
+ protected:
static MockBrowserTestIndexedDBClassFactory* GetTestClassFactory() {
static ::base::LazyInstance<MockBrowserTestIndexedDBClassFactory>::Leaky
s_factory = LAZY_INSTANCE_INITIALIZER;
@@ -186,13 +227,7 @@ class IndexedDBBrowserTest : public ContentBrowserTest,
return GetTestClassFactory();
}
- virtual void DidGetDiskUsage(int64_t bytes) { disk_usage_ = bytes; }
-
- virtual void DidGetBlobFileCount(int count) { blob_file_count_ = count; }
-
- int64_t disk_usage_;
- int blob_file_count_ = 0;
-
+ private:
DISALLOW_COPY_AND_ASSIGN(IndexedDBBrowserTest);
};
@@ -359,10 +394,10 @@ class IndexedDBBrowserTestWithVersion123456Schema : public
IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTestWithVersion123456Schema,
DestroyTest) {
- int64_t original_size = RequestDiskUsage();
+ int64_t original_size = RequestUsage(kFileOrigin);
EXPECT_GT(original_size, 0);
SimpleTest(GetTestUrl("indexeddb", "open_bad_db.html"));
- int64_t new_size = RequestDiskUsage();
+ int64_t new_size = RequestUsage(kFileOrigin);
EXPECT_GT(new_size, 0);
EXPECT_NE(original_size, new_size);
}
@@ -374,10 +409,10 @@ class IndexedDBBrowserTestWithVersion987654SSVData : public
IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTestWithVersion987654SSVData,
DestroyTest) {
- int64_t original_size = RequestDiskUsage();
+ int64_t original_size = RequestUsage(kFileOrigin);
EXPECT_GT(original_size, 0);
SimpleTest(GetTestUrl("indexeddb", "open_bad_db.html"));
- int64_t new_size = RequestDiskUsage();
+ int64_t new_size = RequestUsage(kFileOrigin);
EXPECT_GT(new_size, 0);
EXPECT_NE(original_size, new_size);
}
@@ -389,10 +424,10 @@ class IndexedDBBrowserTestWithCorruptLevelDB : public
IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTestWithCorruptLevelDB,
DestroyTest) {
- int64_t original_size = RequestDiskUsage();
+ int64_t original_size = RequestUsage(kFileOrigin);
EXPECT_GT(original_size, 0);
SimpleTest(GetTestUrl("indexeddb", "open_bad_db.html"));
- int64_t new_size = RequestDiskUsage();
+ int64_t new_size = RequestUsage(kFileOrigin);
EXPECT_GT(new_size, 0);
EXPECT_NE(original_size, new_size);
}
@@ -404,10 +439,10 @@ class IndexedDBBrowserTestWithMissingSSTFile : public
IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTestWithMissingSSTFile,
DestroyTest) {
- int64_t original_size = RequestDiskUsage();
+ int64_t original_size = RequestUsage(kFileOrigin);
EXPECT_GT(original_size, 0);
SimpleTest(GetTestUrl("indexeddb", "open_missing_table.html"));
- int64_t new_size = RequestDiskUsage();
+ int64_t new_size = RequestUsage(kFileOrigin);
EXPECT_GT(new_size, 0);
EXPECT_NE(original_size, new_size);
}
@@ -429,7 +464,7 @@ IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, LevelDBLogFileTest) {
IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, CanDeleteWhenOverQuotaTest) {
SimpleTest(GetTestUrl("indexeddb", "fill_up_5k.html"));
- int64_t size = RequestDiskUsage();
+ int64_t size = RequestUsage(kFileOrigin);
const int kQuotaKilobytes = 2;
EXPECT_GT(size, kQuotaKilobytes * 1024);
SetQuota(kQuotaKilobytes);
@@ -438,13 +473,8 @@ IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, CanDeleteWhenOverQuotaTest) {
IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, EmptyBlob) {
// First delete all IDB's for the test origin
- // TODO(jsbell): Remove static_cast<> when overloads are eliminated.
- GetContext()->TaskRunner()->PostTask(
- FROM_HERE,
- base::BindOnce(static_cast<void (IndexedDBContextImpl::*)(const GURL&)>(
- &IndexedDBContextImpl::DeleteForOrigin),
- GetContext(), GURL("file:///")));
- EXPECT_EQ(0, RequestBlobFileCount()); // Start with no blob files.
+ DeleteForOrigin(kFileOrigin);
+ EXPECT_EQ(0, RequestBlobFileCount(kFileOrigin)); // Start with no blob files.
const GURL test_url = GetTestUrl("indexeddb", "empty_blob.html");
// For some reason Android's futimes fails (EPERM) in this test. Do not assert
// file times on Android, but do so on other platforms. crbug.com/467247
@@ -455,7 +485,7 @@ IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, EmptyBlob) {
SimpleTest(GURL(test_url.spec()));
#endif
// Test stores one blob and one file to disk, so expect two files.
- EXPECT_EQ(2, RequestBlobFileCount());
+ EXPECT_EQ(2, RequestBlobFileCount(kFileOrigin));
}
// Very flaky on many bots. See crbug.com/459835
@@ -493,19 +523,31 @@ IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, BlobsCountAgainstQuota) {
IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, DeleteForOriginDeletesBlobs) {
SimpleTest(GetTestUrl("indexeddb", "write_4mb_blob.html"));
- int64_t size = RequestDiskUsage();
+ int64_t size = RequestUsage(kFileOrigin);
// This assertion assumes that we do not compress blobs.
EXPECT_GT(size, 4 << 20 /* 4 MB */);
- // TODO(jsbell): Remove static_cast<> when overloads are eliminated.
- GetContext()->TaskRunner()->PostTask(
- FROM_HERE,
- base::BindOnce(static_cast<void (IndexedDBContextImpl::*)(const GURL&)>(
- &IndexedDBContextImpl::DeleteForOrigin),
- GetContext(), GURL("file:///")));
- scoped_refptr<base::ThreadTestHelper> helper(
- new base::ThreadTestHelper(GetContext()->TaskRunner()));
- ASSERT_TRUE(helper->Run());
- EXPECT_EQ(0, RequestDiskUsage());
+ DeleteForOrigin(kFileOrigin);
+ EXPECT_EQ(0, RequestUsage(kFileOrigin));
+}
+
+IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, DeleteForOriginIncognito) {
+ const GURL test_url = GetTestUrl("indexeddb", "fill_up_5k.html");
+ const Origin origin = Origin::Create(test_url);
+
+ Shell* browser = CreateOffTheRecordBrowser();
+ NavigateToURLBlockUntilNavigationsComplete(browser, test_url, 2);
+
+ EXPECT_GT(RequestUsage(origin, browser), 5 * 1024);
+
+ IndexedDBContextImpl* context = GetContext(browser);
+ base::RunLoop loop;
+ context->TaskRunner()->PostTask(FROM_HERE, base::BindLambdaForTesting([&]() {
+ context->DeleteForOrigin(origin);
+ loop.Quit();
+ }));
+ loop.Run();
+
+ EXPECT_EQ(0, RequestUsage(origin, browser));
}
IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, DiskFullOnCommit) {
@@ -531,9 +573,23 @@ IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, DiskFullOnCommit) {
namespace {
-static void CompactIndexedDBBackingStore(
- scoped_refptr<IndexedDBContextImpl> context,
- const Origin& origin) {
+std::unique_ptr<net::test_server::HttpResponse> ServePath(
+ std::string request_path) {
+ base::FilePath resource_path =
+ content::GetTestFilePath("indexeddb", request_path.c_str());
+ std::unique_ptr<net::test_server::BasicHttpResponse> http_response(
+ new net::test_server::BasicHttpResponse);
+ http_response->set_code(net::HTTP_OK);
+
+ std::string file_contents;
+ if (!base::ReadFileToString(resource_path, &file_contents))
+ NOTREACHED() << "could not read file " << resource_path;
+ http_response->set_content(file_contents);
+ return std::move(http_response);
+}
+
+void CompactIndexedDBBackingStore(scoped_refptr<IndexedDBContextImpl> context,
+ const Origin& origin) {
IndexedDBFactory* factory = context->GetIDBFactory();
std::pair<IndexedDBFactory::OriginDBMapIterator,
@@ -550,10 +606,9 @@ static void CompactIndexedDBBackingStore(
backing_store->Compact();
}
-static void CorruptIndexedDBDatabase(
- IndexedDBContextImpl* context,
- const Origin& origin,
- base::WaitableEvent* signal_when_finished) {
+void CorruptIndexedDBDatabase(IndexedDBContextImpl* context,
+ const Origin& origin,
+ base::WaitableEvent* signal_when_finished) {
CompactIndexedDBBackingStore(context, origin);
int num_files = 0;
@@ -587,9 +642,9 @@ static void CorruptIndexedDBDatabase(
signal_when_finished->Signal();
}
-static const char s_corrupt_db_test_prefix[] = "/corrupt/test/";
+const char s_corrupt_db_test_prefix[] = "/corrupt/test/";
-static std::unique_ptr<net::test_server::HttpResponse> CorruptDBRequestHandler(
+std::unique_ptr<net::test_server::HttpResponse> CorruptDBRequestHandler(
IndexedDBContextImpl* context,
const Origin& origin,
const std::string& path,
@@ -693,17 +748,20 @@ static std::unique_ptr<net::test_server::HttpResponse> CorruptDBRequestHandler(
return std::move(http_response);
}
- // A request for a test resource
- base::FilePath resource_path =
- content::GetTestFilePath("indexeddb", request_path.c_str());
- std::unique_ptr<net::test_server::BasicHttpResponse> http_response(
- new net::test_server::BasicHttpResponse);
- http_response->set_code(net::HTTP_OK);
- std::string file_contents;
- if (!base::ReadFileToString(resource_path, &file_contents))
+ return ServePath(request_path);
+}
+
+const char s_indexeddb_test_prefix[] = "/indexeddb/test/";
+
+std::unique_ptr<net::test_server::HttpResponse> StaticFileRequestHandler(
+ const std::string& path,
+ IndexedDBBrowserTest* test,
+ const net::test_server::HttpRequest& request) {
+ if (path.find(s_indexeddb_test_prefix) == std::string::npos)
return std::unique_ptr<net::test_server::HttpResponse>();
- http_response->set_content(file_contents);
- return std::move(http_response);
+ std::string request_path =
+ request.relative_url.substr(std::string(s_indexeddb_test_prefix).size());
+ return ServePath(request_path);
}
} // namespace
@@ -738,11 +796,11 @@ INSTANTIATE_TEST_CASE_P(IndexedDBBrowserTestInstantiation,
IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, DeleteCompactsBackingStore) {
const GURL test_url = GetTestUrl("indexeddb", "delete_compact.html");
SimpleTest(GURL(test_url.spec() + "#fill"));
- int64_t after_filling = RequestDiskUsage();
+ int64_t after_filling = RequestUsage(kFileOrigin);
EXPECT_GT(after_filling, 0);
SimpleTest(GURL(test_url.spec() + "#purge"));
- int64_t after_deleting = RequestDiskUsage();
+ int64_t after_deleting = RequestUsage(kFileOrigin);
EXPECT_LT(after_deleting, after_filling);
// The above tests verify basic assertions - that filling writes data and
@@ -839,19 +897,67 @@ IN_PROC_BROWSER_TEST_F(
IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, ForceCloseEventTest) {
NavigateAndWaitForTitle(shell(), "force_close_event.html", nullptr,
"connection ready");
- // TODO(jsbell): Remove static_cast<> when overloads are eliminated.
- GetContext()->TaskRunner()->PostTask(
- FROM_HERE,
- base::BindOnce(static_cast<void (IndexedDBContextImpl::*)(const GURL&)>(
- &IndexedDBContextImpl::DeleteForOrigin),
- GetContext(), GURL("file:///")));
-
+ DeleteForOrigin(kFileOrigin);
base::string16 expected_title16(ASCIIToUTF16("connection closed"));
TitleWatcher title_watcher(shell()->web_contents(), expected_title16);
title_watcher.AlsoWaitForTitle(ASCIIToUTF16("connection closed with error"));
EXPECT_EQ(expected_title16, title_watcher.WaitAndGetTitle());
}
+// The V2 schema corruption test runs in a separate class to avoid corrupting
+// an IDB store that other tests use.
+class IndexedDBBrowserTestV2SchemaCorruption : public IndexedDBBrowserTest {
+ public:
+ void SetUp() override {
+ GetTestClassFactory()->Reset();
+ IndexedDBClassFactory::SetIndexedDBClassFactoryGetter(GetIDBClassFactory);
+ ContentBrowserTest::SetUp();
+ }
+};
+
+// Verify the V2 schema corruption lifecycle:
+// - create a current version backing store (v3 or later)
+// - add an object store, some data, and an object that contains a blob
+// - verify the object+blob are stored in the object store
+// - verify the backing store doesn't have v2 schema corruption
+// - force the schema to downgrade to v2
+// - verify the backing store has v2 schema corruption
+// - verify the object+blob can be fetched
+IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTestV2SchemaCorruption, LifecycleTest) {
+ ASSERT_TRUE(embedded_test_server()->Started() ||
+ embedded_test_server()->InitializeAndListen());
+ const Origin origin = Origin::Create(embedded_test_server()->base_url());
+ embedded_test_server()->RegisterRequestHandler(base::BindRepeating(
+ &StaticFileRequestHandler, s_indexeddb_test_prefix, this));
+ embedded_test_server()->StartAcceptingConnections();
+
+ // Set up the IndexedDB instance so it contains our reference data.
+ std::string test_file =
+ std::string(s_indexeddb_test_prefix) + "v2schemacorrupt_setup.html";
+ SimpleTest(embedded_test_server()->GetURL(test_file));
+
+ // Verify the backing store does not have corruption.
+ V2SchemaCorruptionStatus has_corruption =
+ RequestHasV2SchemaCorruption(origin);
+ ASSERT_EQ(has_corruption, V2SchemaCorruptionStatus::kNo);
+
+ // Revert schema to v2. This closes the targeted backing store.
+ bool schema_downgrade = RequestSchemaDowngrade(origin);
+ ASSERT_EQ(schema_downgrade, true);
+
+ // Re-open the backing store and verify it has corruption.
+ test_file =
+ std::string(s_indexeddb_test_prefix) + "v2schemacorrupt_reopen.html";
+ SimpleTest(embedded_test_server()->GetURL(test_file));
+ has_corruption = RequestHasV2SchemaCorruption(origin);
+ ASSERT_EQ(has_corruption, V2SchemaCorruptionStatus::kYes);
+
+ // Verify that the saved blob is get-able with a v2 backing store.
+ test_file =
+ std::string(s_indexeddb_test_prefix) + "v2schemacorrupt_verify.html";
+ SimpleTest(embedded_test_server()->GetURL(test_file));
+}
+
class IndexedDBBrowserTestSingleProcess : public IndexedDBBrowserTest {
public:
void SetUpCommandLine(base::CommandLine* command_line) override {
diff --git a/chromium/content/browser/indexed_db/indexed_db_callbacks.cc b/chromium/content/browser/indexed_db/indexed_db_callbacks.cc
index 55fbe83dc93..d5369e55609 100644
--- a/chromium/content/browser/indexed_db/indexed_db_callbacks.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_callbacks.cc
@@ -14,6 +14,7 @@
#include "base/metrics/histogram_macros.h"
#include "base/sequenced_task_runner.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/task/post_task.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/time/time.h"
#include "content/browser/child_process_security_policy_impl.h"
@@ -27,6 +28,7 @@
#include "content/browser/indexed_db/indexed_db_tracing.h"
#include "content/browser/indexed_db/indexed_db_transaction.h"
#include "content/browser/indexed_db/indexed_db_value.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/common/content_features.h"
#include "mojo/public/cpp/bindings/strong_associated_binding.h"
#include "storage/browser/blob/blob_data_builder.h"
@@ -220,8 +222,8 @@ void IndexedDBCallbacks::OnError(const IndexedDBDatabaseError& error) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!complete_);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&IOThreadHelper::SendError,
base::Unretained(io_helper_.get()), error));
complete_ = true;
@@ -239,8 +241,8 @@ void IndexedDBCallbacks::OnSuccess(const std::vector<base::string16>& value) {
DCHECK(!complete_);
DCHECK(io_helper_);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&IOThreadHelper::SendSuccessStringList,
base::Unretained(io_helper_.get()), value));
complete_ = true;
@@ -256,8 +258,8 @@ void IndexedDBCallbacks::OnBlocked(int64_t existing_version) {
sent_blocked_ = true;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&IOThreadHelper::SendBlocked,
base::Unretained(io_helper_.get()), existing_version));
@@ -284,8 +286,8 @@ void IndexedDBCallbacks::OnUpgradeNeeded(
connection_created_ = true;
SafeIOThreadConnectionWrapper wrapper(std::move(connection));
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&IOThreadHelper::SendUpgradeNeeded,
base::Unretained(io_helper_.get()), std::move(wrapper),
old_version, data_loss_info.status, data_loss_info.message,
@@ -317,10 +319,10 @@ void IndexedDBCallbacks::OnSuccess(
database_connection = std::move(connection);
SafeIOThreadConnectionWrapper wrapper(std::move(database_connection));
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::BindOnce(&IOThreadHelper::SendSuccessDatabase,
- base::Unretained(io_helper_.get()),
- std::move(wrapper), metadata));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(&IOThreadHelper::SendSuccessDatabase,
+ base::Unretained(io_helper_.get()),
+ std::move(wrapper), metadata));
complete_ = true;
if (!connection_open_start_time_.is_null()) {
@@ -350,8 +352,8 @@ void IndexedDBCallbacks::OnSuccess(std::unique_ptr<IndexedDBCursor> cursor,
SafeIOThreadCursorWrapper cursor_wrapper(std::move(cursor));
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&IOThreadHelper::SendSuccessCursor,
base::Unretained(io_helper_.get()),
std::move(cursor_wrapper), key, primary_key,
@@ -375,8 +377,8 @@ void IndexedDBCallbacks::OnSuccess(const IndexedDBKey& key,
blob_info.swap(value->blob_info);
}
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&IOThreadHelper::SendSuccessCursorContinue,
base::Unretained(io_helper_.get()), key, primary_key,
std::move(mojo_value), std::move(blob_info)));
@@ -400,8 +402,8 @@ void IndexedDBCallbacks::OnSuccessWithPrefetch(
for (size_t i = 0; i < values->size(); ++i)
mojo_values.push_back(ConvertAndEraseValue(&(*values)[i]));
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&IOThreadHelper::SendSuccessCursorPrefetch,
base::Unretained(io_helper_.get()), keys, primary_keys,
std::move(mojo_values), *values));
@@ -421,8 +423,8 @@ void IndexedDBCallbacks::OnSuccess(IndexedDBReturnValue* value) {
blob_info = value->blob_info;
}
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&IOThreadHelper::SendSuccessValue,
base::Unretained(io_helper_.get()), std::move(mojo_value),
std::move(blob_info)));
@@ -442,10 +444,10 @@ void IndexedDBCallbacks::OnSuccessArray(
for (size_t i = 0; i < values->size(); ++i)
mojo_values.push_back(ConvertReturnValue(&(*values)[i]));
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::BindOnce(&IOThreadHelper::SendSuccessArray,
- base::Unretained(io_helper_.get()),
- std::move(mojo_values), *values));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(&IOThreadHelper::SendSuccessArray,
+ base::Unretained(io_helper_.get()),
+ std::move(mojo_values), *values));
complete_ = true;
}
@@ -456,8 +458,8 @@ void IndexedDBCallbacks::OnSuccess(const IndexedDBKey& value) {
DCHECK_EQ(blink::kWebIDBDataLossNone, data_loss_);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&IOThreadHelper::SendSuccessKey,
base::Unretained(io_helper_.get()), value));
complete_ = true;
@@ -467,8 +469,8 @@ void IndexedDBCallbacks::OnSuccess(int64_t value) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!complete_);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&IOThreadHelper::SendSuccessInteger,
base::Unretained(io_helper_.get()), value));
complete_ = true;
@@ -481,9 +483,9 @@ void IndexedDBCallbacks::OnSuccess() {
DCHECK_EQ(blink::kWebIDBDataLossNone, data_loss_);
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::BindOnce(&IOThreadHelper::SendSuccess,
- base::Unretained(io_helper_.get())));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(&IOThreadHelper::SendSuccess,
+ base::Unretained(io_helper_.get())));
complete_ = true;
}
diff --git a/chromium/content/browser/indexed_db/indexed_db_cleanup_on_io_error_unittest.cc b/chromium/content/browser/indexed_db/indexed_db_cleanup_on_io_error_unittest.cc
index 0c702bf0f8f..5f73076637c 100644
--- a/chromium/content/browser/indexed_db/indexed_db_cleanup_on_io_error_unittest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_cleanup_on_io_error_unittest.cc
@@ -14,7 +14,6 @@
#include "content/browser/indexed_db/indexed_db_data_loss_info.h"
#include "content/browser/indexed_db/leveldb/leveldb_database.h"
#include "content/browser/indexed_db/leveldb/mock_leveldb_factory.h"
-#include "net/url_request/url_request_context_getter.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/leveldatabase/env_chromium.h"
@@ -86,7 +85,6 @@ TEST(IndexedDBIOErrorTest, CleanUpTest) {
base::ScopedTempDir temp_directory;
ASSERT_TRUE(temp_directory.CreateUniqueTempDir());
const base::FilePath path = temp_directory.GetPath();
- scoped_refptr<net::URLRequestContextGetter> request_context_getter;
BustedLevelDBFactory busted_factory;
content::MockLevelDBFactory mock_leveldb_factory;
@@ -103,15 +101,14 @@ TEST(IndexedDBIOErrorTest, CleanUpTest) {
bool clean_journal = false;
leveldb::Status s;
scoped_refptr<IndexedDBBackingStore> backing_store =
- IndexedDBBackingStore::Open(
- factory, origin, path, request_context_getter, &data_loss_info,
- &disk_full, &mock_leveldb_factory, task_runner, clean_journal, &s);
+ IndexedDBBackingStore::Open(factory, origin, path, &data_loss_info,
+ &disk_full, &mock_leveldb_factory,
+ task_runner, clean_journal, &s);
}
TEST(IndexedDBNonRecoverableIOErrorTest, NuancedCleanupTest) {
content::IndexedDBFactory* factory = nullptr;
const url::Origin origin = url::Origin::Create(GURL("http://localhost:81"));
- scoped_refptr<net::URLRequestContextGetter> request_context_getter;
base::ScopedTempDir temp_directory;
ASSERT_TRUE(temp_directory.CreateUniqueTempDir());
const base::FilePath path = temp_directory.GetPath();
@@ -135,9 +132,9 @@ TEST(IndexedDBNonRecoverableIOErrorTest, NuancedCleanupTest) {
leveldb_env::kNewLogger,
base::File::FILE_ERROR_NO_SPACE));
scoped_refptr<IndexedDBBackingStore> backing_store =
- IndexedDBBackingStore::Open(
- factory, origin, path, request_context_getter, &data_loss_info,
- &disk_full, &mock_leveldb_factory, task_runner, clean_journal, &s);
+ IndexedDBBackingStore::Open(factory, origin, path, &data_loss_info,
+ &disk_full, &mock_leveldb_factory,
+ task_runner, clean_journal, &s);
ASSERT_TRUE(s.IsIOError());
busted_factory.SetOpenError(MakeIOError("some filename",
@@ -145,18 +142,18 @@ TEST(IndexedDBNonRecoverableIOErrorTest, NuancedCleanupTest) {
leveldb_env::kNewLogger,
base::File::FILE_ERROR_NO_MEMORY));
scoped_refptr<IndexedDBBackingStore> backing_store2 =
- IndexedDBBackingStore::Open(
- factory, origin, path, request_context_getter, &data_loss_info,
- &disk_full, &mock_leveldb_factory, task_runner, clean_journal, &s);
+ IndexedDBBackingStore::Open(factory, origin, path, &data_loss_info,
+ &disk_full, &mock_leveldb_factory,
+ task_runner, clean_journal, &s);
ASSERT_TRUE(s.IsIOError());
busted_factory.SetOpenError(MakeIOError("some filename", "some message",
leveldb_env::kNewLogger,
base::File::FILE_ERROR_IO));
scoped_refptr<IndexedDBBackingStore> backing_store3 =
- IndexedDBBackingStore::Open(
- factory, origin, path, request_context_getter, &data_loss_info,
- &disk_full, &mock_leveldb_factory, task_runner, clean_journal, &s);
+ IndexedDBBackingStore::Open(factory, origin, path, &data_loss_info,
+ &disk_full, &mock_leveldb_factory,
+ task_runner, clean_journal, &s);
ASSERT_TRUE(s.IsIOError());
busted_factory.SetOpenError(MakeIOError("some filename",
@@ -164,9 +161,9 @@ TEST(IndexedDBNonRecoverableIOErrorTest, NuancedCleanupTest) {
leveldb_env::kNewLogger,
base::File::FILE_ERROR_FAILED));
scoped_refptr<IndexedDBBackingStore> backing_store4 =
- IndexedDBBackingStore::Open(
- factory, origin, path, request_context_getter, &data_loss_info,
- &disk_full, &mock_leveldb_factory, task_runner, clean_journal, &s);
+ IndexedDBBackingStore::Open(factory, origin, path, &data_loss_info,
+ &disk_full, &mock_leveldb_factory,
+ task_runner, clean_journal, &s);
ASSERT_TRUE(s.IsIOError());
}
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 2bd6e7fc36e..6aa1736eba6 100644
--- a/chromium/content/browser/indexed_db/indexed_db_context_impl.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_context_impl.cc
@@ -200,9 +200,7 @@ base::ListValue* IndexedDBContextImpl::GetAllOriginsDetails() {
std::unique_ptr<base::ListValue> database_list(
std::make_unique<base::ListValue>());
- for (IndexedDBFactory::OriginDBMapIterator it = range.first;
- it != range.second;
- ++it) {
+ for (auto it = range.first; it != range.second; ++it) {
const IndexedDBDatabase* db = it->second;
std::unique_ptr<base::DictionaryValue> db_info(
std::make_unique<base::DictionaryValue>());
@@ -312,8 +310,6 @@ base::Time IndexedDBContextImpl::GetOriginLastModified(const Origin& origin) {
return factory_->GetLastModified(origin);
}
- if (data_path_.empty())
- return base::Time();
base::FilePath idb_directory = GetLevelDBPath(origin);
base::File::Info file_info;
if (!base::GetFileInfo(idb_directory, &file_info))
@@ -329,8 +325,14 @@ void IndexedDBContextImpl::DeleteForOrigin(const GURL& origin_url) {
void IndexedDBContextImpl::DeleteForOrigin(const Origin& origin) {
DCHECK(TaskRunner()->RunsTasksInCurrentSequence());
ForceClose(origin, FORCE_CLOSE_DELETE_ORIGIN);
- if (data_path_.empty() || !HasOrigin(origin))
+ if (!HasOrigin(origin))
+ return;
+
+ if (is_incognito()) {
+ GetOriginSet()->erase(origin);
+ origin_size_map_.erase(origin);
return;
+ }
base::FilePath idb_directory = GetLevelDBPath(origin);
EnsureDiskUsageCacheInitialized(origin);
@@ -348,7 +350,7 @@ void IndexedDBContextImpl::DeleteForOrigin(const Origin& origin) {
base::DeleteFile(GetBlobStorePath(origin), true /* recursive */);
QueryDiskAndUpdateQuotaUsage(origin);
if (s.ok()) {
- RemoveFromOriginSet(origin);
+ GetOriginSet()->erase(origin);
origin_size_map_.erase(origin);
}
}
@@ -362,7 +364,7 @@ void IndexedDBContextImpl::CopyOriginData(const GURL& origin_url,
void IndexedDBContextImpl::CopyOriginData(const Origin& origin,
IndexedDBContext* dest_context) {
DCHECK(TaskRunner()->RunsTasksInCurrentSequence());
- if (data_path_.empty() || !HasOrigin(origin))
+ if (is_incognito() || !HasOrigin(origin))
return;
IndexedDBContextImpl* dest_context_impl =
@@ -397,23 +399,38 @@ void IndexedDBContextImpl::ForceClose(const Origin origin,
reason,
FORCE_CLOSE_REASON_MAX);
- if (data_path_.empty() || !HasOrigin(origin))
+ if (!HasOrigin(origin))
return;
if (factory_.get())
- factory_->ForceClose(origin);
+ factory_->ForceClose(origin, reason == FORCE_CLOSE_DELETE_ORIGIN);
DCHECK_EQ(0UL, GetConnectionCount(origin));
}
-void IndexedDBContextImpl::ForceSchemaDowngrade(const Origin& origin) {
+bool IndexedDBContextImpl::ForceSchemaDowngrade(const Origin& origin) {
DCHECK(TaskRunner()->RunsTasksInCurrentSequence());
- if (data_path_.empty() || !HasOrigin(origin))
- return;
+ if (is_incognito() || !HasOrigin(origin))
+ return false;
- if (factory_.get())
+ if (factory_.get()) {
factory_->ForceSchemaDowngrade(origin);
- DCHECK_EQ(0UL, GetConnectionCount(origin));
+ return true;
+ }
+ this->ForceClose(origin, FORCE_SCHEMA_DOWNGRADE_INTERNALS_PAGE);
+ return false;
+}
+
+V2SchemaCorruptionStatus IndexedDBContextImpl::HasV2SchemaCorruption(
+ const Origin& origin) {
+ DCHECK(TaskRunner()->RunsTasksInCurrentSequence());
+
+ if (is_incognito() || !HasOrigin(origin))
+ return V2SchemaCorruptionStatus::kUnknown;
+
+ if (factory_.get())
+ return factory_->HasV2SchemaCorruption(origin);
+ return V2SchemaCorruptionStatus::kUnknown;
}
size_t IndexedDBContextImpl::GetConnectionCount(const Origin& origin) {
@@ -462,7 +479,7 @@ void IndexedDBContextImpl::ConnectionOpened(const Origin& origin,
quota_manager_proxy()->NotifyStorageAccessed(
storage::QuotaClient::kIndexedDatabase, origin,
blink::mojom::StorageType::kTemporary);
- if (AddToOriginSet(origin)) {
+ if (GetOriginSet()->insert(origin).second) {
// A newly created db, notify the quota system.
QueryDiskAndUpdateQuotaUsage(origin);
} else {
@@ -486,7 +503,7 @@ void IndexedDBContextImpl::TransactionComplete(const Origin& origin) {
}
void IndexedDBContextImpl::DatabaseDeleted(const Origin& origin) {
- AddToOriginSet(origin);
+ GetOriginSet()->insert(origin);
QueryDiskAndUpdateQuotaUsage(origin);
}
@@ -527,7 +544,7 @@ IndexedDBContextImpl::~IndexedDBContextImpl() {
std::move(factory_)));
}
- if (data_path_.empty())
+ if (is_incognito())
return;
if (force_keep_session_state_)
@@ -567,13 +584,13 @@ base::FilePath IndexedDBContextImpl::GetLevelDBFileName(const Origin& origin) {
base::FilePath IndexedDBContextImpl::GetBlobStorePath(
const Origin& origin) const {
- DCHECK(!data_path_.empty());
+ DCHECK(!is_incognito());
return data_path_.Append(GetBlobStoreFileName(origin));
}
base::FilePath IndexedDBContextImpl::GetLevelDBPath(
const Origin& origin) const {
- DCHECK(!data_path_.empty());
+ DCHECK(!is_incognito());
return data_path_.Append(GetLevelDBFileName(origin));
}
diff --git a/chromium/content/browser/indexed_db/indexed_db_context_impl.h b/chromium/content/browser/indexed_db/indexed_db_context_impl.h
index 856f9e3e482..ed60ffcb0f0 100644
--- a/chromium/content/browser/indexed_db/indexed_db_context_impl.h
+++ b/chromium/content/browser/indexed_db/indexed_db_context_impl.h
@@ -123,7 +123,8 @@ class CONTENT_EXPORT IndexedDBContextImpl : public IndexedDBContext {
// ForceClose takes a value rather than a reference since it may release the
// owning object.
void ForceClose(const url::Origin origin, ForceCloseReason reason);
- void ForceSchemaDowngrade(const url::Origin& origin);
+ bool ForceSchemaDowngrade(const url::Origin& origin);
+ V2SchemaCorruptionStatus HasV2SchemaCorruption(const url::Origin& origin);
// GetStoragePaths returns all paths owned by this database, in arbitrary
// order.
std::vector<base::FilePath> GetStoragePaths(const url::Origin& origin) const;
@@ -176,16 +177,16 @@ class CONTENT_EXPORT IndexedDBContextImpl : public IndexedDBContext {
void QueryDiskAndUpdateQuotaUsage(const url::Origin& origin);
base::Time GetOriginLastModified(const url::Origin& origin);
+ // Returns |origin_set_| (this context's in-memory cache of origins with
+ // backing stores); the cache will be primed as needed by checking disk.
std::set<url::Origin>* GetOriginSet();
- bool AddToOriginSet(const url::Origin& origin) {
- return GetOriginSet()->insert(origin).second;
- }
- void RemoveFromOriginSet(const url::Origin& origin) {
- GetOriginSet()->erase(origin);
- }
scoped_refptr<IndexedDBFactory> factory_;
+
+ // If |data_path_| is empty then this is an incognito session and the backing
+ // store will be held in-memory rather than on-disk.
base::FilePath data_path_;
+
// If true, nothing (not even session-only data) should be deleted on exit.
bool force_keep_session_state_;
scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy_;
diff --git a/chromium/content/browser/indexed_db/indexed_db_database_callbacks.cc b/chromium/content/browser/indexed_db/indexed_db_database_callbacks.cc
index 2da4f50e3b4..329a7acf999 100644
--- a/chromium/content/browser/indexed_db/indexed_db_database_callbacks.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_database_callbacks.cc
@@ -4,10 +4,12 @@
#include "content/browser/indexed_db/indexed_db_database_callbacks.h"
+#include "base/task/post_task.h"
#include "content/browser/indexed_db/indexed_db_context_impl.h"
#include "content/browser/indexed_db/indexed_db_database_error.h"
#include "content/browser/indexed_db/indexed_db_dispatcher_host.h"
#include "content/browser/indexed_db/indexed_db_transaction.h"
+#include "content/public/browser/browser_task_traits.h"
using blink::mojom::IDBDatabaseCallbacksAssociatedPtrInfo;
@@ -50,9 +52,9 @@ void IndexedDBDatabaseCallbacks::OnForcedClose() {
return;
DCHECK(io_helper_);
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::BindOnce(&IOThreadHelper::SendForcedClose,
- base::Unretained(io_helper_.get())));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(&IOThreadHelper::SendForcedClose,
+ base::Unretained(io_helper_.get())));
complete_ = true;
}
@@ -63,10 +65,10 @@ void IndexedDBDatabaseCallbacks::OnVersionChange(int64_t old_version,
return;
DCHECK(io_helper_);
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::BindOnce(&IOThreadHelper::SendVersionChange,
- base::Unretained(io_helper_.get()),
- old_version, new_version));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(&IOThreadHelper::SendVersionChange,
+ base::Unretained(io_helper_.get()),
+ old_version, new_version));
}
void IndexedDBDatabaseCallbacks::OnAbort(
@@ -77,10 +79,10 @@ void IndexedDBDatabaseCallbacks::OnAbort(
return;
DCHECK(io_helper_);
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::BindOnce(&IOThreadHelper::SendAbort,
- base::Unretained(io_helper_.get()),
- transaction.id(), error));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(&IOThreadHelper::SendAbort,
+ base::Unretained(io_helper_.get()),
+ transaction.id(), error));
}
void IndexedDBDatabaseCallbacks::OnComplete(
@@ -91,8 +93,8 @@ void IndexedDBDatabaseCallbacks::OnComplete(
indexed_db_context_->TransactionComplete(transaction.database()->origin());
DCHECK(io_helper_);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&IOThreadHelper::SendComplete,
base::Unretained(io_helper_.get()), transaction.id()));
}
@@ -101,8 +103,8 @@ void IndexedDBDatabaseCallbacks::OnDatabaseChange(
blink::mojom::IDBObserverChangesPtr changes) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(io_helper_);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&IOThreadHelper::SendChanges,
base::Unretained(io_helper_.get()), std::move(changes)));
}
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 e876744e8dc..f7c98abe58c 100644
--- a/chromium/content/browser/indexed_db/indexed_db_dispatcher_host.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_dispatcher_host.cc
@@ -12,11 +12,13 @@
#include "base/sequenced_task_runner.h"
#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/task/post_task.h"
#include "content/browser/indexed_db/indexed_db_callbacks.h"
#include "content/browser/indexed_db/indexed_db_connection.h"
#include "content/browser/indexed_db/indexed_db_context_impl.h"
#include "content/browser/indexed_db/indexed_db_database_callbacks.h"
#include "content/browser/indexed_db/indexed_db_pending_connection.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "storage/browser/blob/blob_storage_context.h"
#include "storage/browser/database/database_util.h"
@@ -29,7 +31,7 @@ namespace {
const char kInvalidOrigin[] = "Origin is invalid";
bool IsValidOrigin(const url::Origin& origin) {
- return !origin.unique();
+ return !origin.opaque();
}
blink::mojom::IDBStatus GetIndexedDBStatus(leveldb::Status status) {
@@ -87,10 +89,8 @@ class IndexedDBDispatcherHost::IDBSequenceHelper {
public:
IDBSequenceHelper(
int ipc_process_id,
- scoped_refptr<net::URLRequestContextGetter> request_context_getter,
scoped_refptr<IndexedDBContextImpl> indexed_db_context)
: ipc_process_id_(ipc_process_id),
- request_context_getter_(std::move(request_context_getter)),
indexed_db_context_(std::move(indexed_db_context)) {}
~IDBSequenceHelper() {}
@@ -116,7 +116,6 @@ class IndexedDBDispatcherHost::IDBSequenceHelper {
private:
const int ipc_process_id_;
- scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
scoped_refptr<IndexedDBContextImpl> indexed_db_context_;
DISALLOW_COPY_AND_ASSIGN(IDBSequenceHelper);
@@ -124,14 +123,12 @@ class IndexedDBDispatcherHost::IDBSequenceHelper {
IndexedDBDispatcherHost::IndexedDBDispatcherHost(
int ipc_process_id,
- scoped_refptr<net::URLRequestContextGetter> request_context_getter,
scoped_refptr<IndexedDBContextImpl> indexed_db_context,
scoped_refptr<ChromeBlobStorageContext> blob_storage_context)
: indexed_db_context_(std::move(indexed_db_context)),
blob_storage_context_(std::move(blob_storage_context)),
ipc_process_id_(ipc_process_id),
idb_helper_(new IDBSequenceHelper(ipc_process_id_,
- std::move(request_context_getter),
indexed_db_context_)),
weak_factory_(this) {
DCHECK(indexed_db_context_.get());
@@ -161,8 +158,8 @@ void IndexedDBDispatcherHost::AddCursorBinding(
void IndexedDBDispatcherHost::RenderProcessExited(
RenderProcessHost* host,
const ChildProcessTerminationInfo& info) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&IndexedDBDispatcherHost::InvalidateWeakPtrsAndClearBindings,
base::Unretained(this)));
@@ -290,8 +287,8 @@ void IndexedDBDispatcherHost::IDBSequenceHelper::GetDatabaseNamesOnIDBThread(
DCHECK(indexed_db_context_->TaskRunner()->RunsTasksInCurrentSequence());
base::FilePath indexed_db_path = indexed_db_context_->data_path();
- indexed_db_context_->GetIDBFactory()->GetDatabaseNames(
- callbacks, origin, indexed_db_path, request_context_getter_);
+ indexed_db_context_->GetIDBFactory()->GetDatabaseNames(callbacks, origin,
+ indexed_db_path);
}
void IndexedDBDispatcherHost::IDBSequenceHelper::OpenOnIDBThread(
@@ -313,10 +310,8 @@ void IndexedDBDispatcherHost::IDBSequenceHelper::OpenOnIDBThread(
std::make_unique<IndexedDBPendingConnection>(
callbacks, database_callbacks, ipc_process_id_, transaction_id,
version);
- DCHECK(request_context_getter_);
indexed_db_context_->GetIDBFactory()->Open(name, std::move(connection),
- request_context_getter_, origin,
- indexed_db_path);
+ origin, indexed_db_path);
}
void IndexedDBDispatcherHost::IDBSequenceHelper::DeleteDatabaseOnIDBThread(
@@ -327,10 +322,8 @@ void IndexedDBDispatcherHost::IDBSequenceHelper::DeleteDatabaseOnIDBThread(
DCHECK(indexed_db_context_->TaskRunner()->RunsTasksInCurrentSequence());
base::FilePath indexed_db_path = indexed_db_context_->data_path();
- DCHECK(request_context_getter_);
indexed_db_context_->GetIDBFactory()->DeleteDatabase(
- name, request_context_getter_, callbacks, origin, indexed_db_path,
- force_close);
+ name, callbacks, origin, indexed_db_path, force_close);
}
void IndexedDBDispatcherHost::IDBSequenceHelper::
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 099b0315498..a4babe252bc 100644
--- a/chromium/content/browser/indexed_db/indexed_db_dispatcher_host.h
+++ b/chromium/content/browser/indexed_db/indexed_db_dispatcher_host.h
@@ -21,7 +21,6 @@
#include "content/public/browser/render_process_host_observer.h"
#include "mojo/public/cpp/bindings/associated_binding_set.h"
#include "mojo/public/cpp/bindings/strong_associated_binding_set.h"
-#include "net/url_request/url_request_context_getter.h"
#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom.h"
namespace base {
@@ -45,7 +44,6 @@ class CONTENT_EXPORT IndexedDBDispatcherHost
// Only call the constructor from the UI thread.
IndexedDBDispatcherHost(
int ipc_process_id,
- scoped_refptr<net::URLRequestContextGetter> request_context_getter,
scoped_refptr<IndexedDBContextImpl> indexed_db_context,
scoped_refptr<ChromeBlobStorageContext> blob_storage_context);
diff --git a/chromium/content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc b/chromium/content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc
index 960febdf847..64bae16348b 100644
--- a/chromium/content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc
@@ -11,6 +11,7 @@
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/utf_offset_string_conversions.h"
+#include "base/task/post_task.h"
#include "base/test/test_simple_task_runner.h"
#include "base/threading/thread.h"
#include "content/browser/indexed_db/indexed_db_callbacks.h"
@@ -20,12 +21,12 @@
#include "content/browser/indexed_db/indexed_db_pending_connection.h"
#include "content/browser/indexed_db/mock_mojo_indexed_db_callbacks.h"
#include "content/browser/indexed_db/mock_mojo_indexed_db_database_callbacks.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/public/test/test_utils.h"
#include "mojo/public/cpp/bindings/associated_interface_ptr.h"
#include "mojo/public/cpp/bindings/strong_associated_binding.h"
-#include "net/url_request/url_request_test_util.h"
#include "storage/browser/test/mock_quota_manager.h"
#include "storage/browser/test/mock_quota_manager_proxy.h"
#include "storage/browser/test/mock_special_storage_policy.h"
@@ -56,6 +57,11 @@ using testing::StrictMock;
namespace content {
namespace {
+// TODO(crbug.com/889590): Replace with common converter.
+url::Origin ToOrigin(const std::string& url) {
+ return url::Origin::Create(GURL(url));
+}
+
ACTION_TEMPLATE(MoveArg,
HAS_1_TEMPLATE_PARAMS(int, k),
AND_1_VALUE_PARAMS(out)) {
@@ -159,7 +165,7 @@ class IndexedDBDispatcherHostTest : public testing::Test {
quota_manager_(base::MakeRefCounted<MockQuotaManager>(
false /*is_incognito*/,
browser_context_.GetPath(),
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO),
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO}),
special_storage_policy_)),
context_impl_(base::MakeRefCounted<IndexedDBContextImpl>(
CreateAndReturnTempDir(&temp_dir_),
@@ -167,12 +173,11 @@ class IndexedDBDispatcherHostTest : public testing::Test {
quota_manager_->proxy())),
host_(new IndexedDBDispatcherHost(
kFakeProcessId,
- base::MakeRefCounted<net::TestURLRequestContextGetter>(
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)),
context_impl_,
ChromeBlobStorageContext::GetFor(&browser_context_))) {
- quota_manager_->SetQuota(
- GURL(kOrigin), blink::mojom::StorageType::kTemporary, kTemporaryQuota);
+ quota_manager_->SetQuota(ToOrigin(kOrigin),
+ blink::mojom::StorageType::kTemporary,
+ kTemporaryQuota);
}
void TearDown() override {
@@ -237,7 +242,7 @@ TEST_F(IndexedDBDispatcherHostTest, CloseAfterUpgrade) {
const char kObjectStoreName[] = "os";
// Open connection.
- TestDatabaseConnection connection(url::Origin::Create(GURL(kOrigin)),
+ TestDatabaseConnection connection(ToOrigin(kOrigin),
base::UTF8ToUTF16(kDatabaseName),
kDBVersion, kTransactionId);
@@ -319,9 +324,8 @@ TEST_F(IndexedDBDispatcherHostTest, OpenNewConnectionWhileUpgrading) {
// Open connection 2, but expect that we won't be called back.
IDBDatabaseAssociatedPtrInfo database_info2;
IndexedDBDatabaseMetadata metadata2;
- TestDatabaseConnection connection2(url::Origin::Create(GURL(kOrigin)),
- base::UTF8ToUTF16(kDatabaseName),
- kDBVersion, 0);
+ TestDatabaseConnection connection2(
+ ToOrigin(kOrigin), base::UTF8ToUTF16(kDatabaseName), kDBVersion, 0);
connection2.Open(idb_mojo_factory_.get());
// Check that we're called in order and the second connection gets it's
@@ -445,7 +449,7 @@ TEST_F(IndexedDBDispatcherHostTest, CompactDatabaseWithConnection) {
const int64_t kTransactionId = 1;
// Open connection.
- TestDatabaseConnection connection(url::Origin::Create(GURL(kOrigin)),
+ TestDatabaseConnection connection(ToOrigin(kOrigin),
base::UTF8ToUTF16(kDatabaseName),
kDBVersion, kTransactionId);
IndexedDBDatabaseMetadata metadata;
@@ -505,7 +509,7 @@ TEST_F(IndexedDBDispatcherHostTest, CompactDatabaseWhileDoingTransaction) {
const char kObjectStoreName[] = "os";
// Open connection.
- TestDatabaseConnection connection(url::Origin::Create(GURL(kOrigin)),
+ TestDatabaseConnection connection(ToOrigin(kOrigin),
base::UTF8ToUTF16(kDatabaseName),
kDBVersion, kTransactionId);
IndexedDBDatabaseMetadata metadata;
@@ -570,7 +574,7 @@ TEST_F(IndexedDBDispatcherHostTest, CompactDatabaseWhileUpgrading) {
const int64_t kTransactionId = 1;
// Open connection.
- TestDatabaseConnection connection(url::Origin::Create(GURL(kOrigin)),
+ TestDatabaseConnection connection(ToOrigin(kOrigin),
base::UTF8ToUTF16(kDatabaseName),
kDBVersion, kTransactionId);
IndexedDBDatabaseMetadata metadata;
@@ -633,7 +637,7 @@ TEST_F(IndexedDBDispatcherHostTest,
const int64_t kTransactionId = 1;
// Open connection.
- TestDatabaseConnection connection(url::Origin::Create(GURL(kOrigin)),
+ TestDatabaseConnection connection(ToOrigin(kOrigin),
base::UTF8ToUTF16(kDatabaseName),
kDBVersion, kTransactionId);
IndexedDBDatabaseMetadata metadata;
@@ -696,7 +700,7 @@ TEST_F(IndexedDBDispatcherHostTest, AbortTransactionsWhileDoingTransaction) {
const char kObjectStoreName[] = "os";
// Open connection.
- TestDatabaseConnection connection(url::Origin::Create(GURL(kOrigin)),
+ TestDatabaseConnection connection(ToOrigin(kOrigin),
base::UTF8ToUTF16(kDatabaseName),
kDBVersion, kTransactionId);
IndexedDBDatabaseMetadata metadata;
@@ -761,7 +765,7 @@ TEST_F(IndexedDBDispatcherHostTest, AbortTransactionsWhileUpgrading) {
const int64_t kTransactionId = 1;
// Open connection.
- TestDatabaseConnection connection(url::Origin::Create(GURL(kOrigin)),
+ TestDatabaseConnection connection(ToOrigin(kOrigin),
base::UTF8ToUTF16(kDatabaseName),
kDBVersion, kTransactionId);
IndexedDBDatabaseMetadata metadata;
@@ -835,7 +839,7 @@ TEST_F(IndexedDBDispatcherHostTest, DISABLED_NotifyIndexedDBListChanged) {
context_impl_->AddObserver(&observer);
// Open connection 1.
- TestDatabaseConnection connection1(url::Origin::Create(GURL(kOrigin)),
+ TestDatabaseConnection connection1(ToOrigin(kOrigin),
base::UTF8ToUTF16(kDatabaseName),
kDBVersion1, kTransactionId1);
IndexedDBDatabaseMetadata metadata1;
@@ -940,7 +944,7 @@ TEST_F(IndexedDBDispatcherHostTest, DISABLED_NotifyIndexedDBListChanged) {
connection2.database->Close();
// Open connection 3.
- TestDatabaseConnection connection3(url::Origin::Create(GURL(kOrigin)),
+ TestDatabaseConnection connection3(ToOrigin(kOrigin),
base::UTF8ToUTF16(kDatabaseName),
kDBVersion3, kTransactionId3);
IndexedDBDatabaseMetadata metadata3;
@@ -1069,7 +1073,7 @@ TEST_F(IndexedDBDispatcherHostTest, NotifyIndexedDBContentChanged) {
connection1.database->Close();
// Open connection 2.
- TestDatabaseConnection connection2(url::Origin::Create(GURL(kOrigin)),
+ TestDatabaseConnection connection2(ToOrigin(kOrigin),
base::UTF8ToUTF16(kDatabaseName),
kDBVersion2, kTransactionId2);
IndexedDBDatabaseMetadata metadata2;
diff --git a/chromium/content/browser/indexed_db/indexed_db_factory.h b/chromium/content/browser/indexed_db/indexed_db_factory.h
index d4e62a6a9f7..9edf2b3e39e 100644
--- a/chromium/content/browser/indexed_db/indexed_db_factory.h
+++ b/chromium/content/browser/indexed_db/indexed_db_factory.h
@@ -23,10 +23,6 @@
#include "url/gurl.h"
#include "url/origin.h"
-namespace net {
-class URLRequestContextGetter;
-}
-
namespace content {
class IndexedDBBackingStore;
@@ -43,21 +39,17 @@ class CONTENT_EXPORT IndexedDBFactory
virtual void ReleaseDatabase(const IndexedDBDatabase::Identifier& identifier,
bool forced_close) = 0;
- virtual void GetDatabaseNames(
- scoped_refptr<IndexedDBCallbacks> callbacks,
- const url::Origin& origin,
- const base::FilePath& data_directory,
- scoped_refptr<net::URLRequestContextGetter> request_context_getter) = 0;
+ virtual void GetDatabaseNames(scoped_refptr<IndexedDBCallbacks> callbacks,
+ const url::Origin& origin,
+ const base::FilePath& data_directory) = 0;
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) = 0;
virtual void DeleteDatabase(
const base::string16& name,
- scoped_refptr<net::URLRequestContextGetter> request_context_getter,
scoped_refptr<IndexedDBCallbacks> callbacks,
const url::Origin& origin,
const base::FilePath& data_directory,
@@ -78,8 +70,15 @@ class CONTENT_EXPORT IndexedDBFactory
virtual OriginDBs GetOpenDatabasesForOrigin(
const url::Origin& origin) const = 0;
- virtual void ForceClose(const url::Origin& origin) = 0;
+ // Close all connections to all databases within the origin. If
+ // |delete_in_memory_store| is true, references to in-memory databases will be
+ // dropped thereby allowing their deletion (otherwise they are retained for
+ // the lifetime of the factory).
+ virtual void ForceClose(const url::Origin& origin,
+ bool delete_in_memory_store = false) = 0;
virtual void ForceSchemaDowngrade(const url::Origin& origin) = 0;
+ virtual V2SchemaCorruptionStatus HasV2SchemaCorruption(
+ const url::Origin& origin) = 0;
// Called by the IndexedDBContext destructor so the factory can do cleanup.
virtual void ContextDestroyed() = 0;
@@ -115,7 +114,6 @@ class CONTENT_EXPORT IndexedDBFactory
virtual scoped_refptr<IndexedDBBackingStore> OpenBackingStore(
const url::Origin& origin,
const base::FilePath& data_directory,
- scoped_refptr<net::URLRequestContextGetter> request_context_getter,
IndexedDBDataLossInfo* data_loss_info,
bool* disk_full,
leveldb::Status* status) = 0;
@@ -123,7 +121,6 @@ class CONTENT_EXPORT IndexedDBFactory
virtual scoped_refptr<IndexedDBBackingStore> OpenBackingStoreHelper(
const url::Origin& origin,
const base::FilePath& data_directory,
- scoped_refptr<net::URLRequestContextGetter> request_context_getter,
IndexedDBDataLossInfo* data_loss_info,
bool* disk_full,
bool first_time,
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 404b2556081..e625f0e6a2e 100644
--- a/chromium/content/browser/indexed_db/indexed_db_factory_impl.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_factory_impl.cc
@@ -15,6 +15,7 @@
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
#include "base/rand_util.h"
+#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "content/browser/indexed_db/indexed_db_backing_store.h"
@@ -137,7 +138,7 @@ void IndexedDBFactoryImpl::RemoveDatabaseFromMaps(
std::pair<OriginDBMap::iterator, OriginDBMap::iterator> range =
origin_dbs_.equal_range(database->identifier().first);
DCHECK(range.first != range.second);
- for (OriginDBMap::iterator it2 = range.first; it2 != range.second; ++it2) {
+ for (auto it2 = range.first; it2 != range.second; ++it2) {
if (it2->second == database) {
origin_dbs_.erase(it2);
break;
@@ -325,7 +326,8 @@ leveldb::Status IndexedDBFactoryImpl::AbortTransactions(const Origin& origin) {
return leveldb::Status::OK();
}
-void IndexedDBFactoryImpl::ForceClose(const Origin& origin) {
+void IndexedDBFactoryImpl::ForceClose(const Origin& origin,
+ bool delete_in_memory_store) {
OriginDBs range = GetOpenDatabasesForOrigin(origin);
while (range.first != range.second) {
@@ -334,19 +336,33 @@ void IndexedDBFactoryImpl::ForceClose(const Origin& origin) {
db->ForceClose();
}
- if (backing_store_map_.find(origin) != backing_store_map_.end())
+ auto it = backing_store_map_.find(origin);
+ if (it != backing_store_map_.end()) {
+ if (delete_in_memory_store)
+ in_memory_backing_stores_.erase(it->second);
+
ReleaseBackingStore(origin, true /* immediate */);
+ }
}
void IndexedDBFactoryImpl::ForceSchemaDowngrade(const Origin& origin) {
- OriginDBs range = GetOpenDatabasesForOrigin(origin);
+ auto it = backing_store_map_.find(origin);
+ if (it == backing_store_map_.end())
+ return;
- while (range.first != range.second) {
- IndexedDBDatabase* db = range.first->second;
- ++range.first;
- leveldb::Status s = db->backing_store()->RevertSchemaToV2();
- DLOG_IF(ERROR, !s.ok()) << "Unable to force downgrade: " << s.ToString();
- }
+ IndexedDBBackingStore* backing_store = it->second.get();
+ leveldb::Status s = backing_store->RevertSchemaToV2();
+ DLOG_IF(ERROR, !s.ok()) << "Unable to force downgrade: " << s.ToString();
+}
+
+V2SchemaCorruptionStatus IndexedDBFactoryImpl::HasV2SchemaCorruption(
+ const Origin& origin) {
+ auto it = backing_store_map_.find(origin);
+ if (it == backing_store_map_.end())
+ return V2SchemaCorruptionStatus::kUnknown;
+
+ IndexedDBBackingStore* backing_store = it->second.get();
+ return backing_store->HasV2SchemaCorruption();
}
void IndexedDBFactoryImpl::ContextDestroyed() {
@@ -386,8 +402,7 @@ void IndexedDBFactoryImpl::ReportOutstandingBlobs(const Origin& origin,
void IndexedDBFactoryImpl::GetDatabaseNames(
scoped_refptr<IndexedDBCallbacks> callbacks,
const Origin& origin,
- const base::FilePath& data_directory,
- scoped_refptr<net::URLRequestContextGetter> request_context_getter) {
+ const base::FilePath& data_directory) {
IDB_TRACE("IndexedDBFactoryImpl::GetDatabaseNames");
// TODO(dgrogan): Plumb data_loss back to script eventually?
IndexedDBDataLossInfo data_loss_info;
@@ -395,8 +410,7 @@ void IndexedDBFactoryImpl::GetDatabaseNames(
leveldb::Status s;
// TODO(cmumford): Handle this error
scoped_refptr<IndexedDBBackingStore> backing_store =
- OpenBackingStore(origin, data_directory, request_context_getter,
- &data_loss_info, &disk_full, &s);
+ OpenBackingStore(origin, data_directory, &data_loss_info, &disk_full, &s);
if (!backing_store.get()) {
IndexedDBDatabaseError error(
blink::kWebIDBDatabaseExceptionUnknownError,
@@ -430,7 +444,6 @@ void IndexedDBFactoryImpl::GetDatabaseNames(
void IndexedDBFactoryImpl::DeleteDatabase(
const base::string16& name,
- scoped_refptr<net::URLRequestContextGetter> request_context_getter,
scoped_refptr<IndexedDBCallbacks> callbacks,
const Origin& origin,
const base::FilePath& data_directory,
@@ -450,8 +463,7 @@ void IndexedDBFactoryImpl::DeleteDatabase(
bool disk_full = false;
leveldb::Status s;
scoped_refptr<IndexedDBBackingStore> backing_store =
- OpenBackingStore(origin, data_directory, request_context_getter,
- &data_loss_info, &disk_full, &s);
+ OpenBackingStore(origin, data_directory, &data_loss_info, &disk_full, &s);
if (!backing_store.get()) {
IndexedDBDatabaseError error(
blink::kWebIDBDatabaseExceptionUnknownError,
@@ -596,11 +608,12 @@ void IndexedDBFactoryImpl::HandleBackingStoreCorruption(
bool IndexedDBFactoryImpl::IsDatabaseOpen(const Origin& origin,
const base::string16& name) const {
- return !!database_map_.count(IndexedDBDatabase::Identifier(origin, name));
+ return base::ContainsKey(database_map_,
+ IndexedDBDatabase::Identifier(origin, name));
}
bool IndexedDBFactoryImpl::IsBackingStoreOpen(const Origin& origin) const {
- return backing_store_map_.find(origin) != backing_store_map_.end();
+ return base::ContainsKey(backing_store_map_, origin);
}
bool IndexedDBFactoryImpl::IsBackingStorePendingClose(
@@ -616,20 +629,18 @@ scoped_refptr<IndexedDBBackingStore>
IndexedDBFactoryImpl::OpenBackingStoreHelper(
const Origin& origin,
const base::FilePath& data_directory,
- scoped_refptr<net::URLRequestContextGetter> request_context_getter,
IndexedDBDataLossInfo* data_loss_info,
bool* disk_full,
bool first_time,
leveldb::Status* status) {
return IndexedDBBackingStore::Open(
- this, origin, data_directory, request_context_getter, data_loss_info,
- disk_full, context_->TaskRunner(), first_time, status);
+ this, origin, data_directory, data_loss_info, disk_full,
+ context_->TaskRunner(), first_time, status);
}
scoped_refptr<IndexedDBBackingStore> IndexedDBFactoryImpl::OpenBackingStore(
const Origin& origin,
const base::FilePath& data_directory,
- scoped_refptr<net::URLRequestContextGetter> request_context_getter,
IndexedDBDataLossInfo* data_loss_info,
bool* disk_full,
leveldb::Status* status) {
@@ -656,22 +667,22 @@ scoped_refptr<IndexedDBBackingStore> IndexedDBFactoryImpl::OpenBackingStore(
} else {
first_time = !backends_opened_since_boot_.count(origin);
- backing_store =
- OpenBackingStoreHelper(origin, data_directory, request_context_getter,
- data_loss_info, disk_full, first_time, status);
+ backing_store = OpenBackingStoreHelper(
+ origin, data_directory, data_loss_info, disk_full, first_time, status);
}
if (backing_store.get()) {
if (first_time)
backends_opened_since_boot_.insert(origin);
backing_store_map_[origin] = backing_store;
+
// If an in-memory database, bind lifetime to this factory instance.
if (open_in_memory)
- session_only_backing_stores_.insert(backing_store);
+ in_memory_backing_stores_.insert(backing_store);
// All backing stores associated with this factory should be of the same
// type.
- DCHECK_NE(session_only_backing_stores_.empty(), open_in_memory);
+ DCHECK_NE(in_memory_backing_stores_.empty(), open_in_memory);
return backing_store;
}
@@ -682,7 +693,6 @@ scoped_refptr<IndexedDBBackingStore> IndexedDBFactoryImpl::OpenBackingStore(
void IndexedDBFactoryImpl::Open(
const base::string16& name,
std::unique_ptr<IndexedDBPendingConnection> connection,
- scoped_refptr<net::URLRequestContextGetter> request_context_getter,
const Origin& origin,
const base::FilePath& data_directory) {
IDB_TRACE("IndexedDBFactoryImpl::Open");
@@ -694,9 +704,8 @@ void IndexedDBFactoryImpl::Open(
bool was_open = (it != database_map_.end());
if (!was_open) {
leveldb::Status s;
- scoped_refptr<IndexedDBBackingStore> backing_store =
- OpenBackingStore(origin, data_directory, request_context_getter,
- &data_loss_info, &disk_full, &s);
+ scoped_refptr<IndexedDBBackingStore> backing_store = OpenBackingStore(
+ origin, data_directory, &data_loss_info, &disk_full, &s);
if (!backing_store.get()) {
if (disk_full) {
connection->callbacks->OnError(IndexedDBDatabaseError(
@@ -757,7 +766,7 @@ size_t IndexedDBFactoryImpl::GetConnectionCount(const Origin& origin) const {
size_t count(0);
OriginDBs range = GetOpenDatabasesForOrigin(origin);
- for (OriginDBMapIterator it = range.first; it != range.second; ++it)
+ for (auto it = range.first; it != range.second; ++it)
count += it->second->ConnectionCount();
return count;
@@ -765,7 +774,9 @@ size_t IndexedDBFactoryImpl::GetConnectionCount(const Origin& origin) const {
int64_t IndexedDBFactoryImpl::GetInMemoryDBSize(const Origin& origin) const {
const auto& it = backing_store_map_.find(origin);
- DCHECK(it != backing_store_map_.end());
+ // Origin won't be present in map if it has been deleted.
+ if (it == backing_store_map_.end())
+ return 0;
const scoped_refptr<IndexedDBBackingStore>& backing_store = it->second;
int64_t level_db_size = 0;
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 b78429e2e2c..669ba668615 100644
--- a/chromium/content/browser/indexed_db/indexed_db_factory_impl.h
+++ b/chromium/content/browser/indexed_db/indexed_db_factory_impl.h
@@ -55,18 +55,14 @@ class CONTENT_EXPORT IndexedDBFactoryImpl : public IndexedDBFactory {
void GetDatabaseNames(scoped_refptr<IndexedDBCallbacks> callbacks,
const url::Origin& origin,
- const base::FilePath& data_directory,
- scoped_refptr<net::URLRequestContextGetter>
- request_context_getter) override;
+ const base::FilePath& data_directory) override;
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;
void DeleteDatabase(
const base::string16& name,
- scoped_refptr<net::URLRequestContextGetter> request_context_getter,
scoped_refptr<IndexedDBCallbacks> callbacks,
const url::Origin& origin,
const base::FilePath& data_directory,
@@ -86,8 +82,11 @@ class CONTENT_EXPORT IndexedDBFactoryImpl : public IndexedDBFactory {
OriginDBs GetOpenDatabasesForOrigin(const url::Origin& origin) const override;
- void ForceClose(const url::Origin& origin) override;
+ void ForceClose(const url::Origin& origin,
+ bool delete_in_memory_store) override;
void ForceSchemaDowngrade(const url::Origin& origin) override;
+ V2SchemaCorruptionStatus HasV2SchemaCorruption(
+ const url::Origin& origin) override;
// Called by the IndexedDBContext destructor so the factory can do cleanup.
void ContextDestroyed() override;
@@ -120,7 +119,6 @@ class CONTENT_EXPORT IndexedDBFactoryImpl : public IndexedDBFactory {
scoped_refptr<IndexedDBBackingStore> OpenBackingStore(
const url::Origin& origin,
const base::FilePath& data_directory,
- scoped_refptr<net::URLRequestContextGetter> request_context_getter,
IndexedDBDataLossInfo* data_loss_info,
bool* disk_full,
leveldb::Status* s) override;
@@ -128,7 +126,6 @@ class CONTENT_EXPORT IndexedDBFactoryImpl : public IndexedDBFactory {
scoped_refptr<IndexedDBBackingStore> OpenBackingStoreHelper(
const url::Origin& origin,
const base::FilePath& data_directory,
- scoped_refptr<net::URLRequestContextGetter> request_context_getter,
IndexedDBDataLossInfo* data_loss_info,
bool* disk_full,
bool first_time,
@@ -181,7 +178,10 @@ class CONTENT_EXPORT IndexedDBFactoryImpl : public IndexedDBFactory {
std::map<url::Origin, scoped_refptr<IndexedDBBackingStore>>
backing_store_map_;
- std::set<scoped_refptr<IndexedDBBackingStore> > session_only_backing_stores_;
+ // In-memory (incognito) backing stores should live as long as the
+ // StoragePartition which owns the IndexedDBContext which owns this
+ // IndexedDBFactory.
+ std::set<scoped_refptr<IndexedDBBackingStore>> in_memory_backing_stores_;
std::map<url::Origin, scoped_refptr<IndexedDBBackingStore>>
backing_stores_with_active_blobs_;
std::set<url::Origin> backends_opened_since_boot_;
diff --git a/chromium/content/browser/indexed_db/indexed_db_factory_unittest.cc b/chromium/content/browser/indexed_db/indexed_db_factory_unittest.cc
index 849666e7be5..8951a04e3b6 100644
--- a/chromium/content/browser/indexed_db/indexed_db_factory_unittest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_factory_unittest.cc
@@ -52,9 +52,8 @@ class MockIDBFactory : public IndexedDBFactoryImpl {
IndexedDBDataLossInfo data_loss_info;
bool disk_full;
leveldb::Status s;
- scoped_refptr<IndexedDBBackingStore> backing_store =
- OpenBackingStore(origin, data_directory, nullptr /* request_context */,
- &data_loss_info, &disk_full, &s);
+ scoped_refptr<IndexedDBBackingStore> backing_store = OpenBackingStore(
+ origin, data_directory, &data_loss_info, &disk_full, &s);
EXPECT_EQ(blink::kWebIDBDataLossNone, data_loss_info.status);
return backing_store;
}
@@ -447,7 +446,6 @@ class DiskFullFactory : public IndexedDBFactoryImpl {
scoped_refptr<IndexedDBBackingStore> OpenBackingStore(
const Origin& origin,
const base::FilePath& data_directory,
- scoped_refptr<net::URLRequestContextGetter> request_context_getter,
IndexedDBDataLossInfo* data_loss_info,
bool* disk_full,
leveldb::Status* s) override {
@@ -503,8 +501,7 @@ TEST_F(IndexedDBFactoryTest, QuotaErrorOnDiskFull) {
callbacks, dummy_database_callbacks,
0 /* child_process_id */, 2 /* transaction_id */,
1 /* version */));
- factory->Open(name, std::move(connection),
- nullptr /* request_context */, origin,
+ factory->Open(name, std::move(connection), origin,
context->data_path());
EXPECT_TRUE(callbacks->error_called());
},
@@ -531,8 +528,7 @@ TEST_F(IndexedDBFactoryTest, BackingStoreReleasedOnForcedClose) {
callbacks, db_callbacks, 0 /* child_process_id */,
transaction_id,
IndexedDBDatabaseMetadata::DEFAULT_VERSION));
- factory->Open(ASCIIToUTF16("db"), std::move(connection),
- nullptr /* request_context */, origin,
+ factory->Open(ASCIIToUTF16("db"), std::move(connection), origin,
context->data_path());
EXPECT_TRUE(callbacks->connection());
@@ -569,8 +565,7 @@ TEST_F(IndexedDBFactoryTest, BackingStoreReleaseDelayedOnClose) {
callbacks, db_callbacks, 0 /* child_process_id */,
transaction_id,
IndexedDBDatabaseMetadata::DEFAULT_VERSION));
- factory->Open(ASCIIToUTF16("db"), std::move(connection),
- nullptr /* request_context */, origin,
+ factory->Open(ASCIIToUTF16("db"), std::move(connection), origin,
context->data_path());
EXPECT_TRUE(callbacks->connection());
@@ -613,9 +608,9 @@ TEST_F(IndexedDBFactoryTest, DeleteDatabaseClosesBackingStore) {
const Origin origin = Origin::Create(GURL("http://localhost:81"));
EXPECT_FALSE(factory->IsBackingStoreOpen(origin));
- factory->DeleteDatabase(
- ASCIIToUTF16("db"), nullptr /* request_context */, callbacks,
- origin, context->data_path(), false /* force_close */);
+ factory->DeleteDatabase(ASCIIToUTF16("db"), callbacks, origin,
+ context->data_path(),
+ false /* force_close */);
EXPECT_TRUE(factory->IsBackingStoreOpen(origin));
EXPECT_TRUE(factory->IsBackingStorePendingClose(origin));
@@ -645,8 +640,7 @@ TEST_F(IndexedDBFactoryTest, GetDatabaseNamesClosesBackingStore) {
const Origin origin = Origin::Create(GURL("http://localhost:81"));
EXPECT_FALSE(factory->IsBackingStoreOpen(origin));
- factory->GetDatabaseNames(callbacks, origin, context->data_path(),
- nullptr /* request_context */);
+ factory->GetDatabaseNames(callbacks, origin, context->data_path());
EXPECT_TRUE(factory->IsBackingStoreOpen(origin));
EXPECT_TRUE(factory->IsBackingStorePendingClose(origin));
@@ -681,8 +675,7 @@ TEST_F(IndexedDBFactoryTest, ForceCloseReleasesBackingStore) {
callbacks, db_callbacks, 0 /* child_process_id */,
transaction_id,
IndexedDBDatabaseMetadata::DEFAULT_VERSION));
- factory->Open(ASCIIToUTF16("db"), std::move(connection),
- nullptr /* request_context */, origin,
+ factory->Open(ASCIIToUTF16("db"), std::move(connection), origin,
context->data_path());
EXPECT_TRUE(callbacks->connection());
@@ -694,13 +687,13 @@ TEST_F(IndexedDBFactoryTest, ForceCloseReleasesBackingStore) {
EXPECT_TRUE(factory->IsBackingStoreOpen(origin));
EXPECT_TRUE(factory->IsBackingStorePendingClose(origin));
- factory->ForceClose(origin);
+ factory->ForceClose(origin, /*delete_in_memory_store=*/false);
EXPECT_FALSE(factory->IsBackingStoreOpen(origin));
EXPECT_FALSE(factory->IsBackingStorePendingClose(origin));
// Ensure it is safe if the store is not open.
- factory->ForceClose(origin);
+ factory->ForceClose(origin, /*delete_in_memory_store=*/false);
},
base::Unretained(context()),
@@ -782,7 +775,7 @@ TEST_F(IndexedDBFactoryTest, DatabaseFailedOpen) {
std::make_unique<IndexedDBPendingConnection>(
*upgrade_callbacks, db_callbacks, 0 /* child_process_id */,
transaction_id, db_version),
- nullptr /* request_context */, origin, context->data_path());
+ origin, context->data_path());
EXPECT_TRUE((*factory)->IsDatabaseOpen(origin, db_name));
},
@@ -822,15 +815,14 @@ TEST_F(IndexedDBFactoryTest, DatabaseFailedOpen) {
std::make_unique<IndexedDBPendingConnection>(
failed_open_callbacks, db_callbacks,
0 /* child_process_id */, transaction_id, db_version));
- factory->Open(db_name, std::move(connection),
- nullptr /* request_context */, origin,
+ factory->Open(db_name, std::move(connection), origin,
context->data_path());
EXPECT_TRUE(failed_open_callbacks->saw_error());
EXPECT_FALSE(factory->IsDatabaseOpen(origin, db_name));
}
// Terminate all pending-close timers.
- factory->ForceClose(origin);
+ factory->ForceClose(origin, /*delete_in_memory_store=*/false);
},
base::Unretained(context()), std::move(factory),
std::move(upgrade_callbacks), base::MakeRefCounted<ErrorCallbacks>(),
@@ -898,7 +890,7 @@ TEST_F(IndexedDBFactoryTest, DataFormatVersion) {
std::make_unique<IndexedDBPendingConnection>(
*callbacks, db_callbacks, 0 /* child_process_id */,
transaction_id, 1 /* version */),
- nullptr /* request_context */, origin, context->data_path());
+ origin, context->data_path());
},
base::Unretained(context()), base::Unretained(&factory),
base::Unretained(&callbacks),
@@ -916,7 +908,7 @@ TEST_F(IndexedDBFactoryTest, DataFormatVersion) {
connection->database()->Commit(
connection->GetTransaction(transaction_id));
connection->Close();
- factory->ForceClose(origin);
+ factory->ForceClose(origin, /*delete_in_memory_store=*/false);
*result = callbacks->data_loss();
},
std::move(factory), std::move(callbacks), origin, transaction_id,
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 7477de76328..7444756a65e 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
@@ -6,7 +6,6 @@
#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 {
namespace {
@@ -20,7 +19,6 @@ IndexedDBFakeBackingStore::IndexedDBFakeBackingStore()
: IndexedDBBackingStore(nullptr /* indexed_db_factory */,
url::Origin::Create(GURL("http://localhost:81")),
base::FilePath(),
- scoped_refptr<net::URLRequestContextGetter>(),
std::unique_ptr<LevelDBDatabase>(),
std::unique_ptr<LevelDBComparator>(),
base::SequencedTaskRunnerHandle::Get().get()) {}
@@ -30,7 +28,6 @@ IndexedDBFakeBackingStore::IndexedDBFakeBackingStore(
: IndexedDBBackingStore(factory,
url::Origin::Create(GURL("http://localhost:81")),
base::FilePath(),
- nullptr /* request_context */,
std::unique_ptr<LevelDBDatabase>(),
std::unique_ptr<LevelDBComparator>(),
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 cd8bc3bdb43..909b8e86fd7 100644
--- a/chromium/content/browser/indexed_db/indexed_db_internals_ui.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_internals_ui.cc
@@ -18,6 +18,7 @@
#include "content/browser/indexed_db/indexed_db_context_impl.h"
#include "content/grit/content_resources.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/download_manager.h"
#include "content/public/browser/download_request_utils.h"
@@ -119,8 +120,8 @@ void IndexedDBInternalsUI::GetAllOriginsOnIndexedDBThread(
context_impl->GetAllOriginsDetails());
bool is_incognito = context_impl->is_incognito();
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&IndexedDBInternalsUI::OnOriginsReady,
base::Unretained(this), std::move(info_list),
is_incognito ? base::FilePath() : context_path));
@@ -261,8 +262,8 @@ void IndexedDBInternalsUI::DownloadOriginDataOnIndexedDBThread(
zip::ZipWithFilterCallback(context->data_path(), zip_path,
base::Bind(AllowWhitelistedPaths, paths));
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&IndexedDBInternalsUI::OnDownloadDataReady,
base::Unretained(this), partition_path, origin, temp_path,
zip_path, connection_count));
@@ -281,8 +282,8 @@ void IndexedDBInternalsUI::ForceCloseOriginOnIndexedDBThread(
context->ForceClose(origin, IndexedDBContextImpl::FORCE_CLOSE_INTERNALS_PAGE);
size_t connection_count = context->GetConnectionCount(origin);
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&IndexedDBInternalsUI::OnForcedSchemaDowngrade,
base::Unretained(this), partition_path, origin,
connection_count));
@@ -303,8 +304,8 @@ void IndexedDBInternalsUI::ForceSchemaDowngradeOriginOnIndexedDBThread(
origin, IndexedDBContextImpl::FORCE_SCHEMA_DOWNGRADE_INTERNALS_PAGE);
size_t connection_count = context->GetConnectionCount(origin);
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&IndexedDBInternalsUI::OnForcedSchemaDowngrade,
base::Unretained(this), partition_path, origin,
connection_count));
diff --git a/chromium/content/browser/indexed_db/indexed_db_transaction_coordinator.cc b/chromium/content/browser/indexed_db/indexed_db_transaction_coordinator.cc
index 91dd95712ad..f8e127b6fbe 100644
--- a/chromium/content/browser/indexed_db/indexed_db_transaction_coordinator.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_transaction_coordinator.cc
@@ -147,8 +147,8 @@ void IndexedDBTransactionCoordinator::ProcessQueuedTransactions() {
template<typename T>
static bool DoSetsIntersect(const std::set<T>& set1,
const std::set<T>& set2) {
- typename std::set<T>::const_iterator it1 = set1.begin();
- typename std::set<T>::const_iterator it2 = set2.begin();
+ auto it1 = set1.begin();
+ auto it2 = set2.begin();
while (it1 != set1.end() && it2 != set2.end()) {
if (*it1 < *it2)
++it1;
diff --git a/chromium/content/browser/indexed_db/indexed_db_unittest.cc b/chromium/content/browser/indexed_db/indexed_db_unittest.cc
index 4763c2f5eaf..e651a8edf6f 100644
--- a/chromium/content/browser/indexed_db/indexed_db_unittest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_unittest.cc
@@ -173,7 +173,6 @@ TEST_F(IndexedDBTest, ForceCloseOpenDatabasesOnDelete) {
const int child_process_id = 0;
const int64_t host_transaction_id = 0;
const int64_t version = 0;
- const scoped_refptr<net::URLRequestContextGetter> request_context;
IndexedDBFactory* factory = idb_context->GetIDBFactory();
@@ -184,14 +183,14 @@ TEST_F(IndexedDBTest, ForceCloseOpenDatabasesOnDelete) {
std::make_unique<IndexedDBPendingConnection>(
open_callbacks, open_db_callbacks,
child_process_id, host_transaction_id, version),
- request_context, origin, idb_context->data_path());
+ origin, idb_context->data_path());
EXPECT_TRUE(base::DirectoryExists(test_path));
factory->Open(base::ASCIIToUTF16("closeddb"),
std::make_unique<IndexedDBPendingConnection>(
closed_callbacks, closed_db_callbacks,
child_process_id, host_transaction_id, version),
- request_context, origin, idb_context->data_path());
+ origin, idb_context->data_path());
closed_callbacks->connection()->Close();
@@ -260,14 +259,13 @@ TEST_F(IndexedDBTest, ForceCloseOpenDatabasesOnCommitFailure) {
const int child_process_id = 0;
const int64_t transaction_id = 1;
- const scoped_refptr<net::URLRequestContextGetter> request_context;
std::unique_ptr<IndexedDBPendingConnection> connection(
std::make_unique<IndexedDBPendingConnection>(
callbacks, db_callbacks, child_process_id, transaction_id,
IndexedDBDatabaseMetadata::DEFAULT_VERSION));
factory->Open(base::ASCIIToUTF16("db"), std::move(connection),
- request_context, Origin(kTestOrigin), temp_path);
+ Origin(kTestOrigin), temp_path);
EXPECT_TRUE(callbacks->connection());
diff --git a/chromium/content/browser/indexed_db/leveldb/leveldb_database.cc b/chromium/content/browser/indexed_db/leveldb/leveldb_database.cc
index 761cc63bb32..5b758222da1 100644
--- a/chromium/content/browser/indexed_db/leveldb/leveldb_database.cc
+++ b/chromium/content/browser/indexed_db/leveldb/leveldb_database.cc
@@ -387,7 +387,7 @@ leveldb::Status LevelDBDatabase::Remove(const StringPiece& key) {
const leveldb::Status s =
db_->Delete(write_options, leveldb_env::MakeSlice(key));
- if (!s.IsNotFound())
+ if (!s.ok() && !s.IsNotFound())
LOG(ERROR) << "LevelDB remove failed: " << s.ToString();
last_modified_ = clock_->Now();
return s;
diff --git a/chromium/content/browser/indexed_db/leveldb/leveldb_transaction.cc b/chromium/content/browser/indexed_db/leveldb/leveldb_transaction.cc
index 89035f6fb43..97690b6f879 100644
--- a/chromium/content/browser/indexed_db/leveldb/leveldb_transaction.cc
+++ b/chromium/content/browser/indexed_db/leveldb/leveldb_transaction.cc
@@ -46,7 +46,7 @@ void LevelDBTransaction::Set(const StringPiece& key,
std::string* value,
bool deleted) {
DCHECK(!finished_);
- DataType::iterator it = data_.find(key);
+ auto it = data_.find(key);
if (it == data_.end()) {
std::unique_ptr<Record> record = std::make_unique<Record>();
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 b2747857a84..2d92895000d 100644
--- a/chromium/content/browser/indexed_db/mock_indexed_db_factory.h
+++ b/chromium/content/browser/indexed_db/mock_indexed_db_factory.h
@@ -21,36 +21,29 @@ class MockIndexedDBFactory : public IndexedDBFactory {
MOCK_METHOD2(ReleaseDatabase,
void(const IndexedDBDatabase::Identifier& identifier,
bool forced_close));
+ MOCK_METHOD3(GetDatabaseNames,
+ void(scoped_refptr<IndexedDBCallbacks> callbacks,
+ const url::Origin& origin,
+ const base::FilePath& data_directory));
MOCK_METHOD4(
- GetDatabaseNames,
- void(scoped_refptr<IndexedDBCallbacks> callbacks,
- const url::Origin& origin,
- const base::FilePath& data_directory,
- scoped_refptr<net::URLRequestContextGetter> request_context_getter));
- MOCK_METHOD5(
OpenProxy,
void(const base::string16& name,
IndexedDBPendingConnection* connection,
- scoped_refptr<net::URLRequestContextGetter> request_context_getter,
const url::Origin& origin,
const base::FilePath& data_directory));
// Googlemock can't deal with move-only types, so *Proxy() is a workaround.
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);
+ OpenProxy(name, connection.get(), origin, data_directory);
}
- MOCK_METHOD6(
- DeleteDatabase,
- void(const base::string16& name,
- scoped_refptr<net::URLRequestContextGetter> request_context_getter,
- scoped_refptr<IndexedDBCallbacks> callbacks,
- const url::Origin& origin,
- const base::FilePath& data_directory,
- bool force_close));
+ MOCK_METHOD5(DeleteDatabase,
+ void(const base::string16& name,
+ scoped_refptr<IndexedDBCallbacks> callbacks,
+ const url::Origin& origin,
+ const base::FilePath& data_directory,
+ bool force_close));
MOCK_METHOD2(AbortTransactionsAndCompactDatabaseProxy,
void(base::OnceCallback<void(leveldb::Status)>* callback,
const url::Origin& origin));
@@ -77,8 +70,11 @@ class MockIndexedDBFactory : public IndexedDBFactory {
// The Android NDK implements a subset of STL, and the gtest templates can't
// deal with std::pair's. This means we can't use GoogleMock for this method
OriginDBs GetOpenDatabasesForOrigin(const url::Origin& origin) const override;
- MOCK_METHOD1(ForceClose, void(const url::Origin& origin));
+ MOCK_METHOD2(ForceClose,
+ void(const url::Origin& origin, bool delete_in_memory_store));
MOCK_METHOD1(ForceSchemaDowngrade, void(const url::Origin& origin));
+ MOCK_METHOD1(HasV2SchemaCorruption,
+ V2SchemaCorruptionStatus(const url::Origin& origin));
MOCK_METHOD0(ContextDestroyed, void());
MOCK_METHOD1(DatabaseDeleted,
void(const IndexedDBDatabase::Identifier& identifier));
@@ -103,26 +99,22 @@ class MockIndexedDBFactory : public IndexedDBFactory {
protected:
~MockIndexedDBFactory() override;
- MOCK_METHOD6(
- OpenBackingStore,
- scoped_refptr<IndexedDBBackingStore>(
- const url::Origin& origin,
- const base::FilePath& data_directory,
- scoped_refptr<net::URLRequestContextGetter> request_context_getter,
- IndexedDBDataLossInfo* data_loss_info,
- bool* disk_full,
- leveldb::Status* s));
-
- MOCK_METHOD7(
- OpenBackingStoreHelper,
- scoped_refptr<IndexedDBBackingStore>(
- const url::Origin& origin,
- const base::FilePath& data_directory,
- scoped_refptr<net::URLRequestContextGetter> request_context_getter,
- IndexedDBDataLossInfo* data_loss_info,
- bool* disk_full,
- bool first_time,
- leveldb::Status* s));
+ MOCK_METHOD5(OpenBackingStore,
+ scoped_refptr<IndexedDBBackingStore>(
+ const url::Origin& origin,
+ const base::FilePath& data_directory,
+ IndexedDBDataLossInfo* data_loss_info,
+ bool* disk_full,
+ leveldb::Status* s));
+
+ MOCK_METHOD6(OpenBackingStoreHelper,
+ scoped_refptr<IndexedDBBackingStore>(
+ const url::Origin& origin,
+ const base::FilePath& data_directory,
+ IndexedDBDataLossInfo* data_loss_info,
+ bool* disk_full,
+ bool first_time,
+ leveldb::Status* s));
private:
DISALLOW_COPY_AND_ASSIGN(MockIndexedDBFactory);
diff --git a/chromium/content/browser/initiator_csp_context.cc b/chromium/content/browser/initiator_csp_context.cc
index a29e02d4e97..2529f9eefbd 100644
--- a/chromium/content/browser/initiator_csp_context.cc
+++ b/chromium/content/browser/initiator_csp_context.cc
@@ -8,8 +8,10 @@ namespace content {
InitiatorCSPContext::InitiatorCSPContext(
const std::vector<ContentSecurityPolicy>& policies,
- base::Optional<CSPSource>& self_source)
- : reporting_render_frame_host_impl_(nullptr) {
+ base::Optional<CSPSource>& self_source,
+ blink::mojom::NavigationInitiatorPtr navigation_initiator)
+ : reporting_render_frame_host_impl_(nullptr),
+ initiator_ptr(std::move(navigation_initiator)) {
for (const auto& policy : policies)
AddContentSecurityPolicy(policy);
@@ -17,6 +19,8 @@ InitiatorCSPContext::InitiatorCSPContext(
SetSelf(self_source.value());
}
+InitiatorCSPContext::~InitiatorCSPContext() {}
+
void InitiatorCSPContext::SetReportingRenderFrameHost(
RenderFrameHostImpl* rfh) {
reporting_render_frame_host_impl_ = rfh;
@@ -24,9 +28,19 @@ void InitiatorCSPContext::SetReportingRenderFrameHost(
void InitiatorCSPContext::ReportContentSecurityPolicyViolation(
const CSPViolationParams& violation_params) {
- if (reporting_render_frame_host_impl_) {
- reporting_render_frame_host_impl_->ReportContentSecurityPolicyViolation(
- violation_params);
+ if (initiator_ptr.is_bound()) {
+ initiator_ptr->SendViolationReport(blink::mojom::CSPViolationParams::New(
+ violation_params.directive, violation_params.effective_directive,
+ violation_params.console_message, violation_params.blocked_url.spec(),
+ violation_params.report_endpoints, violation_params.use_reporting_api,
+ violation_params.header,
+ (blink::mojom::WebContentSecurityPolicyType)
+ violation_params.disposition,
+ violation_params.after_redirect,
+ blink::mojom::SourceLocation::New(
+ violation_params.source_location.url,
+ violation_params.source_location.column_number,
+ violation_params.source_location.line_number)));
}
}
diff --git a/chromium/content/browser/initiator_csp_context.h b/chromium/content/browser/initiator_csp_context.h
index e370eee3b60..097e228b9aa 100644
--- a/chromium/content/browser/initiator_csp_context.h
+++ b/chromium/content/browser/initiator_csp_context.h
@@ -20,8 +20,11 @@ namespace content {
// `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);
+ InitiatorCSPContext(
+ const std::vector<ContentSecurityPolicy>& policies,
+ base::Optional<CSPSource>& self_source,
+ blink::mojom::NavigationInitiatorPtr navigation_initiator);
+ ~InitiatorCSPContext() override;
void ReportContentSecurityPolicyViolation(
const CSPViolationParams& violation_params) override;
@@ -35,6 +38,9 @@ class InitiatorCSPContext : public CSPContext {
private:
RenderFrameHostImpl* reporting_render_frame_host_impl_;
+ blink::mojom::NavigationInitiatorPtr initiator_ptr;
+
+ DISALLOW_COPY_AND_ASSIGN(InitiatorCSPContext);
};
} // namespace content
diff --git a/chromium/content/browser/interface_provider_filtering.cc b/chromium/content/browser/interface_provider_filtering.cc
index 239566b6f1f..2642276f488 100644
--- a/chromium/content/browser/interface_provider_filtering.cc
+++ b/chromium/content/browser/interface_provider_filtering.cc
@@ -6,7 +6,9 @@
#include <utility>
+#include "base/task/post_task.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
#include "services/service_manager/public/cpp/connector.h"
@@ -48,8 +50,8 @@ FilterRendererExposedInterfaces(
service_manager::mojom::InterfaceProviderPtr provider;
auto filtered_request = mojo::MakeRequest(&provider);
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&FilterInterfacesImpl, spec, process_id,
std::move(request), std::move(provider)));
} else {
diff --git a/chromium/content/browser/isolated_origin_browsertest.cc b/chromium/content/browser/isolated_origin_browsertest.cc
index 7c0f014d404..20c7c4f3455 100644
--- a/chromium/content/browser/isolated_origin_browsertest.cc
+++ b/chromium/content/browser/isolated_origin_browsertest.cc
@@ -1115,6 +1115,42 @@ IN_PROC_BROWSER_TEST_F(IsolatedOriginFieldTrialTest, Test) {
policy->IsIsolatedOrigin(url::Origin::Create(GURL("https://bar.com/"))));
}
+class IsolatedOriginCommandLineAndFieldTrialTest
+ : public IsolatedOriginFieldTrialTest {
+ public:
+ IsolatedOriginCommandLineAndFieldTrialTest() = default;
+
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ command_line->AppendSwitchASCII(
+ switches::kIsolateOrigins,
+ "https://cmd.line.com/,https://cmdline.com/");
+ }
+
+ DISALLOW_COPY_AND_ASSIGN(IsolatedOriginCommandLineAndFieldTrialTest);
+};
+
+// Verify that the lists of isolated origins specified via --isolate-origins
+// and via field trials are merged. See https://crbug.com/894535.
+IN_PROC_BROWSER_TEST_F(IsolatedOriginCommandLineAndFieldTrialTest, Test) {
+ auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
+ // --isolate-origins should take effect regardless of the
+ // kDisableSiteIsolationTrials opt-out flag.
+ EXPECT_TRUE(policy->IsIsolatedOrigin(
+ url::Origin::Create(GURL("https://cmd.line.com/"))));
+ EXPECT_TRUE(policy->IsIsolatedOrigin(
+ url::Origin::Create(GURL("https://cmdline.com/"))));
+
+ // Field trial origins should also take effect, but only if the opt-out flag
+ // is not present.
+ bool expected_to_isolate = !base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableSiteIsolationTrials);
+ EXPECT_EQ(expected_to_isolate, policy->IsIsolatedOrigin(url::Origin::Create(
+ GURL("https://field.trial.com/"))));
+ EXPECT_EQ(
+ expected_to_isolate,
+ policy->IsIsolatedOrigin(url::Origin::Create(GURL("https://bar.com/"))));
+}
+
// This is a regresion test for https://crbug.com/793350 - the long list of
// origins to isolate used to be unnecessarily propagated to the renderer
// process, trigerring a crash due to exceeding kZygoteMaxMessageLength.
diff --git a/chromium/content/browser/isolated_origin_util.cc b/chromium/content/browser/isolated_origin_util.cc
index fe25348a652..9086edb778a 100644
--- a/chromium/content/browser/isolated_origin_util.cc
+++ b/chromium/content/browser/isolated_origin_util.cc
@@ -31,7 +31,7 @@ bool IsolatedOriginUtil::DoesOriginMatchIsolatedOrigin(
// static
bool IsolatedOriginUtil::IsValidIsolatedOrigin(const url::Origin& origin) {
- if (origin.unique())
+ if (origin.opaque())
return false;
// Isolated origins should have HTTP or HTTPS schemes. Hosts in other
diff --git a/chromium/content/browser/loader/cors_file_origin_browsertest.cc b/chromium/content/browser/loader/cors_file_origin_browsertest.cc
index 2b0e7a609ba..9790099a59d 100644
--- a/chromium/content/browser/loader/cors_file_origin_browsertest.cc
+++ b/chromium/content/browser/loader/cors_file_origin_browsertest.cc
@@ -29,6 +29,7 @@
#include "services/network/public/cpp/cors/cors.h"
#include "services/network/public/cpp/features.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/features.h"
#include "url/gurl.h"
namespace content {
@@ -39,20 +40,42 @@ using net::test_server::BasicHttpResponse;
using net::test_server::HttpRequest;
using net::test_server::HttpResponse;
+enum class CorsTestMode {
+ kInBlink,
+ kInBrowserProcess,
+ kInNetworkService,
+};
+
// Tests end to end Origin header and CORS check behaviors without
// --allow-file-access-from-files flag.
-class CORSFileOriginBrowserTest : public ContentBrowserTest,
- public testing::WithParamInterface<bool> {
+class CORSFileOriginBrowserTest
+ : public ContentBrowserTest,
+ public testing::WithParamInterface<CorsTestMode> {
public:
CORSFileOriginBrowserTest()
: pass_string_(base::ASCIIToUTF16("PASS")),
fail_string_(base::ASCIIToUTF16("FAIL")) {
- if (GetParam()) {
- scoped_feature_list_.InitAndEnableFeature(
- network::features::kOutOfBlinkCORS);
- } else {
- scoped_feature_list_.InitAndDisableFeature(
- network::features::kOutOfBlinkCORS);
+ switch (GetParam()) {
+ case CorsTestMode::kInBlink:
+ scoped_feature_list_.InitWithFeatures(
+ {} /* enabled */,
+ {network::features::kOutOfBlinkCORS,
+ blink::features::kServiceWorkerServicification,
+ network::features::kNetworkService} /* disabled */);
+ break;
+ case CorsTestMode::kInBrowserProcess:
+ scoped_feature_list_.InitWithFeatures(
+ {network::features::kOutOfBlinkCORS,
+ blink::features::kServiceWorkerServicification} /* enabled */,
+ {network::features::kNetworkService} /* disabled */);
+ break;
+ case CorsTestMode::kInNetworkService:
+ scoped_feature_list_.InitWithFeatures(
+ {network::features::kOutOfBlinkCORS,
+ blink::features::kServiceWorkerServicification,
+ network::features::kNetworkService} /* enabled */,
+ {} /*disabled */);
+ break;
}
}
~CORSFileOriginBrowserTest() override = default;
@@ -77,11 +100,19 @@ class CORSFileOriginBrowserTest : public ContentBrowserTest,
// Does not appear in the expectations, but the title can be on unexpected
// failures.
base::string16 wrong_origin_string =
- base::ASCIIToUTF16("FAIL: request origin does not match");
+ base::ASCIIToUTF16("FAIL: response text does not match");
watcher->AlsoWaitForTitle(wrong_origin_string);
return watcher;
}
+ std::string target_http_url() {
+ return base::StringPrintf("http://127.0.0.1:%d/test", port());
+ }
+ std::string target_file_url() const { return "get.txt"; }
+ std::string target_self_file_url() const {
+ return "cors_file_origin_test.html";
+ }
+
const base::string16& pass_string() const { return pass_string_; }
const base::string16& fail_string() const { return fail_string_; }
@@ -195,9 +226,10 @@ IN_PROC_BROWSER_TEST_P(CORSFileOriginBrowserTest,
AccessControlAllowOriginIsNull) {
std::unique_ptr<TitleWatcher> watcher = CreateWatcher();
EXPECT_TRUE(NavigateToURL(
- shell(), CreateTestDataURL(base::StringPrintf(
- "cors_file_origin_test.html?port=%d&allow=%s&origin=%s",
- port(), "null", "null"))));
+ shell(),
+ CreateTestDataURL(base::StringPrintf(
+ "cors_file_origin_test.html?url=%s&allow=%s&response_text=%s",
+ target_http_url().c_str(), "null", "null"))));
EXPECT_EQ(pass_string(), watcher->WaitAndGetTitle());
EXPECT_TRUE(is_preflight_requested());
@@ -207,21 +239,45 @@ IN_PROC_BROWSER_TEST_P(CORSFileOriginBrowserTest,
AccessControlAllowOriginIsFile) {
std::unique_ptr<TitleWatcher> watcher = CreateWatcher();
EXPECT_TRUE(NavigateToURL(
- shell(), CreateTestDataURL(base::StringPrintf(
- "cors_file_origin_test.html?port=%d&allow=%s&origin=%s",
- port(), "file://", "null"))));
+ shell(),
+ CreateTestDataURL(base::StringPrintf(
+ "cors_file_origin_test.html?url=%s&allow=%s&response_text=%s",
+ target_http_url().c_str(), "file://", "null"))));
EXPECT_EQ(fail_string(), watcher->WaitAndGetTitle());
EXPECT_TRUE(is_preflight_requested());
}
+IN_PROC_BROWSER_TEST_P(CORSFileOriginBrowserTest, AccessToSelfFileUrl) {
+ std::unique_ptr<TitleWatcher> watcher = CreateWatcher();
+ EXPECT_TRUE(NavigateToURL(
+ shell(),
+ CreateTestDataURL(base::StringPrintf(
+ "cors_file_origin_test.html?url=%s&allow=%s&response_text=%s",
+ target_self_file_url().c_str(), "unused", "unused"))));
+
+ EXPECT_EQ(fail_string(), watcher->WaitAndGetTitle());
+}
+
+IN_PROC_BROWSER_TEST_P(CORSFileOriginBrowserTest, AccessToAnotherFileUrl) {
+ std::unique_ptr<TitleWatcher> watcher = CreateWatcher();
+ EXPECT_TRUE(NavigateToURL(
+ shell(),
+ CreateTestDataURL(base::StringPrintf(
+ "cors_file_origin_test.html?url=%s&allow=%s&response_text=%s",
+ target_file_url().c_str(), "unused", "unused"))));
+
+ EXPECT_EQ(fail_string(), watcher->WaitAndGetTitle());
+}
+
IN_PROC_BROWSER_TEST_P(CORSFileOriginBrowserTestWithAllowFileAccessFromFiles,
AccessControlAllowOriginIsNull) {
std::unique_ptr<TitleWatcher> watcher = CreateWatcher();
EXPECT_TRUE(NavigateToURL(
- shell(), CreateTestDataURL(base::StringPrintf(
- "cors_file_origin_test.html?port=%d&allow=%s&origin=%s",
- port(), "null", "file://"))));
+ shell(),
+ CreateTestDataURL(base::StringPrintf(
+ "cors_file_origin_test.html?url=%s&allow=%s&response_text=%s",
+ target_http_url().c_str(), "null", "file://"))));
EXPECT_EQ(fail_string(), watcher->WaitAndGetTitle());
EXPECT_TRUE(is_preflight_requested());
@@ -231,21 +287,47 @@ IN_PROC_BROWSER_TEST_P(CORSFileOriginBrowserTestWithAllowFileAccessFromFiles,
AccessControlAllowOriginIsFile) {
std::unique_ptr<TitleWatcher> watcher = CreateWatcher();
EXPECT_TRUE(NavigateToURL(
- shell(), CreateTestDataURL(base::StringPrintf(
- "cors_file_origin_test.html?port=%d&allow=%s&origin=%s",
- port(), "file://", "file://"))));
+ shell(),
+ CreateTestDataURL(base::StringPrintf(
+ "cors_file_origin_test.html?url=%s&allow=%s&response_text=%s",
+ target_http_url().c_str(), "file://", "file://"))));
EXPECT_EQ(pass_string(), watcher->WaitAndGetTitle());
EXPECT_TRUE(is_preflight_requested());
}
+IN_PROC_BROWSER_TEST_P(CORSFileOriginBrowserTestWithAllowFileAccessFromFiles,
+ AccessToSelfFileUrl) {
+ std::unique_ptr<TitleWatcher> watcher = CreateWatcher();
+ EXPECT_TRUE(NavigateToURL(
+ shell(),
+ CreateTestDataURL(base::StringPrintf(
+ "cors_file_origin_test.html?url=%s&allow=%s&response_text=%s",
+ target_self_file_url().c_str(), "unused", "unused"))));
+
+ EXPECT_EQ(pass_string(), watcher->WaitAndGetTitle());
+}
+
+IN_PROC_BROWSER_TEST_P(CORSFileOriginBrowserTestWithAllowFileAccessFromFiles,
+ AccessToAnotherFileUrl) {
+ std::unique_ptr<TitleWatcher> watcher = CreateWatcher();
+ EXPECT_TRUE(NavigateToURL(
+ shell(),
+ CreateTestDataURL(base::StringPrintf(
+ "cors_file_origin_test.html?url=%s&allow=%s&response_text=%s",
+ target_file_url().c_str(), "unused", "unused"))));
+
+ EXPECT_EQ(pass_string(), watcher->WaitAndGetTitle());
+}
+
IN_PROC_BROWSER_TEST_P(CORSFileOriginBrowserTestWithDisableWebSecurity,
AccessControlAllowOriginIsNull) {
std::unique_ptr<TitleWatcher> watcher = CreateWatcher();
EXPECT_TRUE(NavigateToURL(
- shell(), CreateTestDataURL(base::StringPrintf(
- "cors_file_origin_test.html?port=%d&allow=%s&origin=%s",
- port(), "unused", ""))));
+ shell(),
+ CreateTestDataURL(base::StringPrintf(
+ "cors_file_origin_test.html?url=%s&allow=%s&response_text=%s",
+ target_http_url().c_str(), "unused", ""))));
EXPECT_EQ(pass_string(), watcher->WaitAndGetTitle());
EXPECT_FALSE(is_preflight_requested());
@@ -255,30 +337,59 @@ IN_PROC_BROWSER_TEST_P(CORSFileOriginBrowserTestWithDisableWebSecurity,
AccessControlAllowOriginIsFile) {
std::unique_ptr<TitleWatcher> watcher = CreateWatcher();
EXPECT_TRUE(NavigateToURL(
- shell(), CreateTestDataURL(base::StringPrintf(
- "cors_file_origin_test.html?port=%d&allow=%s&origin=%s",
- port(), "unused", ""))));
+ shell(),
+ CreateTestDataURL(base::StringPrintf(
+ "cors_file_origin_test.html?url=%s&allow=%s&response_text=%s",
+ target_http_url().c_str(), "unused", ""))));
EXPECT_EQ(pass_string(), watcher->WaitAndGetTitle());
EXPECT_FALSE(is_preflight_requested());
}
-// --allow-file-access-from-files is currently not supported by OOR-CORS.
-// We may remove the feature.
+IN_PROC_BROWSER_TEST_P(CORSFileOriginBrowserTestWithDisableWebSecurity,
+ AccessToSelfFileUrl) {
+ std::unique_ptr<TitleWatcher> watcher = CreateWatcher();
+ EXPECT_TRUE(NavigateToURL(
+ shell(),
+ CreateTestDataURL(base::StringPrintf(
+ "cors_file_origin_test.html?url=%s&allow=%s&response_text=%s",
+ target_self_file_url().c_str(), "unused", "unused"))));
+
+ EXPECT_EQ(pass_string(), watcher->WaitAndGetTitle());
+}
+
+IN_PROC_BROWSER_TEST_P(CORSFileOriginBrowserTestWithDisableWebSecurity,
+ AccessToAnotherFileUrl) {
+ std::unique_ptr<TitleWatcher> watcher = CreateWatcher();
+ EXPECT_TRUE(NavigateToURL(
+ shell(),
+ CreateTestDataURL(base::StringPrintf(
+ "cors_file_origin_test.html?url=%s&allow=%s&response_text=%s",
+ target_file_url().c_str(), "unused", "unused"))));
+
+ EXPECT_EQ(pass_string(), watcher->WaitAndGetTitle());
+}
+
INSTANTIATE_TEST_CASE_P(
/* No test prefix */,
CORSFileOriginBrowserTest,
- ::testing::Values(false));
+ ::testing::Values(CorsTestMode::kInBlink,
+ CorsTestMode::kInBrowserProcess,
+ CorsTestMode::kInNetworkService));
INSTANTIATE_TEST_CASE_P(
/* No test prefix */,
CORSFileOriginBrowserTestWithAllowFileAccessFromFiles,
- ::testing::Values(false));
+ ::testing::Values(CorsTestMode::kInBlink,
+ CorsTestMode::kInBrowserProcess,
+ CorsTestMode::kInNetworkService));
INSTANTIATE_TEST_CASE_P(
/* No test prefix */,
CORSFileOriginBrowserTestWithDisableWebSecurity,
- ::testing::Values(false, true));
+ ::testing::Values(CorsTestMode::kInBlink,
+ CorsTestMode::kInBrowserProcess,
+ CorsTestMode::kInNetworkService));
} // namespace
diff --git a/chromium/content/browser/loader/cors_origin_access_list_browsertest.cc b/chromium/content/browser/loader/cors_origin_access_list_browsertest.cc
new file mode 100644
index 00000000000..8f32876deb5
--- /dev/null
+++ b/chromium/content/browser/loader/cors_origin_access_list_browsertest.cc
@@ -0,0 +1,285 @@
+// 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/file_path.h"
+#include "base/macros.h"
+#include "base/path_service.h"
+#include "base/run_loop.h"
+#include "base/strings/string16.h"
+#include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/test/scoped_feature_list.h"
+#include "content/public/browser/browser_context.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/shell/browser/shell.h"
+#include "net/base/host_port_pair.h"
+#include "net/dns/mock_host_resolver.h"
+#include "services/network/public/cpp/features.h"
+#include "services/network/public/mojom/cors.mojom.h"
+#include "services/network/public/mojom/cors_origin_pattern.mojom.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/features.h"
+#include "url/gurl.h"
+#include "url/origin.h"
+
+namespace content {
+
+namespace {
+
+const char kTestPath[] = "/loader/cors_origin_access_list_test.html";
+
+const char kTestHost[] = "crossorigin.example.com";
+const char kTestHostInDifferentCase[] = "CrossOrigin.example.com";
+const char kTestSubdomainHost[] = "subdomain.crossorigin.example.com";
+
+enum class TestMode {
+ kOutOfBlinkCorsWithServicification,
+ kOutOfBlinkCorsWithoutServicification,
+};
+
+// Tests end to end functionality of CORS access origin allow lists.
+class CorsOriginAccessListBrowserTest
+ : public ContentBrowserTest,
+ public testing::WithParamInterface<TestMode> {
+ public:
+ CorsOriginAccessListBrowserTest() {
+ switch (GetParam()) {
+ case TestMode::kOutOfBlinkCorsWithServicification:
+ scoped_feature_list_.InitWithFeatures(
+ // Enabled features
+ {network::features::kOutOfBlinkCORS,
+ network::features::kNetworkService,
+ blink::features::kServiceWorkerServicification},
+ // Disabled features
+ {});
+ break;
+ case TestMode::kOutOfBlinkCorsWithoutServicification:
+ scoped_feature_list_.InitWithFeatures(
+ // Enabled features
+ {network::features::kOutOfBlinkCORS},
+ // Disabled features
+ {network::features::kNetworkService,
+ blink::features::kServiceWorkerServicification});
+ break;
+ }
+ }
+
+ protected:
+ std::unique_ptr<TitleWatcher> CreateWatcher() {
+ // Register all possible result strings here.
+ std::unique_ptr<TitleWatcher> watcher =
+ std::make_unique<TitleWatcher>(shell()->web_contents(), pass_string());
+ watcher->AlsoWaitForTitle(fail_string());
+ return watcher;
+ }
+
+ std::string GetReason() {
+ bool executing = true;
+ std::string reason;
+ shell()->web_contents()->GetMainFrame()->ExecuteJavaScriptForTests(
+ script_,
+ base::BindRepeating(
+ [](bool* flag, std::string* reason, const base::Value* value) {
+ *flag = false;
+ DCHECK(value);
+ DCHECK(value->is_string());
+ *reason = value->GetString();
+ },
+ base::Unretained(&executing), base::Unretained(&reason)));
+ while (executing) {
+ base::RunLoop loop;
+ loop.RunUntilIdle();
+ }
+ return reason;
+ }
+
+ void SetAllowList(const std::string& scheme,
+ const std::string& host,
+ bool allow_subdomains) {
+ std::vector<network::mojom::CorsOriginPatternPtr> list1;
+ list1.push_back(network::mojom::CorsOriginPattern::New(
+ scheme, host, allow_subdomains,
+ network::mojom::CORSOriginAccessMatchPriority::kDefaultPriority));
+ bool first_list_done = false;
+ BrowserContext::SetCorsOriginAccessListsForOrigin(
+ shell()->web_contents()->GetBrowserContext(),
+ url::Origin::Create(embedded_test_server()->base_url().GetOrigin()),
+ std::move(list1), std::vector<network::mojom::CorsOriginPatternPtr>(),
+ base::BindOnce([](bool* flag) { *flag = true; },
+ base::Unretained(&first_list_done)));
+
+ std::vector<network::mojom::CorsOriginPatternPtr> list2;
+ list2.push_back(network::mojom::CorsOriginPattern::New(
+ scheme, host, allow_subdomains,
+ network::mojom::CORSOriginAccessMatchPriority::kDefaultPriority));
+ bool second_list_done = false;
+ BrowserContext::SetCorsOriginAccessListsForOrigin(
+ shell()->web_contents()->GetBrowserContext(),
+ url::Origin::Create(
+ embedded_test_server()->GetURL(kTestHost, "/").GetOrigin()),
+ std::move(list2), std::vector<network::mojom::CorsOriginPatternPtr>(),
+ base::BindOnce([](bool* flag) { *flag = true; },
+ base::Unretained(&second_list_done)));
+ while (!first_list_done || !second_list_done) {
+ base::RunLoop run_loop;
+ run_loop.RunUntilIdle();
+ }
+ }
+
+ std::string host_ip() { return embedded_test_server()->base_url().host(); }
+
+ const base::string16& pass_string() const { return pass_string_; }
+ const base::string16& fail_string() const { return fail_string_; }
+
+ private:
+ void SetUpOnMainThread() override {
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ // Setup to resolve kTestHost, kTestHostInDifferentCase and
+ // kTestSubdomainHost to the 127.0.0.1 that the test server serves.
+ host_resolver()->AddRule(kTestHost,
+ embedded_test_server()->host_port_pair().host());
+ host_resolver()->AddRule(kTestHostInDifferentCase,
+ embedded_test_server()->host_port_pair().host());
+ host_resolver()->AddRule(kTestSubdomainHost,
+ embedded_test_server()->host_port_pair().host());
+ }
+
+ const base::string16 pass_string_ = base::ASCIIToUTF16("PASS");
+ const base::string16 fail_string_ = base::ASCIIToUTF16("FAIL");
+ const base::string16 script_ = base::ASCIIToUTF16("reason");
+
+ base::test::ScopedFeatureList scoped_feature_list_;
+
+ DISALLOW_COPY_AND_ASSIGN(CorsOriginAccessListBrowserTest);
+};
+
+// Tests if specifying only protocol allows all hosts to pass.
+IN_PROC_BROWSER_TEST_P(CorsOriginAccessListBrowserTest, AllowAll) {
+ SetAllowList("http", "", true);
+
+ std::unique_ptr<TitleWatcher> watcher = CreateWatcher();
+ EXPECT_TRUE(
+ NavigateToURL(shell(), embedded_test_server()->GetURL(base::StringPrintf(
+ "%s?target=%s", kTestPath, kTestHost))));
+ EXPECT_EQ(pass_string(), watcher->WaitAndGetTitle()) << GetReason();
+}
+
+// Tests if specifying only protocol allows all IP address based hosts to pass.
+IN_PROC_BROWSER_TEST_P(CorsOriginAccessListBrowserTest, AllowAllForIp) {
+ SetAllowList("http", "", true);
+
+ std::unique_ptr<TitleWatcher> watcher = CreateWatcher();
+ EXPECT_TRUE(NavigateToURL(
+ shell(), embedded_test_server()->GetURL(
+ kTestHost, base::StringPrintf("%s?target=%s", kTestPath,
+ host_ip().c_str()))));
+ EXPECT_EQ(pass_string(), watcher->WaitAndGetTitle()) << GetReason();
+}
+
+// Tests if complete allow list set allows only exactly matched host to pass.
+IN_PROC_BROWSER_TEST_P(CorsOriginAccessListBrowserTest, AllowExactHost) {
+ SetAllowList("http", kTestHost, false);
+
+ std::unique_ptr<TitleWatcher> watcher = CreateWatcher();
+ EXPECT_TRUE(
+ NavigateToURL(shell(), embedded_test_server()->GetURL(base::StringPrintf(
+ "%s?target=%s", kTestPath, kTestHost))));
+ EXPECT_EQ(pass_string(), watcher->WaitAndGetTitle()) << GetReason();
+}
+
+// Tests if complete allow list set allows host that matches exactly, but in
+// case insensitive way to pass.
+IN_PROC_BROWSER_TEST_P(CorsOriginAccessListBrowserTest,
+ AllowExactHostInCaseInsensitive) {
+ SetAllowList("http", kTestHost, false);
+
+ std::unique_ptr<TitleWatcher> watcher = CreateWatcher();
+ EXPECT_TRUE(NavigateToURL(
+ shell(), embedded_test_server()->GetURL(base::StringPrintf(
+ "%s?target=%s", kTestPath, kTestHostInDifferentCase))));
+ EXPECT_EQ(pass_string(), watcher->WaitAndGetTitle()) << GetReason();
+}
+
+// Tests if complete allow list set does not allow a host with a different port
+// to pass.
+IN_PROC_BROWSER_TEST_P(CorsOriginAccessListBrowserTest, BlockDifferentPort) {
+ SetAllowList("http", kTestHost, false);
+
+ std::unique_ptr<TitleWatcher> watcher = CreateWatcher();
+ EXPECT_TRUE(NavigateToURL(
+ shell(), embedded_test_server()->GetURL(base::StringPrintf(
+ "%s?target=%s&port_diff=1", kTestPath, kTestHost))));
+ EXPECT_EQ(fail_string(), watcher->WaitAndGetTitle()) << GetReason();
+}
+
+// Tests if complete allow list set allows a subdomain to pass if it is allowed.
+IN_PROC_BROWSER_TEST_P(CorsOriginAccessListBrowserTest, AllowSubdomain) {
+ SetAllowList("http", kTestHost, true);
+
+ std::unique_ptr<TitleWatcher> watcher = CreateWatcher();
+ EXPECT_TRUE(NavigateToURL(
+ shell(), embedded_test_server()->GetURL(base::StringPrintf(
+ "%s?target=%s", kTestPath, kTestSubdomainHost))));
+ EXPECT_EQ(pass_string(), watcher->WaitAndGetTitle()) << GetReason();
+}
+
+// Tests if complete allow list set does not allow a subdomain to pass.
+IN_PROC_BROWSER_TEST_P(CorsOriginAccessListBrowserTest, BlockSubdomain) {
+ SetAllowList("http", kTestHost, false);
+
+ std::unique_ptr<TitleWatcher> watcher = CreateWatcher();
+ EXPECT_TRUE(NavigateToURL(
+ shell(), embedded_test_server()->GetURL(base::StringPrintf(
+ "%s?target=%s", kTestPath, kTestSubdomainHost))));
+ EXPECT_EQ(fail_string(), watcher->WaitAndGetTitle()) << GetReason();
+}
+
+// Tests if complete allow list set does not allow a host with a different
+// protocol to pass.
+IN_PROC_BROWSER_TEST_P(CorsOriginAccessListBrowserTest,
+ BlockDifferentProtocol) {
+ SetAllowList("https", kTestHost, false);
+
+ std::unique_ptr<TitleWatcher> watcher = CreateWatcher();
+ EXPECT_TRUE(
+ NavigateToURL(shell(), embedded_test_server()->GetURL(base::StringPrintf(
+ "%s?target=%s", kTestPath, kTestHost))));
+ EXPECT_EQ(fail_string(), watcher->WaitAndGetTitle()) << GetReason();
+}
+
+// Tests if IP address based hosts should not follow subdomain match rules.
+IN_PROC_BROWSER_TEST_P(CorsOriginAccessListBrowserTest,
+ SubdomainMatchShouldNotBeAppliedForIPAddress) {
+ SetAllowList("http", "*.0.0.1", true);
+
+ std::unique_ptr<TitleWatcher> watcher = CreateWatcher();
+ EXPECT_TRUE(NavigateToURL(
+ shell(), embedded_test_server()->GetURL(
+ kTestHost, base::StringPrintf("%s?target=%s", kTestPath,
+ host_ip().c_str()))));
+ EXPECT_EQ(fail_string(), watcher->WaitAndGetTitle()) << GetReason();
+}
+
+INSTANTIATE_TEST_CASE_P(
+ OutOfBlinkCorsWithServicification,
+ CorsOriginAccessListBrowserTest,
+ ::testing::Values(TestMode::kOutOfBlinkCorsWithServicification));
+
+INSTANTIATE_TEST_CASE_P(
+ OutOfBlinkCorsWithoutServicification,
+ CorsOriginAccessListBrowserTest,
+ ::testing::Values(TestMode::kOutOfBlinkCorsWithoutServicification));
+
+// TODO(toyoshim): Instantiates tests for the case kOutOfBlinkCORS is disabled
+// and remove relevant LayoutTests if it's possible.
+
+} // namespace
+
+} // namespace content
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 fa11009de25..b811e6d9f86 100644
--- a/chromium/content/browser/loader/cross_site_document_blocking_browsertest.cc
+++ b/chromium/content/browser/loader/cross_site_document_blocking_browsertest.cc
@@ -12,10 +12,12 @@
#include "base/strings/pattern.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
+#include "base/task/post_task.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "content/browser/loader/cross_site_document_resource_handler.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/render_view_host.h"
@@ -217,8 +219,8 @@ class RequestInterceptor {
// Wait until IO cleanup completes.
base::RunLoop run_loop;
- BrowserThread::PostTaskAndReply(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraitsAndReply(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&RequestInterceptor::CleanUpOnIOThread,
base::Unretained(this)),
run_loop.QuitClosure());
@@ -330,10 +332,10 @@ class DisableWebSecurityContentBrowserClient : public TestContentBrowserClient {
// Note that this BaseTest class does not specify an isolation mode via
// command-line flags. Most of the tests are in the --site-per-process subclass
// below.
-class CrossSiteDocumentBlockingTest : public ContentBrowserTest {
+class CrossSiteDocumentBlockingTestBase : public ContentBrowserTest {
public:
- CrossSiteDocumentBlockingTest() {}
- ~CrossSiteDocumentBlockingTest() override {}
+ CrossSiteDocumentBlockingTestBase() = default;
+ ~CrossSiteDocumentBlockingTestBase() override = default;
void SetUpCommandLine(base::CommandLine* command_line) override {
// EmbeddedTestServer::InitializeAndListen() initializes its |base_url_|
@@ -367,10 +369,38 @@ class CrossSiteDocumentBlockingTest : public ContentBrowserTest {
DisableWebSecurityContentBrowserClient new_client;
ContentBrowserClient* old_client = nullptr;
+ DISALLOW_COPY_AND_ASSIGN(CrossSiteDocumentBlockingTestBase);
+};
+
+enum class TestMode {
+ kWithoutOutOfBlinkCors,
+ kWithOutOfBlinkCors,
+};
+class CrossSiteDocumentBlockingTest
+ : public CrossSiteDocumentBlockingTestBase,
+ public testing::WithParamInterface<TestMode> {
+ public:
+ CrossSiteDocumentBlockingTest() {
+ switch (GetParam()) {
+ case TestMode::kWithoutOutOfBlinkCors:
+ scoped_feature_list_.InitAndDisableFeature(
+ network::features::kOutOfBlinkCORS);
+ break;
+ case TestMode::kWithOutOfBlinkCors:
+ scoped_feature_list_.InitAndEnableFeature(
+ network::features::kOutOfBlinkCORS);
+ break;
+ }
+ }
+ ~CrossSiteDocumentBlockingTest() override = default;
+
+ private:
+ base::test::ScopedFeatureList scoped_feature_list_;
+
DISALLOW_COPY_AND_ASSIGN(CrossSiteDocumentBlockingTest);
};
-IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingTest, BlockDocuments) {
+IN_PROC_BROWSER_TEST_P(CrossSiteDocumentBlockingTest, BlockDocuments) {
// Load a page that issues illegal cross-site document requests to bar.com.
// The page uses XHR to request HTML/XML/JSON documents from bar.com, and
// inspects if any of them were successfully received. This test is only
@@ -378,6 +408,15 @@ IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingTest, BlockDocuments) {
// it to see the response body if it makes it to the renderer (even if the
// renderer would normally block access to it).
embedded_test_server()->StartAcceptingConnections();
+
+ // This test does not work and won't make much sense if kOutOfBlinkCORS is
+ // enabled. We need to rewrite this test once the feature is shipped. We would
+ // like to add other tests for verifying behavior for fetch mode "no-cors".
+ // See crbug.com/736308, and discussion at http://crrev.com/c/1253623.
+ // The test server should be started before to shutdown tests safely.
+ if (base::FeatureList::IsEnabled(network::features::kOutOfBlinkCORS))
+ return;
+
GURL foo_url("http://foo.com/cross_site_document_blocking/request.html");
EXPECT_TRUE(NavigateToURL(shell(), foo_url));
@@ -492,8 +531,14 @@ IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingTest, BlockDocuments) {
// can't cause sniffing to fail to force a response to be allowed. This won't
// be a problem for script files mislabeled as HTML/XML/JSON/text (i.e., the
// reason for sniffing), since script tags won't send Range headers.
-IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingTest, RangeRequest) {
+IN_PROC_BROWSER_TEST_P(CrossSiteDocumentBlockingTest, RangeRequest) {
embedded_test_server()->StartAcceptingConnections();
+
+ // This test does not work and won't make much sense if kOutOfBlinkCORS is
+ // enabled. See detailed comments on BlockDocuments above.
+ if (base::FeatureList::IsEnabled(network::features::kOutOfBlinkCORS))
+ return;
+
GURL foo_url("http://foo.com/cross_site_document_blocking/request.html");
EXPECT_TRUE(NavigateToURL(shell(), foo_url));
@@ -534,7 +579,7 @@ IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingTest, RangeRequest) {
}
}
-IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingTest, BlockForVariousTargets) {
+IN_PROC_BROWSER_TEST_P(CrossSiteDocumentBlockingTest, BlockForVariousTargets) {
// This webpage loads a cross-site HTML page in different targets such as
// <img>,<link>,<embed>, etc. Since the requested document is blocked, and one
// character string (' ') is returned instead, this tests that the renderer
@@ -554,7 +599,7 @@ IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingTest, BlockForVariousTargets) {
// Checks to see that CORB blocking applies to processes hosting error pages.
// Regression test for https://crbug.com/814913.
-IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingTest,
+IN_PROC_BROWSER_TEST_P(CrossSiteDocumentBlockingTest,
BlockRequestFromErrorPage) {
embedded_test_server()->StartAcceptingConnections();
GURL error_url = embedded_test_server()->GetURL("bar.com", "/close-socket");
@@ -586,9 +631,14 @@ IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingTest,
EXPECT_EQ("CORB WORKED", result);
}
-IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingTest, BlockHeaders) {
+IN_PROC_BROWSER_TEST_P(CrossSiteDocumentBlockingTest, BlockHeaders) {
embedded_test_server()->StartAcceptingConnections();
+ // This test does not work and won't make much sense if kOutOfBlinkCORS is
+ // enabled. See detailed comments on BlockDocuments above.
+ if (base::FeatureList::IsEnabled(network::features::kOutOfBlinkCORS))
+ return;
+
// Prepare to intercept the network request at the IPC layer.
// This has to be done before the RenderFrameHostImpl is created.
//
@@ -637,7 +687,7 @@ IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingTest, BlockHeaders) {
EXPECT_EQ(0u, interceptor.response_head().content_length);
}
-IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingTest, PrefetchIsNotImpacted) {
+IN_PROC_BROWSER_TEST_P(CrossSiteDocumentBlockingTest, PrefetchIsNotImpacted) {
// Prepare for intercepting the resource request for testing prefetching.
const char* kPrefetchResourcePath = "/prefetch-test";
net::test_server::ControllableHttpResponse response(embedded_test_server(),
@@ -744,6 +794,14 @@ IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingTest, PrefetchIsNotImpacted) {
EXPECT_EQ("<p>contents of the response</p>", response_body);
}
+INSTANTIATE_TEST_CASE_P(WithoutOutOfBlinkCors,
+ CrossSiteDocumentBlockingTest,
+ ::testing::Values(TestMode::kWithoutOutOfBlinkCors));
+
+INSTANTIATE_TEST_CASE_P(WithOutOfBlinkCors,
+ CrossSiteDocumentBlockingTest,
+ ::testing::Values(TestMode::kWithOutOfBlinkCors));
+
// This test class sets up a service worker that can be used to try to respond
// to same-origin requests with cross-origin responses.
class CrossSiteDocumentBlockingServiceWorkerTest : public ContentBrowserTest {
@@ -934,51 +992,17 @@ IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingServiceWorkerTest,
EXPECT_EQ("error: TypeError: Failed to fetch", response);
}
-class CrossSiteDocumentBlockingKillSwitchTest
- : public CrossSiteDocumentBlockingTest {
- public:
- CrossSiteDocumentBlockingKillSwitchTest() {
- // 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 {}
-
- private:
- base::test::ScopedFeatureList scoped_feature_list_;
-
- DISALLOW_COPY_AND_ASSIGN(CrossSiteDocumentBlockingKillSwitchTest);
-};
-
-// After the kill switch is flipped, there should be no document blocking.
-IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingKillSwitchTest,
- NoBlockingWithKillSwitch) {
- // Load a page that issues illegal cross-site document requests to bar.com.
- embedded_test_server()->StartAcceptingConnections();
- GURL foo_url("http://foo.com/cross_site_document_blocking/request.html");
- EXPECT_TRUE(NavigateToURL(shell(), foo_url));
-
- bool was_blocked;
- ASSERT_TRUE(ExecuteScriptAndExtractBool(
- shell(), "sendRequest(\"valid.html\");", &was_blocked));
- EXPECT_FALSE(was_blocked);
-}
-
// Test class to verify that --disable-web-security turns off CORB. This
// inherits from CrossSiteDocumentBlockingTest, so it runs in SitePerProcess.
class CrossSiteDocumentBlockingDisableWebSecurityTest
- : public CrossSiteDocumentBlockingTest {
+ : public CrossSiteDocumentBlockingTestBase {
public:
CrossSiteDocumentBlockingDisableWebSecurityTest() {}
~CrossSiteDocumentBlockingDisableWebSecurityTest() override {}
void SetUpCommandLine(base::CommandLine* command_line) override {
command_line->AppendSwitch(switches::kDisableWebSecurity);
- CrossSiteDocumentBlockingTest::SetUpCommandLine(command_line);
+ CrossSiteDocumentBlockingTestBase::SetUpCommandLine(command_line);
}
private:
@@ -998,40 +1022,9 @@ IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingDisableWebSecurityTest,
EXPECT_FALSE(was_blocked);
}
-// Test class to verify that kCrossSiteDocumentBlockingAlways does not take
-// precedence over --disable-web-security. This inherits from
-// CrossSiteDocumentBlockingTest, so it runs in SitePerProcess.
-class CrossSiteDocumentBlockingDisableVsFeatureTest
- : public CrossSiteDocumentBlockingDisableWebSecurityTest {
- public:
- CrossSiteDocumentBlockingDisableVsFeatureTest() {
- scoped_feature_list_.InitAndEnableFeature(
- features::kCrossSiteDocumentBlockingAlways);
- }
- ~CrossSiteDocumentBlockingDisableVsFeatureTest() override {}
-
- private:
- base::test::ScopedFeatureList scoped_feature_list_;
-
- DISALLOW_COPY_AND_ASSIGN(CrossSiteDocumentBlockingDisableVsFeatureTest);
-};
-
-IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingDisableVsFeatureTest,
- DisableBlocking) {
- // Load a page that issues illegal cross-site document requests.
- embedded_test_server()->StartAcceptingConnections();
- GURL foo_url("http://foo.com/cross_site_document_blocking/request.html");
- EXPECT_TRUE(NavigateToURL(shell(), foo_url));
-
- bool was_blocked;
- ASSERT_TRUE(ExecuteScriptAndExtractBool(
- shell(), "sendRequest(\"valid.html\");", &was_blocked));
- EXPECT_FALSE(was_blocked);
-}
-
// Test class to verify that documents are blocked for isolated origins as well.
class CrossSiteDocumentBlockingIsolatedOriginTest
- : public CrossSiteDocumentBlockingTest {
+ : public CrossSiteDocumentBlockingTestBase {
public:
CrossSiteDocumentBlockingIsolatedOriginTest() {}
~CrossSiteDocumentBlockingIsolatedOriginTest() override {}
@@ -1039,7 +1032,7 @@ class CrossSiteDocumentBlockingIsolatedOriginTest
void SetUpCommandLine(base::CommandLine* command_line) override {
command_line->AppendSwitchASCII(switches::kIsolateOrigins,
"http://bar.com");
- CrossSiteDocumentBlockingTest::SetUpCommandLine(command_line);
+ CrossSiteDocumentBlockingTestBase::SetUpCommandLine(command_line);
}
private:
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 585868689f6..be1724e19ee 100644
--- a/chromium/content/browser/loader/cross_site_document_resource_handler.cc
+++ b/chromium/content/browser/loader/cross_site_document_resource_handler.cc
@@ -15,18 +15,20 @@
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
+#include "base/task/post_task.h"
#include "base/trace_event/trace_event.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/loader/detachable_resource_handler.h"
#include "content/browser/loader/resource_request_info_impl.h"
#include "content/browser/site_instance_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/resource_context.h"
-#include "content/public/browser/site_isolation_policy.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_client.h"
+#include "content/public/common/content_switches.h"
#include "net/base/io_buffer.h"
#include "net/base/mime_sniffer.h"
#include "net/url_request/url_request.h"
@@ -131,8 +133,8 @@ void CrossSiteDocumentResourceHandler::LogBlockedResponse(
// time the posted task runs, the WebContents could have been closed and/or
// navigated to another URL. This is understood and acceptable - this should
// be rare enough to not matter for the collected UKM data.
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(
&CrossSiteDocumentResourceHandler::LogBlockedResponseOnUIThread,
resource_request_info->GetWebContentsGetterForRequest(),
@@ -562,8 +564,8 @@ void CrossSiteDocumentResourceHandler::OnResponseCompleted(
analyzer_->LogAllowedResponse();
if (initiator_scheme_prevented_blocking_ &&
analyzer_->ShouldReportBlockedResponse() && GetRequestInfo()) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&ContentBrowserClient::
LogInitiatorSchemeBypassingDocumentBlocking,
base::Unretained(GetContentClient()->browser()),
@@ -588,26 +590,10 @@ bool CrossSiteDocumentResourceHandler::ShouldBlockBasedOnHeaders(
if (analyzer_->ShouldAllow())
return false;
- // Check if the response's site needs to have its documents protected. By
- // default, this will usually return false.
- // TODO(creis): This check can go away once the logic here is made fully
- // backward compatible and we can enforce it always, regardless of Site
- // Isolation policy.
- switch (SiteIsolationPolicy::IsCrossSiteDocumentBlockingEnabled()) {
- case SiteIsolationPolicy::XSDB_ENABLED_UNCONDITIONALLY:
- break;
- 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;
- }
+ // --disable-web-security also disables Cross-Origin Read Blocking (CORB).
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableWebSecurity))
+ return false;
// Only block if this is a request made from a renderer process.
const ResourceRequestInfoImpl* info = GetRequestInfo();
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 e09e9a1b602..78a959f048f 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
@@ -81,7 +81,7 @@ struct TestScenario {
OriginHeader cors_request;
// Attributes of the HTTP response.
- const char* response_mime_type;
+ const char* response_content_type;
MimeType canonical_mime_type;
bool include_no_sniff_header;
bool simulate_range_response;
@@ -153,24 +153,24 @@ struct TestScenario {
}
packets += "}";
- return os << "\n description = " << scenario.description
- << "\n target_url = " << scenario.target_url
- << "\n resource_type = " << scenario.resource_type
- << "\n initiator_origin = " << scenario.initiator_origin
- << "\n cors_request = "
+ return os << "\n description = " << scenario.description
+ << "\n target_url = " << scenario.target_url
+ << "\n resource_type = " << scenario.resource_type
+ << "\n initiator_origin = " << scenario.initiator_origin
+ << "\n cors_request = "
<< (scenario.cors_request == OriginHeader::kOmit
? "OriginHeader::kOmit"
: "OriginHeader::kInclude")
- << "\n response_mime_type = " << scenario.response_mime_type
- << "\n canonical_mime_type = " << scenario.canonical_mime_type
- << "\n include_no_sniff = "
+ << "\n response_content_type = " << scenario.response_content_type
+ << "\n canonical_mime_type = " << scenario.canonical_mime_type
+ << "\n include_no_sniff = "
<< (scenario.include_no_sniff_header ? "true" : "false")
- << "\n range_response = "
+ << "\n range_response = "
<< (scenario.simulate_range_response ? "true" : "false")
- << "\n cors_response = " << cors_response
- << "\n packets = " << packets
- << "\n verdict = " << verdict
- << "\n verdict_packet = " << scenario.verdict_packet;
+ << "\n cors_response = " << cors_response
+ << "\n packets = " << packets
+ << "\n verdict = " << verdict
+ << "\n verdict_packet = " << scenario.verdict_packet;
}
// An HTML response with an HTML comment that's longer than the sniffing
@@ -207,7 +207,7 @@ const TestScenario kScenarios[] = {
RESOURCE_TYPE_XHR, // resource_type
"http://www.a.com/", // initiator_origin
OriginHeader::kOmit, // cors_request
- "text/html", // response_mime_type
+ "text/html", // response_content_type
MimeType::kInvalidMimeType, // canonical_mime_type
false, // include_no_sniff_header
false, // simulate_range_response
@@ -223,7 +223,7 @@ const TestScenario kScenarios[] = {
RESOURCE_TYPE_XHR, // resource_type
"http://www.a.com/", // initiator_origin
OriginHeader::kOmit, // cors_request
- "text/html", // response_mime_type
+ "text/html", // response_content_type
MimeType::kInvalidMimeType, // canonical_mime_type
false, // include_no_sniff_header
false, // simulate_range_response
@@ -239,7 +239,7 @@ const TestScenario kScenarios[] = {
RESOURCE_TYPE_XHR, // resource_type
"http://www.a.com/", // initiator_origin
OriginHeader::kOmit, // cors_request
- "text/json", // response_mime_type
+ "text/json", // response_content_type
MimeType::kInvalidMimeType, // canonical_mime_type
false, // include_no_sniff_header
false, // simulate_range_response
@@ -255,7 +255,7 @@ const TestScenario kScenarios[] = {
RESOURCE_TYPE_SCRIPT, // resource_type
"http://www.a.com/", // initiator_origin
OriginHeader::kOmit, // cors_request
- "application/javascript", // response_mime_type
+ "application/javascript", // response_content_type
MimeType::kOthers, // canonical_mime_type
false, // include_no_sniff_header
false, // simulate_range_response
@@ -271,7 +271,7 @@ const TestScenario kScenarios[] = {
RESOURCE_TYPE_XHR, // resource_type
"http://www.a.com/", // initiator_origin
OriginHeader::kInclude, // cors_request
- "text/html", // response_mime_type
+ "text/html", // response_content_type
MimeType::kInvalidMimeType, // canonical_mime_type
false, // include_no_sniff_header
false, // simulate_range_response
@@ -287,7 +287,7 @@ const TestScenario kScenarios[] = {
RESOURCE_TYPE_XHR, // resource_type
"http://www.a.com/", // initiator_origin
OriginHeader::kInclude, // cors_request
- "application/rss+xml", // response_mime_type
+ "application/rss+xml", // response_content_type
MimeType::kInvalidMimeType, // canonical_mime_type
false, // include_no_sniff_header
false, // simulate_range_response
@@ -303,7 +303,7 @@ const TestScenario kScenarios[] = {
RESOURCE_TYPE_XHR, // resource_type
"http://www.a.com/", // initiator_origin
OriginHeader::kInclude, // cors_request
- "text/json", // response_mime_type
+ "text/json", // response_content_type
MimeType::kInvalidMimeType, // canonical_mime_type
false, // include_no_sniff_header
false, // simulate_range_response
@@ -319,7 +319,7 @@ const TestScenario kScenarios[] = {
RESOURCE_TYPE_XHR, // resource_type
"http://www.a.com/", // initiator_origin
OriginHeader::kOmit, // cors_request
- "text/html", // response_mime_type
+ "text/html", // response_content_type
MimeType::kInvalidMimeType, // canonical_mime_type
false, // include_no_sniff_header
false, // simulate_range_response
@@ -335,7 +335,7 @@ const TestScenario kScenarios[] = {
RESOURCE_TYPE_XHR, // resource_type
"http://www.a.com/", // initiator_origin
OriginHeader::kOmit, // cors_request
- "text/html", // response_mime_type
+ "text/html", // response_content_type
MimeType::kInvalidMimeType, // canonical_mime_type
false, // include_no_sniff_header
false, // simulate_range_response
@@ -357,7 +357,7 @@ const TestScenario kScenarios[] = {
RESOURCE_TYPE_PLUGIN_RESOURCE, // resource_type
"http://www.a.com/", // initiator_origin
OriginHeader::kOmit, // cors_request
- "text/html", // response_mime_type
+ "text/html", // response_content_type
MimeType::kHtml, // canonical_mime_type
true, // include_no_sniff_header
false, // simulate_range_response
@@ -373,7 +373,7 @@ const TestScenario kScenarios[] = {
RESOURCE_TYPE_PLUGIN_RESOURCE, // resource_type
"http://www.a.com/", // initiator_origin
OriginHeader::kInclude, // cors_request
- "text/html", // response_mime_type
+ "text/html", // response_content_type
MimeType::kInvalidMimeType, // canonical_mime_type
true, // include_no_sniff_header
false, // simulate_range_response
@@ -389,7 +389,7 @@ const TestScenario kScenarios[] = {
RESOURCE_TYPE_SCRIPT, // resource_type
"http://www.a.com/", // initiator_origin
OriginHeader::kInclude, // cors_request
- "application/javascript", // response_mime_type
+ "application/javascript", // response_content_type
MimeType::kInvalidMimeType, // canonical_mime_type
true, // include_no_sniff_header
false, // simulate_range_response
@@ -405,7 +405,7 @@ const TestScenario kScenarios[] = {
RESOURCE_TYPE_SCRIPT, // resource_type
"http://www.a.com/", // initiator_origin
OriginHeader::kOmit, // cors_request
- "application/javascript", // response_mime_type
+ "application/javascript", // response_content_type
MimeType::kOthers, // canonical_mime_type
true, // include_no_sniff_header
false, // simulate_range_response
@@ -421,7 +421,7 @@ const TestScenario kScenarios[] = {
RESOURCE_TYPE_XHR, // resource_type
"http://www.a.com/", // initiator_origin
OriginHeader::kOmit, // cors_request
- "image/png", // response_mime_type
+ "image/png", // response_content_type
MimeType::kOthers, // canonical_mime_type
false, // include_no_sniff_header
false, // simulate_range_response
@@ -437,7 +437,7 @@ const TestScenario kScenarios[] = {
RESOURCE_TYPE_XHR, // resource_type
"http://www.a.com/", // initiator_origin
OriginHeader::kOmit, // cors_request
- "image/png", // response_mime_type
+ "image/png", // response_content_type
MimeType::kOthers, // canonical_mime_type
true, // include_no_sniff_header
false, // simulate_range_response
@@ -455,7 +455,7 @@ const TestScenario kScenarios[] = {
RESOURCE_TYPE_SCRIPT, // resource_type
"http://www.a.com/", // initiator_origin
OriginHeader::kOmit, // cors_request
- "text/html", // response_mime_type
+ "text/html", // response_content_type
MimeType::kHtml, // canonical_mime_type
false, // include_no_sniff_header
false, // simulate_range_response
@@ -471,7 +471,7 @@ const TestScenario kScenarios[] = {
RESOURCE_TYPE_SCRIPT, // resource_type
"http://www.a.com/", // initiator_origin
OriginHeader::kOmit, // cors_request
- "text/plain", // response_mime_type
+ "text/plain", // response_content_type
MimeType::kPlain, // canonical_mime_type
false, // include_no_sniff_header
false, // simulate_range_response
@@ -487,7 +487,7 @@ const TestScenario kScenarios[] = {
RESOURCE_TYPE_SCRIPT, // resource_type
"http://www.a.com/", // initiator_origin
OriginHeader::kOmit, // cors_request
- "text/plain", // response_mime_type
+ "text/plain", // response_content_type
MimeType::kPlain, // canonical_mime_type
false, // include_no_sniff_header
false, // simulate_range_response
@@ -504,7 +504,7 @@ const TestScenario kScenarios[] = {
RESOURCE_TYPE_SCRIPT, // resource_type
"http://www.a.com/", // initiator_origin
OriginHeader::kOmit, // cors_request
- "text/json", // response_mime_type
+ "text/json", // response_content_type
MimeType::kJson, // canonical_mime_type
false, // include_no_sniff_header
false, // simulate_range_response
@@ -520,7 +520,7 @@ const TestScenario kScenarios[] = {
RESOURCE_TYPE_SCRIPT, // resource_type
"http://www.a.com/", // initiator_origin
OriginHeader::kOmit, // cors_request
- "text/plain", // response_mime_type
+ "text/plain", // response_content_type
MimeType::kPlain, // canonical_mime_type
false, // include_no_sniff_header
false, // simulate_range_response
@@ -536,7 +536,7 @@ const TestScenario kScenarios[] = {
RESOURCE_TYPE_SCRIPT, // resource_type
"http://www.a.com/", // initiator_origin
OriginHeader::kOmit, // cors_request
- "text/plain", // response_mime_type
+ "text/plain", // response_content_type
MimeType::kPlain, // canonical_mime_type
false, // include_no_sniff_header
false, // simulate_range_response
@@ -553,7 +553,7 @@ const TestScenario kScenarios[] = {
RESOURCE_TYPE_XHR, // resource_type
"http://www.a.com/", // initiator_origin
OriginHeader::kOmit, // cors_request
- "application/xml", // response_mime_type
+ "application/xml", // response_content_type
MimeType::kXml, // canonical_mime_type
false, // include_no_sniff_header
false, // simulate_range_response
@@ -569,7 +569,7 @@ const TestScenario kScenarios[] = {
RESOURCE_TYPE_XHR, // resource_type
"http://www.a.com/", // initiator_origin
OriginHeader::kOmit, // cors_request
- "text/json", // response_mime_type
+ "text/json", // response_content_type
MimeType::kJson, // canonical_mime_type
false, // include_no_sniff_header
false, // simulate_range_response
@@ -585,7 +585,7 @@ const TestScenario kScenarios[] = {
RESOURCE_TYPE_XHR, // resource_type
"http://www.a.com/", // initiator_origin
OriginHeader::kOmit, // cors_request
- "text/html", // response_mime_type
+ "text/html", // response_content_type
MimeType::kHtml, // canonical_mime_type
false, // include_no_sniff_header
false, // simulate_range_response
@@ -601,7 +601,7 @@ const TestScenario kScenarios[] = {
RESOURCE_TYPE_XHR, // resource_type
"http://www.a.com/", // initiator_origin
OriginHeader::kOmit, // cors_request
- "text/html", // response_mime_type
+ "text/html", // response_content_type
MimeType::kHtml, // canonical_mime_type
false, // include_no_sniff_header
false, // simulate_range_response
@@ -617,7 +617,7 @@ const TestScenario kScenarios[] = {
RESOURCE_TYPE_XHR, // resource_type
"http://www.a.com/", // initiator_origin
OriginHeader::kOmit, // cors_request
- "text/html", // response_mime_type
+ "text/html", // response_content_type
MimeType::kHtml, // canonical_mime_type
false, // include_no_sniff_header
false, // simulate_range_response
@@ -633,7 +633,7 @@ const TestScenario kScenarios[] = {
RESOURCE_TYPE_XHR, // resource_type
"http://www.a.com/", // initiator_origin
OriginHeader::kOmit, // cors_request
- "text/html", // response_mime_type
+ "text/html", // response_content_type
MimeType::kInvalidMimeType, // canonical_mime_type
false, // include_no_sniff_header
false, // simulate_range_response
@@ -649,7 +649,7 @@ const TestScenario kScenarios[] = {
RESOURCE_TYPE_XHR, // resource_type
"http://www.a.com/", // initiator_origin
OriginHeader::kOmit, // cors_request
- "text/html", // response_mime_type
+ "text/html", // response_content_type
MimeType::kInvalidMimeType, // canonical_mime_type
false, // include_no_sniff_header
false, // simulate_range_response
@@ -667,7 +667,7 @@ const TestScenario kScenarios[] = {
RESOURCE_TYPE_XHR, // resource_type
"http://www.a.com/", // initiator_origin
OriginHeader::kOmit, // cors_request
- "text/html", // response_mime_type
+ "text/html", // response_content_type
MimeType::kHtml, // canonical_mime_type
true, // include_no_sniff_header
false, // simulate_range_response
@@ -683,7 +683,7 @@ const TestScenario kScenarios[] = {
RESOURCE_TYPE_XHR, // resource_type
"http://www.a.com/", // initiator_origin
OriginHeader::kOmit, // cors_request
- "text/html; charset=utf-8", // response_mime_type
+ "text/html; charset=utf-8", // response_content_type
MimeType::kHtml, // canonical_mime_type
true, // include_no_sniff_header
false, // simulate_range_response
@@ -699,7 +699,7 @@ const TestScenario kScenarios[] = {
RESOURCE_TYPE_XHR, // resource_type
"http://www.a.com/", // initiator_origin
OriginHeader::kOmit, // cors_request
- "text/html", // response_mime_type
+ "text/html", // response_content_type
MimeType::kHtml, // canonical_mime_type
true, // include_no_sniff_header
false, // simulate_range_response
@@ -715,7 +715,7 @@ const TestScenario kScenarios[] = {
RESOURCE_TYPE_XHR, // resource_type
"https://bar.site.com/", // initiator_origin
OriginHeader::kOmit, // cors_request
- "text/html", // response_mime_type
+ "text/html", // response_content_type
MimeType::kHtml, // canonical_mime_type
true, // include_no_sniff_header
false, // simulate_range_response
@@ -733,7 +733,7 @@ const TestScenario kScenarios[] = {
RESOURCE_TYPE_XHR, // resource_type
"http://foo.example.com/", // initiator_origin
OriginHeader::kInclude, // cors_request
- "text/html", // response_mime_type
+ "text/html", // response_content_type
MimeType::kHtml, // canonical_mime_type
false, // include_no_sniff_header
false, // simulate_range_response
@@ -753,7 +753,7 @@ const TestScenario kScenarios[] = {
RESOURCE_TYPE_XHR, // resource_type
"http://www.a.com/", // initiator_origin
OriginHeader::kInclude, // cors_request
- "text/html", // response_mime_type
+ "text/html", // response_content_type
MimeType::kHtml, // canonical_mime_type
true, // include_no_sniff_header
false, // simulate_range_response
@@ -771,7 +771,7 @@ const TestScenario kScenarios[] = {
RESOURCE_TYPE_XHR, // resource_type
"http://www.a.com/", // initiator_origin
OriginHeader::kOmit, // cors_request
- "text/html", // response_mime_type
+ "text/html", // response_content_type
MimeType::kHtml, // canonical_mime_type
false, // include_no_sniff_header
false, // simulate_range_response
@@ -787,7 +787,7 @@ const TestScenario kScenarios[] = {
RESOURCE_TYPE_XHR, // resource_type
"http://www.a.com/", // initiator_origin
OriginHeader::kOmit, // cors_request
- "application/xml", // response_mime_type
+ "application/xml", // response_content_type
MimeType::kXml, // canonical_mime_type
false, // include_no_sniff_header
false, // simulate_range_response
@@ -803,7 +803,7 @@ const TestScenario kScenarios[] = {
RESOURCE_TYPE_XHR, // resource_type
"http://www.a.com/", // initiator_origin
OriginHeader::kOmit, // cors_request
- "application/json", // response_mime_type
+ "application/json", // response_content_type
MimeType::kJson, // canonical_mime_type
false, // include_no_sniff_header
false, // simulate_range_response
@@ -819,7 +819,7 @@ const TestScenario kScenarios[] = {
RESOURCE_TYPE_XHR, // resource_type
"http://www.a.com/", // initiator_origin
OriginHeader::kOmit, // cors_request
- "text/plain", // response_mime_type
+ "text/plain", // response_content_type
MimeType::kPlain, // canonical_mime_type
false, // include_no_sniff_header
false, // simulate_range_response
@@ -835,7 +835,7 @@ const TestScenario kScenarios[] = {
RESOURCE_TYPE_XHR, // resource_type
"http://www.a.com/", // initiator_origin
OriginHeader::kOmit, // cors_request
- "text/plain", // response_mime_type
+ "text/plain", // response_content_type
MimeType::kPlain, // canonical_mime_type
false, // include_no_sniff_header
false, // simulate_range_response
@@ -851,7 +851,7 @@ const TestScenario kScenarios[] = {
RESOURCE_TYPE_XHR, // resource_type
"http://www.a.com/", // initiator_origin
OriginHeader::kOmit, // cors_request
- "text/plain", // response_mime_type
+ "text/plain", // response_content_type
MimeType::kPlain, // canonical_mime_type
false, // include_no_sniff_header
false, // simulate_range_response
@@ -868,7 +868,7 @@ const TestScenario kScenarios[] = {
RESOURCE_TYPE_XHR, // resource_type
"http://www.a.com/", // initiator_origin
OriginHeader::kOmit, // cors_request
- "text/plain", // response_mime_type
+ "text/plain", // response_content_type
MimeType::kPlain, // canonical_mime_type
false, // include_no_sniff_header
false, // simulate_range_response
@@ -884,7 +884,7 @@ const TestScenario kScenarios[] = {
RESOURCE_TYPE_XHR, // resource_type
"http://www.a.com/", // initiator_origin
OriginHeader::kOmit, // cors_request
- "text/plain", // response_mime_type
+ "text/plain", // response_content_type
MimeType::kPlain, // canonical_mime_type
false, // include_no_sniff_header
false, // simulate_range_response
@@ -900,7 +900,7 @@ const TestScenario kScenarios[] = {
RESOURCE_TYPE_SCRIPT, // resource_type
"http://www.a.com/", // initiator_origin
OriginHeader::kOmit, // cors_request
- "text/html", // response_mime_type
+ "text/html", // response_content_type
MimeType::kHtml, // canonical_mime_type
false, // include_no_sniff_header
false, // simulate_range_response
@@ -918,7 +918,7 @@ const TestScenario kScenarios[] = {
RESOURCE_TYPE_XHR, // resource_type
"http://www.a.com/", // initiator_origin
OriginHeader::kInclude, // cors_request
- "text/html", // response_mime_type
+ "text/html", // response_content_type
MimeType::kHtml, // canonical_mime_type
false, // include_no_sniff_header
false, // simulate_range_response
@@ -934,7 +934,7 @@ const TestScenario kScenarios[] = {
RESOURCE_TYPE_PLUGIN_RESOURCE, // resource_type
"http://www.a.com/", // initiator_origin
OriginHeader::kInclude, // cors_request
- "text/html", // response_mime_type
+ "text/html", // response_content_type
MimeType::kHtml, // canonical_mime_type
false, // include_no_sniff_header
false, // simulate_range_response
@@ -950,7 +950,7 @@ const TestScenario kScenarios[] = {
RESOURCE_TYPE_XHR, // resource_type
"http://c.com/", // initiator_origin
OriginHeader::kOmit, // cors_request
- "text/json", // response_mime_type
+ "text/json", // response_content_type
MimeType::kJson, // canonical_mime_type
false, // include_no_sniff_header
false, // simulate_range_response
@@ -966,7 +966,7 @@ const TestScenario kScenarios[] = {
RESOURCE_TYPE_XHR, // resource_type
"http://c.com/", // initiator_origin
OriginHeader::kOmit, // cors_request
- "audio/x-wav", // response_mime_type
+ "audio/x-wav", // response_content_type
MimeType::kOthers, // canonical_mime_type
true, // include_no_sniff_header
false, // simulate_range_response
@@ -982,7 +982,7 @@ const TestScenario kScenarios[] = {
RESOURCE_TYPE_XHR, // resource_type
"http://c.com/", // initiator_origin
OriginHeader::kOmit, // cors_request
- "application/javascript", // response_mime_type
+ "application/javascript", // response_content_type
MimeType::kOthers, // canonical_mime_type
false, // include_no_sniff_header
false, // simulate_range_response
@@ -998,7 +998,7 @@ const TestScenario kScenarios[] = {
RESOURCE_TYPE_XHR, // resource_type
"http://c.com/", // initiator_origin
OriginHeader::kOmit, // cors_request
- "text/html", // response_mime_type
+ "text/html", // response_content_type
MimeType::kHtml, // canonical_mime_type
true, // include_no_sniff_header
false, // simulate_range_response
@@ -1015,7 +1015,7 @@ const TestScenario kScenarios[] = {
RESOURCE_TYPE_SCRIPT, // resource_type
"http://www.a.com/", // initiator_origin
OriginHeader::kInclude, // cors_request
- "application/javascript", // response_mime_type
+ "application/javascript", // response_content_type
MimeType::kOthers, // canonical_mime_type
true, // include_no_sniff_header
false, // simulate_range_response
@@ -1031,7 +1031,7 @@ const TestScenario kScenarios[] = {
RESOURCE_TYPE_XHR, // resource_type
"http://www.a.com/", // initiator_origin
OriginHeader::kOmit, // cors_request
- "text/html", // response_mime_type
+ "text/html", // response_content_type
MimeType::kHtml, // canonical_mime_type
false, // include_no_sniff_header
false, // simulate_range_response
@@ -1047,7 +1047,7 @@ const TestScenario kScenarios[] = {
RESOURCE_TYPE_XHR, // resource_type
"http://www.a.com/", // initiator_origin
OriginHeader::kOmit, // cors_request
- "text/html", // response_mime_type
+ "text/html", // response_content_type
MimeType::kHtml, // canonical_mime_type
false, // include_no_sniff_header
false, // simulate_range_response
@@ -1063,7 +1063,7 @@ const TestScenario kScenarios[] = {
RESOURCE_TYPE_MEDIA, // resource_type
"http://www.a.com/", // initiator_origin
OriginHeader::kOmit, // cors_request
- "text/plain", // response_mime_type
+ "text/plain", // response_content_type
MimeType::kPlain, // canonical_mime_type
false, // include_no_sniff_header
true, // simulate_range_response
@@ -1079,7 +1079,7 @@ const TestScenario kScenarios[] = {
RESOURCE_TYPE_MEDIA, // resource_type
"http://www.a.com/", // initiator_origin
OriginHeader::kOmit, // cors_request
- "text/html", // response_mime_type
+ "text/html", // response_content_type
MimeType::kHtml, // canonical_mime_type
false, // include_no_sniff_header
true, // simulate_range_response
@@ -1186,7 +1186,7 @@ class CrossSiteDocumentResourceHandlerTest
first_handler_ = std::make_unique<MimeSniffingResourceHandler>(
std::move(first_handler_), &dispatcher_host_, &plugin_service_,
intercepting_handler_.get(), request_.get(),
- REQUEST_CONTEXT_TYPE_SCRIPT);
+ blink::mojom::RequestContextType::SCRIPT);
}
// Create a mock loader to drive our chain of resource loaders.
@@ -1195,7 +1195,7 @@ class CrossSiteDocumentResourceHandlerTest
// Returns a ResourceResponse that matches the TestScenario's parameters.
scoped_refptr<network::ResourceResponse> CreateResponse(
- const char* response_mime_type,
+ const char* response_content_type,
bool include_no_sniff_header,
bool simulate_range_response,
AccessControlAllowOriginHeader cors_response,
@@ -1208,14 +1208,14 @@ class CrossSiteDocumentResourceHandlerTest
// Content-Type header.
std::string charset;
- bool had_charset;
- std::string boundary;
+ bool had_charset = false;
response_headers->AddHeader(std::string("Content-Type: ") +
- response_mime_type);
- response->head.mime_type = response_mime_type;
- net::HttpUtil::ParseContentType(response_mime_type,
+ response_content_type);
+ net::HttpUtil::ParseContentType(response_content_type,
&response->head.mime_type, &charset,
- &had_charset, &boundary);
+ &had_charset, nullptr);
+ EXPECT_FALSE(response->head.mime_type.empty())
+ << "Invalid MIME type defined in kScenarios.";
// No sniff header.
if (include_no_sniff_header)
@@ -1330,7 +1330,7 @@ TEST_P(CrossSiteDocumentResourceHandlerTest, ResponseBlocking) {
// Set up response based on scenario.
scoped_refptr<network::ResourceResponse> response = CreateResponse(
- scenario.response_mime_type, scenario.include_no_sniff_header,
+ scenario.response_content_type, scenario.include_no_sniff_header,
scenario.simulate_range_response, scenario.cors_response,
scenario.initiator_origin);
@@ -1621,7 +1621,7 @@ TEST_P(CrossSiteDocumentResourceHandlerTest, OnWillReadDefer) {
// Set up response based on scenario.
scoped_refptr<network::ResourceResponse> response = CreateResponse(
- scenario.response_mime_type, scenario.include_no_sniff_header,
+ scenario.response_content_type, scenario.include_no_sniff_header,
scenario.simulate_range_response, scenario.cors_response,
scenario.initiator_origin);
@@ -1763,7 +1763,7 @@ TEST_P(CrossSiteDocumentResourceHandlerTest, MimeSnifferInterop) {
// Set up response based on scenario.
scoped_refptr<network::ResourceResponse> response = CreateResponse(
- scenario.response_mime_type, scenario.include_no_sniff_header,
+ scenario.response_content_type, scenario.include_no_sniff_header,
scenario.simulate_range_response, scenario.cors_response,
scenario.initiator_origin);
diff --git a/chromium/content/browser/loader/data_pipe_to_source_stream.cc b/chromium/content/browser/loader/data_pipe_to_source_stream.cc
index 4a3694f5b01..87f422f33ff 100644
--- a/chromium/content/browser/loader/data_pipe_to_source_stream.cc
+++ b/chromium/content/browser/loader/data_pipe_to_source_stream.cc
@@ -33,7 +33,7 @@ std::string DataPipeToSourceStream::Description() const {
int DataPipeToSourceStream::Read(net::IOBuffer* buf,
int buf_size,
net::CompletionOnceCallback callback) {
- base::AutoReset<bool>(&inside_read_, true);
+ base::AutoReset<bool> inside_read_checker(&inside_read_, true);
if (!body_.get()) {
// We have finished reading the pipe.
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 17439b760f7..dc8c30c52d6 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
@@ -44,7 +44,8 @@ class DataPipeToSourceStreamTest
: public ::testing::TestWithParam<DataPipeToSourceStreamTestParam> {
protected:
DataPipeToSourceStreamTest()
- : output_buffer_(new net::IOBufferWithSize(GetParam().buffer_size)) {}
+ : output_buffer_(base::MakeRefCounted<net::IOBufferWithSize>(
+ GetParam().buffer_size)) {}
void Init(base::StringPiece message) {
message_ = message;
diff --git a/chromium/content/browser/loader/detachable_resource_handler.cc b/chromium/content/browser/loader/detachable_resource_handler.cc
index 26593e97ec0..fb8c1c16113 100644
--- a/chromium/content/browser/loader/detachable_resource_handler.cc
+++ b/chromium/content/browser/loader/detachable_resource_handler.cc
@@ -40,10 +40,8 @@ class DetachableResourceHandler::Controller : public ResourceController {
void ResumeForRedirect(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";
- Resume();
+ MarkAsUsed();
+ detachable_handler_->ResumeForRedirect(modified_request_headers);
}
void Cancel() override {
@@ -210,7 +208,7 @@ void DetachableResourceHandler::OnWillRead(
std::unique_ptr<ResourceController> controller) {
if (!next_handler_) {
if (!read_buffer_.get())
- read_buffer_ = new net::IOBuffer(kReadBufSize);
+ read_buffer_ = base::MakeRefCounted<net::IOBuffer>(kReadBufSize);
*buf = read_buffer_;
*buf_size = kReadBufSize;
controller->Resume();
diff --git a/chromium/content/browser/loader/intercepting_resource_handler.cc b/chromium/content/browser/loader/intercepting_resource_handler.cc
index a7c3a1010ea..2037c700112 100644
--- a/chromium/content/browser/loader/intercepting_resource_handler.cc
+++ b/chromium/content/browser/loader/intercepting_resource_handler.cc
@@ -285,8 +285,8 @@ void InterceptingResourceHandler::OnBufferReceived() {
// already handles that case, anyways, so could share that code with the
// no-swap path as well. Or better, just have MimeSniffingResourceHandler
// create and manage the buffer itself.
- first_read_buffer_double_ =
- new net::IOBuffer(static_cast<size_t>(first_read_buffer_size_));
+ first_read_buffer_double_ = base::MakeRefCounted<net::IOBuffer>(
+ static_cast<size_t>(first_read_buffer_size_));
*parent_read_buffer_ = first_read_buffer_double_;
*parent_read_buffer_size_ = first_read_buffer_size_;
diff --git a/chromium/content/browser/loader/intercepting_resource_handler.h b/chromium/content/browser/loader/intercepting_resource_handler.h
index 0e7840e7120..2b71045cac0 100644
--- a/chromium/content/browser/loader/intercepting_resource_handler.h
+++ b/chromium/content/browser/loader/intercepting_resource_handler.h
@@ -148,7 +148,7 @@ class CONTENT_EXPORT InterceptingResourceHandler
// Result of the first read, that may have to be passed to an alternate
// ResourceHandler instead of the original ResourceHandler.
scoped_refptr<net::IOBuffer> first_read_buffer_;
- // Instead of |first_read_buffer_|, this handler creates a new IOBuffer with
+ // Instead of |first_read_buffer_|, this handler creates an IOBuffer with
// the same size and return it to the client.
scoped_refptr<net::IOBuffer> first_read_buffer_double_;
int first_read_buffer_size_ = 0;
diff --git a/chromium/content/browser/loader/loader_browsertest.cc b/chromium/content/browser/loader/loader_browsertest.cc
index 927f2af62d3..4982a6699e9 100644
--- a/chromium/content/browser/loader/loader_browsertest.cc
+++ b/chromium/content/browser/loader/loader_browsertest.cc
@@ -16,11 +16,13 @@
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/task/post_task.h"
#include "build/build_config.h"
#include "content/browser/download/download_manager_impl.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/resource_dispatcher_host_delegate.h"
@@ -67,11 +69,11 @@ class LoaderBrowserTest : public ContentBrowserTest,
protected:
void SetUpOnMainThread() override {
base::FilePath path = GetTestFilePath("", "");
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&net::URLRequestMockHTTPJob::AddUrlHandlers, path));
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&net::URLRequestFailedJob::AddUrlHandler));
host_resolver()->AddRule("*", "127.0.0.1");
}
@@ -286,11 +288,11 @@ std::unique_ptr<net::test_server::HttpResponse> CancelOnRequest(
return nullptr;
if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
- content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
- crash_network_service_callback);
+ base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI},
+ crash_network_service_callback);
} else {
- content::BrowserThread::PostTask(
- content::BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {content::BrowserThread::IO},
base::BindOnce(&ResourceDispatcherHostImpl::CancelRequestsForProcess,
base::Unretained(ResourceDispatcherHostImpl::Get()),
child_id));
@@ -835,23 +837,23 @@ class PreviewsStateBrowserTest : public ContentBrowserTest {
embedded_test_server()->GetURL("/image.jpg"),
embedded_test_server()->GetURL("/title1.html")));
- content::BrowserThread::PostTask(
- content::BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {content::BrowserThread::IO},
base::BindOnce(
&PreviewsStateResourceDispatcherHostDelegate::SetDelegate,
base::Unretained(delegate_.get())));
}
void Reset(PreviewsState previews_state) {
- content::BrowserThread::PostTask(
- content::BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {content::BrowserThread::IO},
base::BindOnce(&PreviewsStateResourceDispatcherHostDelegate::Reset,
base::Unretained(delegate_.get()), previews_state));
}
void CheckResourcesRequested(bool should_get_previews_state_called) {
- content::BrowserThread::PostTask(
- content::BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {content::BrowserThread::IO},
base::BindOnce(&PreviewsStateResourceDispatcherHostDelegate::
CheckResourcesRequested,
base::Unretained(delegate_.get()),
@@ -934,8 +936,6 @@ struct RequestData {
referrer(referrer) {}
};
-const GURL kURLWithUniqueOrigin("data:,");
-
} // namespace
class RequestDataBrowserTest : public ContentBrowserTest {
@@ -1092,7 +1092,7 @@ IN_PROC_BROWSER_TEST_F(RequestDataBrowserTest, BasicCrossSite) {
// document in which they're embedded.
for (size_t i = 2; i < requests.size(); i++) {
SCOPED_TRACE(requests[i].url);
- EXPECT_EQ(kURLWithUniqueOrigin, requests[i].first_party);
+ EXPECT_EQ(GURL::EmptyGURL(), requests[i].first_party);
EXPECT_EQ(nested_origin, requests[i].initiator);
}
}
@@ -1259,7 +1259,7 @@ IN_PROC_BROWSER_TEST_F(RequestDataBrowserTest, CrossOriginNested) {
// 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, requests[3].url);
- EXPECT_EQ(kURLWithUniqueOrigin, requests[3].first_party);
+ EXPECT_EQ(GURL::EmptyGURL(), requests[3].first_party);
EXPECT_EQ(nested_origin, requests[3].initiator);
}
diff --git a/chromium/content/browser/loader/loader_io_thread_notifier.cc b/chromium/content/browser/loader/loader_io_thread_notifier.cc
index 215e2f95fac..44f53d52975 100644
--- a/chromium/content/browser/loader/loader_io_thread_notifier.cc
+++ b/chromium/content/browser/loader/loader_io_thread_notifier.cc
@@ -4,8 +4,10 @@
#include "content/browser/loader/loader_io_thread_notifier.h"
+#include "base/task/post_task.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/global_routing_id.h"
@@ -28,8 +30,8 @@ LoaderIOThreadNotifier::~LoaderIOThreadNotifier() {}
void LoaderIOThreadNotifier::RenderFrameDeleted(
RenderFrameHost* render_frame_host) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&NotifyRenderFrameDeletedOnIO,
static_cast<RenderFrameHostImpl*>(render_frame_host)
->GetGlobalFrameRoutingId()));
diff --git a/chromium/content/browser/loader/merkle_integrity_source_stream_unittest.cc b/chromium/content/browser/loader/merkle_integrity_source_stream_unittest.cc
index 8765b844ae8..1362d4e18b5 100644
--- a/chromium/content/browser/loader/merkle_integrity_source_stream_unittest.cc
+++ b/chromium/content/browser/loader/merkle_integrity_source_stream_unittest.cc
@@ -56,7 +56,7 @@ class MerkleIntegritySourceStreamTest
: output_buffer_size_(GetParam().buffer_size) {}
void Init(const std::string& mi_header_value) {
- output_buffer_ = new net::IOBuffer(output_buffer_size_);
+ output_buffer_ = base::MakeRefCounted<net::IOBuffer>(output_buffer_size_);
std::unique_ptr<net::MockSourceStream> source(new net::MockSourceStream());
if (GetParam().read_result_type == ReadResultType::ONE_BYTE_AT_A_TIME)
source->set_read_one_byte_at_a_time(true);
diff --git a/chromium/content/browser/loader/mime_sniffing_resource_handler.cc b/chromium/content/browser/loader/mime_sniffing_resource_handler.cc
index 74707ef3128..b228a7dd382 100644
--- a/chromium/content/browser/loader/mime_sniffing_resource_handler.cc
+++ b/chromium/content/browser/loader/mime_sniffing_resource_handler.cc
@@ -115,7 +115,7 @@ MimeSniffingResourceHandler::MimeSniffingResourceHandler(
PluginService* plugin_service,
InterceptingResourceHandler* intercepting_handler,
net::URLRequest* request,
- RequestContextType request_context_type)
+ blink::mojom::RequestContextType request_context_type)
: LayeredResourceHandler(request, std::move(next_handler)),
state_(STATE_STARTING),
host_(host),
@@ -161,7 +161,7 @@ void MimeSniffingResourceHandler::OnResponseStarted(
if (!(response_->head.headers.get() &&
response_->head.headers->response_code() == 304)) {
// MIME sniffing should be disabled for a request initiated by fetch().
- if (request_context_type_ != REQUEST_CONTEXT_TYPE_FETCH &&
+ if (request_context_type_ != blink::mojom::RequestContextType::FETCH &&
network::ShouldSniffContent(request(), response_.get())) {
controller->Resume();
return;
diff --git a/chromium/content/browser/loader/mime_sniffing_resource_handler.h b/chromium/content/browser/loader/mime_sniffing_resource_handler.h
index b1223d34f3d..8e85dba33ff 100644
--- a/chromium/content/browser/loader/mime_sniffing_resource_handler.h
+++ b/chromium/content/browser/loader/mime_sniffing_resource_handler.h
@@ -14,8 +14,8 @@
#include "content/browser/loader/layered_resource_handler.h"
#include "content/browser/loader/resource_controller.h"
#include "content/common/content_export.h"
-#include "content/public/common/request_context_type.h"
#include "ppapi/buildflags/buildflags.h"
+#include "third_party/blink/public/platform/modules/fetch/fetch_api_request.mojom.h"
namespace net {
class URLRequest;
@@ -43,12 +43,13 @@ struct WebPluginInfo;
class CONTENT_EXPORT MimeSniffingResourceHandler
: public LayeredResourceHandler {
public:
- MimeSniffingResourceHandler(std::unique_ptr<ResourceHandler> next_handler,
- ResourceDispatcherHostImpl* host,
- PluginService* plugin_service,
- InterceptingResourceHandler* intercepting_handler,
- net::URLRequest* request,
- RequestContextType request_context_type);
+ MimeSniffingResourceHandler(
+ std::unique_ptr<ResourceHandler> next_handler,
+ ResourceDispatcherHostImpl* host,
+ PluginService* plugin_service,
+ InterceptingResourceHandler* intercepting_handler,
+ net::URLRequest* request,
+ blink::mojom::RequestContextType request_context_type);
~MimeSniffingResourceHandler() override;
private:
@@ -198,7 +199,7 @@ class CONTENT_EXPORT MimeSniffingResourceHandler
// needed.
InterceptingResourceHandler* intercepting_handler_;
- RequestContextType request_context_type_;
+ blink::mojom::RequestContextType request_context_type_;
// True if current in an AdvanceState loop. Used to prevent re-entrancy and
// avoid an extra PostTask.
diff --git a/chromium/content/browser/loader/mime_sniffing_resource_handler_unittest.cc b/chromium/content/browser/loader/mime_sniffing_resource_handler_unittest.cc
index 6d23266622c..4a77bb1af41 100644
--- a/chromium/content/browser/loader/mime_sniffing_resource_handler_unittest.cc
+++ b/chromium/content/browser/loader/mime_sniffing_resource_handler_unittest.cc
@@ -244,7 +244,7 @@ MimeSniffingResourceHandlerTest::TestAcceptHeaderSettingWithURLRequest(
MimeSniffingResourceHandler mime_sniffing_handler(
std::move(scoped_test_handler), nullptr, nullptr, nullptr, request,
- REQUEST_CONTEXT_TYPE_UNSPECIFIED);
+ blink::mojom::RequestContextType::UNSPECIFIED);
MockResourceLoader mock_loader(&mime_sniffing_handler);
EXPECT_EQ(MockResourceLoader::Status::IDLE,
@@ -290,7 +290,7 @@ bool MimeSniffingResourceHandlerTest::TestStreamIsIntercepted(
MimeSniffingResourceHandler mime_sniffing_handler(
std::unique_ptr<ResourceHandler>(std::move(scoped_test_handler)), &host,
&plugin_service, intercepting_handler.get(), request.get(),
- REQUEST_CONTEXT_TYPE_UNSPECIFIED);
+ blink::mojom::RequestContextType::UNSPECIFIED);
MockResourceLoader mock_loader(&mime_sniffing_handler);
@@ -357,7 +357,7 @@ void MimeSniffingResourceHandlerTest::TestHandlerSniffing(
MimeSniffingResourceHandler mime_sniffing_handler(
std::move(scoped_test_handler), &host, &plugin_service,
intercepting_handler.get(), request.get(),
- REQUEST_CONTEXT_TYPE_UNSPECIFIED);
+ blink::mojom::RequestContextType::UNSPECIFIED);
MockResourceLoader mock_loader(&mime_sniffing_handler);
@@ -521,7 +521,7 @@ void MimeSniffingResourceHandlerTest::TestHandlerNoSniffing(
MimeSniffingResourceHandler mime_sniffing_handler(
std::move(scoped_test_handler), &host, &plugin_service,
intercepting_handler.get(), request.get(),
- REQUEST_CONTEXT_TYPE_UNSPECIFIED);
+ blink::mojom::RequestContextType::UNSPECIFIED);
MockResourceLoader mock_loader(&mime_sniffing_handler);
@@ -854,7 +854,7 @@ TEST_F(MimeSniffingResourceHandlerTest, 304Handling) {
std::unique_ptr<ResourceHandler>(new TestResourceHandler()), &host,
&plugin_service,
static_cast<InterceptingResourceHandler*>(intercepting_handler.get()),
- request.get(), REQUEST_CONTEXT_TYPE_UNSPECIFIED);
+ request.get(), blink::mojom::RequestContextType::UNSPECIFIED);
MockResourceLoader mock_loader(&mime_sniffing_handler);
@@ -907,7 +907,8 @@ TEST_F(MimeSniffingResourceHandlerTest, FetchShouldDisableMimeSniffing) {
scoped_test_handler->set_on_response_started_result(false);
MimeSniffingResourceHandler mime_sniffing_handler(
std::move(scoped_test_handler), &host, &plugin_service,
- intercepting_handler.get(), request.get(), REQUEST_CONTEXT_TYPE_FETCH);
+ intercepting_handler.get(), request.get(),
+ blink::mojom::RequestContextType::FETCH);
MockResourceLoader mock_loader(&mime_sniffing_handler);
@@ -967,7 +968,7 @@ TEST_F(MimeSniffingResourceHandlerTest, NonEmptyPayloadEndsBeforeDecision) {
MimeSniffingResourceHandler mime_sniffing_handler(
std::move(scoped_test_handler), &host, &plugin_service,
intercepting_handler.get(), request.get(),
- REQUEST_CONTEXT_TYPE_UNSPECIFIED);
+ blink::mojom::RequestContextType::UNSPECIFIED);
MockResourceLoader mock_loader(&mime_sniffing_handler);
@@ -1045,7 +1046,7 @@ TEST_F(MimeSniffingResourceHandlerTest, EmptyPayload) {
MimeSniffingResourceHandler mime_sniffing_handler(
std::move(scoped_test_handler), &host, &plugin_service,
intercepting_handler.get(), request.get(),
- REQUEST_CONTEXT_TYPE_UNSPECIFIED);
+ blink::mojom::RequestContextType::UNSPECIFIED);
MockResourceLoader mock_loader(&mime_sniffing_handler);
diff --git a/chromium/content/browser/loader/mojo_async_resource_handler.cc b/chromium/content/browser/loader/mojo_async_resource_handler.cc
index de7d58c0a73..014399c7f58 100644
--- a/chromium/content/browser/loader/mojo_async_resource_handler.cc
+++ b/chromium/content/browser/loader/mojo_async_resource_handler.cc
@@ -186,6 +186,7 @@ void MojoAsyncResourceHandler::OnResponseStarted(
response->head.request_start = request()->creation_time();
response->head.response_start = base::TimeTicks::Now();
sent_received_response_message_ = true;
+ response->head.was_fetched_via_cache = request()->was_cached();
if ((url_loader_options_ &
network::mojom::kURLLoadOptionSendSSLInfoWithResponse) &&
@@ -298,7 +299,7 @@ void MojoAsyncResourceHandler::OnWillRead(
}
DCHECK(!is_using_io_buffer_not_from_writer_);
is_using_io_buffer_not_from_writer_ = true;
- buffer_ = new net::IOBufferWithSize(kMinAllocationSize);
+ buffer_ = base::MakeRefCounted<net::IOBufferWithSize>(kMinAllocationSize);
}
*buf = buffer_;
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 68e6a784850..5f8fd5bf390 100644
--- a/chromium/content/browser/loader/mojo_async_resource_handler_unittest.cc
+++ b/chromium/content/browser/loader/mojo_async_resource_handler_unittest.cc
@@ -492,7 +492,8 @@ TEST_F(MojoAsyncResourceHandlerTest, OnWillStart) {
}
TEST_F(MojoAsyncResourceHandlerTest, OnResponseStarted) {
- scoped_refptr<net::IOBufferWithSize> metadata = new net::IOBufferWithSize(5);
+ scoped_refptr<net::IOBufferWithSize> metadata =
+ base::MakeRefCounted<net::IOBufferWithSize>(5);
memcpy(metadata->data(), "hello", 5);
handler_->SetMetadata(metadata);
diff --git a/chromium/content/browser/loader/navigation_loader_interceptor.cc b/chromium/content/browser/loader/navigation_loader_interceptor.cc
index 957753b1a9a..630456cb714 100644
--- a/chromium/content/browser/loader/navigation_loader_interceptor.cc
+++ b/chromium/content/browser/loader/navigation_loader_interceptor.cc
@@ -17,7 +17,8 @@ bool NavigationLoaderInterceptor::MaybeCreateLoaderForResponse(
const network::ResourceResponseHead& response,
network::mojom::URLLoaderPtr* loader,
network::mojom::URLLoaderClientRequest* client_request,
- ThrottlingURLLoader* url_loader) {
+ ThrottlingURLLoader* url_loader,
+ bool* skip_other_interceptors) {
return false;
}
diff --git a/chromium/content/browser/loader/navigation_loader_interceptor.h b/chromium/content/browser/loader/navigation_loader_interceptor.h
index ca2f3ad6d5f..1ec858cfaf8 100644
--- a/chromium/content/browser/loader/navigation_loader_interceptor.h
+++ b/chromium/content/browser/loader/navigation_loader_interceptor.h
@@ -93,11 +93,17 @@ class CONTENT_EXPORT NavigationLoaderInterceptor {
// intercept the inflight loading if necessary. Note that the |url_loader|
// will be reset after this method is called, which will also drop the
// URLLoader held by |url_loader_| if it is not unbound yet.
+ // |skip_other_interceptors| is set to true when this interceptor will
+ // exclusively handle the navigation even after redirections. TODO(horo): This
+ // flag was introduced to skip service worker after signed exchange redirect.
+ // Remove this flag when we support service worker and signed exchange
+ // integration. See crbug.com/894755#c1. Nullptr is not allowed.
virtual bool MaybeCreateLoaderForResponse(
const network::ResourceResponseHead& response,
network::mojom::URLLoaderPtr* loader,
network::mojom::URLLoaderClientRequest* client_request,
- ThrottlingURLLoader* url_loader);
+ ThrottlingURLLoader* url_loader,
+ bool* skip_other_interceptors);
};
} // namespace content
diff --git a/chromium/content/browser/loader/navigation_url_loader_impl.cc b/chromium/content/browser/loader/navigation_url_loader_impl.cc
index f14b46b86a8..257cbf5c165 100644
--- a/chromium/content/browser/loader/navigation_url_loader_impl.cc
+++ b/chromium/content/browser/loader/navigation_url_loader_impl.cc
@@ -8,12 +8,15 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
+#include "base/debug/alias.h"
#include "base/feature_list.h"
#include "base/metrics/histogram_macros.h"
#include "base/optional.h"
+#include "base/rand_util.h"
#include "base/stl_util.h"
#include "base/task/post_task.h"
#include "base/trace_event/trace_event.h"
+#include "build/build_config.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"
@@ -26,6 +29,7 @@
#include "content/browser/frame_host/navigation_request_info.h"
#include "content/browser/loader/navigation_loader_interceptor.h"
#include "content/browser/loader/navigation_url_loader_delegate.h"
+#include "content/browser/loader/prefetch_url_loader_service.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"
@@ -46,6 +50,7 @@
#include "content/common/net/record_load_histograms.h"
#include "content/common/throttling_url_loader.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/download_utils.h"
@@ -66,6 +71,7 @@
#include "net/cert/signed_certificate_timestamp_and_status.h"
#include "net/http/http_content_disposition.h"
#include "net/http/http_request_headers.h"
+#include "net/http/http_status_code.h"
#include "net/ssl/ssl_info.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "net/url_request/redirect_util.h"
@@ -82,6 +88,11 @@
#include "services/service_manager/public/cpp/connector.h"
#include "third_party/blink/public/common/mime_util/mime_util.h"
#include "third_party/blink/public/common/service_worker/service_worker_utils.h"
+#include "url/gurl.h"
+
+#if defined(OS_ANDROID)
+#include "content/browser/android/content_url_loader_factory.h"
+#endif
namespace content {
@@ -217,10 +228,8 @@ std::unique_ptr<network::ResourceRequest> CreateResourceRequest(
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()) {
+ if (signed_exchange_utils::ShouldAdvertiseAcceptHeader(
+ url::Origin::Create(request_info->common_params.url))) {
DCHECK(!accept_value.empty());
accept_value.append(kAcceptHeaderSignedExchangeSuffix);
}
@@ -253,9 +262,10 @@ std::unique_ptr<network::ResourceRequest> CreateResourceRequest(
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;
+ static_cast<int>(request_info->begin_params->request_context_type);
new_request->upgrade_if_insecure = request_info->upgrade_if_insecure;
new_request->throttling_profile_id = request_info->devtools_frame_token;
+ new_request->transition_type = request_info->common_params.transition;
return new_request;
}
@@ -436,6 +446,8 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
storage::FileSystemContext* upload_file_system_context,
ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core,
AppCacheNavigationHandleCore* appcache_handle_core,
+ scoped_refptr<SignedExchangePrefetchMetricRecorder>
+ signed_exchange_prefetch_metric_recorder,
bool was_request_intercepted) const {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
@@ -446,7 +458,6 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
weak_factory_.GetWeakPtr(),
base::Unretained(url_request_context_getter),
base::Unretained(upload_file_system_context),
- std::make_unique<NavigationRequestInfo>(*request_info_),
// If the request has already been intercepted, the request should not
// be intercepted again.
// S13nServiceWorker: Requests are intercepted by S13nServiceWorker
@@ -458,23 +469,23 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
? nullptr
: service_worker_navigation_handle_core),
base::Unretained(was_request_intercepted ? nullptr
- : appcache_handle_core));
+ : appcache_handle_core),
+ std::move(signed_exchange_prefetch_metric_recorder));
}
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,
+ scoped_refptr<SignedExchangePrefetchMetricRecorder>
+ signed_exchange_prefetch_metric_recorder,
const network::ResourceRequest& /* resource_request */,
network::mojom::URLLoaderRequest url_loader,
network::mojom::URLLoaderClientPtr url_loader_client) {
- // |resource_request| is unused here. Its info may not be the same as
- // |request_info|, because URLLoaderThrottles may have rewritten it. We
- // don't propagate the fields to |request_info| here because the request
- // will usually go to ResourceDispatcherHost which does its own request
- // modification independent of URLLoaderThrottles.
+ // |resource_request| is unused here. We don't propagate the fields to
+ // |request_info_| here because the request will usually go to
+ // ResourceDispatcherHost which does its own request modifications.
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
DCHECK(started_);
@@ -489,46 +500,71 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
// 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<SignedExchangeRequestHandler>(
- 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->devtools_frame_token, request_info->report_raw_headers,
- request_info->begin_params->load_flags,
+ 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_->devtools_frame_token, request_info_->report_raw_headers,
+ request_info_->begin_params->load_flags,
base::MakeRefCounted<
SignedExchangeURLLoaderFactoryForNonNetworkService>(
resource_context_, url_request_context_getter),
base::BindRepeating(
&URLLoaderRequestController::CreateURLLoaderThrottles,
- base::Unretained(this))));
+ base::Unretained(this)),
+ std::move(signed_exchange_prefetch_metric_recorder)));
}
- uint32_t options = GetURLLoaderOptions(request_info->is_main_frame);
+ uint32_t options = GetURLLoaderOptions(request_info_->is_main_frame);
bool intercepted = false;
if (g_interceptor.Get()) {
+ // Recreate the ResourceRequest for the interceptor, in case a
+ // URLLoaderThrottle had changed request_info_.
+ auto latest_resource_request =
+ CreateResourceRequest(request_info_.get(), frame_tree_node_id_,
+ resource_request_->allow_download);
+ latest_resource_request->headers = resource_request_->headers;
intercepted = g_interceptor.Get().Run(
&url_loader, frame_tree_node_id_, 0 /* request_id */, options,
- *resource_request_.get(), &url_loader_client,
+ *latest_resource_request, &url_loader_client,
net::MutableNetworkTrafficAnnotationTag(
kNavigationUrlLoaderTrafficAnnotation));
}
+ // A URLLoaderThrottle may have changed the headers.
+ request_info_->begin_params->headers =
+ resource_request_->headers.ToString();
+
// The ResourceDispatcherHostImpl can be null in unit tests.
- if (!intercepted && ResourceDispatcherHostImpl::Get()) {
- ResourceDispatcherHostImpl::Get()->BeginNavigationRequest(
+ ResourceDispatcherHostImpl* rdh = ResourceDispatcherHostImpl::Get();
+ if (!intercepted && rdh) {
+ rdh->BeginNavigationRequest(
resource_context_, url_request_context_getter->GetURLRequestContext(),
- upload_file_system_context, *request_info,
+ 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_);
+
+ if (!blink::ServiceWorkerUtils::IsServicificationEnabled()) {
+ // Get the SWProviderHost for non-S13nSW path. For S13nSW path,
+ // |service_worker_provider_host_| must be set in
+ // CreateServiceWorkerInterceptor().
+ net::URLRequest* url_request = rdh->GetURLRequest(global_request_id_);
+ ServiceWorkerProviderHost* service_worker_provider_host =
+ ServiceWorkerRequestHandler::GetProviderHost(url_request);
+ if (service_worker_provider_host) {
+ service_worker_provider_host_ =
+ service_worker_provider_host->AsWeakPtr();
+ }
+ }
}
// 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::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&NavigationURLLoaderImpl::OnRequestStarted, owner_,
base::TimeTicks::Now()));
}
@@ -539,6 +575,8 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
storage::FileSystemContext* upload_file_system_context,
ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core,
AppCacheNavigationHandleCore* appcache_handle_core,
+ scoped_refptr<SignedExchangePrefetchMetricRecorder>
+ signed_exchange_prefetch_metric_recorder,
std::unique_ptr<NavigationRequestInfo> request_info,
std::unique_ptr<NavigationUIData> navigation_ui_data) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -563,7 +601,8 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
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));
+ base::Unretained(appcache_handle_core),
+ base::RetainedRef(signed_exchange_prefetch_metric_recorder));
// Requests to Blob scheme won't get redirected to/from other schemes
// or be intercepted, so we just let it go here.
@@ -627,6 +666,8 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
network_loader_factory_info,
ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core,
AppCacheNavigationHandleCore* appcache_handle_core,
+ scoped_refptr<SignedExchangePrefetchMetricRecorder>
+ signed_exchange_prefetch_metric_recorder,
std::unique_ptr<NavigationRequestInfo> request_info,
std::unique_ptr<NavigationUIData> navigation_ui_data,
network::mojom::URLLoaderFactoryPtrInfo factory_for_webui,
@@ -642,6 +683,11 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
base::Bind(&GetWebContentsFromFrameTreeNodeID, frame_tree_node_id);
navigation_ui_data_ = std::move(navigation_ui_data);
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(&NavigationURLLoaderImpl::OnRequestStarted, owner_,
+ base::TimeTicks::Now()));
+
DCHECK(network_loader_factory_info);
network_loader_factory_ = network::SharedURLLoaderFactory::Create(
std::move(network_loader_factory_info));
@@ -696,11 +742,6 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
}
if (signed_exchange_utils::IsSignedExchangeHandlingEnabled()) {
- // Signed Exchange is currently disabled when Network Service is enabled
- // (https://crbug.com/849935), but still create
- // SignedExchangeRequestHandler in order to show error message (and
- // devtools warning) to users.
-
// 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
@@ -715,7 +756,8 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
request_info->begin_params->load_flags, network_loader_factory_,
base::BindRepeating(
&URLLoaderRequestController::CreateURLLoaderThrottles,
- base::Unretained(this))));
+ base::Unretained(this)),
+ signed_exchange_prefetch_metric_recorder));
}
std::vector<std::unique_ptr<URLLoaderRequestInterceptor>>
@@ -850,7 +892,8 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
// This is the |fallback_callback| passed to
// NavigationLoaderInterceptor::MaybeCreateLoader. It allows an interceptor
// to initially elect to handle a request, and later decide to fallback to
- // the default behavior. This is needed for service worker network fallback.
+ // the default behavior. This is needed for service worker network fallback
+ // and signed exchange (SXG) fallback redirect.
void FallbackToNonInterceptedRequest(bool reset_subresource_loader_params) {
if (reset_subresource_loader_params)
subresource_loader_params_.reset();
@@ -859,21 +902,35 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
// Cancel state on ResourceDispatcherHostImpl so it doesn't complain about
// reusing the request_id after redirects. Otherwise the following sequence
// can happen:
- // RDHI Start(request_id) -> Redirect -> SW interception -> SW fallback to
- // network -> RDHI Start(request_id).
+ // case 1. RDHI Start(request_id) -> Redirect -> SW interception -> SW
+ // fallback to network -> RDHI Start(request_id).
+ // case 2. RDHI Start(request_id) -> SXG interception -> SXG fallback to
+ // network -> RDHI Start(request_id).
if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) {
DCHECK(ResourceDispatcherHostImpl::Get());
ResourceDispatcherHostImpl::Get()->CancelRequest(
global_request_id_.child_id, global_request_id_.request_id);
}
- // |url_loader_| is using the factory for the interceptor that decided to
- // fallback, so restart it with the non-interceptor factory.
- DCHECK(url_loader_);
uint32_t options = network::mojom::kURLLoadOptionNone;
scoped_refptr<network::SharedURLLoaderFactory> factory =
PrepareForNonInterceptedRequest(&options);
- url_loader_->RestartWithFactory(std::move(factory), options);
+ if (url_loader_) {
+ // |url_loader_| is using the factory for the interceptor that decided to
+ // fallback, so restart it with the non-interceptor factory.
+ url_loader_->RestartWithFactory(std::move(factory), options);
+ } else {
+ // In SXG cases we don't have |url_loader_| because it was reset when the
+ // SXG interceptor intercepted the response in
+ // MaybeCreateLoaderForResponse.
+ DCHECK(response_loader_binding_);
+ response_loader_binding_.Close();
+ url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
+ std::move(factory), CreateURLLoaderThrottles(), frame_tree_node_id_,
+ global_request_id_.request_id, options, resource_request_.get(),
+ this /* client */, kNavigationUrlLoaderTrafficAnnotation,
+ base::ThreadTaskRunnerHandle::Get());
+ }
}
scoped_refptr<network::SharedURLLoaderFactory>
@@ -931,8 +988,8 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
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::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&NavigationURLLoaderImpl ::
BindNonNetworkURLLoaderFactoryRequest,
owner_, frame_tree_node_id_,
@@ -974,6 +1031,14 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(!redirect_info_.new_url.is_empty());
+ if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+ auto* common_params =
+ const_cast<CommonNavigationParams*>(&request_info_->common_params);
+ common_params->url = redirect_info_.new_url;
+ common_params->referrer.url = GURL(redirect_info_.new_referrer);
+ common_params->method = redirect_info_.new_method;
+ }
+
if (!IsLoaderInterceptionEnabled()) {
url_loader_->FollowRedirect(modified_request_headers);
return;
@@ -987,7 +1052,6 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
// 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(
@@ -1011,6 +1075,27 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
// |resource_request_| during redirect.
url_loader_modified_request_headers_ = modified_request_headers;
+ if (signed_exchange_utils::NeedToCheckRedirectedURLForAcceptHeader()) {
+ // Currently we send the SignedExchange accept header only for the limited
+ // origins when SignedHTTPExchangeOriginTrial feature is enabled without
+ // SignedHTTPExchange feature. We need to put the SignedExchange accept
+ // header on when redirecting to the origins in the OriginList of
+ // SignedHTTPExchangeAcceptHeader field trial, and need to remove it when
+ // redirecting to out of the OriginList.
+ if (!url_loader_modified_request_headers_)
+ url_loader_modified_request_headers_ = net::HttpRequestHeaders();
+ std::string accept_value = network::kFrameAcceptHeader;
+ if (signed_exchange_utils::ShouldAdvertiseAcceptHeader(
+ url::Origin::Create(resource_request_->url))) {
+ DCHECK(!accept_value.empty());
+ accept_value.append(kAcceptHeaderSignedExchangeSuffix);
+ }
+ url_loader_modified_request_headers_->SetHeader(network::kAcceptHeader,
+ accept_value);
+ resource_request_->headers.SetHeader(network::kAcceptHeader,
+ accept_value);
+ }
+
Restart();
}
@@ -1036,12 +1121,8 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
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(
@@ -1049,6 +1130,16 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
response_loader_binding_.Unbind());
}
+ // 304 responses should abort the navigation, rather than display the page.
+ // This needs to be after the URLLoader has been moved to
+ // |url_loader_client_endpoints| in order to abort the request, to avoid
+ // receiving unexpected call.
+ if (head.headers &&
+ head.headers->response_code() == net::HTTP_NOT_MODIFIED) {
+ OnComplete(network::URLLoaderCompletionStatus(net::ERR_ABORTED));
+ return;
+ }
+
bool is_download;
bool is_stream;
// If there is not an explicit PreviewsState set on the request, turn
@@ -1061,19 +1152,21 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
url_, head.headers.get(), head.mime_type);
bool known_mime_type = blink::IsSupportedMimeType(head.mime_type);
- bool is_download_if_not_handled_by_plugin =
- !response_intercepted && (must_download || !known_mime_type);
-
#if BUILDFLAG(ENABLE_PLUGINS)
- if (!response_intercepted && !must_download && !known_mime_type) {
+ if (!head.intercepted_by_plugin && !must_download && !known_mime_type) {
+ // No plugin throttles intercepted the response. Ask if the plugin
+ // registered to PluginService wants to handle the request.
CheckPluginAndContinueOnReceiveResponse(
head, std::move(url_loader_client_endpoints),
- is_download_if_not_handled_by_plugin, std::vector<WebPluginInfo>());
+ true /* is_download_if_not_handled_by_plugin */,
+ std::vector<WebPluginInfo>());
return;
}
#endif
- is_download = is_download_if_not_handled_by_plugin;
+ // When a plugin intercepted the response, we don't want to download it.
+ is_download =
+ !head.intercepted_by_plugin && (must_download || !known_mime_type);
is_stream = false;
// If NetworkService is on, or an interceptor handled the request, the
@@ -1098,7 +1191,7 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
if (url_request) {
ResourceRequestInfoImpl* info =
ResourceRequestInfoImpl::ForRequest(url_request);
- is_download = !response_intercepted && info->IsDownload();
+ is_download = !head.intercepted_by_plugin && info->IsDownload();
is_stream = info->is_stream();
previews_state = info->GetPreviewsState();
if (rdh->delegate()) {
@@ -1198,8 +1291,8 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
// 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::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&NavigationURLLoaderImpl::OnReceiveResponse, owner_,
response->DeepCopy(),
std::move(url_loader_client_endpoints),
@@ -1237,8 +1330,8 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
// 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::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&NavigationURLLoaderImpl::OnReceiveRedirect, owner_,
redirect_info, response->DeepCopy()));
}
@@ -1252,6 +1345,40 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
void OnStartLoadingResponseBody(mojo::ScopedDataPipeConsumerHandle) override {
// Not reached. At this point, the loader and client endpoints must have
// been unbound and forwarded to the renderer.
+
+ // TODO(crbug.com/882661): Remove these aliases when the linked bug is
+ // fixed.
+ bool received_response = received_response_;
+ base::debug::Alias(&received_response);
+ bool default_loader_used = default_loader_used_;
+ base::debug::Alias(&default_loader_used);
+ DEBUG_ALIAS_FOR_GURL(url, url_);
+ size_t chain_size = url_chain_.size();
+ base::debug::Alias(&chain_size);
+ GURL url0;
+ GURL url1;
+ GURL url2;
+ GURL url3;
+ GURL url4;
+ GURL url5;
+ if (url_chain_.size() > 0)
+ url0 = url_chain_[0];
+ if (url_chain_.size() > 1)
+ url1 = url_chain_[1];
+ if (url_chain_.size() > 2)
+ url2 = url_chain_[2];
+ if (url_chain_.size() > 3)
+ url3 = url_chain_[3];
+ if (url_chain_.size() > 4)
+ url4 = url_chain_[4];
+ if (url_chain_.size() > 5)
+ url5 = url_chain_[5];
+ DEBUG_ALIAS_FOR_GURL(url0_buf, url0);
+ DEBUG_ALIAS_FOR_GURL(url1_buf, url1);
+ DEBUG_ALIAS_FOR_GURL(url2_buf, url2);
+ DEBUG_ALIAS_FOR_GURL(url3_buf, url3);
+ DEBUG_ALIAS_FOR_GURL(url4_buf, url4);
+ DEBUG_ALIAS_FOR_GURL(url5_buf, url5);
CHECK(false);
}
@@ -1276,8 +1403,8 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
}
status_ = status;
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&NavigationURLLoaderImpl::OnComplete, owner_, status));
}
@@ -1291,16 +1418,36 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
if (!default_loader_used_)
return false;
- for (auto& interceptor : interceptors_) {
+ for (size_t i = 0u; i < interceptors_.size(); ++i) {
+ NavigationLoaderInterceptor* interceptor = interceptors_[i].get();
network::mojom::URLLoaderClientRequest response_client_request;
+ bool skip_other_interceptors = false;
if (interceptor->MaybeCreateLoaderForResponse(
response, &response_url_loader_, &response_client_request,
- url_loader_.get())) {
+ url_loader_.get(), &skip_other_interceptors)) {
if (response_loader_binding_.is_bound())
response_loader_binding_.Close();
response_loader_binding_.Bind(std::move(response_client_request));
default_loader_used_ = false;
url_loader_.reset();
+ if (skip_other_interceptors) {
+ std::vector<std::unique_ptr<NavigationLoaderInterceptor>>
+ new_interceptors;
+ new_interceptors.push_back(std::move(interceptors_[i]));
+ new_interceptors.swap(interceptors_);
+ if (service_worker_provider_host_) {
+ // Reset the state of ServiceWorkerProviderHost.
+ // Currently we don't support Service Worker in Signed Exchange
+ // pages. The page will not be controlled by service workers. And
+ // Service Worker related APIs will fail with NoDocumentURL error.
+ // TODO(crbug/898733): Support SignedExchange loading and Service
+ // Worker integration.
+ service_worker_provider_host_->SetControllerRegistration(
+ nullptr, false /* notify_controllerchange */);
+ service_worker_provider_host_->SetDocumentUrl(GURL());
+ service_worker_provider_host_->SetTopmostFrameUrl(GURL());
+ }
+ }
return true;
}
}
@@ -1315,8 +1462,8 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
std::unique_ptr<NavigationLoaderInterceptor> CreateServiceWorkerInterceptor(
const NavigationRequestInfo& request_info,
- ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core)
- const {
+ ServiceWorkerNavigationHandleCore*
+ service_worker_navigation_handle_core) {
const ResourceType resource_type = request_info.is_main_frame
? RESOURCE_TYPE_MAIN_FRAME
: RESOURCE_TYPE_SUB_FRAME;
@@ -1332,7 +1479,7 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
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_);
+ web_contents_getter_, &service_worker_provider_host_);
}
void RecordSCTHistogramIfNeeded(
@@ -1445,6 +1592,10 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
// If true, redirect checks will be handled in a proxy, and not here.
bool bypass_redirect_checks_;
+ // Used to reset the state of ServiceWorkerProviderHost when
+ // SignedExchangeRequestHandler will handle the response.
+ base::WeakPtr<ServiceWorkerProviderHost> service_worker_provider_host_;
+
mutable base::WeakPtrFactory<URLLoaderRequestController> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(URLLoaderRequestController);
@@ -1483,7 +1634,12 @@ NavigationURLLoaderImpl::NavigationURLLoaderImpl(
std::unique_ptr<network::ResourceRequest> new_request = CreateResourceRequest(
request_info.get(), frame_tree_node_id, allow_download_);
- new_request->transition_type = request_info->common_params.transition;
+
+ auto* partition = static_cast<StoragePartitionImpl*>(storage_partition);
+ scoped_refptr<SignedExchangePrefetchMetricRecorder>
+ signed_exchange_prefetch_metric_recorder =
+ partition->GetPrefetchURLLoaderService()
+ ->signed_exchange_prefetch_metric_recorder();
if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) {
DCHECK(!request_controller_);
@@ -1496,16 +1652,17 @@ NavigationURLLoaderImpl::NavigationURLLoaderImpl(
/* proxied_url_loader_factory_info */ nullptr, std::set<std::string>(),
/* bypass_redirect_checks */ false, weak_factory_.GetWeakPtr());
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
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)));
+ base::Unretained(appcache_handle_core),
+ base::RetainedRef(signed_exchange_prefetch_metric_recorder),
+ std::move(request_info), std::move(navigation_ui_data)));
return;
}
@@ -1524,7 +1681,6 @@ NavigationURLLoaderImpl::NavigationURLLoaderImpl(
network::mojom::URLLoaderFactoryPtrInfo proxied_factory_info;
network::mojom::URLLoaderFactoryRequest proxied_factory_request;
bool bypass_redirect_checks = false;
- auto* partition = static_cast<StoragePartitionImpl*>(storage_partition);
if (frame_tree_node) {
// |frame_tree_node| may be null in some unit test environments.
GetContentClient()
@@ -1532,6 +1688,10 @@ NavigationURLLoaderImpl::NavigationURLLoaderImpl(
->RegisterNonNetworkNavigationURLLoaderFactories(
frame_tree_node_id, &non_network_url_loader_factories_);
+ // Navigation requests are not associated with any particular
+ // |network::ResourceRequest::request_initiator| origin - using an opaque
+ // origin instead.
+ url::Origin navigation_request_initiator = url::Origin();
// 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
@@ -1540,8 +1700,8 @@ NavigationURLLoaderImpl::NavigationURLLoaderImpl(
auto factory_request = mojo::MakeRequest(&factory_info);
bool use_proxy = GetContentClient()->browser()->WillCreateURLLoaderFactory(
partition->browser_context(), frame_tree_node->current_frame_host(),
- true /* is_navigation */, new_request->url, &factory_request);
- bypass_redirect_checks = use_proxy;
+ true /* is_navigation */, navigation_request_initiator,
+ &factory_request, &bypass_redirect_checks);
if (RenderFrameDevToolsAgentHost::WillCreateURLLoaderFactory(
frame_tree_node->current_frame_host(), true, false,
&factory_request)) {
@@ -1569,6 +1729,15 @@ NavigationURLLoaderImpl::NavigationURLLoaderImpl(
base::CreateSequencedTaskRunnerWithTraits(
{base::MayBlock(), base::TaskPriority::BEST_EFFORT,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}));
+
+#if defined(OS_ANDROID)
+ non_network_url_loader_factories_[url::kContentScheme] =
+ std::make_unique<ContentURLLoaderFactory>(
+ base::CreateSequencedTaskRunnerWithTraits(
+ {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+ base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}));
+#endif
+
std::set<std::string> known_schemes;
for (auto& iter : non_network_url_loader_factories_)
known_schemes.insert(iter.first);
@@ -1580,13 +1749,14 @@ NavigationURLLoaderImpl::NavigationURLLoaderImpl(
std::move(proxied_factory_request), std::move(proxied_factory_info),
std::move(known_schemes), bypass_redirect_checks,
weak_factory_.GetWeakPtr());
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&URLLoaderRequestController::Start,
base::Unretained(request_controller_.get()),
partition->url_loader_factory_getter()->GetNetworkFactoryInfo(),
service_worker_navigation_handle_core, appcache_handle_core,
+ std::move(signed_exchange_prefetch_metric_recorder),
std::move(request_info), std::move(navigation_ui_data),
std::move(factory_for_webui), frame_tree_node_id,
ServiceManagerConnection::GetForProcess()->GetConnector()->Clone()));
@@ -1601,8 +1771,8 @@ void NavigationURLLoaderImpl::FollowRedirect(
const base::Optional<std::vector<std::string>>&
to_be_removed_request_headers,
const base::Optional<net::HttpRequestHeaders>& modified_request_headers) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&URLLoaderRequestController::FollowRedirect,
base::Unretained(request_controller_.get()),
modified_request_headers));
@@ -1671,12 +1841,19 @@ void NavigationURLLoaderImpl::BindNonNetworkURLLoaderFactoryRequest(
DVLOG(1) << "Ignoring request with unknown scheme: " << url.spec();
return;
}
+
+ // Navigation requests are not associated with any particular
+ // |network::ResourceRequest::request_initiator| origin - using an opaque
+ // origin instead.
+ url::Origin navigation_request_initiator = url::Origin();
+
FrameTreeNode* frame_tree_node =
FrameTreeNode::GloballyFindByID(frame_tree_node_id);
auto* frame = frame_tree_node->current_frame_host();
GetContentClient()->browser()->WillCreateURLLoaderFactory(
frame->GetSiteInstance()->GetBrowserContext(), frame,
- true /* is_navigation */, url, &factory);
+ true /* is_navigation */, navigation_request_initiator, &factory,
+ nullptr /* bypass_redirect_checks */);
it->second->Clone(std::move(factory));
}
diff --git a/chromium/content/browser/loader/navigation_url_loader_impl_unittest.cc b/chromium/content/browser/loader/navigation_url_loader_impl_unittest.cc
index 37cf04dda21..1972331fefb 100644
--- a/chromium/content/browser/loader/navigation_url_loader_impl_unittest.cc
+++ b/chromium/content/browser/loader/navigation_url_loader_impl_unittest.cc
@@ -10,6 +10,7 @@
#include <vector>
#include "base/run_loop.h"
+#include "base/task/post_task.h"
#include "base/test/scoped_feature_list.h"
#include "base/unguessable_token.h"
#include "content/browser/frame_host/navigation_request_info.h"
@@ -19,6 +20,7 @@
#include "content/common/navigation_params.mojom.h"
#include "content/common/service_manager/service_manager_connection_impl.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/navigation_ui_data.h"
#include "content/public/browser/plugin_service.h"
@@ -99,7 +101,8 @@ class TestNavigationLoaderInterceptor : public NavigationLoaderInterceptor {
const network::ResourceResponseHead& response,
network::mojom::URLLoaderPtr* loader,
network::mojom::URLLoaderClientRequest* client_request,
- ThrottlingURLLoader* url_loader) override {
+ ThrottlingURLLoader* url_loader,
+ bool* skip_other_interceptors) override {
return false;
}
@@ -133,7 +136,7 @@ class NavigationURLLoaderImplTest : public testing::Test {
ServiceManagerConnection::SetForProcess(
std::make_unique<ServiceManagerConnectionImpl>(
mojo::MakeRequest(&service),
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)));
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO})));
browser_context_.reset(new TestBrowserContext);
http_test_server_.AddDefaultHandlers(
@@ -163,7 +166,7 @@ class NavigationURLLoaderImplTest : public testing::Test {
mojom::BeginNavigationParamsPtr begin_params =
mojom::BeginNavigationParams::New(
headers, net::LOAD_NORMAL, false /* skip_service_worker */,
- REQUEST_CONTEXT_TYPE_LOCATION,
+ blink::mojom::RequestContextType::LOCATION,
blink::WebMixedContentContextType::kBlockable,
false /* is_form_submission */, GURL() /* searchable_form_url */,
std::string() /* searchable_form_encoding */,
diff --git a/chromium/content/browser/loader/navigation_url_loader_unittest.cc b/chromium/content/browser/loader/navigation_url_loader_unittest.cc
index 75f70ba50a4..7a7eb768fcf 100644
--- a/chromium/content/browser/loader/navigation_url_loader_unittest.cc
+++ b/chromium/content/browser/loader/navigation_url_loader_unittest.cc
@@ -83,7 +83,8 @@ class NavigationURLLoaderTest : public testing::Test {
mojom::BeginNavigationParamsPtr begin_params =
mojom::BeginNavigationParams::New(
std::string() /* headers */, net::LOAD_NORMAL,
- false /* skip_service_worker */, REQUEST_CONTEXT_TYPE_LOCATION,
+ false /* skip_service_worker */,
+ blink::mojom::RequestContextType::LOCATION,
blink::WebMixedContentContextType::kBlockable,
false /* is_form_submission */, GURL() /* searchable_form_url */,
std::string() /* searchable_form_encoding */,
diff --git a/chromium/content/browser/loader/prefetch_browsertest.cc b/chromium/content/browser/loader/prefetch_browsertest.cc
index b3776b2bac6..011142e91ae 100644
--- a/chromium/content/browser/loader/prefetch_browsertest.cc
+++ b/chromium/content/browser/loader/prefetch_browsertest.cc
@@ -10,11 +10,13 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/task/post_task.h"
#include "base/test/scoped_feature_list.h"
#include "content/browser/loader/prefetch_url_loader_service.h"
#include "content/browser/storage_partition_impl.h"
#include "content/browser/web_package/mock_signed_exchange_handler.h"
#include "content/browser/web_package/signed_exchange_loader.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_features.h"
@@ -77,8 +79,8 @@ class PrefetchBrowserTest
StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
BrowserContext::GetDefaultStoragePartition(
shell()->web_contents()->GetBrowserContext()));
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
BindOnce(
&PrefetchURLLoaderService::RegisterPrefetchLoaderCallbackForTest,
base::RetainedRef(partition->GetPrefetchURLLoaderService()),
@@ -108,13 +110,10 @@ class PrefetchBrowserTest
void WatchURLAndRunClosure(
const std::string& relative_url,
int* visit_count,
- net::test_server::HttpRequest::HeaderMap* out_headers,
base::OnceClosure closure,
const net::test_server::HttpRequest& request) {
if (request.relative_url == relative_url) {
(*visit_count)++;
- if (out_headers)
- *out_headers = request.headers;
if (closure)
std::move(closure).Run();
}
@@ -151,7 +150,7 @@ IN_PROC_BROWSER_TEST_P(PrefetchBrowserTest, Simple) {
base::RunLoop prefetch_waiter;
embedded_test_server()->RegisterRequestMonitor(base::BindRepeating(
&PrefetchBrowserTest::WatchURLAndRunClosure, base::Unretained(this),
- target_url, &target_fetch_count, nullptr, prefetch_waiter.QuitClosure()));
+ target_url, &target_fetch_count, prefetch_waiter.QuitClosure()));
embedded_test_server()->RegisterRequestHandler(base::BindRepeating(
&PrefetchBrowserTest::ServeResponses, base::Unretained(this)));
ASSERT_TRUE(embedded_test_server()->Start());
@@ -189,7 +188,7 @@ IN_PROC_BROWSER_TEST_P(PrefetchBrowserTest, DoublePrefetch) {
base::RunLoop prefetch_waiter;
embedded_test_server()->RegisterRequestMonitor(base::BindRepeating(
&PrefetchBrowserTest::WatchURLAndRunClosure, base::Unretained(this),
- target_url, &target_fetch_count, nullptr, prefetch_waiter.QuitClosure()));
+ target_url, &target_fetch_count, prefetch_waiter.QuitClosure()));
embedded_test_server()->RegisterRequestHandler(base::BindRepeating(
&PrefetchBrowserTest::ServeResponses, base::Unretained(this)));
ASSERT_TRUE(embedded_test_server()->Start());
@@ -236,12 +235,10 @@ IN_PROC_BROWSER_TEST_P(PrefetchBrowserTest, NoCacheAndNoStore) {
base::RunLoop nostore_waiter;
embedded_test_server()->RegisterRequestMonitor(base::BindRepeating(
&PrefetchBrowserTest::WatchURLAndRunClosure, base::Unretained(this),
- nocache_url, &nocache_fetch_count, nullptr,
- nocache_waiter.QuitClosure()));
+ nocache_url, &nocache_fetch_count, nocache_waiter.QuitClosure()));
embedded_test_server()->RegisterRequestMonitor(base::BindRepeating(
&PrefetchBrowserTest::WatchURLAndRunClosure, base::Unretained(this),
- nostore_url, &nostore_fetch_count, nullptr,
- nostore_waiter.QuitClosure()));
+ nostore_url, &nostore_fetch_count, nostore_waiter.QuitClosure()));
embedded_test_server()->RegisterRequestHandler(base::BindRepeating(
&PrefetchBrowserTest::ServeResponses, base::Unretained(this)));
ASSERT_TRUE(embedded_test_server()->Start());
@@ -298,11 +295,10 @@ IN_PROC_BROWSER_TEST_P(PrefetchBrowserTest, WithPreload) {
base::RunLoop preload_waiter;
embedded_test_server()->RegisterRequestMonitor(base::BindRepeating(
&PrefetchBrowserTest::WatchURLAndRunClosure, base::Unretained(this),
- target_url, &target_fetch_count, nullptr, base::RepeatingClosure()));
+ target_url, &target_fetch_count, base::RepeatingClosure()));
embedded_test_server()->RegisterRequestMonitor(base::BindRepeating(
&PrefetchBrowserTest::WatchURLAndRunClosure, base::Unretained(this),
- preload_url, &preload_fetch_count, nullptr,
- preload_waiter.QuitClosure()));
+ preload_url, &preload_fetch_count, preload_waiter.QuitClosure()));
embedded_test_server()->RegisterRequestHandler(base::BindRepeating(
&PrefetchBrowserTest::ServeResponses, base::Unretained(this)));
ASSERT_TRUE(embedded_test_server()->Start());
@@ -353,22 +349,20 @@ IN_PROC_BROWSER_TEST_P(PrefetchBrowserTest, WebPackageWithPreload) {
base::RunLoop preload_waiter;
base::RunLoop prefetch_waiter;
- net::test_server::HttpRequest::HeaderMap prefetch_headers;
embedded_test_server()->RegisterRequestMonitor(base::BindRepeating(
&PrefetchBrowserTest::WatchURLAndRunClosure, base::Unretained(this),
- target_sxg, &target_fetch_count, &prefetch_headers,
- prefetch_waiter.QuitClosure()));
+ target_sxg, &target_fetch_count, prefetch_waiter.QuitClosure()));
embedded_test_server()->RegisterRequestMonitor(base::BindRepeating(
&PrefetchBrowserTest::WatchURLAndRunClosure, base::Unretained(this),
- preload_url_in_sxg, &preload_fetch_count, nullptr,
- preload_waiter.QuitClosure()));
+ preload_url_in_sxg, &preload_fetch_count, preload_waiter.QuitClosure()));
embedded_test_server()->RegisterRequestHandler(base::BindRepeating(
&PrefetchBrowserTest::ServeResponses, base::Unretained(this)));
ASSERT_TRUE(embedded_test_server()->Start());
EXPECT_TRUE(CheckPrefetchURLLoaderCountIfSupported(0));
MockSignedExchangeHandlerFactory factory(
- net::OK, GURL(embedded_test_server()->GetURL(target_url)), "text/html",
+ SignedExchangeLoadResult::kSuccess, net::OK,
+ GURL(embedded_test_server()->GetURL(target_url)), "text/html",
{base::StringPrintf(
"Link: <%s>;rel=\"preload\";as=\"script\"",
embedded_test_server()->GetURL(preload_url_in_sxg).spec().c_str())});
@@ -380,11 +374,6 @@ IN_PROC_BROWSER_TEST_P(PrefetchBrowserTest, WebPackageWithPreload) {
prefetch_waiter.Run();
EXPECT_EQ(1, target_fetch_count);
EXPECT_TRUE(CheckPrefetchURLLoaderCountIfSupported(1));
- if (base::FeatureList::IsEnabled(features::kSignedHTTPExchange))
- EXPECT_EQ(prefetch_headers["Accept"],
- "application/signed-exchange;v=b2;q=0.9,*/*;q=0.8");
- else
- EXPECT_EQ(prefetch_headers["Accept"], "*/*");
// Test after this point requires SignedHTTPExchange support
if (!base::FeatureList::IsEnabled(features::kSignedHTTPExchange))
diff --git a/chromium/content/browser/loader/prefetch_url_loader.cc b/chromium/content/browser/loader/prefetch_url_loader.cc
index bbfd85fcc3c..63f58daf2ca 100644
--- a/chromium/content/browser/loader/prefetch_url_loader.cc
+++ b/chromium/content/browser/loader/prefetch_url_loader.cc
@@ -6,14 +6,23 @@
#include "base/feature_list.h"
#include "content/browser/web_package/signed_exchange_prefetch_handler.h"
+#include "content/browser/web_package/signed_exchange_prefetch_metric_recorder.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/loader_util.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
namespace content {
+namespace {
+
+constexpr char kSignedExchangeEnabledAcceptHeaderForPrefetch[] =
+ "application/signed-exchange;v=b2;q=0.9,*/*;q=0.8";
+
+} // namespace
+
PrefetchURLLoader::PrefetchURLLoader(
int32_t routing_id,
int32_t request_id,
@@ -25,7 +34,9 @@ PrefetchURLLoader::PrefetchURLLoader(
scoped_refptr<network::SharedURLLoaderFactory> network_loader_factory,
URLLoaderThrottlesGetter url_loader_throttles_getter,
ResourceContext* resource_context,
- scoped_refptr<net::URLRequestContextGetter> request_context_getter)
+ scoped_refptr<net::URLRequestContextGetter> request_context_getter,
+ scoped_refptr<SignedExchangePrefetchMetricRecorder>
+ signed_exchange_prefetch_metric_recorder)
: frame_tree_node_id_getter_(frame_tree_node_id_getter),
url_(resource_request.url),
report_raw_headers_(resource_request.report_raw_headers),
@@ -36,19 +47,32 @@ PrefetchURLLoader::PrefetchURLLoader(
forwarding_client_(std::move(client)),
url_loader_throttles_getter_(url_loader_throttles_getter),
resource_context_(resource_context),
- request_context_getter_(std::move(request_context_getter)) {
+ request_context_getter_(std::move(request_context_getter)),
+ signed_exchange_prefetch_metric_recorder_(
+ std::move(signed_exchange_prefetch_metric_recorder)) {
DCHECK(network_loader_factory_);
if (resource_request.request_initiator)
request_initiator_ = *resource_request.request_initiator;
+ base::Optional<network::ResourceRequest> modified_resource_request;
+ if (signed_exchange_utils::ShouldAdvertiseAcceptHeader(
+ url::Origin::Create(resource_request.url))) {
+ // Set the SignedExchange accept header only for the limited origins.
+ // (https://wicg.github.io/webpackage/draft-yasskin-http-origin-signed-responses.html#internet-media-type-applicationsigned-exchange).
+ modified_resource_request = resource_request;
+ modified_resource_request->headers.SetHeader(
+ network::kAcceptHeader, kSignedExchangeEnabledAcceptHeaderForPrefetch);
+ }
+
network::mojom::URLLoaderClientPtr network_client;
client_binding_.Bind(mojo::MakeRequest(&network_client));
client_binding_.set_connection_error_handler(base::BindOnce(
&PrefetchURLLoader::OnNetworkConnectionError, base::Unretained(this)));
network_loader_factory_->CreateLoaderAndStart(
mojo::MakeRequest(&loader_), routing_id, request_id, options,
- resource_request, std::move(network_client), traffic_annotation);
+ modified_resource_request ? *modified_resource_request : resource_request,
+ std::move(network_client), traffic_annotation);
}
PrefetchURLLoader::~PrefetchURLLoader() = default;
@@ -60,6 +84,7 @@ void PrefetchURLLoader::FollowRedirect(
DCHECK(!modified_request_headers.has_value()) << "Redirect with modified "
"headers was not supported "
"yet. crbug.com/845683";
+ DCHECK(new_url_for_redirect_.is_valid());
if (signed_exchange_prefetch_handler_) {
// Rebind |client_binding_| and |loader_|.
client_binding_.Bind(signed_exchange_prefetch_handler_->FollowRedirect(
@@ -67,6 +92,25 @@ void PrefetchURLLoader::FollowRedirect(
return;
}
+ if (signed_exchange_utils::NeedToCheckRedirectedURLForAcceptHeader()) {
+ // Currently we send the SignedExchange accept header only for the limited
+ // origins when SignedHTTPExchangeOriginTrial feature is enabled without
+ // SignedHTTPExchange feature. So need to update the accept header by
+ // checking the new URL when redirected.
+ net::HttpRequestHeaders modified_request_headers_for_accept;
+ if (signed_exchange_utils::ShouldAdvertiseAcceptHeader(
+ url::Origin::Create(new_url_for_redirect_))) {
+ modified_request_headers_for_accept.SetHeader(
+ network::kAcceptHeader,
+ kSignedExchangeEnabledAcceptHeaderForPrefetch);
+ } else {
+ modified_request_headers_for_accept.SetHeader(
+ network::kAcceptHeader, network::kDefaultAcceptHeader);
+ }
+ loader_->FollowRedirect(base::nullopt, modified_request_headers_for_accept);
+ return;
+ }
+
loader_->FollowRedirect(base::nullopt, base::nullopt);
}
@@ -100,7 +144,8 @@ void PrefetchURLLoader::OnReceiveResponse(
throttling_profile_id_, response, std::move(loader_),
client_binding_.Unbind(), network_loader_factory_,
request_initiator_, url_, url_loader_throttles_getter_,
- resource_context_, request_context_getter_, this);
+ resource_context_, request_context_getter_, this,
+ signed_exchange_prefetch_metric_recorder_);
return;
}
forwarding_client_->OnReceiveResponse(response);
@@ -109,6 +154,7 @@ void PrefetchURLLoader::OnReceiveResponse(
void PrefetchURLLoader::OnReceiveRedirect(
const net::RedirectInfo& redirect_info,
const network::ResourceResponseHead& head) {
+ new_url_for_redirect_ = redirect_info.new_url;
forwarding_client_->OnReceiveRedirect(redirect_info, head);
}
diff --git a/chromium/content/browser/loader/prefetch_url_loader.h b/chromium/content/browser/loader/prefetch_url_loader.h
index ef4ff33677d..7fc4bcb594c 100644
--- a/chromium/content/browser/loader/prefetch_url_loader.h
+++ b/chromium/content/browser/loader/prefetch_url_loader.h
@@ -31,6 +31,7 @@ namespace content {
class ResourceContext;
class URLLoaderThrottle;
class SignedExchangePrefetchHandler;
+class SignedExchangePrefetchMetricRecorder;
// PrefetchURLLoader which basically just keeps draining the data.
class CONTENT_EXPORT PrefetchURLLoader : public network::mojom::URLLoader,
@@ -57,7 +58,9 @@ class CONTENT_EXPORT PrefetchURLLoader : public network::mojom::URLLoader,
scoped_refptr<network::SharedURLLoaderFactory> network_loader_factory,
URLLoaderThrottlesGetter url_loader_throttles_getter,
ResourceContext* resource_context,
- scoped_refptr<net::URLRequestContextGetter> request_context_getter);
+ scoped_refptr<net::URLRequestContextGetter> request_context_getter,
+ scoped_refptr<SignedExchangePrefetchMetricRecorder>
+ signed_exchange_prefetch_metric_recorder);
~PrefetchURLLoader() override;
private:
@@ -120,6 +123,11 @@ class CONTENT_EXPORT PrefetchURLLoader : public network::mojom::URLLoader,
std::unique_ptr<SignedExchangePrefetchHandler>
signed_exchange_prefetch_handler_;
+ GURL new_url_for_redirect_;
+
+ scoped_refptr<SignedExchangePrefetchMetricRecorder>
+ signed_exchange_prefetch_metric_recorder_;
+
DISALLOW_COPY_AND_ASSIGN(PrefetchURLLoader);
};
diff --git a/chromium/content/browser/loader/prefetch_url_loader_service.cc b/chromium/content/browser/loader/prefetch_url_loader_service.cc
index b7baa69c5cf..497ee220309 100644
--- a/chromium/content/browser/loader/prefetch_url_loader_service.cc
+++ b/chromium/content/browser/loader/prefetch_url_loader_service.cc
@@ -17,12 +17,13 @@
#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"
+#include "third_party/blink/public/common/features.h"
namespace content {
struct PrefetchURLLoaderService::BindContext {
BindContext(int frame_tree_node_id,
- scoped_refptr<URLLoaderFactoryBundle> factory)
+ scoped_refptr<network::SharedURLLoaderFactory> factory)
: frame_tree_node_id(frame_tree_node_id), factory(factory) {}
explicit BindContext(const std::unique_ptr<BindContext>& other)
@@ -32,10 +33,12 @@ struct PrefetchURLLoaderService::BindContext {
~BindContext() = default;
const int frame_tree_node_id;
- scoped_refptr<URLLoaderFactoryBundle> factory;
+ scoped_refptr<network::SharedURLLoaderFactory> factory;
};
-PrefetchURLLoaderService::PrefetchURLLoaderService() = default;
+PrefetchURLLoaderService::PrefetchURLLoaderService()
+ : signed_exchange_prefetch_metric_recorder_(
+ base::MakeRefCounted<SignedExchangePrefetchMetricRecorder>()) {}
void PrefetchURLLoaderService::InitializeResourceContext(
ResourceContext* resource_context,
@@ -50,10 +53,10 @@ void PrefetchURLLoaderService::InitializeResourceContext(
void PrefetchURLLoaderService::GetFactory(
network::mojom::URLLoaderFactoryRequest request,
int frame_tree_node_id,
- std::unique_ptr<URLLoaderFactoryBundleInfo> factories) {
+ std::unique_ptr<network::SharedURLLoaderFactoryInfo> factories) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
auto factory_bundle =
- base::MakeRefCounted<URLLoaderFactoryBundle>(std::move(factories));
+ network::SharedURLLoaderFactory::Create(std::move(factories));
loader_factory_bindings_.AddBinding(
this, std::move(request),
std::make_unique<BindContext>(frame_tree_node_id, factory_bundle));
@@ -88,7 +91,8 @@ void PrefetchURLLoaderService::CreateLoaderAndStart(
base::BindRepeating(
&PrefetchURLLoaderService::CreateURLLoaderThrottles, this,
resource_request, frame_tree_node_id_getter),
- resource_context_, request_context_getter_),
+ resource_context_, request_context_getter_,
+ signed_exchange_prefetch_metric_recorder_),
std::move(request));
}
@@ -103,7 +107,9 @@ void PrefetchURLLoaderService::CreateLoaderAndStart(
network::mojom::URLLoaderClientPtr client,
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(base::FeatureList::IsEnabled(network::features::kNetworkService));
+ DCHECK(base::FeatureList::IsEnabled(network::features::kNetworkService) ||
+ base::FeatureList::IsEnabled(
+ blink::features::kServiceWorkerServicification));
const auto& dispatch_context = *loader_factory_bindings_.dispatch_context();
int frame_tree_node_id = dispatch_context.frame_tree_node_id;
CreateLoaderAndStart(
diff --git a/chromium/content/browser/loader/prefetch_url_loader_service.h b/chromium/content/browser/loader/prefetch_url_loader_service.h
index 69c241394f2..2fafbffa238 100644
--- a/chromium/content/browser/loader/prefetch_url_loader_service.h
+++ b/chromium/content/browser/loader/prefetch_url_loader_service.h
@@ -8,6 +8,7 @@
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "content/browser/web_package/signed_exchange_prefetch_metric_recorder.h"
#include "content/common/content_export.h"
#include "content/common/url_loader_factory_bundle.h"
#include "content/public/browser/browser_thread.h"
@@ -20,7 +21,6 @@ class URLRequestContextGetter;
namespace network {
class SharedURLLoaderFactory;
-class URLLoaderFactoryBundleInfo;
}
namespace content {
@@ -42,9 +42,10 @@ class CONTENT_EXPORT PrefetchURLLoaderService final
ResourceContext* resource_context,
scoped_refptr<net::URLRequestContextGetter> request_context_getter);
- void GetFactory(network::mojom::URLLoaderFactoryRequest request,
- int frame_tree_node_id,
- std::unique_ptr<URLLoaderFactoryBundleInfo> factory_info);
+ void GetFactory(
+ network::mojom::URLLoaderFactoryRequest request,
+ int frame_tree_node_id,
+ std::unique_ptr<network::SharedURLLoaderFactoryInfo> factory_info);
// Used only when NetworkService is not enabled (or indirectly via the
// other CreateLoaderAndStart when NetworkService is enabled).
@@ -70,6 +71,11 @@ class CONTENT_EXPORT PrefetchURLLoaderService final
prefetch_load_callback_for_testing_ = prefetch_load_callback;
}
+ scoped_refptr<SignedExchangePrefetchMetricRecorder>
+ signed_exchange_prefetch_metric_recorder() {
+ return signed_exchange_prefetch_metric_recorder_;
+ }
+
private:
friend class base::DeleteHelper<content::PrefetchURLLoaderService>;
friend struct BrowserThread::DeleteOnThread<BrowserThread::IO>;
@@ -104,6 +110,9 @@ class CONTENT_EXPORT PrefetchURLLoaderService final
base::RepeatingClosure prefetch_load_callback_for_testing_;
+ scoped_refptr<SignedExchangePrefetchMetricRecorder>
+ signed_exchange_prefetch_metric_recorder_;
+
DISALLOW_COPY_AND_ASSIGN(PrefetchURLLoaderService);
};
diff --git a/chromium/content/browser/loader/resource_dispatcher_host_impl.cc b/chromium/content/browser/loader/resource_dispatcher_host_impl.cc
index 2ed617dbab8..8f33f39eb1d 100644
--- a/chromium/content/browser/loader/resource_dispatcher_host_impl.cc
+++ b/chromium/content/browser/loader/resource_dispatcher_host_impl.cc
@@ -373,8 +373,7 @@ void ResourceDispatcherHostImpl::CancelRequestsForContext(
typedef std::vector<std::unique_ptr<ResourceLoader>> LoaderList;
LoaderList loaders_to_cancel;
- for (LoaderMap::iterator i = pending_loaders_.begin();
- i != pending_loaders_.end();) {
+ for (auto i = pending_loaders_.begin(); i != pending_loaders_.end();) {
ResourceLoader* loader = i->second.get();
if (loader->GetRequestInfo()->GetContext() == context) {
loaders_to_cancel.push_back(std::move(i->second));
@@ -389,7 +388,7 @@ void ResourceDispatcherHostImpl::CancelRequestsForContext(
}
}
- for (BlockedLoadersMap::iterator i = blocked_loaders_map_.begin();
+ for (auto i = blocked_loaders_map_.begin();
i != blocked_loaders_map_.end();) {
BlockedLoadersList* loaders = i->second.get();
if (loaders->empty()) {
@@ -771,8 +770,7 @@ void ResourceDispatcherHostImpl::BeginRequest(
// 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());
+ auto index = http_header_interceptor_map_.find(it.name());
if (index != http_header_interceptor_map_.end()) {
HeaderInterceptorInfo& interceptor_info = index->second;
@@ -896,6 +894,11 @@ void ResourceDispatcherHostImpl::ContinuePendingBeginRequest(
new_request->set_referrer_policy(request_data.referrer_policy);
new_request->SetExtraRequestHeaders(headers);
+ if (!request_data.requested_with.empty()) {
+ // X-Requested-With header must be set here to avoid breaking CORS checks.
+ new_request->SetExtraRequestHeaderByName("X-Requested-With",
+ request_data.requested_with, true);
+ }
std::unique_ptr<network::ScopedThrottlingToken> throttling_token =
network::ScopedThrottlingToken::MaybeCreate(
@@ -984,6 +987,8 @@ void ResourceDispatcherHostImpl::ContinuePendingBeginRequest(
-1, // frame_tree_node_id
request_data.plugin_child_id, request_id, request_data.render_frame_id,
request_data.is_main_frame,
+ request_data.fetch_window_id ? *request_data.fetch_window_id
+ : base::UnguessableToken(),
static_cast<ResourceType>(request_data.resource_type),
static_cast<ui::PageTransition>(request_data.transition_type),
false, // is download
@@ -1019,7 +1024,8 @@ void ResourceDispatcherHostImpl::ContinuePendingBeginRequest(
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),
+ static_cast<blink::mojom::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.
@@ -1038,7 +1044,8 @@ void ResourceDispatcherHostImpl::ContinuePendingBeginRequest(
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;
+ request_data.fetch_request_context_type ==
+ static_cast<int>(blink::mojom::RequestContextType::FETCH);
BeginRequestInternal(std::move(new_request), std::move(handler),
is_initiated_by_fetch_api,
std::move(throttling_token));
@@ -1078,7 +1085,8 @@ ResourceDispatcherHostImpl::CreateResourceHandler(
return AddStandardHandlers(
request, static_cast<ResourceType>(request_data.resource_type),
resource_context, request_data.fetch_request_mode,
- static_cast<RequestContextType>(request_data.fetch_request_context_type),
+ static_cast<blink::mojom::RequestContextType>(
+ request_data.fetch_request_context_type),
url_loader_options, requester_info->appcache_service(), child_id,
route_id, std::move(handler));
}
@@ -1089,7 +1097,7 @@ ResourceDispatcherHostImpl::AddStandardHandlers(
ResourceType resource_type,
ResourceContext* resource_context,
network::mojom::FetchRequestMode fetch_request_mode,
- RequestContextType fetch_request_context_type,
+ blink::mojom::RequestContextType fetch_request_context_type,
uint32_t url_loader_options,
AppCacheService* appcache_service,
int child_id,
@@ -1186,6 +1194,7 @@ ResourceRequestInfoImpl* ResourceDispatcherHostImpl::CreateRequestInfo(
ChildProcessHost::kInvalidUniqueID, // plugin_child_id
MakeRequestID(), render_frame_route_id,
false, // is_main_frame
+ {}, // fetch_window_id
RESOURCE_TYPE_SUB_RESOURCE, ui::PAGE_TRANSITION_LINK,
download, // is_download
false, // is_stream
@@ -1206,24 +1215,38 @@ ResourceRequestInfoImpl* ResourceDispatcherHostImpl::CreateRequestInfo(
false); // initiated_in_secure_context
}
+// static
void ResourceDispatcherHostImpl::OnRenderViewHostCreated(
int child_id,
int route_id,
net::URLRequestContextGetter* url_request_context_getter) {
- scheduler_->OnClientCreated(child_id, route_id,
- url_request_context_getter->GetURLRequestContext()
- ->network_quality_estimator());
+ auto* host = ResourceDispatcherHostImpl::Get();
+ if (host && host->scheduler_) {
+ host->scheduler_->OnClientCreated(
+ child_id, route_id,
+ url_request_context_getter->GetURLRequestContext()
+ ->network_quality_estimator());
+ }
}
+// static
void ResourceDispatcherHostImpl::OnRenderViewHostDeleted(int child_id,
int route_id) {
- scheduler_->OnClientDeleted(child_id, route_id);
+ auto* host = ResourceDispatcherHostImpl::Get();
+ if (host && host->scheduler_) {
+ host->scheduler_->OnClientDeleted(child_id, route_id);
+ }
}
+// static
void ResourceDispatcherHostImpl::OnRenderViewHostSetIsLoading(int child_id,
int route_id,
bool is_loading) {
- scheduler_->DeprecatedOnLoadingStateChanged(child_id, route_id, !is_loading);
+ auto* host = ResourceDispatcherHostImpl::Get();
+ if (host && host->scheduler_) {
+ host->scheduler_->DeprecatedOnLoadingStateChanged(child_id, route_id,
+ !is_loading);
+ }
}
// The object died, so cancel and detach all requests associated with it except
@@ -1273,7 +1296,7 @@ void ResourceDispatcherHostImpl::CancelRequestsForRoute(
// Remove matches.
for (size_t i = 0; i < matching_requests.size(); ++i) {
- LoaderMap::iterator iter = pending_loaders_.find(matching_requests[i]);
+ auto iter = pending_loaders_.find(matching_requests[i]);
// Although every matching request was in pending_requests_ when we built
// matching_requests, it is normal for a matching request to be not found
// in pending_requests_ after we have removed some matching requests from
@@ -1312,8 +1335,7 @@ void ResourceDispatcherHostImpl::CancelRequestsForRoute(
// Cancels the request and removes it from the list.
void ResourceDispatcherHostImpl::RemovePendingRequest(int child_id,
int request_id) {
- LoaderMap::iterator i = pending_loaders_.find(
- GlobalRequestID(child_id, request_id));
+ auto i = pending_loaders_.find(GlobalRequestID(child_id, request_id));
if (i == pending_loaders_.end()) {
NOTREACHED() << "Trying to remove a request that's not here";
return;
@@ -1352,8 +1374,7 @@ void ResourceDispatcherHostImpl::CancelRequest(int child_id,
ResourceDispatcherHostImpl::OustandingRequestsStats
ResourceDispatcherHostImpl::GetOutstandingRequestsStats(
const ResourceRequestInfoImpl& info) {
- OutstandingRequestsStatsMap::iterator entry =
- outstanding_requests_stats_map_.find(info.GetChildID());
+ auto entry = outstanding_requests_stats_map_.find(info.GetChildID());
OustandingRequestsStats stats = { 0, 0 };
if (entry != outstanding_requests_stats_map_.end())
stats = entry->second;
@@ -1502,10 +1523,8 @@ void ResourceDispatcherHostImpl::BeginNavigationRequest(
headers.AddHeadersFromString(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()) {
+ if (signed_exchange_utils::ShouldAdvertiseAcceptHeader(
+ url::Origin::Create(info.common_params.url))) {
DCHECK(!accept_value.empty());
accept_value.append(kAcceptHeaderSignedExchangeSuffix);
}
@@ -1552,8 +1571,9 @@ void ResourceDispatcherHostImpl::BeginNavigationRequest(
info.frame_tree_node_id,
ChildProcessHost::kInvalidUniqueID, // plugin_child_id
global_request_id.request_id,
- -1, // request_data.render_frame_id,
- info.is_main_frame, resource_type, info.common_params.transition,
+ -1, // request_data.render_frame_id,
+ info.is_main_frame, {}, // fetch_window_id
+ resource_type, info.common_params.transition,
false, // is download
false, // is stream
info.common_params.allow_download, info.common_params.has_user_gesture,
@@ -2047,8 +2067,7 @@ void ResourceDispatcherHostImpl::CancelBlockedRequestsForRoute(
void ResourceDispatcherHostImpl::ProcessBlockedRequestsForRoute(
const GlobalFrameRoutingId& global_routing_id,
bool cancel_requests) {
- BlockedLoadersMap::iterator iter =
- blocked_loaders_map_.find(global_routing_id);
+ auto iter = blocked_loaders_map_.find(global_routing_id);
if (iter == blocked_loaders_map_.end()) {
// It's possible to reach here if the renderer crashed while an interstitial
// page was showing.
@@ -2104,7 +2123,7 @@ ResourceLoader* ResourceDispatcherHostImpl::GetLoader(
const GlobalRequestID& id) const {
DCHECK(io_thread_task_runner_->BelongsToCurrentThread());
- LoaderMap::const_iterator i = pending_loaders_.find(id);
+ auto i = pending_loaders_.find(id);
if (i == pending_loaders_.end())
return nullptr;
diff --git a/chromium/content/browser/loader/resource_dispatcher_host_impl.h b/chromium/content/browser/loader/resource_dispatcher_host_impl.h
index ec89329e361..7e03c2b4bef 100644
--- a/chromium/content/browser/loader/resource_dispatcher_host_impl.h
+++ b/chromium/content/browser/loader/resource_dispatcher_host_impl.h
@@ -37,13 +37,13 @@
#include "content/public/browser/resource_request_info.h"
#include "content/public/browser/stream_handle.h"
#include "content/public/common/previews_state.h"
-#include "content/public/common/request_context_type.h"
#include "content/public/common/resource_type.h"
#include "net/base/load_states.h"
#include "net/base/request_priority.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "services/network/keepalive_statistics_recorder.h"
#include "services/network/public/mojom/url_loader.mojom.h"
+#include "third_party/blink/public/platform/modules/fetch/fetch_api_request.mojom.h"
#include "url/gurl.h"
namespace base {
@@ -146,18 +146,18 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
static const int kAvgBytesPerOutstandingRequest = 4400;
// Called when a RenderViewHost is created.
- void OnRenderViewHostCreated(
+ static void OnRenderViewHostCreated(
int child_id,
int route_id,
net::URLRequestContextGetter* url_request_context_getter);
// Called when a RenderViewHost is deleted.
- void OnRenderViewHostDeleted(int child_id, int route_id);
+ static void OnRenderViewHostDeleted(int child_id, int route_id);
// Called when a RenderViewHost starts or stops loading.
- void OnRenderViewHostSetIsLoading(int child_id,
- int route_id,
- bool is_loading);
+ static void OnRenderViewHostSetIsLoading(int child_id,
+ int route_id,
+ bool is_loading);
// Force cancels any pending requests for the given process.
void CancelRequestsForProcess(int child_id);
@@ -596,7 +596,7 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
ResourceType resource_type,
ResourceContext* resource_context,
network::mojom::FetchRequestMode fetch_request_mode,
- RequestContextType fetch_request_context_type,
+ blink::mojom::RequestContextType fetch_request_context_type,
uint32_t url_loader_options,
AppCacheService* appcache_service,
int child_id,
diff --git a/chromium/content/browser/loader/resource_dispatcher_host_unittest.cc b/chromium/content/browser/loader/resource_dispatcher_host_unittest.cc
index 38053a77162..eeaff0cc5a2 100644
--- a/chromium/content/browser/loader/resource_dispatcher_host_unittest.cc
+++ b/chromium/content/browser/loader/resource_dispatcher_host_unittest.cc
@@ -36,6 +36,7 @@
#include "content/common/appcache_interfaces.h"
#include "content/common/child_process_host_impl.h"
#include "content/common/navigation_params.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/global_request_id.h"
#include "content/public/browser/render_frame_host.h"
@@ -77,12 +78,14 @@
#include "net/url_request/url_request_simple_job.h"
#include "net/url_request/url_request_test_job.h"
#include "net/url_request/url_request_test_util.h"
+#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/resource_scheduler.h"
#include "services/network/resource_scheduler_params_manager.h"
#include "services/network/test/test_url_loader_client.h"
#include "storage/browser/blob/shareable_file_reference.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/mojom/page/page_visibility_state.mojom.h"
// TODO(eroman): Write unit tests for SafeBrowsing that exercise
@@ -118,8 +121,7 @@ static network::ResourceRequest CreateResourceRequest(const char* method,
// This is used to create a filter matching a specified child id.
class TestFilterSpecifyingChild : public ResourceMessageFilter {
public:
- explicit TestFilterSpecifyingChild(ResourceContext* resource_context,
- int process_id)
+ TestFilterSpecifyingChild(BrowserContext* browser_context, int process_id)
: ResourceMessageFilter(
process_id,
nullptr,
@@ -127,10 +129,11 @@ class TestFilterSpecifyingChild : public ResourceMessageFilter {
nullptr,
nullptr,
nullptr,
+ BrowserContext::GetSharedCorsOriginAccessList(browser_context),
base::Bind(&TestFilterSpecifyingChild::GetContexts,
base::Unretained(this)),
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)),
- resource_context_(resource_context) {
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO})),
+ resource_context_(browser_context->GetResourceContext()) {
InitializeForTest();
set_peer_process_for_testing(base::Process::Current());
}
@@ -161,9 +164,9 @@ class TestFilterSpecifyingChild : public ResourceMessageFilter {
class TestFilter : public TestFilterSpecifyingChild {
public:
- explicit TestFilter(ResourceContext* resource_context)
+ explicit TestFilter(BrowserContext* browser_context)
: TestFilterSpecifyingChild(
- resource_context,
+ browser_context,
ChildProcessHostImpl::GenerateChildProcessUniqueId()) {
ChildProcessSecurityPolicyImpl::GetInstance()->Add(child_id());
}
@@ -630,7 +633,12 @@ class ShareableFileReleaseWaiter {
DISALLOW_COPY_AND_ASSIGN(ShareableFileReleaseWaiter);
};
-class ResourceDispatcherHostTest : public testing::Test {
+enum class TestMode {
+ kWithoutOutOfBlinkCors,
+ kWithOutOfBlinkCors,
+};
+
+class ResourceDispatcherHostTest : public testing::TestWithParam<TestMode> {
public:
typedef ResourceDispatcherHostImpl::LoadInfo LoadInfo;
typedef ResourceDispatcherHostImpl::LoadInfoList LoadInfoList;
@@ -644,6 +652,23 @@ class ResourceDispatcherHostTest : public testing::Test {
use_test_ssl_certificate_(false),
send_data_received_acks_(false),
auto_advance_(false) {
+ switch (GetParam()) {
+ case TestMode::kWithoutOutOfBlinkCors:
+ scoped_feature_list_.InitWithFeatures(
+ // Enabled features
+ {},
+ // Disabled features
+ {network::features::kOutOfBlinkCORS});
+ break;
+ case TestMode::kWithOutOfBlinkCors:
+ scoped_feature_list_.InitWithFeatures(
+ // Enabled features
+ {network::features::kOutOfBlinkCORS,
+ blink::features::kServiceWorkerServicification},
+ // Disabled features
+ {});
+ break;
+ }
host_.SetLoaderDelegate(&loader_delegate_);
browser_context_.reset(new TestBrowserContext());
BrowserContext::EnsureResourceContextInitialized(browser_context_.get());
@@ -676,12 +701,12 @@ class ResourceDispatcherHostTest : public testing::Test {
web_contents_ =
WebContents::Create(WebContents::CreateParams(browser_context_.get()));
web_contents_filter_ = new TestFilterSpecifyingChild(
- browser_context_->GetResourceContext(),
+ browser_context_.get(),
web_contents_->GetMainFrame()->GetProcess()->GetID());
child_ids_.insert(web_contents_->GetMainFrame()->GetProcess()->GetID());
request_context_getter_ = new net::TestURLRequestContextGetter(
- content::BrowserThread::GetTaskRunnerForThread(
- content::BrowserThread::UI));
+ base::CreateSingleThreadTaskRunnerWithTraits(
+ {content::BrowserThread::UI}));
}
void TearDown() override {
@@ -691,8 +716,7 @@ class ResourceDispatcherHostTest : public testing::Test {
EXPECT_TRUE(URLRequestTestDelayedStartJob::DelayedStartQueueEmpty());
URLRequestTestDelayedStartJob::ClearQueue();
- for (std::set<int>::iterator it = child_ids_.begin();
- it != child_ids_.end(); ++it) {
+ for (auto it = child_ids_.begin(); it != child_ids_.end(); ++it) {
host_.CancelRequestsForProcess(*it);
}
@@ -712,8 +736,7 @@ class ResourceDispatcherHostTest : public testing::Test {
// Creates a new TestFilter and registers it with |child_ids_| so as not
// to leak per-child state on test shutdown.
scoped_refptr<TestFilter> MakeTestFilter() {
- auto filter = base::MakeRefCounted<TestFilter>(
- browser_context_->GetResourceContext());
+ auto filter = base::MakeRefCounted<TestFilter>(browser_context_.get());
child_ids_.insert(filter->child_id());
return filter;
}
@@ -809,7 +832,8 @@ class ResourceDispatcherHostTest : public testing::Test {
mojom::BeginNavigationParamsPtr begin_params =
mojom::BeginNavigationParams::New(
std::string() /* headers */, net::LOAD_NORMAL,
- false /* skip_service_worker */, REQUEST_CONTEXT_TYPE_LOCATION,
+ false /* skip_service_worker */,
+ blink::mojom::RequestContextType::LOCATION,
blink::WebMixedContentContextType::kBlockable,
false /* is_form_submission */, GURL() /* searchable_form_url */,
std::string() /* searchable_form_encoding */,
@@ -842,6 +866,15 @@ class ResourceDispatcherHostTest : public testing::Test {
request_info->detachable_handler()->is_detached();
}
+ bool IsAborted(const network::TestURLLoaderClient& client) {
+ // TODO(toyoshim): Once NetworkService or OutOfBlinkCORS is enabled, these
+ // expectations below should be receiving a completion with ERR_ABORTED.
+ if (!client.has_received_completion())
+ return client.has_received_connection_error();
+
+ return client.completion_status().error_code == net::ERR_ABORTED;
+ }
+
void SetMaxDelayableRequests(size_t max_delayable_requests) {
network::ResourceSchedulerParamsManager::ParamsForNetworkQualityContainer c;
for (int i = 0; i != net::EFFECTIVE_CONNECTION_TYPE_LAST; ++i) {
@@ -874,6 +907,7 @@ class ResourceDispatcherHostTest : public testing::Test {
RenderViewHostTestEnabler render_view_host_test_enabler_;
bool auto_advance_;
scoped_refptr<net::TestURLRequestContextGetter> request_context_getter_;
+ base::test::ScopedFeatureList scoped_feature_list_;
};
void ResourceDispatcherHostTest::MakeTestRequest(
@@ -988,7 +1022,7 @@ void CheckSuccessfulRequest(network::TestURLLoaderClient* client,
// Tests whether messages get canceled properly. We issue four requests,
// cancel two of them, and make sure that each sent the proper notifications.
-TEST_F(ResourceDispatcherHostTest, Cancel) {
+TEST_P(ResourceDispatcherHostTest, Cancel) {
network::mojom::URLLoaderPtr loader1, loader2, loader3, loader4;
network::TestURLLoaderClient client1, client2, client3, client4;
MakeTestRequest(0, 1, net::URLRequestTestJob::test_url_1(),
@@ -1038,7 +1072,7 @@ TEST_F(ResourceDispatcherHostTest, Cancel) {
// Shows that detachable requests will timeout if the request takes too long to
// complete.
-TEST_F(ResourceDispatcherHostTest, DetachedResourceTimesOut) {
+TEST_P(ResourceDispatcherHostTest, DetachedResourceTimesOut) {
network::mojom::URLLoaderPtr loader;
network::TestURLLoaderClient client;
MakeTestRequestWithResourceType(
@@ -1058,6 +1092,7 @@ TEST_F(ResourceDispatcherHostTest, DetachedResourceTimesOut) {
loader = nullptr;
// From the renderer's perspective, the request was cancelled.
+ content::RunAllTasksUntilIdle();
client.RunUntilComplete();
EXPECT_EQ(net::ERR_ABORTED, client.completion_status().error_code);
@@ -1082,7 +1117,7 @@ TEST_F(ResourceDispatcherHostTest, DetachedResourceTimesOut) {
// If the filter has disappeared then detachable resources should continue to
// load.
-TEST_F(ResourceDispatcherHostTest, DeletedFilterDetached) {
+TEST_P(ResourceDispatcherHostTest, DeletedFilterDetached) {
network::mojom::URLLoaderPtr loader1;
network::TestURLLoaderClient client1;
base::test::ScopedFeatureList feature_list;
@@ -1102,8 +1137,8 @@ TEST_F(ResourceDispatcherHostTest, DeletedFilterDetached) {
DCHECK_EQ(filter_.get(), info_prefetch->requester_info()->filter());
filter_->OnChannelClosing();
- client1.RunUntilComplete();
- EXPECT_EQ(net::ERR_ABORTED, client1.completion_status().error_code);
+ content::RunAllTasksUntilIdle();
+ DCHECK(IsAborted(client1));
// But it continues detached.
EXPECT_EQ(1, host_.pending_requests());
@@ -1123,7 +1158,7 @@ TEST_F(ResourceDispatcherHostTest, DeletedFilterDetached) {
// If the filter has disappeared (original process dies) then detachable
// resources should continue to load, even when redirected.
-TEST_F(ResourceDispatcherHostTest, DeletedFilterDetachedRedirect) {
+TEST_P(ResourceDispatcherHostTest, DeletedFilterDetachedRedirect) {
network::mojom::URLLoaderPtr loader;
network::TestURLLoaderClient client;
network::ResourceRequest request = CreateResourceRequest(
@@ -1151,8 +1186,8 @@ TEST_F(ResourceDispatcherHostTest, DeletedFilterDetachedRedirect) {
EXPECT_EQ(1u, url_request->url_chain().size());
// From the renderer's perspective, the request was cancelled.
- client.RunUntilComplete();
- EXPECT_EQ(net::ERR_ABORTED, client.completion_status().error_code);
+ content::RunAllTasksUntilIdle();
+ DCHECK(IsAborted(client));
content::RunAllTasksUntilIdle();
// Verify that a redirect was followed.
@@ -1171,7 +1206,7 @@ TEST_F(ResourceDispatcherHostTest, DeletedFilterDetachedRedirect) {
EXPECT_EQ(0, network_delegate()->error_count());
}
-TEST_F(ResourceDispatcherHostTest, CancelWhileStartIsDeferred) {
+TEST_P(ResourceDispatcherHostTest, CancelWhileStartIsDeferred) {
network::mojom::URLLoaderPtr loader;
network::TestURLLoaderClient client;
bool was_deleted = false;
@@ -1199,7 +1234,7 @@ TEST_F(ResourceDispatcherHostTest, CancelWhileStartIsDeferred) {
EXPECT_TRUE(was_deleted);
}
-TEST_F(ResourceDispatcherHostTest, DetachWhileStartIsDeferred) {
+TEST_P(ResourceDispatcherHostTest, DetachWhileStartIsDeferred) {
network::mojom::URLLoaderPtr loader;
network::TestURLLoaderClient client;
bool was_deleted = false;
@@ -1244,7 +1279,7 @@ TEST_F(ResourceDispatcherHostTest, DetachWhileStartIsDeferred) {
// Tests if cancel is called in ResourceThrottle::WillStartRequest, then the
// URLRequest will not be started.
-TEST_F(ResourceDispatcherHostTest, CancelInResourceThrottleWillStartRequest) {
+TEST_P(ResourceDispatcherHostTest, CancelInResourceThrottleWillStartRequest) {
network::mojom::URLLoaderPtr loader;
network::TestURLLoaderClient client;
TestResourceDispatcherHostDelegate delegate;
@@ -1266,7 +1301,7 @@ TEST_F(ResourceDispatcherHostTest, CancelInResourceThrottleWillStartRequest) {
EXPECT_EQ(0, job_factory_->url_request_jobs_created_count());
}
-TEST_F(ResourceDispatcherHostTest, PausedStartError) {
+TEST_P(ResourceDispatcherHostTest, PausedStartError) {
network::mojom::URLLoaderPtr loader;
network::TestURLLoaderClient client;
// Arrange to have requests deferred before processing response headers.
@@ -1286,7 +1321,7 @@ TEST_F(ResourceDispatcherHostTest, PausedStartError) {
EXPECT_EQ(0, host_.pending_requests());
}
-TEST_F(ResourceDispatcherHostTest, ThrottleAndResumeTwice) {
+TEST_P(ResourceDispatcherHostTest, ThrottleAndResumeTwice) {
network::mojom::URLLoaderPtr loader;
network::TestURLLoaderClient client;
// Arrange to have requests deferred before starting.
@@ -1323,7 +1358,7 @@ TEST_F(ResourceDispatcherHostTest, ThrottleAndResumeTwice) {
}
// Tests that the delegate can cancel a request and provide a error code.
-TEST_F(ResourceDispatcherHostTest, CancelInDelegate) {
+TEST_P(ResourceDispatcherHostTest, CancelInDelegate) {
network::mojom::URLLoaderPtr loader;
network::TestURLLoaderClient client;
TestResourceDispatcherHostDelegate delegate;
@@ -1343,7 +1378,7 @@ TEST_F(ResourceDispatcherHostTest, CancelInDelegate) {
EXPECT_EQ(net::ERR_ACCESS_DENIED, client.completion_status().error_code);
}
-TEST_F(ResourceDispatcherHostTest, CancelRequestsForRoute) {
+TEST_P(ResourceDispatcherHostTest, CancelRequestsForRoute) {
network::mojom::URLLoaderPtr loader1, loader2, loader3, loader4;
network::TestURLLoaderClient client1, client2, client3, client4;
base::test::ScopedFeatureList feature_list;
@@ -1397,7 +1432,7 @@ TEST_F(ResourceDispatcherHostTest, CancelRequestsForRoute) {
}
// Tests CancelRequestsForProcess
-TEST_F(ResourceDispatcherHostTest, TestProcessCancel) {
+TEST_P(ResourceDispatcherHostTest, TestProcessCancel) {
network::mojom::URLLoaderPtr loader1, loader2, loader3, loader4;
network::TestURLLoaderClient client1, client2, client3, client4;
scoped_refptr<TestFilter> test_filter = MakeTestFilter();
@@ -1471,7 +1506,7 @@ TEST_F(ResourceDispatcherHostTest, TestProcessCancel) {
// Tests whether the correct requests get canceled when a RenderViewHost is
// deleted.
-TEST_F(ResourceDispatcherHostTest, CancelRequestsOnRenderFrameDeleted) {
+TEST_P(ResourceDispatcherHostTest, CancelRequestsOnRenderFrameDeleted) {
network::mojom::URLLoaderPtr loader1, loader2, loader3, loader4, loader5;
network::TestURLLoaderClient client1, client2, client3, client4, client5;
// Requests all hang once started. This prevents requests from being
@@ -1529,7 +1564,7 @@ TEST_F(ResourceDispatcherHostTest, CancelRequestsOnRenderFrameDeleted) {
EXPECT_EQ(4, network_delegate_.canceled_requests());
}
-TEST_F(ResourceDispatcherHostTest, TestProcessCancelDetachedTimesOut) {
+TEST_P(ResourceDispatcherHostTest, TestProcessCancelDetachedTimesOut) {
network::mojom::URLLoaderPtr loader;
network::TestURLLoaderClient client;
MakeTestRequestWithResourceType(
@@ -1575,7 +1610,7 @@ TEST_F(ResourceDispatcherHostTest, TestProcessCancelDetachedTimesOut) {
}
// Tests blocking and resuming requests.
-TEST_F(ResourceDispatcherHostTest, TestBlockingResumingRequests) {
+TEST_P(ResourceDispatcherHostTest, TestBlockingResumingRequests) {
network::mojom::URLLoaderPtr loader1, loader2, loader3, loader4, loader5,
loader6, loader7;
network::TestURLLoaderClient client1, client2, client3, client4, client5,
@@ -1655,7 +1690,7 @@ TEST_F(ResourceDispatcherHostTest, TestBlockingResumingRequests) {
}
// Tests blocking and canceling requests.
-TEST_F(ResourceDispatcherHostTest, TestBlockingCancelingRequests) {
+TEST_P(ResourceDispatcherHostTest, TestBlockingCancelingRequests) {
network::mojom::URLLoaderPtr loader1, loader2, loader3, loader4, loader5;
network::TestURLLoaderClient client1, client2, client3, client4, client5;
@@ -1689,9 +1724,9 @@ TEST_F(ResourceDispatcherHostTest, TestBlockingCancelingRequests) {
CheckSuccessfulRequest(&client1, net::URLRequestTestJob::test_data_1());
CheckSuccessfulRequest(&client3, net::URLRequestTestJob::test_data_3());
- EXPECT_FALSE(client2.has_received_completion());
- EXPECT_FALSE(client4.has_received_completion());
- EXPECT_FALSE(client5.has_received_completion());
+ EXPECT_FALSE(IsAborted(client2));
+ EXPECT_FALSE(IsAborted(client4));
+ EXPECT_FALSE(IsAborted(client5));
// Cancel requests for RFH 11.
host_.CancelBlockedRequestsForRoute(
@@ -1699,13 +1734,13 @@ TEST_F(ResourceDispatcherHostTest, TestBlockingCancelingRequests) {
content::RunAllTasksUntilIdle();
while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
- EXPECT_FALSE(client2.has_received_completion());
- EXPECT_FALSE(client4.has_received_completion());
- EXPECT_FALSE(client5.has_received_completion());
+ EXPECT_TRUE(IsAborted(client2));
+ EXPECT_TRUE(IsAborted(client4));
+ EXPECT_TRUE(IsAborted(client5));
}
// Tests that blocked requests are canceled if their associated process dies.
-TEST_F(ResourceDispatcherHostTest, TestBlockedRequestsProcessDies) {
+TEST_P(ResourceDispatcherHostTest, TestBlockedRequestsProcessDies) {
network::mojom::URLLoaderPtr loader1, loader2, loader3, loader4, loader5;
network::TestURLLoaderClient client1, client2, client3, client4, client5;
// This second filter is used to emulate a second process.
@@ -1744,9 +1779,9 @@ TEST_F(ResourceDispatcherHostTest, TestBlockedRequestsProcessDies) {
CheckSuccessfulRequest(&client1, net::URLRequestTestJob::test_data_1());
CheckSuccessfulRequest(&client3, net::URLRequestTestJob::test_data_3());
- EXPECT_FALSE(client2.has_received_completion());
- EXPECT_FALSE(client4.has_received_completion());
- EXPECT_FALSE(client5.has_received_completion());
+ EXPECT_TRUE(IsAborted(client2));
+ EXPECT_TRUE(IsAborted(client4));
+ EXPECT_TRUE(IsAborted(client5));
EXPECT_TRUE(host_.blocked_loaders_map_.empty());
second_filter->OnChannelClosing();
@@ -1756,7 +1791,7 @@ TEST_F(ResourceDispatcherHostTest, TestBlockedRequestsProcessDies) {
// away. Note that we rely on Purify for finding the leaks if any.
// If this test turns the Purify bot red, check the ResourceDispatcherHost
// destructor to make sure the blocked requests are deleted.
-TEST_F(ResourceDispatcherHostTest, TestBlockedRequestsDontLeak) {
+TEST_P(ResourceDispatcherHostTest, TestBlockedRequestsDontLeak) {
network::mojom::URLLoaderPtr loader1, loader2, loader3, loader4, loader5,
loader6, loader7, loader8;
network::TestURLLoaderClient client1, client2, client3, client4, client5,
@@ -1813,7 +1848,7 @@ TEST_F(ResourceDispatcherHostTest, TestBlockedRequestsDontLeak) {
}
// Test the private helper method "CalculateApproximateMemoryCost()".
-TEST_F(ResourceDispatcherHostTest, CalculateApproximateMemoryCost) {
+TEST_P(ResourceDispatcherHostTest, CalculateApproximateMemoryCost) {
net::URLRequestContext context;
std::unique_ptr<net::URLRequest> req(context.CreateRequest(
GURL("http://www.google.com"), net::DEFAULT_PRIORITY, nullptr,
@@ -1843,7 +1878,7 @@ TEST_F(ResourceDispatcherHostTest, CalculateApproximateMemoryCost) {
// Test that too much memory for outstanding requests for a particular
// render_process_host_id causes requests to fail.
-TEST_F(ResourceDispatcherHostTest, TooMuchOutstandingRequestsMemory) {
+TEST_P(ResourceDispatcherHostTest, TooMuchOutstandingRequestsMemory) {
// Expected cost of each request as measured by
// ResourceDispatcherHost::CalculateApproximateMemoryCost().
const int kMemoryCostOfTest2Req =
@@ -1927,7 +1962,7 @@ TEST_F(ResourceDispatcherHostTest, TooMuchOutstandingRequestsMemory) {
// Test that when too many requests are outstanding for a particular
// render_process_host_id, any subsequent request from it fails. Also verify
// that the global limit is honored.
-TEST_F(ResourceDispatcherHostTest, TooManyOutstandingRequests) {
+TEST_P(ResourceDispatcherHostTest, TooManyOutstandingRequests) {
// Tighten the bound on the ResourceDispatcherHost, to speed things up.
constexpr size_t kMaxRequestsPerProcess = 2;
host_.set_max_num_in_flight_requests_per_process(kMaxRequestsPerProcess);
@@ -1995,7 +2030,7 @@ TEST_F(ResourceDispatcherHostTest, TooManyOutstandingRequests) {
}
// Tests that we sniff the mime type for a simple request.
-TEST_F(ResourceDispatcherHostTest, MimeSniffed) {
+TEST_P(ResourceDispatcherHostTest, MimeSniffed) {
network::mojom::URLLoaderPtr loader;
network::TestURLLoaderClient client;
std::string raw_headers("HTTP/1.1 200 OK\n\n");
@@ -2016,7 +2051,7 @@ TEST_F(ResourceDispatcherHostTest, MimeSniffed) {
}
// Tests that we don't sniff the mime type when the server provides one.
-TEST_F(ResourceDispatcherHostTest, MimeNotSniffed) {
+TEST_P(ResourceDispatcherHostTest, MimeNotSniffed) {
network::mojom::URLLoaderPtr loader;
network::TestURLLoaderClient client;
std::string raw_headers("HTTP/1.1 200 OK\n"
@@ -2038,7 +2073,7 @@ TEST_F(ResourceDispatcherHostTest, MimeNotSniffed) {
}
// Tests that we don't sniff the mime type when there is no message body.
-TEST_F(ResourceDispatcherHostTest, MimeNotSniffed2) {
+TEST_P(ResourceDispatcherHostTest, MimeNotSniffed2) {
network::mojom::URLLoaderPtr loader;
network::TestURLLoaderClient client;
SetResponse("HTTP/1.1 304 Not Modified\n\n");
@@ -2055,7 +2090,7 @@ TEST_F(ResourceDispatcherHostTest, MimeNotSniffed2) {
EXPECT_EQ("", client.response_head().mime_type);
}
-TEST_F(ResourceDispatcherHostTest, MimeSniff204) {
+TEST_P(ResourceDispatcherHostTest, MimeSniff204) {
network::mojom::URLLoaderPtr loader;
network::TestURLLoaderClient client;
SetResponse("HTTP/1.1 204 No Content\n\n");
@@ -2072,7 +2107,7 @@ TEST_F(ResourceDispatcherHostTest, MimeSniff204) {
EXPECT_EQ("text/plain", client.response_head().mime_type);
}
-TEST_F(ResourceDispatcherHostTest, MimeSniffEmpty) {
+TEST_P(ResourceDispatcherHostTest, MimeSniffEmpty) {
network::mojom::URLLoaderPtr loader;
network::TestURLLoaderClient client;
SetResponse("HTTP/1.1 200 OK\n\n");
@@ -2090,7 +2125,7 @@ TEST_F(ResourceDispatcherHostTest, MimeSniffEmpty) {
}
// Tests for crbug.com/31266 (Non-2xx + application/octet-stream).
-TEST_F(ResourceDispatcherHostTest, ForbiddenDownload) {
+TEST_P(ResourceDispatcherHostTest, ForbiddenDownload) {
std::string raw_headers("HTTP/1.1 403 Forbidden\n"
"Content-disposition: attachment; filename=blah\n"
"Content-type: application/octet-stream\n\n");
@@ -2106,7 +2141,7 @@ TEST_F(ResourceDispatcherHostTest, ForbiddenDownload) {
expected_error_code);
}
-TEST_F(ResourceDispatcherHostTest, CancelRequestsForContextDetached) {
+TEST_P(ResourceDispatcherHostTest, CancelRequestsForContextDetached) {
EXPECT_EQ(0, host_.pending_requests());
network::mojom::URLLoaderPtr loader;
network::TestURLLoaderClient client;
@@ -2163,7 +2198,7 @@ class ExternalProtocolBrowserClient : public TestContentBrowserClient {
// Verifies that if the embedder says that it didn't handle an unkonown protocol
// the request is cancelled and net::ERR_ABORTED is returned. Otherwise it is
// not aborted and net/ layer cancels it with net::ERR_UNKNOWN_URL_SCHEME.
-TEST_F(ResourceDispatcherHostTest, UnknownURLScheme) {
+TEST_P(ResourceDispatcherHostTest, UnknownURLScheme) {
EXPECT_EQ(0, host_.pending_requests());
HandleScheme("http");
@@ -2182,7 +2217,7 @@ TEST_F(ResourceDispatcherHostTest, UnknownURLScheme) {
// Request a very large detachable resource and cancel part way. Some of the
// data should have been sent to the renderer, but not all.
-TEST_F(ResourceDispatcherHostTest, DataSentBeforeDetach) {
+TEST_P(ResourceDispatcherHostTest, DataSentBeforeDetach) {
EXPECT_EQ(0, host_.pending_requests());
constexpr int render_view_id = 0;
@@ -2231,7 +2266,7 @@ WebContents* WebContentsBinder(WebContents* rv) { return rv; }
// Tests GetLoadInfoForAllRoutes when there are 3 requests from the same
// RenderView. The second one is farthest along.
-TEST_F(ResourceDispatcherHostTest, LoadInfo) {
+TEST_P(ResourceDispatcherHostTest, LoadInfo) {
std::unique_ptr<LoadInfoList> infos(new LoadInfoList);
LoadInfo info;
WebContents* wc1 = reinterpret_cast<WebContents*>(0x1);
@@ -2264,7 +2299,7 @@ TEST_F(ResourceDispatcherHostTest, LoadInfo) {
// Tests GetLoadInfoForAllRoutes when there are 2 requests with the same
// priority. The first one (Which will have the lowest ID) should be returned.
-TEST_F(ResourceDispatcherHostTest, LoadInfoSamePriority) {
+TEST_P(ResourceDispatcherHostTest, LoadInfoSamePriority) {
std::unique_ptr<LoadInfoList> infos(new LoadInfoList);
LoadInfo info;
WebContents* wc1 = reinterpret_cast<WebContents*>(0x1);
@@ -2291,7 +2326,7 @@ TEST_F(ResourceDispatcherHostTest, LoadInfoSamePriority) {
}
// Tests GetLoadInfoForAllRoutes when a request is uploading a body.
-TEST_F(ResourceDispatcherHostTest, LoadInfoUploadProgress) {
+TEST_P(ResourceDispatcherHostTest, LoadInfoUploadProgress) {
std::unique_ptr<LoadInfoList> infos(new LoadInfoList);
LoadInfo info;
WebContents* wc1 = reinterpret_cast<WebContents*>(0x1);
@@ -2341,7 +2376,7 @@ TEST_F(ResourceDispatcherHostTest, LoadInfoUploadProgress) {
// Tests GetLoadInfoForAllRoutes when there are 4 requests from 2 different
// RenderViews. Also tests the case where the first / last requests are the
// most interesting ones.
-TEST_F(ResourceDispatcherHostTest, LoadInfoTwoRenderViews) {
+TEST_P(ResourceDispatcherHostTest, LoadInfoTwoRenderViews) {
std::unique_ptr<LoadInfoList> infos(new LoadInfoList);
LoadInfo info;
WebContents* wc1 = reinterpret_cast<WebContents*>(0x1);
@@ -2392,7 +2427,7 @@ TEST_F(ResourceDispatcherHostTest, LoadInfoTwoRenderViews) {
// Tests that a ResourceThrottle that needs to process the response before any
// part of the body is read can do so.
-TEST_F(ResourceDispatcherHostTest, ThrottleMustProcessResponseBeforeRead) {
+TEST_P(ResourceDispatcherHostTest, ThrottleMustProcessResponseBeforeRead) {
// Ensure all jobs will check that no read operation is called.
job_factory_->SetMustNotReadJobGeneration(true);
HandleScheme("http");
@@ -2508,4 +2543,12 @@ net::URLRequestJob* TestURLRequestJobFactory::MaybeInterceptResponse(
return nullptr;
}
+INSTANTIATE_TEST_CASE_P(WithoutOutOfBlinkCors,
+ ResourceDispatcherHostTest,
+ ::testing::Values(TestMode::kWithoutOutOfBlinkCors));
+
+INSTANTIATE_TEST_CASE_P(WithOutOfBlinkCors,
+ ResourceDispatcherHostTest,
+ ::testing::Values(TestMode::kWithOutOfBlinkCors));
+
} // namespace content
diff --git a/chromium/content/browser/loader/resource_hints_impl.cc b/chromium/content/browser/loader/resource_hints_impl.cc
deleted file mode 100644
index bdb06548a3a..00000000000
--- a/chromium/content/browser/loader/resource_hints_impl.cc
+++ /dev/null
@@ -1,109 +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 <string>
-
-#include "base/memory/ref_counted.h"
-#include "base/trace_event/trace_event.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/resource_hints.h"
-#include "net/base/address_list.h"
-#include "net/base/load_flags.h"
-#include "net/http/http_network_session.h"
-#include "net/http/http_request_info.h"
-#include "net/http/http_stream_factory.h"
-#include "net/http/http_transaction_factory.h"
-#include "net/log/net_log_with_source.h"
-#include "net/url_request/http_user_agent_settings.h"
-#include "net/url_request/url_request_context.h"
-#include "net/url_request/url_request_context_getter.h"
-
-namespace content {
-
-namespace {
-
-void OnResolveComplete(std::unique_ptr<net::AddressList> addresses,
- const net::CompletionCallback& callback,
- int result) {
- // Plumb the resolution result into the callback if future consumers want
- // that information.
- callback.Run(result);
-}
-
-} // namespace
-
-void PreconnectUrl(net::URLRequestContextGetter* getter,
- const GURL& url,
- const GURL& site_for_cookies,
- int count,
- bool allow_credentials) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(getter);
- TRACE_EVENT2("net", "PreconnectUrl", "url", url.spec(), "count", count);
-
- net::URLRequestContext* request_context = getter->GetURLRequestContext();
- if (!request_context)
- return;
-
- net::HttpTransactionFactory* factory =
- request_context->http_transaction_factory();
- net::HttpNetworkSession* session = factory->GetSession();
-
- std::string user_agent;
- if (request_context->http_user_agent_settings())
- user_agent = request_context->http_user_agent_settings()->GetUserAgent();
- net::HttpRequestInfo request_info;
- request_info.url = url;
- request_info.method = "GET";
- request_info.extra_headers.SetHeader(net::HttpRequestHeaders::kUserAgent,
- user_agent);
-
- net::NetworkDelegate* delegate = request_context->network_delegate();
- // NetworkDelegate is not set in tests.
- if (!delegate)
- return;
- if (delegate->CanEnablePrivacyMode(url, site_for_cookies))
- request_info.privacy_mode = net::PRIVACY_MODE_ENABLED;
-
- // TODO(yoav): Fix this layering violation, since when credentials are not
- // allowed we should turn on a flag indicating that, rather then turn on
- // private mode, even if lower layers would treat both the same.
- if (!allow_credentials) {
- request_info.privacy_mode = net::PRIVACY_MODE_ENABLED;
- request_info.load_flags = net::LOAD_DO_NOT_SEND_COOKIES |
- net::LOAD_DO_NOT_SAVE_COOKIES |
- net::LOAD_DO_NOT_SEND_AUTH_DATA;
- }
-
- net::HttpStreamFactory* http_stream_factory = session->http_stream_factory();
- http_stream_factory->PreconnectStreams(count, request_info);
-}
-
-int PreresolveUrl(net::URLRequestContextGetter* getter,
- const GURL& url,
- const net::CompletionCallback& callback,
- std::unique_ptr<net::HostResolver::Request>* out_request) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(getter);
- TRACE_EVENT1("net", "PreresolveUrl", "url", url.spec());
-
- net::URLRequestContext* request_context = getter->GetURLRequestContext();
- if (!request_context)
- return net::ERR_CONTEXT_SHUT_DOWN;
-
- auto addresses = std::make_unique<net::AddressList>();
-
- // Save raw pointers before the unique_ptr is invalidated by base::Passed().
- net::AddressList* raw_addresses = addresses.get();
-
- net::HostResolver* resolver = request_context->host_resolver();
- net::HostResolver::RequestInfo resolve_info(net::HostPortPair::FromURL(url));
- resolve_info.set_is_speculative(true);
- return resolver->Resolve(
- resolve_info, net::IDLE, raw_addresses,
- base::BindOnce(&OnResolveComplete, std::move(addresses), callback),
- out_request, net::NetLogWithSource());
-}
-
-} // namespace content
diff --git a/chromium/content/browser/loader/resource_message_filter.cc b/chromium/content/browser/loader/resource_message_filter.cc
index 2f531f5ae08..faed15d613f 100644
--- a/chromium/content/browser/loader/resource_message_filter.cc
+++ b/chromium/content/browser/loader/resource_message_filter.cc
@@ -18,6 +18,7 @@
#include "content/common/resource_messages.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/resource_context.h"
+#include "content/public/browser/shared_cors_origin_access_list.h"
#include "content/public/common/content_switches.h"
#include "services/network/cors/cors_url_loader_factory.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
@@ -44,6 +45,7 @@ ResourceMessageFilter::ResourceMessageFilter(
storage::FileSystemContext* file_system_context,
ServiceWorkerContextWrapper* service_worker_context,
PrefetchURLLoaderService* prefetch_url_loader_service,
+ const SharedCorsOriginAccessList* shared_cors_origin_access_list,
const GetContextsCallback& get_contexts_callback,
const scoped_refptr<base::SingleThreadTaskRunner>& io_thread_runner)
: BrowserMessageFilter(ResourceMsgStart),
@@ -57,6 +59,7 @@ ResourceMessageFilter::ResourceMessageFilter(
service_worker_context,
get_contexts_callback)),
prefetch_url_loader_service_(prefetch_url_loader_service),
+ shared_cors_origin_access_list_(shared_cors_origin_access_list),
io_thread_task_runner_(io_thread_runner),
weak_ptr_factory_(this) {}
@@ -184,7 +187,8 @@ void ResourceMessageFilter::InitializeOnIOThread() {
std::make_unique<URLLoaderFactoryImpl>(requester_info_),
base::BindRepeating(&ResourceDispatcherHostImpl::CancelRequest,
base::Unretained(ResourceDispatcherHostImpl::Get()),
- requester_info_->child_id()));
+ requester_info_->child_id()),
+ &shared_cors_origin_access_list_->GetOriginAccessList());
std::vector<network::mojom::URLLoaderFactoryRequest> requests =
std::move(queued_clone_requests_);
diff --git a/chromium/content/browser/loader/resource_message_filter.h b/chromium/content/browser/loader/resource_message_filter.h
index a0a5a0dc3cb..b2e58d3f169 100644
--- a/chromium/content/browser/loader/resource_message_filter.h
+++ b/chromium/content/browser/loader/resource_message_filter.h
@@ -28,7 +28,6 @@ namespace net {
class URLRequestContext;
} // namespace net
-
namespace content {
class ChromeAppCacheService;
class ChromeBlobStorageContext;
@@ -36,6 +35,7 @@ class PrefetchURLLoaderService;
class ResourceContext;
class ResourceRequesterInfo;
class ServiceWorkerContextWrapper;
+class SharedCorsOriginAccessList;
// This class filters out incoming IPC messages for network requests and
// processes them on the IPC thread. As a result, network requests are not
@@ -62,6 +62,7 @@ class CONTENT_EXPORT ResourceMessageFilter
storage::FileSystemContext* file_system_context,
ServiceWorkerContextWrapper* service_worker_context,
PrefetchURLLoaderService* prefetch_url_loader_service,
+ const SharedCorsOriginAccessList* shared_cors_origin_access_list,
const GetContextsCallback& get_contexts_callback,
const scoped_refptr<base::SingleThreadTaskRunner>& io_thread_runner);
@@ -121,6 +122,9 @@ class CONTENT_EXPORT ResourceMessageFilter
scoped_refptr<PrefetchURLLoaderService> prefetch_url_loader_service_;
+ scoped_refptr<const SharedCorsOriginAccessList>
+ shared_cors_origin_access_list_;
+
// Task runner for the IO thead.
scoped_refptr<base::SingleThreadTaskRunner> io_thread_task_runner_;
diff --git a/chromium/content/browser/loader/resource_request_info_impl.cc b/chromium/content/browser/loader/resource_request_info_impl.cc
index 7fe59fe5542..2786b068dfb 100644
--- a/chromium/content/browser/loader/resource_request_info_impl.cc
+++ b/chromium/content/browser/loader/resource_request_info_impl.cc
@@ -6,6 +6,8 @@
#include "content/browser/frame_host/frame_tree_node.h"
#include "content/browser/loader/resource_message_filter.h"
+#include "content/browser/service_worker/service_worker_provider_host.h"
+#include "content/browser/web_contents/web_contents_getter_registry.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/net/url_request_service_worker_data.h"
#include "content/common/net/url_request_user_data.h"
@@ -72,6 +74,7 @@ void ResourceRequestInfo::AllocateForTesting(
0, // request_id
render_frame_id, // render_frame_id
is_main_frame, // is_main_frame
+ {}, // fetch_window_id
resource_type, // resource_type
ui::PAGE_TRANSITION_LINK, // transition_type
false, // is_download
@@ -140,6 +143,7 @@ ResourceRequestInfoImpl::ResourceRequestInfoImpl(
int request_id,
int render_frame_id,
bool is_main_frame,
+ const base::UnguessableToken& fetch_window_id,
ResourceType resource_type,
ui::PageTransition transition_type,
bool is_download,
@@ -167,6 +171,7 @@ ResourceRequestInfoImpl::ResourceRequestInfoImpl(
request_id_(request_id),
render_frame_id_(render_frame_id),
is_main_frame_(is_main_frame),
+ fetch_window_id_(fetch_window_id),
is_download_(is_download),
is_stream_(is_stream),
allow_download_(allow_download),
@@ -185,7 +190,6 @@ ResourceRequestInfoImpl::ResourceRequestInfoImpl(
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),
@@ -198,10 +202,18 @@ ResourceRequestInfoImpl::~ResourceRequestInfoImpl() {
ResourceRequestInfo::WebContentsGetter
ResourceRequestInfoImpl::GetWebContentsGetterForRequest() const {
- // PlzNavigate: navigation requests are created with a valid FrameTreeNode ID
- // and invalid RenderProcessHost and RenderFrameHost IDs. The FrameTreeNode
- // ID should be used to access the WebContents.
- if (frame_tree_node_id_ != -1) {
+ // If we have a window id, try to use that.
+ if (fetch_window_id_) {
+ ResourceRequestInfo::WebContentsGetter getter =
+ WebContentsGetterRegistry::GetInstance()->Get(fetch_window_id_);
+ if (getter)
+ return getter;
+ }
+
+ // Navigation requests are created with a valid FrameTreeNode ID and invalid
+ // RenderProcessHost and RenderFrameHost IDs. The FrameTreeNode ID should be
+ // used to access the WebContents.
+ if (frame_tree_node_id_ != RenderFrameHost::kNoFrameTreeNodeId) {
DCHECK(IsBrowserSideNavigationEnabled());
return base::Bind(WebContents::FromFrameTreeNodeId, frame_tree_node_id_);
}
@@ -322,11 +334,6 @@ NavigationUIData* ResourceRequestInfoImpl::GetNavigationUIData() const {
return navigation_ui_data_.get();
}
-ResourceRequestInfo::DevToolsStatus ResourceRequestInfoImpl::GetDevToolsStatus()
- const {
- return devtools_status_;
-}
-
void ResourceRequestInfoImpl::SetResourceRequestBlockedReason(
blink::ResourceRequestBlockedReason reason) {
resource_request_blocked_reason_ = reason;
diff --git a/chromium/content/browser/loader/resource_request_info_impl.h b/chromium/content/browser/loader/resource_request_info_impl.h
index ec89c14e24b..ec852ae9294 100644
--- a/chromium/content/browser/loader/resource_request_info_impl.h
+++ b/chromium/content/browser/loader/resource_request_info_impl.h
@@ -52,6 +52,7 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo,
int request_id,
int render_frame_id,
bool is_main_frame,
+ const base::UnguessableToken& fetch_window_id,
ResourceType resource_type,
ui::PageTransition transition_type,
bool is_download,
@@ -98,7 +99,6 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo,
PreviewsState GetPreviewsState() const override;
void SetPreviewsState(PreviewsState previews_state) override;
NavigationUIData* GetNavigationUIData() const override;
- DevToolsStatus GetDevToolsStatus() const override;
void SetResourceRequestBlockedReason(
blink::ResourceRequestBlockedReason reason) override;
base::Optional<blink::ResourceRequestBlockedReason>
@@ -187,10 +187,6 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo,
navigation_ui_data_ = std::move(navigation_ui_data);
}
- void set_devtools_status(DevToolsStatus devtools_status) {
- devtools_status_ = devtools_status;
- }
-
void SetBlobHandles(BlobHandles blob_handles);
bool blocked_response_from_reaching_renderer() const {
@@ -216,6 +212,10 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo,
first_auth_attempt_ = first_auth_attempt;
}
+ const base::UnguessableToken& fetch_window_id() const {
+ return fetch_window_id_;
+ }
+
private:
FRIEND_TEST_ALL_PREFIXES(ResourceDispatcherHostTest,
DeletedFilterDetached);
@@ -231,6 +231,7 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo,
int request_id_;
int render_frame_id_;
bool is_main_frame_;
+ base::UnguessableToken fetch_window_id_;
bool is_download_;
bool is_stream_;
bool allow_download_;
@@ -249,7 +250,6 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo,
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_;
diff --git a/chromium/content/browser/loader/shared_cors_origin_access_list_impl.cc b/chromium/content/browser/loader/shared_cors_origin_access_list_impl.cc
new file mode 100644
index 00000000000..dce98468bed
--- /dev/null
+++ b/chromium/content/browser/loader/shared_cors_origin_access_list_impl.cc
@@ -0,0 +1,51 @@
+// 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/shared_cors_origin_access_list_impl.h"
+
+#include "base/bind.h"
+#include "base/feature_list.h"
+#include "base/task/post_task.h"
+#include "content/public/browser/browser_task_traits.h"
+#include "content/public/browser/browser_thread.h"
+#include "services/network/public/cpp/features.h"
+
+namespace content {
+
+SharedCorsOriginAccessListImpl::SharedCorsOriginAccessListImpl()
+ : SharedCorsOriginAccessList() {}
+
+void SharedCorsOriginAccessListImpl::SetForOrigin(
+ const url::Origin& source_origin,
+ std::vector<network::mojom::CorsOriginPatternPtr> allow_patterns,
+ std::vector<network::mojom::CorsOriginPatternPtr> block_patterns,
+ base::OnceClosure closure) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
+ base::PostTaskWithTraitsAndReply(
+ FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(&SharedCorsOriginAccessListImpl::SetForOriginOnIOThread,
+ base::RetainedRef(this), source_origin,
+ std::move(allow_patterns), std::move(block_patterns)),
+ std::move(closure));
+}
+
+const network::cors::OriginAccessList&
+SharedCorsOriginAccessListImpl::GetOriginAccessList() const {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ return origin_access_list_;
+}
+
+SharedCorsOriginAccessListImpl::~SharedCorsOriginAccessListImpl() = default;
+
+void SharedCorsOriginAccessListImpl::SetForOriginOnIOThread(
+ const url::Origin source_origin,
+ std::vector<network::mojom::CorsOriginPatternPtr> allow_patterns,
+ std::vector<network::mojom::CorsOriginPatternPtr> block_patterns) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ origin_access_list_.SetAllowListForOrigin(source_origin, allow_patterns);
+ origin_access_list_.SetBlockListForOrigin(source_origin, block_patterns);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/loader/shared_cors_origin_access_list_impl.h b/chromium/content/browser/loader/shared_cors_origin_access_list_impl.h
new file mode 100644
index 00000000000..18497e5283c
--- /dev/null
+++ b/chromium/content/browser/loader/shared_cors_origin_access_list_impl.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_LOADER_SHARED_CORS_ORIGIN_ACCESS_LIST_IMPL_H_
+#define CONTENT_BROWSER_LOADER_SHARED_CORS_ORIGIN_ACCESS_LIST_IMPL_H_
+
+#include "base/macros.h"
+#include "content/public/browser/shared_cors_origin_access_list.h"
+#include "services/network/public/cpp/cors/origin_access_list.h"
+
+namespace content {
+
+// SharedCorsOriginAccessList implementation class.
+class SharedCorsOriginAccessListImpl final : public SharedCorsOriginAccessList {
+ public:
+ SharedCorsOriginAccessListImpl();
+
+ // SharedCorsOriginAccessList interface.
+ void SetForOrigin(
+ const url::Origin& source_origin,
+ std::vector<network::mojom::CorsOriginPatternPtr> allow_patterns,
+ std::vector<network::mojom::CorsOriginPatternPtr> block_patterns,
+ base::OnceClosure closure) override;
+ const network::cors::OriginAccessList& GetOriginAccessList() const override;
+
+ protected:
+ ~SharedCorsOriginAccessListImpl() override;
+
+ private:
+ void SetForOriginOnIOThread(
+ const url::Origin source_origin,
+ std::vector<network::mojom::CorsOriginPatternPtr> allow_patterns,
+ std::vector<network::mojom::CorsOriginPatternPtr> block_patterns);
+
+ network::cors::OriginAccessList origin_access_list_;
+
+ DISALLOW_COPY_AND_ASSIGN(SharedCorsOriginAccessListImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_LOADER_SHARED_CORS_ORIGIN_ACCESS_LIST_IMPL_H_
diff --git a/chromium/content/browser/loader/stream_writer.cc b/chromium/content/browser/loader/stream_writer.cc
index 08774aa64b4..70a7502744b 100644
--- a/chromium/content/browser/loader/stream_writer.cc
+++ b/chromium/content/browser/loader/stream_writer.cc
@@ -54,7 +54,7 @@ void StreamWriter::OnWillRead(scoped_refptr<net::IOBuffer>* buf,
DCHECK(buf_size);
DCHECK_LE(min_size, kReadBufSize);
if (!read_buffer_.get())
- read_buffer_ = new net::IOBuffer(kReadBufSize);
+ read_buffer_ = base::MakeRefCounted<net::IOBuffer>(kReadBufSize);
*buf = read_buffer_.get();
*buf_size = kReadBufSize;
}
diff --git a/chromium/content/browser/loader/test_resource_handler.cc b/chromium/content/browser/loader/test_resource_handler.cc
index 0fbeb2706a9..7fc81cd450a 100644
--- a/chromium/content/browser/loader/test_resource_handler.cc
+++ b/chromium/content/browser/loader/test_resource_handler.cc
@@ -272,7 +272,7 @@ void TestResourceHandler::CancelWithError(net::Error net_error) {
}
void TestResourceHandler::SetBufferSize(int buffer_size) {
- buffer_ = new net::IOBuffer(buffer_size);
+ buffer_ = base::MakeRefCounted<net::IOBuffer>(buffer_size);
buffer_size_ = buffer_size;
memset(buffer_->data(), '\0', buffer_size);
}
diff --git a/chromium/content/browser/loader/throttling_resource_handler_unittest.cc b/chromium/content/browser/loader/throttling_resource_handler_unittest.cc
index 838a6b73246..0e6dbf7e424 100644
--- a/chromium/content/browser/loader/throttling_resource_handler_unittest.cc
+++ b/chromium/content/browser/loader/throttling_resource_handler_unittest.cc
@@ -10,7 +10,7 @@
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop.h"
+#include "base/test/scoped_task_environment.h"
#include "content/browser/loader/mock_resource_loader.h"
#include "content/browser/loader/resource_request_info_impl.h"
#include "content/browser/loader/test_resource_handler.h"
@@ -176,7 +176,9 @@ class TestResourceThrottle : public ResourceThrottle {
class ThrottlingResourceHandlerTest : public testing::Test {
public:
ThrottlingResourceHandlerTest()
- : never_started_url_request_(
+ : task_environment_(
+ base::test::ScopedTaskEnvironment::MainThreadType::IO),
+ never_started_url_request_(
request_context_.CreateRequest(GURL(kInitialUrl),
net::DEFAULT_PRIORITY,
&never_started_url_request_delegate_,
@@ -222,7 +224,7 @@ class ThrottlingResourceHandlerTest : public testing::Test {
protected:
// Needs to be first, so it's destroyed last.
- base::MessageLoopForIO message_loop_;
+ base::test::ScopedTaskEnvironment task_environment_;
// Machinery to construct a URLRequest that's just used as an argument to
// methods that expect one, and is never actually started.
diff --git a/chromium/content/browser/loader/upload_data_stream_builder_unittest.cc b/chromium/content/browser/loader/upload_data_stream_builder_unittest.cc
index 8231784cc76..6f38daeee39 100644
--- a/chromium/content/browser/loader/upload_data_stream_builder_unittest.cc
+++ b/chromium/content/browser/loader/upload_data_stream_builder_unittest.cc
@@ -152,7 +152,7 @@ TEST(UploadDataStreamBuilderTest,
int kBufferLength = kZeroLength + 1;
std::unique_ptr<char[]> buffer(new char[kBufferLength]);
scoped_refptr<net::IOBuffer> io_buffer =
- new net::WrappedIOBuffer(buffer.get());
+ base::MakeRefCounted<net::WrappedIOBuffer>(buffer.get());
net::TestCompletionCallback read_callback;
int result =
upload->Read(io_buffer.get(), kBufferLength, read_callback.callback());
@@ -195,8 +195,8 @@ TEST(UploadDataStreamBuilderTest, ResetUploadStreamWithBlob) {
// Read part of the data.
const int kBufferLength = 4;
- scoped_refptr<net::IOBufferWithSize> buffer(
- new net::IOBufferWithSize(kBufferLength));
+ scoped_refptr<net::IOBufferWithSize> buffer =
+ base::MakeRefCounted<net::IOBufferWithSize>(kBufferLength);
net::TestCompletionCallback read_callback;
int result =
upload->Read(buffer.get(), buffer->size(), read_callback.callback());
@@ -209,7 +209,7 @@ TEST(UploadDataStreamBuilderTest, ResetUploadStreamWithBlob) {
upload->Init(init_callback.callback(), net::NetLogWithSource()));
// Read all the data.
- buffer = new net::IOBufferWithSize(kBlobDataLength);
+ buffer = base::MakeRefCounted<net::IOBufferWithSize>(kBlobDataLength);
result =
upload->Read(buffer.get(), buffer->size(), read_callback.callback());
EXPECT_EQ(kBlobDataLength, read_callback.GetResult(result));
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 168eed74072..3fb868c99f8 100644
--- a/chromium/content/browser/loader/url_loader_factory_impl_unittest.cc
+++ b/chromium/content/browser/loader/url_loader_factory_impl_unittest.cc
@@ -18,12 +18,14 @@
#include "base/memory/weak_ptr.h"
#include "base/path_service.h"
#include "base/run_loop.h"
+#include "base/task/post_task.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/loader/mojo_async_resource_handler.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/loader/resource_message_filter.h"
#include "content/browser/loader/resource_request_info_impl.h"
#include "content/browser/loader_delegate_impl.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/resource_context.h"
#include "content/public/browser/resource_dispatcher_host_delegate.h"
#include "content/public/common/content_paths.h"
@@ -74,9 +76,12 @@ class URLLoaderFactoryImplTest : public ::testing::TestWithParam<size_t> {
nullptr,
nullptr,
nullptr,
+ BrowserContext::GetSharedCorsOriginAccessList(
+ browser_context_.get()),
base::Bind(&URLLoaderFactoryImplTest::GetContexts,
base::Unretained(this)),
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO))) {
+ base::CreateSingleThreadTaskRunnerWithTraits(
+ {BrowserThread::IO}))) {
// Some tests specify request.report_raw_headers, but the RDH checks the
// CanReadRawCookies permission before enabling it.
ChildProcessSecurityPolicyImpl::GetInstance()->Add(kChildId);
diff --git a/chromium/content/browser/mach_broker_mac.mm b/chromium/content/browser/mach_broker_mac.mm
index 21d1a5caf2f..01990f7ab91 100644
--- a/chromium/content/browser/mach_broker_mac.mm
+++ b/chromium/content/browser/mach_broker_mac.mm
@@ -8,7 +8,9 @@
#include "base/bind_helpers.h"
#include "base/command_line.h"
#include "base/logging.h"
+#include "base/task/post_task.h"
#include "content/common/content_constants_internal.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/child_process_data.h"
#include "content/public/browser/render_process_host.h"
@@ -34,8 +36,8 @@ void MachBroker::EnsureRunning() {
// Do not attempt to reinitialize in the event of failure.
initialized_ = true;
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::Bind(&MachBroker::RegisterNotifications, base::Unretained(this)));
if (!broker_.Init()) {
diff --git a/chromium/content/browser/manifest/manifest_icon_downloader.cc b/chromium/content/browser/manifest/manifest_icon_downloader.cc
index ac40d4cefb5..0a29672a383 100644
--- a/chromium/content/browser/manifest/manifest_icon_downloader.cc
+++ b/chromium/content/browser/manifest/manifest_icon_downloader.cc
@@ -8,6 +8,8 @@
#include <limits>
+#include "base/task/post_task.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
@@ -108,8 +110,8 @@ void ManifestIconDownloader::OnIconFetched(
// webapp storage system as well.
if (chosen.height() > ideal_icon_size_in_px ||
chosen.width() > ideal_icon_size_in_px) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&ManifestIconDownloader::ScaleIcon,
ideal_icon_size_in_px, chosen, callback));
return;
@@ -128,8 +130,8 @@ void ManifestIconDownloader::ScaleIcon(
bitmap, skia::ImageOperations::RESIZE_BEST, ideal_icon_size_in_px,
ideal_icon_size_in_px);
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(callback, scaled));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(callback, scaled));
}
int ManifestIconDownloader::FindClosestBitmapIndex(
diff --git a/chromium/content/browser/media/android/browser_gpu_video_accelerator_factories.cc b/chromium/content/browser/media/android/browser_gpu_video_accelerator_factories.cc
new file mode 100644
index 00000000000..1b8d471d252
--- /dev/null
+++ b/chromium/content/browser/media/android/browser_gpu_video_accelerator_factories.cc
@@ -0,0 +1,210 @@
+// 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/android/browser_gpu_video_accelerator_factories.h"
+
+#include "content/browser/browser_main_loop.h"
+#include "content/public/browser/android/gpu_video_accelerator_factories_provider.h"
+#include "content/public/common/gpu_stream_constants.h"
+#include "gpu/command_buffer/client/shared_memory_limits.h"
+#include "gpu/command_buffer/common/context_creation_attribs.h"
+#include "gpu/ipc/client/command_buffer_proxy_impl.h"
+#include "gpu/ipc/client/gpu_channel_host.h"
+#include "media/gpu/gpu_video_accelerator_util.h"
+#include "media/gpu/ipc/common/media_messages.h"
+#include "services/ws/public/cpp/gpu/context_provider_command_buffer.h"
+
+namespace content {
+
+namespace {
+
+void OnGpuChannelEstablished(
+ GpuVideoAcceleratorFactoriesCallback callback,
+ scoped_refptr<gpu::GpuChannelHost> gpu_channel_host) {
+ gpu::ContextCreationAttribs attributes;
+ attributes.alpha_size = -1;
+ attributes.red_size = 8;
+ attributes.green_size = 8;
+ attributes.blue_size = 8;
+ attributes.stencil_size = 0;
+ attributes.depth_size = 0;
+ attributes.samples = 0;
+ attributes.sample_buffers = 0;
+ attributes.bind_generates_resource = false;
+
+ gpu::GpuChannelEstablishFactory* factory =
+ BrowserMainLoop::GetInstance()->gpu_channel_establish_factory();
+
+ int32_t stream_id = kGpuStreamIdDefault;
+ gpu::SchedulingPriority stream_priority = kGpuStreamPriorityUI;
+
+ constexpr bool automatic_flushes = false;
+ constexpr bool support_locking = false;
+ constexpr bool support_grcontext = true;
+
+ auto context_provider =
+ base::MakeRefCounted<ws::ContextProviderCommandBuffer>(
+ std::move(gpu_channel_host), factory->GetGpuMemoryBufferManager(),
+ stream_id, stream_priority, gpu::kNullSurfaceHandle,
+ GURL(std::string("chrome://gpu/"
+ "BrowserGpuVideoAcceleratorFactories::"
+ "CreateGpuVideoAcceleratorFactories")),
+ automatic_flushes, support_locking, support_grcontext,
+ gpu::SharedMemoryLimits::ForMailboxContext(), attributes,
+ ws::command_buffer_metrics::ContextType::UNKNOWN);
+
+ // TODO(xingliu): This is on main thread, move to another thread?
+ context_provider->BindToCurrentThread();
+
+ auto gpu_factories = std::make_unique<BrowserGpuVideoAcceleratorFactories>(
+ std::move(context_provider));
+ std::move(callback).Run(std::move(gpu_factories));
+}
+
+} // namespace
+
+void CreateGpuVideoAcceleratorFactories(
+ GpuVideoAcceleratorFactoriesCallback callback) {
+ BrowserMainLoop::GetInstance()
+ ->gpu_channel_establish_factory()
+ ->EstablishGpuChannel(
+ base::BindOnce(&OnGpuChannelEstablished, std::move(callback)));
+}
+
+BrowserGpuVideoAcceleratorFactories::BrowserGpuVideoAcceleratorFactories(
+ scoped_refptr<ws::ContextProviderCommandBuffer> context_provider)
+ : context_provider_(std::move(context_provider)) {}
+
+BrowserGpuVideoAcceleratorFactories::~BrowserGpuVideoAcceleratorFactories() =
+ default;
+
+bool BrowserGpuVideoAcceleratorFactories::IsGpuVideoAcceleratorEnabled() {
+ return false;
+}
+
+base::UnguessableToken BrowserGpuVideoAcceleratorFactories::GetChannelToken() {
+ if (channel_token_.is_empty()) {
+ context_provider_->GetCommandBufferProxy()->channel()->Send(
+ new GpuCommandBufferMsg_GetChannelToken(&channel_token_));
+ }
+
+ return channel_token_;
+}
+
+int32_t BrowserGpuVideoAcceleratorFactories::GetCommandBufferRouteId() {
+ return context_provider_->GetCommandBufferProxy()->route_id();
+}
+
+bool BrowserGpuVideoAcceleratorFactories::IsDecoderConfigSupported(
+ const media::VideoDecoderConfig& config) {
+ // TODO(sandersd): Add a cache here too?
+ return true;
+}
+
+std::unique_ptr<media::VideoDecoder>
+BrowserGpuVideoAcceleratorFactories::CreateVideoDecoder(
+ media::MediaLog* media_log,
+ const media::RequestOverlayInfoCB& request_overlay_info_cb,
+ const gfx::ColorSpace& target_color_space) {
+ return nullptr;
+}
+
+std::unique_ptr<media::VideoDecodeAccelerator>
+BrowserGpuVideoAcceleratorFactories::CreateVideoDecodeAccelerator() {
+ return nullptr;
+}
+
+std::unique_ptr<media::VideoEncodeAccelerator>
+BrowserGpuVideoAcceleratorFactories::CreateVideoEncodeAccelerator() {
+ return nullptr;
+}
+
+bool BrowserGpuVideoAcceleratorFactories::CreateTextures(
+ int32_t count,
+ const gfx::Size& size,
+ std::vector<uint32_t>* texture_ids,
+ std::vector<gpu::Mailbox>* texture_mailboxes,
+ uint32_t texture_target) {
+ return false;
+}
+
+void BrowserGpuVideoAcceleratorFactories::DeleteTexture(uint32_t texture_id) {}
+
+gpu::SyncToken BrowserGpuVideoAcceleratorFactories::CreateSyncToken() {
+ return gpu::SyncToken();
+}
+
+void BrowserGpuVideoAcceleratorFactories::ShallowFlushCHROMIUM() {}
+
+void BrowserGpuVideoAcceleratorFactories::WaitSyncToken(
+ const gpu::SyncToken& sync_token) {}
+
+void BrowserGpuVideoAcceleratorFactories::SignalSyncToken(
+ const gpu::SyncToken& sync_token,
+ base::OnceClosure callback) {}
+
+std::unique_ptr<gfx::GpuMemoryBuffer>
+BrowserGpuVideoAcceleratorFactories::CreateGpuMemoryBuffer(
+ const gfx::Size& size,
+ gfx::BufferFormat format,
+ gfx::BufferUsage usage) {
+ return nullptr;
+}
+
+bool BrowserGpuVideoAcceleratorFactories::
+ ShouldUseGpuMemoryBuffersForVideoFrames(bool for_media_stream) const {
+ return false;
+}
+
+unsigned BrowserGpuVideoAcceleratorFactories::ImageTextureTarget(
+ gfx::BufferFormat format) {
+ return -1;
+}
+
+media::GpuVideoAcceleratorFactories::OutputFormat
+BrowserGpuVideoAcceleratorFactories::VideoFrameOutputFormat(
+ media::VideoPixelFormat pixel_format) {
+ return GpuVideoAcceleratorFactories::OutputFormat::UNDEFINED;
+}
+
+gpu::gles2::GLES2Interface* BrowserGpuVideoAcceleratorFactories::ContextGL() {
+ return nullptr;
+}
+
+std::unique_ptr<base::SharedMemory>
+BrowserGpuVideoAcceleratorFactories::CreateSharedMemory(size_t size) {
+ return nullptr;
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+BrowserGpuVideoAcceleratorFactories::GetTaskRunner() {
+ return nullptr;
+}
+
+media::VideoDecodeAccelerator::Capabilities
+BrowserGpuVideoAcceleratorFactories::GetVideoDecodeAcceleratorCapabilities() {
+ DCHECK(context_provider_);
+ auto* proxy = context_provider_->GetCommandBufferProxy();
+ DCHECK(proxy);
+ DCHECK(proxy->channel());
+
+ return media::GpuVideoAcceleratorUtil::ConvertGpuToMediaDecodeCapabilities(
+ proxy->channel()->gpu_info().video_decode_accelerator_capabilities);
+}
+
+media::VideoEncodeAccelerator::SupportedProfiles
+BrowserGpuVideoAcceleratorFactories::
+ GetVideoEncodeAcceleratorSupportedProfiles() {
+ return media::VideoEncodeAccelerator::SupportedProfiles();
+}
+
+scoped_refptr<ws::ContextProviderCommandBuffer>
+BrowserGpuVideoAcceleratorFactories::GetMediaContextProvider() {
+ return context_provider_;
+}
+
+void BrowserGpuVideoAcceleratorFactories::SetRenderingColorSpace(
+ const gfx::ColorSpace& color_space) {}
+
+} // namespace content
diff --git a/chromium/content/browser/media/android/browser_gpu_video_accelerator_factories.h b/chromium/content/browser/media/android/browser_gpu_video_accelerator_factories.h
new file mode 100644
index 00000000000..a51a02d7d0d
--- /dev/null
+++ b/chromium/content/browser/media/android/browser_gpu_video_accelerator_factories.h
@@ -0,0 +1,76 @@
+// 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_ANDROID_BROWSER_GPU_VIDEO_ACCELERATOR_FACTORIES_H_
+#define CONTENT_BROWSER_MEDIA_ANDROID_BROWSER_GPU_VIDEO_ACCELERATOR_FACTORIES_H_
+
+#include "base/macros.h"
+#include "media/video/gpu_video_accelerator_factories.h"
+
+namespace content {
+
+// Provides hardware video decoding contexts in the browser process. Used to
+// generate video thumbnail.
+class BrowserGpuVideoAcceleratorFactories
+ : public media::GpuVideoAcceleratorFactories {
+ public:
+ explicit BrowserGpuVideoAcceleratorFactories(
+ scoped_refptr<ws::ContextProviderCommandBuffer>);
+ ~BrowserGpuVideoAcceleratorFactories() override;
+
+ private:
+ // media::GpuVideoAcceleratorFactories implementation.
+ bool IsGpuVideoAcceleratorEnabled() override;
+ base::UnguessableToken GetChannelToken() override;
+ int32_t GetCommandBufferRouteId() override;
+ bool IsDecoderConfigSupported(
+ const media::VideoDecoderConfig& config) override;
+ std::unique_ptr<media::VideoDecoder> CreateVideoDecoder(
+ media::MediaLog* media_log,
+ const media::RequestOverlayInfoCB& request_overlay_info_cb,
+ const gfx::ColorSpace& target_color_space) override;
+ std::unique_ptr<media::VideoDecodeAccelerator> CreateVideoDecodeAccelerator()
+ override;
+ std::unique_ptr<media::VideoEncodeAccelerator> CreateVideoEncodeAccelerator()
+ override;
+ bool CreateTextures(int32_t count,
+ const gfx::Size& size,
+ std::vector<uint32_t>* texture_ids,
+ std::vector<gpu::Mailbox>* texture_mailboxes,
+ uint32_t texture_target) override;
+ void DeleteTexture(uint32_t texture_id) override;
+ gpu::SyncToken CreateSyncToken() override;
+ void ShallowFlushCHROMIUM() override;
+ void WaitSyncToken(const gpu::SyncToken& sync_token) override;
+ void SignalSyncToken(const gpu::SyncToken& sync_token,
+ base::OnceClosure callback) override;
+ std::unique_ptr<gfx::GpuMemoryBuffer> CreateGpuMemoryBuffer(
+ const gfx::Size& size,
+ gfx::BufferFormat format,
+ gfx::BufferUsage usage) override;
+ bool ShouldUseGpuMemoryBuffersForVideoFrames(
+ bool for_media_stream) const override;
+ unsigned ImageTextureTarget(gfx::BufferFormat format) override;
+ media::GpuVideoAcceleratorFactories::OutputFormat VideoFrameOutputFormat(
+ media::VideoPixelFormat pixel_format) override;
+ gpu::gles2::GLES2Interface* ContextGL() override;
+ std::unique_ptr<base::SharedMemory> CreateSharedMemory(size_t size) override;
+ scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() override;
+ media::VideoDecodeAccelerator::Capabilities
+ GetVideoDecodeAcceleratorCapabilities() override;
+ media::VideoEncodeAccelerator::SupportedProfiles
+ GetVideoEncodeAcceleratorSupportedProfiles() override;
+ scoped_refptr<ws::ContextProviderCommandBuffer> GetMediaContextProvider()
+ override;
+ void SetRenderingColorSpace(const gfx::ColorSpace& color_space) override;
+
+ scoped_refptr<ws::ContextProviderCommandBuffer> context_provider_;
+ base::UnguessableToken channel_token_;
+
+ DISALLOW_COPY_AND_ASSIGN(BrowserGpuVideoAcceleratorFactories);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_MEDIA_ANDROID_BROWSER_GPU_VIDEO_ACCELERATOR_FACTORIES_H_
diff --git a/chromium/content/browser/media/android/media_player_renderer.cc b/chromium/content/browser/media/android/media_player_renderer.cc
index 05d7c6a039d..4384142774e 100644
--- a/chromium/content/browser/media/android/media_player_renderer.cc
+++ b/chromium/content/browser/media/android/media_player_renderer.cc
@@ -7,11 +7,13 @@
#include <memory>
#include "base/callback_helpers.h"
+#include "base/task/post_task.h"
#include "content/browser/android/scoped_surface_request_manager.h"
#include "content/browser/media/android/media_player_renderer_web_contents_observer.h"
#include "content/browser/media/android/media_resource_getter_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/storage_partition.h"
@@ -89,8 +91,8 @@ void MediaPlayerRenderer::Initialize(media::MediaResource* media_resource,
return;
}
- BrowserThread::PostDelayedTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostDelayedTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::Bind(&MediaPlayerRenderer::CreateMediaPlayer,
weak_factory_.GetWeakPtr(),
media_resource->GetMediaUrlParams(), init_cb),
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 74a94dfa97d..88841bbd902 100644
--- a/chromium/content/browser/media/android/media_resource_getter_impl.cc
+++ b/chromium/content/browser/media/android/media_resource_getter_impl.cc
@@ -13,6 +13,7 @@
#include "content/browser/fileapi/browser_file_system_helper.h"
#include "content/browser/resource_context_impl.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/storage_partition.h"
@@ -44,8 +45,8 @@ network::mojom::CookieManager* GetCookieServiceForContext(
void ReturnResultOnUIThread(
base::OnceCallback<void(const std::string&)> callback,
const std::string& result) {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(std::move(callback), result));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(std::move(callback), result));
}
// Checks the policy for get cookies and returns the cookie line if allowed.
@@ -76,8 +77,8 @@ void CheckPolicyForCookies(const GURL& url,
DCHECK_CURRENTLY_ON(BrowserThread::UI);
// AllowGetCookie has to be called on IO thread.
- BrowserThread::PostTaskAndReplyWithResult(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraitsAndReplyWithResult(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&GetCookiesOnIO, url, site_for_cookies, resource_context,
render_process_id, render_frame_id, cookie_list),
std::move(callback));
@@ -141,6 +142,11 @@ MediaResourceGetterTask::~MediaResourceGetterTask() {}
net::AuthCredentials MediaResourceGetterTask::RequestAuthCredentials(
const GURL& url) const {
DCHECK(GetTaskRunner()->BelongsToCurrentThread());
+ if (!url.IsStandard()) {
+ // Non-standard URLs, such as data, will not be found in HTTP auth cache
+ // anyway, because they have no valid origin, so don't waste the time.
+ return net::AuthCredentials();
+ }
net::HttpTransactionFactory* factory =
context_getter_->GetURLRequestContext()->http_transaction_factory();
if (!factory)
diff --git a/chromium/content/browser/media/audio_input_stream_broker.cc b/chromium/content/browser/media/audio_input_stream_broker.cc
index a93d2ca90f1..0fc989df67f 100644
--- a/chromium/content/browser/media/audio_input_stream_broker.cc
+++ b/chromium/content/browser/media/audio_input_stream_broker.cc
@@ -6,20 +6,24 @@
#include <utility>
+#include "base/bind.h"
#include "base/command_line.h"
+#include "base/location.h"
+#include "base/logging.h"
#include "base/memory/read_only_shared_memory_region.h"
#include "base/metrics/histogram_macros.h"
+#include "base/optional.h"
+#include "base/task/post_task.h"
#include "base/trace_event/trace_event.h"
+#include "build/build_config.h"
#include "content/browser/browser_main_loop.h"
#include "content/browser/media/media_internals.h"
+#include "content/public/browser/browser_task_traits.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/bindings/interface_request.h"
#include "mojo/public/cpp/system/platform_handle.h"
#if defined(OS_CHROMEOS)
@@ -28,12 +32,42 @@
namespace content {
+namespace {
+
+#if defined(OS_CHROMEOS)
+enum KeyboardMicAction { kRegister, kDeregister };
+
+void UpdateKeyboardMicRegistration(KeyboardMicAction action) {
+ if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(&UpdateKeyboardMicRegistration, action));
+ return;
+ }
+ BrowserMainLoop* browser_main_loop = BrowserMainLoop::GetInstance();
+ // May be null in unit tests.
+ if (!browser_main_loop)
+ return;
+ switch (action) {
+ case kRegister:
+ browser_main_loop->keyboard_mic_registration()->Register();
+ return;
+ case kDeregister:
+ browser_main_loop->keyboard_mic_registration()->Deregister();
+ return;
+ }
+}
+#endif
+
+} // namespace
+
AudioInputStreamBroker::AudioInputStreamBroker(
int render_process_id,
int render_frame_id,
const std::string& device_id,
const media::AudioParameters& params,
uint32_t shared_memory_count,
+ media::UserInputMonitorBase* user_input_monitor,
bool enable_agc,
audio::mojom::AudioProcessingConfigPtr processing_config,
AudioStreamBroker::DeleterCallback deleter,
@@ -42,13 +76,14 @@ AudioInputStreamBroker::AudioInputStreamBroker(
device_id_(device_id),
params_(params),
shared_memory_count_(shared_memory_count),
+ user_input_monitor_(user_input_monitor),
enable_agc_(enable_agc),
deleter_(std::move(deleter)),
processing_config_(std::move(processing_config)),
renderer_factory_client_(std::move(renderer_factory_client)),
observer_binding_(this),
weak_ptr_factory_(this) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(renderer_factory_client_);
DCHECK(deleter_);
TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("audio", "AudioInputStreamBroker", this);
@@ -57,53 +92,37 @@ AudioInputStreamBroker::AudioInputStreamBroker(
renderer_factory_client_.set_connection_error_handler(base::BindOnce(
&AudioInputStreamBroker::ClientBindingLost, 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();
+ NotifyProcessHostOfStartedStream(render_process_id);
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();
+ UpdateKeyboardMicRegistration(kRegister);
}
-#else
- user_input_monitor_ = static_cast<media::UserInputMonitorBase*>(
- browser_main_loop->user_input_monitor());
#endif
}
AudioInputStreamBroker::~AudioInputStreamBroker() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
#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();
+ UpdateKeyboardMicRegistration(kDeregister);
}
-#else
+#endif
+
+ // This relies on CreateStream() being called synchronously right after the
+ // constructor.
if (user_input_monitor_)
user_input_monitor_->DisableKeyPressMonitoring();
-#endif
- auto* process_host = RenderProcessHost::FromID(render_process_id());
- if (process_host)
- process_host->OnMediaStreamRemoved();
+ NotifyProcessHostOfStoppedStream(render_process_id());
// TODO(https://crbug.com/829317) update tab recording indicator.
@@ -121,7 +140,7 @@ AudioInputStreamBroker::~AudioInputStreamBroker() {
void AudioInputStreamBroker::CreateStream(
audio::mojom::StreamFactory* factory) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(!observer_binding_.is_bound());
DCHECK(!client_request_);
TRACE_EVENT_NESTABLE_ASYNC_BEGIN1("audio", "CreateStream", this, "device id",
@@ -151,8 +170,6 @@ void AudioInputStreamBroker::CreateStream(
// 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),
@@ -167,7 +184,7 @@ void AudioInputStreamBroker::CreateStream(
}
void AudioInputStreamBroker::DidStartRecording() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
// TODO(https://crbug.com/829317) update tab recording indicator.
}
@@ -176,7 +193,7 @@ void AudioInputStreamBroker::StreamCreated(
media::mojom::ReadOnlyAudioDataPipePtr data_pipe,
bool initially_muted,
const base::Optional<base::UnguessableToken>& stream_id) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
awaiting_created_ = false;
TRACE_EVENT_NESTABLE_ASYNC_END1("audio", "CreateStream", this, "success",
!!data_pipe);
@@ -197,7 +214,7 @@ void AudioInputStreamBroker::StreamCreated(
void AudioInputStreamBroker::ObserverBindingLost(
uint32_t reason,
const std::string& description) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
const uint32_t maxValidReason = static_cast<uint32_t>(
media::mojom::AudioInputStreamObserver::DisconnectReason::kMaxValue);
@@ -214,13 +231,14 @@ void AudioInputStreamBroker::ObserverBindingLost(
}
void AudioInputStreamBroker::ClientBindingLost() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
disconnect_reason_ = media::mojom::AudioInputStreamObserver::
DisconnectReason::kTerminatedByClient;
Cleanup();
}
void AudioInputStreamBroker::Cleanup() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
std::move(deleter_).Run(this);
}
diff --git a/chromium/content/browser/media/audio_input_stream_broker.h b/chromium/content/browser/media/audio_input_stream_broker.h
index 0ed31a6ee2f..397cb49cd8b 100644
--- a/chromium/content/browser/media/audio_input_stream_broker.h
+++ b/chromium/content/browser/media/audio_input_stream_broker.h
@@ -7,12 +7,13 @@
#include <string>
+#include "base/macros.h"
#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_data_pipe.mojom.h"
#include "media/mojo/interfaces/audio_input_stream.mojom.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "services/audio/public/mojom/audio_processing.mojom.h"
@@ -36,6 +37,7 @@ class CONTENT_EXPORT AudioInputStreamBroker final
const std::string& device_id,
const media::AudioParameters& params,
uint32_t shared_memory_count,
+ media::UserInputMonitorBase* user_input_monitor,
bool enable_agc,
audio::mojom::AudioProcessingConfigPtr processing_config,
AudioStreamBroker::DeleterCallback deleter,
@@ -62,8 +64,8 @@ class CONTENT_EXPORT AudioInputStreamBroker final
const std::string device_id_;
media::AudioParameters params_;
const uint32_t shared_memory_count_;
+ media::UserInputMonitorBase* const user_input_monitor_;
const bool enable_agc_;
- media::UserInputMonitorBase* user_input_monitor_ = nullptr;
// Indicates that CreateStream has been called, but not StreamCreated.
bool awaiting_created_ = false;
diff --git a/chromium/content/browser/media/audio_input_stream_broker_unittest.cc b/chromium/content/browser/media/audio_input_stream_broker_unittest.cc
index b68713ab8fc..c21c3176141 100644
--- a/chromium/content/browser/media/audio_input_stream_broker_unittest.cc
+++ b/chromium/content/browser/media/audio_input_stream_broker_unittest.cc
@@ -145,6 +145,7 @@ struct TestEnvironment {
kDeviceId,
TestParams(),
kShMemCount,
+ nullptr /*user_input_monitor*/,
kEnableAgc,
nullptr,
deleter.Get(),
@@ -169,7 +170,8 @@ TEST(AudioInputStreamBrokerTest, StoresProcessAndFrameId) {
AudioInputStreamBroker broker(
kRenderProcessId, kRenderFrameId, kDeviceId, TestParams(), kShMemCount,
- kEnableAgc, nullptr, deleter.Get(), renderer_factory_client.MakePtr());
+ nullptr /*user_input_monitor*/, kEnableAgc, nullptr, deleter.Get(),
+ renderer_factory_client.MakePtr());
EXPECT_EQ(kRenderProcessId, broker.render_process_id());
EXPECT_EQ(kRenderFrameId, broker.render_frame_id());
diff --git a/chromium/content/browser/media/audio_loopback_stream_broker.cc b/chromium/content/browser/media/audio_loopback_stream_broker.cc
index 884508c44f3..1b834987a49 100644
--- a/chromium/content/browser/media/audio_loopback_stream_broker.cc
+++ b/chromium/content/browser/media/audio_loopback_stream_broker.cc
@@ -6,77 +6,39 @@
#include <utility>
+#include "base/bind.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/task/post_task.h"
#include "base/unguessable_token.h"
-#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/render_process_host.h"
+#include "services/audio/public/mojom/stream_factory.mojom.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,
+ AudioStreamBroker::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)),
+ source_(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_CURRENTLY_ON(BrowserThread::IO);
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());
}
@@ -85,31 +47,27 @@ AudioLoopbackStreamBroker::AudioLoopbackStreamBroker(
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 the source that we are capturing from it.
+ source_->AddLoopbackSink(this);
- // 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();
+ NotifyProcessHostOfStartedStream(render_process_id);
}
AudioLoopbackStreamBroker::~AudioLoopbackStreamBroker() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
- source_->OnStopCapturing();
+ if (source_)
+ source_->RemoveLoopbackSink(this);
- if (auto* process_host = RenderProcessHost::FromID(render_process_id()))
- process_host->OnMediaStreamRemoved();
+ NotifyProcessHostOfStoppedStream(render_process_id());
}
void AudioLoopbackStreamBroker::CreateStream(
audio::mojom::StreamFactory* factory) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(!observer_binding_.is_bound());
DCHECK(!client_request_);
- DCHECK(source_->GetGroupID());
+ DCHECK(source_);
if (muter_) // Mute the source.
muter_->Connect(factory);
@@ -135,14 +93,21 @@ void AudioLoopbackStreamBroker::CreateStream(
weak_ptr_factory_.GetWeakPtr(), std::move(stream)));
}
+void AudioLoopbackStreamBroker::OnSourceGone() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ // No further access to |source_| is allowed.
+ source_ = nullptr;
+ Cleanup();
+}
+
void AudioLoopbackStreamBroker::DidStartRecording() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
}
void AudioLoopbackStreamBroker::StreamCreated(
media::mojom::AudioInputStreamPtr stream,
media::mojom::ReadOnlyAudioDataPipePtr data_pipe) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (!data_pipe) {
Cleanup();
@@ -157,7 +122,7 @@ void AudioLoopbackStreamBroker::StreamCreated(
}
void AudioLoopbackStreamBroker::Cleanup() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
std::move(deleter_).Run(this);
}
diff --git a/chromium/content/browser/media/audio_loopback_stream_broker.h b/chromium/content/browser/media/audio_loopback_stream_broker.h
index 9853b4c9768..aa1f6f6d529 100644
--- a/chromium/content/browser/media/audio_loopback_stream_broker.h
+++ b/chromium/content/browser/media/audio_loopback_stream_broker.h
@@ -5,19 +5,25 @@
#ifndef CONTENT_BROWSER_MEDIA_AUDIO_LOOPBACK_STREAM_BROKER_H_
#define CONTENT_BROWSER_MEDIA_AUDIO_LOOPBACK_STREAM_BROKER_H_
+#include <cstdint>
#include <string>
+#include "base/macros.h"
#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_data_pipe.mojom.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 audio {
+namespace mojom {
+class StreamFactory;
+}
+} // namespace audio
namespace content {
@@ -25,12 +31,13 @@ namespace content {
// (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 media::mojom::AudioInputStreamObserver,
+ public AudioStreamBroker::LoopbackSink {
public:
AudioLoopbackStreamBroker(
int render_process_id,
int render_frame_id,
- std::unique_ptr<AudioStreamBrokerFactory::LoopbackSource> source,
+ AudioStreamBroker::LoopbackSource* source,
const media::AudioParameters& params,
uint32_t shared_memory_count,
bool mute_source,
@@ -45,12 +52,17 @@ class CONTENT_EXPORT AudioLoopbackStreamBroker final
// media::AudioInputStreamObserver implementation.
void DidStartRecording() final;
+ // AudioStreamBroker::LoopbackSink
+ void OnSourceGone() final;
+
private:
void StreamCreated(media::mojom::AudioInputStreamPtr stream,
media::mojom::ReadOnlyAudioDataPipePtr data_pipe);
void Cleanup();
- const std::unique_ptr<AudioStreamBrokerFactory::LoopbackSource> source_;
+ // Owner of the output streams to be looped back.
+ AudioStreamBroker::LoopbackSource* source_;
+
const media::AudioParameters params_;
const uint32_t shared_memory_count_;
diff --git a/chromium/content/browser/media/audio_loopback_stream_broker_unittest.cc b/chromium/content/browser/media/audio_loopback_stream_broker_unittest.cc
index 14923ed61e4..f72c1d64c4b 100644
--- a/chromium/content/browser/media/audio_loopback_stream_broker_unittest.cc
+++ b/chromium/content/browser/media/audio_loopback_stream_broker_unittest.cc
@@ -35,16 +35,15 @@ media::AudioParameters TestParams() {
return media::AudioParameters::UnavailableDeviceParams();
}
-class MockSource : public AudioStreamBrokerFactory::LoopbackSource {
+class MockSource : public AudioStreamBroker::LoopbackSource {
public:
- explicit MockSource(const base::UnguessableToken& group_id)
- : group_id_(group_id) {}
+ MockSource() : group_id_(base::UnguessableToken::Create()) {}
~MockSource() override {}
// AudioStreamBrokerFactory::LoopbackSource mocking.
- base::UnguessableToken GetGroupID() override { return group_id_; }
- MOCK_METHOD0(OnStartCapturing, void(void));
- MOCK_METHOD0(OnStopCapturing, void(void));
+ const base::UnguessableToken& GetGroupID() override { return group_id_; }
+ MOCK_METHOD1(AddLoopbackSink, void(AudioStreamBroker::LoopbackSink*));
+ MOCK_METHOD1(RemoveLoopbackSink, void(AudioStreamBroker::LoopbackSink*));
private:
base::UnguessableToken group_id_;
@@ -158,19 +157,17 @@ 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();
+ EXPECT_CALL(source, AddLoopbackSink(_));
broker = std::make_unique<AudioLoopbackStreamBroker>(
- kRenderProcessId, kRenderFrameId, std::move(mock_source), TestParams(),
- kShMemCount, mute_source, deleter.Get(),
- renderer_factory_client.MakePtr());
+ kRenderProcessId, kRenderFrameId, &source, TestParams(), kShMemCount,
+ mute_source, deleter.Get(), renderer_factory_client.MakePtr());
}
void RunUntilIdle() { thread_bundle.RunUntilIdle(); }
TestBrowserThreadBundle thread_bundle;
MockDeleterCallback deleter;
- MockSource* source;
+ MockSource source;
StrictMock<MockRendererAudioInputStreamFactoryClient> renderer_factory_client;
std::unique_ptr<AudioLoopbackStreamBroker> broker;
MockStreamFactory stream_factory;
@@ -184,27 +181,24 @@ TEST(AudioLoopbackStreamBrokerTest, StoresProcessAndFrameId) {
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();
+ MockSource source;
- EXPECT_CALL(*mock_source, OnStartCapturing());
+ EXPECT_CALL(source, AddLoopbackSink(_));
- AudioLoopbackStreamBroker broker(kRenderProcessId, kRenderFrameId,
- std::move(source), TestParams(), kShMemCount,
- !kMuteSource, deleter.Get(),
- renderer_factory_client.MakePtr());
+ AudioLoopbackStreamBroker broker(
+ kRenderProcessId, kRenderFrameId, &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());
+ EXPECT_CALL(source, RemoveLoopbackSink(&broker));
}
TEST(AudioLoopbackStreamBrokerTest, StreamCreationSuccess_Propagates) {
TestEnvironment env(base::UnguessableToken::Create(), !kMuteSource);
MockStreamFactory::StreamRequestData stream_request_data(
- env.source->GetGroupID(), TestParams());
+ env.source.GetGroupID(), TestParams());
env.stream_factory.ExpectStreamCreation(&stream_request_data);
EXPECT_CALL(env.stream_factory, IsMuting(_)).Times(0);
@@ -234,10 +228,10 @@ TEST(AudioLoopbackStreamBrokerTest, StreamCreationSuccess_Propagates) {
TEST(AudioLoopbackStreamBrokerTest, MutedStreamCreation_Mutes) {
TestEnvironment env(base::UnguessableToken::Create(), kMuteSource);
MockStreamFactory::StreamRequestData stream_request_data(
- env.source->GetGroupID(), TestParams());
+ env.source.GetGroupID(), TestParams());
env.stream_factory.ExpectStreamCreation(&stream_request_data);
- EXPECT_CALL(env.stream_factory, IsMuting(env.source->GetGroupID()));
+ EXPECT_CALL(env.stream_factory, IsMuting(env.source.GetGroupID()));
env.broker->CreateStream(env.factory_ptr.get());
env.RunUntilIdle();
@@ -264,10 +258,10 @@ TEST(AudioLoopbackStreamBrokerTest, MutedStreamCreation_Mutes) {
TEST(AudioLoopbackStreamBrokerTest, SourceGone_CallsDeleter) {
TestEnvironment env(base::UnguessableToken::Create(), kMuteSource);
MockStreamFactory::StreamRequestData stream_request_data(
- env.source->GetGroupID(), TestParams());
+ env.source.GetGroupID(), TestParams());
env.stream_factory.ExpectStreamCreation(&stream_request_data);
- EXPECT_CALL(env.stream_factory, IsMuting(env.source->GetGroupID()));
+ EXPECT_CALL(env.stream_factory, IsMuting(env.source.GetGroupID()));
env.broker->CreateStream(env.factory_ptr.get());
env.RunUntilIdle();
@@ -289,10 +283,12 @@ TEST(AudioLoopbackStreamBrokerTest, SourceGone_CallsDeleter) {
Mock::VerifyAndClear(&env.renderer_factory_client);
- EXPECT_CALL(env.deleter, Run(env.broker.release()))
- .WillOnce(testing::DeleteArg<0>());
+ EXPECT_CALL(env.deleter, Run(env.broker.get()));
+
+ // Accessing source is not allowed after OnSourceGone.
+ EXPECT_CALL(env.source, RemoveLoopbackSink(_)).Times(0);
- env.source->WebContentsDestroyed();
+ env.broker->OnSourceGone();
env.RunUntilIdle();
}
@@ -300,7 +296,7 @@ TEST(AudioLoopbackStreamBrokerTest, SourceGone_CallsDeleter) {
TEST(AudioLoopbackStreamBrokerTest, StreamCreationFailure_CallsDeleter) {
TestEnvironment env(base::UnguessableToken::Create(), !kMuteSource);
MockStreamFactory::StreamRequestData stream_request_data(
- env.source->GetGroupID(), TestParams());
+ env.source.GetGroupID(), TestParams());
env.stream_factory.ExpectStreamCreation(&stream_request_data);
EXPECT_CALL(env.stream_factory, IsMuting(_)).Times(0);
@@ -321,7 +317,7 @@ TEST(AudioLoopbackStreamBrokerTest,
RendererFactoryClientDisconnect_CallsDeleter) {
TestEnvironment env(base::UnguessableToken::Create(), !kMuteSource);
MockStreamFactory::StreamRequestData stream_request_data(
- env.source->GetGroupID(), TestParams());
+ env.source.GetGroupID(), TestParams());
env.stream_factory.ExpectStreamCreation(&stream_request_data);
EXPECT_CALL(env.stream_factory, IsMuting(_)).Times(0);
@@ -343,7 +339,7 @@ TEST(AudioLoopbackStreamBrokerTest,
TEST(AudioLoopbackStreamBrokerTest, ObserverDisconnect_CallsDeleter) {
TestEnvironment env(base::UnguessableToken::Create(), !kMuteSource);
MockStreamFactory::StreamRequestData stream_request_data(
- env.source->GetGroupID(), TestParams());
+ env.source.GetGroupID(), TestParams());
env.stream_factory.ExpectStreamCreation(&stream_request_data);
EXPECT_CALL(env.stream_factory, IsMuting(_)).Times(0);
diff --git a/chromium/content/browser/media/audio_output_stream_broker.cc b/chromium/content/browser/media/audio_output_stream_broker.cc
index 1ddd0ad978d..2ee519d96de 100644
--- a/chromium/content/browser/media/audio_output_stream_broker.cc
+++ b/chromium/content/browser/media/audio_output_stream_broker.cc
@@ -16,6 +16,48 @@
namespace content {
+namespace {
+
+// Used in Media.Audio.Render.StreamBrokerDisconnectReason2 histogram, matches
+// StreamBrokerDisconnectReason2 enum.
+enum class StreamBrokerDisconnectReason {
+ kDefault = 0,
+ kPlatformError,
+ kTerminatedByClient,
+ kTerminatedByClientAwaitingCreated,
+ kStreamCreationFailed,
+ kDocumentDestroyed,
+ kDocumentDestroyedAwaitingCreated,
+ kMaxValue = kDocumentDestroyedAwaitingCreated
+};
+
+using DisconnectReason =
+ media::mojom::AudioOutputStreamObserver::DisconnectReason;
+
+StreamBrokerDisconnectReason GetDisconnectReason(DisconnectReason reason,
+ bool awaiting_created) {
+ switch (reason) {
+ case DisconnectReason::kPlatformError:
+ return StreamBrokerDisconnectReason::kPlatformError;
+ case DisconnectReason::kTerminatedByClient:
+ return awaiting_created
+ ? StreamBrokerDisconnectReason::
+ kTerminatedByClientAwaitingCreated
+ : StreamBrokerDisconnectReason::kTerminatedByClient;
+ case DisconnectReason::kStreamCreationFailed:
+ return StreamBrokerDisconnectReason::kStreamCreationFailed;
+ case DisconnectReason::kDocumentDestroyed:
+ return awaiting_created
+ ? StreamBrokerDisconnectReason::
+ kDocumentDestroyedAwaitingCreated
+ : StreamBrokerDisconnectReason::kDocumentDestroyed;
+ case DisconnectReason::kDefault:
+ return StreamBrokerDisconnectReason::kDefault;
+ }
+}
+
+} // namespace
+
AudioOutputStreamBroker::AudioOutputStreamBroker(
int render_process_id,
int render_frame_id,
@@ -49,23 +91,34 @@ AudioOutputStreamBroker::AudioOutputStreamBroker(
media_observer->OnCreatingAudioStream(render_process_id, render_frame_id);
// Unretained is safe because |this| owns |client_|
- client_.set_connection_error_handler(base::BindOnce(
- &AudioOutputStreamBroker::ClientBindingLost, base::Unretained(this)));
+ client_.set_connection_error_handler(
+ base::BindOnce(&AudioOutputStreamBroker::Cleanup, base::Unretained(this),
+ DisconnectReason::kTerminatedByClient));
}
AudioOutputStreamBroker::~AudioOutputStreamBroker() {
DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
- if (awaiting_created_) {
+ const StreamBrokerDisconnectReason reason =
+ GetDisconnectReason(disconnect_reason_, AwaitingCreated());
+
+ if (AwaitingCreated()) {
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_));
+ static_cast<uint32_t>(reason));
+
+ UMA_HISTOGRAM_ENUMERATION("Media.Audio.Render.StreamBrokerDisconnectReason2",
+ reason);
- UMA_HISTOGRAM_ENUMERATION("Media.Audio.Render.StreamBrokerDisconnectReason",
- disconnect_reason_);
+ if (AwaitingCreated()) {
+ UMA_HISTOGRAM_TIMES(
+ "Media.Audio.Render.StreamBrokerDocumentDestroyedAwaitingCreatedTime",
+ base::TimeTicks::Now() - stream_creation_start_time_);
+ }
}
void AudioOutputStreamBroker::CreateStream(
@@ -74,7 +127,7 @@ void AudioOutputStreamBroker::CreateStream(
DCHECK(!observer_binding_.is_bound());
TRACE_EVENT_NESTABLE_ASYNC_BEGIN1("audio", "CreateStream", this, "device id",
output_device_id_);
- awaiting_created_ = true;
+ stream_creation_start_time_ = base::TimeTicks::Now();
// Set up observer ptr. Unretained is safe because |this| owns
// |observer_binding_|.
@@ -107,16 +160,15 @@ void AudioOutputStreamBroker::StreamCreated(
DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
TRACE_EVENT_NESTABLE_ASYNC_END1("audio", "CreateStream", this, "success",
!!data_pipe);
- awaiting_created_ = false;
+ UMA_HISTOGRAM_TIMES("Media.Audio.Render.StreamBrokerStreamCreationTime",
+ base::TimeTicks::Now() - stream_creation_start_time_);
+ stream_creation_start_time_ = base::TimeTicks();
+
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();
+ static_cast<uint32_t>(DisconnectReason::kPlatformError), std::string());
+ Cleanup(DisconnectReason::kStreamCreationFailed);
return;
}
@@ -127,39 +179,31 @@ 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) {
+ if (reason > static_cast<uint32_t>(DisconnectReason::kMaxValue))
NOTREACHED() << "Invalid reason: " << reason;
- } else if (disconnect_reason_ == media::mojom::AudioOutputStreamObserver::
- DisconnectReason::kDocumentDestroyed) {
- disconnect_reason_ =
- static_cast<media::mojom::AudioOutputStreamObserver::DisconnectReason>(
- reason);
- }
+
+ DisconnectReason reason_enum = static_cast<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();
+ static_cast<uint32_t>(DisconnectReason::kPlatformError), std::string());
+ Cleanup((reason_enum == DisconnectReason::kPlatformError && AwaitingCreated())
+ ? DisconnectReason::kStreamCreationFailed
+ : reason_enum);
}
-void AudioOutputStreamBroker::ClientBindingLost() {
- disconnect_reason_ = media::mojom::AudioOutputStreamObserver::
- DisconnectReason::kTerminatedByClient;
- Cleanup();
-}
-
-void AudioOutputStreamBroker::Cleanup() {
+void AudioOutputStreamBroker::Cleanup(DisconnectReason reason) {
DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+ DCHECK_EQ(DisconnectReason::kDocumentDestroyed, disconnect_reason_);
+ disconnect_reason_ = reason;
std::move(deleter_).Run(this);
}
+bool AudioOutputStreamBroker::AwaitingCreated() const {
+ return stream_creation_start_time_ != base::TimeTicks();
+}
+
} // namespace content
diff --git a/chromium/content/browser/media/audio_output_stream_broker.h b/chromium/content/browser/media/audio_output_stream_broker.h
index 0f044081998..458a78caa6b 100644
--- a/chromium/content/browser/media/audio_output_stream_broker.h
+++ b/chromium/content/browser/media/audio_output_stream_broker.h
@@ -44,11 +44,14 @@ class CONTENT_EXPORT AudioOutputStreamBroker final : public AudioStreamBroker {
void CreateStream(audio::mojom::StreamFactory* factory) final;
private:
+ using DisconnectReason =
+ media::mojom::AudioOutputStreamObserver::DisconnectReason;
+
void StreamCreated(media::mojom::AudioOutputStreamPtr stream,
media::mojom::ReadWriteAudioDataPipePtr data_pipe);
void ObserverBindingLost(uint32_t reason, const std::string& description);
- void ClientBindingLost();
- void Cleanup();
+ void Cleanup(DisconnectReason reason);
+ bool AwaitingCreated() const;
SEQUENCE_CHECKER(owning_sequence_);
@@ -57,8 +60,8 @@ class CONTENT_EXPORT AudioOutputStreamBroker final : public AudioStreamBroker {
const base::UnguessableToken group_id_;
const base::Optional<base::UnguessableToken> processing_id_;
- // Indicates that CreateStream has been called, but not StreamCreated.
- bool awaiting_created_ = false;
+ // Set while CreateStream() has been called, but not StreamCreated().
+ base::TimeTicks stream_creation_start_time_;
DeleterCallback deleter_;
@@ -68,9 +71,7 @@ class CONTENT_EXPORT AudioOutputStreamBroker final : public AudioStreamBroker {
mojo::AssociatedBinding<media::mojom::AudioOutputStreamObserver>
observer_binding_;
- media::mojom::AudioOutputStreamObserver::DisconnectReason disconnect_reason_ =
- media::mojom::AudioOutputStreamObserver::DisconnectReason::
- kDocumentDestroyed;
+ DisconnectReason disconnect_reason_ = DisconnectReason::kDocumentDestroyed;
base::WeakPtrFactory<AudioOutputStreamBroker> weak_ptr_factory_;
diff --git a/chromium/content/browser/media/audio_stream_broker.cc b/chromium/content/browser/media/audio_stream_broker.cc
index 9894ff13d7c..875d810eb3d 100644
--- a/chromium/content/browser/media/audio_stream_broker.cc
+++ b/chromium/content/browser/media/audio_stream_broker.cc
@@ -6,9 +6,15 @@
#include <utility>
+#include "base/bind.h"
+#include "base/location.h"
+#include "base/task/post_task.h"
#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"
+#include "content/public/browser/browser_task_traits.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_process_host.h"
namespace content {
@@ -25,6 +31,7 @@ class AudioStreamBrokerFactoryImpl final : public AudioStreamBrokerFactory {
const std::string& device_id,
const media::AudioParameters& params,
uint32_t shared_memory_count,
+ media::UserInputMonitorBase* user_input_monitor,
bool enable_agc,
audio::mojom::AudioProcessingConfigPtr processing_config,
AudioStreamBroker::DeleterCallback deleter,
@@ -32,14 +39,15 @@ class AudioStreamBrokerFactoryImpl final : public AudioStreamBrokerFactory {
final {
return std::make_unique<AudioInputStreamBroker>(
render_process_id, render_frame_id, device_id, params,
- shared_memory_count, enable_agc, std::move(processing_config),
- std::move(deleter), std::move(renderer_factory_client));
+ shared_memory_count, user_input_monitor, enable_agc,
+ std::move(processing_config), 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,
+ AudioStreamBroker::LoopbackSource* source,
const media::AudioParameters& params,
uint32_t shared_memory_count,
bool mute_source,
@@ -47,9 +55,8 @@ class AudioStreamBrokerFactoryImpl final : public AudioStreamBrokerFactory {
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));
+ render_process_id, render_frame_id, source, params, shared_memory_count,
+ mute_source, std::move(deleter), std::move(renderer_factory_client));
}
std::unique_ptr<AudioStreamBroker> CreateAudioOutputStreamBroker(
@@ -70,11 +77,39 @@ class AudioStreamBrokerFactoryImpl final : public AudioStreamBrokerFactory {
} // namespace
+AudioStreamBroker::LoopbackSink::LoopbackSink() = default;
+AudioStreamBroker::LoopbackSink::~LoopbackSink() = default;
+
+AudioStreamBroker::LoopbackSource::LoopbackSource() = default;
+AudioStreamBroker::LoopbackSource::~LoopbackSource() = default;
+
AudioStreamBroker::AudioStreamBroker(int render_process_id, int render_frame_id)
: render_process_id_(render_process_id),
render_frame_id_(render_frame_id) {}
AudioStreamBroker::~AudioStreamBroker() {}
+// static
+void AudioStreamBroker::NotifyProcessHostOfStartedStream(
+ int render_process_id) {
+ auto impl = [](int id) {
+ if (auto* process_host = RenderProcessHost::FromID(id))
+ process_host->OnMediaStreamAdded();
+ };
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(impl, render_process_id));
+}
+
+// static
+void AudioStreamBroker::NotifyProcessHostOfStoppedStream(
+ int render_process_id) {
+ auto impl = [](int id) {
+ if (auto* process_host = RenderProcessHost::FromID(id))
+ process_host->OnMediaStreamRemoved();
+ };
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(impl, render_process_id));
+}
+
AudioStreamBrokerFactory::AudioStreamBrokerFactory() {}
AudioStreamBrokerFactory::~AudioStreamBrokerFactory() {}
diff --git a/chromium/content/browser/media/audio_stream_broker.h b/chromium/content/browser/media/audio_stream_broker.h
index e8deaa11bae..24d8928f4ba 100644
--- a/chromium/content/browser/media/audio_stream_broker.h
+++ b/chromium/content/browser/media/audio_stream_broker.h
@@ -5,15 +5,15 @@
#ifndef CONTENT_BROWSER_MEDIA_AUDIO_STREAM_BROKER_H_
#define CONTENT_BROWSER_MEDIA_AUDIO_STREAM_BROKER_H_
+#include <cstdint>
#include <memory>
#include <string>
-#include <utility>
#include "base/callback.h"
#include "base/macros.h"
+#include "base/optional.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"
#include "services/audio/public/mojom/audio_processing.mojom.h"
@@ -30,16 +30,39 @@ class UnguessableToken;
namespace media {
class AudioParameters;
+class UserInputMonitorBase;
}
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.
+// used for monitoring the stream. All AudioStreamBrokers are used on the IO
+// thread.
class CONTENT_EXPORT AudioStreamBroker {
public:
+ class CONTENT_EXPORT LoopbackSink {
+ public:
+ LoopbackSink();
+ virtual ~LoopbackSink();
+ virtual void OnSourceGone() = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(LoopbackSink);
+ };
+
+ class CONTENT_EXPORT LoopbackSource {
+ public:
+ LoopbackSource();
+ virtual ~LoopbackSource();
+ virtual void AddLoopbackSink(LoopbackSink* sink) = 0;
+ virtual void RemoveLoopbackSink(LoopbackSink* sink) = 0;
+ virtual const base::UnguessableToken& GetGroupID() = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(LoopbackSource);
+ };
+
using DeleterCallback = base::OnceCallback<void(AudioStreamBroker*)>;
AudioStreamBroker(int render_process_id, int render_frame_id);
@@ -47,6 +70,13 @@ class CONTENT_EXPORT AudioStreamBroker {
virtual void CreateStream(audio::mojom::StreamFactory* factory) = 0;
+ // Thread-safe utility that notifies the process host identified by
+ // |render_process_id| of a started stream to ensure that the renderer is not
+ // backgrounded. Must be paired with a later call to
+ // NotifyRenderProcessOfStoppedStream()
+ static void NotifyProcessHostOfStartedStream(int render_process_id);
+ static void NotifyProcessHostOfStoppedStream(int render_process_id);
+
int render_process_id() const { return render_process_id_; }
int render_frame_id() const { return render_frame_id_; }
@@ -58,41 +88,10 @@ class CONTENT_EXPORT AudioStreamBroker {
DISALLOW_COPY_AND_ASSIGN(AudioStreamBroker);
};
-// Used for dependency injection into ForwardingAudioStreamFactory.
+// Used for dependency injection into ForwardingAudioStreamFactory. Used on the
+// IO thread.
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();
@@ -104,6 +103,7 @@ class CONTENT_EXPORT AudioStreamBrokerFactory {
const std::string& device_id,
const media::AudioParameters& params,
uint32_t shared_memory_count,
+ media::UserInputMonitorBase* user_input_monitor,
bool enable_agc,
audio::mojom::AudioProcessingConfigPtr processing_config,
AudioStreamBroker::DeleterCallback deleter,
@@ -113,7 +113,7 @@ class CONTENT_EXPORT AudioStreamBrokerFactory {
virtual std::unique_ptr<AudioStreamBroker> CreateAudioLoopbackStreamBroker(
int render_process_id,
int render_frame_id,
- std::unique_ptr<LoopbackSource> source,
+ AudioStreamBroker::LoopbackSource* source,
const media::AudioParameters& params,
uint32_t shared_memory_count,
bool mute_source,
@@ -132,8 +132,6 @@ class CONTENT_EXPORT AudioStreamBrokerFactory {
AudioStreamBroker::DeleterCallback deleter,
media::mojom::AudioOutputStreamProviderClientPtr client) = 0;
- // TODO(https://crbug.com/830493): Other kinds of streams.
-
private:
DISALLOW_COPY_AND_ASSIGN(AudioStreamBrokerFactory);
};
diff --git a/chromium/content/browser/media/audio_stream_monitor.cc b/chromium/content/browser/media/audio_stream_monitor.cc
index 17b5cb761c6..35d95f3883d 100644
--- a/chromium/content/browser/media/audio_stream_monitor.cc
+++ b/chromium/content/browser/media/audio_stream_monitor.cc
@@ -7,8 +7,10 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/stl_util.h"
+#include "base/task/post_task.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_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/invalidate_type.h"
@@ -82,8 +84,8 @@ void AudioStreamMonitor::RenderProcessGone(int render_process_id) {
void AudioStreamMonitor::StartMonitoringStream(int render_process_id,
int render_frame_id,
int stream_id) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(
[](const StreamID& sid) {
if (AudioStreamMonitor* monitor = GetMonitorForRenderFrame(
@@ -98,8 +100,8 @@ void AudioStreamMonitor::StartMonitoringStream(int render_process_id,
void AudioStreamMonitor::StopMonitoringStream(int render_process_id,
int render_frame_id,
int stream_id) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(
[](const StreamID& sid) {
if (AudioStreamMonitor* monitor = GetMonitorForRenderFrame(
@@ -115,8 +117,8 @@ void AudioStreamMonitor::UpdateStreamAudibleState(int render_process_id,
int render_frame_id,
int stream_id,
bool is_audible) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(
[](const StreamID& sid, bool is_audible) {
if (AudioStreamMonitor* monitor = GetMonitorForRenderFrame(
diff --git a/chromium/content/browser/media/capture/audio_mirroring_manager.cc b/chromium/content/browser/media/capture/audio_mirroring_manager.cc
index 32544941366..c630a2b85af 100644
--- a/chromium/content/browser/media/capture/audio_mirroring_manager.cc
+++ b/chromium/content/browser/media/capture/audio_mirroring_manager.cc
@@ -50,7 +50,7 @@ void AudioMirroringManager::RemoveDiverter(Diverter* diverter) {
// Find and remove the entry from the routing table. If the stream is being
// diverted, it is stopped.
- for (StreamRoutes::iterator it = routes_.begin(); it != routes_.end(); ++it) {
+ for (auto it = routes_.begin(); it != routes_.end(); ++it) {
if (it->diverter == diverter) {
// Stop the diverted flow.
RouteDivertedFlow(&(*it), nullptr);
@@ -103,7 +103,7 @@ void AudioMirroringManager::StopMirroring(MirroringDestination* destination) {
// Each stopped stream becomes a candidate to be diverted to another
// destination.
std::set<GlobalFrameRoutingId> redivert_candidates;
- for (StreamRoutes::iterator it = routes_.begin(); it != routes_.end(); ++it) {
+ for (auto it = routes_.begin(); it != routes_.end(); ++it) {
if (it->destination == destination) {
RouteDivertedFlow(&(*it), nullptr);
redivert_candidates.insert(it->source_render_frame);
@@ -202,7 +202,7 @@ void AudioMirroringManager::UpdateRoutesToDivertDestination(
// Start/stop diverting based on |matches|. Any stopped stream becomes a
// candidate to be diverted to another destination.
std::set<GlobalFrameRoutingId> redivert_candidates;
- for (StreamRoutes::iterator it = routes_.begin(); it != routes_.end(); ++it) {
+ for (auto it = routes_.begin(); it != routes_.end(); ++it) {
if (matches.find(it->source_render_frame) != matches.end()) {
// Only change the route if the stream is not already being diverted.
if (!it->destination)
@@ -230,7 +230,7 @@ void AudioMirroringManager::UpdateRoutesToDuplicateDestination(
return; // Query result callback invoked after StopMirroring().
}
- for (StreamRoutes::iterator it = routes_.begin(); it != routes_.end(); ++it) {
+ for (auto it = routes_.begin(); it != routes_.end(); ++it) {
if (matches.find(it->source_render_frame) != matches.end()) {
// The same destination cannot have both a diverted audio flow and a
// duplicated flow from the same source.
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 d128405139c..a2e413773c8 100644
--- a/chromium/content/browser/media/capture/audio_mirroring_manager_unittest.cc
+++ b/chromium/content/browser/media/capture/audio_mirroring_manager_unittest.cc
@@ -12,6 +12,8 @@
#include "base/bind_helpers.h"
#include "base/macros.h"
#include "base/synchronization/waitable_event.h"
+#include "base/task/post_task.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/public/test/test_utils.h"
@@ -78,9 +80,10 @@ class MockMirroringDestination
render_process_id_, render_frame_id_)) != candidates.end()) {
result.insert(GlobalFrameRoutingId(render_process_id_, render_frame_id_));
}
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::BindOnce(std::move(*results_callback),
- std::move(result), is_duplication_));
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(std::move(*results_callback), std::move(result),
+ is_duplication_));
}
media::AudioOutputStream* SimulateAddInput(
@@ -194,7 +197,7 @@ class AudioMirroringManagerTest : public testing::Test {
int CountStreamsDivertedTo(
const std::unique_ptr<MockMirroringDestination>& dest) const {
int count = 0;
- for (StreamRoutes::const_iterator it = mirroring_manager_.routes_.begin();
+ for (auto it = mirroring_manager_.routes_.begin();
it != mirroring_manager_.routes_.end(); ++it) {
if (it->destination == dest.get())
++count;
@@ -205,7 +208,7 @@ class AudioMirroringManagerTest : public testing::Test {
int CountStreamsDuplicatedTo(
const std::unique_ptr<MockMirroringDestination>& dest) const {
int count = 0;
- for (StreamRoutes::const_iterator it = mirroring_manager_.routes_.begin();
+ for (auto it = mirroring_manager_.routes_.begin();
it != mirroring_manager_.routes_.end(); ++it) {
if (it->duplications.find(dest.get()) != it->duplications.end())
++count;
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
index 72b973e16a8..cce6a7d8609 100644
--- a/chromium/content/browser/media/capture/aura_window_video_capture_device.cc
+++ b/chromium/content/browser/media/capture/aura_window_video_capture_device.cc
@@ -11,8 +11,10 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
+#include "base/task/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/media/capture/mouse_cursor_overlay_controller.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/desktop_media_id.h"
#include "media/base/bind_to_current_loop.h"
@@ -43,8 +45,8 @@ class AuraWindowVideoCaptureDevice::WindowTracker
DCHECK(device_task_runner_);
DCHECK(cursor_controller_);
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&WindowTracker::ResolveTarget, AsWeakPtr(), source_id));
}
@@ -144,8 +146,8 @@ AuraWindowVideoCaptureDevice::~AuraWindowVideoCaptureDevice() = default;
#if defined(OS_CHROMEOS)
void AuraWindowVideoCaptureDevice::CreateCapturer(
viz::mojom::FrameSinkVideoCapturerRequest request) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(
[](base::WeakPtr<WindowTracker> tracker_ptr,
viz::mojom::FrameSinkVideoCapturerRequest request) {
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
index 7ba9955087b..a82d34d5cb3 100644
--- 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
@@ -8,11 +8,13 @@
#include "base/macros.h"
#include "base/run_loop.h"
+#include "base/task/post_task.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_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/desktop_media_id.h"
#include "content/public/browser/web_contents.h"
@@ -152,9 +154,9 @@ class AuraWindowVideoCaptureDeviceBrowserTest
// 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());
+ base::PostDelayedTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ run_loop.QuitClosure(),
+ GetMinCapturePeriod());
run_loop.Run();
}
}
@@ -256,9 +258,9 @@ IN_PROC_BROWSER_TEST_F(AuraWindowVideoCaptureDeviceBrowserTest,
// 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));
+ base::PostDelayedTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ run_loop.QuitClosure(),
+ base::TimeDelta::FromSeconds(5));
run_loop.Run();
EXPECT_FALSE(HasCapturedFramesInQueue());
diff --git a/chromium/content/browser/media/capture/desktop_capture_device.cc b/chromium/content/browser/media/capture/desktop_capture_device.cc
index 50510bdefb7..7e9d1927948 100644
--- a/chromium/content/browser/media/capture/desktop_capture_device.cc
+++ b/chromium/content/browser/media/capture/desktop_capture_device.cc
@@ -19,12 +19,14 @@
#include "base/single_thread_task_runner.h"
#include "base/strings/string_number_conversions.h"
#include "base/synchronization/lock.h"
+#include "base/task/post_task.h"
#include "base/threading/thread.h"
#include "base/threading/thread_restrictions.h"
#include "base/time/tick_clock.h"
#include "base/timer/timer.h"
#include "build/build_config.h"
#include "content/browser/media/capture/desktop_capture_device_uma_types.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/desktop_capture.h"
#include "content/public/browser/desktop_media_id.h"
@@ -254,8 +256,8 @@ void DesktopCaptureDevice::Core::AllocateAndStart(
// TODO(https://crbug.com/823869): Fix DesktopCaptureDeviceTest and remove
// this conditional.
if (BrowserThread::IsThreadInitialized(BrowserThread::UI)) {
- BrowserThread::PostTaskAndReplyWithResult(
- BrowserThread::UI, FROM_HERE, base::BindOnce(&GetServiceConnector),
+ base::PostTaskWithTraitsAndReplyWithResult(
+ FROM_HERE, {BrowserThread::UI}, base::BindOnce(&GetServiceConnector),
base::BindOnce(&DesktopCaptureDevice::Core::RequestWakeLock,
weak_factory_.GetWeakPtr()));
}
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 636f20a88bd..b517707f920 100644
--- a/chromium/content/browser/media/capture/desktop_capture_device_unittest.cc
+++ b/chromium/content/browser/media/capture/desktop_capture_device_unittest.cc
@@ -230,18 +230,13 @@ class DesktopCaptureDeviceTest : public testing::Test {
std::unique_ptr<media::MockVideoCaptureDeviceClient>
CreateMockVideoCaptureDeviceClient() {
auto result = std::make_unique<media::MockVideoCaptureDeviceClient>();
- ON_CALL(*result, ReserveOutputBuffer(_, _, _))
- .WillByDefault(
- Invoke([](const gfx::Size&, media::VideoPixelFormat format, int) {
- EXPECT_TRUE(format == media::PIXEL_FORMAT_I420);
- return media::VideoCaptureDevice::Client::Buffer();
- }));
- ON_CALL(*result, ResurrectLastOutputBuffer(_, _, _))
- .WillByDefault(
- Invoke([](const gfx::Size&, media::VideoPixelFormat format, int) {
- EXPECT_TRUE(format == media::PIXEL_FORMAT_I420);
- return media::VideoCaptureDevice::Client::Buffer();
- }));
+ ON_CALL(*result, ReserveOutputBuffer(_, _, _, _))
+ .WillByDefault(Invoke([](const gfx::Size&,
+ media::VideoPixelFormat format, int,
+ media::VideoCaptureDevice::Client::Buffer*) {
+ EXPECT_TRUE(format == media::PIXEL_FORMAT_I420);
+ return media::VideoCaptureDevice::Client::ReserveResult::kSucceeded;
+ }));
return result;
}
diff --git a/chromium/content/browser/media/capture/desktop_streams_registry_impl.cc b/chromium/content/browser/media/capture/desktop_streams_registry_impl.cc
index 347e00ab4d1..5c78c89b19e 100644
--- a/chromium/content/browser/media/capture/desktop_streams_registry_impl.cc
+++ b/chromium/content/browser/media/capture/desktop_streams_registry_impl.cc
@@ -9,7 +9,9 @@
#include "base/macros.h"
#include "base/no_destructor.h"
#include "base/stl_util.h"
+#include "base/task/post_task.h"
#include "base/time/time.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "crypto/random.h"
@@ -64,8 +66,8 @@ std::string DesktopStreamsRegistryImpl::RegisterStream(
stream.extension_name = extension_name;
stream.type = type;
- BrowserThread::PostDelayedTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostDelayedTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&DesktopStreamsRegistryImpl::CleanupStream,
base::Unretained(this), id),
base::TimeDelta::FromSeconds(kApprovedStreamTimeToLiveSeconds));
@@ -82,7 +84,7 @@ DesktopMediaID DesktopStreamsRegistryImpl::RequestMediaForStreamId(
const DesktopStreamRegistryType type) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- StreamsMap::iterator it = approved_streams_.find(id);
+ auto it = approved_streams_.find(id);
// Verify that if there is a request with the specified ID it was created for
// the same origin and the same renderer.
diff --git a/chromium/content/browser/media/capture/fake_video_capture_stack.cc b/chromium/content/browser/media/capture/fake_video_capture_stack.cc
index 11429d03374..288d5564d0e 100644
--- a/chromium/content/browser/media/capture/fake_video_capture_stack.cc
+++ b/chromium/content/browser/media/capture/fake_video_capture_stack.cc
@@ -65,6 +65,8 @@ class FakeVideoCaptureStack::Receiver : public media::VideoFrameReceiver {
mapping.size(), frame_info->timestamp);
CHECK(frame);
frame->metadata()->MergeInternalValuesFrom(frame_info->metadata);
+ if (frame_info->color_space.has_value())
+ frame->set_color_space(frame_info->color_space.value());
// This destruction observer will unmap the shared memory when the
// VideoFrame goes out-of-scope.
frame->AddDestructionObserver(base::BindOnce(
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 cded50f3122..0ff5cc4b692 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
@@ -14,11 +14,13 @@
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/numerics/safe_conversions.h"
+#include "base/task/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "components/viz/host/host_frame_sink_manager.h"
#include "content/browser/compositor/surface_utils.h"
#include "content/browser/media/capture/mouse_cursor_overlay_controller.h"
+#include "content/public/browser/browser_task_traits.h"
#include "media/base/bind_to_current_loop.h"
#include "media/capture/mojom/video_capture_types.mojom.h"
@@ -91,7 +93,7 @@ void FrameSinkVideoCaptureDevice::AllocateAndStartWithReceiver(
base::Unretained(this)));
capturer_->SetFormat(capture_params_.requested_format.pixel_format,
- media::COLOR_SPACE_UNSPECIFIED);
+ gfx::ColorSpace::CreateREC709());
capturer_->SetMinCapturePeriod(
base::TimeDelta::FromMicroseconds(base::saturated_cast<int64_t>(
base::Time::kMicrosecondsPerSecond /
@@ -105,8 +107,8 @@ void FrameSinkVideoCaptureDevice::AllocateAndStartWithReceiver(
capturer_->ChangeTarget(target_);
}
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&MouseCursorOverlayController::Start,
cursor_controller_->GetWeakPtr(),
capturer_->CreateOverlay(kMouseCursorStackingIndex),
@@ -153,9 +155,9 @@ void FrameSinkVideoCaptureDevice::Resume() {
void FrameSinkVideoCaptureDevice::StopAndDeAllocate() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(&MouseCursorOverlayController::Stop,
- cursor_controller_->GetWeakPtr()));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(&MouseCursorOverlayController::Stop,
+ cursor_controller_->GetWeakPtr()));
MaybeStopConsuming();
capturer_.reset();
@@ -278,8 +280,8 @@ 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::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(
[](viz::mojom::FrameSinkVideoCapturerRequest request) {
viz::HostFrameSinkManager* const manager =
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 341c3a04df6..c0aee9d274d 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
@@ -11,6 +11,8 @@
#include "base/containers/flat_map.h"
#include "base/memory/read_only_shared_memory_region.h"
#include "base/memory/shared_memory_mapping.h"
+#include "base/task/post_task.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/public/test/test_utils.h"
#include "media/base/video_frame.h"
@@ -51,7 +53,7 @@ namespace {
// Convenience macro to post a task to run on the device thread.
#define POST_DEVICE_TASK(closure) \
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, closure)
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO}, closure)
// Convenience macro to block the test procedure until all pending tasks have
// run on the device thread.
@@ -86,7 +88,7 @@ class MockFrameSinkVideoCapturer : public viz::mojom::FrameSinkVideoCapturer {
MOCK_METHOD2(SetFormat,
void(media::VideoPixelFormat format,
- media::ColorSpace color_space));
+ const gfx::ColorSpace& color_space));
MOCK_METHOD1(SetMinCapturePeriod, void(base::TimeDelta min_period));
MOCK_METHOD1(SetMinSizeChangePeriod, void(base::TimeDelta));
MOCK_METHOD3(SetResolutionConstraints,
@@ -258,8 +260,8 @@ class FrameSinkVideoCaptureDeviceForTest : public FrameSinkVideoCaptureDevice {
protected:
void CreateCapturer(viz::mojom::FrameSinkVideoCapturerRequest request) final {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(
[](MockFrameSinkVideoCapturer* capturer,
viz::mojom::FrameSinkVideoCapturerRequest request) {
@@ -371,7 +373,8 @@ class FrameSinkVideoCaptureDeviceTest : public testing::Test {
media::mojom::VideoFrameInfo::New(
kMinCapturePeriod * frame_number,
base::Value(base::Value::Type::DICTIONARY), kFormat,
- kResolution, gfx::Rect(kResolution)),
+ kResolution, gfx::Rect(kResolution),
+ gfx::ColorSpace::CreateREC709(), nullptr),
gfx::Rect(kResolution), gfx::Rect(kResolution),
viz::mojom::FrameSinkVideoConsumerFrameCallbacksPtr(
std::move(callbacks_info)));
diff --git a/chromium/content/browser/media/capture/lame_window_capturer_chromeos.cc b/chromium/content/browser/media/capture/lame_window_capturer_chromeos.cc
index 2a9275ecb73..e0e419769ec 100644
--- a/chromium/content/browser/media/capture/lame_window_capturer_chromeos.cc
+++ b/chromium/content/browser/media/capture/lame_window_capturer_chromeos.cc
@@ -48,13 +48,12 @@ LameWindowCapturerChromeOS::~LameWindowCapturerChromeOS() {
}
void LameWindowCapturerChromeOS::SetFormat(media::VideoPixelFormat format,
- media::ColorSpace color_space) {
+ const gfx::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) {
+ if (color_space.IsValid() && color_space != gfx::ColorSpace::CreateREC709()) {
LOG(DFATAL) << "Unsupported color space: Only BT.709 is supported.";
}
}
@@ -263,12 +262,11 @@ void LameWindowCapturerChromeOS::CaptureNextFrame() {
DCHECK(frame);
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);
+ frame->set_color_space(gfx::ColorSpace::CreateREC709());
// 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
diff --git a/chromium/content/browser/media/capture/lame_window_capturer_chromeos.h b/chromium/content/browser/media/capture/lame_window_capturer_chromeos.h
index 6af4c60068e..0ba5f913056 100644
--- a/chromium/content/browser/media/capture/lame_window_capturer_chromeos.h
+++ b/chromium/content/browser/media/capture/lame_window_capturer_chromeos.h
@@ -56,7 +56,7 @@ class LameWindowCapturerChromeOS : public viz::mojom::FrameSinkVideoCapturer,
// viz::mojom::FrameSinkVideoCapturer implementation.
void SetFormat(media::VideoPixelFormat format,
- media::ColorSpace color_space) final;
+ const gfx::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,
diff --git a/chromium/content/browser/media/capture/mouse_cursor_overlay_controller_browsertest.cc b/chromium/content/browser/media/capture/mouse_cursor_overlay_controller_browsertest.cc
index 5a05b17ff0b..324b1c04850 100644
--- a/chromium/content/browser/media/capture/mouse_cursor_overlay_controller_browsertest.cc
+++ b/chromium/content/browser/media/capture/mouse_cursor_overlay_controller_browsertest.cc
@@ -6,6 +6,8 @@
#include "base/macros.h"
#include "base/run_loop.h"
+#include "base/task/post_task.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/content_browser_test.h"
@@ -61,8 +63,9 @@ class MouseCursorOverlayControllerBrowserTest : public ContentBrowserTest {
auto overlay_ptr = std::make_unique<FakeOverlay>();
FakeOverlay* const overlay = overlay_ptr.get();
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- controller_.Start(std::move(overlay_ptr),
- BrowserThread::GetTaskRunnerForThread(BrowserThread::UI));
+ controller_.Start(
+ std::move(overlay_ptr),
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::UI}));
return overlay;
}
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 ffbe9c52a13..ef590730d52 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
@@ -45,12 +45,14 @@ class MockDeviceClient : public media::VideoCaptureDevice::Client {
MOCK_METHOD0(OnStarted, void(void));
// Trampoline methods to workaround GMOCK problems with std::unique_ptr<>.
- Buffer ReserveOutputBuffer(const gfx::Size& dimensions,
- media::VideoPixelFormat format,
- int frame_feedback_id) override {
+ media::VideoCaptureDevice::Client::ReserveResult ReserveOutputBuffer(
+ const gfx::Size& dimensions,
+ media::VideoPixelFormat format,
+ int frame_feedback_id,
+ Buffer* buffer) override {
EXPECT_EQ(media::PIXEL_FORMAT_I420, format);
DoReserveOutputBuffer();
- return Buffer();
+ return media::VideoCaptureDevice::Client::ReserveResult::kSucceeded;
}
void OnIncomingCapturedBuffer(Buffer buffer,
const media::VideoCaptureFormat& frame_format,
@@ -67,13 +69,6 @@ class MockDeviceClient : public media::VideoCaptureDevice::Client {
const media::VideoFrameMetadata& additional_metadata) override {
DoOnIncomingCapturedVideoFrame();
}
- Buffer ResurrectLastOutputBuffer(const gfx::Size& dimensions,
- media::VideoPixelFormat format,
- int frame_feedback_id) override {
- EXPECT_EQ(media::PIXEL_FORMAT_I420, format);
- DoResurrectLastOutputBuffer();
- return Buffer();
- }
};
class ScreenCaptureDeviceAndroidTest : public testing::Test {
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 75d9bee6e9a..0329e1b1a7b 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
@@ -12,9 +12,11 @@
#include "base/bind_helpers.h"
#include "base/logging.h"
#include "base/macros.h"
+#include "base/task/post_task.h"
#include "base/threading/thread_checker.h"
#include "content/browser/media/capture/audio_mirroring_manager.h"
#include "content/browser/media/capture/web_contents_tracker.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/desktop_media_id.h"
#include "content/public/browser/render_frame_host.h"
@@ -184,8 +186,8 @@ bool WebContentsAudioInputStream::Impl::Open() {
void WebContentsAudioInputStream::Impl::IncrementCapturerCount() {
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&Impl::IncrementCapturerCount, this));
return;
}
@@ -217,8 +219,8 @@ void WebContentsAudioInputStream::Impl::Start(AudioInputCallback* callback) {
// WebContents audio muting is implemented as audio capture to nowhere.
// Unmuting will stop that audio capture, allowing AudioMirroringManager to
// divert audio capture to here.
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(&Impl::UnmuteWebContentsAudio, this));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(&Impl::UnmuteWebContentsAudio, this));
}
void WebContentsAudioInputStream::Impl::Stop() {
@@ -253,8 +255,8 @@ void WebContentsAudioInputStream::Impl::Close() {
void WebContentsAudioInputStream::Impl::DecrementCapturerCount() {
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&Impl::DecrementCapturerCount, this));
return;
}
@@ -273,19 +275,20 @@ void WebContentsAudioInputStream::Impl::ReportError() {
void WebContentsAudioInputStream::Impl::StartMirroring() {
DCHECK(thread_checker_.CalledOnValidThread());
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::BindOnce(&AudioMirroringManager::StartMirroring,
- base::Unretained(mirroring_manager_),
- base::RetainedRef(this)));
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(&AudioMirroringManager::StartMirroring,
+ base::Unretained(mirroring_manager_),
+ base::RetainedRef(this)));
}
void WebContentsAudioInputStream::Impl::StopMirroring() {
DCHECK(thread_checker_.CalledOnValidThread());
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::BindOnce(&AudioMirroringManager::StopMirroring,
- base::Unretained(mirroring_manager_),
- base::RetainedRef(this)));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(&AudioMirroringManager::StopMirroring,
+ base::Unretained(mirroring_manager_),
+ base::RetainedRef(this)));
}
void WebContentsAudioInputStream::Impl::UnmuteWebContentsAudio() {
@@ -299,8 +302,8 @@ void WebContentsAudioInputStream::Impl::UnmuteWebContentsAudio() {
void WebContentsAudioInputStream::Impl::QueryForMatches(
const std::set<GlobalFrameRoutingId>& candidates,
MatchesCallback results_callback) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&Impl::QueryForMatchesOnUIThread, this, candidates,
media::BindToCurrentLoop(std::move(results_callback))));
}
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 f27817f8604..8846494e5f4 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
@@ -16,10 +16,12 @@
#include "base/macros.h"
#include "base/single_thread_task_runner.h"
#include "base/synchronization/waitable_event.h"
+#include "base/task/post_task.h"
#include "base/threading/thread.h"
#include "base/time/time.h"
#include "content/browser/media/capture/audio_mirroring_manager.h"
#include "content/browser/media/capture/web_contents_tracker.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "media/audio/simple_sources.h"
@@ -281,8 +283,8 @@ class WebContentsAudioInputStreamTest : public testing::TestWithParam<bool> {
// causes our mock to set |destination_|. Block until that has happened.
base::WaitableEvent done(base::WaitableEvent::ResetPolicy::AUTOMATIC,
base::WaitableEvent::InitialState::NOT_SIGNALED);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&base::WaitableEvent::Signal, base::Unretained(&done)));
done.Wait();
ASSERT_TRUE(destination_);
diff --git a/chromium/content/browser/media/capture/web_contents_audio_muter.cc b/chromium/content/browser/media/capture/web_contents_audio_muter.cc
index c10f52250b5..77ce90160d3 100644
--- a/chromium/content/browser/media/capture/web_contents_audio_muter.cc
+++ b/chromium/content/browser/media/capture/web_contents_audio_muter.cc
@@ -10,8 +10,10 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/macros.h"
+#include "base/task/post_task.h"
#include "base/time/time.h"
#include "content/browser/media/capture/audio_mirroring_manager.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
@@ -84,8 +86,8 @@ class WebContentsAudioMuter::MuteDestination
void QueryForMatches(const std::set<GlobalFrameRoutingId>& candidates,
MatchesCallback results_callback) override {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&MuteDestination::QueryForMatchesOnUIThread, this,
candidates,
media::BindToCurrentLoop(std::move(results_callback))));
@@ -139,8 +141,8 @@ void WebContentsAudioMuter::StartMuting() {
if (is_muting_)
return;
is_muting_ = true;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&AudioMirroringManager::StartMirroring,
base::Unretained(AudioMirroringManager::GetInstance()),
base::RetainedRef(destination_)));
@@ -151,8 +153,8 @@ void WebContentsAudioMuter::StopMuting() {
if (!is_muting_)
return;
is_muting_ = false;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&AudioMirroringManager::StopMirroring,
base::Unretained(AudioMirroringManager::GetInstance()),
base::RetainedRef(destination_)));
diff --git a/chromium/content/browser/media/capture/web_contents_tracker.cc b/chromium/content/browser/media/capture/web_contents_tracker.cc
index 64abe70e3bc..de71c4b59ac 100644
--- a/chromium/content/browser/media/capture/web_contents_tracker.cc
+++ b/chromium/content/browser/media/capture/web_contents_tracker.cc
@@ -4,7 +4,9 @@
#include "content/browser/media/capture/web_contents_tracker.h"
+#include "base/task/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_widget_host_view.h"
@@ -32,8 +34,8 @@ void WebContentsTracker::Start(int render_process_id, int main_render_frame_id,
if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
StartObservingWebContents(render_process_id, main_render_frame_id);
} else {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&WebContentsTracker::StartObservingWebContents, this,
render_process_id, main_render_frame_id));
}
@@ -48,9 +50,10 @@ void WebContentsTracker::Stop() {
if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
WebContentsObserver::Observe(nullptr);
} else {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(&WebContentsTracker::Observe, this,
- static_cast<WebContents*>(nullptr)));
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(&WebContentsTracker::Observe, this,
+ static_cast<WebContents*>(nullptr)));
}
}
diff --git a/chromium/content/browser/media/capture/web_contents_video_capture_device.cc b/chromium/content/browser/media/capture/web_contents_video_capture_device.cc
index ff8651a5084..9eab080377b 100644
--- a/chromium/content/browser/media/capture/web_contents_video_capture_device.cc
+++ b/chromium/content/browser/media/capture/web_contents_video_capture_device.cc
@@ -11,9 +11,11 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
+#include "base/task/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/media/capture/mouse_cursor_overlay_controller.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_media_capture_id.h"
@@ -43,8 +45,8 @@ class WebContentsVideoCaptureDevice::FrameTracker
DCHECK(device_task_runner_);
DCHECK(cursor_controller_);
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(
[](base::WeakPtr<FrameTracker> self, int process_id, int frame_id) {
if (self) {
@@ -234,16 +236,16 @@ WebContentsVideoCaptureDevice::Create(const std::string& device_id) {
}
void WebContentsVideoCaptureDevice::WillStart() {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&FrameTracker::WillStartCapturingWebContents,
tracker_->AsWeakPtr(),
capture_params().SuggestConstraints().max_frame_size));
}
void WebContentsVideoCaptureDevice::DidStop() {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&FrameTracker::DidStopCapturingWebContents,
tracker_->AsWeakPtr()));
}
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 ec35ff5a5b3..850458675e5 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
@@ -8,11 +8,13 @@
#include "base/macros.h"
#include "base/run_loop.h"
+#include "base/task/post_task.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_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
@@ -133,9 +135,9 @@ class WebContentsVideoCaptureDeviceBrowserTest
// 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());
+ base::PostDelayedTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ run_loop.QuitClosure(),
+ GetMinCapturePeriod());
run_loop.Run();
}
}
@@ -243,9 +245,9 @@ IN_PROC_BROWSER_TEST_F(WebContentsVideoCaptureDeviceBrowserTest,
// 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));
+ base::PostDelayedTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ run_loop.QuitClosure(),
+ base::TimeDelta::FromSeconds(5));
run_loop.Run();
EXPECT_FALSE(HasCapturedFramesInQueue());
diff --git a/chromium/content/browser/media/cdm_storage_impl.cc b/chromium/content/browser/media/cdm_storage_impl.cc
index dd19f2bde50..fa67789e09c 100644
--- a/chromium/content/browser/media/cdm_storage_impl.cc
+++ b/chromium/content/browser/media/cdm_storage_impl.cc
@@ -36,7 +36,7 @@ void CdmStorageImpl::Create(RenderFrameHost* render_frame_host,
const std::string& cdm_file_system_id,
media::mojom::CdmStorageRequest request) {
DVLOG(3) << __func__;
- DCHECK(!render_frame_host->GetLastCommittedOrigin().unique())
+ DCHECK(!render_frame_host->GetLastCommittedOrigin().opaque())
<< "Invalid origin specified for CdmStorageImpl::Create";
// Take a reference to the FileSystemContext.
diff --git a/chromium/content/browser/media/encrypted_media_browsertest.cc b/chromium/content/browser/media/encrypted_media_browsertest.cc
index db7a34efd8d..86957f7b80d 100644
--- a/chromium/content/browser/media/encrypted_media_browsertest.cc
+++ b/chromium/content/browser/media/encrypted_media_browsertest.cc
@@ -182,9 +182,7 @@ class EncryptedMediaTest
}
void SetUpCommandLine(base::CommandLine* command_line) override {
- command_line->AppendSwitchASCII(
- switches::kAutoplayPolicy,
- switches::autoplay::kNoUserGestureRequiredPolicy);
+ MediaBrowserTest::SetUpCommandLine(command_line);
#if defined(SUPPORTS_EXTERNAL_CLEAR_KEY_IN_CONTENT_SHELL)
scoped_feature_list_.InitWithFeatures({media::kExternalClearKeyForTesting},
{});
@@ -274,6 +272,15 @@ IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoClearAudio_WebM_Opus) {
TestSimplePlayback("bear-320x240-opus-av_enc-v.webm", kWebMOpusAudioVp9Video);
}
+// TODO(crbug.com/707127): Decide when it's supported on Android. Also support
+// VP9 Profile2 query and update the mime type.
+#if !defined(OS_ANDROID)
+IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VP9Profile2Video_WebM) {
+ TestSimplePlayback("bear-320x240-v-vp9_profile2_subsample_cenc-v.webm",
+ kWebMVp9VideoOnly);
+}
+#endif
+
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_AudioOnly_MP4_FLAC) {
RunMultipleFileTest(std::string(), std::string(), "bear-flac-cenc.mp4",
kMp4FlacAudioOnly, media::kEnded);
@@ -288,6 +295,20 @@ IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoOnly_MP4_VP9) {
TestSimplePlayback("bear-320x240-v_frag-vp9-cenc.mp4", kMp4Vp9VideoOnly);
}
+// TODO(crbug.com/707127): Decide when it's supported on Android. Also support
+// VP9 Profile2 query and update the mime type.
+#if !defined(OS_ANDROID)
+IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoOnly_MP4_VP9Profile2) {
+ // 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-vp9_profile2_subsample_cenc-v.mp4",
+ kMp4Vp9VideoOnly);
+}
+#endif
+
// Strictly speaking this is not an "encrypted" media test. Keep it here for
// completeness.
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, ConfigChangeVideo_ClearToClear) {
@@ -307,13 +328,16 @@ IN_PROC_BROWSER_TEST_P(EncryptedMediaTest,
TestConfigChange(ConfigChangeType::ENCRYPTED_TO_ENCRYPTED);
}
-// https://crbug.com/788748 https://crbug.com/794080
-#if (defined(OS_ANDROID) || defined(OS_LINUX)) && defined(ADDRESS_SANITIZER)
-#define MAYBE_FrameSizeChangeVideo DISABLED_FrameSizeChangeVideo
-#else
-#define MAYBE_FrameSizeChangeVideo FrameSizeChangeVideo
+IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, FrameSizeChangeVideo) {
+#if defined(OS_ANDROID)
+ // https://crbug.com/778245
+ if (base::android::BuildInfo::GetInstance()->sdk_int() <=
+ base::android::SDK_VERSION_KITKAT) {
+ DVLOG(0) << "Skipping test - FrameSizeChange is flaky on KitKat devices.";
+ return;
+ }
#endif
-IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, MAYBE_FrameSizeChangeVideo) {
+
TestFrameSizeChange();
}
diff --git a/chromium/content/browser/media/forwarding_audio_stream_factory.cc b/chromium/content/browser/media/forwarding_audio_stream_factory.cc
index f9181735959..ff12ffd69af 100644
--- a/chromium/content/browser/media/forwarding_audio_stream_factory.cc
+++ b/chromium/content/browser/media/forwarding_audio_stream_factory.cc
@@ -6,112 +6,82 @@
#include <utility>
+#include "base/bind.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/stl_util.h"
+#include "base/task/post_task.h"
#include "base/trace_event/trace_event.h"
#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/browser/browser_task_traits.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 "media/audio/audio_device_description.h"
-#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "media/base/audio_parameters.h"
+#include "media/base/user_input_monitor.h"
#include "services/audio/public/mojom/constants.mojom.h"
#include "services/service_manager/public/cpp/connector.h"
+#include "ui/gfx/geometry/size.h"
namespace content {
-namespace {
-
-// A mojom::RendererAudioInputStreamFactoryClient that holds a
-// AudioLoopbackStreamCreator::StreamCreatedCallback. The callback runs when the
-// requested audio stream is created.
-class StreamCreatedCallbackAdapter final
- : public mojom::RendererAudioInputStreamFactoryClient {
- public:
- explicit StreamCreatedCallbackAdapter(
- const AudioLoopbackStreamCreator::StreamCreatedCallback& callback)
- : callback_(callback) {
- DCHECK(callback_);
- }
-
- ~StreamCreatedCallbackAdapter() override {}
-
- // mojom::RendererAudioInputStreamFactoryClient implementation.
- void StreamCreated(
- media::mojom::AudioInputStreamPtr stream,
- media::mojom::AudioInputStreamClientRequest client_request,
- media::mojom::ReadOnlyAudioDataPipePtr data_pipe,
- bool initially_muted,
- const base::Optional<base::UnguessableToken>& stream_id) override {
- DCHECK(!initially_muted); // Loopback streams shouldn't be started muted.
- callback_.Run(std::move(stream), std::move(client_request),
- std::move(data_pipe));
- }
-
- private:
- const AudioLoopbackStreamCreator::StreamCreatedCallback callback_;
-
- DISALLOW_COPY_AND_ASSIGN(StreamCreatedCallbackAdapter);
-};
-
-} // namespace
-
-ForwardingAudioStreamFactory::ForwardingAudioStreamFactory(
- WebContents* web_contents,
+ForwardingAudioStreamFactory::Core::Core(
+ base::WeakPtr<ForwardingAudioStreamFactory> owner,
+ media::UserInputMonitorBase* user_input_monitor,
std::unique_ptr<service_manager::Connector> connector,
std::unique_ptr<AudioStreamBrokerFactory> broker_factory)
- : WebContentsObserver(web_contents),
- connector_(std::move(connector)),
+ : user_input_monitor_(user_input_monitor),
+ owner_(std::move(owner)),
broker_factory_(std::move(broker_factory)),
- group_id_(base::UnguessableToken::Create()) {
+ group_id_(base::UnguessableToken::Create()),
+ connector_(std::move(connector)),
+ weak_ptr_factory_(this) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(owner_);
DCHECK(broker_factory_);
+ DCHECK(connector_);
}
-ForwardingAudioStreamFactory::~ForwardingAudioStreamFactory() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ForwardingAudioStreamFactory::Core::~Core() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ for (AudioStreamBroker::LoopbackSink* sink : loopback_sinks_)
+ sink->OnSourceGone();
}
-// 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();
+base::WeakPtr<ForwardingAudioStreamFactory::Core>
+ForwardingAudioStreamFactory::Core::AsWeakPtr() {
+ return weak_ptr_factory_.GetWeakPtr();
}
-void ForwardingAudioStreamFactory::CreateInputStream(
- RenderFrameHost* frame,
+void ForwardingAudioStreamFactory::Core::CreateInputStream(
+ 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,
audio::mojom::AudioProcessingConfigPtr processing_config,
mojom::RendererAudioInputStreamFactoryClientPtr renderer_factory_client) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
- const int process_id = frame ? frame->GetProcess()->GetID() : -1;
- const int frame_id = frame ? frame->GetRoutingID() : -1;
+ // |this| owns |inputs_|, so Unretained is safe.
inputs_
.insert(broker_factory_->CreateAudioInputStreamBroker(
- process_id, frame_id, device_id, params, shared_memory_count,
- enable_agc, std::move(processing_config),
- base::BindOnce(&ForwardingAudioStreamFactory::RemoveInput,
+ render_process_id, render_frame_id, device_id, params,
+ shared_memory_count, user_input_monitor_, enable_agc,
+ std::move(processing_config),
+ base::BindOnce(&ForwardingAudioStreamFactory::Core::RemoveInput,
base::Unretained(this)),
std::move(renderer_factory_client)))
.first->get()
->CreateStream(GetFactory());
}
-void ForwardingAudioStreamFactory::AssociateInputAndOutputForAec(
+void ForwardingAudioStreamFactory::Core::AssociateInputAndOutputForAec(
const base::UnguessableToken& input_stream_id,
const std::string& raw_output_device_id) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
// 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()) {
@@ -120,95 +90,58 @@ void ForwardingAudioStreamFactory::AssociateInputAndOutputForAec(
}
}
-void ForwardingAudioStreamFactory::CreateOutputStream(
- RenderFrameHost* frame,
+void ForwardingAudioStreamFactory::Core::CreateOutputStream(
+ int render_process_id,
+ int render_frame_id,
const std::string& device_id,
const media::AudioParameters& params,
const base::Optional<base::UnguessableToken>& processing_id,
media::mojom::AudioOutputStreamProviderClientPtr client) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
- const int process_id = frame->GetProcess()->GetID();
- const int frame_id = frame->GetRoutingID();
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ // |this| owns |outputs_|, so Unretained is safe.
outputs_
.insert(broker_factory_->CreateAudioOutputStreamBroker(
- process_id, frame_id, ++stream_id_counter_, device_id, params,
- group_id_, processing_id,
- base::BindOnce(&ForwardingAudioStreamFactory::RemoveOutput,
+ render_process_id, render_frame_id, ++stream_id_counter_, device_id,
+ params, group_id_, processing_id,
+ base::BindOnce(&ForwardingAudioStreamFactory::Core::RemoveOutput,
base::Unretained(this)),
std::move(client)))
.first->get()
->CreateStream(GetFactory());
}
-void ForwardingAudioStreamFactory::CreateLoopbackStream(
- RenderFrameHost* frame,
- RenderFrameHost* frame_of_source_web_contents,
+void ForwardingAudioStreamFactory::Core::CreateLoopbackStream(
+ int render_process_id,
+ int render_frame_id,
+ AudioStreamBroker::LoopbackSource* loopback_source,
const media::AudioParameters& params,
uint32_t shared_memory_count,
bool mute_source,
mojom::RendererAudioInputStreamFactoryClientPtr renderer_factory_client) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- DCHECK(frame_of_source_web_contents);
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(loopback_source);
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 ? frame->GetProcess()->GetID() : -1;
- const int frame_id = frame ? frame->GetRoutingID() : -1;
+ // |this| owns |inputs_|, so Unretained is safe.
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,
+ render_process_id, render_frame_id, loopback_source, params,
+ shared_memory_count, mute_source,
+ base::BindOnce(&ForwardingAudioStreamFactory::Core::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());
+ loopback_source->GetGroupID().GetLowForSerialization());
}
-void ForwardingAudioStreamFactory::CreateInProcessLoopbackStream(
- RenderFrameHost* frame_of_source_web_contents,
- const media::AudioParameters& params,
- uint32_t shared_memory_count,
- const AudioLoopbackStreamCreator::StreamCreatedCallback& callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- mojom::RendererAudioInputStreamFactoryClientPtr client;
- mojo::MakeStrongBinding(
- std::make_unique<StreamCreatedCallbackAdapter>(callback),
- mojo::MakeRequest(&client));
- if (frame_of_source_web_contents) {
- CreateLoopbackStream(nullptr, frame_of_source_web_contents, params,
- shared_memory_count, true /* mute_source */,
- std::move(client));
- } else {
- // A null |frame_of_source_web_contents| requests system-wide loopback.
- CreateInputStream(nullptr,
- media::AudioDeviceDescription::kLoopbackWithMuteDeviceId,
- params, shared_memory_count, false /* enable_agc */,
- nullptr /* processing_config */, std::move(client));
- }
-}
-
-void ForwardingAudioStreamFactory::SetMuted(bool muted) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- DCHECK_NE(muted, IsMuted());
+void ForwardingAudioStreamFactory::Core::SetMuted(bool muted) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK_NE(muted, !!muter_);
TRACE_EVENT_INSTANT2("audio", "SetMuted", TRACE_EVENT_SCOPE_THREAD, "group",
group_id_.GetLowForSerialization(), "muted", muted);
@@ -222,35 +155,133 @@ void ForwardingAudioStreamFactory::SetMuted(bool muted) {
muter_->Connect(remote_factory_.get());
}
-bool ForwardingAudioStreamFactory::IsMuted() const {
+void ForwardingAudioStreamFactory::Core::AddLoopbackSink(
+ AudioStreamBroker::LoopbackSink* sink) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ loopback_sinks_.insert(sink);
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(&ForwardingAudioStreamFactory::LoopbackStreamStarted,
+ owner_));
+}
+
+void ForwardingAudioStreamFactory::Core::RemoveLoopbackSink(
+ AudioStreamBroker::LoopbackSink* sink) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ loopback_sinks_.erase(sink);
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(&ForwardingAudioStreamFactory::LoopbackStreamStopped,
+ owner_));
+}
+
+const base::UnguessableToken& ForwardingAudioStreamFactory::Core::GetGroupID() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ return group_id();
+}
+
+// static
+ForwardingAudioStreamFactory* ForwardingAudioStreamFactory::ForFrame(
+ RenderFrameHost* frame) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- return !!muter_;
+
+ auto* contents =
+ static_cast<WebContentsImpl*>(WebContents::FromRenderFrameHost(frame));
+ if (!contents)
+ return nullptr;
+
+ return contents->GetAudioStreamFactory();
}
-void ForwardingAudioStreamFactory::FrameDeleted(
- RenderFrameHost* render_frame_host) {
+// static
+ForwardingAudioStreamFactory::Core* ForwardingAudioStreamFactory::CoreForFrame(
+ RenderFrameHost* frame) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ ForwardingAudioStreamFactory* forwarding_factory =
+ ForwardingAudioStreamFactory::ForFrame(frame);
+ return forwarding_factory ? forwarding_factory->core() : nullptr;
+}
+
+ForwardingAudioStreamFactory::ForwardingAudioStreamFactory(
+ WebContents* web_contents,
+ media::UserInputMonitorBase* user_input_monitor,
+ std::unique_ptr<service_manager::Connector> connector,
+ std::unique_ptr<AudioStreamBrokerFactory> broker_factory)
+ : WebContentsObserver(web_contents), core_(), weak_ptr_factory_(this) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- CleanupStreamsBelongingTo(render_frame_host);
+ core_ =
+ std::make_unique<Core>(weak_ptr_factory_.GetWeakPtr(), user_input_monitor,
+ std::move(connector), std::move(broker_factory));
}
-void ForwardingAudioStreamFactory::CleanupStreamsBelongingTo(
+ForwardingAudioStreamFactory::~ForwardingAudioStreamFactory() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ // Ensure |core_| is deleted on the right thread. DeleteOnIOThread isn't used
+ // as it doesn't post in case it is already executed on the right thread. That
+ // causes issues in unit tests where the UI thread and the IO thread are the
+ // same.
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
+ base::BindOnce([](std::unique_ptr<Core>) {}, std::move(core_)));
+}
+
+void ForwardingAudioStreamFactory::LoopbackStreamStarted() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ web_contents()->IncrementCapturerCount(gfx::Size());
+}
+
+void ForwardingAudioStreamFactory::LoopbackStreamStopped() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ web_contents()->DecrementCapturerCount();
+}
+
+void ForwardingAudioStreamFactory::SetMuted(bool muted) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ if (is_muted_ != muted) {
+ is_muted_ = muted;
+
+ // Unretained is safe since the destruction of |core_| will be posted to the
+ // IO thread later.
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(&Core::SetMuted, base::Unretained(core_.get()), muted));
+ }
+}
+
+bool ForwardingAudioStreamFactory::IsMuted() const {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ return is_muted_;
+}
+
+void ForwardingAudioStreamFactory::FrameDeleted(
RenderFrameHost* render_frame_host) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(render_frame_host);
+
+ // Unretained is safe since the destruction of |core_| will be posted to the
+ // IO thread later.
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(&Core::CleanupStreamsBelongingTo,
+ base::Unretained(core_.get()),
+ render_frame_host->GetProcess()->GetID(),
+ render_frame_host->GetRoutingID()));
+}
- const int process_id =
- render_frame_host ? render_frame_host->GetProcess()->GetID() : -1;
- const int frame_id =
- render_frame_host ? render_frame_host->GetRoutingID() : -1;
+void ForwardingAudioStreamFactory::Core::CleanupStreamsBelongingTo(
+ int render_process_id,
+ int render_frame_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
TRACE_EVENT_BEGIN2("audio", "CleanupStreamsBelongingTo", "group",
group_id_.GetLowForSerialization(), "process id",
- process_id);
+ render_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;
+ [render_process_id, render_frame_id](
+ const std::unique_ptr<AudioStreamBroker>& broker) -> bool {
+ return broker->render_process_id() == render_process_id &&
+ broker->render_frame_id() == render_frame_id;
};
base::EraseIf(outputs_, match_rfh);
@@ -258,27 +289,30 @@ void ForwardingAudioStreamFactory::CleanupStreamsBelongingTo(
ResetRemoteFactoryPtrIfIdle();
- TRACE_EVENT_END1("audio", "CleanupStreamsBelongingTo", "frame_id", frame_id);
+ TRACE_EVENT_END1("audio", "CleanupStreamsBelongingTo", "frame_id",
+ render_frame_id);
}
-void ForwardingAudioStreamFactory::RemoveInput(AudioStreamBroker* broker) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
+void ForwardingAudioStreamFactory::Core::RemoveInput(
+ AudioStreamBroker* broker) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
size_t removed = inputs_.erase(broker);
DCHECK_EQ(1u, removed);
ResetRemoteFactoryPtrIfIdle();
}
-void ForwardingAudioStreamFactory::RemoveOutput(AudioStreamBroker* broker) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
+void ForwardingAudioStreamFactory::Core::RemoveOutput(
+ AudioStreamBroker* broker) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
size_t removed = outputs_.erase(broker);
DCHECK_EQ(1u, removed);
ResetRemoteFactoryPtrIfIdle();
}
-audio::mojom::StreamFactory* ForwardingAudioStreamFactory::GetFactory() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
+audio::mojom::StreamFactory* ForwardingAudioStreamFactory::Core::GetFactory() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (!remote_factory_) {
TRACE_EVENT_INSTANT1(
"audio", "ForwardingAudioStreamFactory: Binding new factory",
@@ -286,9 +320,9 @@ audio::mojom::StreamFactory* ForwardingAudioStreamFactory::GetFactory() {
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)));
+ remote_factory_.set_connection_error_handler(base::BindOnce(
+ &ForwardingAudioStreamFactory::Core::ResetRemoteFactoryPtr,
+ base::Unretained(this)));
// Restore the muting session on reconnect.
if (muter_)
@@ -298,14 +332,14 @@ audio::mojom::StreamFactory* ForwardingAudioStreamFactory::GetFactory() {
return remote_factory_.get();
}
-void ForwardingAudioStreamFactory::ResetRemoteFactoryPtrIfIdle() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
+void ForwardingAudioStreamFactory::Core::ResetRemoteFactoryPtrIfIdle() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (inputs_.empty() && outputs_.empty())
ResetRemoteFactoryPtr();
}
-void ForwardingAudioStreamFactory::ResetRemoteFactoryPtr() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
+void ForwardingAudioStreamFactory::Core::ResetRemoteFactoryPtr() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (remote_factory_) {
TRACE_EVENT_INSTANT1(
"audio", "ForwardingAudioStreamFactory: Resetting factory",
diff --git a/chromium/content/browser/media/forwarding_audio_stream_factory.h b/chromium/content/browser/media/forwarding_audio_stream_factory.h
index 6c1bfbc8dd9..8a995de058f 100644
--- a/chromium/content/browser/media/forwarding_audio_stream_factory.h
+++ b/chromium/content/browser/media/forwarding_audio_stream_factory.h
@@ -5,20 +5,23 @@
#ifndef CONTENT_BROWSER_MEDIA_FORWARDING_AUDIO_STREAM_FACTORY_H_
#define CONTENT_BROWSER_MEDIA_FORWARDING_AUDIO_STREAM_FACTORY_H_
+#include <cstdint>
#include <memory>
#include <string>
#include "base/containers/flat_set.h"
#include "base/containers/unique_ptr_adapters.h"
#include "base/macros.h"
+#include "base/memory/weak_ptr.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/audio_loopback_stream_creator.h"
#include "content/public/browser/web_contents_observer.h"
+#include "media/mojo/interfaces/audio_output_stream.mojom.h"
+#include "services/audio/public/mojom/audio_processing.mojom.h"
#include "services/audio/public/mojom/stream_factory.mojom.h"
namespace service_manager {
@@ -27,11 +30,11 @@ class Connector;
namespace media {
class AudioParameters;
+class UserInputMonitorBase;
}
namespace content {
-class AudioStreamBroker;
class RenderFrameHost;
class WebContents;
@@ -40,60 +43,166 @@ class WebContents;
class CONTENT_EXPORT ForwardingAudioStreamFactory final
: public WebContentsObserver {
public:
+ // Note: all methods of Core may only be called on the IO thread except for
+ // the constructor and group_id(). The destruction of Core is posted to the
+ // IO thread when the owning ForwardingAudioStreamFactory is destructed. For
+ // using |core()|, two rules emerges.
+ // 1) If a task is posted from the UI thread to the IO thread while the
+ // owning ForwardingAudioStreamFactory is alive, |core()| may be posted
+ // Unretained.
+ // 2) If |core()| is held until the owning ForwardingAudioStreamFactory could
+ // potentially be destructed, or if a task is posted to the IO thread with
+ // the intention of accessing |core| after that task returns, using a raw
+ // pointer is not safe. In those cases, take a weak pointer using
+ // AsWeakPtr() and check it for validity before every use. The weak
+ // pointer may only be checked/dereferenced on the IO thread.
+ class CONTENT_EXPORT Core final : public AudioStreamBroker::LoopbackSource {
+ public:
+ Core(base::WeakPtr<ForwardingAudioStreamFactory> owner,
+ media::UserInputMonitorBase* user_input_monitor,
+ std::unique_ptr<service_manager::Connector> connector,
+ std::unique_ptr<AudioStreamBrokerFactory> factory);
+ ~Core() final;
+
+ const base::UnguessableToken& group_id() const { return group_id_; }
+
+ // E.g. to override binder.
+ service_manager::Connector* get_connector_for_testing() {
+ return connector_.get();
+ }
+
+ base::WeakPtr<ForwardingAudioStreamFactory::Core> AsWeakPtr();
+
+ // TODO(https://crbug.com/787806): Automatically restore streams on audio
+ // service restart.
+ void CreateInputStream(
+ 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,
+ audio::mojom::AudioProcessingConfigPtr processing_config,
+ mojom::RendererAudioInputStreamFactoryClientPtr
+ renderer_factory_client);
+
+ void AssociateInputAndOutputForAec(
+ const base::UnguessableToken& input_stream_id,
+ const std::string& raw_output_device_id);
+
+ void CreateOutputStream(
+ int render_process_id,
+ int render_frame_id,
+ const std::string& device_id,
+ const media::AudioParameters& params,
+ const base::Optional<base::UnguessableToken>& processing_id,
+ media::mojom::AudioOutputStreamProviderClientPtr client);
+
+ void CreateLoopbackStream(
+ int render_process_id,
+ int render_frame_id,
+ AudioStreamBroker::LoopbackSource* loopback_source,
+ 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);
+
+ // AudioStreamLoopback::Source implementation
+ void AddLoopbackSink(AudioStreamBroker::LoopbackSink* sink) final;
+ void RemoveLoopbackSink(AudioStreamBroker::LoopbackSink* sink) final;
+ const base::UnguessableToken& GetGroupID() final; // Actually const.
+
+ private:
+ // For CleanupStreamsBelongingTo.
+ friend class ForwardingAudioStreamFactory;
+
+ using StreamBrokerSet = base::flat_set<std::unique_ptr<AudioStreamBroker>,
+ base::UniquePtrComparator>;
+
+ void CleanupStreamsBelongingTo(int render_process_id, int render_frame_id);
+
+ void RemoveInput(AudioStreamBroker* handle);
+ void RemoveOutput(AudioStreamBroker* handle);
+
+ audio::mojom::StreamFactory* GetFactory();
+ void ResetRemoteFactoryPtrIfIdle();
+ void ResetRemoteFactoryPtr();
+
+ media::UserInputMonitorBase* const user_input_monitor_;
+
+ // Used for posting tasks the UI thread to communicate when a loopback
+ // stream is started/stopped. Weak since |this| on the IO thread outlives
+ // |owner| on the UI thread.
+ const base::WeakPtr<ForwardingAudioStreamFactory> owner_;
+
+ const std::unique_ptr<AudioStreamBrokerFactory> broker_factory_;
+
+ // Unique id identifying all streams belonging to the WebContents owning
+ // |this|.
+ const base::UnguessableToken group_id_;
+
+ const std::unique_ptr<service_manager::Connector> connector_;
+
+ // 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_;
+ base::flat_set<AudioStreamBroker::LoopbackSink*> loopback_sinks_;
+
+ base::WeakPtrFactory<ForwardingAudioStreamFactory::Core> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(Core);
+ };
+
+ // 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);
+
+ // Returns the ForwardingAudioStreamFactory::Core 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::Core* CoreForFrame(
+ RenderFrameHost* frame);
+
// |web_contents| is null in the browser-privileged access case, i.e., when
// the streams created with this factory will not be consumed by a renderer.
+ // |connector| will be used on the IO thread.
ForwardingAudioStreamFactory(
WebContents* web_contents,
+ media::UserInputMonitorBase* user_input_monitor,
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() const {
+ // Thread-safe since Core::group_id is thread-safe and |core_| outlives
+ // |this|.
+ return core_->group_id();
+ }
- 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,
- audio::mojom::AudioProcessingConfigPtr processing_config,
- 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,
- const base::Optional<base::UnguessableToken>& processing_id,
- 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);
-
- // Creates a loopback stream that captures the audio from
- // |frame_of_source_web_contents|, or the default system playback if the
- // source is not provided. The source/system audio is muted during capturing.
- void CreateInProcessLoopbackStream(
- RenderFrameHost* frame_of_source_web_contents,
- const media::AudioParameters& params,
- uint32_t shared_memory_count,
- const AudioLoopbackStreamCreator::StreamCreatedCallback& callback);
+ void LoopbackStreamStarted();
+ void LoopbackStreamStopped();
// Sets the muting state for all output streams created through this factory.
void SetMuted(bool muted);
@@ -105,50 +214,13 @@ class CONTENT_EXPORT ForwardingAudioStreamFactory final
// 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();
- }
+ Core* core() { return core_.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_;
+ std::unique_ptr<Core> core_;
+ bool is_muted_ = false;
- StreamBrokerSet inputs_;
- StreamBrokerSet outputs_;
+ base::WeakPtrFactory<ForwardingAudioStreamFactory> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(ForwardingAudioStreamFactory);
};
diff --git a/chromium/content/browser/media/forwarding_audio_stream_factory_unittest.cc b/chromium/content/browser/media/forwarding_audio_stream_factory_unittest.cc
index 421f66bdac7..d390f5817e0 100644
--- a/chromium/content/browser/media/forwarding_audio_stream_factory_unittest.cc
+++ b/chromium/content/browser/media/forwarding_audio_stream_factory_unittest.cc
@@ -10,6 +10,7 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/macros.h"
+#include "base/run_loop.h"
#include "base/test/mock_callback.h"
#include "base/unguessable_token.h"
#include "content/common/media/renderer_audio_input_stream_factory.mojom.h"
@@ -110,6 +111,7 @@ class MockBrokerFactory : public AudioStreamBrokerFactory {
const std::string& device_id,
const media::AudioParameters& params,
uint32_t shared_memory_count,
+ media::UserInputMonitorBase* user_input_monitor,
bool enable_agc,
audio::mojom::AudioProcessingConfigPtr processing_config,
AudioStreamBroker::DeleterCallback deleter,
@@ -148,7 +150,7 @@ class MockBrokerFactory : public AudioStreamBrokerFactory {
std::unique_ptr<AudioStreamBroker> CreateAudioLoopbackStreamBroker(
int render_process_id,
int render_frame_id,
- std::unique_ptr<LoopbackSource> source,
+ AudioStreamBroker::LoopbackSource* source,
const media::AudioParameters& params,
uint32_t shared_memory_count,
bool mute_source,
@@ -172,6 +174,17 @@ class MockBrokerFactory : public AudioStreamBrokerFactory {
DISALLOW_COPY_AND_ASSIGN(MockBrokerFactory);
};
+class MockLoopbackSink : public AudioStreamBroker::LoopbackSink {
+ public:
+ MockLoopbackSink() {}
+ ~MockLoopbackSink() override {}
+
+ MOCK_METHOD0(OnSourceGone, void());
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MockLoopbackSink);
+};
+
class ForwardingAudioStreamFactoryTest : public RenderViewHostTestHarness {
public:
ForwardingAudioStreamFactoryTest()
@@ -253,14 +266,16 @@ 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_));
+ ForwardingAudioStreamFactory factory(
+ web_contents(), nullptr /*user_input_monitor*/, std::move(connector_),
+ std::move(broker_factory_));
EXPECT_CALL(*broker, CreateStream(NotNull()));
mojo::MakeRequest(&client);
- factory.CreateInputStream(main_rfh(), kInputDeviceId, kParams,
- kSharedMemoryCount, kEnableAgc, nullptr,
- std::move(client));
+ factory.core()->CreateInputStream(main_rfh()->GetProcess()->GetID(),
+ main_rfh()->GetRoutingID(), kInputDeviceId,
+ kParams, kSharedMemoryCount, kEnableAgc,
+ nullptr, std::move(client));
}
TEST_F(ForwardingAudioStreamFactoryTest,
@@ -270,14 +285,23 @@ TEST_F(ForwardingAudioStreamFactoryTest,
base::WeakPtr<MockBroker> broker =
ExpectLoopbackBrokerConstruction(main_rfh());
- ForwardingAudioStreamFactory factory(web_contents(), std::move(connector_),
- std::move(broker_factory_));
+ std::unique_ptr<service_manager::Connector> other_connector =
+ connector_->Clone();
+
+ ForwardingAudioStreamFactory factory(
+ web_contents(), nullptr /*user_input_monitor*/, std::move(connector_),
+ std::move(broker_factory_));
+
+ ForwardingAudioStreamFactory source_factory(
+ source_contents.get(), nullptr /*user_input_monitor*/,
+ std::move(other_connector), std::make_unique<MockBrokerFactory>());
EXPECT_CALL(*broker, CreateStream(NotNull()));
mojo::MakeRequest(&client);
- factory.CreateLoopbackStream(main_rfh(), source_contents->GetMainFrame(),
- kParams, kSharedMemoryCount, kMuteSource,
- std::move(client));
+ factory.core()->CreateLoopbackStream(
+ main_rfh()->GetProcess()->GetID(), main_rfh()->GetRoutingID(),
+ source_factory.core(), kParams, kSharedMemoryCount, kMuteSource,
+ std::move(client));
}
TEST_F(ForwardingAudioStreamFactoryTest,
@@ -285,13 +309,15 @@ TEST_F(ForwardingAudioStreamFactoryTest,
media::mojom::AudioOutputStreamProviderClientPtr client;
base::WeakPtr<MockBroker> broker = ExpectOutputBrokerConstruction(main_rfh());
- ForwardingAudioStreamFactory factory(web_contents(), std::move(connector_),
- std::move(broker_factory_));
+ ForwardingAudioStreamFactory factory(
+ web_contents(), nullptr /*user_input_monitor*/, std::move(connector_),
+ std::move(broker_factory_));
EXPECT_CALL(*broker, CreateStream(NotNull()));
mojo::MakeRequest(&client);
- factory.CreateOutputStream(main_rfh(), kOutputDeviceId, kParams,
- base::nullopt, std::move(client));
+ factory.core()->CreateOutputStream(
+ main_rfh()->GetProcess()->GetID(), main_rfh()->GetRoutingID(),
+ kOutputDeviceId, kParams, base::nullopt, std::move(client));
}
TEST_F(ForwardingAudioStreamFactoryTest,
@@ -302,23 +328,26 @@ TEST_F(ForwardingAudioStreamFactoryTest,
base::WeakPtr<MockBroker> other_rfh_broker =
ExpectInputBrokerConstruction(other_rfh());
- ForwardingAudioStreamFactory factory(web_contents(), std::move(connector_),
- std::move(broker_factory_));
+ ForwardingAudioStreamFactory factory(
+ web_contents(), nullptr /*user_input_monitor*/, 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, nullptr,
- std::move(client));
+ factory.core()->CreateInputStream(
+ main_rfh()->GetProcess()->GetID(), main_rfh()->GetRoutingID(),
+ kInputDeviceId, kParams, kSharedMemoryCount, kEnableAgc, nullptr,
+ 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, nullptr,
- std::move(client));
+ factory.core()->CreateInputStream(
+ other_rfh()->GetProcess()->GetID(), other_rfh()->GetRoutingID(),
+ kInputDeviceId, kParams, kSharedMemoryCount, kEnableAgc, nullptr,
+ std::move(client));
testing::Mock::VerifyAndClear(&*other_rfh_broker);
}
@@ -337,23 +366,33 @@ TEST_F(ForwardingAudioStreamFactoryTest,
base::WeakPtr<MockBroker> other_rfh_broker =
ExpectLoopbackBrokerConstruction(other_rfh());
- ForwardingAudioStreamFactory factory(web_contents(), std::move(connector_),
- std::move(broker_factory_));
+ std::unique_ptr<service_manager::Connector> other_connector =
+ connector_->Clone();
+
+ ForwardingAudioStreamFactory factory(
+ web_contents(), nullptr /*user_input_monitor*/, std::move(connector_),
+ std::move(broker_factory_));
+
+ ForwardingAudioStreamFactory source_factory(
+ source_contents.get(), nullptr /*user_input_monitor*/,
+ std::move(other_connector), std::make_unique<MockBrokerFactory>());
{
EXPECT_CALL(*main_rfh_broker, CreateStream(NotNull()));
mojo::MakeRequest(&client);
- factory.CreateLoopbackStream(main_rfh(), source_contents->GetMainFrame(),
- kParams, kSharedMemoryCount, kMuteSource,
- std::move(client));
+ factory.core()->CreateLoopbackStream(
+ main_rfh()->GetProcess()->GetID(), main_rfh()->GetRoutingID(),
+ source_factory.core(), 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));
+ factory.core()->CreateLoopbackStream(
+ other_rfh()->GetProcess()->GetID(), other_rfh()->GetRoutingID(),
+ source_factory.core(), kParams, kSharedMemoryCount, kMuteSource,
+ std::move(client));
testing::Mock::VerifyAndClear(&*other_rfh_broker);
}
@@ -371,21 +410,24 @@ TEST_F(ForwardingAudioStreamFactoryTest,
base::WeakPtr<MockBroker> other_rfh_broker =
ExpectOutputBrokerConstruction(other_rfh());
- ForwardingAudioStreamFactory factory(web_contents(), std::move(connector_),
- std::move(broker_factory_));
+ ForwardingAudioStreamFactory factory(
+ web_contents(), nullptr /*user_input_monitor*/, std::move(connector_),
+ std::move(broker_factory_));
{
EXPECT_CALL(*main_rfh_broker, CreateStream(NotNull()));
mojo::MakeRequest(&client);
- factory.CreateOutputStream(main_rfh(), kOutputDeviceId, kParams,
- base::nullopt, std::move(client));
+ factory.core()->CreateOutputStream(
+ main_rfh()->GetProcess()->GetID(), main_rfh()->GetRoutingID(),
+ kOutputDeviceId, kParams, base::nullopt, 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,
- base::nullopt, std::move(client));
+ factory.core()->CreateOutputStream(
+ other_rfh()->GetProcess()->GetID(), other_rfh()->GetRoutingID(),
+ kOutputDeviceId, kParams, base::nullopt, std::move(client));
testing::Mock::VerifyAndClear(&*other_rfh_broker);
}
@@ -415,55 +457,69 @@ TEST_F(ForwardingAudioStreamFactoryTest, DestroyFrame_DestroysRelatedStreams) {
base::WeakPtr<MockBroker> other_rfh_output_broker =
ExpectOutputBrokerConstruction(other_rfh());
- ForwardingAudioStreamFactory factory(web_contents(), std::move(connector_),
- std::move(broker_factory_));
+ std::unique_ptr<service_manager::Connector> other_connector =
+ connector_->Clone();
+
+ ForwardingAudioStreamFactory factory(
+ web_contents(), nullptr /*user_input_monitor*/, std::move(connector_),
+ std::move(broker_factory_));
+
+ ForwardingAudioStreamFactory source_factory(
+ source_contents.get(), nullptr /*user_input_monitor*/,
+ std::move(other_connector), std::make_unique<MockBrokerFactory>());
{
EXPECT_CALL(*main_rfh_input_broker, CreateStream(NotNull()));
mojo::MakeRequest(&input_client);
- factory.CreateInputStream(main_rfh(), kInputDeviceId, kParams,
- kSharedMemoryCount, kEnableAgc, nullptr,
- std::move(input_client));
+ factory.core()->CreateInputStream(
+ main_rfh()->GetProcess()->GetID(), main_rfh()->GetRoutingID(),
+ kInputDeviceId, kParams, kSharedMemoryCount, kEnableAgc, nullptr,
+ 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, nullptr,
- std::move(input_client));
+ factory.core()->CreateInputStream(
+ other_rfh()->GetProcess()->GetID(), other_rfh()->GetRoutingID(),
+ kInputDeviceId, kParams, kSharedMemoryCount, kEnableAgc, nullptr,
+ 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));
+ factory.core()->CreateLoopbackStream(
+ main_rfh()->GetProcess()->GetID(), main_rfh()->GetRoutingID(),
+ source_factory.core(), 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));
+ factory.core()->CreateLoopbackStream(
+ other_rfh()->GetProcess()->GetID(), other_rfh()->GetRoutingID(),
+ source_factory.core(), 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,
- base::nullopt, std::move(output_client));
+ factory.core()->CreateOutputStream(
+ main_rfh()->GetProcess()->GetID(), main_rfh()->GetRoutingID(),
+ kOutputDeviceId, kParams, base::nullopt, 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,
- base::nullopt, std::move(output_client));
+ factory.core()->CreateOutputStream(
+ other_rfh()->GetProcess()->GetID(), other_rfh()->GetRoutingID(),
+ kOutputDeviceId, kParams, base::nullopt, std::move(output_client));
testing::Mock::VerifyAndClear(&*other_rfh_output_broker);
}
@@ -490,19 +546,22 @@ TEST_F(ForwardingAudioStreamFactoryTest, DestroyWebContents_DestroysStreams) {
base::WeakPtr<MockBroker> output_broker =
ExpectOutputBrokerConstruction(main_rfh());
- ForwardingAudioStreamFactory factory(web_contents(), std::move(connector_),
- std::move(broker_factory_));
+ ForwardingAudioStreamFactory factory(
+ web_contents(), nullptr /*user_input_monitor*/, 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, nullptr,
- std::move(input_client));
+ factory.core()->CreateInputStream(main_rfh()->GetProcess()->GetID(),
+ main_rfh()->GetRoutingID(), kInputDeviceId,
+ kParams, kSharedMemoryCount, kEnableAgc,
+ nullptr, std::move(input_client));
EXPECT_CALL(*output_broker, CreateStream(NotNull()));
mojo::MakeRequest(&output_client);
- factory.CreateOutputStream(main_rfh(), kOutputDeviceId, kParams,
- base::nullopt, std::move(output_client));
+ factory.core()->CreateOutputStream(
+ main_rfh()->GetProcess()->GetID(), main_rfh()->GetRoutingID(),
+ kOutputDeviceId, kParams, base::nullopt, std::move(output_client));
DeleteContents();
base::RunLoop().RunUntilIdle();
@@ -526,38 +585,43 @@ TEST_F(ForwardingAudioStreamFactoryTest, LastStreamDeleted_ClearsFactoryPtr) {
base::WeakPtr<MockBroker> other_rfh_output_broker =
ExpectOutputBrokerConstruction(other_rfh());
- ForwardingAudioStreamFactory factory(web_contents(), std::move(connector_),
- std::move(broker_factory_));
+ ForwardingAudioStreamFactory factory(
+ web_contents(), nullptr /*user_input_monitor*/, 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, nullptr,
- std::move(input_client));
+ factory.core()->CreateInputStream(
+ main_rfh()->GetProcess()->GetID(), main_rfh()->GetRoutingID(),
+ kInputDeviceId, kParams, kSharedMemoryCount, kEnableAgc, nullptr,
+ 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, nullptr,
- std::move(input_client));
+ factory.core()->CreateInputStream(
+ other_rfh()->GetProcess()->GetID(), other_rfh()->GetRoutingID(),
+ kInputDeviceId, kParams, kSharedMemoryCount, kEnableAgc, nullptr,
+ 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,
- base::nullopt, std::move(output_client));
+ factory.core()->CreateOutputStream(
+ main_rfh()->GetProcess()->GetID(), main_rfh()->GetRoutingID(),
+ kOutputDeviceId, kParams, base::nullopt, 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,
- base::nullopt, std::move(output_client));
+ factory.core()->CreateOutputStream(
+ other_rfh()->GetProcess()->GetID(), other_rfh()->GetRoutingID(),
+ kOutputDeviceId, kParams, base::nullopt, std::move(output_client));
testing::Mock::VerifyAndClear(&*other_rfh_output_broker);
}
@@ -583,8 +647,9 @@ TEST_F(ForwardingAudioStreamFactoryTest, LastStreamDeleted_ClearsFactoryPtr) {
TEST_F(ForwardingAudioStreamFactoryTest,
MuteNoOutputStreams_DoesNotConnectMuter) {
- ForwardingAudioStreamFactory factory(web_contents(), std::move(connector_),
- std::move(broker_factory_));
+ ForwardingAudioStreamFactory factory(
+ web_contents(), nullptr /*user_input_monitor*/, std::move(connector_),
+ std::move(broker_factory_));
EXPECT_FALSE(factory.IsMuted());
factory.SetMuted(true);
@@ -603,13 +668,15 @@ TEST_F(ForwardingAudioStreamFactoryTest,
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_));
+ ForwardingAudioStreamFactory factory(
+ web_contents(), nullptr /*user_input_monitor*/, std::move(connector_),
+ std::move(broker_factory_));
EXPECT_CALL(*broker, CreateStream(NotNull()));
mojo::MakeRequest(&client);
- factory.CreateOutputStream(main_rfh(), kOutputDeviceId, kParams,
- base::nullopt, std::move(client));
+ factory.core()->CreateOutputStream(
+ main_rfh()->GetProcess()->GetID(), main_rfh()->GetRoutingID(),
+ kOutputDeviceId, kParams, base::nullopt, std::move(client));
base::RunLoop().RunUntilIdle();
testing::Mock::VerifyAndClear(&*broker);
@@ -633,8 +700,9 @@ 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_));
+ ForwardingAudioStreamFactory factory(
+ web_contents(), nullptr /*user_input_monitor*/, std::move(connector_),
+ std::move(broker_factory_));
EXPECT_FALSE(stream_factory_.IsConnected());
EXPECT_FALSE(factory.IsMuted());
@@ -647,8 +715,9 @@ TEST_F(ForwardingAudioStreamFactoryTest,
EXPECT_CALL(*broker, CreateStream(NotNull()));
mojo::MakeRequest(&client);
- factory.CreateOutputStream(main_rfh(), kOutputDeviceId, kParams,
- base::nullopt, std::move(client));
+ factory.core()->CreateOutputStream(
+ main_rfh()->GetProcess()->GetID(), main_rfh()->GetRoutingID(),
+ kOutputDeviceId, kParams, base::nullopt, std::move(client));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(factory.IsMuted());
EXPECT_TRUE(stream_factory_.IsConnected());
@@ -669,14 +738,16 @@ TEST_F(ForwardingAudioStreamFactoryTest,
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_));
+ ForwardingAudioStreamFactory factory(
+ web_contents(), nullptr /*user_input_monitor*/, std::move(connector_),
+ std::move(broker_factory_));
{
EXPECT_CALL(*broker, CreateStream(NotNull()));
mojo::MakeRequest(&client);
- factory.CreateOutputStream(main_rfh(), kOutputDeviceId, kParams,
- base::nullopt, std::move(client));
+ factory.core()->CreateOutputStream(
+ main_rfh()->GetProcess()->GetID(), main_rfh()->GetRoutingID(),
+ kOutputDeviceId, kParams, base::nullopt, std::move(client));
base::RunLoop().RunUntilIdle();
testing::Mock::VerifyAndClear(&*broker);
}
@@ -692,8 +763,9 @@ TEST_F(ForwardingAudioStreamFactoryTest,
{
EXPECT_CALL(*another_broker, CreateStream(NotNull()));
mojo::MakeRequest(&client);
- factory.CreateOutputStream(main_rfh(), kOutputDeviceId, kParams,
- base::nullopt, std::move(client));
+ factory.core()->CreateOutputStream(
+ main_rfh()->GetProcess()->GetID(), main_rfh()->GetRoutingID(),
+ kOutputDeviceId, kParams, base::nullopt, std::move(client));
base::RunLoop().RunUntilIdle();
testing::Mock::VerifyAndClear(&*another_broker);
}
@@ -711,4 +783,24 @@ TEST_F(ForwardingAudioStreamFactoryTest,
EXPECT_TRUE(stream_factory_.IsMuterConnected());
}
+TEST_F(ForwardingAudioStreamFactoryTest,
+ Destruction_CallsOnSourceGoneOnRegisteredLoopbackSinks) {
+ StrictMock<MockLoopbackSink> sink1;
+ StrictMock<MockLoopbackSink> sink2;
+
+ // We remove |sink1| before |factory| is destructed, so it shouldn't be
+ // called.
+ EXPECT_CALL(sink2, OnSourceGone());
+ {
+ ForwardingAudioStreamFactory factory(
+ web_contents(), nullptr /*user_input_monitor*/, std::move(connector_),
+ std::move(broker_factory_));
+
+ factory.core()->AddLoopbackSink(&sink1);
+ factory.core()->AddLoopbackSink(&sink2);
+ factory.core()->RemoveLoopbackSink(&sink1);
+ }
+ base::RunLoop().RunUntilIdle();
+}
+
} // namespace content
diff --git a/chromium/content/browser/media/in_process_audio_loopback_stream_creator.cc b/chromium/content/browser/media/in_process_audio_loopback_stream_creator.cc
index 618c9b8f3a5..12b51f3f47e 100644
--- a/chromium/content/browser/media/in_process_audio_loopback_stream_creator.cc
+++ b/chromium/content/browser/media/in_process_audio_loopback_stream_creator.cc
@@ -4,16 +4,102 @@
#include "content/browser/media/in_process_audio_loopback_stream_creator.h"
+#include <memory>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/task/post_task.h"
+#include "content/browser/browser_main_loop.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/common/media/renderer_audio_input_stream_factory.mojom.h"
+#include "content/public/browser/browser_task_traits.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/service_manager_connection.h"
+#include "media/audio/audio_device_description.h"
+#include "media/base/user_input_monitor.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
#include "services/service_manager/public/cpp/connector.h"
namespace content {
+namespace {
+
+// A mojom::RendererAudioInputStreamFactoryClient that holds a
+// AudioLoopbackStreamCreator::StreamCreatedCallback. The callback runs when the
+// requested audio stream is created.
+class StreamCreatedCallbackAdapter final
+ : public mojom::RendererAudioInputStreamFactoryClient {
+ public:
+ explicit StreamCreatedCallbackAdapter(
+ const AudioLoopbackStreamCreator::StreamCreatedCallback& callback)
+ : callback_(callback) {
+ DCHECK(callback_);
+ }
+
+ ~StreamCreatedCallbackAdapter() override {}
+
+ // mojom::RendererAudioInputStreamFactoryClient implementation.
+ void StreamCreated(
+ media::mojom::AudioInputStreamPtr stream,
+ media::mojom::AudioInputStreamClientRequest client_request,
+ media::mojom::ReadOnlyAudioDataPipePtr data_pipe,
+ bool initially_muted,
+ const base::Optional<base::UnguessableToken>& stream_id) override {
+ DCHECK(!initially_muted); // Loopback streams shouldn't be started muted.
+ callback_.Run(std::move(stream), std::move(client_request),
+ std::move(data_pipe));
+ }
+
+ private:
+ const AudioLoopbackStreamCreator::StreamCreatedCallback callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(StreamCreatedCallbackAdapter);
+};
+
+void CreateLoopbackStreamHelper(
+ ForwardingAudioStreamFactory::Core* factory,
+ AudioStreamBroker::LoopbackSource* loopback_source,
+ const media::AudioParameters& params,
+ uint32_t total_segments,
+ mojom::RendererAudioInputStreamFactoryClientPtrInfo client_ptr_info) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ const bool mute_source = true;
+ mojom::RendererAudioInputStreamFactoryClientPtr client;
+ client.Bind(std::move(client_ptr_info));
+
+ factory->CreateLoopbackStream(-1, -1, loopback_source, params, total_segments,
+ mute_source, std::move(client));
+}
+
+void CreateSystemWideLoopbackStreamHelper(
+ ForwardingAudioStreamFactory::Core* factory,
+ const media::AudioParameters& params,
+ uint32_t total_segments,
+ mojom::RendererAudioInputStreamFactoryClientPtrInfo client_ptr_info) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ const bool enable_agc = false;
+ mojom::RendererAudioInputStreamFactoryClientPtr client;
+ client.Bind(std::move(client_ptr_info));
+
+ factory->CreateInputStream(
+ -1, -1, media::AudioDeviceDescription::kLoopbackWithMuteDeviceId, params,
+ total_segments, enable_agc, nullptr /* processing_config */,
+ std::move(client));
+}
+
+} // namespace
+
InProcessAudioLoopbackStreamCreator::InProcessAudioLoopbackStreamCreator()
: factory_(nullptr,
+ BrowserMainLoop::GetInstance()
+ ? static_cast<media::UserInputMonitorBase*>(
+ BrowserMainLoop::GetInstance()->user_input_monitor())
+ : nullptr,
content::ServiceManagerConnection::GetForProcess()
->GetConnector()
->Clone(),
@@ -23,7 +109,6 @@ InProcessAudioLoopbackStreamCreator::InProcessAudioLoopbackStreamCreator()
InProcessAudioLoopbackStreamCreator::~InProcessAudioLoopbackStreamCreator() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- factory_.FrameDeleted(nullptr);
}
void InProcessAudioLoopbackStreamCreator::CreateLoopbackStream(
@@ -32,13 +117,27 @@ void InProcessAudioLoopbackStreamCreator::CreateLoopbackStream(
uint32_t total_segments,
const StreamCreatedCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- RenderFrameHost* loopback_source_frame = nullptr;
+ mojom::RendererAudioInputStreamFactoryClientPtrInfo client;
+ mojo::MakeStrongBinding(
+ std::make_unique<StreamCreatedCallbackAdapter>(callback),
+ mojo::MakeRequest(&client));
+ // Deletion of factory_.core() is posted to the IO thread when |factory_| is
+ // destroyed, so Unretained is safe below.
if (loopback_source) {
- loopback_source_frame = loopback_source->GetMainFrame();
- DCHECK(loopback_source_frame);
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(&CreateLoopbackStreamHelper, factory_.core(),
+ static_cast<WebContentsImpl*>(loopback_source)
+ ->GetAudioStreamFactory()
+ ->core(),
+ params, total_segments, std::move(client)));
+ return;
}
- factory_.CreateInProcessLoopbackStream(loopback_source_frame, params,
- total_segments, callback);
+ // A null |frame_of_source_web_contents| requests system-wide loopback.
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(&CreateSystemWideLoopbackStreamHelper, factory_.core(),
+ params, total_segments, std::move(client)));
}
} // namespace content
diff --git a/chromium/content/browser/media/media_browsertest.cc b/chromium/content/browser/media/media_browsertest.cc
index 93bea4f82b9..5aabc37b42b 100644
--- a/chromium/content/browser/media/media_browsertest.cc
+++ b/chromium/content/browser/media/media_browsertest.cc
@@ -30,6 +30,9 @@ void MediaBrowserTest::SetUpCommandLine(base::CommandLine* command_line) {
command_line->AppendSwitchASCII(
switches::kAutoplayPolicy,
switches::autoplay::kNoUserGestureRequiredPolicy);
+ // Disable fallback after decode error to avoid unexpected test pass on the
+ // fallback path.
+ scoped_feature_list_.InitAndDisableFeature(media::kFallbackAfterDecodeError);
}
void MediaBrowserTest::RunMediaTestPage(const std::string& html_page,
diff --git a/chromium/content/browser/media/media_browsertest.h b/chromium/content/browser/media/media_browsertest.h
index b8e0b906d15..bc9af5cb690 100644
--- a/chromium/content/browser/media/media_browsertest.h
+++ b/chromium/content/browser/media/media_browsertest.h
@@ -8,6 +8,7 @@
#include <string>
#include "base/strings/string_split.h"
+#include "base/test/scoped_feature_list.h"
#include "content/public/test/content_browser_test.h"
namespace content {
@@ -44,6 +45,9 @@ class MediaBrowserTest : public ContentBrowserTest {
// Adds titles that RunTest() should wait for.
virtual void AddTitlesToAwait(content::TitleWatcher* title_watcher);
+
+ private:
+ base::test::ScopedFeatureList scoped_feature_list_;
};
} // namespace content
diff --git a/chromium/content/browser/media/media_color_browsertest.cc b/chromium/content/browser/media/media_color_browsertest.cc
index 6cc930bb586..5f38d7429a7 100644
--- a/chromium/content/browser/media/media_color_browsertest.cc
+++ b/chromium/content/browser/media/media_color_browsertest.cc
@@ -53,9 +53,8 @@ IN_PROC_BROWSER_TEST_F(MediaColorTest, Yuv420pH264) {
RunColorTest("yuv420p.mp4");
}
-// This test fails on Android: http://crbug.com/647818 and OSX:
-// http://crbug.com/647838
-#if defined(OS_MACOSX) || defined(OS_ANDROID)
+// This test fails on Android: http://crbug.com/647818
+#if defined(OS_ANDROID)
#define MAYBE_Yuvj420pH264 DISABLED_Yuvj420pH264
#else
#define MAYBE_Yuvj420pH264 Yuvj420pH264
diff --git a/chromium/content/browser/media/media_devices_permission_checker.cc b/chromium/content/browser/media/media_devices_permission_checker.cc
index 8c16627a4a1..95280c196b0 100644
--- a/chromium/content/browser/media/media_devices_permission_checker.cc
+++ b/chromium/content/browser/media/media_devices_permission_checker.cc
@@ -9,10 +9,12 @@
#include "base/bind.h"
#include "base/command_line.h"
+#include "base/task/post_task.h"
#include "content/browser/frame_host/render_frame_host_delegate.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/common/media/media_devices.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/common/content_switches.h"
@@ -114,8 +116,8 @@ void MediaDevicesPermissionChecker::CheckPermission(
return;
}
- BrowserThread::PostTaskAndReplyWithResult(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraitsAndReplyWithResult(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&CheckSinglePermissionOnUIThread, device_type,
render_process_id, render_frame_id),
std::move(callback));
@@ -134,8 +136,8 @@ void MediaDevicesPermissionChecker::CheckPermissions(
return;
}
- BrowserThread::PostTaskAndReplyWithResult(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraitsAndReplyWithResult(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&DoCheckPermissionsOnUIThread, requested,
render_process_id, render_frame_id),
std::move(callback));
diff --git a/chromium/content/browser/media/media_devices_util.cc b/chromium/content/browser/media/media_devices_util.cc
index 58badef2512..59fcb9314f1 100644
--- a/chromium/content/browser/media/media_devices_util.cc
+++ b/chromium/content/browser/media/media_devices_util.cc
@@ -11,10 +11,12 @@
#include "base/command_line.h"
#include "base/strings/string_split.h"
#include "base/strings/string_tokenizer.h"
+#include "base/task/post_task.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_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/media_device_id.h"
#include "content/public/browser/render_frame_host.h"
@@ -117,8 +119,8 @@ void GetDefaultMediaDeviceID(
}
}
- BrowserThread::PostTaskAndReplyWithResult(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraitsAndReplyWithResult(
+ FROM_HERE, {BrowserThread::UI},
base::Bind(&GetDefaultMediaDeviceIDOnUIThread, device_type,
render_process_id, render_frame_id),
callback);
diff --git a/chromium/content/browser/media/media_internals.cc b/chromium/content/browser/media/media_internals.cc
index a4257d16db9..fe54364f26d 100644
--- a/chromium/content/browser/media/media_internals.cc
+++ b/chromium/content/browser/media/media_internals.cc
@@ -9,17 +9,21 @@
#include <tuple>
#include <utility>
+#include "base/containers/adapters.h"
+#include "base/feature_list.h"
#include "base/macros.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
+#include "base/stl_util.h"
#include "base/strings/string16.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
+#include "base/task/post_task.h"
#include "build/build_config.h"
-#include "content/browser/media/session/audio_focus_manager.h"
#include "content/browser/media/session/media_session_impl.h"
#include "content/browser/renderer_host/media/media_stream_manager.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_types.h"
@@ -27,10 +31,16 @@
#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/common/content_features.h"
+#include "content/public/common/service_manager_connection.h"
#include "media/base/audio_parameters.h"
#include "media/base/media_log_event.h"
#include "media/filters/gpu_video_decoder.h"
+#include "media/webrtc/webrtc_switches.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "services/media_session/public/mojom/constants.mojom.h"
+#include "services/service_manager/public/cpp/connector.h"
+#include "services/service_manager/sandbox/features.h"
#if !defined(OS_ANDROID)
#include "media/filters/decrypting_video_decoder.h"
@@ -115,6 +125,10 @@ bool IsIncognito(int render_process_id) {
const char kAudioLogStatusKey[] = "status";
const char kAudioLogUpdateFunction[] = "media.updateAudioComponent";
+const char kAudioFocusFunction[] = "media.onReceiveAudioFocusState";
+const char kAudioFocusIdKey[] = "id";
+const char kAudioFocusSessionsKey[] = "sessions";
+
} // namespace
namespace content {
@@ -269,8 +283,8 @@ void MediaInternals::AudioLogImpl::SendWebContentsTitleHelper(
int render_frame_id) {
// Page title information can only be retrieved from the UI thread.
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&SendWebContentsTitleHelper, cache_key, std::move(dict),
render_process_id, render_frame_id));
return;
@@ -691,6 +705,27 @@ void MediaInternals::SendHistoricalMediaEvents() {
// second UI still works nicely!
}
+void MediaInternals::SendGeneralAudioInformation() {
+ base::DictionaryValue audio_info_data;
+
+ // Audio feature information.
+ auto set_feature_data = [&](auto& feature) {
+ audio_info_data.SetKey(
+ feature.name,
+ base::Value(base::FeatureList::IsEnabled(feature) ? "Enabled"
+ : "Disabled"));
+ };
+ set_feature_data(features::kAudioServiceAudioStreams);
+ set_feature_data(features::kAudioServiceOutOfProcess);
+ set_feature_data(features::kAudioServiceLaunchOnStartup);
+ set_feature_data(service_manager::features::kAudioServiceSandbox);
+ set_feature_data(features::kWebRtcApmInAudioService);
+
+ base::string16 audio_info_update =
+ SerializeUpdate("media.updateGeneralAudioInformation", &audio_info_data);
+ SendUpdate(audio_info_update);
+}
+
void MediaInternals::SendAudioStreamData() {
base::string16 audio_stream_update;
{
@@ -712,32 +747,20 @@ void MediaInternals::SendVideoCaptureDeviceCapabilities() {
}
void MediaInternals::SendAudioFocusState() {
-#if !defined(OS_ANDROID)
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (!CanUpdate())
return;
- base::DictionaryValue audio_focus_data;
- const std::list<AudioFocusManager::StackRow>& stack =
- AudioFocusManager::GetInstance()->audio_focus_stack_;
+ content::ServiceManagerConnection::GetForProcess()
+ ->GetConnector()
+ ->BindInterface(media_session::mojom::kServiceName, &audio_focus_ptr_);
- // We should go backwards through the stack so the top of the stack is always
- // shown first in the list.
- base::ListValue stack_data;
- for (auto iter = stack.rbegin(); iter != stack.rend(); ++iter) {
- MediaSessionImpl::DebugInfo debug_info =
- (*iter).media_session->GetDebugInfo();
- base::DictionaryValue media_session_data;
- media_session_data.SetKey("name", base::Value(debug_info.name));
- media_session_data.SetKey("owner", base::Value(debug_info.owner));
- media_session_data.SetKey("state", base::Value(debug_info.state));
- stack_data.GetList().push_back(std::move(media_session_data));
- }
-
- audio_focus_data.SetKey("sessions", std::move(stack_data));
+ if (!audio_focus_ptr_.is_bound())
+ return;
- SendUpdate(
- SerializeUpdate("media.onReceiveAudioFocusState", &audio_focus_data));
-#endif // !defined(OS_ANDROID)
+ // Get the audio focus state from the media session service.
+ audio_focus_ptr_->GetFocusRequests(base::BindOnce(
+ &MediaInternals::DidGetAudioFocusRequestList, base::Unretained(this)));
}
void MediaInternals::UpdateVideoCaptureDeviceCapabilities(
@@ -821,30 +844,100 @@ void MediaInternals::OnProcessTerminatedForTesting(int process_id) {
}
void MediaInternals::OnFocusGained(
- media_session::mojom::MediaSessionPtr media_session,
+ media_session::mojom::MediaSessionInfoPtr media_session,
media_session::mojom::AudioFocusType type) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(&MediaInternals::SendAudioFocusState,
- base::Unretained(this)));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(&MediaInternals::SendAudioFocusState,
+ base::Unretained(this)));
}
void MediaInternals::OnFocusLost(
- media_session::mojom::MediaSessionPtr media_session) {
+ media_session::mojom::MediaSessionInfoPtr media_session) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(&MediaInternals::SendAudioFocusState,
+ base::Unretained(this)));
+}
+
+void MediaInternals::DidGetAudioFocusRequestList(
+ std::vector<media_session::mojom::AudioFocusRequestStatePtr> stack) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ if (!CanUpdate())
+ return;
+
+ content::ServiceManagerConnection::GetForProcess()
+ ->GetConnector()
+ ->BindInterface(media_session::mojom::kServiceName,
+ &audio_focus_debug_ptr_);
+
+ if (!audio_focus_debug_ptr_.is_bound())
+ return;
+
+ audio_focus_data_.Clear();
+
+ // We should go backwards through the stack so the top of the stack is
+ // always shown first in the list.
+ base::ListValue stack_data;
+ for (const auto& session : base::Reversed(stack)) {
+ if (!session->request_id.has_value())
+ continue;
+
+ std::string id_string = session->request_id.value().ToString();
+ base::DictionaryValue media_session_data;
+ media_session_data.SetKey(kAudioFocusIdKey, base::Value(id_string));
+ stack_data.GetList().push_back(std::move(media_session_data));
+
+ audio_focus_debug_ptr_->GetDebugInfoForRequest(
+ session->request_id.value(),
+ base::BindOnce(&MediaInternals::DidGetAudioFocusDebugInfo,
+ base::Unretained(this), id_string));
+ }
+
+ audio_focus_data_.SetKey(kAudioFocusSessionsKey, std::move(stack_data));
+
+ if (stack.empty())
+ SendUpdate(SerializeUpdate(kAudioFocusFunction, &audio_focus_data_));
+}
+
+void MediaInternals::DidGetAudioFocusDebugInfo(
+ const std::string& id,
+ media_session::mojom::MediaSessionDebugInfoPtr info) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(&MediaInternals::SendAudioFocusState,
- base::Unretained(this)));
+ if (!CanUpdate())
+ return;
+
+ base::Value* sessions_list =
+ audio_focus_data_.FindKey(kAudioFocusSessionsKey);
+ DCHECK(sessions_list);
+
+ bool updated = false;
+ for (auto& session : sessions_list->GetList()) {
+ if (session.FindKey(kAudioFocusIdKey)->GetString() != id)
+ continue;
+
+ session.SetKey("name", base::Value(info->name));
+ session.SetKey("owner", base::Value(info->owner));
+ session.SetKey("state", base::Value(info->state));
+ updated = true;
+ }
+
+ if (!updated)
+ return;
+
+ SendUpdate(SerializeUpdate(kAudioFocusFunction, &audio_focus_data_));
}
void MediaInternals::SendUpdate(const base::string16& update) {
// SendUpdate() may be called from any thread, but must run on the UI thread.
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(&MediaInternals::SendUpdate,
- base::Unretained(this), update));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(&MediaInternals::SendUpdate,
+ base::Unretained(this), update));
return;
}
@@ -871,11 +964,9 @@ void MediaInternals::SaveEvent(int process_id,
// Remove all events for a given player as soon as we have to remove a
// single event for that player to avoid showing incomplete players.
const int id_to_remove = saved_events.front().id;
- saved_events.erase(std::remove_if(saved_events.begin(), saved_events.end(),
- [&](const media::MediaLogEvent& event) {
- return event.id == id_to_remove;
- }),
- saved_events.end());
+ base::EraseIf(saved_events, [&](const media::MediaLogEvent& event) {
+ return event.id == id_to_remove;
+ });
}
}
diff --git a/chromium/content/browser/media/media_internals.h b/chromium/content/browser/media/media_internals.h
index 7aa7ddcaaa8..189904c7ca1 100644
--- a/chromium/content/browser/media/media_internals.h
+++ b/chromium/content/browser/media/media_internals.h
@@ -75,6 +75,9 @@ class CONTENT_EXPORT MediaInternals : public media::AudioLogFactory,
// Replay all saved media events.
void SendHistoricalMediaEvents();
+ // Sends general audio information to each registered UpdateCallback.
+ void SendGeneralAudioInformation();
+
// Sends all audio cached data to each registered UpdateCallback.
void SendAudioStreamData();
@@ -121,10 +124,20 @@ class CONTENT_EXPORT MediaInternals : public media::AudioLogFactory,
MediaInternals();
// AudioFocusObserver implementation.
- void OnFocusGained(media_session::mojom::MediaSessionPtr media_session,
+ void OnFocusGained(media_session::mojom::MediaSessionInfoPtr media_session,
media_session::mojom::AudioFocusType type) override;
void OnFocusLost(
- media_session::mojom::MediaSessionPtr media_session) override;
+ media_session::mojom::MediaSessionInfoPtr media_session) override;
+
+ // Called when we receive the list of audio focus requests to display.
+ void DidGetAudioFocusRequestList(
+ std::vector<media_session::mojom::AudioFocusRequestStatePtr>);
+
+ // Called when we receive audio focus debug info to display for a single
+ // audio focus request.
+ void DidGetAudioFocusDebugInfo(
+ const std::string& id,
+ media_session::mojom::MediaSessionDebugInfoPtr info);
// Sends |update| to each registered UpdateCallback. Safe to call from any
// thread, but will forward to the IO thread.
@@ -152,6 +165,10 @@ class CONTENT_EXPORT MediaInternals : public media::AudioLogFactory,
int render_process_id,
int render_frame_id);
+ // Holds a pointer to the media session service and it's debug interface.
+ media_session::mojom::AudioFocusManagerPtr audio_focus_ptr_;
+ media_session::mojom::AudioFocusManagerDebugPtr audio_focus_debug_ptr_;
+
// Must only be accessed on the UI thread.
std::vector<UpdateCallback> update_callbacks_;
@@ -163,6 +180,9 @@ class CONTENT_EXPORT MediaInternals : public media::AudioLogFactory,
NotificationRegistrar registrar_;
+ // Must only be accessed on the UI thread.
+ base::DictionaryValue audio_focus_data_;
+
// All variables below must be accessed under |lock_|.
base::Lock lock_;
bool can_update_;
diff --git a/chromium/content/browser/media/media_internals_proxy.cc b/chromium/content/browser/media/media_internals_proxy.cc
index 8526ebc04a4..bfa38b2ca18 100644
--- a/chromium/content/browser/media/media_internals_proxy.cc
+++ b/chromium/content/browser/media/media_internals_proxy.cc
@@ -6,9 +6,11 @@
#include "base/bind.h"
#include "base/location.h"
+#include "base/task/post_task.h"
#include "build/build_config.h"
#include "content/browser/media/media_internals.h"
#include "content/browser/media/media_internals_handler.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
namespace content {
@@ -37,10 +39,14 @@ void MediaInternalsProxy::GetEverything() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
MediaInternals::GetInstance()->SendHistoricalMediaEvents();
+ MediaInternals::GetInstance()->SendGeneralAudioInformation();
+#if !defined(OS_ANDROID)
+ MediaInternals::GetInstance()->SendAudioFocusState();
+#endif
// Ask MediaInternals for its data on IO thread.
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&MediaInternalsProxy::GetEverythingOnIOThread, this));
}
@@ -49,10 +55,6 @@ void MediaInternalsProxy::GetEverythingOnIOThread() {
// TODO(xhwang): Investigate whether we can update on UI thread directly.
MediaInternals::GetInstance()->SendAudioStreamData();
MediaInternals::GetInstance()->SendVideoCaptureDeviceCapabilities();
-
-#if !defined(OS_ANDROID)
- MediaInternals::GetInstance()->SendAudioFocusState();
-#endif
}
void MediaInternalsProxy::UpdateUIOnUIThread(const base::string16& update) {
diff --git a/chromium/content/browser/media/media_internals_unittest.cc b/chromium/content/browser/media/media_internals_unittest.cc
index 033385ac2de..32a85ae8abd 100644
--- a/chromium/content/browser/media/media_internals_unittest.cc
+++ b/chromium/content/browser/media/media_internals_unittest.cc
@@ -12,14 +12,15 @@
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/synchronization/lock.h"
#include "base/test/scoped_command_line.h"
#include "base/test/test_message_loop.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
-#include "content/browser/media/session/audio_focus_manager.h"
#include "content/browser/media/session/media_session_impl.h"
#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/test_service_manager_context.h"
#include "content/test/test_web_contents.h"
#include "media/base/audio_parameters.h"
#include "media/base/channel_layout.h"
@@ -27,6 +28,7 @@
#include "media/base/media_switches.h"
#include "services/media_session/public/cpp/switches.h"
#include "services/media_session/public/mojom/audio_focus.mojom.h"
+#include "services/media_session/public/mojom/constants.mojom.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/geometry/size.h"
@@ -35,18 +37,27 @@ namespace {
const int kTestComponentID = 0;
const char kTestDeviceID[] = "test-device-id";
+using media_session::mojom::AudioFocusRequestStatePtr;
+
// This class encapsulates a MediaInternals reference. It also has some useful
// methods to receive a callback, deserialize its associated data and expect
// integer/string values.
class MediaInternalsTestBase {
public:
- MediaInternalsTestBase()
- : media_internals_(content::MediaInternals::GetInstance()) {}
+ MediaInternalsTestBase() : media_internals_(nullptr) {
+ scoped_command_line_.GetProcessCommandLine()->AppendSwitch(
+ media_session::switches::kEnableAudioFocus);
+
+ service_manager_context_ =
+ std::make_unique<content::TestServiceManagerContext>();
+ media_internals_ = content::MediaInternals::GetInstance();
+ }
+
virtual ~MediaInternalsTestBase() {}
protected:
// Extracts and deserializes the JSON update data; merges into |update_data_|.
- void UpdateCallbackImpl(const base::string16& update) {
+ virtual void UpdateCallbackImpl(const base::string16& update) {
// Each update string looks like "<JavaScript Function Name>({<JSON>});"
// or for video capabilities: "<JavaScript Function Name>([{<JSON>}]);".
// In the second case we will be able to extract the dictionary if it is the
@@ -98,7 +109,14 @@ class MediaInternalsTestBase {
const content::TestBrowserThreadBundle thread_bundle_;
base::DictionaryValue update_data_;
- content::MediaInternals* const media_internals_;
+
+ content::MediaInternals* media_internals() const { return media_internals_; }
+
+ private:
+ content::MediaInternals* media_internals_;
+
+ base::test::ScopedCommandLine scoped_command_line_;
+ std::unique_ptr<content::TestServiceManagerContext> service_manager_context_;
};
} // namespace
@@ -114,11 +132,11 @@ class MediaInternalsVideoCaptureDeviceTest : public testing::Test,
: update_cb_(base::Bind(
&MediaInternalsVideoCaptureDeviceTest::UpdateCallbackImpl,
base::Unretained(this))) {
- media_internals_->AddUpdateCallback(update_cb_);
+ media_internals()->AddUpdateCallback(update_cb_);
}
~MediaInternalsVideoCaptureDeviceTest() override {
- media_internals_->RemoveUpdateCallback(update_cb_);
+ media_internals()->RemoveUpdateCallback(update_cb_);
}
protected:
@@ -176,7 +194,7 @@ TEST_F(MediaInternalsVideoCaptureDeviceTest,
// a JSON array of objects to string. So here, the |UpdateCallbackImpl| will
// deserialize the first object in the array. This means we have to have
// exactly one device_info in the |descriptors_and_formats|.
- media_internals_->UpdateVideoCaptureDeviceCapabilities(
+ media_internals()->UpdateVideoCaptureDeviceCapabilities(
descriptors_and_formats);
#if defined(OS_LINUX)
@@ -208,13 +226,13 @@ class MediaInternalsAudioLogTest
base::Unretained(this))),
test_params_(MakeAudioParams()),
test_component_(GetParam()),
- audio_log_(media_internals_->CreateAudioLog(test_component_,
- kTestComponentID)) {
- media_internals_->AddUpdateCallback(update_cb_);
+ audio_log_(media_internals()->CreateAudioLog(test_component_,
+ kTestComponentID)) {
+ media_internals()->AddUpdateCallback(update_cb_);
}
virtual ~MediaInternalsAudioLogTest() {
- media_internals_->RemoveUpdateCallback(update_cb_);
+ media_internals()->RemoveUpdateCallback(update_cb_);
}
protected:
@@ -309,11 +327,14 @@ class MediaInternalsAudioFocusTest : public testing::Test,
base::BindRepeating(&MediaInternalsAudioFocusTest::UpdateCallbackImpl,
base::Unretained(this));
- scoped_command_line_.GetProcessCommandLine()->AppendSwitch(
- media_session::switches::kEnableAudioFocus);
+ browser_context_.reset(new TestBrowserContext());
+ run_loop_ = std::make_unique<base::RunLoop>();
+
+ content::ServiceManagerConnection::GetForProcess()
+ ->GetConnector()
+ ->BindInterface(media_session::mojom::kServiceName, &audio_focus_ptr_);
content::MediaInternals::GetInstance()->AddUpdateCallback(update_cb_);
- browser_context_.reset(new TestBrowserContext());
}
void TearDown() override {
@@ -322,10 +343,33 @@ class MediaInternalsAudioFocusTest : public testing::Test,
}
protected:
- void ExpectValue(base::ListValue expected_list) {
+ void UpdateCallbackImpl(const base::string16& update) override {
+ base::AutoLock auto_lock(lock_);
+ MediaInternalsTestBase::UpdateCallbackImpl(update);
+ call_count_++;
+
+ if (call_count_ == wanted_call_count_)
+ run_loop_->Quit();
+ }
+
+ void ExpectValueAndReset(base::ListValue expected_list) {
+ base::AutoLock auto_lock(lock_);
+
base::DictionaryValue expected_data;
expected_data.SetKey("sessions", std::move(expected_list));
EXPECT_EQ(expected_data, update_data_);
+
+ update_data_.Clear();
+ run_loop_ = std::make_unique<base::RunLoop>();
+ call_count_ = 0;
+ }
+
+ void Reset() {
+ base::AutoLock auto_lock(lock_);
+
+ update_data_.Clear();
+ run_loop_ = std::make_unique<base::RunLoop>();
+ call_count_ = 0;
}
std::unique_ptr<TestWebContents> CreateWebContents() {
@@ -343,16 +387,43 @@ class MediaInternalsAudioFocusTest : public testing::Test,
session->RemoveAllPlayersForTest();
}
- void WaitForCallback() {
- AudioFocusManager::GetInstance()->FlushForTesting();
- base::RunLoop().RunUntilIdle();
+ void WaitForCallbackCount(int count) {
+ wanted_call_count_ = count;
+
+ {
+ base::AutoLock auto_lock(lock_);
+ if (!update_data_.empty() && call_count_ == wanted_call_count_)
+ return;
+ }
+
+ run_loop_->Run();
+ }
+
+ std::string GetRequestIdForTopFocusRequest() {
+ std::string result;
+
+ audio_focus_ptr_->GetFocusRequests(base::BindOnce(
+ [](std::string* out, std::vector<AudioFocusRequestStatePtr> requests) {
+ DCHECK(!requests.empty());
+ *out = requests.back()->request_id.value().ToString();
+ },
+ &result));
+
+ audio_focus_ptr_.FlushForTesting();
+ return result;
}
MediaInternals::UpdateCallback update_cb_;
private:
- base::test::ScopedCommandLine scoped_command_line_;
+ int call_count_ = 0;
+ int wanted_call_count_ = 0;
+
+ base::Lock lock_;
+ std::unique_ptr<base::RunLoop> run_loop_;
std::unique_ptr<TestBrowserContext> browser_context_;
+
+ media_session::mojom::AudioFocusManagerPtr audio_focus_ptr_;
};
TEST_F(MediaInternalsAudioFocusTest, AudioFocusStateIsUpdated) {
@@ -361,18 +432,22 @@ TEST_F(MediaInternalsAudioFocusTest, AudioFocusStateIsUpdated) {
web_contents1->SetTitle(base::UTF8ToUTF16(kTestTitle1));
MediaSessionImpl* media_session1 = MediaSessionImpl::Get(web_contents1.get());
media_session1->RequestSystemAudioFocus(AudioFocusType::kGain);
- WaitForCallback();
+ WaitForCallbackCount(1);
+
+ // Get the |request_id| for the top session.
+ std::string request_id1 = GetRequestIdForTopFocusRequest();
// Check JSON is what we expect.
{
base::DictionaryValue expected_session;
+ expected_session.SetKey("id", base::Value(request_id1));
expected_session.SetKey("name", GetAddressAsValue(media_session1));
expected_session.SetKey("owner", base::Value(kTestTitle1));
expected_session.SetKey("state", base::Value("Active"));
base::ListValue expected_list;
expected_list.GetList().push_back(std::move(expected_session));
- ExpectValue(std::move(expected_list));
+ ExpectValueAndReset(std::move(expected_list));
}
// Create another media session.
@@ -381,16 +456,22 @@ TEST_F(MediaInternalsAudioFocusTest, AudioFocusStateIsUpdated) {
MediaSessionImpl* media_session2 = MediaSessionImpl::Get(web_contents2.get());
media_session2->RequestSystemAudioFocus(
AudioFocusType::kGainTransientMayDuck);
- WaitForCallback();
+ WaitForCallbackCount(2);
+
+ // Get the |request_id| for the top session.
+ std::string request_id2 = GetRequestIdForTopFocusRequest();
+ DCHECK_NE(request_id1, request_id2);
// Check JSON is what we expect.
{
base::DictionaryValue expected_session1;
+ expected_session1.SetKey("id", base::Value(request_id2));
expected_session1.SetKey("name", GetAddressAsValue(media_session2));
expected_session1.SetKey("owner", base::Value(kTestTitle2));
expected_session1.SetKey("state", base::Value("Active"));
base::DictionaryValue expected_session2;
+ expected_session2.SetKey("id", base::Value(request_id1));
expected_session2.SetKey("name", GetAddressAsValue(media_session1));
expected_session2.SetKey("owner", base::Value(kTestTitle1));
expected_session2.SetKey("state", base::Value("Active Ducked"));
@@ -398,33 +479,34 @@ TEST_F(MediaInternalsAudioFocusTest, AudioFocusStateIsUpdated) {
base::ListValue expected_list;
expected_list.GetList().push_back(std::move(expected_session1));
expected_list.GetList().push_back(std::move(expected_session2));
- ExpectValue(std::move(expected_list));
+ ExpectValueAndReset(std::move(expected_list));
}
// Abandon audio focus.
RemoveAllPlayersForTest(media_session2);
- WaitForCallback();
+ WaitForCallbackCount(1);
// Check JSON is what we expect.
{
base::DictionaryValue expected_session;
+ expected_session.SetKey("id", base::Value(request_id1));
expected_session.SetKey("name", GetAddressAsValue(media_session1));
expected_session.SetKey("owner", base::Value(kTestTitle1));
expected_session.SetKey("state", base::Value("Active"));
base::ListValue expected_list;
expected_list.GetList().push_back(std::move(expected_session));
- ExpectValue(std::move(expected_list));
+ ExpectValueAndReset(std::move(expected_list));
}
// Abandon audio focus.
RemoveAllPlayersForTest(media_session1);
- WaitForCallback();
+ WaitForCallbackCount(1);
// Check JSON is what we expect.
{
base::ListValue expected_list;
- ExpectValue(std::move(expected_list));
+ ExpectValueAndReset(std::move(expected_list));
}
}
diff --git a/chromium/content/browser/media/media_source_browsertest.cc b/chromium/content/browser/media/media_source_browsertest.cc
index c03bf22239e..593ae9b0215 100644
--- a/chromium/content/browser/media/media_source_browsertest.cc
+++ b/chromium/content/browser/media/media_source_browsertest.cc
@@ -3,7 +3,6 @@
// found in the LICENSE file.
#include "base/command_line.h"
-#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "content/browser/media/media_browsertest.h"
#include "media/base/media_switches.h"
@@ -37,7 +36,7 @@ const char kMp2tAudioVideo[] = "video/mp2t; codecs=\"mp4a.40.2, avc1.42E01E\"";
namespace content {
-class MediaSourceTest : public content::MediaBrowserTest {
+class MediaSourceTest : public MediaBrowserTest {
public:
void TestSimplePlayback(const std::string& media_file,
const std::string& media_type,
@@ -48,15 +47,6 @@ class MediaSourceTest : public content::MediaBrowserTest {
RunMediaTestPage("media_source_player.html", query_params, expectation,
false);
}
-
- void SetUpCommandLine(base::CommandLine* command_line) override {
- command_line->AppendSwitchASCII(
- switches::kAutoplayPolicy,
- switches::autoplay::kNoUserGestureRequiredPolicy);
- }
-
- protected:
- base::test::ScopedFeatureList scoped_feature_list_;
};
IN_PROC_BROWSER_TEST_F(MediaSourceTest, Playback_VideoAudio_WebM) {
diff --git a/chromium/content/browser/media/media_suspend_browsertest.cc b/chromium/content/browser/media/media_suspend_browsertest.cc
index d0059690e25..1cd1a66f57a 100644
--- a/chromium/content/browser/media/media_suspend_browsertest.cc
+++ b/chromium/content/browser/media/media_suspend_browsertest.cc
@@ -24,13 +24,13 @@ static void SuspendAllMediaPlayersInRenderFrame(RenderFrameHost* rfh) {
// and that players suspended in this way can be resumed. Note: This does not
// test suspend in various ready states; those tests are handled by layout tests
// for ease of writing and ready state manipulation.
-class MediaSuspendTest : public content::MediaBrowserTest {
+class MediaSuspendTest : public MediaBrowserTest {
public:
void RunSuspendTest(const std::string& load_until) {
base::StringPairs query_params;
query_params.emplace_back("event", load_until);
- GURL gurl = content::GetFileUrlWithQuery(
+ GURL gurl = GetFileUrlWithQuery(
media::GetTestDataFilePath("media_suspend_test.html"),
media::GetURLQueryString(query_params));
@@ -74,7 +74,7 @@ class MediaSuspendTest : public content::MediaBrowserTest {
protected:
void SetUpCommandLine(base::CommandLine* command_line) override {
- content::MediaBrowserTest::SetUpCommandLine(command_line);
+ MediaBrowserTest::SetUpCommandLine(command_line);
command_line->AppendSwitch(switches::kExposeInternalsForTesting);
}
};
diff --git a/chromium/content/browser/media/media_web_contents_observer.cc b/chromium/content/browser/media/media_web_contents_observer.cc
index c605c930a59..e636fcad80b 100644
--- a/chromium/content/browser/media/media_web_contents_observer.cc
+++ b/chromium/content/browser/media/media_web_contents_observer.cc
@@ -330,7 +330,8 @@ void MediaWebContentsObserver::OnPictureInPictureModeStarted(
int delegate_id,
const viz::SurfaceId& surface_id,
const gfx::Size& natural_size,
- int request_id) {
+ int request_id,
+ bool show_play_pause_button) {
DCHECK(surface_id.is_valid());
pip_player_ = MediaPlayerId(render_frame_host, delegate_id);
@@ -339,6 +340,11 @@ void MediaWebContentsObserver::OnPictureInPictureModeStarted(
gfx::Size window_size =
web_contents_impl()->EnterPictureInPicture(surface_id, natural_size);
+ if (auto* pip_controller =
+ PictureInPictureWindowControllerImpl::FromWebContents(
+ web_contents_impl()))
+ pip_controller->SetAlwaysHidePlayPauseButton(show_play_pause_button);
+
render_frame_host->Send(
new MediaPlayerDelegateMsg_OnPictureInPictureModeStarted_ACK(
render_frame_host->GetRoutingID(), delegate_id, request_id,
@@ -371,19 +377,20 @@ void MediaWebContentsObserver::OnPictureInPictureSurfaceChanged(
RenderFrameHost* render_frame_host,
int delegate_id,
const viz::SurfaceId& surface_id,
- const gfx::Size& natural_size) {
+ const gfx::Size& natural_size,
+ bool show_play_pause_button) {
DCHECK(surface_id.is_valid());
pip_player_ = MediaPlayerId(render_frame_host, delegate_id);
- PictureInPictureWindowControllerImpl* pip_controller =
- PictureInPictureWindowControllerImpl::FromWebContents(
- web_contents_impl());
-
// The PictureInPictureWindowController instance may not have been created by
// the embedder.
- if (pip_controller)
+ if (auto* pip_controller =
+ PictureInPictureWindowControllerImpl::FromWebContents(
+ web_contents_impl())) {
pip_controller->EmbedSurface(surface_id, natural_size);
+ pip_controller->SetAlwaysHidePlayPauseButton(show_play_pause_button);
+ }
}
void MediaWebContentsObserver::ClearWakeLocks(
diff --git a/chromium/content/browser/media/media_web_contents_observer.h b/chromium/content/browser/media/media_web_contents_observer.h
index febe37fe409..5994a563d4a 100644
--- a/chromium/content/browser/media/media_web_contents_observer.h
+++ b/chromium/content/browser/media/media_web_contents_observer.h
@@ -136,7 +136,8 @@ class CONTENT_EXPORT MediaWebContentsObserver : public WebContentsObserver {
int delegate_id,
const viz::SurfaceId&,
const gfx::Size& natural_size,
- int request_id);
+ int request_id,
+ bool show_play_pause_button);
void OnPictureInPictureModeEnded(RenderFrameHost* render_frame_host,
int delegate_id,
int request_id);
@@ -147,7 +148,8 @@ class CONTENT_EXPORT MediaWebContentsObserver : public WebContentsObserver {
void OnPictureInPictureSurfaceChanged(RenderFrameHost*,
int delegate_id,
const viz::SurfaceId&,
- const gfx::Size&);
+ const gfx::Size&,
+ bool show_play_pause_button);
// Clear |render_frame_host|'s tracking entry for its WakeLocks.
void ClearWakeLocks(RenderFrameHost* render_frame_host);
diff --git a/chromium/content/browser/media/midi_host_unittest.cc b/chromium/content/browser/media/midi_host_unittest.cc
index 869ea9701ae..88406488ab6 100644
--- a/chromium/content/browser/media/midi_host_unittest.cc
+++ b/chromium/content/browser/media/midi_host_unittest.cc
@@ -9,9 +9,9 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
+#include "base/test/scoped_task_environment.h"
#include "content/common/media/midi_messages.h"
#include "content/public/test/test_browser_thread.h"
#include "media/midi/midi_manager.h"
@@ -118,7 +118,8 @@ class MidiHostForTesting : public MidiHost {
class MidiHostTest : public testing::Test {
public:
MidiHostTest()
- : io_browser_thread_(BrowserThread::IO, &message_loop_),
+ : io_browser_thread_(BrowserThread::IO,
+ task_environment_.GetMainThreadTaskRunner()),
data_(kNoteOn, kNoteOn + arraysize(kNoteOn)),
port_id_(0) {
std::unique_ptr<FakeMidiManagerFactory> factory =
@@ -173,7 +174,7 @@ class MidiHostTest : public testing::Test {
}
private:
- base::MessageLoop message_loop_;
+ base::test::ScopedTaskEnvironment task_environment_;
TestBrowserThread io_browser_thread_;
std::vector<uint8_t> data_;
diff --git a/chromium/content/browser/media/session/audio_focus_delegate.h b/chromium/content/browser/media/session/audio_focus_delegate.h
index ba23f16f875..38eb74add84 100644
--- a/chromium/content/browser/media/session/audio_focus_delegate.h
+++ b/chromium/content/browser/media/session/audio_focus_delegate.h
@@ -5,13 +5,7 @@
#ifndef CONTENT_BROWSER_MEDIA_SESSION_AUDIO_FOCUS_DELEGATE_H_
#define CONTENT_BROWSER_MEDIA_SESSION_AUDIO_FOCUS_DELEGATE_H_
-#include "content/browser/media/session/audio_focus_manager.h"
-
-namespace media_session {
-namespace mojom {
-enum class AudioFocusType;
-} // namespace mojom
-} // namespace media_session
+#include "services/media_session/public/mojom/audio_focus.mojom.h"
namespace content {
@@ -27,12 +21,23 @@ class AudioFocusDelegate {
virtual ~AudioFocusDelegate() = default;
- virtual bool RequestAudioFocus(
+ enum class AudioFocusResult {
+ kSuccess,
+ kFailed,
+ kDelayed,
+ };
+
+ virtual AudioFocusResult RequestAudioFocus(
media_session::mojom::AudioFocusType audio_focus_type) = 0;
virtual void AbandonAudioFocus() = 0;
// Retrieves the current |AudioFocusType| for the associated |MediaSession|.
- virtual media_session::mojom::AudioFocusType GetCurrentFocusType() const = 0;
+ virtual base::Optional<media_session::mojom::AudioFocusType>
+ GetCurrentFocusType() const = 0;
+
+ // |MediaSession| should call this when it's state changes.
+ virtual void MediaSessionInfoChanged(
+ media_session::mojom::MediaSessionInfoPtr) = 0;
};
} // namespace content
diff --git a/chromium/content/browser/media/session/audio_focus_delegate_android.cc b/chromium/content/browser/media/session/audio_focus_delegate_android.cc
index 211aad42013..bb4e9cc7943 100644
--- a/chromium/content/browser/media/session/audio_focus_delegate_android.cc
+++ b/chromium/content/browser/media/session/audio_focus_delegate_android.cc
@@ -30,14 +30,17 @@ void AudioFocusDelegateAndroid::Initialize() {
Java_AudioFocusDelegate_create(env, reinterpret_cast<intptr_t>(this)));
}
-bool AudioFocusDelegateAndroid::RequestAudioFocus(
+AudioFocusDelegate::AudioFocusResult
+AudioFocusDelegateAndroid::RequestAudioFocus(
media_session::mojom::AudioFocusType audio_focus_type) {
JNIEnv* env = base::android::AttachCurrentThread();
DCHECK(env);
- return Java_AudioFocusDelegate_requestAudioFocus(
+ bool success = Java_AudioFocusDelegate_requestAudioFocus(
env, j_media_session_delegate_,
audio_focus_type ==
media_session::mojom::AudioFocusType::kGainTransientMayDuck);
+ return success ? AudioFocusDelegate::AudioFocusResult::kSuccess
+ : AudioFocusDelegate::AudioFocusResult::kFailed;
}
void AudioFocusDelegateAndroid::AbandonAudioFocus() {
@@ -46,7 +49,7 @@ void AudioFocusDelegateAndroid::AbandonAudioFocus() {
Java_AudioFocusDelegate_abandonAudioFocus(env, j_media_session_delegate_);
}
-media_session::mojom::AudioFocusType
+base::Optional<media_session::mojom::AudioFocusType>
AudioFocusDelegateAndroid::GetCurrentFocusType() const {
JNIEnv* env = base::android::AttachCurrentThread();
DCHECK(env);
@@ -61,7 +64,7 @@ void AudioFocusDelegateAndroid::OnSuspend(JNIEnv*,
if (!media_session_->IsActive())
return;
- media_session_->Suspend(MediaSession::SuspendType::SYSTEM);
+ media_session_->Suspend(MediaSession::SuspendType::kSystem);
}
void AudioFocusDelegateAndroid::OnResume(JNIEnv*,
@@ -69,7 +72,7 @@ void AudioFocusDelegateAndroid::OnResume(JNIEnv*,
if (!media_session_->IsSuspended())
return;
- media_session_->Resume(MediaSession::SuspendType::SYSTEM);
+ media_session_->Resume(MediaSession::SuspendType::kSystem);
}
void AudioFocusDelegateAndroid::OnStartDucking(JNIEnv*, jobject) {
diff --git a/chromium/content/browser/media/session/audio_focus_delegate_android.h b/chromium/content/browser/media/session/audio_focus_delegate_android.h
index 8c18679e42e..f4a3b13c9aa 100644
--- a/chromium/content/browser/media/session/audio_focus_delegate_android.h
+++ b/chromium/content/browser/media/session/audio_focus_delegate_android.h
@@ -27,10 +27,11 @@ class AudioFocusDelegateAndroid : public AudioFocusDelegate {
void Initialize();
- bool RequestAudioFocus(
+ AudioFocusResult RequestAudioFocus(
media_session::mojom::AudioFocusType audio_focus_type) override;
void AbandonAudioFocus() override;
- media_session::mojom::AudioFocusType GetCurrentFocusType() const override;
+ base::Optional<media_session::mojom::AudioFocusType> GetCurrentFocusType()
+ const override;
// Called when the Android system requests the MediaSession to be suspended.
// Called by Java through JNI.
@@ -53,6 +54,10 @@ class AudioFocusDelegateAndroid : public AudioFocusDelegate {
void RecordSessionDuck(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj);
+ // This is not used by this delegate.
+ void MediaSessionInfoChanged(
+ media_session::mojom::MediaSessionInfoPtr) override {}
+
private:
// Weak pointer because |this| is owned by |media_session_|.
MediaSessionImpl* media_session_;
diff --git a/chromium/content/browser/media/session/audio_focus_delegate_default.cc b/chromium/content/browser/media/session/audio_focus_delegate_default.cc
index eb7ec76aaf2..10fd87a95a5 100644
--- a/chromium/content/browser/media/session/audio_focus_delegate_default.cc
+++ b/chromium/content/browser/media/session/audio_focus_delegate_default.cc
@@ -4,9 +4,13 @@
#include "content/browser/media/session/audio_focus_delegate.h"
-#include "content/browser/media/session/audio_focus_manager.h"
+#include "content/browser/media/session/media_session_impl.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/common/service_manager_connection.h"
#include "services/media_session/public/cpp/switches.h"
#include "services/media_session/public/mojom/audio_focus.mojom.h"
+#include "services/media_session/public/mojom/constants.mojom.h"
+#include "services/service_manager/public/cpp/connector.h"
namespace content {
@@ -14,6 +18,8 @@ using media_session::mojom::AudioFocusType;
namespace {
+const char kAudioFocusSourceName[] = "web";
+
// AudioFocusDelegateDefault is the default implementation of
// AudioFocusDelegate which only handles audio focus between WebContents.
class AudioFocusDelegateDefault : public AudioFocusDelegate {
@@ -22,49 +28,134 @@ class AudioFocusDelegateDefault : public AudioFocusDelegate {
~AudioFocusDelegateDefault() override;
// AudioFocusDelegate implementation.
- bool RequestAudioFocus(AudioFocusType audio_focus_type) override;
+ AudioFocusResult RequestAudioFocus(AudioFocusType audio_focus_type) override;
void AbandonAudioFocus() override;
- AudioFocusType GetCurrentFocusType() const override;
+ base::Optional<media_session::mojom::AudioFocusType> GetCurrentFocusType()
+ const override;
+ void MediaSessionInfoChanged(
+ media_session::mojom::MediaSessionInfoPtr) override;
private:
+ // Finishes an async audio focus request.
+ void FinishAudioFocusRequest(AudioFocusType type);
+
+ // Ensures that |audio_focus_ptr_| is connected.
+ void EnsureServiceConnection();
+
+ // Holds the latest MediaSessionInfo for |media_session_|.
+ media_session::mojom::MediaSessionInfoPtr session_info_;
+
+ // Holds a pointer to the Media Session service.
+ media_session::mojom::AudioFocusManagerPtr audio_focus_ptr_;
+
+ // If the media session has acquired audio focus then this will contain a
+ // pointer to that requests AudioFocusRequestClient.
+ media_session::mojom::AudioFocusRequestClientPtr request_client_ptr_;
+
// Weak pointer because |this| is owned by |media_session_|.
MediaSessionImpl* media_session_;
// The last requested AudioFocusType by the associated |media_session_|.
- AudioFocusType audio_focus_type_if_disabled_;
+ base::Optional<AudioFocusType> audio_focus_type_;
};
} // anonymous namespace
AudioFocusDelegateDefault::AudioFocusDelegateDefault(
MediaSessionImpl* media_session)
- : media_session_(media_session) {}
+ : media_session_(media_session) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+}
AudioFocusDelegateDefault::~AudioFocusDelegateDefault() = default;
-bool AudioFocusDelegateDefault::RequestAudioFocus(
- AudioFocusType audio_focus_type) {
- audio_focus_type_if_disabled_ = audio_focus_type;
+AudioFocusDelegate::AudioFocusResult
+AudioFocusDelegateDefault::RequestAudioFocus(AudioFocusType audio_focus_type) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
- if (!media_session::IsAudioFocusEnabled())
- return true;
+ if (!media_session::IsAudioFocusEnabled()) {
+ audio_focus_type_ = audio_focus_type;
+ return AudioFocusDelegate::AudioFocusResult::kSuccess;
+ }
+
+ if (request_client_ptr_.is_bound()) {
+ // We have an existing request so we should request an updated focus type.
+ request_client_ptr_->RequestAudioFocus(
+ session_info_.Clone(), audio_focus_type,
+ base::BindOnce(&AudioFocusDelegateDefault::FinishAudioFocusRequest,
+ base::Unretained(this), audio_focus_type));
+ } else {
+ EnsureServiceConnection();
+
+ // Create a mojo interface pointer to our media session.
+ media_session::mojom::MediaSessionPtr media_session;
+ media_session_->BindToMojoRequest(mojo::MakeRequest(&media_session));
+
+ audio_focus_ptr_->RequestAudioFocus(
+ mojo::MakeRequest(&request_client_ptr_), std::move(media_session),
+ session_info_.Clone(), audio_focus_type,
+ base::BindOnce(&AudioFocusDelegateDefault::FinishAudioFocusRequest,
+ base::Unretained(this), audio_focus_type));
+ }
- AudioFocusManager::GetInstance()->RequestAudioFocus(media_session_,
- audio_focus_type);
- return true;
+ // Return delayed as we make the async call to request audio focus.
+ return AudioFocusDelegate::AudioFocusResult::kDelayed;
}
void AudioFocusDelegateDefault::AbandonAudioFocus() {
- AudioFocusManager::GetInstance()->AbandonAudioFocus(media_session_);
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ audio_focus_type_.reset();
+
+ if (!request_client_ptr_.is_bound())
+ return;
+
+ request_client_ptr_->AbandonAudioFocus();
+ request_client_ptr_.reset();
}
-AudioFocusType AudioFocusDelegateDefault::GetCurrentFocusType() const {
- if (media_session::IsAudioFocusEnabled()) {
- return AudioFocusManager::GetInstance()->GetFocusTypeForSession(
- media_session_);
- }
+base::Optional<media_session::mojom::AudioFocusType>
+AudioFocusDelegateDefault::GetCurrentFocusType() const {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ return audio_focus_type_;
+}
+
+void AudioFocusDelegateDefault::MediaSessionInfoChanged(
+ media_session::mojom::MediaSessionInfoPtr session_info) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ if (request_client_ptr_.is_bound())
+ request_client_ptr_->MediaSessionInfoChanged(session_info.Clone());
+
+ session_info_ = std::move(session_info);
+}
+
+void AudioFocusDelegateDefault::FinishAudioFocusRequest(AudioFocusType type) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(request_client_ptr_.is_bound());
+
+ audio_focus_type_ = type;
+ media_session_->FinishSystemAudioFocusRequest(type, true /* result */);
+}
+
+void AudioFocusDelegateDefault::EnsureServiceConnection() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ if (!media_session::IsAudioFocusEnabled())
+ return;
+
+ if (audio_focus_ptr_.is_bound() && !audio_focus_ptr_.encountered_error())
+ return;
+
+ audio_focus_ptr_.reset();
+
+ // Connect to the Media Session service and bind |audio_focus_ptr_| to it.
+ service_manager::Connector* connector =
+ ServiceManagerConnection::GetForProcess()->GetConnector();
+ connector->BindInterface(media_session::mojom::kServiceName,
+ mojo::MakeRequest(&audio_focus_ptr_));
- return audio_focus_type_if_disabled_;
+ audio_focus_ptr_->SetSourceName(kAudioFocusSourceName);
}
// static
diff --git a/chromium/content/browser/media/session/audio_focus_delegate_default_browsertest.cc b/chromium/content/browser/media/session/audio_focus_delegate_default_browsertest.cc
index 8d5e777f70a..97d63ea2ef2 100644
--- a/chromium/content/browser/media/session/audio_focus_delegate_default_browsertest.cc
+++ b/chromium/content/browser/media/session/audio_focus_delegate_default_browsertest.cc
@@ -5,45 +5,183 @@
#include "base/command_line.h"
#include "content/browser/media/session/media_session_impl.h"
#include "content/browser/media/session/mock_media_session_player_observer.h"
+#include "content/public/common/service_manager_connection.h"
#include "content/public/test/content_browser_test.h"
#include "content/shell/browser/shell.h"
#include "media/base/media_content_type.h"
#include "services/media_session/public/cpp/switches.h"
+#include "services/media_session/public/cpp/test/audio_focus_test_util.h"
+#include "services/media_session/public/mojom/audio_focus.mojom.h"
+#include "services/media_session/public/mojom/constants.mojom.h"
+#include "services/service_manager/public/cpp/connector.h"
namespace content {
+using media_session::test::TestAudioFocusObserver;
+
+namespace {
+
+const char kExpectedSourceName[] = "web";
+
+} // namespace
+
+class MediaSessionStateObserver
+ : public media_session::mojom::MediaSessionObserver {
+ public:
+ explicit MediaSessionStateObserver(
+ media_session::mojom::MediaSession* media_session)
+ : binding_(this) {
+ media_session::mojom::MediaSessionObserverPtr observer;
+ binding_.Bind(mojo::MakeRequest(&observer));
+ media_session->AddObserver(std::move(observer));
+ }
+
+ ~MediaSessionStateObserver() override = default;
+
+ // media_session::mojom::MediaSessionObserver
+ void MediaSessionInfoChanged(
+ media_session::mojom::MediaSessionInfoPtr session_info) override {
+ if (desired_state_.has_value() &&
+ desired_state_.value() == session_info->state) {
+ run_loop_.Quit();
+ return;
+ }
+
+ session_info_ = std::move(session_info);
+ }
+
+ void WaitForState(
+ media_session::mojom::MediaSessionInfo::SessionState state) {
+ if (session_info_ && state == session_info_->state)
+ return;
+
+ desired_state_ = state;
+ run_loop_.Run();
+ }
+
+ protected:
+ base::RunLoop run_loop_;
+ mojo::Binding<media_session::mojom::MediaSessionObserver> binding_;
+ base::Optional<media_session::mojom::MediaSessionInfo::SessionState>
+ desired_state_;
+ media_session::mojom::MediaSessionInfoPtr session_info_;
+
+ DISALLOW_COPY_AND_ASSIGN(MediaSessionStateObserver);
+};
+
class AudioFocusDelegateDefaultBrowserTest : public ContentBrowserTest {
protected:
+ void SetUpOnMainThread() override {
+ service_manager::Connector* connector =
+ ServiceManagerConnection::GetForProcess()->GetConnector();
+ connector->BindInterface(media_session::mojom::kServiceName,
+ mojo::MakeRequest(&audio_focus_ptr_));
+ }
+
void SetUpCommandLine(base::CommandLine* command_line) override {
command_line->AppendSwitch(media_session::switches::kEnableAudioFocus);
}
+ void CheckSessionSourceName() {
+ audio_focus_ptr_->GetFocusRequests(base::BindOnce(
+ [](std::vector<media_session::mojom::AudioFocusRequestStatePtr>
+ requests) {
+ for (auto& request : requests)
+ EXPECT_EQ(kExpectedSourceName, request->source_name.value());
+ }));
+
+ audio_focus_ptr_.FlushForTesting();
+ }
+
void Run(WebContents* start_contents, WebContents* interrupt_contents) {
std::unique_ptr<MockMediaSessionPlayerObserver>
player_observer(new MockMediaSessionPlayerObserver);
MediaSessionImpl* media_session = MediaSessionImpl::Get(start_contents);
- ASSERT_TRUE(media_session);
+ EXPECT_TRUE(media_session);
MediaSessionImpl* other_media_session =
MediaSessionImpl::Get(interrupt_contents);
- ASSERT_TRUE(other_media_session);
+ EXPECT_TRUE(other_media_session);
player_observer->StartNewPlayer();
- media_session->AddPlayer(player_observer.get(), 0,
- media::MediaContentType::Persistent);
- EXPECT_TRUE(media_session->IsActive());
- EXPECT_FALSE(other_media_session->IsActive());
+
+ {
+ std::unique_ptr<TestAudioFocusObserver> observer = CreateObserver();
+ media_session->AddPlayer(player_observer.get(), 0,
+ media::MediaContentType::Persistent);
+ observer->WaitForGainedEvent();
+ }
+
+ {
+ MediaSessionStateObserver state_observer(media_session);
+ state_observer.WaitForState(
+ media_session::mojom::MediaSessionInfo::SessionState::kActive);
+ }
+
+ {
+ MediaSessionStateObserver state_observer(other_media_session);
+ state_observer.WaitForState(
+ media_session::mojom::MediaSessionInfo::SessionState::kInactive);
+ }
+
+ CheckSessionSourceName();
player_observer->StartNewPlayer();
- other_media_session->AddPlayer(player_observer.get(), 1,
- media::MediaContentType::Persistent);
- EXPECT_FALSE(media_session->IsActive());
- EXPECT_TRUE(other_media_session->IsActive());
- media_session->Stop(MediaSessionImpl::SuspendType::UI);
- other_media_session->Stop(MediaSessionImpl::SuspendType::UI);
+ {
+ std::unique_ptr<TestAudioFocusObserver> observer = CreateObserver();
+ other_media_session->AddPlayer(player_observer.get(), 1,
+ media::MediaContentType::Persistent);
+ observer->WaitForGainedEvent();
+ }
+
+ {
+ MediaSessionStateObserver state_observer(media_session);
+ state_observer.WaitForState(
+ media_session::mojom::MediaSessionInfo::SessionState::kSuspended);
+ }
+
+ {
+ MediaSessionStateObserver state_observer(other_media_session);
+ state_observer.WaitForState(
+ media_session::mojom::MediaSessionInfo::SessionState::kActive);
+ }
+
+ CheckSessionSourceName();
+
+ {
+ std::unique_ptr<TestAudioFocusObserver> observer = CreateObserver();
+ media_session->Stop(MediaSessionImpl::SuspendType::kUI);
+ other_media_session->Stop(MediaSessionImpl::SuspendType::kUI);
+ observer->WaitForLostEvent();
+ }
+
+ {
+ MediaSessionStateObserver state_observer(media_session);
+ state_observer.WaitForState(
+ media_session::mojom::MediaSessionInfo::SessionState::kInactive);
+ }
+
+ {
+ MediaSessionStateObserver state_observer(other_media_session);
+ state_observer.WaitForState(
+ media_session::mojom::MediaSessionInfo::SessionState::kInactive);
+ }
+ }
+
+ private:
+ std::unique_ptr<TestAudioFocusObserver> CreateObserver() {
+ std::unique_ptr<TestAudioFocusObserver> observer =
+ std::make_unique<TestAudioFocusObserver>();
+ media_session::mojom::AudioFocusObserverPtr observer_ptr;
+ observer->BindToMojoRequest(mojo::MakeRequest(&observer_ptr));
+ audio_focus_ptr_->AddObserver(std::move(observer_ptr));
+ audio_focus_ptr_.FlushForTesting();
+ return observer;
}
+
+ media_session::mojom::AudioFocusManagerPtr audio_focus_ptr_;
};
// Two windows from the same BrowserContext.
diff --git a/chromium/content/browser/media/session/audio_focus_manager.cc b/chromium/content/browser/media/session/audio_focus_manager.cc
deleted file mode 100644
index fbd8af4da47..00000000000
--- a/chromium/content/browser/media/session/audio_focus_manager.cc
+++ /dev/null
@@ -1,173 +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/media/session/audio_focus_manager.h"
-
-#include "content/browser/media/session/audio_focus_observer.h"
-#include "content/browser/media/session/media_session_impl.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/web_contents.h"
-#include "mojo/public/cpp/bindings/interface_request.h"
-#include "services/media_session/public/mojom/audio_focus.mojom.h"
-
-namespace content {
-
-using media_session::mojom::AudioFocusType;
-
-namespace {
-
-media_session::mojom::MediaSessionPtr GetSessionMojoPtr(
- MediaSessionImpl* session) {
- media_session::mojom::MediaSessionPtr media_session_ptr;
- session->BindToMojoRequest(mojo::MakeRequest(&media_session_ptr));
- return media_session_ptr;
-}
-
-} // namespace
-
-// static
-AudioFocusManager* AudioFocusManager::GetInstance() {
- return base::Singleton<AudioFocusManager>::get();
-}
-
-void AudioFocusManager::RequestAudioFocus(MediaSessionImpl* media_session,
- AudioFocusType type) {
- if (!audio_focus_stack_.empty() &&
- audio_focus_stack_.back().media_session == media_session &&
- audio_focus_stack_.back().audio_focus_type == type &&
- audio_focus_stack_.back().media_session->IsActive()) {
- // Early returning if |media_session| is already on top (has focus) and is
- // active.
- return;
- }
-
- MaybeRemoveFocusEntry(media_session);
-
- // TODO(zqzhang): It seems like MediaSessionImpl is exposed to
- // AudioFocusManager
- // too much. Maybe it's better to do some abstraction and refactoring to clean
- // up the relation between AudioFocusManager and MediaSessionImpl.
- // See https://crbug.com/651069
- if (type == AudioFocusType::kGainTransientMayDuck) {
- for (auto& old_session : audio_focus_stack_) {
- old_session.media_session->StartDucking();
- }
- } else {
- for (auto& old_session : audio_focus_stack_) {
- if (old_session.media_session->IsActive()) {
- if (old_session.media_session->HasPepper())
- old_session.media_session->StartDucking();
- else
- old_session.media_session->Suspend(
- MediaSessionImpl::SuspendType::SYSTEM);
- }
- }
- }
-
- // Store the MediaSession and requested focus type.
- audio_focus_stack_.emplace_back(media_session, type);
- audio_focus_stack_.back().media_session->StopDucking();
-
- // Notify observers that we were gained audio focus.
- observers_.ForAllPtrs(
- [media_session,
- type](media_session::mojom::AudioFocusObserver* observer) {
- observer->OnFocusGained(GetSessionMojoPtr(media_session), type);
- });
-}
-
-void AudioFocusManager::AbandonAudioFocus(MediaSessionImpl* media_session) {
- if (audio_focus_stack_.empty())
- return;
-
- if (audio_focus_stack_.back().media_session != media_session) {
- MaybeRemoveFocusEntry(media_session);
- return;
- }
-
- audio_focus_stack_.pop_back();
- if (audio_focus_stack_.empty()) {
- // Notify observers that we lost audio focus.
- observers_.ForAllPtrs(
- [media_session](media_session::mojom::AudioFocusObserver* observer) {
- observer->OnFocusLost(GetSessionMojoPtr(media_session));
- });
- return;
- }
-
- // Allow the top-most MediaSessionImpl having Pepper to unduck pepper even if
- // it's
- // not active.
- for (auto iter = audio_focus_stack_.rbegin();
- iter != audio_focus_stack_.rend(); ++iter) {
- if (!iter->media_session->HasPepper())
- continue;
-
- MediaSessionImpl* pepper_session = iter->media_session;
- AudioFocusType focus_type = iter->audio_focus_type;
- pepper_session->StopDucking();
- MaybeRemoveFocusEntry(pepper_session);
- audio_focus_stack_.emplace_back(pepper_session, focus_type);
- return;
- }
- // Only try to unduck the new MediaSessionImpl on top. The session might be
- // still
- // inactive but it will not be resumed (so it doesn't surprise the user).
- audio_focus_stack_.back().media_session->StopDucking();
-
- // Notify observers that we lost audio focus.
- observers_.ForAllPtrs(
- [media_session](media_session::mojom::AudioFocusObserver* observer) {
- observer->OnFocusLost(GetSessionMojoPtr(media_session));
- });
-}
-
-mojo::InterfacePtrSetElementId AudioFocusManager::AddObserver(
- media_session::mojom::AudioFocusObserverPtr observer) {
- return observers_.AddPtr(std::move(observer));
-}
-
-AudioFocusType AudioFocusManager::GetFocusTypeForSession(
- MediaSessionImpl* media_session) const {
- for (auto row : audio_focus_stack_) {
- if (row.media_session == media_session)
- return row.audio_focus_type;
- }
-
- NOTREACHED();
- return AudioFocusType::kGain;
-}
-
-void AudioFocusManager::RemoveObserver(mojo::InterfacePtrSetElementId id) {
- observers_.RemovePtr(id);
-}
-
-void AudioFocusManager::ResetForTesting() {
- audio_focus_stack_.clear();
- observers_.CloseAll();
-}
-
-void AudioFocusManager::FlushForTesting() {
- observers_.FlushForTesting();
-}
-
-AudioFocusManager::AudioFocusManager() {
- // Make sure we start AudioFocusManager on the browser UI thread. This is to
- // ensure thread consistency for mojo::InterfaceSetPtr.
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
-}
-
-AudioFocusManager::~AudioFocusManager() = default;
-
-void AudioFocusManager::MaybeRemoveFocusEntry(MediaSessionImpl* media_session) {
- for (auto iter = audio_focus_stack_.begin(); iter != audio_focus_stack_.end();
- ++iter) {
- if (iter->media_session == media_session) {
- audio_focus_stack_.erase(iter);
- break;
- }
- }
-}
-
-} // namespace content
diff --git a/chromium/content/browser/media/session/audio_focus_manager.h b/chromium/content/browser/media/session/audio_focus_manager.h
deleted file mode 100644
index 3bc2cc78253..00000000000
--- a/chromium/content/browser/media/session/audio_focus_manager.h
+++ /dev/null
@@ -1,76 +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_MEDIA_SESSION_AUDIO_FOCUS_MANAGER_H_
-#define CONTENT_BROWSER_MEDIA_SESSION_AUDIO_FOCUS_MANAGER_H_
-
-#include <list>
-#include <unordered_map>
-
-#include "base/memory/singleton.h"
-#include "content/common/content_export.h"
-#include "content/public/browser/web_contents_observer.h"
-#include "mojo/public/cpp/bindings/interface_ptr_set.h"
-#include "services/media_session/public/mojom/audio_focus.mojom.h"
-
-namespace content {
-
-class MediaSessionImpl;
-
-class CONTENT_EXPORT AudioFocusManager {
- public:
- // Returns Chromium's internal AudioFocusManager.
- static AudioFocusManager* GetInstance();
-
- void RequestAudioFocus(MediaSessionImpl* media_session,
- media_session::mojom::AudioFocusType type);
-
- void AbandonAudioFocus(MediaSessionImpl* media_session);
-
- media_session::mojom::AudioFocusType GetFocusTypeForSession(
- MediaSessionImpl* media_session) const;
-
- // Adds/removes audio focus observers.
- mojo::InterfacePtrSetElementId AddObserver(
- media_session::mojom::AudioFocusObserverPtr);
- void RemoveObserver(mojo::InterfacePtrSetElementId);
-
- private:
- friend struct base::DefaultSingletonTraits<AudioFocusManager>;
- friend class AudioFocusManagerTest;
-
- // Media internals UI needs access to internal state.
- friend class MediaInternalsAudioFocusTest;
- friend class MediaInternals;
-
- // Flush for testing will flush any pending messages to the observers.
- void FlushForTesting();
-
- // Reset for testing will clear any built up internal state.
- void ResetForTesting();
-
- AudioFocusManager();
- ~AudioFocusManager();
-
- void MaybeRemoveFocusEntry(MediaSessionImpl* media_session);
-
- // Weak reference of managed observers. Observers are expected to remove
- // themselves before being destroyed.
- mojo::InterfacePtrSet<media_session::mojom::AudioFocusObserver> observers_;
-
- // Weak reference of managed MediaSessions and their requested focus type.
- // A MediaSession must abandon audio focus before its destruction.
- struct StackRow {
- StackRow(MediaSessionImpl* media_session,
- media_session::mojom::AudioFocusType audio_focus_type)
- : media_session(media_session), audio_focus_type(audio_focus_type) {}
- MediaSessionImpl* media_session;
- media_session::mojom::AudioFocusType audio_focus_type;
- };
- std::list<StackRow> audio_focus_stack_;
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_MEDIA_SESSION_AUDIO_FOCUS_MANAGER_H_
diff --git a/chromium/content/browser/media/session/audio_focus_manager_unittest.cc b/chromium/content/browser/media/session/audio_focus_manager_unittest.cc
deleted file mode 100644
index fc4a5974244..00000000000
--- a/chromium/content/browser/media/session/audio_focus_manager_unittest.cc
+++ /dev/null
@@ -1,550 +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/media/session/audio_focus_manager.h"
-
-#include <memory>
-
-#include "base/command_line.h"
-#include "base/optional.h"
-#include "base/run_loop.h"
-#include "content/browser/media/session/audio_focus_observer.h"
-#include "content/browser/media/session/media_session_impl.h"
-#include "content/browser/media/session/media_session_player_observer.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/test_web_contents.h"
-#include "media/base/media_content_type.h"
-#include "services/media_session/public/cpp/switches.h"
-#include "services/media_session/public/mojom/audio_focus.mojom.h"
-
-namespace content {
-
-using media_session::mojom::AudioFocusType;
-using media_session::mojom::MediaSessionPtr;
-
-namespace {
-
-class MockAudioFocusObserver : public AudioFocusObserver {
- public:
- MockAudioFocusObserver() { RegisterAudioFocusObserver(); }
-
- void OnFocusGained(MediaSessionPtr session, AudioFocusType type) override {
- EXPECT_TRUE(session.is_bound());
- focus_gained_call_ = type;
- focus_lost_call_ = false;
- }
-
- void OnFocusLost(MediaSessionPtr session) override {
- EXPECT_TRUE(session.is_bound());
- focus_lost_call_ = true;
- focus_gained_call_.reset();
- }
-
- base::Optional<AudioFocusType> focus_gained_call_;
- bool focus_lost_call_ = false;
-};
-
-class MockMediaSessionPlayerObserver : public MediaSessionPlayerObserver {
- public:
- void OnSuspend(int player_id) override {}
- void OnResume(int player_id) override {}
- void OnSeekForward(int player_id, base::TimeDelta seek_time) override {}
- void OnSeekBackward(int player_id, base::TimeDelta seek_time) override {}
- void OnSetVolumeMultiplier(
- int player_id, double volume_multiplier) override {}
- RenderFrameHost* render_frame_host() const override { return nullptr; }
-};
-
-} // anonymous namespace
-
-using SuspendType = MediaSession::SuspendType;
-
-class AudioFocusManagerTest : public testing::Test {
- public:
- AudioFocusManagerTest() = default;
-
- void SetUp() override {
- base::CommandLine::ForCurrentProcess()->AppendSwitch(
- media_session::switches::kEnableAudioFocus);
- rph_factory_.reset(new MockRenderProcessHostFactory());
- RenderProcessHostImpl::set_render_process_host_factory_for_testing(
- rph_factory_.get());
- browser_context_.reset(new TestBrowserContext());
- pepper_observer_.reset(new MockMediaSessionPlayerObserver());
-
- // AudioFocusManager is a singleton so we should make sure we reset any
- // state in between tests.
- AudioFocusManager::GetInstance()->ResetForTesting();
- }
-
- void TearDown() override {
- // Run pending tasks.
- base::RunLoop().RunUntilIdle();
-
- browser_context_.reset();
- RenderProcessHostImpl::set_render_process_host_factory_for_testing(nullptr);
- rph_factory_.reset();
- }
-
- MediaSessionImpl* GetAudioFocusedSession() const {
- const AudioFocusManager* manager = AudioFocusManager::GetInstance();
- const auto& audio_focus_stack = manager->audio_focus_stack_;
-
- for (auto iter = audio_focus_stack.rbegin();
- iter != audio_focus_stack.rend(); ++iter) {
- if ((*iter).audio_focus_type == AudioFocusType::kGain)
- return (*iter).media_session;
- }
- return nullptr;
- }
-
- int GetTransientMaybeDuckCount() const {
- const AudioFocusManager* manager = AudioFocusManager::GetInstance();
- const auto& audio_focus_stack = manager->audio_focus_stack_;
- int count = 0;
-
- for (auto iter = audio_focus_stack.rbegin();
- iter != audio_focus_stack.rend(); ++iter) {
- if ((*iter).audio_focus_type == AudioFocusType::kGainTransientMayDuck)
- ++count;
- else
- break;
- }
-
- return count;
- }
-
- double IsSessionDucking(MediaSessionImpl* session) {
- return session->is_ducking_; // Quack! Quack!
- }
-
- void RequestAudioFocus(MediaSessionImpl* session,
- AudioFocusType audio_focus_type) {
- session->RequestSystemAudioFocus(audio_focus_type);
- }
-
- void AbandonAudioFocus(MediaSessionImpl* session) {
- session->AbandonSystemAudioFocusIfNeeded();
- }
-
- void FlushForTesting() {
- AudioFocusManager::GetInstance()->FlushForTesting();
- }
-
- std::unique_ptr<WebContents> CreateWebContents() {
- return TestWebContents::Create(browser_context_.get(),
- SiteInstance::SiteInstance::Create(browser_context_.get()));
- }
-
- std::unique_ptr<MediaSessionPlayerObserver> pepper_observer_;
-
- private:
- TestBrowserThreadBundle test_browser_thread_bundle_;
-
- std::unique_ptr<MockRenderProcessHostFactory> rph_factory_;
- std::unique_ptr<TestBrowserContext> browser_context_;
-};
-
-TEST_F(AudioFocusManagerTest, InstanceAvailableAndSame) {
- AudioFocusManager* audio_focus_manager = AudioFocusManager::GetInstance();
- ASSERT_TRUE(!!audio_focus_manager);
- ASSERT_EQ(audio_focus_manager, AudioFocusManager::GetInstance());
-}
-
-TEST_F(AudioFocusManagerTest, RequestAudioFocusGain_ReplaceFocusedEntry) {
- std::unique_ptr<WebContents> web_contents_1(CreateWebContents());
- MediaSessionImpl* media_session_1 =
- MediaSessionImpl::Get(web_contents_1.get());
-
- std::unique_ptr<WebContents> web_contents_2(CreateWebContents());
- MediaSessionImpl* media_session_2 =
- MediaSessionImpl::Get(web_contents_2.get());
-
- std::unique_ptr<WebContents> web_contents_3(CreateWebContents());
- MediaSessionImpl* media_session_3 =
- MediaSessionImpl::Get(web_contents_3.get());
-
- ASSERT_EQ(nullptr, GetAudioFocusedSession());
-
- RequestAudioFocus(media_session_1, AudioFocusType::kGain);
- ASSERT_EQ(media_session_1, GetAudioFocusedSession());
-
- RequestAudioFocus(media_session_2, AudioFocusType::kGain);
- ASSERT_EQ(media_session_2, GetAudioFocusedSession());
-
- RequestAudioFocus(media_session_3, AudioFocusType::kGain);
- ASSERT_EQ(media_session_3, GetAudioFocusedSession());
-}
-
-TEST_F(AudioFocusManagerTest, RequestAudioFocusGain_Duplicate) {
- std::unique_ptr<WebContents> web_contents(CreateWebContents());
- MediaSessionImpl* media_session = MediaSessionImpl::Get(web_contents.get());
-
- ASSERT_EQ(nullptr, GetAudioFocusedSession());
-
- RequestAudioFocus(media_session, AudioFocusType::kGain);
- ASSERT_EQ(media_session, GetAudioFocusedSession());
-
- RequestAudioFocus(media_session, AudioFocusType::kGain);
- ASSERT_EQ(media_session, GetAudioFocusedSession());
-}
-
-TEST_F(AudioFocusManagerTest, RequestAudioFocusGain_FromTransient) {
- std::unique_ptr<WebContents> web_contents(CreateWebContents());
- MediaSessionImpl* media_session = MediaSessionImpl::Get(web_contents.get());
-
- RequestAudioFocus(media_session, AudioFocusType::kGainTransientMayDuck);
- ASSERT_EQ(nullptr, GetAudioFocusedSession());
- ASSERT_EQ(1, GetTransientMaybeDuckCount());
-
- RequestAudioFocus(media_session, AudioFocusType::kGain);
- ASSERT_EQ(media_session, GetAudioFocusedSession());
- ASSERT_EQ(0, GetTransientMaybeDuckCount());
-}
-
-TEST_F(AudioFocusManagerTest, RequestAudioFocusTransient_FromGain) {
- std::unique_ptr<WebContents> web_contents(CreateWebContents());
- MediaSessionImpl* media_session = MediaSessionImpl::Get(web_contents.get());
-
- RequestAudioFocus(media_session, AudioFocusType::kGain);
- ASSERT_EQ(media_session, GetAudioFocusedSession());
- ASSERT_EQ(0, GetTransientMaybeDuckCount());
-
- RequestAudioFocus(media_session, AudioFocusType::kGainTransientMayDuck);
- ASSERT_EQ(nullptr, GetAudioFocusedSession());
- ASSERT_EQ(1, GetTransientMaybeDuckCount());
- ASSERT_FALSE(IsSessionDucking(media_session));
-}
-
-TEST_F(AudioFocusManagerTest, RequestAudioFocusTransient_FromGainWhileDucking) {
- std::unique_ptr<WebContents> web_contents_1(CreateWebContents());
- MediaSessionImpl* media_session_1 =
- MediaSessionImpl::Get(web_contents_1.get());
-
- std::unique_ptr<WebContents> web_contents_2(CreateWebContents());
- MediaSessionImpl* media_session_2 =
- MediaSessionImpl::Get(web_contents_2.get());
-
- RequestAudioFocus(media_session_1, AudioFocusType::kGain);
- ASSERT_EQ(0, GetTransientMaybeDuckCount());
- ASSERT_FALSE(IsSessionDucking(media_session_1));
-
- RequestAudioFocus(media_session_2, AudioFocusType::kGainTransientMayDuck);
- ASSERT_EQ(1, GetTransientMaybeDuckCount());
- ASSERT_TRUE(IsSessionDucking(media_session_1));
-
- RequestAudioFocus(media_session_1, AudioFocusType::kGainTransientMayDuck);
- ASSERT_EQ(2, GetTransientMaybeDuckCount());
- ASSERT_FALSE(IsSessionDucking(media_session_1));
-}
-
-TEST_F(AudioFocusManagerTest, AbandonAudioFocus_RemovesFocusedEntry) {
- std::unique_ptr<WebContents> web_contents(CreateWebContents());
- MediaSessionImpl* media_session = MediaSessionImpl::Get(web_contents.get());
-
- RequestAudioFocus(media_session, AudioFocusType::kGain);
- ASSERT_EQ(media_session, GetAudioFocusedSession());
-
- AbandonAudioFocus(media_session);
- ASSERT_EQ(nullptr, GetAudioFocusedSession());
-}
-
-TEST_F(AudioFocusManagerTest, AbandonAudioFocus_NoAssociatedEntry) {
- std::unique_ptr<WebContents> web_contents(CreateWebContents());
- MediaSessionImpl* media_session = MediaSessionImpl::Get(web_contents.get());
-
- AbandonAudioFocus(media_session);
- ASSERT_EQ(nullptr, GetAudioFocusedSession());
-}
-
-TEST_F(AudioFocusManagerTest, AbandonAudioFocus_RemovesTransientEntry) {
- std::unique_ptr<WebContents> web_contents(CreateWebContents());
- MediaSessionImpl* media_session = MediaSessionImpl::Get(web_contents.get());
-
- RequestAudioFocus(media_session, AudioFocusType::kGainTransientMayDuck);
- ASSERT_EQ(1, GetTransientMaybeDuckCount());
-
- {
- MockAudioFocusObserver observer;
- AbandonAudioFocus(media_session);
- FlushForTesting();
-
- EXPECT_EQ(0, GetTransientMaybeDuckCount());
- EXPECT_TRUE(observer.focus_lost_call_);
- }
-}
-
-TEST_F(AudioFocusManagerTest, AbandonAudioFocus_WhileDuckingThenResume) {
- std::unique_ptr<WebContents> web_contents_1(CreateWebContents());
- MediaSessionImpl* media_session_1 =
- MediaSessionImpl::Get(web_contents_1.get());
-
- std::unique_ptr<WebContents> web_contents_2(CreateWebContents());
- MediaSessionImpl* media_session_2 =
- MediaSessionImpl::Get(web_contents_2.get());
-
- RequestAudioFocus(media_session_1, AudioFocusType::kGain);
- ASSERT_EQ(0, GetTransientMaybeDuckCount());
- ASSERT_FALSE(IsSessionDucking(media_session_1));
-
- RequestAudioFocus(media_session_2, AudioFocusType::kGainTransientMayDuck);
- ASSERT_EQ(1, GetTransientMaybeDuckCount());
- ASSERT_TRUE(IsSessionDucking(media_session_1));
-
- AbandonAudioFocus(media_session_1);
- ASSERT_EQ(1, GetTransientMaybeDuckCount());
-
- AbandonAudioFocus(media_session_2);
- ASSERT_EQ(0, GetTransientMaybeDuckCount());
-
- RequestAudioFocus(media_session_1, AudioFocusType::kGain);
- ASSERT_FALSE(IsSessionDucking(media_session_1));
-}
-
-TEST_F(AudioFocusManagerTest, AbandonAudioFocus_StopsDucking) {
- std::unique_ptr<WebContents> web_contents_1(CreateWebContents());
- MediaSessionImpl* media_session_1 =
- MediaSessionImpl::Get(web_contents_1.get());
-
- std::unique_ptr<WebContents> web_contents_2(CreateWebContents());
- MediaSessionImpl* media_session_2 =
- MediaSessionImpl::Get(web_contents_2.get());
-
- RequestAudioFocus(media_session_1, AudioFocusType::kGain);
- ASSERT_EQ(0, GetTransientMaybeDuckCount());
- ASSERT_FALSE(IsSessionDucking(media_session_1));
-
- RequestAudioFocus(media_session_2, AudioFocusType::kGainTransientMayDuck);
- ASSERT_EQ(1, GetTransientMaybeDuckCount());
- ASSERT_TRUE(IsSessionDucking(media_session_1));
-
- AbandonAudioFocus(media_session_2);
- ASSERT_EQ(0, GetTransientMaybeDuckCount());
- ASSERT_FALSE(IsSessionDucking(media_session_1));
-}
-
-TEST_F(AudioFocusManagerTest, DuckWhilePlaying) {
- std::unique_ptr<WebContents> web_contents_1(CreateWebContents());
- MediaSessionImpl* media_session_1 =
- MediaSessionImpl::Get(web_contents_1.get());
-
- std::unique_ptr<WebContents> web_contents_2(CreateWebContents());
- MediaSessionImpl* media_session_2 =
- MediaSessionImpl::Get(web_contents_2.get());
-
- RequestAudioFocus(media_session_1, AudioFocusType::kGain);
- ASSERT_FALSE(IsSessionDucking(media_session_1));
-
- RequestAudioFocus(media_session_2, AudioFocusType::kGainTransientMayDuck);
- ASSERT_TRUE(IsSessionDucking(media_session_1));
-}
-
-TEST_F(AudioFocusManagerTest, GainSuspendsTransient) {
- std::unique_ptr<WebContents> web_contents_1(CreateWebContents());
- MediaSessionImpl* media_session_1 =
- MediaSessionImpl::Get(web_contents_1.get());
-
- std::unique_ptr<WebContents> web_contents_2(CreateWebContents());
- MediaSessionImpl* media_session_2 =
- MediaSessionImpl::Get(web_contents_2.get());
-
- RequestAudioFocus(media_session_2, AudioFocusType::kGainTransientMayDuck);
-
- RequestAudioFocus(media_session_1, AudioFocusType::kGain);
- ASSERT_TRUE(media_session_2->IsSuspended());
-}
-
-TEST_F(AudioFocusManagerTest, DuckWithMultipleTransients) {
- std::unique_ptr<WebContents> web_contents_1(CreateWebContents());
- MediaSessionImpl* media_session_1 =
- MediaSessionImpl::Get(web_contents_1.get());
-
- std::unique_ptr<WebContents> web_contents_2(CreateWebContents());
- MediaSessionImpl* media_session_2 =
- MediaSessionImpl::Get(web_contents_2.get());
-
- std::unique_ptr<WebContents> web_contents_3(CreateWebContents());
- MediaSessionImpl* media_session_3 =
- MediaSessionImpl::Get(web_contents_3.get());
-
- RequestAudioFocus(media_session_1, AudioFocusType::kGain);
- ASSERT_FALSE(IsSessionDucking(media_session_1));
-
- RequestAudioFocus(media_session_2, AudioFocusType::kGainTransientMayDuck);
- ASSERT_TRUE(IsSessionDucking(media_session_1));
-
- RequestAudioFocus(media_session_3, AudioFocusType::kGainTransientMayDuck);
- ASSERT_TRUE(IsSessionDucking(media_session_1));
-
- AbandonAudioFocus(media_session_2);
- ASSERT_TRUE(IsSessionDucking(media_session_1));
-
- AbandonAudioFocus(media_session_3);
- ASSERT_FALSE(IsSessionDucking(media_session_1));
-}
-
-TEST_F(AudioFocusManagerTest, WebContentsDestroyed_ReleasesFocus) {
- std::unique_ptr<WebContents> web_contents(CreateWebContents());
- MediaSessionImpl* media_session = MediaSessionImpl::Get(web_contents.get());
-
- RequestAudioFocus(media_session, AudioFocusType::kGain);
- ASSERT_EQ(media_session, GetAudioFocusedSession());
-
- web_contents.reset();
- ASSERT_EQ(nullptr, GetAudioFocusedSession());
-}
-
-TEST_F(AudioFocusManagerTest, WebContentsDestroyed_ReleasesTransients) {
- std::unique_ptr<WebContents> web_contents(CreateWebContents());
- MediaSessionImpl* media_session = MediaSessionImpl::Get(web_contents.get());
-
- RequestAudioFocus(media_session, AudioFocusType::kGainTransientMayDuck);
- ASSERT_EQ(1, GetTransientMaybeDuckCount());
-
- web_contents.reset();
- ASSERT_EQ(0, GetTransientMaybeDuckCount());
-}
-
-TEST_F(AudioFocusManagerTest, WebContentsDestroyed_StopsDucking) {
- std::unique_ptr<WebContents> web_contents_1(CreateWebContents());
- MediaSessionImpl* media_session_1 =
- MediaSessionImpl::Get(web_contents_1.get());
-
- std::unique_ptr<WebContents> web_contents_2(CreateWebContents());
- MediaSessionImpl* media_session_2 =
- MediaSessionImpl::Get(web_contents_2.get());
-
- RequestAudioFocus(media_session_1, AudioFocusType::kGain);
- ASSERT_FALSE(IsSessionDucking(media_session_1));
-
- RequestAudioFocus(media_session_2, AudioFocusType::kGainTransientMayDuck);
- ASSERT_TRUE(IsSessionDucking(media_session_1));
-
- web_contents_2.reset();
- ASSERT_FALSE(IsSessionDucking(media_session_1));
-}
-
-TEST_F(AudioFocusManagerTest, PepperRequestsGainFocus) {
- std::unique_ptr<WebContents> web_contents(CreateWebContents());
- MediaSessionImpl* media_session = MediaSessionImpl::Get(web_contents.get());
-
- media_session->AddPlayer(
- pepper_observer_.get(), 0, media::MediaContentType::Pepper);
- ASSERT_EQ(media_session, GetAudioFocusedSession());
-
- media_session->RemovePlayer(pepper_observer_.get(), 0);
- ASSERT_EQ(nullptr, GetAudioFocusedSession());
-}
-
-TEST_F(AudioFocusManagerTest, GainDucksPepper) {
- std::unique_ptr<WebContents> web_contents_1(CreateWebContents());
- MediaSessionImpl* media_session_1 =
- MediaSessionImpl::Get(web_contents_1.get());
-
- std::unique_ptr<WebContents> web_contents_2(CreateWebContents());
- MediaSessionImpl* media_session_2 =
- MediaSessionImpl::Get(web_contents_2.get());
-
- media_session_1->AddPlayer(
- pepper_observer_.get(), 0, media::MediaContentType::Pepper);
-
- RequestAudioFocus(media_session_2, AudioFocusType::kGain);
-
- ASSERT_EQ(media_session_2, GetAudioFocusedSession());
- ASSERT_TRUE(media_session_1->IsActive());
- ASSERT_TRUE(IsSessionDucking(media_session_1));
-}
-
-TEST_F(AudioFocusManagerTest, AbandoningGainFocusRevokesTopMostPepperSession) {
- std::unique_ptr<WebContents> web_contents_1(CreateWebContents());
- MediaSessionImpl* media_session_1 =
- MediaSessionImpl::Get(web_contents_1.get());
-
- std::unique_ptr<WebContents> web_contents_2(CreateWebContents());
- MediaSessionImpl* media_session_2 =
- MediaSessionImpl::Get(web_contents_2.get());
-
- std::unique_ptr<WebContents> web_contents_3(CreateWebContents());
- MediaSessionImpl* media_session_3 =
- MediaSessionImpl::Get(web_contents_3.get());
-
- media_session_1->AddPlayer(
- pepper_observer_.get(), 0, media::MediaContentType::Pepper);
-
- RequestAudioFocus(media_session_2, AudioFocusType::kGain);
- RequestAudioFocus(media_session_3, AudioFocusType::kGain);
-
- ASSERT_EQ(media_session_3, GetAudioFocusedSession());
- ASSERT_TRUE(media_session_2->IsSuspended());
- ASSERT_TRUE(media_session_1->IsActive());
- ASSERT_TRUE(IsSessionDucking(media_session_1));
-
- AbandonAudioFocus(media_session_3);
- ASSERT_EQ(media_session_1, GetAudioFocusedSession());
-}
-
-TEST_F(AudioFocusManagerTest, AudioFocusObserver_AbandonNoop) {
- std::unique_ptr<WebContents> web_contents(CreateWebContents());
- MediaSessionImpl* media_session = MediaSessionImpl::Get(web_contents.get());
-
- {
- MockAudioFocusObserver observer;
- AbandonAudioFocus(media_session);
- FlushForTesting();
-
- EXPECT_EQ(nullptr, GetAudioFocusedSession());
- EXPECT_FALSE(observer.focus_lost_call_);
- }
-}
-
-TEST_F(AudioFocusManagerTest, AudioFocusObserver_RequestNoop) {
- std::unique_ptr<WebContents> web_contents(CreateWebContents());
- MediaSessionImpl* media_session = MediaSessionImpl::Get(web_contents.get());
-
- {
- MockAudioFocusObserver observer;
- RequestAudioFocus(media_session, AudioFocusType::kGain);
- FlushForTesting();
-
- EXPECT_EQ(media_session, GetAudioFocusedSession());
- EXPECT_EQ(AudioFocusType::kGain, observer.focus_gained_call_.value());
- }
-
- {
- MockAudioFocusObserver observer;
- RequestAudioFocus(media_session, AudioFocusType::kGain);
- FlushForTesting();
-
- EXPECT_EQ(media_session, GetAudioFocusedSession());
- EXPECT_FALSE(observer.focus_gained_call_.has_value());
- }
-}
-
-TEST_F(AudioFocusManagerTest, AudioFocusObserver_TransientMayDuck) {
- std::unique_ptr<WebContents> web_contents(CreateWebContents());
- MediaSessionImpl* media_session = MediaSessionImpl::Get(web_contents.get());
-
- {
- MockAudioFocusObserver observer;
- RequestAudioFocus(media_session, AudioFocusType::kGainTransientMayDuck);
- FlushForTesting();
-
- EXPECT_EQ(1, GetTransientMaybeDuckCount());
- EXPECT_EQ(AudioFocusType::kGainTransientMayDuck,
- observer.focus_gained_call_.value());
- }
-
- {
- MockAudioFocusObserver observer;
- AbandonAudioFocus(media_session);
- FlushForTesting();
-
- EXPECT_EQ(0, GetTransientMaybeDuckCount());
- EXPECT_TRUE(observer.focus_lost_call_);
- }
-}
-
-} // namespace content
diff --git a/chromium/content/browser/media/session/audio_focus_observer.cc b/chromium/content/browser/media/session/audio_focus_observer.cc
index b78c54c4b5f..33077b1109c 100644
--- a/chromium/content/browser/media/session/audio_focus_observer.cc
+++ b/chromium/content/browser/media/session/audio_focus_observer.cc
@@ -4,41 +4,52 @@
#include "content/browser/media/session/audio_focus_observer.h"
-#include "build/build_config.h"
-#include "content/browser/media/session/audio_focus_manager.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/common/service_manager_connection.h"
#include "mojo/public/cpp/bindings/interface_request.h"
+#include "services/media_session/public/mojom/constants.mojom.h"
+#include "services/service_manager/public/cpp/connector.h"
namespace content {
AudioFocusObserver::AudioFocusObserver() : binding_(this) {}
void AudioFocusObserver::RegisterAudioFocusObserver() {
- if (observer_id_.has_value())
+ ConnectToService();
+
+ if (!audio_focus_ptr_.is_bound() || audio_focus_ptr_.encountered_error())
+ return;
+
+ if (binding_.is_bound())
return;
-#if !defined(OS_ANDROID)
- // TODO(https://crbug.com/873320): Add support for Android.
DCHECK_CURRENTLY_ON(BrowserThread::UI);
media_session::mojom::AudioFocusObserverPtr observer;
binding_.Bind(mojo::MakeRequest(&observer));
- observer_id_ =
- AudioFocusManager::GetInstance()->AddObserver(std::move(observer));
-#endif
+ audio_focus_ptr_->AddObserver(std::move(observer));
}
void AudioFocusObserver::UnregisterAudioFocusObserver() {
- if (!observer_id_.has_value())
- return;
-
-#if !defined(OS_ANDROID)
- // TODO(https://crbug.com/873320): Add support for Android.
DCHECK_CURRENTLY_ON(BrowserThread::UI);
binding_.Close();
- AudioFocusManager::GetInstance()->RemoveObserver(observer_id_.value());
-#endif
+}
+
+void AudioFocusObserver::ConnectToService() {
+ if (audio_focus_ptr_.encountered_error())
+ audio_focus_ptr_.reset();
+
+ if (audio_focus_ptr_.is_bound())
+ return;
+
+ ServiceManagerConnection* connection =
+ ServiceManagerConnection::GetForProcess();
+
+ if (!connection)
+ return;
- observer_id_.reset();
+ service_manager::Connector* connector = connection->GetConnector();
+ connector->BindInterface(media_session::mojom::kServiceName,
+ mojo::MakeRequest(&audio_focus_ptr_));
}
AudioFocusObserver::~AudioFocusObserver() = default;
diff --git a/chromium/content/browser/media/session/audio_focus_observer.h b/chromium/content/browser/media/session/audio_focus_observer.h
index c4eae2b9f56..0e3f481d68c 100644
--- a/chromium/content/browser/media/session/audio_focus_observer.h
+++ b/chromium/content/browser/media/session/audio_focus_observer.h
@@ -6,10 +6,8 @@
#define CONTENT_BROWSER_MEDIA_SESSION_AUDIO_FOCUS_OBSERVER_H_
#include "base/macros.h"
-#include "base/optional.h"
#include "content/common/content_export.h"
#include "mojo/public/cpp/bindings/binding.h"
-#include "mojo/public/cpp/bindings/interface_ptr_set.h"
#include "services/media_session/public/mojom/audio_focus.mojom.h"
namespace content {
@@ -23,11 +21,11 @@ class CONTENT_EXPORT AudioFocusObserver
~AudioFocusObserver() override;
// The given media session gained audio focus with the specified type.
- void OnFocusGained(::media_session::mojom::MediaSessionPtr,
+ void OnFocusGained(::media_session::mojom::MediaSessionInfoPtr,
media_session::mojom::AudioFocusType) override {}
// The given media session lost audio focus.
- void OnFocusLost(::media_session::mojom::MediaSessionPtr) override {}
+ void OnFocusLost(::media_session::mojom::MediaSessionInfoPtr) override {}
protected:
// Called by subclasses to (un-)register the observer with AudioFocusManager.
@@ -35,7 +33,8 @@ class CONTENT_EXPORT AudioFocusObserver
void UnregisterAudioFocusObserver();
private:
- base::Optional<mojo::InterfacePtrSetElementId> observer_id_;
+ void ConnectToService();
+ media_session::mojom::AudioFocusManagerPtr audio_focus_ptr_;
mojo::Binding<media_session::mojom::AudioFocusObserver> binding_;
diff --git a/chromium/content/browser/media/session/media_session_android.cc b/chromium/content/browser/media/session/media_session_android.cc
index e110c52ea5e..d8505beca20 100644
--- a/chromium/content/browser/media/session/media_session_android.cc
+++ b/chromium/content/browser/media/session/media_session_android.cc
@@ -119,21 +119,21 @@ void MediaSessionAndroid::Resume(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& j_obj) {
DCHECK(media_session());
- media_session()->Resume(MediaSession::SuspendType::UI);
+ media_session()->Resume(MediaSession::SuspendType::kUI);
}
void MediaSessionAndroid::Suspend(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& j_obj) {
DCHECK(media_session());
- media_session()->Suspend(MediaSession::SuspendType::UI);
+ media_session()->Suspend(MediaSession::SuspendType::kUI);
}
void MediaSessionAndroid::Stop(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& j_obj) {
DCHECK(media_session());
- media_session()->Stop(MediaSession::SuspendType::UI);
+ media_session()->Stop(MediaSession::SuspendType::kUI);
}
void MediaSessionAndroid::SeekForward(
diff --git a/chromium/content/browser/media/session/media_session_browsertest.cc b/chromium/content/browser/media/session/media_session_browsertest.cc
index f89836e50a4..b6c4fcb1bb8 100644
--- a/chromium/content/browser/media/session/media_session_browsertest.cc
+++ b/chromium/content/browser/media/session/media_session_browsertest.cc
@@ -127,7 +127,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, MediaSessionNoOpWhenDisabled) {
StartPlaybackAndWait(shell(), "long-video");
StartPlaybackAndWait(shell(), "long-audio");
- media_session->Suspend(MediaSession::SuspendType::SYSTEM);
+ media_session->Suspend(MediaSession::SuspendType::kSystem);
StopPlaybackAndWait(shell(), "long-audio");
// At that point, only "long-audio" is paused.
@@ -146,11 +146,11 @@ IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, SimplePlayPause) {
StartPlaybackAndWait(shell(), "long-video");
- media_session->Suspend(MediaSession::SuspendType::SYSTEM);
+ media_session->Suspend(MediaSession::SuspendType::kSystem);
WaitForStop(shell());
EXPECT_FALSE(IsPlaying(shell(), "long-video"));
- media_session->Resume(MediaSession::SuspendType::SYSTEM);
+ media_session->Resume(MediaSession::SuspendType::kSystem);
WaitForStart(shell());
EXPECT_TRUE(IsPlaying(shell(), "long-video"));
}
@@ -166,12 +166,12 @@ IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, MultiplePlayersPlayPause) {
StartPlaybackAndWait(shell(), "long-video");
StartPlaybackAndWait(shell(), "long-audio");
- media_session->Suspend(MediaSession::SuspendType::SYSTEM);
+ media_session->Suspend(MediaSession::SuspendType::kSystem);
WaitForStop(shell());
EXPECT_FALSE(IsPlaying(shell(), "long-video"));
EXPECT_FALSE(IsPlaying(shell(), "long-audio"));
- media_session->Resume(MediaSession::SuspendType::SYSTEM);
+ media_session->Resume(MediaSession::SuspendType::kSystem);
WaitForStart(shell());
EXPECT_TRUE(IsPlaying(shell(), "long-video"));
EXPECT_TRUE(IsPlaying(shell(), "long-audio"));
@@ -217,22 +217,22 @@ IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, MultipleTabsPlayPause) {
StartPlaybackAndWait(shell(), "long-video");
StartPlaybackAndWait(other_shell, "long-video");
- media_session->Suspend(MediaSession::SuspendType::SYSTEM);
+ media_session->Suspend(MediaSession::SuspendType::kSystem);
WaitForStop(shell());
EXPECT_FALSE(IsPlaying(shell(), "long-video"));
EXPECT_TRUE(IsPlaying(other_shell, "long-video"));
- other_media_session->Suspend(MediaSession::SuspendType::SYSTEM);
+ other_media_session->Suspend(MediaSession::SuspendType::kSystem);
WaitForStop(other_shell);
EXPECT_FALSE(IsPlaying(shell(), "long-video"));
EXPECT_FALSE(IsPlaying(other_shell, "long-video"));
- media_session->Resume(MediaSession::SuspendType::SYSTEM);
+ media_session->Resume(MediaSession::SuspendType::kSystem);
WaitForStart(shell());
EXPECT_TRUE(IsPlaying(shell(), "long-video"));
EXPECT_FALSE(IsPlaying(other_shell, "long-video"));
- other_media_session->Resume(MediaSession::SuspendType::SYSTEM);
+ other_media_session->Resume(MediaSession::SuspendType::kSystem);
WaitForStart(other_shell);
EXPECT_TRUE(IsPlaying(shell(), "long-video"));
EXPECT_TRUE(IsPlaying(other_shell, "long-video"));
diff --git a/chromium/content/browser/media/session/media_session_controllers_manager_unittest.cc b/chromium/content/browser/media/session/media_session_controllers_manager_unittest.cc
index 0c8afb247db..9841b8ce7b0 100644
--- a/chromium/content/browser/media/session/media_session_controllers_manager_unittest.cc
+++ b/chromium/content/browser/media/session/media_session_controllers_manager_unittest.cc
@@ -7,6 +7,7 @@
#include "base/command_line.h"
#include "build/build_config.h"
#include "content/browser/media/session/media_session_controller.h"
+#include "content/public/test/test_service_manager_context.h"
#include "content/test/test_render_view_host.h"
#include "content/test/test_web_contents.h"
#include "media/base/media_content_type.h"
@@ -54,6 +55,8 @@ class MediaSessionControllersManagerTest
}
#endif
+ service_manager_context_ = std::make_unique<TestServiceManagerContext>();
+
media_player_id_ = MediaSessionControllersManager::MediaPlayerId(
contents()->GetMainFrame(), 1);
mock_media_session_controller_ =
@@ -86,6 +89,7 @@ class MediaSessionControllersManagerTest
void TearDown() override {
manager_.reset();
+ service_manager_context_.reset();
RenderViewHostImplTestHarness::TearDown();
}
@@ -98,6 +102,7 @@ class MediaSessionControllersManagerTest
StrictMock<MockMediaSessionController>* mock_media_session_controller_ptr_ =
nullptr;
std::unique_ptr<MediaSessionControllersManager> manager_;
+ std::unique_ptr<TestServiceManagerContext> service_manager_context_;
};
TEST_P(MediaSessionControllersManagerTest, RequestPlayAddsSessionsToMap) {
diff --git a/chromium/content/browser/media/session/media_session_impl.cc b/chromium/content/browser/media/session/media_session_impl.cc
index 15bab907e47..19cf17e9c0b 100644
--- a/chromium/content/browser/media/session/media_session_impl.cc
+++ b/chromium/content/browser/media/session/media_session_impl.cc
@@ -29,6 +29,7 @@
namespace content {
using MediaSessionUserAction = MediaSessionUmaHelper::MediaSessionUserAction;
+using media_session::mojom::MediaSessionInfo;
namespace {
@@ -43,6 +44,11 @@ const char kDebugInfoStateSeparator[] = " ";
using MapRenderFrameHostToDepth = std::map<RenderFrameHost*, size_t>;
+using media_session::mojom::AudioFocusType;
+
+using MediaSessionSuspendedSource =
+ MediaSessionUmaHelper::MediaSessionSuspendedSource;
+
size_t ComputeFrameDepth(RenderFrameHost* rfh,
MapRenderFrameHostToDepth* map_rfh_to_depth) {
DCHECK(rfh);
@@ -90,11 +96,6 @@ void MaybePushBackString(std::vector<std::string>& vector,
} // anonymous namespace
-using media_session::mojom::AudioFocusType;
-
-using MediaSessionSuspendedSource =
- MediaSessionUmaHelper::MediaSessionSuspendedSource;
-
MediaSessionImpl::PlayerIdentifier::PlayerIdentifier(
MediaSessionPlayerObserver* observer,
int player_id)
@@ -105,6 +106,12 @@ bool MediaSessionImpl::PlayerIdentifier::operator==(
return this->observer == other.observer && this->player_id == other.player_id;
}
+bool MediaSessionImpl::PlayerIdentifier::operator<(
+ const PlayerIdentifier& other) const {
+ return MediaSessionImpl::PlayerIdentifier::Hash()(*this) <
+ MediaSessionImpl::PlayerIdentifier::Hash()(other);
+}
+
size_t MediaSessionImpl::PlayerIdentifier::Hash::operator()(
const PlayerIdentifier& player_identifier) const {
size_t hash = BASE_HASH_NAMESPACE::hash<MediaSessionPlayerObserver*>()(
@@ -151,6 +158,7 @@ void MediaSessionImpl::WebContentsDestroyed() {
normal_players_.clear();
pepper_players_.clear();
one_shot_players_.clear();
+
AbandonSystemAudioFocusIfNeeded();
}
@@ -217,19 +225,27 @@ bool MediaSessionImpl::AddPlayer(MediaSessionPlayerObserver* observer,
else
required_audio_focus_type = AudioFocusType::kGainTransientMayDuck;
+ PlayerIdentifier key(observer, player_id);
+
// If the audio focus is already granted and is of type Content, there is
// nothing to do. If it is granted of type Transient the requested type is
// also transient, there is also nothing to do. Otherwise, the session needs
// to request audio focus again.
if (audio_focus_state_ == State::ACTIVE) {
- AudioFocusType current_focus_type = delegate_->GetCurrentFocusType();
+ base::Optional<AudioFocusType> current_focus_type =
+ delegate_->GetCurrentFocusType();
if (current_focus_type == AudioFocusType::kGain ||
current_focus_type == required_audio_focus_type) {
- normal_players_.insert(PlayerIdentifier(observer, player_id));
+ auto iter = normal_players_.find(key);
+ if (iter == normal_players_.end())
+ normal_players_.emplace(std::move(key), required_audio_focus_type);
+ else
+ iter->second = required_audio_focus_type;
return true;
}
}
+ bool old_controllable = IsControllable();
State old_audio_focus_state = audio_focus_state_;
RequestSystemAudioFocus(required_audio_focus_type);
@@ -241,10 +257,19 @@ bool MediaSessionImpl::AddPlayer(MediaSessionPlayerObserver* observer,
if (old_audio_focus_state != State::ACTIVE)
normal_players_.clear();
- normal_players_.insert(PlayerIdentifier(observer, player_id));
+ auto iter = normal_players_.find(key);
+ if (iter == normal_players_.end())
+ normal_players_.emplace(std::move(key), required_audio_focus_type);
+ else
+ iter->second = required_audio_focus_type;
UpdateRoutedService();
- NotifyAboutStateChange();
+
+ if (old_audio_focus_state != audio_focus_state_ ||
+ old_controllable != IsControllable()) {
+ NotifyAboutStateChange();
+ }
+
return true;
}
@@ -254,11 +279,11 @@ void MediaSessionImpl::RemovePlayer(MediaSessionPlayerObserver* observer,
PlayerIdentifier identifier(observer, player_id);
- auto it = normal_players_.find(identifier);
- if (it != normal_players_.end())
- normal_players_.erase(it);
+ auto iter = normal_players_.find(identifier);
+ if (iter != normal_players_.end())
+ normal_players_.erase(iter);
- it = pepper_players_.find(identifier);
+ auto it = pepper_players_.find(identifier);
if (it != pepper_players_.end())
pepper_players_.erase(it);
@@ -280,7 +305,7 @@ void MediaSessionImpl::RemovePlayers(MediaSessionPlayerObserver* observer) {
bool was_controllable = IsControllable();
for (auto it = normal_players_.begin(); it != normal_players_.end();) {
- if (it->observer == observer)
+ if (it->first.observer == observer)
normal_players_.erase(it++);
else
++it;
@@ -345,27 +370,30 @@ void MediaSessionImpl::OnPlayerPaused(MediaSessionPlayerObserver* observer,
// Otherwise, suspend the session.
DCHECK(IsActive());
- OnSuspendInternal(SuspendType::CONTENT, State::SUSPENDED);
+ OnSuspendInternal(SuspendType::kContent, State::SUSPENDED);
}
void MediaSessionImpl::Resume(SuspendType suspend_type) {
if (!IsSuspended())
return;
- if (suspend_type == SuspendType::UI) {
+ if (suspend_type == SuspendType::kUI) {
MediaSessionUmaHelper::RecordMediaSessionUserAction(
MediaSessionUmaHelper::MediaSessionUserAction::PlayDefault);
}
// When the resume requests comes from another source than system, audio focus
// must be requested.
- if (suspend_type != SuspendType::SYSTEM) {
+ if (suspend_type != SuspendType::kSystem) {
// Request audio focus again in case we lost it because another app started
- // playing while the playback was paused.
- State audio_focus_state = RequestSystemAudioFocus(desired_audio_focus_type_)
- ? State::ACTIVE
- : State::INACTIVE;
- SetAudioFocusState(audio_focus_state);
+ // playing while the playback was paused. If the audio focus request is
+ // delayed we will resume the player when the request completes.
+ AudioFocusDelegate::AudioFocusResult result =
+ RequestSystemAudioFocus(desired_audio_focus_type_);
+
+ SetAudioFocusState(result != AudioFocusDelegate::AudioFocusResult::kFailed
+ ? State::ACTIVE
+ : State::INACTIVE);
if (audio_focus_state_ != State::ACTIVE)
return;
@@ -378,7 +406,7 @@ void MediaSessionImpl::Suspend(SuspendType suspend_type) {
if (!IsActive())
return;
- if (suspend_type == SuspendType::UI) {
+ if (suspend_type == SuspendType::kUI) {
MediaSessionUmaHelper::RecordMediaSessionUserAction(
MediaSessionUserAction::PauseDefault);
}
@@ -388,16 +416,16 @@ void MediaSessionImpl::Suspend(SuspendType suspend_type) {
void MediaSessionImpl::Stop(SuspendType suspend_type) {
DCHECK(audio_focus_state_ != State::INACTIVE);
- DCHECK(suspend_type != SuspendType::CONTENT);
+ DCHECK(suspend_type != SuspendType::kContent);
DCHECK(!HasPepper());
- if (suspend_type == SuspendType::UI) {
+ if (suspend_type == SuspendType::kUI) {
MediaSessionUmaHelper::RecordMediaSessionUserAction(
MediaSessionUmaHelper::MediaSessionUserAction::StopDefault);
}
// TODO(mlamouri): merge the logic between UI and SYSTEM.
- if (suspend_type == SuspendType::SYSTEM) {
+ if (suspend_type == SuspendType::kSystem) {
OnSuspendInternal(suspend_type, State::INACTIVE);
return;
}
@@ -413,12 +441,12 @@ void MediaSessionImpl::Stop(SuspendType suspend_type) {
void MediaSessionImpl::SeekForward(base::TimeDelta seek_time) {
for (const auto& it : normal_players_)
- it.observer->OnSeekForward(it.player_id, seek_time);
+ it.first.observer->OnSeekForward(it.first.player_id, seek_time);
}
void MediaSessionImpl::SeekBackward(base::TimeDelta seek_time) {
for (const auto& it : normal_players_)
- it.observer->OnSeekBackward(it.player_id, seek_time);
+ it.first.observer->OnSeekBackward(it.first.player_id, seek_time);
}
bool MediaSessionImpl::IsControllable() const {
@@ -448,6 +476,7 @@ void MediaSessionImpl::StartDucking() {
return;
is_ducking_ = true;
UpdateVolumeMultiplier();
+ NotifyObserversInfoChanged();
}
void MediaSessionImpl::StopDucking() {
@@ -455,11 +484,15 @@ void MediaSessionImpl::StopDucking() {
return;
is_ducking_ = false;
UpdateVolumeMultiplier();
+ NotifyObserversInfoChanged();
}
void MediaSessionImpl::UpdateVolumeMultiplier() {
- for (const auto& it : normal_players_)
- it.observer->OnSetVolumeMultiplier(it.player_id, GetVolumeMultiplier());
+ for (const auto& it : normal_players_) {
+ it.first.observer->OnSetVolumeMultiplier(it.first.player_id,
+ GetVolumeMultiplier());
+ }
+
for (const auto& it : pepper_players_)
it.observer->OnSetVolumeMultiplier(it.player_id, GetVolumeMultiplier());
}
@@ -502,13 +535,19 @@ void MediaSessionImpl::RemoveAllPlayersForTest() {
AbandonSystemAudioFocusIfNeeded();
}
+void MediaSessionImpl::OnSystemAudioFocusRequested(bool result) {
+ uma_helper_.RecordRequestAudioFocusResult(result);
+ if (result)
+ StopDucking();
+}
+
void MediaSessionImpl::OnSuspendInternal(SuspendType suspend_type,
State new_state) {
DCHECK(!HasPepper());
DCHECK(new_state == State::SUSPENDED || new_state == State::INACTIVE);
// UI suspend cannot use State::INACTIVE.
- DCHECK(suspend_type == SuspendType::SYSTEM || new_state == State::SUSPENDED);
+ DCHECK(suspend_type == SuspendType::kSystem || new_state == State::SUSPENDED);
if (!one_shot_players_.empty())
return;
@@ -517,10 +556,10 @@ void MediaSessionImpl::OnSuspendInternal(SuspendType suspend_type,
return;
switch (suspend_type) {
- case SuspendType::UI:
+ case SuspendType::kUI:
uma_helper_.RecordSessionSuspended(MediaSessionSuspendedSource::UI);
break;
- case SuspendType::SYSTEM:
+ case SuspendType::kSystem:
switch (new_state) {
case State::SUSPENDED:
uma_helper_.RecordSessionSuspended(
@@ -535,7 +574,7 @@ void MediaSessionImpl::OnSuspendInternal(SuspendType suspend_type,
break;
}
break;
- case SuspendType::CONTENT:
+ case SuspendType::kContent:
uma_helper_.RecordSessionSuspended(MediaSessionSuspendedSource::CONTENT);
break;
}
@@ -543,12 +582,12 @@ void MediaSessionImpl::OnSuspendInternal(SuspendType suspend_type,
SetAudioFocusState(new_state);
suspend_type_ = suspend_type;
- if (suspend_type != SuspendType::CONTENT) {
+ if (suspend_type != SuspendType::kContent) {
// SuspendType::CONTENT happens when the suspend action came from
// the page in which case the player is already paused.
// Otherwise, the players need to be paused.
for (const auto& it : normal_players_)
- it.observer->OnSuspend(it.player_id);
+ it.first.observer->OnSuspend(it.first.player_id);
}
for (const auto& it : pepper_players_)
@@ -559,13 +598,13 @@ void MediaSessionImpl::OnSuspendInternal(SuspendType suspend_type,
}
void MediaSessionImpl::OnResumeInternal(SuspendType suspend_type) {
- if (suspend_type == SuspendType::SYSTEM && suspend_type_ != suspend_type)
+ if (suspend_type == SuspendType::kSystem && suspend_type_ != suspend_type)
return;
SetAudioFocusState(State::ACTIVE);
for (const auto& it : normal_players_)
- it.observer->OnResume(it.player_id);
+ it.first.observer->OnResume(it.first.player_id);
for (const auto& it : pepper_players_)
it.observer->OnSetVolumeMultiplier(it.player_id, GetVolumeMultiplier());
@@ -587,31 +626,44 @@ MediaSessionImpl::MediaSessionImpl(WebContents* web_contents)
void MediaSessionImpl::Initialize() {
delegate_ = AudioFocusDelegate::Create(this);
+ delegate_->MediaSessionInfoChanged(GetMediaSessionInfoSync());
}
-bool MediaSessionImpl::RequestSystemAudioFocus(
+AudioFocusDelegate::AudioFocusResult MediaSessionImpl::RequestSystemAudioFocus(
AudioFocusType audio_focus_type) {
- bool result = delegate_->RequestAudioFocus(audio_focus_type);
- uma_helper_.RecordRequestAudioFocusResult(result);
-
- // Make sure we are unducked.
- if (result)
- StopDucking();
+ // |kGainTransient| is not used in MediaSessionImpl.
+ DCHECK_NE(media_session::mojom::AudioFocusType::kGainTransient,
+ audio_focus_type);
- // MediaSessionImpl must change its state & audio focus type AFTER requesting
- // audio focus.
- SetAudioFocusState(result ? State::ACTIVE : State::INACTIVE);
+ AudioFocusDelegate::AudioFocusResult result =
+ delegate_->RequestAudioFocus(audio_focus_type);
desired_audio_focus_type_ = audio_focus_type;
+
+ bool success = result != AudioFocusDelegate::AudioFocusResult::kFailed;
+ SetAudioFocusState(success ? State::ACTIVE : State::INACTIVE);
+
+ // If we are delayed then we should return now and wait for the response from
+ // the audio focus delegate.
+ if (result == AudioFocusDelegate::AudioFocusResult::kDelayed)
+ return result;
+
+ OnSystemAudioFocusRequested(success);
return result;
}
-const MediaSessionImpl::DebugInfo MediaSessionImpl::GetDebugInfo() {
- MediaSessionImpl::DebugInfo debug_info;
+void MediaSessionImpl::BindToMojoRequest(
+ mojo::InterfaceRequest<media_session::mojom::MediaSession> request) {
+ bindings_.AddBinding(this, std::move(request));
+}
+
+void MediaSessionImpl::GetDebugInfo(GetDebugInfoCallback callback) {
+ media_session::mojom::MediaSessionDebugInfoPtr info(
+ media_session::mojom::MediaSessionDebugInfo::New());
// Convert the address of |this| to a string and use it as the name.
std::stringstream stream;
stream << this;
- debug_info.name = stream.str();
+ info->name = stream.str();
// Add the title and the url to the owner.
std::vector<std::string> owner_parts;
@@ -619,21 +671,88 @@ const MediaSessionImpl::DebugInfo MediaSessionImpl::GetDebugInfo() {
base::UTF16ToUTF8(web_contents()->GetTitle()));
MaybePushBackString(owner_parts,
web_contents()->GetLastCommittedURL().spec());
- debug_info.owner = base::JoinString(owner_parts, kDebugInfoOwnerSeparator);
+ info->owner = base::JoinString(owner_parts, kDebugInfoOwnerSeparator);
// Add the ducking state to state.
std::vector<std::string> state_parts;
MaybePushBackString(state_parts,
IsActive() ? kDebugInfoActive : kDebugInfoInactive);
MaybePushBackString(state_parts, is_ducking_ ? kDebugInfoDucked : "");
- debug_info.state = base::JoinString(state_parts, kDebugInfoStateSeparator);
+ info->state = base::JoinString(state_parts, kDebugInfoStateSeparator);
- return debug_info;
+ std::move(callback).Run(std::move(info));
}
-void MediaSessionImpl::BindToMojoRequest(
- mojo::InterfaceRequest<media_session::mojom::MediaSession> request) {
- bindings_.AddBinding(this, std::move(request));
+media_session::mojom::MediaSessionInfoPtr
+MediaSessionImpl::GetMediaSessionInfoSync() {
+ media_session::mojom::MediaSessionInfoPtr info(
+ media_session::mojom::MediaSessionInfo::New());
+
+ switch (audio_focus_state_) {
+ case State::ACTIVE:
+ info->state = MediaSessionInfo::SessionState::kActive;
+ break;
+ case State::SUSPENDED:
+ info->state = MediaSessionInfo::SessionState::kSuspended;
+ break;
+ case State::INACTIVE:
+ info->state = MediaSessionInfo::SessionState::kInactive;
+ break;
+ }
+
+ // The state should always be kDucked if we are ducked.
+ if (is_ducking_)
+ info->state = MediaSessionInfo::SessionState::kDucking;
+
+ // If we have Pepper players then we should force ducking.
+ info->force_duck = HasPepper();
+ return info;
+}
+
+void MediaSessionImpl::GetMediaSessionInfo(
+ GetMediaSessionInfoCallback callback) {
+ std::move(callback).Run(GetMediaSessionInfoSync());
+}
+
+void MediaSessionImpl::AddObserver(
+ media_session::mojom::MediaSessionObserverPtr observer) {
+ observer->MediaSessionInfoChanged(GetMediaSessionInfoSync());
+ mojo_observers_.AddPtr(std::move(observer));
+}
+
+void MediaSessionImpl::FinishSystemAudioFocusRequest(
+ AudioFocusType audio_focus_type,
+ bool result) {
+ // If the media session is not active then we do not need to enforce the
+ // result of the audio focus request.
+ if (audio_focus_state_ != State::ACTIVE) {
+ AbandonSystemAudioFocusIfNeeded();
+ return;
+ }
+
+ OnSystemAudioFocusRequested(result);
+
+ if (!result) {
+ switch (audio_focus_type) {
+ case AudioFocusType::kGain:
+ // If the gain audio focus request failed then we should suspend the
+ // media session.
+ OnSuspendInternal(SuspendType::kSystem, State::SUSPENDED);
+ break;
+ case AudioFocusType::kGainTransient:
+ // MediaSessionImpl does not use |kGainTransient|.
+ NOTREACHED();
+ break;
+ case AudioFocusType::kGainTransientMayDuck:
+ // The focus request failed, we should suspend any players that have
+ // the same audio focus type.
+ for (auto& player : normal_players_) {
+ if (audio_focus_type == player.second)
+ player.first.observer->OnSuspend(player.first.player_id);
+ }
+ break;
+ }
+ }
}
void MediaSessionImpl::AbandonSystemAudioFocusIfNeeded() {
@@ -672,24 +791,46 @@ void MediaSessionImpl::SetAudioFocusState(State audio_focus_state) {
uma_helper_.OnSessionInactive();
break;
}
+
+ NotifyObserversInfoChanged();
+}
+
+void MediaSessionImpl::FlushForTesting() {
+ mojo_observers_.FlushForTesting();
+}
+
+void MediaSessionImpl::NotifyObserversInfoChanged() {
+ media_session::mojom::MediaSessionInfoPtr current_info =
+ GetMediaSessionInfoSync();
+
+ mojo_observers_.ForAllPtrs(
+ [&current_info](media_session::mojom::MediaSessionObserver* observer) {
+ observer->MediaSessionInfoChanged(current_info.Clone());
+ });
+
+ delegate_->MediaSessionInfoChanged(current_info.Clone());
}
bool MediaSessionImpl::AddPepperPlayer(MediaSessionPlayerObserver* observer,
int player_id) {
- bool success = RequestSystemAudioFocus(AudioFocusType::kGain);
- DCHECK(success);
+ AudioFocusDelegate::AudioFocusResult result =
+ RequestSystemAudioFocus(AudioFocusType::kGain);
+ DCHECK_NE(AudioFocusDelegate::AudioFocusResult::kFailed, result);
pepper_players_.insert(PlayerIdentifier(observer, player_id));
observer->OnSetVolumeMultiplier(player_id, GetVolumeMultiplier());
NotifyAboutStateChange();
- return success;
+ return result != AudioFocusDelegate::AudioFocusResult::kFailed;
}
bool MediaSessionImpl::AddOneShotPlayer(MediaSessionPlayerObserver* observer,
int player_id) {
- if (!RequestSystemAudioFocus(AudioFocusType::kGain))
+ AudioFocusDelegate::AudioFocusResult result =
+ RequestSystemAudioFocus(AudioFocusType::kGain);
+
+ if (result == AudioFocusDelegate::AudioFocusResult::kFailed)
return false;
one_shot_players_.insert(PlayerIdentifier(observer, player_id));
@@ -762,8 +903,8 @@ void MediaSessionImpl::DidReceiveAction(
RenderFrameHost* rfh_of_routed_service =
routed_service_ ? routed_service_->GetRenderFrameHost() : nullptr;
for (const auto& player : normal_players_) {
- if (player.observer->render_frame_host() != rfh_of_routed_service)
- player.observer->OnSuspend(player.player_id);
+ if (player.first.observer->render_frame_host() != rfh_of_routed_service)
+ player.first.observer->OnSuspend(player.first.player_id);
}
for (const auto& player : pepper_players_) {
if (player.observer->render_frame_host() != rfh_of_routed_service) {
@@ -806,7 +947,7 @@ MediaSessionServiceImpl* MediaSessionImpl::ComputeServiceForRouting() {
// prefer the top-most frame.
std::set<RenderFrameHost*> frames;
for (const auto& player : normal_players_) {
- RenderFrameHost* frame = player.observer->render_frame_host();
+ RenderFrameHost* frame = player.first.observer->render_frame_host();
if (frame)
frames.insert(frame);
}
diff --git a/chromium/content/browser/media/session/media_session_impl.h b/chromium/content/browser/media/session/media_session_impl.h
index 42f85c71133..3c1e003c2b6 100644
--- a/chromium/content/browser/media/session/media_session_impl.h
+++ b/chromium/content/browser/media/session/media_session_impl.h
@@ -15,7 +15,7 @@
#include "base/macros.h"
#include "base/observer_list.h"
#include "base/optional.h"
-#include "content/browser/media/session/audio_focus_manager.h"
+#include "content/browser/media/session/audio_focus_delegate.h"
#include "content/browser/media/session/media_session_uma_helper.h"
#include "content/common/content_export.h"
#include "content/public/browser/media_session.h"
@@ -25,6 +25,7 @@
#include "content/public/common/media_metadata.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 "services/media_session/public/mojom/audio_focus.mojom.h"
#if defined(OS_ANDROID)
@@ -37,15 +38,8 @@ namespace media {
enum class MediaContentType;
} // namespace media
-namespace media_session {
-namespace mojom {
-enum class AudioFocusType;
-} // namespace mojom
-} // namespace media_session
-
namespace content {
-class AudioFocusDelegate;
class AudioFocusManagerTest;
class MediaSessionImplServiceRoutingTest;
class MediaSessionImplStateObserver;
@@ -124,43 +118,6 @@ class MediaSessionImpl : public MediaSession,
CONTENT_EXPORT void OnPlayerPaused(MediaSessionPlayerObserver* observer,
int player_id);
- // Resume the media session.
- // |type| represents the origin of the request.
- CONTENT_EXPORT void Resume(MediaSession::SuspendType suspend_type) override;
-
- // Suspend the media session.
- // |type| represents the origin of the request.
- CONTENT_EXPORT void Suspend(MediaSession::SuspendType suspend_type) override;
-
- // Stop the media session.
- // |type| represents the origin of the request.
- CONTENT_EXPORT void Stop(MediaSession::SuspendType suspend_type) override;
-
- // Seek the media session forward.
- CONTENT_EXPORT void SeekForward(base::TimeDelta seek_time) override;
-
- // Seek the media session backward.
- CONTENT_EXPORT void SeekBackward(base::TimeDelta seek_time) override;
-
- // Returns if the session can be controlled by Resume() and Suspend() calls
- // above.
- CONTENT_EXPORT bool IsControllable() const override;
-
- // Compute if the actual playback state is paused by combining the
- // MediaSessionService declared state and guessed state (audio_focus_state_).
- CONTENT_EXPORT bool IsActuallyPaused() const override;
-
- // Set the volume multiplier applied during ducking.
- CONTENT_EXPORT void SetDuckingVolumeMultiplier(double multiplier) override;
-
- // Let the media session start ducking such that the volume multiplier is
- // reduced.
- CONTENT_EXPORT void StartDucking() override;
-
- // Let the media session stop ducking such that the volume multiplier is
- // recovered.
- CONTENT_EXPORT void StopDucking() override;
-
void AddObserver(MediaSessionObserver* observer) override;
void RemoveObserver(MediaSessionObserver* observer) override;
@@ -198,31 +155,77 @@ class MediaSessionImpl : public MediaSession,
// observers if the service is currently routed.
void OnMediaSessionActionsChanged(MediaSessionServiceImpl* service);
+ // Requests audio focus to the AudioFocusDelegate.
+ // Returns whether the request was granted.
+ CONTENT_EXPORT AudioFocusDelegate::AudioFocusResult RequestSystemAudioFocus(
+ media_session::mojom::AudioFocusType audio_focus_type);
+
+ // Creates a binding between |this| and |request|.
+ void BindToMojoRequest(
+ mojo::InterfaceRequest<media_session::mojom::MediaSession> request);
+
+ // Returns information about the MediaSession.
+ media_session::mojom::MediaSessionInfoPtr GetMediaSessionInfoSync();
+
+ // MediaSession overrides ---------------------------------------------------
+
+ // Resume the media session.
+ // |type| represents the origin of the request.
+ CONTENT_EXPORT void Resume(MediaSession::SuspendType suspend_type) override;
+
+ // Stop the media session.
+ // |type| represents the origin of the request.
+ CONTENT_EXPORT void Stop(MediaSession::SuspendType suspend_type) override;
+
+ // Seek the media session forward.
+ CONTENT_EXPORT void SeekForward(base::TimeDelta seek_time) override;
+
+ // Seek the media session backward.
+ CONTENT_EXPORT void SeekBackward(base::TimeDelta seek_time) override;
+
+ // Returns if the session can be controlled by Resume() and Suspend() calls
+ // above.
+ CONTENT_EXPORT bool IsControllable() const override;
+
+ // Compute if the actual playback state is paused by combining the
+ // MediaSessionService declared state and guessed state (audio_focus_state_).
+ CONTENT_EXPORT bool IsActuallyPaused() const override;
+
// Called when a MediaSessionAction is received. The action will be forwarded
// 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(
- media_session::mojom::AudioFocusType audio_focus_type);
+ // Set the volume multiplier applied during ducking.
+ CONTENT_EXPORT void SetDuckingVolumeMultiplier(double multiplier) override;
- // Returns debugging information to be displayed on chrome://media-internals.
- struct DebugInfo {
- // A unique name for the MediaSession.
- std::string name;
+ // Suspend the media session.
+ // |type| represents the origin of the request.
+ CONTENT_EXPORT void Suspend(MediaSession::SuspendType suspend_type) override;
- // The title and URL of the owning WebContents.
- std::string owner;
+ // Let the media session start ducking such that the volume multiplier is
+ // reduced.
+ CONTENT_EXPORT void StartDucking() override;
- // State information stored in a string e.g. Ducked.
- std::string state;
- };
- const DebugInfo GetDebugInfo();
+ // Let the media session stop ducking such that the volume multiplier is
+ // recovered.
+ CONTENT_EXPORT void StopDucking() override;
- // Creates a binding between |this| and |request|.
- void BindToMojoRequest(
- mojo::InterfaceRequest<media_session::mojom::MediaSession> request);
+ // Returns information about the MediaSession. The sync method is not actually
+ // slower and should be used over the async one which is available over mojo.
+ void GetMediaSessionInfo(GetMediaSessionInfoCallback callback) override;
+
+ // Returns debugging information to be displayed on chrome://media-internals.
+ void GetDebugInfo(GetDebugInfoCallback) override;
+
+ // Adds a mojo based observer to listen to events related to this session.
+ void AddObserver(
+ media_session::mojom::MediaSessionObserverPtr observer) override;
+
+ // Called by |AudioFocusDelegate| when an async audio focus request is
+ // completed.
+ CONTENT_EXPORT void FinishSystemAudioFocusRequest(
+ media_session::mojom::AudioFocusType type,
+ bool result);
private:
friend class content::WebContentsUserData<MediaSessionImpl>;
@@ -232,6 +235,7 @@ class MediaSessionImpl : public MediaSession,
friend class content::MediaSessionImplServiceRoutingTest;
friend class content::MediaSessionImplStateObserver;
friend class content::MediaSessionServiceImplBrowserTest;
+ friend class MediaSessionImplTest;
friend class MediaInternalsAudioFocusTest;
CONTENT_EXPORT void SetDelegateForTests(
@@ -246,6 +250,7 @@ class MediaSessionImpl : public MediaSession,
void operator=(const PlayerIdentifier&) = delete;
bool operator==(const PlayerIdentifier& player_identifier) const;
+ bool operator<(const PlayerIdentifier&) const;
// Hash operator for base::hash_map<>.
struct Hash {
@@ -262,6 +267,10 @@ class MediaSessionImpl : public MediaSession,
void Initialize();
+ // Called when system audio focus has been requested and whether the request
+ // was granted.
+ void OnSystemAudioFocusRequested(bool result);
+
CONTENT_EXPORT void OnSuspendInternal(MediaSession::SuspendType suspend_type,
State new_state);
CONTENT_EXPORT void OnResumeInternal(MediaSession::SuspendType suspend_type);
@@ -280,6 +289,12 @@ class MediaSessionImpl : public MediaSession,
// It sets audio_focus_state_ and notifies observers about the state change.
void SetAudioFocusState(State audio_focus_state);
+ // Flushes any mojo bindings for testing.
+ CONTENT_EXPORT void FlushForTesting();
+
+ // Notifies mojo observers that the MediaSessionInfo has changed.
+ void NotifyObserversInfoChanged();
+
// Update the volume multiplier when ducking state changes.
void UpdateVolumeMultiplier();
@@ -311,7 +326,8 @@ class MediaSessionImpl : public MediaSession,
CONTENT_EXPORT MediaSessionServiceImpl* ComputeServiceForRouting();
std::unique_ptr<AudioFocusDelegate> delegate_;
- PlayersMap normal_players_;
+ std::map<PlayerIdentifier, media_session::mojom::AudioFocusType>
+ normal_players_;
PlayersMap pepper_players_;
PlayersMap one_shot_players_;
@@ -352,6 +368,9 @@ class MediaSessionImpl : public MediaSession,
// Bindings for Mojo pointers to |this| held by media route providers.
mojo::BindingSet<media_session::mojom::MediaSession> bindings_;
+ mojo::InterfacePtrSet<media_session::mojom::MediaSessionObserver>
+ mojo_observers_;
+
DISALLOW_COPY_AND_ASSIGN(MediaSessionImpl);
};
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 a39d86d6a83..7e686667fa4 100644
--- a/chromium/content/browser/media/session/media_session_impl_browsertest.cc
+++ b/chromium/content/browser/media/session/media_session_impl_browsertest.cc
@@ -51,21 +51,47 @@ const double kDifferentDuckingVolumeMultiplier = 0.018;
class MockAudioFocusDelegate : public AudioFocusDelegate {
public:
- MockAudioFocusDelegate() {}
+ MockAudioFocusDelegate(MediaSessionImpl* media_session, bool async_mode)
+ : media_session_(media_session), async_mode_(async_mode) {}
MOCK_METHOD0(AbandonAudioFocus, void());
- bool RequestAudioFocus(AudioFocusType audio_focus_type) {
- audio_focus_type_ = audio_focus_type;
- return true;
+ AudioFocusDelegate::AudioFocusResult RequestAudioFocus(
+ AudioFocusType audio_focus_type) {
+ if (async_mode_) {
+ requests_.push_back(audio_focus_type);
+ return AudioFocusDelegate::AudioFocusResult::kDelayed;
+ } else {
+ audio_focus_type_ = audio_focus_type;
+ return AudioFocusDelegate::AudioFocusResult::kSuccess;
+ }
}
- AudioFocusType GetCurrentFocusType() const {
- DCHECK(audio_focus_type_.has_value());
- return audio_focus_type_.value();
+ base::Optional<AudioFocusType> GetCurrentFocusType() const {
+ return audio_focus_type_;
}
+ void MediaSessionInfoChanged(
+ media_session::mojom::MediaSessionInfoPtr session_info) override {}
+
+ void ResolveRequest(bool result) {
+ if (!async_mode_)
+ return;
+
+ audio_focus_type_ = requests_.front();
+ requests_.pop_front();
+
+ media_session_->FinishSystemAudioFocusRequest(audio_focus_type_.value(),
+ result);
+ }
+
+ bool HasRequests() const { return !requests_.empty(); }
+
private:
+ MediaSessionImpl* media_session_;
+ const bool async_mode_ = false;
+
+ std::list<AudioFocusType> requests_;
base::Optional<AudioFocusType> audio_focus_type_;
};
@@ -88,7 +114,8 @@ class MediaSessionImplBrowserTest : public content::ContentBrowserTest {
media_session_ = MediaSessionImpl::Get(shell()->web_contents());
mock_media_session_observer_.reset(
new NiceMock<content::MockMediaSessionObserver>(media_session_));
- mock_audio_focus_delegate_ = new NiceMock<MockAudioFocusDelegate>;
+ mock_audio_focus_delegate_ = new NiceMock<MockAudioFocusDelegate>(
+ media_session_, true /* async_mode */);
media_session_->SetDelegateForTests(
base::WrapUnique(mock_audio_focus_delegate_));
ASSERT_TRUE(media_session_);
@@ -106,8 +133,10 @@ class MediaSessionImplBrowserTest : public content::ContentBrowserTest {
void StartNewPlayer(MockMediaSessionPlayerObserver* player_observer,
media::MediaContentType media_content_type) {
- bool result = AddPlayer(player_observer, player_observer->StartNewPlayer(),
- media_content_type);
+ int player_id = player_observer->StartNewPlayer();
+
+ bool result = AddPlayer(player_observer, player_id, media_content_type);
+
EXPECT_TRUE(result);
}
@@ -133,22 +162,22 @@ class MediaSessionImplBrowserTest : public content::ContentBrowserTest {
bool IsActive() { return media_session_->IsActive(); }
- AudioFocusType GetSessionAudioFocusType() {
+ base::Optional<AudioFocusType> GetSessionAudioFocusType() {
return mock_audio_focus_delegate_->GetCurrentFocusType();
}
bool IsControllable() { return media_session_->IsControllable(); }
- void UIResume() { media_session_->Resume(MediaSession::SuspendType::UI); }
+ void UIResume() { media_session_->Resume(MediaSession::SuspendType::kUI); }
void SystemResume() {
- media_session_->OnResumeInternal(MediaSession::SuspendType::SYSTEM);
+ media_session_->OnResumeInternal(MediaSession::SuspendType::kSystem);
}
- void UISuspend() { media_session_->Suspend(MediaSession::SuspendType::UI); }
+ void UISuspend() { media_session_->Suspend(MediaSession::SuspendType::kUI); }
void SystemSuspend(bool temporary) {
- media_session_->OnSuspendInternal(MediaSession::SuspendType::SYSTEM,
+ media_session_->OnSuspendInternal(MediaSession::SuspendType::kSystem,
temporary
? MediaSessionImpl::State::SUSPENDED
: MediaSessionImpl::State::INACTIVE);
@@ -175,6 +204,18 @@ class MediaSessionImplBrowserTest : public content::ContentBrowserTest {
mock_media_session_service_->SetPlaybackState(state);
}
+ void ResolveAudioFocusSuccess() {
+ mock_audio_focus_delegate()->ResolveRequest(true /* result */);
+ }
+
+ void ResolveAudioFocusFailure() {
+ mock_audio_focus_delegate()->ResolveRequest(false /* result */);
+ }
+
+ bool HasUnresolvedAudioFocusRequest() {
+ return mock_audio_focus_delegate()->HasRequests();
+ }
+
content::MockMediaSessionObserver* mock_media_session_observer() {
return mock_media_session_observer_.get();
}
@@ -191,6 +232,14 @@ class MediaSessionImplBrowserTest : public content::ContentBrowserTest {
return media_session_->uma_helper_for_test();
}
+ void SetAudioFocusDelegateForTests(MockAudioFocusDelegate* delegate) {
+ mock_audio_focus_delegate_ = delegate;
+ media_session_->SetDelegateForTests(
+ base::WrapUnique(mock_audio_focus_delegate_));
+ }
+
+ bool IsDucking() const { return media_session_->is_ducking_; }
+
protected:
MediaSessionImpl* media_session_;
std::unique_ptr<content::MockMediaSessionObserver>
@@ -201,20 +250,37 @@ class MediaSessionImplBrowserTest : public content::ContentBrowserTest {
DISALLOW_COPY_AND_ASSIGN(MediaSessionImplBrowserTest);
};
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+class MediaSessionImplParamBrowserTest
+ : public MediaSessionImplBrowserTest,
+ public testing::WithParamInterface<bool> {
+ protected:
+ MediaSessionImplParamBrowserTest() = default;
+
+ void SetUpOnMainThread() override {
+ MediaSessionImplBrowserTest::SetUpOnMainThread();
+
+ SetAudioFocusDelegateForTests(
+ new NiceMock<MockAudioFocusDelegate>(media_session_, GetParam()));
+ }
+};
+
+INSTANTIATE_TEST_CASE_P(, MediaSessionImplParamBrowserTest, testing::Bool());
+
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
PlayersFromSameObserverDoNotStopEachOtherInSameSession) {
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ ResolveAudioFocusSuccess();
EXPECT_TRUE(player_observer->IsPlaying(0));
EXPECT_TRUE(player_observer->IsPlaying(1));
EXPECT_TRUE(player_observer->IsPlaying(2));
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
PlayersFromManyObserverDoNotStopEachOtherInSameSession) {
auto player_observer_1 = std::make_unique<MockMediaSessionPlayerObserver>();
auto player_observer_2 = std::make_unique<MockMediaSessionPlayerObserver>();
@@ -223,19 +289,21 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
StartNewPlayer(player_observer_1.get(), media::MediaContentType::Persistent);
StartNewPlayer(player_observer_2.get(), media::MediaContentType::Persistent);
StartNewPlayer(player_observer_3.get(), media::MediaContentType::Persistent);
+ ResolveAudioFocusSuccess();
EXPECT_TRUE(player_observer_1->IsPlaying(0));
EXPECT_TRUE(player_observer_2->IsPlaying(0));
EXPECT_TRUE(player_observer_3->IsPlaying(0));
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
SuspendedMediaSessionStopsPlayers) {
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ ResolveAudioFocusSuccess();
SystemSuspend(true);
@@ -244,13 +312,14 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
EXPECT_FALSE(player_observer->IsPlaying(2));
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
ResumedMediaSessionRestartsPlayers) {
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ ResolveAudioFocusSuccess();
SystemSuspend(true);
SystemResume();
@@ -260,11 +329,12 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
EXPECT_TRUE(player_observer->IsPlaying(2));
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
StartedPlayerOnSuspendedSessionPlaysAlone) {
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ ResolveAudioFocusSuccess();
EXPECT_TRUE(player_observer->IsPlaying(0));
@@ -273,6 +343,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
EXPECT_FALSE(player_observer->IsPlaying(0));
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ ResolveAudioFocusSuccess();
EXPECT_FALSE(player_observer->IsPlaying(0));
EXPECT_TRUE(player_observer->IsPlaying(1));
@@ -284,7 +355,8 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
EXPECT_TRUE(player_observer->IsPlaying(2));
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, InitialVolumeMultiplier) {
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
+ InitialVolumeMultiplier) {
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
@@ -292,9 +364,14 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, InitialVolumeMultiplier) {
EXPECT_EQ(kDefaultVolumeMultiplier, player_observer->GetVolumeMultiplier(0));
EXPECT_EQ(kDefaultVolumeMultiplier, player_observer->GetVolumeMultiplier(1));
+
+ ResolveAudioFocusSuccess();
+
+ EXPECT_EQ(kDefaultVolumeMultiplier, player_observer->GetVolumeMultiplier(0));
+ EXPECT_EQ(kDefaultVolumeMultiplier, player_observer->GetVolumeMultiplier(1));
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
StartDuckingReducesVolumeMultiplier) {
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
@@ -310,7 +387,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
EXPECT_EQ(kDuckingVolumeMultiplier, player_observer->GetVolumeMultiplier(2));
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
StopDuckingRecoversVolumeMultiplier) {
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
@@ -327,7 +404,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
EXPECT_EQ(kDefaultVolumeMultiplier, player_observer->GetVolumeMultiplier(2));
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
DuckingUsesConfiguredMultiplier) {
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
@@ -344,14 +421,16 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
EXPECT_EQ(kDefaultVolumeMultiplier, player_observer->GetVolumeMultiplier(1));
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, AudioFocusInitialState) {
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
+ AudioFocusInitialState) {
EXPECT_FALSE(IsActive());
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
AddPlayerOnSuspendedFocusUnducks) {
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ ResolveAudioFocusSuccess();
UISuspend();
EXPECT_FALSE(IsActive());
@@ -361,53 +440,65 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
EXPECT_TRUE(
AddPlayer(player_observer.get(), 0, media::MediaContentType::Persistent));
+ ResolveAudioFocusSuccess();
EXPECT_EQ(kDefaultVolumeMultiplier, player_observer->GetVolumeMultiplier(0));
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
CanRequestFocusBeforePlayerCreation) {
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
media_session_->RequestSystemAudioFocus(AudioFocusType::kGain);
EXPECT_TRUE(IsActive());
+ ResolveAudioFocusSuccess();
+ EXPECT_TRUE(IsActive());
+
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
EXPECT_TRUE(IsActive());
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, StartPlayerGivesFocus) {
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
+ StartPlayerGivesFocus) {
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ EXPECT_TRUE(IsActive());
+ ResolveAudioFocusSuccess();
EXPECT_TRUE(IsActive());
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
SuspendGivesAwayAudioFocus) {
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ ResolveAudioFocusSuccess();
SystemSuspend(true);
EXPECT_FALSE(IsActive());
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, StopGivesAwayAudioFocus) {
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
+ StopGivesAwayAudioFocus) {
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ ResolveAudioFocusSuccess();
- media_session_->Stop(MediaSession::SuspendType::UI);
+ media_session_->Stop(MediaSession::SuspendType::kUI);
EXPECT_FALSE(IsActive());
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, ResumeGivesBackAudioFocus) {
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
+ SystemResumeGivesBackAudioFocus) {
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ ResolveAudioFocusSuccess();
SystemSuspend(true);
SystemResume();
@@ -415,13 +506,30 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, ResumeGivesBackAudioFocus) {
EXPECT_TRUE(IsActive());
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
+ UIResumeGivesBackAudioFocus) {
+ auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ ResolveAudioFocusSuccess();
+
+ UISuspend();
+
+ UIResume();
+ EXPECT_TRUE(IsActive());
+
+ ResolveAudioFocusSuccess();
+ EXPECT_TRUE(IsActive());
+}
+
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
RemovingLastPlayerDropsAudioFocus) {
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ ResolveAudioFocusSuccess();
RemovePlayer(player_observer.get(), 0);
EXPECT_TRUE(IsActive());
@@ -431,7 +539,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
EXPECT_FALSE(IsActive());
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
RemovingLastPlayerFromManyObserversDropsAudioFocus) {
auto player_observer_1 = std::make_unique<MockMediaSessionPlayerObserver>();
auto player_observer_2 = std::make_unique<MockMediaSessionPlayerObserver>();
@@ -440,6 +548,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
StartNewPlayer(player_observer_1.get(), media::MediaContentType::Persistent);
StartNewPlayer(player_observer_2.get(), media::MediaContentType::Persistent);
StartNewPlayer(player_observer_3.get(), media::MediaContentType::Persistent);
+ ResolveAudioFocusSuccess();
RemovePlayer(player_observer_1.get(), 0);
EXPECT_TRUE(IsActive());
@@ -449,7 +558,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
EXPECT_FALSE(IsActive());
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
RemovingAllPlayersFromObserversDropsAudioFocus) {
auto player_observer_1 = std::make_unique<MockMediaSessionPlayerObserver>();
auto player_observer_2 = std::make_unique<MockMediaSessionPlayerObserver>();
@@ -458,6 +567,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
StartNewPlayer(player_observer_1.get(), media::MediaContentType::Persistent);
StartNewPlayer(player_observer_2.get(), media::MediaContentType::Persistent);
StartNewPlayer(player_observer_2.get(), media::MediaContentType::Persistent);
+ ResolveAudioFocusSuccess();
RemovePlayers(player_observer_1.get());
EXPECT_TRUE(IsActive());
@@ -465,29 +575,40 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
EXPECT_FALSE(IsActive());
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, ResumePlayGivesAudioFocus) {
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
+ ResumePlayGivesAudioFocus) {
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ ResolveAudioFocusSuccess();
RemovePlayer(player_observer.get(), 0);
EXPECT_FALSE(IsActive());
EXPECT_TRUE(
AddPlayer(player_observer.get(), 0, media::MediaContentType::Persistent));
+ ResolveAudioFocusSuccess();
EXPECT_TRUE(IsActive());
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
ResumeSuspendSeekAreSentOnlyOncePerPlayers) {
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
+ EXPECT_EQ(0, player_observer->received_suspend_calls());
+ EXPECT_EQ(0, player_observer->received_resume_calls());
+
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
EXPECT_EQ(0, player_observer->received_suspend_calls());
EXPECT_EQ(0, player_observer->received_resume_calls());
+
+ ResolveAudioFocusSuccess();
+
+ EXPECT_EQ(0, player_observer->received_suspend_calls());
+ EXPECT_EQ(0, player_observer->received_resume_calls());
EXPECT_EQ(0, player_observer->received_seek_forward_calls());
EXPECT_EQ(0, player_observer->received_seek_backward_calls());
@@ -504,14 +625,22 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
EXPECT_EQ(3, player_observer->received_seek_backward_calls());
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
ResumeSuspendSeekAreSentOnlyOncePerPlayersAddedTwice) {
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
+ EXPECT_EQ(0, player_observer->received_suspend_calls());
+ EXPECT_EQ(0, player_observer->received_resume_calls());
+
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ EXPECT_EQ(0, player_observer->received_suspend_calls());
+ EXPECT_EQ(0, player_observer->received_resume_calls());
+
+ ResolveAudioFocusSuccess();
+
// Adding the three players above again.
EXPECT_TRUE(
AddPlayer(player_observer.get(), 0, media::MediaContentType::Persistent));
@@ -538,33 +667,38 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
EXPECT_EQ(3, player_observer->received_seek_backward_calls());
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
RemovingTheSamePlayerTwiceIsANoop) {
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ ResolveAudioFocusSuccess();
RemovePlayer(player_observer.get(), 0);
RemovePlayer(player_observer.get(), 0);
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, AudioFocusType) {
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest, AudioFocusType) {
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
// Starting a player with a given type should set the session to that type.
StartNewPlayer(player_observer.get(), media::MediaContentType::Transient);
+ ResolveAudioFocusSuccess();
EXPECT_EQ(AudioFocusType::kGainTransientMayDuck, GetSessionAudioFocusType());
// Adding a player of the same type should have no effect on the type.
StartNewPlayer(player_observer.get(), media::MediaContentType::Transient);
+ EXPECT_FALSE(HasUnresolvedAudioFocusRequest());
EXPECT_EQ(AudioFocusType::kGainTransientMayDuck, GetSessionAudioFocusType());
// Adding a player of Content type should override the current type.
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ ResolveAudioFocusSuccess();
EXPECT_EQ(AudioFocusType::kGain, GetSessionAudioFocusType());
// Adding a player of the Transient type should have no effect on the type.
StartNewPlayer(player_observer.get(), media::MediaContentType::Transient);
+ EXPECT_FALSE(HasUnresolvedAudioFocusRequest());
EXPECT_EQ(AudioFocusType::kGain, GetSessionAudioFocusType());
EXPECT_TRUE(player_observer->IsPlaying(0));
@@ -591,7 +725,8 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, AudioFocusType) {
EXPECT_EQ(AudioFocusType::kGain, GetSessionAudioFocusType());
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, ControlsShowForContent) {
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
+ ControlsShowForContent) {
EXPECT_CALL(*mock_media_session_observer(),
MediaSessionStateChanged(true, false));
@@ -599,12 +734,13 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, ControlsShowForContent) {
// Starting a player with a content type should show the media controls.
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ ResolveAudioFocusSuccess();
EXPECT_TRUE(IsControllable());
EXPECT_TRUE(IsActive());
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
ControlsNoShowForTransient) {
EXPECT_CALL(*mock_media_session_observer(),
MediaSessionStateChanged(false, false));
@@ -613,12 +749,14 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
// Starting a player with a transient type should not show the media controls.
StartNewPlayer(player_observer.get(), media::MediaContentType::Transient);
+ ResolveAudioFocusSuccess();
EXPECT_FALSE(IsControllable());
EXPECT_TRUE(IsActive());
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, ControlsHideWhenStopped) {
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
+ ControlsHideWhenStopped) {
Expectation showControls = EXPECT_CALL(*mock_media_session_observer(),
MediaSessionStateChanged(true, false));
EXPECT_CALL(*mock_media_session_observer(),
@@ -628,6 +766,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, ControlsHideWhenStopped) {
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ ResolveAudioFocusSuccess();
RemovePlayers(player_observer.get());
@@ -635,7 +774,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, ControlsHideWhenStopped) {
EXPECT_FALSE(IsActive());
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
ControlsShownAcceptTransient) {
EXPECT_CALL(*mock_media_session_observer(),
MediaSessionStateChanged(true, false));
@@ -643,6 +782,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ ResolveAudioFocusSuccess();
// Transient player join the session without affecting the controls.
StartNewPlayer(player_observer.get(), media::MediaContentType::Transient);
@@ -651,7 +791,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
EXPECT_TRUE(IsActive());
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
ControlsShownAfterContentAdded) {
Expectation dontShowControls = EXPECT_CALL(
*mock_media_session_observer(), MediaSessionStateChanged(false, false));
@@ -662,15 +802,17 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
StartNewPlayer(player_observer.get(), media::MediaContentType::Transient);
+ ResolveAudioFocusSuccess();
// The controls are shown when the content player is added.
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ ResolveAudioFocusSuccess();
EXPECT_TRUE(IsControllable());
EXPECT_TRUE(IsActive());
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
ControlsStayIfOnlyOnePlayerHasBeenPaused) {
EXPECT_CALL(*mock_media_session_observer(),
MediaSessionStateChanged(true, false));
@@ -678,6 +820,8 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ ResolveAudioFocusSuccess();
+
StartNewPlayer(player_observer.get(), media::MediaContentType::Transient);
// Removing only content player doesn't hide the controls since the session
@@ -688,7 +832,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
EXPECT_TRUE(IsActive());
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
ControlsHideWhenTheLastPlayerIsRemoved) {
Expectation showControls = EXPECT_CALL(*mock_media_session_observer(),
MediaSessionStateChanged(true, false));
@@ -700,6 +844,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ ResolveAudioFocusSuccess();
RemovePlayer(player_observer.get(), 0);
@@ -712,7 +857,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
EXPECT_FALSE(IsActive());
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
ControlsHideWhenAllThePlayersAreRemoved) {
Expectation showControls = EXPECT_CALL(*mock_media_session_observer(),
MediaSessionStateChanged(true, false));
@@ -724,6 +869,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ ResolveAudioFocusSuccess();
RemovePlayers(player_observer.get());
@@ -731,7 +877,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
EXPECT_FALSE(IsActive());
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
ControlsNotHideWhenTheLastPlayerIsPaused) {
Expectation showControls = EXPECT_CALL(*mock_media_session_observer(),
MediaSessionStateChanged(true, false));
@@ -743,6 +889,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ ResolveAudioFocusSuccess();
OnPlayerPaused(player_observer.get(), 0);
@@ -755,7 +902,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
EXPECT_FALSE(IsActive());
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
SuspendTemporaryUpdatesControls) {
Expectation showControls = EXPECT_CALL(*mock_media_session_observer(),
MediaSessionStateChanged(true, false));
@@ -766,6 +913,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ ResolveAudioFocusSuccess();
SystemSuspend(true);
@@ -773,7 +921,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
EXPECT_FALSE(IsActive());
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
ControlsUpdatedWhenResumed) {
Expectation showControls = EXPECT_CALL(*mock_media_session_observer(),
MediaSessionStateChanged(true, false));
@@ -787,6 +935,8 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ ResolveAudioFocusSuccess();
+
SystemSuspend(true);
SystemResume();
@@ -794,7 +944,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
EXPECT_TRUE(IsActive());
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
ControlsHideWhenSessionSuspendedPermanently) {
Expectation showControls = EXPECT_CALL(*mock_media_session_observer(),
MediaSessionStateChanged(true, false));
@@ -805,6 +955,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ ResolveAudioFocusSuccess();
SystemSuspend(false);
@@ -812,8 +963,8 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
EXPECT_FALSE(IsActive());
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
- ConstrolsHideWhenSessionStops) {
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
+ ControlsHideWhenSessionStops) {
Expectation showControls = EXPECT_CALL(*mock_media_session_observer(),
MediaSessionStateChanged(true, false));
Expectation pauseControls = EXPECT_CALL(*mock_media_session_observer(),
@@ -826,14 +977,15 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ ResolveAudioFocusSuccess();
- media_session_->Stop(MediaSession::SuspendType::UI);
+ media_session_->Stop(MediaSession::SuspendType::kUI);
EXPECT_FALSE(IsControllable());
EXPECT_FALSE(IsActive());
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
ControlsHideWhenSessionChangesFromContentToTransient) {
Expectation showControls = EXPECT_CALL(*mock_media_session_observer(),
MediaSessionStateChanged(true, false));
@@ -847,17 +999,19 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ ResolveAudioFocusSuccess();
SystemSuspend(true);
// This should reset the session and change it to a transient, so
// hide the controls.
StartNewPlayer(player_observer.get(), media::MediaContentType::Transient);
+ ResolveAudioFocusSuccess();
EXPECT_FALSE(IsControllable());
EXPECT_TRUE(IsActive());
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
ControlsUpdatedWhenNewPlayerResetsSession) {
Expectation showControls = EXPECT_CALL(*mock_media_session_observer(),
MediaSessionStateChanged(true, false));
@@ -871,16 +1025,18 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ ResolveAudioFocusSuccess();
SystemSuspend(true);
// This should reset the session and update the controls.
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ ResolveAudioFocusSuccess();
EXPECT_TRUE(IsControllable());
EXPECT_TRUE(IsActive());
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
ControlsResumedWhenPlayerIsResumed) {
Expectation showControls = EXPECT_CALL(*mock_media_session_observer(),
MediaSessionStateChanged(true, false));
@@ -894,16 +1050,18 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ ResolveAudioFocusSuccess();
SystemSuspend(true);
// This should resume the session and update the controls.
AddPlayer(player_observer.get(), 0, media::MediaContentType::Persistent);
+ ResolveAudioFocusSuccess();
EXPECT_TRUE(IsControllable());
EXPECT_TRUE(IsActive());
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
ControlsUpdatedDueToResumeSessionAction) {
Expectation showControls = EXPECT_CALL(*mock_media_session_observer(),
MediaSessionStateChanged(true, false));
@@ -914,13 +1072,14 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ ResolveAudioFocusSuccess();
UISuspend();
EXPECT_TRUE(IsControllable());
EXPECT_FALSE(IsActive());
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
ControlsUpdatedDueToSuspendSessionAction) {
Expectation showControls = EXPECT_CALL(*mock_media_session_observer(),
MediaSessionStateChanged(true, false));
@@ -934,14 +1093,19 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ ResolveAudioFocusSuccess();
UISuspend();
+
UIResume();
+ EXPECT_TRUE(IsControllable());
+ EXPECT_TRUE(IsActive());
+ ResolveAudioFocusSuccess();
EXPECT_TRUE(IsControllable());
EXPECT_TRUE(IsActive());
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
ControlsDontShowWhenOneShotIsPresent) {
EXPECT_CALL(*mock_media_session_observer(),
MediaSessionStateChanged(false, false));
@@ -949,6 +1113,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
StartNewPlayer(player_observer.get(), media::MediaContentType::OneShot);
+ ResolveAudioFocusSuccess();
EXPECT_FALSE(IsControllable());
EXPECT_TRUE(IsActive());
@@ -962,7 +1127,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
EXPECT_TRUE(IsActive());
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
ControlsHiddenAfterRemoveOneShotWithoutOtherPlayers) {
Expectation expect_1 = EXPECT_CALL(*mock_media_session_observer(),
MediaSessionStateChanged(false, false));
@@ -976,13 +1141,14 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
StartNewPlayer(player_observer.get(), media::MediaContentType::OneShot);
+ ResolveAudioFocusSuccess();
RemovePlayer(player_observer.get(), 0);
EXPECT_FALSE(IsControllable());
EXPECT_FALSE(IsActive());
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
ControlsShowAfterRemoveOneShotWithPersistentPresent) {
Expectation uncontrollable = EXPECT_CALL(
*mock_media_session_observer(), MediaSessionStateChanged(false, false));
@@ -996,6 +1162,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
StartNewPlayer(player_observer.get(), media::MediaContentType::OneShot);
StartNewPlayer(player_observer.get(), media::MediaContentType::Transient);
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ ResolveAudioFocusSuccess();
RemovePlayer(player_observer.get(), 0);
@@ -1003,13 +1170,14 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
EXPECT_TRUE(IsActive());
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
DontSuspendWhenOneShotIsPresent) {
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
StartNewPlayer(player_observer.get(), media::MediaContentType::OneShot);
StartNewPlayer(player_observer.get(), media::MediaContentType::Transient);
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ ResolveAudioFocusSuccess();
SystemSuspend(false);
@@ -1019,11 +1187,12 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
EXPECT_EQ(0, player_observer->received_suspend_calls());
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
DontResumeBySystemUISuspendedSessions) {
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ ResolveAudioFocusSuccess();
UISuspend();
EXPECT_TRUE(IsControllable());
@@ -1034,80 +1203,103 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
EXPECT_FALSE(IsActive());
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
AllowUIResumeForSystemSuspend) {
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ ResolveAudioFocusSuccess();
SystemSuspend(true);
EXPECT_TRUE(IsControllable());
EXPECT_FALSE(IsActive());
UIResume();
+ ResolveAudioFocusSuccess();
+
EXPECT_TRUE(IsControllable());
EXPECT_TRUE(IsActive());
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, ResumeSuspendFromUI) {
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest, ResumeSuspendFromUI) {
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ ResolveAudioFocusSuccess();
UISuspend();
EXPECT_TRUE(IsControllable());
EXPECT_FALSE(IsActive());
UIResume();
+ EXPECT_TRUE(IsActive());
+
+ ResolveAudioFocusSuccess();
EXPECT_TRUE(IsControllable());
EXPECT_TRUE(IsActive());
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, ResumeSuspendFromSystem) {
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
+ ResumeSuspendFromSystem) {
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ ResolveAudioFocusSuccess();
SystemSuspend(true);
EXPECT_TRUE(IsControllable());
EXPECT_FALSE(IsActive());
SystemResume();
+ EXPECT_FALSE(HasUnresolvedAudioFocusRequest());
EXPECT_TRUE(IsControllable());
EXPECT_TRUE(IsActive());
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, OneShotTakesGainFocus) {
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
+ OneShotTakesGainFocus) {
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
StartNewPlayer(player_observer.get(), media::MediaContentType::OneShot);
+ ResolveAudioFocusSuccess();
+
StartNewPlayer(player_observer.get(), media::MediaContentType::Transient);
+ EXPECT_FALSE(HasUnresolvedAudioFocusRequest());
+
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ EXPECT_FALSE(HasUnresolvedAudioFocusRequest());
EXPECT_EQ(AudioFocusType::kGain,
mock_audio_focus_delegate()->GetCurrentFocusType());
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, RemovingOneShotDropsFocus) {
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
+ RemovingOneShotDropsFocus) {
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
EXPECT_CALL(*mock_audio_focus_delegate(), AbandonAudioFocus());
StartNewPlayer(player_observer.get(), media::MediaContentType::OneShot);
+ ResolveAudioFocusSuccess();
+
RemovePlayer(player_observer.get(), 0);
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
RemovingOneShotWhileStillHavingOtherPlayersKeepsFocus) {
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
EXPECT_CALL(*mock_audio_focus_delegate(), AbandonAudioFocus())
.Times(1); // Called in TearDown
StartNewPlayer(player_observer.get(), media::MediaContentType::OneShot);
+ ResolveAudioFocusSuccess();
+
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ EXPECT_FALSE(HasUnresolvedAudioFocusRequest());
+
RemovePlayer(player_observer.get(), 0);
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
ActualPlaybackStateWhilePlayerPaused) {
EnsureMediaSessionService();
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>(
@@ -1131,6 +1323,8 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
.InSequence(s);
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ ResolveAudioFocusSuccess();
+
OnPlayerPaused(player_observer.get(), 0);
SetPlaybackState(blink::mojom::MediaSessionPlaybackState::PLAYING);
SetPlaybackState(blink::mojom::MediaSessionPlaybackState::PAUSED);
@@ -1141,7 +1335,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
::testing::Mock::VerifyAndClear(mock_media_session_observer());
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
ActualPlaybackStateWhilePlayerPlaying) {
EnsureMediaSessionService();
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>(
@@ -1161,6 +1355,8 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
.InSequence(s);
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ ResolveAudioFocusSuccess();
+
SetPlaybackState(blink::mojom::MediaSessionPlaybackState::PLAYING);
SetPlaybackState(blink::mojom::MediaSessionPlaybackState::PAUSED);
SetPlaybackState(blink::mojom::MediaSessionPlaybackState::NONE);
@@ -1170,7 +1366,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
::testing::Mock::VerifyAndClear(mock_media_session_observer());
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
ActualPlaybackStateWhilePlayerRemoved) {
EnsureMediaSessionService();
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>(
@@ -1185,6 +1381,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
.InSequence(s);
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ ResolveAudioFocusSuccess();
RemovePlayer(player_observer.get(), 0);
SetPlaybackState(blink::mojom::MediaSessionPlaybackState::PLAYING);
@@ -1196,12 +1393,13 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
::testing::Mock::VerifyAndClear(mock_media_session_observer());
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
UMA_Suspended_SystemTransient) {
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
base::HistogramTester tester;
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ ResolveAudioFocusSuccess();
SystemSuspend(true);
std::unique_ptr<base::HistogramSamples> samples(
@@ -1212,12 +1410,13 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
EXPECT_EQ(0, samples->GetCount(2)); // UI
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
UMA_Suspended_SystemPermantent) {
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
base::HistogramTester tester;
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ ResolveAudioFocusSuccess();
SystemSuspend(false);
std::unique_ptr<base::HistogramSamples> samples(
@@ -1228,12 +1427,13 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
EXPECT_EQ(0, samples->GetCount(2)); // UI
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, UMA_Suspended_UI) {
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest, UMA_Suspended_UI) {
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
base::HistogramTester tester;
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ ResolveAudioFocusSuccess();
UISuspend();
std::unique_ptr<base::HistogramSamples> samples(
@@ -1244,20 +1444,24 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, UMA_Suspended_UI) {
EXPECT_EQ(1, samples->GetCount(2)); // UI
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, UMA_Suspended_Multiple) {
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
+ UMA_Suspended_Multiple) {
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
base::HistogramTester tester;
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ ResolveAudioFocusSuccess();
UISuspend();
UIResume();
+ ResolveAudioFocusSuccess();
SystemSuspend(true);
SystemResume();
UISuspend();
UIResume();
+ ResolveAudioFocusSuccess();
SystemSuspend(false);
@@ -1269,16 +1473,19 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, UMA_Suspended_Multiple) {
EXPECT_EQ(2, samples->GetCount(2)); // UI
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, UMA_Suspended_Crossing) {
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
+ UMA_Suspended_Crossing) {
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
base::HistogramTester tester;
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ ResolveAudioFocusSuccess();
UISuspend();
SystemSuspend(true);
SystemSuspend(false);
UIResume();
+ ResolveAudioFocusSuccess();
SystemSuspend(true);
SystemSuspend(true);
@@ -1293,12 +1500,13 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, UMA_Suspended_Crossing) {
EXPECT_EQ(1, samples->GetCount(2)); // UI
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, UMA_Suspended_Stop) {
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest, UMA_Suspended_Stop) {
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
base::HistogramTester tester;
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
- media_session_->Stop(MediaSession::SuspendType::UI);
+ ResolveAudioFocusSuccess();
+ media_session_->Stop(MediaSession::SuspendType::kUI);
std::unique_ptr<base::HistogramSamples> samples(
tester.GetHistogramSamplesSinceCreation("Media.Session.Suspended"));
@@ -1308,7 +1516,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, UMA_Suspended_Stop) {
EXPECT_EQ(1, samples->GetCount(2)); // UI
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
UMA_ActiveTime_NoActivation) {
base::HistogramTester tester;
@@ -1321,7 +1529,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
EXPECT_EQ(0, samples->TotalCount());
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
UMA_ActiveTime_SimpleActivation) {
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
base::HistogramTester tester;
@@ -1332,9 +1540,10 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
media_session_uma_helper->SetClockForTest(&clock);
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ ResolveAudioFocusSuccess();
clock.Advance(base::TimeDelta::FromMilliseconds(1000));
- media_session_->Stop(MediaSession::SuspendType::UI);
+ media_session_->Stop(MediaSession::SuspendType::kUI);
std::unique_ptr<base::HistogramSamples> samples(
tester.GetHistogramSamplesSinceCreation("Media.Session.ActiveTime"));
@@ -1342,7 +1551,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
EXPECT_EQ(1, samples->GetCount(1000));
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
UMA_ActiveTime_ActivationWithUISuspension) {
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
base::HistogramTester tester;
@@ -1353,15 +1562,17 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
media_session_uma_helper->SetClockForTest(&clock);
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ ResolveAudioFocusSuccess();
clock.Advance(base::TimeDelta::FromMilliseconds(1000));
UISuspend();
clock.Advance(base::TimeDelta::FromMilliseconds(2000));
UIResume();
+ ResolveAudioFocusSuccess();
clock.Advance(base::TimeDelta::FromMilliseconds(1000));
- media_session_->Stop(MediaSession::SuspendType::UI);
+ media_session_->Stop(MediaSession::SuspendType::kUI);
std::unique_ptr<base::HistogramSamples> samples(
tester.GetHistogramSamplesSinceCreation("Media.Session.ActiveTime"));
@@ -1369,7 +1580,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
EXPECT_EQ(1, samples->GetCount(2000));
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
UMA_ActiveTime_ActivationWithSystemSuspension) {
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
base::HistogramTester tester;
@@ -1380,6 +1591,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
media_session_uma_helper->SetClockForTest(&clock);
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ ResolveAudioFocusSuccess();
clock.Advance(base::TimeDelta::FromMilliseconds(1000));
SystemSuspend(true);
@@ -1388,7 +1600,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
SystemResume();
clock.Advance(base::TimeDelta::FromMilliseconds(1000));
- media_session_->Stop(MediaSession::SuspendType::UI);
+ media_session_->Stop(MediaSession::SuspendType::kUI);
std::unique_ptr<base::HistogramSamples> samples(
tester.GetHistogramSamplesSinceCreation("Media.Session.ActiveTime"));
@@ -1396,7 +1608,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
EXPECT_EQ(1, samples->GetCount(2000));
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
UMA_ActiveTime_ActivateSuspendedButNotStopped) {
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
base::HistogramTester tester;
@@ -1407,6 +1619,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
media_session_uma_helper->SetClockForTest(&clock);
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ ResolveAudioFocusSuccess();
clock.Advance(base::TimeDelta::FromMilliseconds(500));
SystemSuspend(true);
@@ -1427,7 +1640,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
}
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
UMA_ActiveTime_ActivateSuspendStopTwice) {
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
base::HistogramTester tester;
@@ -1438,14 +1651,16 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
media_session_uma_helper->SetClockForTest(&clock);
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ ResolveAudioFocusSuccess();
clock.Advance(base::TimeDelta::FromMilliseconds(500));
SystemSuspend(true);
- media_session_->Stop(MediaSession::SuspendType::UI);
+ media_session_->Stop(MediaSession::SuspendType::kUI);
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ ResolveAudioFocusSuccess();
clock.Advance(base::TimeDelta::FromMilliseconds(5000));
SystemResume();
- media_session_->Stop(MediaSession::SuspendType::UI);
+ media_session_->Stop(MediaSession::SuspendType::kUI);
std::unique_ptr<base::HistogramSamples> samples(
tester.GetHistogramSamplesSinceCreation("Media.Session.ActiveTime"));
@@ -1454,7 +1669,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
EXPECT_EQ(1, samples->GetCount(5000));
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
UMA_ActiveTime_MultipleActivations) {
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
base::HistogramTester tester;
@@ -1465,12 +1680,14 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
media_session_uma_helper->SetClockForTest(&clock);
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ ResolveAudioFocusSuccess();
clock.Advance(base::TimeDelta::FromMilliseconds(10000));
RemovePlayer(player_observer.get(), 0);
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ ResolveAudioFocusSuccess();
clock.Advance(base::TimeDelta::FromMilliseconds(1000));
- media_session_->Stop(MediaSession::SuspendType::UI);
+ media_session_->Stop(MediaSession::SuspendType::kUI);
std::unique_ptr<base::HistogramSamples> samples(
tester.GetHistogramSamplesSinceCreation("Media.Session.ActiveTime"));
@@ -1479,7 +1696,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
EXPECT_EQ(1, samples->GetCount(10000));
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
AddingObserverNotifiesCurrentInformation_EmptyInfo) {
media_session_->RemoveObserver(mock_media_session_observer());
EXPECT_CALL(*mock_media_session_observer(),
@@ -1492,7 +1709,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
media_session_->AddObserver(mock_media_session_observer());
}
-IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest,
AddingObserverNotifiesCurrentInformation_WithInfo) {
// Set up the service and information.
EnsureMediaSessionService();
@@ -1512,6 +1729,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>(
shell()->web_contents()->GetMainFrame());
StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ ResolveAudioFocusSuccess();
// Check if the expectations are met when the observer is newly added.
media_session_->RemoveObserver(mock_media_session_observer());
@@ -1523,3 +1741,217 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
MediaSessionActionsChanged(Eq(expectedActions)));
media_session_->AddObserver(mock_media_session_observer());
}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, Async_RequestFailure_Gain) {
+ auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Transient);
+
+ EXPECT_TRUE(player_observer->IsPlaying(0));
+ EXPECT_TRUE(player_observer->IsPlaying(1));
+ EXPECT_TRUE(IsActive());
+
+ // The gain request failed so we should suspend the whole session.
+ ResolveAudioFocusFailure();
+ EXPECT_FALSE(player_observer->IsPlaying(0));
+ EXPECT_FALSE(player_observer->IsPlaying(1));
+ EXPECT_FALSE(IsActive());
+
+ ResolveAudioFocusSuccess();
+ EXPECT_FALSE(player_observer->IsPlaying(0));
+ EXPECT_FALSE(player_observer->IsPlaying(1));
+ EXPECT_FALSE(IsActive());
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+ Async_RequestFailure_GainTransient) {
+ auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Transient);
+
+ EXPECT_TRUE(player_observer->IsPlaying(0));
+ EXPECT_TRUE(player_observer->IsPlaying(1));
+ EXPECT_TRUE(IsActive());
+
+ ResolveAudioFocusSuccess();
+ EXPECT_TRUE(player_observer->IsPlaying(0));
+ EXPECT_TRUE(player_observer->IsPlaying(1));
+ EXPECT_TRUE(IsActive());
+
+ // A transient audio focus failure should only affect transient players.
+ ResolveAudioFocusFailure();
+ EXPECT_TRUE(player_observer->IsPlaying(0));
+ EXPECT_FALSE(player_observer->IsPlaying(1));
+ EXPECT_TRUE(IsActive());
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, Async_GainThenTransient) {
+ auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Transient);
+
+ EXPECT_TRUE(player_observer->IsPlaying(0));
+ EXPECT_TRUE(player_observer->IsPlaying(1));
+
+ ResolveAudioFocusSuccess();
+ EXPECT_TRUE(player_observer->IsPlaying(0));
+ EXPECT_TRUE(player_observer->IsPlaying(1));
+
+ ResolveAudioFocusSuccess();
+ EXPECT_TRUE(player_observer->IsPlaying(0));
+ EXPECT_TRUE(player_observer->IsPlaying(1));
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, Async_TransientThenGain) {
+ auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Transient);
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+
+ EXPECT_TRUE(player_observer->IsPlaying(0));
+ EXPECT_TRUE(player_observer->IsPlaying(1));
+
+ ResolveAudioFocusSuccess();
+ EXPECT_TRUE(player_observer->IsPlaying(0));
+ EXPECT_TRUE(player_observer->IsPlaying(1));
+
+ ResolveAudioFocusSuccess();
+ EXPECT_TRUE(player_observer->IsPlaying(0));
+ EXPECT_TRUE(player_observer->IsPlaying(1));
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+ Async_SuspendBeforeResolve) {
+ auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ EXPECT_TRUE(player_observer->IsPlaying(0));
+
+ SystemSuspend(true);
+ EXPECT_FALSE(player_observer->IsPlaying(0));
+ EXPECT_FALSE(IsActive());
+
+ ResolveAudioFocusSuccess();
+ EXPECT_FALSE(player_observer->IsPlaying(0));
+ EXPECT_FALSE(IsActive());
+
+ SystemResume();
+ EXPECT_TRUE(IsActive());
+ EXPECT_TRUE(player_observer->IsPlaying(0));
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, Async_ResumeBeforeResolve) {
+ auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ EXPECT_TRUE(IsActive());
+ EXPECT_TRUE(player_observer->IsPlaying(0));
+
+ UISuspend();
+ EXPECT_FALSE(IsActive());
+ EXPECT_FALSE(player_observer->IsPlaying(0));
+
+ UIResume();
+ EXPECT_TRUE(IsActive());
+ EXPECT_TRUE(player_observer->IsPlaying(0));
+
+ ResolveAudioFocusSuccess();
+ EXPECT_TRUE(IsActive());
+ EXPECT_TRUE(player_observer->IsPlaying(0));
+
+ ResolveAudioFocusFailure();
+ EXPECT_FALSE(IsActive());
+ EXPECT_FALSE(player_observer->IsPlaying(0));
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, Async_RemoveBeforeResolve) {
+ {
+ auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
+
+ EXPECT_CALL(*mock_audio_focus_delegate(), AbandonAudioFocus());
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ EXPECT_TRUE(player_observer->IsPlaying(0));
+
+ RemovePlayer(player_observer.get(), 0);
+ }
+
+ ResolveAudioFocusSuccess();
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, Async_StopBeforeResolve) {
+ auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Transient);
+ ResolveAudioFocusSuccess();
+ EXPECT_TRUE(player_observer->IsPlaying(0));
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ EXPECT_TRUE(player_observer->IsPlaying(1));
+
+ media_session_->Stop(MediaSession::SuspendType::kUI);
+ ResolveAudioFocusSuccess();
+
+ EXPECT_FALSE(player_observer->IsPlaying(0));
+ EXPECT_FALSE(player_observer->IsPlaying(1));
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, Async_Unducking_Failure) {
+ auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ EXPECT_TRUE(IsActive());
+ EXPECT_TRUE(player_observer->IsPlaying(0));
+
+ SystemStartDucking();
+ EXPECT_TRUE(IsDucking());
+
+ ResolveAudioFocusFailure();
+ EXPECT_TRUE(IsDucking());
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, Async_Unducking_Inactive) {
+ auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ EXPECT_TRUE(IsActive());
+ EXPECT_TRUE(player_observer->IsPlaying(0));
+
+ media_session_->Stop(MediaSession::SuspendType::kUI);
+ SystemStartDucking();
+ EXPECT_TRUE(IsDucking());
+
+ ResolveAudioFocusSuccess();
+ EXPECT_TRUE(IsDucking());
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, Async_Unducking_Success) {
+ auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ EXPECT_TRUE(IsActive());
+ EXPECT_TRUE(player_observer->IsPlaying(0));
+
+ SystemStartDucking();
+ EXPECT_TRUE(IsDucking());
+
+ ResolveAudioFocusSuccess();
+ EXPECT_FALSE(IsDucking());
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, Async_Unducking_Suspended) {
+ auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ EXPECT_TRUE(IsActive());
+ EXPECT_TRUE(player_observer->IsPlaying(0));
+
+ UISuspend();
+ SystemStartDucking();
+ EXPECT_TRUE(IsDucking());
+
+ ResolveAudioFocusSuccess();
+ EXPECT_TRUE(IsDucking());
+}
diff --git a/chromium/content/browser/media/session/media_session_impl_uma_unittest.cc b/chromium/content/browser/media/session/media_session_impl_uma_unittest.cc
index 1efa52b4fd1..df1e97b29cf 100644
--- a/chromium/content/browser/media/session/media_session_impl_uma_unittest.cc
+++ b/chromium/content/browser/media/session/media_session_impl_uma_unittest.cc
@@ -96,7 +96,7 @@ class MediaSessionImplUmaTest : public RenderViewHostImplTestHarness {
};
TEST_F(MediaSessionImplUmaTest, RecordPauseDefaultOnUISuspend) {
- GetSession()->Suspend(SuspendType::UI);
+ GetSession()->Suspend(SuspendType::kUI);
std::unique_ptr<base::HistogramSamples> samples(
GetHistogramSamplesSinceTestStart("Media.Session.UserAction"));
EXPECT_EQ(1, samples->TotalCount());
@@ -105,22 +105,22 @@ TEST_F(MediaSessionImplUmaTest, RecordPauseDefaultOnUISuspend) {
}
TEST_F(MediaSessionImplUmaTest, RecordPauseDefaultOnSystemSuspend) {
- GetSession()->Suspend(SuspendType::SYSTEM);
+ GetSession()->Suspend(SuspendType::kSystem);
std::unique_ptr<base::HistogramSamples> samples(
GetHistogramSamplesSinceTestStart("Media.Session.UserAction"));
EXPECT_EQ(0, samples->TotalCount());
}
TEST_F(MediaSessionImplUmaTest, RecordPauseDefaultOnContentSuspend) {
- GetSession()->Suspend(SuspendType::CONTENT);
+ GetSession()->Suspend(SuspendType::kContent);
std::unique_ptr<base::HistogramSamples> samples(
GetHistogramSamplesSinceTestStart("Media.Session.UserAction"));
EXPECT_EQ(0, samples->TotalCount());
}
TEST_F(MediaSessionImplUmaTest, RecordPauseDefaultOnUIResume) {
- GetSession()->Suspend(SuspendType::SYSTEM);
- GetSession()->Resume(SuspendType::UI);
+ GetSession()->Suspend(SuspendType::kSystem);
+ GetSession()->Resume(SuspendType::kUI);
std::unique_ptr<base::HistogramSamples> samples(
GetHistogramSamplesSinceTestStart("Media.Session.UserAction"));
EXPECT_EQ(1, samples->TotalCount());
@@ -129,8 +129,8 @@ TEST_F(MediaSessionImplUmaTest, RecordPauseDefaultOnUIResume) {
}
TEST_F(MediaSessionImplUmaTest, RecordPauseDefaultOnSystemResume) {
- GetSession()->Suspend(SuspendType::SYSTEM);
- GetSession()->Resume(SuspendType::SYSTEM);
+ GetSession()->Suspend(SuspendType::kSystem);
+ GetSession()->Resume(SuspendType::kSystem);
std::unique_ptr<base::HistogramSamples> samples(
GetHistogramSamplesSinceTestStart("Media.Session.UserAction"));
EXPECT_EQ(0, samples->TotalCount());
@@ -138,15 +138,15 @@ TEST_F(MediaSessionImplUmaTest, RecordPauseDefaultOnSystemResume) {
// This should never happen but just check this to be safe.
TEST_F(MediaSessionImplUmaTest, RecordPauseDefaultOnContentResume) {
- GetSession()->Suspend(SuspendType::SYSTEM);
- GetSession()->Resume(SuspendType::CONTENT);
+ GetSession()->Suspend(SuspendType::kSystem);
+ GetSession()->Resume(SuspendType::kContent);
std::unique_ptr<base::HistogramSamples> samples(
GetHistogramSamplesSinceTestStart("Media.Session.UserAction"));
EXPECT_EQ(0, samples->TotalCount());
}
TEST_F(MediaSessionImplUmaTest, RecordPauseDefaultOnUIStop) {
- GetSession()->Stop(SuspendType::UI);
+ GetSession()->Stop(SuspendType::kUI);
std::unique_ptr<base::HistogramSamples> samples(
GetHistogramSamplesSinceTestStart("Media.Session.UserAction"));
EXPECT_EQ(1, samples->TotalCount());
@@ -156,7 +156,7 @@ TEST_F(MediaSessionImplUmaTest, RecordPauseDefaultOnUIStop) {
// This should never happen but just check this to be safe.
TEST_F(MediaSessionImplUmaTest, RecordPauseDefaultOnSystemStop) {
- GetSession()->Stop(SuspendType::SYSTEM);
+ GetSession()->Stop(SuspendType::kSystem);
std::unique_ptr<base::HistogramSamples> samples(
GetHistogramSamplesSinceTestStart("Media.Session.UserAction"));
EXPECT_EQ(0, samples->TotalCount());
diff --git a/chromium/content/browser/media/session/media_session_impl_unittest.cc b/chromium/content/browser/media/session/media_session_impl_unittest.cc
new file mode 100644
index 00000000000..12ead50c781
--- /dev/null
+++ b/chromium/content/browser/media/session/media_session_impl_unittest.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/media/session/media_session_impl.h"
+
+#include <memory>
+
+#include "base/command_line.h"
+#include "build/build_config.h"
+#include "content/browser/media/session/media_session_player_observer.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_service_manager_context.h"
+#include "content/test/test_web_contents.h"
+#include "media/base/media_content_type.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/interface_request.h"
+#include "services/media_session/public/cpp/switches.h"
+#include "services/media_session/public/cpp/test/audio_focus_test_util.h"
+#include "services/media_session/public/mojom/audio_focus.mojom.h"
+#include "services/media_session/public/mojom/constants.mojom.h"
+#include "services/media_session/public/mojom/media_session.mojom.h"
+#include "services/service_manager/public/cpp/connector.h"
+
+namespace content {
+
+using media_session::mojom::AudioFocusType;
+using media_session::mojom::MediaSessionInfo;
+using media_session::mojom::MediaSessionInfoPtr;
+using media_session::test::TestAudioFocusObserver;
+
+namespace {
+
+class MockMediaSessionPlayerObserver : public MediaSessionPlayerObserver {
+ public:
+ void OnSuspend(int player_id) override {}
+ void OnResume(int player_id) override {}
+ void OnSeekForward(int player_id, base::TimeDelta seek_time) override {}
+ void OnSeekBackward(int player_id, base::TimeDelta seek_time) override {}
+ void OnSetVolumeMultiplier(int player_id, double volume_multiplier) override {
+ }
+ RenderFrameHost* render_frame_host() const override { return nullptr; }
+};
+
+class MockMediaSessionMojoObserver
+ : public media_session::mojom::MediaSessionObserver {
+ public:
+ explicit MockMediaSessionMojoObserver(MediaSessionImpl* media_session)
+ : binding_(this) {
+ media_session::mojom::MediaSessionObserverPtr observer;
+ binding_.Bind(mojo::MakeRequest(&observer));
+ media_session->AddObserver(std::move(observer));
+ }
+
+ void MediaSessionInfoChanged(MediaSessionInfoPtr session) override {
+ session_info_ = std::move(session);
+
+ if (wanted_state_.has_value() &&
+ wanted_state_.value() == session_info_->state) {
+ run_loop_.Quit();
+ }
+ }
+
+ void WaitForState(MediaSessionInfo::SessionState wanted_state) {
+ if (session_info_ && session_info_->state == wanted_state)
+ return;
+
+ wanted_state_ = wanted_state;
+ run_loop_.Run();
+ }
+
+ MediaSessionInfoPtr session_info_;
+
+ private:
+ base::Optional<MediaSessionInfo::SessionState> wanted_state_;
+ base::RunLoop run_loop_;
+
+ mojo::Binding<media_session::mojom::MediaSessionObserver> binding_;
+};
+
+class MockAudioFocusDelegate : public AudioFocusDelegate {
+ public:
+ MockAudioFocusDelegate() = default;
+ ~MockAudioFocusDelegate() override = default;
+
+ void AbandonAudioFocus() override {}
+ AudioFocusResult RequestAudioFocus(AudioFocusType type) override {
+ return AudioFocusResult::kSuccess;
+ }
+ base::Optional<AudioFocusType> GetCurrentFocusType() const override {
+ return AudioFocusType::kGain;
+ }
+
+ void MediaSessionInfoChanged(MediaSessionInfoPtr session_info) override {
+ session_info_ = std::move(session_info);
+ }
+
+ MediaSessionInfo::SessionState GetState() const {
+ DCHECK(!session_info_.is_null());
+ return session_info_->state;
+ }
+
+ private:
+ MediaSessionInfoPtr session_info_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockAudioFocusDelegate);
+};
+
+} // anonymous namespace
+
+class MediaSessionImplTest : public testing::Test {
+ public:
+ MediaSessionImplTest() = default;
+
+ void SetUp() override {
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
+ media_session::switches::kEnableAudioFocus);
+
+ rph_factory_.reset(new MockRenderProcessHostFactory());
+ RenderProcessHostImpl::set_render_process_host_factory_for_testing(
+ rph_factory_.get());
+ browser_context_.reset(new TestBrowserContext());
+ pepper_observer_.reset(new MockMediaSessionPlayerObserver());
+
+ // Connect to the Media Session service and bind |audio_focus_ptr_| to it.
+ service_manager_context_ = std::make_unique<TestServiceManagerContext>();
+ service_manager::Connector* connector =
+ ServiceManagerConnection::GetForProcess()->GetConnector();
+ connector->BindInterface(media_session::mojom::kServiceName,
+ mojo::MakeRequest(&audio_focus_ptr_));
+ }
+
+ void TearDown() override {
+ service_manager_context_.reset();
+ browser_context_.reset();
+ RenderProcessHostImpl::set_render_process_host_factory_for_testing(nullptr);
+ rph_factory_.reset();
+ }
+
+ void RequestAudioFocus(MediaSessionImpl* session,
+ AudioFocusType audio_focus_type) {
+ session->RequestSystemAudioFocus(audio_focus_type);
+ }
+
+ void AbandonAudioFocus(MediaSessionImpl* session) {
+ session->AbandonSystemAudioFocusIfNeeded();
+ }
+
+ bool GetForceDuck(MediaSessionImpl* session) {
+ return media_session::test::GetMediaSessionInfoSync(session)->force_duck;
+ }
+
+ MediaSessionInfo::SessionState GetState(MediaSessionImpl* session) {
+ return media_session::test::GetMediaSessionInfoSync(session)->state;
+ }
+
+ bool HasMojoObservers(MediaSessionImpl* session) {
+ return !session->mojo_observers_.empty();
+ }
+
+ void FlushForTesting(MediaSessionImpl* session) {
+ session->FlushForTesting();
+ }
+
+ std::unique_ptr<WebContents> CreateWebContents() {
+ return TestWebContents::Create(
+ browser_context_.get(), SiteInstance::Create(browser_context_.get()));
+ }
+
+ std::unique_ptr<TestAudioFocusObserver> CreateAudioFocusObserver() {
+ std::unique_ptr<TestAudioFocusObserver> observer =
+ std::make_unique<TestAudioFocusObserver>();
+
+ media_session::mojom::AudioFocusObserverPtr observer_ptr;
+ observer->BindToMojoRequest(mojo::MakeRequest(&observer_ptr));
+ audio_focus_ptr_->AddObserver(std::move(observer_ptr));
+ audio_focus_ptr_.FlushForTesting();
+
+ return observer;
+ }
+
+ std::unique_ptr<MediaSessionPlayerObserver> pepper_observer_;
+
+ void SetDelegateForTests(MediaSessionImpl* session,
+ AudioFocusDelegate* delegate) {
+ session->SetDelegateForTests(base::WrapUnique(delegate));
+ }
+
+ private:
+ TestBrowserThreadBundle test_browser_thread_bundle_;
+
+ media_session::mojom::AudioFocusManagerPtr audio_focus_ptr_;
+
+ std::unique_ptr<TestServiceManagerContext> service_manager_context_;
+ std::unique_ptr<MockRenderProcessHostFactory> rph_factory_;
+ std::unique_ptr<TestBrowserContext> browser_context_;
+};
+
+TEST_F(MediaSessionImplTest, SessionInfoState) {
+ std::unique_ptr<WebContents> web_contents(CreateWebContents());
+ MediaSessionImpl* media_session = MediaSessionImpl::Get(web_contents.get());
+ EXPECT_EQ(MediaSessionInfo::SessionState::kInactive, GetState(media_session));
+
+ {
+ MockMediaSessionMojoObserver observer(media_session);
+ RequestAudioFocus(media_session, AudioFocusType::kGain);
+ FlushForTesting(media_session);
+ observer.WaitForState(MediaSessionInfo::SessionState::kActive);
+
+ EXPECT_TRUE(observer.session_info_.Equals(
+ media_session::test::GetMediaSessionInfoSync(media_session)));
+ }
+
+ {
+ MockMediaSessionMojoObserver observer(media_session);
+ media_session->StartDucking();
+ FlushForTesting(media_session);
+ observer.WaitForState(MediaSessionInfo::SessionState::kDucking);
+
+ EXPECT_TRUE(observer.session_info_.Equals(
+ media_session::test::GetMediaSessionInfoSync(media_session)));
+ }
+
+ {
+ MockMediaSessionMojoObserver observer(media_session);
+ media_session->StopDucking();
+ FlushForTesting(media_session);
+ observer.WaitForState(MediaSessionInfo::SessionState::kActive);
+
+ EXPECT_TRUE(observer.session_info_.Equals(
+ media_session::test::GetMediaSessionInfoSync(media_session)));
+ }
+
+ {
+ MockMediaSessionMojoObserver observer(media_session);
+ media_session->Suspend(MediaSession::SuspendType::kSystem);
+ FlushForTesting(media_session);
+ observer.WaitForState(MediaSessionInfo::SessionState::kSuspended);
+
+ EXPECT_TRUE(observer.session_info_.Equals(
+ media_session::test::GetMediaSessionInfoSync(media_session)));
+ }
+
+ {
+ MockMediaSessionMojoObserver observer(media_session);
+ media_session->Resume(MediaSession::SuspendType::kSystem);
+ FlushForTesting(media_session);
+ observer.WaitForState(MediaSessionInfo::SessionState::kActive);
+
+ EXPECT_TRUE(observer.session_info_.Equals(
+ media_session::test::GetMediaSessionInfoSync(media_session)));
+ }
+
+ {
+ MockMediaSessionMojoObserver observer(media_session);
+ AbandonAudioFocus(media_session);
+ FlushForTesting(media_session);
+ observer.WaitForState(MediaSessionInfo::SessionState::kInactive);
+
+ EXPECT_TRUE(observer.session_info_.Equals(
+ media_session::test::GetMediaSessionInfoSync(media_session)));
+ }
+}
+
+TEST_F(MediaSessionImplTest, NotifyDelegateOnStateChange) {
+ std::unique_ptr<WebContents> web_contents(CreateWebContents());
+ MediaSessionImpl* media_session = MediaSessionImpl::Get(web_contents.get());
+ MockAudioFocusDelegate* delegate = new MockAudioFocusDelegate();
+ SetDelegateForTests(media_session, delegate);
+
+ RequestAudioFocus(media_session, AudioFocusType::kGain);
+ EXPECT_EQ(MediaSessionInfo::SessionState::kActive, delegate->GetState());
+
+ media_session->StartDucking();
+ EXPECT_EQ(MediaSessionInfo::SessionState::kDucking, delegate->GetState());
+
+ media_session->StopDucking();
+ EXPECT_EQ(MediaSessionInfo::SessionState::kActive, delegate->GetState());
+
+ media_session->Suspend(MediaSession::SuspendType::kSystem);
+ EXPECT_EQ(MediaSessionInfo::SessionState::kSuspended, delegate->GetState());
+
+ media_session->Resume(MediaSession::SuspendType::kSystem);
+ EXPECT_EQ(MediaSessionInfo::SessionState::kActive, delegate->GetState());
+
+ AbandonAudioFocus(media_session);
+ EXPECT_EQ(MediaSessionInfo::SessionState::kInactive, delegate->GetState());
+}
+
+TEST_F(MediaSessionImplTest, PepperForcesDuckAndRequestsFocus) {
+ std::unique_ptr<WebContents> web_contents(CreateWebContents());
+ MediaSessionImpl* media_session = MediaSessionImpl::Get(web_contents.get());
+
+ media_session->AddPlayer(pepper_observer_.get(), 0,
+ media::MediaContentType::Pepper);
+
+ {
+ MockMediaSessionMojoObserver observer(media_session);
+ observer.WaitForState(MediaSessionInfo::SessionState::kActive);
+ }
+
+ EXPECT_TRUE(GetForceDuck(media_session));
+
+ media_session->RemovePlayer(pepper_observer_.get(), 0);
+
+ {
+ MockMediaSessionMojoObserver observer(media_session);
+ observer.WaitForState(MediaSessionInfo::SessionState::kInactive);
+ }
+
+ EXPECT_FALSE(GetForceDuck(media_session));
+}
+
+TEST_F(MediaSessionImplTest, RegisterMojoObserver) {
+ std::unique_ptr<WebContents> web_contents(CreateWebContents());
+ MediaSessionImpl* media_session = MediaSessionImpl::Get(web_contents.get());
+
+ EXPECT_FALSE(HasMojoObservers(media_session));
+
+ MockMediaSessionMojoObserver observer(media_session);
+ FlushForTesting(media_session);
+
+ EXPECT_TRUE(HasMojoObservers(media_session));
+}
+
+#if !defined(OS_ANDROID)
+
+TEST_F(MediaSessionImplTest, WebContentsDestroyed_ReleasesFocus) {
+ std::unique_ptr<WebContents> web_contents(CreateWebContents());
+ MediaSessionImpl* media_session = MediaSessionImpl::Get(web_contents.get());
+
+ {
+ std::unique_ptr<TestAudioFocusObserver> observer =
+ CreateAudioFocusObserver();
+ RequestAudioFocus(media_session, AudioFocusType::kGain);
+ observer->WaitForGainedEvent();
+ }
+
+ {
+ MockMediaSessionMojoObserver observer(media_session);
+ observer.WaitForState(MediaSessionInfo::SessionState::kActive);
+ }
+
+ {
+ std::unique_ptr<TestAudioFocusObserver> observer =
+ CreateAudioFocusObserver();
+ web_contents.reset();
+ observer->WaitForLostEvent();
+ }
+}
+
+TEST_F(MediaSessionImplTest, WebContentsDestroyed_ReleasesTransients) {
+ std::unique_ptr<WebContents> web_contents(CreateWebContents());
+ MediaSessionImpl* media_session = MediaSessionImpl::Get(web_contents.get());
+
+ {
+ std::unique_ptr<TestAudioFocusObserver> observer =
+ CreateAudioFocusObserver();
+ RequestAudioFocus(media_session, AudioFocusType::kGainTransientMayDuck);
+ observer->WaitForGainedEvent();
+ }
+
+ {
+ MockMediaSessionMojoObserver observer(media_session);
+ observer.WaitForState(MediaSessionInfo::SessionState::kActive);
+ }
+
+ {
+ std::unique_ptr<TestAudioFocusObserver> observer =
+ CreateAudioFocusObserver();
+ web_contents.reset();
+ observer->WaitForLostEvent();
+ }
+}
+
+TEST_F(MediaSessionImplTest, WebContentsDestroyed_StopsDucking) {
+ std::unique_ptr<WebContents> web_contents_1(CreateWebContents());
+ MediaSessionImpl* media_session_1 =
+ MediaSessionImpl::Get(web_contents_1.get());
+
+ std::unique_ptr<WebContents> web_contents_2(CreateWebContents());
+ MediaSessionImpl* media_session_2 =
+ MediaSessionImpl::Get(web_contents_2.get());
+
+ {
+ std::unique_ptr<TestAudioFocusObserver> observer =
+ CreateAudioFocusObserver();
+ RequestAudioFocus(media_session_1, AudioFocusType::kGain);
+ observer->WaitForGainedEvent();
+ }
+
+ {
+ MockMediaSessionMojoObserver observer(media_session_1);
+ observer.WaitForState(MediaSessionInfo::SessionState::kActive);
+ }
+
+ {
+ std::unique_ptr<TestAudioFocusObserver> observer =
+ CreateAudioFocusObserver();
+ RequestAudioFocus(media_session_2, AudioFocusType::kGainTransientMayDuck);
+ observer->WaitForGainedEvent();
+ }
+
+
+ {
+ MockMediaSessionMojoObserver observer(media_session_1);
+ observer.WaitForState(MediaSessionInfo::SessionState::kDucking);
+ }
+
+ {
+ std::unique_ptr<TestAudioFocusObserver> observer =
+ CreateAudioFocusObserver();
+ web_contents_2.reset();
+ observer->WaitForLostEvent();
+ }
+
+ {
+ MockMediaSessionMojoObserver observer(media_session_1);
+ observer.WaitForState(MediaSessionInfo::SessionState::kActive);
+ }
+}
+
+#endif // !defined(OS_ANDROID)
+
+} // namespace content
diff --git a/chromium/content/browser/media/webaudio/audio_context_manager_browsertest.cc b/chromium/content/browser/media/webaudio/audio_context_manager_browsertest.cc
index 9ab3e351ae6..d01bf8cbbf9 100644
--- a/chromium/content/browser/media/webaudio/audio_context_manager_browsertest.cc
+++ b/chromium/content/browser/media/webaudio/audio_context_manager_browsertest.cc
@@ -2,11 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "components/ukm/test_ukm_recorder.h"
#include "content/public/browser/web_contents_observer.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/shell/browser/shell.h"
+#include "net/dns/mock_host_resolver.h"
+#include "services/metrics/public/cpp/ukm_builders.h"
namespace content {
@@ -51,7 +54,14 @@ class WaitForAudioContextSilent : WebContentsObserver {
} // namespace
-class AudioContextManagerTest : public ContentBrowserTest {};
+class AudioContextManagerTest : public ContentBrowserTest {
+ public:
+ void SetUpOnMainThread() override {
+ host_resolver()->AddRule("*", "127.0.0.1");
+ content::SetupCrossSiteRedirector(embedded_test_server());
+ ASSERT_TRUE(embedded_test_server()->Start());
+ }
+};
IN_PROC_BROWSER_TEST_F(AudioContextManagerTest, AudioContextPlaybackRecorded) {
NavigateToURL(shell(),
@@ -72,4 +82,57 @@ IN_PROC_BROWSER_TEST_F(AudioContextManagerTest, AudioContextPlaybackRecorded) {
}
}
+IN_PROC_BROWSER_TEST_F(AudioContextManagerTest, AudioContextPlaybackTimeUkm) {
+ ukm::TestAutoSetUkmRecorder test_ukm_recorder;
+ using Entry = ukm::builders::Media_WebAudio_AudioContext_AudibleTime;
+
+ GURL url = embedded_test_server()->GetURL(
+ "example.com", "/media/webaudio/playback-test.html");
+ NavigateToURL(shell(), url);
+
+ EXPECT_EQ(0u, test_ukm_recorder.GetEntriesByName(Entry::kEntryName).size());
+
+ // Play/pause something audible, it should lead to new Ukm entry.
+ {
+ ASSERT_TRUE(ExecuteScript(shell()->web_contents(), "gain.gain.value = 1;"));
+ WaitForAudioContextAudible wait_audible(shell()->web_contents());
+
+ ASSERT_TRUE(ExecuteScript(shell()->web_contents(), "gain.gain.value = 0;"));
+ WaitForAudioContextSilent wait_silent(shell()->web_contents());
+ }
+
+ EXPECT_EQ(1u, test_ukm_recorder.GetEntriesByName(Entry::kEntryName).size());
+
+ // Playback must have been recorded.
+ {
+ auto ukm_entries = test_ukm_recorder.GetEntriesByName(Entry::kEntryName);
+
+ ASSERT_EQ(1u, ukm_entries.size());
+ auto* entry = ukm_entries[0];
+
+ // The test doesn't check the URL because not the full Ukm stack is running
+ // in //content.
+
+ EXPECT_TRUE(
+ test_ukm_recorder.EntryHasMetric(entry, Entry::kAudibleTimeName));
+ EXPECT_GE(*test_ukm_recorder.GetEntryMetric(entry, Entry::kAudibleTimeName),
+ 0);
+
+ EXPECT_TRUE(
+ test_ukm_recorder.EntryHasMetric(entry, Entry::kIsMainFrameName));
+ test_ukm_recorder.ExpectEntryMetric(entry, Entry::kIsMainFrameName, true);
+ }
+
+ // Play/pause again and check that there is a new entry.
+ {
+ ASSERT_TRUE(ExecuteScript(shell()->web_contents(), "gain.gain.value = 1;"));
+ WaitForAudioContextAudible wait_audible(shell()->web_contents());
+
+ ASSERT_TRUE(ExecuteScript(shell()->web_contents(), "gain.gain.value = 0;"));
+ WaitForAudioContextSilent wait_silent(shell()->web_contents());
+ }
+
+ EXPECT_EQ(2u, test_ukm_recorder.GetEntriesByName(Entry::kEntryName).size());
+}
+
} // namespace content
diff --git a/chromium/content/browser/media/webaudio/audio_context_manager_impl.cc b/chromium/content/browser/media/webaudio/audio_context_manager_impl.cc
index 889ccb0026a..1ed05d21f0f 100644
--- a/chromium/content/browser/media/webaudio/audio_context_manager_impl.cc
+++ b/chromium/content/browser/media/webaudio/audio_context_manager_impl.cc
@@ -4,14 +4,30 @@
#include "content/browser/media/webaudio/audio_context_manager_impl.h"
+#include "base/time/default_tick_clock.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#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 "mojo/public/cpp/bindings/strong_binding.h"
+#include "services/metrics/public/cpp/ukm_builders.h"
+#include "services/metrics/public/cpp/ukm_recorder.h"
namespace content {
+namespace {
+
+// Returns the time in milleseconds following these rules:
+// - if the time is below 10 seconds, return the raw value;
+// - otherwise, return the value rounded to the closes second.
+int64_t GetBucketedTimeInMilliseconds(const base::TimeDelta& time) {
+ if (time.InMilliseconds() < 10 * base::Time::kMillisecondsPerSecond)
+ return time.InMilliseconds();
+ return time.InSeconds() * base::Time::kMillisecondsPerSecond;
+}
+
+} // namespace
+
void AudioContextManagerImpl::Create(
RenderFrameHost* render_frame_host,
blink::mojom::AudioContextManagerRequest request) {
@@ -27,24 +43,56 @@ AudioContextManagerImpl::AudioContextManagerImpl(
blink::mojom::AudioContextManagerRequest request)
: FrameServiceBase(render_frame_host, std::move(request)),
render_frame_host_impl_(
- static_cast<RenderFrameHostImpl*>(render_frame_host)) {
+ static_cast<RenderFrameHostImpl*>(render_frame_host)),
+ clock_(base::DefaultTickClock::GetInstance()) {
DCHECK(render_frame_host);
}
-AudioContextManagerImpl::~AudioContextManagerImpl() = default;
+AudioContextManagerImpl::~AudioContextManagerImpl() {
+ // Takes care pending "audible start" times.
+ base::TimeTicks now = clock_->NowTicks();
+ for (const auto& entry : pending_audible_durations_) {
+ if (!entry.second.is_null())
+ RecordAudibleTime(now - entry.second);
+ }
+ pending_audible_durations_.clear();
+}
void AudioContextManagerImpl::AudioContextAudiblePlaybackStarted(
int32_t audio_context_id) {
- // Notify observers that audible audio started playing from a WebAudio
- // AudioContext.
+ DCHECK(pending_audible_durations_[audio_context_id].is_null());
+
+ // Keeps track of the start audible time for this context.
+ pending_audible_durations_[audio_context_id] = clock_->NowTicks();
+
render_frame_host_impl_->AudioContextPlaybackStarted(audio_context_id);
}
void AudioContextManagerImpl::AudioContextAudiblePlaybackStopped(
int32_t audio_context_id) {
- // Notify observers that audible audio stopped playing from a WebAudio
- // AudioContext.
+ base::TimeTicks then = pending_audible_durations_[audio_context_id];
+ DCHECK(!then.is_null());
+
+ RecordAudibleTime(clock_->NowTicks() - then);
+
+ // Resets the context slot because the context is not audible.
+ pending_audible_durations_[audio_context_id] = base::TimeTicks();
+
render_frame_host_impl_->AudioContextPlaybackStopped(audio_context_id);
}
+void AudioContextManagerImpl::RecordAudibleTime(base::TimeDelta audible_time) {
+ DCHECK(!audible_time.is_zero());
+
+ ukm::UkmRecorder* ukm_recorder = ukm::UkmRecorder::Get();
+ DCHECK(ukm_recorder);
+
+ ukm::builders::Media_WebAudio_AudioContext_AudibleTime(
+ static_cast<WebContentsImpl*>(web_contents())
+ ->GetUkmSourceIdForLastCommittedSource())
+ .SetIsMainFrame(web_contents()->GetMainFrame() == render_frame_host_impl_)
+ .SetAudibleTime(GetBucketedTimeInMilliseconds(audible_time))
+ .Record(ukm_recorder);
+}
+
} // namespace content
diff --git a/chromium/content/browser/media/webaudio/audio_context_manager_impl.h b/chromium/content/browser/media/webaudio/audio_context_manager_impl.h
index 06d1c6b4220..0df4d2d6c07 100644
--- a/chromium/content/browser/media/webaudio/audio_context_manager_impl.h
+++ b/chromium/content/browser/media/webaudio/audio_context_manager_impl.h
@@ -17,7 +17,10 @@ class RenderFrameHostImpl;
// Implements the mojo interface between WebAudio and the browser so that
// WebAudio can report when audible sounds from an AudioContext starts and
-// stops.
+// stops. A manager instance can be associated with multiple AudioContexts.
+//
+// We do not expect to see more than 3~4 AudioContexts per render frame, so
+// handling multiple contexts would not be a significant bottle neck.
class CONTENT_EXPORT AudioContextManagerImpl final
: public content::FrameServiceBase<blink::mojom::AudioContextManager> {
public:
@@ -29,13 +32,28 @@ class CONTENT_EXPORT AudioContextManagerImpl final
static void Create(RenderFrameHost* render_frame_host,
blink::mojom::AudioContextManagerRequest request);
- // Called when AudioContext starts or stops playing audible audio.
+ // Notify observers that audible audio started/stopped playing from an
+ // AudioContext.
void AudioContextAudiblePlaybackStarted(int32_t audio_context_id) final;
void AudioContextAudiblePlaybackStopped(int32_t audio_context_id) final;
+ void set_clock_for_testing(base::TickClock* clock) { clock_ = clock; }
+
private:
+ // Send measured audible duration to UKM database.
+ void RecordAudibleTime(base::TimeDelta);
+
RenderFrameHostImpl* const render_frame_host_impl_;
+ // To track pending audible time. Stores ID of AudioContext (int32_t) and
+ // the start time of audible period (base::TimeTicks).
+ base::flat_map<int32_t, base::TimeTicks> pending_audible_durations_;
+
+ // Clock used to calculate time between start and stop event. Can be override
+ // by tests.
+ // It is not owned by the implementation.
+ const base::TickClock* clock_;
+
DISALLOW_COPY_AND_ASSIGN(AudioContextManagerImpl);
};
diff --git a/chromium/content/browser/media/webaudio/audio_context_manager_impl_unittest.cc b/chromium/content/browser/media/webaudio/audio_context_manager_impl_unittest.cc
new file mode 100644
index 00000000000..0d229d84101
--- /dev/null
+++ b/chromium/content/browser/media/webaudio/audio_context_manager_impl_unittest.cc
@@ -0,0 +1,102 @@
+// 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/webaudio/audio_context_manager_impl.h"
+
+#include "base/test/simple_test_tick_clock.h"
+#include "components/ukm/test_ukm_recorder.h"
+#include "content/public/test/test_renderer_host.h"
+#include "services/metrics/public/cpp/ukm_builders.h"
+
+namespace content {
+
+class AudioContextManagerImplTest : public RenderViewHostTestHarness {
+ public:
+ using UkmEntry = ukm::builders::Media_WebAudio_AudioContext_AudibleTime;
+
+ void SetUp() override {
+ RenderViewHostTestHarness::SetUp();
+
+ clock_.SetNowTicks(base::TimeTicks::Now());
+
+ blink::mojom::AudioContextManagerPtr service_ptr;
+ audio_context_manager_ = new AudioContextManagerImpl(
+ main_rfh(), mojo::MakeRequest(&service_ptr));
+ audio_context_manager_->set_clock_for_testing(&clock_);
+ }
+
+ AudioContextManagerImpl* audio_context_manager() {
+ return audio_context_manager_;
+ }
+
+ const ukm::TestAutoSetUkmRecorder& test_ukm_recorder() const {
+ return test_ukm_recorder_;
+ }
+
+ base::SimpleTestTickClock& clock() { return clock_; }
+
+ private:
+ AudioContextManagerImpl* audio_context_manager_ = nullptr;
+ ukm::TestAutoSetUkmRecorder test_ukm_recorder_;
+ base::SimpleTestTickClock clock_;
+};
+
+TEST_F(AudioContextManagerImplTest, TimeBelow10SecondsIsRaw) {
+ // Entry for 42 milliseconds.
+ audio_context_manager()->AudioContextAudiblePlaybackStarted(0);
+ clock().Advance(base::TimeDelta::FromMilliseconds(42));
+ audio_context_manager()->AudioContextAudiblePlaybackStopped(0);
+
+ // Entry for 4242 milliseconds.
+ audio_context_manager()->AudioContextAudiblePlaybackStarted(0);
+ clock().Advance(base::TimeDelta::FromMilliseconds(4242));
+ audio_context_manager()->AudioContextAudiblePlaybackStopped(0);
+
+ // Entry for 9999 milliseconds.
+ audio_context_manager()->AudioContextAudiblePlaybackStarted(0);
+ clock().Advance(base::TimeDelta::FromMilliseconds(9999));
+ audio_context_manager()->AudioContextAudiblePlaybackStopped(0);
+
+ auto ukm_entries = test_ukm_recorder().GetEntriesByName(UkmEntry::kEntryName);
+ EXPECT_EQ(3u, ukm_entries.size());
+
+ const std::vector<int> expected = {42, 4242, 9999};
+ for (size_t i = 0; i < expected.size(); ++i) {
+ EXPECT_EQ(expected[i], *test_ukm_recorder().GetEntryMetric(
+ ukm_entries[i], UkmEntry::kAudibleTimeName));
+ }
+}
+
+TEST_F(AudioContextManagerImplTest, TimeGreater10SecondsIsRoundedDown) {
+ // Entry for 42 seconds.
+ audio_context_manager()->AudioContextAudiblePlaybackStarted(0);
+ clock().Advance(base::TimeDelta::FromSeconds(42));
+ audio_context_manager()->AudioContextAudiblePlaybackStopped(0);
+
+ // Entry for 42.42 seconds.
+ audio_context_manager()->AudioContextAudiblePlaybackStarted(0);
+ clock().Advance(base::TimeDelta::FromSecondsD(42.42));
+ audio_context_manager()->AudioContextAudiblePlaybackStopped(0);
+
+ // Entry for 10.01 seconds.
+ audio_context_manager()->AudioContextAudiblePlaybackStarted(0);
+ clock().Advance(base::TimeDelta::FromSecondsD(10.01));
+ audio_context_manager()->AudioContextAudiblePlaybackStopped(0);
+
+ // Entry for 10.99 seconds.
+ audio_context_manager()->AudioContextAudiblePlaybackStarted(0);
+ clock().Advance(base::TimeDelta::FromSecondsD(10.99));
+ audio_context_manager()->AudioContextAudiblePlaybackStopped(0);
+
+ auto ukm_entries = test_ukm_recorder().GetEntriesByName(UkmEntry::kEntryName);
+ EXPECT_EQ(4u, ukm_entries.size());
+
+ const std::vector<int> expected = {42000, 42000, 10000, 10000};
+ for (size_t i = 0; i < expected.size(); ++i) {
+ EXPECT_EQ(expected[i], *test_ukm_recorder().GetEntryMetric(
+ ukm_entries[i], UkmEntry::kAudibleTimeName));
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/browser/memory/memory_coordinator_impl_browsertest.cc b/chromium/content/browser/memory/memory_coordinator_impl_browsertest.cc
index 3a84581863b..730dae4272c 100644
--- a/chromium/content/browser/memory/memory_coordinator_impl_browsertest.cc
+++ b/chromium/content/browser/memory/memory_coordinator_impl_browsertest.cc
@@ -4,10 +4,12 @@
#include "content/browser/memory/memory_coordinator_impl.h"
+#include "base/task/post_task.h"
#include "base/test/scoped_feature_list.h"
#include "content/browser/browser_main_loop.h"
#include "content/browser/gpu/gpu_process_host.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/common/content_features.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
@@ -45,8 +47,8 @@ IN_PROC_BROWSER_TEST_F(MemoryCoordinatorImplBrowserTest, HandleAdded) {
// Query the GPU process ID from the IO thread.
int gpu_process_id = -1;
base::WaitableEvent io_event;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&GetGpuProcessIDOnIO, &gpu_process_id, &io_event));
io_event.Wait();
ASSERT_NE(gpu_process_id, -1);
diff --git a/chromium/content/browser/memory/memory_monitor_android.cc b/chromium/content/browser/memory/memory_monitor_android.cc
index 64ddf5ba53d..4125dff458a 100644
--- a/chromium/content/browser/memory/memory_monitor_android.cc
+++ b/chromium/content/browser/memory/memory_monitor_android.cc
@@ -5,8 +5,8 @@
#include "content/browser/memory/memory_monitor_android.h"
#include "base/android/jni_android.h"
+#include "base/memory/memory_pressure_listener.h"
#include "base/memory/ptr_util.h"
-#include "content/browser/memory/memory_coordinator_impl.h"
#include "jni/MemoryMonitorAndroid_jni.h"
namespace content {
@@ -69,12 +69,10 @@ static void JNI_MemoryMonitorAndroid_OnTrimMemory(
const base::android::JavaParamRef<jclass>& jcaller,
jint level) {
DCHECK(level >= 0 && level <= kTrimMemoryLevelMax);
- auto* coordinator = MemoryCoordinatorImpl::GetInstance();
- DCHECK(coordinator);
if (level >= kTrimMemoryRunningCritical) {
- coordinator->ForceSetMemoryCondition(MemoryCondition::CRITICAL,
- base::TimeDelta::FromMinutes(1));
+ base::MemoryPressureListener::NotifyMemoryPressure(
+ base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
}
}
@@ -88,10 +86,6 @@ MemoryMonitorAndroid::MemoryMonitorAndroid(std::unique_ptr<Delegate> delegate)
: delegate_(std::move(delegate)) {
DCHECK(delegate_.get());
RegisterComponentCallbacks();
- application_state_listener_ =
- std::make_unique<base::android::ApplicationStatusListener>(
- base::Bind(&MemoryMonitorAndroid::OnApplicationStateChange,
- base::Unretained(this)));
}
MemoryMonitorAndroid::~MemoryMonitorAndroid() {}
@@ -106,19 +100,6 @@ void MemoryMonitorAndroid::GetMemoryInfo(MemoryInfo* out) {
delegate_->GetMemoryInfo(out);
}
-void MemoryMonitorAndroid::OnApplicationStateChange(
- base::android::ApplicationState state) {
- auto* coordinator = MemoryCoordinatorImpl::GetInstance();
- if (!coordinator)
- return;
-
- if (state == base::android::APPLICATION_STATE_HAS_RUNNING_ACTIVITIES) {
- coordinator->OnForegrounded();
- } else if (state == base::android::APPLICATION_STATE_HAS_PAUSED_ACTIVITIES) {
- coordinator->OnBackgrounded();
- }
-}
-
// Implementation of a factory function defined in memory_monitor.h.
std::unique_ptr<MemoryMonitor> CreateMemoryMonitor() {
return MemoryMonitorAndroid::Create();
diff --git a/chromium/content/browser/memory/memory_monitor_android.h b/chromium/content/browser/memory/memory_monitor_android.h
index 7f06897a6d9..2e123672e6a 100644
--- a/chromium/content/browser/memory/memory_monitor_android.h
+++ b/chromium/content/browser/memory/memory_monitor_android.h
@@ -47,11 +47,7 @@ class CONTENT_EXPORT MemoryMonitorAndroid : public MemoryMonitor {
Delegate* delegate() { return delegate_.get(); }
private:
- void OnApplicationStateChange(base::android::ApplicationState state);
-
std::unique_ptr<Delegate> delegate_;
- std::unique_ptr<base::android::ApplicationStatusListener>
- application_state_listener_;
DISALLOW_COPY_AND_ASSIGN(MemoryMonitorAndroid);
};
diff --git a/chromium/content/browser/memory/memory_monitor_win.cc b/chromium/content/browser/memory/memory_monitor_win.cc
index bf336c16ee2..979bb287ae7 100644
--- a/chromium/content/browser/memory/memory_monitor_win.cc
+++ b/chromium/content/browser/memory/memory_monitor_win.cc
@@ -15,10 +15,6 @@ namespace {
const int kKBperMB = 1024;
-// A global static instance of the default delegate. Used by default by
-// MemoryMonitorWin.
-MemoryMonitorDelegate g_memory_monitor_win_delegate;
-
} // namespace
// A system is considered 'large memory' if it has more than 1.5GB of system
@@ -73,7 +69,7 @@ int MemoryMonitorWin::GetTargetFreeMB(MemoryMonitorDelegate* delegate) {
// Implementation of factory function defined in memory_monitor.h.
std::unique_ptr<MemoryMonitor> CreateMemoryMonitor() {
- return MemoryMonitorWin::Create(&g_memory_monitor_win_delegate);
+ return MemoryMonitorWin::Create(MemoryMonitorDelegate::GetInstance());
}
} // namespace content
diff --git a/chromium/content/browser/message_port_provider.cc b/chromium/content/browser/message_port_provider.cc
index e5d8f6681d5..70893810d98 100644
--- a/chromium/content/browser/message_port_provider.cc
+++ b/chromium/content/browser/message_port_provider.cc
@@ -9,7 +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"
+#include "third_party/blink/public/common/messaging/string_message_codec.h"
#if defined(OS_ANDROID)
#include "base/android/jni_string.h"
diff --git a/chromium/content/browser/mojo_sandbox_browsertest.cc b/chromium/content/browser/mojo_sandbox_browsertest.cc
index 89168cc96c9..05cbca2b0cb 100644
--- a/chromium/content/browser/mojo_sandbox_browsertest.cc
+++ b/chromium/content/browser/mojo_sandbox_browsertest.cc
@@ -9,8 +9,10 @@
#include "base/bind.h"
#include "base/macros.h"
#include "base/run_loop.h"
+#include "base/task/post_task.h"
#include "content/browser/utility_process_host.h"
#include "content/browser/utility_process_host_client.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/bind_interface_helpers.h"
#include "content/public/test/content_browser_test.h"
@@ -28,8 +30,8 @@ class MojoSandboxTest : public ContentBrowserTest {
void SetUpOnMainThread() override {
base::RunLoop run_loop;
- BrowserThread::PostTaskAndReply(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraitsAndReply(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&MojoSandboxTest::StartUtilityProcessOnIoThread,
base::Unretained(this)),
run_loop.QuitClosure());
@@ -38,8 +40,8 @@ class MojoSandboxTest : public ContentBrowserTest {
void TearDownOnMainThread() override {
base::RunLoop run_loop;
- BrowserThread::PostTaskAndReply(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraitsAndReply(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&MojoSandboxTest::StopUtilityProcessOnIoThread,
base::Unretained(this)),
run_loop.QuitClosure());
diff --git a/chromium/content/browser/browser_side_navigation_browsertest.cc b/chromium/content/browser/navigation_browsertest.cc
index 852370df647..64be3e158be 100644
--- a/chromium/content/browser/browser_side_navigation_browsertest.cc
+++ b/chromium/content/browser/navigation_browsertest.cc
@@ -8,6 +8,7 @@
#include "base/files/scoped_temp_dir.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/task/post_task.h"
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "content/browser/child_process_security_policy_impl.h"
@@ -16,7 +17,10 @@
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/frame_messages.h"
+#include "content/common/view_messages.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_message_filter.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/download_manager_delegate.h"
#include "content/public/browser/navigation_controller.h"
@@ -136,33 +140,52 @@ class NavigationRecorder : public WebContentsObserver {
std::vector<std::string> records_;
};
+// Used to wait for an observed IPC to be received.
+class BrowserMessageObserver : public content::BrowserMessageFilter {
+ public:
+ BrowserMessageObserver(uint32_t observed_message_class,
+ uint32_t observed_message_type)
+ : content::BrowserMessageFilter(observed_message_class),
+ observed_message_type_(observed_message_type) {}
+
+ bool OnMessageReceived(const IPC::Message& message) override {
+ if (message.type() == observed_message_type_)
+ loop.Quit();
+ return false;
+ }
+
+ void Wait() { loop.Run(); }
+
+ private:
+ ~BrowserMessageObserver() override {}
+ uint32_t observed_message_type_;
+ base::RunLoop loop;
+ DISALLOW_COPY_AND_ASSIGN(BrowserMessageObserver);
+};
+
} // namespace
-// Test with BrowserSideNavigation enabled (aka PlzNavigate).
+// Test about navigation.
// If you don't need a custom embedded test server, please use the next class
-// below (BrowserSideNavigationBrowserTest), it will automatically start the
+// below (NavigationBrowserTest), it will automatically start the
// default server.
-// TODO(clamy): Rename those NavigationBrowserTests.
-class BrowserSideNavigationBaseBrowserTest : public ContentBrowserTest {
+class NavigationBaseBrowserTest : public ContentBrowserTest {
protected:
void SetUpOnMainThread() override {
host_resolver()->AddRule("*", "127.0.0.1");
}
};
-class BrowserSideNavigationBrowserTest
- : public BrowserSideNavigationBaseBrowserTest {
+class NavigationBrowserTest : public NavigationBaseBrowserTest {
protected:
void SetUpOnMainThread() override {
- BrowserSideNavigationBaseBrowserTest::SetUpOnMainThread();
+ NavigationBaseBrowserTest::SetUpOnMainThread();
ASSERT_TRUE(embedded_test_server()->Start());
}
};
-// Ensure that browser initiated basic navigations work with browser side
-// navigation.
-IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBrowserTest,
- BrowserInitiatedNavigations) {
+// Ensure that browser initiated basic navigations work.
+IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, BrowserInitiatedNavigations) {
// Perform a navigation with no live renderer.
{
TestNavigationObserver observer(shell()->web_contents());
@@ -174,7 +197,9 @@ IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBrowserTest,
RenderFrameHost* initial_rfh =
static_cast<WebContentsImpl*>(shell()->web_contents())
- ->GetFrameTree()->root()->current_frame_host();
+ ->GetFrameTree()
+ ->root()
+ ->current_frame_host();
// Perform a same site navigation.
{
@@ -187,7 +212,9 @@ IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBrowserTest,
// The RenderFrameHost should not have changed.
EXPECT_EQ(initial_rfh, static_cast<WebContentsImpl*>(shell()->web_contents())
- ->GetFrameTree()->root()->current_frame_host());
+ ->GetFrameTree()
+ ->root()
+ ->current_frame_host());
// Perform a cross-site navigation.
{
@@ -200,12 +227,13 @@ IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBrowserTest,
// The RenderFrameHost should have changed.
EXPECT_NE(initial_rfh, static_cast<WebContentsImpl*>(shell()->web_contents())
- ->GetFrameTree()->root()->current_frame_host());
+ ->GetFrameTree()
+ ->root()
+ ->current_frame_host());
}
-// Ensure that renderer initiated same-site navigations work with browser side
-// navigation.
-IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBrowserTest,
+// Ensure that renderer initiated same-site navigations work.
+IN_PROC_BROWSER_TEST_F(NavigationBrowserTest,
RendererInitiatedSameSiteNavigation) {
// Perform a navigation with no live renderer.
{
@@ -218,7 +246,9 @@ IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBrowserTest,
RenderFrameHost* initial_rfh =
static_cast<WebContentsImpl*>(shell()->web_contents())
- ->GetFrameTree()->root()->current_frame_host();
+ ->GetFrameTree()
+ ->root()
+ ->current_frame_host();
// Simulate clicking on a same-site link.
{
@@ -236,12 +266,13 @@ IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBrowserTest,
// The RenderFrameHost should not have changed.
EXPECT_EQ(initial_rfh, static_cast<WebContentsImpl*>(shell()->web_contents())
- ->GetFrameTree()->root()->current_frame_host());
+ ->GetFrameTree()
+ ->root()
+ ->current_frame_host());
}
-// Ensure that renderer initiated cross-site navigations work with browser side
-// navigation.
-IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBrowserTest,
+// Ensure that renderer initiated cross-site navigations work.
+IN_PROC_BROWSER_TEST_F(NavigationBrowserTest,
RendererInitiatedCrossSiteNavigation) {
// Perform a navigation with no live renderer.
{
@@ -254,13 +285,15 @@ IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBrowserTest,
RenderFrameHost* initial_rfh =
static_cast<WebContentsImpl*>(shell()->web_contents())
- ->GetFrameTree()->root()->current_frame_host();
+ ->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));";
+ "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;
@@ -294,8 +327,8 @@ IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBrowserTest,
}
}
-// Ensure that browser side navigation handles navigation failures.
-IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBrowserTest, FailedNavigation) {
+// Ensure navigation failures are handled.
+IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, FailedNavigation) {
// Perform a navigation with no live renderer.
{
TestNavigationObserver observer(shell()->web_contents());
@@ -309,8 +342,8 @@ IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBrowserTest, FailedNavigation) {
{
TestNavigationObserver observer(shell()->web_contents());
GURL error_url(embedded_test_server()->GetURL("/close-socket"));
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&net::URLRequestFailedJob::AddUrlHandler));
NavigateToURL(shell(), error_url);
EXPECT_EQ(error_url, observer.last_navigation_url());
@@ -320,9 +353,8 @@ IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBrowserTest, FailedNavigation) {
}
}
-// Ensure that browser side navigation can load browser initiated navigations
-// to view-source URLs.
-IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBrowserTest,
+// Ensure that browser initiated navigations to view-source URLs works.
+IN_PROC_BROWSER_TEST_F(NavigationBrowserTest,
ViewSourceNavigation_BrowserInitiated) {
TestNavigationObserver observer(shell()->web_contents());
GURL url(embedded_test_server()->GetURL("/title1.html"));
@@ -333,9 +365,8 @@ IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBrowserTest,
EXPECT_TRUE(observer.last_navigation_succeeded());
}
-// Ensure that browser side navigation blocks content initiated navigations to
-// view-source URLs.
-IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBrowserTest,
+// Ensure that content initiated navigations to view-sources URLs are blocked.
+IN_PROC_BROWSER_TEST_F(NavigationBrowserTest,
ViewSourceNavigation_RendererInitiated) {
TestNavigationObserver observer(shell()->web_contents());
GURL kUrl(embedded_test_server()->GetURL("/simple_links.html"));
@@ -366,21 +397,20 @@ IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBrowserTest,
// Ensure that closing a page by running its beforeunload handler doesn't hang
// if there's an ongoing navigation.
-IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBrowserTest,
- UnloadDuringNavigation) {
+IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, UnloadDuringNavigation) {
content::WindowedNotificationObserver close_observer(
content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
content::Source<content::WebContents>(shell()->web_contents()));
GURL url("chrome://resources/css/tabs.css");
NavigationHandleObserver handle_observer(shell()->web_contents(), url);
shell()->LoadURL(url);
- shell()->web_contents()->DispatchBeforeUnload();
+ shell()->web_contents()->DispatchBeforeUnload(false /* auto_cancel */);
close_observer.Wait();
EXPECT_EQ(net::ERR_ABORTED, handle_observer.net_error_code());
}
// Ensure that the referrer of a navigation is properly sanitized.
-IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBrowserTest, SanitizeReferrer) {
+IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, SanitizeReferrer) {
const GURL kInsecureUrl(embedded_test_server()->GetURL("/title1.html"));
const Referrer kSecureReferrer(
GURL("https://secure-url.com"),
@@ -412,8 +442,7 @@ IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBrowserTest, SanitizeReferrer) {
// Test to verify that an exploited renderer process trying to upload a file
// it hasn't been explicitly granted permissions to is correctly terminated.
-IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBrowserTest,
- PostUploadIllegalFilePath) {
+IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, PostUploadIllegalFilePath) {
GURL form_url(
embedded_test_server()->GetURL("/form_that_posts_to_echoall.html"));
EXPECT_TRUE(NavigateToURL(shell(), form_url));
@@ -475,7 +504,7 @@ IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBrowserTest,
// based on Blink's state instead of the history state in the browser process,
// which ends up loading the originally blocked URL. With PlzNavigate, the
// reload uses the NavigationEntry state to create a navigation and commit it.
-IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBrowserTest,
+IN_PROC_BROWSER_TEST_F(NavigationBrowserTest,
VerifyBlockedErrorPageURL_Reload) {
NavigationControllerImpl& controller = static_cast<NavigationControllerImpl&>(
shell()->web_contents()->GetController());
@@ -507,17 +536,16 @@ IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBrowserTest,
controller.GetLastCommittedEntry()->GetVirtualURL());
}
-class BrowserSideNavigationBrowserDisableWebSecurityTest
- : public BrowserSideNavigationBrowserTest {
+class NavigationDisableWebSecurityTest : public NavigationBrowserTest {
public:
- BrowserSideNavigationBrowserDisableWebSecurityTest() {}
+ NavigationDisableWebSecurityTest() {}
protected:
void SetUpCommandLine(base::CommandLine* command_line) override {
// Simulate a compromised renderer, otherwise the cross-origin request to
// file: is blocked.
command_line->AppendSwitch(switches::kDisableWebSecurity);
- BrowserSideNavigationBrowserTest::SetUpCommandLine(command_line);
+ NavigationBrowserTest::SetUpCommandLine(command_line);
}
};
@@ -527,7 +555,7 @@ class BrowserSideNavigationBrowserDisableWebSecurityTest
// TODO(nasko): This test case belongs better in
// security_exploit_browsertest.cc, so move it there once PlzNavigate is on
// by default.
-IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBrowserDisableWebSecurityTest,
+IN_PROC_BROWSER_TEST_F(NavigationDisableWebSecurityTest,
ValidateBaseUrlForDataUrl) {
GURL start_url(embedded_test_server()->GetURL("/title1.html"));
EXPECT_TRUE(NavigateToURL(shell(), start_url));
@@ -557,14 +585,13 @@ IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBrowserDisableWebSecurityTest,
GURL() /* history_url_for_data_url */, PREVIEWS_UNSPECIFIED,
base::TimeTicks::Now() /* navigation_start */, "GET",
nullptr /* post_data */, base::Optional<SourceLocation>(),
- CSPDisposition::CHECK, false /* started_from_context_menu */,
- false /* has_user_gesture */,
- std::vector<ContentSecurityPolicy>() /* initiator_csp */,
- CSPSource() /* initiator_self_source */);
+ false /* started_from_context_menu */, false /* has_user_gesture */,
+ InitiatorCSPInfo());
mojom::BeginNavigationParamsPtr begin_params =
mojom::BeginNavigationParams::New(
std::string() /* headers */, net::LOAD_NORMAL,
- false /* skip_service_worker */, REQUEST_CONTEXT_TYPE_LOCATION,
+ false /* skip_service_worker */,
+ blink::mojom::RequestContextType::LOCATION,
blink::WebMixedContentContextType::kBlockable,
false /* is_form_submission */, GURL() /* searchable_form_url */,
std::string() /* searchable_form_encoding */,
@@ -581,10 +608,10 @@ IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBrowserDisableWebSecurityTest,
mojo::MakeRequestAssociatedWithDedicatedPipe(&navigation_client);
rfh->frame_host_binding_for_testing().impl()->BeginNavigation(
common_params, std::move(begin_params), nullptr,
- navigation_client.PassInterface());
+ navigation_client.PassInterface(), nullptr);
} else {
rfh->frame_host_binding_for_testing().impl()->BeginNavigation(
- common_params, std::move(begin_params), nullptr, nullptr);
+ common_params, std::move(begin_params), nullptr, nullptr, nullptr);
}
EXPECT_EQ(bad_message::RFH_BASE_URL_FOR_DATA_URL_SPECIFIED,
process_kill_waiter.Wait());
@@ -610,7 +637,7 @@ IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBrowserDisableWebSecurityTest,
EXPECT_TRUE(result.empty());
}
-IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBrowserTest, BackFollowedByReload) {
+IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, BackFollowedByReload) {
// First, make two history entries.
GURL url1(embedded_test_server()->GetURL("/title1.html"));
GURL url2(embedded_test_server()->GetURL("/title2.html"));
@@ -630,7 +657,7 @@ IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBrowserTest, BackFollowedByReload) {
// Test that a navigation response can be entirely fetched, even after the
// NavigationURLLoader has been deleted.
-IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBaseBrowserTest,
+IN_PROC_BROWSER_TEST_F(NavigationBaseBrowserTest,
FetchResponseAfterNavigationURLLoaderDeleted) {
net::test_server::ControllableHttpResponse response(embedded_test_server(),
"/main_document");
@@ -678,11 +705,11 @@ IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBaseBrowserTest,
}
// Navigation are started in the browser process. After the headers are
-// received, the URLLoaderClient is transfered from the browser process to the
+// received, the URLLoaderClient is transferred from the browser process to the
// renderer process. This test ensures that when the the URLLoader is deleted
// (in the browser process), the URLLoaderClient (in the renderer process) stops
// properly.
-IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBaseBrowserTest,
+IN_PROC_BROWSER_TEST_F(NavigationBaseBrowserTest,
CancelRequestAfterReadyToCommit) {
// This test cancels the request using the ResourceDispatchHost. With the
// NetworkService, it is not used so the request is not canceled.
@@ -728,8 +755,8 @@ IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBaseBrowserTest,
static_cast<ResourceDispatcherHostImpl*>(ResourceDispatcherHost::Get());
rdh->CancelRequest(global_id.child_id, global_id.request_id);
};
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::BindOnce(cancel_request, global_id));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(cancel_request, global_id));
// 3) Check that the load stops properly.
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
@@ -737,8 +764,7 @@ IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBaseBrowserTest,
// 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,
- DataURLWithReferenceFragment) {
+IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, DataURLWithReferenceFragment) {
GURL url("data:text/html,body#foo");
EXPECT_TRUE(NavigateToURL(shell(), url));
@@ -762,7 +788,7 @@ IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBrowserTest,
// 1) Start on a document with history.length == 1.
// 2) Create an iframe and call history.pushState at the same time.
// 3) history.back() must work.
-IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBrowserTest,
+IN_PROC_BROWSER_TEST_F(NavigationBrowserTest,
IframeAndPushStateSimultaneously) {
GURL main_url = embedded_test_server()->GetURL("/simple_page.html");
GURL iframe_url = embedded_test_server()->GetURL("/hello.html");
@@ -809,7 +835,7 @@ IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBrowserTest,
// Regression test for https://crbug.com/260144
// Back/Forward navigation in an iframe must not stop ongoing XHR.
-IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBaseBrowserTest,
+IN_PROC_BROWSER_TEST_F(NavigationBaseBrowserTest,
IframeNavigationsDoNotStopXHR) {
// A response for the XHR request. It will be delayed until the end of all the
// navigations.
@@ -898,7 +924,7 @@ IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBaseBrowserTest,
}
// Regression test for https://crbug.com/856396.
-IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBaseBrowserTest,
+IN_PROC_BROWSER_TEST_F(NavigationBaseBrowserTest,
ReplacingDocumentLoaderFiresLoadEvent) {
net::test_server::ControllableHttpResponse main_document_response(
embedded_test_server(), "/main_document");
@@ -952,11 +978,10 @@ IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBaseBrowserTest,
}
}
-class NavigationDownloadBrowserTest
- : public BrowserSideNavigationBaseBrowserTest {
+class NavigationDownloadBrowserTest : public NavigationBaseBrowserTest {
protected:
void SetUpOnMainThread() override {
- BrowserSideNavigationBaseBrowserTest::SetUpOnMainThread();
+ NavigationBaseBrowserTest::SetUpOnMainThread();
// Set up a test download directory, in order to prevent prompting for
// handling downloads.
@@ -1028,7 +1053,7 @@ IN_PROC_BROWSER_TEST_F(NavigationDownloadBrowserTest,
// 4) The browser gets notified of the commit of the first navigation. This
// should not destroy the NavigationRequest corresponding to the second
// navigation.
-IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBrowserTest,
+IN_PROC_BROWSER_TEST_F(NavigationBrowserTest,
RaceNewNavigationCommitWhileOldOneFinishesLoading) {
// Start the test with an initial document.
GURL main_url(embedded_test_server()->GetURL("/simple_page.html"));
@@ -1100,4 +1125,95 @@ IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBrowserTest,
recorder.records()[5].c_str());
}
+// Renderer initiated back/forward navigation in beforeunload should not prevent
+// the user to navigate away from a website.
+IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, HistoryBackInBeforeUnload) {
+ GURL url_1(embedded_test_server()->GetURL("/title1.html"));
+ GURL url_2(embedded_test_server()->GetURL("/title2.html"));
+
+ EXPECT_TRUE(NavigateToURL(shell(), url_1));
+ EXPECT_TRUE(ExecuteScript(shell()->web_contents(),
+ "onbeforeunload = function() {"
+ " history.pushState({}, null, '/');"
+ " history.back();"
+ "};"));
+ EXPECT_TRUE(NavigateToURL(shell(), url_2));
+}
+
+// Same as 'HistoryBackInBeforeUnload', but wraps history.back() inside
+// window.setTimeout(). Thus it is executed "outside" of its beforeunload
+// handler and thus avoid basic navigation circumventions.
+// Regression test for: https://crbug.com/879965.
+IN_PROC_BROWSER_TEST_F(NavigationBrowserTest,
+ HistoryBackInBeforeUnloadAfterSetTimeout) {
+ GURL url_1(embedded_test_server()->GetURL("/title1.html"));
+ GURL url_2(embedded_test_server()->GetURL("/title2.html"));
+
+ EXPECT_TRUE(NavigateToURL(shell(), url_1));
+ EXPECT_TRUE(ExecuteScript(shell()->web_contents(),
+ "onbeforeunload = function() {"
+ " history.pushState({}, null, '/');"
+ " setTimeout(()=>history.back());"
+ "};"));
+ TestNavigationManager navigation(shell()->web_contents(), url_2);
+ auto ipc_observer = base::MakeRefCounted<BrowserMessageObserver>(
+ ViewMsgStart, ViewHostMsg_GoToEntryAtOffset::ID);
+ static_cast<RenderFrameHostImpl*>(shell()->web_contents()->GetMainFrame())
+ ->GetProcess()
+ ->AddFilter(ipc_observer.get());
+
+ shell()->LoadURL(url_2);
+ ipc_observer->Wait();
+ navigation.WaitForNavigationFinished();
+
+ EXPECT_TRUE(navigation.was_successful());
+}
+
+// Renderer initiated back/forward navigation can't cancel an ongoing browser
+// initiated navigation if it is not user initiated.
+IN_PROC_BROWSER_TEST_F(NavigationBrowserTest,
+ HistoryBackCancelPendingNavigationNoUserGesture) {
+ GURL url_1(embedded_test_server()->GetURL("/title1.html"));
+ GURL url_2(embedded_test_server()->GetURL("/title2.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), url_1));
+
+ // 1) A pending browser initiated navigation (omnibox, ...) starts.
+ TestNavigationManager navigation(shell()->web_contents(), url_2);
+ shell()->LoadURL(url_2);
+ EXPECT_TRUE(navigation.WaitForRequestStart());
+
+ // 2) history.back() is sent but is not user initiated.
+ EXPECT_TRUE(
+ ExecuteScriptWithoutUserGesture(shell()->web_contents(),
+ "history.pushState({}, null, '/');"
+ "history.back();"));
+
+ // 3) The first pending navigation is not canceled and can continue.
+ navigation.WaitForNavigationFinished(); // Resume navigation.
+ EXPECT_TRUE(navigation.was_successful());
+}
+
+// Renderer initiated back/forward navigation can cancel an ongoing browser
+// initiated navigation if it is user initiated.
+IN_PROC_BROWSER_TEST_F(NavigationBrowserTest,
+ HistoryBackCancelPendingNavigationUserGesture) {
+ GURL url_1(embedded_test_server()->GetURL("/title1.html"));
+ GURL url_2(embedded_test_server()->GetURL("/title2.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), url_1));
+
+ // 1) A pending browser initiated navigation (omnibox, ...) starts.
+ TestNavigationManager navigation(shell()->web_contents(), url_2);
+ shell()->LoadURL(url_2);
+ EXPECT_TRUE(navigation.WaitForRequestStart());
+
+ // 2) history.back() is sent and is user initiated.
+ EXPECT_TRUE(ExecuteScript(shell()->web_contents(),
+ "history.pushState({}, null, '/');"
+ "history.back();"));
+
+ // 3) Check the first pending navigation has been canceled.
+ navigation.WaitForNavigationFinished(); // Resume navigation.
+ EXPECT_FALSE(navigation.was_successful());
+}
+
} // namespace content
diff --git a/chromium/content/browser/net/network_quality_observer_impl.cc b/chromium/content/browser/net/network_quality_observer_impl.cc
index dafe9179271..6aecc4332e4 100644
--- a/chromium/content/browser/net/network_quality_observer_impl.cc
+++ b/chromium/content/browser/net/network_quality_observer_impl.cc
@@ -5,15 +5,14 @@
#include "content/browser/net/network_quality_observer_impl.h"
#include "base/metrics/histogram_macros.h"
-#include "content/browser/renderer_host/render_process_host_impl.h"
+#include "content/common/renderer.mojom.h"
#include "content/common/view_messages.h"
#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/network_quality_observer_factory.h"
#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/render_process_host.h"
-#include "net/nqe/network_quality_estimator.h"
namespace {
@@ -57,121 +56,22 @@ bool MetricChangedMeaningfully(int32_t past_value, int32_t current_value) {
namespace content {
-// UiThreadObserver observes the changes to the network quality on the UI
-// thread, and notifies the renderers of the change in the network quality.
-class NetworkQualityObserverImpl::UiThreadObserver
- : public content::NotificationObserver {
- public:
- UiThreadObserver()
- : last_notified_type_(net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN) {}
-
- ~UiThreadObserver() override {
- if (!registrar_.IsRegistered(this, NOTIFICATION_RENDERER_PROCESS_CREATED,
- NotificationService::AllSources())) {
- return;
- }
- registrar_.Remove(this, NOTIFICATION_RENDERER_PROCESS_CREATED,
- NotificationService::AllSources());
- }
-
- void InitOnUIThread() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_CREATED,
- NotificationService::AllSources());
- }
-
- void OnEffectiveConnectionTypeChanged(net::EffectiveConnectionType type) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
- if (last_notified_type_ == type)
- return;
-
- last_notified_type_ = type;
-
- // Notify all the existing renderers of the change in the network quality.
- for (RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator());
- !it.IsAtEnd(); it.Advance()) {
- if (it.GetCurrentValue()->IsInitializedAndNotDead()) {
- it.GetCurrentValue()->GetRendererInterface()->OnNetworkQualityChanged(
- last_notified_type_, last_notified_network_quality_.http_rtt(),
- last_notified_network_quality_.transport_rtt(),
- last_notified_network_quality_.downstream_throughput_kbps());
- }
- }
- }
-
- void OnRTTOrThroughputEstimatesComputed(
- const net::nqe::internal::NetworkQuality& network_quality) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
- last_notified_network_quality_ = network_quality;
-
- // Notify all the existing renderers of the change in the network quality.
- for (RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator());
- !it.IsAtEnd(); it.Advance()) {
- if (it.GetCurrentValue()->IsInitializedAndNotDead()) {
- it.GetCurrentValue()->GetRendererInterface()->OnNetworkQualityChanged(
- last_notified_type_, last_notified_network_quality_.http_rtt(),
- last_notified_network_quality_.transport_rtt(),
- last_notified_network_quality_.downstream_throughput_kbps());
- }
- }
- }
-
- private:
- // NotificationObserver implementation:
- void Observe(int type,
- const NotificationSource& source,
- const NotificationDetails& details) override {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- DCHECK_EQ(NOTIFICATION_RENDERER_PROCESS_CREATED, type);
-
- RenderProcessHost* rph = Source<RenderProcessHost>(source).ptr();
-
- // Notify the newly created renderer of the current network quality.
- rph->GetRendererInterface()->OnNetworkQualityChanged(
- last_notified_type_, last_notified_network_quality_.http_rtt(),
- last_notified_network_quality_.transport_rtt(),
- last_notified_network_quality_.downstream_throughput_kbps());
- }
-
- content::NotificationRegistrar registrar_;
-
- // The network quality that was last sent to the renderers.
- net::EffectiveConnectionType last_notified_type_;
- net::nqe::internal::NetworkQuality last_notified_network_quality_;
-
- DISALLOW_COPY_AND_ASSIGN(UiThreadObserver);
-};
-
NetworkQualityObserverImpl::NetworkQualityObserverImpl(
- net::NetworkQualityEstimator* network_quality_estimator)
- : network_quality_estimator_(network_quality_estimator),
+ network::NetworkQualityTracker* network_quality_tracker)
+ : network_quality_tracker_(network_quality_tracker),
last_notified_type_(net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN) {
- network_quality_estimator_->AddRTTAndThroughputEstimatesObserver(this);
- network_quality_estimator_->AddEffectiveConnectionTypeObserver(this);
-
- ui_thread_observer_ = std::make_unique<UiThreadObserver>();
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::BindOnce(&UiThreadObserver::InitOnUIThread,
- base::Unretained(ui_thread_observer_.get())));
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_CREATED,
+ NotificationService::AllSources());
+ network_quality_tracker_->AddRTTAndThroughputEstimatesObserver(this);
+ network_quality_tracker_->AddEffectiveConnectionTypeObserver(this);
}
NetworkQualityObserverImpl::~NetworkQualityObserverImpl() {
DCHECK(thread_checker_.CalledOnValidThread());
- network_quality_estimator_->RemoveRTTAndThroughputEstimatesObserver(this);
- network_quality_estimator_->RemoveEffectiveConnectionTypeObserver(this);
-
- DCHECK(ui_thread_observer_);
-
- // If possible, delete |ui_thread_observer_| on UI thread.
- UiThreadObserver* ui_thread_observer_ptr = ui_thread_observer_.release();
- bool posted = BrowserThread::DeleteSoon(BrowserThread::UI, FROM_HERE,
- ui_thread_observer_ptr);
-
- if (!posted)
- delete ui_thread_observer_ptr;
+ network_quality_tracker_->RemoveRTTAndThroughputEstimatesObserver(this);
+ network_quality_tracker_->RemoveEffectiveConnectionTypeObserver(this);
}
void NetworkQualityObserverImpl::OnEffectiveConnectionTypeChanged(
@@ -183,11 +83,31 @@ void NetworkQualityObserverImpl::OnEffectiveConnectionTypeChanged(
last_notified_type_ = type;
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::BindOnce(&UiThreadObserver::OnEffectiveConnectionTypeChanged,
- base::Unretained(ui_thread_observer_.get()),
- last_notified_type_));
+ // Notify all the existing renderers of the change in the network quality.
+ for (RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator());
+ !it.IsAtEnd(); it.Advance()) {
+ if (it.GetCurrentValue()->IsInitializedAndNotDead()) {
+ it.GetCurrentValue()->GetRendererInterface()->OnNetworkQualityChanged(
+ last_notified_type_, last_notified_network_quality_.http_rtt(),
+ last_notified_network_quality_.transport_rtt(),
+ last_notified_network_quality_.downstream_throughput_kbps());
+ }
+ }
+}
+
+void NetworkQualityObserverImpl::Observe(int type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK_EQ(NOTIFICATION_RENDERER_PROCESS_CREATED, type);
+
+ RenderProcessHost* rph = Source<RenderProcessHost>(source).ptr();
+
+ // Notify the newly created renderer of the current network quality.
+ rph->GetRendererInterface()->OnNetworkQualityChanged(
+ last_notified_type_, last_notified_network_quality_.http_rtt(),
+ last_notified_network_quality_.transport_rtt(),
+ last_notified_network_quality_.downstream_throughput_kbps());
}
void NetworkQualityObserverImpl::OnRTTOrThroughputEstimatesComputed(
@@ -223,18 +143,23 @@ void NetworkQualityObserverImpl::OnRTTOrThroughputEstimatesComputed(
last_notified_network_quality_ = net::nqe::internal::NetworkQuality(
http_rtt, transport_rtt, downstream_throughput_kbps);
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::BindOnce(&UiThreadObserver::OnRTTOrThroughputEstimatesComputed,
- base::Unretained(ui_thread_observer_.get()),
- last_notified_network_quality_));
+ // Notify all the existing renderers of the change in the network quality.
+ for (RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator());
+ !it.IsAtEnd(); it.Advance()) {
+ if (it.GetCurrentValue()->IsInitializedAndNotDead()) {
+ it.GetCurrentValue()->GetRendererInterface()->OnNetworkQualityChanged(
+ last_notified_type_, last_notified_network_quality_.http_rtt(),
+ last_notified_network_quality_.transport_rtt(),
+ last_notified_network_quality_.downstream_throughput_kbps());
+ }
+ }
}
-std::unique_ptr<net::RTTAndThroughputEstimatesObserver>
+std::unique_ptr<
+ network::NetworkQualityTracker::RTTAndThroughputEstimatesObserver>
CreateNetworkQualityObserver(
- net::NetworkQualityEstimator* network_quality_estimator) {
- return std::make_unique<NetworkQualityObserverImpl>(
- network_quality_estimator);
+ network::NetworkQualityTracker* network_quality_tracker) {
+ return std::make_unique<NetworkQualityObserverImpl>(network_quality_tracker);
}
-} // namespace content \ No newline at end of file
+} // namespace content
diff --git a/chromium/content/browser/net/network_quality_observer_impl.h b/chromium/content/browser/net/network_quality_observer_impl.h
index 2c5a1818839..4a6fe632edd 100644
--- a/chromium/content/browser/net/network_quality_observer_impl.h
+++ b/chromium/content/browser/net/network_quality_observer_impl.h
@@ -13,31 +13,31 @@
#include "base/threading/thread_checker.h"
#include "base/time/time.h"
#include "content/common/content_export.h"
-#include "content/public/browser/network_quality_observer_factory.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_registrar.h"
#include "net/nqe/effective_connection_type.h"
-#include "net/nqe/effective_connection_type_observer.h"
#include "net/nqe/network_quality.h"
-#include "net/nqe/rtt_throughput_estimates_observer.h"
-
-namespace net {
-class NetworkQualityEstimator;
-}
+#include "services/network/public/cpp/network_quality_tracker.h"
namespace content {
// Listens for changes to the network quality and manages sending updates to
// each RenderProcess via mojo.
class CONTENT_EXPORT NetworkQualityObserverImpl
- : public net::EffectiveConnectionTypeObserver,
- public net::RTTAndThroughputEstimatesObserver {
+ : public network::NetworkQualityTracker::EffectiveConnectionTypeObserver,
+ public network::NetworkQualityTracker::RTTAndThroughputEstimatesObserver,
+ public content::NotificationObserver {
public:
explicit NetworkQualityObserverImpl(
- net::NetworkQualityEstimator* network_quality_estimator);
+ network::NetworkQualityTracker* network_quality_tracker);
~NetworkQualityObserverImpl() override;
private:
- class UiThreadObserver;
+ // content::NotificationObserver:
+ void Observe(int type,
+ const NotificationSource& source,
+ const NotificationDetails& details) override;
// net::EffectiveConnectionTypeObserver implementation:
void OnEffectiveConnectionTypeChanged(
@@ -49,20 +49,16 @@ class CONTENT_EXPORT NetworkQualityObserverImpl
base::TimeDelta transport_rtt,
int32_t downstream_throughput_kbps) override;
- // |ui_thread_observer_| is owned by |this|, and interacts with
- // the render processes. It is created on the IO thread but afterwards, should
- // only be accessed on the UI thread. |ui_thread_observer_| is guaranteed to
- // be non-null during the lifetime of |this|.
- std::unique_ptr<UiThreadObserver> ui_thread_observer_;
-
- // |network_quality_estimator_| is guaranteed to be non-null during the
+ // |network_quality_tracker_| is guaranteed to be non-null during the
// lifetime of |this|.
- net::NetworkQualityEstimator* network_quality_estimator_;
+ network::NetworkQualityTracker* network_quality_tracker_;
// The network quality when the |ui_thread_observer_| was last notified.
net::EffectiveConnectionType last_notified_type_;
net::nqe::internal::NetworkQuality last_notified_network_quality_;
+ content::NotificationRegistrar registrar_;
+
base::ThreadChecker thread_checker_;
DISALLOW_COPY_AND_ASSIGN(NetworkQualityObserverImpl);
@@ -70,4 +66,4 @@ class CONTENT_EXPORT NetworkQualityObserverImpl
} // namespace content
-#endif // CONTENT_BROWSER_NET_NETWORK_QUALITY_OBSERVER_IMPL_H_ \ No newline at end of file
+#endif // CONTENT_BROWSER_NET_NETWORK_QUALITY_OBSERVER_IMPL_H_
diff --git a/chromium/content/browser/net/network_quality_observer_impl_unittest.cc b/chromium/content/browser/net/network_quality_observer_impl_unittest.cc
index cd9ab62b89b..eeba7c7ee5c 100644
--- a/chromium/content/browser/net/network_quality_observer_impl_unittest.cc
+++ b/chromium/content/browser/net/network_quality_observer_impl_unittest.cc
@@ -9,7 +9,7 @@
#include "base/time/time.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "net/nqe/effective_connection_type.h"
-#include "net/nqe/network_quality_estimator_test_util.h"
+#include "services/network/test/test_network_quality_tracker.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
@@ -19,25 +19,32 @@ TEST(NetworkQualityObserverImplTest, TestObserverNotified) {
content::TestBrowserThreadBundle thread_bundle(
content::TestBrowserThreadBundle::Options::IO_MAINLOOP);
- net::TestNetworkQualityEstimator estimator;
- estimator.SetStartTimeNullHttpRtt(base::TimeDelta::FromMilliseconds(1));
+ network::TestNetworkQualityTracker test_network_quality_tracker;
+
+ NetworkQualityObserverImpl impl(&test_network_quality_tracker);
+
+ test_network_quality_tracker.ReportRTTsAndThroughputForTesting(
+ base::TimeDelta::FromMilliseconds(1), 100);
- NetworkQualityObserverImpl observer(&estimator);
- // Give a chance for |observer| to register with the |estimator|.
base::RunLoop().RunUntilIdle();
base::HistogramTester histogram_tester;
- estimator.SetStartTimeNullHttpRtt(base::TimeDelta::FromMilliseconds(500));
+
+ test_network_quality_tracker.ReportRTTsAndThroughputForTesting(
+ base::TimeDelta::FromMilliseconds(500), 100);
+
// RTT changed from 1 msec to 500 msec.
histogram_tester.ExpectBucketCount(
"NQE.ContentObserver.NetworkQualityMeaningfullyChanged", 1, 1);
- estimator.SetStartTimeNullHttpRtt(base::TimeDelta::FromMilliseconds(625));
+ test_network_quality_tracker.ReportRTTsAndThroughputForTesting(
+ base::TimeDelta::FromMilliseconds(625), 100);
// RTT changed from 500 msec to 625 msec.
histogram_tester.ExpectBucketCount(
"NQE.ContentObserver.NetworkQualityMeaningfullyChanged", 1, 2);
- estimator.SetStartTimeNullHttpRtt(base::TimeDelta::FromMilliseconds(626));
+ test_network_quality_tracker.ReportRTTsAndThroughputForTesting(
+ base::TimeDelta::FromMilliseconds(626), 100);
// RTT changed from 625 msec to 626 msec which is not a meaningful change.
histogram_tester.ExpectBucketCount(
"NQE.ContentObserver.NetworkQualityMeaningfullyChanged", 1, 2);
diff --git a/chromium/content/browser/net/quota_policy_cookie_store.cc b/chromium/content/browser/net/quota_policy_cookie_store.cc
index ecf284fd0d9..7416a8606d3 100644
--- a/chromium/content/browser/net/quota_policy_cookie_store.cc
+++ b/chromium/content/browser/net/quota_policy_cookie_store.cc
@@ -14,6 +14,7 @@
#include "base/memory/ref_counted.h"
#include "base/sequenced_task_runner.h"
#include "base/task/post_task.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/cookie_store_factory.h"
#include "net/cookies/canonical_cookie.h"
@@ -83,12 +84,12 @@ std::unique_ptr<net::CookieStore> CreateCookieStore(
if (!client_task_runner.get()) {
client_task_runner =
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO);
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO});
}
if (!background_task_runner.get()) {
background_task_runner = base::CreateSequencedTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+ {base::MayBlock(), net::GetCookieStoreBackgroundSequencePriority(),
base::TaskShutdownBehavior::BLOCK_SHUTDOWN});
}
diff --git a/chromium/content/browser/net_info_browsertest.cc b/chromium/content/browser/net_info_browsertest.cc
index e5bf126c3c4..e506f12bbfe 100644
--- a/chromium/content/browser/net_info_browsertest.cc
+++ b/chromium/content/browser/net_info_browsertest.cc
@@ -22,7 +22,7 @@
#include "net/dns/mock_host_resolver.h"
#include "net/log/test_net_log.h"
#include "net/nqe/effective_connection_type.h"
-#include "net/nqe/network_quality_estimator_test_util.h"
+#include "services/network/test/test_network_quality_tracker.h"
namespace {
@@ -49,7 +49,9 @@ void VerifyRtt(base::TimeDelta expected_rtt, int32_t got_rtt_milliseconds) {
// For example, if sample is 300 msec, after adding noise, it may become 330,
// and after rounding off, it would spill over to the next bucket of 350 msec.
EXPECT_GE((expected_rtt.InMilliseconds() * 0.1) + 50,
- std::abs(expected_rtt.InMilliseconds() - got_rtt_milliseconds));
+ std::abs(expected_rtt.InMilliseconds() - got_rtt_milliseconds))
+ << " expected_rtt=" << expected_rtt
+ << " got_rtt_milliseconds=" << got_rtt_milliseconds;
}
void VerifyDownlinkKbps(double expected_kbps, double got_kbps) {
@@ -74,7 +76,8 @@ void VerifyDownlinkKbps(double expected_kbps, double got_kbps) {
// sample may spill over to the next bucket due to the added noise of 10%.
// For example, if sample is 300 kbps, after adding noise, it may become 330,
// and after rounding off, it would spill over to the next bucket of 350 kbps.
- EXPECT_GE((expected_kbps * 0.1) + 50, std::abs(expected_kbps - got_kbps));
+ EXPECT_GE((expected_kbps * 0.1) + 50, std::abs(expected_kbps - got_kbps))
+ << " expected_kbps=" << expected_kbps << " got_kbps=" << got_kbps;
}
} // namespace
@@ -82,6 +85,15 @@ void VerifyDownlinkKbps(double expected_kbps, double got_kbps) {
namespace content {
class NetInfoBrowserTest : public content::ContentBrowserTest {
+ public:
+ NetInfoBrowserTest()
+ : test_network_quality_tracker_(
+ std::make_unique<network::TestNetworkQualityTracker>()) {}
+
+ network::NetworkQualityTracker* GetNetworkQualityTracker() const {
+ return test_network_quality_tracker_.get();
+ }
+
protected:
void SetUpCommandLine(base::CommandLine* command_line) override {
// TODO(jkarlin): Once NetInfo is enabled on all platforms remove this
@@ -145,6 +157,10 @@ class NetInfoBrowserTest : public content::ContentBrowserTest {
EXPECT_TRUE(ExecuteScriptAndExtractInt(shell(), script, &data));
return data;
}
+
+ private:
+ std::unique_ptr<network::TestNetworkQualityTracker>
+ test_network_quality_tracker_;
};
// Make sure the type is correct when the page is first opened.
@@ -219,10 +235,7 @@ IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest, TwoRenderViewsInOneProcess) {
IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest,
NetworkQualityEstimatorNotInitialized) {
base::HistogramTester histogram_tester;
- net::TestNetworkQualityEstimator estimator(
- std::map<std::string, std::string>(), false, false, true,
- std::make_unique<net::BoundTestNetLog>());
- NetworkQualityObserverImpl impl(&estimator);
+ NetworkQualityObserverImpl impl(GetNetworkQualityTracker());
EXPECT_TRUE(embedded_test_server()->Start());
EXPECT_TRUE(
@@ -234,20 +247,17 @@ IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest,
VerifyDownlinkKbps(10000, RunScriptExtractDouble("getDownlink()") * 1000);
}
-// Make sure the changes in the effective connection typeare notified to the
+// Make sure the changes in the effective connection type are notified to the
// render thread.
IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest,
- EffectiveConnectionTypeChangeNotfied) {
+ EffectiveConnectionTypeChangeNotified) {
base::HistogramTester histogram_tester;
- net::TestNetworkQualityEstimator estimator(
- std::map<std::string, std::string>(), false, false, true,
- std::make_unique<net::BoundTestNetLog>());
- NetworkQualityObserverImpl impl(&estimator);
+ NetworkQualityObserverImpl impl(GetNetworkQualityTracker());
- net::nqe::internal::NetworkQuality network_quality_1(
- base::TimeDelta::FromSeconds(1), base::TimeDelta::FromSeconds(2), 300);
- estimator.NotifyObserversOfRTTOrThroughputEstimatesComputed(
- network_quality_1);
+ base::TimeDelta http_rtt(base::TimeDelta::FromMilliseconds(1000));
+ int32_t downstream_throughput_kbps = 300;
+ GetNetworkQualityTracker()->ReportRTTsAndThroughputForTesting(
+ http_rtt, downstream_throughput_kbps);
EXPECT_TRUE(embedded_test_server()->Start());
EXPECT_TRUE(
@@ -263,11 +273,11 @@ IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest,
// Changing the effective connection type from 2G to 3G is guaranteed to
// generate the notification to the renderers, irrespective of the current
// effective connection type.
- estimator.NotifyObserversOfEffectiveConnectionType(
+ GetNetworkQualityTracker()->ReportEffectiveConnectionTypeForTesting(
net::EFFECTIVE_CONNECTION_TYPE_2G);
base::RunLoop().RunUntilIdle();
EXPECT_EQ("2g", RunScriptExtractString("getEffectiveType()"));
- estimator.NotifyObserversOfEffectiveConnectionType(
+ GetNetworkQualityTracker()->ReportEffectiveConnectionTypeForTesting(
net::EFFECTIVE_CONNECTION_TYPE_3G);
base::RunLoop().RunUntilIdle();
EXPECT_EQ("3g", RunScriptExtractString("getEffectiveType()"));
@@ -281,15 +291,13 @@ IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest,
// thread, and the changed network quality is accessible via Javascript API.
IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest, NetworkQualityChangeNotified) {
base::HistogramTester histogram_tester;
- net::TestNetworkQualityEstimator estimator(
- std::map<std::string, std::string>(), false, false, true,
- std::make_unique<net::BoundTestNetLog>());
- NetworkQualityObserverImpl impl(&estimator);
+ NetworkQualityObserverImpl impl(GetNetworkQualityTracker());
+
+ base::TimeDelta http_rtt(base::TimeDelta::FromMilliseconds(1000));
+ int32_t downstream_throughput_kbps = 300;
- net::nqe::internal::NetworkQuality network_quality_1(
- base::TimeDelta::FromSeconds(1), base::TimeDelta::FromSeconds(2), 300);
- estimator.NotifyObserversOfRTTOrThroughputEstimatesComputed(
- network_quality_1);
+ GetNetworkQualityTracker()->ReportRTTsAndThroughputForTesting(
+ http_rtt, downstream_throughput_kbps);
EXPECT_TRUE(embedded_test_server()->Start());
EXPECT_TRUE(
@@ -299,18 +307,18 @@ IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest, NetworkQualityChangeNotified) {
EXPECT_FALSE(
histogram_tester.GetAllSamples("NQE.RenderThreadNotified").empty());
- VerifyRtt(network_quality_1.http_rtt(), RunScriptExtractInt("getRtt()"));
- VerifyDownlinkKbps(network_quality_1.downstream_throughput_kbps(),
+ VerifyRtt(http_rtt, RunScriptExtractInt("getRtt()"));
+ VerifyDownlinkKbps(downstream_throughput_kbps,
RunScriptExtractDouble("getDownlink()") * 1000);
// Verify that the network quality change is accessible via Javascript API.
- net::nqe::internal::NetworkQuality network_quality_2(
- base::TimeDelta::FromSeconds(10), base::TimeDelta::FromSeconds(20), 3000);
- estimator.NotifyObserversOfRTTOrThroughputEstimatesComputed(
- network_quality_2);
+ http_rtt = base::TimeDelta::FromSeconds(10);
+ downstream_throughput_kbps = 3000;
+ GetNetworkQualityTracker()->ReportRTTsAndThroughputForTesting(
+ http_rtt, downstream_throughput_kbps);
base::RunLoop().RunUntilIdle();
- VerifyRtt(network_quality_2.http_rtt(), RunScriptExtractInt("getRtt()"));
- VerifyDownlinkKbps(network_quality_2.downstream_throughput_kbps(),
+ VerifyRtt(http_rtt, RunScriptExtractInt("getRtt()"));
+ VerifyDownlinkKbps(downstream_throughput_kbps,
RunScriptExtractDouble("getDownlink()") * 1000);
}
@@ -318,43 +326,37 @@ IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest, NetworkQualityChangeNotified) {
// 50 milliseconds or 50 kbps.
IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest, NetworkQualityChangeRounded) {
base::HistogramTester histogram_tester;
- net::TestNetworkQualityEstimator estimator(
- std::map<std::string, std::string>(), false, false, true,
- std::make_unique<net::BoundTestNetLog>());
- NetworkQualityObserverImpl impl(&estimator);
+ NetworkQualityObserverImpl impl(GetNetworkQualityTracker());
// Verify that the network quality is rounded properly.
- net::nqe::internal::NetworkQuality network_quality_1(
- base::TimeDelta::FromMilliseconds(103),
- base::TimeDelta::FromMilliseconds(212), 8303);
- estimator.NotifyObserversOfRTTOrThroughputEstimatesComputed(
- network_quality_1);
+ base::TimeDelta http_rtt(base::TimeDelta::FromMilliseconds(103));
+ int32_t downstream_throughput_kbps = 8303;
+ GetNetworkQualityTracker()->ReportRTTsAndThroughputForTesting(
+ http_rtt, downstream_throughput_kbps);
EXPECT_TRUE(embedded_test_server()->Start());
EXPECT_TRUE(
NavigateToURL(shell(), embedded_test_server()->GetURL("/net_info.html")));
- VerifyRtt(network_quality_1.http_rtt(), RunScriptExtractInt("getRtt()"));
- VerifyDownlinkKbps(network_quality_1.downstream_throughput_kbps(),
+ VerifyRtt(http_rtt, RunScriptExtractInt("getRtt()"));
+ VerifyDownlinkKbps(downstream_throughput_kbps,
RunScriptExtractDouble("getDownlink()") * 1000);
- net::nqe::internal::NetworkQuality network_quality_2(
- base::TimeDelta::FromMilliseconds(1103),
- base::TimeDelta::FromMilliseconds(212), 1307);
- estimator.NotifyObserversOfRTTOrThroughputEstimatesComputed(
- network_quality_2);
+ http_rtt = base::TimeDelta::FromMilliseconds(1103);
+ downstream_throughput_kbps = 1307;
+ GetNetworkQualityTracker()->ReportRTTsAndThroughputForTesting(
+ http_rtt, downstream_throughput_kbps);
base::RunLoop().RunUntilIdle();
- VerifyRtt(network_quality_2.http_rtt(), RunScriptExtractInt("getRtt()"));
- VerifyDownlinkKbps(network_quality_2.downstream_throughput_kbps(),
+ VerifyRtt(http_rtt, RunScriptExtractInt("getRtt()"));
+ VerifyDownlinkKbps(downstream_throughput_kbps,
RunScriptExtractDouble("getDownlink()") * 1000);
- net::nqe::internal::NetworkQuality network_quality_3(
- base::TimeDelta::FromMilliseconds(2112),
- base::TimeDelta::FromMilliseconds(2112), 2112);
- estimator.NotifyObserversOfRTTOrThroughputEstimatesComputed(
- network_quality_3);
+ http_rtt = base::TimeDelta::FromMilliseconds(2112);
+ downstream_throughput_kbps = 2112;
+ GetNetworkQualityTracker()->ReportRTTsAndThroughputForTesting(
+ http_rtt, downstream_throughput_kbps);
base::RunLoop().RunUntilIdle();
- VerifyRtt(network_quality_3.http_rtt(), RunScriptExtractInt("getRtt()"));
- VerifyDownlinkKbps(network_quality_3.downstream_throughput_kbps(),
+ VerifyRtt(http_rtt, RunScriptExtractInt("getRtt()"));
+ VerifyDownlinkKbps(downstream_throughput_kbps,
RunScriptExtractDouble("getDownlink()") * 1000);
}
@@ -362,43 +364,39 @@ IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest, NetworkQualityChangeRounded) {
// limit.
IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest, NetworkQualityChangeUpperLimit) {
base::HistogramTester histogram_tester;
- net::TestNetworkQualityEstimator estimator(
- std::map<std::string, std::string>(), false, false, true,
- std::make_unique<net::BoundTestNetLog>());
- NetworkQualityObserverImpl impl(&estimator);
+ NetworkQualityObserverImpl impl(GetNetworkQualityTracker());
- net::nqe::internal::NetworkQuality network_quality(
- base::TimeDelta::FromMilliseconds(12003),
- base::TimeDelta::FromMilliseconds(212), 30300);
- estimator.NotifyObserversOfRTTOrThroughputEstimatesComputed(network_quality);
+ base::TimeDelta http_rtt(base::TimeDelta::FromMilliseconds(12003));
+ int32_t downstream_throughput_kbps = 30300;
+
+ GetNetworkQualityTracker()->ReportRTTsAndThroughputForTesting(
+ http_rtt, downstream_throughput_kbps);
EXPECT_TRUE(embedded_test_server()->Start());
EXPECT_TRUE(
NavigateToURL(shell(), embedded_test_server()->GetURL("/net_info.html")));
- VerifyRtt(network_quality.http_rtt(), RunScriptExtractInt("getRtt()"));
- VerifyDownlinkKbps(network_quality.downstream_throughput_kbps(),
+ VerifyRtt(http_rtt, RunScriptExtractInt("getRtt()"));
+ VerifyDownlinkKbps(downstream_throughput_kbps,
RunScriptExtractDouble("getDownlink()") * 1000);
}
// Make sure the noise added to the network quality varies with the hostname.
IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest, NetworkQualityRandomized) {
base::HistogramTester histogram_tester;
- net::TestNetworkQualityEstimator estimator(
- std::map<std::string, std::string>(), false, false, true,
- std::make_unique<net::BoundTestNetLog>());
- NetworkQualityObserverImpl impl(&estimator);
+ NetworkQualityObserverImpl impl(GetNetworkQualityTracker());
+
+ base::TimeDelta http_rtt(base::TimeDelta::FromMilliseconds(2000));
+ int32_t downstream_throughput_kbps = 3000;
- net::nqe::internal::NetworkQuality network_quality(
- base::TimeDelta::FromMilliseconds(2000),
- base::TimeDelta::FromMilliseconds(200), 3000);
- estimator.NotifyObserversOfRTTOrThroughputEstimatesComputed(network_quality);
+ GetNetworkQualityTracker()->ReportRTTsAndThroughputForTesting(
+ http_rtt, downstream_throughput_kbps);
EXPECT_TRUE(embedded_test_server()->Start());
EXPECT_TRUE(
NavigateToURL(shell(), embedded_test_server()->GetURL("/net_info.html")));
- VerifyRtt(network_quality.http_rtt(), RunScriptExtractInt("getRtt()"));
- VerifyDownlinkKbps(network_quality.downstream_throughput_kbps(),
+ VerifyRtt(http_rtt, RunScriptExtractInt("getRtt()"));
+ VerifyDownlinkKbps(downstream_throughput_kbps,
RunScriptExtractDouble("getDownlink()") * 1000);
const int32_t rtt_noise_milliseconds = RunScriptExtractInt("getRtt()") - 2000;
@@ -408,8 +406,8 @@ IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest, NetworkQualityRandomized) {
// When the hostname is not changed, the noise should not change.
EXPECT_TRUE(
NavigateToURL(shell(), embedded_test_server()->GetURL("/net_info.html")));
- VerifyRtt(network_quality.http_rtt(), RunScriptExtractInt("getRtt()"));
- VerifyDownlinkKbps(network_quality.downstream_throughput_kbps(),
+ VerifyRtt(http_rtt, RunScriptExtractInt("getRtt()"));
+ VerifyDownlinkKbps(downstream_throughput_kbps,
RunScriptExtractDouble("getDownlink()") * 1000);
EXPECT_EQ(rtt_noise_milliseconds, RunScriptExtractInt("getRtt()") - 2000);
EXPECT_EQ(downlink_noise_kbps,
@@ -425,8 +423,8 @@ IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest, NetworkQualityRandomized) {
std::string fake_hostname = "example" + base::IntToString(i) + ".com";
EXPECT_TRUE(NavigateToURL(shell(), embedded_test_server()->GetURL(
fake_hostname, "/net_info.html")));
- VerifyRtt(network_quality.http_rtt(), RunScriptExtractInt("getRtt()"));
- VerifyDownlinkKbps(network_quality.downstream_throughput_kbps(),
+ VerifyRtt(http_rtt, RunScriptExtractInt("getRtt()"));
+ VerifyDownlinkKbps(downstream_throughput_kbps,
RunScriptExtractDouble("getDownlink()") * 1000);
int32_t new_rtt_noise_milliseconds = RunScriptExtractInt("getRtt()") - 2000;
@@ -444,32 +442,27 @@ IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest, NetworkQualityRandomized) {
// Make sure the minor changes (<10%) in the network quality are not notified.
IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest, NetworkQualityChangeNotNotified) {
base::HistogramTester histogram_tester;
- net::TestNetworkQualityEstimator estimator(
- std::map<std::string, std::string>(), false, false, true,
- std::make_unique<net::BoundTestNetLog>());
- NetworkQualityObserverImpl impl(&estimator);
+ NetworkQualityObserverImpl impl(GetNetworkQualityTracker());
// Verify that the network quality is rounded properly.
- net::nqe::internal::NetworkQuality network_quality_1(
- base::TimeDelta::FromMilliseconds(1123),
- base::TimeDelta::FromMilliseconds(1212), 1303);
- estimator.NotifyObserversOfRTTOrThroughputEstimatesComputed(
- network_quality_1);
+ base::TimeDelta http_rtt(base::TimeDelta::FromMilliseconds(1123));
+ int32_t downstream_throughput_kbps = 1303;
+ GetNetworkQualityTracker()->ReportRTTsAndThroughputForTesting(
+ http_rtt, downstream_throughput_kbps);
EXPECT_TRUE(embedded_test_server()->Start());
EXPECT_TRUE(
NavigateToURL(shell(), embedded_test_server()->GetURL("/net_info.html")));
- VerifyRtt(network_quality_1.http_rtt(), RunScriptExtractInt("getRtt()"));
- VerifyDownlinkKbps(network_quality_1.downstream_throughput_kbps(),
+ VerifyRtt(http_rtt, RunScriptExtractInt("getRtt()"));
+ VerifyDownlinkKbps(downstream_throughput_kbps,
RunScriptExtractDouble("getDownlink()") * 1000);
// All the 3 metrics change by less than 10%. So, the observers are not
// notified.
- net::nqe::internal::NetworkQuality network_quality_2(
- base::TimeDelta::FromMilliseconds(1223),
- base::TimeDelta::FromMilliseconds(1312), 1403);
- estimator.NotifyObserversOfRTTOrThroughputEstimatesComputed(
- network_quality_2);
+ http_rtt = base::TimeDelta::FromMilliseconds(1223);
+ downstream_throughput_kbps = 1403;
+ GetNetworkQualityTracker()->ReportRTTsAndThroughputForTesting(
+ http_rtt, downstream_throughput_kbps);
base::RunLoop().RunUntilIdle();
VerifyRtt(base::TimeDelta::FromMilliseconds(1100),
RunScriptExtractInt("getRtt()"));
@@ -477,11 +470,10 @@ IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest, NetworkQualityChangeNotNotified) {
// HTTP RTT has changed by more than 10% from the last notified value of
// |network_quality_1|. The observers should be notified.
- net::nqe::internal::NetworkQuality network_quality_3(
- base::TimeDelta::FromMilliseconds(2223),
- base::TimeDelta::FromMilliseconds(1312), 1403);
- estimator.NotifyObserversOfRTTOrThroughputEstimatesComputed(
- network_quality_3);
+ http_rtt = base::TimeDelta::FromMilliseconds(2223);
+ downstream_throughput_kbps = 1403;
+ GetNetworkQualityTracker()->ReportRTTsAndThroughputForTesting(
+ http_rtt, downstream_throughput_kbps);
base::RunLoop().RunUntilIdle();
VerifyRtt(base::TimeDelta::FromMilliseconds(2200),
RunScriptExtractInt("getRtt()"));
diff --git a/chromium/content/browser/network_service_browsertest.cc b/chromium/content/browser/network_service_browsertest.cc
index 25c031a14ea..85ee34408d6 100644
--- a/chromium/content/browser/network_service_browsertest.cc
+++ b/chromium/content/browser/network_service_browsertest.cc
@@ -7,6 +7,7 @@
#include "build/build_config.h"
#include "content/browser/storage_partition_impl.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/network_service_instance.h"
#include "content/public/browser/url_data_source.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_observer.h"
@@ -18,10 +19,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/simple_url_loader_test_helper.h"
#include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.h"
#include "net/dns/mock_host_resolver.h"
+#include "net/http/http_response_headers.h"
+#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "services/network/public/cpp/features.h"
+#include "services/network/public/cpp/resource_request.h"
+#include "services/network/public/cpp/simple_url_loader.h"
+
+#if defined(OS_ANDROID)
+#include "base/android/application_status_listener.h"
+#endif
namespace content {
@@ -79,12 +89,10 @@ class WebUITestWebUIControllerFactory : public WebUIControllerFactory {
}
};
-class WebUIDataSource : public URLDataSource {
+class TestWebUIDataSource : public URLDataSource {
public:
- WebUIDataSource() {}
-
- private:
- ~WebUIDataSource() override {}
+ TestWebUIDataSource() {}
+ ~TestWebUIDataSource() override {}
std::string GetSource() const override { return "webui"; }
@@ -102,7 +110,8 @@ class WebUIDataSource : public URLDataSource {
return "text/html";
}
- DISALLOW_COPY_AND_ASSIGN(WebUIDataSource);
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TestWebUIDataSource);
};
class NetworkServiceBrowserTest : public ContentBrowserTest {
@@ -111,6 +120,7 @@ class NetworkServiceBrowserTest : public ContentBrowserTest {
scoped_feature_list_.InitAndEnableFeature(
network::features::kNetworkService);
EXPECT_TRUE(embedded_test_server()->Start());
+ EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
WebUIControllerFactory::RegisterFactory(&factory_);
}
@@ -148,7 +158,7 @@ class NetworkServiceBrowserTest : public ContentBrowserTest {
void SetUpOnMainThread() override {
URLDataSource::Add(shell()->web_contents()->GetBrowserContext(),
- new WebUIDataSource);
+ std::make_unique<TestWebUIDataSource>());
}
void SetUpCommandLine(base::CommandLine* command_line) override {
@@ -158,9 +168,32 @@ class NetworkServiceBrowserTest : public ContentBrowserTest {
IsolateAllSitesForTesting(command_line);
}
+ base::FilePath GetCacheDirectory() { return temp_dir_.GetPath(); }
+
+ base::FilePath GetCacheIndexDirectory() {
+ return GetCacheDirectory().AppendASCII("index-dir");
+ }
+
+ void LoadURL(const GURL& url,
+ network::mojom::URLLoaderFactory* loader_factory) {
+ std::unique_ptr<network::ResourceRequest> request =
+ std::make_unique<network::ResourceRequest>();
+ request->url = url;
+ content::SimpleURLLoaderTestHelper simple_loader_helper;
+ std::unique_ptr<network::SimpleURLLoader> simple_loader =
+ network::SimpleURLLoader::Create(std::move(request),
+ TRAFFIC_ANNOTATION_FOR_TESTS);
+
+ simple_loader->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
+ loader_factory, simple_loader_helper.GetCallback());
+ simple_loader_helper.WaitForCallback();
+ ASSERT_TRUE(simple_loader_helper.response_body());
+ }
+
private:
WebUITestWebUIControllerFactory factory_;
base::test::ScopedFeatureList scoped_feature_list_;
+ base::ScopedTempDir temp_dir_;
DISALLOW_COPY_AND_ASSIGN(NetworkServiceBrowserTest);
};
@@ -196,6 +229,75 @@ IN_PROC_BROWSER_TEST_F(NetworkServiceBrowserTest,
EXPECT_FALSE(FetchResource(file_url));
}
+IN_PROC_BROWSER_TEST_F(NetworkServiceBrowserTest,
+ SimpleUrlLoader_NoAuthWhenNoWebContents) {
+ auto request = std::make_unique<network::ResourceRequest>();
+ request->url = embedded_test_server()->GetURL("/auth-basic?password=");
+ auto loader = network::SimpleURLLoader::Create(std::move(request),
+ TRAFFIC_ANNOTATION_FOR_TESTS);
+ auto loader_factory = BrowserContext::GetDefaultStoragePartition(
+ shell()->web_contents()->GetBrowserContext())
+ ->GetURLLoaderFactoryForBrowserProcess();
+ scoped_refptr<net::HttpResponseHeaders> headers;
+ base::RunLoop loop;
+ loader->DownloadHeadersOnly(
+ loader_factory.get(),
+ base::BindOnce(
+ [](base::OnceClosure quit_closure,
+ scoped_refptr<net::HttpResponseHeaders>* rh_out,
+ scoped_refptr<net::HttpResponseHeaders> rh_in) {
+ *rh_out = rh_in;
+ std::move(quit_closure).Run();
+ },
+ loop.QuitClosure(), &headers));
+ loop.Run();
+ ASSERT_TRUE(headers.get());
+ ASSERT_EQ(headers->response_code(), 401);
+}
+
+#if defined(OS_ANDROID)
+IN_PROC_BROWSER_TEST_F(NetworkServiceBrowserTest,
+ HttpCacheWrittenToDiskOnApplicationStateChange) {
+ base::ScopedAllowBlockingForTesting allow_blocking;
+
+ // Create network context with cache pointing to the temp cache dir.
+ network::mojom::NetworkContextPtr network_context;
+ network::mojom::NetworkContextParamsPtr context_params =
+ network::mojom::NetworkContextParams::New();
+ context_params->http_cache_path = GetCacheDirectory();
+ GetNetworkService()->CreateNetworkContext(mojo::MakeRequest(&network_context),
+ std::move(context_params));
+
+ network::mojom::URLLoaderFactoryParamsPtr params =
+ network::mojom::URLLoaderFactoryParams::New();
+ params->process_id = network::mojom::kBrowserProcessId;
+ params->is_corb_enabled = false;
+ network::mojom::URLLoaderFactoryPtr loader_factory;
+ network_context->CreateURLLoaderFactory(mojo::MakeRequest(&loader_factory),
+ std::move(params));
+
+ // Load a URL and check the cache index size.
+ LoadURL(embedded_test_server()->GetURL("/cachetime"), loader_factory.get());
+ int64_t directory_size = base::ComputeDirectorySize(GetCacheIndexDirectory());
+
+ // Load another URL, cache index should not be written to disk yet.
+ LoadURL(embedded_test_server()->GetURL("/cachetime?foo"),
+ loader_factory.get());
+ EXPECT_EQ(directory_size,
+ base::ComputeDirectorySize(GetCacheIndexDirectory()));
+
+ // After application state changes, cache index should be written to disk.
+ base::android::ApplicationStatusListener::NotifyApplicationStateChange(
+ base::android::APPLICATION_STATE_HAS_STOPPED_ACTIVITIES);
+ base::RunLoop().RunUntilIdle();
+ content::FlushNetworkServiceInstanceForTesting();
+ disk_cache::FlushCacheThreadForTesting();
+
+ EXPECT_GT(base::ComputeDirectorySize(GetCacheIndexDirectory()),
+ directory_size);
+}
+#endif
+
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 81a0655e94e..b27a801cc8d 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 "base/task/post_task.h"
+#include "base/unguessable_token.h"
#include "content/browser/browsing_data/clear_site_data_handler.h"
#include "content/browser/devtools/devtools_url_loader_interceptor.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
@@ -13,12 +14,15 @@
#include "content/browser/ssl/ssl_error_handler.h"
#include "content/browser/ssl/ssl_manager.h"
#include "content/browser/ssl_private_key_impl.h"
+#include "content/browser/web_contents/web_contents_getter_registry.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/child_process_security_policy.h"
#include "content/public/browser/global_request_id.h"
#include "content/public/browser/login_delegate.h"
+#include "content/public/browser/network_service_instance.h"
#include "content/public/browser/resource_request_info.h"
#include "content/public/common/resource_type.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
@@ -75,8 +79,8 @@ class SSLClientAuthDelegate : public SSLClientAuthHandler::Delegate {
web_contents->GetBrowserContext();
content::ResourceContext* resource_context =
browser_context->GetResourceContext();
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&SSLClientAuthDelegate::CreateSSLClientAuthHandler,
base::Unretained(this), resource_context,
web_contents_getter));
@@ -102,8 +106,8 @@ class SSLClientAuthDelegate : public SSLClientAuthHandler::Delegate {
std::move(ssl_private_key_request));
}
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&SSLClientAuthDelegate::RunCallback,
base::Unretained(this), cert, algorithm_preferences,
std::move(ssl_private_key),
@@ -116,8 +120,8 @@ class SSLClientAuthDelegate : public SSLClientAuthHandler::Delegate {
network::mojom::SSLPrivateKeyPtr ssl_private_key;
mojo::MakeRequest(&ssl_private_key);
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&SSLClientAuthDelegate::RunCallback,
base::Unretained(this), nullptr, std::vector<uint16_t>(),
std::move(ssl_private_key),
@@ -185,8 +189,8 @@ class LoginHandlerDelegate {
auth_challenge_responder_.set_connection_error_handler(base::BindOnce(
&LoginHandlerDelegate::OnRequestCancelled, base::Unretained(this)));
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&LoginHandlerDelegate::DispatchInterceptorHookAndStart,
base::Unretained(this), process_id, routing_id,
request_id));
@@ -198,8 +202,8 @@ class LoginHandlerDelegate {
return;
// LoginDelegate::OnRequestCancelled can only be called from the IO thread.
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&LoginHandlerDelegate::OnRequestCancelledOnIOThread,
base::Unretained(this)));
}
@@ -249,8 +253,8 @@ class LoginHandlerDelegate {
void RunAuthCredentials(
const base::Optional<net::AuthCredentials>& auth_credentials) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&LoginHandlerDelegate::RunAuthCredentialsOnUI,
base::Unretained(this), auth_credentials));
}
@@ -305,11 +309,51 @@ void HandleFileUploadRequest(
std::move(files)));
}
+base::RepeatingCallback<WebContents*(void)> GetWebContentsFromRegistry(
+ const base::UnguessableToken& window_id) {
+ return WebContentsGetterRegistry::GetInstance()->Get(window_id);
+}
+
+void OnCertificateRequestedContinuation(
+ uint32_t process_id,
+ uint32_t routing_id,
+ uint32_t request_id,
+ const scoped_refptr<net::SSLCertRequestInfo>& cert_info,
+ network::mojom::NetworkServiceClient::OnCertificateRequestedCallback
+ callback,
+ base::RepeatingCallback<WebContents*(void)> web_contents_getter) {
+ if (!web_contents_getter) {
+ web_contents_getter =
+ process_id != network::mojom::kBrowserProcessId
+ ? base::BindRepeating(WebContentsImpl::FromRenderFrameHostID,
+ process_id, routing_id)
+ : base::BindRepeating(WebContents::FromFrameTreeNodeId, routing_id);
+ }
+ if (!web_contents_getter.Run()) {
+ network::mojom::SSLPrivateKeyPtr ssl_private_key;
+ mojo::MakeRequest(&ssl_private_key);
+ std::move(callback).Run(nullptr, std::vector<uint16_t>(),
+ std::move(ssl_private_key),
+ true /* cancel_certificate_selection */);
+ return;
+ }
+ new SSLClientAuthDelegate(std::move(callback), std::move(web_contents_getter),
+ cert_info); // deletes self
+}
+
} // namespace
NetworkServiceClient::NetworkServiceClient(
network::mojom::NetworkServiceClientRequest network_service_client_request)
- : binding_(this, std::move(network_service_client_request)) {}
+ : binding_(this, std::move(network_service_client_request))
+#if defined(OS_ANDROID)
+ ,
+ app_status_listener_(base::android::ApplicationStatusListener::New(
+ base::BindRepeating(&NetworkServiceClient::OnApplicationStateChange,
+ base::Unretained(this))))
+#endif
+{
+}
NetworkServiceClient::~NetworkServiceClient() = default;
@@ -330,8 +374,7 @@ void NetworkServiceClient::OnAuthRequired(
: base::Bind(WebContents::FromFrameTreeNodeId, routing_id);
if (!web_contents_getter.Run()) {
- std::move(auth_challenge_responder)
- ->OnAuthCredentials(net::AuthCredentials());
+ std::move(auth_challenge_responder)->OnAuthCredentials(base::nullopt);
return;
}
@@ -351,26 +394,27 @@ void NetworkServiceClient::OnAuthRequired(
}
void NetworkServiceClient::OnCertificateRequested(
+ const base::Optional<base::UnguessableToken>& window_id,
uint32_t process_id,
uint32_t routing_id,
uint32_t request_id,
const scoped_refptr<net::SSLCertRequestInfo>& cert_info,
network::mojom::NetworkServiceClient::OnCertificateRequestedCallback
callback) {
- 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()) {
- network::mojom::SSLPrivateKeyPtr ssl_private_key;
- mojo::MakeRequest(&ssl_private_key);
- std::move(callback).Run(nullptr, std::vector<uint16_t>(),
- std::move(ssl_private_key),
- true /* cancel_certificate_selection */);
+ base::RepeatingCallback<WebContents*(void)> web_contents_getter;
+
+ // Use |window_id| if it's provided.
+ if (window_id) {
+ base::PostTaskWithTraitsAndReplyWithResult(
+ FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(&GetWebContentsFromRegistry, *window_id),
+ base::BindOnce(&OnCertificateRequestedContinuation, process_id,
+ routing_id, request_id, cert_info, std::move(callback)));
return;
}
- new SSLClientAuthDelegate(std::move(callback), std::move(web_contents_getter),
- cert_info); // deletes self
+
+ OnCertificateRequestedContinuation(process_id, routing_id, request_id,
+ cert_info, std::move(callback), {});
}
void NetworkServiceClient::OnSSLCertificateError(
@@ -473,4 +517,11 @@ void NetworkServiceClient::OnClearSiteData(int process_id,
std::move(callback));
}
+#if defined(OS_ANDROID)
+void NetworkServiceClient::OnApplicationStateChange(
+ base::android::ApplicationState state) {
+ GetNetworkService()->OnApplicationStateChange(state);
+}
+#endif
+
} // namespace content
diff --git a/chromium/content/browser/network_service_client.h b/chromium/content/browser/network_service_client.h
index 1c0edbed8db..53ed471a6e1 100644
--- a/chromium/content/browser/network_service_client.h
+++ b/chromium/content/browser/network_service_client.h
@@ -6,11 +6,16 @@
#define CONTENT_BROWSER_NETWORK_SERVICE_IMPL_H_
#include "base/macros.h"
+#include "build/build_config.h"
#include "content/common/content_export.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "services/network/public/mojom/network_service.mojom.h"
#include "url/gurl.h"
+#if defined(OS_ANDROID)
+#include "base/android/application_status_listener.h"
+#endif
+
namespace content {
class CONTENT_EXPORT NetworkServiceClient
@@ -33,6 +38,7 @@ class CONTENT_EXPORT NetworkServiceClient
network::mojom::AuthChallengeResponderPtr
auth_challenge_responder) override;
void OnCertificateRequested(
+ const base::Optional<base::UnguessableToken>& window_id,
uint32_t process_id,
uint32_t routing_id,
uint32_t request_id,
@@ -72,9 +78,18 @@ class CONTENT_EXPORT NetworkServiceClient
int load_flags,
OnClearSiteDataCallback callback) override;
+#if defined(OS_ANDROID)
+ void OnApplicationStateChange(base::android::ApplicationState state);
+#endif
+
private:
mojo::Binding<network::mojom::NetworkServiceClient> binding_;
+#if defined(OS_ANDROID)
+ std::unique_ptr<base::android::ApplicationStatusListener>
+ app_status_listener_;
+#endif
+
DISALLOW_COPY_AND_ASSIGN(NetworkServiceClient);
};
diff --git a/chromium/content/browser/network_service_instance.cc b/chromium/content/browser/network_service_instance.cc
index 905301ab321..e2e06d84c84 100644
--- a/chromium/content/browser/network_service_instance.cc
+++ b/chromium/content/browser/network_service_instance.cc
@@ -4,8 +4,20 @@
#include "content/public/browser/network_service_instance.h"
+#include <map>
+#include <memory>
+#include <string>
+#include <utility>
+
+#include "base/environment.h"
#include "base/feature_list.h"
+#include "base/no_destructor.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/task/post_task.h"
+#include "build/build_config.h"
#include "content/browser/network_service_client.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/common/service_manager_connection.h"
@@ -15,6 +27,7 @@
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/network_connection_tracker.h"
#include "services/network/public/cpp/network_switches.h"
+#include "services/network/public/mojom/net_log.mojom.h"
#include "services/network/public/mojom/network_change_manager.mojom.h"
#include "services/service_manager/public/cpp/connector.h"
@@ -43,6 +56,24 @@ void BindNetworkChangeManagerRequest(
GetNetworkService()->GetNetworkChangeManager(std::move(request));
}
+using CrashHandlersMap =
+ std::map<NetworkServiceCrashHandlerId, base::RepeatingClosure>;
+CrashHandlersMap& GetCrashHandlersMap() {
+ static base::NoDestructor<CrashHandlersMap> s_map;
+ return *s_map;
+}
+
+void OnNetworkServiceCrash() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK(g_network_service_ptr);
+ DCHECK(g_network_service_ptr->is_bound());
+ DCHECK(g_network_service_ptr->encountered_error());
+ for (const auto& it : GetCrashHandlersMap()) {
+ const base::RepeatingClosure& handler = it.second;
+ handler.Run();
+ }
+}
+
} // namespace
network::mojom::NetworkService* GetNetworkService() {
@@ -64,10 +95,12 @@ CONTENT_EXPORT network::mojom::NetworkService* GetNetworkServiceFromConnector(
if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
connector->BindInterface(mojom::kNetworkServiceName,
g_network_service_ptr);
+ g_network_service_ptr->set_connection_error_handler(
+ base::BindOnce(&OnNetworkServiceCrash));
} else {
DCHECK(!g_network_service_ptr->is_bound());
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(CreateNetworkServiceOnIO,
mojo::MakeRequest(g_network_service_ptr)));
}
@@ -77,31 +110,83 @@ CONTENT_EXPORT network::mojom::NetworkService* GetNetworkServiceFromConnector(
g_client = new NetworkServiceClient(mojo::MakeRequest(&client_ptr));
(*g_network_service_ptr)->SetClient(std::move(client_ptr));
- if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
const base::CommandLine* command_line =
base::CommandLine::ForCurrentProcess();
- if (command_line->HasSwitch(network::switches::kLogNetLog)) {
- base::FilePath log_path =
- command_line->GetSwitchValuePath(network::switches::kLogNetLog);
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+ if (command_line->HasSwitch(network::switches::kLogNetLog)) {
+ base::FilePath log_path =
+ command_line->GetSwitchValuePath(network::switches::kLogNetLog);
+
+ base::DictionaryValue client_constants =
+ GetContentClient()->GetNetLogConstants();
+
+ base::File file(log_path, base::File::FLAG_CREATE_ALWAYS |
+ base::File::FLAG_WRITE);
+ LOG_IF(ERROR, !file.IsValid())
+ << "Failed opening: " << log_path.value();
+
+ // TODO(mmenke): Get capture mode from the command line.
+ (*g_network_service_ptr)
+ ->StartNetLog(std::move(file),
+ network::mojom::NetLogCaptureMode::DEFAULT,
+ std::move(client_constants));
+ }
+ }
- base::DictionaryValue client_constants =
- GetContentClient()->GetNetLogConstants();
+ if (command_line->HasSwitch(network::switches::kSSLKeyLogFile)) {
+ base::FilePath log_path =
+ command_line->GetSwitchValuePath(network::switches::kSSLKeyLogFile);
+ LOG_IF(WARNING, log_path.empty())
+ << "ssl-key-log-file argument missing";
+ if (!log_path.empty())
+ (*g_network_service_ptr)->SetSSLKeyLogFile(log_path);
+ }
- base::File file(
- log_path, base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
- LOG_IF(ERROR, !file.IsValid())
- << "Failed opening: " << log_path.value();
- (*g_network_service_ptr)
- ->StartNetLog(std::move(file), std::move(client_constants));
+ std::unique_ptr<base::Environment> env(base::Environment::Create());
+ std::string env_str;
+ if (env->GetVar("SSLKEYLOGFILE", &env_str)) {
+#if defined(OS_WIN)
+ // base::Environment returns environment variables in UTF-8 on Windows.
+ base::FilePath log_path(base::UTF8ToUTF16(env_str));
+#else
+ base::FilePath log_path(env_str);
+#endif
+ if (!log_path.empty())
+ (*g_network_service_ptr)->SetSSLKeyLogFile(log_path);
}
- }
- GetContentClient()->browser()->OnNetworkServiceCreated(
- g_network_service_ptr->get());
+ GetContentClient()->browser()->OnNetworkServiceCreated(
+ g_network_service_ptr->get());
}
return g_network_service_ptr->get();
}
+NetworkServiceCrashHandlerId RegisterNetworkServiceCrashHandler(
+ base::RepeatingClosure handler) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK(!handler.is_null());
+
+ static int next_handler_id = 1;
+ NetworkServiceCrashHandlerId handler_id =
+ NetworkServiceCrashHandlerId::FromUnsafeValue(next_handler_id++);
+
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+ CrashHandlersMap& map = GetCrashHandlersMap();
+ map[handler_id] = std::move(handler);
+ }
+
+ return handler_id;
+}
+
+void UnregisterNetworkServiceCrashHandler(
+ NetworkServiceCrashHandlerId handler_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+ CrashHandlersMap& map = GetCrashHandlersMap();
+ map.erase(handler_id);
+ }
+}
+
network::NetworkService* GetNetworkServiceImpl() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
@@ -129,9 +214,19 @@ network::NetworkConnectionTracker* GetNetworkConnectionTracker() {
return g_network_connection_tracker;
}
+void GetNetworkConnectionTrackerFromUIThread(
+ base::OnceCallback<void(network::NetworkConnectionTracker*)> callback) {
+ base::PostTaskWithTraitsAndReplyWithResult(
+ FROM_HERE, {BrowserThread::UI, base::TaskPriority::BEST_EFFORT},
+ base::BindOnce(&GetNetworkConnectionTracker), std::move(callback));
+}
+
void SetNetworkConnectionTrackerForTesting(
network::NetworkConnectionTracker* network_connection_tracker) {
- g_network_connection_tracker = network_connection_tracker;
+ if (g_network_connection_tracker != network_connection_tracker) {
+ DCHECK(!g_network_connection_tracker || !network_connection_tracker);
+ g_network_connection_tracker = network_connection_tracker;
+ }
}
} // namespace content
diff --git a/chromium/content/browser/network_service_restart_browsertest.cc b/chromium/content/browser/network_service_restart_browsertest.cc
index a868b80d5c5..48d4220b544 100644
--- a/chromium/content/browser/network_service_restart_browsertest.cc
+++ b/chromium/content/browser/network_service_restart_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 "base/callback.h"
+#include "base/run_loop.h"
#include "base/test/bind_test_util.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/test_timeouts.h"
@@ -10,6 +12,9 @@
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/frame_host/render_frame_message_filter.h"
#include "content/browser/renderer_host/render_process_host_impl.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_context_core_observer.h"
#include "content/browser/storage_partition_impl.h"
#include "content/browser/url_loader_factory_getter.h"
#include "content/public/browser/browser_context.h"
@@ -32,6 +37,10 @@
#include "services/network/public/cpp/simple_url_loader.h"
#include "services/network/public/mojom/network_service.mojom.h"
+#if BUILDFLAG(ENABLE_PLUGINS)
+#include "content/public/test/ppapi_test_utils.h"
+#endif
+
namespace content {
namespace {
@@ -100,6 +109,33 @@ void WaitForCondition(base::RepeatingCallback<bool()> condition) {
}
}
+class ServiceWorkerStatusObserver : public ServiceWorkerContextCoreObserver {
+ public:
+ void WaitForState(EmbeddedWorkerStatus expected_status) {
+ if (latest_status_ == expected_status)
+ return;
+
+ expected_status_ = expected_status;
+ base::RunLoop loop;
+ callback_ = loop.QuitClosure();
+ loop.Run();
+ }
+
+ private:
+ void OnRunningStateChanged(int64_t version_id,
+ EmbeddedWorkerStatus running_status) override {
+ latest_status_ = running_status;
+ if (expected_status_.has_value() &&
+ running_status == expected_status_.value()) {
+ std::move(callback_).Run();
+ }
+ }
+
+ base::Optional<EmbeddedWorkerStatus> expected_status_;
+ EmbeddedWorkerStatus latest_status_;
+ base::OnceClosure callback_;
+};
+
} // namespace
// This test source has been excluded from Android as Android doesn't have
@@ -111,10 +147,18 @@ class NetworkServiceRestartBrowserTest : public ContentBrowserTest {
network::features::kNetworkService);
}
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+#if BUILDFLAG(ENABLE_PLUGINS)
+ ASSERT_TRUE(ppapi::RegisterCorbTestPlugin(command_line));
+#endif
+ ContentBrowserTest::SetUpCommandLine(command_line);
+ }
+
void SetUpOnMainThread() override {
embedded_test_server()->RegisterRequestMonitor(
base::BindRepeating(&NetworkServiceRestartBrowserTest::MonitorRequest,
base::Unretained(this)));
+ host_resolver()->AddRule("*", "127.0.0.1");
EXPECT_TRUE(embedded_test_server()->Start());
ContentBrowserTest::SetUpOnMainThread();
}
@@ -279,6 +323,61 @@ IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
EXPECT_FALSE(network_context2.encountered_error());
}
+void IncrementInt(int* i) {
+ *i = *i + 1;
+}
+
+// This test verifies basic functionality of RegisterNetworkServiceCrashHandler
+// and UnregisterNetworkServiceCrashHandler.
+IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest, CrashHandlers) {
+ network::mojom::NetworkContextPtr network_context = CreateNetworkContext();
+ EXPECT_TRUE(network_context.is_bound());
+
+ // Register 2 crash handlers.
+ int counter1 = 0;
+ int counter2 = 0;
+ NetworkServiceCrashHandlerId handler_id1 = RegisterNetworkServiceCrashHandler(
+ base::BindRepeating(&IncrementInt, base::Unretained(&counter1)));
+ NetworkServiceCrashHandlerId handler_id2 = RegisterNetworkServiceCrashHandler(
+ base::BindRepeating(&IncrementInt, base::Unretained(&counter2)));
+
+ // Crash the NetworkService process.
+ SimulateNetworkServiceCrash();
+ // |network_context| will receive an error notification, but it's not
+ // guaranteed to have arrived at this point. Flush the pointer to make sure
+ // the notification has been received.
+ network_context.FlushForTesting();
+ EXPECT_TRUE(network_context.is_bound());
+ EXPECT_TRUE(network_context.encountered_error());
+
+ // Verify the crash handlers executed.
+ EXPECT_EQ(1, counter1);
+ EXPECT_EQ(1, counter2);
+
+ // Revive the NetworkService process.
+ network_context = CreateNetworkContext();
+ EXPECT_TRUE(network_context.is_bound());
+
+ // Unregister one of the handlers.
+ UnregisterNetworkServiceCrashHandler(handler_id2);
+
+ // Crash the NetworkService process.
+ SimulateNetworkServiceCrash();
+ // |network_context| will receive an error notification, but it's not
+ // guaranteed to have arrived at this point. Flush the pointer to make sure
+ // the notification has been received.
+ network_context.FlushForTesting();
+ EXPECT_TRUE(network_context.is_bound());
+ EXPECT_TRUE(network_context.encountered_error());
+
+ // Verify only the first crash handler executed.
+ EXPECT_EQ(2, counter1);
+ EXPECT_EQ(1, counter2);
+
+ // Test cleanup.
+ UnregisterNetworkServiceCrashHandler(handler_id1);
+}
+
// Make sure |StoragePartitionImpl::GetNetworkContext()| returns valid interface
// after crash.
IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
@@ -592,6 +691,224 @@ IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest, MultipleWorkerFetch) {
EXPECT_EQ(last_request_relative_url(), "/title2.html");
}
+// Flaky on Linux TSan (https://crbug.com/889855)
+#if defined(OS_LINUX) && defined(THREAD_SANITIZER)
+#define MAYBE_FetchFromServiceWorkerControlledPage_NoFetchHandler \
+ DISABLED_FetchFromServiceWorkerControlledPage_NoFetchHandler
+#else
+#define MAYBE_FetchFromServiceWorkerControlledPage_NoFetchHandler \
+ FetchFromServiceWorkerControlledPage_NoFetchHandler
+#endif
+// Make sure fetch from a page controlled by a service worker which doesn't have
+// a fetch handler works after crash.
+IN_PROC_BROWSER_TEST_F(
+ NetworkServiceRestartBrowserTest,
+ MAYBE_FetchFromServiceWorkerControlledPage_NoFetchHandler) {
+ StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
+ BrowserContext::GetDefaultStoragePartition(browser_context()));
+ ServiceWorkerStatusObserver observer;
+ ServiceWorkerContextWrapper* service_worker_context =
+ partition->GetServiceWorkerContext();
+ service_worker_context->AddObserver(&observer);
+
+ // Register a service worker which controls /service_worker/.
+ EXPECT_TRUE(NavigateToURL(shell(),
+ embedded_test_server()->GetURL(
+ "/service_worker/create_service_worker.html")));
+ EXPECT_EQ("DONE", EvalJs(shell(), "register('empty.js')"));
+
+ // Navigate to a controlled page.
+ EXPECT_TRUE(NavigateToURL(
+ shell(),
+ embedded_test_server()->GetURL("/service_worker/fetch_from_page.html")));
+
+ // Fetch from the controlled page.
+ const std::string script = "fetch_from_page('/echo');";
+ EXPECT_EQ("Echo", EvalJs(shell(), script));
+
+ // Crash the NetworkService process. Existing interfaces should receive error
+ // notifications at some point.
+ SimulateNetworkServiceCrash();
+ // Flush the interface to make sure the error notification was received.
+ partition->FlushNetworkInterfaceForTesting();
+
+ // Service worker should be stopped when network service crashes.
+ observer.WaitForState(EmbeddedWorkerStatus::STOPPED);
+
+ // Fetch from the controlled page again.
+ EXPECT_EQ("Echo", EvalJs(shell(), script));
+
+ service_worker_context->RemoveObserver(&observer);
+}
+
+// Flaky on Linux TSan (https://crbug.com/889855)
+#if defined(OS_LINUX) && defined(THREAD_SANITIZER)
+#define MAYBE_FetchFromServiceWorkerControlledPage_PassThrough \
+ DISABLED_FetchFromServiceWorkerControlledPage_PassThrough
+#else
+#define MAYBE_FetchFromServiceWorkerControlledPage_PassThrough \
+ FetchFromServiceWorkerControlledPage_PassThrough
+#endif
+// Make sure fetch from a page controlled by a service worker which has a fetch
+// handler but falls back to the network works after crash.
+IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
+ MAYBE_FetchFromServiceWorkerControlledPage_PassThrough) {
+ StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
+ BrowserContext::GetDefaultStoragePartition(browser_context()));
+ ServiceWorkerStatusObserver observer;
+ ServiceWorkerContextWrapper* service_worker_context =
+ partition->GetServiceWorkerContext();
+ service_worker_context->AddObserver(&observer);
+
+ // Register a service worker which controls /service_worker/.
+ EXPECT_TRUE(NavigateToURL(shell(),
+ embedded_test_server()->GetURL(
+ "/service_worker/create_service_worker.html")));
+ EXPECT_EQ("DONE", EvalJs(shell(), "register('fetch_event_pass_through.js')"));
+
+ // Navigate to a controlled page.
+ EXPECT_TRUE(NavigateToURL(
+ shell(),
+ embedded_test_server()->GetURL("/service_worker/fetch_from_page.html")));
+
+ // Fetch from the controlled page.
+ const std::string script = "fetch_from_page('/echo');";
+ EXPECT_EQ("Echo", EvalJs(shell(), script));
+
+ // Crash the NetworkService process. Existing interfaces should receive error
+ // notifications at some point.
+ SimulateNetworkServiceCrash();
+ // Flush the interface to make sure the error notification was received.
+ partition->FlushNetworkInterfaceForTesting();
+
+ // Service worker should be stopped when network service crashes.
+ observer.WaitForState(EmbeddedWorkerStatus::STOPPED);
+
+ // Fetch from the controlled page again.
+ EXPECT_EQ("Echo", EvalJs(shell(), script));
+
+ service_worker_context->RemoveObserver(&observer);
+}
+
+// Flaky on Linux TSan (https://crbug.com/889855)
+#if defined(OS_LINUX) && defined(THREAD_SANITIZER)
+#define MAYBE_FetchFromServiceWorkerControlledPage_RespondWithFetch \
+ DISABLED_FetchFromServiceWorkerControlledPage_RespondWithFetch
+#else
+#define MAYBE_FetchFromServiceWorkerControlledPage_RespondWithFetch \
+ FetchFromServiceWorkerControlledPage_RespondWithFetch
+#endif
+// Make sure fetch from a page controlled by a service worker which has a fetch
+// handler and responds with fetch() works after crash.
+IN_PROC_BROWSER_TEST_F(
+ NetworkServiceRestartBrowserTest,
+ MAYBE_FetchFromServiceWorkerControlledPage_RespondWithFetch) {
+ StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
+ BrowserContext::GetDefaultStoragePartition(browser_context()));
+ ServiceWorkerStatusObserver observer;
+ ServiceWorkerContextWrapper* service_worker_context =
+ partition->GetServiceWorkerContext();
+ service_worker_context->AddObserver(&observer);
+
+ // Register a service worker which controls /service_worker/.
+ EXPECT_TRUE(NavigateToURL(shell(),
+ embedded_test_server()->GetURL(
+ "/service_worker/create_service_worker.html")));
+ EXPECT_EQ("DONE",
+ EvalJs(shell(), "register('fetch_event_respond_with_fetch.js')"));
+
+ // Navigate to a controlled page.
+ EXPECT_TRUE(NavigateToURL(
+ shell(),
+ embedded_test_server()->GetURL("/service_worker/fetch_from_page.html")));
+
+ // Fetch from the controlled page.
+ const std::string script = "fetch_from_page('/echo');";
+ EXPECT_EQ("Echo", EvalJs(shell(), script));
+
+ // Crash the NetworkService process. Existing interfaces should receive error
+ // notifications at some point.
+ SimulateNetworkServiceCrash();
+ // Flush the interface to make sure the error notification was received.
+ partition->FlushNetworkInterfaceForTesting();
+
+ // Service worker should be stopped when network service crashes.
+ observer.WaitForState(EmbeddedWorkerStatus::STOPPED);
+
+ // Fetch from the controlled page again.
+ EXPECT_EQ("Echo", EvalJs(shell(), script));
+
+ service_worker_context->RemoveObserver(&observer);
+}
+
+// Make sure fetch from service worker context works after crash.
+IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest, ServiceWorkerFetch) {
+ StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
+ BrowserContext::GetDefaultStoragePartition(browser_context()));
+ ServiceWorkerStatusObserver observer;
+ ServiceWorkerContextWrapper* service_worker_context =
+ partition->GetServiceWorkerContext();
+ service_worker_context->AddObserver(&observer);
+
+ const GURL page_url = embedded_test_server()->GetURL(
+ "/service_worker/fetch_from_service_worker.html");
+ const GURL fetch_url = embedded_test_server()->GetURL("/echo");
+
+ // Navigate to the page and register a service worker.
+ EXPECT_TRUE(NavigateToURL(shell(), page_url));
+ EXPECT_EQ("ready", EvalJs(shell(), "setup();"));
+
+ // Fetch from the service worker.
+ const std::string script =
+ "fetch_from_service_worker('" + fetch_url.spec() + "');";
+ EXPECT_EQ("Echo", EvalJs(shell(), script));
+
+ // Crash the NetworkService process. Existing interfaces should receive error
+ // notifications at some point.
+ SimulateNetworkServiceCrash();
+ // Flush the interface to make sure the error notification was received.
+ partition->FlushNetworkInterfaceForTesting();
+
+ // Service worker should be stopped when network service crashes.
+ observer.WaitForState(EmbeddedWorkerStatus::STOPPED);
+
+ // Fetch from the service worker again.
+ EXPECT_EQ("Echo", EvalJs(shell(), script));
+
+ service_worker_context->RemoveObserver(&observer);
+}
+
+// Make sure shared workers terminate after crash.
+IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest, SharedWorker) {
+ StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
+ BrowserContext::GetDefaultStoragePartition(browser_context()));
+
+ const GURL page_url =
+ embedded_test_server()->GetURL("/workers/fetch_from_shared_worker.html");
+ const GURL fetch_url = embedded_test_server()->GetURL("/echo");
+
+ // Navigate to the page and prepare a shared worker.
+ EXPECT_TRUE(NavigateToURL(shell(), page_url));
+
+ // Fetch from the shared worker to ensure it has started.
+ const std::string script =
+ "fetch_from_shared_worker('" + fetch_url.spec() + "');";
+ EXPECT_EQ("Echo", EvalJs(shell(), script));
+
+ // There should be one worker host. We will later wait for it to terminate.
+ SharedWorkerServiceImpl* service = partition->GetSharedWorkerService();
+ EXPECT_EQ(1u, service->worker_hosts_.size());
+ base::RunLoop loop;
+ service->SetWorkerTerminationCallbackForTesting(loop.QuitClosure());
+
+ // Crash the NetworkService process.
+ SimulateNetworkServiceCrash();
+
+ // Wait for the worker to detect the crash and self-terminate.
+ loop.Run();
+ EXPECT_TRUE(service->worker_hosts_.empty());
+}
+
// Make sure the entry in |NetworkService::GetTotalNetworkUsages()| was cleared
// after process closed.
IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
@@ -670,7 +987,8 @@ IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
// Make sure cookie access doesn't hang or fail after a network process crash.
IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest, Cookies) {
auto* web_contents = shell()->web_contents();
- NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"));
+ ASSERT_TRUE(
+ NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html")));
EXPECT_TRUE(ExecuteScript(web_contents, "document.cookie = 'foo=bar';"));
std::string cookie;
@@ -688,11 +1006,11 @@ IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest, Cookies) {
// Need to use FlushAsyncForTesting instead of FlushForTesting because the IO
// thread doesn't support nested message loops.
base::RunLoop run_loop;
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::BindLambdaForTesting([&]() {
- filter->GetCookieManager()->FlushAsyncForTesting(
- run_loop.QuitClosure());
- }));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO},
+ base::BindLambdaForTesting([&]() {
+ filter->GetCookieManager()->FlushAsyncForTesting(
+ run_loop.QuitClosure());
+ }));
// content_shell uses in-memory cookie database, so the value saved earlier
// won't persist across crashes. What matters is that new access works.
@@ -705,4 +1023,68 @@ IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest, Cookies) {
EXPECT_EQ("foo=bar", cookie);
}
+#if BUILDFLAG(ENABLE_PLUGINS)
+// Make sure that "trusted" plugins continue to be able to issue cross-origin
+// requests after a network process crash.
+IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest, Plugin) {
+ auto* web_contents = shell()->web_contents();
+ ASSERT_TRUE(NavigateToURL(web_contents,
+ embedded_test_server()->GetURL("/title1.html")));
+
+ // Load the test plugin (see ppapi::RegisterFlashTestPlugin and
+ // ppapi/tests/power_saver_test_plugin.cc).
+ const char kLoadingScript[] = R"(
+ var obj = document.createElement('object');
+ obj.id = 'plugin';
+ obj.data = 'test.swf';
+ obj.type = 'application/x-shockwave-flash';
+ obj.width = 400;
+ obj.height = 400;
+
+ document.body.appendChild(obj);
+ )";
+ ASSERT_TRUE(ExecJs(web_contents, kLoadingScript));
+
+ // Ask the plugin to perform a cross-origin, CORB-eligible (i.e.
+ // application/json + nosniff) URL request. Plugins with universal access
+ // should not be subject to CORS/CORB and so the request should go through.
+ // See also https://crbug.com/874515 and https://crbug.com/846339.
+ GURL cross_origin_url = embedded_test_server()->GetURL(
+ "cross.origin.com", "/site_isolation/nosniff.json");
+ const char kFetchScriptTemplate[] = R"(
+ new Promise(function (resolve, reject) {
+ var obj = document.getElementById('plugin');
+ function callback(event) {
+ // Ignore plugin messages unrelated to requestUrl.
+ if (!event.data.startsWith('requestUrl: '))
+ return;
+
+ obj.removeEventListener('message', callback);
+ resolve('msg-from-plugin: ' + event.data);
+ };
+ obj.addEventListener('message', callback);
+ obj.postMessage('requestUrl: ' + $1);
+ });
+ )";
+ std::string fetch_script = JsReplace(kFetchScriptTemplate, cross_origin_url);
+ ASSERT_EQ(
+ "msg-from-plugin: requestUrl: RESPONSE BODY: "
+ "runMe({ \"name\" : \"chromium\" });\n",
+ EvalJs(web_contents, fetch_script));
+
+ // Crash the Network Service process and wait until host frame's
+ // URLLoaderFactory has been refreshed.
+ SimulateNetworkServiceCrash();
+ main_frame()->FlushNetworkAndNavigationInterfacesForTesting();
+
+ // Try the fetch again - it should still work (i.e. the mechanism for relaxing
+ // CORB for universal-access-plugins should be resilient to network process
+ // crashes). See also https://crbug.com/891904.
+ ASSERT_EQ(
+ "msg-from-plugin: requestUrl: RESPONSE BODY: "
+ "runMe({ \"name\" : \"chromium\" });\n",
+ EvalJs(web_contents, fetch_script));
+}
+#endif
+
} // namespace content
diff --git a/chromium/content/browser/notification_service_impl.cc b/chromium/content/browser/notification_service_impl.cc
index 9f38bb05106..12581ecdfa2 100644
--- a/chromium/content/browser/notification_service_impl.cc
+++ b/chromium/content/browser/notification_service_impl.cc
@@ -146,8 +146,7 @@ NotificationServiceImpl::~NotificationServiceImpl() {
for (int i = 0; i < static_cast<int>(observers_.size()); i++) {
NotificationSourceMap omap = observers_[i];
- for (NotificationSourceMap::iterator it = omap.begin();
- it != omap.end(); ++it)
+ for (auto it = omap.begin(); it != omap.end(); ++it)
delete it->second;
}
}
diff --git a/chromium/content/browser/notifications/blink_notification_service_impl.cc b/chromium/content/browser/notifications/blink_notification_service_impl.cc
index 73c5d6b436e..2a4592f1565 100644
--- a/chromium/content/browser/notifications/blink_notification_service_impl.cc
+++ b/chromium/content/browser/notifications/blink_notification_service_impl.cc
@@ -7,10 +7,13 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/callback_helpers.h"
+#include "base/feature_list.h"
#include "base/logging.h"
#include "base/strings/string16.h"
+#include "base/task/post_task.h"
#include "content/browser/notifications/notification_event_dispatcher_impl.h"
#include "content/browser/notifications/platform_notification_context_impl.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/notification_database_data.h"
@@ -18,8 +21,9 @@
#include "content/public/browser/permission_type.h"
#include "content/public/browser/platform_notification_service.h"
#include "content/public/common/content_client.h"
-#include "content/public/common/notification_resources.h"
-#include "content/public/common/platform_notification_data.h"
+#include "content/public/common/content_features.h"
+#include "third_party/blink/public/common/notifications/notification_resources.h"
+#include "third_party/blink/public/common/notifications/platform_notification_data.h"
#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
#include "url/gurl.h"
@@ -27,6 +31,10 @@ namespace content {
namespace {
+const char kBadMessageImproperNotificationImage[] =
+ "Received an unexpected message with image while notification images are "
+ "disabled.";
+
// Returns the implementation of the PlatformNotificationService. May be NULL.
PlatformNotificationService* GetNotificationService() {
return GetContentClient()->browser()->GetPlatformNotificationService();
@@ -79,10 +87,13 @@ void BlinkNotificationServiceImpl::OnConnectionError() {
void BlinkNotificationServiceImpl::DisplayNonPersistentNotification(
const std::string& token,
- const PlatformNotificationData& platform_notification_data,
- const NotificationResources& notification_resources,
+ const blink::PlatformNotificationData& platform_notification_data,
+ const blink::NotificationResources& notification_resources,
blink::mojom::NonPersistentNotificationListenerPtr event_listener_ptr) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ if (!ValidateNotificationResources(notification_resources))
+ return;
+
if (!GetNotificationService())
return;
@@ -133,12 +144,28 @@ BlinkNotificationServiceImpl::CheckPermissionStatus() {
origin_.GetURL());
}
+bool BlinkNotificationServiceImpl::ValidateNotificationResources(
+ const blink::NotificationResources& notification_resources) {
+ if (notification_resources.image.drawsNothing() ||
+ base::FeatureList::IsEnabled(features::kNotificationContentImage))
+ return true;
+ binding_.ReportBadMessage(kBadMessageImproperNotificationImage);
+ // The above ReportBadMessage() closes |binding_| but does not trigger its
+ // connection error handler, so we need to call the error handler explicitly
+ // here to do some necessary work.
+ OnConnectionError();
+ return false;
+}
+
void BlinkNotificationServiceImpl::DisplayPersistentNotification(
int64_t service_worker_registration_id,
- const PlatformNotificationData& platform_notification_data,
- const NotificationResources& notification_resources,
+ const blink::PlatformNotificationData& platform_notification_data,
+ const blink::NotificationResources& notification_resources,
DisplayPersistentNotificationCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ if (!ValidateNotificationResources(notification_resources))
+ return;
+
if (!GetNotificationService()) {
std::move(callback).Run(PersistentNotificationError::INTERNAL_ERROR);
return;
@@ -153,8 +180,8 @@ void BlinkNotificationServiceImpl::DisplayPersistentNotification(
GetNotificationService()->ReadNextPersistentNotificationId(
browser_context_);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&BlinkNotificationServiceImpl::
DisplayPersistentNotificationOnIOThread,
weak_factory_for_io_.GetWeakPtr(),
@@ -166,8 +193,8 @@ void BlinkNotificationServiceImpl::DisplayPersistentNotification(
void BlinkNotificationServiceImpl::DisplayPersistentNotificationOnIOThread(
int64_t service_worker_registration_id,
int64_t next_persistent_notification_id,
- const PlatformNotificationData& platform_notification_data,
- const NotificationResources& notification_resources,
+ const blink::PlatformNotificationData& platform_notification_data,
+ const blink::NotificationResources& notification_resources,
DisplayPersistentNotificationCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -193,15 +220,15 @@ void BlinkNotificationServiceImpl::DisplayPersistentNotificationOnIOThread(
void BlinkNotificationServiceImpl::
DisplayPersistentNotificationWithIdOnIOThread(
int64_t service_worker_registration_id,
- const PlatformNotificationData& platform_notification_data,
- const NotificationResources& notification_resources,
+ const blink::PlatformNotificationData& platform_notification_data,
+ const blink::NotificationResources& notification_resources,
DisplayPersistentNotificationCallback callback,
bool success,
const std::string& notification_id) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (!success) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(std::move(callback),
PersistentNotificationError::INTERNAL_ERROR));
return;
@@ -220,8 +247,8 @@ void BlinkNotificationServiceImpl::
void BlinkNotificationServiceImpl::
DisplayPersistentNotificationWithServiceWorkerOnIOThread(
const std::string& notification_id,
- const PlatformNotificationData& platform_notification_data,
- const NotificationResources& notification_resources,
+ const blink::PlatformNotificationData& platform_notification_data,
+ const blink::NotificationResources& notification_resources,
DisplayPersistentNotificationCallback callback,
blink::ServiceWorkerStatusCode service_worker_status,
scoped_refptr<ServiceWorkerRegistration> registration) {
@@ -233,8 +260,8 @@ void BlinkNotificationServiceImpl::
// of the notification's sender.
if (service_worker_status == blink::ServiceWorkerStatusCode::kOk &&
registration->pattern().GetOrigin() == origin_.GetURL()) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(
&PlatformNotificationService::DisplayPersistentNotification,
base::Unretained(GetNotificationService()), browser_context_,
@@ -244,8 +271,8 @@ void BlinkNotificationServiceImpl::
error = PersistentNotificationError::NONE;
}
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(std::move(callback), error));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(std::move(callback), error));
}
void BlinkNotificationServiceImpl::ClosePersistentNotification(
@@ -263,8 +290,8 @@ void BlinkNotificationServiceImpl::ClosePersistentNotification(
// Deleting the data associated with |notification_id| from the notification
// database has to be done on the IO thread, but there's no reason to postpone
// removing the notification from the user's display until that's done.
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&PlatformNotificationContextImpl::DeleteNotificationData,
notification_context_, notification_id, origin_.GetURL(),
base::DoNothing()));
@@ -281,7 +308,7 @@ void BlinkNotificationServiceImpl::GetNotifications(
// try to get notifications without permission, so return empty vectors
// indicating that no (accessible) notifications exist at this time.
std::move(callback).Run(std::vector<std::string>(),
- std::vector<PlatformNotificationData>());
+ std::vector<blink::PlatformNotificationData>());
return;
}
@@ -289,8 +316,8 @@ void BlinkNotificationServiceImpl::GetNotifications(
&BlinkNotificationServiceImpl::DidGetNotificationsOnIOThread,
weak_factory_for_io_.GetWeakPtr(), filter_tag, std::move(callback));
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&PlatformNotificationContextImpl::
ReadAllNotificationDataForServiceWorkerRegistration,
notification_context_, origin_.GetURL(),
@@ -307,7 +334,7 @@ void BlinkNotificationServiceImpl::DidGetNotificationsOnIOThread(
DCHECK_CURRENTLY_ON(BrowserThread::IO);
std::vector<std::string> ids;
- std::vector<PlatformNotificationData> datas;
+ std::vector<blink::PlatformNotificationData> datas;
for (const NotificationDatabaseData& database_data : notifications) {
// An empty filter tag matches all, else we need an exact match.
@@ -319,8 +346,8 @@ void BlinkNotificationServiceImpl::DidGetNotificationsOnIOThread(
}
// Make sure to invoke the |callback| on the UI thread again.
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(std::move(callback), std::move(ids), std::move(datas)));
}
diff --git a/chromium/content/browser/notifications/blink_notification_service_impl.h b/chromium/content/browser/notifications/blink_notification_service_impl.h
index 193f5d241c3..1ae12ca9550 100644
--- a/chromium/content/browser/notifications/blink_notification_service_impl.h
+++ b/chromium/content/browser/notifications/blink_notification_service_impl.h
@@ -16,11 +16,14 @@
#include "third_party/blink/public/platform/modules/permissions/permission_status.mojom.h"
#include "url/origin.h"
+namespace blink {
+struct PlatformNotificationData;
+}
+
namespace content {
struct NotificationDatabaseData;
class PlatformNotificationContextImpl;
-struct PlatformNotificationData;
// Implementation of the NotificationService used for Web Notifications. Is
// responsible for displaying, updating and reading of both non-persistent
@@ -41,14 +44,14 @@ class CONTENT_EXPORT BlinkNotificationServiceImpl
void GetPermissionStatus(GetPermissionStatusCallback callback) override;
void DisplayNonPersistentNotification(
const std::string& token,
- const PlatformNotificationData& platform_notification_data,
- const NotificationResources& notification_resources,
+ const blink::PlatformNotificationData& platform_notification_data,
+ const blink::NotificationResources& notification_resources,
blink::mojom::NonPersistentNotificationListenerPtr listener_ptr) override;
void CloseNonPersistentNotification(const std::string& token) override;
void DisplayPersistentNotification(
int64_t service_worker_registration_id,
- const PlatformNotificationData& platform_notification_data,
- const NotificationResources& notification_resources,
+ const blink::PlatformNotificationData& platform_notification_data,
+ const blink::NotificationResources& notification_resources,
DisplayPersistentNotificationCallback) override;
void ClosePersistentNotification(const std::string& notification_id) override;
void GetNotifications(int64_t service_worker_registration_id,
@@ -62,25 +65,32 @@ class CONTENT_EXPORT BlinkNotificationServiceImpl
// Check the permission status for the current |origin_|.
blink::mojom::PermissionStatus CheckPermissionStatus();
+ // Validate |notification_resources| received in a Mojo IPC message.
+ // If the validation failed, we'd close the Mojo connection |binding_| and
+ // destroy |this| by calling OnConnectionError() directly, then return false.
+ // So, please do not touch |this| again after you got a false return value.
+ bool ValidateNotificationResources(
+ const blink::NotificationResources& notification_resources);
+
void DisplayPersistentNotificationOnIOThread(
int64_t service_worker_registration_id,
int64_t persistent_notification_id,
- const PlatformNotificationData& platform_notification_data,
- const NotificationResources& notification_resources,
+ const blink::PlatformNotificationData& platform_notification_data,
+ const blink::NotificationResources& notification_resources,
DisplayPersistentNotificationCallback callback);
void DisplayPersistentNotificationWithIdOnIOThread(
int64_t service_worker_registration_id,
- const PlatformNotificationData& platform_notification_data,
- const NotificationResources& notification_resources,
+ const blink::PlatformNotificationData& platform_notification_data,
+ const blink::NotificationResources& notification_resources,
DisplayPersistentNotificationCallback callback,
bool success,
const std::string& notification_id);
void DisplayPersistentNotificationWithServiceWorkerOnIOThread(
const std::string& notification_id,
- const PlatformNotificationData& platform_notification_data,
- const NotificationResources& notification_resources,
+ const blink::PlatformNotificationData& platform_notification_data,
+ const blink::NotificationResources& notification_resources,
DisplayPersistentNotificationCallback callback,
blink::ServiceWorkerStatusCode service_worker_status,
scoped_refptr<ServiceWorkerRegistration> registration);
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 618c7bd88cd..9985cfee820 100644
--- a/chromium/content/browser/notifications/blink_notification_service_impl_unittest.cc
+++ b/chromium/content/browser/notifications/blink_notification_service_impl_unittest.cc
@@ -11,6 +11,7 @@
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/run_loop.h"
+#include "base/test/scoped_feature_list.h"
#include "base/test/test_simple_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/notifications/blink_notification_service_impl.h"
@@ -19,18 +20,21 @@
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/common/service_worker/service_worker_types.h"
#include "content/public/browser/permission_type.h"
+#include "content/public/common/content_features.h"
#include "content/public/test/mock_permission_manager.h"
#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/public/test/test_utils.h"
#include "content/test/mock_platform_notification_service.h"
#include "content/test/test_content_browser_client.h"
+#include "mojo/core/embedder/embedder.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/bindings/interface_request.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/modules/notifications/notification_service.mojom.h"
#include "third_party/blink/public/platform/modules/permissions/permission_status.mojom.h"
+#include "third_party/skia/include/core/SkBitmap.h"
using ::testing::Return;
using ::testing::_;
@@ -41,6 +45,16 @@ namespace {
const char kTestOrigin[] = "https://example.com";
const char kTestServiceWorkerUrl[] = "https://example.com/sw.js";
+const char kBadMessageImproperNotificationImage[] =
+ "Received an unexpected message with image while notification images are "
+ "disabled.";
+
+SkBitmap CreateBitmap(int width, int height, SkColor color) {
+ SkBitmap bitmap;
+ bitmap.allocN32Pixels(width, height);
+ bitmap.eraseColor(color);
+ return bitmap;
+}
class MockNonPersistentNotificationListener
: public blink::mojom::NonPersistentNotificationListener {
@@ -110,19 +124,25 @@ class BlinkNotificationServiceImplTest : public ::testing::Test {
// will be initialized long before it is read from so this is fine.
RunAllTasksUntilIdle();
- blink::mojom::NotificationServicePtr notification_service_ptr;
notification_service_ = std::make_unique<BlinkNotificationServiceImpl>(
notification_context_.get(), &browser_context_,
embedded_worker_helper_->context_wrapper(),
url::Origin::Create(GURL(kTestOrigin)),
- mojo::MakeRequest(&notification_service_ptr));
+ mojo::MakeRequest(&notification_service_ptr_));
// Provide a mock permission manager to the |browser_context_|.
browser_context_.SetPermissionControllerDelegate(
std::make_unique<testing::NiceMock<MockPermissionManager>>());
+
+ mojo::core::SetDefaultProcessErrorCallback(base::AdaptCallbackForRepeating(
+ base::BindOnce(&BlinkNotificationServiceImplTest::OnMojoError,
+ base::Unretained(this))));
}
void TearDown() override {
+ mojo::core::SetDefaultProcessErrorCallback(
+ mojo::core::ProcessErrorCallback());
+
embedded_worker_helper_.reset();
// Give pending shutdown operations a chance to finish.
@@ -222,7 +242,7 @@ class BlinkNotificationServiceImplTest : public ::testing::Test {
void DidGetNotifications(
base::OnceClosure quit_closure,
const std::vector<std::string>& notification_ids,
- const std::vector<PlatformNotificationData>& notification_datas) {
+ const std::vector<blink::PlatformNotificationData>& notification_datas) {
get_notifications_callback_result_ = notification_ids;
std::move(quit_closure).Run();
}
@@ -242,12 +262,29 @@ class BlinkNotificationServiceImplTest : public ::testing::Test {
std::move(quit_closure).Run();
}
+ void DisplayNonPersistentNotification(
+ const std::string& token,
+ const blink::PlatformNotificationData& platform_notification_data,
+ const blink::NotificationResources& notification_resources,
+ blink::mojom::NonPersistentNotificationListenerPtr event_listener_ptr) {
+ notification_service_ptr_->DisplayNonPersistentNotification(
+ token, platform_notification_data, notification_resources,
+ std::move(event_listener_ptr));
+ // TODO(https://crbug.com/787459): Pass a callback to
+ // DisplayNonPersistentNotification instead of waiting for all tasks to run
+ // here; a callback parameter will be needed anyway to enable
+ // non-persistent notification event acknowledgements - see bug.
+ RunAllTasksUntilIdle();
+ }
+
void DisplayPersistentNotificationSync(
int64_t service_worker_registration_id,
- const PlatformNotificationData& platform_notification_data,
- const NotificationResources& notification_resources) {
+ const blink::PlatformNotificationData& platform_notification_data,
+ const blink::NotificationResources& notification_resources) {
base::RunLoop run_loop;
- notification_service_->DisplayPersistentNotification(
+ notification_service_ptr_.set_connection_error_handler(
+ run_loop.QuitClosure());
+ notification_service_ptr_->DisplayPersistentNotification(
service_worker_registration_id, platform_notification_data,
notification_resources,
base::BindOnce(
@@ -308,12 +345,16 @@ class BlinkNotificationServiceImplTest : public ::testing::Test {
}
protected:
+ void OnMojoError(const std::string& error) { bad_messages_.push_back(error); }
+
TestBrowserThreadBundle thread_bundle_; // Must be first member.
std::unique_ptr<EmbeddedWorkerTestHelper> embedded_worker_helper_;
std::unique_ptr<BlinkNotificationServiceImpl> notification_service_;
+ blink::mojom::NotificationServicePtr notification_service_ptr_;
+
TestBrowserContext browser_context_;
scoped_refptr<PlatformNotificationContextImpl> notification_context_;
@@ -324,6 +365,8 @@ class BlinkNotificationServiceImplTest : public ::testing::Test {
blink::mojom::PersistentNotificationError display_persistent_callback_result_;
+ std::vector<std::string> bad_messages_;
+
private:
NotificationBrowserClient notification_browser_client_;
@@ -383,16 +426,11 @@ TEST_F(BlinkNotificationServiceImplTest,
DisplayNonPersistentNotificationWithPermission) {
SetPermissionStatus(blink::mojom::PermissionStatus::GRANTED);
- notification_service_->DisplayNonPersistentNotification(
- "token", PlatformNotificationData(), NotificationResources(),
+ DisplayNonPersistentNotification(
+ "token", blink::PlatformNotificationData(),
+ blink::NotificationResources(),
non_persistent_notification_listener_.GetPtr());
- // TODO(https://crbug.com/787459): Pass a callback to
- // DisplayNonPersistentNotification instead of waiting for all tasks to run
- // here; a callback parameter will be needed anyway to enable
- // non-persistent notification event acknowledgements - see bug.
- RunAllTasksUntilIdle();
-
EXPECT_EQ(1u, GetDisplayedNotifications().size());
}
@@ -400,28 +438,94 @@ TEST_F(BlinkNotificationServiceImplTest,
DisplayNonPersistentNotificationWithoutPermission) {
SetPermissionStatus(blink::mojom::PermissionStatus::DENIED);
- notification_service_->DisplayNonPersistentNotification(
- "token", PlatformNotificationData(), NotificationResources(),
+ DisplayNonPersistentNotification(
+ "token", blink::PlatformNotificationData(),
+ blink::NotificationResources(),
non_persistent_notification_listener_.GetPtr());
- // TODO(https://crbug.com/787459): Pass a callback to
- // DisplayNonPersistentNotification instead of waiting for all tasks to run
- // here; a callback parameter will be needed anyway to enable
- // non-persistent notification event acknowledgements - see bug.
+ EXPECT_EQ(0u, GetDisplayedNotifications().size());
+}
+
+TEST_F(BlinkNotificationServiceImplTest,
+ DisplayNonPersistentNotificationWithContentImageSwitchOn) {
+ SetPermissionStatus(blink::mojom::PermissionStatus::GRANTED);
+
+ blink::NotificationResources resources;
+ resources.image = CreateBitmap(200, 100, SK_ColorMAGENTA);
+ DisplayNonPersistentNotification(
+ "token", blink::PlatformNotificationData(), resources,
+ non_persistent_notification_listener_.GetPtr());
+
+ EXPECT_EQ(1u, GetDisplayedNotifications().size());
+}
+
+TEST_F(BlinkNotificationServiceImplTest,
+ DisplayNonPersistentNotificationWithContentImageSwitchOff) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndDisableFeature(
+ features::kNotificationContentImage);
+ SetPermissionStatus(blink::mojom::PermissionStatus::GRANTED);
+
+ ASSERT_TRUE(bad_messages_.empty());
+ blink::NotificationResources resources;
+ resources.image = CreateBitmap(200, 100, SK_ColorMAGENTA);
+ DisplayNonPersistentNotification(
+ "token", blink::PlatformNotificationData(), resources,
+ non_persistent_notification_listener_.GetPtr());
+ EXPECT_EQ(1u, bad_messages_.size());
+ EXPECT_EQ(kBadMessageImproperNotificationImage, bad_messages_[0]);
+}
+
+TEST_F(BlinkNotificationServiceImplTest,
+ DisplayPersistentNotificationWithContentImageSwitchOn) {
+ SetPermissionStatus(blink::mojom::PermissionStatus::GRANTED);
+
+ scoped_refptr<ServiceWorkerRegistration> registration;
+ RegisterServiceWorker(&registration);
+
+ blink::NotificationResources resources;
+ resources.image = CreateBitmap(200, 100, SK_ColorMAGENTA);
+ DisplayPersistentNotificationSync(
+ registration->id(), blink::PlatformNotificationData(), resources);
+
+ EXPECT_EQ(blink::mojom::PersistentNotificationError::NONE,
+ display_persistent_callback_result_);
+
+ // Wait for service to receive the Display call.
RunAllTasksUntilIdle();
- EXPECT_EQ(0u, GetDisplayedNotifications().size());
+ EXPECT_EQ(1u, GetDisplayedNotifications().size());
}
TEST_F(BlinkNotificationServiceImplTest,
- DisplayPersistentNotificationWithPermission) {
+ DisplayPersistentNotificationWithContentImageSwitchOff) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndDisableFeature(
+ features::kNotificationContentImage);
SetPermissionStatus(blink::mojom::PermissionStatus::GRANTED);
scoped_refptr<ServiceWorkerRegistration> registration;
RegisterServiceWorker(&registration);
+ ASSERT_TRUE(bad_messages_.empty());
+ blink::NotificationResources resources;
+ resources.image = CreateBitmap(200, 100, SK_ColorMAGENTA);
DisplayPersistentNotificationSync(
- registration->id(), PlatformNotificationData(), NotificationResources());
+ registration->id(), blink::PlatformNotificationData(), resources);
+ EXPECT_EQ(1u, bad_messages_.size());
+ EXPECT_EQ(kBadMessageImproperNotificationImage, bad_messages_[0]);
+}
+
+TEST_F(BlinkNotificationServiceImplTest,
+ DisplayPersistentNotificationWithPermission) {
+ SetPermissionStatus(blink::mojom::PermissionStatus::GRANTED);
+
+ scoped_refptr<ServiceWorkerRegistration> registration;
+ RegisterServiceWorker(&registration);
+
+ DisplayPersistentNotificationSync(registration->id(),
+ blink::PlatformNotificationData(),
+ blink::NotificationResources());
EXPECT_EQ(blink::mojom::PersistentNotificationError::NONE,
display_persistent_callback_result_);
@@ -438,8 +542,9 @@ TEST_F(BlinkNotificationServiceImplTest, CloseDisplayedPersistentNotification) {
scoped_refptr<ServiceWorkerRegistration> registration;
RegisterServiceWorker(&registration);
- DisplayPersistentNotificationSync(
- registration->id(), PlatformNotificationData(), NotificationResources());
+ DisplayPersistentNotificationSync(registration->id(),
+ blink::PlatformNotificationData(),
+ blink::NotificationResources());
ASSERT_EQ(blink::mojom::PersistentNotificationError::NONE,
display_persistent_callback_result_);
@@ -465,8 +570,9 @@ TEST_F(BlinkNotificationServiceImplTest,
scoped_refptr<ServiceWorkerRegistration> registration;
RegisterServiceWorker(&registration);
- DisplayPersistentNotificationSync(
- registration->id(), PlatformNotificationData(), NotificationResources());
+ DisplayPersistentNotificationSync(registration->id(),
+ blink::PlatformNotificationData(),
+ blink::NotificationResources());
ASSERT_EQ(blink::mojom::PersistentNotificationError::NONE,
display_persistent_callback_result_);
@@ -498,8 +604,9 @@ TEST_F(BlinkNotificationServiceImplTest,
scoped_refptr<ServiceWorkerRegistration> registration;
RegisterServiceWorker(&registration);
- DisplayPersistentNotificationSync(
- registration->id(), PlatformNotificationData(), NotificationResources());
+ DisplayPersistentNotificationSync(registration->id(),
+ blink::PlatformNotificationData(),
+ blink::NotificationResources());
EXPECT_EQ(blink::mojom::PersistentNotificationError::PERMISSION_DENIED,
display_persistent_callback_result_);
@@ -517,11 +624,13 @@ TEST_F(BlinkNotificationServiceImplTest,
scoped_refptr<ServiceWorkerRegistration> registration;
RegisterServiceWorker(&registration);
- DisplayPersistentNotificationSync(
- registration->id(), PlatformNotificationData(), NotificationResources());
+ DisplayPersistentNotificationSync(registration->id(),
+ blink::PlatformNotificationData(),
+ blink::NotificationResources());
- DisplayPersistentNotificationSync(
- registration->id(), PlatformNotificationData(), NotificationResources());
+ DisplayPersistentNotificationSync(registration->id(),
+ blink::PlatformNotificationData(),
+ blink::NotificationResources());
// Wait for service to receive all the Display calls.
RunAllTasksUntilIdle();
@@ -538,8 +647,9 @@ TEST_F(BlinkNotificationServiceImplTest, GetNotifications) {
EXPECT_EQ(
0u, GetNotificationsSync(registration->id(), "" /* filter_tag */).size());
- DisplayPersistentNotificationSync(
- registration->id(), PlatformNotificationData(), NotificationResources());
+ DisplayPersistentNotificationSync(registration->id(),
+ blink::PlatformNotificationData(),
+ blink::NotificationResources());
// Wait for service to receive all the Display calls.
RunAllTasksUntilIdle();
@@ -554,8 +664,9 @@ TEST_F(BlinkNotificationServiceImplTest, GetNotificationsWithoutPermission) {
scoped_refptr<ServiceWorkerRegistration> registration;
RegisterServiceWorker(&registration);
- DisplayPersistentNotificationSync(
- registration->id(), PlatformNotificationData(), NotificationResources());
+ DisplayPersistentNotificationSync(registration->id(),
+ blink::PlatformNotificationData(),
+ blink::NotificationResources());
// Wait for service to receive all the Display calls.
RunAllTasksUntilIdle();
@@ -572,18 +683,19 @@ TEST_F(BlinkNotificationServiceImplTest, GetNotificationsWithFilter) {
scoped_refptr<ServiceWorkerRegistration> registration;
RegisterServiceWorker(&registration);
- PlatformNotificationData platform_notification_data;
+ blink::PlatformNotificationData platform_notification_data;
platform_notification_data.tag = "tagA";
- PlatformNotificationData other_platform_notification_data;
+ blink::PlatformNotificationData other_platform_notification_data;
other_platform_notification_data.tag = "tagB";
- DisplayPersistentNotificationSync(
- registration->id(), platform_notification_data, NotificationResources());
+ DisplayPersistentNotificationSync(registration->id(),
+ platform_notification_data,
+ blink::NotificationResources());
DisplayPersistentNotificationSync(registration->id(),
other_platform_notification_data,
- NotificationResources());
+ blink::NotificationResources());
// Wait for service to receive all the Display calls.
RunAllTasksUntilIdle();
diff --git a/chromium/content/browser/notifications/notification_database.cc b/chromium/content/browser/notifications/notification_database.cc
index bc54e5a090f..85c98c8b117 100644
--- a/chromium/content/browser/notifications/notification_database.cc
+++ b/chromium/content/browser/notifications/notification_database.cc
@@ -10,8 +10,10 @@
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
+#include "base/task/post_task.h"
#include "content/browser/notifications/notification_database_data_conversions.h"
#include "content/common/service_worker/service_worker_types.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_database_data.h"
#include "storage/common/database/database_identifier.h"
@@ -268,8 +270,8 @@ NotificationDatabase::Status NotificationDatabase::DeleteNotificationData(
NotificationDatabaseData data;
Status status = ReadNotificationData(notification_id, origin, &data);
if (status == STATUS_OK && record_notification_to_ukm_callback_) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(record_notification_to_ukm_callback_, data));
}
std::string key = CreateDataKey(origin, notification_id);
@@ -392,8 +394,8 @@ NotificationDatabase::DeleteAllNotificationDataInternal(
}
if (record_notification_to_ukm_callback_) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(record_notification_to_ukm_callback_,
notification_database_data));
}
diff --git a/chromium/content/browser/notifications/notification_database_data.proto b/chromium/content/browser/notifications/notification_database_data.proto
index 6a631180461..e521c888634 100644
--- a/chromium/content/browser/notifications/notification_database_data.proto
+++ b/chromium/content/browser/notifications/notification_database_data.proto
@@ -35,11 +35,11 @@ message NotificationDatabaseDataProto {
optional int64 time_until_close_millis = 12;
optional ClosedReason closed_reason = 13;
- // A notification action, corresponds to content::PlatformNotificationAction.
+ // A notification action, corresponds to blink::PlatformNotificationAction.
//
// Next tag: 6
message NotificationAction {
- // Corresponds to PlatformNotificationActionType.
+ // Corresponds to blink::PlatformNotificationActionType.
enum Type {
BUTTON = 0;
TEXT = 1;
@@ -53,7 +53,7 @@ message NotificationDatabaseDataProto {
}
// Actual data payload of the notification. This message is the protocol
- // buffer meant to serialize the content::PlatformNotificationData structure.
+ // buffer meant to serialize the blink::PlatformNotificationData structure.
//
// Next tag: 16
message NotificationData {
diff --git a/chromium/content/browser/notifications/notification_database_data_conversions.cc b/chromium/content/browser/notifications/notification_database_data_conversions.cc
index 904963094eb..83b0b0043fc 100644
--- a/chromium/content/browser/notifications/notification_database_data_conversions.cc
+++ b/chromium/content/browser/notifications/notification_database_data_conversions.cc
@@ -60,7 +60,8 @@ bool DeserializeNotificationDatabaseData(const std::string& input,
break;
}
- PlatformNotificationData* notification_data = &output->notification_data;
+ blink::PlatformNotificationData* notification_data =
+ &output->notification_data;
const NotificationDatabaseDataProto::NotificationData& payload =
message.notification_data();
@@ -69,14 +70,15 @@ bool DeserializeNotificationDatabaseData(const std::string& input,
switch (payload.direction()) {
case NotificationDatabaseDataProto::NotificationData::LEFT_TO_RIGHT:
notification_data->direction =
- PlatformNotificationData::DIRECTION_LEFT_TO_RIGHT;
+ blink::PlatformNotificationData::DIRECTION_LEFT_TO_RIGHT;
break;
case NotificationDatabaseDataProto::NotificationData::RIGHT_TO_LEFT:
notification_data->direction =
- PlatformNotificationData::DIRECTION_RIGHT_TO_LEFT;
+ blink::PlatformNotificationData::DIRECTION_RIGHT_TO_LEFT;
break;
case NotificationDatabaseDataProto::NotificationData::AUTO:
- notification_data->direction = PlatformNotificationData::DIRECTION_AUTO;
+ notification_data->direction =
+ blink::PlatformNotificationData::DIRECTION_AUTO;
break;
}
@@ -110,14 +112,14 @@ bool DeserializeNotificationDatabaseData(const std::string& input,
notification_data->actions.clear();
for (const auto& payload_action : payload.actions()) {
- PlatformNotificationAction action;
+ blink::PlatformNotificationAction action;
switch (payload_action.type()) {
case NotificationDatabaseDataProto::NotificationAction::BUTTON:
- action.type = PLATFORM_NOTIFICATION_ACTION_TYPE_BUTTON;
+ action.type = blink::PLATFORM_NOTIFICATION_ACTION_TYPE_BUTTON;
break;
case NotificationDatabaseDataProto::NotificationAction::TEXT:
- action.type = PLATFORM_NOTIFICATION_ACTION_TYPE_TEXT;
+ action.type = blink::PLATFORM_NOTIFICATION_ACTION_TYPE_TEXT;
break;
default:
NOTREACHED();
@@ -143,20 +145,21 @@ bool SerializeNotificationDatabaseData(const NotificationDatabaseData& input,
std::unique_ptr<NotificationDatabaseDataProto::NotificationData> payload(
new NotificationDatabaseDataProto::NotificationData());
- const PlatformNotificationData& notification_data = input.notification_data;
+ const blink::PlatformNotificationData& notification_data =
+ input.notification_data;
payload->set_title(base::UTF16ToUTF8(notification_data.title));
switch (notification_data.direction) {
- case PlatformNotificationData::DIRECTION_LEFT_TO_RIGHT:
+ case blink::PlatformNotificationData::DIRECTION_LEFT_TO_RIGHT:
payload->set_direction(
NotificationDatabaseDataProto::NotificationData::LEFT_TO_RIGHT);
break;
- case PlatformNotificationData::DIRECTION_RIGHT_TO_LEFT:
+ case blink::PlatformNotificationData::DIRECTION_RIGHT_TO_LEFT:
payload->set_direction(
NotificationDatabaseDataProto::NotificationData::RIGHT_TO_LEFT);
break;
- case PlatformNotificationData::DIRECTION_AUTO:
+ case blink::PlatformNotificationData::DIRECTION_AUTO:
payload->set_direction(
NotificationDatabaseDataProto::NotificationData::AUTO);
break;
@@ -182,16 +185,17 @@ bool SerializeNotificationDatabaseData(const NotificationDatabaseData& input,
notification_data.data.size());
}
- for (const PlatformNotificationAction& action : notification_data.actions) {
+ for (const blink::PlatformNotificationAction& action :
+ notification_data.actions) {
NotificationDatabaseDataProto::NotificationAction* payload_action =
payload->add_actions();
switch (action.type) {
- case PLATFORM_NOTIFICATION_ACTION_TYPE_BUTTON:
+ case blink::PLATFORM_NOTIFICATION_ACTION_TYPE_BUTTON:
payload_action->set_type(
NotificationDatabaseDataProto::NotificationAction::BUTTON);
break;
- case PLATFORM_NOTIFICATION_ACTION_TYPE_TEXT:
+ case blink::PLATFORM_NOTIFICATION_ACTION_TYPE_TEXT:
payload_action->set_type(
NotificationDatabaseDataProto::NotificationAction::TEXT);
break;
diff --git a/chromium/content/browser/notifications/notification_database_data_unittest.cc b/chromium/content/browser/notifications/notification_database_data_unittest.cc
index 9de61d52c50..db0241218f9 100644
--- a/chromium/content/browser/notifications/notification_database_data_unittest.cc
+++ b/chromium/content/browser/notifications/notification_database_data_unittest.cc
@@ -30,8 +30,8 @@ const int kTimeUntilFirstClickMillis = 11111;
const int kTimeUntilLastClickMillis = 22222;
const int kTimeUntilCloseMillis = 33333;
-const PlatformNotificationActionType kNotificationActionType =
- PLATFORM_NOTIFICATION_ACTION_TYPE_TEXT;
+const blink::PlatformNotificationActionType kNotificationActionType =
+ blink::PLATFORM_NOTIFICATION_ACTION_TYPE_TEXT;
const char kOrigin[] = "https://example.com/";
const char kNotificationTitle[] = "My Notification";
const char kNotificationLang[] = "nl";
@@ -54,10 +54,10 @@ TEST(NotificationDatabaseDataTest, SerializeAndDeserializeData) {
std::vector<char> developer_data(
kNotificationData, kNotificationData + base::size(kNotificationData));
- PlatformNotificationData notification_data;
+ blink::PlatformNotificationData notification_data;
notification_data.title = base::ASCIIToUTF16(kNotificationTitle);
notification_data.direction =
- PlatformNotificationData::DIRECTION_RIGHT_TO_LEFT;
+ blink::PlatformNotificationData::DIRECTION_RIGHT_TO_LEFT;
notification_data.lang = kNotificationLang;
notification_data.body = base::ASCIIToUTF16(kNotificationBody);
notification_data.tag = kNotificationTag;
@@ -71,7 +71,7 @@ TEST(NotificationDatabaseDataTest, SerializeAndDeserializeData) {
notification_data.require_interaction = true;
notification_data.data = developer_data;
for (size_t i = 0; i < blink::kWebNotificationMaxActions; i++) {
- PlatformNotificationAction notification_action;
+ blink::PlatformNotificationAction notification_action;
notification_action.type = kNotificationActionType;
notification_action.action = base::NumberToString(i);
notification_action.title = base::NumberToString16(i);
@@ -128,7 +128,7 @@ TEST(NotificationDatabaseDataTest, SerializeAndDeserializeData) {
copied_data.time_until_close_millis);
EXPECT_EQ(database_data.closed_reason, copied_data.closed_reason);
- const PlatformNotificationData& copied_notification_data =
+ const blink::PlatformNotificationData& copied_notification_data =
copied_data.notification_data;
EXPECT_EQ(notification_data.title, copied_notification_data.title);
@@ -199,14 +199,14 @@ TEST(NotificationDatabaseDataTest, ActionDeserializationIsNotAdditive) {
}
TEST(NotificationDatabaseDataTest, SerializeAndDeserializeActionTypes) {
- PlatformNotificationActionType action_types[] = {
- PLATFORM_NOTIFICATION_ACTION_TYPE_BUTTON,
- PLATFORM_NOTIFICATION_ACTION_TYPE_TEXT};
+ blink::PlatformNotificationActionType action_types[] = {
+ blink::PLATFORM_NOTIFICATION_ACTION_TYPE_BUTTON,
+ blink::PLATFORM_NOTIFICATION_ACTION_TYPE_TEXT};
- for (PlatformNotificationActionType action_type : action_types) {
- PlatformNotificationData notification_data;
+ for (blink::PlatformNotificationActionType action_type : action_types) {
+ blink::PlatformNotificationData notification_data;
- PlatformNotificationAction action;
+ blink::PlatformNotificationAction action;
action.type = action_type;
notification_data.actions.push_back(action);
@@ -226,13 +226,13 @@ TEST(NotificationDatabaseDataTest, SerializeAndDeserializeActionTypes) {
}
TEST(NotificationDatabaseDataTest, SerializeAndDeserializeDirections) {
- PlatformNotificationData::Direction directions[] = {
- PlatformNotificationData::DIRECTION_LEFT_TO_RIGHT,
- PlatformNotificationData::DIRECTION_RIGHT_TO_LEFT,
- PlatformNotificationData::DIRECTION_AUTO};
+ blink::PlatformNotificationData::Direction directions[] = {
+ blink::PlatformNotificationData::DIRECTION_LEFT_TO_RIGHT,
+ blink::PlatformNotificationData::DIRECTION_RIGHT_TO_LEFT,
+ blink::PlatformNotificationData::DIRECTION_AUTO};
for (size_t i = 0; i < base::size(directions); ++i) {
- PlatformNotificationData notification_data;
+ blink::PlatformNotificationData notification_data;
notification_data.direction = directions[i];
NotificationDatabaseData database_data;
@@ -273,11 +273,11 @@ TEST(NotificationDatabaseDataTest, SerializeAndDeserializeClosedReasons) {
}
TEST(NotificationDatabaseDataTest, SerializeAndDeserializeNullPlaceholder) {
- PlatformNotificationAction action;
+ blink::PlatformNotificationAction action;
action.type = kNotificationActionType;
action.placeholder = base::NullableString16(); // null string.
- PlatformNotificationData notification_data;
+ blink::PlatformNotificationData notification_data;
notification_data.actions.push_back(action);
NotificationDatabaseData database_data;
diff --git a/chromium/content/browser/notifications/notification_database_unittest.cc b/chromium/content/browser/notifications/notification_database_unittest.cc
index fb0d6cb80fe..8f0978c3a15 100644
--- a/chromium/content/browser/notifications/notification_database_unittest.cc
+++ b/chromium/content/browser/notifications/notification_database_unittest.cc
@@ -13,9 +13,9 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "content/public/browser/notification_database_data.h"
-#include "content/public/common/platform_notification_data.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/notifications/platform_notification_data.h"
#include "third_party/leveldatabase/src/include/leveldb/db.h"
#include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
#include "url/gurl.h"
@@ -283,10 +283,10 @@ TEST_F(NotificationDatabaseTest, ReadNotificationDataReflection) {
GURL origin("https://example.com");
- PlatformNotificationData notification_data;
+ blink::PlatformNotificationData notification_data;
notification_data.title = base::UTF8ToUTF16("My Notification");
notification_data.direction =
- PlatformNotificationData::DIRECTION_RIGHT_TO_LEFT;
+ blink::PlatformNotificationData::DIRECTION_RIGHT_TO_LEFT;
notification_data.lang = "nl-NL";
notification_data.body = base::UTF8ToUTF16("Hello, world!");
notification_data.tag = "replace id";
@@ -318,7 +318,7 @@ TEST_F(NotificationDatabaseTest, ReadNotificationDataReflection) {
EXPECT_EQ(database_data.service_worker_registration_id,
read_database_data.service_worker_registration_id);
- const PlatformNotificationData& read_notification_data =
+ const blink::PlatformNotificationData& read_notification_data =
read_database_data.notification_data;
EXPECT_EQ(notification_data.title, read_notification_data.title);
diff --git a/chromium/content/browser/notifications/notification_event_dispatcher_impl.cc b/chromium/content/browser/notifications/notification_event_dispatcher_impl.cc
index d8acb3229bf..db206cc9fc7 100644
--- a/chromium/content/browser/notifications/notification_event_dispatcher_impl.cc
+++ b/chromium/content/browser/notifications/notification_event_dispatcher_impl.cc
@@ -8,17 +8,19 @@
#include "base/callback.h"
#include "base/callback_helpers.h"
#include "base/optional.h"
+#include "base/task/post_task.h"
#include "build/build_config.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"
#include "content/browser/service_worker/service_worker_storage.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/common/persistent_notification_status.h"
-#include "content/public/common/platform_notification_data.h"
+#include "third_party/blink/public/common/notifications/platform_notification_data.h"
namespace content {
namespace {
@@ -40,8 +42,8 @@ void NotificationEventFinished(
PersistentNotificationStatus status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(dispatch_complete_callback, status));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(dispatch_complete_callback, status));
}
// To be called when a notification event has finished with a
@@ -146,8 +148,8 @@ void DispatchNotificationEventOnRegistration(
break;
}
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(dispatch_error_callback, status));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(dispatch_error_callback, status));
}
// Finds the ServiceWorkerRegistration associated with the |origin| and
@@ -169,8 +171,8 @@ void FindServiceWorkerRegistration(
LOG(INFO) << "Lookup for ServiceWoker Registration: success: " << success;
#endif
if (!success) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(dispatch_error_callback,
PersistentNotificationStatus::kDatabaseError));
return;
@@ -353,8 +355,8 @@ void DispatchNotificationEvent(
scoped_refptr<PlatformNotificationContext> notification_context =
partition->GetPlatformNotificationContext();
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&ReadNotificationDatabaseData, notification_id, origin, interaction,
service_worker_context, notification_context,
diff --git a/chromium/content/browser/notifications/notification_id_generator.cc b/chromium/content/browser/notifications/notification_id_generator.cc
index 99fa0034c4d..9ab34c96aae 100644
--- a/chromium/content/browser/notifications/notification_id_generator.cc
+++ b/chromium/content/browser/notifications/notification_id_generator.cc
@@ -64,7 +64,7 @@ std::string NotificationIdGenerator::GenerateForPersistentNotification(
std::string NotificationIdGenerator::GenerateForNonPersistentNotification(
const url::Origin& origin,
const std::string& token) const {
- DCHECK(!origin.unique());
+ DCHECK(!origin.opaque());
DCHECK(!token.empty());
return base::StringPrintf(
"%c%c%s%c%s", kNonPersistentNotificationPrefix, kNotificationTagSeparator,
diff --git a/chromium/content/browser/notifications/platform_notification_context_impl.cc b/chromium/content/browser/notifications/platform_notification_context_impl.cc
index 13ece81608b..9b31e66db71 100644
--- a/chromium/content/browser/notifications/platform_notification_context_impl.cc
+++ b/chromium/content/browser/notifications/platform_notification_context_impl.cc
@@ -13,6 +13,7 @@
#include "content/browser/notifications/notification_database.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/notification_database_data.h"
@@ -55,8 +56,8 @@ void PlatformNotificationContextImpl::Initialize() {
GetContentClient()->browser()->GetPlatformNotificationService();
if (!service) {
auto displayed_notifications = std::make_unique<std::set<std::string>>();
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&PlatformNotificationContextImpl::InitializeOnIO, this,
std::move(displayed_notifications), false));
return;
@@ -76,8 +77,8 @@ void PlatformNotificationContextImpl::DidGetNotificationsOnUI(
std::unique_ptr<std::set<std::string>> displayed_notifications,
bool supports_synchronization) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&PlatformNotificationContextImpl::InitializeOnIO, this,
std::move(displayed_notifications),
supports_synchronization));
@@ -112,8 +113,8 @@ void PlatformNotificationContextImpl::Shutdown() {
services_.clear();
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&PlatformNotificationContextImpl::ShutdownOnIO, this));
}
@@ -173,8 +174,8 @@ void PlatformNotificationContextImpl::DoReadNotificationData(
NotificationDatabase::STATUS_COUNT);
if (status == NotificationDatabase::STATUS_OK) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(callback, true /* success */, database_data));
return;
}
@@ -183,9 +184,9 @@ void PlatformNotificationContextImpl::DoReadNotificationData(
if (status == NotificationDatabase::STATUS_ERROR_CORRUPTED)
DestroyDatabase();
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::BindOnce(callback, false /* success */,
- NotificationDatabaseData()));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(callback, false /* success */,
+ NotificationDatabaseData()));
}
void PlatformNotificationContextImpl::
@@ -197,8 +198,8 @@ void PlatformNotificationContextImpl::
bool supports_synchronization) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&PlatformNotificationContextImpl::
SynchronizeDisplayedNotificationsForServiceWorkerRegistrationOnIO,
@@ -243,8 +244,8 @@ void PlatformNotificationContextImpl::
return;
}
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(
&PlatformNotificationService::GetDisplayedNotifications,
base::Unretained(service), browser_context_,
@@ -291,8 +292,8 @@ void PlatformNotificationContextImpl::
}
}
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(callback, true /* success */, notification_datas));
// Remove notifications that are not actually on display anymore.
@@ -305,8 +306,8 @@ void PlatformNotificationContextImpl::
if (status == NotificationDatabase::STATUS_ERROR_CORRUPTED)
DestroyDatabase();
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(callback, false /* success */,
std::vector<NotificationDatabaseData>()));
}
@@ -352,9 +353,9 @@ void PlatformNotificationContextImpl::DoWriteNotificationData(
if (delete_status == NotificationDatabase::STATUS_ERROR_CORRUPTED) {
DestroyDatabase();
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::BindOnce(callback, false /* success */,
- "" /* notification_id */));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(callback, false /* success */,
+ "" /* notification_id */));
return;
}
}
@@ -373,8 +374,8 @@ void PlatformNotificationContextImpl::DoWriteNotificationData(
NotificationDatabase::STATUS_COUNT);
if (status == NotificationDatabase::STATUS_OK) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(callback, true /* success */,
write_database_data.notification_id));
@@ -385,8 +386,8 @@ void PlatformNotificationContextImpl::DoWriteNotificationData(
if (status == NotificationDatabase::STATUS_ERROR_CORRUPTED)
DestroyDatabase();
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(callback, false /* success */, "" /* notification_id */));
}
@@ -424,8 +425,8 @@ void PlatformNotificationContextImpl::DoDeleteNotificationData(
success = true;
}
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::BindOnce(callback, success));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(callback, success));
}
void PlatformNotificationContextImpl::OnRegistrationDeleted(
@@ -536,7 +537,7 @@ void PlatformNotificationContextImpl::OpenDatabase(
database_.reset();
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, failure_closure);
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO}, failure_closure);
}
bool PlatformNotificationContextImpl::DestroyDatabase() {
diff --git a/chromium/content/browser/notifications/platform_notification_context_unittest.cc b/chromium/content/browser/notifications/platform_notification_context_unittest.cc
index 1e566931611..761d302fbf3 100644
--- a/chromium/content/browser/notifications/platform_notification_context_unittest.cc
+++ b/chromium/content/browser/notifications/platform_notification_context_unittest.cc
@@ -15,12 +15,12 @@
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/common/service_worker/service_worker_types.h"
#include "content/public/browser/notification_database_data.h"
-#include "content/public/common/notification_resources.h"
#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/test/mock_platform_notification_service.h"
#include "content/test/test_content_browser_client.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/notifications/notification_resources.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
#include "url/gurl.h"
@@ -530,8 +530,8 @@ TEST_F(PlatformNotificationContextTest, SynchronizeNotifications) {
NotificationDatabaseData notification_database_data;
notification_database_data.service_worker_registration_id =
kFakeServiceWorkerRegistrationId;
- PlatformNotificationData notification_data;
- content::NotificationResources notification_resources;
+ blink::PlatformNotificationData notification_data;
+ blink::NotificationResources notification_resources;
context->WriteNotificationData(
next_persistent_notification_id(), kFakeServiceWorkerRegistrationId,
diff --git a/chromium/content/browser/ns_view_bridge_factory_host.mm b/chromium/content/browser/ns_view_bridge_factory_host.mm
new file mode 100644
index 00000000000..c1c59669e36
--- /dev/null
+++ b/chromium/content/browser/ns_view_bridge_factory_host.mm
@@ -0,0 +1,51 @@
+// 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/ns_view_bridge_factory_host.h"
+
+#include "base/no_destructor.h"
+
+namespace content {
+
+namespace {
+
+using HostIdToFactoryMap = std::map<uint64_t, NSViewBridgeFactoryHost*>;
+
+HostIdToFactoryMap* GetHostIdToFactoryMap() {
+ static base::NoDestructor<HostIdToFactoryMap> instance;
+ return instance.get();
+}
+
+} // namespace
+
+// static
+const uint64_t NSViewBridgeFactoryHost::kLocalDirectHostId = -1;
+
+// static
+NSViewBridgeFactoryHost* NSViewBridgeFactoryHost::GetFromHostId(
+ uint64_t host_id) {
+ auto found = GetHostIdToFactoryMap()->find(host_id);
+ if (found == GetHostIdToFactoryMap()->end())
+ return nullptr;
+ return found->second;
+}
+
+NSViewBridgeFactoryHost::NSViewBridgeFactoryHost(
+ mojom::NSViewBridgeFactoryAssociatedRequest* request,
+ uint64_t host_id)
+ : host_id_(host_id) {
+ *request = mojo::MakeRequest(&factory_);
+ DCHECK(!GetHostIdToFactoryMap()->count(host_id_));
+ GetHostIdToFactoryMap()->insert(std::make_pair(host_id_, this));
+}
+
+NSViewBridgeFactoryHost::~NSViewBridgeFactoryHost() {
+ GetHostIdToFactoryMap()->erase(host_id_);
+}
+
+mojom::NSViewBridgeFactory* NSViewBridgeFactoryHost::GetFactory() {
+ return factory_.get();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/ns_view_bridge_factory_impl.mm b/chromium/content/browser/ns_view_bridge_factory_impl.mm
new file mode 100644
index 00000000000..5230e9f97a0
--- /dev/null
+++ b/chromium/content/browser/ns_view_bridge_factory_impl.mm
@@ -0,0 +1,63 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/public/browser/ns_view_bridge_factory_impl.h"
+
+#include <utility>
+
+#include "base/macros.h"
+#include "base/no_destructor.h"
+#include "content/browser/renderer_host/render_widget_host_ns_view_bridge_local.h"
+#include "content/browser/web_contents/web_contents_ns_view_bridge.h"
+#include "ui/accelerated_widget_mac/window_resize_helper_mac.h"
+
+namespace content {
+
+// static
+NSViewBridgeFactoryImpl* NSViewBridgeFactoryImpl::Get() {
+ static base::NoDestructor<NSViewBridgeFactoryImpl> instance;
+ return instance.get();
+}
+
+void NSViewBridgeFactoryImpl::BindRequest(
+ mojom::NSViewBridgeFactoryAssociatedRequest request) {
+ binding_.Bind(std::move(request),
+ ui::WindowResizeHelperMac::Get()->task_runner());
+}
+
+void NSViewBridgeFactoryImpl::CreateRenderWidgetHostNSViewBridge(
+ mojom::StubInterfaceAssociatedPtrInfo stub_client,
+ mojom::StubInterfaceAssociatedRequest stub_bridge_request) {
+ // Cast from the stub interface to the mojom::RenderWidgetHostNSViewClient
+ // and mojom::RenderWidgetHostNSViewBridge private interfaces.
+ // TODO(ccameron): Remove the need for this cast.
+ // https://crbug.com/888290
+ mojom::RenderWidgetHostNSViewClientAssociatedPtr client(
+ mojo::AssociatedInterfacePtrInfo<mojom::RenderWidgetHostNSViewClient>(
+ stub_client.PassHandle(), 0));
+ mojom::RenderWidgetHostNSViewBridgeAssociatedRequest bridge_request(
+ stub_bridge_request.PassHandle());
+
+ // Create a RenderWidgetHostNSViewBridgeLocal. The resulting object will be
+ // destroyed when its underlying pipe is closed.
+ ignore_result(new RenderWidgetHostNSViewBridgeLocal(
+ std::move(client), std::move(bridge_request)));
+}
+
+void NSViewBridgeFactoryImpl::CreateWebContentsNSViewBridge(
+ uint64_t view_id,
+ mojom::WebContentsNSViewClientAssociatedPtrInfo client,
+ mojom::WebContentsNSViewBridgeAssociatedRequest bridge_request) {
+ // Note that the resulting object will be destroyed when its underlying pipe
+ // is closed.
+ ignore_result(new WebContentsNSViewBridge(
+ view_id, mojom::WebContentsNSViewClientAssociatedPtr(std::move(client)),
+ std::move(bridge_request)));
+}
+
+NSViewBridgeFactoryImpl::NSViewBridgeFactoryImpl() : binding_(this) {}
+
+NSViewBridgeFactoryImpl::~NSViewBridgeFactoryImpl() {}
+
+} // namespace content
diff --git a/chromium/content/browser/oop_browsertest.cc b/chromium/content/browser/oop_browsertest.cc
index eaf658ca213..3fcfe558d33 100644
--- a/chromium/content/browser/oop_browsertest.cc
+++ b/chromium/content/browser/oop_browsertest.cc
@@ -38,7 +38,7 @@ class OOPBrowserTest : public ContentBrowserTest {
command_line->AppendSwitch(switches::kEnablePixelOutputInTests);
command_line->AppendSwitch(switches::kEnableOopRasterization);
- const bool use_gpu_in_tests = !features::IsUsingWindowService();
+ const bool use_gpu_in_tests = !features::IsMultiProcessMash();
if (use_gpu_in_tests)
command_line->AppendSwitch(switches::kUseGpuInTests);
}
@@ -54,7 +54,13 @@ class OOPBrowserTest : public ContentBrowserTest {
// This test calls into system GL which is not instrumented with MSAN.
#if !defined(MEMORY_SANITIZER)
-IN_PROC_BROWSER_TEST_F(OOPBrowserTest, Basic) {
+// TODO(crbug.com/880948) Disabled for crashes on Linux CFI, see bug.
+#if defined(OS_LINUX)
+#define MAYBE_Basic DISABLED_Basic
+#else
+#define MAYBE_Basic Basic
+#endif
+IN_PROC_BROWSER_TEST_F(OOPBrowserTest, MAYBE_Basic) {
// Create a div to ensure we don't use solid color quads.
GURL url = GURL(
"data:text/html,"
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 d604c1992fa..a8d1286084b 100644
--- a/chromium/content/browser/payments/payment_app_content_unittest_base.cc
+++ b/chromium/content/browser/payments/payment_app_content_unittest_base.cc
@@ -95,7 +95,7 @@ class PaymentAppContentUnitTestBase::PaymentAppForWorkerTestHelper
} else {
pending_response_callback_ = std::move(response_callback);
std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
- base::Time::Now());
+ base::TimeTicks::Now());
}
}
@@ -227,7 +227,8 @@ void PaymentAppContentUnitTestBase::SetNoPaymentRequestResponseImmediately() {
void PaymentAppContentUnitTestBase::RespondPendingPaymentRequest() {
std::move(worker_helper_->pending_response_callback_)
->OnResponseForPaymentRequest(
- payments::mojom::PaymentHandlerResponse::New(), base::Time::Now());
+ payments::mojom::PaymentHandlerResponse::New(),
+ base::TimeTicks::Now());
}
int64_t PaymentAppContentUnitTestBase::last_sw_registration_id() const {
diff --git a/chromium/content/browser/payments/payment_app_context_impl.cc b/chromium/content/browser/payments/payment_app_context_impl.cc
index f4801e11a63..f091da1820d 100644
--- a/chromium/content/browser/payments/payment_app_context_impl.cc
+++ b/chromium/content/browser/payments/payment_app_context_impl.cc
@@ -8,7 +8,9 @@
#include "base/bind.h"
#include "base/stl_util.h"
+#include "base/task/post_task.h"
#include "content/browser/payments/payment_manager.h"
+#include "content/public/browser/browser_task_traits.h"
namespace content {
@@ -23,8 +25,8 @@ void PaymentAppContextImpl::Init(
DCHECK(!did_shutdown_on_io_.IsSet());
#endif
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&PaymentAppContextImpl::CreatePaymentAppDatabaseOnIO, this,
service_worker_context));
}
@@ -36,8 +38,8 @@ void PaymentAppContextImpl::Shutdown() {
// IO thread. When the last reference to |this| is released, |this| is
// automatically scheduled for deletion on the UI thread (see
// content::BrowserThread::DeleteOnUIThread in the header file).
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&PaymentAppContextImpl::ShutdownOnIO, this));
}
@@ -45,8 +47,8 @@ void PaymentAppContextImpl::CreatePaymentManager(
payments::mojom::PaymentManagerRequest request) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&PaymentAppContextImpl::CreatePaymentManagerOnIO, this,
std::move(request)));
}
diff --git a/chromium/content/browser/payments/payment_app_info_fetcher.cc b/chromium/content/browser/payments/payment_app_info_fetcher.cc
index c1714b4cfe6..4efac89daa1 100644
--- a/chromium/content/browser/payments/payment_app_info_fetcher.cc
+++ b/chromium/content/browser/payments/payment_app_info_fetcher.cc
@@ -8,9 +8,11 @@
#include "base/base64.h"
#include "base/bind_helpers.h"
+#include "base/task/post_task.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/global_routing_id.h"
#include "content/public/browser/manifest_icon_downloader.h"
@@ -34,8 +36,8 @@ void PaymentAppInfoFetcher::Start(
std::unique_ptr<std::vector<GlobalFrameRoutingId>> provider_hosts =
service_worker_context->GetProviderHostIds(context_url.GetOrigin());
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&PaymentAppInfoFetcher::StartOnUI, context_url,
std::move(provider_hosts), std::move(callback)));
}
@@ -122,9 +124,10 @@ void PaymentAppInfoFetcher::SelfDeleteFetcher::Start(
void PaymentAppInfoFetcher::SelfDeleteFetcher::RunCallbackAndDestroy() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::BindOnce(std::move(callback_),
- std::move(fetched_payment_app_info_)));
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(std::move(callback_),
+ std::move(fetched_payment_app_info_)));
delete this;
}
diff --git a/chromium/content/browser/payments/payment_app_installer.cc b/chromium/content/browser/payments/payment_app_installer.cc
index 6a6e31bdb07..9ec51d4332a 100644
--- a/chromium/content/browser/payments/payment_app_installer.cc
+++ b/chromium/content/browser/payments/payment_app_installer.cc
@@ -4,14 +4,18 @@
#include "content/browser/payments/payment_app_installer.h"
+#include <utility>
+
#include "base/bind.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
+#include "base/task/post_task.h"
#include "content/browser/payments/payment_app_context_impl.h"
#include "content/browser/service_worker/service_worker_context_watcher.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/storage_partition_impl.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents.h"
@@ -26,12 +30,10 @@ class SelfDeleteInstaller
: public WebContentsObserver,
public base::RefCountedThreadSafe<SelfDeleteInstaller> {
public:
- SelfDeleteInstaller(WebContents* web_contents,
- const std::string& app_name,
+ SelfDeleteInstaller(const std::string& app_name,
const std::string& app_icon,
const GURL& sw_url,
const GURL& scope,
- bool use_cache,
const std::string& method,
PaymentAppInstaller::InstallPaymentAppCallback callback)
: app_name_(app_name),
@@ -41,6 +43,12 @@ class SelfDeleteInstaller
method_(method),
callback_(std::move(callback)) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ }
+
+ void Init(WebContents* web_contents, bool use_cache) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ AddRef(); // Balanced by Release() in FinishInstallation.
// TODO(crbug.com/782270): Listen for web contents events to terminate
// installation early.
@@ -66,7 +74,7 @@ class SelfDeleteInstaller
blink::mojom::ServiceWorkerUpdateViaCache::kNone;
}
service_worker_context->RegisterServiceWorker(
- sw_url, option,
+ sw_url_, option,
base::BindOnce(&SelfDeleteInstaller::OnRegisterServiceWorkerResult,
this));
}
@@ -131,8 +139,8 @@ class SelfDeleteInstaller
scoped_refptr<PaymentAppContextImpl> payment_app_context =
partition->GetPaymentAppContext();
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&SelfDeleteInstaller::SetPaymentAppInfoOnIO, this,
payment_app_context, registration_id_, scope_.spec(),
app_name_, app_icon_, method_));
@@ -156,8 +164,8 @@ class SelfDeleteInstaller
void OnSetPaymentAppInfo(payments::mojom::PaymentHandlerStatus status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&SelfDeleteInstaller::FinishInstallation, this,
status == payments::mojom::PaymentHandlerStatus::SUCCESS
? true
@@ -184,6 +192,7 @@ class SelfDeleteInstaller
}
Observe(nullptr);
+ Release(); // Balanced by AddRef() in the constructor.
}
std::string app_name_;
@@ -212,8 +221,9 @@ void PaymentAppInstaller::Install(WebContents* web_contents,
InstallPaymentAppCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- new SelfDeleteInstaller(web_contents, app_name, app_icon, sw_url, scope,
- use_cache, method, std::move(callback));
+ auto installer = base::MakeRefCounted<SelfDeleteInstaller>(
+ app_name, app_icon, sw_url, scope, method, std::move(callback));
+ installer->Init(web_contents, use_cache);
}
} // namespace content
diff --git a/chromium/content/browser/payments/payment_app_provider_impl.cc b/chromium/content/browser/payments/payment_app_provider_impl.cc
index 3cfa0bde2bc..d3042e6a2fc 100644
--- a/chromium/content/browser/payments/payment_app_provider_impl.cc
+++ b/chromium/content/browser/payments/payment_app_provider_impl.cc
@@ -6,6 +6,7 @@
#include "base/base64.h"
#include "base/strings/string_util.h"
+#include "base/task/post_task.h"
#include "content/browser/payments/payment_app_context_impl.h"
#include "content/browser/payments/payment_app_installer.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
@@ -13,6 +14,7 @@
#include "content/browser/service_worker/service_worker_version.h"
#include "content/browser/storage_partition_impl.h"
#include "content/common/service_worker/service_worker_utils.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/permission_controller.h"
#include "content/public/browser/permission_type.h"
@@ -124,12 +126,12 @@ class RespondWithCallbacks
void OnResponseForPaymentRequest(
payments::mojom::PaymentHandlerResponsePtr response,
- base::Time dispatch_event_time) override {
+ base::TimeTicks dispatch_event_time) override {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
service_worker_version_->FinishRequest(request_id_, false,
std::move(dispatch_event_time));
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(std::move(invoke_payment_app_callback_),
std::move(response)));
@@ -137,25 +139,26 @@ class RespondWithCallbacks
delete this;
}
- void OnResponseForCanMakePayment(bool can_make_payment,
- base::Time dispatch_event_time) override {
+ void OnResponseForCanMakePayment(
+ bool can_make_payment,
+ base::TimeTicks dispatch_event_time) override {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
service_worker_version_->FinishRequest(request_id_, false,
std::move(dispatch_event_time));
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(std::move(payment_event_result_callback_),
can_make_payment));
delete this;
}
void OnResponseForAbortPayment(bool payment_aborted,
- base::Time dispatch_event_time) override {
+ base::TimeTicks dispatch_event_time) override {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
service_worker_version_->FinishRequest(request_id_, false,
std::move(dispatch_event_time));
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(std::move(payment_event_result_callback_),
payment_aborted));
@@ -168,15 +171,15 @@ class RespondWithCallbacks
DCHECK(service_worker_status != blink::ServiceWorkerStatusCode::kOk);
if (event_type_ == ServiceWorkerMetrics::EventType::PAYMENT_REQUEST) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(std::move(invoke_payment_app_callback_),
payments::mojom::PaymentHandlerResponse::New()));
} else if (event_type_ ==
ServiceWorkerMetrics::EventType::CAN_MAKE_PAYMENT ||
event_type_ == ServiceWorkerMetrics::EventType::ABORT_PAYMENT) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(std::move(payment_event_result_callback_), false));
}
@@ -193,7 +196,7 @@ class RespondWithCallbacks
DCHECK_CURRENTLY_ON(BrowserThread::IO);
service_worker_version_->FinishRequest(request_id_, false,
- base::Time::Now());
+ base::TimeTicks::Now());
OnErrorStatus(blink::ServiceWorkerStatusCode::kErrorAbort);
}
@@ -205,8 +208,8 @@ class RespondWithCallbacks
InvokePaymentAppCallbackRepository::GetInstance()->RemoveCallback(
browser_context_);
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&CloseClientWindowOnUIThread, browser_context_));
}
@@ -232,8 +235,9 @@ class RespondWithCallbacks
void DidGetAllPaymentAppsOnIO(
PaymentAppProvider::GetAllPaymentAppsCallback callback,
PaymentAppProvider::PaymentApps apps) {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(std::move(callback), std::move(apps)));
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(std::move(callback), std::move(apps)));
}
void GetAllPaymentAppsOnIO(
@@ -253,8 +257,8 @@ void DispatchAbortPaymentEvent(
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (service_worker_status != blink::ServiceWorkerStatusCode::kOk) {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(std::move(callback), false));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(std::move(callback), false));
return;
}
@@ -282,8 +286,8 @@ void DispatchCanMakePaymentEvent(
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (service_worker_status != blink::ServiceWorkerStatusCode::kOk) {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(std::move(callback), false));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(std::move(callback), false));
return;
}
@@ -311,8 +315,8 @@ void DispatchPaymentRequestEvent(
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (service_worker_status != blink::ServiceWorkerStatusCode::kOk) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(std::move(callback),
payments::mojom::PaymentHandlerResponse::New()));
return;
@@ -374,8 +378,8 @@ void StartServiceWorkerForDispatch(BrowserContext* browser_context,
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context =
partition->GetServiceWorkerContext();
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&FindRegistrationOnIO, std::move(service_worker_context),
registration_id, std::move(callback)));
}
@@ -451,8 +455,8 @@ void PaymentAppProviderImpl::GetAllPaymentApps(
scoped_refptr<PaymentAppContextImpl> payment_app_context =
partition->GetPaymentAppContext();
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&GetAllPaymentAppsOnIO, payment_app_context,
base::BindOnce(&CheckPermissionForPaymentApps,
browser_context, std::move(callback))));
@@ -488,8 +492,8 @@ void PaymentAppProviderImpl::InstallAndInvokePaymentApp(
DCHECK(base::IsStringUTF8(sw_scope));
GURL scope = GURL(sw_scope);
if (!url.is_valid() || !scope.is_valid() || method.empty()) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(std::move(callback),
payments::mojom::PaymentHandlerResponse::New()));
return;
@@ -562,8 +566,8 @@ void PaymentAppProviderImpl::OnClosingOpenedWindow(
BrowserContext* browser_context) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&AbortInvokePaymentApp, browser_context));
}
diff --git a/chromium/content/browser/payments/payment_instrument_icon_fetcher.cc b/chromium/content/browser/payments/payment_instrument_icon_fetcher.cc
index 3bb8cffa724..f1481f6b37f 100644
--- a/chromium/content/browser/payments/payment_instrument_icon_fetcher.cc
+++ b/chromium/content/browser/payments/payment_instrument_icon_fetcher.cc
@@ -8,9 +8,11 @@
#include "base/base64.h"
#include "base/bind_helpers.h"
+#include "base/task/post_task.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/storage_partition_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/manifest_icon_downloader.h"
#include "third_party/blink/public/common/manifest/manifest_icon_selector.h"
@@ -42,8 +44,8 @@ void OnIconFetched(
if (bitmap.drawsNothing()) {
if (icons.empty()) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(std::move(callback), std::string()));
} else {
// If could not download or decode the chosen image(e.g. not supported,
@@ -61,8 +63,8 @@ void OnIconFetched(
base::StringPiece(reinterpret_cast<const char*>(&bitmap_data[0]),
bitmap_data.size()),
&encoded_data);
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::BindOnce(std::move(callback), encoded_data));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(std::move(callback), encoded_data));
}
void DownloadBestMatchingIcon(
@@ -80,8 +82,9 @@ void DownloadBestMatchingIcon(
// developers in advance unlike when fetching or decoding fails. We already
// checked whether they are valid in renderer side. So, if the icon url is
// invalid, it's something wrong.
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::BindOnce(std::move(callback), std::string()));
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(std::move(callback), std::string()));
return;
}
@@ -146,8 +149,8 @@ void PaymentInstrumentIconFetcher::Start(
PaymentInstrumentIconFetcherCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&StartOnUI, scope, std::move(provider_hosts), icons,
std::move(callback)));
}
diff --git a/chromium/content/browser/permissions/permission_service_impl.cc b/chromium/content/browser/permissions/permission_service_impl.cc
index f84599df41c..064107bb019 100644
--- a/chromium/content/browser/permissions/permission_service_impl.cc
+++ b/chromium/content/browser/permissions/permission_service_impl.cc
@@ -82,6 +82,9 @@ bool PermissionDescriptorToPermissionType(
case PermissionName::PAYMENT_HANDLER:
*permission_type = PermissionType::PAYMENT_HANDLER;
return true;
+ case PermissionName::BACKGROUND_FETCH:
+ *permission_type = PermissionType::BACKGROUND_FETCH;
+ return true;
}
NOTREACHED();
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 ba0270dd8d3..d0758e65cb4 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
@@ -71,16 +71,6 @@ gfx::Size PictureInPictureWindowControllerImpl::Show() {
return window_->GetBounds().size();
}
-void PictureInPictureWindowControllerImpl::ClickCustomControl(
- const std::string& control_id) {
- DCHECK(window_);
-
- media_player_id_->render_frame_host->Send(
- new MediaPlayerDelegateMsg_ClickPictureInPictureControl(
- media_player_id_->render_frame_host->GetRoutingID(),
- media_player_id_->delegate_id, control_id));
-}
-
void PictureInPictureWindowControllerImpl::SetPictureInPictureCustomControls(
const std::vector<blink::PictureInPictureControlInfo>& controls) {
DCHECK(window_);
@@ -189,6 +179,24 @@ bool PictureInPictureWindowControllerImpl::TogglePlayPause() {
return true;
}
+void PictureInPictureWindowControllerImpl::CustomControlPressed(
+ const std::string& control_id) {
+ DCHECK(window_);
+
+ media_player_id_->render_frame_host->Send(
+ new MediaPlayerDelegateMsg_ClickPictureInPictureControl(
+ media_player_id_->render_frame_host->GetRoutingID(),
+ media_player_id_->delegate_id, control_id));
+}
+
+void PictureInPictureWindowControllerImpl::SetAlwaysHidePlayPauseButton(
+ bool is_visible) {
+ if (!window_)
+ return;
+
+ window_->SetAlwaysHidePlayPauseButton(is_visible);
+}
+
void PictureInPictureWindowControllerImpl::OnLeavingPictureInPicture(
bool should_pause_video,
bool should_reset_pip_player) {
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 a5c6499509e..17fb5e892e7 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
@@ -38,8 +38,6 @@ class PictureInPictureWindowControllerImpl
CONTENT_EXPORT void Close(bool should_pause_video,
bool should_reset_pip_player) override;
CONTENT_EXPORT void OnWindowDestroyed() override;
- CONTENT_EXPORT void ClickCustomControl(
- const std::string& control_id) override;
CONTENT_EXPORT void SetPictureInPictureCustomControls(
const std::vector<blink::PictureInPictureControlInfo>& controls) override;
CONTENT_EXPORT void EmbedSurface(const viz::SurfaceId& surface_id,
@@ -49,8 +47,11 @@ class PictureInPictureWindowControllerImpl
CONTENT_EXPORT bool IsPlayerActive() override;
CONTENT_EXPORT WebContents* GetInitiatorWebContents() override;
CONTENT_EXPORT bool TogglePlayPause() override;
+ CONTENT_EXPORT void CustomControlPressed(
+ const std::string& control_id) override;
CONTENT_EXPORT void UpdatePlaybackState(bool is_playing,
bool reached_end_of_stream) override;
+ CONTENT_EXPORT void SetAlwaysHidePlayPauseButton(bool is_visible) override;
private:
friend class WebContentsUserData<PictureInPictureWindowControllerImpl>;
diff --git a/chromium/content/browser/plugin_data_remover_impl.cc b/chromium/content/browser/plugin_data_remover_impl.cc
index fefc248ddbb..43ec1a50e93 100644
--- a/chromium/content/browser/plugin_data_remover_impl.cc
+++ b/chromium/content/browser/plugin_data_remover_impl.cc
@@ -12,12 +12,14 @@
#include "base/sequenced_task_runner_helpers.h"
#include "base/strings/utf_string_conversions.h"
#include "base/synchronization/waitable_event.h"
+#include "base/task/post_task.h"
#include "base/version.h"
#include "build/build_config.h"
#include "content/browser/plugin_service_impl.h"
#include "content/browser/renderer_host/pepper/pepper_flash_file_message_filter.h"
#include "content/common/child_process_host_impl.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/child_process_host.h"
#include "content/public/common/content_constants.h"
@@ -48,8 +50,7 @@ void PluginDataRemover::GetSupportedPlugins(
PluginService::GetInstance()->GetPluginInfoArray(
GURL(), kFlashPluginSwfMimeType, allow_wildcard, &plugins, nullptr);
base::Version min_version(kMinFlashVersion);
- for (std::vector<WebPluginInfo>::iterator it = plugins.begin();
- it != plugins.end(); ++it) {
+ for (auto it = plugins.begin(); it != plugins.end(); ++it) {
base::Version version;
WebPluginInfo::CreateVersionFromString(it->version, &version);
if (version.IsValid() && min_version.CompareTo(version) == -1)
@@ -74,11 +75,12 @@ class PluginDataRemoverImpl::Context
}
void Init(const std::string& mime_type) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&Context::InitOnIOThread, this, mime_type));
- BrowserThread::PostDelayedTask(
- BrowserThread::IO, FROM_HERE, base::BindOnce(&Context::OnTimeout, this),
+ base::PostDelayedTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(&Context::OnTimeout, this),
base::TimeDelta::FromMilliseconds(kRemovalTimeoutMs));
}
diff --git a/chromium/content/browser/plugin_private_storage_helper.cc b/chromium/content/browser/plugin_private_storage_helper.cc
index 60fa438616b..57f5b7e0bef 100644
--- a/chromium/content/browser/plugin_private_storage_helper.cc
+++ b/chromium/content/browser/plugin_private_storage_helper.cc
@@ -21,6 +21,8 @@
#include "base/logging.h"
#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/task/post_task.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "ppapi/shared_impl/ppapi_constants.h"
#include "storage/browser/fileapi/async_file_util.h"
@@ -308,11 +310,12 @@ void PluginPrivateDataDeletionHelper::CheckOriginsOnFileTaskRunner(
}
// Currently the plugin private filesystem is only used by Encrypted
- // Media Content Decryption Modules, which are treated as pepper plugins.
- // Each CDM gets a directory based on the mimetype (e.g. plugin
- // application/x-ppapi-widevine-cdm uses directory
- // application_x-ppapi-widevine-cdm). Enumerate through the set of
- // directories so that data from any CDM used by this origin is deleted.
+ // Media Content Decryption Modules (CDM), which used to be hosted as pepper
+ // plugins. Each CDM gets a directory based on the CdmInfo::file_system_id,
+ // e.g. application/x-ppapi-widevine-cdm (same as previous plugin mimetypes
+ // to avoid data migration). See https://crbug.com/479923 for the history.
+ // Enumerate through the set of directories so that data from any CDM used
+ // by this origin is deleted.
base::FileEnumerator file_enumerator(path, false,
base::FileEnumerator::DIRECTORIES);
for (base::FilePath plugin_path = file_enumerator.Next();
@@ -323,8 +326,8 @@ void PluginPrivateDataDeletionHelper::CheckOriginsOnFileTaskRunner(
filesystem_context_.get(), origin.GetOrigin(),
plugin_path.BaseName().MaybeAsASCII(), begin_, end_,
decrement_callback);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&PluginPrivateDataByOriginChecker::CheckFilesOnIOThread,
base::Unretained(helper)));
diff --git a/chromium/content/browser/plugin_service_impl.cc b/chromium/content/browser/plugin_service_impl.cc
index 3a6480c7177..7834d3d1843 100644
--- a/chromium/content/browser/plugin_service_impl.cc
+++ b/chromium/content/browser/plugin_service_impl.cc
@@ -31,6 +31,7 @@
#include "content/common/pepper_plugin_list.h"
#include "content/common/plugin_list.h"
#include "content/common/view_messages.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/plugin_service_filter.h"
@@ -272,9 +273,9 @@ void PluginServiceImpl::OpenChannelToPpapiBroker(
int render_frame_id,
const base::FilePath& path,
PpapiPluginProcessHost::BrokerClient* client) {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(&PluginServiceImpl::RecordBrokerUsage,
- render_process_id, render_frame_id));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(&PluginServiceImpl::RecordBrokerUsage,
+ render_process_id, render_frame_id));
PpapiPluginProcessHost* plugin_host = FindOrStartPpapiBrokerProcess(
render_process_id, path);
@@ -414,8 +415,7 @@ static const unsigned int kCrashesInterval = 120;
void PluginServiceImpl::RegisterPluginCrash(const base::FilePath& path) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- std::map<base::FilePath, std::vector<base::Time> >::iterator i =
- crash_times_.find(path);
+ auto i = crash_times_.find(path);
if (i == crash_times_.end()) {
crash_times_[path] = std::vector<base::Time>();
i = crash_times_.find(path);
diff --git a/chromium/content/browser/plugin_service_impl_browsertest.cc b/chromium/content/browser/plugin_service_impl_browsertest.cc
index 1dfaa4d45c8..23fc78b5b5d 100644
--- a/chromium/content/browser/plugin_service_impl_browsertest.cc
+++ b/chromium/content/browser/plugin_service_impl_browsertest.cc
@@ -11,8 +11,10 @@
#include "base/optional.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/task/post_task.h"
#include "build/build_config.h"
#include "content/browser/ppapi_plugin_process_host.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/test/content_browser_test.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -82,8 +84,8 @@ class PluginServiceImplBrowserTest : public ContentBrowserTest {
client->SetRunLoop(&run_loop);
PluginServiceImpl* service = PluginServiceImpl::GetInstance();
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&PluginServiceImpl::OpenChannelToPpapiPlugin,
base::Unretained(service), 0, plugin_path_, profile_dir_,
origin, base::Unretained(client)));
diff --git a/chromium/content/browser/pointer_lock_browsertest.cc b/chromium/content/browser/pointer_lock_browsertest.cc
index d6eaf149a84..05b56a7255e 100644
--- a/chromium/content/browser/pointer_lock_browsertest.cc
+++ b/chromium/content/browser/pointer_lock_browsertest.cc
@@ -319,6 +319,55 @@ IN_PROC_BROWSER_TEST_F(PointerLockBrowserTest,
root->current_frame_host()->GetRenderWidgetHost()));
}
+IN_PROC_BROWSER_TEST_F(PointerLockBrowserTest, PointerLockOopifCrashes) {
+ // This test runs three times, testing a crash at each level of the frametree.
+ for (int crash_depth = 0; crash_depth < 3; crash_depth++) {
+ 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* lock_node = root->child_at(0)->child_at(0);
+
+ // Pick which node to crash.
+ FrameTreeNode* crash_node = root;
+ for (int i = 0; i < crash_depth; i++)
+ crash_node = crash_node->child_at(0);
+
+ // Request a pointer lock to |lock_node|'s document.body.
+ EXPECT_EQ("success", EvalJs(lock_node, R"(
+ new Promise((resolve, reject) => {
+ document.addEventListener('pointerlockchange', resolve);
+ document.addEventListener('pointerlockerror', reject);
+ document.body.requestPointerLock();
+ }).then(() => 'success');
+ )"));
+
+ // Root (platform) RenderWidgetHostView should have the pointer locked.
+ EXPECT_TRUE(root->current_frame_host()->GetView()->IsMouseLocked());
+ EXPECT_EQ(lock_node->current_frame_host()->GetRenderWidgetHost(),
+ web_contents()->GetMouseLockWidget());
+
+ // Crash the process of |crash_node|.
+ RenderProcessHost* crash_process =
+ crash_node->current_frame_host()->GetProcess();
+ RenderProcessHostWatcher crash_observer(
+ crash_process, RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
+ crash_process->Shutdown(0);
+ crash_observer.Wait();
+
+ // This should cancel the pointer lock.
+ EXPECT_EQ(nullptr, web_contents()->GetMouseLockWidget());
+ EXPECT_EQ(nullptr, web_contents()->mouse_lock_widget_);
+ EXPECT_FALSE(web_contents()->HasMouseLock(
+ root->current_frame_host()->GetRenderWidgetHost()));
+ if (crash_depth != 0)
+ EXPECT_FALSE(root->current_frame_host()->GetView()->IsMouseLocked());
+ else
+ EXPECT_EQ(nullptr, root->current_frame_host()->GetView());
+ }
+}
+
IN_PROC_BROWSER_TEST_F(PointerLockBrowserTest, PointerLockWheelEventRouting) {
GURL main_url(embedded_test_server()->GetURL(
"a.com", "/cross_site_iframe_factory.html?a(b)"));
diff --git a/chromium/content/browser/portal/portal.cc b/chromium/content/browser/portal/portal.cc
index 14430222d47..ff5a59c41d0 100644
--- a/chromium/content/browser/portal/portal.cc
+++ b/chromium/content/browser/portal/portal.cc
@@ -9,6 +9,7 @@
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_delegate.h"
#include "content/public/common/content_switches.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "third_party/blink/public/common/features.h"
@@ -53,6 +54,9 @@ void Portal::Init(
WebContents::FromRenderFrameHost(owner_render_frame_host_)
->GetBrowserContext());
portal_contents_ = WebContents::Create(params);
+ WebContents::FromRenderFrameHost(owner_render_frame_host_)
+ ->GetDelegate()
+ ->PortalWebContentsCreated(portal_contents_.get());
}
void Portal::Navigate(const GURL& url) {
@@ -60,6 +64,34 @@ void Portal::Navigate(const GURL& url) {
portal_contents_->GetController().LoadURLWithParams(load_url_params);
}
+void Portal::Activate(
+ base::OnceCallback<void(blink::mojom::PortalActivationStatus)> callback) {
+ WebContents* outer_contents =
+ WebContents::FromRenderFrameHost(owner_render_frame_host_);
+ WebContentsDelegate* delegate = outer_contents->GetDelegate();
+ if (delegate) {
+ bool is_loading = portal_contents_->IsLoading();
+ WebContents* portal_contents = portal_contents_.get();
+ std::unique_ptr<WebContents> contents = delegate->SwapWebContents(
+ outer_contents, std::move(portal_contents_), true, is_loading);
+
+ if (contents.get() == outer_contents) {
+ // TODO(lfg): The old WebContents is currently discarded, but should be
+ // kept and passed to the new page.
+ std::move(callback).Run(blink::mojom::PortalActivationStatus::kSuccess);
+ } else {
+ DCHECK_EQ(portal_contents, contents.get());
+ portal_contents_ = std::move(contents);
+ std::move(callback).Run(
+ blink::mojom::PortalActivationStatus::kNotSupported);
+ }
+
+ return;
+ }
+
+ std::move(callback).Run(blink::mojom::PortalActivationStatus::kNotSupported);
+}
+
void Portal::RenderFrameDeleted(RenderFrameHost* render_frame_host) {
if (render_frame_host == owner_render_frame_host_)
binding_->Close(); // Also deletes |this|.
diff --git a/chromium/content/browser/portal/portal.h b/chromium/content/browser/portal/portal.h
index f894cb7d65c..c6cd4896127 100644
--- a/chromium/content/browser/portal/portal.h
+++ b/chromium/content/browser/portal/portal.h
@@ -44,6 +44,8 @@ class CONTENT_EXPORT Portal : public blink::mojom::Portal,
void Init(base::OnceCallback<void(const base::UnguessableToken&)> callback)
override;
void Navigate(const GURL& url) override;
+ void Activate(base::OnceCallback<void(blink::mojom::PortalActivationStatus)>
+ callback) override;
// WebContentsObserver overrides.
void RenderFrameDeleted(RenderFrameHost* render_frame_host) override;
diff --git a/chromium/content/browser/portal/portal_browsertest.cc b/chromium/content/browser/portal/portal_browsertest.cc
index a9a661e8b7b..82fdddf230d 100644
--- a/chromium/content/browser/portal/portal_browsertest.cc
+++ b/chromium/content/browser/portal/portal_browsertest.cc
@@ -5,9 +5,11 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/test/scoped_feature_list.h"
+#include "build/build_config.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/portal/portal.h"
#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/browser/web_contents_delegate.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"
@@ -16,9 +18,12 @@
#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 "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/portal/portal.mojom.h"
#include "url/url_constants.h"
+using testing::_;
namespace content {
@@ -38,8 +43,23 @@ class PortalInterceptorForTesting final
ASSERT_FALSE(portal_initialized_);
portal_initialized_ = true;
- if (run_loop_)
+ if (run_loop_) {
run_loop_->Quit();
+ run_loop_ = nullptr;
+ }
+ }
+
+ void Activate(base::OnceCallback<void(blink::mojom::PortalActivationStatus)>
+ callback) override {
+ portal_activated_ = true;
+
+ if (run_loop_) {
+ run_loop_->Quit();
+ run_loop_ = nullptr;
+ }
+
+ // |this| can be destroyed after Activate() is called.
+ portal_->Activate(std::move(callback));
}
void WaitForInit() {
@@ -49,7 +69,15 @@ class PortalInterceptorForTesting final
base::RunLoop run_loop;
run_loop_ = &run_loop;
run_loop.Run();
- run_loop_ = nullptr;
+ }
+
+ void WaitForActivate() {
+ if (portal_activated_)
+ return;
+
+ base::RunLoop run_loop;
+ run_loop_ = &run_loop;
+ run_loop.Run();
}
// Test getters.
@@ -66,6 +94,7 @@ class PortalInterceptorForTesting final
std::unique_ptr<content::Portal> portal_;
bool portal_initialized_ = false;
+ bool portal_activated_ = false;
base::RunLoop* run_loop_ = nullptr;
};
@@ -91,6 +120,25 @@ PortalInterceptorForTesting* PortalInterceptorForTesting::From(
return interceptor;
}
+class MockPortalWebContentsDelegate : public WebContentsDelegate {
+ public:
+ MockPortalWebContentsDelegate() {}
+ ~MockPortalWebContentsDelegate() override {}
+
+ MOCK_METHOD4(
+ DoSwapWebContents,
+ std::unique_ptr<WebContents>(WebContents*, WebContents*, bool, bool));
+ std::unique_ptr<WebContents> SwapWebContents(
+ WebContents* old_contents,
+ std::unique_ptr<WebContents> new_contents,
+ bool did_start_load,
+ bool did_finish_load) override {
+ DoSwapWebContents(old_contents, new_contents.get(), did_start_load,
+ did_finish_load);
+ return new_contents;
+ }
+};
+
// The PortalCreatedObserver observes portal creations on
// |render_frame_host_impl|. This observer can be used to monitor for multiple
// Portal creations on the same RenderFrameHost, by repeatedly calling
@@ -252,4 +300,91 @@ IN_PROC_BROWSER_TEST_F(PortalBrowserTest, NavigatePortal) {
}
}
+// Tests that the WebContentsDelegate will receive a request to swap the
+// WebContents when a portal is activated.
+// Disabled due to flakiness on Android. See https://crbug.com/892669.
+#if defined(OS_ANDROID)
+#define MAYBE_ActivatePortal DISABLED_ActivatePortal
+#else
+#define MAYBE_ActivatePortal ActivatePortal
+#endif
+
+IN_PROC_BROWSER_TEST_F(PortalBrowserTest, MAYBE_ActivatePortal) {
+ EXPECT_TRUE(NavigateToURL(
+ shell(), embedded_test_server()->GetURL("portal.test", "/title1.html")));
+ WebContentsImpl* web_contents_impl =
+ static_cast<WebContentsImpl*>(shell()->web_contents());
+ RenderFrameHostImpl* main_frame = web_contents_impl->GetMainFrame();
+
+ PortalCreatedObserver portal_created_observer(main_frame);
+ GURL a_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+ EXPECT_TRUE(ExecJs(main_frame,
+ JsReplace("var portal = document.createElement('portal');"
+ "portal.src = $1;"
+ "document.body.appendChild(portal);",
+ a_url)));
+ Portal* portal = portal_created_observer.WaitUntilPortalCreated();
+ PortalInterceptorForTesting* portal_interceptor =
+ PortalInterceptorForTesting::From(portal);
+ portal_interceptor->WaitForInit();
+
+ MockPortalWebContentsDelegate mock_delegate;
+ shell()->web_contents()->SetDelegate(&mock_delegate);
+
+ base::RunLoop run_loop;
+ EXPECT_CALL(mock_delegate,
+ DoSwapWebContents(shell()->web_contents(),
+ portal->GetPortalContents(), _, _))
+ .WillOnce(testing::DoAll(
+ testing::InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit),
+ testing::ReturnNull()));
+ EXPECT_TRUE(
+ ExecJs(main_frame, "document.querySelector('portal').activate();"));
+ run_loop.Run();
+}
+
+// Tests that a portal can be activated in content_shell.
+// Disabled due to flakiness on Android. See https://crbug.com/892669.
+#if defined(OS_ANDROID)
+#define MAYBE_ActivatePortalInShell DISABLED_ActivatePortalInShell
+#else
+#define MAYBE_ActivatePortalInShell ActivatePortalInShell
+#endif
+IN_PROC_BROWSER_TEST_F(PortalBrowserTest, MAYBE_ActivatePortalInShell) {
+ EXPECT_TRUE(NavigateToURL(
+ shell(), embedded_test_server()->GetURL("portal.test", "/title1.html")));
+ WebContentsImpl* web_contents_impl =
+ static_cast<WebContentsImpl*>(shell()->web_contents());
+ RenderFrameHostImpl* main_frame = web_contents_impl->GetMainFrame();
+
+ Portal* portal = nullptr;
+ {
+ PortalCreatedObserver portal_created_observer(main_frame);
+ GURL a_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+ EXPECT_TRUE(ExecJs(
+ main_frame, JsReplace("var portal = document.createElement('portal');"
+ "portal.src = $1;"
+ "document.body.appendChild(portal);",
+ a_url)));
+ portal = portal_created_observer.WaitUntilPortalCreated();
+ }
+ PortalInterceptorForTesting* portal_interceptor =
+ PortalInterceptorForTesting::From(portal);
+ portal_interceptor->WaitForInit();
+
+ // Ensure that the portal WebContents exists and is different from the tab's
+ // WebContents.
+ WebContents* portal_contents = portal->GetPortalContents();
+ EXPECT_NE(nullptr, portal_contents);
+ EXPECT_NE(portal_contents, shell()->web_contents());
+
+ ExecuteScriptAsync(main_frame,
+ "document.querySelector('portal').activate();");
+ portal_interceptor->WaitForActivate();
+
+ // After activation, the shell's WebContents should be the previous portal's
+ // WebContents.
+ EXPECT_EQ(portal_contents, shell()->web_contents());
+}
+
} // namespace content
diff --git a/chromium/content/browser/power_monitor_browsertest.cc b/chromium/content/browser/power_monitor_browsertest.cc
index ffd7190d197..19fa617b74c 100644
--- a/chromium/content/browser/power_monitor_browsertest.cc
+++ b/chromium/content/browser/power_monitor_browsertest.cc
@@ -6,9 +6,11 @@
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/task/post_task.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/utility_process_host.h"
#include "content/browser/utility_process_host_client.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/gpu_service_registry.h"
#include "content/public/browser/render_frame_host.h"
@@ -150,8 +152,8 @@ class PowerMonitorTest : public ContentBrowserTest {
void StartUtilityProcess(mojom::PowerMonitorTestPtr* power_monitor_test,
base::Closure utility_bound_closure) {
utility_bound_closure_ = std::move(utility_bound_closure);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&StartUtilityProcessOnIOThread,
mojo::MakeRequest(power_monitor_test)));
}
@@ -240,8 +242,8 @@ IN_PROC_BROWSER_TEST_F(PowerMonitorTest, TestGpuProcess) {
EXPECT_EQ(1, request_count_from_gpu());
mojom::PowerMonitorTestPtr power_monitor_gpu;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&BindInterfaceForGpuOnIOThread,
mojo::MakeRequest(&power_monitor_gpu)));
diff --git a/chromium/content/browser/ppapi_plugin_process_host.cc b/chromium/content/browser/ppapi_plugin_process_host.cc
index 1df1149921b..3c2cf89aa1f 100644
--- a/chromium/content/browser/ppapi_plugin_process_host.cc
+++ b/chromium/content/browser/ppapi_plugin_process_host.cc
@@ -23,14 +23,15 @@
#include "content/common/child_process_host_impl.h"
#include "content/common/content_switches_internal.h"
#include "content/public/browser/content_browser_client.h"
+#include "content/public/browser/network_service_instance.h"
#include "content/public/common/content_constants.h"
#include "content/public/common/content_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 "net/base/network_change_notifier.h"
#include "ppapi/proxy/ppapi_messages.h"
+#include "services/network/public/cpp/network_connection_tracker.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"
@@ -129,25 +130,38 @@ class PpapiPluginSandboxedProcessLauncherDelegate
};
class PpapiPluginProcessHost::PluginNetworkObserver
- : public net::NetworkChangeNotifier::NetworkChangeObserver {
+ : public network::NetworkConnectionTracker::NetworkConnectionObserver {
public:
explicit PluginNetworkObserver(PpapiPluginProcessHost* process_host)
- : process_host_(process_host) {
- net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
+ : process_host_(process_host),
+ network_connection_tracker_(nullptr),
+ weak_factory_(this) {
+ GetNetworkConnectionTrackerFromUIThread(
+ base::BindOnce(&PluginNetworkObserver::SetNetworkConnectionTracker,
+ weak_factory_.GetWeakPtr()));
+ }
+
+ void SetNetworkConnectionTracker(
+ network::NetworkConnectionTracker* network_connection_tracker) {
+ DCHECK(network_connection_tracker);
+ network_connection_tracker_ = network_connection_tracker;
+ network_connection_tracker_->AddNetworkConnectionObserver(this);
}
~PluginNetworkObserver() override {
- net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
+ if (network_connection_tracker_)
+ network_connection_tracker_->RemoveNetworkConnectionObserver(this);
}
- void OnNetworkChanged(
- net::NetworkChangeNotifier::ConnectionType type) override {
+ void OnConnectionChanged(network::mojom::ConnectionType type) override {
process_host_->Send(new PpapiMsg_SetNetworkState(
- type != net::NetworkChangeNotifier::CONNECTION_NONE));
+ type != network::mojom::ConnectionType::CONNECTION_NONE));
}
private:
PpapiPluginProcessHost* const process_host_;
+ network::NetworkConnectionTracker* network_connection_tracker_;
+ base::WeakPtrFactory<PluginNetworkObserver> weak_factory_;
};
PpapiPluginProcessHost::~PpapiPluginProcessHost() {
diff --git a/chromium/content/browser/presentation/presentation_service_impl_unittest.cc b/chromium/content/browser/presentation/presentation_service_impl_unittest.cc
index 51fd39f10ab..c8abad15dfb 100644
--- a/chromium/content/browser/presentation/presentation_service_impl_unittest.cc
+++ b/chromium/content/browser/presentation/presentation_service_impl_unittest.cc
@@ -175,11 +175,9 @@ class MockReceiverPresentationServiceDelegate
class MockPresentationConnection : public PresentationConnection {
public:
- MOCK_METHOD2(OnMessage,
- void(PresentationConnectionMessagePtr message,
- base::OnceCallback<void(bool)> send_message_cb));
+ MOCK_METHOD1(OnMessage, void(PresentationConnectionMessagePtr message));
MOCK_METHOD1(DidChangeState, void(PresentationConnectionState state));
- MOCK_METHOD0(RequestClose, void());
+ MOCK_METHOD1(DidClose, void(blink::mojom::PresentationConnectionCloseReason));
};
class MockPresentationController : public blink::mojom::PresentationController {
diff --git a/chromium/content/browser/process_internals/BUILD.gn b/chromium/content/browser/process_internals/BUILD.gn
index fedd9d9609b..a85f61cf4a0 100644
--- a/chromium/content/browser/process_internals/BUILD.gn
+++ b/chromium/content/browser/process_internals/BUILD.gn
@@ -8,4 +8,8 @@ mojom("mojo_bindings") {
sources = [
"process_internals.mojom",
]
+
+ deps = [
+ "//url/mojom:url_mojom_gurl",
+ ]
}
diff --git a/chromium/content/browser/process_internals/process_internals.mojom b/chromium/content/browser/process_internals/process_internals.mojom
index d8fe8594f2d..fe11eebcb85 100644
--- a/chromium/content/browser/process_internals/process_internals.mojom
+++ b/chromium/content/browser/process_internals/process_internals.mojom
@@ -4,6 +4,37 @@
module mojom;
+import "url/mojom/url.mojom";
+
+// Basic information describing a SiteInstance.
+struct SiteInstanceInfo {
+ int32 id;
+
+ // Boolean indicating whether the SiteInstance is locked to a specific URL.
+ // It does not indicate the granularity of the lock URL.
+ bool locked;
+
+ url.mojom.Url? site_url;
+};
+
+// Basic information describing a frame and all of its subframes.
+struct FrameInfo {
+ int32 routing_id;
+ int32 process_id;
+
+ SiteInstanceInfo site_instance;
+ url.mojom.Url? last_committed_url;
+
+ array<FrameInfo> subframes;
+};
+
+// Basic information describing a WebContents object and all frames that are
+// in it.
+struct WebContentsInfo {
+ string title;
+ FrameInfo root_frame;
+};
+
// Interface used by chrome://process-internals to query data from the
// browser process.
interface ProcessInternalsHandler {
@@ -13,4 +44,8 @@ interface ProcessInternalsHandler {
// Returns the number of isolated origins.
GetIsolatedOriginsSize() => (uint32 size);
+
+ // Returns an array of WebContentsInfo structs for all WebContents
+ // associated with the profile in which this call is made.
+ GetAllWebContentsInfo() => (array<WebContentsInfo> infos);
};
diff --git a/chromium/content/browser/process_internals/process_internals_handler_impl.cc b/chromium/content/browser/process_internals/process_internals_handler_impl.cc
index dbd0e5792b1..2011f1b54d2 100644
--- a/chromium/content/browser/process_internals/process_internals_handler_impl.cc
+++ b/chromium/content/browser/process_internals/process_internals_handler_impl.cc
@@ -4,15 +4,53 @@
#include "content/browser/process_internals/process_internals_handler_impl.h"
+#include <utility>
+#include <vector>
+
+#include "base/strings/string_piece.h"
#include "content/browser/process_internals/process_internals.mojom.h"
+#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/site_isolation_policy.h"
#include "content/public/browser/web_contents.h"
namespace content {
+namespace {
+
+::mojom::FrameInfoPtr FrameTreeNodeToFrameInfo(FrameTreeNode* ftn) {
+ RenderFrameHost* frame = ftn->current_frame_host();
+ auto frame_info = ::mojom::FrameInfo::New();
+
+ frame_info->routing_id = frame->GetRoutingID();
+ frame_info->process_id = frame->GetProcess()->GetID();
+ frame_info->last_committed_url =
+ frame->GetLastCommittedURL().is_valid()
+ ? base::make_optional(frame->GetLastCommittedURL())
+ : base::nullopt;
+
+ SiteInstanceImpl* site_instance =
+ static_cast<SiteInstanceImpl*>(frame->GetSiteInstance());
+ frame_info->site_instance = ::mojom::SiteInstanceInfo::New();
+ frame_info->site_instance->id = site_instance->GetId();
+ frame_info->site_instance->locked = site_instance->lock_url().is_valid();
+ frame_info->site_instance->site_url =
+ site_instance->HasSite()
+ ? base::make_optional(site_instance->GetSiteURL())
+ : base::nullopt;
+
+ for (size_t i = 0; i < ftn->child_count(); ++i) {
+ frame_info->subframes.push_back(FrameTreeNodeToFrameInfo(ftn->child_at(i)));
+ }
+
+ return frame_info;
+}
+
+} // namespace
+
ProcessInternalsHandlerImpl::ProcessInternalsHandlerImpl(
+ BrowserContext* browser_context,
mojo::InterfaceRequest<::mojom::ProcessInternalsHandler> request)
- : binding_(this, std::move(request)) {}
+ : browser_context_(browser_context), binding_(this, std::move(request)) {}
ProcessInternalsHandlerImpl::~ProcessInternalsHandlerImpl() = default;
@@ -21,8 +59,6 @@ void ProcessInternalsHandlerImpl::GetIsolationMode(
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");
@@ -36,4 +72,26 @@ void ProcessInternalsHandlerImpl::GetIsolatedOriginsSize(
std::move(callback).Run(size);
}
+void ProcessInternalsHandlerImpl::GetAllWebContentsInfo(
+ GetAllWebContentsInfoCallback callback) {
+ std::vector<::mojom::WebContentsInfoPtr> infos;
+ std::vector<WebContentsImpl*> all_contents =
+ WebContentsImpl::GetAllWebContents();
+
+ for (WebContentsImpl* web_contents : all_contents) {
+ // Do not return WebContents that don't belong to the current
+ // BrowserContext to avoid leaking data between contexts.
+ if (web_contents->GetBrowserContext() != browser_context_)
+ continue;
+
+ auto info = ::mojom::WebContentsInfo::New();
+ info->title = base::UTF16ToUTF8(web_contents->GetTitle());
+ info->root_frame =
+ FrameTreeNodeToFrameInfo(web_contents->GetFrameTree()->root());
+ infos.push_back(std::move(info));
+ }
+
+ std::move(callback).Run(std::move(infos));
+}
+
} // 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
index 54b7def12f9..4d75ba9c131 100644
--- a/chromium/content/browser/process_internals/process_internals_handler_impl.h
+++ b/chromium/content/browser/process_internals/process_internals_handler_impl.h
@@ -17,14 +17,17 @@ namespace content {
class ProcessInternalsHandlerImpl : public ::mojom::ProcessInternalsHandler {
public:
ProcessInternalsHandlerImpl(
+ BrowserContext* browser_context,
mojo::InterfaceRequest<::mojom::ProcessInternalsHandler> request);
~ProcessInternalsHandlerImpl() override;
// mojom::ProcessInternalsHandler overrides:
void GetIsolationMode(GetIsolationModeCallback callback) override;
void GetIsolatedOriginsSize(GetIsolatedOriginsSizeCallback callback) override;
+ void GetAllWebContentsInfo(GetAllWebContentsInfoCallback callback) override;
private:
+ BrowserContext* browser_context_;
mojo::Binding<::mojom::ProcessInternalsHandler> binding_;
DISALLOW_COPY_AND_ASSIGN(ProcessInternalsHandlerImpl);
diff --git a/chromium/content/browser/process_internals/process_internals_ui.cc b/chromium/content/browser/process_internals/process_internals_ui.cc
index 8c3558c5b61..0c3ea14ce1d 100644
--- a/chromium/content/browser/process_internals/process_internals_ui.cc
+++ b/chromium/content/browser/process_internals/process_internals_ui.cc
@@ -34,7 +34,9 @@ ProcessInternalsUI::ProcessInternalsUI(WebUI* web_ui)
WebUIDataSource* source =
WebUIDataSource::Create(kChromeUIProcessInternalsHost);
+ source->AddResourcePath("url.mojom.js", IDR_URL_MOJO_JS);
source->AddResourcePath("process_internals.js", IDR_PROCESS_INTERNALS_JS);
+ source->AddResourcePath("process_internals.css", IDR_PROCESS_INTERNALS_CSS);
source->AddResourcePath("process_internals.mojom.js",
IDR_PROCESS_INTERNALS_MOJO_JS);
source->SetDefaultResource(IDR_PROCESS_INTERNALS_HTML);
@@ -50,13 +52,15 @@ ProcessInternalsUI::ProcessInternalsUI(WebUI* web_ui)
ProcessInternalsUI::~ProcessInternalsUI() = default;
void ProcessInternalsUI::BindProcessInternalsHandler(
- ::mojom::ProcessInternalsHandlerRequest request) {
- ui_handler_ =
- std::make_unique<ProcessInternalsHandlerImpl>(std::move(request));
+ ::mojom::ProcessInternalsHandlerRequest request,
+ RenderFrameHost* render_frame_host) {
+ ui_handler_ = std::make_unique<ProcessInternalsHandlerImpl>(
+ render_frame_host->GetSiteInstance()->GetBrowserContext(),
+ std::move(request));
}
void ProcessInternalsUI::OnInterfaceRequestFromFrame(
- content::RenderFrameHost* render_frame_host,
+ 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
@@ -67,7 +71,7 @@ void ProcessInternalsUI::OnInterfaceRequestFromFrame(
return;
}
- registry_.TryBindInterface(interface_name, interface_pipe);
+ registry_.TryBindInterface(interface_name, interface_pipe, render_frame_host);
}
} // namespace content
diff --git a/chromium/content/browser/process_internals/process_internals_ui.h b/chromium/content/browser/process_internals/process_internals_ui.h
index 8c760bcf5f8..bd2bdc6f0d3 100644
--- a/chromium/content/browser/process_internals/process_internals_ui.h
+++ b/chromium/content/browser/process_internals/process_internals_ui.h
@@ -32,11 +32,12 @@ class ProcessInternalsUI : public WebUIController, public WebContentsObserver {
registry_.AddInterface(std::move(binder));
}
void BindProcessInternalsHandler(
- ::mojom::ProcessInternalsHandlerRequest request);
+ ::mojom::ProcessInternalsHandlerRequest request,
+ RenderFrameHost* render_frame_host);
private:
std::unique_ptr<::mojom::ProcessInternalsHandler> ui_handler_;
- service_manager::BinderRegistry registry_;
+ service_manager::BinderRegistryWithArgs<content::RenderFrameHost*> registry_;
DISALLOW_COPY_AND_ASSIGN(ProcessInternalsUI);
};
diff --git a/chromium/content/browser/push_messaging/push_messaging_manager.cc b/chromium/content/browser/push_messaging/push_messaging_manager.cc
index 91018ad3310..267d942e20b 100644
--- a/chromium/content/browser/push_messaging/push_messaging_manager.cc
+++ b/chromium/content/browser/push_messaging/push_messaging_manager.cc
@@ -15,6 +15,7 @@
#include "base/metrics/histogram_macros.h"
#include "base/optional.h"
#include "base/strings/string_number_conversions.h"
+#include "base/task/post_task.h"
#include "content/browser/permissions/permission_controller_impl.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/service_worker/service_worker_context_core.h"
@@ -22,6 +23,7 @@
#include "content/browser/service_worker/service_worker_storage.h"
#include "content/common/push_messaging.mojom.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/permission_type.h"
#include "content/public/browser/push_messaging_service.h"
#include "content/public/browser/render_frame_host.h"
@@ -369,8 +371,8 @@ void PushMessagingManager::DidCheckForExistingRegistration(
// the subscription algorithm instead of trying to subscribe.
if (!data.options.sender_info.empty()) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&Core::RegisterOnUI, base::Unretained(ui_core_.get()),
std::move(data)));
} else {
@@ -405,8 +407,8 @@ void PushMessagingManager::DidGetSenderIdFromStorage(
return;
}
data.options.sender_info = fixed_sender_id;
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&Core::RegisterOnUI, base::Unretained(ui_core_.get()),
std::move(data)));
}
@@ -419,8 +421,8 @@ void PushMessagingManager::Core::RegisterOnUI(
if (!is_incognito()) {
// This might happen if InstanceIDProfileService::IsInstanceIDEnabled
// returns false because the Instance ID kill switch was enabled.
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&PushMessagingManager::SendSubscriptionError,
io_parent_, std::move(data),
mojom::PushRegistrationStatus::SERVICE_NOT_AVAILABLE));
@@ -429,8 +431,8 @@ void PushMessagingManager::Core::RegisterOnUI(
// have happened if we had a PushMessagingService available.
if (!data.FromDocument() || !data.options.user_visible_only) {
// Throw a permission denied error under the same circumstances.
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&PushMessagingManager::SendSubscriptionError, io_parent_,
std::move(data),
@@ -487,8 +489,8 @@ void PushMessagingManager::Core::DidRequestPermissionInIncognito(
DCHECK_CURRENTLY_ON(BrowserThread::UI);
// Notification permission should always be denied in incognito.
DCHECK_EQ(blink::mojom::PermissionStatus::DENIED, status);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&PushMessagingManager::SendSubscriptionError, io_parent_,
std::move(data),
@@ -511,8 +513,8 @@ void PushMessagingManager::Core::DidRegister(
data.existing_subscription_id.value() != push_subscription_id;
if (status == mojom::PushRegistrationStatus::SUCCESS_FROM_PUSH_SERVICE) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&PushMessagingManager::PersistRegistrationOnIO, io_parent_,
std::move(data), push_subscription_id, p256dh, auth,
@@ -521,8 +523,8 @@ void PushMessagingManager::Core::DidRegister(
SUCCESS_NEW_SUBSCRIPTION_FROM_PUSH_SERVICE
: mojom::PushRegistrationStatus::SUCCESS_FROM_PUSH_SERVICE));
} else {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&PushMessagingManager::SendSubscriptionError, io_parent_,
std::move(data), status));
}
@@ -637,8 +639,8 @@ void PushMessagingManager::UnsubscribeHavingGottenSenderId(
DCHECK_EQ(1u, sender_ids.size());
sender_id = sender_ids[0];
}
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&Core::UnregisterFromService,
base::Unretained(ui_core_.get()), std::move(callback),
service_worker_registration_id, requesting_origin,
@@ -656,8 +658,8 @@ void PushMessagingManager::Core::UnregisterFromService(
// This shouldn't be possible in incognito mode, since we've already checked
// that we have an existing registration. Hence it's ok to throw an error.
DCHECK(!is_incognito());
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&PushMessagingManager::DidUnregister, io_parent_,
std::move(callback),
mojom::PushUnregistrationStatus::SERVICE_NOT_AVAILABLE));
@@ -678,8 +680,8 @@ void PushMessagingManager::Core::DidUnregisterFromService(
mojom::PushUnregistrationStatus unregistration_status) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&PushMessagingManager::DidUnregister, io_parent_,
std::move(callback), unregistration_status));
}
@@ -772,8 +774,8 @@ void PushMessagingManager::DidGetSubscription(
const GURL endpoint =
CreateEndpoint(uses_standard_protocol, push_subscription_id);
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&Core::GetSubscriptionInfoOnUI,
base::Unretained(ui_core_.get()), origin,
service_worker_registration_id, sender_info,
@@ -845,9 +847,9 @@ void PushMessagingManager::Core::GetSubscriptionDidGetInfoOnUI(
mojom::PushGetRegistrationStatus status =
mojom::PushGetRegistrationStatus::SUCCESS;
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::BindOnce(std::move(callback), status,
- endpoint, options, p256dh, auth));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(std::move(callback), status,
+ endpoint, options, p256dh, auth));
RecordGetRegistrationStatus(status);
} else {
@@ -856,8 +858,8 @@ void PushMessagingManager::Core::GetSubscriptionDidGetInfoOnUI(
// Shouldn't be possible to have a stored push subscription in a profile
// with no push service, but this case can occur when the renderer is
// shutting down.
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(std::move(callback),
mojom::PushGetRegistrationStatus::RENDERER_SHUTDOWN,
base::nullopt /* endpoint */,
@@ -889,8 +891,8 @@ void PushMessagingManager::Core::GetSubscriptionDidUnsubscribe(
mojom::PushGetRegistrationStatus get_status,
mojom::PushUnregistrationStatus unsubscribe_status) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(std::move(callback), get_status,
base::nullopt /* endpoint */, base::nullopt /* options */,
base::nullopt /* p256dh */, base::nullopt /* auth */));
diff --git a/chromium/content/browser/push_messaging/push_messaging_router.cc b/chromium/content/browser/push_messaging/push_messaging_router.cc
index 697ca1fabf8..5734e177333 100644
--- a/chromium/content/browser/push_messaging/push_messaging_router.cc
+++ b/chromium/content/browser/push_messaging/push_messaging_router.cc
@@ -8,10 +8,12 @@
#include "base/bind.h"
#include "base/metrics/histogram_macros.h"
+#include "base/task/post_task.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_registration.h"
#include "content/browser/service_worker/service_worker_storage.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/common/push_messaging_status.mojom.h"
@@ -25,8 +27,8 @@ void RunDeliverCallback(
const PushMessagingRouter::DeliverMessageCallback& deliver_message_callback,
mojom::PushDeliveryStatus delivery_status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(deliver_message_callback, delivery_status));
}
@@ -45,8 +47,8 @@ void PushMessagingRouter::DeliverMessage(
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context =
static_cast<ServiceWorkerContextWrapper*>(
partition->GetServiceWorkerContext());
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&PushMessagingRouter::FindServiceWorkerRegistration,
origin, service_worker_registration_id, std::move(payload),
deliver_message_callback, service_worker_context));
diff --git a/chromium/content/browser/quota_dispatcher_host.cc b/chromium/content/browser/quota_dispatcher_host.cc
index c32742729ad..350bdf3b32f 100644
--- a/chromium/content/browser/quota_dispatcher_host.cc
+++ b/chromium/content/browser/quota_dispatcher_host.cc
@@ -11,6 +11,8 @@
#include "base/bind.h"
#include "base/memory/weak_ptr.h"
#include "base/numerics/safe_conversions.h"
+#include "base/task/post_task.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/render_process_host.h"
@@ -51,8 +53,8 @@ void QuotaDispatcherHost::CreateForWorker(
// one provided by QuotaDispatcher.
// Bind on the IO thread.
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&BindConnectorOnIOThread, host->GetID(), MSG_ROUTING_NONE,
base::RetainedRef(host->GetStoragePartition()->GetQuotaManager()),
@@ -65,8 +67,8 @@ void QuotaDispatcherHost::CreateForFrame(
int render_frame_id,
blink::mojom::QuotaDispatcherHostRequest request) {
// Bind on the IO thread.
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&BindConnectorOnIOThread, host->GetID(), render_frame_id,
base::RetainedRef(host->GetStoragePartition()->GetQuotaManager()),
@@ -93,7 +95,7 @@ void QuotaDispatcherHost::QueryStorageUsageAndQuota(
StorageType storage_type,
QueryStorageUsageAndQuotaCallback callback) {
quota_manager_->GetUsageAndQuotaForWebApps(
- origin.GetURL(), storage_type,
+ origin, storage_type,
base::BindOnce(&QuotaDispatcherHost::DidQueryStorageUsageAndQuota,
weak_factory_.GetWeakPtr(), std::move(callback)));
}
@@ -115,7 +117,7 @@ void QuotaDispatcherHost::RequestStorageQuota(
return;
}
- if (origin.unique()) {
+ if (origin.opaque()) {
mojo::ReportBadMessage("Unique origins may not request storage quota.");
return;
}
@@ -124,13 +126,13 @@ void QuotaDispatcherHost::RequestStorageQuota(
storage_type == StorageType::kPersistent);
if (storage_type == StorageType::kPersistent) {
quota_manager_->GetUsageAndQuotaForWebApps(
- origin.GetURL(), storage_type,
+ origin, storage_type,
base::BindOnce(&QuotaDispatcherHost::DidGetPersistentUsageAndQuota,
weak_factory_.GetWeakPtr(), origin, storage_type,
requested_size, std::move(callback)));
} else {
quota_manager_->GetUsageAndQuotaForWebApps(
- origin.GetURL(), storage_type,
+ origin, storage_type,
base::BindOnce(&QuotaDispatcherHost::DidGetTemporaryUsageAndQuota,
weak_factory_.GetWeakPtr(), requested_size,
std::move(callback)));
@@ -164,7 +166,7 @@ void QuotaDispatcherHost::DidGetPersistentUsageAndQuota(
// TODO(nhiroki): The backend should accept uint64_t values.
int64_t requested_quota_signed =
base::saturated_cast<int64_t>(requested_quota);
- if (quota_manager_->IsStorageUnlimited(origin.GetURL(), storage_type) ||
+ if (quota_manager_->IsStorageUnlimited(origin, storage_type) ||
requested_quota_signed <= current_quota) {
std::move(callback).Run(blink::mojom::QuotaStatusCode::kOk, current_usage,
requested_quota);
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 7dc490ea560..71a9e1024b6 100644
--- a/chromium/content/browser/renderer_host/browser_compositor_view_mac.h
+++ b/chromium/content/browser/renderer_host/browser_compositor_view_mac.h
@@ -137,6 +137,7 @@ class CONTENT_EXPORT BrowserCompositorMac : public DelegatedFrameHostClient,
void OnFirstSurfaceActivation(const viz::SurfaceInfo& surface_info) override;
void OnBeginFrame(base::TimeTicks frame_time) override;
void OnFrameTokenChanged(uint32_t frame_token) override;
+ float GetDeviceScaleFactor() const override;
base::WeakPtr<BrowserCompositorMac> GetWeakPtr() {
return weak_factory_.GetWeakPtr();
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 fb23caccdd1..65670cccb50 100644
--- a/chromium/content/browser/renderer_host/browser_compositor_view_mac.mm
+++ b/chromium/content/browser/renderer_host/browser_compositor_view_mac.mm
@@ -401,6 +401,10 @@ void BrowserCompositorMac::OnFrameTokenChanged(uint32_t frame_token) {
client_->OnFrameTokenChanged(frame_token);
}
+float BrowserCompositorMac::GetDeviceScaleFactor() const {
+ return dfh_display_.device_scale_factor();
+}
+
void BrowserCompositorMac::DidNavigate() {
// The first navigation does not need a new LocalSurfaceID. The renderer can
// use the ID that was already provided.
diff --git a/chromium/content/browser/renderer_host/clipboard_host_impl.cc b/chromium/content/browser/renderer_host/clipboard_host_impl.cc
index 60928166661..0b8dc1505a6 100644
--- a/chromium/content/browser/renderer_host/clipboard_host_impl.cc
+++ b/chromium/content/browser/renderer_host/clipboard_host_impl.cc
@@ -6,11 +6,13 @@
#include <utility>
+#include "base/location.h"
#include "base/macros.h"
#include "base/pickle.h"
+#include "base/sequenced_task_runner.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/threading/sequenced_task_runner_handle.h"
#include "build/build_config.h"
-#include "mojo/public/cpp/bindings/strong_binding.h"
#include "mojo/public/cpp/system/platform_handle.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/clipboard/clipboard.h"
@@ -20,15 +22,23 @@
namespace content {
-ClipboardHostImpl::ClipboardHostImpl()
- : clipboard_(ui::Clipboard::GetForCurrentThread()),
+ClipboardHostImpl::ClipboardHostImpl(blink::mojom::ClipboardHostRequest request)
+ : binding_(this, std::move(request)),
+ clipboard_(ui::Clipboard::GetForCurrentThread()),
clipboard_writer_(
new ui::ScopedClipboardWriter(ui::CLIPBOARD_TYPE_COPY_PASTE)) {}
void ClipboardHostImpl::Create(blink::mojom::ClipboardHostRequest request) {
- mojo::MakeStrongBinding(
- base::WrapUnique<ClipboardHostImpl>(new ClipboardHostImpl()),
- std::move(request));
+ // Clipboard implementations do interesting things, like run nested message
+ // loops. Since StrongBinding<T> synchronously destroys on failure, that can
+ // result in some unfortunate use-after-frees after the nested message loops
+ // exit.
+ auto* host = new ClipboardHostImpl(std::move(request));
+ host->binding_.set_connection_error_handler(base::BindOnce(
+ [](ClipboardHostImpl* host) {
+ base::SequencedTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, host);
+ },
+ host));
}
ClipboardHostImpl::~ClipboardHostImpl() {
diff --git a/chromium/content/browser/renderer_host/clipboard_host_impl.h b/chromium/content/browser/renderer_host/clipboard_host_impl.h
index f9c6a3db4af..82a0d6be9de 100644
--- a/chromium/content/browser/renderer_host/clipboard_host_impl.h
+++ b/chromium/content/browser/renderer_host/clipboard_host_impl.h
@@ -11,6 +11,7 @@
#include "base/macros.h"
#include "build/build_config.h"
#include "content/common/content_export.h"
+#include "mojo/public/cpp/bindings/binding.h"
#include "third_party/blink/public/mojom/clipboard/clipboard.mojom.h"
#include "ui/base/clipboard/clipboard.h"
@@ -33,7 +34,7 @@ class CONTENT_EXPORT ClipboardHostImpl : public blink::mojom::ClipboardHost {
private:
friend class ClipboardHostImplTest;
- ClipboardHostImpl();
+ explicit ClipboardHostImpl(blink::mojom::ClipboardHostRequest request);
// content::mojom::ClipboardHost
void GetSequenceNumber(ui::ClipboardType clipboard_type,
@@ -73,7 +74,8 @@ class CONTENT_EXPORT ClipboardHostImpl : public blink::mojom::ClipboardHost {
void WriteStringToFindPboard(const base::string16& text) override;
#endif
- ui::Clipboard* clipboard_; // Not owned
+ mojo::Binding<blink::mojom::ClipboardHost> binding_;
+ ui::Clipboard* const clipboard_; // Not owned
std::unique_ptr<ui::ScopedClipboardWriter> clipboard_writer_;
};
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 a3a0e92ec35..50b866d09b6 100644
--- a/chromium/content/browser/renderer_host/clipboard_host_impl_unittest.cc
+++ b/chromium/content/browser/renderer_host/clipboard_host_impl_unittest.cc
@@ -7,8 +7,12 @@
#include <stddef.h>
#include <stdint.h>
+#include "base/callback_helpers.h"
#include "base/run_loop.h"
+#include "base/strings/string16.h"
+#include "base/test/bind_test_util.h"
#include "content/public/test/test_browser_thread_bundle.h"
+#include "mojo/public/cpp/system/message_pipe.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/test/test_clipboard.h"
@@ -19,26 +23,21 @@ namespace content {
class ClipboardHostImplTest : public ::testing::Test {
protected:
ClipboardHostImplTest()
- : clipboard_(ui::TestClipboard::CreateForCurrentThread()) {}
+ : clipboard_(ui::TestClipboard::CreateForCurrentThread()) {
+ ClipboardHostImpl::Create(mojo::MakeRequest(&ptr_));
+ }
~ClipboardHostImplTest() override {
ui::Clipboard::DestroyClipboardForCurrentThread();
}
- void CallWriteImage(const SkBitmap& bitmap) {
- host_.WriteImage(ui::CLIPBOARD_TYPE_COPY_PASTE, bitmap);
- }
+ blink::mojom::ClipboardHostPtr& mojo_clipboard() { return ptr_; }
- void CallCommitWrite() {
- host_.CommitWrite(ui::CLIPBOARD_TYPE_COPY_PASTE);
- base::RunLoop().RunUntilIdle();
- }
-
- ui::Clipboard* clipboard() { return clipboard_; }
+ ui::Clipboard* system_clipboard() { return clipboard_; }
private:
const TestBrowserThreadBundle thread_bundle_;
- ClipboardHostImpl host_;
+ blink::mojom::ClipboardHostPtr ptr_;
ui::Clipboard* const clipboard_;
};
@@ -47,20 +46,48 @@ TEST_F(ClipboardHostImplTest, SimpleImage) {
SkBitmap bitmap;
bitmap.allocN32Pixels(3, 2);
bitmap.eraseARGB(255, 0, 255, 0);
- CallWriteImage(bitmap);
+ mojo_clipboard()->WriteImage(ui::CLIPBOARD_TYPE_COPY_PASTE, bitmap);
uint64_t sequence_number =
- clipboard()->GetSequenceNumber(ui::CLIPBOARD_TYPE_COPY_PASTE);
- CallCommitWrite();
+ system_clipboard()->GetSequenceNumber(ui::CLIPBOARD_TYPE_COPY_PASTE);
+ mojo_clipboard()->CommitWrite(ui::CLIPBOARD_TYPE_COPY_PASTE);
+ base::RunLoop().RunUntilIdle();
- EXPECT_NE(sequence_number,
- clipboard()->GetSequenceNumber(ui::CLIPBOARD_TYPE_COPY_PASTE));
- EXPECT_FALSE(clipboard()->IsFormatAvailable(
+ EXPECT_NE(sequence_number, system_clipboard()->GetSequenceNumber(
+ ui::CLIPBOARD_TYPE_COPY_PASTE));
+ EXPECT_FALSE(system_clipboard()->IsFormatAvailable(
ui::Clipboard::GetPlainTextFormatType(), ui::CLIPBOARD_TYPE_COPY_PASTE));
- EXPECT_TRUE(clipboard()->IsFormatAvailable(
+ EXPECT_TRUE(system_clipboard()->IsFormatAvailable(
ui::Clipboard::GetBitmapFormatType(), ui::CLIPBOARD_TYPE_COPY_PASTE));
- SkBitmap actual = clipboard()->ReadImage(ui::CLIPBOARD_TYPE_COPY_PASTE);
+ SkBitmap actual =
+ system_clipboard()->ReadImage(ui::CLIPBOARD_TYPE_COPY_PASTE);
EXPECT_TRUE(gfx::BitmapsAreEqual(bitmap, actual));
}
+TEST_F(ClipboardHostImplTest, ReentrancyInSyncCall) {
+ // Due to the nature of this test, it's somewhat racy. On some platforms
+ // (currently Linux), reading the clipboard requires running a nested message
+ // loop. During that time, it's possible to send a bad message that causes the
+ // message pipe to be closed. Make sure ClipboardHostImpl doesn't UaF |this|
+ // after exiting the nested message loop.
+
+ // ReadText() is a sync method, so normally, one wouldn't call this method
+ // directly. These are not normal times though...
+ base::RunLoop run_loop;
+ mojo_clipboard()->ReadText(
+ ui::CLIPBOARD_TYPE_COPY_PASTE,
+ base::BindLambdaForTesting(
+ [&run_loop](const base::string16& ignored) { run_loop.Quit(); }));
+
+ // Now purposely write a raw message which (hopefully) won't deserialize to
+ // anything valid. The receiver side should still be in the midst of
+ // dispatching ReadText() when Mojo attempts to deserialize this message,
+ // which should cause a validation failure that signals a connection error.
+ mojo::WriteMessageRaw(mojo_clipboard().internal_state()->handle(), "moo", 3,
+ nullptr, 0, MOJO_WRITE_MESSAGE_FLAG_NONE);
+ run_loop.Run();
+
+ EXPECT_TRUE(mojo_clipboard().encountered_error());
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/code_cache_host_impl.cc b/chromium/content/browser/renderer_host/code_cache_host_impl.cc
new file mode 100644
index 00000000000..17dcbed2857
--- /dev/null
+++ b/chromium/content/browser/renderer_host/code_cache_host_impl.cc
@@ -0,0 +1,239 @@
+// 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/code_cache_host_impl.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/task/post_task.h"
+#include "base/threading/thread.h"
+#include "build/build_config.h"
+#include "content/browser/cache_storage/cache_storage_cache.h"
+#include "content/browser/cache_storage/cache_storage_cache_handle.h"
+#include "content/browser/cache_storage/cache_storage_context_impl.h"
+#include "content/browser/cache_storage/cache_storage_manager.h"
+#include "content/browser/child_process_security_policy_impl.h"
+#include "content/browser/code_cache/generated_code_cache.h"
+#include "content/browser/code_cache/generated_code_cache_context.h"
+#include "content/browser/renderer_host/render_process_host_impl.h"
+#include "content/browser/storage_partition_impl.h"
+#include "content/public/browser/resource_context.h"
+#include "content/public/browser/storage_partition.h"
+#include "content/public/common/content_features.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "net/base/features.h"
+#include "net/base/io_buffer.h"
+#include "url/gurl.h"
+#include "url/origin.h"
+
+using blink::mojom::CacheStorageError;
+
+namespace content {
+
+namespace {
+
+void NoOpCacheStorageErrorCallback(CacheStorageCacheHandle cache_handle,
+ CacheStorageError error) {}
+
+base::Optional<url::Origin> GetRendererOrigin(const GURL& url,
+ int render_process_id) {
+ GURL requesting_url =
+ ChildProcessSecurityPolicyImpl::GetInstance()->GetOriginLock(
+ render_process_id);
+
+ if (!requesting_url.is_valid() || !url.is_valid())
+ return base::nullopt;
+
+ url::Origin origin = url::Origin::Create(requesting_url);
+
+ // Don't cache the code corresponding to unique origins. The same-origin
+ // checks should always fail for unique origins but the serialized value of
+ // unique origins does not ensure this.
+ if (origin.opaque())
+ return base::nullopt;
+
+ return origin;
+}
+
+} // namespace
+
+CodeCacheHostImpl::CodeCacheHostImpl(
+ int render_process_id,
+ scoped_refptr<CacheStorageContextImpl> cache_storage_context,
+ scoped_refptr<GeneratedCodeCacheContext> generated_code_cache_context)
+ : render_process_id_(render_process_id),
+ cache_storage_context_(std::move(cache_storage_context)),
+ generated_code_cache_context_(std::move(generated_code_cache_context)),
+ weak_ptr_factory_(this) {}
+
+CodeCacheHostImpl::~CodeCacheHostImpl() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+}
+
+// static
+void CodeCacheHostImpl::Create(
+ int render_process_id,
+ scoped_refptr<CacheStorageContextImpl> cache_storage_context,
+ scoped_refptr<GeneratedCodeCacheContext> generated_code_cache_context,
+ blink::mojom::CodeCacheHostRequest request) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ mojo::MakeStrongBinding(
+ std::make_unique<CodeCacheHostImpl>(
+ render_process_id, std::move(cache_storage_context),
+ std::move(generated_code_cache_context)),
+ std::move(request));
+}
+
+void CodeCacheHostImpl::DidGenerateCacheableMetadata(
+ blink::mojom::CodeCacheType cache_type,
+ const GURL& url,
+ base::Time expected_response_time,
+ const std::vector<uint8_t>& data) {
+ if (!url.SchemeIsHTTPOrHTTPS()) {
+ mojo::ReportBadMessage("Invalid URL scheme for code cache.");
+ return;
+ }
+
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (!base::FeatureList::IsEnabled(net::features::kIsolatedCodeCache)) {
+ // Only store Javascript (not WebAssembly) code in the single-keyed cache.
+ if (cache_type == blink::mojom::CodeCacheType::kJavascript) {
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(&CodeCacheHostImpl::DidGenerateCacheableMetadataOnUI,
+ render_process_id_, url, expected_response_time,
+ data));
+ } else {
+ mojo::ReportBadMessage("Single-keyed code cache is Javascript only.");
+ return;
+ }
+ } else {
+ GeneratedCodeCache* code_cache = GetCodeCache(cache_type);
+ if (!code_cache)
+ return;
+
+ base::Optional<url::Origin> requesting_origin =
+ GetRendererOrigin(url, render_process_id_);
+ if (!requesting_origin)
+ return;
+
+ code_cache->WriteData(url, *requesting_origin, expected_response_time,
+ data);
+ }
+}
+
+void CodeCacheHostImpl::FetchCachedCode(blink::mojom::CodeCacheType cache_type,
+ const GURL& url,
+ FetchCachedCodeCallback callback) {
+ GeneratedCodeCache* code_cache = GetCodeCache(cache_type);
+ if (!code_cache) {
+ std::move(callback).Run(base::Time(), std::vector<uint8_t>());
+ return;
+ }
+
+ base::Optional<url::Origin> requesting_origin =
+ GetRendererOrigin(url, render_process_id_);
+ if (!requesting_origin) {
+ std::move(callback).Run(base::Time(), std::vector<uint8_t>());
+ return;
+ }
+
+ auto read_callback = base::BindRepeating(
+ &CodeCacheHostImpl::OnReceiveCachedCode, weak_ptr_factory_.GetWeakPtr(),
+ base::Passed(&callback));
+ code_cache->FetchEntry(url, *requesting_origin, read_callback);
+}
+
+void CodeCacheHostImpl::ClearCodeCacheEntry(
+ blink::mojom::CodeCacheType cache_type,
+ const GURL& url) {
+ GeneratedCodeCache* code_cache = GetCodeCache(cache_type);
+ if (!code_cache)
+ return;
+
+ base::Optional<url::Origin> requesting_origin =
+ GetRendererOrigin(url, render_process_id_);
+ if (!requesting_origin)
+ return;
+
+ code_cache->DeleteEntry(url, *requesting_origin);
+}
+
+void CodeCacheHostImpl::DidGenerateCacheableMetadataInCacheStorage(
+ const GURL& url,
+ base::Time expected_response_time,
+ const std::vector<uint8_t>& data,
+ const url::Origin& cache_storage_origin,
+ const std::string& cache_storage_cache_name) {
+ scoped_refptr<net::IOBuffer> buf =
+ base::MakeRefCounted<net::IOBuffer>(data.size());
+ if (!data.empty())
+ memcpy(buf->data(), &data.front(), data.size());
+
+ cache_storage_context_->cache_manager()->OpenCache(
+ cache_storage_origin, CacheStorageOwner::kCacheAPI,
+ cache_storage_cache_name,
+ base::BindOnce(&CodeCacheHostImpl::OnCacheStorageOpenCallback,
+ weak_ptr_factory_.GetWeakPtr(), url,
+ expected_response_time, buf, data.size()));
+}
+
+GeneratedCodeCache* CodeCacheHostImpl::GetCodeCache(
+ blink::mojom::CodeCacheType cache_type) {
+ if (!generated_code_cache_context_)
+ return nullptr;
+
+ if (cache_type == blink::mojom::CodeCacheType::kJavascript)
+ return generated_code_cache_context_->generated_js_code_cache();
+
+ DCHECK_EQ(blink::mojom::CodeCacheType::kWebAssembly, cache_type);
+ return generated_code_cache_context_->generated_wasm_code_cache();
+}
+
+void CodeCacheHostImpl::OnReceiveCachedCode(FetchCachedCodeCallback callback,
+ const base::Time& response_time,
+ const std::vector<uint8_t>& data) {
+ // TODO(crbug.com/867848): Pass the data as a mojo data pipe instead
+ // of vector<uint8>
+ std::move(callback).Run(response_time, data);
+}
+
+void CodeCacheHostImpl::OnCacheStorageOpenCallback(
+ const GURL& url,
+ base::Time expected_response_time,
+ scoped_refptr<net::IOBuffer> buf,
+ int buf_len,
+ CacheStorageCacheHandle cache_handle,
+ CacheStorageError error) {
+ if (error != CacheStorageError::kSuccess || !cache_handle.value())
+ return;
+ CacheStorageCache* cache = cache_handle.value();
+ cache->WriteSideData(
+ base::BindOnce(&NoOpCacheStorageErrorCallback, std::move(cache_handle)),
+ url, expected_response_time, buf, buf_len);
+}
+
+// static
+void CodeCacheHostImpl::DidGenerateCacheableMetadataOnUI(
+ int render_process_id,
+ const GURL& url,
+ base::Time expected_response_time,
+ const std::vector<uint8_t>& data) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ RenderProcessHost* host = RenderProcessHost::FromID(render_process_id);
+ if (!host)
+ return;
+
+ // Use the same priority for the metadata write as for script
+ // resources (see defaultPriorityForResourceType() in WebKit's
+ // CachedResource.cpp). Note that WebURLRequest::PriorityMedium
+ // corresponds to net::LOW (see ConvertWebKitPriorityToNetPriority()
+ // in weburlloader_impl.cc).
+ const net::RequestPriority kPriority = net::LOW;
+ host->GetStoragePartition()->GetNetworkContext()->WriteCacheMetadata(
+ url, kPriority, expected_response_time, data);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/code_cache_host_impl.h b/chromium/content/browser/renderer_host/code_cache_host_impl.h
new file mode 100644
index 00000000000..4e0844adaad
--- /dev/null
+++ b/chromium/content/browser/renderer_host/code_cache_host_impl.h
@@ -0,0 +1,104 @@
+// 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_CODE_CACHE_HOST_IMPL_H_
+#define CONTENT_BROWSER_RENDERER_HOST_CODE_CACHE_HOST_IMPL_H_
+
+#include <string>
+
+#include "base/memory/scoped_refptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/strings/string16.h"
+#include "build/build_config.h"
+#include "content/common/content_export.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "third_party/blink/public/mojom/loader/code_cache.mojom.h"
+#include "third_party/blink/public/platform/modules/cache_storage/cache_storage.mojom.h"
+
+class GURL;
+
+namespace net {
+class IOBuffer;
+}
+
+namespace url {
+class Origin;
+}
+
+namespace content {
+
+class CacheStorageContextImpl;
+class CacheStorageCacheHandle;
+class GeneratedCodeCache;
+class GeneratedCodeCacheContext;
+
+// The implementation of a CodeCacheHost, which stores and retrieves resource
+// metadata, either bytecode or native code, generated by a renderer process.
+// Instances of this class are owned by by the Mojo pipe that's passed to the
+// renderer process via StrongBinding.
+// Instances of this class must be created and used on the IO thread.
+class CONTENT_EXPORT CodeCacheHostImpl : public blink::mojom::CodeCacheHost {
+ public:
+ CodeCacheHostImpl(
+ int render_process_id,
+ scoped_refptr<CacheStorageContextImpl> cache_storage_context,
+ scoped_refptr<GeneratedCodeCacheContext> generated_code_cache_context);
+ ~CodeCacheHostImpl() override;
+
+ static void Create(
+ int render_process_id,
+ scoped_refptr<CacheStorageContextImpl> cache_storage_context,
+ scoped_refptr<GeneratedCodeCacheContext> generated_code_cache_context,
+ blink::mojom::CodeCacheHostRequest request);
+
+ private:
+ // blink::mojom::CodeCacheHost implementation.
+ void DidGenerateCacheableMetadata(blink::mojom::CodeCacheType cache_type,
+ const GURL& url,
+ base::Time expected_response_time,
+ const std::vector<uint8_t>& data) override;
+ void FetchCachedCode(blink::mojom::CodeCacheType cache_type,
+ const GURL& url,
+ FetchCachedCodeCallback) override;
+ void ClearCodeCacheEntry(blink::mojom::CodeCacheType cache_type,
+ const GURL& url) override;
+ void DidGenerateCacheableMetadataInCacheStorage(
+ const GURL& url,
+ base::Time expected_response_time,
+ const std::vector<uint8_t>& data,
+ const url::Origin& cache_storage_origin,
+ const std::string& cache_storage_cache_name) override;
+
+ // Helpers.
+ GeneratedCodeCache* GetCodeCache(blink::mojom::CodeCacheType cache_type);
+ void OnReceiveCachedCode(FetchCachedCodeCallback callback,
+ const base::Time& response_time,
+ const std::vector<uint8_t>& data);
+ void OnCacheStorageOpenCallback(const GURL& url,
+ base::Time expected_response_time,
+ scoped_refptr<net::IOBuffer> buf,
+ int buf_len,
+ CacheStorageCacheHandle cache_handle,
+ blink::mojom::CacheStorageError error);
+ static void DidGenerateCacheableMetadataOnUI(
+ int render_process_id,
+ const GURL& url,
+ base::Time expected_response_time,
+ const std::vector<uint8_t>& data);
+
+ // Our render process host ID, used to bind to the correct render process.
+ const int render_process_id_;
+
+ scoped_refptr<CacheStorageContextImpl> cache_storage_context_;
+
+ scoped_refptr<GeneratedCodeCacheContext> generated_code_cache_context_;
+
+ base::WeakPtrFactory<CodeCacheHostImpl> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(CodeCacheHostImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_CODE_CACHE_HOST_IMPL_H_
diff --git a/chromium/content/browser/renderer_host/compositor_impl_android.cc b/chromium/content/browser/renderer_host/compositor_impl_android.cc
index ebfb4c19fb0..7e99e812763 100644
--- a/chromium/content/browser/renderer_host/compositor_impl_android.cc
+++ b/chromium/content/browser/renderer_host/compositor_impl_android.cc
@@ -27,6 +27,7 @@
#include "base/single_thread_task_runner.h"
#include "base/synchronization/lock.h"
#include "base/sys_info.h"
+#include "base/task/post_task.h"
#include "base/threading/simple_thread.h"
#include "base/threading/thread.h"
#include "base/threading/thread_checker.h"
@@ -61,15 +62,17 @@
#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
#include "content/browser/browser_main_loop.h"
#include "content/browser/compositor/surface_utils.h"
+#include "content/browser/gpu/browser_gpu_channel_host_factory.h"
#include "content/browser/gpu/compositor_util.h"
#include "content/browser/gpu/gpu_data_manager_impl.h"
#include "content/browser/gpu/gpu_process_host.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
-#include "content/common/gpu_stream_constants.h"
#include "content/public/browser/android/compositor.h"
#include "content/public/browser/android/compositor_client.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_switches.h"
+#include "content/public/common/gpu_stream_constants.h"
#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"
@@ -78,9 +81,11 @@
#include "gpu/ipc/client/gpu_channel_host.h"
#include "gpu/ipc/common/gpu_surface_tracker.h"
#include "gpu/vulkan/buildflags.h"
+#if BUILDFLAG(ENABLE_VULKAN)
#include "gpu/vulkan/init/vulkan_factory.h"
#include "gpu/vulkan/vulkan_implementation.h"
#include "gpu/vulkan/vulkan_surface.h"
+#endif
#include "services/viz/privileged/interfaces/compositing/frame_sink_manager.mojom.h"
#include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom.h"
#include "services/ws/public/cpp/gpu/context_provider_command_buffer.h"
@@ -104,6 +109,8 @@ namespace content {
namespace {
+static const char* kBrowser = "Browser";
+
// These functions are called based on application visibility status.
void SendOnBackgroundedToGpuService() {
content::GpuProcessHost::CallOnIO(
@@ -127,6 +134,14 @@ void SendOnForegroundedToGpuService() {
}));
}
+void BrowserGpuChannelHostFactorySetApplicationVisible(bool is_visible) {
+ // This code relies on the browser's GpuChannelEstablishFactory being the
+ // BrowserGpuChannelHostFactory.
+ DCHECK_EQ(BrowserMainLoop::GetInstance()->gpu_channel_establish_factory(),
+ BrowserGpuChannelHostFactory::instance());
+ BrowserGpuChannelHostFactory::instance()->SetApplicationVisible(is_visible);
+}
+
// The client_id used here should not conflict with the client_id generated
// from RenderWidgetHostImpl.
constexpr uint32_t kDefaultClientId = 0u;
@@ -144,18 +159,28 @@ class SingleThreadTaskGraphRunner : public cc::SingleThreadTaskGraphRunner {
class AndroidHostDisplayClient : public viz::HostDisplayClient {
public:
explicit AndroidHostDisplayClient(
- base::RepeatingCallback<void(const gfx::Size&)> on_swap)
+ base::RepeatingCallback<void(const gfx::Size&)> on_swap,
+ base::RepeatingCallback<void(gpu::ContextResult)>
+ on_context_creation_failure)
: HostDisplayClient(gfx::kNullAcceleratedWidget),
- on_swap_(std::move(on_swap)) {}
+ on_swap_(std::move(on_swap)),
+ on_context_creation_failure_(std::move(on_context_creation_failure)) {}
// viz::mojom::DisplayClient implementation:
void DidCompleteSwapWithSize(const gfx::Size& pixel_size) override {
if (on_swap_)
on_swap_.Run(pixel_size);
}
+ void OnFatalOrSurfaceContextCreationFailure(
+ gpu::ContextResult context_result) override {
+ if (on_context_creation_failure_)
+ on_context_creation_failure_.Run(context_result);
+ }
private:
base::RepeatingCallback<void(const gfx::Size&)> on_swap_;
+ base::RepeatingCallback<void(gpu::ContextResult)>
+ on_context_creation_failure_;
};
class CompositorDependencies {
@@ -184,14 +209,19 @@ class CompositorDependencies {
host_frame_sink_manager.SetConnectionLostCallback(base::BindRepeating(
[]() { CompositorDependencies::Get().CreateVizFrameSinkManager(); }));
- pending_connect_viz_on_main_thread_ = base::BindOnce(
- &CompositorDependencies::
- OnReadyToConnectVizFrameSinkManagerOnMainThread,
- base::Unretained(this), std::move(frame_sink_manager_request),
+ // Set up a pending request which will be run once we've successfully
+ // connected to the GPU process.
+ pending_connect_viz_on_io_thread_ = base::BindOnce(
+ &CompositorDependencies::ConnectVizFrameSinkManagerOnIOThread,
+ std::move(frame_sink_manager_request),
frame_sink_manager_client.PassInterface());
+ }
- // Will connect using the above callback if we are foreground.
- TryEstablishVizConnectionIfNeeded();
+ void TryEstablishVizConnectionIfNeeded() {
+ if (!pending_connect_viz_on_io_thread_)
+ return;
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO},
+ std::move(pending_connect_viz_on_io_thread_));
}
SingleThreadTaskGraphRunner task_graph_runner;
@@ -216,11 +246,15 @@ class CompositorDependencies {
CompositorDependencies()
: frame_sink_id_allocator(kDefaultClientId),
- app_listener_(base::BindRepeating(
- &CompositorDependencies::OnApplicationStateChange,
- base::Unretained(this))) {
+ app_listener_(
+ base::android::ApplicationStatusListener::New(base::BindRepeating(
+ &CompositorDependencies::OnApplicationStateChange,
+ base::Unretained(this)))) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ // Ensure we're in the correct state at start up.
+ OnApplicationStateChange(app_listener_->GetState());
+
bool enable_viz =
base::FeatureList::IsEnabled(features::kVizDisplayCompositor);
if (!enable_viz) {
@@ -233,54 +267,20 @@ class CompositorDependencies {
} else {
CreateVizFrameSinkManager();
}
-
- // Ensure we're in the correct state at start up.
- OnApplicationStateChange(app_listener_.GetState());
- }
-
- 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(
+ // Called on IO thread, after a GPU connection has already been established.
+ // |gpu_process_host| should only be invalid if a channel has been
+ // established and lost. In this case the ConnectionLost callback will be
+ // re-run when the request is deleted (goes out of scope).
+ static void ConnectVizFrameSinkManagerOnIOThread(
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->gpu_host()->ConnectFrameSinkManager(std::move(request),
- std::move(client));
- }
- }
-
- void TryEstablishVizConnectionIfNeeded() {
- // We don't connect to the viz process if backgrounded, as the OS may
- // repeatedly kill the resulting process. Instead wait until we come to the
- // foreground.
- if (pending_connect_viz_on_main_thread_ && application_is_foreground_) {
- BrowserMainLoop::GetInstance()
- ->gpu_channel_establish_factory()
- ->EstablishGpuChannel(std::move(pending_connect_viz_on_main_thread_));
- }
+ if (!gpu_process_host)
+ return;
+ gpu_process_host->gpu_host()->ConnectFrameSinkManager(std::move(request),
+ std::move(client));
}
void EnqueueLowEndBackgroundCleanup() {
@@ -323,18 +323,23 @@ class CompositorDependencies {
case base::android::APPLICATION_STATE_UNKNOWN:
case base::android::APPLICATION_STATE_HAS_RUNNING_ACTIVITIES:
case base::android::APPLICATION_STATE_HAS_PAUSED_ACTIVITIES:
+ if (application_is_foreground_)
+ return;
+ application_is_foreground_ = true;
GpuDataManagerImpl::GetInstance()->SetApplicationVisible(true);
+ BrowserGpuChannelHostFactorySetApplicationVisible(true);
SendOnForegroundedToGpuService();
low_end_background_cleanup_task_.Cancel();
- application_is_foreground_ = true;
- TryEstablishVizConnectionIfNeeded();
break;
case base::android::APPLICATION_STATE_HAS_STOPPED_ACTIVITIES:
case base::android::APPLICATION_STATE_HAS_DESTROYED_ACTIVITIES:
+ if (!application_is_foreground_)
+ return;
+ application_is_foreground_ = false;
GpuDataManagerImpl::GetInstance()->SetApplicationVisible(false);
+ BrowserGpuChannelHostFactorySetApplicationVisible(false);
SendOnBackgroundedToGpuService();
EnqueueLowEndBackgroundCleanup();
- application_is_foreground_ = false;
}
}
@@ -343,9 +348,11 @@ class CompositorDependencies {
base::CancelableOnceClosure low_end_background_cleanup_task_;
// An instance of Android AppListener.
- base::android::ApplicationStatusListener app_listener_;
+ std::unique_ptr<base::android::ApplicationStatusListener> app_listener_;
bool application_is_foreground_ = true;
- gpu::GpuChannelEstablishedCallback pending_connect_viz_on_main_thread_;
+
+ // A callback which connects to the viz service on the IO thread.
+ base::OnceClosure pending_connect_viz_on_io_thread_;
};
const unsigned int kMaxDisplaySwapBuffers = 1U;
@@ -372,28 +379,10 @@ scoped_refptr<viz::VulkanContextProvider> GetSharedVulkanContextProvider() {
gpu::SharedMemoryLimits GetCompositorContextSharedMemoryLimits(
gfx::NativeWindow window) {
- constexpr size_t kBytesPerPixel = 4;
- const gfx::Size size = display::Screen::GetScreen()
- ->GetDisplayNearestWindow(window)
- .GetSizeInPixel();
- const size_t full_screen_texture_size_in_bytes =
- size.width() * size.height() * kBytesPerPixel;
-
- gpu::SharedMemoryLimits limits;
- // This limit is meant to hold the contents of the display compositor
- // drawing the scene. See discussion here:
- // https://codereview.chromium.org/1900993002/diff/90001/content/browser/renderer_host/compositor_impl_android.cc?context=3&column_width=80&tab_spaces=8
- limits.command_buffer_size = 64 * 1024;
- // These limits are meant to hold the uploads for the browser UI without
- // any excess space.
- limits.start_transfer_buffer_size = 64 * 1024;
- limits.min_transfer_buffer_size = 64 * 1024;
- limits.max_transfer_buffer_size = full_screen_texture_size_in_bytes;
- // Texture uploads may use mapped memory so give a reasonable limit for
- // them.
- limits.mapped_memory_reclaim_limit = full_screen_texture_size_in_bytes;
-
- return limits;
+ const gfx::Size screen_size = display::Screen::GetScreen()
+ ->GetDisplayNearestWindow(window)
+ .GetSizeInPixel();
+ return gpu::SharedMemoryLimits::ForDisplayCompositor(screen_size);
}
gpu::ContextCreationAttribs GetCompositorContextAttributes(
@@ -778,7 +767,7 @@ CompositorImpl::CompositorImpl(CompositorClient* client,
needs_animate_(false),
pending_frames_(0U),
layer_tree_frame_sink_request_pending_(false),
- lock_manager_(base::ThreadTaskRunnerHandle::Get(), this),
+ lock_manager_(base::ThreadTaskRunnerHandle::Get()),
enable_surface_synchronization_(
features::IsSurfaceSynchronizationEnabled()),
enable_viz_(
@@ -924,7 +913,7 @@ void CompositorImpl::CreateLayerTreeHost() {
params.main_task_runner = base::ThreadTaskRunnerHandle::Get();
params.settings = &settings;
params.mutator_host = animation_host_.get();
- host_ = cc::LayerTreeHost::CreateSingleThreaded(this, &params);
+ host_ = cc::LayerTreeHost::CreateSingleThreaded(this, std::move(params));
DCHECK(!host_->IsVisible());
host_->SetViewportSizeAndScale(size_, root_window_->GetDipScale(),
GenerateLocalSurfaceId());
@@ -1026,9 +1015,7 @@ void CompositorImpl::SetNeedsComposite() {
host_->SetNeedsAnimate();
}
-void CompositorImpl::UpdateLayerTreeHost(VisualStateUpdate requested_update) {
- if (requested_update == VisualStateUpdate::kPrePaint)
- return;
+void CompositorImpl::UpdateLayerTreeHost() {
client_->UpdateLayerTreeHost();
if (needs_animate_) {
needs_animate_ = false;
@@ -1104,6 +1091,10 @@ bool CompositorImpl::CreateVulkanOutputSurface() {
void CompositorImpl::OnGpuChannelEstablished(
scoped_refptr<gpu::GpuChannelHost> gpu_channel_host) {
+ // At this point we know we have a valid GPU process, establish our viz
+ // connection if needed.
+ CompositorDependencies::Get().TryEstablishVizConnectionIfNeeded();
+
// We might end up queing multiple GpuChannel requests for the same
// LayerTreeFrameSink request as the visibility of the compositor changes, so
// the LayerTreeFrameSink request could have been handled already.
@@ -1149,9 +1140,9 @@ void CompositorImpl::OnGpuChannelEstablished(
requires_alpha_channel_),
ws::command_buffer_metrics::ContextType::BROWSER_COMPOSITOR);
auto result = context_provider->BindToCurrentThread();
- LOG_IF(FATAL, result == gpu::ContextResult::kFatalFailure)
- << "Fatal error making Gpu context";
if (result != gpu::ContextResult::kSuccess) {
+ if (gpu::IsFatalOrSurfaceFailure(result))
+ OnFatalOrSurfaceContextCreationFailure(result);
HandlePendingLayerTreeFrameSinkRequest();
return;
}
@@ -1192,6 +1183,10 @@ void CompositorImpl::InitializeDisplay(
renderer_settings.allow_antialiasing = false;
renderer_settings.highp_threshold_min = 2048;
renderer_settings.auto_resize_output_surface = false;
+ renderer_settings.initial_screen_size =
+ display::Screen::GetScreen()
+ ->GetDisplayNearestWindow(root_window_)
+ .GetSizeInPixel();
auto* gpu_memory_buffer_manager = BrowserMainLoop::GetInstance()
->gpu_channel_establish_factory()
->GetGpuMemoryBufferManager();
@@ -1327,7 +1322,10 @@ bool CompositorImpl::HavePendingReadbacks() {
std::unique_ptr<ui::CompositorLock> CompositorImpl::GetCompositorLock(
ui::CompositorLockClient* client,
base::TimeDelta timeout) {
- return lock_manager_.GetCompositorLock(client, timeout);
+ std::unique_ptr<cc::ScopedDeferCommits> scoped_defer_commits =
+ host_ ? host_->DeferCommits() : nullptr;
+ return lock_manager_.GetCompositorLock(client, timeout,
+ std::move(scoped_defer_commits));
}
bool CompositorImpl::IsDrawingFirstVisibleFrame() const {
@@ -1347,11 +1345,6 @@ void CompositorImpl::SetVSyncPaused(bool paused) {
display_private_->SetVSyncPaused(paused);
}
-void CompositorImpl::OnCompositorLockStateChanged(bool locked) {
- if (host_)
- host_->SetDeferCommits(locked);
-}
-
void CompositorImpl::InitializeVizLayerTreeFrameSink(
scoped_refptr<ws::ContextProviderCommandBuffer> context_provider) {
DCHECK(enable_viz_);
@@ -1372,9 +1365,12 @@ void CompositorImpl::InitializeVizLayerTreeFrameSink(
viz::mojom::CompositorFrameSinkClientRequest client_request =
mojo::MakeRequest(&root_params->compositor_frame_sink_client);
root_params->display_private = mojo::MakeRequest(&display_private_);
- display_client_ =
- std::make_unique<AndroidHostDisplayClient>(base::BindRepeating(
- &CompositorImpl::DidSwapBuffers, weak_factory_.GetWeakPtr()));
+ display_client_ = std::make_unique<AndroidHostDisplayClient>(
+ base::BindRepeating(&CompositorImpl::DidSwapBuffers,
+ weak_factory_.GetWeakPtr()),
+ base::BindRepeating(
+ &CompositorImpl::OnFatalOrSurfaceContextCreationFailure,
+ weak_factory_.GetWeakPtr()));
root_params->display_client =
display_client_->GetBoundPtr(task_runner).PassInterface();
@@ -1382,6 +1378,10 @@ void CompositorImpl::InitializeVizLayerTreeFrameSink(
renderer_settings.allow_antialiasing = false;
renderer_settings.highp_threshold_min = 2048;
renderer_settings.requires_alpha_channel = requires_alpha_channel_;
+ renderer_settings.initial_screen_size =
+ display::Screen::GetScreen()
+ ->GetDisplayNearestWindow(root_window_)
+ .GetSizeInPixel();
root_params->frame_sink_id = frame_sink_id_;
root_params->widget = surface_handle_;
root_params->gpu_compositing = true;
@@ -1403,7 +1403,9 @@ void CompositorImpl::InitializeVizLayerTreeFrameSink(
params.enable_surface_synchronization = true;
params.hit_test_data_provider =
std::make_unique<viz::HitTestDataProviderDrawQuad>(
- /*should_ask_for_child_region=*/false);
+ false /* should_ask_for_child_region */,
+ true /* root_accepts_events */);
+ params.client_name = kBrowser;
auto layer_tree_frame_sink =
std::make_unique<cc::mojo_embedder::AsyncLayerTreeFrameSink>(
std::move(context_provider), nullptr, &params);
@@ -1420,4 +1422,16 @@ viz::LocalSurfaceId CompositorImpl::GenerateLocalSurfaceId() const {
return viz::LocalSurfaceId();
}
+void CompositorImpl::OnFatalOrSurfaceContextCreationFailure(
+ gpu::ContextResult context_result) {
+ DCHECK(gpu::IsFatalOrSurfaceFailure(context_result));
+ LOG_IF(FATAL, context_result == gpu::ContextResult::kFatalFailure)
+ << "Fatal error making Gpu context";
+
+ if (context_result == gpu::ContextResult::kSurfaceFailure) {
+ SetSurface(nullptr);
+ client_->RecreateSurface();
+ }
+}
+
} // 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 465dee6734a..7190d3c5139 100644
--- a/chromium/content/browser/renderer_host/compositor_impl_android.h
+++ b/chromium/content/browser/renderer_host/compositor_impl_android.h
@@ -66,7 +66,6 @@ class CONTENT_EXPORT CompositorImpl
: public Compositor,
public cc::LayerTreeHostClient,
public cc::LayerTreeHostSingleThreadClient,
- public ui::CompositorLockManagerClient,
public ui::UIResourceProvider,
public ui::WindowAndroidCompositor,
public viz::HostFrameSinkClient,
@@ -112,12 +111,9 @@ class CONTENT_EXPORT CompositorImpl
void BeginMainFrame(const viz::BeginFrameArgs& args) override {}
void BeginMainFrameNotExpectedSoon() override {}
void BeginMainFrameNotExpectedUntil(base::TimeTicks time) override {}
- void UpdateLayerTreeHost(VisualStateUpdate requested_update) override;
- void ApplyViewportDeltas(const gfx::Vector2dF& inner_delta,
- const gfx::Vector2dF& outer_delta,
- const gfx::Vector2dF& elastic_overscroll_delta,
- float page_scale,
- float top_controls_delta) override {}
+ void UpdateLayerTreeHost() override;
+ void ApplyViewportChanges(const cc::ApplyViewportChangesArgs& args) override {
+ }
void RecordWheelAndTouchScrollingCount(bool has_scrolled_by_wheel,
bool has_scrolled_by_touch) override {}
void RequestNewLayerTreeFrameSink() override;
@@ -131,6 +127,7 @@ class CONTENT_EXPORT CompositorImpl
void DidPresentCompositorFrame(
uint32_t frame_token,
const gfx::PresentationFeedback& feedback) override {}
+ void RecordEndOfFrameMetrics(base::TimeTicks frame_begin_time) override {}
// LayerTreeHostSingleThreadClient implementation.
void DidSubmitCompositorFrame() override;
@@ -159,9 +156,6 @@ class CONTENT_EXPORT CompositorImpl
void OnDisplayMetricsChanged(const display::Display& display,
uint32_t changed_metrics) override;
- // ui::CompositorLockManagerClient implementation.
- void OnCompositorLockStateChanged(bool locked) override;
-
void SetVisible(bool visible);
void CreateLayerTreeHost();
@@ -197,6 +191,10 @@ class CONTENT_EXPORT CompositorImpl
// Registers the root frame sink ID.
void RegisterRootFrameSink();
+ // Called when we fail to create the context for the root frame sink.
+ void OnFatalOrSurfaceContextCreationFailure(
+ gpu::ContextResult context_result);
+
// Viz specific functions:
void InitializeVizLayerTreeFrameSink(
scoped_refptr<ws::ContextProviderCommandBuffer> context_provider);
diff --git a/chromium/content/browser/renderer_host/compositor_impl_android_browsertest.cc b/chromium/content/browser/renderer_host/compositor_impl_android_browsertest.cc
index 207c42dd823..e2b2f8a6159 100644
--- a/chromium/content/browser/renderer_host/compositor_impl_android_browsertest.cc
+++ b/chromium/content/browser/renderer_host/compositor_impl_android_browsertest.cc
@@ -11,8 +11,8 @@
#include "content/browser/renderer_host/compositor_impl_android.h"
#include "content/browser/renderer_host/render_widget_host_view_android.h"
#include "content/browser/web_contents/web_contents_impl.h"
-#include "content/common/gpu_stream_constants.h"
#include "content/public/common/content_switches.h"
+#include "content/public/common/gpu_stream_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"
diff --git a/chromium/content/browser/renderer_host/delegated_frame_host.cc b/chromium/content/browser/renderer_host/delegated_frame_host.cc
index 995ba36a5e1..36f068e3361 100644
--- a/chromium/content/browser/renderer_host/delegated_frame_host.cc
+++ b/chromium/content/browser/renderer_host/delegated_frame_host.cc
@@ -45,7 +45,8 @@ DelegatedFrameHost::DelegatedFrameHost(const viz::FrameSinkId& frame_sink_id,
base::FeatureList::IsEnabled(features::kVizDisplayCompositor)),
should_register_frame_sink_id_(should_register_frame_sink_id),
host_frame_sink_manager_(GetHostFrameSinkManager()),
- frame_evictor_(std::make_unique<viz::FrameEvictor>(this)) {
+ frame_evictor_(std::make_unique<viz::FrameEvictor>(this)),
+ weak_factory_(this) {
ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
factory->GetContextFactory()->AddObserver(this);
DCHECK(host_frame_sink_manager_);
@@ -95,6 +96,8 @@ void DelegatedFrameHost::CopyFromCompositingSurface(
const gfx::Rect& src_subrect,
const gfx::Size& output_size,
base::OnceCallback<void(const SkBitmap&)> callback) {
+ DCHECK(CanCopyFromCompositingSurface());
+
std::unique_ptr<viz::CopyOutputRequest> request =
std::make_unique<viz::CopyOutputRequest>(
viz::CopyOutputRequest::ResultFormat::RGBA_BITMAP,
@@ -110,23 +113,11 @@ void DelegatedFrameHost::CopyFromCompositingSurface(
if (!output_size.IsEmpty())
request->set_result_selection(gfx::Rect(output_size));
- // If there is enough information to populate the copy output request fields,
- // then process it now. Otherwise, wait until the information becomes
- // available.
- if (CanCopyFromCompositingSurface() &&
- active_local_surface_id_ == pending_local_surface_id_)
- ProcessCopyOutputRequest(std::move(request));
- else
- pending_first_frame_requests_.push_back(std::move(request));
-}
-
-void DelegatedFrameHost::ProcessCopyOutputRequest(
- std::unique_ptr<viz::CopyOutputRequest> request) {
if (!request->has_area())
request->set_area(gfx::Rect(pending_surface_dip_size_));
- request->set_area(
- gfx::ScaleToRoundedRect(request->area(), active_device_scale_factor_));
+ request->set_area(gfx::ScaleToRoundedRect(request->area(),
+ client_->GetDeviceScaleFactor()));
if (request->has_result_selection()) {
const gfx::Rect& area = request->area();
@@ -148,7 +139,7 @@ void DelegatedFrameHost::ProcessCopyOutputRequest(
}
bool DelegatedFrameHost::CanCopyFromCompositingSurface() const {
- return HasFallbackSurface() && active_device_scale_factor_ != 0.f;
+ return pending_local_surface_id_.is_valid();
}
bool DelegatedFrameHost::TransformPointToLocalCoordSpaceLegacy(
@@ -219,15 +210,18 @@ void DelegatedFrameHost::EmbedSurface(
pending_local_surface_id_ = new_pending_local_surface_id;
pending_surface_dip_size_ = new_pending_dip_size;
+ viz::SurfaceId new_primary_surface_id(frame_sink_id_,
+ pending_local_surface_id_);
+
if (!client_->DelegatedFrameHostIsVisible()) {
- // If the tab is resized while hidden, reset the fallback so that the next
+ // If the tab is resized while hidden, advance 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()) {
+ HasPrimarySurface()) {
client_->DelegatedFrameHostGetLayer()->SetFallbackSurfaceId(
- viz::SurfaceId());
+ new_primary_surface_id);
}
// Don't update the SurfaceLayer when invisible to avoid blocking on
// renderers that do not submit CompositorFrames. Next time the renderer
@@ -237,7 +231,6 @@ void DelegatedFrameHost::EmbedSurface(
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
@@ -254,7 +247,7 @@ void DelegatedFrameHost::EmbedSurface(
#endif
current_frame_size_in_dip_ = pending_surface_dip_size_;
client_->DelegatedFrameHostGetLayer()->SetShowPrimarySurface(
- surface_id, current_frame_size_in_dip_, GetGutterColor(),
+ new_primary_surface_id, current_frame_size_in_dip_, GetGutterColor(),
deadline_policy, false /* stretch_content_to_fill_bounds */);
if (compositor_ && !base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableResizeLock)) {
@@ -319,33 +312,13 @@ void DelegatedFrameHost::OnBeginFramePausedChanged(bool paused) {
void DelegatedFrameHost::OnFirstSurfaceActivation(
const viz::SurfaceInfo& surface_info) {
- // 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()) {
- DCHECK(host_frame_sink_manager_);
- host_frame_sink_manager_->DropTemporaryReference(surface_info.id());
- return;
- }
-
- client_->DelegatedFrameHostGetLayer()->SetFallbackSurfaceId(
- surface_info.id());
active_local_surface_id_ = surface_info.id().local_surface_id();
- active_device_scale_factor_ = surface_info.device_scale_factor();
// This is used by macOS' unique resize path.
client_->OnFirstSurfaceActivation(surface_info);
frame_evictor_->SwappedFrame(client_->DelegatedFrameHostIsVisible());
// Note: the frame may have been evicted immediately.
-
- if (!pending_first_frame_requests_.empty()) {
- DCHECK(CanCopyFromCompositingSurface());
- for (auto& request : pending_first_frame_requests_)
- ProcessCopyOutputRequest(std::move(request));
- pending_first_frame_requests_.clear();
- }
}
void DelegatedFrameHost::OnFrameTokenChanged(uint32_t frame_token) {
@@ -359,18 +332,27 @@ void DelegatedFrameHost::OnBeginFrame(const viz::BeginFrameArgs& args) {
}
void DelegatedFrameHost::ResetFallbackToFirstNavigationSurface() {
- if (HasFallbackSurface()) {
- client_->DelegatedFrameHostGetLayer()->SetFallbackSurfaceId(viz::SurfaceId(
- frame_sink_id_, first_local_surface_id_after_navigation_));
+ if (!HasPrimarySurface())
+ return;
+
+ const viz::SurfaceId* fallback_surface_id =
+ client_->DelegatedFrameHostGetLayer()->GetFallbackSurfaceId();
+
+ // Don't update the fallback if it's already newer than the first id after
+ // navigation.
+ if (fallback_surface_id &&
+ fallback_surface_id->frame_sink_id() == frame_sink_id_ &&
+ fallback_surface_id->local_surface_id().IsSameOrNewerThan(
+ first_local_surface_id_after_navigation_)) {
+ return;
}
+
+ client_->DelegatedFrameHostGetLayer()->SetFallbackSurfaceId(
+ viz::SurfaceId(frame_sink_id_, first_local_surface_id_after_navigation_));
}
void DelegatedFrameHost::EvictDelegatedFrame() {
- // Reset fallback and primary surfaces.
- if (HasFallbackSurface()) {
- client_->DelegatedFrameHostGetLayer()->SetFallbackSurfaceId(
- viz::SurfaceId());
- }
+ // Reset primary surface.
if (HasPrimarySurface()) {
client_->DelegatedFrameHostGetLayer()->SetShowPrimarySurface(
viz::SurfaceId(), current_frame_size_in_dip_, GetGutterColor(),
@@ -411,14 +393,6 @@ void DelegatedFrameHost::OnCompositingShuttingDown(ui::Compositor* compositor) {
void DelegatedFrameHost::OnLostSharedContext() {}
void DelegatedFrameHost::OnLostVizProcess() {
- // With OOP-D renderer surface was destroyed if the GPU process crashed. Reset
- // the fallback Surface but leave the primary so we embed the renderer surface
- // again.
- if (HasFallbackSurface()) {
- client_->DelegatedFrameHostGetLayer()->SetFallbackSurfaceId(
- viz::SurfaceId());
- }
-
if (HasSavedFrame())
frame_evictor_->DiscardedFrame();
}
@@ -482,7 +456,6 @@ void DelegatedFrameHost::ResetCompositorFrameSinkSupport() {
void DelegatedFrameHost::DidNavigate() {
first_local_surface_id_after_navigation_ = pending_local_surface_id_;
- received_frame_after_navigation_ = false;
}
bool DelegatedFrameHost::IsPrimarySurfaceEvicted() const {
@@ -496,20 +469,45 @@ void DelegatedFrameHost::WindowTitleChanged(const std::string& title) {
}
void DelegatedFrameHost::TakeFallbackContentFrom(DelegatedFrameHost* other) {
- if (!other->HasFallbackSurface() || HasFallbackSurface())
+ // If the other view is not showing anything, we can't obtain a fallback.
+ if (!other->HasPrimarySurface())
+ return;
+
+ // This method should not overwrite the existing fallback. This method is only
+ // supposed to be called when the view was just created and there is no
+ // existing fallback.
+ if (HasFallbackSurface())
return;
+ const viz::SurfaceId* other_primary =
+ other->client_->DelegatedFrameHostGetLayer()->GetPrimarySurfaceId();
+
+ const viz::SurfaceId* other_fallback =
+ other->client_->DelegatedFrameHostGetLayer()->GetFallbackSurfaceId();
+
+ // In two cases we need to obtain a new fallback from the primary id of the
+ // other view instead of using its fallback:
+ // - When the other view has no fallback,
+ // - When a fallback exists but has a different FrameSinkId or embed token
+ // than the primary. If we use the fallback, then the resulting SurfaceRange
+ // in this view will not cover any surface with the FrameSinkId / embed token
+ // of the old view's primary.
+ viz::SurfaceId desired_fallback;
+ if (!other_fallback || !other_primary->IsSameOrNewerThan(*other_fallback)) {
+ desired_fallback = other_primary->ToSmallestId();
+ } else {
+ desired_fallback = *other_fallback;
+ }
+
if (!HasPrimarySurface()) {
client_->DelegatedFrameHostGetLayer()->SetShowPrimarySurface(
- *other->client_->DelegatedFrameHostGetLayer()->GetFallbackSurfaceId(),
- other->client_->DelegatedFrameHostGetLayer()->size(),
+ desired_fallback, other->client_->DelegatedFrameHostGetLayer()->size(),
other->client_->DelegatedFrameHostGetLayer()->background_color(),
cc::DeadlinePolicy::UseDefaultDeadline(),
false /* stretch_content_to_fill_bounds */);
}
- client_->DelegatedFrameHostGetLayer()->SetFallbackSurfaceId(
- *other->client_->DelegatedFrameHostGetLayer()->GetFallbackSurfaceId());
+ client_->DelegatedFrameHostGetLayer()->SetFallbackSurfaceId(desired_fallback);
}
} // 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 b223d4708b3..b5492e018ec 100644
--- a/chromium/content/browser/renderer_host/delegated_frame_host.h
+++ b/chromium/content/browser/renderer_host/delegated_frame_host.h
@@ -10,6 +10,7 @@
#include <vector>
#include "base/gtest_prod_util.h"
+#include "base/memory/weak_ptr.h"
#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"
@@ -43,14 +44,13 @@ class CONTENT_EXPORT DelegatedFrameHostClient {
virtual ui::Layer* DelegatedFrameHostGetLayer() const = 0;
virtual bool DelegatedFrameHostIsVisible() const = 0;
-
// Returns the color that the resize gutters should be drawn with.
virtual SkColor DelegatedFrameHostGetGutterColor() const = 0;
-
virtual void OnFirstSurfaceActivation(
const viz::SurfaceInfo& surface_info) = 0;
virtual void OnBeginFrame(base::TimeTicks frame_time) = 0;
virtual void OnFrameTokenChanged(uint32_t frame_token) = 0;
+ virtual float GetDeviceScaleFactor() const = 0;
};
// The DelegatedFrameHost is used to host all of the RenderWidgetHostView state
@@ -179,6 +179,10 @@ class CONTENT_EXPORT DelegatedFrameHost
// |other|.
void TakeFallbackContentFrom(DelegatedFrameHost* other);
+ base::WeakPtr<DelegatedFrameHost> GetWeakPtr() {
+ return weak_factory_.GetWeakPtr();
+ }
+
private:
friend class DelegatedFrameHostClient;
FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest,
@@ -194,9 +198,6 @@ class CONTENT_EXPORT DelegatedFrameHost
void CreateCompositorFrameSinkSupport();
void ResetCompositorFrameSinkSupport();
- void ProcessCopyOutputRequest(
- std::unique_ptr<viz::CopyOutputRequest> request);
-
const viz::FrameSinkId frame_sink_id_;
DelegatedFrameHostClient* const client_;
const bool enable_viz_;
@@ -206,8 +207,6 @@ class CONTENT_EXPORT DelegatedFrameHost
// The surface id that was most recently activated by
// OnFirstSurfaceActivation.
viz::LocalSurfaceId active_local_surface_id_;
- // 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
// EmbedSurface or WasShown. This is the surface that we expect
@@ -238,10 +237,8 @@ class CONTENT_EXPORT DelegatedFrameHost
std::unique_ptr<viz::FrameEvictor> frame_evictor_;
viz::LocalSurfaceId first_local_surface_id_after_navigation_;
- bool received_frame_after_navigation_ = false;
- std::vector<std::unique_ptr<viz::CopyOutputRequest>>
- pending_first_frame_requests_;
+ base::WeakPtrFactory<DelegatedFrameHost> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(DelegatedFrameHost);
};
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 b3dc666da0f..f1714b9fd2d 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
@@ -54,4 +54,8 @@ void DelegatedFrameHostClientAura::OnFrameTokenChanged(uint32_t frame_token) {
render_widget_host_view_->OnFrameTokenChangedForView(frame_token);
}
+float DelegatedFrameHostClientAura::GetDeviceScaleFactor() const {
+ return render_widget_host_view_->device_scale_factor_;
+}
+
} // namespace content
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 3df3bbb637d..30858853177 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
@@ -33,6 +33,7 @@ class CONTENT_EXPORT DelegatedFrameHostClientAura
void OnFirstSurfaceActivation(const viz::SurfaceInfo& surface_info) override;
void OnBeginFrame(base::TimeTicks frame_time) override;
void OnFrameTokenChanged(uint32_t frame_token) override;
+ float GetDeviceScaleFactor() const override;
private:
RenderWidgetHostViewAura* render_widget_host_view_;
diff --git a/chromium/content/browser/renderer_host/dwrite_font_proxy_message_filter_win_unittest.cc b/chromium/content/browser/renderer_host/dwrite_font_proxy_message_filter_win_unittest.cc
index 78db7022f9c..c06c66a2b6b 100644
--- a/chromium/content/browser/renderer_host/dwrite_font_proxy_message_filter_win_unittest.cc
+++ b/chromium/content/browser/renderer_host/dwrite_font_proxy_message_filter_win_unittest.cc
@@ -19,9 +19,7 @@
#include "mojo/public/cpp/bindings/binding.h"
#include "services/service_manager/public/cpp/bind_source_info.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/gfx/win/direct_write.h"
-
-namespace mswr = Microsoft::WRL;
+#include "third_party/blink/public/common/dwrite_rasterizer_support/dwrite_rasterizer_support.h"
namespace content {
@@ -32,18 +30,6 @@ class DWriteFontProxyImplUnitTest : public testing::Test {
DWriteFontProxyImplUnitTest()
: binding_(&impl_, mojo::MakeRequest(&dwrite_font_proxy_)) {}
- bool IsDWrite2Available() {
- mswr::ComPtr<IDWriteFactory> factory;
- gfx::win::CreateDWriteFactory(&factory);
- mswr::ComPtr<IDWriteFactory2> factory2;
- factory.As<IDWriteFactory2>(&factory2);
-
- if (!factory2.Get()) {
- // IDWriteFactory2 is expected to not be available before Win8.1
- EXPECT_LT(base::win::GetVersion(), base::win::VERSION_WIN8_1);
- }
- return factory2.Get();
- }
mojom::DWriteFontProxy& dwrite_font_proxy() { return *dwrite_font_proxy_; }
base::test::ScopedTaskEnvironment scoped_task_environment_;
@@ -119,7 +105,7 @@ TEST_F(DWriteFontProxyImplUnitTest, GetFontFilesIndexOutOfBounds) {
}
TEST_F(DWriteFontProxyImplUnitTest, MapCharacter) {
- if (!IsDWrite2Available())
+ if (!blink::DWriteRasterizerSupport::IsDWriteFactory2Available())
return;
mojom::MapCharactersResultPtr result;
@@ -140,7 +126,7 @@ TEST_F(DWriteFontProxyImplUnitTest, MapCharacter) {
}
TEST_F(DWriteFontProxyImplUnitTest, MapCharacterInvalidCharacter) {
- if (!IsDWrite2Available())
+ if (!blink::DWriteRasterizerSupport::IsDWriteFactory2Available())
return;
mojom::MapCharactersResultPtr result;
@@ -157,7 +143,7 @@ TEST_F(DWriteFontProxyImplUnitTest, MapCharacterInvalidCharacter) {
}
TEST_F(DWriteFontProxyImplUnitTest, MapCharacterInvalidAfterValid) {
- if (!IsDWrite2Available())
+ if (!blink::DWriteRasterizerSupport::IsDWriteFactory2Available())
return;
mojom::MapCharactersResultPtr result;
diff --git a/chromium/content/browser/renderer_host/embedded_frame_sink_provider_impl_unittest.cc b/chromium/content/browser/renderer_host/embedded_frame_sink_provider_impl_unittest.cc
index 71073a5ff02..045779e38bd 100644
--- a/chromium/content/browser/renderer_host/embedded_frame_sink_provider_impl_unittest.cc
+++ b/chromium/content/browser/renderer_host/embedded_frame_sink_provider_impl_unittest.cc
@@ -8,8 +8,8 @@
#include <utility>
#include <vector>
-#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
+#include "base/test/scoped_task_environment.h"
#include "build/build_config.h"
#include "components/viz/common/quads/compositor_frame.h"
#include "components/viz/host/host_frame_sink_manager.h"
@@ -141,7 +141,7 @@ class EmbeddedFrameSinkProviderImplTest : public testing::Test {
private:
// A MessageLoop is required for mojo bindings which are used to
// connect to graphics services.
- base::MessageLoop message_loop_;
+ base::test::ScopedTaskEnvironment task_environment_;
viz::ServerSharedBitmapManager shared_bitmap_manager_;
viz::FakeHostFrameSinkClient host_frame_sink_client_;
std::unique_ptr<viz::HostFrameSinkManager> host_frame_sink_manager_;
diff --git a/chromium/content/browser/renderer_host/hit_test_debug_key_event_observer.cc b/chromium/content/browser/renderer_host/hit_test_debug_key_event_observer.cc
new file mode 100644
index 00000000000..ee542014434
--- /dev/null
+++ b/chromium/content/browser/renderer_host/hit_test_debug_key_event_observer.cc
@@ -0,0 +1,76 @@
+// 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/hit_test_debug_key_event_observer.h"
+
+#include "components/viz/common/hit_test/hit_test_region_list.h"
+#include "components/viz/host/host_frame_sink_manager.h"
+#include "content/browser/compositor/surface_utils.h"
+#include "content/browser/renderer_host/render_widget_host_impl.h"
+#include "content/browser/renderer_host/render_widget_host_view_base.h"
+#include "ui/events/keycodes/keyboard_codes.h"
+
+typedef blink::WebInputEvent::Type Type;
+typedef blink::WebInputEvent::Modifiers Modifiers;
+
+namespace {
+
+viz::HitTestQuery* GetHitTestQuery(
+ viz::HostFrameSinkManager* host_frame_sink_manager,
+ const viz::FrameSinkId& frame_sink_id) {
+ 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);
+ if (iter == display_hit_test_query_map.end())
+ return nullptr;
+ return iter->second.get();
+}
+
+} // namespace
+
+namespace content {
+
+HitTestDebugKeyEventObserver::HitTestDebugKeyEventObserver(
+ RenderWidgetHostImpl* host)
+ : host_(host), hit_test_query_(nullptr) {
+ host_->AddInputEventObserver(this);
+}
+
+HitTestDebugKeyEventObserver::~HitTestDebugKeyEventObserver() {
+ host_->RemoveInputEventObserver(this);
+}
+
+void HitTestDebugKeyEventObserver::OnInputEventAck(
+ InputEventAckSource source,
+ InputEventAckState state,
+ const blink::WebInputEvent& event) {
+ if (INPUT_EVENT_ACK_STATE_CONSUMED == state ||
+ (event.GetType() != Type::kRawKeyDown &&
+ event.GetType() != Type::kKeyDown)) {
+ return;
+ }
+
+ const blink::WebKeyboardEvent& key_event =
+ static_cast<const blink::WebKeyboardEvent&>(event);
+
+ if (key_event.windows_key_code != ui::VKEY_H ||
+ key_event.GetModifiers() !=
+ (Modifiers::kControlKey | Modifiers::kShiftKey)) {
+ return;
+ }
+
+ if (!hit_test_query_) {
+ hit_test_query_ = GetHitTestQuery(GetHostFrameSinkManager(),
+ host_->GetView()->GetRootFrameSinkId());
+ }
+ if (hit_test_query_) {
+ std::string printed_hit_test_data = hit_test_query_->PrintHitTestData();
+ VLOG(1) << (printed_hit_test_data.empty() ? "No hit-test data."
+ : printed_hit_test_data);
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/hit_test_debug_key_event_observer.h b/chromium/content/browser/renderer_host/hit_test_debug_key_event_observer.h
new file mode 100644
index 00000000000..90e20efba0d
--- /dev/null
+++ b/chromium/content/browser/renderer_host/hit_test_debug_key_event_observer.h
@@ -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.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_HIT_TEST_DEBUG_KEY_EVENT_OBSERVER_H_
+#define CONTENT_BROWSER_RENDERER_HOST_HIT_TEST_DEBUG_KEY_EVENT_OBSERVER_H_
+
+#include "content/public/browser/render_widget_host.h"
+
+namespace viz {
+
+class HitTestQuery;
+
+} // namespace viz
+
+namespace content {
+
+class RenderWidgetHostImpl;
+
+// Implements the RenderWidgetHost::InputEventObserver interface, and acts on
+// keyboard input events to print hit-test data.
+class HitTestDebugKeyEventObserver
+ : public RenderWidgetHost::InputEventObserver {
+ public:
+ explicit HitTestDebugKeyEventObserver(RenderWidgetHostImpl* host);
+ ~HitTestDebugKeyEventObserver() override;
+
+ // RenderWidgetHost::InputEventObserver:
+ void OnInputEventAck(InputEventAckSource source,
+ InputEventAckState state,
+ const blink::WebInputEvent&) override;
+
+ private:
+ RenderWidgetHostImpl* host_;
+ viz::HitTestQuery* hit_test_query_;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_HIT_TEST_DEBUG_KEY_EVENT_OBSERVER_H_
diff --git a/chromium/content/browser/renderer_host/input/OWNERS b/chromium/content/browser/renderer_host/input/OWNERS
index 86bfa17ec3d..e6d74ae941f 100644
--- a/chromium/content/browser/renderer_host/input/OWNERS
+++ b/chromium/content/browser/renderer_host/input/OWNERS
@@ -1,5 +1,6 @@
dtapuska@chromium.org
tdresser@chromium.org
+nzolghadr@chromium.org
# TEAM: input-dev@chromium.org
diff --git a/chromium/content/browser/renderer_host/input/autoscroll_browsertest.cc b/chromium/content/browser/renderer_host/input/autoscroll_browsertest.cc
index 0b662c1fd05..731d4cca767 100644
--- a/chromium/content/browser/renderer_host/input/autoscroll_browsertest.cc
+++ b/chromium/content/browser/renderer_host/input/autoscroll_browsertest.cc
@@ -33,6 +33,52 @@ const std::string kAutoscrollDataURL = R"HTML(
namespace content {
+// Waits for a GSB ack and checks that the acked event has none zero scroll
+// delta hints.
+class GestureScrollBeginWatcher : public RenderWidgetHost::InputEventObserver {
+ public:
+ GestureScrollBeginWatcher(RenderWidgetHost* rwh)
+ : rwh_(static_cast<RenderWidgetHostImpl*>(rwh)->GetWeakPtr()) {
+ rwh->AddInputEventObserver(this);
+ Reset();
+ }
+ ~GestureScrollBeginWatcher() override {
+ if (rwh_)
+ rwh_->RemoveInputEventObserver(this);
+ }
+
+ void OnInputEventAck(InputEventAckSource,
+ InputEventAckState,
+ const blink::WebInputEvent& event) override {
+ if (event.GetType() == blink::WebInputEvent::kGestureScrollBegin) {
+ blink::WebGestureEvent received_begin =
+ *static_cast<const blink::WebGestureEvent*>(&event);
+ DCHECK(received_begin.data.scroll_begin.delta_x_hint ||
+ received_begin.data.scroll_begin.delta_y_hint);
+ if (run_loop_)
+ run_loop_->Quit();
+ gesture_scroll_begin_seen_ = true;
+ }
+ }
+
+ void Wait() {
+ if (gesture_scroll_begin_seen_)
+ return;
+ DCHECK(run_loop_);
+ run_loop_->Run();
+ }
+
+ void Reset() {
+ gesture_scroll_begin_seen_ = false;
+ run_loop_ = std::make_unique<base::RunLoop>();
+ }
+
+ private:
+ base::WeakPtr<RenderWidgetHostImpl> rwh_;
+ std::unique_ptr<base::RunLoop> run_loop_;
+ bool gesture_scroll_begin_seen_;
+};
+
class AutoscrollBrowserTest : public ContentBrowserTest {
public:
AutoscrollBrowserTest() {}
@@ -82,60 +128,75 @@ class AutoscrollBrowserTest : public ContentBrowserTest {
GetWidgetHost()->ForwardMouseEvent(up_event);
}
+ void WaitForScroll(RenderFrameSubmissionObserver& observer) {
+ gfx::Vector2dF default_scroll_offset;
+ while (observer.LastRenderFrameMetadata()
+ .root_scroll_offset.value_or(default_scroll_offset)
+ .y() <= 0) {
+ observer.WaitForMetadataChange();
+ }
+ }
+
private:
DISALLOW_COPY_AND_ASSIGN(AutoscrollBrowserTest);
};
+// We don't plan on supporting middle click autoscroll on Android.
+// See https://crbug.com/686223
+#if !defined(OS_ANDROID)
// TODO(sahel): This test is flaky https://crbug.com/838769
IN_PROC_BROWSER_TEST_F(AutoscrollBrowserTest, DISABLED_AutoscrollFling) {
LoadURL(kAutoscrollDataURL);
// Start autoscroll with middle click.
- auto input_msg_watcher = std::make_unique<InputMsgWatcher>(
- GetWidgetHost(), blink::WebInputEvent::kGestureScrollBegin);
+ auto scroll_begin_watcher =
+ std::make_unique<GestureScrollBeginWatcher>(GetWidgetHost());
SimulateMiddleClick(10, 10, blink::WebInputEvent::kNoModifiers);
- input_msg_watcher->WaitForAck();
// The page should start scrolling with mouse move.
RenderFrameSubmissionObserver observer(
GetWidgetHost()->render_frame_metadata_provider());
blink::WebMouseEvent move_event = SyntheticWebMouseEventBuilder::Build(
- blink::WebInputEvent::kMouseMove, 30, 30,
+ blink::WebInputEvent::kMouseMove, 50, 50,
blink::WebInputEvent::kNoModifiers);
move_event.SetTimeStamp(ui::EventTimeForNow());
- move_event.SetPositionInScreen(30, 30);
+ move_event.SetPositionInScreen(50, 50);
GetWidgetHost()->ForwardMouseEvent(move_event);
- gfx::Vector2dF default_scroll_offset;
- while (observer.LastRenderFrameMetadata()
- .root_scroll_offset.value_or(default_scroll_offset)
- .y() <= 0) {
- observer.WaitForMetadataChange();
- }
+ scroll_begin_watcher->Wait();
+ WaitForScroll(observer);
+}
+
+// Tests that the GSB sent in the beginning of a middle click autoscroll has
+// none-zero delta hints.
+IN_PROC_BROWSER_TEST_F(AutoscrollBrowserTest, AutoscrollFlingGSBDeltaHints) {
+ LoadURL(kAutoscrollDataURL);
+
+ // Start autoscroll with middle click.
+ auto scroll_begin_watcher =
+ std::make_unique<GestureScrollBeginWatcher>(GetWidgetHost());
+ SimulateMiddleClick(10, 10, blink::WebInputEvent::kNoModifiers);
+
+ // A GSB will be sent on first mouse move.
+ blink::WebMouseEvent move_event = SyntheticWebMouseEventBuilder::Build(
+ blink::WebInputEvent::kMouseMove, 50, 50,
+ blink::WebInputEvent::kNoModifiers);
+ move_event.SetTimeStamp(ui::EventTimeForNow());
+ move_event.SetPositionInScreen(50, 50);
+ GetWidgetHost()->ForwardMouseEvent(move_event);
+ // The test crashes if the received GSB has zero delta hints.
+ scroll_begin_watcher->Wait();
}
-#if !defined(OS_ANDROID)
-#define MAYBE_WheelScrollingWorksAfterAutoscrollCancel \
- WheelScrollingWorksAfterAutoscrollCancel
-#else
-#define MAYBE_WheelScrollingWorksAfterAutoscrollCancel \
- DISABLED_WheelScrollingWorksAfterAutoscrollCancel
-#endif
// Checks that wheel scrolling works after autoscroll cancelation.
IN_PROC_BROWSER_TEST_F(AutoscrollBrowserTest,
- MAYBE_WheelScrollingWorksAfterAutoscrollCancel) {
+ WheelScrollingWorksAfterAutoscrollCancel) {
LoadURL(kAutoscrollDataURL);
// Start autoscroll with middle click.
- auto input_msg_watcher = std::make_unique<InputMsgWatcher>(
- GetWidgetHost(), blink::WebInputEvent::kGestureScrollBegin);
SimulateMiddleClick(10, 10, blink::WebInputEvent::kNoModifiers);
- input_msg_watcher->WaitForAck();
// Without moving the mouse cancel the autoscroll fling with another click.
- input_msg_watcher = std::make_unique<InputMsgWatcher>(
- GetWidgetHost(), blink::WebInputEvent::kGestureScrollEnd);
SimulateMiddleClick(10, 10, blink::WebInputEvent::kNoModifiers);
- input_msg_watcher->WaitForAck();
// The mouse wheel scrolling must work after autoscroll cancellation.
RenderFrameSubmissionObserver observer(
@@ -144,12 +205,52 @@ IN_PROC_BROWSER_TEST_F(AutoscrollBrowserTest,
SyntheticWebMouseWheelEventBuilder::Build(10, 10, 0, -53, 0, true);
wheel_event.phase = blink::WebMouseWheelEvent::kPhaseBegan;
GetWidgetHost()->ForwardWheelEvent(wheel_event);
- gfx::Vector2dF default_scroll_offset;
- while (observer.LastRenderFrameMetadata()
- .root_scroll_offset.value_or(default_scroll_offset)
- .y() <= 0) {
- observer.WaitForMetadataChange();
- }
+ WaitForScroll(observer);
+}
+
+// Checks that autoscrolling still works after changing the scroll direction
+// when the element is fully scrolled.
+IN_PROC_BROWSER_TEST_F(AutoscrollBrowserTest,
+ AutoscrollDirectionChangeAfterFullyScrolled) {
+ LoadURL(kAutoscrollDataURL);
+
+ // Start autoscroll with middle click.
+ auto scroll_begin_watcher =
+ std::make_unique<GestureScrollBeginWatcher>(GetWidgetHost());
+ SimulateMiddleClick(100, 100, blink::WebInputEvent::kNoModifiers);
+
+ // Move the mouse up, no scrolling happens since the page is at its extent.
+ auto scroll_update_watcher = std::make_unique<InputMsgWatcher>(
+ GetWidgetHost(), blink::WebInputEvent::kGestureScrollUpdate);
+ blink::WebMouseEvent move_up = SyntheticWebMouseEventBuilder::Build(
+ blink::WebInputEvent::kMouseMove, 20, 20,
+ blink::WebInputEvent::kNoModifiers);
+ move_up.SetTimeStamp(ui::EventTimeForNow());
+ move_up.SetPositionInScreen(20, 20);
+ GetWidgetHost()->ForwardMouseEvent(move_up);
+ scroll_begin_watcher->Wait();
+ EXPECT_EQ(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS,
+ scroll_update_watcher->WaitForAck());
+
+ // Wait for 300ms before changing the scroll direction.
+ base::RunLoop run_loop;
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE, run_loop.QuitClosure(),
+ base::TimeDelta::FromMillisecondsD(300));
+ run_loop.Run();
+
+ // Now move the mouse down and wait for the page to scroll. The test will
+ // timeout if autoscrolling does not work after direction change.
+ RenderFrameSubmissionObserver observer(
+ GetWidgetHost()->render_frame_metadata_provider());
+ blink::WebMouseEvent move_down = SyntheticWebMouseEventBuilder::Build(
+ blink::WebInputEvent::kMouseMove, 180, 180,
+ blink::WebInputEvent::kNoModifiers);
+ move_down.SetTimeStamp(ui::EventTimeForNow());
+ move_down.SetPositionInScreen(180, 180);
+ GetWidgetHost()->ForwardMouseEvent(move_down);
+ WaitForScroll(observer);
}
+#endif // !defined(OS_ANDROID)
} // namespace content
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 835b21e194f..dda80454bdd 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
@@ -13,6 +13,7 @@
#include "build/build_config.h"
#include "content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.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"
@@ -245,12 +246,17 @@ IN_PROC_BROWSER_TEST_F(CompositorEventAckBrowserTest,
MAYBE_TouchStartDuringFling) {
LoadURL(kBlockingTouchStartDataURL);
+ // Send the touch events via routing since they need to be registered by the
+ // TouchEventAckQueue.
+ auto* root_view = GetWidgetHost()->GetView();
+ auto* input_event_router = GetWidgetHost()->delegate()->GetInputEventRouter();
+
// Send a TouchStart so that we can set allowed touch action to Auto.
SyntheticWebTouchEvent touch_event;
touch_event.PressPoint(50, 50);
touch_event.SetTimeStamp(ui::EventTimeForNow());
- GetWidgetHost()->ForwardTouchEventWithLatencyInfo(touch_event,
- ui::LatencyInfo());
+ input_event_router->RouteTouchEvent(root_view, &touch_event,
+ ui::LatencyInfo());
GetWidgetHost()->input_router()->OnSetTouchAction(cc::kTouchActionAuto);
// Send GSB to start scrolling sequence.
@@ -282,8 +288,12 @@ IN_PROC_BROWSER_TEST_F(CompositorEventAckBrowserTest,
observer.WaitForMetadataChange();
touch_event.ReleasePoint(0);
- GetWidgetHost()->ForwardTouchEventWithLatencyInfo(touch_event,
- ui::LatencyInfo());
+ // TODO(wjmaclean): Figure out why we can send two touch events with the same
+ // id, and not only does it work, it fails to work if we give the second
+ // event a unique id!
+ // touch_event.unique_touch_event_id = ui::GetNextTouchEventId();
+ input_event_router->RouteTouchEvent(root_view, &touch_event,
+ ui::LatencyInfo());
touch_event.ResetPoints();
// Send a touch start event and wait for its ack. The touch start must be
@@ -294,8 +304,8 @@ IN_PROC_BROWSER_TEST_F(CompositorEventAckBrowserTest,
WebInputEvent::kTouchStart);
touch_event.PressPoint(50, 50);
touch_event.SetTimeStamp(ui::EventTimeForNow());
- GetWidgetHost()->ForwardTouchEventWithLatencyInfo(touch_event,
- ui::LatencyInfo());
+ input_event_router->RouteTouchEvent(root_view, &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 cba336b610d..14afc422dcc 100644
--- a/chromium/content/browser/renderer_host/input/fling_browsertest.cc
+++ b/chromium/content/browser/renderer_host/input/fling_browsertest.cc
@@ -204,11 +204,11 @@ class BrowserSideFlingBrowserTest : public ContentBrowserTest {
}
}
- void GiveItSomeTime() {
+ void GiveItSomeTime(int64_t time_delta_ms = 10) {
base::RunLoop run_loop;
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, run_loop.QuitClosure(),
- base::TimeDelta::FromMilliseconds(10));
+ base::TimeDelta::FromMilliseconds(time_delta_ms));
run_loop.Run();
}
@@ -250,6 +250,34 @@ IN_PROC_BROWSER_TEST_F(BrowserSideFlingBrowserTest, TouchpadFling) {
WaitForScroll();
}
+// Tests that flinging does not continue after navigating to a page that uses
+// the same renderer.
+IN_PROC_BROWSER_TEST_F(BrowserSideFlingBrowserTest,
+ FlingingStopsAfterNavigation) {
+ GURL first_url(embedded_test_server()->GetURL(
+ "b.a.com", "/scrollable_page_with_iframe.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), first_url));
+ MainThreadFrameObserver main_thread_sync1(GetWidgetHost());
+ main_thread_sync1.Wait();
+ SimulateTouchscreenFling(GetWidgetHost());
+ WaitForScroll();
+
+ // Navigate to a second page with the same domain.
+ GURL second_url(
+ embedded_test_server()->GetURL("a.com", "/scrollable_page.html"));
+ NavigateToURL(shell(), second_url);
+ MainThreadFrameObserver main_thread_sync2(GetWidgetHost());
+ main_thread_sync2.Wait();
+
+ // Wait for 100ms. Then check that the second page has not scrolled.
+ GiveItSomeTime(100);
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+ EXPECT_EQ(
+ 0, EvalJs(root->current_frame_host(), "window.scrollY").ExtractDouble());
+}
+
IN_PROC_BROWSER_TEST_F(BrowserSideFlingBrowserTest, TouchscreenFlingInOOPIF) {
LoadPageWithOOPIF();
SimulateTouchscreenFling(child_view_->host());
diff --git a/chromium/content/browser/renderer_host/input/fling_controller.cc b/chromium/content/browser/renderer_host/input/fling_controller.cc
index a82ea976947..c09268dd6f2 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/time/default_tick_clock.h"
#include "base/trace_event/trace_event.h"
#include "content/browser/renderer_host/input/gesture_event_queue.h"
#include "content/public/browser/content_browser_client.h"
@@ -54,6 +55,7 @@ FlingController::FlingController(
touchscreen_tap_suppression_controller_(
config.touchscreen_tap_suppression_config),
fling_in_progress_(false),
+ clock_(base::DefaultTickClock::GetInstance()),
weak_ptr_factory_(this) {
DCHECK(gesture_event_queue);
DCHECK(event_sender_client);
@@ -188,14 +190,13 @@ void FlingController::ProcessGestureFlingStart(
current_fling_parameters_.velocity,
current_fling_parameters_.source_device,
current_fling_parameters_.modifiers);
-
// Wait for BeginFrame to call ProgressFling when
// SetNeedsBeginFrameForFlingProgress is used to progress flings instead of
// compositor animation observer (happens on Android WebView).
if (scheduler_client_->NeedsBeginFrameForFlingProgress())
ScheduleFlingProgress();
else
- ProgressFling(base::TimeTicks::Now());
+ ProgressFling(clock_->NowTicks());
}
void FlingController::ScheduleFlingProgress() {
@@ -288,7 +289,7 @@ void FlingController::GenerateAndSendWheelEvents(
blink::WebMouseWheelEvent::Phase phase) {
MouseWheelEventWithLatencyInfo synthetic_wheel(
WebInputEvent::kMouseWheel, current_fling_parameters_.modifiers,
- base::TimeTicks::Now(), ui::LatencyInfo(ui::SourceEventType::WHEEL));
+ clock_->NowTicks(), 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;
@@ -307,7 +308,7 @@ void FlingController::GenerateAndSendGestureScrollEvents(
WebInputEvent::Type type,
const gfx::Vector2dF& delta /* = gfx::Vector2dF() */) {
GestureEventWithLatencyInfo synthetic_gesture(
- type, current_fling_parameters_.modifiers, base::TimeTicks::Now(),
+ type, current_fling_parameters_.modifiers, clock_->NowTicks(),
ui::LatencyInfo(ui::SourceEventType::INERTIAL));
synthetic_gesture.event.SetPositionInWidget(current_fling_parameters_.point);
synthetic_gesture.event.SetPositionInScreen(
diff --git a/chromium/content/browser/renderer_host/input/fling_controller.h b/chromium/content/browser/renderer_host/input/fling_controller.h
index 56e997187ca..3f02f832422 100644
--- a/chromium/content/browser/renderer_host/input/fling_controller.h
+++ b/chromium/content/browser/renderer_host/input/fling_controller.h
@@ -106,6 +106,8 @@ class CONTENT_EXPORT FlingController {
// Returns the |TouchpadTapSuppressionController| instance.
TouchpadTapSuppressionController* GetTouchpadTapSuppressionController();
+ void set_clock_for_testing(const base::TickClock* clock) { clock_ = clock; }
+
protected:
std::unique_ptr<ui::FlingBooster> fling_booster_;
@@ -178,6 +180,9 @@ class CONTENT_EXPORT FlingController {
// for determining if the fling start time should be re-initialized.
bool has_fling_animation_started_;
+ // The clock used; overridable for tests.
+ const base::TickClock* clock_;
+
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 3478d4eb08e..51e37f88793 100644
--- a/chromium/content/browser/renderer_host/input/fling_controller_unittest.cc
+++ b/chromium/content/browser/renderer_host/input/fling_controller_unittest.cc
@@ -4,8 +4,10 @@
#include "content/browser/renderer_host/input/fling_controller.h"
+#include "base/rand_util.h"
#include "base/run_loop.h"
#include "base/test/scoped_task_environment.h"
+#include "base/test/simple_test_tick_clock.h"
#include "build/build_config.h"
#include "content/browser/renderer_host/input/gesture_event_queue.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -16,6 +18,10 @@ using blink::WebGestureEvent;
using blink::WebInputEvent;
using blink::WebMouseWheelEvent;
+namespace {
+constexpr double kFrameDelta = 1000.0 / 60.0;
+} // namespace
+
namespace content {
class FakeFlingController : public FlingController {
@@ -51,6 +57,8 @@ class FlingControllerTest : public GestureEventQueueClient,
GestureEventQueue::Config());
fling_controller_ = std::make_unique<FakeFlingController>(
queue_.get(), this, this, FlingController::Config());
+ fling_controller_->set_clock_for_testing(&mock_clock_);
+ AdvanceTime();
}
// GestureEventQueueClient
@@ -90,14 +98,19 @@ class FlingControllerTest : public GestureEventQueueClient,
}
void SimulateFlingStart(blink::WebGestureDevice source_device,
- const gfx::Vector2dF& velocity) {
+ const gfx::Vector2dF& velocity,
+ bool wait_before_processing = true) {
scheduled_next_fling_progress_ = false;
sent_scroll_gesture_count_ = 0;
WebGestureEvent fling_start(WebInputEvent::kGestureFlingStart, 0,
- base::TimeTicks::Now(), source_device);
+ NowTicks(), 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);
+ if (wait_before_processing) {
+ // Wait for up to one frame before processing the event.
+ AdvanceTime(base::RandInt(0, static_cast<int>(kFrameDelta)));
+ }
if (!fling_controller_->FilterGestureEvent(fling_start_with_latency))
fling_controller_->ProcessGestureFlingStart(fling_start_with_latency);
}
@@ -105,7 +118,7 @@ class FlingControllerTest : public GestureEventQueueClient,
void SimulateFlingCancel(blink::WebGestureDevice source_device) {
notified_client_after_fling_stop_ = false;
WebGestureEvent fling_cancel(WebInputEvent::kGestureFlingCancel, 0,
- base::TimeTicks::Now(), source_device);
+ NowTicks(), source_device);
// autoscroll fling cancel doesn't allow fling boosting.
if (source_device == blink::kWebGestureDeviceSyntheticAutoscroll)
fling_cancel.data.fling_cancel.prevent_boosting = true;
@@ -125,6 +138,12 @@ class FlingControllerTest : public GestureEventQueueClient,
bool FlingInProgress() { return fling_controller_->fling_in_progress(); }
bool FlingBoosted() { return fling_controller_->FlingBoosted(); }
+ void AdvanceTime(double time_delta_ms = kFrameDelta) {
+ mock_clock_.Advance(base::TimeDelta::FromMillisecondsD(time_delta_ms));
+ }
+
+ base::TimeTicks NowTicks() const { return mock_clock_.NowTicks(); }
+
protected:
std::unique_ptr<FakeFlingController> fling_controller_;
WebMouseWheelEvent last_sent_wheel_;
@@ -136,6 +155,8 @@ class FlingControllerTest : public GestureEventQueueClient,
int sent_scroll_gesture_count_ = 0;
private:
+ base::SimpleTestTickClock mock_clock_;
+
bool needs_begin_frame_for_fling_progress_;
base::test::ScopedTaskEnvironment scoped_task_environment_;
std::unique_ptr<GestureEventQueue> queue_;
@@ -163,9 +184,7 @@ TEST_P(FlingControllerTest,
EXPECT_EQ(WebInputEvent::kGestureScrollEnd, last_sent_gesture_.GetType());
}
-// TODO(https://crbug.com/836996): Timing-dependent flakes on some platforms.
-TEST_P(FlingControllerTest, DISABLED_ControllerHandlesTouchpadGestureFling) {
- base::TimeTicks progress_time = base::TimeTicks::Now();
+TEST_P(FlingControllerTest, ControllerHandlesTouchpadGestureFling) {
SimulateFlingStart(blink::kWebGestureDeviceTouchpad, gfx::Vector2dF(1000, 0));
EXPECT_TRUE(FlingInProgress());
// Processing GFS will send the first fling prgoress event if the time delta
@@ -173,8 +192,8 @@ TEST_P(FlingControllerTest, DISABLED_ControllerHandlesTouchpadGestureFling) {
// is called is large enough.
bool process_GFS_sent_first_event = first_wheel_event_sent_;
- progress_time += base::TimeDelta::FromMilliseconds(17);
- ProgressFling(progress_time);
+ AdvanceTime();
+ ProgressFling(NowTicks());
if (!process_GFS_sent_first_event) {
EXPECT_EQ(WebMouseWheelEvent::kPhaseBegan, last_sent_wheel_.momentum_phase);
@@ -185,8 +204,8 @@ TEST_P(FlingControllerTest, DISABLED_ControllerHandlesTouchpadGestureFling) {
EXPECT_GT(last_sent_wheel_.delta_x, 0.f);
// The rest of the wheel events must have momentum_phase == KPhaseChanged.
- progress_time += base::TimeDelta::FromMilliseconds(17);
- ProgressFling(progress_time);
+ AdvanceTime();
+ ProgressFling(NowTicks());
EXPECT_EQ(WebMouseWheelEvent::kPhaseChanged, last_sent_wheel_.momentum_phase);
EXPECT_GT(last_sent_wheel_.delta_x, 0.f);
@@ -196,24 +215,22 @@ TEST_P(FlingControllerTest, DISABLED_ControllerHandlesTouchpadGestureFling) {
EXPECT_TRUE(FlingInProgress());
// Wait for the boosting timer to expire. The delayed cancelation must work.
- progress_time += base::TimeDelta::FromMilliseconds(500);
- ProgressFling(progress_time);
+ AdvanceTime(500);
+ ProgressFling(NowTicks());
EXPECT_FALSE(FlingInProgress());
EXPECT_EQ(WebMouseWheelEvent::kPhaseEnded, last_sent_wheel_.momentum_phase);
EXPECT_EQ(0.f, last_sent_wheel_.delta_x);
EXPECT_EQ(0.f, last_sent_wheel_.delta_y);
}
-// TODO(https://crbug.com/836996): Timing-dependent flakes on some platforms.
-TEST_P(FlingControllerTest, DISABLED_ControllerHandlesTouchscreenGestureFling) {
- base::TimeTicks progress_time = base::TimeTicks::Now();
+TEST_P(FlingControllerTest, ControllerHandlesTouchscreenGestureFling) {
SimulateFlingStart(blink::kWebGestureDeviceTouchscreen,
gfx::Vector2dF(1000, 0));
EXPECT_TRUE(FlingInProgress());
// The fling progress will generate and send GSU events with inertial state.
- progress_time += base::TimeDelta::FromMilliseconds(17);
- ProgressFling(progress_time);
+ AdvanceTime();
+ ProgressFling(NowTicks());
ASSERT_EQ(WebInputEvent::kGestureScrollUpdate, last_sent_gesture_.GetType());
EXPECT_EQ(WebGestureEvent::kMomentumPhase,
last_sent_gesture_.data.scroll_update.inertial_phase);
@@ -225,16 +242,13 @@ TEST_P(FlingControllerTest, DISABLED_ControllerHandlesTouchscreenGestureFling) {
EXPECT_TRUE(FlingInProgress());
// Wait for the boosting timer to expire. The delayed cancelation must work.
- progress_time += base::TimeDelta::FromMilliseconds(500);
- ProgressFling(progress_time);
+ AdvanceTime(500);
+ ProgressFling(NowTicks());
EXPECT_FALSE(FlingInProgress());
EXPECT_EQ(WebInputEvent::kGestureScrollEnd, last_sent_gesture_.GetType());
}
-// TODO(https://crbug.com/836996): Timing-dependent flakes on some platforms.
-TEST_P(FlingControllerTest,
- DISABLED_ControllerSendsWheelEndWhenTouchpadFlingIsOver) {
- base::TimeTicks progress_time = base::TimeTicks::Now();
+TEST_P(FlingControllerTest, ControllerSendsWheelEndWhenTouchpadFlingIsOver) {
SimulateFlingStart(blink::kWebGestureDeviceTouchpad, gfx::Vector2dF(100, 0));
EXPECT_TRUE(FlingInProgress());
// Processing GFS will send the first fling prgoress event if the time delta
@@ -242,8 +256,8 @@ TEST_P(FlingControllerTest,
// is called is large enough.
bool process_GFS_sent_first_event = first_wheel_event_sent_;
- progress_time += base::TimeDelta::FromMilliseconds(17);
- ProgressFling(progress_time);
+ AdvanceTime();
+ ProgressFling(NowTicks());
if (!process_GFS_sent_first_event) {
EXPECT_EQ(WebMouseWheelEvent::kPhaseBegan, last_sent_wheel_.momentum_phase);
} else {
@@ -252,14 +266,14 @@ TEST_P(FlingControllerTest,
}
EXPECT_GT(last_sent_wheel_.delta_x, 0.f);
- progress_time += base::TimeDelta::FromMilliseconds(17);
- ProgressFling(progress_time);
+ AdvanceTime();
+ ProgressFling(NowTicks());
while (FlingInProgress()) {
EXPECT_EQ(WebMouseWheelEvent::kPhaseChanged,
last_sent_wheel_.momentum_phase);
EXPECT_GT(last_sent_wheel_.delta_x, 0.f);
- progress_time += base::TimeDelta::FromMilliseconds(17);
- ProgressFling(progress_time);
+ AdvanceTime();
+ ProgressFling(NowTicks());
}
EXPECT_EQ(WebMouseWheelEvent::kPhaseEnded, last_sent_wheel_.momentum_phase);
@@ -267,33 +281,28 @@ TEST_P(FlingControllerTest,
EXPECT_EQ(0.f, last_sent_wheel_.delta_y);
}
-// TODO(https://crbug.com/836996): Timing-dependent flakes on some platforms.
-TEST_P(FlingControllerTest,
- DISABLED_ControllerSendsGSEWhenTouchscreenFlingIsOver) {
- base::TimeTicks progress_time = base::TimeTicks::Now();
+TEST_P(FlingControllerTest, ControllerSendsGSEWhenTouchscreenFlingIsOver) {
SimulateFlingStart(blink::kWebGestureDeviceTouchscreen,
gfx::Vector2dF(100, 0));
EXPECT_TRUE(FlingInProgress());
- progress_time += base::TimeDelta::FromMilliseconds(17);
- ProgressFling(progress_time);
+ AdvanceTime();
+ ProgressFling(NowTicks());
while (FlingInProgress()) {
ASSERT_EQ(WebInputEvent::kGestureScrollUpdate,
last_sent_gesture_.GetType());
EXPECT_EQ(WebGestureEvent::kMomentumPhase,
last_sent_gesture_.data.scroll_update.inertial_phase);
EXPECT_GT(last_sent_gesture_.data.scroll_update.delta_x, 0.f);
- progress_time += base::TimeDelta::FromMilliseconds(17);
- ProgressFling(progress_time);
+ AdvanceTime();
+ ProgressFling(NowTicks());
}
EXPECT_EQ(WebInputEvent::kGestureScrollEnd, last_sent_gesture_.GetType());
}
-// TODO(https://crbug.com/836996): Timing-dependent flakes on some platforms.
TEST_P(FlingControllerTest,
- DISABLED_EarlyTouchpadFlingCancelationOnInertialGSUAckNotConsumed) {
- base::TimeTicks progress_time = base::TimeTicks::Now();
+ EarlyTouchpadFlingCancelationOnInertialGSUAckNotConsumed) {
SimulateFlingStart(blink::kWebGestureDeviceTouchpad, gfx::Vector2dF(1000, 0));
EXPECT_TRUE(FlingInProgress());
// Processing GFS will send the first fling prgoress event if the time delta
@@ -301,8 +310,8 @@ TEST_P(FlingControllerTest,
// is called is large enough.
bool process_GFS_sent_first_event = first_wheel_event_sent_;
- progress_time += base::TimeDelta::FromMilliseconds(17);
- ProgressFling(progress_time);
+ AdvanceTime();
+ ProgressFling(NowTicks());
if (!process_GFS_sent_first_event) {
EXPECT_EQ(WebMouseWheelEvent::kPhaseBegan, last_sent_wheel_.momentum_phase);
} else {
@@ -313,7 +322,7 @@ TEST_P(FlingControllerTest,
// A non-consumed GSU ack in inertial state cancels out the rest of the fling.
WebGestureEvent scroll_update(WebInputEvent::kGestureScrollUpdate, 0,
- base::TimeTicks::Now());
+ NowTicks());
scroll_update.data.scroll_update.inertial_phase =
WebGestureEvent::kMomentumPhase;
@@ -326,15 +335,13 @@ TEST_P(FlingControllerTest,
EXPECT_EQ(0.f, last_sent_wheel_.delta_y);
}
-// TODO(https://crbug.com/836996): Timing-dependent flakes on some platforms.
TEST_P(FlingControllerTest,
- DISABLED_EarlyTouchscreenFlingCancelationOnInertialGSUAckNotConsumed) {
- base::TimeTicks progress_time = base::TimeTicks::Now();
+ EarlyTouchscreenFlingCancelationOnInertialGSUAckNotConsumed) {
SimulateFlingStart(blink::kWebGestureDeviceTouchscreen,
gfx::Vector2dF(1000, 0));
EXPECT_TRUE(FlingInProgress());
- progress_time += base::TimeDelta::FromMilliseconds(17);
- ProgressFling(progress_time);
+ AdvanceTime();
+ ProgressFling(NowTicks());
ASSERT_EQ(WebInputEvent::kGestureScrollUpdate, last_sent_gesture_.GetType());
EXPECT_EQ(WebGestureEvent::kMomentumPhase,
last_sent_gesture_.data.scroll_update.inertial_phase);
@@ -342,7 +349,7 @@ TEST_P(FlingControllerTest,
// A non-consumed GSU ack in inertial state cancels out the rest of the fling.
WebGestureEvent scroll_update(WebInputEvent::kGestureScrollUpdate, 0,
- base::TimeTicks::Now());
+ NowTicks());
scroll_update.data.scroll_update.inertial_phase =
WebGestureEvent::kMomentumPhase;
@@ -353,9 +360,7 @@ TEST_P(FlingControllerTest,
EXPECT_EQ(WebInputEvent::kGestureScrollEnd, last_sent_gesture_.GetType());
}
-// Flaky. https://crbug.com/836996.
-TEST_P(FlingControllerTest, DISABLED_EarlyTouchpadFlingCancelationOnFlingStop) {
- base::TimeTicks progress_time = base::TimeTicks::Now();
+TEST_P(FlingControllerTest, EarlyTouchpadFlingCancelationOnFlingStop) {
SimulateFlingStart(blink::kWebGestureDeviceTouchpad, gfx::Vector2dF(1000, 0));
EXPECT_TRUE(FlingInProgress());
// Processing GFS will send the first fling prgoress event if the time delta
@@ -363,8 +368,8 @@ TEST_P(FlingControllerTest, DISABLED_EarlyTouchpadFlingCancelationOnFlingStop) {
// is called is large enough.
bool process_GFS_sent_first_event = first_wheel_event_sent_;
- progress_time += base::TimeDelta::FromMilliseconds(17);
- ProgressFling(progress_time);
+ AdvanceTime();
+ ProgressFling(NowTicks());
if (!process_GFS_sent_first_event) {
EXPECT_EQ(WebMouseWheelEvent::kPhaseBegan, last_sent_wheel_.momentum_phase);
} else {
@@ -381,14 +386,13 @@ TEST_P(FlingControllerTest, DISABLED_EarlyTouchpadFlingCancelationOnFlingStop) {
}
TEST_P(FlingControllerTest, EarlyTouchscreenFlingCancelationOnFlingStop) {
- base::TimeTicks progress_time = base::TimeTicks::Now();
SimulateFlingStart(blink::kWebGestureDeviceTouchscreen,
gfx::Vector2dF(1000, 0));
EXPECT_TRUE(FlingInProgress());
// progress fling must send GSU events.
- progress_time += base::TimeDelta::FromMilliseconds(17);
- ProgressFling(progress_time);
+ AdvanceTime();
+ ProgressFling(NowTicks());
ASSERT_EQ(WebInputEvent::kGestureScrollUpdate, last_sent_gesture_.GetType());
EXPECT_EQ(WebGestureEvent::kMomentumPhase,
last_sent_gesture_.data.scroll_update.inertial_phase);
@@ -417,24 +421,21 @@ TEST_P(FlingControllerTest, GestureFlingCancelsFiltered) {
EXPECT_TRUE(last_fling_cancel_filtered_);
}
-// Flaky. https://crbug.com/836996.
-TEST_P(FlingControllerTest, DISABLED_GestureFlingNotCancelledBySmallTimeDelta) {
- base::TimeTicks progress_time = base::TimeTicks::Now();
+TEST_P(FlingControllerTest, GestureFlingNotCancelledBySmallTimeDelta) {
SimulateFlingStart(blink::kWebGestureDeviceTouchscreen,
- gfx::Vector2dF(1000, 0));
+ gfx::Vector2dF(1000, 0), false);
EXPECT_TRUE(FlingInProgress());
+ int current_sent_scroll_gesture_count = sent_scroll_gesture_count_;
// If we the first progress tick happens too close to the fling_start time,
// the controller won't send any GSU events, but the fling is still active.
- // progress_time += base::TimeDelta::FromMilliseconds(1);
- ProgressFling(progress_time);
- EXPECT_EQ(blink::kWebGestureDeviceUninitialized,
- last_sent_gesture_.SourceDevice());
+ ProgressFling(NowTicks());
+ EXPECT_EQ(current_sent_scroll_gesture_count, sent_scroll_gesture_count_);
EXPECT_TRUE(FlingInProgress());
// The rest of the progress flings must advance the fling normally.
- progress_time += base::TimeDelta::FromMilliseconds(17);
- ProgressFling(progress_time);
+ AdvanceTime();
+ ProgressFling(NowTicks());
EXPECT_EQ(blink::kWebGestureDeviceTouchscreen,
last_sent_gesture_.SourceDevice());
ASSERT_EQ(WebInputEvent::kGestureScrollUpdate, last_sent_gesture_.GetType());
@@ -443,9 +444,9 @@ TEST_P(FlingControllerTest, DISABLED_GestureFlingNotCancelledBySmallTimeDelta) {
EXPECT_GT(last_sent_gesture_.data.scroll_update.delta_x, 0.f);
}
-// TODO(https://crbug.com/836996): Timing-dependent flakes on some platforms.
-TEST_P(FlingControllerTest, DISABLED_GestureFlingWithNegativeTimeDelta) {
- base::TimeTicks progress_time = base::TimeTicks::Now();
+TEST_P(FlingControllerTest, GestureFlingWithNegativeTimeDelta) {
+ base::TimeTicks initial_time = NowTicks();
+ AdvanceTime();
SimulateFlingStart(blink::kWebGestureDeviceTouchscreen,
gfx::Vector2dF(1000, 0));
EXPECT_TRUE(FlingInProgress());
@@ -454,13 +455,12 @@ TEST_P(FlingControllerTest, DISABLED_GestureFlingWithNegativeTimeDelta) {
// If we get a negative time delta, that is, the Progress tick time happens
// before the fling's start time then we should *not* try progressing the
// fling.
- progress_time -= base::TimeDelta::FromMilliseconds(5);
- ProgressFling(progress_time);
+ ProgressFling(initial_time);
EXPECT_EQ(current_sent_scroll_gesture_count, sent_scroll_gesture_count_);
// The rest of the progress flings must advance the fling normally.
- progress_time += base::TimeDelta::FromMilliseconds(17);
- ProgressFling(progress_time);
+ AdvanceTime();
+ ProgressFling(NowTicks());
EXPECT_EQ(blink::kWebGestureDeviceTouchscreen,
last_sent_gesture_.SourceDevice());
ASSERT_EQ(WebInputEvent::kGestureScrollUpdate, last_sent_gesture_.GetType());
@@ -476,7 +476,6 @@ TEST_P(FlingControllerTest, DISABLED_GestureFlingWithNegativeTimeDelta) {
#define MAYBE_ControllerBoostsTouchpadFling ControllerBoostsTouchpadFling
#endif
TEST_P(FlingControllerTest, MAYBE_ControllerBoostsTouchpadFling) {
- base::TimeTicks progress_time = base::TimeTicks::Now();
SimulateFlingStart(blink::kWebGestureDeviceTouchpad, gfx::Vector2dF(1000, 0));
EXPECT_TRUE(FlingInProgress());
// Processing GFS will send the first fling prgoress event if the time delta
@@ -484,8 +483,8 @@ TEST_P(FlingControllerTest, MAYBE_ControllerBoostsTouchpadFling) {
// is called is large enough.
bool process_GFS_sent_first_event = first_wheel_event_sent_;
- progress_time += base::TimeDelta::FromMilliseconds(17);
- ProgressFling(progress_time);
+ AdvanceTime();
+ ProgressFling(NowTicks());
if (!process_GFS_sent_first_event) {
EXPECT_EQ(WebMouseWheelEvent::kPhaseBegan, last_sent_wheel_.momentum_phase);
} else {
@@ -495,8 +494,8 @@ TEST_P(FlingControllerTest, MAYBE_ControllerBoostsTouchpadFling) {
EXPECT_GT(last_sent_wheel_.delta_x, 0.f);
// The rest of the wheel events must have momentum_phase == KPhaseChanged.
- progress_time += base::TimeDelta::FromMilliseconds(17);
- ProgressFling(progress_time);
+ AdvanceTime();
+ ProgressFling(NowTicks());
EXPECT_EQ(WebMouseWheelEvent::kPhaseChanged, last_sent_wheel_.momentum_phase);
EXPECT_GT(last_sent_wheel_.delta_x, 0.f);
@@ -512,14 +511,12 @@ TEST_P(FlingControllerTest, MAYBE_ControllerBoostsTouchpadFling) {
}
TEST_P(FlingControllerTest, ControllerBoostsTouchscreenFling) {
- base::TimeTicks progress_time = base::TimeTicks::Now();
SimulateFlingStart(blink::kWebGestureDeviceTouchscreen,
gfx::Vector2dF(1000, 0));
EXPECT_TRUE(FlingInProgress());
-
// Fling progress must send GSU events.
- progress_time += base::TimeDelta::FromMilliseconds(17);
- ProgressFling(progress_time);
+ AdvanceTime();
+ ProgressFling(NowTicks());
ASSERT_EQ(WebInputEvent::kGestureScrollUpdate, last_sent_gesture_.GetType());
EXPECT_EQ(WebGestureEvent::kMomentumPhase,
last_sent_gesture_.data.scroll_update.inertial_phase);
@@ -538,7 +535,6 @@ TEST_P(FlingControllerTest, ControllerBoostsTouchscreenFling) {
}
TEST_P(FlingControllerTest, ControllerNotifiesTheClientAfterFlingStart) {
- base::TimeTicks progress_time = base::TimeTicks::Now();
SimulateFlingStart(blink::kWebGestureDeviceTouchscreen,
gfx::Vector2dF(1000, 0));
EXPECT_TRUE(FlingInProgress());
@@ -550,21 +546,20 @@ TEST_P(FlingControllerTest, ControllerNotifiesTheClientAfterFlingStart) {
// Wait for the boosting timer to expire. The delayed cancelation must work
// and the client must be notified after fling cancelation.
- progress_time += base::TimeDelta::FromMilliseconds(500);
- ProgressFling(progress_time);
+ AdvanceTime(500);
+ ProgressFling(NowTicks());
EXPECT_FALSE(FlingInProgress());
EXPECT_EQ(WebInputEvent::kGestureScrollEnd, last_sent_gesture_.GetType());
EXPECT_TRUE(notified_client_after_fling_stop_);
}
TEST_P(FlingControllerTest, MiddleClickAutoScrollFling) {
- base::TimeTicks progress_time = base::TimeTicks::Now();
SimulateFlingStart(blink::kWebGestureDeviceSyntheticAutoscroll,
gfx::Vector2dF(1000, 0));
EXPECT_TRUE(FlingInProgress());
- progress_time += base::TimeDelta::FromMilliseconds(17);
- ProgressFling(progress_time);
+ AdvanceTime();
+ ProgressFling(NowTicks());
ASSERT_EQ(WebInputEvent::kGestureScrollUpdate, last_sent_gesture_.GetType());
EXPECT_EQ(WebGestureEvent::kMomentumPhase,
last_sent_gesture_.data.scroll_update.inertial_phase);
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 582b96fb30c..d50dbf0156c 100644
--- a/chromium/content/browser/renderer_host/input/input_router_impl.cc
+++ b/chromium/content/browser/renderer_host/input/input_router_impl.cc
@@ -33,9 +33,6 @@
namespace content {
-using base::Time;
-using base::TimeDelta;
-using base::TimeTicks;
using blink::WebGestureEvent;
using blink::WebInputEvent;
using blink::WebKeyboardEvent;
@@ -185,10 +182,10 @@ void InputRouterImpl::SendGestureEvent(
void InputRouterImpl::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);
+ TouchEventWithLatencyInfo updated_touch_event = touch_event;
+ SetMovementXYForTouchPoints(&updated_touch_event.event);
+ input_stream_validator_.Validate(updated_touch_event.event);
+ touch_event_queue_.QueueEvent(updated_touch_event);
}
void InputRouterImpl::NotifySiteIsMobileOptimized(bool is_mobile_optimized) {
@@ -335,21 +332,30 @@ void InputRouterImpl::SendTouchEventImmediately(
void InputRouterImpl::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) {
+ if (WebTouchEventTraits::IsTouchSequenceStart(event.event)) {
touch_action_filter_.AppendToGestureSequenceForDebugging("T");
- // Touch action must be auto when there is no consumer
- touch_action_filter_.OnSetTouchAction(cc::kTouchActionAuto);
- touch_action_filter_.SetActiveTouchInProgress(true);
- UpdateTouchAckTimeoutEnabled();
+ touch_action_filter_.AppendToGestureSequenceForDebugging(
+ base::NumberToString(ack_result).c_str());
+ touch_action_filter_.AppendToGestureSequenceForDebugging(
+ base::NumberToString(event.event.unique_touch_event_id).c_str());
+ touch_action_filter_.IncreaseActiveTouches();
+ // There are some cases the touch action may not have value when receiving
+ // the ACK for the touch start, such as input ack state is
+ // NO_CONSUMER_EXISTS, or the renderer has swapped out. In these cases, set
+ // touch action Auto.
+ if (!touch_action_filter_.allowed_touch_action().has_value()) {
+ touch_action_filter_.OnSetTouchAction(cc::kTouchActionAuto);
+ UpdateTouchAckTimeoutEnabled();
+ }
}
disposition_handler_->OnTouchEventAck(event, ack_source, ack_result);
if (WebTouchEventTraits::IsTouchSequenceEnd(event.event)) {
+ touch_action_filter_.AppendToGestureSequenceForDebugging("E");
+ touch_action_filter_.AppendToGestureSequenceForDebugging(
+ base::NumberToString(event.event.unique_touch_event_id).c_str());
+ touch_action_filter_.DecreaseActiveTouches();
touch_action_filter_.ReportAndResetTouchAction();
- touch_action_filter_.SetActiveTouchInProgress(false);
UpdateTouchAckTimeoutEnabled();
}
}
@@ -596,7 +602,6 @@ void InputRouterImpl::OnHasTouchEventHandlers(bool has_handlers) {
void InputRouterImpl::ForceSetTouchActionAuto() {
touch_action_filter_.AppendToGestureSequenceForDebugging("F");
touch_action_filter_.OnSetTouchAction(cc::kTouchActionAuto);
- touch_action_filter_.SetActiveTouchInProgress(true);
}
void InputRouterImpl::OnHasTouchEventHandlersForTest(bool has_handlers) {
@@ -614,9 +619,8 @@ void InputRouterImpl::OnSetTouchAction(cc::TouchAction touch_action) {
touch_action_filter_.AppendToGestureSequenceForDebugging("S");
touch_action_filter_.AppendToGestureSequenceForDebugging(
- std::to_string(touch_action).c_str());
+ base::NumberToString(touch_action).c_str());
touch_action_filter_.OnSetTouchAction(touch_action);
- touch_action_filter_.SetActiveTouchInProgress(true);
// kTouchActionNone should disable the touch ack timeout.
UpdateTouchAckTimeoutEnabled();
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 9f2862155d0..5aa7c74e123 100644
--- a/chromium/content/browser/renderer_host/input/input_router_impl.h
+++ b/chromium/content/browser/renderer_host/input/input_router_impl.h
@@ -114,7 +114,8 @@ class CONTENT_EXPORT InputRouterImpl : public InputRouter,
private:
friend class InputRouterImplTest;
friend class MockRenderWidgetHost;
- friend class RenderWidgetHostBrowserTest;
+ friend class RenderWidgetHostSitePerProcessTest;
+ friend class SitePerProcessBrowserTouchActionTest;
// Keeps track of last position of touch points and sets MovementXY for them.
void SetMovementXYForTouchPoints(blink::WebTouchEvent* event);
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 e06e5c15acb..18f0cbce82b 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
@@ -255,12 +255,12 @@ class InputRouterImplTest : public testing::Test {
}
void SimulateWheelEvent(float x,
- float y,
- float dX,
- float dY,
- int modifiers,
- bool precise,
- WebMouseWheelEvent::Phase phase) {
+ 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;
@@ -424,6 +424,33 @@ class InputRouterImplTest : public testing::Test {
disposition_handler_->GetAndResetAckCount();
}
+ void ActiveTouchSequenceCountTest(
+ const base::Optional<cc::TouchAction>& touch_action,
+ InputEventAckState state) {
+ PressTouchPoint(1, 1);
+ base::Optional<ui::DidOverscrollParams> overscroll;
+ input_router_->SendTouchEvent(TouchEventWithLatencyInfo(touch_event_));
+ input_router_->TouchEventHandled(
+ TouchEventWithLatencyInfo(touch_event_), InputEventAckSource::BROWSER,
+ ui::LatencyInfo(), state, overscroll, touch_action);
+ EXPECT_EQ(input_router_->touch_action_filter_.num_of_active_touches_, 1);
+ ReleaseTouchPoint(0);
+ input_router_->OnTouchEventAck(TouchEventWithLatencyInfo(touch_event_),
+ InputEventAckSource::BROWSER, state);
+ EXPECT_EQ(input_router_->touch_action_filter_.num_of_active_touches_, 0);
+ }
+
+ void OnTouchEventAckWithAckState(InputEventAckState ack_state) {
+ input_router_->OnHasTouchEventHandlers(true);
+ EXPECT_FALSE(input_router_->AllowedTouchAction().has_value());
+ PressTouchPoint(1, 1);
+ input_router_->SendTouchEvent(TouchEventWithLatencyInfo(touch_event_));
+ input_router_->OnTouchEventAck(TouchEventWithLatencyInfo(touch_event_),
+ InputEventAckSource::BROWSER, ack_state);
+ EXPECT_EQ(input_router_->AllowedTouchAction().value(),
+ cc::kTouchActionAuto);
+ }
+
InputRouter::Config config_;
std::unique_ptr<MockInputRouterImplClient> client_;
std::unique_ptr<InputRouterImpl> input_router_;
@@ -592,6 +619,64 @@ TEST_F(InputRouterImplTest, CoalescesWheelEvents) {
EXPECT_EQ(0u, dispatched_messages.size());
}
+// Test that the active touch sequence count increment when the touch start is
+// not ACKed from the main thread.
+TEST_F(InputRouterImplTest, ActiveTouchSequenceCountWithoutTouchAction) {
+ base::Optional<cc::TouchAction> touch_action;
+ ActiveTouchSequenceCountTest(touch_action,
+ INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING);
+}
+
+TEST_F(InputRouterImplTest,
+ ActiveTouchSequenceCountWithoutTouchActionNoConsumer) {
+ base::Optional<cc::TouchAction> touch_action;
+ ActiveTouchSequenceCountTest(touch_action,
+ INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
+}
+
+// Test that the active touch sequence count increment when the touch start is
+// ACKed from the main thread.
+TEST_F(InputRouterImplTest, ActiveTouchSequenceCountWithTouchAction) {
+ base::Optional<cc::TouchAction> touch_action(cc::kTouchActionPanY);
+ ActiveTouchSequenceCountTest(touch_action,
+ INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING);
+}
+
+TEST_F(InputRouterImplTest, ActiveTouchSequenceCountWithTouchActionNoConsumer) {
+ base::Optional<cc::TouchAction> touch_action(cc::kTouchActionPanY);
+ ActiveTouchSequenceCountTest(touch_action,
+ INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
+}
+
+TEST_F(InputRouterImplTest, TouchActionAutoWithAckStateConsumed) {
+ OnTouchEventAckWithAckState(INPUT_EVENT_ACK_STATE_CONSUMED);
+}
+
+TEST_F(InputRouterImplTest, TouchActionAutoWithAckStateNotConsumed) {
+ OnTouchEventAckWithAckState(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+}
+
+TEST_F(InputRouterImplTest, TouchActionAutoWithAckStateConsumedShouldBubble) {
+ OnTouchEventAckWithAckState(INPUT_EVENT_ACK_STATE_CONSUMED_SHOULD_BUBBLE);
+}
+
+TEST_F(InputRouterImplTest, TouchActionAutoWithAckStateNoConsumerExists) {
+ OnTouchEventAckWithAckState(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
+}
+
+TEST_F(InputRouterImplTest, TouchActionAutoWithAckStateIgnored) {
+ OnTouchEventAckWithAckState(INPUT_EVENT_ACK_STATE_IGNORED);
+}
+
+TEST_F(InputRouterImplTest, TouchActionAutoWithAckStateNonBlocking) {
+ OnTouchEventAckWithAckState(INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING);
+}
+
+TEST_F(InputRouterImplTest, TouchActionAutoWithAckStateNonBlockingDueToFling) {
+ OnTouchEventAckWithAckState(
+ INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING_DUE_TO_FLING);
+}
+
// Tests that touch-events are sent properly.
TEST_F(InputRouterImplTest, TouchEventQueue) {
OnHasTouchEventHandlers(true);
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 3b1595d2e49..a26f229afa3 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
@@ -13,6 +13,7 @@
#include "build/build_config.h"
#include "content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.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"
@@ -141,14 +142,14 @@ class MainThreadEventQueueBrowserTest : public ContentBrowserTest {
}
void DoTouchMove() {
- SyntheticWebTouchEvent kEvents[4];
- kEvents[0].PressPoint(10, 10);
- kEvents[1].PressPoint(10, 10);
- 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, 40);
+ SyntheticWebTouchEvent events[4];
+ events[0].PressPoint(10, 10);
+ events[1].PressPoint(10, 10);
+ events[1].MovePoint(0, 20, 20);
+ events[2].PressPoint(10, 10);
+ events[2].MovePoint(0, 30, 30);
+ events[3].PressPoint(10, 10);
+ events[3].MovePoint(0, 35, 40);
// Send a click event to cause some jankiness. This is done via a click
// event as ExecuteScript is synchronous.
@@ -157,8 +158,11 @@ class MainThreadEventQueueBrowserTest : public ContentBrowserTest {
auto input_msg_watcher = std::make_unique<InputMsgWatcher>(
GetWidgetHost(), blink::WebInputEvent::kTouchMove);
- for (const auto& event : kEvents)
- GetWidgetHost()->ForwardEmulatedTouchEvent(event, nullptr);
+ auto* root_view = GetWidgetHost()->GetView();
+ auto* input_event_router =
+ GetWidgetHost()->delegate()->GetInputEventRouter();
+ for (auto& event : events)
+ input_event_router->RouteTouchEvent(root_view, &event, ui::LatencyInfo());
// 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/mouse_latency_browsertest.cc b/chromium/content/browser/renderer_host/input/mouse_latency_browsertest.cc
index a7c0c6dca37..b784cb04a90 100644
--- a/chromium/content/browser/renderer_host/input/mouse_latency_browsertest.cc
+++ b/chromium/content/browser/renderer_host/input/mouse_latency_browsertest.cc
@@ -151,7 +151,7 @@ class TracingRenderWidgetHostFactory : public RenderWidgetHostFactory {
class MouseLatencyBrowserTest : public ContentBrowserTest {
public:
- MouseLatencyBrowserTest() : loop_(base::MessageLoop::TYPE_UI) {}
+ MouseLatencyBrowserTest() {}
~MouseLatencyBrowserTest() override {}
RenderWidgetHostImpl* GetWidgetHost() {
@@ -306,7 +306,6 @@ class MouseLatencyBrowserTest : public ContentBrowserTest {
}
private:
- base::MessageLoop loop_;
std::unique_ptr<base::RunLoop> runner_;
base::Value trace_data_;
TracingRenderWidgetHostFactory widget_factory_;
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 db69b0d9fb3..52f29658403 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
@@ -8,6 +8,7 @@
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "content/common/input/input_event_dispatch_type.h"
+#include "content/common/input/web_mouse_wheel_event_traits.h"
#include "content/public/common/content_features.h"
#include "ui/events/base_event_utils.h"
#include "ui/events/blink/web_input_event_traits.h"
@@ -57,6 +58,10 @@ void MouseWheelEventQueue::QueueEvent(
event.latency.Terminate();
last_event->CoalesceWith(event);
+ // The deltas for the coalesced event change; the corresponding action
+ // might be different now.
+ last_event->event.event_action =
+ WebMouseWheelEventTraits::GetEventAction(last_event->event);
TRACE_EVENT_INSTANT2("input", "MouseWheelEventQueue::CoalescedWheelEvent",
TRACE_EVENT_SCOPE_THREAD, "total_dx",
last_event->event.delta_x, "total_dy",
@@ -65,7 +70,13 @@ void MouseWheelEventQueue::QueueEvent(
}
}
- wheel_queue_.push_back(std::make_unique<QueuedWebMouseWheelEvent>(event));
+ MouseWheelEventWithLatencyInfo event_with_action(event.event, event.latency);
+ event_with_action.event.event_action =
+ WebMouseWheelEventTraits::GetEventAction(event.event);
+ // Update the expected event action before queuing the event. From this point
+ // on, the action should not change.
+ wheel_queue_.push_back(
+ std::make_unique<QueuedWebMouseWheelEvent>(event_with_action));
TryForwardNextEventToRenderer();
LOCAL_HISTOGRAM_COUNTS_100("Renderer.WheelQueueSize", wheel_queue_.size());
}
@@ -78,8 +89,8 @@ bool MouseWheelEventQueue::CanGenerateGestureScroll(
return false;
}
- if (!ui::WebInputEventTraits::CanCauseScroll(
- event_sent_for_gesture_ack_->event)) {
+ if (event_sent_for_gesture_ack_->event.event_action ==
+ blink::WebMouseWheelEvent::EventAction::kPageZoom) {
TRACE_EVENT_INSTANT0("input", "Wheel Event Cannot Cause Scroll",
TRACE_EVENT_SCOPE_THREAD);
return false;
@@ -129,8 +140,8 @@ void MouseWheelEventQueue::ProcessMouseWheelAck(
#if !defined(OS_MACOSX)
// Swap X & Y if Shift is down and when there is no horizontal movement.
- if ((event_sent_for_gesture_ack_->event.GetModifiers() &
- WebInputEvent::kShiftKey) != 0 &&
+ if (event_sent_for_gesture_ack_->event.event_action ==
+ blink::WebMouseWheelEvent::EventAction::kScrollHorizontal &&
event_sent_for_gesture_ack_->event.delta_x == 0) {
scroll_update.data.scroll_update.delta_x =
event_sent_for_gesture_ack_->event.delta_y;
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 718e02bf755..a7b9c1d78df 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
@@ -14,6 +14,7 @@
#include "base/logging.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
+#include "base/stl_util.h"
#include "base/test/scoped_task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/renderer_host/input/timeout_monitor.h"
@@ -155,9 +156,7 @@ class PassthroughTouchEventQueueTest : public testing::Test,
int unique_event_id) {
queue_->ProcessTouchAck(InputEventAckSource::COMPOSITOR_THREAD, ack_result,
ui::LatencyInfo(), unique_event_id);
- sent_events_ids_.erase(std::remove(sent_events_ids_.begin(),
- sent_events_ids_.end(), unique_event_id),
- sent_events_ids_.end());
+ base::Erase(sent_events_ids_, unique_event_id);
}
void SendGestureEventAck(WebInputEvent::Type type,
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 2d8e33bd72a..ad008cb8313 100644
--- a/chromium/content/browser/renderer_host/input/scroll_latency_browsertest.cc
+++ b/chromium/content/browser/renderer_host/input/scroll_latency_browsertest.cc
@@ -62,7 +62,7 @@ namespace content {
class ScrollLatencyBrowserTest : public ContentBrowserTest {
public:
- ScrollLatencyBrowserTest() : loop_(base::MessageLoop::TYPE_UI) {}
+ ScrollLatencyBrowserTest() {}
~ScrollLatencyBrowserTest() override {}
RenderWidgetHostImpl* GetWidgetHost() {
@@ -140,7 +140,6 @@ class ScrollLatencyBrowserTest : public ContentBrowserTest {
private:
base::HistogramTester histogram_tester_;
- base::MessageLoop loop_;
std::unique_ptr<MainThreadFrameObserver> frame_observer_;
DISALLOW_COPY_AND_ASSIGN(ScrollLatencyBrowserTest);
diff --git a/chromium/content/browser/renderer_host/input/synthetic_gesture.cc b/chromium/content/browser/renderer_host/input/synthetic_gesture.cc
index fd09c2ab43d..f5ba649b1b1 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_gesture.cc
+++ b/chromium/content/browser/renderer_host/input/synthetic_gesture.cc
@@ -52,4 +52,8 @@ std::unique_ptr<SyntheticGesture> SyntheticGesture::Create(
}
}
+bool SyntheticGesture::AllowHighFrequencyDispatch() const {
+ return true;
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/synthetic_gesture.h b/chromium/content/browser/renderer_host/input/synthetic_gesture.h
index 90d49902470..6f5d330575d 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_gesture.h
+++ b/chromium/content/browser/renderer_host/input/synthetic_gesture.h
@@ -51,6 +51,12 @@ class CONTENT_EXPORT SyntheticGesture {
virtual Result ForwardInputEvents(
const base::TimeTicks& timestamp, SyntheticGestureTarget* target) = 0;
+ // Returns whether the gesture events can be dispatched at high frequency
+ // (e.g. at 120Hz), instead of the regular frequence (at 60Hz). Some gesture
+ // interact differently depending on how long they take (e.g. the TAP gesture
+ // generates a click only if its duration is longer than a threshold).
+ virtual bool AllowHighFrequencyDispatch() const;
+
protected:
DISALLOW_COPY_AND_ASSIGN(SyntheticGesture);
};
diff --git a/chromium/content/browser/renderer_host/input/synthetic_gesture_controller.cc b/chromium/content/browser/renderer_host/input/synthetic_gesture_controller.cc
index 44308e011ed..eef8cd03df4 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_gesture_controller.cc
+++ b/chromium/content/browser/renderer_host/input/synthetic_gesture_controller.cc
@@ -40,11 +40,10 @@ void SyntheticGestureController::QueueSyntheticGesture(
StartGesture(*pending_gesture_queue_.FrontGesture());
}
-void SyntheticGestureController::StartTimer() {
- // TODO(sad): Change the interval to allow sending multiple events per begin
- // frame.
+void SyntheticGestureController::StartTimer(bool high_frequency) {
dispatch_timer_.Start(
- FROM_HERE, base::TimeDelta::FromMicroseconds(16666),
+ FROM_HERE,
+ base::TimeDelta::FromMicroseconds(high_frequency ? 8333 : 16666),
base::BindRepeating(
[](base::WeakPtr<SyntheticGestureController> weak_ptr) {
if (weak_ptr)
@@ -90,7 +89,7 @@ void SyntheticGestureController::StartGesture(const SyntheticGesture& gesture) {
"SyntheticGestureController::running",
&gesture);
if (!dispatch_timer_.IsRunning())
- StartTimer();
+ StartTimer(gesture.AllowHighFrequencyDispatch());
}
void SyntheticGestureController::StopGesture(
diff --git a/chromium/content/browser/renderer_host/input/synthetic_gesture_controller.h b/chromium/content/browser/renderer_host/input/synthetic_gesture_controller.h
index 085fdc353ff..dcc3b8ebcfb 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_gesture_controller.h
+++ b/chromium/content/browser/renderer_host/input/synthetic_gesture_controller.h
@@ -52,7 +52,7 @@ class CONTENT_EXPORT SyntheticGestureController {
private:
friend class SyntheticGestureControllerTestBase;
- void StartTimer();
+ void StartTimer(bool high_frequency);
void StartGesture(const SyntheticGesture& gesture);
void StopGesture(const SyntheticGesture& gesture,
OnGestureCompleteCallback completion_callback,
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 74d0eb047d9..82e72f820ae 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
@@ -676,7 +676,9 @@ class MockSyntheticPointerMouseActionTarget
testing::AssertionResult SyntheticMouseActionDispatchedCorrectly(
const SyntheticPointerActionParams& param,
- int click_count) {
+ int click_count,
+ SyntheticPointerActionParams::Button button =
+ SyntheticPointerActionParams::Button::NO_BUTTON) {
if (type_ != ToWebMouseEventType(param.pointer_action_type())) {
return testing::AssertionFailure()
<< "Pointer type was " << WebInputEvent::GetName(type_)
@@ -690,16 +692,31 @@ class MockSyntheticPointerMouseActionTarget
<< click_count << ".";
}
- if (clickCount_ == 1 && button_ != WebMouseEvent::Button::kLeft) {
- return testing::AssertionFailure()
- << "Pointer button was " << (int)button_ << ", expected "
- << (int)WebMouseEvent::Button::kLeft << ".";
- }
+ if (button_ != WebMouseEvent::Button::kNoButton) {
+ if (param.pointer_action_type() ==
+ SyntheticPointerActionParams::PointerActionType::PRESS ||
+ param.pointer_action_type() ==
+ SyntheticPointerActionParams::PointerActionType::RELEASE) {
+ if (clickCount_ != 1) {
+ return testing::AssertionFailure() << "Pointer click count was "
+ << clickCount_ << ", expected 1.";
+ }
+ }
- if (clickCount_ == 0 && button_ != WebMouseEvent::Button::kNoButton) {
- return testing::AssertionFailure()
- << "Pointer button was " << (int)button_ << ", expected "
- << (int)WebMouseEvent::Button::kNoButton << ".";
+ if (param.pointer_action_type() ==
+ SyntheticPointerActionParams::PointerActionType::MOVE) {
+ if (clickCount_ != 0) {
+ return testing::AssertionFailure() << "Pointer click count was "
+ << clickCount_ << ", expected 0.";
+ }
+ }
+
+ if (button_ !=
+ SyntheticPointerActionParams::GetWebMouseEventButton(button)) {
+ return testing::AssertionFailure()
+ << "Pointer button was " << static_cast<int>(button_)
+ << ", expected " << static_cast<int>(button) << ".";
+ }
}
if ((param.pointer_action_type() ==
@@ -1760,9 +1777,9 @@ TEST_F(SyntheticGestureControllerTest, PointerTouchAction) {
SyntheticPointerActionParams param1 = SyntheticPointerActionParams(
SyntheticPointerActionParams::PointerActionType::PRESS);
param0.set_position(gfx::PointF(54, 89));
- param0.set_index(0);
+ param0.set_pointer_id(0);
param1.set_position(gfx::PointF(79, 132));
- param1.set_index(1);
+ param1.set_pointer_id(1);
param_list.push_back(param0);
param_list.push_back(param1);
SyntheticPointerActionListParams params(param_list);
@@ -1859,8 +1876,8 @@ TEST_F(SyntheticGestureControllerTest, PointerMouseAction) {
EXPECT_EQ(2, num_success_);
EXPECT_EQ(0, num_failure_);
EXPECT_EQ(pointer_mouse_target->num_dispatched_pointer_actions(), 2);
- EXPECT_TRUE(
- pointer_mouse_target->SyntheticMouseActionDispatchedCorrectly(param, 1));
+ EXPECT_TRUE(pointer_mouse_target->SyntheticMouseActionDispatchedCorrectly(
+ param, 1, SyntheticPointerActionParams::Button::LEFT));
// Third, send a mouse move.
param.set_pointer_action_type(
@@ -1875,8 +1892,8 @@ TEST_F(SyntheticGestureControllerTest, PointerMouseAction) {
EXPECT_EQ(3, num_success_);
EXPECT_EQ(0, num_failure_);
EXPECT_EQ(pointer_mouse_target->num_dispatched_pointer_actions(), 3);
- EXPECT_TRUE(
- pointer_mouse_target->SyntheticMouseActionDispatchedCorrectly(param, 1));
+ EXPECT_TRUE(pointer_mouse_target->SyntheticMouseActionDispatchedCorrectly(
+ param, 0, SyntheticPointerActionParams::Button::LEFT));
// Fourth, send a mouse release.
param.set_pointer_action_type(
@@ -1890,8 +1907,8 @@ TEST_F(SyntheticGestureControllerTest, PointerMouseAction) {
EXPECT_EQ(4, num_success_);
EXPECT_EQ(0, num_failure_);
EXPECT_EQ(pointer_mouse_target->num_dispatched_pointer_actions(), 4);
- EXPECT_TRUE(
- pointer_mouse_target->SyntheticMouseActionDispatchedCorrectly(param, 1));
+ EXPECT_TRUE(pointer_mouse_target->SyntheticMouseActionDispatchedCorrectly(
+ param, 1, SyntheticPointerActionParams::Button::LEFT));
}
TEST_F(SyntheticGestureControllerTest, PointerPenAction) {
@@ -1932,8 +1949,8 @@ TEST_F(SyntheticGestureControllerTest, PointerPenAction) {
EXPECT_EQ(2, num_success_);
EXPECT_EQ(0, num_failure_);
EXPECT_EQ(pointer_pen_target->num_dispatched_pointer_actions(), 2);
- EXPECT_TRUE(
- pointer_pen_target->SyntheticMouseActionDispatchedCorrectly(param, 1));
+ EXPECT_TRUE(pointer_pen_target->SyntheticMouseActionDispatchedCorrectly(
+ param, 1, SyntheticPointerActionParams::Button::LEFT));
// Third, send a pen move.
param.set_pointer_action_type(
@@ -1948,8 +1965,8 @@ TEST_F(SyntheticGestureControllerTest, PointerPenAction) {
EXPECT_EQ(3, num_success_);
EXPECT_EQ(0, num_failure_);
EXPECT_EQ(pointer_pen_target->num_dispatched_pointer_actions(), 3);
- EXPECT_TRUE(
- pointer_pen_target->SyntheticMouseActionDispatchedCorrectly(param, 1));
+ EXPECT_TRUE(pointer_pen_target->SyntheticMouseActionDispatchedCorrectly(
+ param, 0, SyntheticPointerActionParams::Button::LEFT));
// Fourth, send a pen release.
param.set_pointer_action_type(
@@ -1963,8 +1980,8 @@ TEST_F(SyntheticGestureControllerTest, PointerPenAction) {
EXPECT_EQ(4, num_success_);
EXPECT_EQ(0, num_failure_);
EXPECT_EQ(pointer_pen_target->num_dispatched_pointer_actions(), 4);
- EXPECT_TRUE(
- pointer_pen_target->SyntheticMouseActionDispatchedCorrectly(param, 1));
+ EXPECT_TRUE(pointer_pen_target->SyntheticMouseActionDispatchedCorrectly(
+ param, 1, SyntheticPointerActionParams::Button::LEFT));
// Fifth, send a pen leave.
param.set_pointer_action_type(
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 4a48a9684bc..3ae84c103c5 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_mouse_driver.cc
+++ b/chromium/content/browser/renderer_host/input/synthetic_mouse_driver.cc
@@ -41,13 +41,13 @@ void SyntheticMouseDriver::Press(float x,
void SyntheticMouseDriver::Move(float x, float y, int index) {
DCHECK_EQ(index, 0);
- blink::WebMouseEvent::Button button = mouse_event_.button;
- int click_count = mouse_event_.click_count;
mouse_event_ = SyntheticWebMouseEventBuilder::Build(
blink::WebInputEvent::kMouseMove, x, y, last_modifiers_,
mouse_event_.pointer_type);
- mouse_event_.button = button;
- mouse_event_.click_count = click_count;
+ mouse_event_.button =
+ SyntheticPointerActionParams::GetWebMouseEventButtonFromModifier(
+ last_modifiers_);
+ mouse_event_.click_count = 0;
}
void SyntheticMouseDriver::Release(
@@ -72,9 +72,6 @@ void SyntheticMouseDriver::Leave(int index) {
bool SyntheticMouseDriver::UserInputCheck(
const SyntheticPointerActionParams& params) const {
- if (params.index() != 0)
- return false;
-
if (params.pointer_action_type() ==
SyntheticPointerActionParams::PointerActionType::NOT_INITIALIZED) {
return false;
@@ -90,9 +87,6 @@ bool SyntheticMouseDriver::UserInputCheck(
if (params.pointer_action_type() ==
SyntheticPointerActionParams::PointerActionType::RELEASE) {
- if (mouse_event_.click_count <= 0)
- return false;
-
int modifiers =
SyntheticPointerActionParams::GetWebMouseEventModifier(params.button());
if (!(last_modifiers_ & modifiers))
diff --git a/chromium/content/browser/renderer_host/input/synthetic_pointer_action.cc b/chromium/content/browser/renderer_host/input/synthetic_pointer_action.cc
index 65dccb01a30..9e889dabb22 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_pointer_action.cc
+++ b/chromium/content/browser/renderer_host/input/synthetic_pointer_action.cc
@@ -47,6 +47,10 @@ SyntheticGesture::Result SyntheticPointerAction::ForwardInputEvents(
: SyntheticGesture::GESTURE_RUNNING;
}
+bool SyntheticPointerAction::AllowHighFrequencyDispatch() const {
+ return false;
+}
+
SyntheticPointerAction::GestureState
SyntheticPointerAction::ForwardTouchOrMouseInputEvents(
const base::TimeTicks& timestamp,
@@ -64,18 +68,18 @@ SyntheticPointerAction::ForwardTouchOrMouseInputEvents(
switch (param.pointer_action_type()) {
case SyntheticPointerActionParams::PointerActionType::PRESS:
synthetic_pointer_driver_->Press(param.position().x(),
- param.position().y(), param.index(),
- param.button());
+ param.position().y(),
+ param.pointer_id(), param.button());
break;
case SyntheticPointerActionParams::PointerActionType::MOVE:
- synthetic_pointer_driver_->Move(param.position().x(),
- param.position().y(), param.index());
+ synthetic_pointer_driver_->Move(
+ param.position().x(), param.position().y(), param.pointer_id());
break;
case SyntheticPointerActionParams::PointerActionType::RELEASE:
- synthetic_pointer_driver_->Release(param.index(), param.button());
+ synthetic_pointer_driver_->Release(param.pointer_id(), param.button());
break;
case SyntheticPointerActionParams::PointerActionType::LEAVE:
- synthetic_pointer_driver_->Leave(param.index());
+ synthetic_pointer_driver_->Leave(param.pointer_id());
break;
case SyntheticPointerActionParams::PointerActionType::IDLE:
break;
diff --git a/chromium/content/browser/renderer_host/input/synthetic_pointer_action.h b/chromium/content/browser/renderer_host/input/synthetic_pointer_action.h
index 39b3656d7c5..e836a08de98 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_pointer_action.h
+++ b/chromium/content/browser/renderer_host/input/synthetic_pointer_action.h
@@ -24,6 +24,7 @@ class CONTENT_EXPORT SyntheticPointerAction : public SyntheticGesture {
SyntheticGesture::Result ForwardInputEvents(
const base::TimeTicks& timestamp,
SyntheticGestureTarget* target) override;
+ bool AllowHighFrequencyDispatch() const override;
private:
enum GestureState { UNINITIALIZED, RUNNING, INVALID, DONE };
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 8f480dd77dc..7b66c3bff07 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
@@ -145,10 +145,10 @@ class MockSyntheticPointerTouchActionTarget
SyntheticPointerActionParams::PointerActionType::PRESS ||
param.pointer_action_type() ==
SyntheticPointerActionParams::PointerActionType::MOVE) {
- if (indexes_[index] != param.index()) {
+ if (indexes_[index] != param.pointer_id()) {
return testing::AssertionFailure()
<< "Pointer index at index " << index << " was "
- << indexes_[index] << ", expected " << param.index() << ".";
+ << indexes_[index] << ", expected " << param.pointer_id() << ".";
}
if (positions_[index] != param.position()) {
@@ -193,7 +193,7 @@ class MockSyntheticPointerTouchActionTarget
private:
int num_dispatched_pointer_actions_;
gfx::PointF positions_[WebTouchEvent::kTouchesLengthCap];
- int indexes_[WebTouchEvent::kTouchesLengthCap];
+ uint32_t indexes_[WebTouchEvent::kTouchesLengthCap];
WebTouchPoint::State states_[WebTouchEvent::kTouchesLengthCap];
};
@@ -217,6 +217,8 @@ class MockSyntheticPointerMouseActionTarget
const SyntheticPointerActionParams& param,
int click_count,
std::vector<SyntheticPointerActionParams::Button> buttons,
+ SyntheticPointerActionParams::Button button =
+ SyntheticPointerActionParams::Button::NO_BUTTON,
SyntheticGestureParams::GestureSourceType source_type =
SyntheticGestureParams::MOUSE_INPUT) {
if (GetDefaultSyntheticGestureSourceType() != source_type) {
@@ -239,9 +241,25 @@ class MockSyntheticPointerMouseActionTarget
<< click_count << ".";
}
- if (click_count_ == 1) {
- DCHECK_GT(buttons.size(), 0U);
- SyntheticPointerActionParams::Button button = buttons[buttons.size() - 1];
+ if (button_ != WebMouseEvent::Button::kNoButton) {
+ if (param.pointer_action_type() ==
+ SyntheticPointerActionParams::PointerActionType::PRESS ||
+ param.pointer_action_type() ==
+ SyntheticPointerActionParams::PointerActionType::RELEASE) {
+ if (click_count_ != 1) {
+ return testing::AssertionFailure() << "Pointer click count was "
+ << click_count_ << ", expected 1.";
+ }
+ }
+
+ if (param.pointer_action_type() ==
+ SyntheticPointerActionParams::PointerActionType::MOVE) {
+ if (click_count_ != 0) {
+ return testing::AssertionFailure() << "Pointer click count was "
+ << click_count_ << ", expected 0.";
+ }
+ }
+
if (button_ !=
SyntheticPointerActionParams::GetWebMouseEventButton(button)) {
return testing::AssertionFailure()
@@ -250,14 +268,6 @@ class MockSyntheticPointerMouseActionTarget
}
}
- if (click_count_ == 0 && button_ != WebMouseEvent::Button::kNoButton) {
- DCHECK_EQ(buttons.size(), 0U);
- return testing::AssertionFailure()
- << "Pointer button was " << static_cast<int>(button_)
- << ", expected "
- << static_cast<int>(WebMouseEvent::Button::kNoButton) << ".";
- }
-
int modifiers = 0;
for (size_t index = 0; index < buttons.size(); ++index)
modifiers |= SyntheticPointerActionParams::GetWebMouseEventModifier(
@@ -346,7 +356,7 @@ TEST_F(SyntheticPointerActionTest, PointerTouchAction) {
// Send a touch press for one finger.
SyntheticPointerActionParams param1 = SyntheticPointerActionParams(
SyntheticPointerActionParams::PointerActionType::PRESS);
- param1.set_index(0);
+ param1.set_pointer_id(0);
param1.set_position(gfx::PointF(54, 89));
SyntheticPointerActionListParams::ParamList param_list1;
param_list1.push_back(param1);
@@ -359,7 +369,7 @@ TEST_F(SyntheticPointerActionTest, PointerTouchAction) {
param1.set_position(gfx::PointF(133, 156));
SyntheticPointerActionParams param2 = SyntheticPointerActionParams(
SyntheticPointerActionParams::PointerActionType::PRESS);
- param2.set_index(1);
+ param2.set_pointer_id(1);
param2.set_position(gfx::PointF(79, 132));
SyntheticPointerActionListParams::ParamList param_list2;
param_list2.push_back(param1);
@@ -429,7 +439,7 @@ TEST_F(SyntheticPointerActionTest, PointerTouchActionsMultiPressRelease) {
// Send a touch press for one finger.
SyntheticPointerActionParams param1 = SyntheticPointerActionParams(
SyntheticPointerActionParams::PointerActionType::PRESS);
- param1.set_index(0);
+ param1.set_pointer_id(0);
param1.set_position(gfx::PointF(54, 89));
SyntheticPointerActionListParams::ParamList param_list1;
param_list1.push_back(param1);
@@ -437,7 +447,7 @@ TEST_F(SyntheticPointerActionTest, PointerTouchActionsMultiPressRelease) {
SyntheticPointerActionParams param2 = SyntheticPointerActionParams(
SyntheticPointerActionParams::PointerActionType::PRESS);
- param2.set_index(1);
+ param2.set_pointer_id(1);
param2.set_position(gfx::PointF(123, 69));
param1.set_pointer_action_type(
SyntheticPointerActionParams::PointerActionType::IDLE);
@@ -497,7 +507,7 @@ TEST_F(SyntheticPointerActionTest, PointerTouchActionTypeInvalid) {
// first.
SyntheticPointerActionParams param = SyntheticPointerActionParams(
SyntheticPointerActionParams::PointerActionType::MOVE);
- param.set_index(0);
+ param.set_pointer_id(0);
param.set_position(gfx::PointF(54, 89));
params_.PushPointerActionParams(param);
pointer_action_.reset(new SyntheticPointerAction(params_));
@@ -580,19 +590,19 @@ TEST_F(SyntheticPointerActionTest, PointerMouseAction) {
EXPECT_EQ(0, num_failure_);
buttons.push_back(SyntheticPointerActionParams::Button::LEFT);
EXPECT_TRUE(pointer_mouse_target->SyntheticMouseActionDispatchedCorrectly(
- param2, 1, buttons));
+ param2, 1, buttons, SyntheticPointerActionParams::Button::LEFT));
ForwardSyntheticPointerAction();
EXPECT_EQ(3, num_success_);
EXPECT_EQ(0, num_failure_);
EXPECT_TRUE(pointer_mouse_target->SyntheticMouseActionDispatchedCorrectly(
- param3, 1, buttons));
+ param3, 0, buttons, SyntheticPointerActionParams::Button::LEFT));
ForwardSyntheticPointerAction();
EXPECT_EQ(4, num_success_);
EXPECT_EQ(0, num_failure_);
EXPECT_TRUE(pointer_mouse_target->SyntheticMouseActionDispatchedCorrectly(
- param4, 1, buttons));
+ param4, 1, buttons, SyntheticPointerActionParams::Button::LEFT));
}
TEST_F(SyntheticPointerActionTest, PointerMouseActionMultiPress) {
@@ -605,25 +615,36 @@ TEST_F(SyntheticPointerActionTest, PointerMouseActionMultiPress) {
param1.set_button(SyntheticPointerActionParams::Button::LEFT);
params_.PushPointerActionParams(param1);
- // Press a mouse's middle button.
+ // Move the mouse while left button is pressed.
SyntheticPointerActionParams param2 = SyntheticPointerActionParams(
- SyntheticPointerActionParams::PointerActionType::PRESS);
- param2.set_position(gfx::PointF(189, 62));
- param2.set_button(SyntheticPointerActionParams::Button::MIDDLE);
+ SyntheticPointerActionParams::PointerActionType::MOVE);
+ param2.set_position(gfx::PointF(139, 98));
params_.PushPointerActionParams(param2);
- // Release a mouse's middle button.
+ // Press the mouse's middle button.
SyntheticPointerActionParams param3 = SyntheticPointerActionParams(
- SyntheticPointerActionParams::PointerActionType::RELEASE);
+ SyntheticPointerActionParams::PointerActionType::PRESS);
+ param3.set_position(gfx::PointF(139, 98));
param3.set_button(SyntheticPointerActionParams::Button::MIDDLE);
params_.PushPointerActionParams(param3);
- pointer_action_.reset(new SyntheticPointerAction(params_));
- // Release a mouse's middle button.
+ // Move the mouse while left and middle buttons are pressed.
SyntheticPointerActionParams param4 = SyntheticPointerActionParams(
- SyntheticPointerActionParams::PointerActionType::RELEASE);
- param4.set_button(SyntheticPointerActionParams::Button::LEFT);
+ SyntheticPointerActionParams::PointerActionType::MOVE);
+ param4.set_position(gfx::PointF(86, 69));
params_.PushPointerActionParams(param4);
+
+ // Release a mouse's middle button.
+ SyntheticPointerActionParams param5 = SyntheticPointerActionParams(
+ SyntheticPointerActionParams::PointerActionType::RELEASE);
+ param5.set_button(SyntheticPointerActionParams::Button::MIDDLE);
+ params_.PushPointerActionParams(param5);
+
+ // Release a mouse's left button.
+ SyntheticPointerActionParams param6 = SyntheticPointerActionParams(
+ SyntheticPointerActionParams::PointerActionType::RELEASE);
+ param6.set_button(SyntheticPointerActionParams::Button::LEFT);
+ params_.PushPointerActionParams(param6);
pointer_action_.reset(new SyntheticPointerAction(params_));
ForwardSyntheticPointerAction();
@@ -634,27 +655,41 @@ TEST_F(SyntheticPointerActionTest, PointerMouseActionMultiPress) {
std::vector<SyntheticPointerActionParams::Button> buttons(
1, SyntheticPointerActionParams::Button::LEFT);
EXPECT_TRUE(pointer_mouse_target->SyntheticMouseActionDispatchedCorrectly(
- param1, 1, buttons));
+ param1, 1, buttons, SyntheticPointerActionParams::Button::LEFT));
ForwardSyntheticPointerAction();
EXPECT_EQ(2, num_success_);
EXPECT_EQ(0, num_failure_);
- buttons.push_back(SyntheticPointerActionParams::Button::MIDDLE);
+ buttons.push_back(SyntheticPointerActionParams::Button::LEFT);
EXPECT_TRUE(pointer_mouse_target->SyntheticMouseActionDispatchedCorrectly(
- param2, 1, buttons));
+ param2, 0, buttons, SyntheticPointerActionParams::Button::LEFT));
ForwardSyntheticPointerAction();
EXPECT_EQ(3, num_success_);
EXPECT_EQ(0, num_failure_);
+ buttons.push_back(SyntheticPointerActionParams::Button::MIDDLE);
EXPECT_TRUE(pointer_mouse_target->SyntheticMouseActionDispatchedCorrectly(
- param3, 1, buttons));
+ param3, 1, buttons, SyntheticPointerActionParams::Button::MIDDLE));
ForwardSyntheticPointerAction();
EXPECT_EQ(4, num_success_);
EXPECT_EQ(0, num_failure_);
+ EXPECT_TRUE(pointer_mouse_target->SyntheticMouseActionDispatchedCorrectly(
+ param4, 0, buttons, SyntheticPointerActionParams::Button::MIDDLE));
+
+ ForwardSyntheticPointerAction();
+ EXPECT_EQ(5, num_success_);
+ EXPECT_EQ(0, num_failure_);
+ EXPECT_TRUE(pointer_mouse_target->SyntheticMouseActionDispatchedCorrectly(
+ param5, 1, buttons, SyntheticPointerActionParams::Button::MIDDLE));
buttons.pop_back();
+
+ ForwardSyntheticPointerAction();
+ EXPECT_EQ(6, num_success_);
+ EXPECT_EQ(0, num_failure_);
EXPECT_TRUE(pointer_mouse_target->SyntheticMouseActionDispatchedCorrectly(
- param4, 1, buttons));
+ param6, 1, buttons, SyntheticPointerActionParams::Button::LEFT));
+ buttons.pop_back();
}
TEST_F(SyntheticPointerActionTest, PointerMouseActionTypeInvalid) {
@@ -689,7 +724,7 @@ TEST_F(SyntheticPointerActionTest, PointerMouseActionTypeInvalid) {
std::vector<SyntheticPointerActionParams::Button> buttons(
1, SyntheticPointerActionParams::Button::LEFT);
EXPECT_TRUE(pointer_mouse_target->SyntheticMouseActionDispatchedCorrectly(
- param, 1, buttons));
+ param, 1, buttons, SyntheticPointerActionParams::Button::LEFT));
ForwardSyntheticPointerAction();
EXPECT_EQ(1, num_success_);
@@ -729,27 +764,31 @@ TEST_F(SyntheticPointerActionTest, PointerPenAction) {
EXPECT_EQ(0, num_failure_);
std::vector<SyntheticPointerActionParams::Button> buttons;
EXPECT_TRUE(pointer_pen_target->SyntheticMouseActionDispatchedCorrectly(
- param1, 0, buttons, SyntheticGestureParams::PEN_INPUT));
+ param1, 0, buttons, SyntheticPointerActionParams::Button::NO_BUTTON,
+ SyntheticGestureParams::PEN_INPUT));
ForwardSyntheticPointerAction();
EXPECT_EQ(2, num_success_);
EXPECT_EQ(0, num_failure_);
buttons.push_back(SyntheticPointerActionParams::Button::LEFT);
EXPECT_TRUE(pointer_pen_target->SyntheticMouseActionDispatchedCorrectly(
- param2, 1, buttons, SyntheticGestureParams::PEN_INPUT));
+ param2, 1, buttons, SyntheticPointerActionParams::Button::LEFT,
+ SyntheticGestureParams::PEN_INPUT));
ForwardSyntheticPointerAction();
EXPECT_EQ(3, num_success_);
EXPECT_EQ(0, num_failure_);
EXPECT_TRUE(pointer_pen_target->SyntheticMouseActionDispatchedCorrectly(
- param3, 1, buttons, SyntheticGestureParams::PEN_INPUT));
+ param3, 1, buttons, SyntheticPointerActionParams::Button::LEFT,
+ SyntheticGestureParams::PEN_INPUT));
ForwardSyntheticPointerAction();
EXPECT_EQ(4, num_success_);
EXPECT_EQ(0, num_failure_);
buttons.pop_back();
EXPECT_TRUE(pointer_pen_target->SyntheticMouseActionDispatchedCorrectly(
- param4, 0, buttons, SyntheticGestureParams::PEN_INPUT));
+ param4, 0, buttons, SyntheticPointerActionParams::Button::NO_BUTTON,
+ SyntheticGestureParams::PEN_INPUT));
}
TEST_F(SyntheticPointerActionTest, EmptyParams) {
diff --git a/chromium/content/browser/renderer_host/input/synthetic_tap_gesture.cc b/chromium/content/browser/renderer_host/input/synthetic_tap_gesture.cc
index 80503e564d7..54b70a02bb2 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_tap_gesture.cc
+++ b/chromium/content/browser/renderer_host/input/synthetic_tap_gesture.cc
@@ -46,6 +46,10 @@ SyntheticGesture::Result SyntheticTapGesture::ForwardInputEvents(
: SyntheticGesture::GESTURE_RUNNING;
}
+bool SyntheticTapGesture::AllowHighFrequencyDispatch() const {
+ return false;
+}
+
void SyntheticTapGesture::ForwardTouchOrMouseInputEvents(
const base::TimeTicks& timestamp, SyntheticGestureTarget* target) {
switch (state_) {
diff --git a/chromium/content/browser/renderer_host/input/synthetic_tap_gesture.h b/chromium/content/browser/renderer_host/input/synthetic_tap_gesture.h
index 03d4f470f26..b3d2bfc5ee8 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_tap_gesture.h
+++ b/chromium/content/browser/renderer_host/input/synthetic_tap_gesture.h
@@ -22,6 +22,7 @@ class CONTENT_EXPORT SyntheticTapGesture : public SyntheticGesture {
SyntheticGesture::Result ForwardInputEvents(
const base::TimeTicks& timestamp,
SyntheticGestureTarget* target) override;
+ bool AllowHighFrequencyDispatch() const override;
private:
enum GestureState {
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 c16c6e00c9c..e4b16def1f7 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_touch_driver.cc
+++ b/chromium/content/browser/renderer_host/input/synthetic_touch_driver.cc
@@ -8,14 +8,10 @@
namespace content {
-SyntheticTouchDriver::SyntheticTouchDriver() {
- std::fill(index_map_.begin(), index_map_.end(), -1);
-}
+SyntheticTouchDriver::SyntheticTouchDriver() {}
SyntheticTouchDriver::SyntheticTouchDriver(SyntheticWebTouchEvent touch_event)
- : touch_event_(touch_event) {
- std::fill(index_map_.begin(), index_map_.end(), -1);
-}
+ : touch_event_(touch_event) {}
SyntheticTouchDriver::~SyntheticTouchDriver() {}
@@ -25,7 +21,7 @@ void SyntheticTouchDriver::DispatchEvent(SyntheticGestureTarget* target,
if (touch_event_.GetType() != blink::WebInputEvent::kUndefined)
target->DispatchInputEventToPlatform(touch_event_);
touch_event_.ResetPoints();
- ResetIndexMap();
+ ResetPointerIdIndexMap();
}
void SyntheticTouchDriver::Press(float x,
@@ -33,24 +29,25 @@ void SyntheticTouchDriver::Press(float x,
int index,
SyntheticPointerActionParams::Button button) {
DCHECK_GE(index, 0);
- DCHECK_LT(index, blink::WebTouchEvent::kTouchesLengthCap);
+ DCHECK(pointer_id_map_.find(index) == pointer_id_map_.end());
int touch_index = touch_event_.PressPoint(x, y);
- index_map_[index] = touch_index;
+ touch_event_.touches[touch_index].id = index;
+ pointer_id_map_[index] = touch_index;
}
void SyntheticTouchDriver::Move(float x, float y, int index) {
DCHECK_GE(index, 0);
- DCHECK_LT(index, blink::WebTouchEvent::kTouchesLengthCap);
- touch_event_.MovePoint(index_map_[index], x, y);
+ DCHECK(pointer_id_map_.find(index) != pointer_id_map_.end());
+ touch_event_.MovePoint(pointer_id_map_[index], x, y);
}
void SyntheticTouchDriver::Release(
int index,
SyntheticPointerActionParams::Button button) {
DCHECK_GE(index, 0);
- DCHECK_LT(index, blink::WebTouchEvent::kTouchesLengthCap);
- touch_event_.ReleasePoint(index_map_[index]);
- index_map_[index] = -1;
+ DCHECK(pointer_id_map_.find(index) != pointer_id_map_.end());
+ touch_event_.ReleasePoint(pointer_id_map_[index]);
+ pointer_id_map_.erase(index);
}
void SyntheticTouchDriver::Leave(int index) {
@@ -59,10 +56,6 @@ void SyntheticTouchDriver::Leave(int index) {
bool SyntheticTouchDriver::UserInputCheck(
const SyntheticPointerActionParams& params) const {
- if (params.index() < 0 ||
- params.index() >= blink::WebTouchEvent::kTouchesLengthCap)
- return false;
-
if (params.pointer_action_type() ==
SyntheticPointerActionParams::PointerActionType::NOT_INITIALIZED) {
return false;
@@ -70,26 +63,26 @@ bool SyntheticTouchDriver::UserInputCheck(
if (params.pointer_action_type() ==
SyntheticPointerActionParams::PointerActionType::PRESS &&
- index_map_[params.index()] >= 0) {
+ pointer_id_map_.find(params.pointer_id()) != pointer_id_map_.end()) {
return false;
}
if (params.pointer_action_type() ==
SyntheticPointerActionParams::PointerActionType::MOVE &&
- index_map_[params.index()] == -1) {
+ pointer_id_map_.find(params.pointer_id()) == pointer_id_map_.end()) {
return false;
}
if (params.pointer_action_type() ==
SyntheticPointerActionParams::PointerActionType::RELEASE &&
- index_map_[params.index()] == -1) {
+ pointer_id_map_.find(params.pointer_id()) == pointer_id_map_.end()) {
return false;
}
return true;
}
-void SyntheticTouchDriver::ResetIndexMap() {
+void SyntheticTouchDriver::ResetPointerIdIndexMap() {
unsigned free_index = 0;
for (unsigned int i = 0; i < blink::WebTouchEvent::kTouchesLengthCap; ++i) {
if (free_index >= touch_event_.touches_length)
@@ -97,18 +90,22 @@ void SyntheticTouchDriver::ResetIndexMap() {
if (touch_event_.touches[i].state !=
blink::WebTouchPoint::kStateUndefined) {
touch_event_.touches[free_index] = touch_event_.touches[i];
- int index = GetIndexFromMap(i);
- index_map_[index] = free_index;
+ int pointer_id = GetIndexFromMap(i);
+ pointer_id_map_[pointer_id] = free_index;
free_index++;
}
}
}
int SyntheticTouchDriver::GetIndexFromMap(int value) const {
- int index = std::find(index_map_.begin(), index_map_.end(), value) -
- index_map_.begin();
- DCHECK(index >= 0 && index < blink::WebTouchEvent::kTouchesLengthCap);
- return index;
+ PointerIdIndexMap::const_iterator it;
+ for (it = pointer_id_map_.begin(); it != pointer_id_map_.end(); ++it) {
+ if (it->second == value) {
+ return it->first;
+ }
+ }
+ NOTREACHED() << "Failed to find the value.";
+ return -1;
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/synthetic_touch_driver.h b/chromium/content/browser/renderer_host/input/synthetic_touch_driver.h
index 3f8102a212d..bd2e8ececbc 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_touch_driver.h
+++ b/chromium/content/browser/renderer_host/input/synthetic_touch_driver.h
@@ -37,13 +37,13 @@ class CONTENT_EXPORT SyntheticTouchDriver : public SyntheticPointerDriver {
const SyntheticPointerActionParams& params) const override;
private:
- using IndexMap = std::array<int, blink::WebTouchEvent::kTouchesLengthCap>;
+ using PointerIdIndexMap = std::map<int, int>;
- void ResetIndexMap();
+ void ResetPointerIdIndexMap();
int GetIndexFromMap(int value) const;
SyntheticWebTouchEvent touch_event_;
- IndexMap index_map_;
+ PointerIdIndexMap pointer_id_map_;
DISALLOW_COPY_AND_ASSIGN(SyntheticTouchDriver);
};
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 41c2c94fe34..835b0d6c7f0 100644
--- a/chromium/content/browser/renderer_host/input/touch_action_browsertest.cc
+++ b/chromium/content/browser/renderer_host/input/touch_action_browsertest.cc
@@ -7,6 +7,7 @@
#include "base/auto_reset.h"
#include "base/bind.h"
#include "base/command_line.h"
+#include "base/json/json_reader.h"
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
@@ -18,7 +19,9 @@
#include "content/browser/renderer_host/render_widget_host_impl.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/actions_parser.h"
#include "content/common/input/synthetic_gesture_params.h"
+#include "content/common/input/synthetic_pointer_action_list_params.h"
#include "content/common/input/synthetic_smooth_scroll_gesture_params.h"
#include "content/common/input_messages.h"
#include "content/public/browser/render_view_host.h"
@@ -168,9 +171,6 @@ class TouchActionBrowserTest : public ContentBrowserTest {
void SetUpCommandLine(base::CommandLine* cmd) override {
cmd->AppendSwitchASCII(switches::kTouchEventFeatureDetection,
switches::kTouchEventFeatureDetectionEnabled);
- // TODO(rbyers): Remove this switch once touch-action ships.
- // http://crbug.com/241964
- cmd->AppendSwitch(switches::kEnableExperimentalWebPlatformFeatures);
}
// ContentBrowserTest:
@@ -319,6 +319,45 @@ class TouchActionBrowserTest : public ContentBrowserTest {
expected_scroll_position_after_scroll);
}
+ // Generate touch events for a double tap and drag zoom gesture at
+ // coordinates (50, 50).
+ void DoDoubleTapDragZoom() {
+ DCHECK(URLLoaded());
+
+ const std::string pointer_actions_json = R"HTML(
+ [{
+ "source": "touch",
+ "actions": [
+ { "name": "pointerDown", "x": 50, "y": 50 },
+ { "name": "pointerUp" },
+ { "name": "pause", "duration": 0.05 },
+ { "name": "pointerDown", "x": 50, "y": 50 },
+ { "name": "pointerMove", "x": 50, "y": 150 },
+ { "name": "pointerUp" }
+ ]
+ }]
+ )HTML";
+
+ base::JSONReader json_reader;
+ std::unique_ptr<base::Value> params =
+ json_reader.ReadToValue(pointer_actions_json);
+ ASSERT_TRUE(params.get()) << json_reader.GetErrorMessage();
+ ActionsParser actions_parser(params.get());
+
+ ASSERT_TRUE(actions_parser.ParsePointerActionSequence());
+
+ run_loop_ = std::make_unique<base::RunLoop>();
+
+ GetWidgetHost()->QueueSyntheticGesture(
+ SyntheticGesture::Create(actions_parser.gesture_params()),
+ base::BindOnce(&TouchActionBrowserTest::OnSyntheticGestureCompleted,
+ base::Unretained(this)));
+
+ // Runs until we get the OnSyntheticGestureCompleted callback
+ run_loop_->Run();
+ run_loop_.reset();
+ }
+
private:
void CheckScrollOffset(
bool wait_until_scrolled,
@@ -535,4 +574,43 @@ IN_PROC_BROWSER_TEST_F(TouchActionBrowserTest,
gfx::Vector2d(45, 0), kShortJankTime);
}
+namespace {
+
+const std::string kDoubleTapZoomDataURL = R"HTML(
+ data:text/html,<!DOCTYPE html>
+ <meta name='viewport' content='width=device-width'/>
+ <style>
+ html, body {
+ margin: 0;
+ }
+ .spacer { height: 10000px; }
+ .touchaction { width: 75px; height: 75px; touch-action: none; }
+ </style>
+ <div class="touchaction"></div>
+ <div class=spacer></div>
+ <script>
+ document.title='ready';
+ </script>)HTML";
+
+} // namespace
+
+// Test that |touch-action: none| correctly blocks a double-tap and drag zoom
+// gesture.
+IN_PROC_BROWSER_TEST_F(TouchActionBrowserTest, BlockDoubleTapDragZoom) {
+ LoadURL(kDoubleTapZoomDataURL.c_str());
+
+ ASSERT_EQ(1, ExecuteScriptAndExtractDouble("window.visualViewport.scale"));
+
+ DoDoubleTapDragZoom();
+
+ // Since we don't expect anything to change, we don't know how long to wait
+ // before we're sure the zoom was blocked. Do a scroll so that we can wait
+ // until the offset changes. At that point, we know the zoom should have
+ // taken effect if it wasn't blocked by touch-action.
+ DoTouchScroll(gfx::Point(300, 300), gfx::Vector2d(0, 200), true, 10075,
+ gfx::Vector2d(0, 200), kNoJankTime);
+
+ EXPECT_EQ(1, ExecuteScriptAndExtractDouble("window.visualViewport.scale"));
+}
+
} // 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 8a35a81229d..c420cf79179 100644
--- a/chromium/content/browser/renderer_host/input/touch_action_filter.cc
+++ b/chromium/content/browser/renderer_host/input/touch_action_filter.cc
@@ -9,6 +9,7 @@
#include "base/debug/crash_logging.h"
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
+#include "base/strings/string_number_conversions.h"
#include "third_party/blink/public/platform/web_gesture_event.h"
using blink::WebInputEvent;
@@ -62,14 +63,13 @@ FilterGestureEventResult TouchActionFilter::FilterGestureEvent(
if (!scrolling_touch_action_.has_value())
SetTouchAction(cc::kTouchActionAuto);
}
+ gesture_scroll_in_progress_ = true;
gesture_sequence_.append("B");
if (!scrolling_touch_action_.has_value()) {
static auto* crash_key = base::debug::AllocateCrashKeyString(
"scrollbegin-gestures", base::debug::CrashKeySize::Size256);
base::debug::SetCrashKeyString(crash_key, gesture_sequence_);
gesture_sequence_.clear();
- // https://crbug.com/869375, temporary fix to prevent crash.
- SetTouchAction(cc::kTouchActionAuto);
}
suppress_manipulation_events_ =
ShouldSuppressManipulation(*gesture_event);
@@ -96,8 +96,6 @@ FilterGestureEventResult TouchActionFilter::FilterGestureEvent(
"scrollupdate-gestures", base::debug::CrashKeySize::Size256);
base::debug::SetCrashKeyString(crash_key, gesture_sequence_);
gesture_sequence_.clear();
- // https://crbug.com/869375, temporary fix to prevent crash.
- SetTouchAction(cc::kTouchActionAuto);
}
if (IsYAxisActionDisallowed(scrolling_touch_action_.value())) {
gesture_event->data.scroll_update.delta_y = 0;
@@ -117,6 +115,7 @@ FilterGestureEventResult TouchActionFilter::FilterGestureEvent(
case WebInputEvent::kGestureScrollEnd:
gesture_sequence_.clear();
+ gesture_scroll_in_progress_ = false;
gesture_sequence_in_progress_ = false;
ReportGestureEventFiltered(suppress_manipulation_events_);
return FilterManipulationEventAndResetState()
@@ -124,22 +123,50 @@ FilterGestureEventResult TouchActionFilter::FilterGestureEvent(
: FilterGestureEventResult::kFilterGestureEventAllowed;
case WebInputEvent::kGesturePinchBegin:
+ if (!gesture_scroll_in_progress_) {
+ suppress_manipulation_events_ =
+ ShouldSuppressManipulation(*gesture_event);
+ }
+ FALLTHROUGH;
case WebInputEvent::kGesturePinchUpdate:
- case WebInputEvent::kGesturePinchEnd:
gesture_sequence_.append("P");
ReportGestureEventFiltered(suppress_manipulation_events_);
return suppress_manipulation_events_
? FilterGestureEventResult::kFilterGestureEventFiltered
: FilterGestureEventResult::kFilterGestureEventAllowed;
+ case WebInputEvent::kGesturePinchEnd:
+ ReportGestureEventFiltered(suppress_manipulation_events_);
+ // If we're in a double-tap and drag zoom, we won't be bracketed between
+ // a GSB/GSE pair so end the sequence now. Otherwise this will happen
+ // when we get the GSE.
+ if (!gesture_scroll_in_progress_) {
+ gesture_sequence_.clear();
+ gesture_sequence_in_progress_ = false;
+ return FilterManipulationEventAndResetState()
+ ? FilterGestureEventResult::kFilterGestureEventFiltered
+ : FilterGestureEventResult::kFilterGestureEventAllowed;
+ }
+ 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.
+ // The double tap gesture is a tap ending event. If a double-tap gesture is
+ // filtered out, replace it with a tap event but preserve the tap-count to
+ // allow firing dblclick event in Blink.
+ //
+ // TODO(mustaq): This replacement of a double-tap gesture with a tap seems
+ // buggy, it produces an inconsistent gesture event stream: GestureTapCancel
+ // followed by GestureTap. See crbug.com/874474#c47 for a repro. We don't
+ // know of any bug resulting from it, but it's better to fix the broken
+ // assumption here at least to avoid introducing new bugs in future.
case WebInputEvent::kGestureDoubleTap:
gesture_sequence_in_progress_ = false;
gesture_sequence_.append("D");
DCHECK_EQ(1, gesture_event->data.tap.tap_count);
- if (!allow_current_double_tap_event_)
+ if (!allow_current_double_tap_event_) {
gesture_event->SetType(WebInputEvent::kGestureTap);
+ gesture_event->data.tap.tap_count = 2;
+ }
allow_current_double_tap_event_ = true;
break;
@@ -152,8 +179,6 @@ FilterGestureEventResult TouchActionFilter::FilterGestureEvent(
"tapunconfirmed-gestures", base::debug::CrashKeySize::Size256);
base::debug::SetCrashKeyString(crash_key, gesture_sequence_);
gesture_sequence_.clear();
- // https://crbug.com/869375, temporary fix to prevent crash.
- SetTouchAction(cc::kTouchActionAuto);
}
allow_current_double_tap_event_ = (scrolling_touch_action_.value() &
cc::kTouchActionDoubleTapZoom) != 0;
@@ -185,13 +210,18 @@ FilterGestureEventResult TouchActionFilter::FilterGestureEvent(
gesture_sequence_in_progress_ = true;
// If the gesture is hitting a region that has a non-blocking (such as a
// passive) event listener.
- if (gesture_event->is_source_touch_event_set_non_blocking)
+ // In theory, the num_of_active_touches_ should be > 0 at this point. But
+ // crash reports suggest otherwise.
+ if (gesture_event->is_source_touch_event_set_non_blocking ||
+ num_of_active_touches_ <= 0)
SetTouchAction(cc::kTouchActionAuto);
scrolling_touch_action_ = allowed_touch_action_;
if (scrolling_touch_action_.has_value())
- gesture_sequence_.append("O1");
+ gesture_sequence_.append("OY");
else
- gesture_sequence_.append("O2");
+ gesture_sequence_.append("ON");
+ gesture_sequence_.append(
+ base::NumberToString(gesture_event->unique_touch_event_id));
DCHECK(!drop_current_tap_ending_event_);
break;
@@ -248,24 +278,25 @@ void TouchActionFilter::OnSetTouchAction(cc::TouchAction touch_action) {
scrolling_touch_action_ = allowed_touch_action_;
}
-void TouchActionFilter::SetActiveTouchInProgress(
- bool active_touch_in_progress) {
- active_touch_in_progress_ = active_touch_in_progress;
+void TouchActionFilter::IncreaseActiveTouches() {
+ num_of_active_touches_++;
+}
+
+void TouchActionFilter::DecreaseActiveTouches() {
+ num_of_active_touches_--;
}
void TouchActionFilter::ReportAndResetTouchAction() {
if (has_touch_event_handler_)
- gesture_sequence_.append("R1");
+ gesture_sequence_.append("RY");
else
- gesture_sequence_.append("R0");
+ gesture_sequence_.append("RN");
ReportTouchAction();
- ResetTouchAction();
+ if (num_of_active_touches_ <= 0)
+ ResetTouchAction();
}
void TouchActionFilter::ReportTouchAction() {
- // https://crbug.com/869375, temporary fix to prevent crash.
- if (!scrolling_touch_action_.has_value())
- SetTouchAction(cc::kTouchActionAuto);
// Report the effective touch action computed by blink such as
// kTouchActionNone, kTouchActionPanX, etc.
// Since |cc::kTouchActionAuto| is equivalent to |cc::kTouchActionMax|, we
@@ -324,7 +355,12 @@ void TouchActionFilter::OnSetWhiteListedTouchAction(
bool TouchActionFilter::ShouldSuppressManipulation(
const blink::WebGestureEvent& gesture_event) {
- DCHECK_EQ(gesture_event.GetType(), WebInputEvent::kGestureScrollBegin);
+ DCHECK(gesture_event.GetType() == WebInputEvent::kGestureScrollBegin ||
+ WebInputEvent::IsPinchGestureEventType(gesture_event.GetType()));
+
+ if (WebInputEvent::IsPinchGestureEventType(gesture_event.GetType())) {
+ return (scrolling_touch_action_.value() & cc::kTouchActionPinchZoom) == 0;
+ }
if (gesture_event.data.scroll_begin.pointer_count >= 2) {
// Any GestureScrollBegin with more than one fingers is like a pinch-zoom
@@ -369,13 +405,13 @@ void TouchActionFilter::OnHasTouchEventHandlers(bool has_handlers) {
return;
has_touch_event_handler_ = has_handlers;
if (has_touch_event_handler_)
- gesture_sequence_.append("L1");
+ gesture_sequence_.append("LY");
else
- gesture_sequence_.append("L0");
+ gesture_sequence_.append("LN");
// We have set the associated touch action if the touch start already happened
// or there is a gesture in progress. In these cases, we should not reset the
// associated touch action.
- if (!gesture_sequence_in_progress_ && !active_touch_in_progress_) {
+ if (!gesture_sequence_in_progress_ && num_of_active_touches_ <= 0) {
ResetTouchAction();
if (has_touch_event_handler_)
scrolling_touch_action_.reset();
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 2d157fbebe9..d28115dc2ab 100644
--- a/chromium/content/browser/renderer_host/input/touch_action_filter.h
+++ b/chromium/content/browser/renderer_host/input/touch_action_filter.h
@@ -9,7 +9,6 @@
#include "base/optional.h"
#include "cc/input/touch_action.h"
#include "content/common/content_export.h"
-#include "third_party/blink/public/platform/web_input_event.h"
namespace blink {
class WebGestureEvent;
@@ -67,14 +66,17 @@ class CONTENT_EXPORT TouchActionFilter {
void OnHasTouchEventHandlers(bool has_handlers);
- void SetActiveTouchInProgress(bool active_touch_in_progress);
+ void IncreaseActiveTouches();
+ void DecreaseActiveTouches();
// Debugging only.
void AppendToGestureSequenceForDebugging(const char* str);
private:
+ friend class InputRouterImplTest;
friend class MockRenderWidgetHost;
friend class TouchActionFilterTest;
+ friend class SitePerProcessBrowserTouchActionTest;
bool ShouldSuppressManipulation(const blink::WebGestureEvent&);
bool FilterManipulationEventAndResetState();
@@ -107,8 +109,11 @@ class CONTENT_EXPORT TouchActionFilter {
// before GSE.
bool gesture_sequence_in_progress_ = false;
- // True at touch start and false at touch end.
- bool active_touch_in_progress_ = false;
+ // True if we're between a GSB and a GSE.
+ bool gesture_scroll_in_progress_ = false;
+
+ // Increment at receiving ACK for touch start and decrement at touch end.
+ int num_of_active_touches_ = 0;
// What touch actions are currently permitted.
base::Optional<cc::TouchAction> allowed_touch_action_;
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 95d48e39153..caef54592cb 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
@@ -45,6 +45,7 @@ class TouchActionFilterTest : public testing::Test {
// Scrolls with no direction hint are permitted in the |action| direction.
filter_.ResetTouchAction();
filter_.OnSetTouchAction(action);
+ filter_.IncreaseActiveTouches();
WebGestureEvent scroll_begin =
SyntheticWebGestureEventBuilder::BuildScrollBegin(0, 0,
@@ -64,12 +65,14 @@ class TouchActionFilterTest : public testing::Test {
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
FilterGestureEventResult::kFilterGestureEventAllowed);
+ filter_.DecreaseActiveTouches();
}
{
// Scrolls biased towards the touch-action axis are permitted.
filter_.ResetTouchAction();
filter_.OnSetTouchAction(action);
+ filter_.IncreaseActiveTouches();
WebGestureEvent scroll_begin =
SyntheticWebGestureEventBuilder::BuildScrollBegin(scroll_x, scroll_y,
kSourceDevice);
@@ -100,6 +103,7 @@ class TouchActionFilterTest : public testing::Test {
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
FilterGestureEventResult::kFilterGestureEventAllowed);
+ filter_.DecreaseActiveTouches();
}
{
@@ -107,6 +111,7 @@ class TouchActionFilterTest : public testing::Test {
// suppressed entirely.
filter_.ResetTouchAction();
filter_.OnSetTouchAction(action);
+ filter_.IncreaseActiveTouches();
WebGestureEvent scroll_begin =
SyntheticWebGestureEventBuilder::BuildScrollBegin(scroll_y, scroll_x,
kSourceDevice);
@@ -125,6 +130,7 @@ class TouchActionFilterTest : public testing::Test {
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
FilterGestureEventResult::kFilterGestureEventFiltered);
+ filter_.DecreaseActiveTouches();
}
}
@@ -140,6 +146,7 @@ class TouchActionFilterTest : public testing::Test {
// Scrolls towards the touch-action direction are permitted.
filter_.ResetTouchAction();
filter_.OnSetTouchAction(action);
+ filter_.IncreaseActiveTouches();
WebGestureEvent scroll_begin =
SyntheticWebGestureEventBuilder::BuildScrollBegin(scroll_x, scroll_y,
kSourceDevice);
@@ -155,6 +162,7 @@ class TouchActionFilterTest : public testing::Test {
FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
FilterGestureEventResult::kFilterGestureEventAllowed);
+ filter_.DecreaseActiveTouches();
}
{
@@ -162,6 +170,7 @@ class TouchActionFilterTest : public testing::Test {
// suppressed entirely.
filter_.ResetTouchAction();
filter_.OnSetTouchAction(action);
+ filter_.IncreaseActiveTouches();
WebGestureEvent scroll_begin =
SyntheticWebGestureEventBuilder::BuildScrollBegin(
-scroll_x, -scroll_y, kSourceDevice);
@@ -177,6 +186,7 @@ class TouchActionFilterTest : public testing::Test {
FilterGestureEventResult::kFilterGestureEventFiltered);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
FilterGestureEventResult::kFilterGestureEventFiltered);
+ filter_.DecreaseActiveTouches();
}
{
@@ -184,6 +194,7 @@ class TouchActionFilterTest : public testing::Test {
// suppressed entirely.
filter_.ResetTouchAction();
filter_.OnSetTouchAction(action);
+ filter_.IncreaseActiveTouches();
WebGestureEvent scroll_begin =
SyntheticWebGestureEventBuilder::BuildScrollBegin(
-scroll_x - scroll_y, -scroll_x - scroll_y, kSourceDevice);
@@ -199,6 +210,7 @@ class TouchActionFilterTest : public testing::Test {
FilterGestureEventResult::kFilterGestureEventFiltered);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
FilterGestureEventResult::kFilterGestureEventFiltered);
+ filter_.DecreaseActiveTouches();
}
}
TouchActionFilter filter_;
@@ -220,6 +232,7 @@ TEST_F(TouchActionFilterTest, SimpleFilter) {
// cc::kTouchActionAuto doesn't cause any filtering.
filter_.ResetTouchAction();
filter_.OnSetTouchAction(cc::kTouchActionAuto);
+ filter_.IncreaseActiveTouches();
EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
@@ -230,10 +243,12 @@ TEST_F(TouchActionFilterTest, SimpleFilter) {
EXPECT_EQ(kDeltaY, scroll_update.data.scroll_update.delta_y);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
FilterGestureEventResult::kFilterGestureEventAllowed);
+ filter_.DecreaseActiveTouches();
// cc::kTouchActionNone filters out all scroll events, but no other events.
filter_.ResetTouchAction();
filter_.OnSetTouchAction(cc::kTouchActionNone);
+ filter_.IncreaseActiveTouches();
EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
@@ -246,10 +261,12 @@ TEST_F(TouchActionFilterTest, SimpleFilter) {
EXPECT_EQ(kDeltaY, scroll_update.data.scroll_update.delta_y);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
FilterGestureEventResult::kFilterGestureEventFiltered);
+ filter_.DecreaseActiveTouches();
// When a new touch sequence begins, the state is reset.
filter_.ResetTouchAction();
filter_.OnSetTouchAction(cc::kTouchActionAuto);
+ filter_.IncreaseActiveTouches();
EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
@@ -258,10 +275,12 @@ TEST_F(TouchActionFilterTest, SimpleFilter) {
FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
FilterGestureEventResult::kFilterGestureEventAllowed);
+ filter_.DecreaseActiveTouches();
// Setting touch action doesn't impact any in-progress gestures.
filter_.ResetTouchAction();
filter_.OnSetTouchAction(cc::kTouchActionAuto);
+ filter_.IncreaseActiveTouches();
EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
@@ -271,20 +290,24 @@ TEST_F(TouchActionFilterTest, SimpleFilter) {
FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
FilterGestureEventResult::kFilterGestureEventAllowed);
+ filter_.DecreaseActiveTouches();
// And the state is still cleared for the next gesture.
filter_.ResetTouchAction();
filter_.OnSetTouchAction(cc::kTouchActionAuto);
+ filter_.IncreaseActiveTouches();
EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
FilterGestureEventResult::kFilterGestureEventAllowed);
+ filter_.DecreaseActiveTouches();
// Changing the touch action during a gesture has no effect.
filter_.ResetTouchAction();
filter_.OnSetTouchAction(cc::kTouchActionNone);
+ filter_.IncreaseActiveTouches();
EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
@@ -298,6 +321,7 @@ TEST_F(TouchActionFilterTest, SimpleFilter) {
EXPECT_EQ(kDeltaY, scroll_update.data.scroll_update.delta_y);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
FilterGestureEventResult::kFilterGestureEventFiltered);
+ filter_.DecreaseActiveTouches();
}
TEST_F(TouchActionFilterTest, PanLeft) {
@@ -370,6 +394,7 @@ TEST_F(TouchActionFilterTest, PanXY) {
// Scrolls hinted in the X axis are permitted and unmodified.
filter_.ResetTouchAction();
filter_.OnSetTouchAction(cc::kTouchActionPan);
+ filter_.IncreaseActiveTouches();
WebGestureEvent scroll_begin =
SyntheticWebGestureEventBuilder::BuildScrollBegin(-7, 6, kSourceDevice);
EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
@@ -387,12 +412,14 @@ TEST_F(TouchActionFilterTest, PanXY) {
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
FilterGestureEventResult::kFilterGestureEventAllowed);
+ filter_.DecreaseActiveTouches();
}
{
// Scrolls hinted in the Y axis are permitted and unmodified.
filter_.ResetTouchAction();
filter_.OnSetTouchAction(cc::kTouchActionPan);
+ filter_.IncreaseActiveTouches();
WebGestureEvent scroll_begin =
SyntheticWebGestureEventBuilder::BuildScrollBegin(-6, 7, kSourceDevice);
EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
@@ -410,12 +437,14 @@ TEST_F(TouchActionFilterTest, PanXY) {
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
FilterGestureEventResult::kFilterGestureEventAllowed);
+ filter_.DecreaseActiveTouches();
}
{
// A two-finger gesture is not allowed.
filter_.ResetTouchAction();
filter_.OnSetTouchAction(cc::kTouchActionPan);
+ filter_.IncreaseActiveTouches();
WebGestureEvent scroll_begin =
SyntheticWebGestureEventBuilder::BuildScrollBegin(-6, 7, kSourceDevice,
2);
@@ -432,6 +461,7 @@ TEST_F(TouchActionFilterTest, PanXY) {
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
FilterGestureEventResult::kFilterGestureEventFiltered);
+ filter_.DecreaseActiveTouches();
}
}
@@ -466,6 +496,7 @@ TEST_F(TouchActionFilterTest, MultiTouch) {
filter_.ResetTouchAction();
filter_.OnSetTouchAction(cc::kTouchActionNone);
filter_.OnSetTouchAction(cc::kTouchActionAuto);
+ filter_.IncreaseActiveTouches();
EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
@@ -478,12 +509,14 @@ TEST_F(TouchActionFilterTest, MultiTouch) {
EXPECT_EQ(kDeltaY, scroll_update.data.scroll_update.delta_y);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
FilterGestureEventResult::kFilterGestureEventFiltered);
+ filter_.DecreaseActiveTouches();
// Intersection of PAN_X and PAN_Y is NONE.
filter_.ResetTouchAction();
filter_.OnSetTouchAction(cc::kTouchActionPanX);
filter_.OnSetTouchAction(cc::kTouchActionPanY);
filter_.OnSetTouchAction(cc::kTouchActionPan);
+ filter_.IncreaseActiveTouches();
EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
@@ -492,6 +525,7 @@ TEST_F(TouchActionFilterTest, MultiTouch) {
FilterGestureEventResult::kFilterGestureEventFiltered);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
FilterGestureEventResult::kFilterGestureEventFiltered);
+ filter_.DecreaseActiveTouches();
}
class TouchActionFilterPinchTest : public testing::Test {
@@ -518,6 +552,7 @@ class TouchActionFilterPinchTest : public testing::Test {
// Pinch is allowed with touch-action: auto.
filter_.ResetTouchAction();
filter_.OnSetTouchAction(cc::kTouchActionAuto);
+ filter_.IncreaseActiveTouches();
EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
@@ -530,10 +565,12 @@ class TouchActionFilterPinchTest : public testing::Test {
FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
FilterGestureEventResult::kFilterGestureEventAllowed);
+ filter_.DecreaseActiveTouches();
// Pinch is not allowed with touch-action: none.
filter_.ResetTouchAction();
filter_.OnSetTouchAction(cc::kTouchActionNone);
+ filter_.IncreaseActiveTouches();
EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
@@ -552,11 +589,13 @@ class TouchActionFilterPinchTest : public testing::Test {
FilterGestureEventResult::kFilterGestureEventFiltered);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
FilterGestureEventResult::kFilterGestureEventFiltered);
+ filter_.DecreaseActiveTouches();
// Pinch is not allowed with touch-action: pan-x pan-y except for force
// enable zoom.
filter_.ResetTouchAction();
filter_.OnSetTouchAction(cc::kTouchActionPan);
+ filter_.IncreaseActiveTouches();
EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_NE(filter_.FilterGestureEvent(&scroll_begin),
@@ -579,10 +618,12 @@ class TouchActionFilterPinchTest : public testing::Test {
force_enable_zoom
? FilterGestureEventResult::kFilterGestureEventFiltered
: FilterGestureEventResult::kFilterGestureEventAllowed);
+ filter_.DecreaseActiveTouches();
// Pinch is allowed with touch-action: manipulation.
filter_.ResetTouchAction();
filter_.OnSetTouchAction(cc::kTouchActionManipulation);
+ filter_.IncreaseActiveTouches();
EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
@@ -595,10 +636,12 @@ class TouchActionFilterPinchTest : public testing::Test {
FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
FilterGestureEventResult::kFilterGestureEventAllowed);
+ filter_.DecreaseActiveTouches();
// Pinch state is automatically reset at the end of a scroll.
filter_.ResetTouchAction();
filter_.OnSetTouchAction(cc::kTouchActionAuto);
+ filter_.IncreaseActiveTouches();
EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
@@ -611,10 +654,12 @@ class TouchActionFilterPinchTest : public testing::Test {
FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
FilterGestureEventResult::kFilterGestureEventAllowed);
+ filter_.DecreaseActiveTouches();
// Pinching is only computed at GestureScrollBegin time.
filter_.ResetTouchAction();
filter_.OnSetTouchAction(cc::kTouchActionAuto);
+ filter_.IncreaseActiveTouches();
EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
@@ -641,11 +686,13 @@ class TouchActionFilterPinchTest : public testing::Test {
FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
FilterGestureEventResult::kFilterGestureEventAllowed);
+ filter_.DecreaseActiveTouches();
// 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);
+ filter_.IncreaseActiveTouches();
EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
@@ -665,10 +712,12 @@ class TouchActionFilterPinchTest : public testing::Test {
FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
FilterGestureEventResult::kFilterGestureEventAllowed);
+ filter_.DecreaseActiveTouches();
// Scrolling is allowed when two fingers are down.
filter_.ResetTouchAction();
filter_.OnSetTouchAction(cc::kTouchActionPinchZoom);
+ filter_.IncreaseActiveTouches();
EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
@@ -681,12 +730,14 @@ class TouchActionFilterPinchTest : public testing::Test {
FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
FilterGestureEventResult::kFilterGestureEventAllowed);
+ filter_.DecreaseActiveTouches();
// 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);
+ filter_.IncreaseActiveTouches();
EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
@@ -699,6 +750,7 @@ class TouchActionFilterPinchTest : public testing::Test {
FilterGestureEventResult::kFilterGestureEventFiltered);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
FilterGestureEventResult::kFilterGestureEventFiltered);
+ filter_.DecreaseActiveTouches();
}
private:
@@ -759,6 +811,7 @@ TEST_F(TouchActionFilterTest, DoubleTap) {
// Double tap is disabled with any touch action other than auto.
filter_.ResetTouchAction();
filter_.OnSetTouchAction(cc::kTouchActionManipulation);
+ filter_.IncreaseActiveTouches();
EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&unconfirmed_tap),
@@ -775,6 +828,8 @@ TEST_F(TouchActionFilterTest, DoubleTap) {
EXPECT_EQ(filter_.FilterGestureEvent(&double_tap),
FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(WebInputEvent::kGestureTap, double_tap.GetType());
+ EXPECT_EQ(2, double_tap.data.tap.tap_count);
+ filter_.DecreaseActiveTouches();
}
TEST_F(TouchActionFilterTest, SingleTapWithTouchActionAuto) {
@@ -808,6 +863,7 @@ TEST_F(TouchActionFilterTest, SingleTap) {
// With touch action other than auto, tap unconfirmed is turned into tap.
filter_.ResetTouchAction();
filter_.OnSetTouchAction(cc::kTouchActionNone);
+ filter_.IncreaseActiveTouches();
EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&unconfirmed_tap1),
@@ -815,6 +871,7 @@ TEST_F(TouchActionFilterTest, SingleTap) {
EXPECT_EQ(WebInputEvent::kGestureTap, unconfirmed_tap1.GetType());
EXPECT_EQ(filter_.FilterGestureEvent(&tap),
FilterGestureEventResult::kFilterGestureEventFiltered);
+ filter_.DecreaseActiveTouches();
}
TEST_F(TouchActionFilterTest, TouchActionResetsOnResetTouchAction) {
@@ -829,26 +886,32 @@ TEST_F(TouchActionFilterTest, TouchActionResetsOnResetTouchAction) {
filter_.ResetTouchAction();
filter_.OnSetTouchAction(cc::kTouchActionNone);
+ filter_.IncreaseActiveTouches();
EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
FilterGestureEventResult::kFilterGestureEventFiltered);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
FilterGestureEventResult::kFilterGestureEventFiltered);
+ filter_.DecreaseActiveTouches();
filter_.ResetTouchAction();
filter_.OnSetTouchAction(cc::kTouchActionNone);
+ filter_.IncreaseActiveTouches();
EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&tap),
FilterGestureEventResult::kFilterGestureEventAllowed);
+ filter_.DecreaseActiveTouches();
filter_.ResetTouchAction();
filter_.OnSetTouchAction(cc::kTouchActionAuto);
+ filter_.IncreaseActiveTouches();
EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
FilterGestureEventResult::kFilterGestureEventAllowed);
+ filter_.DecreaseActiveTouches();
}
TEST_F(TouchActionFilterTest, TouchActionResetMidSequence) {
@@ -868,6 +931,7 @@ TEST_F(TouchActionFilterTest, TouchActionResetMidSequence) {
WebInputEvent::kGestureScrollEnd, kSourceDevice);
filter_.OnSetTouchAction(cc::kTouchActionNone);
+ filter_.IncreaseActiveTouches();
EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
@@ -887,9 +951,11 @@ TEST_F(TouchActionFilterTest, TouchActionResetMidSequence) {
FilterGestureEventResult::kFilterGestureEventFiltered);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
FilterGestureEventResult::kFilterGestureEventFiltered);
+ filter_.DecreaseActiveTouches();
// A new scroll and pinch sequence should be allowed.
filter_.OnSetTouchAction(cc::kTouchActionAuto);
+ filter_.IncreaseActiveTouches();
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&pinch_begin),
@@ -906,6 +972,7 @@ TEST_F(TouchActionFilterTest, TouchActionResetMidSequence) {
FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
FilterGestureEventResult::kFilterGestureEventAllowed);
+ filter_.DecreaseActiveTouches();
}
// This test makes sure that we do not reset scrolling touch action in the
@@ -925,6 +992,7 @@ TEST_F(TouchActionFilterTest, TouchActionNotResetWithinGestureSequence) {
WebGestureEvent scroll_end = SyntheticWebGestureEventBuilder::Build(
WebInputEvent::kGestureScrollEnd, kSourceDevice);
+ filter_.IncreaseActiveTouches();
EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(cc::kTouchActionPanY, ScrollingTouchAction().value());
@@ -934,6 +1002,7 @@ TEST_F(TouchActionFilterTest, TouchActionNotResetWithinGestureSequence) {
EXPECT_EQ(filter_.FilterGestureEvent(&scroll_update),
FilterGestureEventResult::kFilterGestureEventAllowed);
// Simulate a touch sequence end by calling ReportAndResetTouchAction.
+ filter_.DecreaseActiveTouches();
filter_.ReportAndResetTouchAction();
EXPECT_FALSE(filter_.allowed_touch_action().has_value());
EXPECT_EQ(cc::kTouchActionPanY, ScrollingTouchAction().value());
@@ -985,6 +1054,7 @@ TEST_F(TouchActionFilterTest, OnHasTouchEventHandlersReceivedDuringDoubleTap) {
WebInputEvent::kGestureDoubleTap, kSourceDevice);
// Simulate a double tap gesture: GTD-->GTC-->GTD-->GTC-->GDT.
+ filter_.IncreaseActiveTouches();
EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(ScrollingTouchAction().value(), cc::kTouchActionAuto);
@@ -1000,6 +1070,7 @@ TEST_F(TouchActionFilterTest, OnHasTouchEventHandlersReceivedDuringDoubleTap) {
FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(filter_.FilterGestureEvent(&double_tap),
FilterGestureEventResult::kFilterGestureEventAllowed);
+ filter_.DecreaseActiveTouches();
}
TEST_F(TouchActionFilterTest, OnHasTouchEventHandlersReceivedDuringScroll) {
@@ -1079,7 +1150,7 @@ TEST_F(TouchActionFilterTest, OnHasTouchEventHandlersReceivedAfterTouchStart) {
// Receive a touch start ack, set the touch action.
filter_.OnSetTouchAction(cc::kTouchActionPanY);
- filter_.SetActiveTouchInProgress(true);
+ filter_.IncreaseActiveTouches();
filter_.OnHasTouchEventHandlers(false);
EXPECT_EQ(ScrollingTouchAction().value(), cc::kTouchActionPanY);
EXPECT_EQ(filter_.allowed_touch_action().value(), cc::kTouchActionPanY);
@@ -1088,6 +1159,33 @@ TEST_F(TouchActionFilterTest, OnHasTouchEventHandlersReceivedAfterTouchStart) {
EXPECT_EQ(filter_.allowed_touch_action().value(), cc::kTouchActionPanY);
}
+TEST_F(TouchActionFilterTest, ResetTouchActionWithActiveTouch) {
+ filter_.OnHasTouchEventHandlers(true);
+ EXPECT_FALSE(ScrollingTouchAction().has_value());
+ EXPECT_FALSE(filter_.allowed_touch_action().has_value());
+
+ // Receive a touch start ack, set the touch action.
+ filter_.OnSetTouchAction(cc::kTouchActionPanY);
+ filter_.IncreaseActiveTouches();
+
+ // Somehow we get the ACK for the second touch start before the ACK for the
+ // first touch end.
+ filter_.OnSetTouchAction(cc::kTouchActionPan);
+ filter_.IncreaseActiveTouches();
+
+ // The first touch end comes, we report and reset touch action. The touch
+ // actions should still have value.
+ filter_.DecreaseActiveTouches();
+ filter_.ReportAndResetTouchAction();
+ EXPECT_EQ(ScrollingTouchAction().value(), cc::kTouchActionPanY);
+ EXPECT_EQ(filter_.allowed_touch_action().value(), cc::kTouchActionPanY);
+
+ // The ack for the second touch end comes, the touch actions will be reset.
+ filter_.DecreaseActiveTouches();
+ filter_.ReportAndResetTouchAction();
+ EXPECT_FALSE(filter_.allowed_touch_action().has_value());
+}
+
// If the renderer is busy, the gesture event might have come before the
// OnHasTouchEventHanlders IPC is received. In this case, we should allow all
// the gestures.
@@ -1122,6 +1220,20 @@ TEST_F(TouchActionFilterTest, ScrollBeginWithoutTapDown) {
EXPECT_EQ(filter_.allowed_touch_action().value(), cc::kTouchActionAuto);
}
+// This tests a gesture tap down with |num_of_active_touches_| == 0
+TEST_F(TouchActionFilterTest, TapDownWithZeroNumOfActiveTouches) {
+ filter_.OnHasTouchEventHandlers(true);
+ EXPECT_FALSE(ScrollingTouchAction().has_value());
+ EXPECT_FALSE(filter_.allowed_touch_action().has_value());
+
+ WebGestureEvent tap_down = SyntheticWebGestureEventBuilder::Build(
+ WebInputEvent::kGestureTapDown, kSourceDevice);
+ EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_TRUE(ScrollingTouchAction().has_value());
+ EXPECT_EQ(ScrollingTouchAction().value(), cc::kTouchActionAuto);
+}
+
TEST_F(TouchActionFilterTest, ScrollBeginWithoutTapDownWithKnownTouchAction) {
filter_.OnHasTouchEventHandlers(true);
EXPECT_FALSE(ScrollingTouchAction().has_value());
diff --git a/chromium/content/browser/renderer_host/input/touch_emulator.cc b/chromium/content/browser/renderer_host/input/touch_emulator.cc
index e5cfa600cf5..ab7c6f7f23a 100644
--- a/chromium/content/browser/renderer_host/input/touch_emulator.cc
+++ b/chromium/content/browser/renderer_host/input/touch_emulator.cc
@@ -71,6 +71,7 @@ TouchEmulator::TouchEmulator(TouchEmulatorClient* client,
ui::GestureProviderConfigType::CURRENT_PLATFORM),
double_tap_enabled_(true),
use_2x_cursors_(false),
+ pinch_gesture_mode_for_testing_(false),
emulated_stream_active_sequence_count_(0),
native_stream_active_sequence_count_(0),
last_emulated_start_target_(nullptr),
@@ -516,6 +517,7 @@ void TouchEmulator::ScrollEnd(const WebGestureEvent& event) {
WebGestureEvent scroll_event(
WebInputEvent::kGestureScrollEnd, ModifiersWithoutMouseButtons(event),
event.TimeStamp(), blink::kWebGestureDeviceTouchscreen);
+ scroll_event.unique_touch_event_id = event.unique_touch_event_id;
client_->ForwardEmulatedGestureEvent(scroll_event);
}
@@ -571,7 +573,11 @@ void TouchEmulator::FillTouchEventAndPoint(const WebMouseEvent& mouse_event,
}
bool TouchEmulator::InPinchGestureMode() const {
- return shift_pressed_;
+ return shift_pressed_ || pinch_gesture_mode_for_testing_;
+}
+
+void TouchEmulator::SetPinchGestureModeForTesting(bool pinch_gesture_mode) {
+ pinch_gesture_mode_for_testing_ = pinch_gesture_mode;
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/touch_emulator.h b/chromium/content/browser/renderer_host/input/touch_emulator.h
index 55fabad3b55..20d2656e513 100644
--- a/chromium/content/browser/renderer_host/input/touch_emulator.h
+++ b/chromium/content/browser/renderer_host/input/touch_emulator.h
@@ -85,6 +85,14 @@ class CONTENT_EXPORT TouchEmulator : public ui::GestureProviderClient {
// Cancel any touches, for example, when focus is lost.
void CancelTouch();
+ // This is needed because SyntheticGestureSmoothDrag doesn't support setting
+ // key-modifiers on the drag sequence.
+ // https://crbug.com/901374.
+ void SetPinchGestureModeForTesting(bool pinch_gesture_mode);
+ bool suppress_next_fling_cancel_for_testing() const {
+ return suppress_next_fling_cancel_;
+ }
+
private:
// ui::GestureProviderClient implementation.
void OnGestureEvent(const ui::GestureEventData& gesture) override;
@@ -147,6 +155,7 @@ class CONTENT_EXPORT TouchEmulator : public ui::GestureProviderClient {
bool mouse_pressed_;
bool shift_pressed_;
+ bool pinch_gesture_mode_for_testing_;
blink::WebTouchEvent touch_event_;
int emulated_stream_active_sequence_count_;
diff --git a/chromium/content/browser/renderer_host/input/touch_input_browsertest.cc b/chromium/content/browser/renderer_host/input/touch_input_browsertest.cc
index ddab75b7c0a..181dcb75270 100644
--- a/chromium/content/browser/renderer_host/input/touch_input_browsertest.cc
+++ b/chromium/content/browser/renderer_host/input/touch_input_browsertest.cc
@@ -12,7 +12,9 @@
#include "build/build_config.h"
#include "components/viz/common/features.h"
#include "content/browser/gpu/compositor_util.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/web_contents/web_contents_impl.h"
#include "content/common/input/synthetic_web_input_event_builders.h"
#include "content/common/input_messages.h"
@@ -99,8 +101,11 @@ class TouchInputBrowserTest : public ContentBrowserTest {
protected:
void SendTouchEvent(SyntheticWebTouchEvent* event) {
- GetWidgetHost()->ForwardTouchEventWithLatencyInfo(*event,
- ui::LatencyInfo());
+ auto* root_view = GetWidgetHost()->GetView();
+ auto* input_event_router =
+ GetWidgetHost()->delegate()->GetInputEventRouter();
+ input_event_router->RouteTouchEvent(root_view, event, ui::LatencyInfo());
+
event->ResetPoints();
}
void LoadURL() {
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 86f8645c735..11af0a042d0 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
@@ -30,6 +30,7 @@
#include "ui/aura/window.h"
#include "ui/aura/window_tree_host.h"
#include "ui/display/display_switches.h"
+#include "ui/events/event_sink.h"
#include "ui/events/event_utils.h"
#include "ui/events/test/event_generator.h"
#include "ui/touch_selection/touch_selection_controller_test_api.h"
@@ -178,10 +179,8 @@ class TouchSelectionControllerClientAuraTest : public ContentBrowserTest {
new TestTouchSelectionControllerClientAura(rwhva);
rwhva->SetSelectionControllerClientForTest(
base::WrapUnique(selection_controller_client_));
- rwhva->event_handler()->disable_input_event_router_for_testing();
}
- protected:
void SetUpOnMainThread() override {
ContentBrowserTest::SetUpOnMainThread();
if (!ui::TouchSelectionMenuRunner::GetInstance())
@@ -235,30 +234,49 @@ IN_PROC_BROWSER_TEST_F(TouchSelectionControllerClientAuraTest, BasicSelection) {
EXPECT_TRUE(ui::TouchSelectionMenuRunner::GetInstance()->IsRunning());
}
-class GestureLongPressWaiter : public RenderWidgetHost::InputEventObserver {
+class GestureEventWaiter : public RenderWidgetHost::InputEventObserver {
public:
- GestureLongPressWaiter(RenderWidgetHost* rwh)
+ explicit GestureEventWaiter(RenderWidgetHost* rwh,
+ blink::WebInputEvent::Type target_event_type)
: rwh_(static_cast<RenderWidgetHostImpl*>(rwh)->GetWeakPtr()),
- gesture_long_press_seen_(false) {
+ target_event_type_(target_event_type),
+ gesture_event_type_seen_(false),
+ gesture_event_type_ack_seen_(false) {
rwh->AddInputEventObserver(this);
}
- ~GestureLongPressWaiter() override {
+ ~GestureEventWaiter() override {
if (rwh_)
rwh_->RemoveInputEventObserver(this);
}
+ void OnInputEvent(const blink::WebInputEvent& event) override {
+ if (event.GetType() == target_event_type_) {
+ gesture_event_type_seen_ = true;
+ if (run_loop_)
+ run_loop_->Quit();
+ }
+ }
+
void OnInputEventAck(InputEventAckSource,
InputEventAckState,
const blink::WebInputEvent& event) override {
- if (event.GetType() == blink::WebInputEvent::kGestureLongPress) {
- gesture_long_press_seen_ = true;
+ if (event.GetType() == target_event_type_) {
+ gesture_event_type_ack_seen_ = true;
if (run_loop_)
run_loop_->Quit();
}
}
void Wait() {
- if (gesture_long_press_seen_)
+ if (gesture_event_type_seen_)
+ return;
+ run_loop_.reset(new base::RunLoop);
+ run_loop_->Run();
+ run_loop_.reset();
+ }
+
+ void WaitForAck() {
+ if (gesture_event_type_ack_seen_)
return;
run_loop_.reset(new base::RunLoop);
run_loop_->Run();
@@ -268,7 +286,9 @@ class GestureLongPressWaiter : public RenderWidgetHost::InputEventObserver {
private:
base::WeakPtr<RenderWidgetHostImpl> rwh_;
std::unique_ptr<base::RunLoop> run_loop_;
- bool gesture_long_press_seen_;
+ blink::WebInputEvent::Type target_event_type_;
+ bool gesture_event_type_seen_;
+ bool gesture_event_type_ack_seen_;
};
class TouchSelectionControllerClientAuraSiteIsolationTest
@@ -291,25 +311,32 @@ class TouchSelectionControllerClientAuraSiteIsolationTest
// Get main frame view for event insertion.
RenderWidgetHostViewAura* main_view = GetRenderWidgetHostViewAura();
+ GestureEventWaiter long_press_waiter(
+ expected_target->GetRenderWidgetHost(),
+ blink::WebInputEvent::kGestureLongPress);
SendTouch(main_view, ui::ET_TOUCH_PRESSED, point);
- SendTouch(main_view, ui::ET_TOUCH_RELEASED, point);
- SendGestureTap(main_view, point);
-
- // Since our hit-testing is now asynchronous, wait for the Ack to come
- // back before proceeding.
- GestureLongPressWaiter long_press_waiter(
- expected_target->GetRenderWidgetHost());
- SendGestureLongPress(main_view, point);
+ // Wait until we see the out-bound LongPress on its way to the renderer, so
+ // we know it's ok to send the TOUCH_RELEASED to end the sequence.
long_press_waiter.Wait();
+ SendTouch(main_view, ui::ET_TOUCH_RELEASED, point);
+ // Now wait for the LongPress ack to return from the renderer, so our caller
+ // knows the LongPress event has been consumed and any relevant selection
+ // performed.
+ long_press_waiter.WaitForAck();
}
- void SimpleTap(gfx::Point point) {
+ void SimpleTap(gfx::Point point, RenderWidgetHostViewBase* expected_target) {
// Get main frame view for event insertion.
RenderWidgetHostViewAura* main_view = GetRenderWidgetHostViewAura();
+ GestureEventWaiter tap_down_waiter(expected_target->GetRenderWidgetHost(),
+ blink::WebInputEvent::kGestureTapDown);
+ GestureEventWaiter tap_waiter(expected_target->GetRenderWidgetHost(),
+ blink::WebInputEvent::kGestureTap);
SendTouch(main_view, ui::ET_TOUCH_PRESSED, point);
+ tap_down_waiter.Wait();
SendTouch(main_view, ui::ET_TOUCH_RELEASED, point);
- SendGestureTap(main_view, point);
+ tap_waiter.WaitForAck();
}
private:
@@ -317,33 +344,18 @@ class TouchSelectionControllerClientAuraSiteIsolationTest
ui::EventType type,
gfx::Point point) {
DCHECK(type >= ui::ET_TOUCH_RELEASED && type << ui::ET_TOUCH_CANCELLED);
+ // If we want the GestureRecognizer to create the gestures for us, we must
+ // register the outgoing touch event with it by sending it through the
+ // window's event dispatching system.
+ aura::Window* shell_window = shell()->window();
+ aura::Window* content_window = view->GetNativeView();
+ aura::Window::ConvertPointToTarget(content_window, shell_window, &point);
+ ui::EventSink* sink = content_window->GetHost()->event_sink();
ui::TouchEvent touch(
type, point, ui::EventTimeForNow(),
ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0));
- view->OnTouchEvent(&touch);
- }
-
- void SendGestureTap(RenderWidgetHostViewAura* view, gfx::Point point) {
- ui::GestureEventDetails tap_down_details(ui::ET_GESTURE_TAP_DOWN);
- tap_down_details.set_device_type(ui::GestureDeviceType::DEVICE_TOUCHSCREEN);
- ui::GestureEvent gesture_tap_down(point.x(), point.y(), 0,
- ui::EventTimeForNow(), tap_down_details);
- view->OnGestureEvent(&gesture_tap_down);
- ui::GestureEventDetails tap_details(ui::ET_GESTURE_TAP);
- tap_details.set_device_type(ui::GestureDeviceType::DEVICE_TOUCHSCREEN);
- tap_details.set_tap_count(1);
- ui::GestureEvent gesture_tap(point.x(), point.y(), 0, ui::EventTimeForNow(),
- tap_details);
- view->OnGestureEvent(&gesture_tap);
- }
-
- void SendGestureLongPress(RenderWidgetHostViewAura* view, gfx::Point point) {
- ui::GestureEventDetails long_press_details(ui::ET_GESTURE_LONG_PRESS);
- long_press_details.set_device_type(
- ui::GestureDeviceType::DEVICE_TOUCHSCREEN);
- ui::GestureEvent gesture_long_press(
- point.x(), point.y(), 0, ui::EventTimeForNow(), long_press_details);
- view->OnGestureEvent(&gesture_long_press);
+ ui::EventDispatchDetails details = sink->OnEventFromSource(&touch);
+ ASSERT_FALSE(details.dispatcher_destroyed);
}
};
@@ -466,11 +478,13 @@ IN_PROC_BROWSER_TEST_P(TouchSelectionControllerClientAuraSiteIsolationTest,
if (GetParam()) {
gfx::PointF point_outside_iframe =
child_view->TransformPointToRootCoordSpaceF(gfx::PointF(-1.f, -1.f));
- SimpleTap(gfx::Point(point_outside_iframe.x(), point_outside_iframe.y()));
+ SimpleTap(gfx::Point(point_outside_iframe.x(), point_outside_iframe.y()),
+ parent_view);
} else {
gfx::PointF point_inside_iframe =
child_view->TransformPointToRootCoordSpaceF(gfx::PointF(+1.f, +1.f));
- SimpleTap(gfx::Point(point_inside_iframe.x(), point_inside_iframe.y()));
+ SimpleTap(gfx::Point(point_inside_iframe.x(), point_inside_iframe.y()),
+ child_view);
}
parent_selection_controller_client->Wait();
diff --git a/chromium/content/browser/renderer_host/input/touch_selection_controller_client_child_frame.cc b/chromium/content/browser/renderer_host/input/touch_selection_controller_client_child_frame.cc
index e419b3fbed8..08acc8569f2 100644
--- a/chromium/content/browser/renderer_host/input/touch_selection_controller_client_child_frame.cc
+++ b/chromium/content/browser/renderer_host/input/touch_selection_controller_client_child_frame.cc
@@ -7,7 +7,7 @@
#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_view_child_frame.h"
-#include "content/common/view_messages.h"
+#include "content/common/widget_messages.h"
#include "content/public/browser/touch_selection_controller_client_manager.h"
#include "content/public/common/use_zoom_for_dsf_policy.h"
#include "ui/base/clipboard/clipboard.h"
@@ -206,9 +206,9 @@ void TouchSelectionControllerClientChildFrame::RunContextMenu() {
gfx::PointF origin = rwhv_->TransformPointToRootCoordSpaceF(gfx::PointF());
anchor_point.Offset(-origin.x(), -origin.y());
RenderWidgetHostImpl* host = rwhv_->host();
- host->Send(new ViewMsg_ShowContextMenu(host->GetRoutingID(),
- ui::MENU_SOURCE_TOUCH_EDIT_MENU,
- gfx::ToRoundedPoint(anchor_point)));
+ host->Send(new WidgetMsg_ShowContextMenu(host->GetRoutingID(),
+ ui::MENU_SOURCE_TOUCH_EDIT_MENU,
+ gfx::ToRoundedPoint(anchor_point)));
// Hide selection handles after getting rect-between-bounds from touch
// selection controller; otherwise, rect would be empty and the above
diff --git a/chromium/content/browser/renderer_host/input/touch_selection_controller_client_manager_android.cc b/chromium/content/browser/renderer_host/input/touch_selection_controller_client_manager_android.cc
index fc968742ec8..d34a19317a6 100644
--- a/chromium/content/browser/renderer_host/input/touch_selection_controller_client_manager_android.cc
+++ b/chromium/content/browser/renderer_host/input/touch_selection_controller_client_manager_android.cc
@@ -11,7 +11,7 @@ namespace content {
TouchSelectionControllerClientManagerAndroid::
TouchSelectionControllerClientManagerAndroid(
RenderWidgetHostViewAndroid* rwhv)
- : rwhv_(rwhv), active_client_(rwhv), page_scale_factor_(1.f) {
+ : rwhv_(rwhv), active_client_(rwhv) {
DCHECK(rwhv_);
}
@@ -21,27 +21,6 @@ TouchSelectionControllerClientManagerAndroid::
observer.OnManagerWillDestroy(this);
}
-void TouchSelectionControllerClientManagerAndroid::SetPageScaleFactor(
- float page_scale_factor) {
- page_scale_factor_ = page_scale_factor;
-}
-
-namespace {
-
-gfx::SelectionBound ScaleSelectionBound(const gfx::SelectionBound& bound,
- float scale) {
- gfx::SelectionBound scaled_bound;
- gfx::PointF scaled_top = bound.edge_top();
- scaled_top.Scale(scale);
- gfx::PointF scaled_bottom = bound.edge_bottom();
- scaled_bottom.Scale(scale);
- scaled_bound.SetEdge(scaled_top, scaled_bottom);
- scaled_bound.set_type(bound.type());
- scaled_bound.set_visible(bound.visible());
- return scaled_bound;
-}
-} // namespace
-
// TouchSelectionControllerClientManager implementation.
void TouchSelectionControllerClientManagerAndroid::DidStopFlinging() {
// TODO(wjmaclean): determine what, if anything, needs to happen here.
@@ -61,13 +40,9 @@ void TouchSelectionControllerClientManagerAndroid::UpdateClientSelectionBounds(
}
active_client_ = client;
- if (active_client_ != rwhv_) {
- manager_selection_start_ = ScaleSelectionBound(start, page_scale_factor_);
- manager_selection_end_ = ScaleSelectionBound(end, page_scale_factor_);
- } else {
- manager_selection_start_ = start;
- manager_selection_end_ = end;
- }
+ manager_selection_start_ = start;
+ manager_selection_end_ = end;
+
// Notify TouchSelectionController if anything should change here. Only
// update if the client is different and not making a change to empty, or
// is the same client.
@@ -109,30 +84,18 @@ void TouchSelectionControllerClientManagerAndroid::SetNeedsAnimate() {
void TouchSelectionControllerClientManagerAndroid::MoveCaret(
const gfx::PointF& position) {
- gfx::PointF scaled_position = position;
- if (active_client_ != rwhv_)
- scaled_position.Scale(1 / page_scale_factor_);
- active_client_->MoveCaret(scaled_position);
+ active_client_->MoveCaret(position);
}
void TouchSelectionControllerClientManagerAndroid::MoveRangeSelectionExtent(
const gfx::PointF& extent) {
- gfx::PointF scaled_extent = extent;
- if (active_client_ != rwhv_)
- scaled_extent.Scale(1 / page_scale_factor_);
- active_client_->MoveRangeSelectionExtent(scaled_extent);
+ active_client_->MoveRangeSelectionExtent(extent);
}
void TouchSelectionControllerClientManagerAndroid::SelectBetweenCoordinates(
const gfx::PointF& base,
const gfx::PointF& extent) {
- gfx::PointF scaled_extent = extent;
- gfx::PointF scaled_base = base;
- if (active_client_ != rwhv_) {
- scaled_extent.Scale(1 / page_scale_factor_);
- scaled_base.Scale(1 / page_scale_factor_);
- }
- active_client_->SelectBetweenCoordinates(scaled_base, scaled_extent);
+ active_client_->SelectBetweenCoordinates(base, extent);
}
void TouchSelectionControllerClientManagerAndroid::OnSelectionEvent(
diff --git a/chromium/content/browser/renderer_host/input/touch_selection_controller_client_manager_android.h b/chromium/content/browser/renderer_host/input/touch_selection_controller_client_manager_android.h
index b839bddccbf..d3f3fb19515 100644
--- a/chromium/content/browser/renderer_host/input/touch_selection_controller_client_manager_android.h
+++ b/chromium/content/browser/renderer_host/input/touch_selection_controller_client_manager_android.h
@@ -21,8 +21,6 @@ class TouchSelectionControllerClientManagerAndroid
explicit TouchSelectionControllerClientManagerAndroid(
RenderWidgetHostViewAndroid* rwhv);
~TouchSelectionControllerClientManagerAndroid() override;
- void SetPageScaleFactor(float page_scale_factor);
- float page_scale_factor() { return page_scale_factor_; }
// TouchSelectionControllerClientManager implementation.
void DidStopFlinging() override;
@@ -52,7 +50,6 @@ class TouchSelectionControllerClientManagerAndroid
private:
RenderWidgetHostViewAndroid* rwhv_;
TouchSelectionControllerClient* active_client_;
- float page_scale_factor_;
gfx::SelectionBound manager_selection_start_;
gfx::SelectionBound manager_selection_end_;
base::ObserverList<TouchSelectionControllerClientManager::Observer>::Unchecked
diff --git a/chromium/content/browser/renderer_host/input/web_input_event_builders_mac_unittest.mm b/chromium/content/browser/renderer_host/input/web_input_event_builders_mac_unittest.mm
index bad84541740..b0a397f10d1 100644
--- a/chromium/content/browser/renderer_host/input/web_input_event_builders_mac_unittest.mm
+++ b/chromium/content/browser/renderer_host/input/web_input_event_builders_mac_unittest.mm
@@ -434,7 +434,7 @@ TEST(WebInputEventBuilderMacTest, USDvorakQWERTYCommand) {
}
// Test conversion from key combination with Control to DomKey.
-// TODO(chongz): Move DomKey tests for all platforms into one place.
+// TODO(input-dev): Move DomKey tests for all platforms into one place.
// http://crbug.com/587589
// This test case only works for U.S. layout.
TEST(WebInputEventBuilderMacTest, DomKeyCtrlShift) {
@@ -781,4 +781,4 @@ TEST(WebInputEventBuilderMacTest, BuildWebTouchEvents) {
EXPECT_EQ(60, touch_event.touches[0].twist);
EXPECT_FLOAT_EQ(60.0, touch_event.touches[0].rotation_angle);
}
-#endif // MAC_OS_X_VERSION_10_12 \ No newline at end of file
+#endif // MAC_OS_X_VERSION_10_12
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 718bb1a6e5a..4706dac9f7f 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
@@ -14,11 +14,13 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
#include "base/strings/stringprintf.h"
+#include "base/task/post_task.h"
#include "content/browser/media/capture/desktop_capture_device_uma_types.h"
#include "content/browser/media/capture/web_contents_audio_input_stream.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/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents_media_capture_id.h"
@@ -65,8 +67,8 @@ class AudioInputDelegateImpl::ControllerEventHandler
: stream_id_(stream_id), weak_delegate_(std::move(weak_delegate)) {}
void OnCreated(bool initially_muted) override {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&AudioInputDelegateImpl::SendCreatedNotification,
weak_delegate_, initially_muted));
}
@@ -76,8 +78,8 @@ class AudioInputDelegateImpl::ControllerEventHandler
// we log it here.
LogMessage(stream_id_,
base::StringPrintf("AIC reports error_code=%d", error_code));
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&AudioInputDelegateImpl::OnError, weak_delegate_));
}
@@ -88,9 +90,9 @@ class AudioInputDelegateImpl::ControllerEventHandler
void OnMuted(bool is_muted) override {
LogMessage(stream_id_, is_muted ? "OnMuted: State changed to muted"
: "OnMuted: State changed to not muted");
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::BindOnce(&AudioInputDelegateImpl::OnMuted,
- weak_delegate_, is_muted));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(&AudioInputDelegateImpl::OnMuted,
+ weak_delegate_, is_muted));
}
private:
@@ -182,8 +184,8 @@ AudioInputDelegateImpl::AudioInputDelegateImpl(
render_process_id_(render_process_id),
weak_factory_(this) {
// Prevent process backgrounding while audio input is active:
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&NotifyProcessHostStreamAdded, render_process_id_));
controller_event_handler_ = std::make_unique<ControllerEventHandler>(
@@ -231,8 +233,8 @@ AudioInputDelegateImpl::~AudioInputDelegateImpl() {
audio_log_->OnClosed();
LogMessage(stream_id_, "Closing stream");
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&NotifyProcessHostStreamRemoved, render_process_id_));
// We pass |controller_event_handler_| and |writer_| in here to make sure they
diff --git a/chromium/content/browser/renderer_host/media/audio_input_device_manager.cc b/chromium/content/browser/renderer_host/media/audio_input_device_manager.cc
index 2e72505f818..26172e5ae38 100644
--- a/chromium/content/browser/renderer_host/media/audio_input_device_manager.cc
+++ b/chromium/content/browser/renderer_host/media/audio_input_device_manager.cc
@@ -11,7 +11,9 @@
#include "base/callback.h"
#include "base/command_line.h"
#include "base/metrics/histogram_macros.h"
+#include "base/task/post_task.h"
#include "build/build_config.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/media_stream_request.h"
#include "media/audio/audio_input_ipc.h"
@@ -57,7 +59,7 @@ AudioInputDeviceManager::~AudioInputDeviceManager() {
const MediaStreamDevice* AudioInputDeviceManager::GetOpenedDeviceById(
int session_id) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- MediaStreamDevices::iterator device = GetDevice(session_id);
+ auto device = GetDevice(session_id);
if (device == devices_.end())
return nullptr;
@@ -115,7 +117,7 @@ int AudioInputDeviceManager::Open(const MediaStreamDevice& device) {
void AudioInputDeviceManager::Close(int session_id) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- MediaStreamDevices::iterator device = GetDevice(session_id);
+ auto device = GetDevice(session_id);
if (device == devices_.end())
return;
const MediaStreamType stream_type = device->type;
@@ -124,8 +126,8 @@ void AudioInputDeviceManager::Close(int session_id) {
// Post a callback through the listener on IO thread since
// MediaStreamManager is expecting the callback asynchronously.
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&AudioInputDeviceManager::ClosedOnIOThread, this,
stream_type, session_id));
}
@@ -155,8 +157,8 @@ void AudioInputDeviceManager::KeyboardMicRegistration::DeregisterIfNeeded() {
--*shared_registration_count_;
DCHECK_GE(*shared_registration_count_, 0);
if (*shared_registration_count_ == 0) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&SetKeyboardMicStreamActiveOnUIThread, false));
}
}
@@ -172,8 +174,8 @@ void AudioInputDeviceManager::RegisterKeyboardMicStream(
++keyboard_mic_streams_count_;
if (keyboard_mic_streams_count_ == 1) {
- BrowserThread::PostTaskAndReply(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraitsAndReply(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&SetKeyboardMicStreamActiveOnUIThread, true),
base::BindOnce(std::move(callback),
KeyboardMicRegistration(&keyboard_mic_streams_count_)));
@@ -221,8 +223,7 @@ void AudioInputDeviceManager::ClosedOnIOThread(MediaStreamType stream_type,
MediaStreamDevices::iterator AudioInputDeviceManager::GetDevice(
int session_id) {
- for (MediaStreamDevices::iterator it = devices_.begin(); it != devices_.end();
- ++it) {
+ for (auto it = devices_.begin(); it != devices_.end(); ++it) {
if (it->session_id == session_id)
return it;
}
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 a843d538ebf..2f09cdb7cbb 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
@@ -9,10 +9,10 @@
#include "base/bind.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"
#include "base/test/mock_callback.h"
+#include "base/test/scoped_task_environment.h"
#include "media/audio/audio_input_delegate.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -122,7 +122,7 @@ class AudioInputStreamHandleTest : public Test {
}
private:
- base::MessageLoop message_loop_;
+ base::test::ScopedTaskEnvironment task_environment_;
StrictMock<MockRendererAudioInputStreamFactoryClient> client_;
mojom::RendererAudioInputStreamFactoryClientPtr client_ptr_;
mojo::Binding<mojom::RendererAudioInputStreamFactoryClient> client_binding_;
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 5d888b45bed..c890bb8df13 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
@@ -6,11 +6,13 @@
#include "base/bind.h"
#include "base/metrics/histogram_macros.h"
+#include "base/task/post_task.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"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/media_device_id.h"
#include "content/public/browser/render_frame_host.h"
@@ -168,8 +170,8 @@ void AudioOutputAuthorizationHandler::RequestDeviceAuthorization(
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(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraitsAndReplyWithResult(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&GetMediaDeviceSaltAndOrigin, render_process_id_,
render_frame_id),
base::BindOnce(&AudioOutputAuthorizationHandler::HashDeviceId,
@@ -189,8 +191,8 @@ void AudioOutputAuthorizationHandler::RequestDeviceAuthorization(
trace_scope->CheckAccessStart(device_id);
// Check device permissions if nondefault device is requested.
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&CheckAccessOnUIThread, render_process_id_,
render_frame_id, override_permissions_,
permissions_override_value_,
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 15a70a66df8..fc657650af9 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
@@ -9,7 +9,9 @@
#include "base/bind.h"
#include "base/command_line.h"
#include "base/run_loop.h"
+#include "base/task/post_task.h"
#include "base/test/mock_callback.h"
+#include "content/public/browser/browser_task_traits.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"
@@ -54,7 +56,7 @@ class TestBrowserContextWithRealURLRequestContextGetter
public:
TestBrowserContextWithRealURLRequestContextGetter() {
request_context_ = base::MakeRefCounted<net::TestURLRequestContextGetter>(
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO));
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO}));
salt_ = TestBrowserContext::GetMediaDeviceIDSalt();
}
@@ -132,15 +134,16 @@ class AudioOutputAuthorizationHandlerTest : public RenderViewHostTestHarness {
// enough for our code.
for (int i = 0; i < 20; ++i) {
base::RunLoop().RunUntilIdle();
- SyncWith(BrowserThread::GetTaskRunnerForThread(BrowserThread::IO));
+ SyncWith(
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO}));
SyncWith(audio_manager_->GetWorkerTaskRunner());
}
}
std::string GetRawNondefaultId() {
std::string id;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&AudioOutputAuthorizationHandlerTest::GetRawNondefaultIdOnIOThread,
base::Unretained(this), base::Unretained(&id)));
@@ -198,8 +201,8 @@ TEST_F(AudioOutputAuthorizationHandlerTest, AuthorizeDefaultDevice_Ok) {
std::make_unique<AudioOutputAuthorizationHandler>(
GetAudioSystem(), GetMediaStreamManager(), process()->GetID());
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&AudioOutputAuthorizationHandler::RequestDeviceAuthorization,
base::Unretained(handler.get()), main_rfh()->GetRoutingID(), 0,
@@ -220,8 +223,8 @@ TEST_F(AudioOutputAuthorizationHandlerTest,
std::make_unique<AudioOutputAuthorizationHandler>(
GetAudioSystem(), GetMediaStreamManager(), process()->GetID());
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&AudioOutputAuthorizationHandler::RequestDeviceAuthorization,
base::Unretained(handler.get()), main_rfh()->GetRoutingID(), 0,
@@ -243,8 +246,8 @@ TEST_F(AudioOutputAuthorizationHandlerTest,
std::unique_ptr<AudioOutputAuthorizationHandler> handler =
std::make_unique<AudioOutputAuthorizationHandler>(
GetAudioSystem(), GetMediaStreamManager(), process()->GetID());
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&AudioOutputAuthorizationHandler::OverridePermissionsForTesting,
base::Unretained(handler.get()), false));
@@ -254,8 +257,8 @@ TEST_F(AudioOutputAuthorizationHandlerTest,
std::string(), std::string()))
.Times(1);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&AudioOutputAuthorizationHandler::RequestDeviceAuthorization,
base::Unretained(handler.get()), main_rfh()->GetRoutingID(), 0,
@@ -276,8 +279,8 @@ TEST_F(AudioOutputAuthorizationHandlerTest,
std::unique_ptr<AudioOutputAuthorizationHandler> handler =
std::make_unique<AudioOutputAuthorizationHandler>(
GetAudioSystem(), GetMediaStreamManager(), process()->GetID());
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&AudioOutputAuthorizationHandler::OverridePermissionsForTesting,
base::Unretained(handler.get()), true));
@@ -286,8 +289,8 @@ TEST_F(AudioOutputAuthorizationHandlerTest,
raw_nondefault_id, std::string()))
.Times(1);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&AudioOutputAuthorizationHandler::RequestDeviceAuthorization,
base::Unretained(handler.get()), main_rfh()->GetRoutingID(), 0,
@@ -308,8 +311,8 @@ TEST_F(AudioOutputAuthorizationHandlerTest, AuthorizeInvalidDeviceId_NotFound) {
std::string(), std::string()))
.Times(1);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&AudioOutputAuthorizationHandler::RequestDeviceAuthorization,
base::Unretained(handler.get()), main_rfh()->GetRoutingID(), 0,
@@ -343,8 +346,8 @@ TEST_F(AudioOutputAuthorizationHandlerTest,
std::string(), std::string()))
.Times(1);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&AudioOutputAuthorizationHandler::RequestDeviceAuthorization,
base::Unretained(handler.get()), main_rfh()->GetRoutingID(), 0,
@@ -367,8 +370,8 @@ TEST_F(AudioOutputAuthorizationHandlerTest,
std::string()))
.Times(1);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&AudioOutputAuthorizationHandler::RequestDeviceAuthorization,
base::Unretained(handler.get()), main_rfh()->GetRoutingID(),
@@ -389,16 +392,16 @@ TEST_F(AudioOutputAuthorizationHandlerTest,
std::unique_ptr<AudioOutputAuthorizationHandler> handler =
std::make_unique<AudioOutputAuthorizationHandler>(
GetAudioSystem(), GetMediaStreamManager(), process()->GetID());
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&AudioOutputAuthorizationHandler::OverridePermissionsForTesting,
base::Unretained(handler.get()), true));
EXPECT_CALL(listener, Run(media::OUTPUT_DEVICE_STATUS_OK, _,
raw_nondefault_id, std::string()));
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&AudioOutputAuthorizationHandler::RequestDeviceAuthorization,
base::Unretained(handler.get()), main_rfh()->GetRoutingID(), 0,
@@ -413,8 +416,8 @@ TEST_F(AudioOutputAuthorizationHandlerTest,
context->set_media_device_id_salt("new salt");
EXPECT_CALL(listener, Run(media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND, _, _,
std::string()));
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&AudioOutputAuthorizationHandler::RequestDeviceAuthorization,
base::Unretained(handler.get()), main_rfh()->GetRoutingID(), 0,
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 81cd7e4f1f4..aa87128fe0b 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
@@ -9,10 +9,12 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/strings/stringprintf.h"
+#include "base/task/post_task.h"
#include "content/browser/media/audio_stream_monitor.h"
#include "content/browser/media/capture/audio_mirroring_manager.h"
#include "content/browser/media/media_internals.h"
#include "content/browser/renderer_host/media/media_stream_manager.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/media_observer.h"
#include "media/audio/audio_output_controller.h"
@@ -64,29 +66,29 @@ AudioOutputDelegateImpl::ControllerEventHandler::ControllerEventHandler(
: delegate_(std::move(delegate)), stream_id_(stream_id) {}
void AudioOutputDelegateImpl::ControllerEventHandler::OnControllerCreated() {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&AudioOutputDelegateImpl::SendCreatedNotification,
delegate_));
}
void AudioOutputDelegateImpl::ControllerEventHandler::OnControllerPlaying() {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&AudioOutputDelegateImpl::UpdatePlayingState, delegate_,
true));
}
void AudioOutputDelegateImpl::ControllerEventHandler::OnControllerPaused() {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&AudioOutputDelegateImpl::UpdatePlayingState, delegate_,
false));
}
void AudioOutputDelegateImpl::ControllerEventHandler::OnControllerError() {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&AudioOutputDelegateImpl::OnError, delegate_));
}
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 ac462bdb117..83bca5dac78 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
@@ -13,7 +13,9 @@
#include "base/command_line.h"
#include "base/run_loop.h"
#include "base/sync_socket.h"
+#include "base/task/post_task.h"
#include "content/browser/media/capture/audio_mirroring_manager.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/media_observer.h"
#include "content/public/test/test_browser_thread_bundle.h"
@@ -206,7 +208,7 @@ class AudioOutputDelegateTest : public testing::Test {
EXPECT_CALL(mirroring_manager_, RemoveDiverter(NotNull()));
}
SyncWithAllThreads();
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, std::move(done));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI}, std::move(done));
}
void PlayTest(base::Closure done, bool use_bound_observer) {
@@ -252,7 +254,7 @@ class AudioOutputDelegateTest : public testing::Test {
EXPECT_CALL(mirroring_manager_, RemoveDiverter(NotNull()));
}
SyncWithAllThreads();
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, std::move(done));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI}, std::move(done));
}
void PauseTest(base::Closure done) {
@@ -283,7 +285,7 @@ class AudioOutputDelegateTest : public testing::Test {
EXPECT_CALL(mirroring_manager_, RemoveDiverter(NotNull()));
}
SyncWithAllThreads();
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, std::move(done));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI}, std::move(done));
}
void PlayPausePlayTest(base::Closure done) {
@@ -320,7 +322,7 @@ class AudioOutputDelegateTest : public testing::Test {
EXPECT_CALL(mirroring_manager_, RemoveDiverter(NotNull()));
}
SyncWithAllThreads();
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, std::move(done));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI}, std::move(done));
}
void PlayPlayTest(base::Closure done) {
@@ -354,7 +356,7 @@ class AudioOutputDelegateTest : public testing::Test {
EXPECT_CALL(mirroring_manager_, RemoveDiverter(NotNull()));
}
SyncWithAllThreads();
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, std::move(done));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI}, std::move(done));
}
void CreateDivertTest(base::Closure done) {
@@ -386,7 +388,7 @@ class AudioOutputDelegateTest : public testing::Test {
EXPECT_CALL(mirroring_manager_, RemoveDiverter(NotNull()));
}
SyncWithAllThreads();
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, std::move(done));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI}, std::move(done));
}
void CreateDivertPauseTest(base::Closure done) {
@@ -417,7 +419,7 @@ class AudioOutputDelegateTest : public testing::Test {
EXPECT_CALL(mirroring_manager_, RemoveDiverter(NotNull()));
}
SyncWithAllThreads();
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, std::move(done));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI}, std::move(done));
}
void PlayDivertTest(base::Closure done) {
@@ -451,7 +453,7 @@ class AudioOutputDelegateTest : public testing::Test {
EXPECT_CALL(mirroring_manager_, RemoveDiverter(NotNull()));
}
SyncWithAllThreads();
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, std::move(done));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI}, std::move(done));
}
void TrampolineToUI(base::Closure done,
@@ -459,7 +461,7 @@ class AudioOutputDelegateTest : public testing::Test {
// Destruct and then sync since destruction will post some tasks.
delegate.reset();
SyncWithAllThreads();
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, std::move(done));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI}, std::move(done));
}
void ErrorTest(base::Closure done) {
@@ -517,7 +519,7 @@ class AudioOutputDelegateTest : public testing::Test {
std::move(observer_ptr), kDefaultDeviceId);
}
SyncWithAllThreads();
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, std::move(done));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI}, std::move(done));
}
void PlayAndDestroyTest(base::Closure done) {
@@ -547,7 +549,7 @@ class AudioOutputDelegateTest : public testing::Test {
delegate.OnPlayStream();
}
SyncWithAllThreads();
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, std::move(done));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI}, std::move(done));
}
void ErrorAndDestroyTest(base::Closure done) {
@@ -576,7 +578,7 @@ class AudioOutputDelegateTest : public testing::Test {
delegate.GetControllerForTesting()->OnError();
}
SyncWithAllThreads();
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, std::move(done));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI}, std::move(done));
}
protected:
@@ -594,7 +596,8 @@ class AudioOutputDelegateTest : public testing::Test {
// least one task will be run. 20 iterations should be enough for our code.
for (int i = 0; i < 20; ++i) {
base::RunLoop(base::RunLoop::Type::kNestableTasksAllowed).RunUntilIdle();
- SyncWith(BrowserThread::GetTaskRunnerForThread(BrowserThread::UI));
+ SyncWith(
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::UI}));
SyncWith(audio_manager_->GetWorkerTaskRunner());
}
}
@@ -615,8 +618,8 @@ class AudioOutputDelegateTest : public testing::Test {
TEST_F(AudioOutputDelegateTest, Create) {
base::RunLoop l;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&AudioOutputDelegateTest::CreateTest,
base::Unretained(this), l.QuitClosure()));
l.Run();
@@ -624,8 +627,8 @@ TEST_F(AudioOutputDelegateTest, Create) {
TEST_F(AudioOutputDelegateTest, Play) {
base::RunLoop l;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&AudioOutputDelegateTest::PlayTest, base::Unretained(this),
l.QuitClosure(), true /* use_bound_observer */));
l.Run();
@@ -633,8 +636,8 @@ TEST_F(AudioOutputDelegateTest, Play) {
TEST_F(AudioOutputDelegateTest, PlayWithUnboundObserver) {
base::RunLoop l;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&AudioOutputDelegateTest::PlayTest, base::Unretained(this),
l.QuitClosure(), false /* use_bound_observer */));
l.Run();
@@ -642,8 +645,8 @@ TEST_F(AudioOutputDelegateTest, PlayWithUnboundObserver) {
TEST_F(AudioOutputDelegateTest, Pause) {
base::RunLoop l;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&AudioOutputDelegateTest::PauseTest,
base::Unretained(this), l.QuitClosure()));
l.Run();
@@ -651,8 +654,8 @@ TEST_F(AudioOutputDelegateTest, Pause) {
TEST_F(AudioOutputDelegateTest, PlayPausePlay) {
base::RunLoop l;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&AudioOutputDelegateTest::PlayPausePlayTest,
base::Unretained(this), l.QuitClosure()));
l.Run();
@@ -660,8 +663,8 @@ TEST_F(AudioOutputDelegateTest, PlayPausePlay) {
TEST_F(AudioOutputDelegateTest, PlayPlay) {
base::RunLoop l;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&AudioOutputDelegateTest::PlayPlayTest,
base::Unretained(this), l.QuitClosure()));
l.Run();
@@ -669,8 +672,8 @@ TEST_F(AudioOutputDelegateTest, PlayPlay) {
TEST_F(AudioOutputDelegateTest, PlayDivert) {
base::RunLoop l;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&AudioOutputDelegateTest::PlayDivertTest,
base::Unretained(this), l.QuitClosure()));
l.Run();
@@ -678,8 +681,8 @@ TEST_F(AudioOutputDelegateTest, PlayDivert) {
TEST_F(AudioOutputDelegateTest, CreateDivert) {
base::RunLoop l;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&AudioOutputDelegateTest::CreateDivertTest,
base::Unretained(this), l.QuitClosure()));
l.Run();
@@ -687,8 +690,8 @@ TEST_F(AudioOutputDelegateTest, CreateDivert) {
TEST_F(AudioOutputDelegateTest, Error) {
base::RunLoop l;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&AudioOutputDelegateTest::ErrorTest,
base::Unretained(this), l.QuitClosure()));
l.Run();
@@ -696,8 +699,8 @@ TEST_F(AudioOutputDelegateTest, Error) {
TEST_F(AudioOutputDelegateTest, CreateAndDestroy) {
base::RunLoop l;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&AudioOutputDelegateTest::CreateAndDestroyTest,
base::Unretained(this), l.QuitClosure()));
l.Run();
@@ -705,8 +708,8 @@ TEST_F(AudioOutputDelegateTest, CreateAndDestroy) {
TEST_F(AudioOutputDelegateTest, PlayAndDestroy) {
base::RunLoop l;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&AudioOutputDelegateTest::PlayAndDestroyTest,
base::Unretained(this), l.QuitClosure()));
l.Run();
@@ -714,8 +717,8 @@ TEST_F(AudioOutputDelegateTest, PlayAndDestroy) {
TEST_F(AudioOutputDelegateTest, ErrorAndDestroy) {
base::RunLoop l;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&AudioOutputDelegateTest::PlayAndDestroyTest,
base::Unretained(this), l.QuitClosure()));
l.Run();
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 ffa3e8c0062..d70bb7c1fa2 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
@@ -10,10 +10,12 @@
#include "base/command_line.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/stringprintf.h"
+#include "base/task/post_task.h"
#include "build/build_config.h"
+#include "content/browser/gpu/video_capture_dependencies.h"
#include "content/browser/renderer_host/media/in_process_launched_video_capture_device.h"
#include "content/browser/renderer_host/media/video_capture_controller.h"
-#include "content/browser/renderer_host/media/video_capture_dependencies.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/desktop_media_id.h"
#include "content/public/common/media_stream_request.h"
@@ -49,8 +51,8 @@ std::unique_ptr<media::VideoCaptureJpegDecoder> CreateGpuJpegDecoder(
return std::make_unique<media::VideoCaptureJpegDecoderImpl>(
base::BindRepeating(
&content::VideoCaptureDependencies::CreateJpegDecodeAccelerator),
- content::BrowserThread::GetTaskRunnerForThread(
- content::BrowserThread::IO),
+ base::CreateSingleThreadTaskRunnerWithTraits(
+ {content::BrowserThread::IO}),
std::move(decode_done_cb), std::move(send_log_message_cb));
}
@@ -99,7 +101,7 @@ void InProcessVideoCaptureDeviceLauncher::LaunchDeviceAsync(
// to the IO thread.
auto receiver = std::make_unique<media::VideoFrameReceiverOnTaskRunner>(
receiver_on_io_thread,
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO));
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO}));
base::OnceClosure start_capture_closure;
// Use of Unretained |this| is safe, because |done_cb| guarantees that |this|
diff --git a/chromium/content/browser/renderer_host/media/media_capture_devices_impl.cc b/chromium/content/browser/renderer_host/media/media_capture_devices_impl.cc
index 9a8444f1392..02f6e4e6501 100644
--- a/chromium/content/browser/renderer_host/media/media_capture_devices_impl.cc
+++ b/chromium/content/browser/renderer_host/media/media_capture_devices_impl.cc
@@ -4,8 +4,10 @@
#include "content/browser/renderer_host/media/media_capture_devices_impl.h"
+#include "base/task/post_task.h"
#include "content/browser/browser_main_loop.h"
#include "content/browser/renderer_host/media/media_stream_manager.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
namespace content {
@@ -14,8 +16,8 @@ namespace {
void EnsureMonitorCaptureDevices() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&MediaStreamManager::EnsureDeviceMonitorStarted,
base::Unretained(
@@ -57,8 +59,8 @@ void MediaCaptureDevicesImpl::AddVideoCaptureObserver(
MediaStreamManager* media_stream_manager =
BrowserMainLoop::GetInstance()->media_stream_manager();
if (media_stream_manager != nullptr) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&MediaStreamManager::AddVideoCaptureObserver,
base::Unretained(media_stream_manager), observer));
} else {
@@ -70,8 +72,8 @@ void MediaCaptureDevicesImpl::RemoveAllVideoCaptureObservers() {
MediaStreamManager* media_stream_manager =
BrowserMainLoop::GetInstance()->media_stream_manager();
if (media_stream_manager != nullptr) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&MediaStreamManager::RemoveAllVideoCaptureObservers,
base::Unretained(media_stream_manager)));
} else {
@@ -84,8 +86,8 @@ void MediaCaptureDevicesImpl::OnAudioCaptureDevicesChanged(
if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
UpdateAudioDevicesOnUIThread(devices);
} else {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&MediaCaptureDevicesImpl::UpdateAudioDevicesOnUIThread,
base::Unretained(this), devices));
}
@@ -96,8 +98,8 @@ void MediaCaptureDevicesImpl::OnVideoCaptureDevicesChanged(
if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
UpdateVideoDevicesOnUIThread(devices);
} else {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&MediaCaptureDevicesImpl::UpdateVideoDevicesOnUIThread,
base::Unretained(this), devices));
}
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 1812e217cec..6f3fe56d91c 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
@@ -10,6 +10,7 @@
#include "base/bind_helpers.h"
#include "base/command_line.h"
+#include "base/task/post_task.h"
#include "base/task_runner_util.h"
#include "content/browser/bad_message.h"
#include "content/browser/media/media_devices_permission_checker.h"
@@ -17,6 +18,7 @@
#include "content/browser/renderer_host/media/video_capture_manager.h"
#include "content/common/media/media_devices.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/media_device_id.h"
#include "content/public/browser/render_frame_host.h"
@@ -122,7 +124,8 @@ void MediaDevicesDispatcherHost::GetVideoInputCapabilities(
GetVideoInputCapabilitiesCallback client_callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
base::PostTaskAndReplyWithResult(
- BrowserThread::GetTaskRunnerForThread(BrowserThread::UI).get(), FROM_HERE,
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::UI}).get(),
+ FROM_HERE,
base::BindOnce(media_stream_manager_->media_devices_manager()
->salt_and_origin_callback(),
render_process_id_, render_frame_id_),
@@ -149,7 +152,8 @@ void MediaDevicesDispatcherHost::GetAvailableVideoInputDeviceFormats(
void MediaDevicesDispatcherHost::GetAudioInputCapabilities(
GetAudioInputCapabilitiesCallback client_callback) {
base::PostTaskAndReplyWithResult(
- BrowserThread::GetTaskRunnerForThread(BrowserThread::UI).get(), FROM_HERE,
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::UI}).get(),
+ FROM_HERE,
base::BindOnce(media_stream_manager_->media_devices_manager()
->salt_and_origin_callback(),
render_process_id_, render_frame_id_),
@@ -251,7 +255,8 @@ void MediaDevicesDispatcherHost::GetVideoInputDeviceFormats(
GetVideoInputDeviceFormatsCallback client_callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
base::PostTaskAndReplyWithResult(
- BrowserThread::GetTaskRunnerForThread(BrowserThread::UI).get(), FROM_HERE,
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::UI}).get(),
+ FROM_HERE,
base::BindOnce(media_stream_manager_->media_devices_manager()
->salt_and_origin_callback(),
render_process_id_, render_frame_id_),
@@ -267,11 +272,12 @@ void MediaDevicesDispatcherHost::EnumerateVideoDevicesForFormats(
bool try_in_use_first,
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.device_id_salt,
- salt_and_origin.origin));
+ media_stream_manager_->video_capture_manager()->EnumerateDevices(
+ base::BindOnce(
+ &MediaDevicesDispatcherHost::FinalizeGetVideoInputDeviceFormats,
+ weak_factory_.GetWeakPtr(), base::Passed(&client_callback), device_id,
+ try_in_use_first, salt_and_origin.device_id_salt,
+ salt_and_origin.origin));
}
void MediaDevicesDispatcherHost::FinalizeGetVideoInputDeviceFormats(
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 307115c6d57..d79886ff495 100644
--- a/chromium/content/browser/renderer_host/media/media_devices_manager.cc
+++ b/chromium/content/browser/renderer_host/media/media_devices_manager.cc
@@ -14,7 +14,9 @@
#include "base/command_line.h"
#include "base/location.h"
#include "base/sequence_checker.h"
+#include "base/stl_util.h"
#include "base/strings/stringprintf.h"
+#include "base/task/post_task.h"
#include "base/task_runner_util.h"
#include "base/threading/thread_checker.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -23,6 +25,7 @@
#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_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_features.h"
#include "media/audio/audio_device_description.h"
@@ -422,7 +425,8 @@ void MediaDevicesManager::EnumerateDevices(
DCHECK_CURRENTLY_ON(BrowserThread::IO);
base::PostTaskAndReplyWithResult(
- BrowserThread::GetTaskRunnerForThread(BrowserThread::UI).get(), FROM_HERE,
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::UI}).get(),
+ FROM_HERE,
base::BindOnce(salt_and_origin_callback_, render_process_id,
render_frame_id),
base::BindOnce(&MediaDevicesManager::CheckPermissionsForEnumerateDevices,
@@ -515,8 +519,8 @@ void MediaDevicesManager::StartMonitoring() {
}
#if defined(OS_MACOSX)
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::Bind(&MediaDevicesManager::StartMonitoringOnUIThread,
base::Unretained(this)));
#endif
@@ -584,11 +588,9 @@ media::VideoCaptureFormats MediaDevicesManager::GetVideoInputFormats(
video_capture_manager_->GetDeviceSupportedFormats(device_id, &formats);
ReplaceInvalidFrameRatesWithFallback(&formats);
// Remove formats that have zero resolution.
- formats.erase(std::remove_if(formats.begin(), formats.end(),
- [](const media::VideoCaptureFormat& format) {
- return format.frame_size.GetArea() <= 0;
- }),
- formats.end());
+ base::EraseIf(formats, [](const media::VideoCaptureFormat& format) {
+ return format.frame_size.GetArea() <= 0;
+ });
// If the device does not report any valid format, use a fallback list of
// standard formats.
@@ -733,8 +735,8 @@ void MediaDevicesManager::DoEnumerateDevices(MediaDeviceType type) {
break;
case MEDIA_DEVICE_TYPE_VIDEO_INPUT:
video_capture_manager_->EnumerateDevices(
- base::Bind(&MediaDevicesManager::VideoInputDevicesEnumerated,
- weak_factory_.GetWeakPtr()));
+ base::BindOnce(&MediaDevicesManager::VideoInputDevicesEnumerated,
+ weak_factory_.GetWeakPtr()));
break;
case MEDIA_DEVICE_TYPE_AUDIO_OUTPUT:
EnumerateAudioDevices(false /* is_input */);
@@ -946,7 +948,8 @@ void MediaDevicesManager::NotifyDeviceChangeSubscribers(
const SubscriptionRequest& request = subscription.second;
if (request.subscribe_types[type]) {
base::PostTaskAndReplyWithResult(
- BrowserThread::GetTaskRunnerForThread(BrowserThread::UI).get(),
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::UI})
+ .get(),
FROM_HERE,
base::BindOnce(salt_and_origin_callback_, request.render_process_id,
request.render_frame_id),
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 7ba5aff3293..2a4b6cfecf4 100644
--- a/chromium/content/browser/renderer_host/media/media_devices_manager.h
+++ b/chromium/content/browser/renderer_host/media/media_devices_manager.h
@@ -15,7 +15,7 @@
#include "base/containers/flat_map.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "base/system_monitor/system_monitor.h"
+#include "base/system/system_monitor.h"
#include "content/browser/media/media_devices_util.h"
#include "content/common/content_export.h"
#include "content/common/media/media_devices.h"
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 9f623c4c883..8a7be0e38d2 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
@@ -7,8 +7,10 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/logging.h"
+#include "base/task/post_task.h"
#include "base/task_runner_util.h"
#include "content/browser/renderer_host/media/media_stream_manager.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h"
#include "services/service_manager/public/cpp/interface_provider.h"
@@ -83,8 +85,8 @@ MediaStreamDispatcherHost::GetMediaStreamDeviceObserver() {
observer.set_connection_error_handler(base::BindOnce(
&MediaStreamDispatcherHost::OnMediaStreamDeviceObserverConnectionError,
weak_factory_.GetWeakPtr()));
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&BindMediaStreamDeviceObserverRequest, render_process_id_,
render_frame_id_, std::move(dispatcher_request)));
media_stream_device_observer_ = std::move(observer);
@@ -113,7 +115,8 @@ void MediaStreamDispatcherHost::GenerateStream(
DCHECK_CURRENTLY_ON(BrowserThread::IO);
base::PostTaskAndReplyWithResult(
- BrowserThread::GetTaskRunnerForThread(BrowserThread::UI).get(), FROM_HERE,
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::UI}).get(),
+ FROM_HERE,
base::BindOnce(salt_and_origin_callback_, render_process_id_,
render_frame_id_),
base::BindOnce(&MediaStreamDispatcherHost::DoGenerateStream,
@@ -164,7 +167,8 @@ void MediaStreamDispatcherHost::OpenDevice(int32_t page_request_id,
DCHECK_CURRENTLY_ON(BrowserThread::IO);
base::PostTaskAndReplyWithResult(
- BrowserThread::GetTaskRunnerForThread(BrowserThread::UI).get(), FROM_HERE,
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::UI}).get(),
+ FROM_HERE,
base::BindOnce(salt_and_origin_callback_, render_process_id_,
render_frame_id_),
base::BindOnce(&MediaStreamDispatcherHost::DoOpenDevice,
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 a1cd9c20c51..a9677e7bb22 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
@@ -16,7 +16,7 @@
#include "base/containers/queue.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
-#include "base/system_monitor/system_monitor.h"
+#include "base/system/system_monitor.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "content/browser/renderer_host/media/audio_input_device_manager.h"
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 a154e72ac00..280d5f2319b 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_manager.cc
+++ b/chromium/content/browser/renderer_host/media/media_stream_manager.cc
@@ -23,12 +23,14 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
+#include "base/task/post_task.h"
#include "base/task_runner_util.h"
#include "base/threading/thread.h"
#include "base/threading/thread_local.h"
#include "build/build_config.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/gpu/gpu_process_host.h"
+#include "content/browser/gpu/video_capture_dependencies.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"
@@ -36,10 +38,11 @@
#include "content/browser/renderer_host/media/media_devices_manager.h"
#include "content/browser/renderer_host/media/media_stream_ui_proxy.h"
#include "content/browser/renderer_host/media/service_video_capture_provider.h"
-#include "content/browser/renderer_host/media/video_capture_dependencies.h"
#include "content/browser/renderer_host/media/video_capture_manager.h"
#include "content/browser/renderer_host/media/video_capture_provider_switcher.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
+#include "content/browser/screenlock_monitor/screenlock_monitor.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/desktop_media_id.h"
@@ -60,6 +63,7 @@
#include "media/capture/video/fake_video_capture_device.h"
#include "media/capture/video/fake_video_capture_device_factory.h"
#include "media/capture/video/video_capture_system_impl.h"
+#include "media/mojo/interfaces/display_media_information.mojom.h"
#include "services/video_capture/public/uma/video_capture_service_event.h"
#include "url/gurl.h"
#include "url/origin.h"
@@ -190,14 +194,20 @@ MediaStreamType AdjustAudioStreamTypeBasedOnCommandLineSwitches(
: MEDIA_NO_SERVICE;
}
-// Returns DesktopMediaID with fake initializers if
-// |kUseFakeDeviceForMediaStream| is set. Returns the default DesktopMediaID
-// otherwise.
-DesktopMediaID FindDesktopMediaIDFromFakeDeviceConfig() {
+// Returns MediaStreamDevice built with DesktopMediaID with fake
+// initializers if |kUseFakeDeviceForMediaStream| is set. Returns a
+// MediaStreamDevice with default DesktopMediaID otherwise.
+MediaStreamDevice MediaStreamDeviceFromFakeDeviceConfig() {
// TODO(emircan): When getDisplayMedia() accepts constraints, pick
// the corresponding type.
- DesktopMediaID media_id =
- DesktopMediaID(DesktopMediaID::TYPE_SCREEN, DesktopMediaID::kNullId);
+ DesktopMediaID media_id(DesktopMediaID::TYPE_SCREEN, DesktopMediaID::kNullId);
+
+ MediaStreamDevice device(MEDIA_DISPLAY_VIDEO_CAPTURE, media_id.ToString(),
+ media_id.ToString());
+ media::mojom::DisplayCaptureSurfaceType display_surface =
+ media::mojom::DisplayCaptureSurfaceType::MONITOR;
+ device.display_media_info = media::mojom::DisplayMediaInformation::New(
+ display_surface, true, media::mojom::CursorCaptureType::NEVER);
const base::CommandLine* command_line =
base::CommandLine::ForCurrentProcess();
@@ -210,26 +220,31 @@ DesktopMediaID FindDesktopMediaIDFromFakeDeviceConfig() {
switches::kUseFakeDeviceForMediaStream),
&config);
if (config.empty())
- return media_id;
+ return device;
DesktopMediaID::Type desktop_media_type = DesktopMediaID::TYPE_NONE;
switch (config[0].display_media_type) {
case media::FakeVideoCaptureDevice::DisplayMediaType::ANY:
- desktop_media_type = DesktopMediaID::TYPE_SCREEN;
- break;
case media::FakeVideoCaptureDevice::DisplayMediaType::MONITOR:
desktop_media_type = DesktopMediaID::TYPE_SCREEN;
+ display_surface = media::mojom::DisplayCaptureSurfaceType::MONITOR;
break;
case media::FakeVideoCaptureDevice::DisplayMediaType::WINDOW:
desktop_media_type = DesktopMediaID::TYPE_WINDOW;
+ display_surface = media::mojom::DisplayCaptureSurfaceType::WINDOW;
break;
case media::FakeVideoCaptureDevice::DisplayMediaType::BROWSER:
desktop_media_type = DesktopMediaID::TYPE_WEB_CONTENTS;
+ display_surface = media::mojom::DisplayCaptureSurfaceType::BROWSER;
break;
}
media_id = DesktopMediaID(desktop_media_type, DesktopMediaID::kFakeId);
}
- return media_id;
+ device = MediaStreamDevice(MEDIA_DISPLAY_VIDEO_CAPTURE, media_id.ToString(),
+ media_id.ToString());
+ device.display_media_info = media::mojom::DisplayMediaInformation::New(
+ display_surface, true, media::mojom::CursorCaptureType::NEVER);
+ return device;
}
} // namespace
@@ -422,8 +437,8 @@ class MediaStreamManager::DeviceRequest {
// static
void MediaStreamManager::SendMessageToNativeLog(const std::string& message) {
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&MediaStreamManager::SendMessageToNativeLog, message));
return;
}
@@ -504,7 +519,8 @@ MediaStreamManager::MediaStreamManager(
video_capture_provider = InProcessVideoCaptureProvider::CreateInstance(
std::make_unique<media::VideoCaptureSystemImpl>(
media::CreateVideoCaptureDeviceFactory(
- BrowserThread::GetTaskRunnerForThread(BrowserThread::UI))),
+ base::CreateSingleThreadTaskRunnerWithTraits(
+ {BrowserThread::UI}))),
std::move(device_task_runner),
base::BindRepeating(&SendVideoCaptureLogMessage));
}
@@ -603,9 +619,9 @@ std::string MediaStreamManager::MakeMediaAccessRequest(
// and thus can not handle a response. Using base::Unretained is safe since
// MediaStreamManager is deleted on the UI thread, after the IO thread has
// been stopped.
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::BindOnce(&MediaStreamManager::SetUpRequest,
- base::Unretained(this), label));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(&MediaStreamManager::SetUpRequest,
+ base::Unretained(this), label));
return label;
}
@@ -647,9 +663,9 @@ void MediaStreamManager::GenerateStream(
// and thus can not handle a response. Using base::Unretained is safe since
// MediaStreamManager is deleted on the UI thread, after the IO thread has
// been stopped.
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::BindOnce(&MediaStreamManager::SetUpRequest,
- base::Unretained(this), label));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(&MediaStreamManager::SetUpRequest,
+ base::Unretained(this), label));
}
void MediaStreamManager::CancelRequest(int render_process_id,
@@ -697,7 +713,7 @@ void MediaStreamManager::CancelRequest(const std::string& label) {
void MediaStreamManager::CancelAllRequests(int render_process_id,
int render_frame_id) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DeviceRequests::iterator request_it = requests_.begin();
+ auto request_it = requests_.begin();
while (request_it != requests_.end()) {
if (request_it->second->requesting_process_id != render_process_id ||
request_it->second->requesting_frame_id != render_frame_id) {
@@ -757,7 +773,7 @@ void MediaStreamManager::StopDevice(MediaStreamType type, int session_id) {
DVLOG(1) << "StopDevice"
<< "{type = " << type << "}"
<< "{session_id = " << session_id << "}";
- DeviceRequests::iterator request_it = requests_.begin();
+ auto request_it = requests_.begin();
while (request_it != requests_.end()) {
DeviceRequest* request = request_it->second;
MediaStreamDevices* devices = &request->devices;
@@ -766,7 +782,7 @@ void MediaStreamManager::StopDevice(MediaStreamType type, int session_id) {
++request_it;
continue;
}
- MediaStreamDevices::iterator device_it = devices->begin();
+ auto device_it = devices->begin();
while (device_it != devices->end()) {
if (device_it->type != type || device_it->session_id != session_id) {
++device_it;
@@ -847,9 +863,9 @@ void MediaStreamManager::OpenDevice(int render_process_id,
// and thus can not handle a response. Using base::Unretained is safe since
// MediaStreamManager is deleted on the UI thread, after the IO thread has
// been stopped.
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::BindOnce(&MediaStreamManager::SetUpRequest,
- base::Unretained(this), label));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(&MediaStreamManager::SetUpRequest,
+ base::Unretained(this), label));
}
bool MediaStreamManager::TranslateSourceIdToDeviceId(
@@ -1018,8 +1034,8 @@ MediaStreamManager::DeviceRequest* MediaStreamManager::FindRequest(
void MediaStreamManager::DeleteRequest(const std::string& label) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DVLOG(1) << "DeleteRequest({label= " << label << "})";
- for (DeviceRequests::iterator request_it = requests_.begin();
- request_it != requests_.end(); ++request_it) {
+ for (auto request_it = requests_.begin(); request_it != requests_.end();
+ ++request_it) {
if (request_it->first == label) {
std::unique_ptr<DeviceRequest> request(request_it->second);
requests_.erase(request_it);
@@ -1089,10 +1105,7 @@ void MediaStreamManager::PostRequestToUI(
if (request->video_type() == MEDIA_DISPLAY_VIDEO_CAPTURE) {
DCHECK(devices.empty());
- DesktopMediaID media_id = FindDesktopMediaIDFromFakeDeviceConfig();
- devices.push_back(MediaStreamDevice(MEDIA_DISPLAY_VIDEO_CAPTURE,
- media_id.ToString(),
- media_id.ToString()));
+ devices.push_back(MediaStreamDeviceFromFakeDeviceConfig());
}
std::unique_ptr<FakeMediaStreamUIProxy> fake_ui = fake_ui_factory_.Run();
fake_ui->SetAvailableDevices(devices);
@@ -1233,8 +1246,8 @@ bool MediaStreamManager::SetUpTabCaptureRequest(DeviceRequest* request,
return false;
}
- BrowserThread::PostTaskAndReplyWithResult(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraitsAndReplyWithResult(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&MediaStreamManager::ResolveTabCaptureDeviceIdOnUIThread,
base::Unretained(this), capture_device_id,
request->requesting_process_id,
@@ -1450,8 +1463,8 @@ void MediaStreamManager::InitializeMaybeAsync(
// initialization is done synchronously. Other clients call this from a
// different thread and expect initialization to run asynchronously.
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&MediaStreamManager::InitializeMaybeAsync,
base::Unretained(this),
std::move(video_capture_provider)));
@@ -1474,7 +1487,8 @@ void MediaStreamManager::InitializeMaybeAsync(
video_capture_manager_ =
new VideoCaptureManager(std::move(video_capture_provider),
- base::BindRepeating(&SendVideoCaptureLogMessage));
+ base::BindRepeating(&SendVideoCaptureLogMessage),
+ ScreenlockMonitor::Get());
video_capture_manager_->RegisterListener(this);
// Using base::Unretained(this) is safe because |this| owns and therefore
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 fae5c3ca81c..f8ac784541f 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
@@ -436,6 +436,7 @@ TEST_F(MediaStreamManagerTest, GetDisplayMediaRequest) {
run_loop_.Run();
EXPECT_EQ(MEDIA_DISPLAY_VIDEO_CAPTURE, video_device.type);
+ EXPECT_TRUE(video_device.display_media_info.has_value());
EXPECT_CALL(*media_observer_, OnMediaRequestStateChanged(
_, _, _, _, MEDIA_DISPLAY_VIDEO_CAPTURE,
MEDIA_REQUEST_STATE_CLOSING));
diff --git a/chromium/content/browser/renderer_host/media/media_stream_track_metrics_host.cc b/chromium/content/browser/renderer_host/media/media_stream_track_metrics_host.cc
index 4d22fb1c51a..120bc443e69 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_track_metrics_host.cc
+++ b/chromium/content/browser/renderer_host/media/media_stream_track_metrics_host.cc
@@ -21,9 +21,7 @@ MediaStreamTrackMetricsHost::MediaStreamTrackMetricsHost() {}
MediaStreamTrackMetricsHost::~MediaStreamTrackMetricsHost() {
// Our render process has exited. We won't receive any more IPC
// messages from it. Assume all tracks ended now.
- for (TrackMap::iterator it = tracks_.begin();
- it != tracks_.end();
- ++it) {
+ for (auto it = tracks_.begin(); it != tracks_.end(); ++it) {
TrackInfo& info = it->second;
ReportDuration(info);
}
diff --git a/chromium/content/browser/renderer_host/media/media_stream_ui_proxy.cc b/chromium/content/browser/renderer_host/media/media_stream_ui_proxy.cc
index 43c3b83d83d..4db595a7b34 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_ui_proxy.cc
+++ b/chromium/content/browser/renderer_host/media/media_stream_ui_proxy.cc
@@ -8,9 +8,11 @@
#include "base/command_line.h"
#include "base/macros.h"
+#include "base/task/post_task.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_impl.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_switches.h"
#include "media/capture/video/fake_video_capture_device.h"
@@ -163,8 +165,8 @@ void MediaStreamUIProxy::Core::ProcessAccessRequestResponse(
result = MEDIA_DEVICE_PERMISSION_DENIED;
ui_ = std::move(stream_ui);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&MediaStreamUIProxy::ProcessAccessRequestResponse, proxy_,
filtered_devices, result));
}
@@ -172,8 +174,8 @@ void MediaStreamUIProxy::Core::ProcessAccessRequestResponse(
void MediaStreamUIProxy::Core::ProcessStopRequestFromUI() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&MediaStreamUIProxy::ProcessStopRequestFromUI, proxy_));
}
@@ -216,8 +218,8 @@ void MediaStreamUIProxy::RequestAccess(
DCHECK_CURRENTLY_ON(BrowserThread::IO);
response_callback_ = std::move(response_callback);
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&Core::RequestAccess, base::Unretained(core_.get()),
std::move(request)));
}
@@ -231,8 +233,8 @@ void MediaStreamUIProxy::OnStarted(base::OnceClosure stop_callback,
// Owned by the PostTaskAndReply callback.
gfx::NativeViewId* window_id = new gfx::NativeViewId(0);
- BrowserThread::PostTaskAndReply(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraitsAndReply(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&Core::OnStarted, base::Unretained(core_.get()),
window_id),
base::BindOnce(&MediaStreamUIProxy::OnWindowId,
@@ -294,8 +296,8 @@ void FakeMediaStreamUIProxy::RequestAccess(
if (base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
switches::kUseFakeUIForMediaStream) == "deny") {
// Immediately deny the request.
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&MediaStreamUIProxy::Core::ProcessAccessRequestResponse,
base::Unretained(core_.get()),
request->render_process_id, request->render_frame_id,
@@ -334,8 +336,8 @@ void FakeMediaStreamUIProxy::RequestAccess(
devices_to_use.clear();
}
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(
&MediaStreamUIProxy::Core::ProcessAccessRequestResponse,
base::Unretained(core_.get()), request->render_process_id,
diff --git a/chromium/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc b/chromium/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc
index 54c050bceba..73cdee45f57 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc
@@ -7,11 +7,12 @@
#include <string>
#include <utility>
-#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
+#include "base/task/post_task.h"
#include "build/build_config.h"
#include "content/browser/frame_host/render_frame_host_delegate.h"
-#include "content/public/test/test_browser_thread.h"
+#include "content/public/browser/browser_task_traits.h"
+#include "content/public/test/test_browser_thread_bundle.h"
#include "content/test/test_render_frame_host.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -65,9 +66,7 @@ class MockStopStreamHandler {
class MediaStreamUIProxyTest : public testing::Test {
public:
- MediaStreamUIProxyTest()
- : ui_thread_(BrowserThread::UI, &message_loop_),
- io_thread_(BrowserThread::IO, &message_loop_) {
+ MediaStreamUIProxyTest() {
proxy_ = MediaStreamUIProxy::CreateForTests(&delegate_);
}
@@ -77,9 +76,7 @@ class MediaStreamUIProxyTest : public testing::Test {
}
protected:
- base::MessageLoop message_loop_;
- TestBrowserThread ui_thread_;
- TestBrowserThread io_thread_;
+ TestBrowserThreadBundle thread_bundle_;
MockRenderFrameHostDelegate delegate_;
MockResponseCallback response_callback_;
@@ -324,8 +321,8 @@ class MediaStreamUIProxyFeaturePolicyTest
DCHECK_CURRENTLY_ON(BrowserThread::UI);
base::RunLoop run_loop;
quit_closure_ = run_loop.QuitClosure();
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&MediaStreamUIProxyFeaturePolicyTest::GetResultForRequestOnIOThread,
base::Unretained(this), std::move(request)));
@@ -376,8 +373,8 @@ class MediaStreamUIProxyFeaturePolicyTest
MediaStreamRequestResult result) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
proxy_.reset();
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&MediaStreamUIProxyFeaturePolicyTest::FinishedGetResult,
base::Unretained(this), devices, result));
}
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
index 5093cee0282..a84a59521eb 100644
--- 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
@@ -7,10 +7,12 @@
#include <utility>
#include "base/feature_list.h"
+#include "base/task/post_task.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/browser_task_traits.h"
#include "content/public/browser/media_device_id.h"
#include "content/public/common/content_features.h"
#include "media/base/audio_parameters.h"
@@ -33,8 +35,8 @@ void CheckPermissionAndGetSaltAndOrigin(
// 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));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(std::move(cb), salt_and_origin));
}
void OldEnumerateOutputDevices(
@@ -69,8 +71,8 @@ RenderFrameAudioInputStreamFactoryHandle::CreateFactory(
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::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&RenderFrameAudioInputStreamFactoryHandle::Init,
base::Unretained(handle.get()), std::move(request)));
return handle;
@@ -191,8 +193,8 @@ void OldRenderFrameAudioInputStreamFactory::AssociateInputAndOutputForAec(
}
}
} else {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(
CheckPermissionAndGetSaltAndOrigin, output_device_id,
render_process_id_, render_frame_id_,
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
index df02e54c4e6..e323b9c5f9c 100644
--- 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
@@ -8,10 +8,12 @@
#include <utility>
#include "base/metrics/histogram_macros.h"
+#include "base/task/post_task.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/browser_task_traits.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"
@@ -32,8 +34,8 @@ RenderFrameAudioOutputStreamFactoryHandle::CreateFactory(
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::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&RenderFrameAudioOutputStreamFactoryHandle::Init,
base::Unretained(handle.get()), std::move(request)));
return handle;
diff --git a/chromium/content/browser/renderer_host/media/peer_connection_tracker_host.cc b/chromium/content/browser/renderer_host/media/peer_connection_tracker_host.cc
index 2e3d9fd57ce..d8f55ef00d6 100644
--- a/chromium/content/browser/renderer_host/media/peer_connection_tracker_host.cc
+++ b/chromium/content/browser/renderer_host/media/peer_connection_tracker_host.cc
@@ -5,9 +5,11 @@
#include "content/browser/renderer_host/media/peer_connection_tracker_host.h"
#include "base/power_monitor/power_monitor.h"
+#include "base/task/post_task.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/webrtc/webrtc_internals.h"
#include "content/common/media/peer_connection_tracker_messages.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/webrtc_event_logger.h"
namespace content {
@@ -80,8 +82,8 @@ void PeerConnectionTrackerHost::OnAddPeerConnection(
void PeerConnectionTrackerHost::RemovePeerConnection(int lid) {
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&PeerConnectionTrackerHost::RemovePeerConnection, this,
lid));
return;
@@ -101,8 +103,8 @@ void PeerConnectionTrackerHost::UpdatePeerConnection(int lid,
const std::string& type,
const std::string& value) {
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&PeerConnectionTrackerHost::UpdatePeerConnection, this,
lid, type, value));
return;
@@ -137,8 +139,8 @@ void PeerConnectionTrackerHost::GetUserMedia(
const std::string& audio_constraints,
const std::string& video_constraints) {
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&PeerConnectionTrackerHost::GetUserMedia, this, origin,
audio, video, audio_constraints, video_constraints));
return;
@@ -154,8 +156,8 @@ void PeerConnectionTrackerHost::GetUserMedia(
void PeerConnectionTrackerHost::WebRtcEventLogWrite(int lid,
const std::string& output) {
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&PeerConnectionTrackerHost::WebRtcEventLogWrite, this,
lid, output));
return;
@@ -169,8 +171,8 @@ void PeerConnectionTrackerHost::WebRtcEventLogWrite(int lid,
}
void PeerConnectionTrackerHost::OnSuspend() {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&PeerConnectionTrackerHost::SendOnSuspendOnUIThread,
this));
}
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 d4d96fb5bfe..936d379fd15 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
@@ -4,15 +4,27 @@
#include "content/browser/renderer_host/media/render_frame_audio_input_stream_factory.h"
+#include <cstdint>
#include <string>
#include <utility>
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/memory/weak_ptr.h"
+#include "base/task/post_task.h"
#include "base/trace_event/trace_event.h"
-#include "content/browser/browser_main_loop.h"
+#include "base/unguessable_token.h"
+#include "content/browser/media/audio_stream_broker.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/media/media_devices_util.h"
+#include "content/browser/renderer_host/media/audio_input_device_manager.h"
+#include "content/browser/renderer_host/media/media_devices_manager.h"
#include "content/browser/renderer_host/media/media_stream_manager.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/media_device_id.h"
#include "content/public/browser/render_frame_host.h"
@@ -20,25 +32,29 @@
#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"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "services/audio/public/mojom/audio_processing.mojom.h"
+#include "url/origin.h"
namespace content {
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));
+AudioStreamBroker::LoopbackSource* GetLoopbackSourceOnUIThread(
+ int render_process_id,
+ int render_frame_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ auto* source = ForwardingAudioStreamFactory::CoreForFrame(
+ (RenderFrameHost::FromID(render_process_id, render_frame_id)));
+ if (!source) {
+ // The source of the capture has already been destroyed, so fail early.
+ return nullptr;
}
+ // Note: this pointer is sent over to the IO thread. This is safe since the
+ // destruction of |source| is posted to the IO thread and it hasn't been
+ // posted yet.
+ return source;
}
void EnumerateOutputDevices(MediaStreamManager* media_stream_manager,
@@ -59,75 +75,170 @@ void TranslateDeviceId(const std::string& device_id,
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));
+ cb.Run(device_info.device_id);
break;
}
}
// If we're unable to translate the device id, |cb| will not be run.
}
+void GetSaltOriginAndPermissionsOnUIThread(
+ int process_id,
+ int frame_id,
+ base::OnceCallback<void(MediaDeviceSaltAndOrigin salt_and_origin,
+ bool has_access)> cb) {
+ auto salt_and_origin = GetMediaDeviceSaltAndOrigin(process_id, frame_id);
+ bool access = MediaDevicesPermissionChecker().CheckPermissionOnUIThread(
+ MEDIA_DEVICE_TYPE_AUDIO_OUTPUT, process_id, frame_id);
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(std::move(cb), std::move(salt_and_origin), access));
+}
+
} // namespace
+class RenderFrameAudioInputStreamFactory::Core final
+ : public mojom::RendererAudioInputStreamFactory {
+ public:
+ Core(mojom::RendererAudioInputStreamFactoryRequest request,
+ MediaStreamManager* media_stream_manager,
+ RenderFrameHost* render_frame_host);
+
+ ~Core() final;
+
+ void Init(mojom::RendererAudioInputStreamFactoryRequest request);
+
+ // 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,
+ audio::mojom::AudioProcessingConfigPtr processing_config) final;
+
+ void AssociateInputAndOutputForAec(
+ const base::UnguessableToken& input_stream_id,
+ const std::string& output_device_id) final;
+
+ void CreateLoopbackStream(
+ mojom::RendererAudioInputStreamFactoryClientPtr client,
+ const media::AudioParameters& audio_params,
+ uint32_t shared_memory_count,
+ bool disable_local_echo,
+ AudioStreamBroker::LoopbackSource* loopback_source);
+
+ void AssociateInputAndOutputForAecAfterCheckingAccess(
+ const base::UnguessableToken& input_stream_id,
+ const std::string& output_device_id,
+ MediaDeviceSaltAndOrigin salt_and_origin,
+ bool access_granted);
+
+ void AssociateTranslatedOutputDeviceForAec(
+ const base::UnguessableToken& input_stream_id,
+ const std::string& raw_output_device_id);
+
+ MediaStreamManager* const media_stream_manager_;
+ const int process_id_;
+ const int frame_id_;
+ const url::Origin origin_;
+
+ mojo::Binding<RendererAudioInputStreamFactory> binding_;
+ // Always null-check this weak pointer before dereferencing it.
+ base::WeakPtr<ForwardingAudioStreamFactory::Core> forwarding_factory_;
+
+ base::WeakPtrFactory<Core> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(Core);
+};
+
RenderFrameAudioInputStreamFactory::RenderFrameAudioInputStreamFactory(
mojom::RendererAudioInputStreamFactoryRequest request,
- scoped_refptr<AudioInputDeviceManager> audio_input_device_manager,
+ MediaStreamManager* media_stream_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) {
+ : core_(new Core(std::move(request),
+ media_stream_manager,
+ render_frame_host)) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
}
RenderFrameAudioInputStreamFactory::~RenderFrameAudioInputStreamFactory() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ // Ensure |core_| is deleted on the right thread. DeleteOnIOThread isn't used
+ // as it doesn't post in case it is already executed on the right thread. That
+ // causes issues in unit tests where the UI thread and the IO thread are the
+ // same.
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
+ base::BindOnce([](std::unique_ptr<Core>) {}, std::move(core_)));
}
-void RenderFrameAudioInputStreamFactory::CreateStream(
- mojom::RendererAudioInputStreamFactoryClientPtr client,
- int32_t session_id,
- const media::AudioParameters& audio_params,
- bool automatic_gain_control,
- uint32_t shared_memory_count,
- audio::mojom::AudioProcessingConfigPtr processing_config) {
+RenderFrameAudioInputStreamFactory::Core::Core(
+ mojom::RendererAudioInputStreamFactoryRequest request,
+ MediaStreamManager* media_stream_manager,
+ RenderFrameHost* render_frame_host)
+ : media_stream_manager_(media_stream_manager),
+ process_id_(render_frame_host->GetProcess()->GetID()),
+ frame_id_(render_frame_host->GetRoutingID()),
+ origin_(render_frame_host->GetLastCommittedOrigin()),
+ binding_(this),
+ weak_ptr_factory_(this) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- TRACE_EVENT_INSTANT1("audio",
- "RenderFrameAudioInputStreamFactory::CreateStream",
- TRACE_EVENT_SCOPE_THREAD, "session id", session_id);
- 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, std::move(processing_config))));
+ ForwardingAudioStreamFactory::Core* tmp_factory =
+ ForwardingAudioStreamFactory::CoreForFrame(render_frame_host);
+
+ if (!tmp_factory) {
+ // The only case when we not have a forwarding factory at this point is when
+ // the frame belongs to an interstitial. Interstitials don't need audio, so
+ // it's fine to drop the request.
+ return;
+ }
+
+ forwarding_factory_ = tmp_factory->AsWeakPtr();
+
+ // Unretained is safe since the destruction of |this| is posted to the IO
+ // thread.
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(&Core::Init, base::Unretained(this), std::move(request)));
+}
+
+RenderFrameAudioInputStreamFactory::Core::~Core() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
}
-void RenderFrameAudioInputStreamFactory::CreateStreamAfterLookingUpDevice(
+void RenderFrameAudioInputStreamFactory::Core::Init(
+ mojom::RendererAudioInputStreamFactoryRequest request) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ binding_.Bind(std::move(request));
+}
+
+void RenderFrameAudioInputStreamFactory::Core::CreateStream(
mojom::RendererAudioInputStreamFactoryClientPtr client,
+ int32_t session_id,
const media::AudioParameters& audio_params,
bool automatic_gain_control,
uint32_t shared_memory_count,
- audio::mojom::AudioProcessingConfigPtr processing_config,
- 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)
+ audio::mojom::AudioProcessingConfigPtr processing_config) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ TRACE_EVENT1("audio", "RenderFrameAudioInputStreamFactory::CreateStream",
+ "session id", session_id);
+
+ if (!forwarding_factory_)
return;
+ const MediaStreamDevice* device =
+ media_stream_manager_->audio_input_device_manager()->GetOpenedDeviceById(
+ session_id);
+
+ if (!device) {
+ TRACE_EVENT_INSTANT0("audio", "device not found", TRACE_EVENT_SCOPE_THREAD);
+ return;
+ }
+
WebContentsMediaCaptureId capture_id;
- if (WebContentsMediaCaptureId::Parse(device.id, &capture_id)) {
+ if (WebContentsMediaCaptureId::Parse(device->id, &capture_id)) {
// For MEDIA_GUM_DESKTOP_AUDIO_CAPTURE, the source is selected from
// picker window, we do not mute the source audio. For
// MEDIA_GUM_TAB_AUDIO_CAPTURE, the probable use case is Cast, we mute
@@ -135,84 +246,101 @@ void RenderFrameAudioInputStreamFactory::CreateStreamAfterLookingUpDevice(
// 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));
+ base::PostTaskWithTraitsAndReplyWithResult(
+ FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(&GetLoopbackSourceOnUIThread,
+ capture_id.render_process_id,
+ capture_id.main_render_frame_id),
+ base::BindOnce(
+ &RenderFrameAudioInputStreamFactory::Core::CreateLoopbackStream,
+ weak_ptr_factory_.GetWeakPtr(), std::move(client), audio_params,
+ shared_memory_count, capture_id.disable_local_echo));
- if (device.type == MEDIA_GUM_DESKTOP_AUDIO_CAPTURE)
+ if (device->type == MEDIA_GUM_DESKTOP_AUDIO_CAPTURE)
IncrementDesktopCaptureCounter(SYSTEM_LOOPBACK_AUDIO_CAPTURER_CREATED);
+ return;
} else {
- factory->CreateInputStream(render_frame_host_, device.id, audio_params,
- shared_memory_count, automatic_gain_control,
- std::move(processing_config), std::move(client));
+ forwarding_factory_->CreateInputStream(
+ process_id_, frame_id_, device->id, audio_params, shared_memory_count,
+ automatic_gain_control, std::move(processing_config),
+ std::move(client));
// Only count for captures from desktop media picker dialog and system loop
// back audio.
- if (device.type == MEDIA_GUM_DESKTOP_AUDIO_CAPTURE &&
- (media::AudioDeviceDescription::IsLoopbackDevice(device.id))) {
+ if (device->type == MEDIA_GUM_DESKTOP_AUDIO_CAPTURE &&
+ (media::AudioDeviceDescription::IsLoopbackDevice(device->id))) {
IncrementDesktopCaptureCounter(SYSTEM_LOOPBACK_AUDIO_CAPTURER_CREATED);
}
}
}
-void RenderFrameAudioInputStreamFactory::AssociateInputAndOutputForAec(
+void RenderFrameAudioInputStreamFactory::Core::CreateLoopbackStream(
+ mojom::RendererAudioInputStreamFactoryClientPtr client,
+ const media::AudioParameters& audio_params,
+ uint32_t shared_memory_count,
+ bool disable_local_echo,
+ AudioStreamBroker::LoopbackSource* loopback_source) {
+ if (!loopback_source || !forwarding_factory_)
+ return;
+
+ forwarding_factory_->CreateLoopbackStream(
+ process_id_, frame_id_, loopback_source, audio_params,
+ shared_memory_count, disable_local_echo, std::move(client));
+}
+
+void RenderFrameAudioInputStreamFactory::Core::AssociateInputAndOutputForAec(
const base::UnguessableToken& input_stream_id,
const std::string& output_device_id) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (!IsValidDeviceId(output_device_id))
return;
- ForwardingAudioStreamFactory* factory =
- ForwardingAudioStreamFactory::ForFrame(render_frame_host_);
- if (!factory)
- return;
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(
+ &GetSaltOriginAndPermissionsOnUIThread, process_id_, frame_id_,
+ base::BindOnce(
+ &Core::AssociateInputAndOutputForAecAfterCheckingAccess,
+ weak_ptr_factory_.GetWeakPtr(), input_stream_id,
+ output_device_id)));
+}
- 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);
+void RenderFrameAudioInputStreamFactory::Core::
+ AssociateInputAndOutputForAecAfterCheckingAccess(
+ const base::UnguessableToken& input_stream_id,
+ const std::string& output_device_id,
+ MediaDeviceSaltAndOrigin salt_and_origin,
+ bool access_granted) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
- // 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)) {
+ if (!forwarding_factory_ || !access_granted)
return;
- }
if (media::AudioDeviceDescription::IsDefaultDevice(output_device_id) ||
media::AudioDeviceDescription::IsCommunicationsDevice(output_device_id)) {
- factory->AssociateInputAndOutputForAec(input_stream_id, output_device_id);
+ forwarding_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))));
+ EnumerateOutputDevices(
+ media_stream_manager_,
+ base::BindRepeating(
+ &TranslateDeviceId, output_device_id, salt_and_origin,
+ base::BindRepeating(&RenderFrameAudioInputStreamFactory::Core::
+ AssociateTranslatedOutputDeviceForAec,
+ weak_ptr_factory_.GetWeakPtr(),
+ input_stream_id)));
}
}
-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);
+void RenderFrameAudioInputStreamFactory::Core::
+ AssociateTranslatedOutputDeviceForAec(
+ const base::UnguessableToken& input_stream_id,
+ const std::string& raw_output_device_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ if (!forwarding_factory_)
+ return;
+ forwarding_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 49ec1176c36..ceafa6ae239 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
@@ -5,72 +5,34 @@
#ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_RENDER_FRAME_AUDIO_INPUT_STREAM_FACTORY_H_
#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_RENDER_FRAME_AUDIO_INPUT_STREAM_FACTORY_H_
-#include <cstdint>
-#include <string>
+#include <memory>
#include "base/macros.h"
-#include "base/memory/scoped_refptr.h"
-#include "content/browser/renderer_host/media/audio_input_device_manager.h"
#include "content/common/content_export.h"
#include "content/common/media/renderer_audio_input_stream_factory.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 {
-class AudioParameters;
-} // namespace media
namespace content {
-class AudioInputDeviceManager;
+class MediaStreamManager;
class RenderFrameHost;
-// 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.
-class CONTENT_EXPORT RenderFrameAudioInputStreamFactory
- : public mojom::RendererAudioInputStreamFactory {
+// Handles a RendererAudioInputStreamFactory request for a render frame host.
+// Should be constructed and destructed on the UI thread, but will process mojo
+// messages on the IO thread. This class relates to ForwardingAudioStreamFactory
+// the same way as RenderFrameAudioOutputStreamFactory, and a class diagram can
+// be found in render_frame_audio_output_stream_factory.h
+class CONTENT_EXPORT RenderFrameAudioInputStreamFactory final {
public:
RenderFrameAudioInputStreamFactory(
mojom::RendererAudioInputStreamFactoryRequest request,
- scoped_refptr<AudioInputDeviceManager> audio_input_device_manager,
+ MediaStreamManager* media_stream_manager,
RenderFrameHost* render_frame_host);
- ~RenderFrameAudioInputStreamFactory() override;
+ ~RenderFrameAudioInputStreamFactory();
private:
- // 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,
- audio::mojom::AudioProcessingConfigPtr processing_config) override;
-
- void CreateStreamAfterLookingUpDevice(
- mojom::RendererAudioInputStreamFactoryClientPtr client,
- const media::AudioParameters& audio_params,
- bool automatic_gain_control,
- uint32_t shared_memory_count,
- audio::mojom::AudioProcessingConfigPtr processing_config,
- const MediaStreamDevice& device);
-
- void AssociateInputAndOutputForAec(
- const base::UnguessableToken& input_stream_id,
- const std::string& output_device_id) override;
-
- void AssociateTranslatedOutputDeviceForAec(
- const base::UnguessableToken& input_stream_id,
- const std::string& raw_output_device_id);
-
- const mojo::Binding<RendererAudioInputStreamFactory> binding_;
- const scoped_refptr<AudioInputDeviceManager> audio_input_device_manager_;
- RenderFrameHost* const render_frame_host_;
-
- base::WeakPtrFactory<RenderFrameAudioInputStreamFactory> weak_ptr_factory_;
+ class Core;
+ std::unique_ptr<Core> core_;
DISALLOW_COPY_AND_ASSIGN(RenderFrameAudioInputStreamFactory);
};
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 a5ae3806e45..f2cb24bbc4b 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
@@ -4,7 +4,6 @@
#include "content/browser/renderer_host/media/render_frame_audio_input_stream_factory.h"
-#include <memory>
#include <string>
#include <utility>
@@ -12,8 +11,11 @@
#include "base/bind_helpers.h"
#include "base/macros.h"
#include "base/run_loop.h"
+#include "base/task/post_task.h"
#include "content/browser/media/forwarding_audio_stream_factory.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_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
@@ -52,7 +54,8 @@ class RenderFrameAudioInputStreamFactoryTest
audio_system_(media::AudioSystemImpl::CreateInstance()),
media_stream_manager_(std::make_unique<MediaStreamManager>(
audio_system_.get(),
- BrowserThread::GetTaskRunnerForThread(BrowserThread::UI))) {}
+ base::CreateSingleThreadTaskRunnerWithTraits(
+ {BrowserThread::UI}))) {}
~RenderFrameAudioInputStreamFactoryTest() override {}
@@ -63,6 +66,7 @@ class RenderFrameAudioInputStreamFactoryTest
// Set up the ForwardingAudioStreamFactory.
service_manager::Connector::TestApi connector_test_api(
ForwardingAudioStreamFactory::ForFrame(main_rfh())
+ ->core()
->get_connector_for_testing());
connector_test_api.OverrideBinderForTesting(
service_manager::Identity(audio::mojom::kServiceName),
@@ -180,17 +184,15 @@ class RenderFrameAudioInputStreamFactoryTest
TEST_F(RenderFrameAudioInputStreamFactoryTest, ConstructDestruct) {
mojom::RendererAudioInputStreamFactoryPtr factory_ptr;
- RenderFrameAudioInputStreamFactory factory(mojo::MakeRequest(&factory_ptr),
- audio_input_device_manager(),
- main_rfh());
+ RenderFrameAudioInputStreamFactory factory(
+ mojo::MakeRequest(&factory_ptr), media_stream_manager_.get(), main_rfh());
}
TEST_F(RenderFrameAudioInputStreamFactoryTest,
CreateOpenedStream_ForwardsCall) {
mojom::RendererAudioInputStreamFactoryPtr factory_ptr;
- RenderFrameAudioInputStreamFactory factory(mojo::MakeRequest(&factory_ptr),
- audio_input_device_manager(),
- main_rfh());
+ RenderFrameAudioInputStreamFactory factory(
+ mojo::MakeRequest(&factory_ptr), media_stream_manager_.get(), main_rfh());
int session_id = audio_input_device_manager()->Open(
MediaStreamDevice(MEDIA_DEVICE_AUDIO_CAPTURE, kDeviceId, kDeviceName));
@@ -210,9 +212,8 @@ 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());
+ RenderFrameAudioInputStreamFactory factory(
+ mojo::MakeRequest(&factory_ptr), media_stream_manager_.get(), main_rfh());
RenderFrameHost* main_frame = source_contents->GetMainFrame();
WebContentsMediaCaptureId capture_id(main_frame->GetProcess()->GetID(),
@@ -235,9 +236,8 @@ 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());
+ RenderFrameAudioInputStreamFactory factory(
+ mojo::MakeRequest(&factory_ptr), media_stream_manager_.get(), main_rfh());
RenderFrameHost* main_frame = source_contents->GetMainFrame();
WebContentsMediaCaptureId capture_id(main_frame->GetProcess()->GetID(),
@@ -260,9 +260,8 @@ TEST_F(RenderFrameAudioInputStreamFactoryTest,
TEST_F(RenderFrameAudioInputStreamFactoryTest,
CreateStreamWithoutValidSessionId_Fails) {
mojom::RendererAudioInputStreamFactoryPtr factory_ptr;
- RenderFrameAudioInputStreamFactory factory(mojo::MakeRequest(&factory_ptr),
- audio_input_device_manager(),
- main_rfh());
+ RenderFrameAudioInputStreamFactory factory(
+ mojo::MakeRequest(&factory_ptr), media_stream_manager_.get(), main_rfh());
int session_id = 123;
mojom::RendererAudioInputStreamFactoryClientPtr client;
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 dadd1cdd502..a1c650a3a30 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
@@ -4,71 +4,146 @@
#include "content/browser/renderer_host/media/render_frame_audio_output_stream_factory.h"
+#include <cstdint>
+#include <string>
#include <utility>
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/containers/flat_set.h"
+#include "base/containers/unique_ptr_adapters.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/memory/weak_ptr.h"
+#include "base/optional.h"
+#include "base/task/post_task.h"
+#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
+#include "base/unguessable_token.h"
#include "content/browser/media/forwarding_audio_stream_factory.h"
#include "content/browser/renderer_host/media/audio_output_authorization_handler.h"
+#include "content/public/browser/browser_task_traits.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 "media/base/bind_to_current_loop.h"
+#include "media/base/output_device_info.h"
+#include "media/mojo/interfaces/audio_output_stream.mojom.h"
+#include "mojo/public/cpp/bindings/binding.h"
namespace content {
-// 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 {
+class RenderFrameAudioOutputStreamFactory::Core final
+ : public mojom::RendererAudioOutputStreamFactory {
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)));
+ Core(RenderFrameHost* frame,
+ media::AudioSystem* audio_system,
+ MediaStreamManager* media_stream_manager,
+ mojom::RendererAudioOutputStreamFactoryRequest request);
+
+ ~Core() final = default;
+
+ void Init(mojom::RendererAudioOutputStreamFactoryRequest request);
+
+ size_t current_number_of_providers_for_testing() {
+ return stream_providers_.size();
}
- ~ProviderImpl() final { DCHECK_CURRENTLY_ON(BrowserThread::UI); }
+ private:
+ // This class implements media::mojom::AudioOutputStreamProvider for a single
+ // streams and cleans itself up (using the |owner| pointer) when done.
+ class ProviderImpl final : public media::mojom::AudioOutputStreamProvider {
+ public:
+ ProviderImpl(media::mojom::AudioOutputStreamProviderRequest request,
+ RenderFrameAudioOutputStreamFactory::Core* owner,
+ const std::string& device_id)
+ : owner_(owner),
+ device_id_(device_id),
+ binding_(this, std::move(request)) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ // Unretained is safe since |this| owns |binding_|.
+ binding_.set_connection_error_handler(
+ base::BindOnce(&ProviderImpl::Done, base::Unretained(this)));
+ }
- void Acquire(
- const media::AudioParameters& params,
- media::mojom::AudioOutputStreamProviderClientPtr provider_client,
- const base::Optional<base::UnguessableToken>& processing_id) 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, processing_id,
- std::move(provider_client));
+ ~ProviderImpl() final { DCHECK_CURRENTLY_ON(BrowserThread::IO); }
+
+ void Acquire(
+ const media::AudioParameters& params,
+ media::mojom::AudioOutputStreamProviderClientPtr provider_client,
+ const base::Optional<base::UnguessableToken>& processing_id) final {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ TRACE_EVENT1("audio",
+ "RenderFrameAudioOutputStreamFactory::ProviderImpl::Acquire",
+ "raw device id", device_id_);
+
+ base::WeakPtr<ForwardingAudioStreamFactory::Core> factory =
+ owner_->forwarding_factory_;
+ if (factory) {
+ factory->CreateOutputStream(owner_->process_id_, owner_->frame_id_,
+ device_id_, params, processing_id,
+ std::move(provider_client));
+ }
+
+ // Since the stream creation has been propagated, |this| is no longer
+ // needed.
+ Done();
}
- // Since the stream creation has been propagated, |this| is no longer
- // needed.
- Done();
- }
+ void Done() { owner_->DeleteProvider(this); }
- void Done() { owner_->DeleteProvider(this); }
+ private:
+ RenderFrameAudioOutputStreamFactory::Core* const owner_;
+ const std::string device_id_;
- private:
- RenderFrameAudioOutputStreamFactory* const owner_;
- const std::string device_id_;
+ mojo::Binding<media::mojom::AudioOutputStreamProvider> binding_;
+
+ DISALLOW_COPY_AND_ASSIGN(ProviderImpl);
+ };
- mojo::Binding<media::mojom::AudioOutputStreamProvider> binding_;
+ using OutputStreamProviderSet =
+ base::flat_set<std::unique_ptr<media::mojom::AudioOutputStreamProvider>,
+ base::UniquePtrComparator>;
- DISALLOW_COPY_AND_ASSIGN(ProviderImpl);
+ // mojom::RendererAudioOutputStreamFactory implementation.
+ void RequestDeviceAuthorization(
+ media::mojom::AudioOutputStreamProviderRequest provider_request,
+ int32_t session_id,
+ const std::string& device_id,
+ RequestDeviceAuthorizationCallback callback) final;
+
+ // 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 DeleteProvider(media::mojom::AudioOutputStreamProvider* stream_provider);
+
+ const int process_id_;
+ const int frame_id_;
+ AudioOutputAuthorizationHandler authorization_handler_;
+
+ mojo::Binding<mojom::RendererAudioOutputStreamFactory> binding_;
+ // Always null-check this weak pointer before dereferencing it.
+ base::WeakPtr<ForwardingAudioStreamFactory::Core> forwarding_factory_;
+
+ // The OutputStreamProviders for authorized streams are kept here while
+ // waiting for the renderer to finish creating the stream, and destructed
+ // afterwards.
+ OutputStreamProviderSet stream_providers_;
+
+ // Weak pointers are used to cancel device authorizations that are in flight
+ // while |this| is destructed.
+ base::WeakPtrFactory<Core> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(Core);
};
RenderFrameAudioOutputStreamFactory::RenderFrameAudioOutputStreamFactory(
@@ -76,53 +151,92 @@ RenderFrameAudioOutputStreamFactory::RenderFrameAudioOutputStreamFactory(
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) {
+ : core_(new Core(frame,
+ audio_system,
+ media_stream_manager,
+ std::move(request))) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
}
RenderFrameAudioOutputStreamFactory::~RenderFrameAudioOutputStreamFactory() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ // Ensure |core_| is deleted on the right thread. DeleteOnIOThread isn't used
+ // as it doesn't post in case it is already executed on the right thread. That
+ // causes issues in unit tests where the UI thread and the IO thread are the
+ // same.
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
+ base::BindOnce([](std::unique_ptr<Core>) {}, std::move(core_)));
+}
+
+size_t
+RenderFrameAudioOutputStreamFactory::CurrentNumberOfProvidersForTesting() {
+ return core_->current_number_of_providers_for_testing();
+}
+
+RenderFrameAudioOutputStreamFactory::Core::Core(
+ RenderFrameHost* frame,
+ media::AudioSystem* audio_system,
+ MediaStreamManager* media_stream_manager,
+ mojom::RendererAudioOutputStreamFactoryRequest request)
+ : process_id_(frame->GetProcess()->GetID()),
+ frame_id_(frame->GetRoutingID()),
+ authorization_handler_(audio_system, media_stream_manager, process_id_),
+ binding_(this),
+ weak_ptr_factory_(this) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ ForwardingAudioStreamFactory::Core* tmp_factory =
+ ForwardingAudioStreamFactory::CoreForFrame(frame);
+
+ if (!tmp_factory) {
+ // The only case when we not have a forwarding factory at this point is when
+ // the frame belongs to an interstitial. Interstitials don't need audio, so
+ // it's fine to drop the request.
+ return;
+ }
+
+ forwarding_factory_ = tmp_factory->AsWeakPtr();
+
+ // Unretained is safe since the destruction of |this| is posted to the IO
+ // thread.
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(&Core::Init, base::Unretained(this), std::move(request)));
+}
+
+void RenderFrameAudioOutputStreamFactory::Core::Init(
+ mojom::RendererAudioOutputStreamFactoryRequest request) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ binding_.Bind(std::move(request));
}
-void RenderFrameAudioOutputStreamFactory::RequestDeviceAuthorization(
+void RenderFrameAudioOutputStreamFactory::Core::RequestDeviceAuthorization(
media::mojom::AudioOutputStreamProviderRequest provider_request,
int32_t session_id,
const std::string& device_id,
RequestDeviceAuthorizationCallback callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
TRACE_EVENT2(
"audio",
"RenderFrameAudioOutputStreamFactory::RequestDeviceAuthorization",
"device id", device_id, "session_id", session_id);
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,
+ completed_callback = base::BindOnce(
+ &RenderFrameAudioOutputStreamFactory::Core::AuthorizationCompleted,
weak_ptr_factory_.GetWeakPtr(), auth_start_time,
- std::move(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)));
+ authorization_handler_.RequestDeviceAuthorization(
+ frame_id_, session_id, device_id, std::move(completed_callback));
}
-void RenderFrameAudioOutputStreamFactory::AuthorizationCompleted(
+void RenderFrameAudioOutputStreamFactory::Core::AuthorizationCompleted(
base::TimeTicks auth_start_time,
media::mojom::AudioOutputStreamProviderRequest request,
RequestDeviceAuthorizationCallback callback,
@@ -130,7 +244,7 @@ void RenderFrameAudioOutputStreamFactory::AuthorizationCompleted(
const media::AudioParameters& params,
const std::string& raw_device_id,
const std::string& device_id_for_renderer) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
TRACE_EVENT2("audio",
"RenderFrameAudioOutputStreamFactory::AuthorizationCompleted",
"raw device id", raw_device_id, "status", status);
@@ -148,9 +262,9 @@ void RenderFrameAudioOutputStreamFactory::AuthorizationCompleted(
}
}
-void RenderFrameAudioOutputStreamFactory::DeleteProvider(
+void RenderFrameAudioOutputStreamFactory::Core::DeleteProvider(
media::mojom::AudioOutputStreamProvider* stream_provider) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
size_t deleted = stream_providers_.erase(stream_provider);
DCHECK_EQ(1u, deleted);
}
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 fbc229bdd8b..50362670e66 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
@@ -5,36 +5,41 @@
#ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_RENDER_FRAME_AUDIO_OUTPUT_STREAM_FACTORY_H_
#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_RENDER_FRAME_AUDIO_OUTPUT_STREAM_FACTORY_H_
+#include <cstddef>
#include <memory>
-#include <string>
-#include "base/containers/flat_set.h"
-#include "base/containers/unique_ptr_adapters.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 AudioOutputAuthorizationHandler;
class MediaStreamManager;
class RenderFrameHost;
-// 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 {
+// This class is related to ForwardingAudioStreamFactory as follows:
+//
+// WebContentsImpl <-- RenderFrameHostImpl
+// ^ ^
+// | |
+// ForwardingAudioStreamFactory RenderFrameAudioOutputStreamFactory
+// ^ ^
+// | |
+// FASF::Core <-- RFAOSF::Core
+//
+// Both FASF::Core and RFAOSF::Core live on (and are destructed on) the IO
+// thread. A weak pointer to ForwardingAudioStreamFactory is used since
+// WebContentsImpl is sometimes destructed shortly before RenderFrameHostImpl.
+
+// This class 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. It should be constructed and
+// destructed on the UI thread, but will process mojo messages on the IO thread.
+class CONTENT_EXPORT RenderFrameAudioOutputStreamFactory final {
public:
RenderFrameAudioOutputStreamFactory(
RenderFrameHost* frame,
@@ -42,56 +47,13 @@ class CONTENT_EXPORT RenderFrameAudioOutputStreamFactory
MediaStreamManager* media_stream_manager,
mojom::RendererAudioOutputStreamFactoryRequest request);
- ~RenderFrameAudioOutputStreamFactory() override;
+ ~RenderFrameAudioOutputStreamFactory();
- size_t current_number_of_providers_for_testing() {
- return stream_providers_.size();
- }
+ size_t CurrentNumberOfProvidersForTesting();
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 provider_request,
- 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 DeleteProvider(media::mojom::AudioOutputStreamProvider* stream_provider);
-
- const mojo::Binding<mojom::RendererAudioOutputStreamFactory> binding_;
- RenderFrameHost* const frame_;
- const std::unique_ptr<AudioOutputAuthorizationHandler,
- BrowserThread::DeleteOnIOThread>
- authorization_handler_;
-
- // The OutputStreamProviders for authorized streams are kept here while
- // waiting for the renderer to finish creating the stream, and destructed
- // afterwards.
- OutputStreamProviderSet stream_providers_;
-
- // Weak pointers are used to cancel device authorizations that are in flight
- // while |this| is destructed.
- base::WeakPtrFactory<RenderFrameAudioOutputStreamFactory> weak_ptr_factory_;
+ class Core;
+ std::unique_ptr<Core> core_;
DISALLOW_COPY_AND_ASSIGN(RenderFrameAudioOutputStreamFactory);
};
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 ed17a87080b..f7f4fc6015a 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
@@ -5,17 +5,20 @@
#include "content/browser/renderer_host/media/render_frame_audio_output_stream_factory.h"
#include <memory>
+#include <string>
#include <utility>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/macros.h"
#include "base/run_loop.h"
+#include "base/task/post_task.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/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/test/mock_render_process_host.h"
@@ -55,7 +58,8 @@ class RenderFrameAudioOutputStreamFactoryTest
audio_system_(media::AudioSystemImpl::CreateInstance()),
media_stream_manager_(std::make_unique<MediaStreamManager>(
audio_system_.get(),
- BrowserThread::GetTaskRunnerForThread(BrowserThread::UI))) {}
+ base::CreateSingleThreadTaskRunnerWithTraits(
+ {BrowserThread::UI}))) {}
~RenderFrameAudioOutputStreamFactoryTest() override {}
@@ -66,6 +70,7 @@ class RenderFrameAudioOutputStreamFactoryTest
// Set up the ForwardingAudioStreamFactory.
service_manager::Connector::TestApi connector_test_api(
ForwardingAudioStreamFactory::ForFrame(main_rfh())
+ ->core()
->get_connector_for_testing());
connector_test_api.OverrideBinderForTesting(
service_manager::Identity(audio::mojom::kServiceName),
@@ -152,7 +157,7 @@ TEST_F(RenderFrameAudioOutputStreamFactoryTest,
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(1u, factory.current_number_of_providers_for_testing());
+ EXPECT_EQ(1u, factory.CurrentNumberOfProvidersForTesting());
}
TEST_F(
@@ -175,7 +180,7 @@ TEST_F(
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(0u, factory.current_number_of_providers_for_testing());
+ EXPECT_EQ(0u, factory.CurrentNumberOfProvidersForTesting());
}
TEST_F(
@@ -197,7 +202,7 @@ TEST_F(
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(0u, factory.current_number_of_providers_for_testing());
+ EXPECT_EQ(0u, factory.CurrentNumberOfProvidersForTesting());
}
TEST_F(RenderFrameAudioOutputStreamFactoryTest,
@@ -225,7 +230,7 @@ TEST_F(RenderFrameAudioOutputStreamFactoryTest,
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(!!audio_service_stream_factory_.last_created_callback);
- EXPECT_EQ(0u, factory.current_number_of_providers_for_testing());
+ EXPECT_EQ(0u, factory.CurrentNumberOfProvidersForTesting());
}
TEST_F(RenderFrameAudioOutputStreamFactoryTest,
diff --git a/chromium/content/browser/renderer_host/media/service_video_capture_device_launcher.cc b/chromium/content/browser/renderer_host/media/service_video_capture_device_launcher.cc
index 07e01aaabe7..fbba2356d02 100644
--- a/chromium/content/browser/renderer_host/media/service_video_capture_device_launcher.cc
+++ b/chromium/content/browser/renderer_host/media/service_video_capture_device_launcher.cc
@@ -4,7 +4,9 @@
#include "content/browser/renderer_host/media/service_video_capture_device_launcher.h"
+#include "base/task/post_task.h"
#include "content/browser/renderer_host/media/service_launched_video_capture_device.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "media/capture/video/video_frame_receiver_on_task_runner.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
@@ -24,8 +26,8 @@ void ConcludeLaunchDeviceWithSuccess(
auto receiver_adapter =
std::make_unique<video_capture::ReceiverMediaToMojoAdapter>(
std::make_unique<media::VideoFrameReceiverOnTaskRunner>(
- std::move(receiver),
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)));
+ std::move(receiver), base::CreateSingleThreadTaskRunnerWithTraits(
+ {BrowserThread::IO})));
video_capture::mojom::ReceiverPtr receiver_proxy;
mojo::MakeStrongBinding<video_capture::mojom::Receiver>(
std::move(receiver_adapter), mojo::MakeRequest(&receiver_proxy));
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 37c732611ce..74859ea5f35 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
@@ -6,12 +6,12 @@
#include "base/run_loop.h"
#include "base/test/mock_callback.h"
-#include "base/test/scoped_task_environment.h"
#include "base/threading/thread.h"
#include "content/browser/renderer_host/media/service_launched_video_capture_device.h"
#include "content/browser/renderer_host/media/video_capture_factory_delegate.h"
+#include "content/public/test/test_browser_thread_bundle.h"
#include "mojo/public/cpp/bindings/binding.h"
-#include "services/video_capture/public/mojom/device_factory.mojom.h"
+#include "services/video_capture/public/cpp/mock_device_factory.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -25,45 +25,6 @@ static const std::string kStubDeviceId = "StubDevice";
static const media::VideoCaptureParams kArbitraryParams;
static const base::WeakPtr<media::VideoFrameReceiver> kNullReceiver;
-class MockDeviceFactory : public video_capture::mojom::DeviceFactory {
- public:
- void CreateDevice(const std::string& device_id,
- video_capture::mojom::DeviceRequest device_request,
- CreateDeviceCallback callback) override {
- DoCreateDevice(device_id, &device_request, callback);
- }
-
- void GetDeviceInfos(GetDeviceInfosCallback callback) override {
- DoGetDeviceInfos(callback);
- }
-
- void AddSharedMemoryVirtualDevice(
- const media::VideoCaptureDeviceInfo& device_info,
- video_capture::mojom::ProducerPtr producer,
- bool send_buffer_handles_to_producer_as_raw_file_descriptors,
- 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));
- MOCK_METHOD3(DoCreateDevice,
- 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::SharedMemoryVirtualDeviceRequest*
- virtual_device_request));
-};
-
class MockVideoCaptureDeviceLauncherCallbacks
: public VideoCaptureDeviceLauncher::Callbacks {
public:
@@ -113,8 +74,8 @@ class ServiceVideoCaptureDeviceLauncherTest : public testing::Test {
void RunLaunchingDeviceIsAbortedTest(
video_capture::mojom::DeviceAccessResultCode service_result_code);
- base::test::ScopedTaskEnvironment scoped_task_environment_;
- MockDeviceFactory mock_device_factory_;
+ TestBrowserThreadBundle thread_bundle_;
+ video_capture::MockDeviceFactory mock_device_factory_;
MockVideoCaptureDeviceLauncherCallbacks mock_callbacks_;
video_capture::mojom::DeviceFactoryPtr device_factory_;
std::unique_ptr<mojo::Binding<video_capture::mojom::DeviceFactory>>
diff --git a/chromium/content/browser/renderer_host/media/service_video_capture_provider.cc b/chromium/content/browser/renderer_host/media/service_video_capture_provider.cc
index 34445f23d22..f3cf7f94cd3 100644
--- a/chromium/content/browser/renderer_host/media/service_video_capture_provider.cc
+++ b/chromium/content/browser/renderer_host/media/service_video_capture_provider.cc
@@ -5,10 +5,10 @@
#include "content/browser/renderer_host/media/service_video_capture_provider.h"
#include "content/browser/renderer_host/media/service_video_capture_device_launcher.h"
-#include "content/browser/renderer_host/media/video_capture_dependencies.h"
#include "content/browser/renderer_host/media/video_capture_factory_delegate.h"
#include "content/common/child_process_host_impl.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/delegate_to_browser_gpu_service_accelerator_factory.h"
#include "content/public/common/service_manager_connection.h"
#include "mojo/public/cpp/bindings/callback_helpers.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
@@ -47,19 +47,10 @@ class ServiceConnectorImpl
std::unique_ptr<service_manager::Connector> connector_;
};
-class DelegateToBrowserGpuServiceAcceleratorFactory
- : public video_capture::mojom::AcceleratorFactory {
- public:
- void CreateJpegDecodeAccelerator(
- media::mojom::JpegDecodeAcceleratorRequest jda_request) override {
- content::VideoCaptureDependencies::CreateJpegDecodeAccelerator(
- std::move(jda_request));
- }
-};
-
std::unique_ptr<video_capture::mojom::AcceleratorFactory>
CreateAcceleratorFactory() {
- return std::make_unique<DelegateToBrowserGpuServiceAcceleratorFactory>();
+ return std::make_unique<
+ content::DelegateToBrowserGpuServiceAcceleratorFactory>();
}
} // anonymous namespace
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 0b5aecf53b7..966647be2ab 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
@@ -10,8 +10,8 @@
#include "content/public/browser/video_capture_device_launcher.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "mojo/public/cpp/bindings/binding.h"
-#include "services/video_capture/public/mojom/device_factory.mojom.h"
-#include "services/video_capture/public/mojom/device_factory_provider.mojom.h"
+#include "services/video_capture/public/cpp/mock_device_factory.h"
+#include "services/video_capture/public/cpp/mock_device_factory_provider.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -36,63 +36,6 @@ class MockServiceConnector
void(video_capture::mojom::DeviceFactoryProviderPtr* provider));
};
-class MockDeviceFactoryProvider
- : public video_capture::mojom::DeviceFactoryProvider {
- public:
- void ConnectToDeviceFactory(
- video_capture::mojom::DeviceFactoryRequest request) override {
- DoConnectToDeviceFactory(request);
- }
-
- void InjectGpuDependencies(video_capture::mojom::AcceleratorFactoryPtr
- accelerator_factory) override {
- DoInjectGpuDependencies(accelerator_factory);
- }
-
- MOCK_METHOD1(
- DoInjectGpuDependencies,
- void(video_capture::mojom::AcceleratorFactoryPtr& accelerator_factory));
- MOCK_METHOD1(SetShutdownDelayInSeconds, void(float seconds));
- MOCK_METHOD1(DoConnectToDeviceFactory,
- void(video_capture::mojom::DeviceFactoryRequest& request));
-};
-
-class MockDeviceFactory : public video_capture::mojom::DeviceFactory {
- public:
- void GetDeviceInfos(GetDeviceInfosCallback callback) override {
- DoGetDeviceInfos(callback);
- }
- void CreateDevice(const std::string& device_id,
- video_capture::mojom::DeviceRequest device_request,
- CreateDeviceCallback callback) override {
- DoCreateDevice(device_id, &device_request, callback);
- }
- void AddSharedMemoryVirtualDevice(
- const media::VideoCaptureDeviceInfo& device_info,
- video_capture::mojom::ProducerPtr producer,
- bool send_buffer_handles_to_producer_as_raw_file_descriptors,
- 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));
- MOCK_METHOD3(DoCreateDevice,
- 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::SharedMemoryVirtualDeviceRequest*
- virtual_device_request));
-};
-
class MockVideoCaptureDeviceLauncherCallbacks
: public VideoCaptureDeviceLauncher::Callbacks {
public:
@@ -147,10 +90,10 @@ class ServiceVideoCaptureProviderTest : public testing::Test {
content::TestBrowserThreadBundle test_browser_thread_bundle_;
MockServiceConnector* mock_service_connector_;
- MockDeviceFactoryProvider mock_device_factory_provider_;
+ video_capture::MockDeviceFactoryProvider mock_device_factory_provider_;
mojo::Binding<video_capture::mojom::DeviceFactoryProvider>
factory_provider_binding_;
- MockDeviceFactory mock_device_factory_;
+ video_capture::MockDeviceFactory mock_device_factory_;
mojo::Binding<video_capture::mojom::DeviceFactory> device_factory_binding_;
std::unique_ptr<ServiceVideoCaptureProvider> provider_;
base::MockCallback<VideoCaptureProvider::GetDeviceInfosCallback> results_cb_;
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 7306b1ee393..86421309571 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_browsertest.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_browsertest.cc
@@ -4,12 +4,14 @@
#include "base/command_line.h"
#include "base/run_loop.h"
+#include "base/task/post_task.h"
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "content/browser/browser_main_loop.h"
#include "content/browser/renderer_host/media/media_stream_manager.h"
#include "content/browser/renderer_host/media/video_capture_controller.h"
#include "content/browser/renderer_host/media/video_capture_manager.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
@@ -35,10 +37,9 @@ static const float kFrameRateToRequest = 15.0f;
class MockVideoCaptureControllerEventHandler
: public VideoCaptureControllerEventHandler {
public:
- MOCK_METHOD4(DoOnNewBuffer,
+ MOCK_METHOD3(DoOnNewBuffer,
void(VideoCaptureControllerID id,
media::mojom::VideoBufferHandlePtr* buffer_handle,
- int length,
int buffer_id));
MOCK_METHOD2(OnBufferDestroyed,
void(VideoCaptureControllerID, int buffer_id));
@@ -55,9 +56,8 @@ class MockVideoCaptureControllerEventHandler
void OnNewBuffer(VideoCaptureControllerID id,
media::mojom::VideoBufferHandlePtr buffer_handle,
- int length,
int buffer_id) override {
- DoOnNewBuffer(id, &buffer_handle, length, buffer_id);
+ DoOnNewBuffer(id, &buffer_handle, buffer_id);
}
};
@@ -243,8 +243,8 @@ IN_PROC_BROWSER_TEST_P(VideoCaptureBrowserTest, StartAndImmediatelyStop) {
base::Bind(&VideoCaptureBrowserTest::TearDownCaptureDeviceOnIOThread,
base::Unretained(this),
std::move(quit_run_loop_on_current_thread_cb), true);
- BrowserThread::PostTask(
- content::BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {content::BrowserThread::IO},
base::BindOnce(
&VideoCaptureBrowserTest::SetUpAndStartCaptureDeviceOnIOThread,
base::Unretained(this), std::move(after_start_continuation)));
@@ -305,7 +305,7 @@ IN_PROC_BROWSER_TEST_P(VideoCaptureBrowserTest,
must_wait_for_gpu_decode_to_start = false;
}));
}
- EXPECT_CALL(mock_controller_event_handler_, DoOnNewBuffer(_, _, _, _))
+ EXPECT_CALL(mock_controller_event_handler_, DoOnNewBuffer(_, _, _))
.Times(AtLeast(1));
EXPECT_CALL(mock_controller_event_handler_, OnBufferReady(_, _, _))
.WillRepeatedly(Invoke(
@@ -330,8 +330,8 @@ IN_PROC_BROWSER_TEST_P(VideoCaptureBrowserTest,
}));
base::Closure do_nothing;
- BrowserThread::PostTask(
- content::BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {content::BrowserThread::IO},
base::BindOnce(
&VideoCaptureBrowserTest::SetUpAndStartCaptureDeviceOnIOThread,
base::Unretained(this), std::move(do_nothing)));
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 773dbcc181a..80175b1c299 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
@@ -17,7 +17,7 @@
#include "base/bind.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop.h"
+#include "base/test/scoped_task_environment.h"
#include "build/build_config.h"
#include "content/browser/renderer_host/media/video_capture_controller.h"
#include "media/base/video_frame.h"
@@ -77,11 +77,14 @@ class VideoCaptureBufferPoolTest
DVLOG(1) << media::VideoPixelFormatToString(pixel_format) << " "
<< dimensions.ToString();
const int arbitrary_frame_feedback_id = 0;
- const int buffer_id = pool_->ReserveForProducer(dimensions, pixel_format,
- arbitrary_frame_feedback_id,
- &buffer_id_to_drop);
- if (buffer_id == media::VideoCaptureBufferPool::kInvalidId)
+ int buffer_id = media::VideoCaptureBufferPool::kInvalidId;
+ const auto reserve_result = pool_->ReserveForProducer(
+ dimensions, pixel_format, nullptr, arbitrary_frame_feedback_id,
+ &buffer_id, &buffer_id_to_drop);
+ if (reserve_result !=
+ media::VideoCaptureDevice::Client::ReserveResult::kSucceeded) {
return std::unique_ptr<Buffer>();
+ }
EXPECT_EQ(expected_dropped_id_, buffer_id_to_drop);
std::unique_ptr<media::VideoCaptureBufferHandle> buffer_handle =
@@ -90,18 +93,7 @@ class VideoCaptureBufferPoolTest
new Buffer(pool_, std::move(buffer_handle), buffer_id));
}
- std::unique_ptr<Buffer> ResurrectLastBuffer(
- const gfx::Size& dimensions,
- 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(
- pool_, pool_->GetHandleForInProcessAccess(buffer_id), buffer_id));
- }
-
- base::MessageLoop loop_;
+ base::test::ScopedTaskEnvironment task_environment_;
int expected_dropped_id_;
scoped_refptr<media::VideoCaptureBufferPool> pool_;
@@ -273,125 +265,6 @@ TEST_P(VideoCaptureBufferPoolTest, BufferPool) {
buffer4.reset();
}
-// Tests that a previously-released buffer can be immediately resurrected under
-// normal conditions.
-TEST_P(VideoCaptureBufferPoolTest, ResurrectsLastBuffer) {
- ExpectDroppedId(media::VideoCaptureBufferPool::kInvalidId);
-
- // At the start, there should be nothing to resurrect.
- std::unique_ptr<Buffer> resurrected =
- ResurrectLastBuffer(gfx::Size(10, 10), GetParam());
- ASSERT_EQ(nullptr, resurrected.get());
-
- // Reserve a 10x10 buffer and fill it with 0xab values.
- std::unique_ptr<Buffer> original =
- ReserveBuffer(gfx::Size(10, 10), GetParam());
- ASSERT_NE(nullptr, original.get());
- const size_t original_mapped_size = original->mapped_size();
- memset(original->data(), 0xab, original_mapped_size);
-
- // Try to resurrect a buffer BEFORE releasing |original|. This should fail.
- resurrected = ResurrectLastBuffer(gfx::Size(10, 10), GetParam());
- ASSERT_EQ(nullptr, resurrected.get());
-
- // Release |original| and then try to resurrect it. Confirm the content of
- // the resurrected buffer is a fill of 0xab values.
- original.reset();
- resurrected = ResurrectLastBuffer(gfx::Size(10, 10), GetParam());
- ASSERT_NE(nullptr, resurrected.get());
- ASSERT_EQ(original_mapped_size, resurrected->mapped_size());
- uint8_t* resurrected_memory = reinterpret_cast<uint8_t*>(resurrected->data());
- for (size_t i = 0; i < original_mapped_size; ++i)
- EXPECT_EQ(0xab, resurrected_memory[i]) << "Mismatch at byte offset: " << i;
-
- // Now, fill the resurrected buffer with 0xbc values and release it.
- memset(resurrected_memory, 0xbc, original_mapped_size);
- resurrected.reset();
-
- // Finally, resurrect the buffer again, and confirm it contains a fill of 0xbc
- // values.
- resurrected = ResurrectLastBuffer(gfx::Size(10, 10), GetParam());
- ASSERT_NE(nullptr, resurrected.get());
- ASSERT_EQ(original_mapped_size, resurrected->mapped_size());
- resurrected_memory = reinterpret_cast<uint8_t*>(resurrected->data());
- for (size_t i = 0; i < original_mapped_size; ++i)
- EXPECT_EQ(0xbc, resurrected_memory[i]) << "Mismatch at byte offset: " << i;
-}
-
-// Tests that a buffer cannot be resurrected if its properties do not match.
-TEST_P(VideoCaptureBufferPoolTest, DoesNotResurrectIfPropertiesNotMatched) {
- ExpectDroppedId(media::VideoCaptureBufferPool::kInvalidId);
-
- // Reserve a 10x10 buffer, fill it with 0xcd values, and release it.
- std::unique_ptr<Buffer> original =
- ReserveBuffer(gfx::Size(10, 10), GetParam());
- ASSERT_NE(nullptr, original.get());
- const size_t original_mapped_size = original->mapped_size();
- memset(original->data(), 0xcd, original_mapped_size);
- original.reset();
-
- // Expect that the buffer cannot be resurrected if the dimensions do not
- // match.
- std::unique_ptr<Buffer> resurrected =
- ResurrectLastBuffer(gfx::Size(8, 8), GetParam());
- ASSERT_EQ(nullptr, resurrected.get());
-
- // Expect that the buffer cannot be resurrected if the pixel format does not
- // match.
- 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.
- resurrected = ResurrectLastBuffer(gfx::Size(10, 10), GetParam());
- ASSERT_NE(nullptr, resurrected.get());
- ASSERT_EQ(original_mapped_size, resurrected->mapped_size());
- uint8_t* resurrected_memory = reinterpret_cast<uint8_t*>(resurrected->data());
- for (size_t i = 0; i < original_mapped_size; ++i)
- EXPECT_EQ(0xcd, resurrected_memory[i]) << "Mismatch at byte offset: " << i;
-}
-
-// Tests that the buffers are managed by the pool such that the last-released
-// buffer is kept around as long as possible (for successful resurrection).
-TEST_P(VideoCaptureBufferPoolTest, AvoidsClobberingForResurrectingLastBuffer) {
- ExpectDroppedId(media::VideoCaptureBufferPool::kInvalidId);
-
- // Reserve a 10x10 buffer, fill it with 0xde values, and release it.
- std::unique_ptr<Buffer> original =
- ReserveBuffer(gfx::Size(10, 10), GetParam());
- ASSERT_NE(nullptr, original.get());
- const size_t original_mapped_size = original->mapped_size();
- memset(original->data(), 0xde, original_mapped_size);
- original.reset();
-
- // Reserve all but one of the pool's buffers.
- std::vector<std::unique_ptr<Buffer>> held_buffers;
- for (int i = 0; i < kTestBufferPoolSize - 1; ++i) {
- held_buffers.push_back(ReserveBuffer(gfx::Size(10, 10), GetParam()));
- ASSERT_NE(nullptr, held_buffers.back().get());
- }
-
- // Now, attempt to resurrect the original buffer. This should succeed.
- std::unique_ptr<Buffer> resurrected =
- ResurrectLastBuffer(gfx::Size(10, 10), GetParam());
- ASSERT_NE(nullptr, resurrected.get());
- ASSERT_EQ(original_mapped_size, resurrected->mapped_size());
- uint8_t* resurrected_memory = reinterpret_cast<uint8_t*>(resurrected->data());
- for (size_t i = 0; i < original_mapped_size; ++i)
- EXPECT_EQ(0xde, resurrected_memory[i]) << "Mismatch at byte offset: " << i;
- resurrected.reset();
-
- // Reserve the final buffer in the pool, and then confirm resurrection does
- // not succeed.
- held_buffers.push_back(ReserveBuffer(gfx::Size(10, 10), GetParam()));
- ASSERT_NE(nullptr, held_buffers.back().get());
- resurrected = ResurrectLastBuffer(gfx::Size(10, 10), GetParam());
- ASSERT_EQ(nullptr, resurrected.get());
-}
-
INSTANTIATE_TEST_CASE_P(,
VideoCaptureBufferPoolTest,
testing::ValuesIn(kCapturePixelFormats));
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 b964d0e82f9..0602d0a05f8 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_controller.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_controller.cc
@@ -47,17 +47,66 @@ static const int kInfiniteRatio = 99999;
base::UmaHistogramSparse( \
name, (height) ? ((width)*100) / (height) : kInfiniteRatio);
-void LogVideoFrameDrop(media::VideoCaptureFrameDropReason reason) {
- UMA_HISTOGRAM_ENUMERATION(
- "Media.VideoCapture.FrameDrop", reason,
- static_cast<int>(media::VideoCaptureFrameDropReason::kMaxValue) + 1);
+void LogVideoFrameDrop(media::VideoCaptureFrameDropReason reason,
+ MediaStreamType stream_type) {
+ const int kEnumCount =
+ static_cast<int>(media::VideoCaptureFrameDropReason::kMaxValue) + 1;
+ UMA_HISTOGRAM_ENUMERATION("Media.VideoCapture.FrameDrop", reason, kEnumCount);
+ switch (stream_type) {
+ case MEDIA_DEVICE_VIDEO_CAPTURE:
+ UMA_HISTOGRAM_ENUMERATION("Media.VideoCapture.FrameDrop.DeviceCapture",
+ reason, kEnumCount);
+ break;
+ case MEDIA_GUM_TAB_VIDEO_CAPTURE:
+ UMA_HISTOGRAM_ENUMERATION("Media.VideoCapture.FrameDrop.GumTabCapture",
+ reason, kEnumCount);
+ break;
+ case MEDIA_GUM_DESKTOP_VIDEO_CAPTURE:
+ UMA_HISTOGRAM_ENUMERATION(
+ "Media.VideoCapture.FrameDrop.GumDesktopCapture", reason, kEnumCount);
+ break;
+ case MEDIA_DISPLAY_VIDEO_CAPTURE:
+ UMA_HISTOGRAM_ENUMERATION("Media.VideoCapture.FrameDrop.DisplayCapture",
+ reason, kEnumCount);
+ break;
+ default:
+ // Do nothing
+ return;
+ }
}
void LogMaxConsecutiveVideoFrameDropCountExceeded(
- media::VideoCaptureFrameDropReason reason) {
- UMA_HISTOGRAM_ENUMERATION(
- "Media.VideoCapture.MaxFrameDropExceeded", reason,
- static_cast<int>(media::VideoCaptureFrameDropReason::kMaxValue) + 1);
+ media::VideoCaptureFrameDropReason reason,
+ MediaStreamType stream_type) {
+ const int kEnumCount =
+ static_cast<int>(media::VideoCaptureFrameDropReason::kMaxValue) + 1;
+ UMA_HISTOGRAM_ENUMERATION("Media.VideoCapture.MaxFrameDropExceeded", reason,
+ kEnumCount);
+ switch (stream_type) {
+ case MEDIA_DEVICE_VIDEO_CAPTURE:
+ UMA_HISTOGRAM_ENUMERATION(
+ "Media.VideoCapture.MaxFrameDropExceeded.DeviceCapture", reason,
+ kEnumCount);
+ break;
+ case MEDIA_GUM_TAB_VIDEO_CAPTURE:
+ UMA_HISTOGRAM_ENUMERATION(
+ "Media.VideoCapture.MaxFrameDropExceeded.GumTabCapture", reason,
+ kEnumCount);
+ break;
+ case MEDIA_GUM_DESKTOP_VIDEO_CAPTURE:
+ UMA_HISTOGRAM_ENUMERATION(
+ "Media.VideoCapture.MaxFrameDropExceeded.GumDesktopCapture", reason,
+ kEnumCount);
+ break;
+ case MEDIA_DISPLAY_VIDEO_CAPTURE:
+ UMA_HISTOGRAM_ENUMERATION(
+ "Media.VideoCapture.MaxFrameDropExceeded.DisplayCapture", reason,
+ kEnumCount);
+ break;
+ default:
+ // Do nothing
+ return;
+ }
}
void CallOnError(media::VideoCaptureError error,
@@ -462,13 +511,9 @@ void VideoCaptureController::OnFrameReadyInBuffer(
if (!base::ContainsValue(client->known_buffer_context_ids,
buffer_context_id)) {
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)
- .ImageAllocationSize();
client->event_handler->OnNewBuffer(
client->controller_id, buffer_context_iter->CloneBufferHandle(),
- mapped_size, buffer_context_id);
+ buffer_context_id);
}
if (!base::ContainsValue(client->buffers_in_use, buffer_context_id))
@@ -487,10 +532,10 @@ void VideoCaptureController::OnFrameReadyInBuffer(
}
if (!has_received_frames_) {
- UMA_HISTOGRAM_COUNTS("Media.VideoCapture.Width",
- frame_info->coded_size.width());
- UMA_HISTOGRAM_COUNTS("Media.VideoCapture.Height",
- frame_info->coded_size.height());
+ UMA_HISTOGRAM_COUNTS_1M("Media.VideoCapture.Width",
+ frame_info->coded_size.width());
+ UMA_HISTOGRAM_COUNTS_1M("Media.VideoCapture.Height",
+ frame_info->coded_size.height());
UMA_HISTOGRAM_ASPECT_RATIO("Media.VideoCapture.AspectRatio",
frame_info->coded_size.width(),
frame_info->coded_size.height());
@@ -502,7 +547,7 @@ void VideoCaptureController::OnFrameReadyInBuffer(
frame_rate = video_capture_format_->frame_rate;
}
}
- UMA_HISTOGRAM_COUNTS("Media.VideoCapture.FrameRate", frame_rate);
+ UMA_HISTOGRAM_COUNTS_1M("Media.VideoCapture.FrameRate", frame_rate);
UMA_HISTOGRAM_TIMES("Media.VideoCapture.DelayUntilFirstFrame",
base::TimeTicks::Now() - time_of_start_request_);
OnLog("First frame received at VideoCaptureController");
@@ -540,7 +585,7 @@ void VideoCaptureController::OnFrameDropped(
if (++frame_drop_log_state_.drop_count >
kMaxConsecutiveFrameDropForSameReasonCount) {
frame_drop_log_state_.max_log_count_exceeded = true;
- LogMaxConsecutiveVideoFrameDropCountExceeded(reason);
+ LogMaxConsecutiveVideoFrameDropCountExceeded(reason, stream_type_);
std::ostringstream string_stream;
string_stream << "Too many consecutive frames dropped with reason code "
<< static_cast<int>(reason)
@@ -553,7 +598,7 @@ void VideoCaptureController::OnFrameDropped(
frame_drop_log_state_ = FrameDropLogState(reason);
}
- LogVideoFrameDrop(reason);
+ LogVideoFrameDrop(reason, stream_type_);
std::ostringstream string_stream;
string_stream << "Frame dropped with reason code "
<< static_cast<int>(reason);
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 a2564afb998..8c849cbcdf8 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
@@ -38,7 +38,6 @@ class CONTENT_EXPORT VideoCaptureControllerEventHandler {
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.
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 a5af5ca6252..0e9abecdbf3 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
@@ -19,12 +19,14 @@
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
+#include "base/task/post_task.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/renderer_host/media/media_stream_provider.h"
#include "content/browser/renderer_host/media/mock_video_capture_provider.h"
#include "content/browser/renderer_host/media/video_capture_controller_event_handler.h"
#include "content/browser/renderer_host/media/video_capture_manager.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "media/base/video_frame_metadata.h"
@@ -75,7 +77,6 @@ class MockVideoCaptureControllerEventHandler
}
void OnNewBuffer(VideoCaptureControllerID id,
media::mojom::VideoBufferHandlePtr buffer_handle,
- int length,
int buffer_id) override {
DoBufferCreated(id, buffer_id);
}
@@ -163,7 +164,7 @@ class VideoCaptureControllerTest
media::VideoCaptureBufferType::kSharedMemory,
std::make_unique<media::VideoFrameReceiverOnTaskRunner>(
controller_->GetWeakPtrForIOThread(),
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)),
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO})),
buffer_pool_, media::VideoCaptureJpegDecoderFactoryCB()));
}
@@ -316,11 +317,12 @@ TEST_P(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
uint8_t buffer_no = 1;
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,
- arbitrary_frame_feedback_id);
- ASSERT_TRUE(buffer.is_valid());
+ media::VideoCaptureDevice::Client::Buffer buffer;
+ const auto result_code = device_client_->ReserveOutputBuffer(
+ device_format.frame_size, device_format.pixel_format,
+ arbitrary_frame_feedback_id, &buffer);
+ ASSERT_EQ(media::VideoCaptureDevice::Client::ReserveResult::kSucceeded,
+ result_code);
auto buffer_access = buffer.handle_provider->GetHandleForInProcessAccess();
ASSERT_EQ(1.0 / kPoolSize, device_client_->GetBufferPoolUtilization());
memset(buffer_access->data(), buffer_no++, buffer_access->mapped_size());
@@ -362,11 +364,12 @@ TEST_P(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
// case pretend that the Buffer pointer is held by the device for a long
// 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,
- arbitrary_frame_feedback_id_2);
- ASSERT_TRUE(buffer2.is_valid());
+ media::VideoCaptureDevice::Client::Buffer buffer2;
+ const auto result_code_2 = device_client_->ReserveOutputBuffer(
+ device_format.frame_size, device_format.pixel_format,
+ arbitrary_frame_feedback_id_2, &buffer2);
+ ASSERT_EQ(media::VideoCaptureDevice::Client::ReserveResult::kSucceeded,
+ result_code_2);
auto buffer2_access = buffer2.handle_provider->GetHandleForInProcessAccess();
memset(buffer2_access->data(), buffer_no++, buffer2_access->mapped_size());
client_a_->resource_utilization_ = 0.5;
@@ -380,25 +383,13 @@ TEST_P(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
arbitrary_reference_time_,
arbitrary_timestamp_);
- // The buffer should be delivered to the clients in any order.
- {
- InSequence s;
- EXPECT_CALL(*client_a_, DoBufferCreated(client_a_route_1, _));
- EXPECT_CALL(*client_a_,
- DoBufferReady(client_a_route_1, device_format.frame_size));
- }
- {
- InSequence s;
- EXPECT_CALL(*client_b_, DoBufferCreated(client_b_route_1, _));
- EXPECT_CALL(*client_b_,
- DoBufferReady(client_b_route_1, device_format.frame_size));
- }
- {
- InSequence s;
- EXPECT_CALL(*client_a_, DoBufferCreated(client_a_route_2, _));
- EXPECT_CALL(*client_a_,
- DoBufferReady(client_a_route_2, device_format.frame_size));
- }
+ // The frame should be delivered to the clients in any order.
+ EXPECT_CALL(*client_a_,
+ DoBufferReady(client_a_route_1, device_format.frame_size));
+ EXPECT_CALL(*client_b_,
+ DoBufferReady(client_b_route_1, device_format.frame_size));
+ EXPECT_CALL(*client_a_,
+ DoBufferReady(client_a_route_2, device_format.frame_size));
base::RunLoop().RunUntilIdle();
Mock::VerifyAndClearExpectations(client_a_.get());
Mock::VerifyAndClearExpectations(client_b_.get());
@@ -411,11 +402,12 @@ TEST_P(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
// Third, fourth, and fifth buffers. Pretend they all arrive at the same time.
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,
- arbitrary_frame_feedback_id);
- ASSERT_TRUE(buffer.is_valid());
+ media::VideoCaptureDevice::Client::Buffer buffer;
+ const auto result_code = device_client_->ReserveOutputBuffer(
+ device_format.frame_size, device_format.pixel_format,
+ arbitrary_frame_feedback_id, &buffer);
+ ASSERT_EQ(media::VideoCaptureDevice::Client::ReserveResult::kSucceeded,
+ result_code);
auto buffer_access = buffer.handle_provider->GetHandleForInProcessAccess();
memset(buffer_access->data(), buffer_no++, buffer_access->mapped_size());
device_client_->OnIncomingCapturedBuffer(std::move(buffer), device_format,
@@ -423,31 +415,32 @@ TEST_P(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
arbitrary_timestamp_);
}
// ReserveOutputBuffer ought to fail now, because the pool is depleted.
- ASSERT_FALSE(device_client_
- ->ReserveOutputBuffer(device_format.frame_size,
- device_format.pixel_format,
- arbitrary_frame_feedback_id)
- .is_valid());
+ media::VideoCaptureDevice::Client::Buffer buffer_fail;
+ ASSERT_EQ(
+ media::VideoCaptureDevice::Client::ReserveResult::kMaxBufferCountExceeded,
+ device_client_->ReserveOutputBuffer(
+ device_format.frame_size, device_format.pixel_format,
+ arbitrary_frame_feedback_id, &buffer_fail));
// The new client needs to be notified of the creation of |kPoolSize| buffers;
- // the old clients only |kPoolSize - 2|.
+ // the old clients only |kPoolSize - 1|.
EXPECT_CALL(*client_b_, DoBufferCreated(client_b_route_2, _))
.Times(kPoolSize);
EXPECT_CALL(*client_b_,
DoBufferReady(client_b_route_2, device_format.frame_size))
.Times(kPoolSize);
EXPECT_CALL(*client_a_, DoBufferCreated(client_a_route_1, _))
- .Times(kPoolSize - 2);
+ .Times(kPoolSize - 1);
EXPECT_CALL(*client_a_,
DoBufferReady(client_a_route_1, device_format.frame_size))
.Times(kPoolSize);
EXPECT_CALL(*client_a_, DoBufferCreated(client_a_route_2, _))
- .Times(kPoolSize - 2);
+ .Times(kPoolSize - 1);
EXPECT_CALL(*client_a_,
DoBufferReady(client_a_route_2, device_format.frame_size))
.Times(kPoolSize);
EXPECT_CALL(*client_b_, DoBufferCreated(client_b_route_1, _))
- .Times(kPoolSize - 2);
+ .Times(kPoolSize - 1);
EXPECT_CALL(*client_b_,
DoBufferReady(client_b_route_1, device_format.frame_size))
.Times(kPoolSize);
@@ -462,28 +455,30 @@ TEST_P(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
EXPECT_CALL(*client_b_, DoEnded(client_b_route_1)).Times(1);
controller_->StopSession(300);
// Queue up another buffer.
- media::VideoCaptureDevice::Client::Buffer buffer3 =
- device_client_->ReserveOutputBuffer(device_format.frame_size,
- device_format.pixel_format,
- arbitrary_frame_feedback_id);
- ASSERT_TRUE(buffer3.is_valid());
+ media::VideoCaptureDevice::Client::Buffer buffer3;
+ const auto result_code_3 = device_client_->ReserveOutputBuffer(
+ device_format.frame_size, device_format.pixel_format,
+ arbitrary_frame_feedback_id, &buffer3);
+ ASSERT_EQ(media::VideoCaptureDevice::Client::ReserveResult::kSucceeded,
+ result_code_3);
auto buffer3_access = buffer3.handle_provider->GetHandleForInProcessAccess();
memset(buffer3_access->data(), buffer_no++, buffer3_access->mapped_size());
device_client_->OnIncomingCapturedBuffer(std::move(buffer3), device_format,
arbitrary_reference_time_,
arbitrary_timestamp_);
- media::VideoCaptureDevice::Client::Buffer buffer4 =
- device_client_->ReserveOutputBuffer(device_format.frame_size,
- device_format.pixel_format,
- arbitrary_frame_feedback_id);
+ media::VideoCaptureDevice::Client::Buffer buffer4;
+ const auto result_code_4 = device_client_->ReserveOutputBuffer(
+ device_format.frame_size, device_format.pixel_format,
+ arbitrary_frame_feedback_id, &buffer4);
{
// Kill A2 via session close (posts a task to disconnect, but A2 must not
// be sent either of these two buffers).
EXPECT_CALL(*client_a_, DoEnded(client_a_route_2)).Times(1);
controller_->StopSession(200);
}
- ASSERT_TRUE(buffer4.is_valid());
+ ASSERT_EQ(media::VideoCaptureDevice::Client::ReserveResult::kSucceeded,
+ result_code_4);
auto buffer4_access = buffer4.handle_provider->GetHandleForInProcessAccess();
memset(buffer4_access->data(), buffer_no++, buffer4_access->mapped_size());
device_client_->OnIncomingCapturedBuffer(std::move(buffer4), device_format,
@@ -544,10 +539,12 @@ TEST_F(VideoCaptureControllerTest, ErrorBeforeDeviceCreation) {
media::VideoCaptureFormat device_format(
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,
- arbitrary_frame_feedback_id);
+ media::VideoCaptureDevice::Client::Buffer buffer;
+ const auto reserve_result = device_client_->ReserveOutputBuffer(
+ device_format.frame_size, device_format.pixel_format,
+ arbitrary_frame_feedback_id, &buffer);
+ ASSERT_EQ(media::VideoCaptureDevice::Client::ReserveResult::kSucceeded,
+ reserve_result);
device_client_->OnIncomingCapturedBuffer(std::move(buffer), device_format,
arbitrary_reference_time_,
arbitrary_timestamp_);
@@ -578,11 +575,12 @@ TEST_F(VideoCaptureControllerTest, ErrorAfterDeviceCreation) {
media::VideoCaptureFormat device_format(
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,
- arbitrary_frame_feedback_id);
- ASSERT_TRUE(buffer.is_valid());
+ media::VideoCaptureDevice::Client::Buffer buffer;
+ const auto result_code = device_client_->ReserveOutputBuffer(
+ device_format.frame_size, device_format.pixel_format,
+ arbitrary_frame_feedback_id, &buffer);
+ ASSERT_EQ(media::VideoCaptureDevice::Client::ReserveResult::kSucceeded,
+ result_code);
device_client_->OnError(
media::VideoCaptureError::kIntentionalErrorRaisedByUnitTest, FROM_HERE,
@@ -643,21 +641,14 @@ TEST_F(VideoCaptureControllerTest, FrameFeedbackIsReportedForSequenceOfFrames) {
.Times(1);
// Device prepares and pushes a frame.
- // For the first half of the frames we exercise ReserveOutputBuffer() while
- // for the second half we exercise ResurrectLastOutputBuffer().
// The frame is expected to arrive at |client_a_|.DoBufferReady(), which
// automatically notifies |controller_| that it has finished consuming it.
media::VideoCaptureDevice::Client::Buffer buffer;
- if (frame_index < kTestFrameSequenceLength / 2) {
- buffer = device_client_->ReserveOutputBuffer(
- arbitrary_format.frame_size, arbitrary_format.pixel_format,
- stub_frame_feedback_id);
- } else {
- buffer = device_client_->ResurrectLastOutputBuffer(
- arbitrary_format.frame_size, arbitrary_format.pixel_format,
- stub_frame_feedback_id);
- }
- ASSERT_TRUE(buffer.is_valid());
+ const auto result_code = device_client_->ReserveOutputBuffer(
+ arbitrary_format.frame_size, arbitrary_format.pixel_format,
+ stub_frame_feedback_id, &buffer);
+ ASSERT_EQ(media::VideoCaptureDevice::Client::ReserveResult::kSucceeded,
+ result_code);
device_client_->OnIncomingCapturedBuffer(
std::move(buffer), arbitrary_format, arbitrary_reference_time_,
arbitrary_timestamp_);
@@ -861,20 +852,17 @@ TEST_F(VideoCaptureControllerTest, DroppedFramesGetLoggedInUMA) {
controller_->OnFrameDropped(
media::VideoCaptureFrameDropReason::kDeviceClientFrameHasInvalidFormat);
controller_->OnFrameDropped(
- media::VideoCaptureFrameDropReason::
- kDeviceClientFailedToReserveBufferFromBufferPool);
+ media::VideoCaptureFrameDropReason::kBufferPoolMaxBufferCountExceeded);
controller_->OnFrameDropped(
media::VideoCaptureFrameDropReason::kDeviceClientFrameHasInvalidFormat);
histogram_tester.ExpectBucketCount(
- "Media.VideoCapture.FrameDrop",
+ "Media.VideoCapture.FrameDrop.DeviceCapture",
media::VideoCaptureFrameDropReason::kDeviceClientFrameHasInvalidFormat,
2);
histogram_tester.ExpectBucketCount(
- "Media.VideoCapture.FrameDrop",
- media::VideoCaptureFrameDropReason::
- kDeviceClientFailedToReserveBufferFromBufferPool,
- 1);
+ "Media.VideoCapture.FrameDrop.DeviceCapture",
+ media::VideoCaptureFrameDropReason::kBufferPoolMaxBufferCountExceeded, 1);
}
// Tests that too many frames dropped for the same reason emits a special UMA
@@ -890,7 +878,7 @@ TEST_F(VideoCaptureControllerTest,
media::VideoCaptureFrameDropReason::kDeviceClientFrameHasInvalidFormat);
}
histogram_tester.ExpectBucketCount(
- "Media.VideoCapture.FrameDrop",
+ "Media.VideoCapture.FrameDrop.DeviceCapture",
media::VideoCaptureFrameDropReason::kDeviceClientFrameHasInvalidFormat,
VideoCaptureController::kMaxConsecutiveFrameDropForSameReasonCount);
@@ -899,12 +887,12 @@ TEST_F(VideoCaptureControllerTest,
controller_->OnFrameDropped(
media::VideoCaptureFrameDropReason::kDeviceClientFrameHasInvalidFormat);
histogram_tester.ExpectBucketCount(
- "Media.VideoCapture.FrameDrop",
+ "Media.VideoCapture.FrameDrop.DeviceCapture",
media::VideoCaptureFrameDropReason::kDeviceClientFrameHasInvalidFormat,
VideoCaptureController::kMaxConsecutiveFrameDropForSameReasonCount);
histogram_tester.ExpectBucketCount(
- "Media.VideoCapture.MaxFrameDropExceeded",
+ "Media.VideoCapture.MaxFrameDropExceeded.DeviceCapture",
media::VideoCaptureFrameDropReason::kDeviceClientFrameHasInvalidFormat,
1);
}
@@ -930,7 +918,7 @@ TEST_F(VideoCaptureControllerTest,
media::VideoCaptureFrameDropReason::kDeviceClientFrameHasInvalidFormat);
}
histogram_tester.ExpectBucketCount(
- "Media.VideoCapture.FrameDrop",
+ "Media.VideoCapture.FrameDrop.DeviceCapture",
media::VideoCaptureFrameDropReason::kDeviceClientFrameHasInvalidFormat,
2 * VideoCaptureController::kMaxConsecutiveFrameDropForSameReasonCount -
1);
@@ -954,7 +942,7 @@ TEST_F(VideoCaptureControllerTest, DeliveredFrameReenablesDroppedFrameLogging) {
controller_->OnFrameDropped(
media::VideoCaptureFrameDropReason::kDeviceClientFrameHasInvalidFormat);
histogram_tester.ExpectBucketCount(
- "Media.VideoCapture.FrameDrop",
+ "Media.VideoCapture.FrameDrop.DeviceCapture",
media::VideoCaptureFrameDropReason::kDeviceClientFrameHasInvalidFormat,
VideoCaptureController::kMaxConsecutiveFrameDropForSameReasonCount + 1);
}
@@ -974,20 +962,17 @@ TEST_F(VideoCaptureControllerTest,
// Drop for a different reason
controller_->OnFrameDropped(
- media::VideoCaptureFrameDropReason::
- kDeviceClientFailedToReserveBufferFromBufferPool);
+ media::VideoCaptureFrameDropReason::kBufferPoolMaxBufferCountExceeded);
controller_->OnFrameDropped(
media::VideoCaptureFrameDropReason::kDeviceClientFrameHasInvalidFormat);
histogram_tester.ExpectBucketCount(
- "Media.VideoCapture.FrameDrop",
+ "Media.VideoCapture.FrameDrop.DeviceCapture",
media::VideoCaptureFrameDropReason::kDeviceClientFrameHasInvalidFormat,
VideoCaptureController::kMaxConsecutiveFrameDropForSameReasonCount + 1);
histogram_tester.ExpectBucketCount(
- "Media.VideoCapture.FrameDrop",
- media::VideoCaptureFrameDropReason::
- kDeviceClientFailedToReserveBufferFromBufferPool,
- 1);
+ "Media.VideoCapture.FrameDrop.DeviceCapture",
+ media::VideoCaptureFrameDropReason::kBufferPoolMaxBufferCountExceeded, 1);
}
} // namespace content
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 d35e6a28544..40301360b51 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_host.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_host.cc
@@ -8,9 +8,11 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
+#include "base/task/post_task.h"
#include "content/browser/browser_main_loop.h"
#include "content/browser/renderer_host/media/media_stream_manager.h"
#include "content/browser/renderer_host/media/video_capture_manager.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
@@ -109,8 +111,8 @@ void VideoCaptureHost::OnError(VideoCaptureControllerID controller_id,
media::VideoCaptureError error) {
DVLOG(1) << __func__;
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&VideoCaptureHost::DoError, weak_factory_.GetWeakPtr(),
controller_id, error));
}
@@ -118,7 +120,6 @@ void VideoCaptureHost::OnError(VideoCaptureControllerID controller_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())
@@ -158,8 +159,8 @@ void VideoCaptureHost::OnBufferReady(
void VideoCaptureHost::OnEnded(VideoCaptureControllerID controller_id) {
DVLOG(1) << __func__;
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&VideoCaptureHost::DoEnded, weak_factory_.GetWeakPtr(),
controller_id));
}
@@ -400,8 +401,8 @@ void VideoCaptureHost::NotifyStreamAdded() {
++number_of_active_streams_;
// base::Unretained() usage is safe because |render_process_host_delegate_|
// is destroyed on UI thread.
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&RenderProcessHostDelegate::NotifyStreamAdded,
base::Unretained(render_process_host_delegate_.get())));
}
@@ -417,8 +418,8 @@ void VideoCaptureHost::NotifyStreamRemoved() {
--number_of_active_streams_;
// base::Unretained() usage is safe because |render_process_host_delegate_| is
// destroyed on UI thread.
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&RenderProcessHostDelegate::NotifyStreamRemoved,
base::Unretained(render_process_host_delegate_.get())));
}
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 5fdecfe6c63..afaf18d8102 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_host.h
+++ b/chromium/content/browser/renderer_host/media/video_capture_host.h
@@ -57,7 +57,6 @@ class CONTENT_EXPORT VideoCaptureHost
media::VideoCaptureError error) override;
void OnNewBuffer(VideoCaptureControllerID id,
media::mojom::VideoBufferHandlePtr buffer_handle,
- int length,
int buffer_id) override;
void OnBufferDestroyed(VideoCaptureControllerID id,
int buffer_id) override;
diff --git a/chromium/content/browser/renderer_host/media/video_capture_manager.cc b/chromium/content/browser/renderer_host/media/video_capture_manager.cc
index 12e9dc70f33..ec2803c1ac9 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_manager.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_manager.cc
@@ -22,6 +22,7 @@
#include "build/build_config.h"
#include "content/browser/media/media_internals.h"
#include "content/browser/renderer_host/media/video_capture_controller.h"
+#include "content/browser/screenlock_monitor/screenlock_monitor.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/desktop_media_id.h"
#include "content/public/common/media_stream_request.h"
@@ -85,14 +86,23 @@ VideoCaptureManager::CaptureDeviceStartRequest::CaptureDeviceStartRequest(
VideoCaptureManager::VideoCaptureManager(
std::unique_ptr<VideoCaptureProvider> video_capture_provider,
- base::RepeatingCallback<void(const std::string&)> emit_log_message_cb)
+ base::RepeatingCallback<void(const std::string&)> emit_log_message_cb,
+ ScreenlockMonitor* monitor)
: new_capture_session_id_(1),
video_capture_provider_(std::move(video_capture_provider)),
- emit_log_message_cb_(std::move(emit_log_message_cb)) {}
+ emit_log_message_cb_(std::move(emit_log_message_cb)),
+ screenlock_monitor_(monitor) {
+ if (screenlock_monitor_) {
+ screenlock_monitor_->AddObserver(this);
+ }
+}
VideoCaptureManager::~VideoCaptureManager() {
DCHECK(controllers_.empty());
DCHECK(device_start_request_queue_.empty());
+ if (screenlock_monitor_) {
+ screenlock_monitor_->RemoveObserver(this);
+ }
}
void VideoCaptureManager::AddVideoCaptureObserver(
@@ -114,9 +124,9 @@ void VideoCaptureManager::RegisterListener(
listeners_.AddObserver(listener);
#if defined(OS_ANDROID)
application_state_has_running_activities_ = true;
- app_status_listener_.reset(new base::android::ApplicationStatusListener(
- base::Bind(&VideoCaptureManager::OnApplicationStateChange,
- base::Unretained(this))));
+ app_status_listener_ = base::android::ApplicationStatusListener::New(
+ base::BindRepeating(&VideoCaptureManager::OnApplicationStateChange,
+ base::Unretained(this)));
#endif
}
@@ -127,14 +137,15 @@ void VideoCaptureManager::UnregisterListener(
}
void VideoCaptureManager::EnumerateDevices(
- const EnumerationCallback& client_callback) {
+ EnumerationCallback client_callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
EmitLogMessage("VideoCaptureManager::EnumerateDevices", 1);
// Pass a timer for UMA histogram collection.
- video_capture_provider_->GetDeviceInfosAsync(media::BindToCurrentLoop(
- base::Bind(&VideoCaptureManager::OnDeviceInfosReceived, this,
- base::Owned(new base::ElapsedTimer()), client_callback)));
+ video_capture_provider_->GetDeviceInfosAsync(
+ media::BindToCurrentLoop(base::BindOnce(
+ &VideoCaptureManager::OnDeviceInfosReceived, this,
+ base::Owned(new base::ElapsedTimer()), std::move(client_callback))));
}
int VideoCaptureManager::Open(const MediaStreamDevice& device) {
@@ -170,9 +181,8 @@ void VideoCaptureManager::Close(int capture_session_id) {
<< capture_session_id;
EmitLogMessage(string_stream.str(), 1);
- SessionMap::iterator session_it = sessions_.find(capture_session_id);
+ auto session_it = sessions_.find(capture_session_id);
if (session_it == sessions_.end()) {
- NOTREACHED();
return;
}
@@ -249,7 +259,7 @@ void VideoCaptureManager::DoStopDevice(VideoCaptureController* controller) {
void VideoCaptureManager::ProcessDeviceStartRequestQueue() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DeviceStartQueue::iterator request = device_start_request_queue_.begin();
+ auto request = device_start_request_queue_.begin();
if (request == device_start_request_queue_.end())
return;
@@ -506,7 +516,7 @@ bool VideoCaptureManager::GetDeviceSupportedFormats(
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(supported_formats->empty());
- SessionMap::iterator it = sessions_.find(capture_session_id);
+ auto it = sessions_.find(capture_session_id);
if (it == sessions_.end())
return false;
std::ostringstream string_stream;
@@ -535,7 +545,7 @@ bool VideoCaptureManager::GetDeviceFormatsInUse(
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(formats_in_use->empty());
- SessionMap::iterator it = sessions_.find(capture_session_id);
+ auto it = sessions_.find(capture_session_id);
if (it == sessions_.end())
return false;
std::ostringstream string_stream;
@@ -572,7 +582,7 @@ void VideoCaptureManager::SetDesktopCaptureWindowId(
void VideoCaptureManager::MaybePostDesktopCaptureWindowId(
media::VideoCaptureSessionId session_id) {
- SessionMap::iterator session_it = sessions_.find(session_id);
+ auto session_it = sessions_.find(session_id);
if (session_it == sessions_.end())
return;
@@ -684,7 +694,7 @@ void VideoCaptureManager::OnClosed(
void VideoCaptureManager::OnDeviceInfosReceived(
base::ElapsedTimer* timer,
- const EnumerationCallback& client_callback,
+ EnumerationCallback client_callback,
const std::vector<media::VideoCaptureDeviceInfo>& device_infos) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
UMA_HISTOGRAM_TIMES(
@@ -715,7 +725,7 @@ void VideoCaptureManager::OnDeviceInfosReceived(
descriptors_and_formats);
}
- client_callback.Run(devices);
+ std::move(client_callback).Run(devices);
}
void VideoCaptureManager::DestroyControllerIfNoClients(
@@ -802,7 +812,7 @@ VideoCaptureController* VideoCaptureManager::GetOrCreateController(
const media::VideoCaptureParams& params) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- SessionMap::iterator session_it = sessions_.find(capture_session_id);
+ auto session_it = sessions_.find(capture_session_id);
if (session_it == sessions_.end())
return nullptr;
const MediaStreamDevice& device_info = session_it->second;
@@ -889,6 +899,24 @@ void VideoCaptureManager::ResumeDevices() {
}
#endif // defined(OS_ANDROID)
+void VideoCaptureManager::OnScreenLocked() {
+#if !defined(OS_ANDROID)
+ // Stop screen sharing when screen is locked on desktop platforms only.
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ EmitLogMessage("VideoCaptureManager::OnScreenLocked", 1);
+
+ std::vector<media::VideoCaptureSessionId> desktopcapture_session_ids;
+ for (auto it : sessions_) {
+ if (IsDesktopCaptureMediaType(it.second.type))
+ desktopcapture_session_ids.push_back(it.first);
+ }
+
+ for (auto session_id : desktopcapture_session_ids) {
+ Close(session_id);
+ }
+#endif // OS_ANDROID
+}
+
void VideoCaptureManager::EmitLogMessage(const std::string& message,
int verbose_log_level) {
DVLOG(verbose_log_level) << message;
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 a32d287958c..69ab00edf2e 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_manager.h
+++ b/chromium/content/browser/renderer_host/media/video_capture_manager.h
@@ -23,6 +23,7 @@
#include "content/browser/renderer_host/media/video_capture_device_launch_observer.h"
#include "content/browser/renderer_host/media/video_capture_provider.h"
#include "content/common/content_export.h"
+#include "content/public/browser/screenlock_observer.h"
#include "media/base/video_facing.h"
#include "media/capture/video/video_capture_device.h"
#include "media/capture/video/video_capture_device_info.h"
@@ -35,6 +36,7 @@
namespace content {
class VideoCaptureController;
class VideoCaptureControllerEventHandler;
+class ScreenlockMonitor;
// VideoCaptureManager is used to open/close, start/stop, enumerate available
// video capture devices, and manage VideoCaptureController's.
@@ -43,7 +45,8 @@ class VideoCaptureControllerEventHandler;
// the Browser::IO thread. A device can only be opened once.
class CONTENT_EXPORT VideoCaptureManager
: public MediaStreamProvider,
- public VideoCaptureDeviceLaunchObserver {
+ public VideoCaptureDeviceLaunchObserver,
+ public ScreenlockObserver {
public:
using VideoCaptureDevice = media::VideoCaptureDevice;
@@ -53,7 +56,8 @@ class CONTENT_EXPORT VideoCaptureManager
explicit VideoCaptureManager(
std::unique_ptr<VideoCaptureProvider> video_capture_provider,
- base::RepeatingCallback<void(const std::string&)> emit_log_message_cb);
+ base::RepeatingCallback<void(const std::string&)> emit_log_message_cb,
+ ScreenlockMonitor* monitor = nullptr);
// AddVideoCaptureObserver() can be called only before any devices are opened.
// RemoveAllVideoCaptureObservers() can be called only after all devices
@@ -172,10 +176,10 @@ class CONTENT_EXPORT VideoCaptureManager
#endif
using EnumerationCallback =
- base::Callback<void(const media::VideoCaptureDeviceDescriptors&)>;
+ base::OnceCallback<void(const media::VideoCaptureDeviceDescriptors&)>;
// Asynchronously obtains descriptors for the available devices.
// As a side-effect, updates |devices_info_cache_|.
- void EnumerateDevices(const EnumerationCallback& client_callback);
+ void EnumerateDevices(EnumerationCallback client_callback);
// VideoCaptureDeviceLaunchObserver implementation:
void OnDeviceLaunched(VideoCaptureController* controller) override;
@@ -203,7 +207,7 @@ class CONTENT_EXPORT VideoCaptureManager
void OnDeviceInfosReceived(
base::ElapsedTimer* timer,
- const EnumerationCallback& client_callback,
+ EnumerationCallback client_callback,
const std::vector<media::VideoCaptureDeviceInfo>& device_infos);
// Helpers to report an event to our Listener.
@@ -262,6 +266,9 @@ class CONTENT_EXPORT VideoCaptureManager
bool application_state_has_running_activities_;
#endif
+ // ScreenlockObserver implementation:
+ void OnScreenLocked() override;
+
void EmitLogMessage(const std::string& message, int verbose_log_level);
// Only accessed on Browser::IO thread.
@@ -288,6 +295,7 @@ class CONTENT_EXPORT VideoCaptureManager
const std::unique_ptr<VideoCaptureProvider> video_capture_provider_;
base::RepeatingCallback<void(const std::string&)> emit_log_message_cb_;
+ ScreenlockMonitor* screenlock_monitor_;
base::ObserverList<media::VideoCaptureObserver>::Unchecked capture_observers_;
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 ce592438e1d..b9d98f0a1d0 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
@@ -18,9 +18,13 @@
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "build/build_config.h"
#include "content/browser/renderer_host/media/in_process_video_capture_provider.h"
#include "content/browser/renderer_host/media/media_stream_provider.h"
#include "content/browser/renderer_host/media/video_capture_controller_event_handler.h"
+#include "content/browser/screenlock_monitor/screenlock_monitor.h"
+#include "content/browser/screenlock_monitor/screenlock_monitor_source.h"
+#include "content/public/browser/desktop_media_id.h"
#include "content/public/common/media_stream_request.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "media/capture/video/fake_video_capture_device_factory.h"
@@ -33,6 +37,7 @@ using ::testing::AnyNumber;
using ::testing::DoAll;
using ::testing::InSequence;
using ::testing::InvokeWithoutArgs;
+using ::testing::Mock;
using ::testing::Return;
using ::testing::SaveArg;
@@ -160,7 +165,6 @@ class MockFrameObserver : public VideoCaptureControllerEventHandler {
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(
@@ -179,6 +183,18 @@ class MockVideoCaptureObserver : public media::VideoCaptureObserver {
MOCK_METHOD1(OnVideoCaptureStopped, void(media::VideoFacingMode));
};
+// Needed to generate ScreenLocked event to |vcm_|.
+class ScreenlockMonitorTestSource : public ScreenlockMonitorSource {
+ public:
+ ScreenlockMonitorTestSource() = default;
+ ~ScreenlockMonitorTestSource() override = default;
+
+ void GenerateScreenLockedEvent() {
+ ProcessScreenlockEvent(SCREEN_LOCK_EVENT);
+ base::RunLoop().RunUntilIdle();
+ }
+};
+
} // namespace
// Test class
@@ -188,7 +204,7 @@ class VideoCaptureManagerTest : public testing::Test {
~VideoCaptureManagerTest() override {}
void HandleEnumerationResult(
- const base::Closure& quit_closure,
+ base::OnceClosure quit_closure,
const media::VideoCaptureDeviceDescriptors& descriptors) {
MediaStreamDevices devices;
for (const auto& descriptor : descriptors) {
@@ -196,7 +212,22 @@ class VideoCaptureManagerTest : public testing::Test {
descriptor.GetNameAndModel());
}
devices_ = devices;
- quit_closure.Run();
+ std::move(quit_closure).Run();
+ }
+
+ void HandleEnumerationResultAsDisplayMediaDevices(
+ base::OnceClosure quit_closure,
+ const media::VideoCaptureDeviceDescriptors& descriptors) {
+ MediaStreamDevices devices;
+ for (const auto& descriptor : descriptors) {
+ devices.emplace_back(MEDIA_DISPLAY_VIDEO_CAPTURE,
+ DesktopMediaID(DesktopMediaID::TYPE_SCREEN,
+ DesktopMediaID::kFakeId, false)
+ .ToString(),
+ descriptor.GetNameAndModel());
+ }
+ devices_ = devices;
+ std::move(quit_closure).Run();
}
protected:
@@ -211,9 +242,14 @@ class VideoCaptureManagerTest : public testing::Test {
std::make_unique<InProcessVideoCaptureProvider>(
std::move(video_capture_system),
base::ThreadTaskRunnerHandle::Get(), kIgnoreLogMessageCB);
+ screenlock_monitor_source_ = new ScreenlockMonitorTestSource();
+ screenlock_monitor_ = std::make_unique<ScreenlockMonitor>(
+ std::unique_ptr<ScreenlockMonitorSource>(screenlock_monitor_source_));
+
vcm_ =
new VideoCaptureManager(std::move(video_capture_provider),
- base::BindRepeating([](const std::string&) {}));
+ base::BindRepeating([](const std::string&) {}),
+ ScreenlockMonitor::Get());
const int32_t kNumberOfFakeDevices = 2;
video_capture_device_factory_->SetToDefaultDevicesConfig(
kNumberOfFakeDevices);
@@ -222,8 +258,8 @@ class VideoCaptureManagerTest : public testing::Test {
base::RunLoop run_loop;
vcm_->EnumerateDevices(
- base::Bind(&VideoCaptureManagerTest::HandleEnumerationResult,
- base::Unretained(this), run_loop.QuitClosure()));
+ base::BindOnce(&VideoCaptureManagerTest::HandleEnumerationResult,
+ base::Unretained(this), run_loop.QuitClosure()));
run_loop.Run();
ASSERT_GE(devices_.size(), 2u);
}
@@ -295,6 +331,8 @@ class VideoCaptureManagerTest : public testing::Test {
#endif
int next_client_id_;
+ ScreenlockMonitorTestSource* screenlock_monitor_source_;
+ std::unique_ptr<ScreenlockMonitor> screenlock_monitor_;
std::map<VideoCaptureControllerID, VideoCaptureController*> controllers_;
scoped_refptr<VideoCaptureManager> vcm_;
std::unique_ptr<MockMediaStreamProviderListener> listener_;
@@ -418,8 +456,8 @@ TEST_F(VideoCaptureManagerTest, ConnectAndDisconnectDevices) {
video_capture_device_factory_->SetToDefaultDevicesConfig(1);
base::RunLoop run_loop;
vcm_->EnumerateDevices(
- base::Bind(&VideoCaptureManagerTest::HandleEnumerationResult,
- base::Unretained(this), run_loop.QuitClosure()));
+ base::BindOnce(&VideoCaptureManagerTest::HandleEnumerationResult,
+ base::Unretained(this), run_loop.QuitClosure()));
run_loop.Run();
ASSERT_EQ(devices_.size(), 1u);
@@ -427,8 +465,8 @@ TEST_F(VideoCaptureManagerTest, ConnectAndDisconnectDevices) {
video_capture_device_factory_->SetToDefaultDevicesConfig(3);
base::RunLoop run_loop2;
vcm_->EnumerateDevices(
- base::Bind(&VideoCaptureManagerTest::HandleEnumerationResult,
- base::Unretained(this), run_loop2.QuitClosure()));
+ base::BindOnce(&VideoCaptureManagerTest::HandleEnumerationResult,
+ base::Unretained(this), run_loop2.QuitClosure()));
run_loop2.Run();
ASSERT_EQ(devices_.size(), 3u);
@@ -653,7 +691,7 @@ TEST_F(VideoCaptureManagerTest, OpenTwo) {
EXPECT_CALL(*listener_, Opened(MEDIA_DEVICE_VIDEO_CAPTURE, _)).Times(2);
EXPECT_CALL(*listener_, Closed(MEDIA_DEVICE_VIDEO_CAPTURE, _)).Times(2);
- MediaStreamDevices::iterator it = devices_.begin();
+ auto it = devices_.begin();
int video_session_id_first = vcm_->Open(*it);
++it;
@@ -795,6 +833,65 @@ TEST_F(VideoCaptureManagerTest, PauseAndResumeDevice) {
}
#endif
+// Try to open, start a device capture device, and confirm it's not affected by
+// the ScreenLocked event.
+TEST_F(VideoCaptureManagerTest, DeviceCaptureDeviceNotClosedOnScreenlock) {
+ InSequence s;
+ // ScreenLocked event shouldn't affect camera capture device.
+ EXPECT_CALL(*listener_, Opened(MEDIA_DEVICE_VIDEO_CAPTURE, _));
+ EXPECT_CALL(*frame_observer_, OnStarted(_));
+ EXPECT_CALL(*listener_, Closed(MEDIA_DEVICE_VIDEO_CAPTURE, _)).Times(0);
+
+ int video_session_id = vcm_->Open(devices_.front());
+ VideoCaptureControllerID client_id = StartClient(video_session_id, true);
+
+ // Pretend screen is locked, which should not close the device.
+ screenlock_monitor_source_->GenerateScreenLockedEvent();
+ Mock::VerifyAndClearExpectations(listener_.get());
+
+ EXPECT_CALL(*listener_, Closed(MEDIA_DEVICE_VIDEO_CAPTURE, _));
+ StopClient(client_id);
+ vcm_->Close(video_session_id);
+
+ // Wait to check callbacks before removing the listener.
+ base::RunLoop().RunUntilIdle();
+ vcm_->UnregisterListener(listener_.get());
+}
+
+#if defined(ENABLE_SCREEN_CAPTURE) && !defined(OS_ANDROID)
+// Try to open, start a desktop capture device, and confirm it's closed on
+// ScreenLocked event on desktop platforms.
+TEST_F(VideoCaptureManagerTest, DesktopCaptureDeviceClosedOnScreenlock) {
+ InSequence s;
+ // ScreenLocked event should stop desktop capture device.
+ EXPECT_CALL(*listener_, Opened(MEDIA_DISPLAY_VIDEO_CAPTURE, _));
+ EXPECT_CALL(*frame_observer_, OnStarted(_));
+ EXPECT_CALL(*listener_, Closed(MEDIA_DISPLAY_VIDEO_CAPTURE, _));
+
+ // Simulate we add 1 fake display media device.
+ video_capture_device_factory_->SetToDefaultDevicesConfig(1);
+ base::RunLoop run_loop;
+ vcm_->EnumerateDevices(base::BindOnce(
+ &VideoCaptureManagerTest::HandleEnumerationResultAsDisplayMediaDevices,
+ base::Unretained(this), run_loop.QuitClosure()));
+ run_loop.Run();
+ ASSERT_EQ(devices_.size(), 1u);
+
+ int video_session_id = vcm_->Open(devices_.front());
+ VideoCaptureControllerID client_id = StartClient(video_session_id, true);
+
+ // Pretend screen is locked, which should close the device.
+ screenlock_monitor_source_->GenerateScreenLockedEvent();
+ Mock::VerifyAndClearExpectations(listener_.get());
+
+ StopClient(client_id);
+
+ // Wait to check callbacks before removing the listener.
+ base::RunLoop().RunUntilIdle();
+ vcm_->UnregisterListener(listener_.get());
+}
+#endif // ENABLE_SCREEN_CAPTURE && !OS_ANDROID
+
// TODO(mcasas): Add a test to check consolidation of the supported formats
// provided by the device when http://crbug.com/323913 is closed.
diff --git a/chromium/content/browser/renderer_host/overscroll_controller.cc b/chromium/content/browser/renderer_host/overscroll_controller.cc
index 73c7bbe0e26..23c45860f8f 100644
--- a/chromium/content/browser/renderer_host/overscroll_controller.cc
+++ b/chromium/content/browser/renderer_host/overscroll_controller.cc
@@ -29,6 +29,10 @@ bool IsGestureEventFromTouchpad(const blink::WebInputEvent& event) {
return gesture.SourceDevice() == blink::kWebGestureDeviceTouchpad;
}
+bool IsGestureEventFromAutoscroll(const blink::WebGestureEvent event) {
+ return event.SourceDevice() == blink::kWebGestureDeviceSyntheticAutoscroll;
+}
+
bool IsGestureScrollUpdateInertialEvent(const blink::WebInputEvent& event) {
if (event.GetType() != blink::WebInputEvent::kGestureScrollUpdate)
return false;
@@ -68,6 +72,10 @@ bool OverscrollController::ShouldProcessEvent(
event.GetType() != blink::WebInputEvent::kGestureScrollUpdate)
return false;
+ // Gesture events with Autoscroll source don't cause overscrolling.
+ if (IsGestureEventFromAutoscroll(gesture))
+ return false;
+
blink::WebGestureEvent::ScrollUnits scrollUnits;
switch (event.GetType()) {
case blink::WebInputEvent::kGestureScrollBegin:
@@ -523,6 +531,8 @@ bool OverscrollController::ProcessOverscroll(float delta_x,
if (overscroll_mode_ == OVERSCROLL_NONE)
return false;
+ overscroll_ignored_ = false;
+
// Tell the delegate about the overscroll update so that it can update
// the display accordingly (e.g. show history preview etc.).
if (delegate_) {
diff --git a/chromium/content/browser/renderer_host/overscroll_controller_unittest.cc b/chromium/content/browser/renderer_host/overscroll_controller_unittest.cc
index 166d1fe359d..fc980f1cebd 100644
--- a/chromium/content/browser/renderer_host/overscroll_controller_unittest.cc
+++ b/chromium/content/browser/renderer_host/overscroll_controller_unittest.cc
@@ -496,11 +496,18 @@ TEST_F(OverscrollControllerTest, DisableTouchpadOverscrollHistoryNavigation) {
}
// 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) {
+// scroll, it does not trigger pull-to-refresh. Verifies following sequence of
+// scrolls:
+// 1) Page scroll;
+// 2) Scroll before cool off -> PTR not triggered;
+// 3) Scroll before cool off -> PTR not triggered;
+// 4) Scroll after cool off -> PTR triggered;
+// 5) Scroll before cool off -> PTR triggered.
+TEST_F(OverscrollControllerTest, PullToRefreshBeforeCoolOff) {
ScopedPullToRefreshMode scoped_mode(
OverscrollConfig::PullToRefreshMode::kEnabled);
+ // 1) Page scroll.
base::TimeTicks timestamp =
blink::WebInputEvent::GetStaticTimeStampForTests();
@@ -510,11 +517,42 @@ TEST_F(OverscrollControllerTest, PullToRefreshCoolOff) {
SimulateAck(false);
// Simulate a touchscreen gesture scroll-update event that passes the start
+ // threshold and ACK it as 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());
+
+ // 2) Scroll before cool off -> PTR not triggered.
+ timestamp += base::TimeDelta::FromMilliseconds(500);
+
+ 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);
+ SimulateAck(false);
EXPECT_EQ(OVERSCROLL_NONE, controller_mode());
EXPECT_EQ(OverscrollSource::NONE, controller_source());
EXPECT_EQ(OVERSCROLL_NONE, delegate()->current_mode());
@@ -533,9 +571,8 @@ TEST_F(OverscrollControllerTest, PullToRefreshCoolOff) {
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);
+ // 3) Scroll before cool off -> PTR not triggered.
+ timestamp += base::TimeDelta::FromMilliseconds(500);
EXPECT_FALSE(SimulateGestureEvent(blink::WebInputEvent::kGestureScrollBegin,
blink::kWebGestureDeviceTouchscreen,
@@ -565,6 +602,173 @@ TEST_F(OverscrollControllerTest, PullToRefreshCoolOff) {
EXPECT_EQ(OverscrollSource::NONE, controller_source());
EXPECT_EQ(OVERSCROLL_NONE, delegate()->current_mode());
EXPECT_EQ(OVERSCROLL_NONE, delegate()->completed_mode());
+
+ // 4) Scroll after cool off -> PTR triggered.
+ 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, 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 which will end pull-to-refresh,
+ // and ACK it as not processed. Pull-to-refresh should be aborted.
+ 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());
+
+ // 5) Scroll before cool off -> PTR triggered.
+ timestamp += base::TimeDelta::FromMilliseconds(500);
+
+ 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, 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 which will end pull-to-refresh,
+ // and ACK it as not processed. Pull-to-refresh should be aborted.
+ 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());
+}
+
+// Verifies that if an overscroll happens after cool off period after a page
+// scroll, it triggers pull-to-refresh. Verifies the following sequence of
+// scrolls:
+// 1) Page scroll;
+// 2) Scroll after cool off -> PTR triggered;
+// 3) Scroll before cool off -> PTR triggered;
+TEST_F(OverscrollControllerTest, PullToRefreshAfterCoolOff) {
+ ScopedPullToRefreshMode scoped_mode(
+ OverscrollConfig::PullToRefreshMode::kEnabled);
+
+ // 1) Page scroll.
+ 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 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());
+
+ // 2) Scroll after cool off -> PTR triggered.
+ 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, 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 which will end pull-to-refresh,
+ // and ACK it as not processed. Pull-to-refresh should be aborted.
+ 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());
+
+ // 3) Scroll before cool off -> PTR triggered.
+ timestamp += base::TimeDelta::FromMilliseconds(500);
+
+ 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, 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 which will end pull-to-refresh,
+ // and ACK it as not processed. Pull-to-refresh should be aborted.
+ 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_dispatcher_host.cc b/chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.cc
index ce859120f2e..6bd32e88e38 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.cc
+++ b/chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.cc
@@ -70,6 +70,9 @@ void P2PSocketDispatcherHost::BindRequest(
if (!rph)
return;
+ // In case the renderer was connected previously but the network process
+ // crashed.
+ binding_.Close();
network::mojom::P2PTrustedSocketManagerClientPtr
trusted_socket_manager_client;
binding_.Bind(mojo::MakeRequest(&trusted_socket_manager_client));
diff --git a/chromium/content/browser/renderer_host/pepper/browser_ppapi_host_impl.cc b/chromium/content/browser/renderer_host/pepper/browser_ppapi_host_impl.cc
index 09c612c70a1..f4bef214757 100644
--- a/chromium/content/browser/renderer_host/pepper/browser_ppapi_host_impl.cc
+++ b/chromium/content/browser/renderer_host/pepper/browser_ppapi_host_impl.cc
@@ -57,8 +57,7 @@ BrowserPpapiHostImpl::BrowserPpapiHostImpl(
plugin_path_(plugin_path),
profile_data_directory_(profile_data_directory),
in_process_(in_process),
- external_plugin_(external_plugin),
- ssl_context_helper_(new SSLContextHelper()) {
+ external_plugin_(external_plugin) {
message_filter_ = new HostMessageFilter(ppapi_host_.get(), this);
ppapi_host_->AddHostFactoryFilter(std::unique_ptr<ppapi::host::HostFactory>(
new ContentBrowserPepperHostFactory(this)));
diff --git a/chromium/content/browser/renderer_host/pepper/browser_ppapi_host_impl.h b/chromium/content/browser/renderer_host/pepper/browser_ppapi_host_impl.h
index 8aeaed49765..e892474cf59 100644
--- a/chromium/content/browser/renderer_host/pepper/browser_ppapi_host_impl.h
+++ b/chromium/content/browser/renderer_host/pepper/browser_ppapi_host_impl.h
@@ -18,7 +18,6 @@
#include "base/observer_list.h"
#include "base/process/process.h"
#include "content/browser/renderer_host/pepper/content_browser_pepper_host_factory.h"
-#include "content/browser/renderer_host/pepper/ssl_context_helper.h"
#include "content/common/content_export.h"
#include "content/common/pepper_renderer_instance_data.h"
#include "content/public/browser/browser_ppapi_host.h"
@@ -100,10 +99,6 @@ class CONTENT_EXPORT BrowserPpapiHostImpl : public BrowserPpapiHost {
return message_filter_;
}
- const scoped_refptr<SSLContextHelper>& ssl_context_helper() const {
- return ssl_context_helper_;
- }
-
private:
friend class BrowserPpapiHostTest;
@@ -153,8 +148,6 @@ class CONTENT_EXPORT BrowserPpapiHostImpl : public BrowserPpapiHost {
// BrowserPpapiHost::CreateExternalPluginProcess.
bool external_plugin_;
- scoped_refptr<SSLContextHelper> ssl_context_helper_;
-
// Tracks all PP_Instances in this plugin and associated data.
std::unordered_map<PP_Instance, std::unique_ptr<InstanceData>> instance_map_;
diff --git a/chromium/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.cc b/chromium/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.cc
index 782cd8b785b..69eb47a8259 100644
--- a/chromium/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.cc
+++ b/chromium/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.cc
@@ -246,12 +246,18 @@ std::unique_ptr<ppapi::host::ResourceHost>
ContentBrowserPepperHostFactory::CreateAcceptedTCPSocket(
PP_Instance instance,
ppapi::TCPSocketVersion version,
- std::unique_ptr<net::TCPSocket> socket) {
+ network::mojom::TCPConnectedSocketPtrInfo connected_socket,
+ network::mojom::SocketObserverRequest socket_observer_request,
+ mojo::ScopedDataPipeConsumerHandle receive_stream,
+ mojo::ScopedDataPipeProducerHandle send_stream) {
if (!CanCreateSocket())
return std::unique_ptr<ppapi::host::ResourceHost>();
- scoped_refptr<ppapi::host::ResourceMessageFilter> tcp_socket(
- new PepperTCPSocketMessageFilter(host_, instance, version,
- std::move(socket)));
+ scoped_refptr<PepperTCPSocketMessageFilter> tcp_socket(
+ base::MakeRefCounted<PepperTCPSocketMessageFilter>(
+ nullptr /* factory */, host_, instance, version));
+ tcp_socket->SetConnectedSocket(
+ std::move(connected_socket), std::move(socket_observer_request),
+ std::move(receive_stream), std::move(send_stream));
return std::unique_ptr<ppapi::host::ResourceHost>(
new ppapi::host::MessageFilterHost(host_->GetPpapiHost(), instance, 0,
tcp_socket));
diff --git a/chromium/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.h b/chromium/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.h
index d9b3a55c36a..4c755131198 100644
--- a/chromium/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.h
+++ b/chromium/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.h
@@ -10,10 +10,11 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "net/socket/tcp_socket.h"
+#include "mojo/public/cpp/system/data_pipe.h"
#include "ppapi/c/pp_resource.h"
#include "ppapi/host/host_factory.h"
#include "ppapi/shared_impl/ppb_tcp_socket_shared.h"
+#include "services/network/public/mojom/tcp_socket.mojom.h"
namespace ppapi {
class PpapiPermissions;
@@ -41,7 +42,10 @@ class ContentBrowserPepperHostFactory : public ppapi::host::HostFactory {
std::unique_ptr<ppapi::host::ResourceHost> CreateAcceptedTCPSocket(
PP_Instance instance,
ppapi::TCPSocketVersion version,
- std::unique_ptr<net::TCPSocket> socket);
+ network::mojom::TCPConnectedSocketPtrInfo connected_socket,
+ network::mojom::SocketObserverRequest socket_observer_request,
+ mojo::ScopedDataPipeConsumerHandle receive_stream,
+ mojo::ScopedDataPipeProducerHandle send_stream);
private:
std::unique_ptr<ppapi::host::ResourceHost> CreateNewTCPSocket(
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 14641886701..1e1b3bd810c 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
@@ -15,6 +15,7 @@
#include "content/browser/renderer_host/pepper/pepper_file_system_browser_host.h"
#include "content/browser/renderer_host/pepper/pepper_security_helper.h"
#include "content/common/view_messages.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/render_process_host.h"
@@ -203,26 +204,21 @@ int32_t PepperFileIOHost::OnHostMsgOpen(
if (!CanOpenFileSystemURLWithPepperFlags(
open_flags, render_process_id_, file_system_url_))
return PP_ERROR_NOACCESS;
- BrowserThread::PostTaskAndReplyWithResult(
- BrowserThread::UI,
- FROM_HERE,
+ base::PostTaskWithTraitsAndReplyWithResult(
+ FROM_HERE, {BrowserThread::UI},
base::Bind(&GetUIThreadStuffForInternalFileSystems, render_process_id_),
base::Bind(&PepperFileIOHost::GotUIThreadStuffForInternalFileSystems,
- AsWeakPtr(),
- context->MakeReplyMessageContext(),
+ AsWeakPtr(), context->MakeReplyMessageContext(),
platform_file_flags));
} else {
base::FilePath path = file_ref_host->GetExternalFilePath();
if (!CanOpenWithPepperFlags(open_flags, render_process_id_, path))
return PP_ERROR_NOACCESS;
- BrowserThread::PostTaskAndReplyWithResult(
- BrowserThread::UI,
- FROM_HERE,
+ base::PostTaskWithTraitsAndReplyWithResult(
+ FROM_HERE, {BrowserThread::UI},
base::Bind(&GetResolvedRenderProcessId, render_process_id_),
- base::Bind(&PepperFileIOHost::GotResolvedRenderProcessId,
- AsWeakPtr(),
- context->MakeReplyMessageContext(),
- path,
+ base::Bind(&PepperFileIOHost::GotResolvedRenderProcessId, AsWeakPtr(),
+ context->MakeReplyMessageContext(), path,
platform_file_flags));
}
state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
@@ -399,15 +395,12 @@ int32_t PepperFileIOHost::OnHostMsgRequestOSFileHandle(
GURL document_url =
browser_ppapi_host_->GetDocumentURLForInstance(pp_instance());
- BrowserThread::PostTaskAndReplyWithResult(
- BrowserThread::UI,
- FROM_HERE,
- base::Bind(&GetPluginAllowedToCallRequestOSFileHandle,
- render_process_id_,
+ base::PostTaskWithTraitsAndReplyWithResult(
+ FROM_HERE, {BrowserThread::UI},
+ base::Bind(&GetPluginAllowedToCallRequestOSFileHandle, render_process_id_,
document_url),
base::Bind(&PepperFileIOHost::GotPluginAllowedToCallRequestOSFileHandle,
- AsWeakPtr(),
- context->MakeReplyMessageContext()));
+ AsWeakPtr(), context->MakeReplyMessageContext()));
return PP_OK_COMPLETIONPENDING;
}
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_file_system_browser_host.cc b/chromium/content/browser/renderer_host/pepper/pepper_file_system_browser_host.cc
index ca2abd58bb4..a53e31554a8 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_file_system_browser_host.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_file_system_browser_host.cc
@@ -6,10 +6,12 @@
#include "base/bind.h"
#include "base/callback.h"
+#include "base/task/post_task.h"
#include "content/browser/renderer_host/pepper/pepper_file_io_host.h"
#include "content/browser/renderer_host/pepper/quota_reservation.h"
#include "content/common/pepper_file_util.h"
#include "content/public/browser/browser_ppapi_host.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/plugin_service.h"
#include "content/public/browser/render_process_host.h"
@@ -89,13 +91,11 @@ void PepperFileSystemBrowserHost::OpenExisting(const GURL& root_url,
called_open_ = true;
// Get the file system context asynchronously, and then complete the Open
// operation by calling |callback|.
- BrowserThread::PostTaskAndReplyWithResult(
- BrowserThread::UI,
- FROM_HERE,
+ base::PostTaskWithTraitsAndReplyWithResult(
+ FROM_HERE, {BrowserThread::UI},
base::Bind(&GetFileSystemContextFromRenderId, render_process_id),
base::Bind(&PepperFileSystemBrowserHost::OpenExistingFileSystem,
- weak_factory_.GetWeakPtr(),
- callback));
+ weak_factory_.GetWeakPtr(), callback));
}
int32_t PepperFileSystemBrowserHost::OnResourceMessageReceived(
@@ -137,7 +137,7 @@ void PepperFileSystemBrowserHost::CloseQuotaFile(
PepperFileIOHost* file_io_host,
const ppapi::FileGrowth& file_growth) {
int32_t id = file_io_host->pp_resource();
- FileMap::iterator it = files_.find(id);
+ auto it = files_.find(id);
if (it != files_.end()) {
files_.erase(it);
} else {
@@ -173,13 +173,11 @@ int32_t PepperFileSystemBrowserHost::OnHostMsgOpen(
return PP_ERROR_FAILED;
}
- BrowserThread::PostTaskAndReplyWithResult(
- BrowserThread::UI,
- FROM_HERE,
+ base::PostTaskWithTraitsAndReplyWithResult(
+ FROM_HERE, {BrowserThread::UI},
base::Bind(&GetFileSystemContextFromRenderId, render_process_id),
base::Bind(&PepperFileSystemBrowserHost::OpenFileSystem,
- weak_factory_.GetWeakPtr(),
- context->MakeReplyMessageContext(),
+ weak_factory_.GetWeakPtr(), context->MakeReplyMessageContext(),
file_system_type));
return PP_OK_COMPLETIONPENDING;
}
@@ -341,15 +339,12 @@ int32_t PepperFileSystemBrowserHost::OnHostMsgInitIsolatedFileSystem(
fsid,
ppapi::IsolatedFileSystemTypeToRootName(type)));
- BrowserThread::PostTaskAndReplyWithResult(
- BrowserThread::UI,
- FROM_HERE,
+ base::PostTaskWithTraitsAndReplyWithResult(
+ FROM_HERE, {BrowserThread::UI},
base::Bind(&GetFileSystemContextFromRenderId, render_process_id),
base::Bind(&PepperFileSystemBrowserHost::OpenIsolatedFileSystem,
- weak_factory_.GetWeakPtr(),
- context->MakeReplyMessageContext(),
- fsid,
- type));
+ weak_factory_.GetWeakPtr(), context->MakeReplyMessageContext(),
+ fsid, type));
return PP_OK_COMPLETIONPENDING;
}
@@ -417,7 +412,7 @@ bool PepperFileSystemBrowserHost::ShouldCreateQuotaReservation() const {
storage::FileSystemType file_system_type =
PepperFileSystemTypeToFileSystemType(type_);
return !quota_manager_proxy->quota_manager()->IsStorageUnlimited(
- root_url_.GetOrigin(),
+ url::Origin::Create(root_url_),
storage::FileSystemTypeToQuotaStorageType(file_system_type));
}
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_host_resolver_message_filter.cc b/chromium/content/browser/renderer_host/pepper/pepper_host_resolver_message_filter.cc
index d1cbc98e979..ca3fcf25f9d 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_host_resolver_message_filter.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_host_resolver_message_filter.cc
@@ -9,9 +9,11 @@
#include <memory>
#include "base/logging.h"
+#include "base/task/post_task.h"
#include "content/browser/renderer_host/pepper/browser_ppapi_host_impl.h"
#include "content/browser/renderer_host/pepper/pepper_socket_utils.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/storage_partition.h"
@@ -96,7 +98,7 @@ scoped_refptr<base::TaskRunner>
PepperHostResolverMessageFilter::OverrideTaskRunnerForMessage(
const IPC::Message& message) {
if (message.type() == PpapiHostMsg_HostResolver_Resolve::ID)
- return BrowserThread::GetTaskRunnerForThread(BrowserThread::UI);
+ return base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::UI});
return nullptr;
}
@@ -163,8 +165,8 @@ void PepperHostResolverMessageFilter::OnComplete(
DCHECK_CURRENTLY_ON(BrowserThread::UI);
binding_.Close();
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&PepperHostResolverMessageFilter::OnLookupFinished, this,
result, std::move(resolved_addresses),
host_resolve_context_));
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_network_monitor_host.cc b/chromium/content/browser/renderer_host/pepper/pepper_network_monitor_host.cc
index 9f0fc648abf..9023d5b8490 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_network_monitor_host.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_network_monitor_host.cc
@@ -10,7 +10,9 @@
#include "base/task_runner_util.h"
#include "content/browser/renderer_host/pepper/browser_ppapi_host_impl.h"
#include "content/browser/renderer_host/pepper/pepper_socket_utils.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/network_service_instance.h"
#include "content/public/common/socket_permission_request.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/shared_impl/private/net_address_private_impl.h"
@@ -46,30 +48,32 @@ PepperNetworkMonitorHost::PepperNetworkMonitorHost(BrowserPpapiHostImpl* host,
PP_Instance instance,
PP_Resource resource)
: ResourceHost(host->GetPpapiHost(), instance, resource),
+ network_connection_tracker_(nullptr),
weak_factory_(this) {
int render_process_id;
int render_frame_id;
host->GetRenderFrameIDsForInstance(
instance, &render_process_id, &render_frame_id);
- BrowserThread::PostTaskAndReplyWithResult(
- BrowserThread::UI,
- FROM_HERE,
- base::Bind(&CanUseNetworkMonitor,
- host->external_plugin(),
- render_process_id,
- render_frame_id),
+ base::PostTaskWithTraitsAndReplyWithResult(
+ FROM_HERE, {BrowserThread::UI},
+ base::Bind(&CanUseNetworkMonitor, host->external_plugin(),
+ render_process_id, render_frame_id),
base::Bind(&PepperNetworkMonitorHost::OnPermissionCheckResult,
weak_factory_.GetWeakPtr()));
}
PepperNetworkMonitorHost::~PepperNetworkMonitorHost() {
- net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
+ if (network_connection_tracker_)
+ network_connection_tracker_->RemoveNetworkConnectionObserver(this);
}
-void PepperNetworkMonitorHost::OnNetworkChanged(
- net::NetworkChangeNotifier::ConnectionType type) {
- if (type == net::NetworkChangeNotifier::GetConnectionType())
+void PepperNetworkMonitorHost::OnConnectionChanged(
+ network::mojom::ConnectionType type) {
+ auto current_type = network::mojom::ConnectionType::CONNECTION_UNKNOWN;
+ network_connection_tracker_->GetConnectionType(&current_type,
+ base::DoNothing());
+ if (type == current_type)
GetAndSendNetworkList();
}
@@ -81,10 +85,21 @@ void PepperNetworkMonitorHost::OnPermissionCheckResult(
return;
}
- net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
+ base::PostTaskWithTraitsAndReplyWithResult(
+ FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(&content::GetNetworkConnectionTracker),
+ base::BindOnce(&PepperNetworkMonitorHost::SetNetworkConnectionTracker,
+ weak_factory_.GetWeakPtr()));
GetAndSendNetworkList();
}
+void PepperNetworkMonitorHost::SetNetworkConnectionTracker(
+ network::NetworkConnectionTracker* network_connection_tracker) {
+ DCHECK_EQ(network_connection_tracker_, nullptr);
+ network_connection_tracker_ = network_connection_tracker;
+ network_connection_tracker_->AddNetworkConnectionObserver(this);
+}
+
void PepperNetworkMonitorHost::GetAndSendNetworkList() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_network_monitor_host.h b/chromium/content/browser/renderer_host/pepper/pepper_network_monitor_host.h
index 5e61b20fe27..6cf89098900 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_network_monitor_host.h
+++ b/chromium/content/browser/renderer_host/pepper/pepper_network_monitor_host.h
@@ -9,10 +9,10 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "content/common/content_export.h"
-#include "net/base/network_change_notifier.h"
#include "net/base/network_interfaces.h"
#include "ppapi/host/host_message_context.h"
#include "ppapi/host/resource_host.h"
+#include "services/network/public/cpp/network_connection_tracker.h"
namespace content {
@@ -21,7 +21,7 @@ class BrowserPpapiHostImpl;
// The host for PPB_NetworkMonitor. This class lives on the IO thread.
class CONTENT_EXPORT PepperNetworkMonitorHost
: public ppapi::host::ResourceHost,
- public net::NetworkChangeNotifier::NetworkChangeObserver {
+ public network::NetworkConnectionTracker::NetworkConnectionObserver {
public:
PepperNetworkMonitorHost(BrowserPpapiHostImpl* host,
PP_Instance instance,
@@ -29,18 +29,21 @@ class CONTENT_EXPORT PepperNetworkMonitorHost
~PepperNetworkMonitorHost() override;
- // net::NetworkChangeNotifier::NetworkChangeObserver interface.
- void OnNetworkChanged(
- net::NetworkChangeNotifier::ConnectionType type) override;
+ // network::NetworkConnectionTracker::NetworkConnectionObserver interface.
+ void OnConnectionChanged(network::mojom::ConnectionType type) override;
private:
void OnPermissionCheckResult(bool can_use_network_monitor);
+ void SetNetworkConnectionTracker(
+ network::NetworkConnectionTracker* network_connection_tracker);
void GetAndSendNetworkList();
void SendNetworkList(std::unique_ptr<net::NetworkInterfaceList> list);
ppapi::host::ReplyMessageContext reply_context_;
+ network::NetworkConnectionTracker* network_connection_tracker_;
+
base::WeakPtrFactory<PepperNetworkMonitorHost> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(PepperNetworkMonitorHost);
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_network_proxy_host.cc b/chromium/content/browser/renderer_host/pepper/pepper_network_proxy_host.cc
index 75774080312..e7a74ba592d 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_network_proxy_host.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_network_proxy_host.cc
@@ -5,10 +5,12 @@
#include "content/browser/renderer_host/pepper/pepper_network_proxy_host.h"
#include "base/bind.h"
+#include "base/task/post_task.h"
#include "content/browser/renderer_host/pepper/browser_ppapi_host_impl.h"
#include "content/browser/renderer_host/pepper/pepper_proxy_lookup_helper.h"
#include "content/browser/renderer_host/pepper/pepper_socket_utils.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
@@ -59,8 +61,8 @@ PepperNetworkProxyHost::PepperNetworkProxyHost(BrowserPpapiHostImpl* host,
weak_factory_(this) {
host->GetRenderFrameIDsForInstance(instance, &render_process_id_,
&render_frame_id_);
- BrowserThread::PostTaskAndReplyWithResult(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraitsAndReplyWithResult(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&GetUIThreadDataOnUIThread, render_process_id_,
render_frame_id_, host->external_plugin()),
base::BindOnce(&PepperNetworkProxyHost::DidGetUIThreadData,
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_print_settings_manager.cc b/chromium/content/browser/renderer_host/pepper/pepper_print_settings_manager.cc
index 0a3c9da3d24..54c4e339a43 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_print_settings_manager.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_print_settings_manager.cc
@@ -4,6 +4,8 @@
#include "content/browser/renderer_host/pepper/pepper_print_settings_manager.h"
+#include "base/task/post_task.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/common/content_client.h"
@@ -111,8 +113,8 @@ PepperPrintSettingsManager::Result ComputeDefaultPrintSettings() {
void PepperPrintSettingsManagerImpl::GetDefaultPrintSettings(
PepperPrintSettingsManager::Callback callback) {
- BrowserThread::PostTaskAndReplyWithResult(
- BrowserThread::UI, FROM_HERE, base::Bind(ComputeDefaultPrintSettings),
+ base::PostTaskWithTraitsAndReplyWithResult(
+ FROM_HERE, {BrowserThread::UI}, base::Bind(ComputeDefaultPrintSettings),
std::move(callback));
}
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_proxy_lookup_helper.cc b/chromium/content/browser/renderer_host/pepper/pepper_proxy_lookup_helper.cc
index 95928393273..5861950d2bf 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_proxy_lookup_helper.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_proxy_lookup_helper.cc
@@ -9,7 +9,9 @@
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/sequenced_task_runner.h"
+#include "base/task/post_task.h"
#include "base/threading/sequenced_task_runner_handle.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/bindings/interface_request.h"
@@ -29,8 +31,8 @@ class PepperProxyLookupHelper::UIThreadHelper
: binding_(this),
look_up_complete_callback_(std::move(look_up_complete_callback)),
callback_task_runner_(base::SequencedTaskRunnerHandle::Get()) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&UIThreadHelper::StartLookup, base::Unretained(this),
url, std::move(look_up_proxy_for_url_callback)));
}
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_proxy_lookup_helper_unittest.cc b/chromium/content/browser/renderer_host/pepper/pepper_proxy_lookup_helper_unittest.cc
index 25f87fdcad3..76619fea2b7 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_proxy_lookup_helper_unittest.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_proxy_lookup_helper_unittest.cc
@@ -14,6 +14,8 @@
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "base/run_loop.h"
+#include "base/task/post_task.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "net/proxy_resolution/proxy_info.h"
@@ -37,8 +39,8 @@ class PepperProxyLookupHelperTest : public testing::Test {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
base::RunLoop run_loop;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&PepperProxyLookupHelperTest::StartLookupOnIOThread,
base::Unretained(this), run_loop.QuitClosure()));
run_loop.Run();
@@ -60,8 +62,8 @@ class PepperProxyLookupHelperTest : public testing::Test {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
base::RunLoop run_loop;
- BrowserThread::PostTaskAndReply(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraitsAndReply(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&PepperProxyLookupHelperTest::DestroyLookupHelperOnIOThread,
base::Unretained(this)),
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.cc b/chromium/content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.cc
index 429d3d217da..f0aadfcb9d3 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.cc
@@ -10,18 +10,23 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/logging.h"
+#include "base/task/post_task.h"
#include "build/build_config.h"
#include "content/browser/renderer_host/pepper/browser_ppapi_host_impl.h"
#include "content/browser/renderer_host/pepper/content_browser_pepper_host_factory.h"
#include "content/browser/renderer_host/pepper/pepper_socket_utils.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/storage_partition.h"
#include "content/public/common/socket_permission_request.h"
+#include "mojo/public/cpp/bindings/callback_helpers.h"
+#include "mojo/public/cpp/bindings/interface_request.h"
#include "net/base/ip_address.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
-#include "net/log/net_log_source.h"
+#include "net/traffic_annotation/network_traffic_annotation.h"
#include "ppapi/c/pp_errors.h"
-#include "ppapi/c/private/ppb_net_address_private.h"
#include "ppapi/host/dispatch_host_message.h"
#include "ppapi/host/error_conversion.h"
#include "ppapi/host/ppapi_host.h"
@@ -30,6 +35,7 @@
#include "ppapi/shared_impl/api_id.h"
#include "ppapi/shared_impl/ppb_tcp_socket_shared.h"
#include "ppapi/shared_impl/private/net_address_private_impl.h"
+#include "services/network/public/mojom/network_context.mojom.h"
#if defined(OS_CHROMEOS)
#include "chromeos/network/firewall_hole.h"
@@ -40,12 +46,15 @@ using ppapi::host::NetErrorToPepperError;
namespace {
-size_t g_num_instances = 0;
+static size_t g_num_instances = 0;
} // namespace
namespace content {
+network::mojom::NetworkContext*
+ PepperTCPServerSocketMessageFilter::network_context_for_testing = nullptr;
+
PepperTCPServerSocketMessageFilter::PepperTCPServerSocketMessageFilter(
ContentBrowserPepperHostFactory* factory,
BrowserPpapiHostImpl* host,
@@ -55,10 +64,12 @@ PepperTCPServerSocketMessageFilter::PepperTCPServerSocketMessageFilter(
factory_(factory),
instance_(instance),
state_(STATE_BEFORE_LISTENING),
+ bound_addr_(NetAddressPrivateImpl::kInvalidNetAddress),
external_plugin_(host->external_plugin()),
private_api_(private_api),
render_process_id_(0),
- render_frame_id_(0) {
+ render_frame_id_(0),
+ weak_ptr_factory_(this) {
++g_num_instances;
DCHECK(factory_);
DCHECK(ppapi_host_);
@@ -73,19 +84,35 @@ PepperTCPServerSocketMessageFilter::~PepperTCPServerSocketMessageFilter() {
}
// static
+void PepperTCPServerSocketMessageFilter::SetNetworkContextForTesting(
+ network::mojom::NetworkContext* network_context) {
+ network_context_for_testing = network_context;
+}
+
+// static
size_t PepperTCPServerSocketMessageFilter::GetNumInstances() {
return g_num_instances;
}
+void PepperTCPServerSocketMessageFilter::OnFilterDestroyed() {
+ ResourceMessageFilter::OnFilterDestroyed();
+ // Need to close all mojo pipes the socket on the UI thread. Calling Close()
+ // also ensures that future messages will be ignored, so the mojo pipes won't
+ // be re-created, so after Close() runs, |this| can be safely deleted on the
+ // IO thread.
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(&PepperTCPServerSocketMessageFilter::Close, this));
+}
+
scoped_refptr<base::TaskRunner>
PepperTCPServerSocketMessageFilter::OverrideTaskRunnerForMessage(
const IPC::Message& message) {
switch (message.type()) {
case PpapiHostMsg_TCPServerSocket_Listen::ID:
- return BrowserThread::GetTaskRunnerForThread(BrowserThread::UI);
case PpapiHostMsg_TCPServerSocket_Accept::ID:
case PpapiHostMsg_TCPServerSocket_StopListening::ID:
- return BrowserThread::GetTaskRunnerForThread(BrowserThread::IO);
+ return base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::UI});
}
return nullptr;
}
@@ -122,16 +149,45 @@ int32_t PepperTCPServerSocketMessageFilter::OnMsgListen(
return PP_ERROR_NOACCESS;
}
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&PepperTCPServerSocketMessageFilter::DoListen, this,
- context->MakeReplyMessageContext(), addr, backlog));
+ net::IPAddressBytes address;
+ uint16_t port;
+
+ if (state_ != STATE_BEFORE_LISTENING ||
+ !NetAddressPrivateImpl::NetAddressToIPEndPoint(addr, &address, &port)) {
+ Close();
+ return PP_ERROR_FAILED;
+ }
+
+ network::mojom::NetworkContext* network_context = network_context_for_testing;
+ if (!network_context) {
+ RenderProcessHost* render_process_host =
+ RenderProcessHost::FromID(render_process_id_);
+ network_context =
+ render_process_host->GetStoragePartition()->GetNetworkContext();
+ if (!network_context)
+ return PP_ERROR_FAILED;
+ }
+
+ state_ = STATE_LISTEN_IN_PROGRESS;
+
+ ppapi::host::ReplyMessageContext reply_context =
+ context->MakeReplyMessageContext();
+
+ network_context->CreateTCPServerSocket(
+ net::IPEndPoint(net::IPAddress(address), port), backlog,
+ pepper_socket_utils::PepperTCPNetworkAnnotationTag(),
+ mojo::MakeRequest(&socket_),
+ mojo::WrapCallbackWithDefaultInvokeIfNotRun(
+ base::BindOnce(&PepperTCPServerSocketMessageFilter::OnListenCompleted,
+ weak_ptr_factory_.GetWeakPtr(), reply_context),
+ net::ERR_FAILED, base::nullopt /* local_addr_out */));
+
return PP_OK_COMPLETIONPENDING;
}
int32_t PepperTCPServerSocketMessageFilter::OnMsgAccept(
const ppapi::host::HostMessageContext* context) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(context);
if (state_ != STATE_LISTENING)
@@ -140,190 +196,193 @@ int32_t PepperTCPServerSocketMessageFilter::OnMsgAccept(
state_ = STATE_ACCEPT_IN_PROGRESS;
ppapi::host::ReplyMessageContext reply_context(
context->MakeReplyMessageContext());
- int net_result = socket_->Accept(
- &accepted_socket_, &accepted_address_,
- base::Bind(&PepperTCPServerSocketMessageFilter::OnAcceptCompleted,
- base::Unretained(this), reply_context));
- if (net_result != net::ERR_IO_PENDING)
- OnAcceptCompleted(reply_context, net_result);
+
+ network::mojom::SocketObserverPtr socket_observer;
+ network::mojom::SocketObserverRequest socket_observer_request =
+ mojo::MakeRequest(&socket_observer);
+ socket_->Accept(
+ std::move(socket_observer),
+ mojo::WrapCallbackWithDefaultInvokeIfNotRun(
+ base::BindOnce(&PepperTCPServerSocketMessageFilter::OnAcceptCompleted,
+ base::Unretained(this), reply_context,
+ std::move(socket_observer_request)),
+ net::ERR_FAILED, base::nullopt /* remote_addr */,
+ network::mojom::TCPConnectedSocketPtr(),
+ mojo::ScopedDataPipeConsumerHandle(),
+ mojo::ScopedDataPipeProducerHandle()));
return PP_OK_COMPLETIONPENDING;
}
int32_t PepperTCPServerSocketMessageFilter::OnMsgStopListening(
const ppapi::host::HostMessageContext* context) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(context);
- state_ = STATE_CLOSED;
- socket_.reset();
-#if defined(OS_CHROMEOS)
- firewall_hole_.reset();
-#endif // defined(OS_CHROMEOS)
+ Close();
return PP_OK;
}
-void PepperTCPServerSocketMessageFilter::DoListen(
+void PepperTCPServerSocketMessageFilter::OnListenCompleted(
const ppapi::host::ReplyMessageContext& context,
- const PP_NetAddress_Private& addr,
- int32_t backlog) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ int net_result,
+ const base::Optional<net::IPEndPoint>& local_addr) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
- net::IPAddressBytes address;
- uint16_t port;
- if (state_ != STATE_BEFORE_LISTENING ||
- !NetAddressPrivateImpl::NetAddressToIPEndPoint(addr, &address, &port)) {
+ // Exit early if this is called during Close().
+ if (state_ == STATE_CLOSED) {
+ DCHECK_EQ(net::ERR_FAILED, net_result);
SendListenError(context, PP_ERROR_FAILED);
- state_ = STATE_CLOSED;
return;
}
- state_ = STATE_LISTEN_IN_PROGRESS;
-
- socket_.reset(new net::TCPSocket(nullptr, nullptr, net::NetLogSource()));
- int net_result = net::OK;
- do {
- net::IPEndPoint ip_end_point(net::IPAddress(address), port);
- net_result = socket_->Open(ip_end_point.GetFamily());
- if (net_result != net::OK)
- break;
- net_result = socket_->SetDefaultOptionsForServer();
- if (net_result != net::OK)
- break;
- net_result = socket_->Bind(ip_end_point);
- if (net_result != net::OK)
- break;
- net_result = socket_->Listen(backlog);
- } while (false);
-
- if (net_result != net::ERR_IO_PENDING) {
-#if defined(OS_CHROMEOS)
- OpenFirewallHole(context, net_result);
-#else
- OnListenCompleted(context, net_result);
-#endif
- }
-}
+ DCHECK(socket_.is_bound());
+ DCHECK_EQ(state_, STATE_LISTEN_IN_PROGRESS);
-void PepperTCPServerSocketMessageFilter::OnListenCompleted(
- const ppapi::host::ReplyMessageContext& context,
- int net_result) {
- if (state_ != STATE_LISTEN_IN_PROGRESS) {
- SendListenError(context, PP_ERROR_FAILED);
- state_ = STATE_CLOSED;
- return;
- }
if (net_result != net::OK) {
SendListenError(context, NetErrorToPepperError(net_result));
+ socket_.reset();
state_ = STATE_BEFORE_LISTENING;
return;
}
- DCHECK(socket_.get());
-
- net::IPEndPoint end_point;
- PP_NetAddress_Private addr;
-
- int32_t pp_result =
- NetErrorToPepperError(socket_->GetLocalAddress(&end_point));
- if (pp_result != PP_OK) {
- SendListenError(context, pp_result);
- state_ = STATE_BEFORE_LISTENING;
- return;
- }
- if (!NetAddressPrivateImpl::IPEndPointToNetAddress(
- end_point.address().bytes(), end_point.port(), &addr)) {
+ if (!local_addr ||
+ !NetAddressPrivateImpl::IPEndPointToNetAddress(
+ local_addr->address().bytes(), local_addr->port(), &bound_addr_)) {
SendListenError(context, PP_ERROR_FAILED);
+ socket_.reset();
state_ = STATE_BEFORE_LISTENING;
return;
}
- SendListenReply(context, PP_OK, addr);
+#if defined(OS_CHROMEOS)
+ OpenFirewallHole(context, *local_addr);
+#else
+ SendListenReply(context, PP_OK, bound_addr_);
state_ = STATE_LISTENING;
+#endif
}
#if defined(OS_CHROMEOS)
void PepperTCPServerSocketMessageFilter::OpenFirewallHole(
const ppapi::host::ReplyMessageContext& context,
- int net_result) {
- if (net_result != net::OK) {
- return;
- }
- net::IPEndPoint local_addr;
- socket_->GetLocalAddress(&local_addr);
- pepper_socket_utils::FirewallHoleOpenCallback callback =
- base::Bind(&PepperTCPServerSocketMessageFilter::OnFirewallHoleOpened,
- this, context, net_result);
+ const net::IPEndPoint& local_addr) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ pepper_socket_utils::FirewallHoleOpenCallback callback = base::BindRepeating(
+ &PepperTCPServerSocketMessageFilter::OnFirewallHoleOpened, this, context);
pepper_socket_utils::OpenTCPFirewallHole(local_addr, callback);
}
void PepperTCPServerSocketMessageFilter::OnFirewallHoleOpened(
const ppapi::host::ReplyMessageContext& context,
- int32_t net_result,
std::unique_ptr<chromeos::FirewallHole> hole) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
LOG_IF(WARNING, !hole.get()) << "Firewall hole could not be opened.";
firewall_hole_.reset(hole.release());
- OnListenCompleted(context, net_result);
+
+ SendListenReply(context, PP_OK, bound_addr_);
+ state_ = STATE_LISTENING;
}
#endif // defined(OS_CHROMEOS)
void PepperTCPServerSocketMessageFilter::OnAcceptCompleted(
const ppapi::host::ReplyMessageContext& context,
- int net_result) {
- if (state_ != STATE_ACCEPT_IN_PROGRESS) {
- SendAcceptError(context, PP_ERROR_FAILED);
- state_ = STATE_CLOSED;
+ network::mojom::SocketObserverRequest socket_observer_request,
+ int net_result,
+ const base::Optional<net::IPEndPoint>& remote_addr,
+ network::mojom::TCPConnectedSocketPtr connected_socket,
+ mojo::ScopedDataPipeConsumerHandle receive_stream,
+ mojo::ScopedDataPipeProducerHandle send_stream) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ // Exit early if this is called during Close().
+ if (state_ == STATE_CLOSED) {
+ DCHECK_EQ(net::ERR_FAILED, net_result);
+ SendListenError(context, PP_ERROR_FAILED);
return;
}
- state_ = STATE_LISTENING;
+ DCHECK_EQ(state_, STATE_ACCEPT_IN_PROGRESS);
+ state_ = STATE_LISTENING;
if (net_result != net::OK) {
SendAcceptError(context, NetErrorToPepperError(net_result));
return;
}
- DCHECK(accepted_socket_.get());
-
- net::IPEndPoint ip_end_point_local;
- PP_NetAddress_Private local_addr = NetAddressPrivateImpl::kInvalidNetAddress;
- PP_NetAddress_Private remote_addr = NetAddressPrivateImpl::kInvalidNetAddress;
-
- int32_t pp_result = NetErrorToPepperError(
- accepted_socket_->GetLocalAddress(&ip_end_point_local));
- if (pp_result != PP_OK) {
- SendAcceptError(context, pp_result);
+ if (!remote_addr || !connected_socket.is_bound()) {
+ SendAcceptError(context, NetErrorToPepperError(net_result));
return;
}
+
+ DCHECK(socket_observer_request.is_pending());
+
+ PP_NetAddress_Private pp_remote_addr =
+ NetAddressPrivateImpl::kInvalidNetAddress;
+
if (!NetAddressPrivateImpl::IPEndPointToNetAddress(
- ip_end_point_local.address().bytes(), ip_end_point_local.port(),
- &local_addr) ||
- !NetAddressPrivateImpl::IPEndPointToNetAddress(
- accepted_address_.address().bytes(), accepted_address_.port(),
- &remote_addr)) {
- SendAcceptError(context, PP_ERROR_FAILED);
+ remote_addr->address().bytes(), remote_addr->port(),
+ &pp_remote_addr)) {
+ SendAcceptError(context, PP_ERROR_ADDRESS_INVALID);
return;
}
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(
+ &PepperTCPServerSocketMessageFilter::OnAcceptCompletedOnIOThread,
+ this, context, connected_socket.PassInterface(),
+ std::move(socket_observer_request), std::move(receive_stream),
+ std::move(send_stream), bound_addr_, pp_remote_addr));
+}
+
+void PepperTCPServerSocketMessageFilter::OnAcceptCompletedOnIOThread(
+ const ppapi::host::ReplyMessageContext& context,
+ network::mojom::TCPConnectedSocketPtrInfo connected_socket,
+ network::mojom::SocketObserverRequest socket_observer_request,
+ mojo::ScopedDataPipeConsumerHandle receive_stream,
+ mojo::ScopedDataPipeProducerHandle send_stream,
+ PP_NetAddress_Private pp_local_addr,
+ PP_NetAddress_Private pp_remote_addr) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ // |factory_| is guaranteed to be non-NULL here. Only those instances created
+ // in CONNECTED state have a NULL |factory_|, while getting here requires
+ // LISTENING state.
std::unique_ptr<ppapi::host::ResourceHost> host =
- factory_->CreateAcceptedTCPSocket(instance_,
- ppapi::TCP_SOCKET_VERSION_PRIVATE,
- std::move(accepted_socket_));
+ factory_->CreateAcceptedTCPSocket(
+ instance_, ppapi::TCP_SOCKET_VERSION_PRIVATE,
+ std::move(connected_socket), std::move(socket_observer_request),
+ std::move(receive_stream), std::move(send_stream));
if (!host) {
SendAcceptError(context, PP_ERROR_NOSPACE);
return;
}
- int pending_resource_id =
- ppapi_host_->AddPendingResourceHost(std::move(host));
- if (pending_resource_id) {
- SendAcceptReply(
- context, PP_OK, pending_resource_id, local_addr, remote_addr);
+
+ int pending_host_id = ppapi_host_->AddPendingResourceHost(std::move(host));
+ if (pending_host_id) {
+ SendAcceptReply(context, PP_OK, pending_host_id, pp_local_addr,
+ pp_remote_addr);
} else {
SendAcceptError(context, PP_ERROR_NOSPACE);
}
}
+void PepperTCPServerSocketMessageFilter::Close() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ // Need to do these first, as destroying Mojo pipes may invoke some of the
+ // callbacks with failure messages.
+ weak_ptr_factory_.InvalidateWeakPtrs();
+ state_ = STATE_CLOSED;
+
+ socket_.reset();
+#if defined(OS_CHROMEOS)
+ firewall_hole_.reset();
+#endif // defined(OS_CHROMEOS)
+}
+
void PepperTCPServerSocketMessageFilter::SendListenReply(
const ppapi::host::ReplyMessageContext& context,
int32_t pp_result,
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.h b/chromium/content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.h
index 9c7be218c21..96456ab062c 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.h
+++ b/chromium/content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.h
@@ -13,20 +13,28 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "base/optional.h"
#include "build/build_config.h"
#include "content/common/content_export.h"
+#include "mojo/public/cpp/system/data_pipe.h"
#include "net/base/ip_endpoint.h"
-#include "net/socket/tcp_socket.h"
#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/private/ppb_net_address_private.h"
#include "ppapi/host/resource_message_filter.h"
-
-struct PP_NetAddress_Private;
+#include "services/network/public/mojom/tcp_socket.mojom.h"
#if defined(OS_CHROMEOS)
#include "chromeos/network/firewall_hole.h"
#include "content/public/browser/browser_thread.h"
#endif // defined(OS_CHROMEOS)
+namespace network {
+namespace mojom {
+class NetworkContext;
+}
+} // namespace network
+
namespace ppapi {
namespace host {
class PpapiHost;
@@ -48,6 +56,11 @@ class CONTENT_EXPORT PepperTCPServerSocketMessageFilter
PP_Instance instance,
bool private_api);
+ // Sets a global NetworkContext object to be used instead of the real one for
+ // doing all network operations.
+ static void SetNetworkContextForTesting(
+ network::mojom::NetworkContext* network_context);
+
static size_t GetNumInstances();
protected:
@@ -63,6 +76,7 @@ class CONTENT_EXPORT PepperTCPServerSocketMessageFilter
};
// ppapi::host::ResourceMessageFilter overrides.
+ void OnFilterDestroyed() override;
scoped_refptr<base::TaskRunner> OverrideTaskRunnerForMessage(
const IPC::Message& message) override;
int32_t OnResourceMessageReceived(
@@ -76,13 +90,31 @@ class CONTENT_EXPORT PepperTCPServerSocketMessageFilter
int32_t OnMsgStopListening(const ppapi::host::HostMessageContext* context);
void DoListen(const ppapi::host::ReplyMessageContext& context,
- const PP_NetAddress_Private& addr,
int32_t backlog);
void OnListenCompleted(const ppapi::host::ReplyMessageContext& context,
- int net_result);
- void OnAcceptCompleted(const ppapi::host::ReplyMessageContext& context,
- int net_result);
+ int net_result,
+ const base::Optional<net::IPEndPoint>& local_addr);
+ void OnAcceptCompleted(
+ const ppapi::host::ReplyMessageContext& context,
+ network::mojom::SocketObserverRequest socket_observer_request,
+ int net_result,
+ const base::Optional<net::IPEndPoint>& remote_addr,
+ network::mojom::TCPConnectedSocketPtr connected_socket,
+ mojo::ScopedDataPipeConsumerHandle receive_stream,
+ mojo::ScopedDataPipeProducerHandle send_stream);
+ void OnAcceptCompletedOnIOThread(
+ const ppapi::host::ReplyMessageContext& context,
+ network::mojom::TCPConnectedSocketPtrInfo connected_socket,
+ network::mojom::SocketObserverRequest socket_observer_request,
+ mojo::ScopedDataPipeConsumerHandle receive_stream,
+ mojo::ScopedDataPipeProducerHandle send_stream,
+ PP_NetAddress_Private pp_local_addr,
+ PP_NetAddress_Private pp_remote_addr);
+
+ // Closes the socket and FirewallHole, if they're open, and prevents
+ // |this| from being used further, even with a new socket.
+ void Close();
void SendListenReply(const ppapi::host::ReplyMessageContext& context,
int32_t pp_result,
@@ -99,9 +131,8 @@ class CONTENT_EXPORT PepperTCPServerSocketMessageFilter
#if defined(OS_CHROMEOS)
void OpenFirewallHole(const ppapi::host::ReplyMessageContext& context,
- int net_result);
+ const net::IPEndPoint& local_addr);
void OnFirewallHoleOpened(const ppapi::host::ReplyMessageContext& context,
- int32_t net_result,
std::unique_ptr<chromeos::FirewallHole> hole);
#endif // defined(OS_CHROMEOS)
@@ -113,9 +144,9 @@ class CONTENT_EXPORT PepperTCPServerSocketMessageFilter
PP_Instance instance_;
State state_;
- std::unique_ptr<net::TCPSocket> socket_;
- std::unique_ptr<net::TCPSocket> accepted_socket_;
- net::IPEndPoint accepted_address_;
+ network::mojom::TCPServerSocketPtr socket_;
+
+ PP_NetAddress_Private bound_addr_;
#if defined(OS_CHROMEOS)
std::unique_ptr<chromeos::FirewallHole,
@@ -130,6 +161,13 @@ class CONTENT_EXPORT PepperTCPServerSocketMessageFilter
int render_process_id_;
int render_frame_id_;
+ // Used in place of the StoragePartition's NetworkContext when non-null.
+ static network::mojom::NetworkContext* network_context_for_testing;
+
+ // Vends weak pointers on the UI thread, for callbacks passed through Mojo
+ // pipes not owned by |this|. All weak pointers released in Close().
+ base::WeakPtrFactory<PepperTCPServerSocketMessageFilter> weak_ptr_factory_;
+
DISALLOW_COPY_AND_ASSIGN(PepperTCPServerSocketMessageFilter);
};
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.cc b/chromium/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.cc
index 6eb9ecd9c87..2e6b9ce144f 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.cc
@@ -6,21 +6,24 @@
#include <cstring>
#include <utility>
-#include <vector>
#include "base/bind.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
+#include "base/task/post_task.h"
#include "build/build_config.h"
#include "content/browser/renderer_host/pepper/content_browser_pepper_host_factory.h"
#include "content/browser/renderer_host/pepper/pepper_socket_utils.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/common/socket_permission_request.h"
+#include "mojo/public/cpp/bindings/callback_helpers.h"
+#include "mojo/public/cpp/bindings/interface_request.h"
#include "net/base/address_family.h"
#include "net/base/host_port_pair.h"
#include "net/base/io_buffer.h"
@@ -28,10 +31,7 @@
#include "net/base/net_errors.h"
#include "net/log/net_log_source.h"
#include "net/log/net_log_with_source.h"
-#include "net/socket/client_socket_factory.h"
-#include "net/socket/client_socket_handle.h"
-#include "net/socket/ssl_client_socket.h"
-#include "net/socket/tcp_client_socket.h"
+#include "net/ssl/ssl_info.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "ppapi/host/dispatch_host_message.h"
#include "ppapi/host/error_conversion.h"
@@ -46,10 +46,10 @@
#endif // defined(OS_CHROMEOS)
using ppapi::NetAddressPrivateImpl;
-using ppapi::host::NetErrorToPepperError;
-using ppapi::proxy::TCPSocketResourceConstants;
using ppapi::TCPSocketState;
using ppapi::TCPSocketVersion;
+using ppapi::host::NetErrorToPepperError;
+using ppapi::proxy::TCPSocketResourceConstants;
namespace {
@@ -59,99 +59,115 @@ size_t g_num_tcp_filter_instances = 0;
namespace content {
+network::mojom::NetworkContext*
+ PepperTCPSocketMessageFilter::network_context_for_testing = nullptr;
+
PepperTCPSocketMessageFilter::PepperTCPSocketMessageFilter(
ContentBrowserPepperHostFactory* factory,
BrowserPpapiHostImpl* host,
PP_Instance instance,
TCPSocketVersion version)
: version_(version),
+ host_(host),
+ factory_(factory),
+ instance_(instance),
external_plugin_(host->external_plugin()),
render_process_id_(0),
render_frame_id_(0),
binding_(this),
- host_(host),
- factory_(factory),
- instance_(instance),
+ socket_observer_binding_(this),
state_(TCPSocketState::INITIAL),
- end_of_file_reached_(false),
bind_input_addr_(NetAddressPrivateImpl::kInvalidNetAddress),
socket_options_(SOCKET_OPTION_NODELAY),
rcvbuf_size_(0),
sndbuf_size_(0),
- address_index_(0),
- socket_(new net::TCPSocket(nullptr, nullptr, net::NetLogSource())),
- ssl_context_helper_(host->ssl_context_helper()),
pending_accept_(false),
+ pending_read_size_(0),
+ pending_read_pp_error_(PP_OK_COMPLETIONPENDING),
pending_read_on_unthrottle_(false),
- pending_read_net_result_(0),
+ pending_write_bytes_written_(0),
+ pending_write_pp_error_(PP_OK_COMPLETIONPENDING),
is_potentially_secure_plugin_context_(
- host->IsPotentiallySecurePluginContext(instance)) {
+ host->IsPotentiallySecurePluginContext(instance)),
+ weak_ptr_factory_(this) {
DCHECK(host);
DCHECK_CURRENTLY_ON(BrowserThread::IO);
++g_num_tcp_filter_instances;
host_->AddInstanceObserver(instance_, this);
- if (!host->GetRenderFrameIDsForInstance(
- instance, &render_process_id_, &render_frame_id_)) {
+ is_throttled_ = host_->IsThrottled(instance_);
+ if (!host->GetRenderFrameIDsForInstance(instance, &render_process_id_,
+ &render_frame_id_)) {
NOTREACHED();
}
}
-PepperTCPSocketMessageFilter::PepperTCPSocketMessageFilter(
- BrowserPpapiHostImpl* host,
- PP_Instance instance,
- TCPSocketVersion version,
- std::unique_ptr<net::TCPSocket> socket)
- : version_(version),
- external_plugin_(host->external_plugin()),
- render_process_id_(0),
- render_frame_id_(0),
- binding_(this),
- host_(host),
- factory_(nullptr),
- instance_(instance),
- state_(TCPSocketState::CONNECTED),
- end_of_file_reached_(false),
- bind_input_addr_(NetAddressPrivateImpl::kInvalidNetAddress),
- socket_options_(SOCKET_OPTION_NODELAY),
- rcvbuf_size_(0),
- sndbuf_size_(0),
- address_index_(0),
- socket_(std::move(socket)),
- ssl_context_helper_(host->ssl_context_helper()),
- pending_accept_(false),
- pending_read_on_unthrottle_(false),
- pending_read_net_result_(0),
- is_potentially_secure_plugin_context_(
- host->IsPotentiallySecurePluginContext(instance)) {
- DCHECK(host);
- DCHECK_NE(version, ppapi::TCP_SOCKET_VERSION_1_0);
+void PepperTCPSocketMessageFilter::SetConnectedSocket(
+ network::mojom::TCPConnectedSocketPtrInfo connected_socket,
+ network::mojom::SocketObserverRequest socket_observer_request,
+ mojo::ScopedDataPipeConsumerHandle receive_stream,
+ mojo::ScopedDataPipeProducerHandle send_stream) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- ++g_num_tcp_filter_instances;
- host_->AddInstanceObserver(instance_, this);
- if (!host->GetRenderFrameIDsForInstance(
- instance, &render_process_id_, &render_frame_id_)) {
- NOTREACHED();
- }
+ // This method grabs a reference to |this|, and releases a reference on the UI
+ // thread, so something should be holding on to a reference on the current
+ // thread to prevent the object from being deleted before this method returns.
+ DCHECK(HasOneRef());
+
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(
+ &PepperTCPSocketMessageFilter::SetConnectedSocketOnUIThread, this,
+ std::move(connected_socket), std::move(socket_observer_request),
+ std::move(receive_stream), std::move(send_stream)));
}
PepperTCPSocketMessageFilter::~PepperTCPSocketMessageFilter() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (host_)
host_->RemoveInstanceObserver(instance_, this);
- if (socket_)
- socket_->Close();
- if (ssl_socket_)
- ssl_socket_->Disconnect();
--g_num_tcp_filter_instances;
}
+void PepperTCPSocketMessageFilter::SetConnectedSocketOnUIThread(
+ network::mojom::TCPConnectedSocketPtrInfo connected_socket,
+ network::mojom::SocketObserverRequest socket_observer_request,
+ mojo::ScopedDataPipeConsumerHandle receive_stream,
+ mojo::ScopedDataPipeProducerHandle send_stream) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK_EQ(state_.state(), TCPSocketState::INITIAL);
+
+ state_ = TCPSocketState(TCPSocketState::CONNECTED);
+ connected_socket_.Bind(std::move(connected_socket));
+ socket_observer_binding_.Bind(std::move(socket_observer_request));
+ socket_observer_binding_.set_connection_error_handler(
+ base::BindOnce(&PepperTCPSocketMessageFilter::OnSocketObserverError,
+ base::Unretained(this)));
+
+ SetStreams(std::move(receive_stream), std::move(send_stream));
+}
+
+// static
+void PepperTCPSocketMessageFilter::SetNetworkContextForTesting(
+ network::mojom::NetworkContext* network_context) {
+ network_context_for_testing = network_context;
+}
+
// static
size_t PepperTCPSocketMessageFilter::GetNumInstances() {
return g_num_tcp_filter_instances;
}
+void PepperTCPSocketMessageFilter::OnFilterDestroyed() {
+ ResourceMessageFilter::OnFilterDestroyed();
+ // Need to close all mojo pipes the socket on the UI thread. Calling Close()
+ // also ensures that future messages will be ignored, so the mojo pipes won't
+ // be re-created, so after Close() runs, |this| can be safely deleted on the
+ // IO thread.
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(&PepperTCPSocketMessageFilter::Close, this));
+}
+
scoped_refptr<base::TaskRunner>
PepperTCPSocketMessageFilter::OverrideTaskRunnerForMessage(
const IPC::Message& message) {
@@ -160,14 +176,13 @@ PepperTCPSocketMessageFilter::OverrideTaskRunnerForMessage(
case PpapiHostMsg_TCPSocket_Connect::ID:
case PpapiHostMsg_TCPSocket_ConnectWithNetAddress::ID:
case PpapiHostMsg_TCPSocket_Listen::ID:
- return BrowserThread::GetTaskRunnerForThread(BrowserThread::UI);
case PpapiHostMsg_TCPSocket_SSLHandshake::ID:
case PpapiHostMsg_TCPSocket_Read::ID:
case PpapiHostMsg_TCPSocket_Write::ID:
case PpapiHostMsg_TCPSocket_Accept::ID:
case PpapiHostMsg_TCPSocket_Close::ID:
case PpapiHostMsg_TCPSocket_SetOption::ID:
- return BrowserThread::GetTaskRunnerForThread(BrowserThread::IO);
+ return base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::UI});
}
return nullptr;
}
@@ -199,13 +214,11 @@ int32_t PepperTCPSocketMessageFilter::OnResourceMessageReceived(
}
void PepperTCPSocketMessageFilter::OnThrottleStateChanged(bool is_throttled) {
- if (pending_read_on_unthrottle_ && !is_throttled) {
- DCHECK(read_buffer_);
- OnReadCompleted(pending_read_reply_message_context_,
- pending_read_net_result_);
- DCHECK(!read_buffer_);
- pending_read_on_unthrottle_ = false;
- }
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(
+ &PepperTCPSocketMessageFilter::ThrottleStateChangedOnUIThread, this,
+ is_throttled));
}
void PepperTCPSocketMessageFilter::OnHostDestroyed() {
@@ -214,18 +227,86 @@ void PepperTCPSocketMessageFilter::OnHostDestroyed() {
host_ = nullptr;
}
+void PepperTCPSocketMessageFilter::ThrottleStateChangedOnUIThread(
+ bool is_throttled) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ is_throttled_ = is_throttled;
+
+ if (pending_read_on_unthrottle_ && !is_throttled) {
+ pending_read_on_unthrottle_ = false;
+ TryRead();
+ }
+}
+
void PepperTCPSocketMessageFilter::OnComplete(
int result,
const base::Optional<net::AddressList>& resolved_addresses) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
binding_.Close();
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&PepperTCPSocketMessageFilter::OnResolveCompleted, this,
- result, std::move(resolved_addresses)));
+ if (!host_resolve_context_.is_valid())
+ return;
+
+ ppapi::host::ReplyMessageContext context = host_resolve_context_;
+ host_resolve_context_ = ppapi::host::ReplyMessageContext();
+
+ if (!state_.IsPending(TCPSocketState::CONNECT)) {
+ DCHECK(state_.state() == TCPSocketState::CLOSED);
+ SendConnectError(context, PP_ERROR_FAILED);
+ return;
+ }
+
+ if (result != net::OK) {
+ SendConnectError(context, NetErrorToPepperError(result));
+ state_.CompletePendingTransition(false);
+ return;
+ }
+
+ StartConnect(context, resolved_addresses.value());
+}
+
+void PepperTCPSocketMessageFilter::OnReadError(int net_error) {
+ // If this method is called more than once, or |net_error| isn't an allowed
+ // value, just ignore the message.
+ if (pending_read_pp_error_ != PP_OK_COMPLETIONPENDING || net_error > 0 ||
+ net_error == net::ERR_IO_PENDING) {
+ return;
+ }
+
+ pending_read_pp_error_ = NetErrorToPepperError(net_error);
+ // Complete pending read with the error message if there's a pending read, and
+ // the read data pipe has already been closed. If the pipe is still open, need
+ // to wait until all data has been read before can start failing reads.
+ if (pending_read_context_.is_valid() && !receive_stream_ &&
+ !pending_read_on_unthrottle_) {
+ TryRead();
+ }
+}
+
+void PepperTCPSocketMessageFilter::OnWriteError(int net_error) {
+ // If this method is called more than once, or |net_error| isn't an allowed
+ // value, just ignore the message.
+ if (pending_write_pp_error_ != PP_OK_COMPLETIONPENDING || net_error > 0 ||
+ net_error == net::ERR_IO_PENDING) {
+ return;
+ }
+
+ pending_write_pp_error_ = NetErrorToPepperError(net_error);
+ // Complete pending write with the error message if there's a pending write,
+ // and the write data pipe has already been closed.
+ if (pending_write_context_.is_valid() && !send_stream_)
+ TryWrite();
+}
+
+void PepperTCPSocketMessageFilter::OnSocketObserverError() {
+ // Note that this method may be called while a connection is still being made.
+ socket_observer_binding_.Close();
- Release(); // Balances AddRef in OnMsgConnect.
+ // Treat this as a read and write error. If read and write errors have already
+ // been received, these calls will do nothing.
+ OnReadError(PP_ERROR_FAILED);
+ OnWriteError(PP_ERROR_FAILED);
}
int32_t PepperTCPSocketMessageFilter::OnMsgBind(
@@ -245,12 +326,45 @@ int32_t PepperTCPSocketMessageFilter::OnMsgBind(
return PP_ERROR_NOACCESS;
}
+ if (state_.IsPending(TCPSocketState::BIND))
+ return PP_ERROR_INPROGRESS;
+
+ if (!state_.IsValidTransition(TCPSocketState::BIND))
+ return PP_ERROR_FAILED;
+
+ DCHECK(!bound_socket_);
+ DCHECK(!connected_socket_);
+ DCHECK(!server_socket_);
+
+ // Validate address.
+ net::IPAddressBytes address;
+ uint16_t port;
+ if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(net_addr, &address,
+ &port)) {
+ state_.DoTransition(TCPSocketState::BIND, false);
+ return PP_ERROR_ADDRESS_INVALID;
+ }
+
+ network::mojom::NetworkContext* network_context = GetNetworkContext();
+ if (!network_context)
+ return PP_ERROR_FAILED;
+
+ // The network service doesn't allow binding a socket without first
+ // specifying if it's going to be used as a read or write socket,
+ // so just hold onto the address for now, without actually binding anything.
bind_input_addr_ = net_addr;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&PepperTCPSocketMessageFilter::DoBind, this,
- context->MakeReplyMessageContext(), net_addr));
+ state_.SetPendingTransition(TCPSocketState::BIND);
+ network_context->CreateTCPBoundSocket(
+ net::IPEndPoint(net::IPAddress(address), port),
+ pepper_socket_utils::PepperTCPNetworkAnnotationTag(),
+ mojo::MakeRequest(&bound_socket_),
+ mojo::WrapCallbackWithDefaultInvokeIfNotRun(
+ base::BindOnce(&PepperTCPSocketMessageFilter::OnBindCompleted,
+ weak_ptr_factory_.GetWeakPtr(),
+ context->MakeReplyMessageContext()),
+ net::ERR_FAILED, base::nullopt /* local_addr */));
+
return PP_OK_COMPLETIONPENDING;
}
@@ -266,39 +380,34 @@ int32_t PepperTCPSocketMessageFilter::OnMsgConnect(
return PP_ERROR_NOACCESS;
}
- SocketPermissionRequest request(
- SocketPermissionRequest::TCP_CONNECT, host, port);
- if (!pepper_socket_utils::CanUseSocketAPIs(external_plugin_,
- true /* private_api */,
- &request,
- render_process_id_,
- render_frame_id_)) {
+ SocketPermissionRequest request(SocketPermissionRequest::TCP_CONNECT, host,
+ port);
+ if (!pepper_socket_utils::CanUseSocketAPIs(
+ external_plugin_, true /* private_api */, &request,
+ render_process_id_, render_frame_id_)) {
return PP_ERROR_NOACCESS;
}
- RenderProcessHost* render_process_host =
- RenderProcessHost::FromID(render_process_id_);
- if (!render_process_host)
+ if (!state_.IsValidTransition(TCPSocketState::CONNECT)) {
+ NOTREACHED() << "This shouldn't be reached since the renderer only tries "
+ << "to connect once.";
+ return PP_ERROR_FAILED;
+ }
+
+ network::mojom::NetworkContext* network_context = GetNetworkContext();
+ if (!network_context)
return PP_ERROR_FAILED;
- auto* storage_partition = render_process_host->GetStoragePartition();
- // Grab a reference to this class to ensure that it's fully alive if a
- // connection error occurs (i.e. ref count is higher than 0 and there's no
- // task from ResourceMessageFilterDeleteTraits to delete this object on the IO
- // thread pending). Balanced in OnComplete();
- AddRef();
network::mojom::ResolveHostClientPtr client_ptr;
binding_.Bind(mojo::MakeRequest(&client_ptr));
binding_.set_connection_error_handler(
base::BindOnce(&PepperTCPSocketMessageFilter::OnComplete,
base::Unretained(this), net::ERR_FAILED, base::nullopt));
- storage_partition->GetNetworkContext()->ResolveHost(
- net::HostPortPair(host, port), nullptr, std::move(client_ptr));
+ network_context->ResolveHost(net::HostPortPair(host, port), nullptr,
+ std::move(client_ptr));
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&PepperTCPSocketMessageFilter::HostResolvingStarted, this,
- context->MakeReplyMessageContext()));
+ state_.SetPendingTransition(TCPSocketState::CONNECT);
+ host_resolve_context_ = context->MakeReplyMessageContext();
return PP_OK_COMPLETIONPENDING;
}
@@ -310,18 +419,28 @@ int32_t PepperTCPSocketMessageFilter::OnMsgConnectWithNetAddress(
content::SocketPermissionRequest request =
pepper_socket_utils::CreateSocketPermissionRequest(
content::SocketPermissionRequest::TCP_CONNECT, net_addr);
- if (!pepper_socket_utils::CanUseSocketAPIs(external_plugin_,
- IsPrivateAPI(),
- &request,
- render_process_id_,
+ if (!pepper_socket_utils::CanUseSocketAPIs(external_plugin_, IsPrivateAPI(),
+ &request, render_process_id_,
render_frame_id_)) {
return PP_ERROR_NOACCESS;
}
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&PepperTCPSocketMessageFilter::DoConnectWithNetAddress,
- this, context->MakeReplyMessageContext(), net_addr));
+ if (!state_.IsValidTransition(TCPSocketState::CONNECT))
+ return PP_ERROR_FAILED;
+
+ state_.SetPendingTransition(TCPSocketState::CONNECT);
+
+ net::IPAddressBytes address;
+ uint16_t port;
+ if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(net_addr, &address,
+ &port)) {
+ state_.CompletePendingTransition(false);
+ return PP_ERROR_ADDRESS_INVALID;
+ }
+
+ StartConnect(
+ context->MakeReplyMessageContext(),
+ net::AddressList(net::IPEndPoint(net::IPAddress(address), port)));
return PP_OK_COMPLETIONPENDING;
}
@@ -329,103 +448,101 @@ int32_t PepperTCPSocketMessageFilter::OnMsgSSLHandshake(
const ppapi::host::HostMessageContext* context,
const std::string& server_name,
uint16_t server_port,
- const std::vector<std::vector<char> >& trusted_certs,
- const std::vector<std::vector<char> >& untrusted_certs) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ const std::vector<std::vector<char>>& trusted_certs,
+ const std::vector<std::vector<char>>& untrusted_certs) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
// Allow to do SSL handshake only if currently the socket has been connected
// and there isn't pending read or write.
if (!state_.IsValidTransition(TCPSocketState::SSL_CONNECT) ||
- read_buffer_.get() || write_buffer_base_.get() || write_buffer_.get()) {
+ pending_read_context_.is_valid() || pending_write_context_.is_valid()) {
return PP_ERROR_FAILED;
}
- // TODO(raymes,rsleevi): Use trusted/untrusted certificates when connecting.
- net::IPEndPoint peer_address;
- if (socket_->GetPeerAddress(&peer_address) != net::OK)
- return PP_ERROR_FAILED;
+ // If there's a pending read or write error, fail the request with that.
+ if (pending_read_pp_error_ != PP_OK_COMPLETIONPENDING) {
+ if (pending_read_pp_error_ == PP_OK)
+ pending_read_pp_error_ = PP_ERROR_FAILED;
+ return pending_read_pp_error_;
+ }
- std::unique_ptr<net::ClientSocketHandle> handle(
- new net::ClientSocketHandle());
- handle->SetSocket(base::WrapUnique<net::StreamSocket>(
- new net::TCPClientSocket(std::move(socket_), peer_address)));
- net::ClientSocketFactory* factory =
- net::ClientSocketFactory::GetDefaultFactory();
- net::HostPortPair host_port_pair(server_name, server_port);
- net::SSLClientSocketContext ssl_context;
- ssl_context.cert_verifier = ssl_context_helper_->GetCertVerifier();
- ssl_context.transport_security_state =
- ssl_context_helper_->GetTransportSecurityState();
- ssl_context.cert_transparency_verifier =
- ssl_context_helper_->GetCertTransparencyVerifier();
- ssl_context.ct_policy_enforcer = ssl_context_helper_->GetCTPolicyEnforcer();
- ssl_socket_ = factory->CreateSSLClientSocket(
- std::move(handle), host_port_pair, ssl_context_helper_->ssl_config(),
- ssl_context);
- if (!ssl_socket_) {
- LOG(WARNING) << "Failed to create an SSL client socket.";
- state_.CompletePendingTransition(false);
- return PP_ERROR_FAILED;
+ if (pending_write_pp_error_ != PP_OK_COMPLETIONPENDING) {
+ if (pending_write_pp_error_ == PP_OK)
+ pending_write_pp_error_ = PP_ERROR_FAILED;
+ return pending_write_pp_error_;
}
+ // TODO(raymes,rsleevi): Use trusted/untrusted certificates when connecting.
+
+ // Close all Mojo pipes except |connected_socket_|.
+ receive_stream_.reset();
+ read_watcher_.reset();
+ send_stream_.reset();
+ write_watcher_.reset();
+ socket_observer_binding_.Close();
+
+ network::mojom::SocketObserverPtr socket_observer;
+ socket_observer_binding_.Bind(mojo::MakeRequest(&socket_observer));
+ socket_observer_binding_.set_connection_error_handler(
+ base::BindOnce(&PepperTCPSocketMessageFilter::OnSocketObserverError,
+ base::Unretained(this)));
+
state_.SetPendingTransition(TCPSocketState::SSL_CONNECT);
- const ppapi::host::ReplyMessageContext reply_context(
- context->MakeReplyMessageContext());
- int net_result = ssl_socket_->Connect(
- base::BindOnce(&PepperTCPSocketMessageFilter::OnSSLHandshakeCompleted,
- base::Unretained(this), reply_context));
- if (net_result != net::ERR_IO_PENDING)
- OnSSLHandshakeCompleted(reply_context, net_result);
+ network::mojom::TLSClientSocketOptionsPtr tls_client_socket_options =
+ network::mojom::TLSClientSocketOptions::New();
+ tls_client_socket_options->send_ssl_info = true;
+ net::HostPortPair host_port_pair(server_name, server_port);
+ connected_socket_->UpgradeToTLS(
+ host_port_pair, std::move(tls_client_socket_options),
+ pepper_socket_utils::PepperTCPNetworkAnnotationTag(),
+ mojo::MakeRequest(&tls_client_socket_), std::move(socket_observer),
+ mojo::WrapCallbackWithDefaultInvokeIfNotRun(
+ base::BindOnce(&PepperTCPSocketMessageFilter::OnSSLHandshakeCompleted,
+ base::Unretained(this),
+ context->MakeReplyMessageContext()),
+ net::ERR_FAILED, mojo::ScopedDataPipeConsumerHandle(),
+ mojo::ScopedDataPipeProducerHandle(), base::nullopt /* ssl_info */));
+
return PP_OK_COMPLETIONPENDING;
}
int32_t PepperTCPSocketMessageFilter::OnMsgRead(
const ppapi::host::HostMessageContext* context,
int32_t bytes_to_read) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (!state_.IsConnected() || end_of_file_reached_)
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ // This only covers the case where the socket was explicitly closed from the
+ // caller, or the filter is being destroyed. Read errors and Mojo errors are
+ // handled in TryRead().
+ if (!state_.IsConnected())
return PP_ERROR_FAILED;
- if (read_buffer_.get())
+
+ if (pending_read_context_.is_valid())
return PP_ERROR_INPROGRESS;
if (bytes_to_read <= 0 ||
bytes_to_read > TCPSocketResourceConstants::kMaxReadSize) {
return PP_ERROR_BADARGUMENT;
}
- ppapi::host::ReplyMessageContext reply_context(
- context->MakeReplyMessageContext());
- read_buffer_ = new net::IOBuffer(bytes_to_read);
-
- int net_result = net::ERR_FAILED;
- if (socket_) {
- DCHECK_EQ(state_.state(), TCPSocketState::CONNECTED);
- net_result = socket_->Read(
- read_buffer_.get(), bytes_to_read,
- base::BindOnce(&PepperTCPSocketMessageFilter::OnReadCompleted,
- base::Unretained(this), reply_context));
- } else if (ssl_socket_) {
- DCHECK_EQ(state_.state(), TCPSocketState::SSL_CONNECTED);
- net_result = ssl_socket_->Read(
- read_buffer_.get(), bytes_to_read,
- base::BindOnce(&PepperTCPSocketMessageFilter::OnReadCompleted,
- base::Unretained(this), reply_context));
- }
- if (net_result != net::ERR_IO_PENDING)
- OnReadCompleted(reply_context, net_result);
+ pending_read_context_ = context->MakeReplyMessageContext();
+ pending_read_size_ = static_cast<uint32_t>(bytes_to_read);
+ TryRead();
return PP_OK_COMPLETIONPENDING;
}
int32_t PepperTCPSocketMessageFilter::OnMsgWrite(
const ppapi::host::HostMessageContext* context,
const std::string& data) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (!state_.IsConnected())
return PP_ERROR_FAILED;
- if (write_buffer_base_.get() || write_buffer_.get())
+ if (pending_write_context_.is_valid())
return PP_ERROR_INPROGRESS;
+ DCHECK(pending_write_data_.empty());
+ DCHECK_EQ(0u, pending_write_bytes_written_);
+
size_t data_size = data.size();
if (data_size == 0 ||
data_size >
@@ -433,11 +550,9 @@ int32_t PepperTCPSocketMessageFilter::OnMsgWrite(
return PP_ERROR_BADARGUMENT;
}
- write_buffer_base_ = base::MakeRefCounted<net::IOBuffer>(data_size);
- memcpy(write_buffer_base_->data(), data.data(), data_size);
- write_buffer_ = base::MakeRefCounted<net::DrainableIOBuffer>(
- write_buffer_base_, data_size);
- DoWrite(context->MakeReplyMessageContext());
+ pending_write_data_ = data;
+ pending_write_context_ = context->MakeReplyMessageContext();
+ TryWrite();
return PP_OK_COMPLETIONPENDING;
}
@@ -446,6 +561,12 @@ int32_t PepperTCPSocketMessageFilter::OnMsgListen(
int32_t backlog) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ if (state_.IsPending(TCPSocketState::LISTEN))
+ return PP_ERROR_INPROGRESS;
+
+ if (!state_.IsValidTransition(TCPSocketState::LISTEN))
+ return PP_ERROR_FAILED;
+
// This is only supported by PPB_TCPSocket v1.1 or above.
if (version_ != ppapi::TCP_SOCKET_VERSION_1_1_OR_ABOVE) {
NOTREACHED();
@@ -455,59 +576,64 @@ int32_t PepperTCPSocketMessageFilter::OnMsgListen(
content::SocketPermissionRequest request =
pepper_socket_utils::CreateSocketPermissionRequest(
content::SocketPermissionRequest::TCP_LISTEN, bind_input_addr_);
- if (!pepper_socket_utils::CanUseSocketAPIs(external_plugin_,
- false /* private_api */,
- &request,
- render_process_id_,
- render_frame_id_)) {
+ if (!pepper_socket_utils::CanUseSocketAPIs(
+ external_plugin_, false /* private_api */, &request,
+ render_process_id_, render_frame_id_)) {
return PP_ERROR_NOACCESS;
}
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&PepperTCPSocketMessageFilter::DoListen, this,
- context->MakeReplyMessageContext(), backlog));
+ DCHECK(bound_socket_);
+ DCHECK(!server_socket_);
+
+ state_.SetPendingTransition(TCPSocketState::LISTEN);
+
+ bound_socket_->Listen(
+ backlog, mojo::MakeRequest(&server_socket_),
+ mojo::WrapCallbackWithDefaultInvokeIfNotRun(
+ base::BindOnce(&PepperTCPSocketMessageFilter::OnListenCompleted,
+ base::Unretained(this),
+ context->MakeReplyMessageContext()),
+ net::ERR_FAILED));
return PP_OK_COMPLETIONPENDING;
}
int32_t PepperTCPSocketMessageFilter::OnMsgAccept(
const ppapi::host::HostMessageContext* context) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (pending_accept_)
return PP_ERROR_INPROGRESS;
if (state_.state() != TCPSocketState::LISTENING)
return PP_ERROR_FAILED;
+ DCHECK(server_socket_);
+
pending_accept_ = true;
- ppapi::host::ReplyMessageContext reply_context(
- context->MakeReplyMessageContext());
- int net_result = socket_->Accept(
- &accepted_socket_, &accepted_address_,
- base::Bind(&PepperTCPSocketMessageFilter::OnAcceptCompleted,
- base::Unretained(this), reply_context));
- if (net_result != net::ERR_IO_PENDING)
- OnAcceptCompleted(reply_context, net_result);
+
+ network::mojom::SocketObserverPtr socket_observer;
+ network::mojom::SocketObserverRequest socket_observer_request =
+ mojo::MakeRequest(&socket_observer);
+ server_socket_->Accept(
+ std::move(socket_observer),
+ mojo::WrapCallbackWithDefaultInvokeIfNotRun(
+ base::BindOnce(&PepperTCPSocketMessageFilter::OnAcceptCompleted,
+ base::Unretained(this),
+ context->MakeReplyMessageContext(),
+ std::move(socket_observer_request)),
+ net::ERR_FAILED, base::nullopt /* remote_addr */,
+ network::mojom::TCPConnectedSocketPtr(),
+ mojo::ScopedDataPipeConsumerHandle(),
+ mojo::ScopedDataPipeProducerHandle()));
return PP_OK_COMPLETIONPENDING;
}
int32_t PepperTCPSocketMessageFilter::OnMsgClose(
const ppapi::host::HostMessageContext* context) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (state_.state() == TCPSocketState::CLOSED)
return PP_OK;
- state_.DoTransition(TCPSocketState::CLOSE, true);
-#if defined(OS_CHROMEOS)
- // Close the firewall hole, it is no longer needed.
- firewall_hole_.reset();
-#endif // defined(OS_CHROMEOS)
- // Make sure we get no further callbacks from |socket_| or |ssl_socket_|.
- if (socket_) {
- socket_->Close();
- } else if (ssl_socket_) {
- ssl_socket_->Disconnect();
- }
+ Close();
return PP_OK;
}
@@ -515,19 +641,37 @@ int32_t PepperTCPSocketMessageFilter::OnMsgSetOption(
const ppapi::host::HostMessageContext* context,
PP_TCPSocket_Option name,
const ppapi::SocketOptionData& value) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ // Options are only applied if |this| is currently being used as a client
+ // socket, or is going to be used as one - they are ignored for server
+ // sockets.
switch (name) {
case PP_TCPSOCKET_OPTION_NO_DELAY: {
bool boolean_value = false;
if (!value.GetBool(&boolean_value))
return PP_ERROR_BADARGUMENT;
- // If the socket is already connected, proxy the value to TCPSocket.
- if (state_.state() == TCPSocketState::CONNECTED)
- return socket_->SetNoDelay(boolean_value) ? PP_OK : PP_ERROR_FAILED;
+ // If |connected_socket_| is connecting or has connected, pass the setting
+ // along.
+ if (connected_socket_.is_bound()) {
+ connected_socket_->SetNoDelay(
+ boolean_value,
+ // Callback that converts a bool to a net error code which it then
+ // passes to the common completion callback routine.
+ base::BindOnce(
+ [](base::OnceCallback<void(int)> completion_callback,
+ bool success) {
+ std::move(completion_callback)
+ .Run(success ? net::OK : net::ERR_FAILED);
+ },
+ CreateCompletionCallback<
+ PpapiPluginMsg_TCPSocket_SetOptionReply>(context)));
+ return PP_OK_COMPLETIONPENDING;
+ }
- // TCPSocket instance is not yet created. So remember the value here.
+ // TCPConnectedSocket instance is not yet created. So remember the value
+ // here.
if (boolean_value) {
socket_options_ |= SOCKET_OPTION_NODELAY;
} else {
@@ -541,10 +685,14 @@ int32_t PepperTCPSocketMessageFilter::OnMsgSetOption(
integer_value > TCPSocketResourceConstants::kMaxSendBufferSize)
return PP_ERROR_BADARGUMENT;
- // If the socket is already connected, proxy the value to TCPSocket.
- if (state_.state() == TCPSocketState::CONNECTED) {
- return NetErrorToPepperError(
- socket_->SetSendBufferSize(integer_value));
+ // If |connected_socket_| is connecting or has connected, pass the setting
+ // along.
+ if (connected_socket_.is_bound()) {
+ connected_socket_->SetSendBufferSize(
+ integer_value,
+ CreateCompletionCallback<PpapiPluginMsg_TCPSocket_SetOptionReply>(
+ context));
+ return PP_OK_COMPLETIONPENDING;
}
// TCPSocket instance is not yet created. So remember the value here.
@@ -558,13 +706,18 @@ int32_t PepperTCPSocketMessageFilter::OnMsgSetOption(
integer_value > TCPSocketResourceConstants::kMaxReceiveBufferSize)
return PP_ERROR_BADARGUMENT;
- // If the socket is already connected, proxy the value to TCPSocket.
- if (state_.state() == TCPSocketState::CONNECTED) {
- return NetErrorToPepperError(
- socket_->SetReceiveBufferSize(integer_value));
+ // If |connected_socket_| is connecting or has connected, pass the setting
+ // along.
+ if (connected_socket_.is_bound()) {
+ connected_socket_->SetReceiveBufferSize(
+ integer_value,
+ CreateCompletionCallback<PpapiPluginMsg_TCPSocket_SetOptionReply>(
+ context));
+ return PP_OK_COMPLETIONPENDING;
}
- // TCPSocket instance is not yet created. So remember the value here.
+ // TCPConnectedSocket instance is not yet created. So remember the value
+ // here.
socket_options_ |= SOCKET_OPTION_RCVBUF_SIZE;
rcvbuf_size_ = integer_value;
return PP_OK;
@@ -574,469 +727,498 @@ int32_t PepperTCPSocketMessageFilter::OnMsgSetOption(
return PP_ERROR_BADARGUMENT;
}
}
+ return PP_OK;
}
-void PepperTCPSocketMessageFilter::DoBind(
- const ppapi::host::ReplyMessageContext& context,
- const PP_NetAddress_Private& net_addr) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
+void PepperTCPSocketMessageFilter::TryRead() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(state_.IsConnected());
+ DCHECK(pending_read_context_.is_valid());
+ DCHECK_GT(pending_read_size_, 0u);
+ DCHECK(!pending_read_on_unthrottle_);
- if (state_.IsPending(TCPSocketState::BIND)) {
- SendBindError(context, PP_ERROR_INPROGRESS);
- return;
- }
- if (!state_.IsValidTransition(TCPSocketState::BIND)) {
- SendBindError(context, PP_ERROR_FAILED);
+ if (is_throttled_) {
+ pending_read_on_unthrottle_ = true;
return;
}
- int pp_result = PP_OK;
- do {
- net::IPAddressBytes address;
- uint16_t port;
- if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(
- net_addr, &address, &port)) {
- pp_result = PP_ERROR_ADDRESS_INVALID;
- break;
- }
- net::IPEndPoint bind_addr(net::IPAddress(address), port);
-
- DCHECK(!socket_->IsValid());
- pp_result = NetErrorToPepperError(socket_->Open(bind_addr.GetFamily()));
- if (pp_result != PP_OK)
- break;
-
- pp_result = NetErrorToPepperError(socket_->SetDefaultOptionsForServer());
- if (pp_result != PP_OK)
- break;
-
- pp_result = NetErrorToPepperError(socket_->Bind(bind_addr));
- if (pp_result != PP_OK)
- break;
+ // This loop's body will generally run only once, unless there's a read error,
+ // in which case, it will start over, to re-apply the initial logic.
+ while (true) {
+ // As long as the read stream is still open, try to read data, even if a
+ // read error has been received from the SocketObserver, as there may still
+ // be data on the pipe.
+ if (!receive_stream_.is_valid()) {
+ // If no read error has been received yet, wait to receive one through
+ // the SocketObserver interface.
+ if (pending_read_pp_error_ == PP_OK_COMPLETIONPENDING) {
+ DCHECK(socket_observer_binding_.is_bound());
+ break;
+ }
- net::IPEndPoint ip_end_point_local;
- pp_result =
- NetErrorToPepperError(socket_->GetLocalAddress(&ip_end_point_local));
- if (pp_result != PP_OK)
+ // Otherwise, pass along the read error.
+ SendReadError(pending_read_pp_error_);
+ // If the socket was closed gracefully, only return OK for a single
+ // read.
+ if (pending_read_pp_error_ == PP_OK)
+ pending_read_pp_error_ = PP_ERROR_FAILED;
break;
+ }
- PP_NetAddress_Private local_addr =
- NetAddressPrivateImpl::kInvalidNetAddress;
- if (!NetAddressPrivateImpl::IPEndPointToNetAddress(
- ip_end_point_local.address().bytes(), ip_end_point_local.port(),
- &local_addr)) {
- pp_result = PP_ERROR_ADDRESS_INVALID;
+ DCHECK(read_watcher_);
+ const void* buffer = nullptr;
+ uint32_t num_bytes = 0;
+ int mojo_result = receive_stream_->BeginReadData(&buffer, &num_bytes,
+ MOJO_READ_DATA_FLAG_NONE);
+ if (mojo_result == MOJO_RESULT_SHOULD_WAIT) {
+ read_watcher_->ArmOrNotify();
break;
}
- SendBindReply(context, PP_OK, local_addr);
- state_.DoTransition(TCPSocketState::BIND, true);
- return;
- } while (false);
- if (socket_->IsValid())
- socket_->Close();
- SendBindError(context, pp_result);
- state_.DoTransition(TCPSocketState::BIND, false);
-}
-
-void PepperTCPSocketMessageFilter::HostResolvingStarted(
- const ppapi::host::ReplyMessageContext& context) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (!state_.IsValidTransition(TCPSocketState::CONNECT)) {
- NOTREACHED() << "This shouldn't be reached since the renderer only tries "
- << "to connect once.";
- SendConnectError(context, PP_ERROR_FAILED);
- return;
- }
-
- state_.SetPendingTransition(TCPSocketState::CONNECT);
- address_index_ = 0;
- address_list_.clear();
- host_resolve_context_ = context;
-}
-
-void PepperTCPSocketMessageFilter::DoConnectWithNetAddress(
- const ppapi::host::ReplyMessageContext& context,
- const PP_NetAddress_Private& net_addr) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- if (!state_.IsValidTransition(TCPSocketState::CONNECT)) {
- SendConnectError(context, PP_ERROR_FAILED);
- return;
- }
+ // On a Mojo pipe error (which may indicate a graceful close, network error,
+ // or network service crash), close read pipe and restart the loop.
+ if (mojo_result != MOJO_RESULT_OK) {
+ read_watcher_.reset();
+ receive_stream_.reset();
+ continue;
+ }
- state_.SetPendingTransition(TCPSocketState::CONNECT);
+ // This is guaranteed by Mojo.
+ DCHECK_GT(num_bytes, 0u);
- net::IPAddressBytes address;
- uint16_t port;
- if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(
- net_addr, &address, &port)) {
- state_.CompletePendingTransition(false);
- SendConnectError(context, PP_ERROR_ADDRESS_INVALID);
- return;
+ uint32_t bytes_to_copy = std::min(num_bytes, pending_read_size_);
+ SendReadReply(PP_OK, std::string(reinterpret_cast<const char*>(buffer),
+ bytes_to_copy));
+ receive_stream_->EndReadData(bytes_to_copy);
+ break;
}
-
- // Copy the single IPEndPoint to address_list_.
- address_index_ = 0;
- address_list_.clear();
- address_list_.push_back(net::IPEndPoint(net::IPAddress(address), port));
- StartConnect(context);
}
-void PepperTCPSocketMessageFilter::DoWrite(
- const ppapi::host::ReplyMessageContext& context) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(write_buffer_base_.get());
- DCHECK(write_buffer_.get());
- DCHECK_GT(write_buffer_->BytesRemaining(), 0);
+void PepperTCPSocketMessageFilter::TryWrite() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(state_.IsConnected());
+ DCHECK(pending_write_context_.is_valid());
+ DCHECK(!pending_write_data_.empty());
+ DCHECK_LT(pending_write_bytes_written_, pending_write_data_.size());
+
+ // The structure of this code largely mirrors TryRead() above, with a couple
+ // differences. The loop will repeat until all bytes are written, there's an
+ // error, or no more buffer space is available. Also, it's possible for a
+ // Mojo write to succeed, but a write to the underlying socket to fail. In
+ // that case, the failure might not be returned to the caller until it tries
+ // to write again. Since the socket APIs themselves don't guarantee that
+ // data has been successfully received by the remote server on success, this
+ // should not cause unexpected problems for consumers.
+ while (true) {
+ if (!send_stream_.is_valid()) {
+ if (pending_write_pp_error_ == PP_OK_COMPLETIONPENDING) {
+ DCHECK(socket_observer_binding_.is_bound());
+ break;
+ }
+ SendWriteReply(pending_write_pp_error_);
+ // Mirror handling of "OK" read errors, only sending "OK" for a single
+ // write, though getting "OK" from a write is probably nonsense, anyways.
+ if (pending_write_pp_error_ == PP_OK)
+ pending_write_pp_error_ = PP_ERROR_FAILED;
+ break;
+ }
- int net_result = net::ERR_FAILED;
- if (socket_) {
- DCHECK_EQ(state_.state(), TCPSocketState::CONNECTED);
- net_result = socket_->Write(
- write_buffer_.get(), write_buffer_->BytesRemaining(),
- base::BindOnce(&PepperTCPSocketMessageFilter::OnWriteCompleted,
- base::Unretained(this), context),
- static_cast<net::NetworkTrafficAnnotationTag>(
- pepper_socket_utils::PepperTCPNetworkAnnotationTag()));
- } else if (ssl_socket_) {
- DCHECK_EQ(state_.state(), TCPSocketState::SSL_CONNECTED);
- net_result = ssl_socket_->Write(
- write_buffer_.get(), write_buffer_->BytesRemaining(),
- base::BindOnce(&PepperTCPSocketMessageFilter::OnWriteCompleted,
- base::Unretained(this), context),
- static_cast<net::NetworkTrafficAnnotationTag>(
- pepper_socket_utils::PepperTCPNetworkAnnotationTag()));
- }
- if (net_result != net::ERR_IO_PENDING)
- OnWriteCompleted(context, net_result);
-}
-
-void PepperTCPSocketMessageFilter::DoListen(
- const ppapi::host::ReplyMessageContext& context,
- int32_t backlog) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- if (state_.IsPending(TCPSocketState::LISTEN)) {
- SendListenReply(context, PP_ERROR_INPROGRESS);
- return;
- }
- if (!state_.IsValidTransition(TCPSocketState::LISTEN)) {
- SendListenReply(context, PP_ERROR_FAILED);
- return;
- }
-
- int32_t pp_result = NetErrorToPepperError(socket_->Listen(backlog));
-#if defined(OS_CHROMEOS)
- OpenFirewallHole(context, pp_result);
-#else
- OnListenCompleted(context, pp_result);
-#endif
-}
+ DCHECK(write_watcher_);
-void PepperTCPSocketMessageFilter::OnResolveCompleted(
- int net_result,
- const base::Optional<net::AddressList>& resolved_addresses) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (!host_resolve_context_.is_valid())
- return;
+ uint32_t num_bytes =
+ pending_write_data_.size() - pending_write_bytes_written_;
+ DCHECK_GT(num_bytes, 0u);
+ int mojo_result = send_stream_->WriteData(
+ pending_write_data_.data() + pending_write_bytes_written_, &num_bytes,
+ MOJO_WRITE_DATA_FLAG_NONE);
+ if (mojo_result == MOJO_RESULT_SHOULD_WAIT) {
+ write_watcher_->ArmOrNotify();
+ break;
+ }
- ppapi::host::ReplyMessageContext context = host_resolve_context_;
- host_resolve_context_ = ppapi::host::ReplyMessageContext();
+ // On a Mojo pipe error (which may indicate a graceful close, network error,
+ // or network service crash), close write pipe and restart the loop.
+ if (mojo_result != MOJO_RESULT_OK) {
+ write_watcher_.reset();
+ send_stream_.reset();
+ continue;
+ }
- if (!state_.IsPending(TCPSocketState::CONNECT)) {
- DCHECK(state_.state() == TCPSocketState::CLOSED);
- SendConnectError(context, PP_ERROR_FAILED);
- return;
- }
+ // This is guaranteed by Mojo.
+ DCHECK_GT(num_bytes, 0u);
- if (net_result != net::OK) {
- SendConnectError(context, NetErrorToPepperError(net_result));
- state_.CompletePendingTransition(false);
- return;
+ pending_write_bytes_written_ += num_bytes;
+ // If all bytes were written, nothing left to do.
+ if (pending_write_bytes_written_ == pending_write_data_.size()) {
+ SendWriteReply(pending_write_bytes_written_);
+ break;
+ }
}
-
- address_list_ = resolved_addresses.value();
- StartConnect(context);
}
void PepperTCPSocketMessageFilter::StartConnect(
- const ppapi::host::ReplyMessageContext& context) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ const ppapi::host::ReplyMessageContext& context,
+ const net::AddressList& address_list) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(state_.IsPending(TCPSocketState::CONNECT));
- DCHECK_LT(address_index_, address_list_.size());
-
- if (!socket_->IsValid()) {
- int net_result = socket_->Open(address_list_[address_index_].GetFamily());
- if (net_result != net::OK) {
- OnConnectCompleted(context, net_result);
- return;
- }
- }
-
- socket_->SetDefaultOptionsForClient();
-
- if (!(socket_options_ & SOCKET_OPTION_NODELAY)) {
- if (!socket_->SetNoDelay(false)) {
- OnConnectCompleted(context, net::ERR_FAILED);
- return;
- }
- }
- if (socket_options_ & SOCKET_OPTION_RCVBUF_SIZE) {
- int net_result = socket_->SetReceiveBufferSize(rcvbuf_size_);
- if (net_result != net::OK) {
- OnConnectCompleted(context, net_result);
- return;
- }
- }
- if (socket_options_ & SOCKET_OPTION_SNDBUF_SIZE) {
- int net_result = socket_->SetSendBufferSize(sndbuf_size_);
- if (net_result != net::OK) {
- OnConnectCompleted(context, net_result);
+ DCHECK(!address_list.empty());
+
+ network::mojom::SocketObserverPtr socket_observer;
+ socket_observer_binding_.Bind(mojo::MakeRequest(&socket_observer));
+
+ socket_observer_binding_.set_connection_error_handler(
+ base::BindOnce(&PepperTCPSocketMessageFilter::OnSocketObserverError,
+ base::Unretained(this)));
+
+ network::mojom::TCPConnectedSocketOptionsPtr socket_options =
+ network::mojom::TCPConnectedSocketOptions::New();
+ socket_options->no_delay = !!(socket_options_ & SOCKET_OPTION_NODELAY);
+ if (socket_options_ & SOCKET_OPTION_RCVBUF_SIZE)
+ socket_options->receive_buffer_size = rcvbuf_size_;
+ if (socket_options_ & SOCKET_OPTION_SNDBUF_SIZE)
+ socket_options->send_buffer_size = sndbuf_size_;
+
+ network::mojom::NetworkContext::CreateTCPConnectedSocketCallback callback =
+ mojo::WrapCallbackWithDefaultInvokeIfNotRun(
+ base::BindOnce(&PepperTCPSocketMessageFilter::OnConnectCompleted,
+ weak_ptr_factory_.GetWeakPtr(), context),
+ net::ERR_FAILED, base::nullopt, base::nullopt,
+ mojo::ScopedDataPipeConsumerHandle(),
+ mojo::ScopedDataPipeProducerHandle());
+ if (bound_socket_) {
+ bound_socket_->Connect(address_list, std::move(socket_options),
+ mojo::MakeRequest(&connected_socket_),
+ std::move(socket_observer), std::move(callback));
+ } else {
+ network::mojom::NetworkContext* network_context = GetNetworkContext();
+ if (!network_context) {
+ // This will delete |callback|, which will invoke OnConnectCompleted()
+ // with an error.
return;
}
+ network_context->CreateTCPConnectedSocket(
+ base::nullopt /* local_addr */, address_list, std::move(socket_options),
+ pepper_socket_utils::PepperTCPNetworkAnnotationTag(),
+ mojo::MakeRequest(&connected_socket_), std::move(socket_observer),
+ std::move(callback));
}
-
- int net_result = socket_->Connect(
- address_list_[address_index_],
- base::BindOnce(&PepperTCPSocketMessageFilter::OnConnectCompleted,
- base::Unretained(this), context));
- if (net_result != net::ERR_IO_PENDING)
- OnConnectCompleted(context, net_result);
}
void PepperTCPSocketMessageFilter::OnConnectCompleted(
const ppapi::host::ReplyMessageContext& context,
- int net_result) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ int net_result,
+ const base::Optional<net::IPEndPoint>& local_addr,
+ const base::Optional<net::IPEndPoint>& peer_addr,
+ mojo::ScopedDataPipeConsumerHandle receive_stream,
+ mojo::ScopedDataPipeProducerHandle send_stream) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
- if (!state_.IsPending(TCPSocketState::CONNECT)) {
- DCHECK(state_.state() == TCPSocketState::CLOSED);
- SendConnectError(context, PP_ERROR_FAILED);
+ int32_t pp_result = NetErrorToPepperError(net_result);
+
+ if (state_.state() == TCPSocketState::CLOSED) {
+ // If this is called as a result of Close() being invoked and closing the
+ // pipe, fail the request without doing anything.
+ DCHECK_EQ(net_result, net::ERR_FAILED);
+ SendConnectError(context, pp_result);
return;
}
- int32_t pp_result = NetErrorToPepperError(net_result);
- do {
- if (pp_result != PP_OK)
- break;
+ DCHECK(state_.IsPending(TCPSocketState::CONNECT));
- net::IPEndPoint ip_end_point_local;
- net::IPEndPoint ip_end_point_remote;
- pp_result =
- NetErrorToPepperError(socket_->GetLocalAddress(&ip_end_point_local));
- if (pp_result != PP_OK)
- break;
- pp_result =
- NetErrorToPepperError(socket_->GetPeerAddress(&ip_end_point_remote));
+ do {
if (pp_result != PP_OK)
break;
- PP_NetAddress_Private local_addr =
+ PP_NetAddress_Private pp_local_addr =
NetAddressPrivateImpl::kInvalidNetAddress;
- PP_NetAddress_Private remote_addr =
+ PP_NetAddress_Private pp_remote_addr =
NetAddressPrivateImpl::kInvalidNetAddress;
- if (!NetAddressPrivateImpl::IPEndPointToNetAddress(
- ip_end_point_local.address().bytes(), ip_end_point_local.port(),
- &local_addr) ||
+ if (!local_addr || !peer_addr ||
+ !NetAddressPrivateImpl::IPEndPointToNetAddress(
+ local_addr->address().bytes(), local_addr->port(),
+ &pp_local_addr) ||
!NetAddressPrivateImpl::IPEndPointToNetAddress(
- ip_end_point_remote.address().bytes(), ip_end_point_remote.port(),
- &remote_addr)) {
+ peer_addr->address().bytes(), peer_addr->port(), &pp_remote_addr)) {
pp_result = PP_ERROR_ADDRESS_INVALID;
break;
}
- SendConnectReply(context, PP_OK, local_addr, remote_addr);
+ SetStreams(std::move(receive_stream), std::move(send_stream));
+
+ bound_socket_.reset();
+
+ SendConnectReply(context, PP_OK, pp_local_addr, pp_remote_addr);
state_.CompletePendingTransition(true);
return;
} while (false);
- if (version_ == ppapi::TCP_SOCKET_VERSION_1_1_OR_ABOVE) {
- DCHECK_EQ(1u, address_list_.size());
+ // Handle errors.
- SendConnectError(context, pp_result);
- state_.CompletePendingTransition(false);
- } else {
- // We have to recreate |socket_| because it doesn't allow a second connect
- // attempt. We won't lose any state such as bound address or set options,
- // because in the private or v1.0 API, connect must be the first operation.
- socket_.reset(new net::TCPSocket(nullptr, nullptr, net::NetLogSource()));
-
- if (address_index_ + 1 < address_list_.size()) {
- DCHECK_EQ(version_, ppapi::TCP_SOCKET_VERSION_PRIVATE);
- address_index_++;
- StartConnect(context);
- } else {
- SendConnectError(context, pp_result);
- // In order to maintain backward compatibility, allow further attempts to
- // connect the socket.
- state_ = TCPSocketState(TCPSocketState::INITIAL);
- }
+ // This can happen even when the network service is behaving correctly, as
+ // we may see the |socket_observer_binding_| closed before receiving an
+ // error.
+ pending_read_pp_error_ = PP_OK_COMPLETIONPENDING;
+ pending_write_pp_error_ = PP_OK_COMPLETIONPENDING;
+
+ Close();
+ SendConnectError(context, pp_result);
+
+ if (version_ != ppapi::TCP_SOCKET_VERSION_1_1_OR_ABOVE) {
+ // In order to maintain backward compatibility, allow further attempts
+ // to connect the socket.
+ state_ = TCPSocketState(TCPSocketState::INITIAL);
}
}
void PepperTCPSocketMessageFilter::OnSSLHandshakeCompleted(
const ppapi::host::ReplyMessageContext& context,
- int net_result) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ int net_result,
+ mojo::ScopedDataPipeConsumerHandle receive_stream,
+ mojo::ScopedDataPipeProducerHandle send_stream,
+ const base::Optional<net::SSLInfo>& ssl_info) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
- if (!state_.IsPending(TCPSocketState::SSL_CONNECT)) {
- DCHECK(state_.state() == TCPSocketState::CLOSED);
- SendSSLHandshakeReply(context, PP_ERROR_FAILED);
+ int pp_result = NetErrorToPepperError(net_result);
+ if (state_.state() == TCPSocketState::CLOSED) {
+ // If this is called as a result of Close() being invoked and closing the
+ // pipe, fail the request without doing anything.
+ DCHECK_EQ(net_result, net::ERR_FAILED);
+ SendSSLHandshakeReply(context, pp_result, base::nullopt /* ssl_info */);
return;
}
- SendSSLHandshakeReply(context, NetErrorToPepperError(net_result));
- state_.CompletePendingTransition(net_result == net::OK);
-}
+ DCHECK(state_.IsPending(TCPSocketState::SSL_CONNECT));
-void PepperTCPSocketMessageFilter::OnReadCompleted(
- const ppapi::host::ReplyMessageContext& context,
- int net_result) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(read_buffer_.get());
+ if (pp_result == PP_OK && !ssl_info)
+ pp_result = PP_ERROR_FAILED;
- if (host_ && host_->IsThrottled(instance_)) {
- pending_read_on_unthrottle_ = true;
- pending_read_reply_message_context_ = context;
- pending_read_net_result_ = net_result;
- return;
- }
+ state_.CompletePendingTransition(pp_result == PP_OK);
- if (net_result > 0) {
- SendReadReply(
- context, PP_OK, std::string(read_buffer_->data(), net_result));
- } else if (net_result == 0) {
- end_of_file_reached_ = true;
- SendReadReply(context, PP_OK, std::string());
+ if (pp_result != PP_OK) {
+ Close();
} else {
- SendReadError(context, NetErrorToPepperError(net_result));
+ SetStreams(std::move(receive_stream), std::move(send_stream));
}
- read_buffer_ = nullptr;
+
+ SendSSLHandshakeReply(context, pp_result, ssl_info);
}
-void PepperTCPSocketMessageFilter::OnWriteCompleted(
+void PepperTCPSocketMessageFilter::OnBindCompleted(
const ppapi::host::ReplyMessageContext& context,
- int net_result) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(write_buffer_base_.get());
- DCHECK(write_buffer_.get());
-
- // Note: For partial writes of 0 bytes, don't continue writing to avoid a
- // likely infinite loop.
- if (net_result > 0) {
- write_buffer_->DidConsume(net_result);
- if (write_buffer_->BytesRemaining() > 0 && state_.IsConnected()) {
- DoWrite(context);
- return;
- }
+ int net_result,
+ const base::Optional<net::IPEndPoint>& local_addr) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ int pp_result = NetErrorToPepperError(net_result);
+ if (state_.state() == TCPSocketState::CLOSED) {
+ // If this is called as a result of Close() being invoked and closing the
+ // pipe, fail the request without doing anything.
+ DCHECK_EQ(net_result, net::ERR_FAILED);
+ SendBindError(context, pp_result);
+ return;
}
- if (net_result >= 0)
- SendWriteReply(context, write_buffer_->BytesConsumed());
- else
- SendWriteReply(context, NetErrorToPepperError(net_result));
+ DCHECK(bound_socket_);
+ DCHECK(state_.IsPending(TCPSocketState::BIND));
+
+ PP_NetAddress_Private bound_address =
+ NetAddressPrivateImpl::kInvalidNetAddress;
+ if (pp_result == PP_OK &&
+ (!local_addr || !NetAddressPrivateImpl::IPEndPointToNetAddress(
+ local_addr->address().bytes(), local_addr->port(),
+ &bound_address))) {
+ pp_result = PP_ERROR_ADDRESS_INVALID;
+ }
- write_buffer_ = nullptr;
- write_buffer_base_ = nullptr;
+ if (pp_result != PP_OK) {
+ bound_socket_.reset();
+ } else {
+ bind_output_ip_endpoint_ = *local_addr;
+ }
+
+ SendBindReply(context, pp_result, bound_address);
+ state_.CompletePendingTransition(pp_result == PP_OK);
}
void PepperTCPSocketMessageFilter::OnListenCompleted(
const ppapi::host::ReplyMessageContext& context,
- int32_t pp_result) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- SendListenReply(context, pp_result);
- state_.DoTransition(TCPSocketState::LISTEN, pp_result == PP_OK);
-}
+ int net_result) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
-#if defined(OS_CHROMEOS)
-void PepperTCPSocketMessageFilter::OpenFirewallHole(
- const ppapi::host::ReplyMessageContext& context,
- int32_t pp_result) {
- if (pp_result != PP_OK) {
+ int pp_result = NetErrorToPepperError(net_result);
+ if (state_.state() == TCPSocketState::CLOSED) {
+ // If this is called as a result of Close() being invoked and closing the
+ // pipe, fail the request without doing anything.
+ DCHECK_EQ(net_result, net::ERR_FAILED);
+ SendListenReply(context, pp_result);
return;
}
- net::IPEndPoint local_addr;
- // Has already been called successfully in DoBind().
- socket_->GetLocalAddress(&local_addr);
- pepper_socket_utils::FirewallHoleOpenCallback callback =
- base::Bind(&PepperTCPSocketMessageFilter::OnFirewallHoleOpened, this,
- context, pp_result);
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::BindOnce(&pepper_socket_utils::OpenTCPFirewallHole, local_addr,
- callback));
-}
+ DCHECK(state_.IsPending(TCPSocketState::LISTEN));
-void PepperTCPSocketMessageFilter::OnFirewallHoleOpened(
- const ppapi::host::ReplyMessageContext& context,
- int32_t result,
- std::unique_ptr<chromeos::FirewallHole> hole) {
- LOG_IF(WARNING, !hole.get()) << "Firewall hole could not be opened.";
- firewall_hole_.reset(hole.release());
+#if defined(OS_CHROMEOS)
+ if (pp_result == PP_OK) {
+ OpenFirewallHole(context);
+ return;
+ }
+#endif // defined(OS_CHROMEOS)
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&PepperTCPSocketMessageFilter::OnListenCompleted, this,
- context, result));
+ SendListenReply(context, pp_result);
+ state_.CompletePendingTransition(pp_result == PP_OK);
+ if (pp_result != PP_OK)
+ Close();
}
-#endif // defined(OS_CHROMEOS)
void PepperTCPSocketMessageFilter::OnAcceptCompleted(
const ppapi::host::ReplyMessageContext& context,
- int net_result) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ network::mojom::SocketObserverRequest socket_observer_request,
+ int net_result,
+ const base::Optional<net::IPEndPoint>& remote_addr,
+ network::mojom::TCPConnectedSocketPtr connected_socket,
+ mojo::ScopedDataPipeConsumerHandle receive_stream,
+ mojo::ScopedDataPipeProducerHandle send_stream) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(pending_accept_);
pending_accept_ = false;
-
if (net_result != net::OK) {
SendAcceptError(context, NetErrorToPepperError(net_result));
return;
}
- DCHECK(accepted_socket_.get());
-
- net::IPEndPoint ip_end_point_local;
- PP_NetAddress_Private local_addr = NetAddressPrivateImpl::kInvalidNetAddress;
- PP_NetAddress_Private remote_addr = NetAddressPrivateImpl::kInvalidNetAddress;
-
- int32_t pp_result = NetErrorToPepperError(
- accepted_socket_->GetLocalAddress(&ip_end_point_local));
- if (pp_result != PP_OK) {
- SendAcceptError(context, pp_result);
+ if (!remote_addr || !connected_socket.is_bound()) {
+ SendAcceptError(context, NetErrorToPepperError(net_result));
return;
}
+
+ DCHECK(socket_observer_request.is_pending());
+
+ PP_NetAddress_Private pp_remote_addr =
+ NetAddressPrivateImpl::kInvalidNetAddress;
+
if (!NetAddressPrivateImpl::IPEndPointToNetAddress(
- ip_end_point_local.address().bytes(), ip_end_point_local.port(),
- &local_addr) ||
- !NetAddressPrivateImpl::IPEndPointToNetAddress(
- accepted_address_.address().bytes(), accepted_address_.port(),
- &remote_addr)) {
+ remote_addr->address().bytes(), remote_addr->port(),
+ &pp_remote_addr)) {
SendAcceptError(context, PP_ERROR_ADDRESS_INVALID);
return;
}
+ PP_NetAddress_Private bound_address =
+ NetAddressPrivateImpl::kInvalidNetAddress;
+ bool success = NetAddressPrivateImpl::IPEndPointToNetAddress(
+ bind_output_ip_endpoint_.address().bytes(),
+ bind_output_ip_endpoint_.port(), &bound_address);
+ // This conversion should succeed, since it succeeded in OnBindComplete()
+ // already.
+ DCHECK(success);
+
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(&PepperTCPSocketMessageFilter::OnAcceptCompletedOnIOThread,
+ this, context, connected_socket.PassInterface(),
+ std::move(socket_observer_request),
+ std::move(receive_stream), std::move(send_stream),
+ bound_address, pp_remote_addr));
+}
+
+void PepperTCPSocketMessageFilter::OnAcceptCompletedOnIOThread(
+ const ppapi::host::ReplyMessageContext& context,
+ network::mojom::TCPConnectedSocketPtrInfo connected_socket,
+ network::mojom::SocketObserverRequest socket_observer_request,
+ mojo::ScopedDataPipeConsumerHandle receive_stream,
+ mojo::ScopedDataPipeProducerHandle send_stream,
+ PP_NetAddress_Private pp_local_addr,
+ PP_NetAddress_Private pp_remote_addr) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
// |factory_| is guaranteed to be non-NULL here. Only those instances created
// in CONNECTED state have a NULL |factory_|, while getting here requires
// LISTENING state.
+ DCHECK(factory_);
+
std::unique_ptr<ppapi::host::ResourceHost> host =
- factory_->CreateAcceptedTCPSocket(instance_, version_,
- std::move(accepted_socket_));
+ factory_->CreateAcceptedTCPSocket(
+ instance_, version_, std::move(connected_socket),
+ std::move(socket_observer_request), std::move(receive_stream),
+ std::move(send_stream));
if (!host) {
SendAcceptError(context, PP_ERROR_NOSPACE);
return;
}
+
int pending_host_id =
host_->GetPpapiHost()->AddPendingResourceHost(std::move(host));
- if (pending_host_id)
- SendAcceptReply(context, PP_OK, pending_host_id, local_addr, remote_addr);
- else
+ if (pending_host_id) {
+ SendAcceptReply(context, PP_OK, pending_host_id, pp_local_addr,
+ pp_remote_addr);
+ } else {
SendAcceptError(context, PP_ERROR_NOSPACE);
+ }
}
+void PepperTCPSocketMessageFilter::SetStreams(
+ mojo::ScopedDataPipeConsumerHandle receive_stream,
+ mojo::ScopedDataPipeProducerHandle send_stream) {
+ DCHECK(!read_watcher_);
+ DCHECK(!write_watcher_);
+
+ receive_stream_ = std::move(receive_stream);
+ read_watcher_ = std::make_unique<mojo::SimpleWatcher>(
+ FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::MANUAL);
+ read_watcher_->Watch(
+ receive_stream_.get(),
+ MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
+ base::BindRepeating(
+ [](PepperTCPSocketMessageFilter* message_filter,
+ MojoResult /* result */,
+ const mojo::HandleSignalsState& /* state */) {
+ // TryRead will correctly handle both cases (data ready to be
+ // read, and the pipe was closed).
+ message_filter->TryRead();
+ },
+ base::Unretained(this)));
+
+ send_stream_ = std::move(send_stream);
+ write_watcher_ = std::make_unique<mojo::SimpleWatcher>(
+ FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::MANUAL);
+ write_watcher_->Watch(
+ send_stream_.get(),
+ MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
+ base::BindRepeating(
+ [](PepperTCPSocketMessageFilter* message_filter,
+ MojoResult /* result */,
+ const mojo::HandleSignalsState& /* state */) {
+ // TryRead will correctly handle both cases (data ready to be
+ // read, and the pipe was closed).
+ message_filter->TryWrite();
+ },
+ base::Unretained(this)));
+}
+
+#if defined(OS_CHROMEOS)
+void PepperTCPSocketMessageFilter::OpenFirewallHole(
+ const ppapi::host::ReplyMessageContext& context) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ pepper_socket_utils::FirewallHoleOpenCallback callback = base::BindRepeating(
+ &PepperTCPSocketMessageFilter::OnFirewallHoleOpened, this, context);
+ pepper_socket_utils::OpenTCPFirewallHole(bind_output_ip_endpoint_, callback);
+}
+
+void PepperTCPSocketMessageFilter::OnFirewallHoleOpened(
+ const ppapi::host::ReplyMessageContext& context,
+ std::unique_ptr<chromeos::FirewallHole> hole) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(state_.IsPending(TCPSocketState::LISTEN));
+ LOG_IF(WARNING, !hole.get()) << "Firewall hole could not be opened.";
+ firewall_hole_.reset(hole.release());
+
+ SendListenReply(context, PP_OK);
+ state_.CompletePendingTransition(true);
+}
+#endif // defined(OS_CHROMEOS)
+
void PepperTCPSocketMessageFilter::SendBindReply(
const ppapi::host::ReplyMessageContext& context,
int32_t pp_result,
@@ -1069,24 +1251,21 @@ void PepperTCPSocketMessageFilter::SendConnectReply(
void PepperTCPSocketMessageFilter::SendConnectError(
const ppapi::host::ReplyMessageContext& context,
int32_t pp_error) {
- SendConnectReply(context,
- pp_error,
- NetAddressPrivateImpl::kInvalidNetAddress,
+ SendConnectReply(context, pp_error, NetAddressPrivateImpl::kInvalidNetAddress,
NetAddressPrivateImpl::kInvalidNetAddress);
}
void PepperTCPSocketMessageFilter::SendSSLHandshakeReply(
const ppapi::host::ReplyMessageContext& context,
- int32_t pp_result) {
+ int32_t pp_result,
+ const base::Optional<net::SSLInfo>& ssl_info) {
ppapi::host::ReplyMessageContext reply_context(context);
reply_context.params.set_result(pp_result);
ppapi::PPB_X509Certificate_Fields certificate_fields;
if (pp_result == PP_OK) {
- // Our socket is guaranteed to be an SSL socket if we get here.
- net::SSLInfo ssl_info;
- ssl_socket_->GetSSLInfo(&ssl_info);
- if (ssl_info.cert.get()) {
- pepper_socket_utils::GetCertificateFields(*ssl_info.cert.get(),
+ DCHECK(ssl_info);
+ if (ssl_info->cert.get()) {
+ pepper_socket_utils::GetCertificateFields(*ssl_info->cert,
&certificate_fields);
}
}
@@ -1094,27 +1273,36 @@ void PepperTCPSocketMessageFilter::SendSSLHandshakeReply(
PpapiPluginMsg_TCPSocket_SSLHandshakeReply(certificate_fields));
}
-void PepperTCPSocketMessageFilter::SendReadReply(
- const ppapi::host::ReplyMessageContext& context,
- int32_t pp_result,
- const std::string& data) {
- ppapi::host::ReplyMessageContext reply_context(context);
- reply_context.params.set_result(pp_result);
- SendReply(reply_context, PpapiPluginMsg_TCPSocket_ReadReply(data));
+void PepperTCPSocketMessageFilter::SendReadReply(int32_t pp_result,
+ const std::string& data) {
+ DCHECK(pending_read_context_.is_valid());
+ DCHECK_GT(pending_read_size_, 0u);
+
+ pending_read_context_.params.set_result(pp_result);
+ SendReply(pending_read_context_, PpapiPluginMsg_TCPSocket_ReadReply(data));
+
+ pending_read_context_ = ppapi::host::ReplyMessageContext();
+ pending_read_size_ = 0;
}
-void PepperTCPSocketMessageFilter::SendReadError(
- const ppapi::host::ReplyMessageContext& context,
- int32_t pp_error) {
- SendReadReply(context, pp_error, std::string());
+void PepperTCPSocketMessageFilter::SendReadError(int32_t pp_error) {
+ SendReadReply(pp_error, std::string());
}
-void PepperTCPSocketMessageFilter::SendWriteReply(
- const ppapi::host::ReplyMessageContext& context,
- int32_t pp_result) {
- ppapi::host::ReplyMessageContext reply_context(context);
- reply_context.params.set_result(pp_result);
- SendReply(reply_context, PpapiPluginMsg_TCPSocket_WriteReply());
+void PepperTCPSocketMessageFilter::SendWriteReply(int32_t pp_result) {
+ DCHECK(pending_write_context_.is_valid());
+ DCHECK(!pending_write_data_.empty());
+ DCHECK(pp_result <= 0 ||
+ static_cast<uint32_t>(pp_result) == pending_write_data_.size());
+ DCHECK(pp_result <= 0 ||
+ static_cast<uint32_t>(pp_result) == pending_write_bytes_written_);
+
+ pending_write_context_.params.set_result(pp_result);
+ SendReply(pending_write_context_, PpapiPluginMsg_TCPSocket_WriteReply());
+
+ pending_write_context_ = ppapi::host::ReplyMessageContext();
+ pending_write_data_.clear();
+ pending_write_bytes_written_ = 0;
}
void PepperTCPSocketMessageFilter::SendListenReply(
@@ -1133,19 +1321,77 @@ void PepperTCPSocketMessageFilter::SendAcceptReply(
const PP_NetAddress_Private& remote_addr) {
ppapi::host::ReplyMessageContext reply_context(context);
reply_context.params.set_result(pp_result);
- SendReply(reply_context,
- PpapiPluginMsg_TCPSocket_AcceptReply(
- pending_host_id, local_addr, remote_addr));
+ SendReply(reply_context, PpapiPluginMsg_TCPSocket_AcceptReply(
+ pending_host_id, local_addr, remote_addr));
}
void PepperTCPSocketMessageFilter::SendAcceptError(
const ppapi::host::ReplyMessageContext& context,
int32_t pp_error) {
- SendAcceptReply(context,
- pp_error,
- 0,
+ SendAcceptReply(context, pp_error, 0,
NetAddressPrivateImpl::kInvalidNetAddress,
NetAddressPrivateImpl::kInvalidNetAddress);
}
+void PepperTCPSocketMessageFilter::Close() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ // Need to do these first, as destroying Mojo pipes may invoke some of the
+ // callbacks with failure messages.
+ weak_ptr_factory_.InvalidateWeakPtrs();
+ state_.DoTransition(TCPSocketState::CLOSE, true);
+
+#if defined(OS_CHROMEOS)
+ // Close the firewall hole, it is no longer needed.
+ firewall_hole_.reset();
+#endif // defined(OS_CHROMEOS)
+
+ // Make sure there are no further callbacks from Mojo, which could end up in a
+ // double free (Add ref on the UI thread, while a deletion is pending on the
+ // IO thread), and that they're closed on the correct thread.
+ bound_socket_.reset();
+ connected_socket_.reset();
+ tls_client_socket_.reset();
+ server_socket_.reset();
+ binding_.Close();
+ socket_observer_binding_.Close();
+
+ read_watcher_.reset();
+ receive_stream_.reset();
+ write_watcher_.reset();
+ send_stream_.reset();
+}
+
+network::mojom::NetworkContext*
+PepperTCPSocketMessageFilter::GetNetworkContext() const {
+ if (network_context_for_testing)
+ return network_context_for_testing;
+
+ RenderProcessHost* render_process_host =
+ RenderProcessHost::FromID(render_process_id_);
+ if (!render_process_host)
+ return nullptr;
+
+ return render_process_host->GetStoragePartition()->GetNetworkContext();
+}
+
+template <class ReturnMessage>
+base::OnceCallback<void(int result)>
+PepperTCPSocketMessageFilter::CreateCompletionCallback(
+ const ppapi::host::HostMessageContext* context) {
+ return mojo::WrapCallbackWithDefaultInvokeIfNotRun(
+ base::BindOnce(&PepperTCPSocketMessageFilter::ReturnResult<ReturnMessage>,
+ base::Unretained(this),
+ context->MakeReplyMessageContext()),
+ net::ERR_FAILED);
+}
+
+template <class ReturnMessage>
+void PepperTCPSocketMessageFilter::ReturnResult(
+ ppapi::host::ReplyMessageContext context,
+ int net_result) {
+ context.params.set_result(NetErrorToPepperError(net_result));
+ SendReply(context, ReturnMessage());
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.h b/chromium/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.h
index 03648b64ef4..8c49f6c4268 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.h
+++ b/chromium/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.h
@@ -15,32 +15,28 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "base/optional.h"
#include "build/build_config.h"
#include "content/browser/renderer_host/pepper/browser_ppapi_host_impl.h"
-#include "content/browser/renderer_host/pepper/ssl_context_helper.h"
#include "content/common/content_export.h"
#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/system/data_pipe.h"
#include "net/base/address_list.h"
#include "net/base/ip_endpoint.h"
-#include "net/socket/tcp_socket.h"
#include "ppapi/c/pp_instance.h"
#include "ppapi/c/ppb_tcp_socket.h"
#include "ppapi/c/private/ppb_net_address_private.h"
#include "ppapi/host/resource_message_filter.h"
#include "ppapi/shared_impl/ppb_tcp_socket_shared.h"
#include "services/network/public/mojom/network_context.mojom.h"
+#include "services/network/public/mojom/tcp_socket.mojom.h"
+#include "services/network/public/mojom/tls_socket.mojom.h"
#if defined(OS_CHROMEOS)
#include "chromeos/network/firewall_hole.h"
-#include "content/public/browser/browser_thread.h"
#endif // defined(OS_CHROMEOS)
-namespace net {
-class DrainableIOBuffer;
-class IOBuffer;
-class SSLClientSocket;
-}
-
namespace ppapi {
class SocketOptionData;
@@ -54,21 +50,38 @@ namespace content {
class BrowserPpapiHostImpl;
class ContentBrowserPepperHostFactory;
+// Handles communication between Pepper and TCP socket Mojo interfaces. The Mojo
+// interfaces and all class variables live on the UI thread, while the class is
+// created on and receives IPCs on the IO thread (The IPCs are then passed to
+// the UI thread).
class CONTENT_EXPORT PepperTCPSocketMessageFilter
: public ppapi::host::ResourceMessageFilter,
public BrowserPpapiHostImpl::InstanceObserver,
- public network::mojom::ResolveHostClient {
+ public network::mojom::ResolveHostClient,
+ public network::mojom::SocketObserver {
public:
+ // |factory| must be non-nullptr unless the consumer immediately calls
+ // SetConnectedSocket(). SetConnectedSocket() must be a separate method,
+ // because something must already be holding onto a reference to |this| when a
+ // task is posted to the UI thread (Which requires grabbing another reference,
+ // which could potentially be released before the constructor returns).
PepperTCPSocketMessageFilter(ContentBrowserPepperHostFactory* factory,
BrowserPpapiHostImpl* host,
PP_Instance instance,
ppapi::TCPSocketVersion version);
- // Used for creating already connected sockets.
- PepperTCPSocketMessageFilter(BrowserPpapiHostImpl* host,
- PP_Instance instance,
- ppapi::TCPSocketVersion version,
- std::unique_ptr<net::TCPSocket> socket);
+ // Switches state to CONNECTED using the provided pipes. May only be called
+ // before any messages are received,
+ void SetConnectedSocket(
+ network::mojom::TCPConnectedSocketPtrInfo connected_socket,
+ network::mojom::SocketObserverRequest socket_observer_request,
+ mojo::ScopedDataPipeConsumerHandle receive_stream,
+ mojo::ScopedDataPipeProducerHandle send_stream);
+
+ // Sets a global NetworkContext object to be used instead of the real one for
+ // doing all network operations.
+ static void SetNetworkContextForTesting(
+ network::mojom::NetworkContext* network_context);
static size_t GetNumInstances();
@@ -81,7 +94,14 @@ class CONTENT_EXPORT PepperTCPSocketMessageFilter
~PepperTCPSocketMessageFilter() override;
+ void SetConnectedSocketOnUIThread(
+ network::mojom::TCPConnectedSocketPtrInfo connected_socket,
+ network::mojom::SocketObserverRequest socket_observer_request,
+ mojo::ScopedDataPipeConsumerHandle receive_stream,
+ mojo::ScopedDataPipeProducerHandle send_stream);
+
// ppapi::host::ResourceMessageFilter overrides.
+ void OnFilterDestroyed() override;
scoped_refptr<base::TaskRunner> OverrideTaskRunnerForMessage(
const IPC::Message& message) override;
int32_t OnResourceMessageReceived(
@@ -92,11 +112,21 @@ class CONTENT_EXPORT PepperTCPSocketMessageFilter
void OnThrottleStateChanged(bool is_throttled) override;
void OnHostDestroyed() override;
+ void ThrottleStateChangedOnUIThread(bool is_throttled);
+
// network::mojom::ResolveHostClient overrides.
void OnComplete(
int result,
const base::Optional<net::AddressList>& resolved_addresses) override;
+ // network::mojom::SocketObserver overrides.
+ void OnReadError(int net_error) override;
+ void OnWriteError(int net_error) override;
+
+ // Called either when the SocketObserver Mojo pipe has an error, or bad data
+ // is received from it.
+ void OnSocketObserverError();
+
int32_t OnMsgBind(const ppapi::host::HostMessageContext* context,
const PP_NetAddress_Private& net_addr);
int32_t OnMsgConnect(const ppapi::host::HostMessageContext* context,
@@ -123,38 +153,73 @@ class CONTENT_EXPORT PepperTCPSocketMessageFilter
PP_TCPSocket_Option name,
const ppapi::SocketOptionData& value);
- void DoBind(const ppapi::host::ReplyMessageContext& context,
- const PP_NetAddress_Private& net_addr);
- void HostResolvingStarted(const ppapi::host::ReplyMessageContext& context);
- void DoConnectWithNetAddress(const ppapi::host::ReplyMessageContext& context,
- const PP_NetAddress_Private& net_addr);
- void DoWrite(const ppapi::host::ReplyMessageContext& context);
- void DoListen(const ppapi::host::ReplyMessageContext& context,
- int32_t backlog);
+ // Attempts to read up to |pending_read_size_| bytes from |receive_stream_|.
+ // If any bytes are read, or there's an error, returns that information to
+ // |pending_read_context_|.
+ void TryRead();
+
+ // Attempts to write |pending_write_data_| to |send_stream_|.
+ // |pending_write_bytes_written_| reflects how much of the data has been
+ // written to the stream so far. Once all bytes are written, or there's an
+ // error, returns that information to |pending_write_context_|.
+ void TryWrite();
void OnResolveCompleted(
int net_result,
const base::Optional<net::AddressList>& resolved_addresses);
- void StartConnect(const ppapi::host::ReplyMessageContext& context);
+
+ // Attempts to connect to all addresses in |address_list| in order.
+ void StartConnect(const ppapi::host::ReplyMessageContext& context,
+ const net::AddressList& address_list);
void OnConnectCompleted(const ppapi::host::ReplyMessageContext& context,
- int net_result);
- void OnSSLHandshakeCompleted(const ppapi::host::ReplyMessageContext& context,
- int net_result);
- void OnReadCompleted(const ppapi::host::ReplyMessageContext& context,
- int net_result);
- void OnWriteCompleted(const ppapi::host::ReplyMessageContext& context,
- int net_result);
- void OnAcceptCompleted(const ppapi::host::ReplyMessageContext& context,
- int net_result);
+ int net_result,
+ const base::Optional<net::IPEndPoint>& local_addr,
+ const base::Optional<net::IPEndPoint>& peer_addr,
+ mojo::ScopedDataPipeConsumerHandle receive_stream,
+ mojo::ScopedDataPipeProducerHandle send_stream);
+
+ void OnSSLHandshakeCompleted(
+ const ppapi::host::ReplyMessageContext& context,
+ int net_result,
+ mojo::ScopedDataPipeConsumerHandle receive_stream,
+ mojo::ScopedDataPipeProducerHandle send_stream,
+ const base::Optional<net::SSLInfo>& ssl_info);
void OnListenCompleted(const ppapi::host::ReplyMessageContext& context,
- int32_t pp_result);
+ int net_result);
+
+ void OnBindCompleted(const ppapi::host::ReplyMessageContext& context,
+ int net_result,
+ const base::Optional<net::IPEndPoint>& local_addr);
+
+ void OnAcceptCompleted(
+ const ppapi::host::ReplyMessageContext& context,
+ network::mojom::SocketObserverRequest socket_observer_request,
+ int net_result,
+ const base::Optional<net::IPEndPoint>& remote_addr,
+ network::mojom::TCPConnectedSocketPtr connected_socket,
+ mojo::ScopedDataPipeConsumerHandle receive_stream,
+ mojo::ScopedDataPipeProducerHandle send_stream);
+
+ void OnAcceptCompletedOnIOThread(
+ const ppapi::host::ReplyMessageContext& context,
+ network::mojom::TCPConnectedSocketPtrInfo connected_socket,
+ network::mojom::SocketObserverRequest socket_observer_request,
+ mojo::ScopedDataPipeConsumerHandle receive_stream,
+ mojo::ScopedDataPipeProducerHandle send_stream,
+ PP_NetAddress_Private pp_local_addr,
+ PP_NetAddress_Private pp_remote_addr);
+
+ // Sets the read/write streams and constructs watchers for them, which are not
+ // armed until there's an attempt to use them that can't complete
+ // synchronously.
+ void SetStreams(mojo::ScopedDataPipeConsumerHandle receive_stream,
+ mojo::ScopedDataPipeProducerHandle send_stream);
+
#if defined(OS_CHROMEOS)
- void OpenFirewallHole(const ppapi::host::ReplyMessageContext& context,
- int32_t pp_result);
+ void OpenFirewallHole(const ppapi::host::ReplyMessageContext& context);
void OnFirewallHoleOpened(const ppapi::host::ReplyMessageContext& context,
- int32_t result,
std::unique_ptr<chromeos::FirewallHole> hole);
#endif // defined(OS_CHROMEOS)
@@ -170,14 +235,13 @@ class CONTENT_EXPORT PepperTCPSocketMessageFilter
void SendConnectError(const ppapi::host::ReplyMessageContext& context,
int32_t pp_error);
void SendSSLHandshakeReply(const ppapi::host::ReplyMessageContext& context,
- int32_t pp_result);
- void SendReadReply(const ppapi::host::ReplyMessageContext& context,
- int32_t pp_result,
- const std::string& data);
- void SendReadError(const ppapi::host::ReplyMessageContext& context,
- int32_t pp_error);
- void SendWriteReply(const ppapi::host::ReplyMessageContext& context,
- int32_t pp_result);
+ int32_t pp_result,
+ const base::Optional<net::SSLInfo>& ssl_info);
+ // The read and write reply messages use the |pending_*_context_| fields, and
+ // clear fields related to the pending read / write request as needed.
+ void SendReadReply(int32_t pp_result, const std::string& data);
+ void SendReadError(int32_t pp_error);
+ void SendWriteReply(int32_t pp_result);
void SendListenReply(const ppapi::host::ReplyMessageContext& context,
int32_t pp_result);
void SendAcceptReply(const ppapi::host::ReplyMessageContext& context,
@@ -188,47 +252,64 @@ class CONTENT_EXPORT PepperTCPSocketMessageFilter
void SendAcceptError(const ppapi::host::ReplyMessageContext& context,
int32_t pp_error);
+ // Closes any open Mojo pipe, and prevents new ones from being opened.
+ void Close();
+
+ network::mojom::NetworkContext* GetNetworkContext() const;
+
bool IsPrivateAPI() const {
return version_ == ppapi::TCP_SOCKET_VERSION_PRIVATE;
}
+ // These are used to create a callback that:
+ // 1) if invoked with a network error code, will pass a message of the
+ // requested type to |context| with the corresponding Pepper error.
+ // 2) If destroyed without being invoked, will pass a message of the requested
+ // type to |context| with PP_ERROR_FAILED.
+ template <class ReturnMessage>
+ base::OnceCallback<void(int net_result)> CreateCompletionCallback(
+ const ppapi::host::HostMessageContext* context);
+ template <class ReturnMessage>
+ void ReturnResult(ppapi::host::ReplyMessageContext context, int net_result);
+
// The following fields are used on both the UI and IO thread.
const ppapi::TCPSocketVersion version_;
+ // The following fields are used only on the IO thread.
+ // Non-owning ptr.
+ BrowserPpapiHostImpl* host_;
+ // Non-owning ptr.
+ ContentBrowserPepperHostFactory* factory_;
+ PP_Instance instance_;
+
// The following fields are used only on the UI thread.
const bool external_plugin_;
+ // Mirrors state of host_->IsThrottled(), but is on UI thread.
+ bool is_throttled_;
+
int render_process_id_;
int render_frame_id_;
// A reference to |this| must always be taken while |binding_| is bound to
// ensure that if the error callback is called the object is alive.
mojo::Binding<network::mojom::ResolveHostClient> binding_;
-
- // The following fields are used only on the IO thread.
- // Non-owning ptr.
- BrowserPpapiHostImpl* host_;
- // Non-owning ptr.
- ContentBrowserPepperHostFactory* factory_;
- PP_Instance instance_;
+ mojo::Binding<network::mojom::SocketObserver> socket_observer_binding_;
ppapi::TCPSocketState state_;
- bool end_of_file_reached_;
// This is the address requested to bind. Please note that this is not the
// bound address. For example, |bind_input_addr_| may have port set to 0.
// It is used to check permission for listening.
PP_NetAddress_Private bind_input_addr_;
+ // The bound address.
+ net::IPEndPoint bind_output_ip_endpoint_;
+
#if defined(OS_CHROMEOS)
- std::unique_ptr<chromeos::FirewallHole,
- content::BrowserThread::DeleteOnUIThread>
- firewall_hole_;
+ std::unique_ptr<chromeos::FirewallHole> firewall_hole_;
#endif // defined(OS_CHROMEOS)
- // Used for DNS request.
- std::unique_ptr<net::HostResolver::Request> request_;
-
// Bitwise-or of SocketOption flags. This stores the state about whether
// each option is set before Connect() is called.
int socket_options_;
@@ -237,42 +318,56 @@ class CONTENT_EXPORT PepperTCPSocketMessageFilter
int32_t rcvbuf_size_;
int32_t sndbuf_size_;
- // |address_list_| may store multiple addresses when
- // PPB_TCPSocket_Private.Connect() is used, which involves name resolution.
- // In that case, we will try each address in the list until a connection is
- // successfully established.
- net::AddressList address_list_;
- // Where we are in the above list.
- size_t address_index_;
ppapi::host::ReplyMessageContext host_resolve_context_;
- // Non-null unless an SSL connection is requested.
- std::unique_ptr<net::TCPSocket> socket_;
- // Non-null if an SSL connection is requested.
- std::unique_ptr<net::SSLClientSocket> ssl_socket_;
-
- scoped_refptr<net::IOBuffer> read_buffer_;
-
- // TCPSocket::Write() may not always write the full buffer, but we would
- // rather have our DoWrite() do so whenever possible. To do this, we may have
- // to call the former multiple times for each of the latter. This entails
- // using a DrainableIOBuffer, which requires an underlying base IOBuffer.
- scoped_refptr<net::IOBuffer> write_buffer_base_;
- scoped_refptr<net::DrainableIOBuffer> write_buffer_;
- scoped_refptr<SSLContextHelper> ssl_context_helper_;
+ // Holds socket if Bind() is called. Will be used to create a connected or
+ // server socket, depending on the next call.
+ network::mojom::TCPBoundSocketPtr bound_socket_;
+ // Holds socket if Connect() is called.
+ network::mojom::TCPConnectedSocketPtr connected_socket_;
+ // Holds socket if socket was upgraded to SSL.
+ network::mojom::TLSClientSocketPtr tls_client_socket_;
+ // Holds socket if Listen() is called.
+ network::mojom::TCPServerSocketPtr server_socket_;
+
+ // Read/write pipes and their watchers. Both the watchers are configured so
+ // that they must be armed to receive a notification.
+ mojo::ScopedDataPipeConsumerHandle receive_stream_;
+ std::unique_ptr<mojo::SimpleWatcher> read_watcher_;
+ mojo::ScopedDataPipeProducerHandle send_stream_;
+ std::unique_ptr<mojo::SimpleWatcher> write_watcher_;
bool pending_accept_;
- std::unique_ptr<net::TCPSocket> accepted_socket_;
- net::IPEndPoint accepted_address_;
+ uint32_t pending_read_size_;
+ ppapi::host::ReplyMessageContext pending_read_context_;
+ // This is set to an error other than PP_OK_COMPLETIONPENDING when a read
+ // error is received through the SocketObserver interface. If the
+ // SocketObserver interface is destroyed and this still hasn't been changed
+ // from its initial value of PP_OK_COMPLETIONPENDING, it's set to
+ // PP_ERROR_FAILED.
+ int pending_read_pp_error_;
// If the plugin is throttled, we defer completing socket reads until
// the plugin is unthrottled.
bool pending_read_on_unthrottle_;
- ppapi::host::ReplyMessageContext pending_read_reply_message_context_;
- int pending_read_net_result_;
+
+ std::string pending_write_data_;
+ // Number of bytes from |pending_write_data_| that have already been written.
+ // Always less than the size of |pending_write_data_|.
+ size_t pending_write_bytes_written_;
+ ppapi::host::ReplyMessageContext pending_write_context_;
+ // This mirrors |pending_read_pp_error_|.
+ int pending_write_pp_error_;
const bool is_potentially_secure_plugin_context_;
+ // Used in place of the StoragePartition's NetworkContext when non-null.
+ static network::mojom::NetworkContext* network_context_for_testing;
+
+ // Vends weak pointers on the UI thread, for callbacks passed through Mojo
+ // pipes not owned by |this|. All weak pointers released in Close().
+ base::WeakPtrFactory<PepperTCPSocketMessageFilter> weak_ptr_factory_;
+
DISALLOW_COPY_AND_ASSIGN(PepperTCPSocketMessageFilter);
};
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.cc b/chromium/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.cc
index 7a19d458a19..2bc70d2b4cd 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.cc
@@ -10,10 +10,12 @@
#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
+#include "base/task/post_task.h"
#include "build/build_config.h"
#include "content/browser/renderer_host/pepper/browser_ppapi_host_impl.h"
#include "content/browser/renderer_host/pepper/pepper_socket_utils.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/render_frame_host.h"
@@ -130,8 +132,8 @@ void PepperUDPSocketMessageFilter::OnFilterDestroyed() {
// that future messages will be ignored, so the mojo pipes won't be
// re-created, so after Close() runs, |this| can be safely deleted on the IO
// thread.
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&PepperUDPSocketMessageFilter::Close, this));
}
@@ -146,7 +148,7 @@ PepperUDPSocketMessageFilter::OverrideTaskRunnerForMessage(
case PpapiHostMsg_UDPSocket_SendTo::ID:
case PpapiHostMsg_UDPSocket_JoinGroup::ID:
case PpapiHostMsg_UDPSocket_LeaveGroup::ID:
- return BrowserThread::GetTaskRunnerForThread(BrowserThread::UI);
+ return base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::UI});
}
return nullptr;
}
@@ -717,8 +719,8 @@ void PepperUDPSocketMessageFilter::SendRecvFromResult(
const PP_NetAddress_Private& addr) {
// Unlike SendReply, which is safe to call on any thread, SendUnsolicitedReply
// calls are only safe to make on the IO thread.
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&PepperUDPSocketMessageFilter::SendRecvFromResultOnIOThread, this,
result, data, addr));
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_vpn_provider_message_filter_chromeos.cc b/chromium/content/browser/renderer_host/pepper/pepper_vpn_provider_message_filter_chromeos.cc
index 232ed55c4eb..15eeaa43a17 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_vpn_provider_message_filter_chromeos.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_vpn_provider_message_filter_chromeos.cc
@@ -4,6 +4,8 @@
#include "content/browser/renderer_host/pepper/pepper_vpn_provider_message_filter_chromeos.h"
+#include "base/task/post_task.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/pepper_vpn_provider_resource_host_proxy.h"
@@ -93,7 +95,7 @@ PepperVpnProviderMessageFilter::OverrideTaskRunnerForMessage(
case PpapiHostMsg_VpnProvider_Bind::ID:
case PpapiHostMsg_VpnProvider_SendPacket::ID:
case PpapiHostMsg_VpnProvider_OnPacketReceivedReply::ID:
- return BrowserThread::GetTaskRunnerForThread(BrowserThread::UI);
+ return base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::UI});
}
return nullptr;
}
diff --git a/chromium/content/browser/renderer_host/pepper/quota_reservation.cc b/chromium/content/browser/renderer_host/pepper/quota_reservation.cc
index 932c7dd645d..72f61233fea 100644
--- a/chromium/content/browser/renderer_host/pepper/quota_reservation.cc
+++ b/chromium/content/browser/renderer_host/pepper/quota_reservation.cc
@@ -8,6 +8,8 @@
#include "base/bind.h"
#include "base/callback.h"
+#include "base/task/post_task.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "storage/browser/fileapi/file_system_operation_runner.h"
#include "storage/browser/fileapi/quota/open_file_handle.h"
@@ -46,7 +48,7 @@ QuotaReservation::QuotaReservation(
QuotaReservation::~QuotaReservation() {
// We should have no open files at this point.
DCHECK(files_.size() == 0);
- for (FileMap::iterator it = files_.begin(); it != files_.end(); ++it)
+ for (auto it = files_.begin(); it != files_.end(); ++it)
delete it->second;
}
@@ -81,7 +83,7 @@ int64_t QuotaReservation::OpenFile(int32_t id,
void QuotaReservation::CloseFile(int32_t id,
const ppapi::FileGrowth& file_growth) {
- FileMap::iterator it = files_.find(id);
+ auto it = files_.find(id);
if (it != files_.end()) {
it->second->UpdateMaxWrittenOffset(file_growth.max_written_offset);
it->second->AddAppendModeWriteAmount(file_growth.append_mode_write_amount);
@@ -95,9 +97,8 @@ void QuotaReservation::CloseFile(int32_t id,
void QuotaReservation::ReserveQuota(int64_t amount,
const ppapi::FileGrowthMap& file_growths,
const ReserveQuotaCallback& callback) {
- for (FileMap::iterator it = files_.begin(); it != files_.end(); ++it) {
- ppapi::FileGrowthMap::const_iterator growth_it =
- file_growths.find(it->first);
+ for (auto it = files_.begin(); it != files_.end(); ++it) {
+ auto growth_it = file_growths.find(it->first);
if (growth_it != file_growths.end()) {
it->second->UpdateMaxWrittenOffset(growth_it->second.max_written_offset);
it->second->AddAppendModeWriteAmount(
@@ -116,12 +117,12 @@ void QuotaReservation::OnClientCrash() { quota_reservation_->OnClientCrash(); }
void QuotaReservation::GotReservedQuota(const ReserveQuotaCallback& callback,
base::File::Error error) {
ppapi::FileSizeMap file_sizes;
- for (FileMap::iterator it = files_.begin(); it != files_.end(); ++it)
+ for (auto it = files_.begin(); it != files_.end(); ++it)
file_sizes[it->first] = it->second->GetMaxWrittenOffset();
if (file_system_context_.get()) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(callback, quota_reservation_->remaining_quota(),
file_sizes));
} else {
diff --git a/chromium/content/browser/renderer_host/pepper/quota_reservation_unittest.cc b/chromium/content/browser/renderer_host/pepper/quota_reservation_unittest.cc
index 204ed5af76e..cc2f82f564a 100644
--- a/chromium/content/browser/renderer_host/pepper/quota_reservation_unittest.cc
+++ b/chromium/content/browser/renderer_host/pepper/quota_reservation_unittest.cc
@@ -136,9 +136,8 @@ void GotReservedQuota(int64_t* reserved_quota_ptr,
*reserved_quota_ptr = reserved_quota;
file_growths_ptr->clear();
- for (ppapi::FileSizeMap::const_iterator it = maximum_written_offsets.begin();
- it != maximum_written_offsets.end();
- ++it)
+ for (auto it = maximum_written_offsets.begin();
+ it != maximum_written_offsets.end(); ++it)
(*file_growths_ptr)[it->first] = ppapi::FileGrowth(it->second, 0);
}
diff --git a/chromium/content/browser/renderer_host/pepper/ssl_context_helper.cc b/chromium/content/browser/renderer_host/pepper/ssl_context_helper.cc
deleted file mode 100644
index 1d6fb4c9621..00000000000
--- a/chromium/content/browser/renderer_host/pepper/ssl_context_helper.cc
+++ /dev/null
@@ -1,42 +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/pepper/ssl_context_helper.h"
-
-#include "net/cert/cert_verifier.h"
-#include "net/cert/ct_policy_enforcer.h"
-#include "net/cert/multi_log_ct_verifier.h"
-#include "net/http/transport_security_state.h"
-
-namespace content {
-
-SSLContextHelper::SSLContextHelper() {}
-
-SSLContextHelper::~SSLContextHelper() {}
-
-net::CertVerifier* SSLContextHelper::GetCertVerifier() {
- if (!cert_verifier_)
- cert_verifier_ = net::CertVerifier::CreateDefault();
- return cert_verifier_.get();
-}
-
-net::TransportSecurityState* SSLContextHelper::GetTransportSecurityState() {
- if (!transport_security_state_)
- transport_security_state_.reset(new net::TransportSecurityState());
- return transport_security_state_.get();
-}
-
-net::CTVerifier* SSLContextHelper::GetCertTransparencyVerifier() {
- if (!cert_transparency_verifier_)
- cert_transparency_verifier_.reset(new net::MultiLogCTVerifier());
- return cert_transparency_verifier_.get();
-}
-
-net::CTPolicyEnforcer* SSLContextHelper::GetCTPolicyEnforcer() {
- if (!ct_policy_enforcer_)
- ct_policy_enforcer_.reset(new net::DefaultCTPolicyEnforcer());
- return ct_policy_enforcer_.get();
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/pepper/ssl_context_helper.h b/chromium/content/browser/renderer_host/pepper/ssl_context_helper.h
deleted file mode 100644
index d2b880ec96e..00000000000
--- a/chromium/content/browser/renderer_host/pepper/ssl_context_helper.h
+++ /dev/null
@@ -1,59 +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_PEPPER_SSL_CONTEXT_HELPER_H_
-#define CONTENT_BROWSER_RENDERER_HOST_PEPPER_SSL_CONTEXT_HELPER_H_
-
-#include <memory>
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "net/ssl/ssl_config_service.h"
-
-namespace net {
-class CertVerifier;
-class CTPolicyEnforcer;
-class CTVerifier;
-class TransportSecurityState;
-}
-
-namespace content {
-
-class SSLContextHelper : public base::RefCounted<SSLContextHelper> {
- public:
- SSLContextHelper();
-
- net::CertVerifier* GetCertVerifier();
- net::TransportSecurityState* GetTransportSecurityState();
- net::CTVerifier* GetCertTransparencyVerifier();
- net::CTPolicyEnforcer* GetCTPolicyEnforcer();
- const net::SSLConfig& ssl_config() { return ssl_config_; }
-
- private:
- friend class base::RefCounted<SSLContextHelper>;
-
- ~SSLContextHelper();
-
- // This is lazily created. Users should use GetCertVerifier to retrieve it.
- std::unique_ptr<net::CertVerifier> cert_verifier_;
- // This is lazily created. Users should use GetTransportSecurityState to
- // retrieve it.
- std::unique_ptr<net::TransportSecurityState> transport_security_state_;
- // This is lazily created. Users should use GetCertTransparencyVerifier to
- // retrieve it.
- std::unique_ptr<net::CTVerifier> cert_transparency_verifier_;
- // This is lazily created. Users should use GetCTPolicyEnforcer to
- // retrieve it.
- std::unique_ptr<net::CTPolicyEnforcer> ct_policy_enforcer_;
-
- // The default SSL configuration settings are used, as opposed to Chrome's SSL
- // settings.
- net::SSLConfig ssl_config_;
-
- DISALLOW_COPY_AND_ASSIGN(SSLContextHelper);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_PEPPER_SSL_CONTEXT_HELPER_H_
diff --git a/chromium/content/browser/renderer_host/popup_window_mac.h b/chromium/content/browser/renderer_host/popup_window_mac.h
index 424e75fa241..1b3d65da55f 100644
--- a/chromium/content/browser/renderer_host/popup_window_mac.h
+++ b/chromium/content/browser/renderer_host/popup_window_mac.h
@@ -7,7 +7,7 @@
#import "base/mac/scoped_nsobject.h"
#include "base/macros.h"
-#include "third_party/blink/public/web/web_popup_type.h"
+#include "content/public/common/widget_type.h"
#include "ui/gfx/geometry/rect.h"
@class NSWindow;
@@ -21,7 +21,6 @@ namespace content {
class PopupWindowMac {
public:
PopupWindowMac(const gfx::Rect& content_rect,
- blink::WebPopupType popup_type,
RenderWidgetHostViewCocoa* cocoa_view);
~PopupWindowMac();
diff --git a/chromium/content/browser/renderer_host/popup_window_mac.mm b/chromium/content/browser/renderer_host/popup_window_mac.mm
index c77d21aeecd..76001b3e373 100644
--- a/chromium/content/browser/renderer_host/popup_window_mac.mm
+++ b/chromium/content/browser/renderer_host/popup_window_mac.mm
@@ -83,12 +83,10 @@
namespace content {
PopupWindowMac::PopupWindowMac(const gfx::Rect& content_rect,
- blink::WebPopupType popup_type,
RenderWidgetHostViewCocoa* cocoa_view)
: cocoa_view_(cocoa_view) {
- bool activatable = popup_type == blink::kWebPopupTypeNone;
[cocoa_view_ setCloseOnDeactivate:YES];
- [cocoa_view_ setCanBeKeyView:activatable ? YES : NO];
+ [cocoa_view_ setCanBeKeyView:NO];
popup_window_.reset([[RenderWidgetPopupWindow alloc]
initWithContentRect:gfx::ScreenRectToNSRect(content_rect)
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 c78d73722dd..0c01ec046dd 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
@@ -34,11 +34,20 @@ void RenderFrameMetadataProviderImpl::Bind(
render_frame_metadata_observer_client_binding_.Close();
render_frame_metadata_observer_client_binding_.Bind(std::move(client_request),
task_runner_);
+
+ if (pending_report_all_frame_submission_.has_value()) {
+ ReportAllFrameSubmissionsForTesting(*pending_report_all_frame_submission_);
+ pending_report_all_frame_submission_.reset();
+ }
}
void RenderFrameMetadataProviderImpl::ReportAllFrameSubmissionsForTesting(
bool enabled) {
- DCHECK(render_frame_metadata_observer_ptr_);
+ if (!render_frame_metadata_observer_ptr_) {
+ pending_report_all_frame_submission_ = enabled;
+ return;
+ }
+
render_frame_metadata_observer_ptr_->ReportAllFrameSubmissionsForTesting(
enabled);
}
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 1e5fdb2bfa5..bcec96f40ea 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
@@ -80,6 +80,8 @@ class CONTENT_EXPORT RenderFrameMetadataProviderImpl
render_frame_metadata_observer_client_binding_;
mojom::RenderFrameMetadataObserverPtr render_frame_metadata_observer_ptr_;
+ base::Optional<bool> pending_report_all_frame_submission_;
+
base::WeakPtrFactory<RenderFrameMetadataProviderImpl> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(RenderFrameMetadataProviderImpl);
diff --git a/chromium/content/browser/renderer_host/render_message_filter.cc b/chromium/content/browser/renderer_host/render_message_filter.cc
index cc6d5b62567..96f0ddcb9df 100644
--- a/chromium/content/browser/renderer_host/render_message_filter.cc
+++ b/chromium/content/browser/renderer_host/render_message_filter.cc
@@ -25,13 +25,7 @@
#include "content/browser/bad_message.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
#include "content/browser/browser_main_loop.h"
-#include "content/browser/cache_storage/cache_storage_cache.h"
-#include "content/browser/cache_storage/cache_storage_cache_handle.h"
-#include "content/browser/cache_storage/cache_storage_context_impl.h"
-#include "content/browser/cache_storage/cache_storage_manager.h"
#include "content/browser/child_process_security_policy_impl.h"
-#include "content/browser/code_cache/generated_code_cache.h"
-#include "content/browser/code_cache/generated_code_cache_context.h"
#include "content/browser/gpu/gpu_data_manager_impl.h"
#include "content/browser/gpu/gpu_process_host.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
@@ -46,6 +40,7 @@
#include "content/common/view_messages.h"
#include "content/public/browser/browser_child_process_host.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/resource_context.h"
#include "content/public/browser/storage_partition.h"
@@ -61,7 +56,6 @@
#include "net/base/io_buffer.h"
#include "net/base/mime_util.h"
#include "net/base/request_priority.h"
-#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/mojom/network_context.mojom.h"
@@ -84,36 +78,11 @@
#include "base/threading/platform_thread.h"
#endif
-using blink::mojom::CacheStorageError;
-
namespace content {
namespace {
const uint32_t kRenderFilteredMessageClasses[] = {ViewMsgStart};
-void NoOpCacheStorageErrorCallback(CacheStorageCacheHandle cache_handle,
- CacheStorageError error) {}
-
-base::Optional<url::Origin> GetRendererOrigin(const GURL& url,
- int render_process_id) {
- GURL requesting_url =
- ChildProcessSecurityPolicyImpl::GetInstance()->GetOriginLock(
- render_process_id);
-
- if (!requesting_url.is_valid() || !url.is_valid())
- return base::nullopt;
-
- url::Origin origin = url::Origin::Create(requesting_url);
-
- // Don't cache the code corresponding to unique origins. The same-origin
- // checks should always fail for unique origins but the serialized value of
- // unique origins does not ensure this.
- if (origin.unique())
- return base::nullopt;
-
- return origin;
-}
-
} // namespace
RenderMessageFilter::RenderMessageFilter(
@@ -121,9 +90,7 @@ RenderMessageFilter::RenderMessageFilter(
BrowserContext* browser_context,
net::URLRequestContextGetter* request_context,
RenderWidgetHelper* render_widget_helper,
- MediaInternals* media_internals,
- CacheStorageContextImpl* cache_storage_context,
- GeneratedCodeCacheContext* generated_code_cache_context)
+ MediaInternals* media_internals)
: BrowserMessageFilter(kRenderFilteredMessageClasses,
arraysize(kRenderFilteredMessageClasses)),
BrowserAssociatedInterface<mojom::RenderMessageFilter>(this, this),
@@ -133,8 +100,6 @@ RenderMessageFilter::RenderMessageFilter(
render_widget_helper_(render_widget_helper),
render_process_id_(render_process_id),
media_internals_(media_internals),
- cache_storage_context_(cache_storage_context),
- generated_code_cache_context_(generated_code_cache_context),
weak_ptr_factory_(this) {
DCHECK(request_context_.get());
@@ -174,12 +139,11 @@ void RenderMessageFilter::GenerateRoutingID(
}
void RenderMessageFilter::CreateNewWidget(int32_t opener_id,
- blink::WebPopupType popup_type,
mojom::WidgetPtr widget,
CreateNewWidgetCallback callback) {
int route_id = MSG_ROUTING_NONE;
- render_widget_helper_->CreateNewWidget(opener_id, popup_type,
- std::move(widget), &route_id);
+ render_widget_helper_->CreateNewWidget(opener_id, std::move(widget),
+ &route_id);
std::move(callback).Run(route_id);
}
@@ -227,114 +191,6 @@ void RenderMessageFilter::SetThreadPriority(int32_t ns_tid,
}
#endif
-void RenderMessageFilter::DidGenerateCacheableMetadata(
- const GURL& url,
- base::Time expected_response_time,
- const std::vector<uint8_t>& data) {
- if (!url.SchemeIsHTTPOrHTTPS()) {
- bad_message::ReceivedBadMessage(
- this, bad_message::RMF_BAD_URL_CACHEABLE_METADATA);
- return;
- }
-
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- if (!base::FeatureList::IsEnabled(features::kIsolatedCodeCache)) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::BindOnce(&RenderMessageFilter::DidGenerateCacheableMetadataOnUI,
- this, url, expected_response_time, data));
- } else {
- if (!generated_code_cache_context_->generated_code_cache())
- return;
-
- base::Optional<url::Origin> requesting_origin =
- GetRendererOrigin(url, render_process_id_);
- if (!requesting_origin)
- return;
-
- generated_code_cache_context_->generated_code_cache()->WriteData(
- url, *requesting_origin, expected_response_time, data);
- }
-}
-
-void RenderMessageFilter::FetchCachedCode(const GURL& url,
- FetchCachedCodeCallback callback) {
- if (!generated_code_cache_context_->generated_code_cache()) {
- std::move(callback).Run(base::Time(), std::vector<uint8_t>());
- return;
- }
-
- base::Optional<url::Origin> requesting_origin =
- GetRendererOrigin(url, render_process_id_);
- if (!requesting_origin) {
- std::move(callback).Run(base::Time(), std::vector<uint8_t>());
- return;
- }
-
- base::RepeatingCallback<void(const base::Time&, const std::vector<uint8_t>&)>
- read_callback = base::BindRepeating(
- &RenderMessageFilter::OnReceiveCachedCode,
- weak_ptr_factory_.GetWeakPtr(), base::Passed(&callback));
- generated_code_cache_context_->generated_code_cache()->FetchEntry(
- url, *requesting_origin, read_callback);
-}
-
-void RenderMessageFilter::OnReceiveCachedCode(
- FetchCachedCodeCallback callback,
- const base::Time& response_time,
- const std::vector<uint8_t>& data) {
- // TODO(crbug.com/867848): Pass the data as a mojo data pipe instead
- // of vector<uint8>
- std::move(callback).Run(response_time, data);
-}
-
-void RenderMessageFilter::ClearCodeCacheEntry(const GURL& url) {
- if (!generated_code_cache_context_->generated_code_cache())
- return;
-
- base::Optional<url::Origin> requesting_origin =
- GetRendererOrigin(url, render_process_id_);
- if (!requesting_origin)
- return;
-
- generated_code_cache_context_->generated_code_cache()->DeleteEntry(
- url, *requesting_origin);
-}
-
-void RenderMessageFilter::DidGenerateCacheableMetadataInCacheStorage(
- const GURL& url,
- base::Time expected_response_time,
- const std::vector<uint8_t>& data,
- const url::Origin& cache_storage_origin,
- const std::string& cache_storage_cache_name) {
- scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(data.size()));
- if (!data.empty())
- memcpy(buf->data(), &data.front(), data.size());
-
- cache_storage_context_->cache_manager()->OpenCache(
- cache_storage_origin, CacheStorageOwner::kCacheAPI,
- cache_storage_cache_name,
- base::BindOnce(&RenderMessageFilter::OnCacheStorageOpenCallback,
- weak_ptr_factory_.GetWeakPtr(), url,
- expected_response_time, buf, data.size()));
-}
-
-void RenderMessageFilter::OnCacheStorageOpenCallback(
- const GURL& url,
- base::Time expected_response_time,
- scoped_refptr<net::IOBuffer> buf,
- int buf_len,
- CacheStorageCacheHandle cache_handle,
- CacheStorageError error) {
- if (error != CacheStorageError::kSuccess || !cache_handle.value())
- return;
- CacheStorageCache* cache = cache_handle.value();
- cache->WriteSideData(
- base::BindOnce(&NoOpCacheStorageErrorCallback, std::move(cache_handle)),
- url, expected_response_time, buf, buf_len);
-}
-
void RenderMessageFilter::OnMediaLogEvents(
const std::vector<media::MediaLogEvent>& events) {
// OnMediaLogEvents() is always dispatched to the UI thread for handling.
@@ -348,23 +204,4 @@ void RenderMessageFilter::HasGpuProcess(HasGpuProcessCallback callback) {
GpuProcessHost::GetHasGpuProcess(std::move(callback));
}
-void RenderMessageFilter::DidGenerateCacheableMetadataOnUI(
- const GURL& url,
- base::Time expected_response_time,
- const std::vector<uint8_t>& data) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- RenderProcessHost* host = RenderProcessHost::FromID(render_process_id_);
- if (!host)
- return;
-
- // Use the same priority for the metadata write as for script
- // resources (see defaultPriorityForResourceType() in WebKit's
- // CachedResource.cpp). Note that WebURLRequest::PriorityMedium
- // corresponds to net::LOW (see ConvertWebKitPriorityToNetPriority()
- // in weburlloader_impl.cc).
- const net::RequestPriority kPriority = net::LOW;
- host->GetStoragePartition()->GetNetworkContext()->WriteCacheMetadata(
- url, kPriority, expected_response_time, data);
-}
-
} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_message_filter.h b/chromium/content/browser/renderer_host/render_message_filter.h
index 76eda81660d..925508cf8d6 100644
--- a/chromium/content/browser/renderer_host/render_message_filter.h
+++ b/chromium/content/browser/renderer_host/render_message_filter.h
@@ -22,10 +22,10 @@
#include "content/public/browser/browser_associated_interface.h"
#include "content/public/browser/browser_message_filter.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/common/widget_type.h"
#include "gpu/config/gpu_info.h"
#include "ipc/message_filter.h"
#include "third_party/blink/public/platform/modules/cache_storage/cache_storage.mojom.h"
-#include "third_party/blink/public/web/web_popup_type.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/gpu_memory_buffer.h"
#include "ui/gfx/native_widget_types.h"
@@ -42,23 +42,15 @@ struct MediaLogEvent;
}
namespace net {
-class IOBuffer;
class URLRequestContextGetter;
}
-namespace url {
-class Origin;
-}
-
namespace content {
class BrowserContext;
-class CacheStorageContextImpl;
-class CacheStorageCacheHandle;
class MediaInternals;
class RenderWidgetHelper;
class ResourceContext;
class ResourceDispatcherHostImpl;
-class GeneratedCodeCacheContext;
// This class filters out incoming IPC messages for the renderer process on the
// IPC thread.
@@ -72,9 +64,7 @@ class CONTENT_EXPORT RenderMessageFilter
BrowserContext* browser_context,
net::URLRequestContextGetter* request_context,
RenderWidgetHelper* render_widget_helper,
- MediaInternals* media_internals,
- CacheStorageContextImpl* cache_storage_context,
- GeneratedCodeCacheContext* generated_code_cache_context);
+ MediaInternals* media_internals);
// BrowserMessageFilter methods:
bool OnMessageReceived(const IPC::Message& message) override;
@@ -96,23 +86,11 @@ class CONTENT_EXPORT RenderMessageFilter
// mojom::RenderMessageFilter:
void GenerateRoutingID(GenerateRoutingIDCallback routing_id) override;
void CreateNewWidget(int32_t opener_id,
- blink::WebPopupType popup_type,
mojom::WidgetPtr widget,
CreateNewWidgetCallback callback) override;
void CreateFullscreenWidget(int opener_id,
mojom::WidgetPtr widget,
CreateFullscreenWidgetCallback callback) override;
- void DidGenerateCacheableMetadata(const GURL& url,
- base::Time expected_response_time,
- const std::vector<uint8_t>& data) override;
- void FetchCachedCode(const GURL& url, FetchCachedCodeCallback) override;
- void ClearCodeCacheEntry(const GURL& url) override;
- void DidGenerateCacheableMetadataInCacheStorage(
- const GURL& url,
- base::Time expected_response_time,
- const std::vector<uint8_t>& data,
- const url::Origin& cache_storage_origin,
- const std::string& cache_storage_cache_name) override;
void HasGpuProcess(HasGpuProcessCallback callback) override;
#if defined(OS_LINUX)
void SetThreadPriority(int32_t ns_tid,
@@ -126,25 +104,11 @@ class CONTENT_EXPORT RenderMessageFilter
base::ThreadPriority priority);
#endif
- void OnReceiveCachedCode(FetchCachedCodeCallback callback,
- const base::Time& response_time,
- const std::vector<uint8_t>& data);
- void OnCacheStorageOpenCallback(const GURL& url,
- base::Time expected_response_time,
- scoped_refptr<net::IOBuffer> buf,
- int buf_len,
- CacheStorageCacheHandle cache_handle,
- blink::mojom::CacheStorageError error);
void OnMediaLogEvents(const std::vector<media::MediaLogEvent>&);
bool CheckBenchmarkingEnabled() const;
bool CheckPreparsedJsCachingEnabled() const;
- // NetworkContext must be called from the UI thread.
- void DidGenerateCacheableMetadataOnUI(const GURL& url,
- base::Time expected_response_time,
- const std::vector<uint8_t>& data);
-
// Cached resource request dispatcher host, guaranteed to be non-null. We do
// not own it; it is managed by the BrowserProcess, which has a wider scope
// than we do.
@@ -161,11 +125,6 @@ class CONTENT_EXPORT RenderMessageFilter
int render_process_id_;
MediaInternals* media_internals_;
- CacheStorageContextImpl* cache_storage_context_;
-
- // TODO(crbug.com/867347): Consider registering its own Mojo interface rather
- // than going through RenderMessageFilter.
- GeneratedCodeCacheContext* generated_code_cache_context_;
base::WeakPtrFactory<RenderMessageFilter> weak_ptr_factory_;
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 b168086cac1..4ae24e5d37c 100644
--- a/chromium/content/browser/renderer_host/render_process_host_browsertest.cc
+++ b/chromium/content/browser/renderer_host/render_process_host_browsertest.cc
@@ -6,11 +6,13 @@
#include "base/command_line.h"
#include "base/run_loop.h"
#include "base/synchronization/waitable_event.h"
+#include "base/task/post_task.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/test_timeouts.h"
#include "build/build_config.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/child_process_launcher_utils.h"
#include "content/public/browser/render_frame_host.h"
@@ -753,8 +755,8 @@ IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, KillProcessZerosAudioStreams) {
// Cycle UI and IO loop once to ensure OnChannelClosing() has been delivered
// to audio stream owners and they get a chance to notify of stream closure.
base::RunLoop run_loop;
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- media::BindToCurrentLoop(run_loop.QuitClosure()));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO},
+ media::BindToCurrentLoop(run_loop.QuitClosure()));
run_loop.Run();
}
@@ -852,8 +854,8 @@ IN_PROC_BROWSER_TEST_F(CaptureStreamRenderProcessHostTest,
// Cycle UI and IO loop once to ensure OnChannelClosing() has been delivered
// to audio stream owners and they get a chance to notify of stream closure.
base::RunLoop run_loop;
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- media::BindToCurrentLoop(run_loop.QuitClosure()));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO},
+ media::BindToCurrentLoop(run_loop.QuitClosure()));
run_loop.Run();
}
@@ -917,8 +919,8 @@ IN_PROC_BROWSER_TEST_F(CaptureStreamRenderProcessHostTest,
// Cycle UI and IO loop once to ensure OnChannelClosing() has been delivered
// to audio stream owners and they get a chance to notify of stream closure.
base::RunLoop run_loop;
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- media::BindToCurrentLoop(run_loop.QuitClosure()));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO},
+ media::BindToCurrentLoop(run_loop.QuitClosure()));
run_loop.Run();
}
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 989b52793c4..cb57a9ea444 100644
--- a/chromium/content/browser/renderer_host/render_process_host_impl.cc
+++ b/chromium/content/browser/renderer_host/render_process_host_impl.cc
@@ -53,6 +53,7 @@
#include "base/synchronization/lock.h"
#include "base/sys_info.h"
#include "base/task/post_task.h"
+#include "base/thread_annotations.h"
#include "base/threading/thread.h"
#include "base/threading/thread_restrictions.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -84,6 +85,8 @@
#include "content/browser/cache_storage/cache_storage_context_impl.h"
#include "content/browser/cache_storage/cache_storage_dispatcher_host.h"
#include "content/browser/child_process_security_policy_impl.h"
+#include "content/browser/code_cache/generated_code_cache.h"
+#include "content/browser/code_cache/generated_code_cache_context.h"
#include "content/browser/compositor/surface_utils.h"
#include "content/browser/dom_storage/dom_storage_context_wrapper.h"
#include "content/browser/dom_storage/dom_storage_message_filter.h"
@@ -111,6 +114,7 @@
#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/code_cache_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/media_stream_manager.h"
@@ -150,7 +154,9 @@
#include "content/common/service_manager/service_manager_connection_impl.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "content/common/view_messages.h"
+#include "content/common/widget_messages.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/network_service_instance.h"
#include "content/public/browser/notification_service.h"
@@ -201,7 +207,6 @@
#include "services/network/public/cpp/network_switches.h"
#include "services/network/public/mojom/network_service.mojom.h"
#include "services/resource_coordinator/public/cpp/process_resource_coordinator.h"
-#include "services/resource_coordinator/public/cpp/resource_coordinator_features.h"
#include "services/service_manager/embedder/switches.h"
#include "services/service_manager/public/cpp/binder_registry.h"
#include "services/service_manager/public/cpp/connector.h"
@@ -417,13 +422,13 @@ class SiteProcessMap : public base::SupportsUserData::Data {
// two WebContents with blank SiteInstances. If that occurs, keeping the
// exising entry and not overwriting it is a predictable behavior that is
// safe.
- SiteToProcessMap::iterator i = map_.find(site);
+ auto i = map_.find(site);
if (i == map_.end())
map_[site] = process;
}
RenderProcessHost* FindProcess(const std::string& site) {
- SiteToProcessMap::iterator i = map_.find(site);
+ auto i = map_.find(site);
if (i != map_.end())
return i->second;
return nullptr;
@@ -438,9 +443,8 @@ class SiteProcessMap : public base::SupportsUserData::Data {
if (i->second == host)
sites.insert(i->first);
}
- for (std::set<std::string>::iterator i = sites.begin(); i != sites.end();
- ++i) {
- SiteToProcessMap::iterator iter = map_.find(*i);
+ for (auto i = sites.begin(); i != sites.end(); ++i) {
+ auto iter = map_.find(*i);
if (iter != map_.end()) {
DCHECK_EQ(iter->second, host);
map_.erase(iter);
@@ -522,8 +526,8 @@ class SessionStorageHolder : public base::SupportsUserData::Data {
session_storage_namespaces_awaiting_close_.release());
}
- void Hold(const SessionStorageNamespaceMap& sessions, int view_route_id) {
- (*session_storage_namespaces_awaiting_close_)[view_route_id] = sessions;
+ void Hold(const SessionStorageNamespaceMap& sessions, int widget_route_id) {
+ (*session_storage_namespaces_awaiting_close_)[widget_route_id] = sessions;
}
void Release(int old_route_id) {
@@ -577,6 +581,15 @@ class SpareRenderProcessHostManager : public RenderProcessHostObserver {
RenderProcessHostImpl::GetMaxRendererProcessCount())
return;
+ // Don't create a spare renderer when the system is under load. This is
+ // currently approximated by only looking at the memory pressure. See also
+ // https://crbug.com/852905.
+ auto* memory_monitor = base::MemoryPressureMonitor::Get();
+ if (memory_monitor &&
+ memory_monitor->GetCurrentPressureLevel() >=
+ base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE)
+ return;
+
spare_render_process_host_ = RenderProcessHostImpl::CreateRenderProcessHost(
browser_context, nullptr /* storage_partition_impl */,
nullptr /* site_instance */, false /* is_for_guests_only */);
@@ -832,8 +845,8 @@ class RenderProcessHostIsReadyObserver : public RenderProcessHostObserver {
private:
void PostTask() {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&RenderProcessHostIsReadyObserver::CallTask,
weak_factory_.GetWeakPtr()));
}
@@ -1228,6 +1241,18 @@ void GetNetworkChangeManager(
GetNetworkService()->GetNetworkChangeManager(std::move(request));
}
+std::set<int>& GetCurrentCorbPluginExceptions() {
+ static base::NoDestructor<std::set<int>> s_data;
+ return *s_data;
+}
+
+void OnNetworkServiceCrash() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ network::mojom::NetworkService* network_service = GetNetworkService();
+ for (int process_id : GetCurrentCorbPluginExceptions())
+ network_service->AddCorbExceptionForPlugin(process_id);
+}
+
void RemoveCorbExceptionForPluginOnIOThread(int process_id) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -1243,10 +1268,11 @@ void RemoveCorbExceptionForPluginOnUIThread(int process_id) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+ GetCurrentCorbPluginExceptions().erase(process_id);
GetNetworkService()->RemoveCorbExceptionForPlugin(process_id);
} else {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&RemoveCorbExceptionForPluginOnIOThread, process_id));
}
}
@@ -1259,15 +1285,23 @@ void AddCorbExceptionForPluginOnUIThread(int process_id) {
// In this case the exception won't be added via NetworkService (because of
// the early return below), but we need to proactively do clean-up on IO
// thread.
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&RemoveCorbExceptionForPluginOnIOThread, process_id));
return;
}
process->CleanupCorbExceptionForPluginUponDestruction();
- if (base::FeatureList::IsEnabled(network::features::kNetworkService))
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+ static NetworkServiceCrashHandlerId s_crash_handler_id;
+ if (s_crash_handler_id.is_null()) {
+ s_crash_handler_id = RegisterNetworkServiceCrashHandler(
+ base::BindRepeating(&OnNetworkServiceCrash));
+ }
+
+ GetCurrentCorbPluginExceptions().insert(process_id);
GetNetworkService()->AddCorbExceptionForPlugin(process_id);
+ }
}
// This is the entry point (i.e. this is called on the IO thread *before*
@@ -1280,8 +1314,8 @@ void AddCorbExceptionForPluginOnIOThread(int process_id) {
if (!base::FeatureList::IsEnabled(network::features::kNetworkService))
network::CrossOriginReadBlocking::AddExceptionForPlugin(process_id);
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&AddCorbExceptionForPluginOnUIThread, process_id));
}
@@ -1310,7 +1344,7 @@ class RenderProcessHostImpl::ConnectionFilterController
}
base::Lock lock_;
- ConnectionFilterImpl* filter_;
+ ConnectionFilterImpl* filter_ PT_GUARDED_BY(lock_);
};
// Held by the RPH's BrowserContext's ServiceManagerConnection, ownership
@@ -1370,9 +1404,8 @@ class RenderProcessHostImpl::ConnectionFilterImpl : public ConnectionFilter {
std::unique_ptr<service_manager::BinderRegistry> registry_;
scoped_refptr<ConnectionFilterController> controller_;
- // Guards |enabled_|.
base::Lock enabled_lock_;
- bool enabled_ = true;
+ bool enabled_ GUARDED_BY(enabled_lock_) = true;
base::WeakPtrFactory<ConnectionFilterImpl> weak_factory_;
@@ -1561,7 +1594,6 @@ RenderProcessHostImpl::RenderProcessHostImpl(
permission_service_context_(new PermissionServiceContext(this)),
indexed_db_factory_(new IndexedDBDispatcherHost(
id_,
- storage_partition_impl_->GetURLRequestContext(),
storage_partition_impl_->GetIndexedDBContext(),
ChromeBlobStorageContext::GetFor(browser_context_))),
service_worker_dispatcher_host_(new ServiceWorkerDispatcherHost(
@@ -1594,9 +1626,10 @@ RenderProcessHostImpl::RenderProcessHostImpl(
if (!GetBrowserContext()->IsOffTheRecord() &&
!base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableGpuShaderDiskCache)) {
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::BindOnce(&CacheShaderInfo, GetID(),
- storage_partition_impl_->GetPath()));
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(&CacheShaderInfo, GetID(),
+ storage_partition_impl_->GetPath()));
}
push_messaging_manager_.reset(new PushMessagingManager(
@@ -1610,13 +1643,13 @@ RenderProcessHostImpl::RenderProcessHostImpl(
InitializeChannelProxy();
- if (!features::IsUsingWindowService()) {
+ if (!features::IsMultiProcessMash()) {
const int id = GetID();
const uint64_t tracing_id =
ChildProcessHostImpl::ChildProcessUniqueIdToTracingProcessId(id);
gpu_client_.reset(new viz::GpuClient(
std::make_unique<BrowserGpuClientDelegate>(), id, tracing_id,
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)));
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO})));
}
GetMemoryDumpProvider().AddHost(this);
@@ -1680,8 +1713,8 @@ RenderProcessHostImpl::~RenderProcessHostImpl() {
if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableGpuShaderDiskCache)) {
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::BindOnce(&RemoveShaderInfo, GetID()));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(&RemoveShaderInfo, GetID()));
}
GetMemoryDumpProvider().RemoveHost(this);
@@ -1755,7 +1788,7 @@ bool RenderProcessHostImpl::Init() {
// 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));
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO}));
}
#endif // !defined(OS_MACOSX)
@@ -1779,7 +1812,7 @@ bool RenderProcessHostImpl::Init() {
// on separate threads.
in_process_renderer_.reset(
g_renderer_main_thread_factory(InProcessChildThreadParams(
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO),
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO}),
&mojo_invitation_, child_connection_->service_token())));
base::Thread::Options options;
@@ -1841,7 +1874,7 @@ void RenderProcessHostImpl::EnableSendQueue() {
void RenderProcessHostImpl::InitializeChannelProxy() {
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner =
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO);
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO});
// Acquire a Connector which will route connections to a new instance of the
// renderer service.
@@ -1944,14 +1977,10 @@ void RenderProcessHostImpl::CreateMessageFilters() {
scoped_refptr<net::URLRequestContextGetter> request_context(
storage_partition_impl_->GetURLRequestContext());
- // TODO(crbug.com/867347): Consider registering Mojo interface for
- // GeneratedCodeCache rather than going through RenderMessageFilter.
scoped_refptr<RenderMessageFilter> render_message_filter =
base::MakeRefCounted<RenderMessageFilter>(
GetID(), GetBrowserContext(), request_context.get(),
- widget_helper_.get(), media_internals,
- storage_partition_impl_->GetCacheStorageContext(),
- storage_partition_impl_->GetGeneratedCodeCacheContext());
+ widget_helper_.get(), media_internals);
AddFilter(render_message_filter.get());
render_frame_message_filter_ = new RenderFrameMessageFilter(
@@ -1983,8 +2012,9 @@ void RenderProcessHostImpl::CreateMessageFilters() {
storage_partition_impl_->GetFileSystemContext(),
storage_partition_impl_->GetServiceWorkerContext(),
storage_partition_impl_->GetPrefetchURLLoaderService(),
+ BrowserContext::GetSharedCorsOriginAccessList(browser_context),
std::move(get_contexts_callback),
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO));
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO}));
AddFilter(resource_message_filter_.get());
@@ -2027,13 +2057,23 @@ void RenderProcessHostImpl::BindCacheStorage(
}
// Send the binding to IO thread, because Cache Storage handles Mojo IPC on IO
// thread entirely.
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&CacheStorageDispatcherHost::AddBinding,
cache_storage_dispatcher_host_, std::move(request),
origin));
}
+void RenderProcessHostImpl::BindFileSystemManager(
+ blink::mojom::FileSystemManagerRequest request) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(&FileSystemManagerImpl::BindRequest,
+ base::Unretained(file_system_manager_impl_.get()),
+ std::move(request)));
+}
+
void RenderProcessHostImpl::CancelProcessShutdownDelayForUnload() {
if (IsKeepAliveRefCountDisabled())
return;
@@ -2047,8 +2087,8 @@ void RenderProcessHostImpl::DelayProcessShutdownForUnload(
return;
IncrementKeepAliveRefCount(RenderProcessHost::KeepAliveClientType::kUnload);
- BrowserThread::PostDelayedTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostDelayedTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(
&RenderProcessHostImpl::CancelProcessShutdownDelayForUnload,
weak_factory_.GetWeakPtr()),
@@ -2110,11 +2150,10 @@ void RenderProcessHostImpl::RegisterMojoInterfaces() {
registry.get(),
base::Bind(&CreateMemoryCoordinatorHandleForRenderProcess, GetID()));
}
- if (resource_coordinator::IsResourceCoordinatorEnabled()) {
- AddUIThreadInterface(
- registry.get(),
- base::Bind(&CreateProcessResourceCoordinator, base::Unretained(this)));
- }
+
+ AddUIThreadInterface(
+ registry.get(),
+ base::Bind(&CreateProcessResourceCoordinator, base::Unretained(this)));
AddUIThreadInterface(registry.get(),
base::BindRepeating(&ClipboardHostImpl::Create));
@@ -2150,8 +2189,14 @@ void RenderProcessHostImpl::RegisterMojoInterfaces() {
base::Unretained(push_messaging_manager_.get())));
file_system_manager_impl_.reset(new FileSystemManagerImpl(
- GetID(), storage_partition_impl_->GetFileSystemContext(),
+ GetID(), MSG_ROUTING_NONE,
+ storage_partition_impl_->GetFileSystemContext(),
ChromeBlobStorageContext::GetFor(GetBrowserContext())));
+ // This interface is still exposed by the RenderProcessHost's registry so
+ // that it can be accessed by PepperFileSystemHost. Blink accesses this
+ // interface through RenderFrameHost/RendererInterfaceBinders.
+ // TODO(https://crbug.com/873661): Make PepperFileSystemHost access this with
+ // the RenderFrameHost's registry, and remove this registration.
registry->AddInterface(
base::BindRepeating(&FileSystemManagerImpl::BindRequest,
base::Unretained(file_system_manager_impl_.get())));
@@ -2191,6 +2236,12 @@ void RenderProcessHostImpl::RegisterMojoInterfaces() {
registry->AddInterface(
base::Bind(&metrics::CreateSingleSampleMetricsProvider));
+ registry->AddInterface(base::BindRepeating(
+ &CodeCacheHostImpl::Create, GetID(),
+ base::RetainedRef(storage_partition_impl_->GetCacheStorageContext()),
+ base::RetainedRef(
+ storage_partition_impl_->GetGeneratedCodeCacheContext())));
+
#if BUILDFLAG(ENABLE_REPORTING)
registry->AddInterface(
base::Bind(&CreateReportingServiceProxy, storage_partition_impl_));
@@ -2218,10 +2269,18 @@ void RenderProcessHostImpl::RegisterMojoInterfaces() {
&RenderProcessHostImpl::CreateRendererHost, base::Unretained(this)));
if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+ // Using an opaque origin here should be safe - the URLLoaderFactory created
+ // for such origin shouldn't have any special privileges.
+ //
+ // TODO(lukasza): https://crbug.com/871827: Use the actual origin that will
+ // be used as |request_initiator|. The origin should come from the browser
+ // process.
+ const url::Origin kSafeOrigin = url::Origin();
+
AddUIThreadInterface(
registry.get(),
base::Bind(&RenderProcessHostImpl::CreateURLLoaderFactory,
- base::Unretained(this)));
+ base::Unretained(this), kSafeOrigin));
}
registry->AddInterface(
@@ -2246,8 +2305,10 @@ void RenderProcessHostImpl::RegisterMojoInterfaces() {
AddUIThreadInterface(registry.get(),
base::BindRepeating(&GetNetworkChangeManager));
- registry->AddInterface(base::BindRepeating(
- &RenderProcessHostImpl::BindVideoDecoderService, base::Unretained(this)));
+ AddUIThreadInterface(
+ registry.get(),
+ base::BindRepeating(&RenderProcessHostImpl::BindVideoDecoderService,
+ base::Unretained(this)));
// ---- Please do not register interfaces below this line ------
//
@@ -2479,14 +2540,7 @@ mojom::Renderer* RenderProcessHostImpl::GetRendererInterface() {
resource_coordinator::ProcessResourceCoordinator*
RenderProcessHostImpl::GetProcessResourceCoordinator() {
- if (process_resource_coordinator_)
- return process_resource_coordinator_.get();
-
- if (!resource_coordinator::IsResourceCoordinatorEnabled()) {
- process_resource_coordinator_ =
- std::make_unique<resource_coordinator::ProcessResourceCoordinator>(
- nullptr);
- } else {
+ if (!process_resource_coordinator_) {
auto* connection = ServiceManagerConnection::GetForProcess();
process_resource_coordinator_ =
std::make_unique<resource_coordinator::ProcessResourceCoordinator>(
@@ -2496,23 +2550,35 @@ RenderProcessHostImpl::GetProcessResourceCoordinator() {
}
void RenderProcessHostImpl::CreateURLLoaderFactory(
+ const url::Origin& origin,
network::mojom::URLLoaderFactoryRequest request) {
if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&ResourceMessageFilter::Clone, resource_message_filter_,
std::move(request)));
return;
}
- network::mojom::URLLoaderFactoryParamsPtr params =
- network::mojom::URLLoaderFactoryParams::New();
- params->process_id = id_;
- params->disable_web_security =
- base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDisableWebSecurity);
- SiteIsolationPolicy::PopulateURLLoaderFactoryParamsPtrForCORB(params.get());
- storage_partition_impl_->GetNetworkContext()->CreateURLLoaderFactory(
- std::move(request), std::move(params));
+
+ network::mojom::NetworkContext* network_context =
+ storage_partition_impl_->GetNetworkContext();
+ network::mojom::URLLoaderFactoryPtrInfo embedder_provided_factory =
+ GetContentClient()->browser()->CreateURLLoaderFactoryForNetworkRequests(
+ this, network_context, origin);
+ if (embedder_provided_factory) {
+ mojo::FuseInterface(std::move(request),
+ std::move(embedder_provided_factory));
+ } else {
+ network::mojom::URLLoaderFactoryParamsPtr params =
+ network::mojom::URLLoaderFactoryParams::New();
+ params->process_id = GetID();
+ params->disable_web_security =
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableWebSecurity);
+ SiteIsolationPolicy::PopulateURLLoaderFactoryParamsPtrForCORB(params.get());
+ network_context->CreateURLLoaderFactory(std::move(request),
+ std::move(params));
+ }
}
void RenderProcessHostImpl::SetIsNeverSuitableForReuse() {
@@ -2586,8 +2652,6 @@ void RenderProcessHostImpl::ShutdownForBadMessage(
std::string site_isolation_mode;
if (SiteIsolationPolicy::UseDedicatedProcessesForAllSites())
site_isolation_mode += "spp ";
- if (SiteIsolationPolicy::IsTopDocumentIsolationEnabled())
- site_isolation_mode += "tdi ";
if (SiteIsolationPolicy::AreIsolatedOriginsEnabled())
site_isolation_mode += "io ";
if (site_isolation_mode.empty())
@@ -2998,7 +3062,7 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kEnableWebVR,
switches::kExplicitlyAllowedPorts,
switches::kFileUrlPathAlias,
- switches::kForceColorProfile,
+ switches::kForceDisplayColorProfile,
switches::kForceDeviceScaleFactor,
switches::kForceGpuMemAvailableMb,
switches::kForceGpuRasterization,
@@ -3119,7 +3183,11 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
renderer_cmd->AppendSwitch(switches::kDisableDatabases);
}
-#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
+#if defined(OS_ANDROID)
+ if (browser_cmd.HasSwitch(switches::kDisableGpuCompositing)) {
+ renderer_cmd->AppendSwitch(switches::kDisableGpuCompositing);
+ }
+#elif !defined(OS_CHROMEOS)
#if !BUILDFLAG(ENABLE_MUS)
// If gpu compositing is not being used, tell the renderer at startup. This
// is inherently racey, as it may change while the renderer is being launched,
@@ -3130,11 +3198,11 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
// no need to check this state and forward it.
if (ImageTransportFactory::GetInstance()->IsGpuCompositingDisabled())
renderer_cmd->AppendSwitch(switches::kDisableGpuCompositing);
-#else
+#else // BUILDFLAG(ENABLE_MUS)
// TODO(tonikitoo): Check if renderer should use software compositing
// through some mechanism that isn't ImageTransportFactory with mus.
-#endif
-#endif
+#endif // !BUILDFLAG(ENABLE_MUS)
+#endif // defined(OS_ANDROID)
// Add kWaitForDebugger to let renderer process wait for a debugger.
if (browser_cmd.HasSwitch(switches::kWaitForDebuggerChildren)) {
@@ -3276,7 +3344,7 @@ bool RenderProcessHostImpl::OnMessageReceived(const IPC::Message& msg) {
IPC_BEGIN_MESSAGE_MAP(RenderProcessHostImpl, msg)
IPC_MESSAGE_HANDLER(ViewHostMsg_UserMetricsRecordAction,
OnUserMetricsRecordAction)
- IPC_MESSAGE_HANDLER(ViewHostMsg_Close_ACK, OnCloseACK)
+ IPC_MESSAGE_HANDLER(WidgetHostMsg_Close_ACK, OnCloseACK)
IPC_MESSAGE_HANDLER(AecDumpMsg_RegisterAecDumpConsumer,
OnRegisterAecDumpConsumer)
IPC_MESSAGE_HANDLER(AecDumpMsg_UnregisterAecDumpConsumer,
@@ -3410,8 +3478,8 @@ void RenderProcessHostImpl::Cleanup() {
return;
if (is_initialized_) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&WebRtcLog::ClearLogMessageCallback, GetID()));
}
@@ -3561,9 +3629,9 @@ void RenderProcessHostImpl::SetEchoCanceller3(
if (!aec3_set_callback_.is_null()) {
MediaStreamManager::SendMessageToNativeLog("RPHI: Failed to set AEC3");
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(std::move(callback), false,
- "Operation already in progress"));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(std::move(callback), false,
+ "Operation already in progress"));
return;
}
@@ -3935,12 +4003,6 @@ RenderProcessHost* RenderProcessHostImpl::GetProcessHostForSiteInstance(
render_process_host = GetSoleProcessHostForSite(
browser_context, site_url, site_instance->lock_url());
break;
- case SiteInstanceImpl::ProcessReusePolicy::USE_DEFAULT_SUBFRAME_PROCESS:
- DCHECK(SiteIsolationPolicy::IsTopDocumentIsolationEnabled());
- DCHECK(!site_instance->is_for_service_worker());
- render_process_host = GetDefaultSubframeProcessHost(
- browser_context, site_instance, is_for_guests_only);
- break;
case SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE:
render_process_host =
FindReusableProcessHostForSiteInstance(site_instance);
@@ -4210,7 +4272,7 @@ void RenderProcessHost::SetHungRendererAnalysisFunction(
void RenderProcessHostImpl::ReleaseOnCloseACK(
RenderProcessHost* host,
const SessionStorageNamespaceMap& sessions,
- int view_route_id) {
+ int widget_route_id) {
DCHECK(host);
if (sessions.empty())
return;
@@ -4220,7 +4282,7 @@ void RenderProcessHostImpl::ReleaseOnCloseACK(
holder = new SessionStorageHolder();
host->SetUserData(kSessionStorageHolderKey, base::WrapUnique(holder));
}
- holder->Hold(sessions, view_route_id);
+ holder->Hold(sessions, widget_route_id);
}
void RenderProcessHostImpl::SuddenTerminationChanged(bool enabled) {
@@ -4294,6 +4356,14 @@ void RenderProcessHostImpl::UpdateProcessPriority() {
return;
}
+ if (!has_recorded_media_stream_frame_depth_metric_ && !visible_clients_ &&
+ media_stream_count_) {
+ UMA_HISTOGRAM_EXACT_LINEAR(
+ "BrowserRenderProcessHost.InvisibleMediaStreamFrameDepth", frame_depth_,
+ 50);
+ has_recorded_media_stream_frame_depth_metric_ = true;
+ }
+
const ChildProcessLauncherPriority priority(
visible_clients_ > 0 || base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableRendererBackgrounding),
@@ -4462,12 +4532,12 @@ void RenderProcessHostImpl::OnUserMetricsRecordAction(
base::RecordComputedAction(action);
}
-void RenderProcessHostImpl::OnCloseACK(int old_route_id) {
+void RenderProcessHostImpl::OnCloseACK(int closed_widget_route_id) {
SessionStorageHolder* holder =
static_cast<SessionStorageHolder*>(GetUserData(kSessionStorageHolderKey));
if (!holder)
return;
- holder->Release(old_route_id);
+ holder->Release(closed_widget_route_id);
}
void RenderProcessHostImpl::OnGpuSwitched() {
@@ -4475,23 +4545,6 @@ void RenderProcessHostImpl::OnGpuSwitched() {
}
// static
-RenderProcessHost* RenderProcessHostImpl::GetDefaultSubframeProcessHost(
- BrowserContext* browser_context,
- SiteInstanceImpl* site_instance,
- bool is_for_guests_only) {
- DefaultSubframeProcessHostHolder* holder =
- static_cast<DefaultSubframeProcessHostHolder*>(
- browser_context->GetUserData(&kDefaultSubframeProcessHostHolderKey));
- if (!holder) {
- holder = new DefaultSubframeProcessHostHolder(browser_context);
- browser_context->SetUserData(kDefaultSubframeProcessHostHolderKey,
- base::WrapUnique(holder));
- }
-
- return holder->GetProcessHost(site_instance, is_for_guests_only);
-}
-
-// static
RenderProcessHost*
RenderProcessHostImpl::FindReusableProcessHostForSiteInstance(
SiteInstanceImpl* site_instance) {
@@ -4554,15 +4607,15 @@ void RenderProcessHostImpl::CreateMediaStreamTrackMetricsHost(
}
void RenderProcessHostImpl::OnRegisterAecDumpConsumer(int id) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&RenderProcessHostImpl::RegisterAecDumpConsumerOnUIThread,
weak_factory_.GetWeakPtr(), id));
}
void RenderProcessHostImpl::OnUnregisterAecDumpConsumer(int id) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(
&RenderProcessHostImpl::UnregisterAecDumpConsumerOnUIThread,
weak_factory_.GetWeakPtr(), id));
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 37bc9b79afd..f11aa8252ea 100644
--- a/chromium/content/browser/renderer_host/render_process_host_impl.h
+++ b/chromium/content/browser/renderer_host/render_process_host_impl.h
@@ -24,6 +24,7 @@
#include "base/process/process.h"
#include "base/single_thread_task_runner.h"
#include "base/synchronization/waitable_event.h"
+#include "base/task/post_task.h"
#include "build/build_config.h"
#include "content/browser/cache_storage/cache_storage_dispatcher_host.h"
#include "content/browser/child_process_launcher.h"
@@ -39,6 +40,7 @@
#include "content/common/media/renderer_audio_output_stream_factory.mojom.h"
#include "content/common/renderer.mojom.h"
#include "content/common/renderer_host.mojom.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/common/service_manager_connection.h"
@@ -57,6 +59,7 @@
#include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
#include "third_party/blink/public/mojom/associated_interfaces/associated_interfaces.mojom.h"
#include "third_party/blink/public/mojom/dom_storage/storage_partition_service.mojom.h"
+#include "third_party/blink/public/mojom/filesystem/file_system.mojom.h"
#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom.h"
#include "ui/gfx/gpu_memory_buffer.h"
#include "ui/gl/gpu_switching_observer.h"
@@ -216,6 +219,7 @@ class CONTENT_EXPORT RenderProcessHostImpl
resource_coordinator::ProcessResourceCoordinator*
GetProcessResourceCoordinator() override;
void CreateURLLoaderFactory(
+ const url::Origin& origin,
network::mojom::URLLoaderFactoryRequest request) override;
void SetIsNeverSuitableForReuse() override;
@@ -255,11 +259,12 @@ class CONTENT_EXPORT RenderProcessHostImpl
// Used to extend the lifetime of the sessions until the render view
// in the renderer is fully closed. This is static because its also called
- // with mock hosts as input in test cases.
- static void ReleaseOnCloseACK(
- RenderProcessHost* host,
- const SessionStorageNamespaceMap& sessions,
- int view_route_id);
+ // with mock hosts as input in test cases. The RenderWidget routing associated
+ // with the view is used as the key since the WidgetMsg_Close and
+ // WidgetHostMsg_Close_ACK logic is centered around RenderWidgets.
+ static void ReleaseOnCloseACK(RenderProcessHost* host,
+ const SessionStorageNamespaceMap& sessions,
+ int widget_route_id);
// Register/unregister the host identified by the host id in the global host
// list.
@@ -315,7 +320,6 @@ class CONTENT_EXPORT RenderProcessHostImpl
// handles all cases. These cases include:
// - process-per-site: see
// RegisterSoleProcessHostForSite/GetSoleProcessHostForSite.
- // - TDI: see GetDefaultSubframeProcessHost.
// - REUSE_PENDING_OR_COMMITTED reuse policy (for ServiceWorkers and OOPIFs):
// see FindReusableProcessHostForSiteInstance.
// - normal process reuse when over process limit: see
@@ -445,6 +449,9 @@ class CONTENT_EXPORT RenderProcessHostImpl
// before the process shuts down.
void DelayProcessShutdownForUnload(const base::TimeDelta& timeout);
+ // Binds request to the FileSystemManager instance owned by the render process
+ // host, and is used by workers via RendererInterfaceBinders.
+ void BindFileSystemManager(blink::mojom::FileSystemManagerRequest request);
FileSystemManagerImpl* GetFileSystemManagerForTesting() {
return file_system_manager_impl_.get();
}
@@ -532,7 +539,7 @@ class CONTENT_EXPORT RenderProcessHostImpl
// Control message handlers.
void OnUserMetricsRecordAction(const std::string& action);
- void OnCloseACK(int old_route_id);
+ void OnCloseACK(int closed_widget_route_id);
// Generates a command line to be used to spawn a renderer and appends the
// results to |*command_line|.
@@ -575,12 +582,6 @@ class CONTENT_EXPORT RenderProcessHostImpl
base::TimeTicks start,
base::TimeTicks end);
- // Returns the default subframe RenderProcessHost to use for |site_instance|.
- static RenderProcessHost* GetDefaultSubframeProcessHost(
- BrowserContext* browser_context,
- SiteInstanceImpl* site_instance,
- bool is_for_guests_only);
-
// Get an existing RenderProcessHost associated with the given browser
// context, if possible. The renderer process is chosen randomly from
// suitable renderers that share the same context and type (determined by the
@@ -648,7 +649,7 @@ class CONTENT_EXPORT RenderProcessHostImpl
registry->AddInterface(
base::Bind(&InterfaceGetter<CallbackType>::GetInterfaceOnUIThread,
instance_weak_factory_->GetWeakPtr(), callback),
- BrowserThread::GetTaskRunnerForThread(BrowserThread::UI));
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::UI}));
}
// Callback to unblock process shutdown after waiting for unload handlers to
@@ -887,6 +888,9 @@ class CONTENT_EXPORT RenderProcessHostImpl
bool cleanup_corb_exception_for_plugin_upon_destruction_ = false;
+ // Fields for recording MediaStream UMA.
+ bool has_recorded_media_stream_frame_depth_metric_ = false;
+
base::WeakPtrFactory<RenderProcessHostImpl> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(RenderProcessHostImpl);
diff --git a/chromium/content/browser/renderer_host/render_view_host_delegate.h b/chromium/content/browser/renderer_host/render_view_host_delegate.h
index f2d59fbd1f4..f529058d126 100644
--- a/chromium/content/browser/renderer_host/render_view_host_delegate.h
+++ b/chromium/content/browser/renderer_host/render_view_host_delegate.h
@@ -16,7 +16,6 @@
#include "content/common/content_export.h"
#include "content/common/render_message_filter.mojom.h"
#include "net/base/load_states.h"
-#include "third_party/blink/public/web/web_popup_type.h"
class GURL;
@@ -125,26 +124,24 @@ class CONTENT_EXPORT RenderViewHostDelegate {
// widget should be created associated with the given |route_id| in the
// process |render_process_id|, but it should not be shown yet. That should
// happen in response to ShowCreatedWidget.
- // |popup_type| indicates if the widget is a popup and what kind of popup it
- // is (select, autofill...).
virtual void CreateNewWidget(int32_t render_process_id,
- int32_t route_id,
- mojom::WidgetPtr widget,
- blink::WebPopupType popup_type) {}
+ int32_t widget_route_id,
+ mojom::WidgetPtr widget) {}
// Creates a full screen RenderWidget. Similar to above.
virtual void CreateNewFullscreenWidget(int32_t render_process_id,
- int32_t route_id,
+ int32_t widget_route_id,
mojom::WidgetPtr widget) {}
// Show the newly created widget with the specified bounds.
// The widget is identified by the route_id passed to CreateNewWidget.
virtual void ShowCreatedWidget(int process_id,
- int route_id,
+ int widget_route_id,
const gfx::Rect& initial_rect) {}
// Show the newly created full screen widget. Similar to above.
- virtual void ShowCreatedFullscreenWidget(int process_id, int route_id) {}
+ virtual void ShowCreatedFullscreenWidget(int process_id,
+ int widget_route_id) {}
// Returns the SessionStorageNamespace the render view should use. Might
// create the SessionStorageNamespace on the fly.
diff --git a/chromium/content/browser/renderer_host/render_view_host_delegate_view.cc b/chromium/content/browser/renderer_host/render_view_host_delegate_view.cc
index 746ea590371..ac2f6c67d0c 100644
--- a/chromium/content/browser/renderer_host/render_view_host_delegate_view.cc
+++ b/chromium/content/browser/renderer_host/render_view_host_delegate_view.cc
@@ -21,7 +21,7 @@ int RenderViewHostDelegateView::GetBottomControlsHeight() const {
return 0;
}
-bool RenderViewHostDelegateView::DoBrowserControlsShrinkBlinkSize() const {
+bool RenderViewHostDelegateView::DoBrowserControlsShrinkRendererSize() const {
return false;
}
diff --git a/chromium/content/browser/renderer_host/render_view_host_delegate_view.h b/chromium/content/browser/renderer_host/render_view_host_delegate_view.h
index 62e97446fb0..3b77252b775 100644
--- a/chromium/content/browser/renderer_host/render_view_host_delegate_view.h
+++ b/chromium/content/browser/renderer_host/render_view_host_delegate_view.h
@@ -80,8 +80,8 @@ class CONTENT_EXPORT RenderViewHostDelegateView {
// Returns the height of the bottom controls in DIP.
virtual int GetBottomControlsHeight() const;
- // Returns true if the browser controls resize Blink's view size.
- virtual bool DoBrowserControlsShrinkBlinkSize() const;
+ // Returns true if the browser controls resize the renderer's view size.
+ virtual bool DoBrowserControlsShrinkRendererSize() const;
// Do post-event tasks for gesture events.
virtual void GestureEventAck(const blink::WebGestureEvent& event,
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 a25a92f7eb0..20e2b14881a 100644
--- a/chromium/content/browser/renderer_host/render_view_host_impl.cc
+++ b/chromium/content/browser/renderer_host/render_view_host_impl.cc
@@ -23,6 +23,7 @@
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/sys_info.h"
+#include "base/task/post_task.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
#include "base/values.h"
@@ -52,10 +53,14 @@
#include "content/common/renderer.mojom.h"
#include "content/common/swapped_out_messages.h"
#include "content/common/view_messages.h"
+// TODO(ajwong): Remove widget_messages.h when WidgetHostMsg_Close is moved to
+// only RenderWidgetHostImpl.
+#include "content/common/widget_messages.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"
#include "content/public/browser/browser_message_filter.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/native_web_keyboard_event.h"
@@ -70,8 +75,6 @@
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/context_menu_params.h"
-#include "content/public/common/file_chooser_file_info.h"
-#include "content/public/common/file_chooser_params.h"
#include "content/public/common/result_codes.h"
#include "content/public/common/url_constants.h"
#include "content/public/common/url_utils.h"
@@ -93,7 +96,6 @@
#include "url/url_constants.h"
#if defined(OS_WIN)
-#include "base/win/win_client_metrics.h"
#include "ui/display/win/screen_win.h"
#include "ui/gfx/geometry/dip_util.h"
#include "ui/gfx/platform_font_win.h"
@@ -118,30 +120,33 @@ using RoutingIDViewMap = base::hash_map<RenderViewHostID, RenderViewHostImpl*>;
base::LazyInstance<RoutingIDViewMap>::Leaky g_routing_id_view_map =
LAZY_INSTANCE_INITIALIZER;
-void GetPlatformSpecificPrefs(RendererPreferences* prefs) {
#if defined(OS_WIN)
- NONCLIENTMETRICS_XP metrics = {0};
- base::win::GetNonClientMetrics(&metrics);
-
- prefs->caption_font_family_name = metrics.lfCaptionFont.lfFaceName;
- prefs->caption_font_height = gfx::PlatformFontWin::GetFontSize(
- metrics.lfCaptionFont);
-
- prefs->small_caption_font_family_name = metrics.lfSmCaptionFont.lfFaceName;
- prefs->small_caption_font_height = gfx::PlatformFontWin::GetFontSize(
- metrics.lfSmCaptionFont);
-
- prefs->menu_font_family_name = metrics.lfMenuFont.lfFaceName;
- prefs->menu_font_height = gfx::PlatformFontWin::GetFontSize(
- metrics.lfMenuFont);
-
- prefs->status_font_family_name = metrics.lfStatusFont.lfFaceName;
- prefs->status_font_height = gfx::PlatformFontWin::GetFontSize(
- metrics.lfStatusFont);
+// Fetches the name and font size of a particular Windows system font.
+void GetFontInfo(gfx::PlatformFontWin::SystemFont system_font,
+ base::string16* name,
+ int32_t* size) {
+ const gfx::Font& font = gfx::PlatformFontWin::GetSystemFont(system_font);
+ *name = base::UTF8ToUTF16(font.GetFontName());
+ *size = font.GetFontSize();
+}
+#endif // OS_WIN
- prefs->message_font_family_name = metrics.lfMessageFont.lfFaceName;
- prefs->message_font_height = gfx::PlatformFontWin::GetFontSize(
- metrics.lfMessageFont);
+void GetPlatformSpecificPrefs(RendererPreferences* prefs) {
+#if defined(OS_WIN)
+ // Note that what is called "height" in this struct is actually the font size;
+ // font "height" typically includes ascender, descender, and padding and is
+ // often a third or so larger than the given font size.
+ GetFontInfo(gfx::PlatformFontWin::SystemFont::kCaption,
+ &prefs->caption_font_family_name, &prefs->caption_font_height);
+ GetFontInfo(gfx::PlatformFontWin::SystemFont::kSmallCaption,
+ &prefs->small_caption_font_family_name,
+ &prefs->small_caption_font_height);
+ GetFontInfo(gfx::PlatformFontWin::SystemFont::kMenu,
+ &prefs->menu_font_family_name, &prefs->menu_font_height);
+ GetFontInfo(gfx::PlatformFontWin::SystemFont::kMessage,
+ &prefs->message_font_family_name, &prefs->message_font_height);
+ GetFontInfo(gfx::PlatformFontWin::SystemFont::kStatus,
+ &prefs->status_font_family_name, &prefs->status_font_height);
prefs->vertical_scroll_bar_width_in_dips =
display::win::ScreenWin::GetSystemMetricsInDIP(SM_CXVSCROLL);
@@ -182,8 +187,7 @@ RenderViewHost* RenderViewHost::From(RenderWidgetHost* rwh) {
RenderViewHostImpl* RenderViewHostImpl::FromID(int process_id, int routing_id) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
RoutingIDViewMap* views = g_routing_id_view_map.Pointer();
- RoutingIDViewMap::iterator it =
- views->find(RenderViewHostID(process_id, routing_id));
+ auto it = views->find(RenderViewHostID(process_id, routing_id));
return it == views->end() ? nullptr : it->second;
}
@@ -244,16 +248,13 @@ RenderViewHostImpl::RenderViewHostImpl(
if (!is_active_)
GetWidget()->UpdatePriority();
- if (ResourceDispatcherHostImpl::Get()) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(
- &ResourceDispatcherHostImpl::OnRenderViewHostCreated,
- base::Unretained(ResourceDispatcherHostImpl::Get()),
- GetProcess()->GetID(), GetRoutingID(),
- base::RetainedRef(
- GetProcess()->GetStoragePartition()->GetURLRequestContext())));
- }
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(
+ &ResourceDispatcherHostImpl::OnRenderViewHostCreated,
+ GetProcess()->GetID(), GetRoutingID(),
+ base::RetainedRef(
+ GetProcess()->GetStoragePartition()->GetURLRequestContext())));
close_timeout_.reset(new TimeoutMonitor(base::Bind(
&RenderViewHostImpl::ClosePageTimeout, weak_factory_.GetWeakPtr())));
@@ -262,13 +263,10 @@ RenderViewHostImpl::RenderViewHostImpl(
}
RenderViewHostImpl::~RenderViewHostImpl() {
- if (ResourceDispatcherHostImpl::Get()) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&ResourceDispatcherHostImpl::OnRenderViewHostDeleted,
- base::Unretained(ResourceDispatcherHostImpl::Get()),
- GetProcess()->GetID(), GetRoutingID()));
- }
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(&ResourceDispatcherHostImpl::OnRenderViewHostDeleted,
+ GetProcess()->GetID(), GetRoutingID()));
// Detach the routing ID as the object is going away.
GetProcess()->RemoveRoute(GetRoutingID());
@@ -584,9 +582,6 @@ WebPreferences RenderViewHostImpl::ComputeWebkitPrefs() {
if (delegate_ && delegate_->HasPersistentVideo())
prefs.media_controls_enabled = false;
- prefs.background_video_track_optimization_enabled =
- base::FeatureList::IsEnabled(media::kBackgroundVideoTrackOptimization);
-
GetContentClient()->browser()->OverrideWebkitPrefs(this, &prefs);
return prefs;
}
@@ -723,8 +718,7 @@ void RenderViewHostImpl::DirectoryEnumerationFinished(
int request_id,
const std::vector<base::FilePath>& files) {
// Grant the security access requested to the given files.
- for (std::vector<base::FilePath>::const_iterator file = files.begin();
- file != files.end(); ++file) {
+ for (auto file = files.begin(); file != files.end(); ++file) {
ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile(
GetProcess()->GetID(), *file);
}
@@ -734,14 +728,10 @@ void RenderViewHostImpl::DirectoryEnumerationFinished(
}
void RenderViewHostImpl::RenderWidgetWillSetIsLoading(bool is_loading) {
- if (ResourceDispatcherHostImpl::Get()) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(
- &ResourceDispatcherHostImpl::OnRenderViewHostSetIsLoading,
- base::Unretained(ResourceDispatcherHostImpl::Get()),
- GetProcess()->GetID(), GetRoutingID(), is_loading));
- }
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(&ResourceDispatcherHostImpl::OnRenderViewHostSetIsLoading,
+ GetProcess()->GetID(), GetRoutingID(), is_loading));
}
bool RenderViewHostImpl::SuddenTerminationAllowed() const {
@@ -778,13 +768,13 @@ bool RenderViewHostImpl::OnMessageReceived(const IPC::Message& msg) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(RenderViewHostImpl, msg)
- IPC_MESSAGE_HANDLER(FrameHostMsg_RenderProcessGone, OnRenderProcessGone)
IPC_MESSAGE_HANDLER(ViewHostMsg_ShowWidget, OnShowWidget)
IPC_MESSAGE_HANDLER(ViewHostMsg_ShowFullscreenWidget,
OnShowFullscreenWidget)
IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateTargetURL, OnUpdateTargetURL)
- IPC_MESSAGE_HANDLER(ViewHostMsg_Close, OnClose)
- IPC_MESSAGE_HANDLER(ViewHostMsg_RequestSetBounds, OnRequestSetBounds)
+ // TODO:(ajwong): Move OnClose to RenderWidgetHostOwnerDelegate.
+ // https://crbug.com/545684
+ IPC_MESSAGE_HANDLER(WidgetHostMsg_Close, OnClose)
IPC_MESSAGE_HANDLER(ViewHostMsg_DocumentAvailableInMainFrame,
OnDocumentAvailableInMainFrame)
IPC_MESSAGE_HANDLER(ViewHostMsg_DidContentsPreferredSizeChange,
@@ -809,44 +799,37 @@ void RenderViewHostImpl::ShutdownAndDestroy() {
// in the renderer has wound down.
if (GetProcess()->IsInitializedAndNotDead()) {
RenderProcessHostImpl::ReleaseOnCloseACK(
- GetProcess(),
- delegate_->GetSessionStorageNamespaceMap(),
- GetRoutingID());
+ GetProcess(), delegate_->GetSessionStorageNamespaceMap(),
+ GetWidget()->GetRoutingID());
}
GetWidget()->ShutdownAndDestroyWidget(false);
delete this;
}
-void RenderViewHostImpl::CreateNewWidget(int32_t route_id,
- mojom::WidgetPtr widget,
- blink::WebPopupType popup_type) {
- delegate_->CreateNewWidget(GetProcess()->GetID(), route_id, std::move(widget),
- popup_type);
+void RenderViewHostImpl::CreateNewWidget(int32_t widget_route_id,
+ mojom::WidgetPtr widget) {
+ delegate_->CreateNewWidget(GetProcess()->GetID(), widget_route_id,
+ std::move(widget));
}
-void RenderViewHostImpl::CreateNewFullscreenWidget(int32_t route_id,
+void RenderViewHostImpl::CreateNewFullscreenWidget(int32_t widget_route_id,
mojom::WidgetPtr widget) {
- delegate_->CreateNewFullscreenWidget(GetProcess()->GetID(), route_id,
+ delegate_->CreateNewFullscreenWidget(GetProcess()->GetID(), widget_route_id,
std::move(widget));
}
-void RenderViewHostImpl::OnShowWidget(int route_id,
+void RenderViewHostImpl::OnShowWidget(int widget_route_id,
const gfx::Rect& initial_rect) {
- delegate_->ShowCreatedWidget(GetProcess()->GetID(), route_id, initial_rect);
- Send(new ViewMsg_SetBounds_ACK(route_id));
-}
-
-void RenderViewHostImpl::OnShowFullscreenWidget(int route_id) {
- delegate_->ShowCreatedFullscreenWidget(GetProcess()->GetID(), route_id);
- Send(new ViewMsg_SetBounds_ACK(route_id));
+ delegate_->ShowCreatedWidget(GetProcess()->GetID(), widget_route_id,
+ initial_rect);
+ Send(new WidgetMsg_SetBounds_ACK(widget_route_id));
}
-void RenderViewHostImpl::OnRenderProcessGone(int status, int exit_code) {
- // Do nothing, otherwise RenderWidgetHostImpl will assume it is not a
- // RenderViewHostImpl and destroy itself.
- // TODO(nasko): Remove this hack once RenderViewHost and RenderWidgetHost are
- // decoupled.
+void RenderViewHostImpl::OnShowFullscreenWidget(int widget_route_id) {
+ delegate_->ShowCreatedFullscreenWidget(GetProcess()->GetID(),
+ widget_route_id);
+ Send(new WidgetMsg_SetBounds_ACK(widget_route_id));
}
void RenderViewHostImpl::OnUpdateTargetURL(const GURL& url) {
@@ -863,12 +846,6 @@ void RenderViewHostImpl::OnClose() {
ClosePageIgnoringUnloadEvents();
}
-void RenderViewHostImpl::OnRequestSetBounds(const gfx::Rect& bounds) {
- if (is_active_)
- delegate_->RequestSetBounds(bounds);
- Send(new ViewMsg_SetBounds_ACK(GetRoutingID()));
-}
-
void RenderViewHostImpl::OnDocumentAvailableInMainFrame(
bool uses_temporary_zoom_level) {
delegate_->DocumentAvailableInMainFrame(this);
@@ -933,9 +910,9 @@ bool RenderViewHostImpl::ShouldContributePriorityToProcess() {
return is_active_;
}
-void RenderViewHostImpl::RenderWidgetDidShutdown() {
- bool rv = Send(new ViewMsg_Close(GetRoutingID()));
- DCHECK(rv);
+void RenderViewHostImpl::RequestSetBounds(const gfx::Rect& bounds) {
+ if (is_active_)
+ delegate_->RequestSetBounds(bounds);
}
WebPreferences RenderViewHostImpl::GetWebkitPreferences() {
@@ -987,10 +964,6 @@ void RenderViewHostImpl::NotifyMoveOrResizeStarted() {
Send(new ViewMsg_MoveOrResizeStarted(GetRoutingID()));
}
-void RenderViewHostImpl::SelectWordAroundCaret() {
- Send(new ViewMsg_SelectWordAroundCaret(GetRoutingID()));
-}
-
void RenderViewHostImpl::PostRenderViewReady() {
GetProcess()->PostTaskWhenProcessIsReady(base::BindOnce(
&RenderViewHostImpl::RenderViewReady, weak_factory_.GetWeakPtr()));
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 af7f7b0d580..e70977a3f79 100644
--- a/chromium/content/browser/renderer_host/render_view_host_impl.h
+++ b/chromium/content/browser/renderer_host/render_view_host_impl.h
@@ -31,7 +31,6 @@
#include "net/base/load_states.h"
#include "third_party/blink/public/web/web_ax_enums.h"
#include "third_party/blink/public/web/web_console_message.h"
-#include "third_party/blink/public/web/web_popup_type.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/base/mojo/window_open_disposition.mojom.h"
@@ -110,7 +109,6 @@ class CONTENT_EXPORT RenderViewHostImpl : public RenderViewHost,
WebPreferences GetWebkitPreferences() override;
void UpdateWebkitPreferences(const WebPreferences& prefs) override;
void OnWebkitPreferencesChanged() override;
- void SelectWordAroundCaret() override;
// RenderProcessHostObserver implementation
void RenderProcessExited(RenderProcessHost* host,
@@ -193,11 +191,8 @@ class CONTENT_EXPORT RenderViewHostImpl : public RenderViewHost,
sudden_termination_allowed_ = enabled;
}
- // Creates a new RenderWidget with the given route id. |popup_type| indicates
- // if this widget is a popup and what kind of popup it is (select, autofill).
- void CreateNewWidget(int32_t route_id,
- mojom::WidgetPtr widget,
- blink::WebPopupType popup_type);
+ // Creates a new RenderWidget with the given route id.
+ void CreateNewWidget(int32_t route_id, mojom::WidgetPtr widget);
// Creates a full screen RenderWidget.
void CreateNewFullscreenWidget(int32_t route_id, mojom::WidgetPtr widget);
@@ -239,19 +234,17 @@ class CONTENT_EXPORT RenderViewHostImpl : public RenderViewHost,
bool MayRenderWidgetForwardKeyboardEvent(
const NativeWebKeyboardEvent& key_event) override;
bool ShouldContributePriorityToProcess() override;
- void RenderWidgetDidShutdown() override;
+ void RequestSetBounds(const gfx::Rect& bounds) override;
// IPC message handlers.
void OnShowView(int route_id,
WindowOpenDisposition disposition,
const gfx::Rect& initial_rect,
bool user_gesture);
- void OnShowWidget(int route_id, const gfx::Rect& initial_rect);
- void OnShowFullscreenWidget(int route_id);
- void OnRenderProcessGone(int status, int error_code);
+ void OnShowWidget(int widget_route_id, const gfx::Rect& initial_rect);
+ void OnShowFullscreenWidget(int widget_route_id);
void OnUpdateTargetURL(const GURL& url);
void OnClose();
- void OnRequestSetBounds(const gfx::Rect& bounds);
void OnDocumentAvailableInMainFrame(bool uses_temporary_zoom_level);
void OnDidContentsPreferredSizeChange(const gfx::Size& new_size);
void OnPasteFromSelectionClipboard();
diff --git a/chromium/content/browser/renderer_host/render_widget_helper.cc b/chromium/content/browser/renderer_host/render_widget_helper.cc
index c54233d8e1c..2fe97895d9c 100644
--- a/chromium/content/browser/renderer_host/render_widget_helper.cc
+++ b/chromium/content/browser/renderer_host/render_widget_helper.cc
@@ -8,11 +8,13 @@
#include "base/bind_helpers.h"
#include "base/lazy_instance.h"
#include "base/posix/eintr_wrapper.h"
+#include "base/task/post_task.h"
#include "base/threading/thread.h"
#include "base/threading/thread_restrictions.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/common/view_messages.h"
+#include "content/public/browser/browser_task_traits.h"
namespace content {
namespace {
@@ -39,7 +41,7 @@ RenderWidgetHelper::~RenderWidgetHelper() {
// Delete this RWH from the map if it is found.
WidgetHelperMap& widget_map = g_widget_helpers.Get();
- WidgetHelperMap::iterator it = widget_map.find(render_process_id_);
+ auto it = widget_map.find(render_process_id_);
if (it != widget_map.end() && it->second == this)
widget_map.erase(it);
}
@@ -50,9 +52,9 @@ void RenderWidgetHelper::Init(
render_process_id_ = render_process_id;
resource_dispatcher_host_ = resource_dispatcher_host;
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::BindOnce(&AddWidgetHelper, render_process_id_,
- base::WrapRefCounted(this)));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(&AddWidgetHelper, render_process_id_,
+ base::WrapRefCounted(this)));
}
int RenderWidgetHelper::GetNextRoutingID() {
@@ -69,37 +71,35 @@ RenderWidgetHelper* RenderWidgetHelper::FromProcessHostID(
}
void RenderWidgetHelper::CreateNewWidget(int opener_id,
- blink::WebPopupType popup_type,
mojom::WidgetPtr widget,
int* route_id) {
*route_id = GetNextRoutingID();
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&RenderWidgetHelper::OnCreateWidgetOnUI, this, opener_id,
- *route_id, widget.PassInterface(), popup_type));
+ *route_id, widget.PassInterface()));
}
void RenderWidgetHelper::CreateNewFullscreenWidget(int opener_id,
mojom::WidgetPtr widget,
int* route_id) {
*route_id = GetNextRoutingID();
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&RenderWidgetHelper::OnCreateFullscreenWidgetOnUI, this,
opener_id, *route_id, widget.PassInterface()));
}
void RenderWidgetHelper::OnCreateWidgetOnUI(int32_t opener_id,
int32_t route_id,
- mojom::WidgetPtrInfo widget_info,
- blink::WebPopupType popup_type) {
+ mojom::WidgetPtrInfo widget_info) {
mojom::WidgetPtr widget;
widget.Bind(std::move(widget_info));
RenderViewHostImpl* host = RenderViewHostImpl::FromID(
render_process_id_, opener_id);
if (host)
- host->CreateNewWidget(route_id, std::move(widget), popup_type);
+ host->CreateNewWidget(route_id, std::move(widget));
}
void RenderWidgetHelper::OnCreateFullscreenWidgetOnUI(
diff --git a/chromium/content/browser/renderer_host/render_widget_helper.h b/chromium/content/browser/renderer_host/render_widget_helper.h
index 30012c94a8c..3ceda85b738 100644
--- a/chromium/content/browser/renderer_host/render_widget_helper.h
+++ b/chromium/content/browser/renderer_host/render_widget_helper.h
@@ -18,7 +18,7 @@
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/global_request_id.h"
-#include "third_party/blink/public/web/web_popup_type.h"
+#include "content/public/common/widget_type.h"
#include "ui/gfx/native_widget_types.h"
namespace content {
@@ -50,7 +50,6 @@ class RenderWidgetHelper
// IO THREAD ONLY -----------------------------------------------------------
void CreateNewWidget(int opener_id,
- blink::WebPopupType popup_type,
mojom::WidgetPtr,
int* route_id);
void CreateNewFullscreenWidget(int opener_id,
@@ -67,8 +66,7 @@ class RenderWidgetHelper
// Called on the UI thread to finish creating a widget.
void OnCreateWidgetOnUI(int32_t opener_id,
int32_t route_id,
- mojom::WidgetPtrInfo widget,
- blink::WebPopupType popup_type);
+ mojom::WidgetPtrInfo widget);
// Called on the UI thread to create a fullscreen widget.
void OnCreateFullscreenWidgetOnUI(int32_t opener_id,
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 373ecd28b14..f7bb0bcd2d4 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_browsertest.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_browsertest.cc
@@ -4,18 +4,11 @@
#include <vector>
-#include "base/optional.h"
#include "base/run_loop.h"
-#include "base/threading/thread_task_runner_handle.h"
+#include "base/test/bind_test_util.h"
#include "base/time/time.h"
-#include "components/viz/common/features.h"
-#include "components/viz/common/frame_sinks/copy_output_request.h"
-#include "components/viz/common/frame_sinks/copy_output_result.h"
-#include "components/viz/common/quads/compositor_frame.h"
-#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/input_router_impl.h"
+#include "content/browser/renderer_host/input/synthetic_smooth_drag_gesture.h"
#include "content/browser/renderer_host/input/touch_action_filter.h"
#include "content/browser/renderer_host/input/touch_emulator.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
@@ -25,37 +18,24 @@
#include "content/common/input/synthetic_web_input_event_builders.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_observer.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 "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 "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 {
-class RenderWidgetHostBrowserTest : public ContentBrowserTest {
- protected:
- WebContentsImpl* web_contents() const {
- return static_cast<WebContentsImpl*>(shell()->web_contents());
- }
-
- TouchActionFilter* GetTouchActionFilterForWidget(RenderWidgetHostImpl* rwhi) {
- return &static_cast<InputRouterImpl*>(rwhi->input_router())
- ->touch_action_filter_;
- }
-};
-
-// The --site-per-porcess version of RenderWidgetHostBrowserTest.
-class RenderWidgetHostSitePerProcessTest : public RenderWidgetHostBrowserTest {
+// This test enables --site-per-porcess flag.
+class RenderWidgetHostSitePerProcessTest : public ContentBrowserTest {
public:
void SetUpCommandLine(base::CommandLine* command_line) override {
IsolateAllSitesForTesting(command_line);
@@ -66,70 +46,17 @@ class RenderWidgetHostSitePerProcessTest : public RenderWidgetHostBrowserTest {
SetupCrossSiteRedirector(embedded_test_server());
ASSERT_TRUE(embedded_test_server()->Start());
}
-};
-IN_PROC_BROWSER_TEST_F(RenderWidgetHostBrowserTest,
- ProhibitsCopyRequestsFromRenderer) {
- NavigateToURL(shell(), GURL("data:text/html,<!doctype html>"
- "<body style='background-color: red;'></body>"));
-
- // Wait for the view's surface to become available.
- auto* const view = static_cast<RenderWidgetHostViewBase*>(
- shell()->web_contents()->GetRenderWidgetHostView());
- while (!view->IsSurfaceAvailableForCopy()) {
- base::RunLoop run_loop;
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, run_loop.QuitClosure(),
- base::TimeDelta::FromMilliseconds(250));
- run_loop.Run();
+ protected:
+ WebContentsImpl* web_contents() const {
+ return static_cast<WebContentsImpl*>(shell()->web_contents());
}
- // The browser process should be allowed to make a CopyOutputRequest.
- bool did_receive_copy_result = false;
- base::RunLoop run_loop;
- view->CopyFromSurface(gfx::Rect(), gfx::Size(),
- base::BindOnce(
- [](bool* success, base::OnceClosure quit_closure,
- const SkBitmap& bitmap) {
- *success = !bitmap.drawsNothing();
- std::move(quit_closure).Run();
- },
- &did_receive_copy_result, run_loop.QuitClosure()));
- run_loop.Run();
- ASSERT_TRUE(did_receive_copy_result);
-
- // Create a simulated-from-renderer CompositorFrame with a CopyOutputRequest.
- viz::CompositorFrame frame;
- std::unique_ptr<viz::RenderPass> pass = viz::RenderPass::Create();
- const gfx::Rect output_rect =
- gfx::Rect(view->GetCompositorViewportPixelSize());
- pass->SetNew(1 /* render pass id */, output_rect, output_rect,
- gfx::Transform());
- bool did_receive_aborted_copy_result = false;
- pass->copy_requests.push_back(std::make_unique<viz::CopyOutputRequest>(
- viz::CopyOutputRequest::ResultFormat::RGBA_BITMAP,
- base::BindOnce(
- [](bool* got_nothing, std::unique_ptr<viz::CopyOutputResult> result) {
- *got_nothing = result->IsEmpty();
- },
- &did_receive_aborted_copy_result)));
- frame.render_pass_list.push_back(std::move(pass));
-
- // 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),
- 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);
-
- // Check that the copy request result callback received an empty result. In a
- // normal browser, the requestor (in the render process) might never see a
- // response to the copy request before the process is killed. Nevertheless,
- // ensure the result is empty, just in case there is a race.
- EXPECT_TRUE(did_receive_aborted_copy_result);
-}
+ TouchActionFilter* GetTouchActionFilterForWidget(RenderWidgetHostImpl* rwhi) {
+ return &static_cast<InputRouterImpl*>(rwhi->input_router())
+ ->touch_action_filter_;
+ }
+};
class TestInputEventObserver : public RenderWidgetHost::InputEventObserver {
public:
@@ -163,8 +90,7 @@ class TestInputEventObserver : public RenderWidgetHost::InputEventObserver {
blink::WebInputEvent::Type acked_touch_event_type_;
};
-class RenderWidgetHostTouchEmulatorBrowserTest
- : public RenderWidgetHostBrowserTest {
+class RenderWidgetHostTouchEmulatorBrowserTest : public ContentBrowserTest {
public:
RenderWidgetHostTouchEmulatorBrowserTest()
: view_(nullptr),
@@ -174,7 +100,7 @@ class RenderWidgetHostTouchEmulatorBrowserTest
simulated_event_time_delta_(base::TimeDelta::FromMilliseconds(100)) {}
void SetUpOnMainThread() override {
- RenderWidgetHostBrowserTest::SetUpOnMainThread();
+ ContentBrowserTest::SetUpOnMainThread();
NavigateToURL(shell(),
GURL("data:text/html,<!doctype html>"
@@ -217,6 +143,58 @@ class RenderWidgetHostTouchEmulatorBrowserTest
base::TimeDelta simulated_event_time_delta_;
};
+// Synthetic mouse events not allowed on Android.
+#if !defined(OS_ANDROID)
+// This test makes sure that TouchEmulator doesn't emit a GestureScrollEnd without a valid
+// unique_touch_event_id when it sees a GestureFlingStart terminating the underlying mouse
+// scroll sequence. If the GestureScrollEnd is given a unique_touch_event_id of 0, then a
+// crash will occur.
+IN_PROC_BROWSER_TEST_F(RenderWidgetHostTouchEmulatorBrowserTest,
+ TouchEmulatorPinchWithGestureFling) {
+ auto* touch_emulator = host()->GetTouchEmulator();
+ touch_emulator->Enable(TouchEmulator::Mode::kEmulatingTouchFromMouse,
+ ui::GestureProviderConfigType::GENERIC_MOBILE);
+ touch_emulator->SetPinchGestureModeForTesting(true);
+
+ TestInputEventObserver observer;
+ host()->AddInputEventObserver(&observer);
+
+ SyntheticSmoothDragGestureParams params;
+ params.start_point = gfx::PointF(10.f, 110.f);
+ params.gesture_source_type = SyntheticGestureParams::MOUSE_INPUT;
+ params.distances.push_back(gfx::Vector2d(0, -10));
+ params.distances.push_back(gfx::Vector2d(0, -10));
+ params.distances.push_back(gfx::Vector2d(0, -10));
+ params.distances.push_back(gfx::Vector2d(0, -10));
+ params.speed_in_pixels_s = 1200;
+
+ std::unique_ptr<SyntheticSmoothDragGesture> gesture(
+ new SyntheticSmoothDragGesture(params));
+
+ InputEventAckWaiter scroll_end_ack_waiter(
+ host(), blink::WebInputEvent::kGestureScrollEnd);
+ base::RunLoop run_loop;
+ host()->QueueSyntheticGesture(
+ std::move(gesture),
+ base::BindOnce(
+ base::BindLambdaForTesting([&](SyntheticGesture::Result result) {
+ EXPECT_EQ(SyntheticGesture::GESTURE_FINISHED, result);
+ run_loop.Quit();
+ })));
+ run_loop.Run();
+ scroll_end_ack_waiter.Wait();
+
+ // Verify that a GestureFlingStart was suppressed by the TouchEmulator, and
+ // that we generated a GestureScrollEnd and routed it without crashing.
+ TestInputEventObserver::EventTypeVector dispatched_events =
+ observer.GetAndResetDispatchedEventTypes();
+ auto it_gse = std::find(dispatched_events.begin(), dispatched_events.end(),
+ blink::WebInputEvent::kGestureScrollEnd);
+ EXPECT_NE(dispatched_events.end(), it_gse);
+ EXPECT_TRUE(touch_emulator->suppress_next_fling_cancel_for_testing());
+}
+#endif // !defined(OS_ANDROID)
+
IN_PROC_BROWSER_TEST_F(RenderWidgetHostTouchEmulatorBrowserTest,
TouchEmulator) {
// All touches will be immediately acked instead of sending them to the
diff --git a/chromium/content/browser/renderer_host/render_widget_host_delegate.cc b/chromium/content/browser/renderer_host/render_widget_host_delegate.cc
index aa01d7b2207..82ce0212717 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_delegate.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_delegate.cc
@@ -12,6 +12,14 @@
namespace content {
+bool RenderWidgetHostDelegate::DoBrowserControlsShrinkRendererSize() const {
+ return false;
+}
+
+int RenderWidgetHostDelegate::GetTopControlsHeight() const {
+ return 0;
+}
+
KeyboardEventProcessingResult RenderWidgetHostDelegate::PreHandleKeyboardEvent(
const NativeWebKeyboardEvent& event) {
return KeyboardEventProcessingResult::NOT_HANDLED;
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 387c81db0e0..883409580f8 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_delegate.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_delegate.h
@@ -56,6 +56,15 @@ struct NativeWebKeyboardEvent;
// of the RenderWidgetHost.
class CONTENT_EXPORT RenderWidgetHostDelegate {
public:
+ // Functions for controlling the browser top controls slide behavior with page
+ // gesture scrolling.
+ virtual void SetTopControlsShownRatio(
+ RenderWidgetHostImpl* render_widget_host,
+ float ratio) {}
+ virtual bool DoBrowserControlsShrinkRendererSize() const;
+ virtual int GetTopControlsHeight() const;
+ virtual void SetTopControlsGestureScrollInProgress(bool in_progress) {}
+
// The RenderWidgetHost has just been created.
virtual void RenderWidgetCreated(RenderWidgetHostImpl* render_widget_host) {}
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 437b43ade73..807466aeeda 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_impl.cc
@@ -15,7 +15,6 @@
#include "base/bind.h"
#include "base/command_line.h"
#include "base/containers/hash_tables.h"
-#include "base/debug/dump_without_crashing.h"
#include "base/i18n/rtl.h"
#include "base/lazy_instance.h"
#include "base/location.h"
@@ -73,6 +72,7 @@
#include "content/common/text_input_state.h"
#include "content/common/view_messages.h"
#include "content/common/visual_properties.h"
+#include "content/common/widget_messages.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/keyboard_event_processing_result.h"
@@ -347,7 +347,6 @@ RenderWidgetHostImpl::RenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
visual_properties_ack_pending_(false),
auto_resize_enabled_(false),
waiting_for_screen_rects_ack_(false),
- needs_repainting_on_restore_(false),
is_unresponsive_(false),
in_flight_event_count_(0),
in_get_backing_store_(false),
@@ -454,8 +453,7 @@ RenderWidgetHostImpl* RenderWidgetHostImpl::FromID(
int32_t routing_id) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
RoutingIDWidgetMap* widgets = g_routing_id_widget_map.Pointer();
- RoutingIDWidgetMap::iterator it = widgets->find(
- RenderWidgetHostID(process_id, routing_id));
+ auto it = widgets->find(RenderWidgetHostID(process_id, routing_id));
return it == widgets->end() ? NULL : it->second;
}
@@ -557,8 +555,8 @@ void RenderWidgetHostImpl::SendScreenRects() {
last_view_screen_rect_ = view_->GetViewBounds();
last_window_screen_rect_ = view_->GetBoundsInRootWindow();
view_->WillSendScreenRects();
- Send(new ViewMsg_UpdateScreenRects(
- GetRoutingID(), last_view_screen_rect_, last_window_screen_rect_));
+ Send(new WidgetMsg_UpdateScreenRects(GetRoutingID(), last_view_screen_rect_,
+ last_window_screen_rect_));
waiting_for_screen_rects_ack_ = true;
}
@@ -611,41 +609,9 @@ void RenderWidgetHostImpl::ShutdownAndDestroyWidget(bool also_delete) {
RejectMouseLockOrUnlockIfNecessary();
if (process_->IsInitializedAndNotDead()) {
- // This logic below simulates the routing behavior from when RenderWidget
- // associated with RenderViews shared the same routing IDs.
- //
- // In the original code, the sharing of the routing ID yielded a bastardized
- // version of dynamic dispatch wherein the ultimate static code path that
- // handled a ViewMsg_Close changed based on if
- //
- // (a) the RenderWidgetImpl was also a RenderViewImpl
- // (b) the RenderViewImpl hooked the message in OnMessageReceived
- //
- // In the current code, if RenderWidgetImpl IS NOT a RenderViewImpl,
- // RenderWidgetHost WILL NOT have a |owner_delegate_| and the message can
- // be dispatched directly. This is the simplest case.
- //
- // If RenderWidgetImpl IS is a RenderViewImpl, then on some platforms
- // (seems like only Mac?) RenderViewImpl overrides ViewMsg::OnClose to do
- // additional processing before passing it up to RenderWidgetImpl::OnClose.
- //
- // When it is not overridden, the message delegated up via
- // IPC_MESSAGE_UNHANDLED to the RenderWidget's message dispatching.
- //
- // Basically, there are 2 overlapping hand-written implementations of
- // dynamic dispatch occuring: one via IPC_MESSAGE_UNHANDLED, and another
- // via calling the super-class method.
- //
- // TODO(ajwong): Once the routing_id split CL lands, remove one of these
- // implementaions of hand-written dyanmic dispatch. The world does not
- // need so many implementations of what's effectively "virtual."
- if (owner_delegate_) {
- owner_delegate_->RenderWidgetDidShutdown();
- } else {
- // Tell the non-view RendererWidget to close.
- bool rv = Send(new ViewMsg_Close(routing_id_));
- DCHECK(rv);
- }
+ // Tell the RendererWidget to close.
+ bool rv = Send(new WidgetMsg_Close(routing_id_));
+ DCHECK(rv);
}
Destroy(also_delete);
@@ -667,26 +633,27 @@ 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(ViewHostMsg_Close, OnClose)
- IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateScreenRects_ACK,
+ IPC_MESSAGE_HANDLER(WidgetHostMsg_Close, OnClose)
+ IPC_MESSAGE_HANDLER(WidgetHostMsg_UpdateScreenRects_ACK,
OnUpdateScreenRectsAck)
- IPC_MESSAGE_HANDLER(ViewHostMsg_RequestSetBounds, OnRequestSetBounds)
- IPC_MESSAGE_HANDLER(ViewHostMsg_SetTooltipText, OnSetTooltipText)
- IPC_MESSAGE_HANDLER(ViewHostMsg_SetCursor, OnSetCursor)
- IPC_MESSAGE_HANDLER(ViewHostMsg_AutoscrollStart, OnAutoscrollStart)
- IPC_MESSAGE_HANDLER(ViewHostMsg_AutoscrollFling, OnAutoscrollFling)
- IPC_MESSAGE_HANDLER(ViewHostMsg_AutoscrollEnd, OnAutoscrollEnd)
- IPC_MESSAGE_HANDLER(ViewHostMsg_TextInputStateChanged,
+ IPC_MESSAGE_HANDLER(WidgetHostMsg_RequestSetBounds, OnRequestSetBounds)
+ IPC_MESSAGE_HANDLER(WidgetHostMsg_SetTooltipText, OnSetTooltipText)
+ IPC_MESSAGE_HANDLER(WidgetHostMsg_SetCursor, OnSetCursor)
+ IPC_MESSAGE_HANDLER(WidgetHostMsg_AutoscrollStart, OnAutoscrollStart)
+ IPC_MESSAGE_HANDLER(WidgetHostMsg_AutoscrollFling, OnAutoscrollFling)
+ IPC_MESSAGE_HANDLER(WidgetHostMsg_AutoscrollEnd, OnAutoscrollEnd)
+ IPC_MESSAGE_HANDLER(WidgetHostMsg_TextInputStateChanged,
OnTextInputStateChanged)
- IPC_MESSAGE_HANDLER(ViewHostMsg_LockMouse, OnLockMouse)
- IPC_MESSAGE_HANDLER(ViewHostMsg_UnlockMouse, OnUnlockMouse)
- IPC_MESSAGE_HANDLER(ViewHostMsg_SelectionBoundsChanged,
+ IPC_MESSAGE_HANDLER(WidgetHostMsg_LockMouse, OnLockMouse)
+ IPC_MESSAGE_HANDLER(WidgetHostMsg_UnlockMouse, OnUnlockMouse)
+ IPC_MESSAGE_HANDLER(WidgetHostMsg_SelectionBoundsChanged,
OnSelectionBoundsChanged)
- IPC_MESSAGE_HANDLER(ViewHostMsg_FocusedNodeTouched, OnFocusedNodeTouched)
+ IPC_MESSAGE_HANDLER(WidgetHostMsg_FocusedNodeTouched, OnFocusedNodeTouched)
IPC_MESSAGE_HANDLER(DragHostMsg_StartDragging, OnStartDragging)
IPC_MESSAGE_HANDLER(DragHostMsg_UpdateDragCursor, OnUpdateDragCursor)
- IPC_MESSAGE_HANDLER(ViewHostMsg_ForceRedrawComplete, OnForceRedrawComplete)
- IPC_MESSAGE_HANDLER(ViewHostMsg_FrameSwapMessages,
+ IPC_MESSAGE_HANDLER(WidgetHostMsg_ForceRedrawComplete,
+ OnForceRedrawComplete)
+ IPC_MESSAGE_HANDLER(WidgetHostMsg_FrameSwapMessages,
OnFrameSwapMessagesReceived)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
@@ -732,7 +699,7 @@ void RenderWidgetHostImpl::WasHidden() {
// If we have a renderer, then inform it that we are being hidden so it can
// reduce its resource utilization.
- Send(new ViewMsg_WasHidden(routing_id_));
+ Send(new WidgetMsg_WasHidden(routing_id_));
// Tell the RenderProcessHost we were hidden.
process_->UpdateClientPriority(this);
@@ -760,12 +727,9 @@ void RenderWidgetHostImpl::WasShown(bool record_presentation_time) {
SendScreenRects();
RestartInputEventAckTimeoutIfNecessary();
- // Always repaint on restore.
- bool needs_repainting = true;
- needs_repainting_on_restore_ = false;
- Send(new ViewMsg_WasShown(
- routing_id_, needs_repainting,
- record_presentation_time ? base::TimeTicks::Now() : base::TimeTicks()));
+ Send(new WidgetMsg_WasShown(routing_id_, record_presentation_time
+ ? base::TimeTicks::Now()
+ : base::TimeTicks()));
process_->UpdateClientPriority(this);
@@ -779,7 +743,8 @@ void RenderWidgetHostImpl::WasShown(bool record_presentation_time) {
// It's possible for our size to be out of sync with the renderer. The
// following is one case that leads to this:
- // 1. SynchronizeVisualProperties -> Send ViewMsg_SynchronizeVisualProperties
+ // 1. SynchronizeVisualProperties -> Send
+ // WidgetMsg_SynchronizeVisualProperties
// to render.
// 2. SynchronizeVisualProperties -> do nothing as
// sync_visual_props_ack_pending_ is true
@@ -791,7 +756,7 @@ void RenderWidgetHostImpl::WasShown(bool record_presentation_time) {
// necessary. SynchronizeVisualProperties does nothing if the sizes are
// already in sync.
//
- // TODO: ideally ViewMsg_WasShown would take a size. This way, the renderer
+ // TODO: ideally WidgetMsg_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
// SynchronizeVisualProperties is usually processed before the renderer is
@@ -845,7 +810,7 @@ bool RenderWidgetHostImpl::GetVisualProperties(
visual_properties->bottom_controls_height *= device_scale;
}
visual_properties->browser_controls_shrink_blink_size =
- view_->DoBrowserControlsShrinkBlinkSize();
+ view_->DoBrowserControlsShrinkRendererSize();
visual_properties->visible_viewport_size = view_->GetVisibleViewportSize();
// TODO(ccameron): GetLocalSurfaceId is not synchronized with the device
// scale factor of the surface. Fix this.
@@ -968,8 +933,8 @@ bool RenderWidgetHostImpl::SynchronizeVisualProperties(
!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))) {
+ if (Send(new WidgetMsg_SynchronizeVisualProperties(routing_id_,
+ *visual_properties))) {
visual_properties_ack_pending_ = needs_ack;
old_visual_properties_.swap(visual_properties);
sent_visual_properties = true;
@@ -1015,6 +980,13 @@ void RenderWidgetHostImpl::Blur() {
focused_widget->SetPageFocus(false);
}
+void RenderWidgetHostImpl::FlushForTesting() {
+ if (associated_widget_input_handler_)
+ return associated_widget_input_handler_.FlushForTesting();
+ if (widget_input_handler_)
+ return widget_input_handler_.FlushForTesting();
+}
+
void RenderWidgetHostImpl::SetPageFocus(bool focused) {
is_focused_ = focused;
@@ -1053,7 +1025,7 @@ void RenderWidgetHostImpl::LostCapture() {
}
void RenderWidgetHostImpl::SetActive(bool active) {
- Send(new ViewMsg_SetActive(routing_id_, active));
+ Send(new WidgetMsg_SetActive(routing_id_, active));
}
void RenderWidgetHostImpl::LostMouseLock() {
@@ -1062,7 +1034,7 @@ void RenderWidgetHostImpl::LostMouseLock() {
}
void RenderWidgetHostImpl::SendMouseLockLost() {
- Send(new ViewMsg_MouseLockLost(routing_id_));
+ Send(new WidgetMsg_MouseLockLost(routing_id_));
}
void RenderWidgetHostImpl::ViewDestroyed() {
@@ -1188,7 +1160,8 @@ void RenderWidgetHostImpl::StopInputEventAckTimeout() {
void RenderWidgetHostImpl::DidNavigate(uint32_t next_source_id) {
current_content_source_id_ = next_source_id;
- did_receive_first_frame_after_navigation_ = false;
+ // Stop the flinging after navigating to a new page.
+ StopFling();
if (enable_surface_synchronization_) {
// Resize messages before navigation are not acked, so reset
@@ -1565,7 +1538,7 @@ void RenderWidgetHostImpl::SetCursor(const WebCursor& cursor) {
void RenderWidgetHostImpl::ShowContextMenuAtPoint(
const gfx::Point& point,
const ui::MenuSourceType source_type) {
- Send(new ViewMsg_ShowContextMenu(GetRoutingID(), source_type, point));
+ Send(new WidgetMsg_ShowContextMenu(GetRoutingID(), source_type, point));
}
void RenderWidgetHostImpl::SendCursorVisibilityState(bool is_visible) {
@@ -1634,6 +1607,9 @@ void RenderWidgetHostImpl::GetScreenInfo(ScreenInfo* result) {
else
DisplayUtil::GetDefaultScreenInfo(result);
+ if (display::Display::HasForceRasterColorProfile())
+ result->color_space = display::Display::GetForcedRasterColorProfile();
+
// TODO(sievers): find a way to make this done another way so the method
// can be const.
if (IsUseZoomForDSFEnabled())
@@ -1773,7 +1749,7 @@ void RenderWidgetHostImpl::GetSnapshotFromBrowser(
if (from_surface) {
pending_surface_browser_snapshots_.insert(
std::make_pair(snapshot_id, callback));
- Send(new ViewMsg_ForceRedraw(GetRoutingID(), snapshot_id));
+ Send(new WidgetMsg_ForceRedraw(GetRoutingID(), snapshot_id));
return;
}
@@ -1786,7 +1762,7 @@ void RenderWidgetHostImpl::GetSnapshotFromBrowser(
#endif
// TODO(nzolghadr): Remove the duplication here and the if block just above.
pending_browser_snapshots_.insert(std::make_pair(snapshot_id, callback));
- Send(new ViewMsg_ForceRedraw(GetRoutingID(), snapshot_id));
+ Send(new WidgetMsg_ForceRedraw(GetRoutingID(), snapshot_id));
}
void RenderWidgetHostImpl::SelectionChanged(const base::string16& text,
@@ -1797,7 +1773,7 @@ void RenderWidgetHostImpl::SelectionChanged(const base::string16& text,
}
void RenderWidgetHostImpl::OnSelectionBoundsChanged(
- const ViewHostMsg_SelectionBounds_Params& params) {
+ const WidgetHostMsg_SelectionBounds_Params& params) {
if (view_)
view_->SelectionBoundsChanged(params);
}
@@ -1961,7 +1937,7 @@ void RenderWidgetHostImpl::CancelUpdateTextDirection() {
void RenderWidgetHostImpl::NotifyTextDirection() {
if (text_direction_updated_) {
if (!text_direction_canceled_)
- Send(new ViewMsg_SetTextDirection(GetRoutingID(), text_direction_));
+ Send(new WidgetMsg_SetTextDirection(GetRoutingID(), text_direction_));
text_direction_updated_ = false;
text_direction_canceled_ = false;
}
@@ -2001,7 +1977,7 @@ void RenderWidgetHostImpl::RejectMouseLockOrUnlockIfNecessary() {
DCHECK(!pending_mouse_lock_request_ || !IsMouseLocked());
if (pending_mouse_lock_request_) {
pending_mouse_lock_request_ = false;
- Send(new ViewMsg_LockMouse_ACK(routing_id_, false));
+ Send(new WidgetMsg_LockMouse_ACK(routing_id_, false));
} else if (IsMouseLocked()) {
view_->UnlockMouse();
}
@@ -2190,10 +2166,12 @@ void RenderWidgetHostImpl::OnUpdateScreenRectsAck() {
}
void RenderWidgetHostImpl::OnRequestSetBounds(const gfx::Rect& bounds) {
- if (view_) {
+ if (owner_delegate_) {
+ owner_delegate_->RequestSetBounds(bounds);
+ } else if (view_) {
view_->SetBounds(bounds);
- Send(new ViewMsg_SetBounds_ACK(routing_id_));
}
+ Send(new WidgetMsg_SetBounds_ACK(routing_id_));
}
void RenderWidgetHostImpl::DidNotProduceFrame(const viz::BeginFrameAck& ack) {
@@ -2257,22 +2235,25 @@ void RenderWidgetHostImpl::OnSetCursor(const WebCursor& cursor) {
void RenderWidgetHostImpl::OnAutoscrollStart(const gfx::PointF& position) {
GetView()->OnAutoscrollStart();
- WebGestureEvent scroll_begin = SyntheticWebGestureEventBuilder::Build(
- WebInputEvent::kGestureScrollBegin,
- blink::kWebGestureDeviceSyntheticAutoscroll);
- scroll_begin.SetPositionInWidget(position);
-
- ForwardGestureEventWithLatencyInfo(
- scroll_begin, ui::LatencyInfo(ui::SourceEventType::OTHER));
-
- // Send a GFS event with zero velocity to make sure that the scroll sequence
- // will end with the GFC generated in |OnAutoscrollEnd()|; Otherwise if the
- // user cancels the autoscroll without moving the mouse, the GFC will get
- // filtered since no GFS is sent in the sequence. https://crbug.com/829794
- OnAutoscrollFling(gfx::Vector2dF());
+ sent_autoscroll_scroll_begin_ = false;
+ autoscroll_start_position_ = position;
}
void RenderWidgetHostImpl::OnAutoscrollFling(const gfx::Vector2dF& velocity) {
+ if (!sent_autoscroll_scroll_begin_ && velocity != gfx::Vector2dF()) {
+ // Send a GSB event with valid delta hints.
+ WebGestureEvent scroll_begin = SyntheticWebGestureEventBuilder::Build(
+ WebInputEvent::kGestureScrollBegin,
+ blink::kWebGestureDeviceSyntheticAutoscroll);
+ scroll_begin.SetPositionInWidget(autoscroll_start_position_);
+ scroll_begin.data.scroll_begin.delta_x_hint = velocity.x();
+ scroll_begin.data.scroll_begin.delta_y_hint = velocity.y();
+
+ ForwardGestureEventWithLatencyInfo(
+ scroll_begin, ui::LatencyInfo(ui::SourceEventType::OTHER));
+ sent_autoscroll_scroll_begin_ = true;
+ }
+
WebGestureEvent event = SyntheticWebGestureEventBuilder::Build(
WebInputEvent::kGestureFlingStart,
blink::kWebGestureDeviceSyntheticAutoscroll);
@@ -2284,6 +2265,11 @@ void RenderWidgetHostImpl::OnAutoscrollFling(const gfx::Vector2dF& velocity) {
}
void RenderWidgetHostImpl::OnAutoscrollEnd() {
+ // Don't send a GFC if no GSB is sent.
+ if (!sent_autoscroll_scroll_begin_)
+ return;
+
+ sent_autoscroll_scroll_begin_ = false;
WebGestureEvent cancel_event = SyntheticWebGestureEventBuilder::Build(
WebInputEvent::kGestureFlingCancel,
blink::kWebGestureDeviceSyntheticAutoscroll);
@@ -2356,7 +2342,7 @@ void RenderWidgetHostImpl::OnProcessSwapMessage(const IPC::Message& message) {
void RenderWidgetHostImpl::OnLockMouse(bool user_gesture,
bool privileged) {
if (pending_mouse_lock_request_) {
- Send(new ViewMsg_LockMouse_ACK(routing_id_, false));
+ Send(new WidgetMsg_LockMouse_ACK(routing_id_, false));
return;
}
@@ -2633,7 +2619,7 @@ bool RenderWidgetHostImpl::IsIgnoringInputEvents() const {
}
void RenderWidgetHostImpl::SetBackgroundOpaque(bool opaque) {
- Send(new ViewMsg_SetBackgroundOpaque(GetRoutingID(), opaque));
+ Send(new WidgetMsg_SetBackgroundOpaque(GetRoutingID(), opaque));
}
bool RenderWidgetHostImpl::GotResponseToLockMouseRequest(bool allowed) {
@@ -2650,11 +2636,11 @@ bool RenderWidgetHostImpl::GotResponseToLockMouseRequest(bool allowed) {
pending_mouse_lock_request_ = false;
if (!view_ || !view_->HasFocus()|| !view_->LockMouse()) {
- Send(new ViewMsg_LockMouse_ACK(routing_id_, false));
+ Send(new WidgetMsg_LockMouse_ACK(routing_id_, false));
return false;
}
- Send(new ViewMsg_LockMouse_ACK(routing_id_, true));
+ Send(new WidgetMsg_LockMouse_ACK(routing_id_, true));
return true;
}
@@ -2678,7 +2664,7 @@ void RenderWidgetHostImpl::DidReceiveRendererFrame() {
}
void RenderWidgetHostImpl::WindowSnapshotReachedScreen(int snapshot_id) {
- DCHECK(base::MessageLoopForUI::IsCurrent());
+ DCHECK(base::MessageLoopCurrentForUI::IsSet());
if (!pending_surface_browser_snapshots_.empty()) {
GetView()->CopyFromSurface(
@@ -2730,7 +2716,7 @@ void RenderWidgetHostImpl::OnSnapshotFromSurfaceReceived(
image = gfx::Image::CreateFrom1xBitmap(bitmap);
// Any pending snapshots with a lower ID than the one received are considered
// to be implicitly complete, and returned the same snapshot data.
- PendingSnapshotMap::iterator it = pending_surface_browser_snapshots_.begin();
+ auto it = pending_surface_browser_snapshots_.begin();
while (it != pending_surface_browser_snapshots_.end()) {
if (it->first <= snapshot_id) {
it->second.Run(image);
@@ -2745,7 +2731,7 @@ void RenderWidgetHostImpl::OnSnapshotReceived(int snapshot_id,
gfx::Image image) {
// Any pending snapshots with a lower ID than the one received are considered
// to be implicitly complete, and returned the same snapshot data.
- PendingSnapshotMap::iterator it = pending_browser_snapshots_.begin();
+ auto it = pending_browser_snapshots_.begin();
while (it != pending_browser_snapshots_.end()) {
if (it->first <= snapshot_id) {
it->second.Run(image);
@@ -2875,59 +2861,8 @@ void RenderWidgetHostImpl::SubmitCompositorFrame(
viz::CompositorFrame frame,
base::Optional<viz::HitTestRegionList> hit_test_region_list,
uint64_t submit_time) {
- // Ensure there are no CopyOutputRequests stowed-away in the CompositorFrame.
- // For security/privacy reasons, renderers are not allowed to make copy
- // requests because they could use this to gain access to content from another
- // domain (e.g., in a child frame).
- if (frame.HasCopyOutputRequests()) {
- bad_message::ReceivedBadMessage(GetProcess(),
- bad_message::RWH_COPY_REQUEST_ATTEMPT);
- return;
- }
-
- auto new_surface_properties =
- RenderWidgetSurfaceProperties::FromCompositorFrame(frame);
-
- if (local_surface_id == last_local_surface_id_ &&
- new_surface_properties != last_surface_properties_) {
- std::string error = base::StringPrintf(
- "[OOPIF? %d] %s\n", view_ && view_->IsRenderWidgetHostViewChildFrame(),
- new_surface_properties.ToDiffString(last_surface_properties_).c_str());
- LOG(ERROR) << "Surface invariants violation: " << error;
-
- static int invariants_violation_count = 0;
- ++invariants_violation_count;
- UMA_HISTOGRAM_COUNTS_1000("Compositing.SurfaceInvariantsViolations",
- invariants_violation_count);
-
- if (features::IsSurfaceInvariantsViolationLoggingEnabled()) {
- static auto* crash_key = base::debug::AllocateCrashKeyString(
- "surface-invariants-violation", base::debug::CrashKeySize::Size256);
- base::debug::ScopedCrashKeyString key_value(crash_key, error);
- base::debug::DumpWithoutCrashing();
- }
-
- if (view_) {
- frame.metadata.begin_frame_ack.has_damage = false;
- view_->OnDidNotProduceFrame(frame.metadata.begin_frame_ack);
- }
- std::vector<viz::ReturnedResource> resources =
- viz::TransferableResource::ReturnResources(frame.resource_list);
- renderer_compositor_frame_sink_->DidReceiveCompositorFrameAck(resources);
-
- return;
- }
-
- last_local_surface_id_ = local_surface_id;
- last_surface_properties_ = new_surface_properties;
-
last_received_content_source_id_ = frame.metadata.content_source_id;
- // |has_damage| is not transmitted.
- frame.metadata.begin_frame_ack.has_damage = true;
-
- last_frame_metadata_ = frame.metadata.Clone();
-
if (enable_surface_synchronization_) {
if (view_) {
// If Surface Synchronization is on, then |new_content_rendering_timeout_|
@@ -2964,12 +2899,10 @@ void RenderWidgetHostImpl::SubmitCompositorFrame(
// After navigation, if a frame belonging to the new page is received, stop
// the timer that triggers clearing the graphics of the last page.
- if (last_received_content_source_id_ >= current_content_source_id_) {
- did_receive_first_frame_after_navigation_ = true;
- if (new_content_rendering_timeout_ &&
- new_content_rendering_timeout_->IsRunning()) {
- new_content_rendering_timeout_->Stop();
- }
+ if (last_received_content_source_id_ >= current_content_source_id_ &&
+ new_content_rendering_timeout_ &&
+ new_content_rendering_timeout_->IsRunning()) {
+ new_content_rendering_timeout_->Stop();
}
}
}
@@ -3057,8 +2990,8 @@ void RenderWidgetHostImpl::ProgressFlingIfNeeded(TimeTicks current_time) {
}
void RenderWidgetHostImpl::ForceFirstFrameAfterNavigationTimeout() {
- if (did_receive_first_frame_after_navigation_ ||
- !new_content_rendering_timeout_) {
+ if (!new_content_rendering_timeout_ ||
+ !new_content_rendering_timeout_->IsRunning()) {
return;
}
new_content_rendering_timeout_->Stop();
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 c2d8cd56243..dba7b4276f5 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_impl.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_impl.h
@@ -49,7 +49,6 @@
#include "content/common/input/input_handler.mojom.h"
#include "content/common/render_frame_metadata.mojom.h"
#include "content/common/render_widget_surface_properties.h"
-#include "content/common/view_message_enums.h"
#include "content/common/widget.mojom.h"
#include "content/public/browser/render_widget_host.h"
#include "content/public/common/input_event_ack_state.h"
@@ -76,7 +75,7 @@
class SkBitmap;
struct FrameHostMsg_HittestData_Params;
-struct ViewHostMsg_SelectionBounds_Params;
+struct WidgetHostMsg_SelectionBounds_Params;
namespace blink {
class WebInputEvent;
@@ -188,6 +187,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl
void NotifyTextDirection() override;
void Focus() override;
void Blur() override;
+ void FlushForTesting() override;
void SetActive(bool active) override;
void ForwardMouseEvent(const blink::WebMouseEvent& mouse_event) override;
void ForwardWheelEvent(const blink::WebMouseWheelEvent& wheel_event) override;
@@ -611,10 +611,6 @@ class CONTENT_EXPORT RenderWidgetHostImpl
render_frame_metadata_observer_client_request,
mojom::RenderFrameMetadataObserverPtr render_frame_metadata_observer);
- const viz::CompositorFrameMetadata& last_frame_metadata() {
- return last_frame_metadata_;
- }
-
RenderFrameMetadataProviderImpl* render_frame_metadata_provider() {
return &render_frame_metadata_provider_;
}
@@ -762,7 +758,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl
private:
FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostTest,
DontPostponeInputEventAckTimeout);
- FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostTest, HiddenPaint);
+ FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostTest, HideShowMessages);
FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostTest, RendererExitedNoDrag);
FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostTest,
StopAndStartInputEventAckTimeout);
@@ -819,7 +815,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl
bool privileged);
void OnUnlockMouse();
void OnSelectionBoundsChanged(
- const ViewHostMsg_SelectionBounds_Params& params);
+ const WidgetHostMsg_SelectionBounds_Params& params);
void OnSetNeedsBeginFrames(bool needs_begin_frames);
void OnHittestData(const FrameHostMsg_HittestData_Params& params);
void OnFocusedNodeTouched(bool editable);
@@ -992,12 +988,6 @@ class CONTENT_EXPORT RenderWidgetHostImpl
// The observers watching us.
base::ObserverList<RenderWidgetHostObserver>::Unchecked 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
- // itself, a paint message could already be in flight at that point.
- bool needs_repainting_on_restore_;
-
// This is true if the renderer is currently unresponsive.
bool is_unresponsive_;
@@ -1125,12 +1115,6 @@ class CONTENT_EXPORT RenderWidgetHostImpl
device::mojom::WakeLockPtr wake_lock_;
#endif
- // These information are used to verify that the renderer does not misbehave
- // when it comes to allocating LocalSurfaceIds. If surface properties change,
- // a new LocalSurfaceId must be created.
- viz::LocalSurfaceId last_local_surface_id_;
- RenderWidgetSurfaceProperties last_surface_properties_;
-
mojo::Binding<viz::mojom::CompositorFrameSink> compositor_frame_sink_binding_;
viz::mojom::CompositorFrameSinkClientPtr renderer_compositor_frame_sink_;
@@ -1138,18 +1122,8 @@ class CONTENT_EXPORT RenderWidgetHostImpl
// we have a view. This is only used if |enable_viz_| is true.
base::OnceCallback<void(const viz::FrameSinkId&)> create_frame_sink_callback_;
- viz::CompositorFrameMetadata last_frame_metadata_;
-
std::unique_ptr<FrameTokenMessageQueue> frame_token_message_queue_;
- // If a CompositorFrame is submitted that references SharedBitmaps that don't
- // exist yet, we keep it here until they are available.
- struct {
- viz::LocalSurfaceId local_surface_id;
- viz::CompositorFrame frame;
- base::Optional<viz::HitTestRegionList> hit_test_region_list;
- } saved_frame_;
-
bool enable_surface_synchronization_ = false;
bool enable_viz_ = false;
@@ -1184,7 +1158,8 @@ class CONTENT_EXPORT RenderWidgetHostImpl
std::unique_ptr<FlingSchedulerBase> fling_scheduler_;
- bool did_receive_first_frame_after_navigation_ = true;
+ bool sent_autoscroll_scroll_begin_ = false;
+ gfx::PointF autoscroll_start_position_;
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 e3d18fefaf8..f19fe1edf21 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
@@ -4,6 +4,8 @@
#include "content/browser/renderer_host/render_widget_host_input_event_router.h"
+#include <algorithm>
+#include <deque>
#include <vector>
#include "base/debug/crash_logging.h"
@@ -32,11 +34,11 @@ namespace {
// Transforms WebTouchEvent touch positions from the root view coordinate
// space to the target view coordinate space.
void TransformEventTouchPositions(blink::WebTouchEvent* event,
- const gfx::Vector2dF& delta) {
+ const gfx::Transform& transform) {
for (unsigned i = 0; i < event->touches_length; ++i) {
- event->touches[i].SetPositionInWidget(
- event->touches[i].PositionInWidget().x + delta.x(),
- event->touches[i].PositionInWidget().y + delta.y());
+ gfx::PointF point(event->touches[i].PositionInWidget());
+ transform.TransformPoint(&point);
+ event->touches[i].SetPositionInWidget(point);
}
}
@@ -82,6 +84,142 @@ bool IsMouseButtonDown(const blink::WebMouseEvent& event) {
namespace content {
+// A class to implement a queue for tracking outbound TouchEvents, and making
+// sure that their acks are returned to the appropriate root view in order.
+// This is important to ensure proper operation of the GestureProvider.
+// Some challenges include:
+// * differentiating between native and emulated TouchEvents, as the latter ack
+// to the TouchEmulator's GestureProvider,
+// * making sure all events from destroyed renderers are acked properly, and
+// without delaying acks from other renderers, and
+// * making sure events are only acked if the root_view (at the time of the
+// out-bound event) is still valid.
+// Some of this logic, e.g. the last item above, is shared with
+// RenderWidgetHostViewBase.
+class TouchEventAckQueue {
+ public:
+ enum class TouchEventAckStatus { TouchEventNotAcked, TouchEventAcked };
+ enum class TouchEventSource { SystemTouchEvent, EmulatedTouchEvent };
+ struct AckData {
+ uint32_t touch_event_id;
+ RenderWidgetHostViewBase* target_view;
+ RenderWidgetHostViewBase* root_view;
+ TouchEventSource touch_event_source;
+ TouchEventAckStatus touch_event_ack_status;
+ InputEventAckState ack_result;
+ };
+
+ TouchEventAckQueue() {}
+
+ void Add(uint32_t touch_event_id,
+ RenderWidgetHostViewBase* target_view,
+ RenderWidgetHostViewBase* root_view,
+ TouchEventSource touch_event_source,
+ TouchEventAckStatus touch_event_ack_status,
+ InputEventAckState ack_result);
+
+ void Add(uint32_t touch_event_id,
+ RenderWidgetHostViewBase* target_view,
+ RenderWidgetHostViewBase* root_view,
+ TouchEventSource touch_event_source);
+
+ void MarkAcked(uint32_t touch_event_id,
+ InputEventAckState ack_result,
+ RenderWidgetHostViewBase* target_view);
+
+ void UpdateQueueAfterTargetDestroyed(RenderWidgetHostViewBase* target_view);
+
+ private:
+ void ProcessAckedTouchEvents();
+ void ReportTouchEventAckQueueUmaStats();
+
+ std::deque<AckData> ack_queue_;
+};
+
+void TouchEventAckQueue::Add(uint32_t touch_event_id,
+ RenderWidgetHostViewBase* target_view,
+ RenderWidgetHostViewBase* root_view,
+ TouchEventSource touch_event_source,
+ TouchEventAckStatus touch_event_ack_status,
+ InputEventAckState ack_result) {
+ AckData data = {
+ touch_event_id, target_view, root_view, touch_event_source,
+ touch_event_ack_status, ack_result};
+ ack_queue_.push_back(data);
+ if (touch_event_ack_status == TouchEventAckStatus::TouchEventAcked)
+ ProcessAckedTouchEvents();
+ ReportTouchEventAckQueueUmaStats();
+}
+
+void TouchEventAckQueue::Add(uint32_t touch_event_id,
+ RenderWidgetHostViewBase* target_view,
+ RenderWidgetHostViewBase* root_view,
+ TouchEventSource touch_event_source) {
+ Add(touch_event_id, target_view, root_view, touch_event_source,
+ TouchEventAckStatus::TouchEventNotAcked, INPUT_EVENT_ACK_STATE_UNKNOWN);
+}
+
+void TouchEventAckQueue::MarkAcked(uint32_t touch_event_id,
+ InputEventAckState ack_result,
+ RenderWidgetHostViewBase* target_view) {
+ auto it = find_if(ack_queue_.begin(), ack_queue_.end(),
+ [touch_event_id](AckData data) {
+ return data.touch_event_id == touch_event_id;
+ });
+ if (it == ack_queue_.end())
+ return;
+ DCHECK(it->touch_event_ack_status != TouchEventAckStatus::TouchEventAcked);
+ DCHECK(target_view && target_view == it->target_view);
+ it->touch_event_ack_status = TouchEventAckStatus::TouchEventAcked;
+ it->ack_result = ack_result;
+ ProcessAckedTouchEvents();
+}
+
+void TouchEventAckQueue::ProcessAckedTouchEvents() {
+ if (ack_queue_.empty())
+ return;
+
+ // TODO(wjmaclean): modify the following loop to actually forward the acks
+ // to the root_view. Must verify that the root_view at the time the event
+ // was registered still exists.
+ while (!ack_queue_.empty() && ack_queue_.front().touch_event_ack_status ==
+ TouchEventAckStatus::TouchEventAcked) {
+ // TODO(wjmaclean): We will eventually ack touch events to the root_view
+ // here. Each ack will require confirmation that the touch event's root
+ // view (at the time of event dispatch) is still valid, otherwise we just
+ // discard the ack.
+ ack_queue_.pop_front();
+ }
+}
+
+void TouchEventAckQueue::ReportTouchEventAckQueueUmaStats() {
+ size_t count = ack_queue_.size();
+ UMA_HISTOGRAM_COUNTS_10000("Event.FrameEventRouting.TouchEventAckQueueSize",
+ count);
+ // TODO(wjmaclean): is it worth also recording how many different renderers
+ // are waiting on touch event acks at the time of reporting?
+}
+
+void TouchEventAckQueue::UpdateQueueAfterTargetDestroyed(
+ RenderWidgetHostViewBase* target_view) {
+ // If a queue entry's root view is being destroyed, just delete it.
+ ack_queue_.erase(remove_if(ack_queue_.begin(), ack_queue_.end(),
+ [target_view](AckData data) {
+ return data.root_view == target_view;
+ }),
+ ack_queue_.end());
+
+ // Otherwise, mark its status accordingly.
+ for_each(ack_queue_.begin(), ack_queue_.end(), [target_view](AckData data) {
+ if (data.target_view == target_view) {
+ data.touch_event_ack_status = TouchEventAckStatus::TouchEventAcked;
+ data.ack_result = INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS;
+ }
+ });
+
+ ProcessAckedTouchEvents();
+}
+
void RenderWidgetHostInputEventRouter::OnRenderWidgetHostViewBaseDestroyed(
RenderWidgetHostViewBase* view) {
// RenderWidgetHostViewBase::RemoveObserver() should only ever be called
@@ -106,6 +244,7 @@ void RenderWidgetHostInputEventRouter::OnRenderWidgetHostViewBaseDestroyed(
touch_target_.target = nullptr;
active_touches_ = 0;
}
+ touch_event_ack_queue_->UpdateQueueAfterTargetDestroyed(view);
if (view == wheel_target_.target)
wheel_target_.target = nullptr;
@@ -202,6 +341,7 @@ RenderWidgetHostInputEventRouter::RenderWidgetHostInputEventRouter()
gesture_pinch_did_send_scroll_begin_(false),
event_targeter_(std::make_unique<RenderWidgetTargeter>(this)),
use_viz_hit_test_(features::IsVizHitTestingEnabled()),
+ touch_event_ack_queue_(new TouchEventAckQueue),
weak_ptr_factory_(this) {}
RenderWidgetHostInputEventRouter::~RenderWidgetHostInputEventRouter() {
@@ -216,6 +356,7 @@ RenderWidgetTargetResult RenderWidgetHostInputEventRouter::FindMouseEventTarget(
RenderWidgetHostViewBase* target = nullptr;
bool needs_transform_point = true;
bool latched_target = true;
+ bool should_verify_result = false;
if (root_view->IsMouseLocked()) {
target = root_view->host()->delegate()->GetMouseLockWidget()->GetView();
}
@@ -234,8 +375,14 @@ RenderWidgetTargetResult RenderWidgetHostInputEventRouter::FindMouseEventTarget(
auto result = FindViewAtLocation(
root_view, event.PositionInWidget(), event.PositionInScreen(),
viz::EventSource::MOUSE, &transformed_point);
+ // Due to performance concerns we do not verify mouse move events.
+ should_verify_result = (event.GetType() == blink::WebInputEvent::kMouseMove)
+ ? false
+ : result.should_verify_result;
if (result.should_query_view) {
- return {result.view, true, transformed_point, latched_target};
+ DCHECK(!should_verify_result);
+ return {result.view, true, transformed_point, latched_target,
+ should_verify_result};
}
target = result.view;
// |transformed_point| is already transformed.
@@ -246,10 +393,11 @@ RenderWidgetTargetResult RenderWidgetHostInputEventRouter::FindMouseEventTarget(
if (!root_view->TransformPointToCoordSpaceForView(
event.PositionInWidget(), target, &transformed_point,
viz::EventSource::MOUSE)) {
- return {nullptr, false, base::nullopt, latched_target};
+ return {nullptr, false, base::nullopt, latched_target, false};
}
}
- return {target, false, transformed_point, latched_target};
+ return {target, false, transformed_point, latched_target,
+ should_verify_result};
}
RenderWidgetTargetResult
@@ -263,25 +411,21 @@ RenderWidgetHostInputEventRouter::FindMouseWheelEventTarget(
if (!root_view->TransformPointToCoordSpaceForView(
event.PositionInWidget(), target, &transformed_point,
viz::EventSource::MOUSE)) {
- return {nullptr, false, base::nullopt, true};
+ return {nullptr, false, base::nullopt, true, false};
}
- return {target, false, transformed_point, true};
+ return {target, false, transformed_point, true, false};
}
- if (event.phase == blink::WebMouseWheelEvent::kPhaseBegan) {
- auto result = FindViewAtLocation(
- root_view, event.PositionInWidget(), event.PositionInScreen(),
- viz::EventSource::MOUSE, &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, true};
-
- auto result = FindViewAtLocation(root_view, event.PositionInWidget(),
- event.PositionInScreen(),
- viz::EventSource::MOUSE, &transformed_point);
- return {result.view, result.should_query_view, transformed_point, false};
+ if (event.phase == blink::WebMouseWheelEvent::kPhaseBegan) {
+ auto result = FindViewAtLocation(
+ root_view, event.PositionInWidget(), event.PositionInScreen(),
+ viz::EventSource::MOUSE, &transformed_point);
+ return {result.view, result.should_query_view, transformed_point, false,
+ result.should_verify_result};
+ }
+ // For non-begin events, the target found for the previous phaseBegan is
+ // used.
+ return {nullptr, false, base::nullopt, true, false};
}
RenderWidgetTargetResult RenderWidgetHostInputEventRouter::FindViewAtLocation(
@@ -294,16 +438,17 @@ RenderWidgetTargetResult RenderWidgetHostInputEventRouter::FindViewAtLocation(
// hit testing.
if (owner_map_.size() <= 1) {
*transformed_point = point;
- return {root_view, false, *transformed_point, false};
+ return {root_view, false, *transformed_point, false, false};
}
viz::FrameSinkId frame_sink_id;
bool query_renderer = false;
+ bool should_verify_result = false;
if (use_viz_hit_test_) {
viz::HitTestQuery* query = GetHitTestQuery(GetHostFrameSinkManager(),
root_view->GetRootFrameSinkId());
if (!query)
- return {root_view, false, base::nullopt, false};
+ return {root_view, false, base::nullopt, false, 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.
@@ -321,8 +466,18 @@ RenderWidgetTargetResult RenderWidgetHostInputEventRouter::FindViewAtLocation(
} else {
*transformed_point = point;
}
+ // To ensure the correctness of viz hit testing with cc generated data, we
+ // verify hit test results when:
+ // a) We use cc generated data to do synchronous hit testing and
+ // b) We use HitTestQuery to find the target (instead of reusing previous
+ // targets when hit testing latched events) and
+ // c) We are not hit testing MouseMove events which is too frequent to
+ // verify it without impacting performance.
+ // The code that implements c) locates in |FindMouseEventTarget|.
if (target.flags & viz::HitTestRegionFlags::kHitTestAsk)
query_renderer = true;
+ else if (features::IsVizHitTestingSurfaceLayerEnabled())
+ should_verify_result = true;
} else {
// The hittest delegate is used to reject hittesting quads based on extra
// hittesting data send by the renderer.
@@ -344,7 +499,8 @@ RenderWidgetTargetResult RenderWidgetHostInputEventRouter::FindViewAtLocation(
*transformed_point = point;
}
- return {view, query_renderer, *transformed_point, false};
+ return {view, query_renderer, *transformed_point, false,
+ should_verify_result};
}
void RenderWidgetHostInputEventRouter::RouteMouseEvent(
@@ -548,7 +704,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, true};
+ return {nullptr, false, base::nullopt, true, false};
active_touches_ += CountChangedTouchPoints(event);
gfx::PointF original_point = gfx::PointF(event.touches[0].PositionInWidget());
@@ -564,23 +720,27 @@ void RenderWidgetHostInputEventRouter::DispatchTouchEvent(
RenderWidgetHostViewBase* target,
const blink::WebTouchEvent& touch_event,
const ui::LatencyInfo& latency,
- const base::Optional<gfx::PointF>& target_location) {
+ const base::Optional<gfx::PointF>& target_location,
+ bool is_emulated_touchevent) {
DCHECK(blink::WebInputEvent::IsTouchEventType(touch_event.GetType()) &&
touch_event.GetType() != blink::WebInputEvent::kTouchScrollStarted);
bool is_sequence_start = !touch_target_.target && target;
if (is_sequence_start) {
touch_target_.target = target;
- // TODO(wjmaclean): Instead of just computing a delta, we should extract
- // the complete transform. We assume it doesn't change for the duration
- // of the touch sequence, though this could be wrong; a better approach
- // might be to always transform each point to the |touch_target_.target|
- // for the duration of the sequence.
- if (target_location.has_value()) {
- touch_target_.delta =
- target_location.value() - touch_event.touches[0].PositionInWidget();
- } else {
- touch_target_.delta = gfx::Vector2dF();
+ // For now we only compute the transform at TouchStart, but in a follow-on
+ // CL this will be computed for all events in order to account for css
+ // animations, pinches, etc.
+ if (!root_view->GetTransformToViewCoordSpace(touch_target_.target,
+ &touch_target_.transform)) {
+ // Fall-back to just using the delta if we are unable to get the full
+ // transform.
+ touch_target_.transform.MakeIdentity();
+ if (target_location.has_value()) {
+ touch_target_.transform.Translate(
+ target_location.value() -
+ touch_event.touches[0].PositionInWidget());
+ }
}
DCHECK(touchscreen_gesture_target_map_.find(
@@ -610,7 +770,15 @@ void RenderWidgetHostInputEventRouter::DispatchTouchEvent(
base::debug::DumpWithoutCrashing();
}
+ TouchEventAckQueue::TouchEventSource event_source =
+ is_emulated_touchevent
+ ? TouchEventAckQueue::TouchEventSource::EmulatedTouchEvent
+ : TouchEventAckQueue::TouchEventSource::SystemTouchEvent;
if (!touch_target_.target) {
+ touch_event_ack_queue_->Add(
+ touch_event.unique_touch_event_id, nullptr, root_view, event_source,
+ TouchEventAckQueue::TouchEventAckStatus::TouchEventAcked,
+ INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
TouchEventWithLatencyInfo touch_with_latency(touch_event, latency);
root_view->ProcessAckedTouchEvent(touch_with_latency,
INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
@@ -625,8 +793,11 @@ void RenderWidgetHostInputEventRouter::DispatchTouchEvent(
}
}
+ touch_event_ack_queue_->Add(touch_event.unique_touch_event_id,
+ touch_target_.target, root_view, event_source);
+
blink::WebTouchEvent event(touch_event);
- TransformEventTouchPositions(&event, touch_target_.delta);
+ TransformEventTouchPositions(&event, touch_target_.transform);
touch_target_.target->ProcessTouchEvent(event, latency);
if (!active_touches_)
@@ -637,6 +808,8 @@ void RenderWidgetHostInputEventRouter::ProcessAckedTouchEvent(
const TouchEventWithLatencyInfo& event,
InputEventAckState ack_result,
RenderWidgetHostViewBase* view) {
+ touch_event_ack_queue_->MarkAcked(event.event.unique_touch_event_id,
+ ack_result, view);
// TODO(wjmaclean): Eventually we will keep track of which outgoing touch
// events are emulated and which aren't, so the decision to hand off to the
// touch emulator won't just rely on the existence of the touch emulator.
@@ -1058,7 +1231,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, gesture_event.PositionInWidget(), true};
+ return {root_view, false, gesture_event.PositionInWidget(), true, false};
// Android sends gesture events that have no corresponding touch sequence, so
// these we hit-test explicitly.
@@ -1073,7 +1246,7 @@ RenderWidgetHostInputEventRouter::FindTouchscreenGestureEventTarget(
// Remaining gesture events will defer to the gesture event target queue
// during dispatch.
- return {nullptr, false, base::nullopt, true};
+ return {nullptr, false, base::nullopt, true, false};
}
bool RenderWidgetHostInputEventRouter::IsViewInMap(
@@ -1091,11 +1264,6 @@ void RenderWidgetHostInputEventRouter::DispatchTouchscreenGestureEvent(
const blink::WebGestureEvent& gesture_event,
const ui::LatencyInfo& latency,
const base::Optional<gfx::PointF>& target_location) {
- // Temporary logging for https://crbug.com/824774.
- static auto* target_source_key = base::debug::AllocateCrashKeyString(
- "touchscreen-gesture-target-source", base::debug::CrashKeySize::Size32);
- base::debug::SetCrashKeyString(target_source_key, "input");
-
if (gesture_event.GetType() == blink::WebInputEvent::kGesturePinchBegin) {
in_touchscreen_gesture_pinch_ = true;
// If the root view wasn't already receiving the gesture stream, then we
@@ -1179,14 +1347,20 @@ void RenderWidgetHostInputEventRouter::DispatchTouchscreenGestureEvent(
// are not associated with touch events, because non-synthetic events can be
// created by ContentView. These will use the target found by the
// RenderWidgetTargeter. These gesture events should always have a
- // unique_touch_event_id of 0.
+ // unique_touch_event_id of 0. They must have a non-null target in order
+ // to get the coordinate transform.
+ DCHECK(target);
touchscreen_gesture_target_.target = target;
touchscreen_gesture_target_in_map_ = IsViewInMap(target);
- base::debug::SetCrashKeyString(target_source_key, "touch_id=0");
- touchscreen_gesture_target_.delta =
- target_location.has_value()
- ? target_location.value() - gesture_event.PositionInWidget()
- : gfx::Vector2dF();
+ if (!root_view->GetTransformToViewCoordSpace(
+ touchscreen_gesture_target_.target,
+ &touchscreen_gesture_target_.transform)) {
+ touchscreen_gesture_target_.transform.MakeIdentity();
+ if (target_location.has_value()) {
+ touch_target_.transform.Translate(target_location.value() -
+ gesture_event.PositionInWidget());
+ }
+ }
} else if (no_matching_id && is_gesture_start) {
// A long-standing Windows issues where occasionally a GestureStart is
// encountered with no targets in the event queue. We never had a repro for
@@ -1209,8 +1383,13 @@ void RenderWidgetHostInputEventRouter::DispatchTouchscreenGestureEvent(
// 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;
+ if (!root_view->GetTransformToViewCoordSpace(
+ touchscreen_gesture_target_.target,
+ &touchscreen_gesture_target_.transform)) {
+ touchscreen_gesture_target_.transform.MakeIdentity();
+ if (target_location.has_value())
+ touch_target_.transform.Translate(transformed_point - original_point);
+ }
} else if (is_gesture_start) {
touchscreen_gesture_target_ = gesture_target_it->second;
touchscreen_gesture_target_map_.erase(gesture_target_it);
@@ -1239,28 +1418,9 @@ void RenderWidgetHostInputEventRouter::DispatchTouchscreenGestureEvent(
}
blink::WebGestureEvent event(gesture_event);
- event.SetPositionInWidget(event.PositionInWidget() +
- touchscreen_gesture_target_.delta);
- // Temporary logging for https://crbug.com/824774.
- static auto* target_ptr_key = base::debug::AllocateCrashKeyString(
- "touchscreen-gesture-target-ptr", base::debug::CrashKeySize::Size64);
- 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())));
+ gfx::PointF transformed_point(gesture_event.PositionInWidget());
+ touchscreen_gesture_target_.transform.TransformPoint(&transformed_point);
+ event.SetPositionInWidget(transformed_point);
if (events_being_flushed_) {
touchscreen_gesture_target_.target->host()
@@ -1287,7 +1447,7 @@ RenderWidgetHostInputEventRouter::FindTouchpadGestureEventTarget(
const blink::WebGestureEvent& event) const {
if (event.GetType() != blink::WebInputEvent::kGesturePinchBegin &&
event.GetType() != blink::WebInputEvent::kGestureFlingCancel) {
- return {nullptr, false, base::nullopt, true};
+ return {nullptr, false, base::nullopt, true, false};
}
gfx::PointF transformed_point;
@@ -1473,8 +1633,8 @@ void RenderWidgetHostInputEventRouter::DispatchEventToTarget(
INPUT_EVENT_ACK_STATE_CONSUMED);
return;
}
- DispatchTouchEvent(root_view, target, touch_event, latency,
- target_location);
+ DispatchTouchEvent(root_view, target, touch_event, latency, target_location,
+ false /* not emulated */);
return;
}
if (blink::WebInputEvent::IsGestureEventType(event.GetType())) {
@@ -1535,7 +1695,7 @@ void RenderWidgetHostInputEventRouter::ForwardEmulatedTouchEvent(
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);
+ ui::LatencyInfo(), transformed_point, true /* emulated */);
}
void RenderWidgetHostInputEventRouter::SetCursor(const WebCursor& cursor) {
@@ -1580,4 +1740,11 @@ void RenderWidgetHostInputEventRouter::SetMouseCaptureTarget(
mouse_capture_target_.target = nullptr;
}
+RenderWidgetHostImpl*
+RenderWidgetHostInputEventRouter::GetMouseCaptureWidgetForTests() const {
+ if (mouse_capture_target_.target)
+ return mouse_capture_target_.target->host();
+ return 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 f32c2cee069..7bcc75bd74e 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
@@ -15,7 +15,6 @@
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "build/build_config.h"
#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"
@@ -26,16 +25,10 @@
#include "content/common/content_export.h"
#include "content/public/common/input_event_ack_state.h"
#include "ui/gfx/geometry/vector2d_conversions.h"
+#include "ui/gfx/transform.h"
struct FrameHostMsg_HittestData_Params;
-#if defined(OS_WIN)
-// Flaky on Windows. https://crbug.com/868308
-#define MAYBE_TouchpadPinchOverOOPIF DISABLED_TouchpadPinchOverOOPIF
-#else
-#define MAYBE_TouchpadPinchOverOOPIF TouchpadPinchOverOOPIF
-#endif // OS_WIN
-
namespace blink {
class WebGestureEvent;
class WebInputEvent;
@@ -60,6 +53,7 @@ class RenderWidgetHostView;
class RenderWidgetHostViewBase;
class RenderWidgetTargeter;
class TouchEmulator;
+class TouchEventAckQueue;
// Class owned by WebContentsImpl for the purpose of directing input events
// to the correct RenderWidgetHost on pages with multiple RenderWidgetHosts.
@@ -133,6 +127,7 @@ class CONTENT_EXPORT RenderWidgetHostInputEventRouter
// Allows a target to claim or release capture of mouse events.
void SetMouseCaptureTarget(RenderWidgetHostViewBase* target,
bool captures_dragging);
+ RenderWidgetHostImpl* GetMouseCaptureWidgetForTests() const;
std::vector<RenderWidgetHostView*> GetRenderWidgetHostViewsForTests() const;
RenderWidgetTargeter* GetRenderWidgetTargeterForTests();
@@ -171,6 +166,7 @@ class CONTENT_EXPORT RenderWidgetHostInputEventRouter
struct TargetData {
RenderWidgetHostViewBase* target;
gfx::Vector2dF delta;
+ gfx::Transform transform;
TargetData() : target(nullptr) {}
};
@@ -253,7 +249,8 @@ class CONTENT_EXPORT RenderWidgetHostInputEventRouter
RenderWidgetHostViewBase* target,
const blink::WebTouchEvent& touch_event,
const ui::LatencyInfo& latency,
- const base::Optional<gfx::PointF>& target_location);
+ const base::Optional<gfx::PointF>& target_location,
+ bool is_emulated);
// Assumes |gesture_event| has coordinates in root view's coordinate space.
void DispatchTouchscreenGestureEvent(
RenderWidgetHostViewBase* root_view,
@@ -336,6 +333,7 @@ class CONTENT_EXPORT RenderWidgetHostInputEventRouter
bool events_being_flushed_ = false;
std::unique_ptr<TouchEmulator> touch_emulator_;
+ std::unique_ptr<TouchEventAckQueue> touch_event_ack_queue_;
base::WeakPtrFactory<RenderWidgetHostInputEventRouter> weak_ptr_factory_;
@@ -350,7 +348,7 @@ class CONTENT_EXPORT RenderWidgetHostInputEventRouter
FRIEND_TEST_ALL_PREFIXES(SitePerProcessHitTestBrowserTest,
InputEventRouterTouchpadGestureTargetTest);
FRIEND_TEST_ALL_PREFIXES(SitePerProcessHitTestBrowserTest,
- MAYBE_TouchpadPinchOverOOPIF);
+ TouchpadPinchOverOOPIF);
FRIEND_TEST_ALL_PREFIXES(SitePerProcessMouseWheelHitTestBrowserTest,
InputEventRouterWheelTargetTest);
FRIEND_TEST_ALL_PREFIXES(SitePerProcessMacBrowserTest,
diff --git a/chromium/content/browser/renderer_host/render_widget_host_ns_view_bridge_local.h b/chromium/content/browser/renderer_host/render_widget_host_ns_view_bridge_local.h
index a7678f05d79..3f625967d3d 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_ns_view_bridge_local.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_ns_view_bridge_local.h
@@ -11,21 +11,34 @@
#import "content/browser/renderer_host/popup_window_mac.h"
#import "content/browser/renderer_host/render_widget_host_view_cocoa.h"
#include "content/common/render_widget_host_ns_view.mojom.h"
+#include "content/public/common/widget_type.h"
+#include "mojo/public/cpp/bindings/associated_binding.h"
#include "ui/accelerated_widget_mac/display_ca_layer_tree.h"
#include "ui/display/display_observer.h"
namespace content {
// Bridge to a locally-hosted NSView -- this is always instantiated in the same
-// process as the NSView. The caller of this interface may exist in another
-// process.
+// process as the NSView. The owner of this class may exist in another
+// process. Because the owner may exist in another process, this class must
+// be destroyed explicitly by its Destroy method.
class RenderWidgetHostNSViewBridgeLocal
: public mojom::RenderWidgetHostNSViewBridge,
public display::DisplayObserver {
public:
+ // Create a bridge that will directly access its client in the same process
+ // via pointers. This object must be explicitly deleted.
RenderWidgetHostNSViewBridgeLocal(
mojom::RenderWidgetHostNSViewClient* client,
- RenderWidgetHostNSViewLocalClient* local_client);
+ RenderWidgetHostNSViewClientHelper* client_helper);
+
+ // Create a bridge that will access its client in another process via a mojo
+ // interface. This object will be deleted when |bridge_request|'s connection
+ // closes.
+ RenderWidgetHostNSViewBridgeLocal(
+ mojom::RenderWidgetHostNSViewClientAssociatedPtr client,
+ mojom::RenderWidgetHostNSViewBridgeAssociatedRequest bridge_request);
+
~RenderWidgetHostNSViewBridgeLocal() override;
// TODO(ccameron): RenderWidgetHostViewMac and other functions currently use
@@ -35,8 +48,8 @@ class RenderWidgetHostNSViewBridgeLocal
RenderWidgetHostViewCocoa* GetRenderWidgetHostViewCocoa();
// mojom::RenderWidgetHostNSViewBridge implementation.
- void InitAsPopup(const gfx::Rect& content_rect,
- blink::WebPopupType popup_type) override;
+ void InitAsPopup(const gfx::Rect& content_rect) override;
+ void SetParentWebContentsNSView(uint64_t parent_ns_view_id) override;
void DisableDisplay() override;
void MakeFirstResponder() override;
void SetBounds(const gfx::Rect& rect) override;
@@ -62,16 +75,25 @@ class RenderWidgetHostNSViewBridgeLocal
void UnlockKeyboard() override;
private:
- bool IsPopup() const {
- // TODO(ccameron): If this is not equivalent to |popup_window_| then
- // there are bugs.
- return popup_type_ != blink::kWebPopupTypeNone;
- }
+ void Initialize(mojom::RenderWidgetHostNSViewClient* client,
+ RenderWidgetHostNSViewClientHelper* client_helper);
+
+ bool IsPopup() const { return !!popup_window_; }
+
+ // Called on a mojo connection error, deletes |this|.
+ void OnConnectionError();
// display::DisplayObserver implementation.
void OnDisplayMetricsChanged(const display::Display& display,
uint32_t metrics) override;
+ // If the client for |this| is in another process and to be accessed via
+ // mojo, then |remote_client_| and |binding_| maintain this interface, and
+ // |remote_client_helper_| is a wrapper around |remote_client_|.
+ mojom::RenderWidgetHostNSViewClientAssociatedPtr remote_client_;
+ mojo::AssociatedBinding<mojom::RenderWidgetHostNSViewBridge> binding_;
+ std::unique_ptr<RenderWidgetHostNSViewClientHelper> remote_client_helper_;
+
// The NSView used for input and display.
base::scoped_nsobject<RenderWidgetHostViewCocoa> cocoa_view_;
@@ -81,7 +103,6 @@ class RenderWidgetHostNSViewBridgeLocal
// The window used for popup widgets, and its helper.
std::unique_ptr<PopupWindowMac> popup_window_;
- blink::WebPopupType popup_type_ = blink::kWebPopupTypeNone;
// The background CALayer which is hosted by |cocoa_view_|, and is used as
// the root of |display_ca_layer_tree_|.
diff --git a/chromium/content/browser/renderer_host/render_widget_host_ns_view_bridge_local.mm b/chromium/content/browser/renderer_host/render_widget_host_ns_view_bridge_local.mm
index 9df5543cc21..f2f17542f83 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_ns_view_bridge_local.mm
+++ b/chromium/content/browser/renderer_host/render_widget_host_ns_view_bridge_local.mm
@@ -6,9 +6,12 @@
#include "base/mac/scoped_cftyperef.h"
#include "base/strings/sys_string_conversions.h"
+#include "content/browser/renderer_host/render_widget_host_ns_view_client_helper.h"
#include "content/common/cursors/webcursor.h"
#import "skia/ext/skia_utils_mac.h"
+#include "ui/accelerated_widget_mac/window_resize_helper_mac.h"
#import "ui/base/cocoa/animation_utils.h"
+#include "ui/base/cocoa/ns_view_ids.h"
#include "ui/display/screen.h"
#include "ui/events/keycodes/dom/dom_code.h"
#include "ui/gfx/mac/coordinate_conversion.h"
@@ -17,12 +20,35 @@ namespace content {
RenderWidgetHostNSViewBridgeLocal::RenderWidgetHostNSViewBridgeLocal(
mojom::RenderWidgetHostNSViewClient* client,
- RenderWidgetHostNSViewLocalClient* local_client) {
+ RenderWidgetHostNSViewClientHelper* client_helper)
+ : binding_(nullptr) {
+ Initialize(client, client_helper);
+}
+
+RenderWidgetHostNSViewBridgeLocal::RenderWidgetHostNSViewBridgeLocal(
+ mojom::RenderWidgetHostNSViewClientAssociatedPtr client,
+ mojom::RenderWidgetHostNSViewBridgeAssociatedRequest bridge_request)
+ : remote_client_(std::move(client)), binding_(this) {
+ binding_.Bind(std::move(bridge_request),
+ ui::WindowResizeHelperMac::Get()->task_runner());
+ // This object will be destroyed when its connection is closed.
+ binding_.set_connection_error_handler(
+ base::BindOnce(&RenderWidgetHostNSViewBridgeLocal::OnConnectionError,
+ base::Unretained(this)));
+ remote_client_helper_ =
+ RenderWidgetHostNSViewClientHelper::CreateForMojoClient(
+ remote_client_.get());
+ Initialize(remote_client_.get(), remote_client_helper_.get());
+}
+
+void RenderWidgetHostNSViewBridgeLocal::Initialize(
+ mojom::RenderWidgetHostNSViewClient* client,
+ RenderWidgetHostNSViewClientHelper* client_helper) {
display::Screen::GetScreen()->AddObserver(this);
cocoa_view_.reset([[RenderWidgetHostViewCocoa alloc]
- initWithClient:client
- withLocalClient:local_client]);
+ initWithClient:client
+ withClientHelper:client_helper]);
background_layer_.reset([[CALayer alloc] init]);
display_ca_layer_tree_ =
@@ -45,17 +71,30 @@ RenderWidgetHostNSViewBridgeLocal::~RenderWidgetHostNSViewBridgeLocal() {
popup_window_.reset();
}
+void RenderWidgetHostNSViewBridgeLocal::OnConnectionError() {
+ delete this;
+}
+
RenderWidgetHostViewCocoa*
RenderWidgetHostNSViewBridgeLocal::GetRenderWidgetHostViewCocoa() {
return cocoa_view_;
}
void RenderWidgetHostNSViewBridgeLocal::InitAsPopup(
- const gfx::Rect& content_rect,
- blink::WebPopupType popup_type) {
- popup_type_ = popup_type;
- popup_window_ =
- std::make_unique<PopupWindowMac>(content_rect, popup_type_, cocoa_view_);
+ const gfx::Rect& content_rect) {
+ popup_window_ = std::make_unique<PopupWindowMac>(content_rect, cocoa_view_);
+}
+
+void RenderWidgetHostNSViewBridgeLocal::SetParentWebContentsNSView(
+ uint64_t parent_ns_view_id) {
+ NSView* parent_ns_view = ui::NSViewIds::GetNSView(parent_ns_view_id);
+ // If the browser passed an invalid handle, then there is no recovery.
+ CHECK(parent_ns_view);
+ // Set the frame and autoresizing mask of the RenderWidgetHostViewCocoa as is
+ // done by WebContentsViewMac.
+ [cocoa_view_ setFrame:[parent_ns_view bounds]];
+ [cocoa_view_ setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
+ [parent_ns_view addSubview:cocoa_view_];
}
void RenderWidgetHostNSViewBridgeLocal::MakeFirstResponder() {
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_helper.h
index 5efb19f2379..b8f764eab1d 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_helper.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_RENDER_WIDGET_HOST_NS_VIEW_CLIENT_H_
-#define CONTENT_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_NS_VIEW_CLIENT_H_
+#ifndef CONTENT_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_NS_VIEW_CLIENT_HELPER_H_
+#define CONTENT_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_NS_VIEW_CLIENT_HELPER_H_
#include "base/macros.h"
@@ -22,6 +22,10 @@ class LatencyInfo;
namespace content {
+namespace mojom {
+class RenderWidgetHostNSViewClient;
+} // namespace mojom
+
class BrowserAccessibilityManager;
struct EditCommand;
struct NativeWebKeyboardEvent;
@@ -32,10 +36,16 @@ struct NativeWebKeyboardEvent;
// instantiated in the local process. This is to implement functions that
// cannot be sent across mojo (e.g, GetRootBrowserAccessibilityManager), or
// to avoid unnecessary translation of event types.
-class RenderWidgetHostNSViewLocalClient {
+class RenderWidgetHostNSViewClientHelper {
public:
- RenderWidgetHostNSViewLocalClient() {}
- virtual ~RenderWidgetHostNSViewLocalClient() {}
+ // Create a RenderWidgetHostNSViewClientHelper that will only implement
+ // functionality through mojo (this is in contrast with an in-process
+ // RenderWidgetHostNSViewClientHelper that would use raw pointer access).
+ static std::unique_ptr<RenderWidgetHostNSViewClientHelper>
+ CreateForMojoClient(content::mojom::RenderWidgetHostNSViewClient* client);
+
+ RenderWidgetHostNSViewClientHelper() {}
+ virtual ~RenderWidgetHostNSViewClientHelper() {}
// Return the RenderWidget's BrowserAccessibilityManager.
// TODO(ccameron): This returns nullptr for non-local NSViews. A scheme for
@@ -73,9 +83,9 @@ class RenderWidgetHostNSViewLocalClient {
const blink::WebGestureEvent& smart_magnify_event) = 0;
private:
- DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostNSViewLocalClient);
+ DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostNSViewClientHelper);
};
} // namespace content
-#endif // CONTENT_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_NS_VIEW_CLIENT_H_
+#endif // CONTENT_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_NS_VIEW_CLIENT_HELPER_H_
diff --git a/chromium/content/browser/renderer_host/render_widget_host_ns_view_client_helper.mm b/chromium/content/browser/renderer_host/render_widget_host_ns_view_client_helper.mm
new file mode 100644
index 00000000000..40bac2663af
--- /dev/null
+++ b/chromium/content/browser/renderer_host/render_widget_host_ns_view_client_helper.mm
@@ -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 "render_widget_host_ns_view_client_helper.h"
+
+#include "content/browser/renderer_host/input/web_input_event_builders_mac.h"
+#include "content/common/render_widget_host_ns_view.mojom.h"
+#include "content/public/browser/native_web_keyboard_event.h"
+
+namespace content {
+
+namespace {
+
+class ForwardingClientHelper : public RenderWidgetHostNSViewClientHelper {
+ public:
+ explicit ForwardingClientHelper(mojom::RenderWidgetHostNSViewClient* client)
+ : client_(client) {}
+
+ private:
+ std::unique_ptr<InputEvent> TranslateEvent(
+ const blink::WebInputEvent& web_event) {
+ return std::make_unique<InputEvent>(web_event, ui::LatencyInfo());
+ }
+
+ // RenderWidgetHostNSViewClientHelper implementation.
+ BrowserAccessibilityManager* GetRootBrowserAccessibilityManager() override {
+ return nullptr;
+ }
+ void ForwardKeyboardEvent(const NativeWebKeyboardEvent& key_event,
+ const ui::LatencyInfo& latency_info) override {
+ const blink::WebKeyboardEvent* web_event =
+ static_cast<const blink::WebKeyboardEvent*>(&key_event);
+ std::unique_ptr<InputEvent> input_event =
+ std::make_unique<InputEvent>(*web_event, latency_info);
+ client_->ForwardKeyboardEvent(std::move(input_event),
+ key_event.skip_in_browser);
+ }
+ void ForwardKeyboardEventWithCommands(
+ const NativeWebKeyboardEvent& key_event,
+ const ui::LatencyInfo& latency_info,
+ const std::vector<EditCommand>& commands) override {
+ const blink::WebKeyboardEvent* web_event =
+ static_cast<const blink::WebKeyboardEvent*>(&key_event);
+ std::unique_ptr<InputEvent> input_event =
+ std::make_unique<InputEvent>(*web_event, latency_info);
+ client_->ForwardKeyboardEventWithCommands(
+ std::move(input_event), key_event.skip_in_browser, commands);
+ }
+ void RouteOrProcessMouseEvent(
+ const blink::WebMouseEvent& web_event) override {
+ client_->RouteOrProcessMouseEvent(TranslateEvent(web_event));
+ }
+ void RouteOrProcessTouchEvent(
+ const blink::WebTouchEvent& web_event) override {
+ client_->RouteOrProcessTouchEvent(TranslateEvent(web_event));
+ }
+ void RouteOrProcessWheelEvent(
+ const blink::WebMouseWheelEvent& web_event) override {
+ client_->RouteOrProcessWheelEvent(TranslateEvent(web_event));
+ }
+ void ForwardMouseEvent(const blink::WebMouseEvent& web_event) override {
+ client_->ForwardMouseEvent(TranslateEvent(web_event));
+ }
+ void ForwardWheelEvent(const blink::WebMouseWheelEvent& web_event) override {
+ client_->ForwardWheelEvent(TranslateEvent(web_event));
+ }
+ void GestureBegin(blink::WebGestureEvent begin_event,
+ bool is_synthetically_injected) override {
+ // The gesture type is not yet known, but assign a type to avoid
+ // serialization asserts (the type will be stripped on the other side).
+ begin_event.SetType(blink::WebInputEvent::kGestureScrollBegin);
+ client_->GestureBegin(TranslateEvent(begin_event),
+ is_synthetically_injected);
+ }
+ void GestureUpdate(blink::WebGestureEvent update_event) override {
+ client_->GestureUpdate(TranslateEvent(update_event));
+ }
+ void GestureEnd(blink::WebGestureEvent end_event) override {
+ client_->GestureEnd(TranslateEvent(end_event));
+ }
+ void SmartMagnify(const blink::WebGestureEvent& web_event) override {
+ client_->SmartMagnify(TranslateEvent(web_event));
+ }
+
+ mojom::RenderWidgetHostNSViewClient* client_ = nullptr;
+
+ DISALLOW_COPY_AND_ASSIGN(ForwardingClientHelper);
+};
+
+} // namespace
+
+// static
+std::unique_ptr<RenderWidgetHostNSViewClientHelper>
+RenderWidgetHostNSViewClientHelper::CreateForMojoClient(
+ content::mojom::RenderWidgetHostNSViewClient* client) {
+ return std::make_unique<ForwardingClientHelper>(client);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_widget_host_owner_delegate.h b/chromium/content/browser/renderer_host/render_widget_host_owner_delegate.h
index 24a08a3fdf6..0ba7bbc5422 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_owner_delegate.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_owner_delegate.h
@@ -57,8 +57,9 @@ class CONTENT_EXPORT RenderWidgetHostOwnerDelegate {
// priority to the RenderProcessHost.
virtual bool ShouldContributePriorityToProcess() = 0;
- // Called when the RenderWidgetHost has shutdown.
- virtual void RenderWidgetDidShutdown() = 0;
+ // Notify the OwnerDelegate that the renderer has requested a change in
+ // the bounds of the content area.
+ virtual void RequestSetBounds(const gfx::Rect& bounds) = 0;
protected:
virtual ~RenderWidgetHostOwnerDelegate() {}
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 138cac8c271..5c5bcdf6377 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_unittest.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_unittest.cc
@@ -40,6 +40,7 @@
#include "content/common/render_frame_metadata.mojom.h"
#include "content/common/view_messages.h"
#include "content/common/visual_properties.h"
+#include "content/common/widget_messages.h"
#include "content/public/browser/keyboard_event_processing_result.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
@@ -955,7 +956,7 @@ TEST_F(RenderWidgetHostTest, SynchronizeVisualProperties) {
EXPECT_FALSE(host_->SynchronizeVisualProperties());
EXPECT_FALSE(host_->visual_properties_ack_pending_);
EXPECT_FALSE(process_->sink().GetUniqueMessageMatching(
- ViewMsg_SynchronizeVisualProperties::ID));
+ WidgetMsg_SynchronizeVisualProperties::ID));
// The zoom has changed so host should send out a sync message
process_->sink().ClearMessages();
@@ -965,7 +966,7 @@ TEST_F(RenderWidgetHostTest, SynchronizeVisualProperties) {
EXPECT_FALSE(host_->visual_properties_ack_pending_);
EXPECT_NEAR(new_zoom_level, host_->old_visual_properties_->zoom_level, 0.01);
EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
- ViewMsg_SynchronizeVisualProperties::ID));
+ WidgetMsg_SynchronizeVisualProperties::ID));
// The initial bounds is the empty rect, so setting it to the same thing
// shouldn't send the resize message.
@@ -974,7 +975,7 @@ TEST_F(RenderWidgetHostTest, SynchronizeVisualProperties) {
host_->SynchronizeVisualProperties();
EXPECT_FALSE(host_->visual_properties_ack_pending_);
EXPECT_FALSE(process_->sink().GetUniqueMessageMatching(
- ViewMsg_SynchronizeVisualProperties::ID));
+ WidgetMsg_SynchronizeVisualProperties::ID));
// No visual properties ACK if the physical backing gets set, but the view
// bounds are zero.
@@ -992,7 +993,7 @@ TEST_F(RenderWidgetHostTest, 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));
+ WidgetMsg_SynchronizeVisualProperties::ID));
// Setting the bounds and physical backing size to nonzero should send out
// the notification and expect an ack.
@@ -1002,7 +1003,7 @@ TEST_F(RenderWidgetHostTest, 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));
+ WidgetMsg_SynchronizeVisualProperties::ID));
cc::RenderFrameMetadata metadata;
metadata.viewport_size_in_pixels = original_size.size();
metadata.local_surface_id = base::nullopt;
@@ -1024,7 +1025,7 @@ TEST_F(RenderWidgetHostTest, SynchronizeVisualProperties) {
EXPECT_FALSE(host_->SynchronizeVisualProperties());
EXPECT_TRUE(host_->visual_properties_ack_pending_);
EXPECT_FALSE(process_->sink().GetUniqueMessageMatching(
- ViewMsg_SynchronizeVisualProperties::ID));
+ WidgetMsg_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
@@ -1036,7 +1037,7 @@ TEST_F(RenderWidgetHostTest, SynchronizeVisualProperties) {
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));
+ WidgetMsg_SynchronizeVisualProperties::ID));
// Send the visual properties ACK for the latest size.
process_->sink().ClearMessages();
@@ -1046,7 +1047,7 @@ TEST_F(RenderWidgetHostTest, SynchronizeVisualProperties) {
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));
+ WidgetMsg_SynchronizeVisualProperties::ID));
// Now clearing the bounds should send out a notification but we shouldn't
// expect a visual properties ACK (since the renderer won't ack empty sizes).
@@ -1058,7 +1059,7 @@ TEST_F(RenderWidgetHostTest, 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));
+ WidgetMsg_SynchronizeVisualProperties::ID));
// Send a rect that has no area but has either width or height set.
process_->sink().ClearMessages();
@@ -1067,7 +1068,7 @@ TEST_F(RenderWidgetHostTest, 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));
+ WidgetMsg_SynchronizeVisualProperties::ID));
// Set the same size again. It should not be sent again.
process_->sink().ClearMessages();
@@ -1075,7 +1076,7 @@ TEST_F(RenderWidgetHostTest, 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));
+ WidgetMsg_SynchronizeVisualProperties::ID));
// A different size should be sent again, however.
view_->SetBounds(gfx::Rect(0, 0, 0, 31));
@@ -1083,7 +1084,7 @@ TEST_F(RenderWidgetHostTest, 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));
+ WidgetMsg_SynchronizeVisualProperties::ID));
// An invalid LocalSurfaceId should result in no change to the
// |visual_properties_ack_pending_| bit.
@@ -1094,7 +1095,7 @@ TEST_F(RenderWidgetHostTest, 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));
+ WidgetMsg_SynchronizeVisualProperties::ID));
}
// Test that a resize event is sent if SynchronizeVisualProperties() is called
@@ -1111,7 +1112,7 @@ TEST_F(RenderWidgetHostTest, ResizeScreenInfo) {
host_->SynchronizeVisualProperties();
EXPECT_FALSE(host_->visual_properties_ack_pending_);
EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
- ViewMsg_SynchronizeVisualProperties::ID));
+ WidgetMsg_SynchronizeVisualProperties::ID));
process_->sink().ClearMessages();
screen_info.orientation_angle = 180;
@@ -1121,7 +1122,7 @@ TEST_F(RenderWidgetHostTest, ResizeScreenInfo) {
host_->SynchronizeVisualProperties();
EXPECT_FALSE(host_->visual_properties_ack_pending_);
EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
- ViewMsg_SynchronizeVisualProperties::ID));
+ WidgetMsg_SynchronizeVisualProperties::ID));
process_->sink().ClearMessages();
screen_info.device_scale_factor = 2.f;
@@ -1130,7 +1131,7 @@ TEST_F(RenderWidgetHostTest, ResizeScreenInfo) {
host_->SynchronizeVisualProperties();
EXPECT_FALSE(host_->visual_properties_ack_pending_);
EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
- ViewMsg_SynchronizeVisualProperties::ID));
+ WidgetMsg_SynchronizeVisualProperties::ID));
process_->sink().ClearMessages();
// No screen change.
@@ -1138,7 +1139,7 @@ TEST_F(RenderWidgetHostTest, ResizeScreenInfo) {
host_->SynchronizeVisualProperties();
EXPECT_FALSE(host_->visual_properties_ack_pending_);
EXPECT_FALSE(process_->sink().GetUniqueMessageMatching(
- ViewMsg_SynchronizeVisualProperties::ID));
+ WidgetMsg_SynchronizeVisualProperties::ID));
}
// Test for crbug.com/25097. If a renderer crashes between a resize and the
@@ -1155,7 +1156,7 @@ TEST_F(RenderWidgetHostTest, ResizeThenCrash) {
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));
+ WidgetMsg_SynchronizeVisualProperties::ID));
// Simulate a renderer crash before the update message. Ensure all the
// visual properties ACK logic is cleared. Must clear the view first so it
@@ -1192,10 +1193,10 @@ TEST_F(RenderWidgetHostTest, Background) {
const IPC::Message* set_background =
process_->sink().GetUniqueMessageMatching(
- ViewMsg_SetBackgroundOpaque::ID);
+ WidgetMsg_SetBackgroundOpaque::ID);
ASSERT_TRUE(set_background);
std::tuple<bool> sent_background;
- ViewMsg_SetBackgroundOpaque::Read(set_background, &sent_background);
+ WidgetMsg_SetBackgroundOpaque::Read(set_background, &sent_background);
EXPECT_FALSE(std::get<0>(sent_background));
host_->SetView(nullptr);
@@ -1203,14 +1204,15 @@ TEST_F(RenderWidgetHostTest, Background) {
}
#endif
-// Test that we don't paint when we're hidden, but we still send the ACK. Most
-// of the rest of the painting is tested in the GetBackingStore* ones.
-TEST_F(RenderWidgetHostTest, HiddenPaint) {
+// Test that the RenderWidgetHost tells the renderer when it is hidden and
+// shown, and can accept a racey update from the renderer after hiding.
+TEST_F(RenderWidgetHostTest, HideShowMessages) {
// Hide the widget, it should have sent out a message to the renderer.
EXPECT_FALSE(host_->is_hidden_);
host_->WasHidden();
EXPECT_TRUE(host_->is_hidden_);
- EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_WasHidden::ID));
+ EXPECT_TRUE(
+ process_->sink().GetUniqueMessageMatching(WidgetMsg_WasHidden::ID));
// Send it an update as from the renderer.
process_->sink().ClearMessages();
@@ -1224,13 +1226,9 @@ TEST_F(RenderWidgetHostTest, HiddenPaint) {
host_->WasShown(false /* record_presentation_time */);
EXPECT_FALSE(host_->is_hidden_);
- // It should have sent out a restored message with a request to paint.
- const IPC::Message* restored = process_->sink().GetUniqueMessageMatching(
- ViewMsg_WasShown::ID);
- ASSERT_TRUE(restored);
- std::tuple<bool, base::TimeTicks> needs_repaint;
- ViewMsg_WasShown::Read(restored, &needs_repaint);
- EXPECT_TRUE(std::get<0>(needs_repaint));
+ // It should have sent out a restored message.
+ EXPECT_TRUE(
+ process_->sink().GetUniqueMessageMatching(WidgetMsg_WasShown::ID));
}
TEST_F(RenderWidgetHostTest, IgnoreKeyEventsHandledByRenderer) {
@@ -1563,7 +1561,16 @@ TEST_F(RenderWidgetHostTest, MultipleInputEvents) {
// Test that the rendering timeout for newly loaded content fires when enough
// time passes without receiving a new compositor frame. This test assumes
// Surface Synchronization is off.
-TEST_F(RenderWidgetHostTest, NewContentRenderingTimeoutWithoutSurfaceSync) {
+// Disabled due to flakiness on Android. See https://crbug.com/892700.
+#if defined(OS_ANDROID)
+#define MAYBE_NewContentRenderingTimeoutWithoutSurfaceSync \
+ DISABLED_NewContentRenderingTimeoutWithoutSurfaceSync
+#else
+#define MAYBE_NewContentRenderingTimeoutWithoutSurfaceSync \
+ NewContentRenderingTimeoutWithoutSurfaceSync
+#endif
+TEST_F(RenderWidgetHostTest,
+ NewContentRenderingTimeoutWithoutSurfaceSync_MAYBE) {
// If Surface Synchronization is on, we have a separate code path for
// cancelling new content rendering timeout that is tested separately.
if (features::IsSurfaceSynchronizationEnabled())
@@ -2000,7 +2007,7 @@ TEST_F(RenderWidgetHostInitialSizeTest, InitialSize) {
// size has actually changed).
EXPECT_FALSE(host_->SynchronizeVisualProperties());
EXPECT_FALSE(process_->sink().GetUniqueMessageMatching(
- ViewMsg_SynchronizeVisualProperties::ID));
+ WidgetMsg_SynchronizeVisualProperties::ID));
EXPECT_EQ(initial_size_, host_->old_visual_properties_->new_size);
EXPECT_TRUE(host_->visual_properties_ack_pending_);
}
@@ -2011,7 +2018,7 @@ TEST_F(RenderWidgetHostTest, HideUnthrottlesResize) {
process_->sink().ClearMessages();
EXPECT_TRUE(host_->SynchronizeVisualProperties());
EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
- ViewMsg_SynchronizeVisualProperties::ID));
+ WidgetMsg_SynchronizeVisualProperties::ID));
EXPECT_EQ(original_size, host_->old_visual_properties_->new_size);
EXPECT_TRUE(host_->visual_properties_ack_pending_);
@@ -2052,7 +2059,7 @@ TEST_F(RenderWidgetHostTest, FrameToken_MessageThenFrame) {
EXPECT_EQ(0u, host_->processed_frame_messages_count());
host_->OnMessageReceived(
- ViewHostMsg_FrameSwapMessages(0, frame_token, messages));
+ WidgetHostMsg_FrameSwapMessages(0, frame_token, messages));
EXPECT_EQ(1u, host_->frame_token_message_queue_->size());
EXPECT_EQ(0u, host_->processed_frame_messages_count());
@@ -2090,7 +2097,7 @@ TEST_F(RenderWidgetHostTest, FrameToken_FrameThenMessage) {
EXPECT_EQ(0u, host_->processed_frame_messages_count());
host_->OnMessageReceived(
- ViewHostMsg_FrameSwapMessages(0, frame_token, messages));
+ WidgetHostMsg_FrameSwapMessages(0, frame_token, messages));
EXPECT_EQ(0u, host_->frame_token_message_queue_->size());
EXPECT_EQ(1u, host_->processed_frame_messages_count());
}
@@ -2111,12 +2118,12 @@ TEST_F(RenderWidgetHostTest, FrameToken_MultipleMessagesThenTokens) {
EXPECT_EQ(0u, host_->processed_frame_messages_count());
host_->OnMessageReceived(
- ViewHostMsg_FrameSwapMessages(0, frame_token1, messages1));
+ WidgetHostMsg_FrameSwapMessages(0, frame_token1, messages1));
EXPECT_EQ(1u, host_->frame_token_message_queue_->size());
EXPECT_EQ(0u, host_->processed_frame_messages_count());
host_->OnMessageReceived(
- ViewHostMsg_FrameSwapMessages(0, frame_token2, messages2));
+ WidgetHostMsg_FrameSwapMessages(0, frame_token2, messages2));
EXPECT_EQ(2u, host_->frame_token_message_queue_->size());
EXPECT_EQ(0u, host_->processed_frame_messages_count());
@@ -2177,12 +2184,12 @@ TEST_F(RenderWidgetHostTest, FrameToken_MultipleTokensThenMessages) {
EXPECT_EQ(0u, host_->processed_frame_messages_count());
host_->OnMessageReceived(
- ViewHostMsg_FrameSwapMessages(0, frame_token1, messages1));
+ WidgetHostMsg_FrameSwapMessages(0, frame_token1, messages1));
EXPECT_EQ(0u, host_->frame_token_message_queue_->size());
EXPECT_EQ(1u, host_->processed_frame_messages_count());
host_->OnMessageReceived(
- ViewHostMsg_FrameSwapMessages(0, frame_token2, messages2));
+ WidgetHostMsg_FrameSwapMessages(0, frame_token2, messages2));
EXPECT_EQ(0u, host_->frame_token_message_queue_->size());
EXPECT_EQ(2u, host_->processed_frame_messages_count());
}
@@ -2203,12 +2210,12 @@ TEST_F(RenderWidgetHostTest, FrameToken_DroppedFrame) {
EXPECT_EQ(0u, host_->processed_frame_messages_count());
host_->OnMessageReceived(
- ViewHostMsg_FrameSwapMessages(0, frame_token1, messages1));
+ WidgetHostMsg_FrameSwapMessages(0, frame_token1, messages1));
EXPECT_EQ(1u, host_->frame_token_message_queue_->size());
EXPECT_EQ(0u, host_->processed_frame_messages_count());
host_->OnMessageReceived(
- ViewHostMsg_FrameSwapMessages(0, frame_token2, messages2));
+ WidgetHostMsg_FrameSwapMessages(0, frame_token2, messages2));
EXPECT_EQ(2u, host_->frame_token_message_queue_->size());
EXPECT_EQ(0u, host_->processed_frame_messages_count());
@@ -2249,7 +2256,7 @@ TEST_F(RenderWidgetHostTest, FrameToken_RendererCrash) {
host_->SetView(nullptr);
host_->OnMessageReceived(
- ViewHostMsg_FrameSwapMessages(0, frame_token1, messages1));
+ WidgetHostMsg_FrameSwapMessages(0, frame_token1, messages1));
EXPECT_EQ(1u, host_->frame_token_message_queue_->size());
EXPECT_EQ(0u, host_->processed_frame_messages_count());
@@ -2275,7 +2282,7 @@ TEST_F(RenderWidgetHostTest, FrameToken_RendererCrash) {
host_->Init();
host_->OnMessageReceived(
- ViewHostMsg_FrameSwapMessages(0, frame_token3, messages3));
+ WidgetHostMsg_FrameSwapMessages(0, frame_token3, messages3));
EXPECT_EQ(1u, host_->frame_token_message_queue_->size());
EXPECT_EQ(0u, 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 c0460f053f2..5cb90605f13 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
@@ -62,8 +62,6 @@
#include "content/browser/renderer_host/render_widget_host_input_event_router.h"
#include "content/browser/renderer_host/ui_events_helper.h"
#include "content/common/content_switches_internal.h"
-#include "content/common/input_messages.h"
-#include "content/common/view_messages.h"
#include "content/public/browser/android/compositor.h"
#include "content/public/browser/android/synchronous_compositor_client.h"
#include "content/public/browser/browser_thread.h"
@@ -73,8 +71,6 @@
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/use_zoom_for_dsf_policy.h"
-#include "ipc/ipc_message_macros.h"
-#include "ipc/ipc_message_start.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkColor.h"
@@ -249,17 +245,6 @@ void RenderWidgetHostViewAndroid::RemoveDestructionObserver(
destruction_observers_.RemoveObserver(observer);
}
-bool RenderWidgetHostViewAndroid::OnMessageReceived(
- const IPC::Message& message) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(RenderWidgetHostViewAndroid, message)
- IPC_MESSAGE_HANDLER(ViewHostMsg_SelectWordAroundCaretAck,
- OnSelectWordAroundCaretAck)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
-}
-
void RenderWidgetHostViewAndroid::InitAsChild(gfx::NativeView parent_view) {
NOTIMPLEMENTED();
}
@@ -473,9 +458,9 @@ bool RenderWidgetHostViewAndroid::IsShowing() {
return is_showing_ && view_.parent();
}
-void RenderWidgetHostViewAndroid::OnSelectWordAroundCaretAck(bool did_select,
- int start_adjust,
- int end_adjust) {
+void RenderWidgetHostViewAndroid::SelectWordAroundCaretAck(bool did_select,
+ int start_adjust,
+ int end_adjust) {
if (!selection_popup_controller_)
return;
selection_popup_controller_->OnSelectWordAroundCaretAck(
@@ -514,9 +499,9 @@ gfx::Size RenderWidgetHostViewAndroid::GetCompositorViewportPixelSize() const {
return view_.GetPhysicalBackingSize();
}
-bool RenderWidgetHostViewAndroid::DoBrowserControlsShrinkBlinkSize() const {
+bool RenderWidgetHostViewAndroid::DoBrowserControlsShrinkRendererSize() const {
auto* delegate_view = GetRenderViewHostDelegateView();
- return delegate_view ? delegate_view->DoBrowserControlsShrinkBlinkSize()
+ return delegate_view ? delegate_view->DoBrowserControlsShrinkRendererSize()
: false;
}
@@ -678,18 +663,18 @@ bool RenderWidgetHostViewAndroid::TransformPointToCoordSpaceForView(
RenderWidgetHostViewBase* target_view,
gfx::PointF* transformed_point,
viz::EventSource source) {
- if (target_view == this || !delegated_frame_host_) {
+ if (target_view == this) {
*transformed_point = point;
return true;
}
- // In TransformPointToLocalCoordSpace() there is a Point-to-Pixel conversion,
- // but it is not necessary here because the final target view is responsible
- // for converting before computing the final transform.
- viz::SurfaceId surface_id = delegated_frame_host_->SurfaceId();
+ viz::SurfaceId surface_id = GetCurrentSurfaceId();
if (!surface_id.is_valid())
return false;
+ // In TransformPointToLocalCoordSpace() there is a Point-to-Pixel conversion,
+ // but it is not necessary here because the final target view is responsible
+ // for converting before computing the final transform.
return target_view->TransformPointToLocalCoordSpace(
point, surface_id, transformed_point, source);
}
@@ -889,8 +874,7 @@ void RenderWidgetHostViewAndroid::CopyFromSurface(
const gfx::Size& output_size,
base::OnceCallback<void(const SkBitmap&)> callback) {
TRACE_EVENT0("cc", "RenderWidgetHostViewAndroid::CopyFromSurface");
- if (!features::IsSurfaceSynchronizationEnabled() &&
- !IsSurfaceAvailableForCopy()) {
+ if (!IsSurfaceAvailableForCopy()) {
std::move(callback).Run(SkBitmap());
return;
}
@@ -1315,8 +1299,6 @@ void RenderWidgetHostViewAndroid::UpdateTouchSelectionController(
DCHECK(touch_selection_controller_client_manager_);
touch_selection_controller_client_manager_->UpdateClientSelectionBounds(
selection.start, selection.end, this, nullptr);
- touch_selection_controller_client_manager_->SetPageScaleFactor(
- page_scale_factor);
// Set parameters for adaptive handle orientation.
gfx::SizeF viewport_size(scrollable_viewport_size_dip);
@@ -1566,7 +1548,7 @@ void RenderWidgetHostViewAndroid::RequestDisallowInterceptTouchEvent() {
void RenderWidgetHostViewAndroid::TransformPointToRootSurface(
gfx::PointF* point) {
*point += gfx::Vector2d(
- 0, DoBrowserControlsShrinkBlinkSize() ? GetTopControlsHeight() : 0);
+ 0, DoBrowserControlsShrinkRendererSize() ? GetTopControlsHeight() : 0);
}
// TODO(jrg): Find out the implications and answer correctly here,
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 6d3920e20e8..85cb772fd1e 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
@@ -95,7 +95,6 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
}
// RenderWidgetHostView implementation.
- bool OnMessageReceived(const IPC::Message& msg) override;
void InitAsChild(gfx::NativeView parent_view) override;
void InitAsPopup(RenderWidgetHostView* parent_host_view,
const gfx::Rect& pos) override;
@@ -119,7 +118,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
base::OnceCallback<void(const SkBitmap&)> callback) override;
void EnsureSurfaceSynchronizedForLayoutTest() override;
uint32_t GetCaptureSequenceNumber() const override;
- bool DoBrowserControlsShrinkBlinkSize() const override;
+ bool DoBrowserControlsShrinkRendererSize() const override;
float GetTopControlsHeight() const override;
float GetBottomControlsHeight() const override;
int GetMouseWheelMinimumGranularity() const override;
@@ -290,9 +289,9 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
void ShowContextMenuAtPoint(const gfx::Point& point, ui::MenuSourceType);
void DismissTextHandles();
void SetTextHandlesTemporarilyHidden(bool hide_handles);
- void OnSelectWordAroundCaretAck(bool did_select,
- int start_adjust,
- int end_adjust);
+ void SelectWordAroundCaretAck(bool did_select,
+ int start_adjust,
+ int end_adjust);
void SynchronousFrameMetadata(viz::CompositorFrameMetadata frame_metadata);
@@ -392,8 +391,6 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
bool Animate(base::TimeTicks frame_time);
void RequestDisallowInterceptTouchEvent();
- bool SyncCompositorOnMessageReceived(const IPC::Message& message);
-
void ComputeEventLatencyOSTouchHistograms(const ui::MotionEvent& event);
void CreateOverscrollControllerIfPossible();
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 b01698c8111..7d4ada0eb03 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
@@ -22,9 +22,11 @@
#include "components/viz/common/features.h"
#include "components/viz/common/frame_sinks/copy_output_request.h"
#include "components/viz/common/frame_sinks/copy_output_result.h"
+#include "components/viz/host/host_frame_sink_manager.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
#include "content/browser/accessibility/browser_accessibility_state_impl.h"
#include "content/browser/bad_message.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_impl.h"
@@ -127,6 +129,10 @@
#include "ui/wm/core/ime_util_chromeos.h"
#endif
+#if defined(OS_FUCHSIA)
+#include "ui/base/ime/input_method_keyboard_controller.h"
+#endif
+
using gfx::RectToSkIRect;
using gfx::SkIRectToRect;
@@ -364,7 +370,7 @@ RenderWidgetHostViewAura::RenderWidgetHostViewAura(
is_guest_view_hack_(is_guest_view_hack),
device_scale_factor_(0.0f),
event_handler_(new RenderWidgetHostViewEventHandler(host(), this, this)),
- frame_sink_id_(features::IsUsingWindowService()
+ frame_sink_id_(features::IsMultiProcessMash()
? viz::FrameSinkId()
: is_guest_view_hack_
? AllocateFrameSinkIdForGuestViewHack()
@@ -403,6 +409,7 @@ RenderWidgetHostViewAura::RenderWidgetHostViewAura(
// RenderWidgetHostViewAura, RenderWidgetHostView implementation:
void RenderWidgetHostViewAura::InitAsChild(gfx::NativeView parent_view) {
+ DCHECK_EQ(widget_type_, WidgetType::kFrame);
if (is_mus_browser_plugin_guest_)
return;
CreateAuraWindow(aura::client::WINDOW_TYPE_CONTROL);
@@ -416,6 +423,7 @@ void RenderWidgetHostViewAura::InitAsChild(gfx::NativeView parent_view) {
void RenderWidgetHostViewAura::InitAsPopup(
RenderWidgetHostView* parent_host_view,
const gfx::Rect& bounds_in_screen) {
+ DCHECK_EQ(widget_type_, WidgetType::kPopup);
// Popups never have |is_mus_browser_plugin_guest_| set to true.
DCHECK(!is_mus_browser_plugin_guest_);
@@ -465,6 +473,7 @@ void RenderWidgetHostViewAura::InitAsPopup(
void RenderWidgetHostViewAura::InitAsFullscreen(
RenderWidgetHostView* reference_host_view) {
+ DCHECK_EQ(widget_type_, WidgetType::kFrame);
// Webview Fullscreen doesn't go through InitAsFullscreen(), so
// |is_mus_browser_plugin_guest_| is always false.
DCHECK(!is_mus_browser_plugin_guest_);
@@ -561,7 +570,7 @@ gfx::NativeViewAccessible RenderWidgetHostViewAura::GetNativeViewAccessible() {
return manager->GetRoot()->GetNativeViewAccessible();
#endif
- NOTIMPLEMENTED();
+ NOTIMPLEMENTED_LOG_ONCE();
return static_cast<gfx::NativeViewAccessible>(nullptr);
}
@@ -751,7 +760,7 @@ void RenderWidgetHostViewAura::SetInsets(const gfx::Insets& insets) {
void RenderWidgetHostViewAura::FocusedNodeTouched(bool editable) {
#if defined(OS_WIN)
auto* input_method = GetInputMethod();
- if (!input_method)
+ if (!input_method || !input_method->GetInputMethodKeyboardController())
return;
auto* controller = input_method->GetInputMethodKeyboardController();
if (editable && host()->GetView() && host()->delegate()) {
@@ -831,12 +840,30 @@ uint32_t RenderWidgetHostViewAura::GetCaptureSequenceNumber() const {
return latest_capture_sequence_number_;
}
+bool RenderWidgetHostViewAura::DoBrowserControlsShrinkRendererSize() const {
+ return host()->delegate() &&
+ host()->delegate()->DoBrowserControlsShrinkRendererSize();
+}
+
+float RenderWidgetHostViewAura::GetTopControlsHeight() const {
+ return host()->delegate() ? host()->delegate()->GetTopControlsHeight() : 0;
+}
+
void RenderWidgetHostViewAura::CopyFromSurface(
const gfx::Rect& src_subrect,
const gfx::Size& dst_size,
base::OnceCallback<void(const SkBitmap&)> callback) {
- delegated_frame_host_->CopyFromCompositingSurface(src_subrect, dst_size,
- std::move(callback));
+ base::WeakPtr<RenderWidgetHostImpl> popup_host;
+ base::WeakPtr<DelegatedFrameHost> popup_frame_host;
+ if (popup_child_host_view_) {
+ popup_host = popup_child_host_view_->host()->GetWeakPtr();
+ popup_frame_host =
+ popup_child_host_view_->GetDelegatedFrameHost()->GetWeakPtr();
+ }
+ RenderWidgetHostViewBase::CopyMainAndPopupFromSurface(
+ host()->GetWeakPtr(), delegated_frame_host_->GetWeakPtr(), popup_host,
+ popup_frame_host, src_subrect, dst_size, device_scale_factor_,
+ std::move(callback));
}
#if defined(OS_WIN)
@@ -904,8 +931,23 @@ void RenderWidgetHostViewAura::DidStopFlinging() {
}
void RenderWidgetHostViewAura::TransformPointToRootSurface(gfx::PointF* point) {
- aura::Window::ConvertPointToTarget(window_, window_->GetRootWindow(), point);
- window_->GetRootWindow()->transform().TransformPoint(point);
+ aura::Window* root = window_->GetRootWindow();
+ aura::Window::ConvertPointToTarget(window_, root, point);
+ root->GetRootWindow()->transform().TransformPoint(point);
+
+// On ChromeOS, the root surface is the whole desktop. When using the
+// window-service converting to screen coordinates gives us that.
+#if defined(OS_CHROMEOS)
+ if (features::IsUsingWindowService()) {
+ aura::client::ScreenPositionClient* screen_client =
+ aura::client::GetScreenPositionClient(root);
+ if (screen_client) {
+ gfx::Point rounded_point(point->x(), point->y());
+ screen_client->ConvertPointToScreen(root, &rounded_point);
+ *point = gfx::PointF(rounded_point);
+ }
+ }
+#endif
}
gfx::Rect RenderWidgetHostViewAura::GetBoundsInRootWindow() {
@@ -938,10 +980,13 @@ gfx::Rect RenderWidgetHostViewAura::GetBoundsInRootWindow() {
bounds.Inset(GetSystemMetrics(SM_CXPADDEDBORDER),
GetSystemMetrics(SM_CXPADDEDBORDER));
}
+
+ // Pixels come back from GetWindowHost, so we need to convert those back to
+ // DIPs here.
+ bounds = display::Screen::GetScreen()->ScreenToDIPRectInWindow(top_level,
+ bounds);
}
- bounds =
- display::Screen::GetScreen()->ScreenToDIPRectInWindow(top_level, bounds);
#endif
return bounds;
@@ -965,6 +1010,15 @@ void RenderWidgetHostViewAura::DidOverscroll(
void RenderWidgetHostViewAura::GestureEventAck(
const blink::WebGestureEvent& event,
InputEventAckState ack_result) {
+ const blink::WebInputEvent::Type event_type = event.GetType();
+ if (event_type == blink::WebGestureEvent::kGestureScrollBegin ||
+ event_type == blink::WebGestureEvent::kGestureScrollEnd) {
+ if (host()->delegate()) {
+ host()->delegate()->SetTopControlsGestureScrollInProgress(
+ event_type == blink::WebGestureEvent::kGestureScrollBegin);
+ }
+ }
+
if (overscroll_controller_) {
overscroll_controller_->ReceivedEventACK(
event, (INPUT_EVENT_ACK_STATE_CONSUMED == ack_result));
@@ -975,7 +1029,7 @@ void RenderWidgetHostViewAura::GestureEventAck(
// action would complete at the end of the active fling progress which
// causes noticeable delay in cases that the fling velocity is large.
// https://crbug.com/797855
- if (event.GetType() == blink::WebInputEvent::kGestureScrollUpdate &&
+ if (event_type == blink::WebInputEvent::kGestureScrollUpdate &&
event.data.scroll_update.inertial_phase ==
blink::WebGestureEvent::kMomentumPhase &&
overscroll_controller_->overscroll_mode() != OVERSCROLL_NONE) {
@@ -1129,9 +1183,8 @@ RenderWidgetHostViewAura::AccessibilityGetNativeViewAccessible() {
return nullptr;
}
-void RenderWidgetHostViewAura::SetMainFrameAXTreeID(
- ui::AXTreeIDRegistry::AXTreeID id) {
- window_->SetProperty(ui::kChildAXTreeID, id);
+void RenderWidgetHostViewAura::SetMainFrameAXTreeID(ui::AXTreeID id) {
+ window_->SetProperty(ui::kChildAXTreeID, new std::string(id.ToString()));
}
bool RenderWidgetHostViewAura::LockMouse() {
@@ -1236,7 +1289,7 @@ ui::TextInputMode RenderWidgetHostViewAura::GetTextInputMode() const {
}
base::i18n::TextDirection RenderWidgetHostViewAura::GetTextDirection() const {
- NOTIMPLEMENTED();
+ NOTIMPLEMENTED_LOG_ONCE();
return base::i18n::UNKNOWN_DIRECTION;
}
@@ -1346,7 +1399,7 @@ bool RenderWidgetHostViewAura::GetTextRange(gfx::Range* range) const {
bool RenderWidgetHostViewAura::GetCompositionTextRange(
gfx::Range* range) const {
// TODO(suzhe): implement this method when fixing http://crbug.com/55130.
- NOTIMPLEMENTED();
+ NOTIMPLEMENTED_LOG_ONCE();
return false;
}
@@ -1366,13 +1419,13 @@ bool RenderWidgetHostViewAura::GetSelectionRange(gfx::Range* range) const {
bool RenderWidgetHostViewAura::SetSelectionRange(const gfx::Range& range) {
// TODO(suzhe): implement this method when fixing http://crbug.com/55130.
- NOTIMPLEMENTED();
+ NOTIMPLEMENTED_LOG_ONCE();
return false;
}
bool RenderWidgetHostViewAura::DeleteRange(const gfx::Range& range) {
// TODO(suzhe): implement this method when fixing http://crbug.com/55130.
- NOTIMPLEMENTED();
+ NOTIMPLEMENTED_LOG_ONCE();
return false;
}
@@ -1474,12 +1527,6 @@ bool RenderWidgetHostViewAura::ShouldDoLearning() {
////////////////////////////////////////////////////////////////////////////////
// RenderWidgetHostViewAura, display::DisplayObserver implementation:
-void RenderWidgetHostViewAura::OnDisplayAdded(
- const display::Display& new_display) {}
-
-void RenderWidgetHostViewAura::OnDisplayRemoved(
- const display::Display& old_display) {}
-
void RenderWidgetHostViewAura::OnDisplayMetricsChanged(
const display::Display& display,
uint32_t metrics) {
@@ -1535,7 +1582,7 @@ bool RenderWidgetHostViewAura::ShouldDescendIntoChildForEventHandling(
}
bool RenderWidgetHostViewAura::CanFocus() {
- return popup_type_ == blink::kWebPopupTypeNone;
+ return widget_type_ == WidgetType::kFrame;
}
void RenderWidgetHostViewAura::OnCaptureLost() {
@@ -1668,16 +1715,23 @@ bool RenderWidgetHostViewAura::TransformPointToCoordSpaceForView(
// In TransformPointToLocalCoordSpace() there is a Point-to-Pixel conversion,
// but it is not necessary here because the final target view is responsible
// for converting before computing the final transform.
- if (!HasFallbackSurface())
- return false;
return target_view->TransformPointToLocalCoordSpace(
point, GetCurrentSurfaceId(), transformed_point, source);
}
viz::FrameSinkId RenderWidgetHostViewAura::GetRootFrameSinkId() {
- if (window_ && window_->GetHost() && window_->GetHost()->compositor())
- return window_->GetHost()->compositor()->frame_sink_id();
- return viz::FrameSinkId();
+ if (!window_ || !window_->GetHost() || !window_->GetHost()->compositor())
+ return viz::FrameSinkId();
+
+ // In single-process mash the root is provided by Ash. Have
+ // HostFrameSinkManager walk the tree to find the right root.
+ if (features::IsSingleProcessMash()) {
+ base::Optional<viz::FrameSinkId> root =
+ GetHostFrameSinkManager()->FindRootFrameSinkId(frame_sink_id_);
+ return root ? *root : viz::FrameSinkId();
+ }
+
+ return window_->GetHost()->compositor()->frame_sink_id();
}
viz::SurfaceId RenderWidgetHostViewAura::GetCurrentSurfaceId() const {
@@ -1703,6 +1757,13 @@ void RenderWidgetHostViewAura::FocusedNodeChanged(
if (!editable && virtual_keyboard_requested_ && window_) {
virtual_keyboard_requested_ = false;
+ if (input_method && input_method->GetInputMethodKeyboardController()) {
+ input_method->GetInputMethodKeyboardController()
+ ->DismissVirtualKeyboard();
+ }
+ }
+#elif defined(OS_FUCHSIA)
+ if (!editable && window_) {
if (input_method) {
input_method->GetInputMethodKeyboardController()
->DismissVirtualKeyboard();
@@ -1714,7 +1775,7 @@ void RenderWidgetHostViewAura::FocusedNodeChanged(
void RenderWidgetHostViewAura::ScheduleEmbed(
ws::mojom::WindowTreeClientPtr client,
base::OnceCallback<void(const base::UnguessableToken&)> callback) {
- DCHECK(features::IsUsingWindowService());
+ DCHECK(features::IsMultiProcessMash());
aura::Env::GetInstance()->ScheduleEmbed(std::move(client),
std::move(callback));
}
@@ -1890,12 +1951,12 @@ RenderWidgetHostViewAura::~RenderWidgetHostViewAura() {
DetachFromInputMethod();
}
if (popup_parent_host_view_) {
- DCHECK(popup_parent_host_view_->popup_child_host_view_ == nullptr ||
+ DCHECK(!popup_parent_host_view_->popup_child_host_view_ ||
popup_parent_host_view_->popup_child_host_view_ == this);
popup_parent_host_view_->SetPopupChild(nullptr);
}
if (popup_child_host_view_) {
- DCHECK(popup_child_host_view_->popup_parent_host_view_ == nullptr ||
+ DCHECK(!popup_child_host_view_->popup_parent_host_view_ ||
popup_child_host_view_->popup_parent_host_view_ == this);
popup_child_host_view_->popup_parent_host_view_ = nullptr;
}
@@ -1917,8 +1978,6 @@ void RenderWidgetHostViewAura::CreateAuraWindow(aura::client::WindowType type) {
DCHECK(!is_mus_browser_plugin_guest_);
window_ = new aura::Window(this);
window_->SetName("RenderWidgetHostViewAura");
- window_->SetProperty(aura::client::kEmbedType,
- aura::client::WindowEmbedType::EMBED_IN_OWNER);
event_handler_->set_window(window_);
window_observer_.reset(new WindowObserver(this));
@@ -1936,7 +1995,7 @@ void RenderWidgetHostViewAura::CreateAuraWindow(aura::client::WindowType type) {
if (frame_sink_id_.is_valid())
window_->SetEmbedFrameSinkId(frame_sink_id_);
- if (!features::IsUsingWindowService())
+ if (!features::IsMultiProcessMash())
return;
// Embed the renderer into the Window.
@@ -2051,6 +2110,19 @@ bool RenderWidgetHostViewAura::SynchronizeVisualProperties(
return host()->SynchronizeVisualProperties();
}
+void RenderWidgetHostViewAura::OnDidUpdateVisualPropertiesComplete(
+ const cc::RenderFrameMetadata& metadata) {
+ DCHECK(window_);
+
+ if (host()->delegate()) {
+ host()->delegate()->SetTopControlsShownRatio(
+ host(), metadata.top_controls_shown_ratio);
+ }
+
+ SynchronizeVisualProperties(cc::DeadlinePolicy::UseDefaultDeadline(),
+ metadata.local_surface_id);
+}
+
ui::InputMethod* RenderWidgetHostViewAura::GetInputMethod() const {
if (!window_)
return nullptr;
@@ -2085,7 +2157,7 @@ RenderWidgetHostViewAura::GetTouchSelectionControllerClientManager() {
}
bool RenderWidgetHostViewAura::NeedsInputGrab() {
- return popup_type_ == blink::kWebPopupTypePage;
+ return widget_type_ == WidgetType::kPopup;
}
bool RenderWidgetHostViewAura::NeedsMouseCapture() {
@@ -2354,7 +2426,7 @@ void RenderWidgetHostViewAura::OnUpdateTextInputStateCalled(
if (state && state->type != ui::TEXT_INPUT_TYPE_NONE &&
state->mode != ui::TEXT_INPUT_MODE_NONE) {
bool show_virtual_keyboard = true;
-#if defined(OS_WIN)
+#if defined(OS_WIN) || defined(OS_FUCHSIA)
show_virtual_keyboard =
last_pointer_type_ == ui::EventPointerType::POINTER_TYPE_TOUCH;
#endif
@@ -2460,10 +2532,8 @@ viz::ScopedSurfaceIdAllocator
RenderWidgetHostViewAura::DidUpdateVisualProperties(
const cc::RenderFrameMetadata& metadata) {
base::OnceCallback<void()> allocation_task = base::BindOnce(
- base::IgnoreResult(
- &RenderWidgetHostViewAura::SynchronizeVisualProperties),
- weak_ptr_factory_.GetWeakPtr(), cc::DeadlinePolicy::UseDefaultDeadline(),
- metadata.local_surface_id);
+ &RenderWidgetHostViewAura::OnDidUpdateVisualPropertiesComplete,
+ weak_ptr_factory_.GetWeakPtr(), metadata);
return window_->GetSurfaceIdAllocator(std::move(allocation_task));
}
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 f237a3d5651..cfb4918a3cb 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
@@ -137,6 +137,8 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
void SetTooltipText(const base::string16& tooltip_text) override;
void DisplayTooltipText(const base::string16& tooltip_text) override;
uint32_t GetCaptureSequenceNumber() const override;
+ bool DoBrowserControlsShrinkRendererSize() const override;
+ float GetTopControlsHeight() const override;
bool IsSurfaceAvailableForCopy() const override;
void CopyFromSurface(
const gfx::Rect& src_rect,
@@ -162,7 +164,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
BrowserAccessibilityDelegate* delegate, bool for_root_frame) override;
gfx::AcceleratedWidget AccessibilityGetAcceleratedWidget() override;
gfx::NativeViewAccessible AccessibilityGetNativeViewAccessible() override;
- void SetMainFrameAXTreeID(ui::AXTreeIDRegistry::AXTreeID id) override;
+ void SetMainFrameAXTreeID(ui::AXTreeID id) override;
bool LockMouse() override;
void UnlockMouse() override;
bool LockKeyboard(base::Optional<base::flat_set<ui::DomCode>> codes) override;
@@ -244,8 +246,6 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
bool ShouldDoLearning() override;
// Overridden from display::DisplayObserver:
- void OnDisplayAdded(const display::Display& new_display) override;
- void OnDisplayRemoved(const display::Display& old_display) override;
void OnDisplayMetricsChanged(const display::Display& display,
uint32_t metrics) override;
@@ -469,6 +469,9 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
const base::Optional<viz::LocalSurfaceId>&
child_allocated_local_surface_id);
+ void OnDidUpdateVisualPropertiesComplete(
+ const cc::RenderFrameMetadata& metadata);
+
// Tracks whether SnapToPhysicalPixelBoundary() has been called.
bool has_snapped_to_boundary() { return has_snapped_to_boundary_; }
void ResetHasSnappedToBoundary() { has_snapped_to_boundary_ = false; }
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 dba7c7d3e47..50d09e66b2a 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
@@ -62,6 +62,7 @@
#include "content/common/input_messages.h"
#include "content/common/text_input_state.h"
#include "content/common/view_messages.h"
+#include "content/common/widget_messages.h"
#include "content/public/browser/keyboard_event_processing_result.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/web_contents_view_delegate.h"
@@ -138,6 +139,18 @@ using blink::WebTouchPoint;
using ui::WebInputEventTraits;
using viz::FrameEvictionManager;
+#define EXPECT_EVICTED(view) \
+ { \
+ EXPECT_FALSE((view)->HasPrimarySurface()); \
+ EXPECT_FALSE((view)->HasSavedFrame()); \
+ }
+
+#define EXPECT_HAS_FRAME(view) \
+ { \
+ EXPECT_TRUE((view)->HasPrimarySurface()); \
+ EXPECT_TRUE((view)->HasSavedFrame()); \
+ }
+
namespace content {
void InstallDelegatedFrameHostClient(
@@ -300,6 +313,10 @@ class FakeRenderWidgetHostViewAura : public RenderWidgetHostViewAura {
return GetDelegatedFrameHost()->HasFallbackSurface();
}
+ bool HasSavedFrame() const {
+ return GetDelegatedFrameHost()->HasSavedFrame();
+ }
+
void ReclaimResources(const std::vector<viz::ReturnedResource>& resources) {
GetDelegatedFrameHost()->ReclaimResources(resources);
}
@@ -1123,6 +1140,7 @@ TEST_F(RenderWidgetHostViewAuraTest, PositionChildPopup) {
// Verify that when the popup is initialized for the first time, it correctly
// treats the input bounds as screen coordinates.
+ view_->SetWidgetType(WidgetType::kPopup);
view_->InitAsPopup(parent_view_, bounds_in_screen);
gfx::Rect final_bounds_in_screen = view_->GetViewBounds();
@@ -1171,36 +1189,38 @@ TEST_F(RenderWidgetHostViewAuraTest, ParentMovementUpdatesScreenRect) {
// Flush the state after initial setup is done.
widget_host_->OnMessageReceived(
- ViewHostMsg_UpdateScreenRects_ACK(widget_host_->GetRoutingID()));
+ WidgetHostMsg_UpdateScreenRects_ACK(widget_host_->GetRoutingID()));
widget_host_->OnMessageReceived(
- ViewHostMsg_UpdateScreenRects_ACK(widget_host_->GetRoutingID()));
+ WidgetHostMsg_UpdateScreenRects_ACK(widget_host_->GetRoutingID()));
sink_->ClearMessages();
// Move parents.
parent2->SetBounds(gfx::Rect(20, 20, 200, 200));
ASSERT_EQ(1U, sink_->message_count());
const IPC::Message* msg = sink_->GetMessageAt(0);
- ASSERT_EQ(static_cast<uint32_t>(ViewMsg_UpdateScreenRects::ID), msg->type());
- ViewMsg_UpdateScreenRects::Param params;
- ViewMsg_UpdateScreenRects::Read(msg, &params);
+ ASSERT_EQ(static_cast<uint32_t>(WidgetMsg_UpdateScreenRects::ID),
+ msg->type());
+ WidgetMsg_UpdateScreenRects::Param params;
+ WidgetMsg_UpdateScreenRects::Read(msg, &params);
EXPECT_EQ(gfx::Rect(24, 24, 100, 100), std::get<0>(params));
EXPECT_EQ(gfx::Rect(1, 1, 300, 300), std::get<1>(params));
sink_->ClearMessages();
widget_host_->OnMessageReceived(
- ViewHostMsg_UpdateScreenRects_ACK(widget_host_->GetRoutingID()));
+ WidgetHostMsg_UpdateScreenRects_ACK(widget_host_->GetRoutingID()));
// There should not be any pending update.
EXPECT_EQ(0U, sink_->message_count());
parent1->SetBounds(gfx::Rect(10, 10, 300, 300));
ASSERT_EQ(1U, sink_->message_count());
msg = sink_->GetMessageAt(0);
- ASSERT_EQ(static_cast<uint32_t>(ViewMsg_UpdateScreenRects::ID), msg->type());
- ViewMsg_UpdateScreenRects::Read(msg, &params);
+ ASSERT_EQ(static_cast<uint32_t>(WidgetMsg_UpdateScreenRects::ID),
+ msg->type());
+ WidgetMsg_UpdateScreenRects::Read(msg, &params);
EXPECT_EQ(gfx::Rect(33, 33, 100, 100), std::get<0>(params));
EXPECT_EQ(gfx::Rect(10, 10, 300, 300), std::get<1>(params));
sink_->ClearMessages();
widget_host_->OnMessageReceived(
- ViewHostMsg_UpdateScreenRects_ACK(widget_host_->GetRoutingID()));
+ WidgetHostMsg_UpdateScreenRects_ACK(widget_host_->GetRoutingID()));
// There should not be any pending update.
EXPECT_EQ(0U, sink_->message_count());
}
@@ -1228,6 +1248,7 @@ TEST_F(RenderWidgetHostViewAuraTest, DestroyFullscreenOnBlur) {
view_ = nullptr;
}
+#if defined(OS_CHROMEOS)
// Checks that a popup view is destroyed when a user clicks outside of the popup
// view and focus does not change. This is the case when the user clicks on the
// desktop background on Chrome OS.
@@ -1236,11 +1257,12 @@ TEST_F(RenderWidgetHostViewAuraTest, DestroyPopupClickOutsidePopup) {
parent_view_->Focus();
EXPECT_TRUE(parent_view_->HasFocus());
+ view_->SetWidgetType(WidgetType::kPopup);
view_->InitAsPopup(parent_view_, gfx::Rect(10, 10, 100, 100));
aura::Window* window = view_->GetNativeView();
ASSERT_TRUE(window != nullptr);
- gfx::Point click_point;
+ gfx::Point click_point(0, 0);
EXPECT_FALSE(window->GetBoundsInRootWindow().Contains(click_point));
aura::Window* parent_window = parent_view_->GetNativeView();
EXPECT_FALSE(parent_window->GetBoundsInRootWindow().Contains(click_point));
@@ -1263,11 +1285,12 @@ TEST_F(RenderWidgetHostViewAuraTest, DestroyPopupTapOutsidePopup) {
parent_view_->Focus();
EXPECT_TRUE(parent_view_->HasFocus());
+ view_->SetWidgetType(WidgetType::kPopup);
view_->InitAsPopup(parent_view_, gfx::Rect(10, 10, 100, 100));
aura::Window* window = view_->GetNativeView();
ASSERT_TRUE(window != nullptr);
- gfx::Point tap_point;
+ gfx::Point tap_point(0, 0);
EXPECT_FALSE(window->GetBoundsInRootWindow().Contains(tap_point));
aura::Window* parent_window = parent_view_->GetNativeView();
EXPECT_FALSE(parent_window->GetBoundsInRootWindow().Contains(tap_point));
@@ -1281,9 +1304,9 @@ TEST_F(RenderWidgetHostViewAuraTest, DestroyPopupTapOutsidePopup) {
widget_host_ = nullptr;
view_ = nullptr;
}
+#endif
#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
-
// On Desktop Linux, select boxes need mouse capture in order to work. Test that
// when a select box is opened via a mouse press that it retains mouse capture
// after the mouse is released.
@@ -1296,7 +1319,7 @@ TEST_F(RenderWidgetHostViewAuraTest, PopupRetainsCaptureAfterMouseRelease) {
parent_view_->GetNativeView()->GetRootWindow(), gfx::Point(300, 300));
generator.PressLeftButton();
- view_->SetPopupType(blink::kWebPopupTypePage);
+ view_->SetWidgetType(WidgetType::kPopup);
view_->InitAsPopup(parent_view_, gfx::Rect(10, 10, 100, 100));
ASSERT_TRUE(view_->NeedsMouseCapture());
aura::Window* window = view_->GetNativeView();
@@ -1314,7 +1337,7 @@ TEST_F(RenderWidgetHostViewAuraTest, PopupClosesWhenParentLosesFocus) {
parent_view_->Focus();
EXPECT_TRUE(parent_view_->HasFocus());
- view_->SetPopupType(blink::kWebPopupTypePage);
+ view_->SetWidgetType(WidgetType::kPopup);
view_->InitAsPopup(parent_view_, gfx::Rect(10, 10, 100, 100));
aura::Window* popup_window = view_->GetNativeView();
@@ -1526,6 +1549,7 @@ TEST_F(RenderWidgetHostViewAuraTest, TouchEventState) {
EXPECT_TRUE(press.synchronous_handling_disabled());
EXPECT_EQ(ui::MotionEvent::Action::DOWN, pointer_state().GetAction());
EXPECT_EQ(1U, pointer_state().GetPointerCount());
+ widget_host_->input_router()->OnSetTouchAction(cc::kTouchActionAuto);
view_->OnTouchEvent(&move);
base::RunLoop().RunUntilIdle();
@@ -1741,8 +1765,7 @@ TEST_F(RenderWidgetHostViewAuraTest,
parent_view_->Focus();
ASSERT_TRUE(parent_view_->HasFocus());
- // kWebPopupTypePage means the child view (popup) will receive input.
- view_->SetPopupType(blink::kWebPopupTypePage);
+ view_->SetWidgetType(WidgetType::kPopup);
view_->InitAsPopup(parent_view_, gfx::Rect(10, 10, 100, 100));
ASSERT_NE(nullptr, view_->GetNativeView());
view_->Show();
@@ -1800,66 +1823,6 @@ TEST_F(RenderWidgetHostViewAuraTest,
}
}
-TEST_F(RenderWidgetHostViewAuraTest,
- KeyEventRoutingKeyboardLockAndChildPopupWithoutInputGrab) {
- parent_view_->SetBounds(gfx::Rect(10, 10, 400, 400));
- parent_view_->Focus();
- ASSERT_TRUE(parent_view_->HasFocus());
-
- // kWebPopupTypeNone means the child view (popup) will not receive input.
- view_->SetPopupType(blink::kWebPopupTypeNone);
- view_->InitAsPopup(parent_view_, gfx::Rect(10, 10, 100, 100));
- ASSERT_NE(nullptr, view_->GetNativeView());
- view_->Show();
-
- // The parent view owns the KeyboardLock for this test.
- auto test_hook = std::make_unique<TestScopedKeyboardHook>();
- test_hook->LockAllKeys();
- parent_view_->event_handler()->scoped_keyboard_hook_ = std::move(test_hook);
-
- // These keys will be handled by the parent view and will not be sent through
- // the prehandler input pipeline.
- std::vector<ui::DomCode> dom_codes = {ui::DomCode::US_A, ui::DomCode::ENTER,
- ui::DomCode::TAB, ui::DomCode::ALT_LEFT,
- ui::DomCode::US_Z};
- MockRenderWidgetHostImpl* parent_host =
- static_cast<MockRenderWidgetHostImpl*>(parent_host_);
- for (ui::DomCode dom_code : dom_codes) {
- ui::KeyEvent key_event(ui::ET_KEY_PRESSED,
- ui::DomCodeToUsLayoutKeyboardCode(dom_code),
- dom_code, ui::EF_NONE);
- parent_view_->OnKeyEvent(&key_event);
- const NativeWebKeyboardEvent* child_event =
- render_widget_host_delegate()->last_event();
- ASSERT_FALSE(child_event)
- << "Failed for DomCode: "
- << ui::KeycodeConverter::DomCodeToCodeString(dom_code);
- // Run the runloop to ensure input messages are dispatched. Otherwise the
- // result of GetAndResetDispatchedMessages() will not be valid.
- base::RunLoop().RunUntilIdle();
- auto child_events = GetAndResetDispatchedMessages();
- ASSERT_TRUE(child_events.empty())
- << "Failed for DomCode: "
- << ui::KeycodeConverter::DomCodeToCodeString(dom_code);
-
- const NativeWebKeyboardEvent* parent_event = delegates_[0]->last_event();
- ASSERT_FALSE(parent_event)
- << "Failed for DomCode: "
- << ui::KeycodeConverter::DomCodeToCodeString(dom_code);
- auto events = parent_host->input_handler()->GetAndResetDispatchedMessages();
- ASSERT_FALSE(events.empty());
- const NativeWebKeyboardEvent* native_key_event =
- static_cast<const NativeWebKeyboardEvent*>(
- events.back()->ToEvent()->Event()->web_event.get());
- ASSERT_TRUE(native_key_event)
- << "Failed for DomCode: "
- << ui::KeycodeConverter::DomCodeToCodeString(dom_code);
- ASSERT_EQ(key_event.key_code(), native_key_event->windows_key_code);
- ASSERT_EQ(ui::KeycodeConverter::DomCodeToNativeKeycode(key_event.code()),
- native_key_event->native_key_code);
- }
-}
-
TEST_F(RenderWidgetHostViewAuraTest, TimerBasedWheelEventPhaseInfo) {
view_->InitAsChild(nullptr);
view_->Show();
@@ -2657,14 +2620,14 @@ 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_SynchronizeVisualProperties::ID),
+ EXPECT_EQ(static_cast<uint32_t>(WidgetMsg_SynchronizeVisualProperties::ID),
sink_->GetMessageAt(0)->type());
{
const IPC::Message* msg = sink_->GetMessageAt(0);
- EXPECT_EQ(static_cast<uint32_t>(ViewMsg_SynchronizeVisualProperties::ID),
+ EXPECT_EQ(static_cast<uint32_t>(WidgetMsg_SynchronizeVisualProperties::ID),
msg->type());
- ViewMsg_SynchronizeVisualProperties::Param params;
- ViewMsg_SynchronizeVisualProperties::Read(msg, &params);
+ WidgetMsg_SynchronizeVisualProperties::Param params;
+ WidgetMsg_SynchronizeVisualProperties::Read(msg, &params);
EXPECT_EQ("100x100", std::get<0>(params).new_size.ToString()); // dip size
EXPECT_EQ("100x100",
std::get<0>(params)
@@ -2679,10 +2642,10 @@ 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_SynchronizeVisualProperties::ID message to the
+ // which sends a WidgetMsg_SynchronizeVisualProperties::ID message to the
// renderer.
EXPECT_EQ(1u, sink_->message_count());
- EXPECT_EQ(static_cast<uint32_t>(ViewMsg_SynchronizeVisualProperties::ID),
+ EXPECT_EQ(static_cast<uint32_t>(WidgetMsg_SynchronizeVisualProperties::ID),
sink_->GetMessageAt(0)->type());
widget_host_->ResetSentVisualProperties();
@@ -2691,13 +2654,13 @@ TEST_F(RenderWidgetHostViewAuraTest, CompositorViewportPixelSizeWithScale) {
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_SynchronizeVisualProperties::ID),
+ EXPECT_EQ(static_cast<uint32_t>(WidgetMsg_SynchronizeVisualProperties::ID),
sink_->GetMessageAt(0)->type());
EXPECT_EQ("100x100", view_->GetCompositorViewportPixelSize().ToString());
}
// This test verifies that in AutoResize mode a new
-// ViewMsg_SynchronizeVisualProperties message is sent when ScreenInfo
+// WidgetMsg_SynchronizeVisualProperties message is sent when ScreenInfo
// changes and that message contains the latest ScreenInfo.
TEST_F(RenderWidgetHostViewAuraTest, AutoResizeWithScale) {
view_->InitAsChild(nullptr);
@@ -2714,10 +2677,10 @@ TEST_F(RenderWidgetHostViewAuraTest, AutoResizeWithScale) {
ASSERT_EQ(1u, sink_->message_count());
{
const IPC::Message* msg = sink_->GetMessageAt(0);
- EXPECT_EQ(static_cast<uint32_t>(ViewMsg_SynchronizeVisualProperties::ID),
+ EXPECT_EQ(static_cast<uint32_t>(WidgetMsg_SynchronizeVisualProperties::ID),
msg->type());
- ViewMsg_SynchronizeVisualProperties::Param params;
- ViewMsg_SynchronizeVisualProperties::Read(msg, &params);
+ WidgetMsg_SynchronizeVisualProperties::Param params;
+ WidgetMsg_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());
@@ -2745,11 +2708,11 @@ 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_SynchronizeVisualProperties::ID);
+ const IPC::Message* msg = sink_->GetFirstMessageMatching(
+ WidgetMsg_SynchronizeVisualProperties::ID);
ASSERT_TRUE(msg);
- ViewMsg_SynchronizeVisualProperties::Param params;
- ViewMsg_SynchronizeVisualProperties::Read(msg, &params);
+ WidgetMsg_SynchronizeVisualProperties::Param params;
+ WidgetMsg_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());
@@ -2762,7 +2725,7 @@ TEST_F(RenderWidgetHostViewAuraTest, AutoResizeWithScale) {
}
// This test verifies that in AutoResize mode a new
-// ViewMsg_SynchronizeVisualProperties message is sent when size changes.
+// WidgetMsg_SynchronizeVisualProperties message is sent when size changes.
TEST_F(RenderWidgetHostViewAuraTest, AutoResizeWithBrowserInitiatedResize) {
view_->InitAsChild(nullptr);
aura::client::ParentWindowWithContext(
@@ -2778,10 +2741,10 @@ TEST_F(RenderWidgetHostViewAuraTest, AutoResizeWithBrowserInitiatedResize) {
ASSERT_EQ(1u, sink_->message_count());
{
const IPC::Message* msg = sink_->GetMessageAt(0);
- EXPECT_EQ(static_cast<uint32_t>(ViewMsg_SynchronizeVisualProperties::ID),
+ EXPECT_EQ(static_cast<uint32_t>(WidgetMsg_SynchronizeVisualProperties::ID),
msg->type());
- ViewMsg_SynchronizeVisualProperties::Param params;
- ViewMsg_SynchronizeVisualProperties::Read(msg, &params);
+ WidgetMsg_SynchronizeVisualProperties::Param params;
+ WidgetMsg_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());
@@ -2810,10 +2773,10 @@ TEST_F(RenderWidgetHostViewAuraTest, AutoResizeWithBrowserInitiatedResize) {
ASSERT_EQ(1u, sink_->message_count());
{
const IPC::Message* msg = sink_->GetMessageAt(0);
- EXPECT_EQ(static_cast<uint32_t>(ViewMsg_SynchronizeVisualProperties::ID),
+ EXPECT_EQ(static_cast<uint32_t>(WidgetMsg_SynchronizeVisualProperties::ID),
msg->type());
- ViewMsg_SynchronizeVisualProperties::Param params;
- ViewMsg_SynchronizeVisualProperties::Read(msg, &params);
+ WidgetMsg_SynchronizeVisualProperties::Param params;
+ WidgetMsg_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());
@@ -3042,7 +3005,7 @@ viz::CompositorFrame MakeDelegatedFrame(float scale_factor,
// This test verifies that returned resources do not require a pending ack.
TEST_F(RenderWidgetHostViewAuraTest, ReturnedResources) {
// TODO: fix for mash.
- if (features::IsUsingWindowService())
+ if (features::IsMultiProcessMash())
return;
gfx::Size view_size(100, 100);
@@ -3076,7 +3039,7 @@ TEST_F(RenderWidgetHostViewAuraTest, TwoOutputSurfaces) {
// TODO(jonross): Delete this test once Viz launches as it will be obsolete.
// https://crbug.com/844469
if (base::FeatureList::IsEnabled(features::kVizDisplayCompositor) ||
- features::IsUsingWindowService()) {
+ features::IsMultiProcessMash()) {
return;
}
@@ -3143,10 +3106,10 @@ TEST_F(RenderWidgetHostViewAuraTest, DISABLED_FullscreenResize) {
{
// 0 is CreatingNew message.
const IPC::Message* msg = sink_->GetMessageAt(0);
- EXPECT_EQ(static_cast<uint32_t>(ViewMsg_SynchronizeVisualProperties::ID),
+ EXPECT_EQ(static_cast<uint32_t>(WidgetMsg_SynchronizeVisualProperties::ID),
msg->type());
- ViewMsg_SynchronizeVisualProperties::Param params;
- ViewMsg_SynchronizeVisualProperties::Read(msg, &params);
+ WidgetMsg_SynchronizeVisualProperties::Param params;
+ WidgetMsg_SynchronizeVisualProperties::Read(msg, &params);
EXPECT_EQ(
"0,0 800x600",
std::get<0>(params).screen_info.available_rect.ToString());
@@ -3171,10 +3134,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_SynchronizeVisualProperties::ID),
+ EXPECT_EQ(static_cast<uint32_t>(WidgetMsg_SynchronizeVisualProperties::ID),
msg->type());
- ViewMsg_SynchronizeVisualProperties::Param params;
- ViewMsg_SynchronizeVisualProperties::Read(msg, &params);
+ WidgetMsg_SynchronizeVisualProperties::Param params;
+ WidgetMsg_SynchronizeVisualProperties::Read(msg, &params);
EXPECT_EQ(
"0,0 1600x1200",
std::get<0>(params).screen_info.available_rect.ToString());
@@ -3206,10 +3169,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_SynchronizeVisualProperties::ID),
+ EXPECT_EQ(static_cast<uint32_t>(WidgetMsg_SynchronizeVisualProperties::ID),
msg->type());
- ViewMsg_SynchronizeVisualProperties::Param params;
- ViewMsg_SynchronizeVisualProperties::Read(msg, &params);
+ WidgetMsg_SynchronizeVisualProperties::Param params;
+ WidgetMsg_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());
@@ -3218,7 +3181,7 @@ TEST_F(RenderWidgetHostViewAuraTest, ZeroSizeStillGetsLocalSurfaceId) {
TEST_F(RenderWidgetHostViewAuraTest, BackgroundColorMatchesCompositorFrame) {
// TODO: fix for mash.
- if (features::IsUsingWindowService())
+ if (features::IsMultiProcessMash())
return;
gfx::Size frame_size(100, 100);
@@ -3300,10 +3263,10 @@ 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_SynchronizeVisualProperties::ID),
+ EXPECT_EQ(static_cast<uint32_t>(WidgetMsg_SynchronizeVisualProperties::ID),
msg->type());
- ViewMsg_SynchronizeVisualProperties::Param params;
- ViewMsg_SynchronizeVisualProperties::Read(msg, &params);
+ WidgetMsg_SynchronizeVisualProperties::Param params;
+ WidgetMsg_SynchronizeVisualProperties::Read(msg, &params);
EXPECT_EQ(size2.ToString(), std::get<0>(params).new_size.ToString());
}
// Send resize ack to observe new Resize messages.
@@ -3356,10 +3319,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_SynchronizeVisualProperties::ID: {
+ case WidgetMsg_SynchronizeVisualProperties::ID: {
EXPECT_FALSE(has_resize);
- ViewMsg_SynchronizeVisualProperties::Param params;
- ViewMsg_SynchronizeVisualProperties::Read(msg, &params);
+ WidgetMsg_SynchronizeVisualProperties::Param params;
+ WidgetMsg_SynchronizeVisualProperties::Read(msg, &params);
EXPECT_EQ(size3.ToString(), std::get<0>(params).new_size.ToString());
has_resize = true;
break;
@@ -3383,7 +3346,7 @@ TEST_F(RenderWidgetHostViewAuraTest, OutputSurfaceIdChange) {
// TODO(jonross): Delete this test once Viz launches as it will be obsolete.
// https://crbug.com/844469
if (base::FeatureList::IsEnabled(features::kVizDisplayCompositor) ||
- features::IsUsingWindowService()) {
+ features::IsMultiProcessMash()) {
return;
}
@@ -3444,7 +3407,7 @@ TEST_F(RenderWidgetHostViewAuraTest, OutputSurfaceIdChange) {
TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
DropFallbackWhenHidden) {
// Early out because DelegatedFrameHost is not used in mash.
- if (features::IsUsingWindowService())
+ if (features::IsMultiProcessMash())
return;
view_->InitAsChild(nullptr);
@@ -3468,11 +3431,10 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
EXPECT_FALSE(view_->HasFallbackSurface());
}
-// This test verifies that the primary SurfaceId is populated on resize and
-// the fallback SurfaceId is populated in OnFirstSurfaceActivation.
+// This test verifies that the primary SurfaceId is populated on resize.
TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest, SurfaceChanges) {
// Early out because DelegatedFrameHost is not used in mash.
- if (features::IsUsingWindowService())
+ if (features::IsMultiProcessMash())
return;
view_->InitAsChild(nullptr);
@@ -3485,25 +3447,8 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest, SurfaceChanges) {
view_->SetSize(gfx::Size(300, 300));
ASSERT_TRUE(view_->HasPrimarySurface());
EXPECT_EQ(gfx::Size(300, 300), view_->window_->layer()->size());
- EXPECT_FALSE(view_->HasFallbackSurface());
EXPECT_EQ(gfx::Size(300, 300),
view_->delegated_frame_host_->CurrentFrameSizeInDipForTesting());
-
- // Resizing should update the primary SurfaceId.
- view_->SetSize(gfx::Size(400, 400));
- EXPECT_EQ(gfx::Size(400, 400), view_->window_->layer()->size());
- EXPECT_EQ(nullptr, view_->window_->layer()->GetFallbackSurfaceId());
- EXPECT_EQ(gfx::Size(400, 400),
- view_->delegated_frame_host_->CurrentFrameSizeInDipForTesting());
-
- // Fallback SurfaceId should be updated in OnFirstSurfaceActivation.
- // Submitting a CompositorFrame should update the fallback SurfaceId
- viz::SurfaceId surface_id(view_->GetFrameSinkId(),
- view_->GetLocalSurfaceId());
- view_->delegated_frame_host_->OnFirstSurfaceActivation(
- viz::SurfaceInfo(surface_id, 1.f, gfx::Size(400, 400)));
- EXPECT_EQ(gfx::Size(400, 400), view_->window_->layer()->size());
- EXPECT_EQ(surface_id, *view_->window_->layer()->GetFallbackSurfaceId());
}
// This test verifies that the primary SurfaceId is updated on device scale
@@ -3511,7 +3456,7 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest, SurfaceChanges) {
TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
DeviceScaleFactorChanges) {
// TODO: fix for mash.
- if (features::IsUsingWindowService())
+ if (features::IsMultiProcessMash())
return;
view_->InitAsChild(nullptr);
@@ -3541,7 +3486,7 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
// TODO(jonross): Delete this test once Viz launches as it will be obsolete.
// https://crbug.com/844469
if (base::FeatureList::IsEnabled(features::kVizDisplayCompositor) ||
- features::IsUsingWindowService()) {
+ features::IsMultiProcessMash()) {
return;
}
@@ -3576,7 +3521,7 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
DiscardDelegatedFrames) {
// Early out because DelegatedFrameHost is not used in mash.
- if (features::IsUsingWindowService())
+ if (features::IsMultiProcessMash())
return;
view_->InitAsChild(nullptr);
@@ -3612,40 +3557,41 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
parent_view_->GetNativeView()->GetRootWindow(), gfx::Rect());
views[i]->SetSize(view_rect.size());
ASSERT_TRUE(views[i]->HasPrimarySurface());
+ ASSERT_FALSE(views[i]->HasSavedFrame());
}
// 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();
ASSERT_TRUE(views[i]->HasPrimarySurface());
- ASSERT_FALSE(views[i]->HasFallbackSurface());
+ ASSERT_FALSE(views[i]->HasSavedFrame());
viz::SurfaceId surface_id(views[i]->GetFrameSinkId(),
views[i]->GetLocalSurfaceId());
views[i]->delegated_frame_host_->OnFirstSurfaceActivation(
viz::SurfaceInfo(surface_id, 1.f, frame_size));
- ASSERT_TRUE(views[i]->HasPrimarySurface());
- EXPECT_TRUE(views[i]->HasFallbackSurface());
+ EXPECT_HAS_FRAME(views[i]);
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());
+ EXPECT_EVICTED(views[0]);
for (size_t i = 1; i < renderer_count; ++i)
- EXPECT_TRUE(views[i]->HasFallbackSurface());
+ EXPECT_HAS_FRAME(views[i]);
// 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());
+ EXPECT_TRUE(views[0]->HasPrimarySurface());
+ EXPECT_FALSE(views[0]->HasSavedFrame());
+ EXPECT_HAS_FRAME(views[1]);
// Swap a frame on it, it should evict the next LRU [1].
viz::SurfaceId surface_id0(views[0]->GetFrameSinkId(),
views[0]->GetLocalSurfaceId());
views[0]->delegated_frame_host_->OnFirstSurfaceActivation(
viz::SurfaceInfo(surface_id0, 1.f, frame_size));
- EXPECT_TRUE(views[0]->HasFallbackSurface());
- EXPECT_FALSE(views[1]->HasFallbackSurface());
+ EXPECT_HAS_FRAME(views[0]);
+ EXPECT_EVICTED(views[1]);
views[0]->Hide();
// LRU renderer is [1], which is still hidden. Showing it and submitting a
@@ -3655,11 +3601,11 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
views[1]->GetLocalSurfaceId());
views[1]->delegated_frame_host_->OnFirstSurfaceActivation(
viz::SurfaceInfo(surface_id1, 1.f, frame_size));
- EXPECT_TRUE(views[0]->HasFallbackSurface());
- EXPECT_TRUE(views[1]->HasFallbackSurface());
- EXPECT_FALSE(views[2]->HasFallbackSurface());
+ EXPECT_HAS_FRAME(views[0]);
+ EXPECT_HAS_FRAME(views[1]);
+ EXPECT_EVICTED(views[2]);
for (size_t i = 3; i < renderer_count; ++i)
- EXPECT_TRUE(views[i]->HasFallbackSurface());
+ EXPECT_HAS_FRAME(views[i]);
// Make all renderers but [0] visible and swap a frame on them, keep [0]
// hidden, it becomes the LRU.
@@ -3671,14 +3617,14 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
views[i]->GetLocalSurfaceId());
views[i]->delegated_frame_host_->OnFirstSurfaceActivation(
viz::SurfaceInfo(surface_id, 1.f, frame_size));
- EXPECT_TRUE(views[i]->HasFallbackSurface());
+ EXPECT_HAS_FRAME(views[i]);
}
- EXPECT_FALSE(views[0]->HasFallbackSurface());
+ EXPECT_EVICTED(views[0]);
// Swap a frame on [0], it should be evicted immediately.
views[0]->delegated_frame_host_->OnFirstSurfaceActivation(
viz::SurfaceInfo(surface_id0, 1.f, frame_size));
- EXPECT_FALSE(views[0]->HasFallbackSurface());
+ EXPECT_EVICTED(views[0]);
// Make [0] visible, and swap a frame on it. Nothing should be evicted
// although we're above the limit.
@@ -3686,25 +3632,26 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
views[0]->delegated_frame_host_->OnFirstSurfaceActivation(
viz::SurfaceInfo(surface_id0, 1.f, frame_size));
for (size_t i = 0; i < renderer_count; ++i)
- EXPECT_TRUE(views[i]->HasFallbackSurface()) << i;
+ EXPECT_HAS_FRAME(views[i]);
// Make [0] hidden, it should evict its frame.
views[0]->Hide();
- EXPECT_FALSE(views[0]->HasFallbackSurface());
+ EXPECT_EVICTED(views[0]);
// Make [0] visible, don't give it a frame, it should be waiting.
views[0]->Show();
// Make [0] hidden, it should stop waiting.
views[0]->Hide();
- // Make [1] hidden, resize it. It should drop its frame.
+ // Make [1] hidden, resize it. It should advance its fallback.
views[1]->Hide();
- EXPECT_TRUE(views[1]->HasFallbackSurface());
gfx::Size size2(200, 200);
views[1]->SetSize(size2);
- EXPECT_FALSE(views[1]->HasFallbackSurface());
// Show it, it should block until we give it a frame.
views[1]->Show();
+ ASSERT_TRUE(views[1]->window_->layer()->GetFallbackSurfaceId());
+ EXPECT_EQ(*views[1]->window_->layer()->GetFallbackSurfaceId(),
+ *views[1]->window_->layer()->GetPrimarySurfaceId());
views[1]->delegated_frame_host_->OnFirstSurfaceActivation(
viz::SurfaceInfo(surface_id1, 1.f, frame_size));
@@ -3716,7 +3663,7 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
TEST_F(RenderWidgetHostViewAuraTest, DiscardDelegatedFramesWithLocking) {
// Early out because DelegatedFrameHost is not used in mash.
- if (features::IsUsingWindowService())
+ if (features::IsMultiProcessMash())
return;
view_->InitAsChild(nullptr);
@@ -3758,12 +3705,12 @@ TEST_F(RenderWidgetHostViewAuraTest, DiscardDelegatedFramesWithLocking) {
views[i]->GetLocalSurfaceId());
views[i]->delegated_frame_host_->OnFirstSurfaceActivation(
viz::SurfaceInfo(surface_id, 1.f, frame_size));
- EXPECT_TRUE(views[i]->HasFallbackSurface());
+ EXPECT_HAS_FRAME(views[i]);
}
// If we hide [0], then [0] should be evicted.
views[0]->Hide();
- EXPECT_FALSE(views[0]->HasFallbackSurface());
+ EXPECT_EVICTED(views[0]);
// If we lock [0] before hiding it, then [0] should not be evicted.
views[0]->Show();
@@ -3771,14 +3718,14 @@ TEST_F(RenderWidgetHostViewAuraTest, DiscardDelegatedFramesWithLocking) {
views[0]->GetLocalSurfaceId());
views[0]->delegated_frame_host_->OnFirstSurfaceActivation(
viz::SurfaceInfo(surface_id, 1.f, frame_size));
- EXPECT_TRUE(views[0]->HasFallbackSurface());
+ EXPECT_HAS_FRAME(views[0]);
views[0]->GetDelegatedFrameHost()->LockResources();
views[0]->Hide();
- EXPECT_TRUE(views[0]->HasFallbackSurface());
+ EXPECT_HAS_FRAME(views[0]);
// If we unlock [0] now, then [0] should be evicted.
views[0]->GetDelegatedFrameHost()->UnlockResources();
- EXPECT_FALSE(views[0]->HasFallbackSurface());
+ EXPECT_EVICTED(views[0]);
for (size_t i = 0; i < renderer_count; ++i) {
views[i]->Destroy();
@@ -3790,7 +3737,7 @@ TEST_F(RenderWidgetHostViewAuraTest, DiscardDelegatedFramesWithLocking) {
// only applies to ChromeOS.
TEST_F(RenderWidgetHostViewAuraTest, DiscardDelegatedFramesWithMemoryPressure) {
// Early out because DelegatedFrameHost is not used in mash.
- if (features::IsUsingWindowService())
+ if (features::IsMultiProcessMash())
return;
view_->InitAsChild(nullptr);
@@ -3837,27 +3784,27 @@ TEST_F(RenderWidgetHostViewAuraTest, DiscardDelegatedFramesWithMemoryPressure) {
kArbitraryLocalSurfaceId);
views[i]->delegated_frame_host_->OnFirstSurfaceActivation(
viz::SurfaceInfo(surface_id, 1.f, frame_size));
- EXPECT_TRUE(views[i]->HasFallbackSurface());
+ EXPECT_HAS_FRAME(views[i]);
}
// If we hide one, it should not get evicted.
views[0]->Hide();
base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(views[0]->HasFallbackSurface());
+ EXPECT_HAS_FRAME(views[0]);
// Using a lesser memory pressure event however, should evict.
SimulateMemoryPressure(
base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE);
base::RunLoop().RunUntilIdle();
- EXPECT_FALSE(views[0]->HasFallbackSurface());
+ EXPECT_EVICTED(views[0]);
// Check the same for a higher pressure event.
views[1]->Hide();
base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(views[1]->HasFallbackSurface());
+ EXPECT_HAS_FRAME(views[1]);
SimulateMemoryPressure(
base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
base::RunLoop().RunUntilIdle();
- EXPECT_FALSE(views[1]->HasFallbackSurface());
+ EXPECT_EVICTED(views[1]);
for (size_t i = 0; i < renderer_count; ++i) {
views[i]->Destroy();
@@ -3897,7 +3844,7 @@ TEST_F(RenderWidgetHostViewAuraTest, ForwardsBeginFrameAcks) {
// TODO(jonross): Delete this test once Viz launches as it will be obsolete.
// https://crbug.com/844469
if (base::FeatureList::IsEnabled(features::kVizDisplayCompositor) ||
- features::IsUsingWindowService()) {
+ features::IsMultiProcessMash()) {
return;
}
@@ -3964,11 +3911,11 @@ TEST_F(RenderWidgetHostViewAuraTest, VisibleViewportTest) {
EXPECT_EQ(60, view_->GetVisibleViewportSize().height());
const IPC::Message* message =
- sink_->GetFirstMessageMatching(ViewMsg_SynchronizeVisualProperties::ID);
+ sink_->GetFirstMessageMatching(WidgetMsg_SynchronizeVisualProperties::ID);
ASSERT_TRUE(message != nullptr);
- ViewMsg_SynchronizeVisualProperties::Param params;
- ViewMsg_SynchronizeVisualProperties::Read(message, &params);
+ WidgetMsg_SynchronizeVisualProperties::Param params;
+ WidgetMsg_SynchronizeVisualProperties::Read(message, &params);
EXPECT_EQ(60, std::get<0>(params).visible_viewport_size.height());
}
@@ -5527,7 +5474,8 @@ TEST_F(RenderWidgetHostViewAuraTest, SetCanScrollForWebMouseWheelEvent) {
events[0]->ToEvent()->Event()->web_event.get());
// Check if scroll is caused when ctrl-scroll is generated from
// mouse wheel event.
- EXPECT_FALSE(WebInputEventTraits::CanCauseScroll(*wheel_event));
+ EXPECT_EQ(blink::WebMouseWheelEvent::EventAction::kPageZoom,
+ wheel_event->event_action);
// Ack'ing the outstanding event should flush the pending event queue.
events[0]->ToEvent()->CallCallback(INPUT_EVENT_ACK_STATE_CONSUMED);
@@ -5551,7 +5499,8 @@ TEST_F(RenderWidgetHostViewAuraTest, SetCanScrollForWebMouseWheelEvent) {
// mouse wheel event.
wheel_event = static_cast<const WebMouseWheelEvent*>(
events[1]->ToEvent()->Event()->web_event.get());
- EXPECT_TRUE(WebInputEventTraits::CanCauseScroll(*wheel_event));
+ EXPECT_NE(blink::WebMouseWheelEvent::EventAction::kPageZoom,
+ wheel_event->event_action);
events[1]->ToEvent()->CallCallback(INPUT_EVENT_ACK_STATE_CONSUMED);
@@ -5572,7 +5521,8 @@ TEST_F(RenderWidgetHostViewAuraTest, SetCanScrollForWebMouseWheelEvent) {
// from scroll event.
wheel_event = static_cast<const WebMouseWheelEvent*>(
events[1]->ToEvent()->Event()->web_event.get());
- EXPECT_TRUE(WebInputEventTraits::CanCauseScroll(*wheel_event));
+ EXPECT_NE(blink::WebMouseWheelEvent::EventAction::kPageZoom,
+ wheel_event->event_action);
}
// Ensures that the mapping from ui::TouchEvent to blink::WebTouchEvent doesn't
@@ -5838,7 +5788,7 @@ TEST_F(RenderWidgetHostViewAuraTest, HitTestRegionListSubmitted) {
// TODO(jonross): Delete this test once Viz launches as it will be obsolete.
// https://crbug.com/844469
if (base::FeatureList::IsEnabled(features::kVizDisplayCompositor) ||
- features::IsUsingWindowService()) {
+ features::IsMultiProcessMash()) {
return;
}
@@ -5880,7 +5830,7 @@ TEST_F(RenderWidgetHostViewAuraTest, HitTestRegionListSubmitted) {
TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
NewContentRenderingTimeout) {
// TODO: fix for mash.
- if (features::IsUsingWindowService())
+ if (features::IsMultiProcessMash())
return;
constexpr base::TimeDelta kTimeout = base::TimeDelta::FromMicroseconds(10);
@@ -5935,7 +5885,7 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
AllocateLocalSurfaceIdOnEviction) {
// TODO: fix for mash.
- if (features::IsUsingWindowService())
+ if (features::IsMultiProcessMash())
return;
view_->InitAsChild(nullptr);
@@ -5958,7 +5908,7 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
DropFallbackIfResizedWhileHidden) {
// Early out because DelegatedFrameHost is not used in mash.
- if (features::IsUsingWindowService())
+ if (features::IsMultiProcessMash())
return;
view_->InitAsChild(nullptr);
@@ -5969,11 +5919,12 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
viz::LocalSurfaceId id1 = view_->GetLocalSurfaceId();
view_->delegated_frame_host_->OnFirstSurfaceActivation(viz::SurfaceInfo(
viz::SurfaceId(view_->GetFrameSinkId(), id1), 1, gfx::Size(20, 20)));
- EXPECT_TRUE(view_->window_->layer()->GetFallbackSurfaceId()->is_valid());
view_->Hide();
view_->SetSize(gfx::Size(54, 32));
view_->Show();
- EXPECT_EQ(nullptr, view_->window_->layer()->GetFallbackSurfaceId());
+ ASSERT_TRUE(view_->window_->layer()->GetFallbackSurfaceId());
+ EXPECT_EQ(*view_->window_->layer()->GetFallbackSurfaceId(),
+ *view_->window_->layer()->GetPrimarySurfaceId());
}
// If a tab is hidden and shown without being resized in the meantime, the
@@ -5981,7 +5932,7 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
DontDropFallbackIfNotResizedWhileHidden) {
// Early out because DelegatedFrameHost is not used in mash.
- if (features::IsUsingWindowService())
+ if (features::IsMultiProcessMash())
return;
view_->InitAsChild(nullptr);
@@ -5990,12 +5941,15 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
gfx::Rect());
view_->Show();
viz::LocalSurfaceId id1 = view_->GetLocalSurfaceId();
- view_->delegated_frame_host_->OnFirstSurfaceActivation(viz::SurfaceInfo(
- viz::SurfaceId(view_->GetFrameSinkId(), id1), 1, gfx::Size(20, 20)));
- EXPECT_TRUE(view_->window_->layer()->GetFallbackSurfaceId()->is_valid());
+ // Force fallback being set.
+ view_->DidNavigate();
+ view_->ResetFallbackToFirstNavigationSurface();
+ ASSERT_TRUE(view_->window_->layer()->GetFallbackSurfaceId());
+ viz::SurfaceId fallback = *view_->window_->layer()->GetFallbackSurfaceId();
view_->Hide();
view_->Show();
- EXPECT_TRUE(view_->window_->layer()->GetFallbackSurfaceId()->is_valid());
+ ASSERT_TRUE(view_->window_->layer()->GetFallbackSurfaceId());
+ EXPECT_EQ(fallback, *view_->window_->layer()->GetPrimarySurfaceId());
}
// Check that TakeFallbackContentFrom() copies the fallback SurfaceId and
@@ -6003,7 +5957,7 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
TakeFallbackContent) {
// Early out because DelegatedFrameHost is not used in mash.
- if (features::IsUsingWindowService())
+ if (features::IsMultiProcessMash())
return;
// Initialize the first view.
@@ -6020,16 +5974,10 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
view2->GetNativeView(), parent_view_->GetNativeView()->GetRootWindow(),
gfx::Rect());
- // Set fallback for the first view.
- viz::LocalSurfaceId id = view_->GetLocalSurfaceId();
- view_->delegated_frame_host_->OnFirstSurfaceActivation(viz::SurfaceInfo(
- viz::SurfaceId(view_->GetFrameSinkId(), id), 1, gfx::Size(20, 20)));
- EXPECT_TRUE(view_->window_->layer()->GetFallbackSurfaceId()->is_valid());
-
- // Call TakeFallbackContentFrom(). The second view should now have the same
- // fallback as the first view.
+ // Call TakeFallbackContentFrom(). The second view should obtain a fallback
+ // from the first view.
view2->TakeFallbackContentFrom(view_);
- EXPECT_EQ(*view_->window_->layer()->GetFallbackSurfaceId(),
+ EXPECT_EQ(view_->window_->layer()->GetPrimarySurfaceId()->ToSmallestId(),
*view2->window_->layer()->GetFallbackSurfaceId());
DestroyView(view2);
@@ -6430,7 +6378,7 @@ TEST_F(InputMethodResultAuraTest, ChangeTextDirectionAndLayoutAlignment) {
ActivateViewForTextInputManager(views_[index], ui::TEXT_INPUT_TYPE_TEXT);
EXPECT_TRUE(!!RunAndReturnIPCSent(ime_finish_session_call,
processes_[index],
- ViewMsg_SetTextDirection::ID));
+ WidgetMsg_SetTextDirection::ID));
}
}
@@ -6465,7 +6413,7 @@ class InputMethodStateAuraTest : public InputMethodAuraTestBase {
// This test is for caret bounds which are calculated based on the tracked value
// for selection bounds.
TEST_F(InputMethodStateAuraTest, GetCaretBounds) {
- ViewHostMsg_SelectionBounds_Params params;
+ WidgetHostMsg_SelectionBounds_Params params;
params.is_anchor_first = true;
params.anchor_dir = blink::kWebTextDirectionLeftToRight;
params.focus_dir = blink::kWebTextDirectionLeftToRight;
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 fae4c74c977..e155153ec1e 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
@@ -16,6 +16,7 @@
#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/delegated_frame_host.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"
@@ -45,16 +46,8 @@
namespace content {
RenderWidgetHostViewBase::RenderWidgetHostViewBase(RenderWidgetHost* host)
- : host_(RenderWidgetHostImpl::From(host)),
- is_fullscreen_(false),
- popup_type_(blink::kWebPopupTypeNone),
- current_device_scale_factor_(0),
- current_display_rotation_(display::Display::ROTATE_0),
- text_input_manager_(nullptr),
- web_contents_accessibility_(nullptr),
- is_currently_scrolling_viewport_(false),
- use_viz_hit_test_(features::IsVizHitTestingEnabled()),
- renderer_frame_number_(0),
+ : use_viz_hit_test_(features::IsVizHitTestingEnabled()),
+ host_(RenderWidgetHostImpl::From(host)),
weak_factory_(this) {
host_->render_frame_metadata_provider()->AddObserver(this);
}
@@ -132,7 +125,7 @@ gfx::Size RenderWidgetHostViewBase::GetCompositorViewportPixelSize() const {
GetDeviceScaleFactor());
}
-bool RenderWidgetHostViewBase::DoBrowserControlsShrinkBlinkSize() const {
+bool RenderWidgetHostViewBase::DoBrowserControlsShrinkRendererSize() const {
return false;
}
@@ -141,7 +134,7 @@ float RenderWidgetHostViewBase::GetTopControlsHeight() const {
}
void RenderWidgetHostViewBase::SelectionBoundsChanged(
- const ViewHostMsg_SelectionBounds_Params& params) {
+ const WidgetHostMsg_SelectionBounds_Params& params) {
#if !defined(OS_ANDROID)
if (GetTextInputManager())
GetTextInputManager()->SelectionBoundsChanged(this, params);
@@ -203,6 +196,87 @@ bool RenderWidgetHostViewBase::IsSurfaceAvailableForCopy() const {
return false;
}
+void RenderWidgetHostViewBase::CopyMainAndPopupFromSurface(
+ base::WeakPtr<RenderWidgetHostImpl> main_host,
+ base::WeakPtr<DelegatedFrameHost> main_frame_host,
+ base::WeakPtr<RenderWidgetHostImpl> popup_host,
+ base::WeakPtr<DelegatedFrameHost> popup_frame_host,
+ const gfx::Rect& src_subrect,
+ const gfx::Size& dst_size,
+ float scale_factor,
+ base::OnceCallback<void(const SkBitmap&)> callback) {
+ if (!main_host || !main_frame_host)
+ return;
+
+#if defined(OS_ANDROID)
+ NOTREACHED()
+ << "RenderWidgetHostViewAndroid::CopyFromSurface calls "
+ "DelegatedFrameHostAndroid::CopyFromCompositingSurface directly, "
+ "and popups are not supported.";
+ return;
+#else
+ if (!popup_host || !popup_frame_host) {
+ // No popup - just call CopyFromCompositingSurface once.
+ main_frame_host->CopyFromCompositingSurface(src_subrect, dst_size,
+ std::move(callback));
+ return;
+ }
+
+ // First locate the popup relative to the main page, in DIPs
+ const gfx::Point parent_location =
+ main_host->GetView()->GetBoundsInRootWindow().origin();
+ const gfx::Point popup_location =
+ popup_host->GetView()->GetBoundsInRootWindow().origin();
+ const gfx::Point offset_dips =
+ PointAtOffsetFromOrigin(popup_location - parent_location);
+ const gfx::Vector2d offset_physical =
+ ScaleToFlooredPoint(offset_dips, scale_factor).OffsetFromOrigin();
+
+ // Queue up the request for the MAIN frame image first, but with a
+ // callback that launches a second request for the popup image.
+ // 1. Call CopyFromCompositingSurface for the main frame, with callback
+ // |main_image_done_callback|. Inside |main_image_done_callback|:
+ // a. Call CopyFromCompositingSurface again, this time on the popup
+ // frame. For this call, build a new callback, |popup_done_callback|,
+ // which:
+ // i. Takes the main image as a parameter, combines the main image with
+ // the just-acquired popup image, and then calls the original
+ // (outer) callback with the combined image.
+ auto main_image_done_callback = base::BindOnce(
+ [](base::OnceCallback<void(const SkBitmap&)> final_callback,
+ const gfx::Vector2d offset,
+ base::WeakPtr<DelegatedFrameHost> popup_frame_host,
+ const gfx::Rect src_subrect, const gfx::Size dst_size,
+ const SkBitmap& main_image) {
+ if (!popup_frame_host)
+ return;
+
+ // Build a new callback that actually combines images.
+ auto popup_done_callback = base::BindOnce(
+ [](base::OnceCallback<void(const SkBitmap&)> final_callback,
+ const gfx::Vector2d offset, const SkBitmap& main_image,
+ const SkBitmap& popup_image) {
+ // Draw popup_image into main_image.
+ SkCanvas canvas(main_image);
+ canvas.drawBitmap(popup_image, offset.x(), offset.y());
+ std::move(final_callback).Run(main_image);
+ },
+ std::move(final_callback), offset, std::move(main_image));
+
+ // Second, request the popup image.
+ gfx::Rect popup_subrect(src_subrect - offset);
+ popup_frame_host->CopyFromCompositingSurface(
+ popup_subrect, dst_size, std::move(popup_done_callback));
+ },
+ std::move(callback), offset_physical, popup_frame_host, src_subrect,
+ dst_size);
+
+ // Request the main image (happens first).
+ main_frame_host->CopyFromCompositingSurface(
+ src_subrect, dst_size, std::move(main_image_done_callback));
+#endif
+}
+
void RenderWidgetHostViewBase::CopyFromSurface(
const gfx::Rect& src_rect,
const gfx::Size& output_size,
@@ -361,12 +435,12 @@ bool RenderWidgetHostViewBase::HasFallbackSurface() const {
return false;
}
-void RenderWidgetHostViewBase::SetPopupType(blink::WebPopupType popup_type) {
- popup_type_ = popup_type;
+void RenderWidgetHostViewBase::SetWidgetType(WidgetType widget_type) {
+ widget_type_ = widget_type;
}
-blink::WebPopupType RenderWidgetHostViewBase::GetPopupType() {
- return popup_type_;
+WidgetType RenderWidgetHostViewBase::GetWidgetType() {
+ return widget_type_;
}
BrowserAccessibilityManager*
@@ -811,6 +885,8 @@ void RenderWidgetHostViewBase::DidNavigate() {
host()->SynchronizeVisualProperties();
}
+// TODO(wjmaclean): Would it simplify this function if we re-implemented it
+// using GetTransformToViewCoordSpace()?
bool RenderWidgetHostViewBase::TransformPointToTargetCoordSpace(
RenderWidgetHostViewBase* original_view,
RenderWidgetHostViewBase* target_view,
@@ -866,6 +942,64 @@ bool RenderWidgetHostViewBase::TransformPointToTargetCoordSpace(
return true;
}
+bool RenderWidgetHostViewBase::GetTransformToViewCoordSpace(
+ RenderWidgetHostViewBase* target_view,
+ gfx::Transform* transform) {
+ DCHECK(transform);
+ if (target_view == this) {
+ transform->MakeIdentity();
+ return true;
+ }
+
+ if (!use_viz_hit_test_)
+ return false;
+ viz::FrameSinkId root_frame_sink_id = 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();
+
+ gfx::Transform transform_this_to_root;
+ if (GetFrameSinkId() != root_frame_sink_id) {
+ gfx::Transform transform_root_to_this;
+ if (!query->GetTransformToTarget(GetFrameSinkId(), &transform_root_to_this))
+ return false;
+ if (!transform_root_to_this.GetInverse(&transform_this_to_root))
+ return false;
+ }
+ gfx::Transform transform_root_to_target;
+ if (!query->GetTransformToTarget(target_view->GetFrameSinkId(),
+ &transform_root_to_target)) {
+ return false;
+ }
+
+ // TODO(wjmaclean): In TransformPointToTargetCoordSpace the device scale
+ // factor is taken from the original view ... does that matter? Presumably
+ // all the views have the same dsf.
+ float device_scale_factor = GetDeviceScaleFactor();
+ gfx::Transform transform_to_pixel;
+ transform_to_pixel.Scale(device_scale_factor, device_scale_factor);
+ gfx::Transform transform_from_pixel;
+ transform_from_pixel.Scale(1.f / device_scale_factor,
+ 1.f / device_scale_factor);
+
+ // Note: gfx::Transform includes optimizations to early-out for scale = 1 or
+ // concatenating an identity matrix, so we don't add those checks here.
+ transform->MakeIdentity();
+
+ transform->ConcatTransform(transform_to_pixel);
+ transform->ConcatTransform(transform_this_to_root);
+ transform->ConcatTransform(transform_root_to_target);
+ transform->ConcatTransform(transform_from_pixel);
+
+ return true;
+}
+
bool RenderWidgetHostViewBase::TransformPointToLocalCoordSpaceViz(
const gfx::PointF& point,
const viz::SurfaceId& original_surface,
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 08454f68a01..c48b0aa86d8 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
@@ -27,11 +27,11 @@
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/common/input_event_ack_state.h"
#include "content/public/common/screen_info.h"
+#include "content/public/common/widget_type.h"
#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/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"
#include "ui/accessibility/ax_tree_id_registry.h"
@@ -49,7 +49,7 @@
#include "services/ws/public/mojom/window_tree.mojom.h"
#endif
-struct ViewHostMsg_SelectionBounds_Params;
+struct WidgetHostMsg_SelectionBounds_Params;
namespace base {
class UnguessableToken;
@@ -88,6 +88,7 @@ class TextInputManager;
class TouchSelectionControllerClientManager;
class WebContentsAccessibility;
class WebCursor;
+class DelegatedFrameHost;
struct TextInputState;
// Basic implementation shared by concrete RenderWidgetHostView subclasses.
@@ -162,9 +163,19 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
void OnLocalSurfaceIdChanged(
const cc::RenderFrameMetadata& metadata) override;
- void SetPopupType(blink::WebPopupType popup_type);
+ static void CopyMainAndPopupFromSurface(
+ base::WeakPtr<RenderWidgetHostImpl> main_host,
+ base::WeakPtr<DelegatedFrameHost> main_frame_host,
+ base::WeakPtr<RenderWidgetHostImpl> popup_host,
+ base::WeakPtr<DelegatedFrameHost> popup_frame_host,
+ const gfx::Rect& src_subrect,
+ const gfx::Size& dst_size,
+ float scale_factor,
+ base::OnceCallback<void(const SkBitmap&)> callback);
- blink::WebPopupType GetPopupType();
+ void SetWidgetType(WidgetType widget_type);
+
+ WidgetType GetWidgetType();
// Return a value that is incremented each time the renderer swaps a new frame
// to the view.
@@ -218,9 +229,9 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
// The size of the view's backing surface in non-DPI-adjusted pixels.
virtual gfx::Size GetCompositorViewportPixelSize() const;
- // Whether or not Blink's viewport size should be shrunk by the height of the
- // URL-bar.
- virtual bool DoBrowserControlsShrinkBlinkSize() const;
+ // Whether or not the renderer's viewport size should be shrunk by the height
+ // of the URL-bar.
+ virtual bool DoBrowserControlsShrinkRendererSize() const;
// The height of the URL-bar browser controls.
virtual float GetTopControlsHeight() const;
@@ -269,7 +280,7 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
virtual gfx::Point AccessibilityOriginInScreen(const gfx::Rect& bounds);
virtual gfx::AcceleratedWidget AccessibilityGetAcceleratedWidget();
virtual gfx::NativeViewAccessible AccessibilityGetNativeViewAccessible();
- virtual void SetMainFrameAXTreeID(ui::AXTreeIDRegistry::AXTreeID id) {}
+ virtual void SetMainFrameAXTreeID(ui::AXTreeID id) {}
// Informs that the focused DOM node has changed.
virtual void FocusedNodeChanged(bool is_editable_node,
const gfx::Rect& node_bounds_in_screen) {}
@@ -391,6 +402,18 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
gfx::PointF* transformed_point,
viz::EventSource source = viz::EventSource::ANY);
+ // On success, returns true and modifies |*transform| to represent the
+ // transformation mapping a point in the coordinate space of this view
+ // into the coordinate space of the target view.
+ // On Failure, returns false, and leaves |*transform| unchanged.
+ // This function will fail if viz hit testing is not enabled, or if either
+ // this view or the target view has no current FrameSinkId. The latter may
+ // happen if either view is not currently visible in the viewport.
+ // This function is useful if there are multiple points to transform between
+ // the same two views. |target_view| must be non-null.
+ bool GetTransformToViewCoordSpace(RenderWidgetHostViewBase* target_view,
+ gfx::Transform* transform);
+
// TODO(kenrb, wjmaclean): This is a temporary subclass identifier for
// RenderWidgetHostViewGuests that is needed for special treatment during
// input event routing. It can be removed either when RWHVGuests properly
@@ -450,7 +473,7 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
// RenderWidget's window's origin. Focus and anchor bound are represented as
// gfx::Rect.
virtual void SelectionBoundsChanged(
- const ViewHostMsg_SelectionBounds_Params& params);
+ const WidgetHostMsg_SelectionBounds_Params& params);
// Updates the range of the marked text in an IME composition.
virtual void ImeCompositionRangeChanged(
@@ -613,16 +636,18 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
virtual bool HasFallbackSurface() const;
+ // Cached bool to test if the VizHitTesting feature is enabled.
+ const bool use_viz_hit_test_;
+
// The model object. Members will become private when
// RenderWidgetHostViewGuest is removed.
RenderWidgetHostImpl* host_;
// Is this a fullscreen view?
- bool is_fullscreen_;
+ bool is_fullscreen_ = false;
- // Whether this view is a popup and what kind of popup it is (select,
- // autofill...).
- blink::WebPopupType popup_type_;
+ // Whether this view is a frame or a popup.
+ WidgetType widget_type_ = WidgetType::kFrame;
// Indicates whether keyboard lock is active for this view.
bool keyboard_locked_ = false;
@@ -632,19 +657,20 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
bool is_scroll_offset_at_top_ = true;
// The scale factor of the display the renderer is currently on.
- float current_device_scale_factor_;
+ float current_device_scale_factor_ = 0;
// The color space of the display the renderer is currently on.
gfx::ColorSpace current_display_color_space_;
// The orientation of the display the renderer is currently on.
- display::Display::Rotation current_display_rotation_;
+ display::Display::Rotation current_display_rotation_ =
+ display::Display::ROTATE_0;
// A reference to current TextInputManager instance this RWHV is registered
// with. This is initially nullptr until the first time the view calls
// GetTextInputManager(). It also becomes nullptr when TextInputManager is
// destroyed before the RWHV is destroyed.
- TextInputManager* text_input_manager_;
+ TextInputManager* text_input_manager_ = nullptr;
// The background color used in the current renderer.
base::Optional<SkColor> content_background_color_;
@@ -653,11 +679,9 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
// |content_background_color|.
base::Optional<SkColor> default_background_color_;
- WebContentsAccessibility* web_contents_accessibility_;
-
- bool is_currently_scrolling_viewport_;
+ WebContentsAccessibility* web_contents_accessibility_ = nullptr;
- bool use_viz_hit_test_ = false;
+ bool is_currently_scrolling_viewport_ = false;
private:
void SynchronizeVisualProperties();
@@ -693,7 +717,7 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
gfx::Rect current_display_area_;
- uint32_t renderer_frame_number_;
+ uint32_t renderer_frame_number_ = 0;
base::ObserverList<RenderWidgetHostViewBaseObserver>::Unchecked observers_;
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 ef607a087cd..99d980ac4ca 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
@@ -36,7 +36,7 @@
#include "content/browser/renderer_host/render_widget_host_view_event_handler.h"
#include "content/browser/renderer_host/text_input_manager.h"
#include "content/common/text_input_state.h"
-#include "content/common/view_messages.h"
+#include "content/common/widget_messages.h"
#include "content/public/browser/guest_mode.h"
#include "content/public/browser/render_process_host.h"
#include "gpu/ipc/common/gpu_messages.h"
@@ -74,7 +74,7 @@ RenderWidgetHostViewChildFrame::RenderWidgetHostViewChildFrame(
enable_viz_(
base::FeatureList::IsEnabled(features::kVizDisplayCompositor)),
weak_factory_(this) {
- if (features::IsUsingWindowService()) {
+ if (features::IsMultiProcessMash()) {
// In Mus the RenderFrameProxy will eventually assign a viz::FrameSinkId
// until then set ours invalid, as operations using it will be disregarded.
frame_sink_id_ = viz::FrameSinkId();
@@ -93,7 +93,7 @@ RenderWidgetHostViewChildFrame::~RenderWidgetHostViewChildFrame() {
if (frame_connector_)
DetachFromTouchSelectionClientManagerIfNecessary();
- if (!features::IsUsingWindowService()) {
+ if (!features::IsMultiProcessMash()) {
ResetCompositorFrameSinkSupport();
if (GetHostFrameSinkManager())
GetHostFrameSinkManager()->InvalidateFrameSinkId(frame_sink_id_);
@@ -147,7 +147,7 @@ void RenderWidgetHostViewChildFrame::SetFrameConnectorDelegate(
if (parent_view) {
DCHECK(parent_view->GetFrameSinkId().is_valid() ||
- features::IsUsingWindowService());
+ features::IsMultiProcessMash());
SetParentFrameSinkId(parent_view->GetFrameSinkId());
}
@@ -168,7 +168,7 @@ void RenderWidgetHostViewChildFrame::SetFrameConnectorDelegate(
}
#if defined(USE_AURA)
- if (features::IsUsingWindowService()) {
+ if (features::IsMultiProcessMash()) {
frame_connector_->EmbedRendererWindowTreeClientInParent(
GetWindowTreeClientFromRenderer());
}
@@ -180,7 +180,7 @@ void RenderWidgetHostViewChildFrame::SetFrameConnectorDelegate(
#if defined(USE_AURA)
void RenderWidgetHostViewChildFrame::SetFrameSinkId(
const viz::FrameSinkId& frame_sink_id) {
- if (features::IsUsingWindowService())
+ if (features::IsMultiProcessMash())
frame_sink_id_ = frame_sink_id;
}
#endif // defined(USE_AURA)
@@ -189,7 +189,7 @@ bool RenderWidgetHostViewChildFrame::OnMessageReceived(
const IPC::Message& msg) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(RenderWidgetHostViewChildFrame, msg)
- IPC_MESSAGE_HANDLER(ViewHostMsg_IntrinsicSizingInfoChanged,
+ IPC_MESSAGE_HANDLER(WidgetHostMsg_IntrinsicSizingInfoChanged,
OnIntrinsicSizingInfoChanged)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
@@ -348,9 +348,12 @@ gfx::NativeView RenderWidgetHostViewChildFrame::GetNativeView() const {
// OOPIF-webview, we need to return the native view to be used by
// RenderWidgetHostViewGuest. Remove this once https://crbug.com/642826 is
// fixed.
- if (frame_connector_)
- return frame_connector_->GetParentRenderWidgetHostView()->GetNativeView();
- return nullptr;
+ if (!frame_connector_)
+ return nullptr;
+
+ RenderWidgetHostView* parent_view =
+ frame_connector_->GetParentRenderWidgetHostView();
+ return parent_view ? parent_view->GetNativeView() : nullptr;
}
gfx::NativeViewAccessible
@@ -481,7 +484,7 @@ void RenderWidgetHostViewChildFrame::UpdateViewportIntersection(
bool occluded_or_obscured) {
if (host()) {
host()->SetIntersectsViewport(!viewport_intersection.IsEmpty());
- host()->Send(new ViewMsg_SetViewportIntersection(
+ host()->Send(new WidgetMsg_SetViewportIntersection(
host()->GetRoutingID(), viewport_intersection, compositor_visible_rect,
occluded_or_obscured));
}
@@ -489,14 +492,14 @@ void RenderWidgetHostViewChildFrame::UpdateViewportIntersection(
void RenderWidgetHostViewChildFrame::SetIsInert() {
if (host() && frame_connector_) {
- host()->Send(new ViewMsg_SetIsInert(host()->GetRoutingID(),
- frame_connector_->IsInert()));
+ host()->Send(new WidgetMsg_SetIsInert(host()->GetRoutingID(),
+ frame_connector_->IsInert()));
}
}
void RenderWidgetHostViewChildFrame::UpdateInheritedEffectiveTouchAction() {
if (host_ && frame_connector_) {
- host_->Send(new ViewMsg_SetInheritedEffectiveTouchAction(
+ host_->Send(new WidgetMsg_SetInheritedEffectiveTouchAction(
host_->GetRoutingID(),
frame_connector_->InheritedEffectiveTouchAction()));
}
@@ -504,7 +507,7 @@ void RenderWidgetHostViewChildFrame::UpdateInheritedEffectiveTouchAction() {
void RenderWidgetHostViewChildFrame::UpdateRenderThrottlingStatus() {
if (host() && frame_connector_) {
- host()->Send(new ViewMsg_UpdateRenderThrottlingStatus(
+ host()->Send(new WidgetMsg_UpdateRenderThrottlingStatus(
host()->GetRoutingID(), frame_connector_->IsThrottled(),
frame_connector_->IsSubtreeThrottled()));
}
@@ -619,7 +622,7 @@ void RenderWidgetHostViewChildFrame::DidCreateNewRendererCompositorFrameSink(
void RenderWidgetHostViewChildFrame::SetParentFrameSinkId(
const viz::FrameSinkId& parent_frame_sink_id) {
if (parent_frame_sink_id_ == parent_frame_sink_id ||
- features::IsUsingWindowService())
+ features::IsMultiProcessMash())
return;
auto* host_frame_sink_manager = GetHostFrameSinkManager();
@@ -640,7 +643,7 @@ void RenderWidgetHostViewChildFrame::SetParentFrameSinkId(
}
void RenderWidgetHostViewChildFrame::SendSurfaceInfoToEmbedder() {
- if (features::IsUsingWindowService())
+ if (features::IsMultiProcessMash())
return;
if (!last_activated_surface_info_.is_valid())
return;
@@ -872,12 +875,6 @@ void RenderWidgetHostViewChildFrame::CopyFromSurface(
const gfx::Rect& src_subrect,
const gfx::Size& output_size,
base::OnceCallback<void(const SkBitmap&)> callback) {
- // TODO(crbug.com/812059): Need a "copy from surface" VIZ API.
- if (enable_viz_) {
- std::move(callback).Run(SkBitmap());
- return;
- }
-
if (!IsSurfaceAvailableForCopy()) {
// Defer submitting the copy request until after a frame is drawn, at which
// point we should be guaranteed that the surface is available.
@@ -1098,7 +1095,7 @@ RenderWidgetHostViewChildFrame::DidUpdateVisualProperties(
}
void RenderWidgetHostViewChildFrame::CreateCompositorFrameSinkSupport() {
- if (features::IsUsingWindowService() || enable_viz_)
+ if (features::IsMultiProcessMash() || enable_viz_)
return;
DCHECK(!support_);
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 96d0d44860b..650fb3130da 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
@@ -160,7 +160,7 @@ IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewChildFrameTest,
IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewChildFrameTest, ChildFrameSinkId) {
// Only when mus hosts viz do we expect a RenderFrameProxy to provide the
// FrameSinkId.
- if (!features::IsUsingWindowService())
+ if (!features::IsMultiProcessMash())
return;
GURL main_url(embedded_test_server()->GetURL("/site_per_process_main.html"));
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 4eff713dfc4..b9a41007d19 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
@@ -29,7 +29,7 @@
#include "content/browser/renderer_host/render_widget_host_delegate.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/common/frame_visual_properties.h"
-#include "content/common/view_messages.h"
+#include "content/common/widget_messages.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/test/mock_render_process_host.h"
#include "content/public/test/test_browser_context.h"
@@ -228,11 +228,11 @@ TEST_F(RenderWidgetHostViewChildFrameTest, ViewportIntersectionUpdated) {
const IPC::Message* intersection_update =
process->sink().GetUniqueMessageMatching(
- ViewMsg_SetViewportIntersection::ID);
+ WidgetMsg_SetViewportIntersection::ID);
ASSERT_TRUE(intersection_update);
std::tuple<gfx::Rect, gfx::Rect, bool> sent_rects;
- ViewMsg_SetViewportIntersection::Read(intersection_update, &sent_rects);
+ WidgetMsg_SetViewportIntersection::Read(intersection_update, &sent_rects);
EXPECT_EQ(intersection_rect, std::get<0>(sent_rects));
EXPECT_EQ(intersection_rect, std::get<1>(sent_rects));
}
@@ -298,10 +298,10 @@ TEST_F(RenderWidgetHostViewChildFrameTest, WasResizedOncePerChange) {
ASSERT_EQ(1u, process->sink().message_count());
const IPC::Message* resize_msg = process->sink().GetUniqueMessageMatching(
- ViewMsg_SynchronizeVisualProperties::ID);
+ WidgetMsg_SynchronizeVisualProperties::ID);
ASSERT_NE(nullptr, resize_msg);
- ViewMsg_SynchronizeVisualProperties::Param params;
- ViewMsg_SynchronizeVisualProperties::Read(resize_msg, &params);
+ WidgetMsg_SynchronizeVisualProperties::Param params;
+ WidgetMsg_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);
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 83af25a5814..fc0105d96d3 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
@@ -31,7 +31,7 @@ namespace mojom {
class RenderWidgetHostNSViewClient;
}
-class RenderWidgetHostNSViewLocalClient;
+class RenderWidgetHostNSViewClientHelper;
class RenderWidgetHostViewMac;
class RenderWidgetHostViewMacEditCommandHelper;
}
@@ -68,15 +68,13 @@ struct DidOverscrollParams;
// This includes events (where the extra translation is unnecessary or loses
// information) and access to accessibility structures (only present in the
// browser process).
- content::RenderWidgetHostNSViewLocalClient* localClient_;
+ content::RenderWidgetHostNSViewClientHelper* clientHelper_;
- // An implementation of the in-process interface that will translate and
- // forward messages through |client_|.
- std::unique_ptr<content::RenderWidgetHostNSViewLocalClient>
- forwardingLocalClient_;
-
- // Dummy client that is always valid (see above comments about client_).
+ // Dummy client and client helper that are always valid (see above comments
+ // about client_).
content::mojom::RenderWidgetHostNSViewClientPtr dummyClient_;
+ std::unique_ptr<content::RenderWidgetHostNSViewClientHelper>
+ dummyClientHelper_;
// This ivar is the cocoa delegate of the NSResponder.
base::scoped_nsobject<NSObject<RenderWidgetHostViewMacDelegate>>
@@ -251,7 +249,7 @@ struct DidOverscrollParams;
// Methods previously marked as private.
- (id)initWithClient:(content::mojom::RenderWidgetHostNSViewClient*)client
- withLocalClient:(content::RenderWidgetHostNSViewLocalClient*)localClient;
+ withClientHelper:(content::RenderWidgetHostNSViewClientHelper*)clientHelper;
- (void)setResponderDelegate:
(NSObject<RenderWidgetHostViewMacDelegate>*)delegate;
- (void)processedGestureScrollEvent:(const blink::WebGestureEvent&)event
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 92f940ef023..ee6cde8137b 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,6 +8,7 @@
#include <utility>
#include "base/debug/crash_logging.h"
+#import "base/mac/foundation_util.h"
#include "base/mac/mac_util.h"
#include "base/stl_util.h"
#include "base/strings/sys_string_conversions.h"
@@ -37,7 +38,7 @@ using content::EditCommand;
using content::InputEvent;
using content::NativeWebKeyboardEvent;
using content::mojom::RenderWidgetHostNSViewClient;
-using content::RenderWidgetHostNSViewLocalClient;
+using content::RenderWidgetHostNSViewClientHelper;
using content::RenderWidgetHostViewMacEditCommandHelper;
using content::WebGestureEventBuilder;
using content::WebMouseEventBuilder;
@@ -51,82 +52,6 @@ using blink::WebTouchEvent;
namespace {
-class ForwardingLocalClient : public RenderWidgetHostNSViewLocalClient {
- public:
- explicit ForwardingLocalClient(RenderWidgetHostNSViewClient* client)
- : client_(client) {}
-
- private:
- std::unique_ptr<InputEvent> TranslateEvent(
- const blink::WebInputEvent& web_event) {
- return std::make_unique<InputEvent>(web_event, ui::LatencyInfo());
- }
-
- // RenderWidgetHostNSViewLocalClient implementation.
- BrowserAccessibilityManager* GetRootBrowserAccessibilityManager() override {
- return nullptr;
- }
- void ForwardKeyboardEvent(const NativeWebKeyboardEvent& key_event,
- const ui::LatencyInfo& latency_info) override {
- const blink::WebKeyboardEvent* web_event =
- static_cast<const blink::WebKeyboardEvent*>(&key_event);
- std::unique_ptr<InputEvent> input_event =
- std::make_unique<InputEvent>(*web_event, latency_info);
- client_->ForwardKeyboardEvent(std::move(input_event),
- key_event.skip_in_browser);
- }
- void ForwardKeyboardEventWithCommands(
- const NativeWebKeyboardEvent& key_event,
- const ui::LatencyInfo& latency_info,
- const std::vector<EditCommand>& commands) override {
- const blink::WebKeyboardEvent* web_event =
- static_cast<const blink::WebKeyboardEvent*>(&key_event);
- std::unique_ptr<InputEvent> input_event =
- std::make_unique<InputEvent>(*web_event, latency_info);
- client_->ForwardKeyboardEventWithCommands(
- std::move(input_event), key_event.skip_in_browser, commands);
- }
- void RouteOrProcessMouseEvent(
- const blink::WebMouseEvent& web_event) override {
- client_->RouteOrProcessMouseEvent(TranslateEvent(web_event));
- }
- void RouteOrProcessTouchEvent(
- const blink::WebTouchEvent& web_event) override {
- client_->RouteOrProcessTouchEvent(TranslateEvent(web_event));
- }
- void RouteOrProcessWheelEvent(
- const blink::WebMouseWheelEvent& web_event) override {
- client_->RouteOrProcessWheelEvent(TranslateEvent(web_event));
- }
- void ForwardMouseEvent(const blink::WebMouseEvent& web_event) override {
- client_->ForwardMouseEvent(TranslateEvent(web_event));
- }
- void ForwardWheelEvent(const blink::WebMouseWheelEvent& web_event) override {
- client_->ForwardWheelEvent(TranslateEvent(web_event));
- }
- void GestureBegin(blink::WebGestureEvent begin_event,
- bool is_synthetically_injected) override {
- // The gesture type is not yet known, but assign a type to avoid
- // serialization asserts (the type will be stripped on the other side).
- begin_event.SetType(blink::WebInputEvent::kGestureScrollBegin);
- client_->GestureBegin(TranslateEvent(begin_event),
- is_synthetically_injected);
- }
- void GestureUpdate(blink::WebGestureEvent update_event) override {
- client_->GestureUpdate(TranslateEvent(update_event));
- }
- void GestureEnd(blink::WebGestureEvent end_event) override {
- client_->GestureEnd(TranslateEvent(end_event));
- }
- void SmartMagnify(const blink::WebGestureEvent& web_event) override {
- client_->SmartMagnify(TranslateEvent(web_event));
- }
-
- RenderWidgetHostNSViewClient* client_ = nullptr;
-
- DISALLOW_COPY_AND_ASSIGN(ForwardingLocalClient);
-};
-
// Whether a keyboard event has been reserved by OSX.
BOOL EventIsReservedBySystem(NSEvent* event) {
content::SystemHotkeyHelperMac* helper =
@@ -212,7 +137,7 @@ void ExtractUnderlines(NSAttributedString* string,
@synthesize textInputType = textInputType_;
- (id)initWithClient:(RenderWidgetHostNSViewClient*)client
- withLocalClient:(RenderWidgetHostNSViewLocalClient*)localClient {
+ withClientHelper:(RenderWidgetHostNSViewClientHelper*)clientHelper {
self = [super initWithFrame:NSZeroRect];
if (self) {
self.acceptsTouchEvents = YES;
@@ -220,12 +145,7 @@ void ExtractUnderlines(NSAttributedString* string,
editCommandHelper_->AddEditingSelectorsToClass([self class]);
client_ = client;
- if (localClient) {
- localClient_ = localClient;
- } else {
- forwardingLocalClient_ = std::make_unique<ForwardingLocalClient>(client_);
- localClient_ = forwardingLocalClient_.get();
- }
+ clientHelper_ = clientHelper;
canBeKeyView_ = YES;
isStylusEnteringProximity_ = false;
keyboardLockActive_ = false;
@@ -372,13 +292,14 @@ void ExtractUnderlines(NSAttributedString* string,
}
- (void)setClientDisconnected {
- // Set the client to be an abandoned message pipe, and set the localClient
+ // Set the client to be an abandoned message pipe, and set the clientHelper
// to forward messages to that client.
content::mojom::RenderWidgetHostNSViewClientRequest dummyClientRequest =
mojo::MakeRequest(&dummyClient_);
+ dummyClientHelper_ = RenderWidgetHostNSViewClientHelper::CreateForMojoClient(
+ dummyClient_.get());
client_ = dummyClient_.get();
- forwardingLocalClient_ = std::make_unique<ForwardingLocalClient>(client_);
- localClient_ = forwardingLocalClient_.get();
+ clientHelper_ = dummyClientHelper_.get();
// |responderDelegate_| may attempt to access the RenderWidgetHostViewMac
// through its internal pointers, so detach it here.
@@ -421,7 +342,7 @@ void ExtractUnderlines(NSAttributedString* string,
WebMouseEvent web_event = WebMouseEventBuilder::Build(event, self);
web_event.SetModifiers(web_event.GetModifiers() |
WebInputEvent::kRelativeMotionEvent);
- localClient_->ForwardMouseEvent(web_event);
+ clientHelper_->ForwardMouseEvent(web_event);
}
- (BOOL)shouldIgnoreMouseEvent:(NSEvent*)theEvent {
@@ -511,7 +432,7 @@ void ExtractUnderlines(NSAttributedString* string,
WebMouseEventBuilder::Build(theEvent, self, pointerType_);
exitEvent.SetType(WebInputEvent::kMouseLeave);
exitEvent.button = WebMouseEvent::Button::kNoButton;
- localClient_->ForwardMouseEvent(exitEvent);
+ clientHelper_->ForwardMouseEvent(exitEvent);
}
mouseEventWasIgnored_ = YES;
return;
@@ -524,7 +445,7 @@ void ExtractUnderlines(NSAttributedString* string,
WebMouseEventBuilder::Build(theEvent, self, pointerType_);
enterEvent.SetType(WebInputEvent::kMouseMove);
enterEvent.button = WebMouseEvent::Button::kNoButton;
- localClient_->RouteOrProcessMouseEvent(enterEvent);
+ clientHelper_->RouteOrProcessMouseEvent(enterEvent);
}
mouseEventWasIgnored_ = NO;
@@ -578,10 +499,10 @@ void ExtractUnderlines(NSAttributedString* string,
if (!send_touch) {
WebMouseEvent event =
WebMouseEventBuilder::Build(theEvent, self, pointerType_);
- localClient_->RouteOrProcessMouseEvent(event);
+ clientHelper_->RouteOrProcessMouseEvent(event);
} else {
WebTouchEvent event = WebTouchEventBuilder::Build(theEvent, self);
- localClient_->RouteOrProcessTouchEvent(event);
+ clientHelper_->RouteOrProcessTouchEvent(event);
}
}
@@ -728,7 +649,7 @@ void ExtractUnderlines(NSAttributedString* string,
// We only handle key down events and just simply forward other events.
if (eventType != NSKeyDown) {
- localClient_->ForwardKeyboardEvent(event, latency_info);
+ clientHelper_->ForwardKeyboardEvent(event, latency_info);
// Possibly autohide the cursor.
if (shouldAutohideCursor) {
@@ -786,7 +707,7 @@ void ExtractUnderlines(NSAttributedString* string,
NativeWebKeyboardEvent fakeEvent = event;
fakeEvent.windows_key_code = 0xE5; // VKEY_PROCESSKEY
fakeEvent.skip_in_browser = true;
- localClient_->ForwardKeyboardEvent(fakeEvent, latency_info);
+ clientHelper_->ForwardKeyboardEvent(fakeEvent, latency_info);
// If this key event was handled by the input method, but
// -doCommandBySelector: (invoked by the call to -interpretKeyEvents: above)
// enqueued edit commands, then in order to let webkit handle them
@@ -797,8 +718,8 @@ void ExtractUnderlines(NSAttributedString* string,
if (hasEditCommands_ && !hasMarkedText_)
delayEventUntilAfterImeCompostion = YES;
} else {
- localClient_->ForwardKeyboardEventWithCommands(event, latency_info,
- editCommands_);
+ clientHelper_->ForwardKeyboardEventWithCommands(event, latency_info,
+ editCommands_);
}
// Then send keypress and/or composition related events.
@@ -856,8 +777,8 @@ void ExtractUnderlines(NSAttributedString* string,
fakeEvent.skip_in_browser = true;
ui::LatencyInfo fake_event_latency_info = latency_info;
fake_event_latency_info.set_source_event_type(ui::SourceEventType::OTHER);
- localClient_->ForwardKeyboardEvent(fakeEvent, fake_event_latency_info);
- localClient_->ForwardKeyboardEventWithCommands(
+ clientHelper_->ForwardKeyboardEvent(fakeEvent, fake_event_latency_info);
+ clientHelper_->ForwardKeyboardEventWithCommands(
event, fake_event_latency_info, editCommands_);
}
@@ -871,7 +792,7 @@ void ExtractUnderlines(NSAttributedString* string,
event.text[0] = textToBeInserted_[0];
event.text[1] = 0;
event.skip_in_browser = true;
- localClient_->ForwardKeyboardEvent(event, latency_info);
+ clientHelper_->ForwardKeyboardEvent(event, latency_info);
} else if ((!textInserted || delayEventUntilAfterImeCompostion) &&
event.text[0] != '\0' &&
((modifierFlags & kCtrlCmdKeyMask) ||
@@ -881,7 +802,7 @@ void ExtractUnderlines(NSAttributedString* string,
// cases, unless the key event generated any other command.
event.SetType(blink::WebInputEvent::kChar);
event.skip_in_browser = true;
- localClient_->ForwardKeyboardEvent(event, latency_info);
+ clientHelper_->ForwardKeyboardEvent(event, latency_info);
}
}
@@ -912,7 +833,7 @@ void ExtractUnderlines(NSAttributedString* string,
// History-swiping is not possible if the logic reaches this point.
WebMouseWheelEvent webEvent = WebMouseWheelEventBuilder::Build(event, self);
webEvent.rails_mode = mouseWheelFilter_.UpdateRailsMode(webEvent);
- localClient_->ForwardWheelEvent(webEvent);
+ clientHelper_->ForwardWheelEvent(webEvent);
if (endWheelMonitor_) {
[NSEvent removeMonitor:endWheelMonitor_];
@@ -926,7 +847,7 @@ void ExtractUnderlines(NSAttributedString* string,
WebGestureEvent gestureBeginEvent(WebGestureEventBuilder::Build(event, self));
- localClient_->GestureBegin(gestureBeginEvent, isSyntheticallyInjected);
+ clientHelper_->GestureBegin(gestureBeginEvent, isSyntheticallyInjected);
}
- (void)handleEndGestureWithEvent:(NSEvent*)event {
@@ -942,7 +863,7 @@ void ExtractUnderlines(NSAttributedString* string,
endEvent.SetSourceDevice(
blink::WebGestureDevice::kWebGestureDeviceTouchpad);
endEvent.SetNeedsWheelEvent(true);
- localClient_->GestureEnd(endEvent);
+ clientHelper_->GestureEnd(endEvent);
}
}
@@ -997,7 +918,7 @@ void ExtractUnderlines(NSAttributedString* string,
- (void)smartMagnifyWithEvent:(NSEvent*)event {
const WebGestureEvent& smartMagnifyEvent =
WebGestureEventBuilder::Build(event, self);
- localClient_->SmartMagnify(smartMagnifyEvent);
+ clientHelper_->SmartMagnify(smartMagnifyEvent);
}
- (void)showLookUpDictionaryOverlayFromRange:(NSRange)range {
@@ -1079,7 +1000,7 @@ void ExtractUnderlines(NSAttributedString* string,
// This is responsible for content scrolling!
WebMouseWheelEvent webEvent = WebMouseWheelEventBuilder::Build(event, self);
webEvent.rails_mode = mouseWheelFilter_.UpdateRailsMode(webEvent);
- localClient_->RouteOrProcessWheelEvent(webEvent);
+ clientHelper_->RouteOrProcessWheelEvent(webEvent);
}
// Called repeatedly during a pinch gesture, with incremental change values.
@@ -1112,7 +1033,7 @@ void ExtractUnderlines(NSAttributedString* string,
}
WebGestureEvent updateEvent = WebGestureEventBuilder::Build(event, self);
- localClient_->GestureUpdate(updateEvent);
+ clientHelper_->GestureUpdate(updateEvent);
}
- (void)viewWillMoveToWindow:(NSWindow*)newWindow {
@@ -1360,7 +1281,7 @@ void ExtractUnderlines(NSAttributedString* string,
- (id)accessibilityAttributeValue:(NSString*)attribute {
BrowserAccessibilityManager* manager =
- localClient_->GetRootBrowserAccessibilityManager();
+ clientHelper_->GetRootBrowserAccessibilityManager();
// Contents specifies document view of RenderWidgetHostViewCocoa provided by
// BrowserAccessibilityManager. Children includes all subviews in addition to
@@ -1386,7 +1307,7 @@ void ExtractUnderlines(NSAttributedString* string,
- (id)accessibilityHitTest:(NSPoint)point {
BrowserAccessibilityManager* manager =
- localClient_->GetRootBrowserAccessibilityManager();
+ clientHelper_->GetRootBrowserAccessibilityManager();
if (!manager)
return self;
NSPoint pointInWindow =
@@ -1401,13 +1322,13 @@ void ExtractUnderlines(NSAttributedString* string,
- (BOOL)accessibilityIsIgnored {
BrowserAccessibilityManager* manager =
- localClient_->GetRootBrowserAccessibilityManager();
+ clientHelper_->GetRootBrowserAccessibilityManager();
return !manager;
}
- (NSUInteger)accessibilityGetIndexOf:(id)child {
BrowserAccessibilityManager* manager =
- localClient_->GetRootBrowserAccessibilityManager();
+ clientHelper_->GetRootBrowserAccessibilityManager();
// Only child is root.
if (manager && ToBrowserAccessibilityCocoa(manager->GetRoot()) == child) {
return 0;
@@ -1428,7 +1349,7 @@ void ExtractUnderlines(NSAttributedString* string,
return popup_focus_override;
BrowserAccessibilityManager* manager =
- localClient_->GetRootBrowserAccessibilityManager();
+ clientHelper_->GetRootBrowserAccessibilityManager();
if (manager) {
BrowserAccessibility* focused_item = manager->GetFocus();
DCHECK(focused_item);
@@ -1790,7 +1711,7 @@ extern NSString* NSTextInputReplacementRangeAttributeName;
WebMouseEvent event(WebInputEvent::kMouseUp, WebInputEvent::kNoModifiers,
ui::EventTimeForNow());
event.button = WebMouseEvent::Button::kLeft;
- localClient_->ForwardMouseEvent(event);
+ clientHelper_->ForwardMouseEvent(event);
hasOpenMouseDown_ = NO;
}
}
@@ -1926,29 +1847,36 @@ extern NSString* NSTextInputReplacementRangeAttributeName;
//
// Supporting application services
//
+
+@interface RenderWidgetHostViewCocoa (
+ NSServicesRequests)<NSServicesMenuRequestor>
+@end
+
@implementation RenderWidgetHostViewCocoa (NSServicesRequests)
- (BOOL)writeSelectionToPasteboard:(NSPasteboard*)pboard types:(NSArray*)types {
- if (textSelectionRange_.is_empty() ||
- ![types containsObject:NSStringPboardType]) {
+ // NB: The NSServicesMenuRequestor protocol has not (as of 10.14) been
+ // upgraded to request UTIs rather than obsolete PboardType constants. Handle
+ // either for when it is upgraded.
+ DCHECK([types containsObject:NSStringPboardType] ||
+ [types containsObject:base::mac::CFToNSCast(kUTTypeUTF8PlainText)]);
+ if (textSelectionRange_.is_empty())
return NO;
- }
NSString* text = base::SysUTF16ToNSString([self selectedText]);
- NSArray* toDeclare = [NSArray arrayWithObject:NSStringPboardType];
- [pboard declareTypes:toDeclare owner:nil];
- return [pboard setString:text forType:NSStringPboardType];
+ return [pboard writeObjects:@[ text ]];
}
- (BOOL)readSelectionFromPasteboard:(NSPasteboard*)pboard {
- NSString* string = [pboard stringForType:NSStringPboardType];
- if (!string)
+ NSArray* objects =
+ [pboard readObjectsForClasses:@[ [NSString class] ] options:0];
+ if (![objects count])
return NO;
// If the user is currently using an IME, confirm the IME input,
// and then insert the text from the service, the same as TextEdit and Safari.
[self finishComposingText];
- [self insertText:string];
+ [self insertText:[objects lastObject]];
return YES;
}
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 940d9c10766..caea824f874 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
@@ -4,8 +4,11 @@
#include "content/browser/renderer_host/render_widget_host_view_event_handler.h"
+#include "base/command_line.h"
#include "base/metrics/user_metrics.h"
#include "base/metrics/user_metrics_action.h"
+#include "components/viz/common/features.h"
+#include "content/browser/renderer_host/hit_test_debug_key_event_observer.h"
#include "content/browser/renderer_host/input/touch_selection_controller_client_aura.h"
#include "content/browser/renderer_host/overscroll_controller.h"
#include "content/browser/renderer_host/render_view_host_delegate.h"
@@ -20,7 +23,6 @@
#include "content/public/common/content_features.h"
#include "ui/aura/client/cursor_client.h"
#include "ui/aura/client/focus_client.h"
-#include "ui/aura/client/screen_position_client.h"
#include "ui/aura/scoped_keyboard_hook.h"
#include "ui/aura/window.h"
#include "ui/aura/window_delegate.h"
@@ -65,19 +67,6 @@ BOOL CALLBACK DismissOwnedPopups(HWND window, LPARAM arg) {
}
#endif // defined(OS_WIN)
-gfx::PointF GetScreenLocationFromEvent(const ui::LocatedEvent& event) {
- aura::Window* root =
- static_cast<aura::Window*>(event.target())->GetRootWindow();
- aura::client::ScreenPositionClient* spc =
- aura::client::GetScreenPositionClient(root);
- if (!spc)
- return event.root_location_f();
-
- gfx::PointF screen_location(event.root_location_f());
- spc->ConvertPointToScreen(root, &screen_location);
- return screen_location;
-}
-
bool IsFractionalScaleFactor(float scale_factor) {
return (scale_factor - static_cast<int>(scale_factor)) > 0;
}
@@ -112,7 +101,16 @@ void MarkUnchangedTouchPointsAsStationary(blink::WebTouchEvent* event,
bool NeedsInputGrab(content::RenderWidgetHostViewBase* view) {
if (!view)
return false;
- return view->GetPopupType() == blink::kWebPopupTypePage;
+ return view->GetWidgetType() == content::WidgetType::kPopup;
+}
+
+// Enables hit-test debug logging.
+const char kEnableVizHitTestDebug[] = "enable-viz-hit-test-debug";
+
+inline bool IsVizHitTestingDebugEnabled() {
+ return features::IsVizHitTestingEnabled() &&
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
+ kEnableVizHitTestDebug);
}
} // namespace
@@ -142,7 +140,10 @@ RenderWidgetHostViewEventHandler::RenderWidgetHostViewEventHandler(
popup_child_event_handler_(nullptr),
delegate_(delegate),
window_(nullptr),
- mouse_wheel_phase_handler_(host_view) {}
+ mouse_wheel_phase_handler_(host_view),
+ debug_observer_(IsVizHitTestingDebugEnabled()
+ ? std::make_unique<HitTestDebugKeyEventObserver>(host)
+ : nullptr) {}
RenderWidgetHostViewEventHandler::~RenderWidgetHostViewEventHandler() {}
@@ -363,8 +364,7 @@ void RenderWidgetHostViewEventHandler::OnMouseEvent(ui::MouseEvent* event) {
}
#endif
blink::WebMouseWheelEvent mouse_wheel_event =
- ui::MakeWebMouseWheelEvent(static_cast<ui::MouseWheelEvent&>(*event),
- base::Bind(&GetScreenLocationFromEvent));
+ ui::MakeWebMouseWheelEvent(*event->AsMouseWheelEvent());
if (mouse_wheel_event.delta_x != 0 || mouse_wheel_event.delta_y != 0) {
bool should_route_event = ShouldRouteEvent(event);
@@ -390,8 +390,7 @@ void RenderWidgetHostViewEventHandler::OnMouseEvent(ui::MouseEvent* event) {
if (event->type() == ui::ET_MOUSE_PRESSED)
FinishImeCompositionSession();
- blink::WebMouseEvent mouse_event = ui::MakeWebMouseEvent(
- *event, base::Bind(&GetScreenLocationFromEvent));
+ blink::WebMouseEvent mouse_event = ui::MakeWebMouseEvent(*event);
ModifyEventMovementAndCoords(*event, &mouse_event);
if (ShouldRouteEvent(event)) {
host_->delegate()->GetInputEventRouter()->RouteMouseEvent(
@@ -433,8 +432,8 @@ void RenderWidgetHostViewEventHandler::OnScrollEvent(ui::ScrollEvent* event) {
if (event->finger_count() != 2)
return;
#endif
- blink::WebMouseWheelEvent mouse_wheel_event = ui::MakeWebMouseWheelEvent(
- *event, base::Bind(&GetScreenLocationFromEvent));
+ blink::WebMouseWheelEvent mouse_wheel_event =
+ ui::MakeWebMouseWheelEvent(*event);
mouse_wheel_phase_handler_.AddPhaseIfNeededAndScheduleEndEvent(
mouse_wheel_event, should_route_event);
@@ -461,8 +460,7 @@ void RenderWidgetHostViewEventHandler::OnScrollEvent(ui::ScrollEvent* event) {
}
} else if (event->type() == ui::ET_SCROLL_FLING_START ||
event->type() == ui::ET_SCROLL_FLING_CANCEL) {
- blink::WebGestureEvent gesture_event = ui::MakeWebGestureEvent(
- *event, base::Bind(&GetScreenLocationFromEvent));
+ blink::WebGestureEvent gesture_event = ui::MakeWebGestureEvent(*event);
if (should_route_event) {
host_->delegate()->GetInputEventRouter()->RouteGestureEvent(
host_view_, &gesture_event,
@@ -552,8 +550,7 @@ void RenderWidgetHostViewEventHandler::OnGestureEvent(ui::GestureEvent* event) {
if (event->type() == ui::ET_GESTURE_TAP)
FinishImeCompositionSession();
- blink::WebGestureEvent gesture =
- ui::MakeWebGestureEvent(*event, base::Bind(&GetScreenLocationFromEvent));
+ blink::WebGestureEvent gesture = ui::MakeWebGestureEvent(*event);
if (event->type() == ui::ET_GESTURE_TAP_DOWN) {
// Webkit does not stop a fling-scroll on tap-down. So explicitly send an
// event to stop any in-progress flings.
@@ -741,8 +738,7 @@ void RenderWidgetHostViewEventHandler::HandleMouseEventWhileLocked(
if (event->type() == ui::ET_MOUSEWHEEL) {
blink::WebMouseWheelEvent mouse_wheel_event =
- ui::MakeWebMouseWheelEvent(static_cast<ui::MouseWheelEvent&>(*event),
- base::Bind(&GetScreenLocationFromEvent));
+ ui::MakeWebMouseWheelEvent(*event->AsMouseWheelEvent());
if (mouse_wheel_event.delta_x != 0 || mouse_wheel_event.delta_y != 0) {
if (ShouldRouteEvent(event)) {
host_->delegate()->GetInputEventRouter()->RouteMouseWheelEvent(
@@ -764,8 +760,7 @@ void RenderWidgetHostViewEventHandler::HandleMouseEventWhileLocked(
return;
}
- blink::WebMouseEvent mouse_event =
- ui::MakeWebMouseEvent(*event, base::Bind(&GetScreenLocationFromEvent));
+ blink::WebMouseEvent mouse_event = ui::MakeWebMouseEvent(*event);
bool is_move_to_center_event =
(event->type() == ui::ET_MOUSE_MOVED ||
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 5db1ce0507a..8b28ee3030a 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
@@ -42,6 +42,7 @@ class OverscrollController;
class RenderWidgetHostImpl;
class RenderWidgetHostViewBase;
class TouchSelectionControllerClientAura;
+class HitTestDebugKeyEventObserver;
// Provides an implementation of ui::EventHandler for use with
// RenderWidgetHostViewBase. A delegate is required in order to provide platform
@@ -290,6 +291,8 @@ class CONTENT_EXPORT RenderWidgetHostViewEventHandler
aura::Window* window_;
MouseWheelPhaseHandler mouse_wheel_phase_handler_;
+ std::unique_ptr<HitTestDebugKeyEventObserver> debug_observer_;
+
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewEventHandler);
};
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 e25f39d32e7..bae1f369841 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
@@ -17,12 +17,13 @@
#include "components/viz/common/surfaces/surface_id.h"
#include "content/browser/renderer_host/browser_compositor_view_mac.h"
#include "content/browser/renderer_host/input/mouse_wheel_phase_handler.h"
-#include "content/browser/renderer_host/render_widget_host_ns_view_client.h"
+#include "content/browser/renderer_host/render_widget_host_ns_view_client_helper.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "content/browser/renderer_host/text_input_manager.h"
#include "content/common/content_export.h"
#include "content/common/render_widget_host_ns_view.mojom.h"
#include "ipc/ipc_sender.h"
+#include "mojo/public/cpp/bindings/associated_binding.h"
#include "ui/accelerated_widget_mac/accelerated_widget_mac.h"
#include "ui/accelerated_widget_mac/ca_transaction_observer.h"
#include "ui/accelerated_widget_mac/display_link_mac.h"
@@ -41,6 +42,7 @@ class ScopedPasswordInputEnabler;
namespace content {
class CursorManager;
+class NSViewBridgeFactoryHost;
class RenderWidgetHost;
class RenderWidgetHostNSViewBridgeLocal;
class RenderWidgetHostViewMac;
@@ -65,7 +67,7 @@ class WebCursor;
// RenderWidgetHostView class hierarchy described in render_widget_host_view.h.
class CONTENT_EXPORT RenderWidgetHostViewMac
: public RenderWidgetHostViewBase,
- public RenderWidgetHostNSViewLocalClient,
+ public RenderWidgetHostNSViewClientHelper,
public mojom::RenderWidgetHostNSViewClient,
public BrowserCompositorMacClient,
public TextInputManager::Observer,
@@ -91,7 +93,6 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
// |delegate| should be set at most once.
CONTENT_EXPORT void SetDelegate(
NSObject<RenderWidgetHostViewMacDelegate>* delegate);
- void SetAllowPauseForResizeOrRepaint(bool allow);
// RenderWidgetHostView implementation.
void InitAsChild(gfx::NativeView parent_view) override;
@@ -300,7 +301,7 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
// RenderWidgetHostImpl as well.
void UpdateNSViewAndDisplayProperties();
- // RenderWidgetHostNSViewLocalClient implementation.
+ // RenderWidgetHostNSViewClientHelper implementation.
BrowserAccessibilityManager* GetRootBrowserAccessibilityManager() override;
void ForwardKeyboardEvent(const NativeWebKeyboardEvent& key_event,
const ui::LatencyInfo& latency_info) override;
@@ -447,6 +448,12 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
// https://crbug.com/831843
RenderWidgetHostImpl* GetWidgetForKeyboardEvent();
+ // Migrate the NSView for this RenderWidgetHostView to be in the process
+ // hosted by |bridge_factory_host|, and make it a child view of the NSView
+ // referred to by |parent_ns_view_id|.
+ void MigrateNSViewBridge(NSViewBridgeFactoryHost* bridge_factory_host,
+ uint64_t parent_ns_view_id);
+
protected:
// This class is to be deleted through the Destroy method.
~RenderWidgetHostViewMac() override;
@@ -507,6 +514,13 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
// not work when the RenderWidgetHostViewCocoa is hosted in an app process.
std::unique_ptr<RenderWidgetHostNSViewBridgeLocal> ns_view_bridge_local_;
+ // If the NSView is hosted in a remote process and accessed via mojo then
+ // - |ns_view_bridge_| will point to |ns_view_bridge_remote_|
+ // - |ns_view_client_binding_| is the binding provided to the bridge.
+ mojom::RenderWidgetHostNSViewBridgeAssociatedPtr ns_view_bridge_remote_;
+ mojo::AssociatedBinding<mojom::RenderWidgetHostNSViewClient>
+ ns_view_client_binding_;
+
// State tracked by Show/Hide/IsShowing.
bool is_visible_ = false;
@@ -535,6 +549,12 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
// RenderWidgetHostViewGuest.
bool is_guest_view_hack_;
+ // Our parent host view, if this is a popup. NULL otherwise.
+ RenderWidgetHostViewMac* popup_parent_host_view_;
+
+ // Our child popup host. NULL if we do not have a child popup.
+ RenderWidgetHostViewMac* popup_child_host_view_;
+
// Display link for getting vsync info.
scoped_refptr<ui::DisplayLinkMac> display_link_;
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 7e3a9aa6adc..94d6e79377d 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
@@ -36,6 +36,7 @@
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_plugin_guest_manager.h"
#include "content/public/browser/native_web_keyboard_event.h"
+#include "content/public/browser/ns_view_bridge_factory_host.h"
#include "content/public/browser/render_widget_host.h"
#include "content/public/browser/web_contents.h"
#include "skia/ext/platform_canvas.h"
@@ -151,8 +152,11 @@ RenderWidgetHostViewMac::RenderWidgetHostViewMac(RenderWidgetHost* widget,
: RenderWidgetHostViewBase(widget),
page_at_minimum_scale_(true),
mouse_wheel_phase_handler_(this),
+ ns_view_client_binding_(this),
is_loading_(false),
is_guest_view_hack_(is_guest_view_hack),
+ popup_parent_host_view_(nullptr),
+ popup_child_host_view_(nullptr),
gesture_provider_(ui::GetGestureProviderConfig(
ui::GestureProviderConfigType::CURRENT_PLATFORM),
this),
@@ -211,13 +215,56 @@ RenderWidgetHostViewMac::RenderWidgetHostViewMac(RenderWidgetHost* widget,
// startup raciness and decrease latency.
needs_begin_frames_ = needs_begin_frames;
UpdateNeedsBeginFramesInternal();
- if (features::IsViewsBrowserCocoa())
- ui::CATransactionCoordinator::Get().AddPreCommitObserver(this);
}
RenderWidgetHostViewMac::~RenderWidgetHostViewMac() {
- if (features::IsViewsBrowserCocoa())
- ui::CATransactionCoordinator::Get().RemovePreCommitObserver(this);
+ if (popup_parent_host_view_) {
+ DCHECK(!popup_parent_host_view_->popup_child_host_view_ ||
+ popup_parent_host_view_->popup_child_host_view_ == this);
+ popup_parent_host_view_->popup_child_host_view_ = nullptr;
+ }
+ if (popup_child_host_view_) {
+ DCHECK(!popup_child_host_view_->popup_parent_host_view_ ||
+ popup_child_host_view_->popup_parent_host_view_ == this);
+ popup_child_host_view_->popup_parent_host_view_ = nullptr;
+ }
+}
+
+void RenderWidgetHostViewMac::MigrateNSViewBridge(
+ NSViewBridgeFactoryHost* bridge_factory_host,
+ uint64_t parent_ns_view_id) {
+ // Disconnect from the previous bridge (this will have the effect of
+ // destroying the associated bridge), and close the binding (to allow it
+ // to be re-bound). Note that |ns_view_bridge_local_| remains valid.
+ ns_view_client_binding_.Close();
+ ns_view_bridge_remote_.reset();
+
+ // If no host is specified, then use the locally hosted NSView.
+ if (!bridge_factory_host) {
+ ns_view_bridge_ = ns_view_bridge_local_.get();
+ return;
+ }
+
+ mojom::RenderWidgetHostNSViewClientAssociatedPtr client;
+ ns_view_client_binding_.Bind(mojo::MakeRequest(&client));
+ mojom::RenderWidgetHostNSViewBridgeAssociatedRequest bridge_request =
+ mojo::MakeRequest(&ns_view_bridge_remote_);
+
+ // Cast from mojom::RenderWidgetHostNSViewClientPtr and
+ // mojom::RenderWidgetHostNSViewBridgeRequest to the public interfaces
+ // accepted by the factory.
+ // TODO(ccameron): Remove the need for this cast.
+ // https://crbug.com/888290
+ mojo::AssociatedInterfacePtrInfo<mojom::StubInterface> stub_client(
+ client.PassInterface().PassHandle(), 0);
+ mojom::StubInterfaceAssociatedRequest stub_bridge_request(
+ bridge_request.PassHandle());
+
+ bridge_factory_host->GetFactory()->CreateRenderWidgetHostNSViewBridge(
+ std::move(stub_client), std::move(stub_bridge_request));
+
+ ns_view_bridge_ = ns_view_bridge_remote_.get();
+ ns_view_bridge_remote_->SetParentWebContentsNSView(parent_ns_view_id);
}
void RenderWidgetHostViewMac::SetParentUiLayer(ui::Layer* parent_ui_layer) {
@@ -246,11 +293,6 @@ void RenderWidgetHostViewMac::SetDelegate(
[cocoa_view() setResponderDelegate:delegate];
}
-void RenderWidgetHostViewMac::SetAllowPauseForResizeOrRepaint(bool allow) {
- // TODO: Remove SetAllowPauseForResizeOrRepaint and SetAllowOtherViews, since
- // they aren't used anymore.
-}
-
ui::TextInputType RenderWidgetHostViewMac::GetTextInputType() {
if (!GetActiveWidget())
return ui::TEXT_INPUT_TYPE_NONE;
@@ -279,13 +321,27 @@ RenderWidgetHostViewMac::GetTextSelection() {
void RenderWidgetHostViewMac::InitAsChild(
gfx::NativeView parent_view) {
+ DCHECK_EQ(widget_type_, WidgetType::kFrame);
}
void RenderWidgetHostViewMac::InitAsPopup(
RenderWidgetHostView* parent_host_view,
const gfx::Rect& pos) {
+ DCHECK_EQ(widget_type_, WidgetType::kPopup);
+
+ popup_parent_host_view_ =
+ static_cast<RenderWidgetHostViewMac*>(parent_host_view);
+
+ RenderWidgetHostViewMac* old_child =
+ popup_parent_host_view_->popup_child_host_view_;
+ if (old_child) {
+ DCHECK(old_child->popup_parent_host_view_ == popup_parent_host_view_);
+ old_child->popup_parent_host_view_ = nullptr;
+ }
+ popup_parent_host_view_->popup_child_host_view_ = this;
+
// This path is used by the time/date picker.
- ns_view_bridge_->InitAsPopup(pos, popup_type_);
+ ns_view_bridge_->InitAsPopup(pos);
}
void RenderWidgetHostViewMac::InitAsFullscreen(
@@ -333,9 +389,6 @@ void RenderWidgetHostViewMac::UpdateNSViewAndDisplayProperties() {
LOG(ERROR) << "Failed to create display link.";
}
- if (features::IsViewsBrowserCocoa())
- ui::CATransactionCoordinator::Get().Synchronize();
-
// During auto-resize it is the responsibility of the caller to ensure that
// the NSView and RenderWidgetHostImpl are kept in sync.
if (host()->auto_resize_enabled())
@@ -624,10 +677,12 @@ void RenderWidgetHostViewMac::Destroy() {
ns_view_bridge_->SetCursorLocked(false);
}
- // Destroy the brige to the NSView. Note that the NSView on the other side
- // of |ns_view_bridge_| may outlive us due to other retains.
+ // Destroy the local and remote briges to the NSView. Note that the NSView on
+ // the other side of |ns_view_bridge_| may outlive us due to other retains.
ns_view_bridge_ = nullptr;
ns_view_bridge_local_.reset();
+ ns_view_client_binding_.Close();
+ ns_view_bridge_remote_.reset();
// Delete the delegated frame state, which will reach back into
// host().
@@ -763,8 +818,19 @@ void RenderWidgetHostViewMac::CopyFromSurface(
const gfx::Rect& src_subrect,
const gfx::Size& dst_size,
base::OnceCallback<void(const SkBitmap&)> callback) {
- browser_compositor_->GetDelegatedFrameHost()->CopyFromCompositingSurface(
- src_subrect, dst_size, std::move(callback));
+ base::WeakPtr<RenderWidgetHostImpl> popup_host;
+ base::WeakPtr<DelegatedFrameHost> popup_frame_host;
+ if (popup_child_host_view_) {
+ popup_host = popup_child_host_view_->host()->GetWeakPtr();
+ popup_frame_host = popup_child_host_view_->BrowserCompositor()
+ ->GetDelegatedFrameHost()
+ ->GetWeakPtr();
+ }
+ RenderWidgetHostViewBase::CopyMainAndPopupFromSurface(
+ host()->GetWeakPtr(),
+ browser_compositor_->GetDelegatedFrameHost()->GetWeakPtr(), popup_host,
+ popup_frame_host, src_subrect, dst_size, display_.device_scale_factor(),
+ std::move(callback));
}
void RenderWidgetHostViewMac::EnsureSurfaceSynchronizedForLayoutTest() {
@@ -1222,8 +1288,6 @@ bool RenderWidgetHostViewMac::TransformPointToCoordSpaceForView(
return true;
}
- if (!HasFallbackSurface())
- return false;
return target_view->TransformPointToLocalCoordSpace(
point, GetCurrentSurfaceId(), transformed_point, source);
}
@@ -1344,7 +1408,7 @@ MouseWheelPhaseHandler* RenderWidgetHostViewMac::GetMouseWheelPhaseHandler() {
}
///////////////////////////////////////////////////////////////////////////////
-// RenderWidgetHostNSViewLocalClient and mojom::RenderWidgetHostNSViewClient
+// RenderWidgetHostNSViewClientHelper and mojom::RenderWidgetHostNSViewClient
// implementation:
BrowserAccessibilityManager*
@@ -1824,7 +1888,7 @@ void RenderWidgetHostViewMac::StopSpeaking() {
///////////////////////////////////////////////////////////////////////////////
// mojom::RenderWidgetHostNSViewClient functions that translate events and
-// forward them to the RenderWidgetHostNSViewLocalClient implementation:
+// forward them to the RenderWidgetHostNSViewClientHelper implementation:
void RenderWidgetHostViewMac::ForwardKeyboardEvent(
std::unique_ptr<InputEvent> input_event,
@@ -2000,10 +2064,7 @@ void RenderWidgetHostViewMac::OnGotStringForDictionaryOverlay(
if ([ns_selected_text length] == 0)
return;
scoped_refptr<ui::UniquePasteboard> pasteboard = new ui::UniquePasteboard;
- NSArray* types = [NSArray arrayWithObject:NSStringPboardType];
- [pasteboard->get() declareTypes:types owner:nil];
- if ([pasteboard->get() setString:ns_selected_text
- forType:NSStringPboardType]) {
+ if ([pasteboard->get() writeObjects:@[ ns_selected_text ]]) {
NSPerformService(@"Look Up in Dictionary", pasteboard->get());
}
}
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm b/chromium/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm
index 26c6b9e09d3..f27cb7c69cf 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm
@@ -9,7 +9,7 @@
#include <stdint.h>
#include "base/mac/scoped_nsautorelease_pool.h"
-#include "base/message_loop/message_loop.h"
+#include "base/test/scoped_task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/compositor/test/test_image_transport_factory.h"
#include "content/browser/gpu/compositor_util.h"
@@ -104,7 +104,7 @@ class RenderWidgetHostViewMacEditCommandHelperTest : public PlatformTest {
void TearDown() override { ImageTransportFactory::Terminate(); }
private:
- base::MessageLoop message_loop_;
+ base::test::ScopedTaskEnvironment task_environment_;
};
class RenderWidgetHostViewMacEditCommandHelperWithTaskEnvTest
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 8e31dddeb00..ed5984e8d1f 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
@@ -17,6 +17,7 @@
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/task/post_task.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/simple_test_tick_clock.h"
@@ -30,7 +31,8 @@
#include "content/browser/renderer_host/text_input_manager.h"
#include "content/common/input_messages.h"
#include "content/common/text_input_state.h"
-#include "content/common/view_messages.h"
+#include "content/common/widget_messages.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/render_widget_host_view_mac_delegate.h"
@@ -531,7 +533,7 @@ TEST_F(RenderWidgetHostViewMacTest, GetFirstRectForCharacterRangeCaretCase) {
gfx::Rect caret_rect(10, 11, 0, 10);
gfx::Range caret_range(0, 0);
- ViewHostMsg_SelectionBounds_Params params;
+ WidgetHostMsg_SelectionBounds_Params params;
gfx::Rect rect;
gfx::Range actual_range;
@@ -1132,8 +1134,8 @@ TEST_F(RenderWidgetHostViewMacTest, GuestViewDoesNotLeak) {
// Let |guest_rwhv_weak| have a chance to delete itself.
base::RunLoop run_loop;
- content::BrowserThread::PostTask(
- content::BrowserThread::UI, FROM_HERE, run_loop.QuitClosure());
+ base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI},
+ run_loop.QuitClosure());
run_loop.Run();
ASSERT_FALSE(guest_rwhv_weak.get());
@@ -1155,7 +1157,7 @@ TEST_F(RenderWidgetHostViewMacTest, Background) {
EXPECT_EQ(static_cast<unsigned>(SK_ColorRED),
*rwhv_mac_->GetBackgroundColor());
set_background = process_host_->sink().GetUniqueMessageMatching(
- ViewMsg_SetBackgroundOpaque::ID);
+ WidgetMsg_SetBackgroundOpaque::ID);
ASSERT_FALSE(set_background);
// Set the color to blue. This should not send an opacity message.
@@ -1163,7 +1165,7 @@ TEST_F(RenderWidgetHostViewMacTest, Background) {
EXPECT_EQ(static_cast<unsigned>(SK_ColorBLUE),
*rwhv_mac_->GetBackgroundColor());
set_background = process_host_->sink().GetUniqueMessageMatching(
- ViewMsg_SetBackgroundOpaque::ID);
+ WidgetMsg_SetBackgroundOpaque::ID);
ASSERT_FALSE(set_background);
// Set the color back to transparent. The background color should now be
@@ -1174,9 +1176,9 @@ TEST_F(RenderWidgetHostViewMacTest, Background) {
EXPECT_EQ(static_cast<unsigned>(SK_ColorWHITE),
*rwhv_mac_->GetBackgroundColor());
set_background = process_host_->sink().GetUniqueMessageMatching(
- ViewMsg_SetBackgroundOpaque::ID);
+ WidgetMsg_SetBackgroundOpaque::ID);
ASSERT_TRUE(set_background);
- ViewMsg_SetBackgroundOpaque::Read(set_background, &sent_background);
+ WidgetMsg_SetBackgroundOpaque::Read(set_background, &sent_background);
EXPECT_FALSE(std::get<0>(sent_background));
// Set the color to red. This should send an opacity message.
@@ -1185,9 +1187,9 @@ TEST_F(RenderWidgetHostViewMacTest, Background) {
EXPECT_EQ(static_cast<unsigned>(SK_ColorBLUE),
*rwhv_mac_->GetBackgroundColor());
set_background = process_host_->sink().GetUniqueMessageMatching(
- ViewMsg_SetBackgroundOpaque::ID);
+ WidgetMsg_SetBackgroundOpaque::ID);
ASSERT_TRUE(set_background);
- ViewMsg_SetBackgroundOpaque::Read(set_background, &sent_background);
+ WidgetMsg_SetBackgroundOpaque::Read(set_background, &sent_background);
EXPECT_TRUE(std::get<0>(sent_background));
}
diff --git a/chromium/content/browser/renderer_host/render_widget_targeter.cc b/chromium/content/browser/renderer_host/render_widget_targeter.cc
index eef715fc681..daa6078f311 100644
--- a/chromium/content/browser/renderer_host/render_widget_targeter.cc
+++ b/chromium/content/browser/renderer_host/render_widget_targeter.cc
@@ -6,6 +6,8 @@
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
+#include "base/rand_util.h"
+#include "components/viz/common/features.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"
@@ -59,7 +61,6 @@ class TracingUmaTracker {
}
~TracingUmaTracker() = default;
TracingUmaTracker(TracingUmaTracker&& tracker) = default;
- TracingUmaTracker& operator=(TracingUmaTracker&& tracker) = default;
void Stop() {
TRACE_EVENT_ASYNC_END0(
@@ -93,11 +94,13 @@ RenderWidgetTargetResult::RenderWidgetTargetResult(
RenderWidgetHostViewBase* in_view,
bool in_should_query_view,
base::Optional<gfx::PointF> in_location,
- bool in_latched_target)
+ bool in_latched_target,
+ bool in_should_verify_result)
: view(in_view),
should_query_view(in_should_query_view),
target_location(in_location),
- latched_target(in_latched_target) {}
+ latched_target(in_latched_target),
+ should_verify_result(in_should_verify_result) {}
RenderWidgetTargetResult::~RenderWidgetTargetResult() = default;
@@ -112,7 +115,9 @@ operator=(TargetingRequest&&) = default;
RenderWidgetTargeter::TargetingRequest::~TargetingRequest() = default;
RenderWidgetTargeter::RenderWidgetTargeter(Delegate* delegate)
- : delegate_(delegate), weak_ptr_factory_(this) {
+ : trace_id_(base::RandUint64()),
+ delegate_(delegate),
+ weak_ptr_factory_(this) {
DCHECK(delegate_);
}
@@ -150,21 +155,37 @@ void RenderWidgetTargeter::FindTargetAndDispatch(
RenderWidgetTargetResult result =
delegate_->FindTargetSynchronously(root_view, event);
+ const gfx::PointF event_location = ComputeEventLocation(event);
+
RenderWidgetHostViewBase* target = result.view;
auto* event_ptr = &event;
async_depth_ = 0;
if (result.should_query_view) {
+ TRACE_EVENT_WITH_FLOW2(
+ "viz,benchmark", "Event.Pipeline", TRACE_ID_GLOBAL(trace_id_),
+ TRACE_EVENT_FLAG_FLOW_OUT, "step", "QueryClient(Start)",
+ "event_location", event_location.ToString());
+
// TODO(kenrb, sadrul): When all event types support asynchronous hit
// testing, we should be able to have FindTargetSynchronously return the
// view and location to use for the renderer hit test query.
// Currently it has to return the surface hit test target, for event types
// that ignore |result.should_query_view|, and therefore we have to use
// root_view and the original event location for the initial query.
- QueryClient(root_view, root_view, *event_ptr, latency,
- ComputeEventLocation(event), nullptr, gfx::PointF());
+ // Do not compare hit test results if we are forced to do async hit testing
+ // by HitTestQuery.
+ QueryClient(root_view, root_view, *event_ptr, latency, event_location,
+ nullptr, gfx::PointF());
} else {
FoundTarget(root_view, target, *event_ptr, latency, result.target_location,
- result.latched_target);
+ result.latched_target, viz::FrameSinkId());
+ // Verify the event targeting results from surface layer viz hit testing if
+ // --use-viz-hit-test-surface-layer is enabled.
+ if (result.should_verify_result && !target->IsRenderWidgetHostViewGuest()) {
+ QueryAndVerifyClient(root_view, root_view, *event_ptr, latency,
+ event_location, nullptr, gfx::PointF(),
+ target->GetFrameSinkId());
+ }
}
}
@@ -172,66 +193,135 @@ void RenderWidgetTargeter::ViewWillBeDestroyed(RenderWidgetHostViewBase* view) {
unresponsive_views_.erase(view);
}
-void RenderWidgetTargeter::QueryClient(
+void RenderWidgetTargeter::QueryClientInternal(
RenderWidgetHostViewBase* root_view,
RenderWidgetHostViewBase* target,
const blink::WebInputEvent& event,
const ui::LatencyInfo& latency,
const gfx::PointF& target_location,
RenderWidgetHostViewBase* last_request_target,
- const gfx::PointF& last_target_location) {
- DCHECK(!request_in_flight_);
+ const gfx::PointF& last_target_location,
+ const viz::FrameSinkId& expected_frame_sink_id) {
+ // Async event targeting and verifying use two different queues, so they don't
+ // block each other.
+ bool is_verifying = expected_frame_sink_id.is_valid();
+ DCHECK((!is_verifying && !request_in_flight_) ||
+ (is_verifying && !verify_request_in_flight_));
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
+ // understand why this happens. https://crbug.com/859492.
+ // We do not verify hit testing result under this circumstance.
if (!target_client) {
- FoundTarget(root_view, target, event, latency, target_location, false);
+ FoundTarget(root_view, target, event, latency, target_location, false,
+ viz::FrameSinkId());
return;
}
- request_in_flight_ = true;
- async_depth_++;
+ if (is_verifying) {
+ verify_request_in_flight_ = true;
+ } else {
+ request_in_flight_ = true;
+ async_depth_++;
+ }
TracingUmaTracker tracker("Event.AsyncTargeting.ResponseTime",
"input,latency");
- async_hit_test_timeout_.reset(new OneShotTimeoutMonitor(
+ auto& hit_test_timeout =
+ is_verifying ? async_verify_hit_test_timeout_ : async_hit_test_timeout_;
+ 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),
+ last_target_location, ui::WebInputEventTraits::Clone(event), latency,
+ expected_frame_sink_id),
async_hit_test_timeout_delay_));
+
+ TRACE_EVENT_WITH_FLOW2(
+ "viz,benchmark", "Event.Pipeline", TRACE_ID_GLOBAL(trace_id_),
+ TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, "step",
+ "QueryClient", "event", blink::WebInputEvent::GetName(event.GetType()));
+
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)));
+ gfx::ToCeiledPoint(target_location), trace_id_,
+ base::BindOnce(
+ &RenderWidgetTargeter::FoundFrameSinkId,
+ weak_ptr_factory_.GetWeakPtr(), root_view->GetWeakPtr(),
+ target->GetWeakPtr(), ui::WebInputEventTraits::Clone(event), latency,
+ is_verifying ? ++last_verify_request_id_ : ++last_request_id_,
+ target_location, std::move(tracker), expected_frame_sink_id));
}
-void RenderWidgetTargeter::FlushEventQueue() {
+void RenderWidgetTargeter::QueryClient(
+ RenderWidgetHostViewBase* root_view,
+ RenderWidgetHostViewBase* target,
+ const blink::WebInputEvent& event,
+ const ui::LatencyInfo& latency,
+ const gfx::PointF& target_location,
+ RenderWidgetHostViewBase* last_request_target,
+ const gfx::PointF& last_target_location) {
+ QueryClientInternal(root_view, target, event, latency, target_location,
+ last_request_target, last_target_location,
+ viz::FrameSinkId());
+}
+
+void RenderWidgetTargeter::QueryAndVerifyClient(
+ RenderWidgetHostViewBase* root_view,
+ RenderWidgetHostViewBase* target,
+ const blink::WebInputEvent& event,
+ const ui::LatencyInfo& latency,
+ const gfx::PointF& target_location,
+ RenderWidgetHostViewBase* last_request_target,
+ const gfx::PointF& last_target_location,
+ const viz::FrameSinkId& expected_frame_sink_id) {
+ if (verify_request_in_flight_) {
+ TargetingRequest request;
+ request.root_view = root_view->GetWeakPtr();
+ request.event = ui::WebInputEventTraits::Clone(event);
+ request.latency = latency;
+ request.expected_frame_sink_id = expected_frame_sink_id;
+ verify_requests_.push(std::move(request));
+ return;
+ }
+ QueryClientInternal(root_view, target, event, latency, target_location,
+ last_request_target, last_target_location,
+ expected_frame_sink_id);
+}
+
+void RenderWidgetTargeter::FlushEventQueue(bool is_verifying) {
bool events_being_flushed = false;
- while (!request_in_flight_ && !requests_.empty()) {
- auto request = std::move(requests_.front());
- requests_.pop();
+ bool& request_in_flight =
+ is_verifying ? verify_request_in_flight_ : request_in_flight_;
+ auto* requests = is_verifying ? &verify_requests_ : &requests_;
+ while (!request_in_flight && !requests->empty()) {
+ auto request = std::move(requests->front());
+ requests->pop();
// The root-view has gone away. Ignore this event, and try to process the
// next event.
if (!request.root_view) {
continue;
}
- request.tracker->Stop();
+ if (request.tracker)
+ request.tracker->Stop();
// Only notify the delegate once that the current event queue is being
// flushed. Once all the events are flushed, notify the delegate again.
- if (!events_being_flushed) {
+ if (!is_verifying && !events_being_flushed) {
delegate_->SetEventsBeingFlushed(true);
events_being_flushed = true;
}
- FindTargetAndDispatch(request.root_view.get(), *request.event,
- request.latency);
+ if (is_verifying) {
+ QueryAndVerifyClient(request.root_view.get(), request.root_view.get(),
+ *request.event, request.latency,
+ ComputeEventLocation(*request.event), nullptr,
+ gfx::PointF(), request.expected_frame_sink_id);
+ } else {
+ FindTargetAndDispatch(request.root_view.get(), *request.event,
+ request.latency);
+ }
}
- delegate_->SetEventsBeingFlushed(false);
+ if (!is_verifying)
+ delegate_->SetEventsBeingFlushed(false);
}
void RenderWidgetTargeter::FoundFrameSinkId(
@@ -242,10 +332,15 @@ void RenderWidgetTargeter::FoundFrameSinkId(
uint32_t request_id,
const gfx::PointF& target_location,
TracingUmaTracker tracker,
+ const viz::FrameSinkId& expected_frame_sink_id,
const viz::FrameSinkId& frame_sink_id,
const gfx::PointF& transformed_location) {
tracker.Stop();
- if (request_id != last_request_id_ || !request_in_flight_) {
+ uint32_t last_id = expected_frame_sink_id.is_valid() ? last_verify_request_id_
+ : last_request_id_;
+ bool in_flight = expected_frame_sink_id.is_valid() ? verify_request_in_flight_
+ : request_in_flight_;
+ if (request_id != last_id || !in_flight) {
// This is a response to a request that already timed out, so the event
// should have already been dispatched. Mark the renderer as responsive
// and otherwise ignore this response.
@@ -253,8 +348,13 @@ void RenderWidgetTargeter::FoundFrameSinkId(
return;
}
- request_in_flight_ = false;
- async_hit_test_timeout_.reset(nullptr);
+ if (expected_frame_sink_id.is_valid()) {
+ verify_request_in_flight_ = false;
+ async_verify_hit_test_timeout_.reset(nullptr);
+ } else {
+ request_in_flight_ = false;
+ async_hit_test_timeout_.reset(nullptr);
+ }
auto* view = delegate_->FindViewFromFrameSinkId(frame_sink_id);
if (!view)
view = target.get();
@@ -263,10 +363,20 @@ 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, false);
+ // Reduced scope is required since FoundTarget can trigger another query
+ // which would end up linked to the current query.
+ {
+ TRACE_EVENT_WITH_FLOW1("viz,benchmark", "Event.Pipeline",
+ TRACE_ID_GLOBAL(trace_id_),
+ TRACE_EVENT_FLAG_FLOW_IN, "step", "FoundTarget");
+ }
+
+ FoundTarget(root_view.get(), view, *event, latency, target_location, false,
+ expected_frame_sink_id);
} else {
- QueryClient(root_view.get(), view, *event, latency, transformed_location,
- target.get(), target_location);
+ QueryClientInternal(root_view.get(), view, *event, latency,
+ transformed_location, target.get(), target_location,
+ expected_frame_sink_id);
}
}
@@ -276,19 +386,27 @@ void RenderWidgetTargeter::FoundTarget(
const blink::WebInputEvent& event,
const ui::LatencyInfo& latency,
const base::Optional<gfx::PointF>& target_location,
- bool latched_target) {
+ bool latched_target,
+ const viz::FrameSinkId& expected_frame_sink_id) {
if (SiteIsolationPolicy::UseDedicatedProcessesForAllSites() &&
- !latched_target) {
+ !latched_target && !expected_frame_sink_id.is_valid()) {
UMA_HISTOGRAM_COUNTS_100("Event.AsyncTargeting.AsyncClientDepth",
async_depth_);
}
+ if (features::IsVizHitTestingSurfaceLayerEnabled() &&
+ expected_frame_sink_id.is_valid()) {
+ UMA_HISTOGRAM_BOOLEAN("Event.VizHitTestSurfaceLayer.ResultsMatch",
+ target->GetFrameSinkId() == expected_frame_sink_id);
+ FlushEventQueue(true);
+ return;
+ }
// 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())
return;
delegate_->DispatchEventToTarget(root_view, target, event, latency,
target_location);
- FlushEventQueue();
+ FlushEventQueue(false);
}
void RenderWidgetTargeter::AsyncHitTestTimedOut(
@@ -298,9 +416,17 @@ void RenderWidgetTargeter::AsyncHitTestTimedOut(
base::WeakPtr<RenderWidgetHostViewBase> last_request_target,
const gfx::PointF& last_target_location,
ui::WebScopedInputEvent event,
- const ui::LatencyInfo& latency) {
- DCHECK(request_in_flight_);
- request_in_flight_ = false;
+ const ui::LatencyInfo& latency,
+ const viz::FrameSinkId& expected_frame_sink_id) {
+ DCHECK(request_in_flight_ || verify_request_in_flight_);
+ // If we time out during a verification, we early out to avoid dispatching
+ // event to root frame.
+ if (expected_frame_sink_id.is_valid()) {
+ verify_request_in_flight_ = false;
+ return;
+ } else {
+ request_in_flight_ = false;
+ }
if (!current_request_root_view)
return;
@@ -315,10 +441,11 @@ void RenderWidgetTargeter::AsyncHitTestTimedOut(
// renderer fails to process it.
FoundTarget(current_request_root_view.get(),
current_request_root_view.get(), *event, latency,
- current_target_location, false);
+ current_target_location, false, viz::FrameSinkId());
} else {
FoundTarget(current_request_root_view.get(), last_request_target.get(),
- *event, latency, last_target_location, false);
+ *event, latency, last_target_location, false,
+ viz::FrameSinkId());
}
}
diff --git a/chromium/content/browser/renderer_host/render_widget_targeter.h b/chromium/content/browser/renderer_host/render_widget_targeter.h
index 5e6dda1dbc3..8994fcfa873 100644
--- a/chromium/content/browser/renderer_host/render_widget_targeter.h
+++ b/chromium/content/browser/renderer_host/render_widget_targeter.h
@@ -11,6 +11,7 @@
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "base/time/time.h"
+#include "components/viz/common/surfaces/frame_sink_id.h"
#include "content/common/content_constants_internal.h"
#include "content/common/content_export.h"
#include "ui/events/blink/web_input_event_traits.h"
@@ -24,22 +25,22 @@ namespace gfx {
class PointF;
}
-namespace viz {
-class FrameSinkId;
-}
-
namespace content {
class RenderWidgetHostViewBase;
class OneShotTimeoutMonitor;
+// TODO(sunxd): Make |RenderWidgetTargetResult| a class. Merge the booleans into
+// a mask to reduce the size. Make the constructor take in enums for better
+// readability.
struct CONTENT_EXPORT RenderWidgetTargetResult {
RenderWidgetTargetResult();
RenderWidgetTargetResult(const RenderWidgetTargetResult&);
RenderWidgetTargetResult(RenderWidgetHostViewBase* view,
bool should_query_view,
base::Optional<gfx::PointF> location,
- bool latched_target);
+ bool latched_target,
+ bool should_verify_result);
~RenderWidgetTargetResult();
RenderWidgetHostViewBase* view = nullptr;
@@ -48,6 +49,11 @@ struct CONTENT_EXPORT RenderWidgetTargetResult {
// When |latched_target| is false, we explicitly hit-tested events instead of
// using a known target.
bool latched_target = false;
+ // When |should_verify_result| is true, RenderWidgetTargeter will do async hit
+ // testing and compare the target with the result of synchronous hit testing.
+ // |should_verify_result| will always be false if we are doing draw quad based
+ // hit testing.
+ bool should_verify_result = false;
};
class TracingUmaTracker;
@@ -99,7 +105,7 @@ class RenderWidgetTargeter {
private:
// Attempts to target and dispatch all events in the queue. It stops if it has
// to query a client, or if the queue becomes empty.
- void FlushEventQueue();
+ void FlushEventQueue(bool is_verifying);
// Queries |target| to find the correct target for |event|.
// |event| is in the coordinate space of |root_view|.
@@ -107,6 +113,22 @@ class RenderWidgetTargeter {
// |last_request_target| and |last_target_location| provide a fallback target
// the case that the query times out. These should be null values when
// querying the root view, and the target's immediate parent view otherwise.
+ // |expected_frame_sink_id| is temporarily added for v2 viz hit testing.
+ // V2 uses cc generated hit test data and we need to verify its correctness.
+ // The variable is the target frame sink id v2 finds in synchronous hit
+ // testing. It should be the same as the async hit testing target if v2 works
+ // correctly.
+ // TODO(sunxd): Remove |expected_frame_sink_id| after verifying synchronous
+ // hit testing correctness. See https://crbug.com/871996.
+ void QueryClientInternal(RenderWidgetHostViewBase* root_view,
+ RenderWidgetHostViewBase* target,
+ const blink::WebInputEvent& event,
+ const ui::LatencyInfo& latency,
+ const gfx::PointF& target_location,
+ RenderWidgetHostViewBase* last_request_target,
+ const gfx::PointF& last_target_location,
+ const viz::FrameSinkId& expected_frame_sink_id);
+
void QueryClient(RenderWidgetHostViewBase* root_view,
RenderWidgetHostViewBase* target,
const blink::WebInputEvent& event,
@@ -115,6 +137,15 @@ class RenderWidgetTargeter {
RenderWidgetHostViewBase* last_request_target,
const gfx::PointF& last_target_location);
+ void QueryAndVerifyClient(RenderWidgetHostViewBase* root_view,
+ RenderWidgetHostViewBase* target,
+ const blink::WebInputEvent& event,
+ const ui::LatencyInfo& latency,
+ const gfx::PointF& target_location,
+ RenderWidgetHostViewBase* last_request_target,
+ const gfx::PointF& last_target_location,
+ const viz::FrameSinkId& expected_frame_sink_id);
+
// |event| is in the coordinate space of |root_view|. |target_location|, if
// set, is the location in |target|'s coordinate space.
// |target| is the current target that will be queried using its
@@ -122,6 +153,8 @@ class RenderWidgetTargeter {
// |frame_sink_id| is returned from the InputTargetClient to indicate where
// the event should be routed, and |transformed_location| is the point in
// that new target's coordinate space.
+ // |expected_frame_sink_id| is the expected hit test result based on
+ // synchronous event targeting with cc generated data.
void FoundFrameSinkId(base::WeakPtr<RenderWidgetHostViewBase> root_view,
base::WeakPtr<RenderWidgetHostViewBase> target,
ui::WebScopedInputEvent event,
@@ -129,6 +162,7 @@ class RenderWidgetTargeter {
uint32_t request_id,
const gfx::PointF& target_location,
TracingUmaTracker tracker,
+ const viz::FrameSinkId& expected_frame_sink_id,
const viz::FrameSinkId& frame_sink_id,
const gfx::PointF& transformed_location);
@@ -141,7 +175,8 @@ class RenderWidgetTargeter {
const blink::WebInputEvent& event,
const ui::LatencyInfo& latency,
const base::Optional<gfx::PointF>& target_location,
- bool latched_target);
+ bool latched_target,
+ const viz::FrameSinkId& expected_frame_sink_id);
// Callback when the hit testing timer fires, to resume event processing
// without further waiting for a response to the last targeting request.
@@ -152,7 +187,8 @@ class RenderWidgetTargeter {
base::WeakPtr<RenderWidgetHostViewBase> last_request_target,
const gfx::PointF& last_target_location,
ui::WebScopedInputEvent event,
- const ui::LatencyInfo& latency);
+ const ui::LatencyInfo& latency,
+ const viz::FrameSinkId& expected_frame_sink_id);
base::TimeDelta async_hit_test_timeout_delay() {
return async_hit_test_timeout_delay_;
@@ -167,6 +203,7 @@ class RenderWidgetTargeter {
base::WeakPtr<RenderWidgetHostViewBase> root_view;
ui::WebScopedInputEvent event;
ui::LatencyInfo latency;
+ viz::FrameSinkId expected_frame_sink_id;
std::unique_ptr<TracingUmaTracker> tracker;
};
@@ -174,6 +211,13 @@ class RenderWidgetTargeter {
uint32_t last_request_id_ = 0;
std::queue<TargetingRequest> requests_;
+ // With viz-hit-testing-surface-layer being enabled, we do async hit testing
+ // for already dispatched events for verification. These verification requests
+ // should not block normal hit testing requests.
+ bool verify_request_in_flight_ = false;
+ uint32_t last_verify_request_id_ = 0;
+ std::queue<TargetingRequest> verify_requests_;
+
std::unordered_set<RenderWidgetHostViewBase*> unresponsive_views_;
// This value keeps track of the number of clients we have asked in order to
@@ -186,6 +230,9 @@ class RenderWidgetTargeter {
base::TimeDelta::FromMilliseconds(kAsyncHitTestTimeoutMs);
std::unique_ptr<OneShotTimeoutMonitor> async_hit_test_timeout_;
+ std::unique_ptr<OneShotTimeoutMonitor> async_verify_hit_test_timeout_;
+
+ uint64_t trace_id_;
Delegate* const delegate_;
base::WeakPtrFactory<RenderWidgetTargeter> weak_ptr_factory_;
diff --git a/chromium/content/browser/renderer_host/text_input_manager.cc b/chromium/content/browser/renderer_host/text_input_manager.cc
index ce3a5ff83cf..ea4a2725997 100644
--- a/chromium/content/browser/renderer_host/text_input_manager.cc
+++ b/chromium/content/browser/renderer_host/text_input_manager.cc
@@ -6,7 +6,7 @@
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
-#include "content/common/view_messages.h"
+#include "content/common/widget_messages.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/range/range.h"
@@ -152,7 +152,7 @@ void TextInputManager::ImeCancelComposition(RenderWidgetHostViewBase* view) {
void TextInputManager::SelectionBoundsChanged(
RenderWidgetHostViewBase* view,
- const ViewHostMsg_SelectionBounds_Params& params) {
+ const WidgetHostMsg_SelectionBounds_Params& params) {
DCHECK(IsRegistered(view));
// Converting the anchor point to root's coordinate space (for child frame
// views).
diff --git a/chromium/content/browser/renderer_host/text_input_manager.h b/chromium/content/browser/renderer_host/text_input_manager.h
index b715544c7a2..ff2aac26c4f 100644
--- a/chromium/content/browser/renderer_host/text_input_manager.h
+++ b/chromium/content/browser/renderer_host/text_input_manager.h
@@ -16,7 +16,7 @@
#include "ui/gfx/range/range.h"
#include "ui/gfx/selection_bound.h"
-struct ViewHostMsg_SelectionBounds_Params;
+struct WidgetHostMsg_SelectionBounds_Params;
namespace content {
@@ -181,8 +181,9 @@ class CONTENT_EXPORT TextInputManager {
// Updates the selection bounds for the |view|. In Aura, selection bounds are
// used to provide the InputMethod with the position of the caret, e.g., in
// setting the position of the ui::ImeWindow.
- void SelectionBoundsChanged(RenderWidgetHostViewBase* view,
- const ViewHostMsg_SelectionBounds_Params& params);
+ void SelectionBoundsChanged(
+ RenderWidgetHostViewBase* view,
+ const WidgetHostMsg_SelectionBounds_Params& params);
// Notify observers that the selection bounds have been updated. This is also
// called when a view with a selection is reactivated.
diff --git a/chromium/content/browser/renderer_host/ui_events_helper.cc b/chromium/content/browser/renderer_host/ui_events_helper.cc
index 8b3330f22c9..1ca84152326 100644
--- a/chromium/content/browser/renderer_host/ui_events_helper.cc
+++ b/chromium/content/browser/renderer_host/ui_events_helper.cc
@@ -78,8 +78,9 @@ bool MakeUITouchEventsFromWebTouchEvents(
auto uievent = std::make_unique<ui::TouchEvent>(
type, gfx::Point(), timestamp,
ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, point.id,
- point.radius_x, point.radius_y, point.force),
- flags, point.rotation_angle);
+ point.radius_x, point.radius_y, point.force,
+ point.rotation_angle),
+ flags);
uievent->set_location_f(location);
uievent->set_root_location_f(location);
uievent->set_latency(touch_with_latency.latency);
diff --git a/chromium/content/browser/renderer_host/web_database_host_impl.cc b/chromium/content/browser/renderer_host/web_database_host_impl.cc
index da7a48e8903..65af343c3f2 100644
--- a/chromium/content/browser/renderer_host/web_database_host_impl.cc
+++ b/chromium/content/browser/renderer_host/web_database_host_impl.cc
@@ -9,7 +9,9 @@
#include "base/metrics/histogram_macros.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/task/post_task.h"
#include "content/browser/child_process_security_policy_impl.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/common/origin_util.h"
@@ -359,8 +361,8 @@ blink::mojom::WebDatabase& WebDatabaseHostImpl::GetWebDatabase() {
if (!database_provider_) {
// The interface binding needs to occur on the UI thread, as we can
// only call RenderProcessHost::FromID() on the UI thread.
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(
[](int process_id, blink::mojom::WebDatabaseRequest request) {
RenderProcessHost* host = RenderProcessHost::FromID(process_id);
@@ -374,7 +376,7 @@ blink::mojom::WebDatabase& WebDatabaseHostImpl::GetWebDatabase() {
}
bool WebDatabaseHostImpl::ValidateOrigin(const url::Origin& origin) {
- if (origin.unique()) {
+ if (origin.opaque()) {
mojo::ReportBadMessage("Invalid origin.");
return false;
}
diff --git a/chromium/content/browser/renderer_interface_binders.cc b/chromium/content/browser/renderer_interface_binders.cc
index c3a8bdc572d..5a6e7ed1611 100644
--- a/chromium/content/browser/renderer_interface_binders.cc
+++ b/chromium/content/browser/renderer_interface_binders.cc
@@ -7,6 +7,7 @@
#include <utility>
#include "base/bind.h"
+#include "base/no_destructor.h"
#include "content/browser/background_fetch/background_fetch_service_impl.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/cookie_store/cookie_store_context.h"
@@ -149,6 +150,13 @@ void RendererInterfaceBinders::InitializeParameterizedBinderRegistry() {
static_cast<RenderProcessHostImpl*>(host)->BindCacheStorage(
std::move(request), origin);
}));
+ // TODO(https://crbug.com/873661): Pass origin to FileSystemMananger.
+ parameterized_binder_registry_.AddInterface(base::BindRepeating(
+ [](blink::mojom::FileSystemManagerRequest request,
+ RenderProcessHost* host, const url::Origin& origin) {
+ static_cast<RenderProcessHostImpl*>(host)->BindFileSystemManager(
+ std::move(request));
+ }));
parameterized_binder_registry_.AddInterface(
base::Bind([](blink::mojom::PermissionServiceRequest request,
RenderProcessHost* host, const url::Origin& origin) {
@@ -186,8 +194,8 @@ void RendererInterfaceBinders::InitializeParameterizedBinderRegistry() {
}
RendererInterfaceBinders& GetRendererInterfaceBinders() {
- CR_DEFINE_STATIC_LOCAL(RendererInterfaceBinders, binders, ());
- return binders;
+ static base::NoDestructor<RendererInterfaceBinders> binders;
+ return *binders;
}
void RendererInterfaceBinders::CreateWebSocket(
diff --git a/chromium/content/browser/resources/gpu/info_view.js b/chromium/content/browser/resources/gpu/info_view.js
index 122f2e874be..780b52a28b3 100644
--- a/chromium/content/browser/resources/gpu/info_view.js
+++ b/chromium/content/browser/resources/gpu/info_view.js
@@ -235,6 +235,7 @@ cr.define('gpu', function() {
'native_gpu_memory_buffers': 'Native GpuMemoryBuffers',
'protected_video_decode': 'Hardware Protected Video Decode',
'surface_synchronization': 'Surface Synchronization',
+ 'surface_control': 'Surface Control',
'vpx_decode': 'VPx Video Decode',
'webgl2': 'WebGL2',
'viz_display_compositor': 'Viz Service Display Compositor',
diff --git a/chromium/content/browser/resources/media/client_renderer.js b/chromium/content/browser/resources/media/client_renderer.js
index 5d04e38d678..894cdd6766f 100644
--- a/chromium/content/browser/resources/media/client_renderer.js
+++ b/chromium/content/browser/resources/media/client_renderer.js
@@ -4,20 +4,24 @@
var ClientRenderer = (function() {
var ClientRenderer = function() {
- this.playerListElement = document.getElementById('player-list');
- var audioTableElement = document.getElementById('audio-property-table');
+ this.playerListElement = $('player-list');
+ var audioTableElement = $('audio-property-table');
if (audioTableElement)
this.audioPropertiesTable = audioTableElement.querySelector('tbody');
- var playerTableElement = document.getElementById('player-property-table');
+ var playerTableElement = $('player-property-table');
if (playerTableElement)
this.playerPropertiesTable = playerTableElement.querySelector('tbody');
- var logElement = document.getElementById('log');
+ var logElement = $('log');
if (logElement)
this.logTable = logElement.querySelector('tbody');
- this.graphElement = document.getElementById('graphs');
- this.audioPropertyName = document.getElementById('audio-property-name');
- this.audioFocusSessionListElement_ =
- document.getElementById('audio-focus-session-list');
+ this.graphElement = $('graphs');
+ this.audioPropertyName = $('audio-property-name');
+ this.audioFocusSessionListElement_ = $('audio-focus-session-list');
+ var generalAudioInformationTableElement = $('general-audio-info-table');
+ if (generalAudioInformationTableElement) {
+ this.generalAudioInformationTable =
+ generalAudioInformationTableElement.querySelector('tbody');
+ }
this.players = null;
this.selectedPlayer = null;
@@ -28,12 +32,12 @@ var ClientRenderer = (function() {
this.selectedPlayerLogIndex = 0;
this.filterFunction = function() { return true; };
- this.filterText = document.getElementById('filter-text');
+ this.filterText = $('filter-text');
if (this.filterText)
this.filterText.onkeyup = this.onTextChange_.bind(this);
- this.clipboardDialog = document.getElementById('clipboard-dialog');
+ this.clipboardDialog = $('clipboard-dialog');
- this.clipboardTextarea = document.getElementById('clipboard-textarea');
+ this.clipboardTextarea = $('clipboard-textarea');
if (this.clipboardTextarea)
this.clipboardTextarea.onblur = this.hideClipboard_.bind(this);
var clipboardButtons = document.getElementsByClassName('copy-button');
@@ -43,7 +47,7 @@ var ClientRenderer = (function() {
}
}
- this.saveLogButton = document.getElementById('save-log-button');
+ this.saveLogButton = $('save-log-button');
if (this.saveLogButton)
this.saveLogButton.onclick = this.saveLog_.bind(this);
@@ -99,7 +103,7 @@ var ClientRenderer = (function() {
}
function selectSelectableButton(id) {
- var element = document.getElementById(id);
+ var element = $(id);
if (!element) {
console.error('failed to select button with id: ' + id);
return;
@@ -118,6 +122,14 @@ var ClientRenderer = (function() {
ClientRenderer.prototype = {
/**
+ * Called to set general audio information.
+ @param audioInfo The map of information.
+ */
+ generalAudioInformationSet: function(audioInfo) {
+ this.drawProperties_(audioInfo, this.generalAudioInformationTable);
+ },
+
+ /**
* Called when an audio component is added to the collection.
* @param componentType Integer AudioComponent enum value; must match values
* from the AudioLogFactory::AudioComponent enum.
@@ -237,14 +249,12 @@ var ClientRenderer = (function() {
},
redrawVideoCaptureCapabilities: function(videoCaptureCapabilities, keys) {
- var copyButtonElement =
- document.getElementById('video-capture-capabilities-copy-button');
+ var copyButtonElement = $('video-capture-capabilities-copy-button');
copyButtonElement.onclick = function() {
this.showClipboard(JSON.stringify(videoCaptureCapabilities, null, 2));
}.bind(this);
- var videoTableBodyElement =
- document.getElementById('video-capture-capabilities-tbody');
+ var videoTableBodyElement = $('video-capture-capabilities-tbody');
removeChildren(videoTableBodyElement);
for (var component in videoCaptureCapabilities) {
@@ -289,16 +299,13 @@ var ClientRenderer = (function() {
var listElement;
switch (componentType) {
case 0:
- listElement = document.getElementById(
- 'audio-input-controller-list');
+ listElement = $('audio-input-controller-list');
break;
case 1:
- listElement = document.getElementById(
- 'audio-output-controller-list');
+ listElement = $('audio-output-controller-list');
break;
case 2:
- listElement = document.getElementById(
- 'audio-output-stream-list');
+ listElement = $('audio-output-stream-list');
break;
default:
console.error('Unrecognized component type: ' + componentType);
@@ -323,13 +330,13 @@ var ClientRenderer = (function() {
var fragment = document.createDocumentFragment();
for (var id in components) {
var li = document.createElement('li');
- var button_cb = this.selectAudioComponent_.bind(
+ var buttonCb = this.selectAudioComponent_.bind(
this, componentType, id, components[id]);
var friendlyName = this.getAudioComponentName_(componentType, id);
var label = document.createElement('label');
label.appendChild(document.createTextNode(friendlyName));
- li.appendChild(createSelectableButton(
- id, buttonGroupName, label, button_cb));
+ li.appendChild(
+ createSelectableButton(id, buttonGroupName, label, buttonCb));
fragment.appendChild(li);
}
removeChildren(listElement);
@@ -372,23 +379,23 @@ var ClientRenderer = (function() {
var p = player.properties;
var label = document.createElement('label');
- var name_text = p.url || 'Player ' + player.id;
- var name_node = document.createElement('div');
- name_node.appendChild(document.createTextNode(name_text));
- name_node.className = 'player-name';
- label.appendChild(name_node);
+ var nameText = p.url || 'Player ' + player.id;
+ var nameNode = document.createElement('div');
+ nameNode.appendChild(document.createTextNode(nameText));
+ nameNode.className = 'player-name';
+ label.appendChild(nameNode);
var frame = [];
if (p.frame_title)
frame.push(p.frame_title);
if (p.frame_url)
frame.push(p.frame_url);
- var frame_text = frame.join(' - ');
- if (frame_text) {
- var frame_node = document.createElement('div');
- frame_node.className = 'player-frame';
- frame_node.appendChild(document.createTextNode(frame_text));
- label.appendChild(frame_node);
+ var frameText = frame.join(' - ');
+ if (frameText) {
+ var frameNode = document.createElement('div');
+ frameNode.className = 'player-frame';
+ frameNode.appendChild(document.createTextNode(frameText));
+ label.appendChild(frameNode);
}
var desc = [];
@@ -402,18 +409,18 @@ var ClientRenderer = (function() {
desc.push(p.audio_codec_name);
if (p.event)
desc.push('(' + p.event + ')');
- var desc_text = desc.join(' ');
- if (desc_text) {
- var desc_node = document.createElement('div');
- desc_node.className = 'player-desc';
- desc_node.appendChild(document.createTextNode(desc_text));
- label.appendChild(desc_node);
+ var descText = desc.join(' ');
+ if (descText) {
+ var descNode = document.createElement('div');
+ descNode.className = 'player-desc';
+ descNode.appendChild(document.createTextNode(descText));
+ label.appendChild(descNode);
}
var li = document.createElement('li');
- var button_cb = this.selectPlayer_.bind(this, player);
+ var buttonCb = this.selectPlayer_.bind(this, player);
li.appendChild(createSelectableButton(
- id, buttonGroupName, label, button_cb, player.destructed));
+ id, buttonGroupName, label, buttonCb, player.destructed));
fragment.appendChild(li);
}
removeChildren(this.playerListElement);
diff --git a/chromium/content/browser/resources/media/main.js b/chromium/content/browser/resources/media/main.js
index 9a25be49b7e..082b336a997 100644
--- a/chromium/content/browser/resources/media/main.js
+++ b/chromium/content/browser/resources/media/main.js
@@ -17,6 +17,10 @@ var media = (function() {
manager = theManager;
};
+ media.updateGeneralAudioInformation = function(audioInfo) {
+ manager.updateGeneralAudioInformation(audioInfo);
+ };
+
media.onReceiveAudioStreamData = function(audioStreamData) {
for (var component in audioStreamData) {
media.updateAudioComponent(audioStreamData[component]);
diff --git a/chromium/content/browser/resources/media/manager.js b/chromium/content/browser/resources/media/manager.js
index 994df2b5bfe..cc75fe75d47 100644
--- a/chromium/content/browser/resources/media/manager.js
+++ b/chromium/content/browser/resources/media/manager.js
@@ -14,12 +14,13 @@ var Manager = (function() {
function Manager(clientRenderer) {
this.players_ = {};
+ this.audioInfo_ = {};
this.audioComponents_ = [];
this.clientRenderer_ = clientRenderer;
- var copyAllPlayerButton = document.getElementById('copy-all-player-button');
- var copyAllAudioButton = document.getElementById('copy-all-audio-button');
- var hidePlayersButton = document.getElementById('hide-players-button');
+ var copyAllPlayerButton = $('copy-all-player-button');
+ var copyAllAudioButton = $('copy-all-audio-button');
+ var hidePlayersButton = $('hide-players-button');
// In tests we may not have these buttons.
if (copyAllPlayerButton) {
@@ -31,7 +32,8 @@ var Manager = (function() {
if (copyAllAudioButton) {
copyAllAudioButton.onclick = function() {
this.clientRenderer_.showClipboard(
- JSON.stringify(this.audioComponents_, null, 2));
+ JSON.stringify(this.audioInfo_, null, 2) + '\n\n' +
+ JSON.stringify(this.audioComponents_, null, 2));
}.bind(this);
}
if (hidePlayersButton) {
@@ -49,6 +51,15 @@ var Manager = (function() {
},
/**
+ * Updates the general audio information.
+ * @param audioInfo The map of information.
+ */
+ updateGeneralAudioInformation: function(audioInfo) {
+ this.audioInfo_ = audioInfo;
+ this.clientRenderer_.generalAudioInformationSet(this.audioInfo_);
+ },
+
+ /**
* Updates an audio-component.
* @param componentType Integer AudioComponent enum value; must match values
* from the AudioLogFactory::AudioComponent enum.
diff --git a/chromium/content/browser/resources/media/media_internals.html b/chromium/content/browser/resources/media/media_internals.html
index 6df11b93b5c..57c84338fd0 100644
--- a/chromium/content/browser/resources/media/media_internals.html
+++ b/chromium/content/browser/resources/media/media_internals.html
@@ -72,6 +72,18 @@ found in the LICENSE file.
</tabpanel>
<tabpanel id="audio">
<button id="copy-all-audio-button">Copy all to clipboard</button>
+ <div>
+ <h2>General Information</h2>
+ <table id="general-audio-info-table">
+ <thead>
+ <tr>
+ <th>Property</th>
+ <th>Value</th>
+ </tr>
+ </thead>
+ <tbody></tbody>
+ </table>
+ </div>
<div id="audio-component-list-wrapper">
<h2>Input Controllers</h2>
<ul id="audio-input-controller-list" class="show-none-if-empty"></ul>
diff --git a/chromium/content/browser/resources/media/stats_graph_helper.js b/chromium/content/browser/resources/media/stats_graph_helper.js
index daa28866f6a..30cdf0ee298 100644
--- a/chromium/content/browser/resources/media/stats_graph_helper.js
+++ b/chromium/content/browser/resources/media/stats_graph_helper.js
@@ -36,8 +36,8 @@ var totalToPerSecond = function(srcDataSeries) {
if (length >= 2) {
var lastDataPoint = srcDataSeries.dataPoints_[length - 1];
var secondLastDataPoint = srcDataSeries.dataPoints_[length - 2];
- return (lastDataPoint.value - secondLastDataPoint.value) * 1000 /
- (lastDataPoint.time - secondLastDataPoint.time);
+ return Math.floor((lastDataPoint.value - secondLastDataPoint.value) * 1000 /
+ (lastDataPoint.time - secondLastDataPoint.time));
}
return 0;
diff --git a/chromium/content/browser/resources/media/util.js b/chromium/content/browser/resources/media/util.js
index 29cc1b152e3..3ab7da77a2b 100644
--- a/chromium/content/browser/resources/media/util.js
+++ b/chromium/content/browser/resources/media/util.js
@@ -30,17 +30,19 @@ var util = (function() {
}
};
util.millisecondsToString = function(timeMillis) {
- function pad(num) {
+ function pad(num, len) {
num = num.toString();
- if (num.length < 2) {
- return '0' + num;
+ while (num.length < len) {
+ num = '0' + num;
}
return num;
}
var date = new Date(timeMillis);
- return pad(date.getUTCHours()) + ':' + pad(date.getUTCMinutes()) + ':' +
- pad(date.getUTCSeconds()) + ' ' + pad((date.getMilliseconds()) % 1000);
+ return pad(date.getUTCHours(), 2) + ':' +
+ pad(date.getUTCMinutes(), 2) + ':' +
+ pad(date.getUTCSeconds(), 2) + '.' +
+ pad((date.getMilliseconds()) % 1000, 3);
};
return util;
diff --git a/chromium/content/browser/resources/process/process_internals.css b/chromium/content/browser/resources/process/process_internals.css
new file mode 100644
index 00000000000..ce59e9da8c7
--- /dev/null
+++ b/chromium/content/browser/resources/process/process_internals.css
@@ -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. */
+
+* {
+ box-sizing: border-box;
+}
+
+html {
+ height: 100%;
+}
+
+body {
+ color: rgb(48, 57, 66);
+ display: flex;
+ flex-direction: column;
+ font-size: 13px;
+ height: 100%;
+ margin: 0;
+ overflow: auto;
+}
+
+#container {
+ display: flex;
+ height: 100%
+}
+
+#navigation {
+ flex-shrink: 0;
+ padding-top: 20px;
+ width: 200px;
+}
+
+#content {
+ flex-grow: 1;
+}
+
+#caption {
+ color: rgb(92, 97, 102);
+ font-size: 1.5rem;
+ padding-bottom: 10px;
+ padding-inline-start: 20px;
+}
+
+.tab-header {
+ border-inline-start: 6px solid transparent;
+ padding-left: 15px;
+}
+
+.tab-header.selected {
+ border-inline-start-color: rgb(78, 87, 100);
+}
+
+.tab-header > button {
+ background-color: white;
+ border: 0;
+ cursor: pointer;
+ font: inherit;
+ line-height: 17px;
+ margin: 6px 0;
+ padding: 0 2px;
+}
+
+.tab-header:not(.selected) > button {
+ color: #999;
+}
+
+#content > div {
+ min-width: 32em;
+ padding: 0 20px 65px 0;
+}
+#content > div:not(.selected) {
+ display: none;
+}
+
+.content-header {
+ background: linear-gradient(white, white 40%, rgba(255, 255, 255, 0.92));
+ border-bottom: 1px solid #eee;
+ font-size: 150%;
+ padding: 20px 0 10px 0;
+ z-index: 1;
+}
+
+.tree-label {
+ user-select: text;
+}
diff --git a/chromium/content/browser/resources/process/process_internals.html b/chromium/content/browser/resources/process/process_internals.html
index 9b63631e817..595fbdcdaae 100644
--- a/chromium/content/browser/resources/process/process_internals.html
+++ b/chromium/content/browser/resources/process/process_internals.html
@@ -6,11 +6,50 @@
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="chrome://resources/css/text_defaults.css">
+ <script src="chrome://resources/js/util.js"></script>
+ <script src="chrome://resources/js/cr.js"></script>
<script src="chrome://resources/js/mojo_bindings.js"></script>
+
+ <link rel="stylesheet" href="chrome://resources/css/tree.css">
+ <script src="chrome://resources/js/cr/ui.js"></script>
+ <script src="chrome://resources/js/cr/ui/tree.js"></script>
+
+ <link rel="stylesheet" href="process_internals.css">
+ <script src="url.mojom.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">Number of isolated origins: <span id='isolated-origins'></span></div>
+<body>
+
+<div id="container">
+ <div id="navigation">
+ <div id="caption">Process Internals</div>
+ </div>
+ <div id="content">
+ <div id="general">
+ <div class="content-header">General info</div>
+ <div id="general-info">
+ <div id="site-isolation-mode">Site Isolation mode: <span id='isolation-mode'>unknown</span></div>
+ <div id="isolated-origins-container">Number of isolated origins: <span id='isolated-origins'></span></div>
+ </div>
+ </div>
+ <div id="web-contents">
+ <div class="content-header">Frame Trees</div>
+ <div id="wc-list" class="list pages"></div>
+ <div id="tree-view-container">
+ <button id="refresh-button">Refresh</button>
+ <div>Legend:</div>
+ <div>Frame[<i>process_id</i>:<i>routing_id</i>]:
+ SI:<i>site_instance_id</i>, <i>whether process is locked to a
+ site</i>, site: <i>site_url</i> | url:
+ <i>last_committed_url</i>
+ </div>
+ <tree id="tree-view"></tree>
+ </div>
+ </div>
+ </div>
+</div>
+
+</body>
</html>
diff --git a/chromium/content/browser/resources/process/process_internals.js b/chromium/content/browser/resources/process/process_internals.js
index 155847443a7..c299e9a8c02 100644
--- a/chromium/content/browser/resources/process/process_internals.js
+++ b/chromium/content/browser/resources/process/process_internals.js
@@ -2,16 +2,169 @@
// 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.
+ * Reference to the backend providing all the data.
* @type {mojom.ProcessInternalsHandlerPtr}
*/
-var uiHandler = null;
+let uiHandler = null;
+
+/**
+ * @param {string} id Tab id.
+ * @return {boolean} True if successful.
+ */
+function selectTab(id) {
+ const tabContents = document.querySelectorAll('#content > div');
+ const tabHeaders = $('navigation').querySelectorAll('.tab-header');
+ let found = false;
+ for (let i = 0; i < tabContents.length; i++) {
+ const tabContent = tabContents[i];
+ const tabHeader = tabHeaders[i];
+ const isTargetTab = tabContent.id == id;
+
+ found = found || isTargetTab;
+ tabContent.classList.toggle('selected', isTargetTab);
+ tabHeader.classList.toggle('selected', isTargetTab);
+ }
+ if (!found)
+ return false;
+ window.location.hash = id;
+ return true;
+}
+
+function onHashChange() {
+ let hash = window.location.hash.slice(1).toLowerCase();
+ if (!selectTab(hash))
+ selectTab('general');
+}
+
+function setupTabs() {
+ const tabContents = document.querySelectorAll('#content > div');
+ for (let i = 0; i < tabContents.length; i++) {
+ const tabContent = tabContents[i];
+ const tabName = tabContent.querySelector('.content-header').textContent;
+
+ let tabHeader = document.createElement('div');
+ tabHeader.className = 'tab-header';
+ let button = document.createElement('button');
+ button.textContent = tabName;
+ tabHeader.appendChild(button);
+ tabHeader.addEventListener('click', selectTab.bind(null, tabContent.id));
+ $('navigation').appendChild(tabHeader);
+ }
+ onHashChange();
+}
+
+/**
+ * Root of the WebContents tree.
+ * @type {cr.ui.Tree|null}
+ */
+let treeViewRoot = null;
+
+/**
+ * Initialize and return |treeViewRoot|.
+ * @return {cr.ui.Tree} Initialized |treeViewRoot|.
+ */
+function getTreeViewRoot() {
+ if (!treeViewRoot) {
+ cr.ui.decorate('#tree-view', cr.ui.Tree);
+
+ treeViewRoot = /** @type {cr.ui.Tree} */ ($('tree-view'));
+ treeViewRoot.detail = {payload: {}, children: {}};
+ }
+ return treeViewRoot;
+}
+
+/**
+ * Initialize and return a tree item representing a FrameInfo object and
+ * recursively creates its subframe objects.
+ * @param {mojom.FrameInfo} frame
+ * @return {Array}
+ */
+function frameToTreeItem(frame) {
+ // Compose the string which will appear in the entry for this frame.
+ let itemLabel = `Frame[${frame.processId}:${frame.routingId}]:`;
+ itemLabel += ` SI:${frame.siteInstance.id}`;
+ if (frame.siteInstance.locked)
+ itemLabel += ', locked';
+ if (frame.siteInstance.siteUrl)
+ itemLabel += `, site:${frame.siteInstance.siteUrl.url}`;
+ if (frame.lastCommittedUrl)
+ itemLabel += ` | url: ${frame.lastCommittedUrl.url}`;
+
+ let item = new cr.ui.TreeItem(
+ {label: itemLabel, detail: {payload: {}, children: {}}});
+ item.mayHaveChildren_ = true;
+ item.expanded = true;
+ item.icon = '';
+
+ let frameCount = 1;
+ for (const subframe of frame.subframes) {
+ let result = frameToTreeItem(subframe);
+ const subItem = result[0];
+ const count = result[1];
+
+ frameCount += count;
+ item.add(subItem);
+ }
+
+ return [item, frameCount];
+}
+
+/**
+ * Initialize and return a tree item representing the WebContentsInfo object
+ * and contains all frames in it as a subtree.
+ * @param {mojom.WebContentsInfo} webContents
+ * @return {cr.ui.TreeItem}
+ */
+function webContentsToTreeItem(webContents) {
+ let itemLabel = 'WebContents: ';
+ if (webContents.title.length > 0)
+ itemLabel += webContents.title + ', ';
+
+ let item = new cr.ui.TreeItem(
+ {label: itemLabel, detail: {payload: {}, children: {}}});
+ item.mayHaveChildren_ = true;
+ item.expanded = true;
+ item.icon = '';
+
+ let result = frameToTreeItem(webContents.rootFrame);
+ const rootItem = result[0];
+ const count = result[1];
+
+ itemLabel += `${count} frame` + (count > 1 ? 's.' : '.');
+ item.label = itemLabel;
+
+ item.add(rootItem);
+ return item;
+}
+
+/**
+ * This is a callback which is invoked when the data for WebContents
+ * associated with the browser profile is received from the browser process.
+ * @param {mojom.ProcessInternalsHandler_GetAllWebContentsInfo_ResponseParams} input
+ */
+function populateWebContentsTab(input) {
+ let tree = getTreeViewRoot();
+
+ // Clear the tree first before populating it with the new content.
+ tree.innerText = '';
+
+ for (const webContents of input.infos) {
+ const item = webContentsToTreeItem(webContents);
+ tree.add(item);
+ }
+}
+
+/**
+ * Function which retrieves the data for all WebContents associated with the
+ * current browser profile. The result is passed to populateWebContentsTab.
+ */
+function loadWebContentsInfo() {
+ uiHandler.getAllWebContentsInfo().then(populateWebContentsTab);
+}
document.addEventListener('DOMContentLoaded', function() {
// Setup Mojo interface to the backend.
@@ -22,11 +175,19 @@ document.addEventListener('DOMContentLoaded', function() {
// Get the Site Isolation mode and populate it.
uiHandler.getIsolationMode().then((response) => {
- document.getElementById('isolation-mode').innerText = response.mode;
+ $('isolation-mode').innerText = response.mode;
});
uiHandler.getIsolatedOriginsSize().then((response) => {
- document.getElementById('isolated-origins').innerText = response.size;
+ $('isolated-origins').innerText = response.size;
});
+
+ // Setup the tabbed UI
+ setupTabs();
+
+ // Start loading the information about WebContents.
+ loadWebContentsInfo();
+
+ $('refresh-button').addEventListener('click', loadWebContentsInfo);
});
})();
diff --git a/chromium/content/browser/scheduler/OWNERS b/chromium/content/browser/scheduler/OWNERS
new file mode 100644
index 00000000000..970514cb53e
--- /dev/null
+++ b/chromium/content/browser/scheduler/OWNERS
@@ -0,0 +1,4 @@
+altimin@chromium.org
+alexclarke@chromium.org
+eseckler@chromium.org
+skyostil@chromium.org
diff --git a/chromium/content/browser/scheduler/browser_task_executor.cc b/chromium/content/browser/scheduler/browser_task_executor.cc
new file mode 100644
index 00000000000..e96642469fc
--- /dev/null
+++ b/chromium/content/browser/scheduler/browser_task_executor.cc
@@ -0,0 +1,153 @@
+// 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/scheduler/browser_task_executor.h"
+
+#include "base/no_destructor.h"
+#include "content/browser/browser_thread_impl.h"
+
+namespace content {
+namespace {
+
+// |g_browser_task_executor| is intentionally leaked on shutdown.
+BrowserTaskExecutor* g_browser_task_executor = nullptr;
+
+// An implementation of SingleThreadTaskRunner to be used in conjunction with
+// BrowserThread. BrowserThreadTaskRunners are vended by
+// base::Create*TaskRunnerWithTraits({BrowserThread::UI/IO}).
+//
+// TODO(gab): Consider replacing this with direct calls to task runners obtained
+// via |BrowserThreadImpl::GetTaskRunnerForThread()| -- only works if none are
+// requested before starting the threads.
+class BrowserThreadTaskRunner : public base::SingleThreadTaskRunner {
+ public:
+ explicit BrowserThreadTaskRunner(BrowserThread::ID identifier)
+ : id_(identifier) {}
+
+ // SingleThreadTaskRunner implementation.
+ bool PostDelayedTask(const base::Location& from_here,
+ base::OnceClosure task,
+ base::TimeDelta delay) override {
+ return BrowserThreadImpl::GetTaskRunnerForThread(id_)->PostDelayedTask(
+ from_here, std::move(task), delay);
+ }
+
+ bool PostNonNestableDelayedTask(const base::Location& from_here,
+ base::OnceClosure task,
+ base::TimeDelta delay) override {
+ return BrowserThreadImpl::GetTaskRunnerForThread(id_)
+ ->PostNonNestableDelayedTask(from_here, std::move(task), delay);
+ }
+
+ bool RunsTasksInCurrentSequence() const override {
+ return BrowserThread::CurrentlyOn(id_);
+ }
+
+ private:
+ ~BrowserThreadTaskRunner() override {}
+
+ const BrowserThread::ID id_;
+
+ DISALLOW_COPY_AND_ASSIGN(BrowserThreadTaskRunner);
+};
+
+} // namespace
+
+BrowserTaskExecutor::BrowserTaskExecutor() = default;
+BrowserTaskExecutor::~BrowserTaskExecutor() = default;
+
+// static
+void BrowserTaskExecutor::Create() {
+ DCHECK(!g_browser_task_executor);
+ g_browser_task_executor = new BrowserTaskExecutor();
+ base::RegisterTaskExecutor(BrowserTaskTraitsExtension::kExtensionId,
+ g_browser_task_executor);
+}
+
+// static
+void BrowserTaskExecutor::ResetForTesting() {
+ if (g_browser_task_executor) {
+ base::UnregisterTaskExecutorForTesting(
+ BrowserTaskTraitsExtension::kExtensionId);
+ delete g_browser_task_executor;
+ g_browser_task_executor = nullptr;
+ }
+}
+
+bool BrowserTaskExecutor::PostDelayedTaskWithTraits(
+ const base::Location& from_here,
+ const base::TaskTraits& traits,
+ base::OnceClosure task,
+ base::TimeDelta delay) {
+ DCHECK_EQ(BrowserTaskTraitsExtension::kExtensionId, traits.extension_id());
+ const BrowserTaskTraitsExtension& extension =
+ traits.GetExtension<BrowserTaskTraitsExtension>();
+ if (extension.nestable()) {
+ return GetTaskRunner(extension)->PostDelayedTask(from_here, std::move(task),
+ delay);
+ } else {
+ return GetTaskRunner(extension)->PostNonNestableDelayedTask(
+ from_here, std::move(task), delay);
+ }
+}
+
+scoped_refptr<base::TaskRunner> BrowserTaskExecutor::CreateTaskRunnerWithTraits(
+ const base::TaskTraits& traits) {
+ return GetTaskRunner(traits);
+}
+
+scoped_refptr<base::SequencedTaskRunner>
+BrowserTaskExecutor::CreateSequencedTaskRunnerWithTraits(
+ const base::TaskTraits& traits) {
+ return GetTaskRunner(traits);
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+BrowserTaskExecutor::CreateSingleThreadTaskRunnerWithTraits(
+ const base::TaskTraits& traits,
+ base::SingleThreadTaskRunnerThreadMode thread_mode) {
+ return GetTaskRunner(traits);
+}
+
+#if defined(OS_WIN)
+scoped_refptr<base::SingleThreadTaskRunner>
+BrowserTaskExecutor::CreateCOMSTATaskRunnerWithTraits(
+ const base::TaskTraits& traits,
+ base::SingleThreadTaskRunnerThreadMode thread_mode) {
+ return GetTaskRunner(traits);
+}
+#endif // defined(OS_WIN)
+
+scoped_refptr<base::SingleThreadTaskRunner> BrowserTaskExecutor::GetTaskRunner(
+ const base::TaskTraits& traits) {
+ DCHECK_EQ(BrowserTaskTraitsExtension::kExtensionId, traits.extension_id());
+ const BrowserTaskTraitsExtension& extension =
+ traits.GetExtension<BrowserTaskTraitsExtension>();
+ return GetTaskRunner(extension);
+}
+
+scoped_refptr<base::SingleThreadTaskRunner> BrowserTaskExecutor::GetTaskRunner(
+ const BrowserTaskTraitsExtension& extension) {
+ BrowserThread::ID thread_id = extension.browser_thread();
+ DCHECK_GE(thread_id, 0);
+ DCHECK_LT(thread_id, BrowserThread::ID::ID_COUNT);
+ return GetProxyTaskRunnerForThread(thread_id);
+}
+
+// static
+scoped_refptr<base::SingleThreadTaskRunner>
+BrowserTaskExecutor::GetProxyTaskRunnerForThread(BrowserThread::ID id) {
+ using TaskRunnerMap = std::array<scoped_refptr<base::SingleThreadTaskRunner>,
+ BrowserThread::ID_COUNT>;
+ static const base::NoDestructor<TaskRunnerMap> task_runners([] {
+ TaskRunnerMap task_runners;
+ for (int i = 0; i < BrowserThread::ID_COUNT; ++i)
+ task_runners[i] = base::MakeRefCounted<BrowserThreadTaskRunner>(
+ static_cast<BrowserThread::ID>(i));
+ return task_runners;
+ }());
+ return (*task_runners)[id];
+}
+
+} // namespace content
diff --git a/chromium/content/browser/scheduler/browser_task_executor.h b/chromium/content/browser/scheduler/browser_task_executor.h
new file mode 100644
index 00000000000..418d6176f04
--- /dev/null
+++ b/chromium/content/browser/scheduler/browser_task_executor.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_SCHEDULER_BROWSER_TASK_EXECUTOR_H_
+#define CONTENT_BROWSER_SCHEDULER_BROWSER_TASK_EXECUTOR_H_
+
+#include "base/gtest_prod_util.h"
+#include "base/task/task_executor.h"
+#include "build/build_config.h"
+#include "content/common/content_export.h"
+#include "content/public/browser/browser_task_traits.h"
+
+namespace content {
+
+// This class's job is to map base::TaskTraits to actual task queues for the
+// browser process.
+class CONTENT_EXPORT BrowserTaskExecutor : public base::TaskExecutor {
+ public:
+ // Creates and registers a BrowserTaskExecutor that facilitates posting tasks
+ // to a BrowserThread via //base/task/post_task.h.
+ static void Create();
+
+ // Unregister and delete the TaskExecutor after a test.
+ static void ResetForTesting();
+
+ // base::TaskExecutor implementation.
+ bool PostDelayedTaskWithTraits(const base::Location& from_here,
+ const base::TaskTraits& traits,
+ base::OnceClosure task,
+ base::TimeDelta delay) override;
+
+ scoped_refptr<base::TaskRunner> CreateTaskRunnerWithTraits(
+ const base::TaskTraits& traits) override;
+
+ scoped_refptr<base::SequencedTaskRunner> CreateSequencedTaskRunnerWithTraits(
+ const base::TaskTraits& traits) override;
+
+ scoped_refptr<base::SingleThreadTaskRunner>
+ CreateSingleThreadTaskRunnerWithTraits(
+ const base::TaskTraits& traits,
+ base::SingleThreadTaskRunnerThreadMode thread_mode) override;
+
+#if defined(OS_WIN)
+ scoped_refptr<base::SingleThreadTaskRunner> CreateCOMSTATaskRunnerWithTraits(
+ const base::TaskTraits& traits,
+ base::SingleThreadTaskRunnerThreadMode thread_mode) override;
+#endif // defined(OS_WIN)
+
+ private:
+ // For GetProxyTaskRunnerForThread().
+ FRIEND_TEST_ALL_PREFIXES(BrowserTaskExecutorTest,
+ EnsureUIThreadTraitPointsToExpectedQueue);
+ FRIEND_TEST_ALL_PREFIXES(BrowserTaskExecutorTest,
+ EnsureIOThreadTraitPointsToExpectedQueue);
+
+ BrowserTaskExecutor();
+ ~BrowserTaskExecutor() override;
+
+ scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner(
+ const base::TaskTraits& traits);
+
+ scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner(
+ const BrowserTaskTraitsExtension& extension);
+
+ static scoped_refptr<base::SingleThreadTaskRunner>
+ GetProxyTaskRunnerForThread(BrowserThread::ID id);
+
+ DISALLOW_COPY_AND_ASSIGN(BrowserTaskExecutor);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_SCHEDULER_BROWSER_TASK_EXECUTOR_H_
diff --git a/chromium/content/browser/scheduler/browser_task_executor_unittest.cc b/chromium/content/browser/scheduler/browser_task_executor_unittest.cc
new file mode 100644
index 00000000000..7f283afecab
--- /dev/null
+++ b/chromium/content/browser/scheduler/browser_task_executor_unittest.cc
@@ -0,0 +1,51 @@
+// 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/scheduler/browser_task_executor.h"
+
+#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
+#include "base/task/post_task.h"
+#include "base/task/task_scheduler/task_scheduler.h"
+#include "content/browser/browser_thread_impl.h"
+#include "content/public/browser/browser_task_traits.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+class BrowserTaskExecutorTest : public testing::Test {
+ public:
+ void SetUp() override {
+ base::TaskScheduler::CreateAndStartWithDefaultParams("Test");
+ BrowserTaskExecutor::Create();
+ message_loop_ = std::make_unique<base::MessageLoop>();
+ }
+
+ void TearDown() override {
+ BrowserTaskExecutor::ResetForTesting();
+ base::TaskScheduler::GetInstance()->Shutdown();
+ base::TaskScheduler::GetInstance()->JoinForTesting();
+ base::TaskScheduler::SetInstance(nullptr);
+ message_loop_.reset();
+ }
+
+ static void RunUntilIdle() { base::RunLoop().RunUntilIdle(); }
+
+ protected:
+ std::unique_ptr<base::MessageLoop> message_loop_;
+};
+
+TEST_F(BrowserTaskExecutorTest, EnsureUIThreadTraitPointsToExpectedQueue) {
+ EXPECT_EQ(
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::UI}),
+ BrowserTaskExecutor::GetProxyTaskRunnerForThread(BrowserThread::UI));
+}
+
+TEST_F(BrowserTaskExecutorTest, EnsureIOThreadTraitPointsToExpectedQueue) {
+ EXPECT_EQ(
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO}),
+ BrowserTaskExecutor::GetProxyTaskRunnerForThread(BrowserThread::IO));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/scheduler/responsiveness/README b/chromium/content/browser/scheduler/responsiveness/README
index 68ee4d93be7..96429ebb75a 100644
--- a/chromium/content/browser/scheduler/responsiveness/README
+++ b/chromium/content/browser/scheduler/responsiveness/README
@@ -3,7 +3,7 @@ execution latency on the UI and IO threads of the browser process.
There are four types of work executed on the UI and IO threads.
1) Both the UI and IO threads can have tasks posted to them via the Task
- Scheduler [e.g. via content::BrowserThread::PostTask].
+ Scheduler [e.g. via base::PostTaskWithTraits with a BrowserThread::ID].
2) The UI thread processes native events directly from the message loop
[NSEvents on macOS, MSGs on Windows, InputEvents on Android, XEvents on
X11, etc.]
diff --git a/chromium/content/browser/scheduler/responsiveness/native_event_observer.cc b/chromium/content/browser/scheduler/responsiveness/native_event_observer.cc
index 4225e9aa6df..0aa5e6e69fa 100644
--- a/chromium/content/browser/scheduler/responsiveness/native_event_observer.cc
+++ b/chromium/content/browser/scheduler/responsiveness/native_event_observer.cc
@@ -17,14 +17,9 @@
#include "ui/events/platform/platform_event_source.h"
-#if defined(USE_X11)
-#include "ui/events/platform/x11/x11_event_source.h" // nogncheck
-#elif defined(USE_OZONE)
-#include "ui/events/event.h"
-#endif
-
#if defined(OS_LINUX)
-#include "ui/events/platform_event.h"
+#include "ui/aura/env.h"
+#include "ui/events/event.h"
#endif
#if defined(OS_WIN)
@@ -71,41 +66,25 @@ NativeEventObserver::~NativeEventObserver() {
#if defined(OS_LINUX)
void NativeEventObserver::RegisterObserver() {
- ui::PlatformEventSource::GetInstance()->AddPlatformEventObserver(this);
+ aura::Env::GetInstance()->AddWindowEventDispatcherObserver(this);
}
void NativeEventObserver::DeregisterObserver() {
- ui::PlatformEventSource::GetInstance()->RemovePlatformEventObserver(this);
+ aura::Env::GetInstance()->RemoveWindowEventDispatcherObserver(this);
}
-void NativeEventObserver::WillProcessEvent(const ui::PlatformEvent& event) {
+void NativeEventObserver::OnWindowEventDispatcherStartedProcessing(
+ aura::WindowEventDispatcher* dispatcher,
+ const ui::Event& event) {
+ EventInfo info{&event, event.time_stamp()};
+ events_being_processed_.push_back(info);
will_run_event_callback_.Run(&event);
}
-void NativeEventObserver::DidProcessEvent(const ui::PlatformEvent& event) {
-#if defined(USE_OZONE)
- did_run_event_callback_.Run(&event, event->time_stamp());
-#elif defined(USE_X11)
- // X11 uses a uint32_t on the wire protocol. Xlib casts this to an unsigned
- // long by prepending with 0s. We cast back to a uint32_t so that subtraction
- // works properly when the timestamp overflows back to 0.
- uint32_t event_server_time_ms =
- static_cast<uint32_t>(ui::X11EventSource::GetInstance()->GetTimestamp());
- uint32_t current_server_time_ms = static_cast<uint32_t>(
- ui::X11EventSource::GetInstance()->GetCurrentServerTime());
-
- // On X11, event times are in X11 Server time. To convert to base::TimeTicks,
- // we perform a round-trip to the X11 Server, subtract the two times to get a
- // TimeDelta, and then subtract that from base::TimeTicks::Now(). Since we're
- // working with units of time from an external source, we clamp the TimeDelta
- // to reasonable values.
- uint32_t delta_ms = current_server_time_ms - event_server_time_ms;
- base::TimeDelta delta = base::TimeDelta::FromMilliseconds(delta_ms);
- base::TimeDelta sanitized = ClampDeltaFromExternalSource(delta);
-
- did_run_event_callback_.Run(&event, base::TimeTicks::Now() - sanitized);
-#else
-#error
-#endif
+void NativeEventObserver::OnWindowEventDispatcherFinishedProcessingEvent(
+ aura::WindowEventDispatcher* dispatcher) {
+ EventInfo& info = events_being_processed_.back();
+ did_run_event_callback_.Run(info.unique_id, info.creation_time);
+ events_being_processed_.pop_back();
}
#endif // defined(OS_LINUX)
diff --git a/chromium/content/browser/scheduler/responsiveness/native_event_observer.h b/chromium/content/browser/scheduler/responsiveness/native_event_observer.h
index 5aaefd3daf5..cf2ef28d0d0 100644
--- a/chromium/content/browser/scheduler/responsiveness/native_event_observer.h
+++ b/chromium/content/browser/scheduler/responsiveness/native_event_observer.h
@@ -7,6 +7,7 @@
#include "base/callback.h"
#include "base/macros.h"
+#include "base/time/time.h"
#include "build/build_config.h"
#include "content/common/content_export.h"
@@ -15,7 +16,7 @@
#endif
#if defined(OS_LINUX)
-#include "ui/events/platform/platform_event_observer.h"
+#include "ui/aura/window_event_dispatcher_observer.h"
#endif
#if defined(OS_WIN)
@@ -40,7 +41,7 @@ class CONTENT_EXPORT NativeEventObserver
#if defined(OS_MACOSX)
: public NativeEventProcessorObserver
#elif defined(OS_LINUX)
- : public ui::PlatformEventObserver
+ : public aura::WindowEventDispatcherObserver
#elif defined(OS_WIN)
: public base::MessagePumpForUI::Observer
#endif
@@ -73,10 +74,12 @@ class CONTENT_EXPORT NativeEventObserver
void DidRunNativeEvent(const void* opaque_identifier,
base::TimeTicks creation_time) override;
#elif defined(OS_LINUX)
- // PlatformEventObserver overrides:
- // Exposed for tests.
- void WillProcessEvent(const ui::PlatformEvent& event) override;
- void DidProcessEvent(const ui::PlatformEvent& event) override;
+ // aura::WindowEventDispatcherObserver overrides:
+ void OnWindowEventDispatcherStartedProcessing(
+ aura::WindowEventDispatcher* dispatcher,
+ const ui::Event& event) override;
+ void OnWindowEventDispatcherFinishedProcessingEvent(
+ aura::WindowEventDispatcher* dispatcher) override;
#elif defined(OS_WIN)
// base::MessagePumpForUI::Observer overrides:
void WillDispatchMSG(const MSG& msg) override;
@@ -87,6 +90,14 @@ class CONTENT_EXPORT NativeEventObserver
void RegisterObserver();
void DeregisterObserver();
+#if defined(OS_LINUX)
+ struct EventInfo {
+ const void* unique_id;
+ base::TimeTicks creation_time;
+ };
+ std::vector<EventInfo> events_being_processed_;
+#endif
+
WillRunEventCallback will_run_event_callback_;
DidRunEventCallback did_run_event_callback_;
diff --git a/chromium/content/browser/scheduler/responsiveness/watcher.cc b/chromium/content/browser/scheduler/responsiveness/watcher.cc
index 2e61f5db182..2cee5678737 100644
--- a/chromium/content/browser/scheduler/responsiveness/watcher.cc
+++ b/chromium/content/browser/scheduler/responsiveness/watcher.cc
@@ -5,9 +5,11 @@
#include "content/browser/scheduler/responsiveness/watcher.h"
#include "base/pending_task.h"
+#include "base/task/post_task.h"
#include "content/browser/scheduler/responsiveness/calculator.h"
#include "content/browser/scheduler/responsiveness/message_loop_observer.h"
#include "content/browser/scheduler/responsiveness/native_event_observer.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
namespace content {
@@ -30,11 +32,12 @@ void Watcher::SetUp() {
calculator_ = CreateCalculator();
native_event_observer_ui_ = CreateNativeEventObserver();
+ currently_running_metadata_ui_.reserve(5);
RegisterMessageLoopObserverUI();
- content::BrowserThread::PostTask(
- content::BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {content::BrowserThread::IO},
base::BindOnce(&Watcher::SetUpOnIOThread, base::Unretained(this),
calculator_.get()));
}
@@ -48,8 +51,8 @@ void Watcher::Destroy() {
message_loop_observer_ui_.reset();
native_event_observer_ui_.reset();
- content::BrowserThread::PostTask(
- content::BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {content::BrowserThread::IO},
base::BindOnce(&Watcher::TearDownOnIOThread, base::Unretained(this)));
}
@@ -96,6 +99,7 @@ void Watcher::RegisterMessageLoopObserverIO() {
void Watcher::SetUpOnIOThread(Calculator* calculator) {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ currently_running_metadata_io_.reserve(5);
RegisterMessageLoopObserverIO();
calculator_io_ = calculator;
}
@@ -106,8 +110,8 @@ void Watcher::TearDownOnIOThread() {
message_loop_observer_io_.reset();
calculator_io_ = nullptr;
- content::BrowserThread::PostTask(
- content::BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {content::BrowserThread::UI},
base::BindOnce(&Watcher::TearDownOnUIThread, base::Unretained(this)));
}
@@ -156,23 +160,23 @@ void Watcher::DidRunTaskOnIOThread(const base::PendingTask* task) {
}
void Watcher::WillRunTask(const base::PendingTask* task,
- std::stack<Metadata>* currently_running_metadata) {
+ std::vector<Metadata>* currently_running_metadata) {
// Reentrancy should be rare.
if (UNLIKELY(!currently_running_metadata->empty())) {
- currently_running_metadata->top().caused_reentrancy = true;
+ currently_running_metadata->back().caused_reentrancy = true;
}
- currently_running_metadata->emplace(task);
+ currently_running_metadata->emplace_back(task);
// For delayed tasks, record the time right before the task is run.
if (!task->delayed_run_time.is_null()) {
- currently_running_metadata->top().delayed_task_start =
+ currently_running_metadata->back().delayed_task_start =
base::TimeTicks::Now();
}
}
void Watcher::DidRunTask(const base::PendingTask* task,
- std::stack<Metadata>* currently_running_metadata,
+ std::vector<Metadata>* currently_running_metadata,
int* mismatched_task_identifiers,
TaskOrEventFinishedCallback callback) {
// Calls to DidRunTask should always be paired with WillRunTask. The only time
@@ -180,16 +184,16 @@ void Watcher::DidRunTask(const base::PendingTask* task,
// TaskRunner Observers may be added while a task is being run, which means
// that there was no corresponding WillRunTask.
if (UNLIKELY(currently_running_metadata->empty() ||
- (task != currently_running_metadata->top().identifier))) {
+ (task != currently_running_metadata->back().identifier))) {
*mismatched_task_identifiers += 1;
DCHECK_LE(*mismatched_task_identifiers, 1);
return;
}
- bool caused_reentrancy = currently_running_metadata->top().caused_reentrancy;
+ bool caused_reentrancy = currently_running_metadata->back().caused_reentrancy;
base::TimeTicks delayed_task_start =
- currently_running_metadata->top().delayed_task_start;
- currently_running_metadata->pop();
+ currently_running_metadata->back().delayed_task_start;
+ currently_running_metadata->pop_back();
// Ignore tasks that caused reentrancy, since their execution latency will
// be very large, but Chrome was still responsive.
@@ -218,10 +222,10 @@ void Watcher::WillRunEventOnUIThread(const void* opaque_identifier) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
// Reentrancy should be rare.
if (UNLIKELY(!currently_running_metadata_ui_.empty())) {
- currently_running_metadata_ui_.top().caused_reentrancy = true;
+ currently_running_metadata_ui_.back().caused_reentrancy = true;
}
- currently_running_metadata_ui_.emplace(opaque_identifier);
+ currently_running_metadata_ui_.emplace_back(opaque_identifier);
}
void Watcher::DidRunEventOnUIThread(const void* opaque_identifier,
@@ -234,15 +238,15 @@ void Watcher::DidRunEventOnUIThread(const void* opaque_identifier,
// task is being run, which means that there was no corresponding WillRunTask.
if (UNLIKELY(currently_running_metadata_ui_.empty() ||
(opaque_identifier !=
- currently_running_metadata_ui_.top().identifier))) {
+ currently_running_metadata_ui_.back().identifier))) {
mismatched_event_identifiers_ui_ += 1;
DCHECK_LE(mismatched_event_identifiers_ui_, 1);
return;
}
bool caused_reentrancy =
- currently_running_metadata_ui_.top().caused_reentrancy;
- currently_running_metadata_ui_.pop();
+ currently_running_metadata_ui_.back().caused_reentrancy;
+ currently_running_metadata_ui_.pop_back();
// Ignore events that caused reentrancy, since their execution latency will
// be very large, but Chrome was still responsive.
diff --git a/chromium/content/browser/scheduler/responsiveness/watcher.h b/chromium/content/browser/scheduler/responsiveness/watcher.h
index 0e6d3edfce7..b8f516de6ad 100644
--- a/chromium/content/browser/scheduler/responsiveness/watcher.h
+++ b/chromium/content/browser/scheduler/responsiveness/watcher.h
@@ -6,7 +6,7 @@
#define CONTENT_BROWSER_SCHEDULER_RESPONSIVENESS_WATCHER_H_
#include <memory>
-#include <stack>
+#include <vector>
#include "base/callback.h"
#include "base/gtest_prod_util.h"
@@ -98,13 +98,13 @@ class CONTENT_EXPORT Watcher : public base::RefCounted<Watcher> {
// Common implementations for the thread-specific methods.
void WillRunTask(const base::PendingTask* task,
- std::stack<Metadata>* currently_running_metadata);
+ std::vector<Metadata>* currently_running_metadata);
// |callback| will either be synchronously invoked, or else never invoked.
using TaskOrEventFinishedCallback =
base::OnceCallback<void(base::TimeTicks, base::TimeTicks)>;
void DidRunTask(const base::PendingTask* task,
- std::stack<Metadata>* currently_running_metadata,
+ std::vector<Metadata>* currently_running_metadata,
int* mismatched_task_identifiers,
TaskOrEventFinishedCallback callback);
@@ -120,7 +120,7 @@ class CONTENT_EXPORT Watcher : public base::RefCounted<Watcher> {
std::unique_ptr<NativeEventObserver> native_event_observer_ui_;
// Metadata for currently running tasks and events on the UI thread.
- std::stack<Metadata> currently_running_metadata_ui_;
+ std::vector<Metadata> currently_running_metadata_ui_;
// Task identifiers should only be mismatched once, since the Watcher may
// register itself during a Task execution, and thus doesn't capture the
@@ -133,7 +133,7 @@ class CONTENT_EXPORT Watcher : public base::RefCounted<Watcher> {
int mismatched_event_identifiers_ui_ = 0;
// The following members are all affine to the IO thread.
- std::stack<Metadata> currently_running_metadata_io_;
+ std::vector<Metadata> currently_running_metadata_io_;
int mismatched_task_identifiers_io_ = 0;
std::unique_ptr<MessageLoopObserver> message_loop_observer_io_;
diff --git a/chromium/content/browser/scheduler/responsiveness/watcher_unittest.cc b/chromium/content/browser/scheduler/responsiveness/watcher_unittest.cc
index c80be85babb..fd6ded28069 100644
--- a/chromium/content/browser/scheduler/responsiveness/watcher_unittest.cc
+++ b/chromium/content/browser/scheduler/responsiveness/watcher_unittest.cc
@@ -8,9 +8,11 @@
#include "base/pending_task.h"
#include "base/run_loop.h"
#include "base/synchronization/lock.h"
+#include "base/task/post_task.h"
#include "build/build_config.h"
#include "content/browser/scheduler/responsiveness/calculator.h"
#include "content/browser/scheduler/responsiveness/native_event_observer.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -206,24 +208,24 @@ class ResponsivenessWatcherRealIOThreadTest : public testing::Test {
#endif
TEST_F(ResponsivenessWatcherRealIOThreadTest, MAYBE_MessageLoopObserver) {
// Post a do-nothing task onto the UI thread.
- content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
- base::BindOnce([]() {}));
+ base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI},
+ base::BindOnce([]() {}));
// Post a do-nothing task onto the IO thread.
- content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
- base::BindOnce([]() {}));
+ base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO},
+ base::BindOnce([]() {}));
// Post a task onto the IO thread that hops back to the UI thread. This
// guarantees that both of the do-nothing tasks have already been processed.
base::RunLoop run_loop;
- content::BrowserThread::PostTask(
- content::BrowserThread::IO, FROM_HERE,
- base::BindOnce(
- [](base::OnceClosure quit_closure) {
- content::BrowserThread::PostTask(
- content::BrowserThread::UI, FROM_HERE, std::move(quit_closure));
- },
- run_loop.QuitClosure()));
+ base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO},
+ base::BindOnce(
+ [](base::OnceClosure quit_closure) {
+ base::PostTaskWithTraits(
+ FROM_HERE, {content::BrowserThread::UI},
+ std::move(quit_closure));
+ },
+ run_loop.QuitClosure()));
run_loop.Run();
ASSERT_GE(watcher_->NumTasksOnUIThread(), 1);
diff --git a/chromium/content/browser/screen_orientation/screen_orientation_browsertest.cc b/chromium/content/browser/screen_orientation/screen_orientation_browsertest.cc
index 45bd8008d22..199b8cd580c 100644
--- a/chromium/content/browser/screen_orientation/screen_orientation_browsertest.cc
+++ b/chromium/content/browser/screen_orientation/screen_orientation_browsertest.cc
@@ -346,7 +346,7 @@ IN_PROC_BROWSER_TEST_F(ScreenOrientationOOPIFBrowserTest, ScreenOrientation) {
// Regression test for triggering a screen orientation change for a pending
// main frame RenderFrameHost. See https://crbug.com/764202. In the bug, this
// was triggered via the DevTools audit panel and
-// ViewMsg_EnableDeviceEmulation, which calls RenderWidget::Resize on the
+// WidgetMsg_EnableDeviceEmulation, which calls RenderWidget::Resize on the
// renderer side. The test fakes this by directly sending the resize message
// to the widget.
IN_PROC_BROWSER_TEST_F(ScreenOrientationOOPIFBrowserTest,
diff --git a/chromium/content/browser/screenlock_monitor/OWNERS b/chromium/content/browser/screenlock_monitor/OWNERS
new file mode 100644
index 00000000000..f32afb48692
--- /dev/null
+++ b/chromium/content/browser/screenlock_monitor/OWNERS
@@ -0,0 +1 @@
+braveyao@chromium.org \ No newline at end of file
diff --git a/chromium/content/browser/screenlock_monitor/screenlock_monitor.cc b/chromium/content/browser/screenlock_monitor/screenlock_monitor.cc
new file mode 100644
index 00000000000..f15322babe6
--- /dev/null
+++ b/chromium/content/browser/screenlock_monitor/screenlock_monitor.cc
@@ -0,0 +1,56 @@
+// 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/screenlock_monitor/screenlock_monitor.h"
+
+#include "base/trace_event/trace_event.h"
+#include "content/browser/screenlock_monitor/screenlock_monitor_source.h"
+
+namespace content {
+
+static ScreenlockMonitor* g_screenlock_monitor = nullptr;
+
+ScreenlockMonitor::ScreenlockMonitor(
+ std::unique_ptr<ScreenlockMonitorSource> source)
+ : observers_(new base::ObserverListThreadSafe<ScreenlockObserver>()),
+ source_(std::move(source)) {
+ DCHECK(!g_screenlock_monitor);
+ g_screenlock_monitor = this;
+}
+
+ScreenlockMonitor::~ScreenlockMonitor() {
+ DCHECK_EQ(this, g_screenlock_monitor);
+ g_screenlock_monitor = nullptr;
+}
+
+// static
+ScreenlockMonitor* ScreenlockMonitor::Get() {
+ return g_screenlock_monitor;
+}
+
+void ScreenlockMonitor::AddObserver(ScreenlockObserver* obs) {
+ observers_->AddObserver(obs);
+}
+
+void ScreenlockMonitor::RemoveObserver(ScreenlockObserver* obs) {
+ observers_->RemoveObserver(obs);
+}
+
+void ScreenlockMonitor::NotifyScreenLocked() {
+ TRACE_EVENT_INSTANT0("screenlock_monitor",
+ "ScreenlockMonitor::NotifyScreenLocked",
+ TRACE_EVENT_SCOPE_GLOBAL);
+ DVLOG(1) << "Screen Locked";
+ observers_->Notify(FROM_HERE, &ScreenlockObserver::OnScreenLocked);
+}
+
+void ScreenlockMonitor::NotifyScreenUnlocked() {
+ TRACE_EVENT_INSTANT0("screenlock_monitor",
+ "ScreenlockMonitor::NotifyScreenUnlocked",
+ TRACE_EVENT_SCOPE_GLOBAL);
+ DVLOG(1) << "Screen Unlocked";
+ observers_->Notify(FROM_HERE, &ScreenlockObserver::OnScreenUnlocked);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/screenlock_monitor/screenlock_monitor.h b/chromium/content/browser/screenlock_monitor/screenlock_monitor.h
new file mode 100644
index 00000000000..81b1e7c867c
--- /dev/null
+++ b/chromium/content/browser/screenlock_monitor/screenlock_monitor.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_SCREENLOCK_MONITOR_SCREENLOCK_MONITOR_H_
+#define CONTENT_BROWSER_SCREENLOCK_MONITOR_SCREENLOCK_MONITOR_H_
+
+#include <memory>
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/observer_list_threadsafe.h"
+#include "content/common/content_export.h"
+#include "content/public/browser/screenlock_observer.h"
+
+namespace content {
+
+class ScreenlockMonitorSource;
+
+// A class used to monitor the screenlock state change and notify the observers
+// about the change event.
+// Currently available on Win/MacOSX/ChromOS only.
+// TODO(crbug.com/887585): Keep studying for a solid way to do this on Linux.
+class CONTENT_EXPORT ScreenlockMonitor {
+ public:
+ ScreenlockMonitor(std::unique_ptr<ScreenlockMonitorSource> source);
+ ~ScreenlockMonitor();
+
+ // Get the process-wide ScreenlockMonitor (if not present, returns NULL).
+ static ScreenlockMonitor* Get();
+
+ // Add and remove an observer.
+ // Can be called from any thread. |observer| is notified on the sequence
+ // from which it was registered.
+ // Must not be called from within a notification callback.
+ void AddObserver(ScreenlockObserver* observer);
+ void RemoveObserver(ScreenlockObserver* observer);
+
+ private:
+ friend class ScreenlockMonitorSource;
+
+ void NotifyScreenLocked();
+ void NotifyScreenUnlocked();
+
+ scoped_refptr<base::ObserverListThreadSafe<ScreenlockObserver>> observers_;
+ std::unique_ptr<ScreenlockMonitorSource> source_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScreenlockMonitor);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_SCREENLOCK_MONITOR_SCREENLOCK_MONITOR_H_ \ No newline at end of file
diff --git a/chromium/content/browser/screenlock_monitor/screenlock_monitor_device_source.cc b/chromium/content/browser/screenlock_monitor/screenlock_monitor_device_source.cc
new file mode 100644
index 00000000000..0a5bdeea5be
--- /dev/null
+++ b/chromium/content/browser/screenlock_monitor/screenlock_monitor_device_source.cc
@@ -0,0 +1,21 @@
+// 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/screenlock_monitor/screenlock_monitor_device_source.h"
+
+namespace content {
+
+ScreenlockMonitorDeviceSource::ScreenlockMonitorDeviceSource() {
+#if defined(OS_MACOSX)
+ StartListeningForScreenlock();
+#endif // OS_MACOSX
+}
+
+ScreenlockMonitorDeviceSource::~ScreenlockMonitorDeviceSource() {
+#if defined(OS_MACOSX)
+ StopListeningForScreenlock();
+#endif // OS_MACOSX
+}
+
+} // namespace content
diff --git a/chromium/content/browser/screenlock_monitor/screenlock_monitor_device_source.h b/chromium/content/browser/screenlock_monitor/screenlock_monitor_device_source.h
new file mode 100644
index 00000000000..8d70faea1dc
--- /dev/null
+++ b/chromium/content/browser/screenlock_monitor/screenlock_monitor_device_source.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_BROWSER_SCREENLOCK_MONITOR_SCREENLOCK_MONITOR_DEVICE_SOURCE_H_
+#define CONTENT_BROWSER_SCREENLOCK_MONITOR_SCREENLOCK_MONITOR_DEVICE_SOURCE_H_
+
+#include <memory>
+
+#include "base/macros.h"
+#include "build/build_config.h"
+#include "content/browser/screenlock_monitor/screenlock_monitor_source.h"
+#include "content/common/content_export.h"
+
+#if defined(OS_WIN)
+#include <windows.h>
+#include <wtsapi32.h>
+#endif // OS_WIN
+
+#if defined(OS_CHROMEOS)
+#include "components/session_manager/core/session_manager_observer.h"
+#endif // OS_CHROMEOS
+
+#if defined(OS_WIN)
+namespace base {
+namespace win {
+class MessageWindow;
+}
+} // namespace base
+#endif // OS_WIN
+
+namespace content {
+
+// A class used to monitor the screenlock state change on each supported
+// platform and notify the change event to monitor.
+class CONTENT_EXPORT ScreenlockMonitorDeviceSource
+ : public ScreenlockMonitorSource {
+ public:
+ ScreenlockMonitorDeviceSource();
+ ~ScreenlockMonitorDeviceSource() override;
+
+ private:
+#if defined(OS_WIN)
+ // Represents a message-only window for screenlock message handling on Win.
+ // Only allow ScreenlockMonitor to create it.
+ class SessionMessageWindow {
+ public:
+ SessionMessageWindow();
+ ~SessionMessageWindow();
+
+ private:
+ bool OnWndProc(UINT message, WPARAM wparam, LPARAM lparam, LRESULT* result);
+ void ProcessWTSSessionLockMessage(WPARAM event_id);
+
+ std::unique_ptr<base::win::MessageWindow> window_;
+
+ DISALLOW_COPY_AND_ASSIGN(SessionMessageWindow);
+ };
+
+ SessionMessageWindow session_message_window_;
+#endif // OS_WIN
+
+#if defined(OS_MACOSX)
+ void StartListeningForScreenlock();
+ void StopListeningForScreenlock();
+#endif // OS_MACOSX
+
+#if defined(OS_CHROMEOS)
+ class ScreenLockListener : public session_manager::SessionManagerObserver {
+ public:
+ ScreenLockListener();
+ ~ScreenLockListener() override;
+
+ // session_manager::SessionManagerObserver:
+ void OnSessionStateChanged() override;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ScreenLockListener);
+ };
+
+ ScreenLockListener screenlock_listener_;
+#endif // OS_CHROMEOS
+
+ DISALLOW_COPY_AND_ASSIGN(ScreenlockMonitorDeviceSource);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_SCREENLOCK_MONITOR_SCREENLOCK_MONITOR_DEVICE_SOURCE_H_
diff --git a/chromium/content/browser/screenlock_monitor/screenlock_monitor_device_source_chromeos.cc b/chromium/content/browser/screenlock_monitor/screenlock_monitor_device_source_chromeos.cc
new file mode 100644
index 00000000000..3cbd2441bf7
--- /dev/null
+++ b/chromium/content/browser/screenlock_monitor/screenlock_monitor_device_source_chromeos.cc
@@ -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.
+
+#include "content/browser/screenlock_monitor/screenlock_monitor_device_source.h"
+
+#include "components/session_manager/core/session_manager.h"
+
+namespace content {
+
+ScreenlockMonitorDeviceSource::ScreenLockListener::ScreenLockListener() {
+ if (session_manager::SessionManager::Get()) {
+ session_manager::SessionManager::Get()->AddObserver(this);
+ }
+}
+
+ScreenlockMonitorDeviceSource::ScreenLockListener::~ScreenLockListener() {
+ if (session_manager::SessionManager::Get()) {
+ session_manager::SessionManager::Get()->RemoveObserver(this);
+ }
+}
+
+void ScreenlockMonitorDeviceSource::ScreenLockListener::
+ OnSessionStateChanged() {
+ ScreenlockEvent screenlock_event;
+ if (session_manager::SessionManager::Get()->IsScreenLocked()) {
+ screenlock_event = SCREEN_LOCK_EVENT;
+ } else {
+ screenlock_event = SCREEN_UNLOCK_EVENT;
+ }
+
+ ProcessScreenlockEvent(screenlock_event);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/screenlock_monitor/screenlock_monitor_device_source_mac.mm b/chromium/content/browser/screenlock_monitor/screenlock_monitor_device_source_mac.mm
new file mode 100644
index 00000000000..883372720ce
--- /dev/null
+++ b/chromium/content/browser/screenlock_monitor/screenlock_monitor_device_source_mac.mm
@@ -0,0 +1,52 @@
+// 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/screenlock_monitor/screenlock_monitor_device_source.h"
+
+#include <CoreFoundation/CoreFoundation.h>
+
+namespace content {
+
+namespace {
+
+CFStringRef kScreenLockedEvent = CFSTR("com.apple.screenIsLocked");
+CFStringRef kScreenUnlockedEvent = CFSTR("com.apple.screenIsUnlocked");
+
+void OnScreenlockNotificationReceived(CFNotificationCenterRef center,
+ void* observer,
+ CFStringRef name,
+ const void* object,
+ CFDictionaryRef userInfo) {
+ ScreenlockMonitorSource::ScreenlockEvent screenlock_event;
+ if (CFEqual(name, kScreenLockedEvent)) {
+ screenlock_event = ScreenlockMonitorSource::SCREEN_LOCK_EVENT;
+ } else if (CFEqual(name, kScreenUnlockedEvent)) {
+ screenlock_event = ScreenlockMonitorSource::SCREEN_UNLOCK_EVENT;
+ } else {
+ return;
+ }
+
+ ScreenlockMonitorSource::ProcessScreenlockEvent(screenlock_event);
+}
+
+} // namespace
+
+void ScreenlockMonitorDeviceSource::StartListeningForScreenlock() {
+ CFNotificationCenterAddObserver(
+ CFNotificationCenterGetDistributedCenter(), this,
+ &OnScreenlockNotificationReceived, kScreenLockedEvent, nullptr,
+ CFNotificationSuspensionBehaviorDeliverImmediately);
+
+ CFNotificationCenterAddObserver(
+ CFNotificationCenterGetDistributedCenter(), this,
+ &OnScreenlockNotificationReceived, kScreenUnlockedEvent, nullptr,
+ CFNotificationSuspensionBehaviorDeliverImmediately);
+}
+
+void ScreenlockMonitorDeviceSource::StopListeningForScreenlock() {
+ CFNotificationCenterRemoveEveryObserver(
+ CFNotificationCenterGetDistributedCenter(), this);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/screenlock_monitor/screenlock_monitor_device_source_win.cc b/chromium/content/browser/screenlock_monitor/screenlock_monitor_device_source_win.cc
new file mode 100644
index 00000000000..486470e3d64
--- /dev/null
+++ b/chromium/content/browser/screenlock_monitor/screenlock_monitor_device_source_win.cc
@@ -0,0 +1,70 @@
+// 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/screenlock_monitor/screenlock_monitor_device_source.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/task/post_task.h"
+#include "base/win/message_window.h"
+
+namespace content {
+
+ScreenlockMonitorDeviceSource::SessionMessageWindow::SessionMessageWindow() {
+ // Create a window for receiving session change notifications.
+ window_.reset(new base::win::MessageWindow());
+ if (!window_->Create(base::BindRepeating(&SessionMessageWindow::OnWndProc,
+ base::Unretained(this)))) {
+ DLOG(ERROR) << "Failed to create the screenlock monitor window.";
+ window_.reset();
+ return;
+ }
+
+ base::OnceClosure wts_register =
+ base::BindOnce(base::IgnoreResult(&::WTSRegisterSessionNotification),
+ window_->hwnd(), NOTIFY_FOR_ALL_SESSIONS);
+
+ base::CreateCOMSTATaskRunnerWithTraits({})->PostTask(FROM_HERE,
+ std::move(wts_register));
+}
+
+ScreenlockMonitorDeviceSource::SessionMessageWindow::~SessionMessageWindow() {
+ // There should be no race condition between this code and the worker thread.
+ // WTSUnRegisterSessionNotification is only called from destruction as we are
+ // in shutdown, which means no other worker threads can be running.
+ if (window_) {
+ ::WTSUnRegisterSessionNotification(window_->hwnd());
+ window_.reset();
+ }
+}
+
+bool ScreenlockMonitorDeviceSource::SessionMessageWindow::OnWndProc(
+ UINT message,
+ WPARAM wparam,
+ LPARAM lparam,
+ LRESULT* result) {
+ if (message == WM_WTSSESSION_CHANGE) {
+ ProcessWTSSessionLockMessage(wparam);
+ }
+ return true;
+}
+
+void ScreenlockMonitorDeviceSource::SessionMessageWindow::
+ ProcessWTSSessionLockMessage(WPARAM event_id) {
+ ScreenlockEvent screenlock_event;
+ switch (event_id) {
+ case WTS_SESSION_LOCK:
+ screenlock_event = SCREEN_LOCK_EVENT;
+ break;
+ case WTS_SESSION_UNLOCK:
+ screenlock_event = SCREEN_UNLOCK_EVENT;
+ break;
+ default:
+ return;
+ }
+
+ ProcessScreenlockEvent(screenlock_event);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/screenlock_monitor/screenlock_monitor_source.cc b/chromium/content/browser/screenlock_monitor/screenlock_monitor_source.cc
new file mode 100644
index 00000000000..ef61bd3cf5e
--- /dev/null
+++ b/chromium/content/browser/screenlock_monitor/screenlock_monitor_source.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/screenlock_monitor/screenlock_monitor_source.h"
+
+#include "content/browser/screenlock_monitor/screenlock_monitor.h"
+
+namespace content {
+
+ScreenlockMonitorSource::ScreenlockMonitorSource() = default;
+ScreenlockMonitorSource::~ScreenlockMonitorSource() = default;
+
+// static
+void ScreenlockMonitorSource::ProcessScreenlockEvent(ScreenlockEvent event_id) {
+ ScreenlockMonitor* monitor = ScreenlockMonitor::Get();
+ if (!monitor) {
+ return;
+ }
+
+ switch (event_id) {
+ case SCREEN_LOCK_EVENT:
+ monitor->NotifyScreenLocked();
+ break;
+ case SCREEN_UNLOCK_EVENT:
+ monitor->NotifyScreenUnlocked();
+ break;
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/browser/screenlock_monitor/screenlock_monitor_source.h b/chromium/content/browser/screenlock_monitor/screenlock_monitor_source.h
new file mode 100644
index 00000000000..6a7f5dcc608
--- /dev/null
+++ b/chromium/content/browser/screenlock_monitor/screenlock_monitor_source.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_SCREENLOCK_MONITOR_SCREENLOCK_MONITOR_SOURCE_H_
+#define CONTENT_BROWSER_SCREENLOCK_MONITOR_SCREENLOCK_MONITOR_SOURCE_H_
+
+#include "base/macros.h"
+#include "content/common/content_export.h"
+
+namespace content {
+
+// A class to communicate screenlock state changes from each platform-specific
+// sub-class source implementation to the screenlock monitor.
+class CONTENT_EXPORT ScreenlockMonitorSource {
+ public:
+ ScreenlockMonitorSource();
+ virtual ~ScreenlockMonitorSource();
+
+ enum ScreenlockEvent { SCREEN_LOCK_EVENT, SCREEN_UNLOCK_EVENT };
+
+ // ProcessScreenlockEvent should only be called from a single thread.
+ static void ProcessScreenlockEvent(ScreenlockEvent event_id);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ScreenlockMonitorSource);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_SCREENLOCK_MONITOR_SCREENLOCK_MONITOR_SOURCE_H_
diff --git a/chromium/content/browser/screenlock_monitor/screenlock_monitor_unittest.cc b/chromium/content/browser/screenlock_monitor/screenlock_monitor_unittest.cc
new file mode 100644
index 00000000000..5f2da1f620b
--- /dev/null
+++ b/chromium/content/browser/screenlock_monitor/screenlock_monitor_unittest.cc
@@ -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.
+
+#include "content/browser/screenlock_monitor/screenlock_monitor.h"
+
+#include "base/macros.h"
+#include "base/message_loop/message_loop.h"
+#include "base/message_loop/message_loop_current.h"
+#include "base/run_loop.h"
+#include "content/browser/screenlock_monitor/screenlock_monitor_source.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+class ScreenlockMonitorTestSource : public ScreenlockMonitorSource {
+ public:
+ ScreenlockMonitorTestSource() {
+ DCHECK(base::MessageLoopCurrent::Get())
+ << "ScreenlocMonitorTestSource requires a MessageLoop.";
+ }
+ ~ScreenlockMonitorTestSource() override = default;
+
+ void GenerateScreenLockedEvent() {
+ ProcessScreenlockEvent(SCREEN_LOCK_EVENT);
+ base::RunLoop().RunUntilIdle();
+ }
+
+ void GenerateScreenUnlockedEvent() {
+ ProcessScreenlockEvent(SCREEN_UNLOCK_EVENT);
+ base::RunLoop().RunUntilIdle();
+ }
+};
+
+class ScreenlockMonitorTestObserver : public ScreenlockObserver {
+ public:
+ ScreenlockMonitorTestObserver() : is_screen_locked_(false) {}
+ ~ScreenlockMonitorTestObserver() override = default;
+
+ // ScreenlockObserver callbacks.
+ void OnScreenLocked() override { is_screen_locked_ = true; }
+ void OnScreenUnlocked() override { is_screen_locked_ = false; }
+
+ bool IsScreenLocked() { return is_screen_locked_; }
+
+ private:
+ bool is_screen_locked_;
+};
+
+class ScreenlockMonitorTest : public testing::Test {
+ protected:
+ ScreenlockMonitorTest() {
+ screenlock_monitor_source_ = new ScreenlockMonitorTestSource();
+ screenlock_monitor_ = std::make_unique<ScreenlockMonitor>(
+ std::unique_ptr<ScreenlockMonitorSource>(screenlock_monitor_source_));
+ }
+ ~ScreenlockMonitorTest() override = default;
+
+ protected:
+ ScreenlockMonitorTestSource* screenlock_monitor_source_;
+ std::unique_ptr<ScreenlockMonitor> screenlock_monitor_;
+
+ private:
+ base::MessageLoop message_loop_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScreenlockMonitorTest);
+};
+
+TEST_F(ScreenlockMonitorTest, ScreenlockNotifications) {
+ const int kObservers = 5;
+
+ ScreenlockMonitorTestObserver observers[kObservers];
+ for (int index = 0; index < kObservers; ++index)
+ screenlock_monitor_->AddObserver(&observers[index]);
+
+ // Pretend screen is locked.
+ screenlock_monitor_source_->GenerateScreenLockedEvent();
+ // Ensure all observers were notified of the event
+ for (int index = 0; index < kObservers; ++index)
+ EXPECT_TRUE(observers[index].IsScreenLocked());
+
+ // Pretend screen is unlocked.
+ screenlock_monitor_source_->GenerateScreenUnlockedEvent();
+ // Ensure all observers were notified of the event
+ for (int index = 0; index < kObservers; ++index)
+ EXPECT_FALSE(observers[index].IsScreenLocked());
+}
+
+} // namespace content \ No newline at end of file
diff --git a/chromium/content/browser/security_exploit_browsertest.cc b/chromium/content/browser/security_exploit_browsertest.cc
index e9cb49ebc81..82af6087231 100644
--- a/chromium/content/browser/security_exploit_browsertest.cc
+++ b/chromium/content/browser/security_exploit_browsertest.cc
@@ -9,12 +9,15 @@
#include "base/feature_list.h"
#include "base/macros.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/task/post_task.h"
+#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "content/browser/bad_message.h"
#include "content/browser/dom_storage/dom_storage_context_wrapper.h"
#include "content/browser/dom_storage/session_storage_namespace_impl.h"
#include "content/browser/frame_host/navigator.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
+#include "content/browser/frame_host/render_frame_proxy_host.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/renderer_host/render_view_host_factory.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
@@ -23,7 +26,9 @@
#include "content/common/frame_messages.h"
#include "content/common/render_message_filter.mojom.h"
#include "content/common/view_messages.h"
+#include "content/public/browser/blob_handle.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/interstitial_page.h"
@@ -34,7 +39,6 @@
#include "content/public/common/appcache_info.h"
#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/common/content_switches.h"
-#include "content/public/common/file_chooser_params.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"
@@ -46,6 +50,7 @@
#include "content/test/mock_widget_impl.h"
#include "content/test/test_content_browser_client.h"
#include "ipc/ipc_security_test_util.h"
+#include "mojo/public/cpp/bindings/strong_associated_binding.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/url_request/url_request_slow_download_job.h"
@@ -55,6 +60,8 @@
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/mojom/url_loader.mojom.h"
#include "services/network/test/test_url_loader_client.h"
+#include "storage/browser/blob/blob_registry_impl.h"
+#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/web/web_triggering_event_info.h"
using IPC::IpcSecurityTestUtil;
@@ -145,6 +152,55 @@ network::ResourceRequest CreateXHRRequestWithOrigin(const char* origin) {
return request;
}
+std::unique_ptr<content::BlobHandle> CreateMemoryBackedBlob(
+ BrowserContext* browser_context,
+ const std::string& contents,
+ const std::string& content_type) {
+ std::unique_ptr<content::BlobHandle> result;
+ base::RunLoop loop;
+ BrowserContext::CreateMemoryBackedBlob(
+ browser_context, contents.c_str(), contents.length(), content_type,
+ base::BindOnce(
+ [](std::unique_ptr<content::BlobHandle>* out_blob,
+ base::OnceClosure done,
+ std::unique_ptr<content::BlobHandle> blob) {
+ *out_blob = std::move(blob);
+ std::move(done).Run();
+ },
+ &result, loop.QuitClosure()));
+ loop.Run();
+ EXPECT_TRUE(result);
+ return result;
+}
+
+// Helper class to interpose on Blob URL registrations, replacing the URL
+// contained in incoming registration requests with the specified URL.
+class BlobURLStoreInterceptor
+ : public blink::mojom::BlobURLStoreInterceptorForTesting {
+ public:
+ explicit BlobURLStoreInterceptor(GURL target_url) : target_url_(target_url) {}
+
+ void Intercept(
+ mojo::StrongAssociatedBindingPtr<blink::mojom::BlobURLStore> binding) {
+ url_store_ = binding->SwapImplForTesting(this);
+ }
+
+ blink::mojom::BlobURLStore* GetForwardingInterface() override {
+ return url_store_;
+ }
+
+ void Register(blink::mojom::BlobPtr blob,
+ const GURL& url,
+ RegisterCallback callback) override {
+ GetForwardingInterface()->Register(std::move(blob), target_url_,
+ std::move(callback));
+ }
+
+ private:
+ blink::mojom::BlobURLStore* url_store_;
+ GURL target_url_;
+};
+
} // namespace
// The goal of these tests will be to "simulate" exploited renderer processes,
@@ -178,32 +234,33 @@ class SecurityExploitBrowserTest : public ContentBrowserTest {
// initialization, ref. comment on InitializeAndListen() above.
embedded_test_server()->StartAcceptingConnections();
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&net::URLRequestSlowDownloadJob::AddUrlHandler));
}
static void CreateLoaderAndStart(
- RenderProcessHost* process,
+ RenderFrameHost* frame,
int route_id,
int request_id,
const network::ResourceRequest& resource_request) {
network::mojom::URLLoaderPtr loader;
network::TestURLLoaderClient client;
- CreateLoaderAndStart(process, mojo::MakeRequest(&loader), route_id,
+ CreateLoaderAndStart(frame, mojo::MakeRequest(&loader), route_id,
request_id, resource_request,
client.CreateInterfacePtr().PassInterface());
}
static void CreateLoaderAndStart(
- RenderProcessHost* process,
+ RenderFrameHost* frame,
network::mojom::URLLoaderRequest request,
int route_id,
int request_id,
const network::ResourceRequest& resource_request,
network::mojom::URLLoaderClientPtrInfo client) {
network::mojom::URLLoaderFactoryPtr factory;
- process->CreateURLLoaderFactory(mojo::MakeRequest(&factory));
+ frame->GetProcess()->CreateURLLoaderFactory(frame->GetLastCommittedOrigin(),
+ mojo::MakeRequest(&factory));
factory->CreateLoaderAndStart(
std::move(request), route_id, request_id,
network::mojom::kURLLoadOptionNone, resource_request,
@@ -234,12 +291,12 @@ class SecurityExploitBrowserTest : public ContentBrowserTest {
network::mojom::URLLoaderPtr loader1, loader2;
network::TestURLLoaderClient client1, client2;
- CreateLoaderAndStart(rfh->GetProcess(), mojo::MakeRequest(&loader1),
- rfh->GetRoutingID(), kRequestIdNotPreviouslyUsed,
- request, client1.CreateInterfacePtr().PassInterface());
- CreateLoaderAndStart(rfh->GetProcess(), mojo::MakeRequest(&loader2),
- rfh->GetRoutingID(), kRequestIdNotPreviouslyUsed,
- request, client2.CreateInterfacePtr().PassInterface());
+ CreateLoaderAndStart(rfh, mojo::MakeRequest(&loader1), rfh->GetRoutingID(),
+ kRequestIdNotPreviouslyUsed, request,
+ client1.CreateInterfacePtr().PassInterface());
+ CreateLoaderAndStart(rfh, mojo::MakeRequest(&loader2), rfh->GetRoutingID(),
+ kRequestIdNotPreviouslyUsed, request,
+ client2.CreateInterfacePtr().PassInterface());
EXPECT_EQ(bad_message::RDH_INVALID_REQUEST_ID, kill_waiter.Wait());
}
@@ -259,7 +316,7 @@ void SecurityExploitBrowserTest::TestFileChooserWithPath(
shell()->web_contents()->GetMainFrame();
RenderProcessHostKillWaiter kill_waiter(compromised_renderer->GetProcess());
- FileChooserParams params;
+ blink::mojom::FileChooserParams params;
params.default_file_name = path;
FrameHostMsg_RunFileChooser evil(compromised_renderer->GetRoutingID(),
@@ -331,8 +388,8 @@ IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest,
// different timing in the test, let's simulate a CreateNewWidget call coming
// from the IO thread. Use the existing window routing id to cause a
// deliberate collision.
- pending_rfh->render_view_host()->CreateNewWidget(
- duplicate_routing_id, std::move(widget), blink::kWebPopupTypePage);
+ pending_rfh->render_view_host()->CreateNewWidget(duplicate_routing_id,
+ std::move(widget));
// If the above operation doesn't crash, the test has succeeded!
}
@@ -476,7 +533,7 @@ IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, InvalidOriginHeaders) {
{
RenderProcessHostKillWaiter kill_waiter(web_rfh->GetProcess());
- CreateLoaderAndStart(web_rfh->GetProcess(), web_rfh->GetRoutingID(),
+ CreateLoaderAndStart(web_rfh, web_rfh->GetRoutingID(),
kRequestIdNotPreviouslyUsed, chrome_origin_msg);
EXPECT_EQ(bad_message::RDH_ILLEGAL_ORIGIN, kill_waiter.Wait());
}
@@ -491,7 +548,7 @@ IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, InvalidOriginHeaders) {
"Origin", "", base::Bind(&OnHttpHeaderReceived));
RenderProcessHostKillWaiter kill_waiter(web_rfh->GetProcess());
- CreateLoaderAndStart(web_rfh->GetProcess(), web_rfh->GetRoutingID(),
+ CreateLoaderAndStart(web_rfh, web_rfh->GetRoutingID(),
kRequestIdNotPreviouslyUsed,
embedder_isolated_origin_msg);
EXPECT_EQ(bad_message::RDH_ILLEGAL_ORIGIN, kill_waiter.Wait());
@@ -501,7 +558,7 @@ IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, InvalidOriginHeaders) {
NavigateToURL(shell(), web_url);
{
RenderProcessHostKillWaiter kill_waiter(web_rfh->GetProcess());
- CreateLoaderAndStart(web_rfh->GetProcess(), web_rfh->GetRoutingID(),
+ CreateLoaderAndStart(web_rfh, web_rfh->GetRoutingID(),
kRequestIdNotPreviouslyUsed, invalid_origin_msg);
EXPECT_EQ(bad_message::RDH_ILLEGAL_ORIGIN, kill_waiter.Wait());
}
@@ -510,7 +567,7 @@ IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, InvalidOriginHeaders) {
NavigateToURL(shell(), web_url);
{
RenderProcessHostKillWaiter kill_waiter(web_rfh->GetProcess());
- CreateLoaderAndStart(web_rfh->GetProcess(), web_rfh->GetRoutingID(),
+ CreateLoaderAndStart(web_rfh, web_rfh->GetRoutingID(),
kRequestIdNotPreviouslyUsed,
invalid_scheme_origin_msg);
EXPECT_EQ(bad_message::RDH_ILLEGAL_ORIGIN, kill_waiter.Wait());
@@ -768,4 +825,231 @@ IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, PageStateToWrongEntry) {
ASSERT_EQ(child1_url, child1->current_url());
}
+// Check that when site isolation is enabled, an origin can't create a blob URL
+// for a different origin. See https://crbug.com/886976.
+IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest,
+ CreateBlobURLInDifferentOrigin) {
+ IsolateAllSitesForTesting(base::CommandLine::ForCurrentProcess());
+
+ GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+ RenderFrameHost* rfh = shell()->web_contents()->GetMainFrame();
+
+ // All these are attacker controlled values.
+ std::string blob_type = "text/html";
+ std::string blob_contents = "<html><body>pwned.</body></html>";
+ std::string blob_path = "5881f76e-10d2-410d-8c61-ef210502acfd";
+
+ // Target a different origin.
+ std::string target_origin = "http://b.com";
+
+ // Set up a blob ID and populate it with attacker-controlled value. This
+ // is just using the blob APIs directly since creating arbitrary blobs is not
+ // what is prohibited; this data is not in any origin.
+ std::unique_ptr<BlobHandle> blob = CreateMemoryBackedBlob(
+ rfh->GetSiteInstance()->GetBrowserContext(), blob_contents, blob_type);
+ std::string blob_id = blob->GetUUID();
+
+ base::HistogramTester histograms;
+ // Try registering a blob URL for b.com. This IPC should result
+ // in a kill because a.com should not be abllowed to create blob URLs outside
+ // of its own origin.
+ RenderProcessHostWatcher crash_observer(
+ rfh->GetProcess(), RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
+ PwnMessageHelper::RegisterBlobURL(
+ rfh->GetProcess(), GURL("blob:" + target_origin + "/" + blob_path),
+ blob_id);
+ // If the process is killed, this test passes.
+ crash_observer.Wait();
+ histograms.ExpectUniqueSample("Stability.BadMessageTerminated.Content",
+ 139 /* BDH_DISALLOWED_ORIGIN */, 1);
+}
+
+class SecurityExploitBrowserTestMojoBlobURLs
+ : public SecurityExploitBrowserTest {
+ public:
+ SecurityExploitBrowserTestMojoBlobURLs() {
+ scoped_feature_list_.InitAndEnableFeature(blink::features::kMojoBlobURLs);
+ }
+
+ void TearDown() override {
+ storage::BlobRegistryImpl::SetURLStoreCreationHookForTesting(nullptr);
+ }
+
+ private:
+ base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+// Check that when site isolation is enabled, an origin can't create a blob URL
+// for a different origin. Similar to the test above, but checks the
+// mojo-based Blob URL implementation. See https://crbug.com/886976.
+IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTestMojoBlobURLs,
+ CreateMojoBlobURLInDifferentOrigin) {
+ IsolateAllSitesForTesting(base::CommandLine::ForCurrentProcess());
+
+ GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+ RenderFrameHost* rfh = shell()->web_contents()->GetMainFrame();
+
+ // Intercept future blob URL registrations and overwrite the blob URL origin
+ // with b.com.
+ std::string target_origin = "http://b.com";
+ std::string blob_path = "5881f76e-10d2-410d-8c61-ef210502acfd";
+ BlobURLStoreInterceptor interceptor(
+ GURL("blob:" + target_origin + "/" + blob_path));
+ auto intercept_hook = base::BindRepeating(&BlobURLStoreInterceptor::Intercept,
+ base::Unretained(&interceptor));
+ storage::BlobRegistryImpl::SetURLStoreCreationHookForTesting(&intercept_hook);
+
+ // Register a blob URL from the a.com main frame, which will go through the
+ // interceptor above and be rewritten to register the blob URL with the b.com
+ // origin. This should result in a kill because a.com should not be allowed
+ // to create blob URLs outside of its own origin.
+ base::HistogramTester histograms;
+ RenderProcessHostWatcher crash_observer(
+ rfh->GetProcess(), RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
+
+ // The renderer should always get killed, but sometimes ExecuteScript returns
+ // true anyway, so just ignore the result.
+ ignore_result(
+ content::ExecuteScript(rfh, "URL.createObjectURL(new Blob(['foo']))"));
+
+ // If the process is killed, this test passes.
+ crash_observer.Wait();
+ histograms.ExpectUniqueSample("Stability.BadMessageTerminated.Content", 123,
+ 1);
+}
+
+// Check that with site isolation enabled, an origin can't create a filesystem
+// URL for a different origin. See https://crbug.com/888001.
+IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest,
+ CreateFilesystemURLInDifferentOrigin) {
+ IsolateAllSitesForTesting(base::CommandLine::ForCurrentProcess());
+
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b)"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+ RenderFrameHost* rfh = shell()->web_contents()->GetMainFrame();
+
+ // Block the renderer on operation that never completes, to shield it from
+ // receiving unexpected browser->renderer IPCs that might CHECK.
+ rfh->ExecuteJavaScriptWithUserGestureForTests(
+ base::ASCIIToUTF16("var r = new XMLHttpRequest();"
+ "r.open('GET', '/slow?99999', false);"
+ "r.send(null);"
+ "while (1);"));
+
+ // Set up a blob ID and populate it with attacker-controlled value. This
+ // is just using the blob APIs directly since creating arbitrary blobs is not
+ // what is prohibited; this data is not in any origin.
+ std::string payload = "<html><body>pwned.</body></html>";
+ std::string payload_type = "text/html";
+ std::unique_ptr<content::BlobHandle> blob = CreateMemoryBackedBlob(
+ rfh->GetSiteInstance()->GetBrowserContext(), payload, payload_type);
+ std::string blob_id = blob->GetUUID();
+
+ // Target a different origin.
+ std::string target_origin = "http://b.com";
+ GURL target_url =
+ GURL("filesystem:" + target_origin + "/temporary/exploit.html");
+
+ // Note: a well-behaved renderer would always call Open first before calling
+ // Create and Write, but it's actually not necessary for the original attack
+ // to succeed, so we omit it. As a result there are some log warnings from the
+ // quota observer.
+
+ PwnMessageHelper::FileSystemCreate(rfh->GetProcess(), 23, target_url, false,
+ false, false);
+
+ // Write the blob into the file. If successful, this places an
+ // attacker-controlled value in a resource on the target origin.
+ PwnMessageHelper::FileSystemWrite(rfh->GetProcess(), 24, target_url, blob_id,
+ 0);
+
+ // Now navigate to |target_url| in a subframe. It should not succeed, and the
+ // subframe should not contain |payload|.
+ TestNavigationObserver observer(shell()->web_contents());
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+ NavigateFrameToURL(root->child_at(0), target_url);
+ EXPECT_FALSE(observer.last_navigation_succeeded());
+ EXPECT_EQ(net::ERR_FILE_NOT_FOUND, observer.last_net_error_code());
+
+ RenderFrameHost* attacked_rfh = root->child_at(0)->current_frame_host();
+ std::string body =
+ EvalJs(attacked_rfh, "document.body.innerText").ExtractString();
+ EXPECT_TRUE(base::StartsWith(body, "Could not load the requested resource",
+ base::CompareCase::INSENSITIVE_ASCII))
+ << " body=" << body;
+}
+
+// Verify that when a compromised renderer tries to navigate a remote frame to
+// a disallowed URL (e.g., file URL), that navigation is blocked.
+IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest,
+ BlockIllegalOpenURLFromRemoteFrame) {
+ // This test is only valid in site-per-process mode, where a cross-site
+ // iframe will have a proxy in the main frame's 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));
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+ FrameTreeNode* child = root->child_at(0);
+
+ // Simulate an IPC message where the top frame asks the remote subframe to
+ // navigate to a file: URL.
+ GURL file_url("file:///");
+ FrameHostMsg_OpenURL_Params params;
+ params.url = file_url;
+ params.uses_post = false;
+ params.disposition = WindowOpenDisposition::CURRENT_TAB;
+ params.should_replace_current_entry = false;
+ params.user_gesture = true;
+ params.is_history_navigation_in_new_child = false;
+
+ SiteInstance* a_com_instance = root->current_frame_host()->GetSiteInstance();
+ RenderFrameProxyHost* proxy =
+ child->render_manager()->GetRenderFrameProxyHost(a_com_instance);
+ EXPECT_TRUE(proxy);
+
+ {
+ FrameHostMsg_OpenURL msg(proxy->GetRoutingID(), params);
+ IPC::IpcSecurityTestUtil::PwnMessageReceived(
+ proxy->GetProcess()->GetChannel(), msg);
+ }
+
+ // Verify that the malicious navigation was blocked. Currently, this happens
+ // by rewriting the target URL to about:blank.
+ //
+ // TODO(alexmos): Consider killing the renderer process in this case, since
+ // this security check is already enforced in the renderer process.
+ EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
+ EXPECT_EQ(GURL(url::kAboutBlankURL),
+ child->current_frame_host()->GetLastCommittedURL());
+
+ // Navigate to the starting page again to recreate the proxy, then try the
+ // same malicious navigation with a chrome:// URL.
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+ child = root->child_at(0);
+ proxy = child->render_manager()->GetRenderFrameProxyHost(a_com_instance);
+ EXPECT_TRUE(proxy);
+
+ GURL chrome_url(std::string(kChromeUIScheme) + "://" +
+ std::string(kChromeUIGpuHost));
+ params.url = chrome_url;
+ {
+ FrameHostMsg_OpenURL msg(proxy->GetRoutingID(), params);
+ IPC::IpcSecurityTestUtil::PwnMessageReceived(
+ proxy->GetProcess()->GetChannel(), msg);
+ }
+ EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
+ EXPECT_EQ(GURL(url::kAboutBlankURL),
+ child->current_frame_host()->GetLastCommittedURL());
+}
+
} // namespace content
diff --git a/chromium/content/browser/service_manager/common_browser_interfaces.cc b/chromium/content/browser/service_manager/common_browser_interfaces.cc
index f537f90fa48..631c58056b6 100644
--- a/chromium/content/browser/service_manager/common_browser_interfaces.cc
+++ b/chromium/content/browser/service_manager/common_browser_interfaces.cc
@@ -19,6 +19,7 @@
#include "content/browser/browser_main_loop.h"
#include "content/browser/gpu/browser_gpu_client_delegate.h"
#include "content/common/child_process_host_impl.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/connection_filter.h"
#include "content/public/common/service_manager_connection.h"
@@ -51,7 +52,7 @@ class ConnectionFilterImpl : public ConnectionFilter {
#elif defined(OS_MACOSX)
registry_.AddInterface(base::BindRepeating(&FontLoaderDispatcher::Create));
#endif
- if (!features::IsUsingWindowService()) {
+ if (!features::IsMultiProcessMash()) {
// 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();
@@ -106,7 +107,7 @@ class ConnectionFilterImpl : public ConnectionFilter {
auto gpu_client = std::make_unique<viz::GpuClient>(
std::make_unique<BrowserGpuClientDelegate>(), gpu_client_id,
gpu_client_tracing_id,
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO));
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO}));
gpu_client->SetConnectionErrorHandler(
base::BindOnce(&ConnectionFilterImpl::OnGpuConnectionClosed,
base::Unretained(this), source_info.identity));
diff --git a/chromium/content/browser/service_manager/service_manager_context.cc b/chromium/content/browser/service_manager/service_manager_context.cc
index f35734b66d0..5119d521cd2 100644
--- a/chromium/content/browser/service_manager/service_manager_context.cc
+++ b/chromium/content/browser/service_manager/service_manager_context.cc
@@ -59,12 +59,14 @@
#include "services/data_decoder/public/mojom/constants.mojom.h"
#include "services/device/device_service.h"
#include "services/device/public/mojom/constants.mojom.h"
+#include "services/media_session/media_session_service.h"
+#include "services/media_session/public/cpp/switches.h"
+#include "services/media_session/public/mojom/constants.mojom.h"
#include "services/metrics/metrics_mojo_service.h"
#include "services/metrics/public/mojom/constants.mojom.h"
#include "services/network/network_service.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/mojom/network_service_test.mojom.h"
-#include "services/resource_coordinator/public/cpp/resource_coordinator_features.h"
#include "services/resource_coordinator/public/mojom/service_constants.mojom.h"
#include "services/resource_coordinator/resource_coordinator_service.h"
#include "services/service_manager/connect_params.h"
@@ -548,12 +550,18 @@ ServiceManagerContext::ServiceManagerContext(
packaged_services_connection_->AddEmbeddedService(device::mojom::kServiceName,
device_info);
- if (base::FeatureList::IsEnabled(features::kGlobalResourceCoordinator)) {
- service_manager::EmbeddedServiceInfo resource_coordinator_info;
- resource_coordinator_info.factory =
- base::Bind(&resource_coordinator::ResourceCoordinatorService::Create);
+ service_manager::EmbeddedServiceInfo resource_coordinator_info;
+ resource_coordinator_info.factory =
+ base::Bind(&resource_coordinator::ResourceCoordinatorService::Create);
+ packaged_services_connection_->AddEmbeddedService(
+ resource_coordinator::mojom::kServiceName, resource_coordinator_info);
+
+ if (media_session::IsMediaSessionEnabled()) {
+ service_manager::EmbeddedServiceInfo media_session_info;
+ media_session_info.factory =
+ base::BindRepeating(&media_session::MediaSessionService::Create);
packaged_services_connection_->AddEmbeddedService(
- resource_coordinator::mojom::kServiceName, resource_coordinator_info);
+ media_session::mojom::kServiceName, media_session_info);
}
{
diff --git a/chromium/content/browser/service_worker/embedded_worker_instance.cc b/chromium/content/browser/service_worker/embedded_worker_instance.cc
index 597aba71671..05e0bcd55cd 100644
--- a/chromium/content/browser/service_worker/embedded_worker_instance.cc
+++ b/chromium/content/browser/service_worker/embedded_worker_instance.cc
@@ -7,9 +7,13 @@
#include <utility>
#include "base/bind_helpers.h"
+#include "base/callback.h"
#include "base/feature_list.h"
#include "base/macros.h"
#include "base/metrics/histogram_macros.h"
+#include "base/no_destructor.h"
+#include "base/optional.h"
+#include "base/task/post_task.h"
#include "base/trace_event/trace_event.h"
#include "content/browser/bad_message.h"
#include "content/browser/devtools/service_worker_devtools_manager.h"
@@ -24,6 +28,7 @@
#include "content/common/service_worker/service_worker_types.h"
#include "content/common/url_loader_factory_bundle.mojom.h"
#include "content/common/url_schemes.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/common/child_process_host.h"
@@ -42,6 +47,14 @@ namespace content {
namespace {
+base::Optional<EmbeddedWorkerInstance::CreateNetworkFactoryCallback>&
+GetNetworkFactoryCallbackForTest() {
+ static base::NoDestructor<
+ base::Optional<EmbeddedWorkerInstance::CreateNetworkFactoryCallback>>
+ callback;
+ return *callback;
+}
+
// When a service worker version's failure count exceeds
// |kMaxSameProcessFailureCount|, the embedded worker is forced to start in a
// new process.
@@ -54,10 +67,12 @@ const char kServiceWorkerTerminationCanceledMesage[] =
void NotifyWorkerReadyForInspectionOnUI(
int worker_process_id,
int worker_route_id,
+ blink::mojom::DevToolsAgentHostAssociatedRequest host_request,
blink::mojom::DevToolsAgentAssociatedPtrInfo devtools_agent_ptr_info) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
ServiceWorkerDevToolsManager::GetInstance()->WorkerReadyForInspection(
- worker_process_id, worker_route_id, std::move(devtools_agent_ptr_info));
+ worker_process_id, worker_route_id, std::move(host_request),
+ std::move(devtools_agent_ptr_info));
}
void NotifyWorkerDestroyedOnUI(int worker_process_id, int worker_route_id) {
@@ -79,36 +94,49 @@ void NotifyWorkerVersionDoomedOnUI(int worker_process_id, int worker_route_id) {
worker_process_id, worker_route_id);
}
+// Returns a factory bundle for doing loads on behalf of the specified |rph| and
+// |origin|. The returned bundle has a default factory that goes to network and
+// it may also include scheme-specific factories that don't go to network.
+//
+// The network factory does not support reconnection to the network service.
std::unique_ptr<URLLoaderFactoryBundleInfo> CreateFactoryBundle(
RenderProcessHost* rph,
- bool use_non_network_factories) {
+ const url::Origin& origin) {
auto factory_bundle = std::make_unique<URLLoaderFactoryBundleInfo>();
network::mojom::URLLoaderFactoryPtrInfo default_factory_info;
- rph->CreateURLLoaderFactory(mojo::MakeRequest(&default_factory_info));
+ if (!GetNetworkFactoryCallbackForTest()) {
+ rph->CreateURLLoaderFactory(origin,
+ mojo::MakeRequest(&default_factory_info));
+ } else {
+ network::mojom::URLLoaderFactoryPtr original_factory;
+ rph->CreateURLLoaderFactory(origin, mojo::MakeRequest(&original_factory));
+ GetNetworkFactoryCallbackForTest()->Run(
+ mojo::MakeRequest(&default_factory_info), rph->GetID(),
+ original_factory.PassInterface());
+ }
factory_bundle->default_factory_info() = std::move(default_factory_info);
- if (use_non_network_factories) {
- ContentBrowserClient::NonNetworkURLLoaderFactoryMap factories;
- GetContentClient()
- ->browser()
- ->RegisterNonNetworkSubresourceURLLoaderFactories(
- rph->GetID(), MSG_ROUTING_NONE, &factories);
-
- 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());
- }
+ ContentBrowserClient::NonNetworkURLLoaderFactoryMap non_network_factories;
+ GetContentClient()
+ ->browser()
+ ->RegisterNonNetworkSubresourceURLLoaderFactories(
+ rph->GetID(), MSG_ROUTING_NONE, &non_network_factories);
+
+ for (auto& pair : non_network_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 and fetch() 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->scheme_specific_factory_infos().emplace(
+ scheme, factory_ptr.PassInterface());
}
return factory_bundle;
}
@@ -148,8 +176,8 @@ void SetupOnUIThread(base::WeakPtr<ServiceWorkerProcessManager> process_manager,
std::unique_ptr<URLLoaderFactoryBundleInfo> factory_bundle_for_renderer;
if (!process_manager) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
std::move(callback), blink::ServiceWorkerStatusCode::kErrorAbort,
std::move(params), std::move(process_info),
@@ -165,8 +193,8 @@ void SetupOnUIThread(base::WeakPtr<ServiceWorkerProcessManager> process_manager,
params->embedded_worker_id, params->scope, params->script_url,
can_use_existing_process, process_info.get());
if (status != blink::ServiceWorkerStatusCode::kOk) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(std::move(callback), status, std::move(params),
std::move(process_info), std::move(devtools_proxy),
std::move(factory_bundle_for_browser),
@@ -202,23 +230,26 @@ void SetupOnUIThread(base::WeakPtr<ServiceWorkerProcessManager> process_manager,
std::move(request));
}
- // S13nServiceWorker:
- // Create a default loader for network fallback.
- // The factory from RPH::CreateURLLoaderFactory() 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).
+ // S13nServiceWorker: Create factory bundles for this worker to do loading.
+ // These bundles don't support reconnection to the network service, see
+ // below comments.
if (blink::ServiceWorkerUtils::IsServicificationEnabled()) {
- // For performance, we only create the loader factories for non-http(s)
- // URLs (e.g. chrome-extension://) when the main script URL is
- // non-http(s). We assume an http(s) service worker cannot
- // importScripts a non-http(s) URL.
- bool use_non_network_factories = !params->script_url.SchemeIsHTTPOrHTTPS();
-
- factory_bundle_for_browser =
- CreateFactoryBundle(rph, use_non_network_factories);
- factory_bundle_for_renderer =
- CreateFactoryBundle(rph, use_non_network_factories);
+ const url::Origin origin = url::Origin::Create(params->script_url);
+
+ // The bundle for the browser is passed to ServiceWorkerScriptLoaderFactory
+ // and used to request non-installed service worker scripts. It's OK to not
+ // support reconnection to then network service because it can only used
+ // until the service worker reaches the 'installed' state.
+ //
+ // TODO(falken): Only make this bundle for non-installed service workers.
+ factory_bundle_for_browser = CreateFactoryBundle(rph, origin);
+
+ // The bundle for the renderer is passed to the service worker, and
+ // used for subresource loading from the service worker (i.e., fetch()).
+ // It's OK to not support reconnection to the network service because the
+ // service worker terminates itself when the connection breaks, so a new
+ // instance can be started.
+ factory_bundle_for_renderer = CreateFactoryBundle(rph, origin);
}
// Register to DevTools and update params accordingly.
@@ -248,8 +279,8 @@ void SetupOnUIThread(base::WeakPtr<ServiceWorkerProcessManager> process_manager,
process_manager->browser_context(), std::move(watcher_ptr));
// Continue to OnSetupCompleted on the IO thread.
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(std::move(callback), status, std::move(params),
std::move(process_info), std::move(devtools_proxy),
std::move(factory_bundle_for_browser),
@@ -288,32 +319,34 @@ class EmbeddedWorkerInstance::DevToolsProxy {
~DevToolsProxy() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(NotifyWorkerDestroyedOnUI,
- process_id_, agent_route_id_));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(NotifyWorkerDestroyedOnUI,
+ process_id_, agent_route_id_));
}
void NotifyWorkerReadyForInspection(
+ blink::mojom::DevToolsAgentHostAssociatedRequest host_request,
blink::mojom::DevToolsAgentAssociatedPtrInfo devtools_agent_ptr_info) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(NotifyWorkerReadyForInspectionOnUI, process_id_,
- agent_route_id_, std::move(devtools_agent_ptr_info)));
+ agent_route_id_, std::move(host_request),
+ std::move(devtools_agent_ptr_info)));
}
void NotifyWorkerVersionInstalled() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(NotifyWorkerVersionInstalledOnUI,
- process_id_, agent_route_id_));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(NotifyWorkerVersionInstalledOnUI,
+ process_id_, agent_route_id_));
}
void NotifyWorkerVersionDoomed() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(NotifyWorkerVersionDoomedOnUI,
- process_id_, agent_route_id_));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(NotifyWorkerVersionDoomedOnUI,
+ process_id_, agent_route_id_));
}
bool ShouldNotifyWorkerStopIgnored() const {
@@ -349,8 +382,8 @@ class EmbeddedWorkerInstance::WorkerProcessHandle {
~WorkerProcessHandle() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&ServiceWorkerProcessManager::ReleaseWorkerProcess,
process_manager_, embedded_worker_id_));
}
@@ -414,8 +447,8 @@ class EmbeddedWorkerInstance::StartTask {
break;
case ProcessAllocationState::ALLOCATING:
// Abort half-baked process allocation on the UI thread.
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&ServiceWorkerProcessManager::ReleaseWorkerProcess,
instance_->context_->process_manager()->AsWeakPtr(),
instance_->embedded_worker_id()));
@@ -475,8 +508,8 @@ class EmbeddedWorkerInstance::StartTask {
// 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::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(
&SetupOnUIThread, process_manager, can_use_existing_process,
std::move(params), std::move(request_), context.get(), context,
@@ -777,15 +810,7 @@ void EmbeddedWorkerInstance::RequestTermination(
return;
}
- if (status() == EmbeddedWorkerStatus::STOPPING) {
- std::move(callback).Run(true /* will_be_terminated */);
- return;
- }
- owner_version_->StopWorkerIfIdle(true /* requested_from_renderer */);
-
- // If DevTools is attached and the worker won't be stopped, the worker needs
- // to continue to work.
- std::move(callback).Run(status() != EmbeddedWorkerStatus::RUNNING);
+ std::move(callback).Run(owner_version_->OnRequestTermination());
}
void EmbeddedWorkerInstance::CountFeature(blink::mojom::WebFeature feature) {
@@ -793,12 +818,16 @@ void EmbeddedWorkerInstance::CountFeature(blink::mojom::WebFeature feature) {
}
void EmbeddedWorkerInstance::OnReadyForInspection() {
- if (devtools_proxy_) {
- blink::mojom::DevToolsAgentAssociatedPtrInfo devtools_agent_ptr_info;
- client_->BindDevToolsAgent(mojo::MakeRequest(&devtools_agent_ptr_info));
- devtools_proxy_->NotifyWorkerReadyForInspection(
- std::move(devtools_agent_ptr_info));
- }
+ if (!devtools_proxy_)
+ return;
+ blink::mojom::DevToolsAgentHostAssociatedPtrInfo host_ptr_info;
+ blink::mojom::DevToolsAgentHostAssociatedRequest host_request =
+ mojo::MakeRequest(&host_ptr_info);
+ blink::mojom::DevToolsAgentAssociatedPtrInfo devtools_agent_ptr_info;
+ client_->BindDevToolsAgent(std::move(host_ptr_info),
+ mojo::MakeRequest(&devtools_agent_ptr_info));
+ devtools_proxy_->NotifyWorkerReadyForInspection(
+ std::move(host_request), std::move(devtools_agent_ptr_info));
}
void EmbeddedWorkerInstance::OnScriptReadStarted() {
@@ -1047,4 +1076,10 @@ std::string EmbeddedWorkerInstance::StartingPhaseToString(StartingPhase phase) {
return std::string();
}
+// static
+void EmbeddedWorkerInstance::SetNetworkFactoryForTesting(
+ const CreateNetworkFactoryCallback& create_network_factory_callback) {
+ GetNetworkFactoryCallbackForTest() = create_network_factory_callback;
+}
+
} // namespace content
diff --git a/chromium/content/browser/service_worker/embedded_worker_instance.h b/chromium/content/browser/service_worker/embedded_worker_instance.h
index 261425d2f41..e0202212b8f 100644
--- a/chromium/content/browser/service_worker/embedded_worker_instance.h
+++ b/chromium/content/browser/service_worker/embedded_worker_instance.h
@@ -200,6 +200,16 @@ class CONTENT_EXPORT EmbeddedWorkerInstance
static std::string StatusToString(EmbeddedWorkerStatus status);
static std::string StartingPhaseToString(StartingPhase phase);
+ using CreateNetworkFactoryCallback = base::RepeatingCallback<void(
+ network::mojom::URLLoaderFactoryRequest request,
+ int process_id,
+ network::mojom::URLLoaderFactoryPtrInfo original_factory)>;
+ // Allows overriding the URLLoaderFactory creation for loading subresources
+ // from service workers (i.e., fetch()) and for loading non-installed service
+ // worker scripts.
+ static void SetNetworkFactoryForTesting(
+ const CreateNetworkFactoryCallback& url_loader_factory_callback);
+
// Forces this instance into STOPPED status and releases any state about the
// running worker. Called when connection with the renderer died or the
// renderer is unresponsive. Essentially, it throws away any information
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 5dac55e4405..eb96a7337ab 100644
--- a/chromium/content/browser/service_worker/embedded_worker_instance_unittest.cc
+++ b/chromium/content/browser/service_worker/embedded_worker_instance_unittest.cc
@@ -125,8 +125,8 @@ class EmbeddedWorkerInstanceTest : public testing::TestWithParam<bool>,
options, context()->storage()->NewRegistrationId(),
context()->AsWeakPtr());
pair.second = base::MakeRefCounted<ServiceWorkerVersion>(
- pair.first.get(), script_url, context()->storage()->NewVersionId(),
- context()->AsWeakPtr());
+ pair.first.get(), script_url, blink::mojom::ScriptType::kClassic,
+ context()->storage()->NewVersionId(), context()->AsWeakPtr());
return pair;
}
diff --git a/chromium/content/browser/service_worker/embedded_worker_registry.cc b/chromium/content/browser/service_worker/embedded_worker_registry.cc
index 34287d99034..896a7240d6d 100644
--- a/chromium/content/browser/service_worker/embedded_worker_registry.cc
+++ b/chromium/content/browser/service_worker/embedded_worker_registry.cc
@@ -44,9 +44,7 @@ std::unique_ptr<EmbeddedWorkerInstance> EmbeddedWorkerRegistry::CreateWorker(
}
void EmbeddedWorkerRegistry::Shutdown() {
- for (WorkerInstanceMap::iterator it = worker_map_.begin();
- it != worker_map_.end();
- ++it) {
+ for (auto it = worker_map_.begin(); it != worker_map_.end(); ++it) {
it->second->Stop();
}
}
@@ -74,7 +72,7 @@ void EmbeddedWorkerRegistry::AbortLifetimeTracking(int embedded_worker_id) {
EmbeddedWorkerInstance* EmbeddedWorkerRegistry::GetWorker(
int embedded_worker_id) {
- WorkerInstanceMap::iterator found = worker_map_.find(embedded_worker_id);
+ auto found = worker_map_.find(embedded_worker_id);
if (found == worker_map_.end())
return nullptr;
return found->second;
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 92fcf8b5fe8..7c41d084e3b 100644
--- a/chromium/content/browser/service_worker/embedded_worker_test_helper.cc
+++ b/chromium/content/browser/service_worker/embedded_worker_test_helper.cc
@@ -48,10 +48,11 @@ void OnFetchEventCommon(
response->status_code = 200;
response->status_text = "OK";
response->response_type = network::mojom::FetchResponseType::kDefault;
- response_callback->OnResponse(std::move(response), base::Time::Now());
+ response_callback->OnResponse(
+ std::move(response), blink::mojom::ServiceWorkerFetchEventTiming::New());
std::move(finish_callback)
.Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
- base::Time::Now());
+ base::TimeTicks::Now());
}
} // namespace
@@ -266,7 +267,7 @@ class EmbeddedWorkerTestHelper::MockServiceWorker
void DispatchNotificationClickEvent(
const std::string& notification_id,
- const PlatformNotificationData& notification_data,
+ const blink::PlatformNotificationData& notification_data,
int action_index,
const base::Optional<base::string16>& reply,
DispatchNotificationClickEventCallback callback) override {
@@ -279,7 +280,7 @@ class EmbeddedWorkerTestHelper::MockServiceWorker
void DispatchNotificationCloseEvent(
const std::string& notification_id,
- const PlatformNotificationData& notification_data,
+ const blink::PlatformNotificationData& notification_data,
DispatchNotificationCloseEventCallback callback) override {
if (!helper_)
return;
@@ -581,28 +582,28 @@ void EmbeddedWorkerTestHelper::OnActivateEvent(
mojom::ServiceWorker::DispatchActivateEventCallback callback) {
dispatched_events()->push_back(Event::Activate);
std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
- base::Time::Now());
+ base::TimeTicks::Now());
}
void EmbeddedWorkerTestHelper::OnBackgroundFetchAbortEvent(
const BackgroundFetchRegistration& registration,
mojom::ServiceWorker::DispatchBackgroundFetchAbortEventCallback callback) {
std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
- base::Time::Now());
+ base::TimeTicks::Now());
}
void EmbeddedWorkerTestHelper::OnBackgroundFetchClickEvent(
const BackgroundFetchRegistration& registration,
mojom::ServiceWorker::DispatchBackgroundFetchClickEventCallback callback) {
std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
- base::Time::Now());
+ base::TimeTicks::Now());
}
void EmbeddedWorkerTestHelper::OnBackgroundFetchFailEvent(
const BackgroundFetchRegistration& registration,
mojom::ServiceWorker::DispatchBackgroundFetchFailEventCallback callback) {
std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
- base::Time::Now());
+ base::TimeTicks::Now());
}
void EmbeddedWorkerTestHelper::OnBackgroundFetchSuccessEvent(
@@ -610,7 +611,7 @@ void EmbeddedWorkerTestHelper::OnBackgroundFetchSuccessEvent(
mojom::ServiceWorker::DispatchBackgroundFetchSuccessEventCallback
callback) {
std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
- base::Time::Now());
+ base::TimeTicks::Now());
}
void EmbeddedWorkerTestHelper::OnCookieChangeEvent(
@@ -618,21 +619,21 @@ void EmbeddedWorkerTestHelper::OnCookieChangeEvent(
::network::mojom::CookieChangeCause cause,
mojom::ServiceWorker::DispatchCookieChangeEventCallback callback) {
std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
- base::Time::Now());
+ base::TimeTicks::Now());
}
void EmbeddedWorkerTestHelper::OnExtendableMessageEvent(
mojom::ExtendableMessageEventPtr event,
mojom::ServiceWorker::DispatchExtendableMessageEventCallback callback) {
std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
- base::Time::Now());
+ base::TimeTicks::Now());
}
void EmbeddedWorkerTestHelper::OnInstallEvent(
mojom::ServiceWorker::DispatchInstallEventCallback callback) {
dispatched_events()->push_back(Event::Install);
std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
- true /* has_fetch_handler */, base::Time::Now());
+ true /* has_fetch_handler */, base::TimeTicks::Now());
}
void EmbeddedWorkerTestHelper::OnFetchEvent(
@@ -649,33 +650,33 @@ void EmbeddedWorkerTestHelper::OnPushEvent(
base::Optional<std::string> payload,
mojom::ServiceWorker::DispatchPushEventCallback callback) {
std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
- base::Time::Now());
+ base::TimeTicks::Now());
}
void EmbeddedWorkerTestHelper::OnNotificationClickEvent(
const std::string& notification_id,
- const PlatformNotificationData& notification_data,
+ const blink::PlatformNotificationData& notification_data,
int action_index,
const base::Optional<base::string16>& reply,
mojom::ServiceWorker::DispatchNotificationClickEventCallback callback) {
std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
- base::Time::Now());
+ base::TimeTicks::Now());
}
void EmbeddedWorkerTestHelper::OnNotificationCloseEvent(
const std::string& notification_id,
- const PlatformNotificationData& notification_data,
+ const blink::PlatformNotificationData& notification_data,
mojom::ServiceWorker::DispatchNotificationCloseEventCallback callback) {
std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
- base::Time::Now());
+ base::TimeTicks::Now());
}
void EmbeddedWorkerTestHelper::OnAbortPaymentEvent(
payments::mojom::PaymentHandlerResponseCallbackPtr response_callback,
mojom::ServiceWorker::DispatchAbortPaymentEventCallback callback) {
- response_callback->OnResponseForAbortPayment(true, base::Time::Now());
+ response_callback->OnResponseForAbortPayment(true, base::TimeTicks::Now());
std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
- base::Time::Now());
+ base::TimeTicks::Now());
}
void EmbeddedWorkerTestHelper::OnCanMakePaymentEvent(
@@ -690,9 +691,9 @@ void EmbeddedWorkerTestHelper::OnCanMakePaymentEvent(
}
}
response_callback->OnResponseForCanMakePayment(can_make_payment,
- base::Time::Now());
+ base::TimeTicks::Now());
std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
- base::Time::Now());
+ base::TimeTicks::Now());
}
void EmbeddedWorkerTestHelper::OnPaymentRequestEvent(
@@ -700,9 +701,9 @@ void EmbeddedWorkerTestHelper::OnPaymentRequestEvent(
payments::mojom::PaymentHandlerResponseCallbackPtr response_callback,
mojom::ServiceWorker::DispatchPaymentRequestEventCallback callback) {
response_callback->OnResponseForPaymentRequest(
- payments::mojom::PaymentHandlerResponse::New(), base::Time::Now());
+ payments::mojom::PaymentHandlerResponse::New(), base::TimeTicks::Now());
std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
- base::Time::Now());
+ base::TimeTicks::Now());
}
void EmbeddedWorkerTestHelper::OnSetIdleTimerDelayToZero(
@@ -933,7 +934,7 @@ void EmbeddedWorkerTestHelper::OnFetchEventStub(
void EmbeddedWorkerTestHelper::OnNotificationClickEventStub(
const std::string& notification_id,
- const PlatformNotificationData& notification_data,
+ const blink::PlatformNotificationData& notification_data,
int action_index,
const base::Optional<base::string16>& reply,
mojom::ServiceWorker::DispatchNotificationClickEventCallback callback) {
@@ -946,7 +947,7 @@ void EmbeddedWorkerTestHelper::OnNotificationClickEventStub(
void EmbeddedWorkerTestHelper::OnNotificationCloseEventStub(
const std::string& notification_id,
- const PlatformNotificationData& notification_data,
+ const blink::PlatformNotificationData& notification_data,
mojom::ServiceWorker::DispatchNotificationCloseEventCallback callback) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
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 04943106abf..e3c8fc90669 100644
--- a/chromium/content/browser/service_worker/embedded_worker_test_helper.h
+++ b/chromium/content/browser/service_worker/embedded_worker_test_helper.h
@@ -33,6 +33,10 @@
class GURL;
+namespace blink {
+struct PlatformNotificationData;
+}
+
namespace content {
struct BackgroundFetchRegistration;
@@ -42,7 +46,6 @@ class MockRenderProcessHost;
class ServiceWorkerContextCore;
class ServiceWorkerContextWrapper;
class TestBrowserContext;
-struct PlatformNotificationData;
// In-Process EmbeddedWorker test helper.
//
@@ -80,7 +83,8 @@ class EmbeddedWorkerTestHelper {
void AddMessageToConsole(blink::WebConsoleMessage::Level level,
const std::string& message) override;
void BindDevToolsAgent(
- blink::mojom::DevToolsAgentAssociatedRequest request) override {}
+ blink::mojom::DevToolsAgentHostAssociatedPtrInfo,
+ blink::mojom::DevToolsAgentAssociatedRequest) override {}
base::WeakPtr<EmbeddedWorkerTestHelper> helper_;
mojo::Binding<mojom::EmbeddedWorkerInstanceClient> binding_;
@@ -196,13 +200,13 @@ class EmbeddedWorkerTestHelper {
mojom::ServiceWorker::DispatchFetchEventCallback finish_callback);
virtual void OnNotificationClickEvent(
const std::string& notification_id,
- const PlatformNotificationData& notification_data,
+ const blink::PlatformNotificationData& notification_data,
int action_index,
const base::Optional<base::string16>& reply,
mojom::ServiceWorker::DispatchNotificationClickEventCallback callback);
virtual void OnNotificationCloseEvent(
const std::string& notification_id,
- const PlatformNotificationData& notification_data,
+ const blink::PlatformNotificationData& notification_data,
mojom::ServiceWorker::DispatchNotificationCloseEventCallback callback);
virtual void OnPushEvent(
base::Optional<std::string> payload,
@@ -290,13 +294,13 @@ class EmbeddedWorkerTestHelper {
mojom::ServiceWorker::DispatchFetchEventCallback finish_callback);
void OnNotificationClickEventStub(
const std::string& notification_id,
- const PlatformNotificationData& notification_data,
+ const blink::PlatformNotificationData& notification_data,
int action_index,
const base::Optional<base::string16>& reply,
mojom::ServiceWorker::DispatchNotificationClickEventCallback callback);
void OnNotificationCloseEventStub(
const std::string& notification_id,
- const PlatformNotificationData& notification_data,
+ const blink::PlatformNotificationData& notification_data,
mojom::ServiceWorker::DispatchNotificationCloseEventCallback callback);
void OnPushEventStub(
base::Optional<std::string> payload,
diff --git a/chromium/content/browser/service_worker/payment_handler_support.cc b/chromium/content/browser/service_worker/payment_handler_support.cc
index ccf233ffddc..c98173fd292 100644
--- a/chromium/content/browser/service_worker/payment_handler_support.cc
+++ b/chromium/content/browser/service_worker/payment_handler_support.cc
@@ -4,9 +4,11 @@
#include "content/browser/service_worker/payment_handler_support.h"
+#include "base/task/post_task.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/storage_partition_impl.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/common/content_client.h"
@@ -47,16 +49,16 @@ class ShowPaymentHandlerWindowReplier {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (response_callback_) {
DCHECK(fallback_);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(std::move(fallback_), std::move(response_callback_)));
}
}
void Run(bool success, int render_process_id, int render_frame_id) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(std::move(callback_), std::move(response_callback_),
success, render_process_id, render_frame_id));
}
@@ -97,8 +99,8 @@ void PaymentHandlerSupport::ShowPaymentHandlerWindow(
response_callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(context);
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&ShowPaymentHandlerWindowOnUI,
base::WrapRefCounted(context->wrapper()), url,
std::move(callback), std::move(fallback),
diff --git a/chromium/content/browser/service_worker/service_worker_browsertest.cc b/chromium/content/browser/service_worker/service_worker_browsertest.cc
index 7e129e81e95..a62f6839ac5 100644
--- a/chromium/content/browser/service_worker/service_worker_browsertest.cc
+++ b/chromium/content/browser/service_worker/service_worker_browsertest.cc
@@ -47,6 +47,7 @@
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/service_worker/service_worker_types.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/navigation_entry.h"
@@ -122,8 +123,8 @@ void RunAndQuit(base::OnceClosure closure,
void RunOnIOThreadWithDelay(base::OnceClosure closure, base::TimeDelta delay) {
base::RunLoop run_loop;
- BrowserThread::PostDelayedTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostDelayedTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&RunAndQuit, std::move(closure), run_loop.QuitClosure(),
base::RetainedRef(base::ThreadTaskRunnerHandle::Get())),
delay);
@@ -135,16 +136,16 @@ void RunOnIOThread(base::OnceClosure closure) {
}
void RunOnIOThread(
- const base::Callback<void(const base::Closure& continuation)>& closure) {
+ base::OnceCallback<void(base::OnceClosure continuation)> callback) {
base::RunLoop run_loop;
- base::Closure quit_on_original_thread =
- base::Bind(base::IgnoreResult(&base::SingleThreadTaskRunner::PostTask),
- base::ThreadTaskRunnerHandle::Get().get(),
- FROM_HERE,
- run_loop.QuitClosure());
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(closure, std::move(quit_on_original_thread)));
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(
+ std::move(callback),
+ base::BindOnce(
+ base::IgnoreResult(&base::SingleThreadTaskRunner::PostTask),
+ base::ThreadTaskRunnerHandle::Get().get(), FROM_HERE,
+ run_loop.QuitClosure())));
run_loop.Run();
}
@@ -164,7 +165,7 @@ void ReceiveFindRegistrationStatus(
scoped_refptr<ServiceWorkerRegistration> registration) {
*out_status = status;
if (!quit.is_null())
- BrowserThread::PostTask(run_quit_thread, FROM_HERE, std::move(quit));
+ base::PostTaskWithTraits(FROM_HERE, {run_quit_thread}, std::move(quit));
}
ServiceWorkerStorage::FindRegistrationCallback CreateFindRegistrationReceiver(
@@ -212,8 +213,8 @@ class WorkerActivatedObserver
context_->RemoveObserver(this);
version_id_ = version_id;
registration_id_ = version->registration_id();
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&WorkerActivatedObserver::Quit, this));
}
}
@@ -484,8 +485,8 @@ class ConsoleListener : public EmbeddedWorkerInstance::Listener {
int line_number,
const GURL& source_url) override {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&ConsoleListener::OnReportConsoleMessageOnUI,
base::Unretained(this), message));
}
@@ -509,14 +510,16 @@ class ConsoleListener : public EmbeddedWorkerInstance::Listener {
void OnReportConsoleMessageOnUI(const base::string16& message) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
messages_.push_back(message);
- if (!quit_.is_null() && messages_.size() == expected_message_count_)
- quit_.Run();
+ if (messages_.size() == expected_message_count_) {
+ DCHECK(quit_);
+ std::move(quit_).Run();
+ }
}
// These parameters must be accessed on the UI thread.
std::vector<base::string16> messages_;
size_t expected_message_count_ = 0;
- base::Closure quit_;
+ base::OnceClosure quit_;
};
// Listens to console messages on ServiceWorkerContextWrapper.
@@ -586,8 +589,8 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
// Dispatch install on a worker.
base::Optional<blink::ServiceWorkerStatusCode> status;
base::RunLoop install_run_loop;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&self::InstallOnIOThread, base::Unretained(this),
install_run_loop.QuitClosure(), &status));
install_run_loop.Run();
@@ -595,8 +598,8 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
// Stop the worker.
base::RunLoop stop_run_loop;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&self::StopOnIOThread, base::Unretained(this),
stop_run_loop.QuitClosure()));
stop_run_loop.Run();
@@ -606,8 +609,8 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
blink::ServiceWorkerStatusCode expected_status) {
base::Optional<blink::ServiceWorkerStatusCode> status;
base::RunLoop run_loop;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&self::ActivateOnIOThread, base::Unretained(this),
run_loop.QuitClosure(), &status));
run_loop.Run();
@@ -624,8 +627,8 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
FetchResult fetch_result;
fetch_result.status = blink::ServiceWorkerStatusCode::kErrorFailed;
base::RunLoop fetch_run_loop;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&self::FetchOnIOThread, base::Unretained(this),
fetch_run_loop.QuitClosure(), &prepare_result,
&fetch_result));
@@ -650,8 +653,8 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
registration_->set_last_update_check(base::Time::Now());
version_ = new ServiceWorkerVersion(
- registration_.get(),
- embedded_test_server()->GetURL(worker_url),
+ registration_.get(), embedded_test_server()->GetURL(worker_url),
+ blink::mojom::ScriptType::kClassic,
wrapper()->context()->storage()->NewVersionId(),
wrapper()->context()->AsWeakPtr());
@@ -686,6 +689,7 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
scoped_refptr<ServiceWorkerVersion> waiting_version(
new ServiceWorkerVersion(
registration_.get(), embedded_test_server()->GetURL(worker_url),
+ blink::mojom::ScriptType::kClassic,
wrapper()->context()->storage()->NewVersionId(),
wrapper()->context()->AsWeakPtr()));
waiting_version->set_fetch_handler_existence(
@@ -699,8 +703,8 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI));
base::Optional<blink::ServiceWorkerStatusCode> status;
base::RunLoop start_run_loop;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&self::StartOnIOThread, base::Unretained(this),
start_run_loop.QuitClosure(), &status));
start_run_loop.Run();
@@ -710,8 +714,8 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
void StopWorker() {
ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI));
base::RunLoop stop_run_loop;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&self::StopOnIOThread, base::Unretained(this),
stop_run_loop.QuitClosure()));
stop_run_loop.Run();
@@ -722,8 +726,8 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI));
base::Optional<blink::ServiceWorkerStatusCode> status;
base::RunLoop store_run_loop;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&self::StoreOnIOThread, base::Unretained(this),
store_run_loop.QuitClosure(), &status, version_id));
store_run_loop.Run();
@@ -738,8 +742,8 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
blink::ServiceWorkerStatusCode* out_status,
bool* out_update_found) {
base::RunLoop update_run_loop;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&self::UpdateOnIOThread, base::Unretained(this), registration_id,
base::BindOnce(
@@ -755,8 +759,8 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
blink::ServiceWorkerStatusCode status =
blink::ServiceWorkerStatusCode::kErrorFailed;
base::RunLoop run_loop;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&self::FindRegistrationForIdOnIOThread,
base::Unretained(this), run_loop.QuitClosure(), &status,
id, origin));
@@ -787,12 +791,13 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
wrapper()->context()->RemoveLiveRegistration(id);
}
- void StartOnIOThread(const base::Closure& done,
+ void StartOnIOThread(base::OnceClosure done,
base::Optional<blink::ServiceWorkerStatusCode>* result) {
ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
version_->SetMainScriptHttpResponseInfo(CreateHttpResponseInfo());
- version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
- CreateReceiver(BrowserThread::UI, done, result));
+ version_->StartWorker(
+ ServiceWorkerMetrics::EventType::UNKNOWN,
+ CreateReceiver(BrowserThread::UI, std::move(done), result));
}
void InstallOnIOThread(
@@ -806,27 +811,29 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
}
void DispatchInstallEventOnIOThread(
- const base::Closure& done,
+ base::OnceClosure done,
base::Optional<blink::ServiceWorkerStatusCode>* result,
blink::ServiceWorkerStatusCode start_worker_status) {
ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
ASSERT_EQ(blink::ServiceWorkerStatusCode::kOk, start_worker_status);
version_->SetStatus(ServiceWorkerVersion::INSTALLING);
- int request_id =
- version_->StartRequest(ServiceWorkerMetrics::EventType::INSTALL,
- CreateReceiver(BrowserThread::UI, done, result));
- version_->endpoint()->DispatchInstallEvent(
- base::BindOnce(&self::ReceiveInstallEventOnIOThread,
- base::Unretained(this), done, result, request_id));
+
+ auto repeating_done = base::AdaptCallbackForRepeating(std::move(done));
+ int request_id = version_->StartRequest(
+ ServiceWorkerMetrics::EventType::INSTALL,
+ CreateReceiver(BrowserThread::UI, repeating_done, result));
+ version_->endpoint()->DispatchInstallEvent(base::BindOnce(
+ &self::ReceiveInstallEventOnIOThread, base::Unretained(this),
+ repeating_done, result, request_id));
}
void ReceiveInstallEventOnIOThread(
- const base::Closure& done,
+ base::OnceClosure done,
base::Optional<blink::ServiceWorkerStatusCode>* out_result,
int request_id,
blink::mojom::ServiceWorkerEventStatus status,
bool has_fetch_handler,
- base::Time dispatch_event_time) {
+ base::TimeTicks dispatch_event_time) {
version_->FinishRequest(
request_id, status == blink::mojom::ServiceWorkerEventStatus::COMPLETED,
dispatch_event_time);
@@ -837,10 +844,10 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
*out_result = mojo::ConvertTo<blink::ServiceWorkerStatusCode>(status);
if (!done.is_null())
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, done);
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI}, std::move(done));
}
- void StoreOnIOThread(const base::Closure& done,
+ void StoreOnIOThread(base::OnceClosure done,
base::Optional<blink::ServiceWorkerStatusCode>* result,
int64_t version_id) {
ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
@@ -848,30 +855,30 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
wrapper()->context()->GetLiveVersion(version_id);
wrapper()->context()->storage()->StoreRegistration(
registration_.get(), version,
- CreateReceiver(BrowserThread::UI, done, result));
+ CreateReceiver(BrowserThread::UI, std::move(done), result));
}
void ActivateOnIOThread(
- const base::RepeatingClosure& done,
+ base::OnceClosure done,
base::Optional<blink::ServiceWorkerStatusCode>* result) {
ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
version_->RunAfterStartWorker(
ServiceWorkerMetrics::EventType::ACTIVATE,
base::BindOnce(&self::DispatchActivateEventOnIOThread,
- base::Unretained(this), done, result));
+ base::Unretained(this), std::move(done), result));
}
void DispatchActivateEventOnIOThread(
- const base::Closure& done,
+ base::OnceClosure done,
base::Optional<blink::ServiceWorkerStatusCode>* result,
blink::ServiceWorkerStatusCode start_worker_status) {
ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
ASSERT_EQ(blink::ServiceWorkerStatusCode::kOk, start_worker_status);
version_->SetStatus(ServiceWorkerVersion::ACTIVATING);
registration_->SetActiveVersion(version_.get());
- int request_id =
- version_->StartRequest(ServiceWorkerMetrics::EventType::INSTALL,
- CreateReceiver(BrowserThread::UI, done, result));
+ int request_id = version_->StartRequest(
+ ServiceWorkerMetrics::EventType::INSTALL,
+ CreateReceiver(BrowserThread::UI, std::move(done), result));
version_->endpoint()->DispatchActivateEvent(
version_->CreateSimpleEventCallback(request_id));
}
@@ -899,10 +906,10 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
*out_status = status;
*out_update_found = !!registration->installing_version();
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, done_on_ui);
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI}, done_on_ui);
}
- void FetchOnIOThread(const base::Closure& done,
+ void FetchOnIOThread(base::OnceClosure done,
bool* prepare_result,
FetchResult* result) {
ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
@@ -911,7 +918,7 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
ResourceType resource_type = RESOURCE_TYPE_MAIN_FRAME;
base::OnceClosure prepare_callback = CreatePrepareReceiver(prepare_result);
ServiceWorkerFetchDispatcher::FetchCallback fetch_callback =
- CreateResponseReceiver(done, blob_context_.get(), result);
+ CreateResponseReceiver(std::move(done), blob_context_.get(), result);
auto request = std::make_unique<network::ResourceRequest>();
request->url = url;
request->method = "GET";
@@ -927,8 +934,8 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
base::Time GetLastUpdateCheck(int64_t registration_id) {
base::Time last_update_time;
base::RunLoop time_run_loop;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&self::GetLastUpdateCheckOnIOThread,
base::Unretained(this), registration_id,
&last_update_time, time_run_loop.QuitClosure()));
@@ -944,7 +951,7 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
wrapper()->context()->GetLiveRegistration(registration_id);
ASSERT_TRUE(registration);
*out_time = registration->last_update_check();
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, done_on_ui);
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI}, done_on_ui);
}
void SetLastUpdateCheckOnIOThread(int64_t registration_id,
@@ -955,20 +962,21 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
wrapper()->context()->GetLiveRegistration(registration_id);
ASSERT_TRUE(registration);
registration->set_last_update_check(last_update_time);
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, done_on_ui);
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI}, done_on_ui);
}
// Contrary to the style guide, the output parameter of this function comes
// before input parameters so Bind can be used on it to create a FetchCallback
// to pass to DispatchFetchEvent.
void ReceiveFetchResultOnIOThread(
- const base::Closure& quit,
+ base::OnceClosure quit,
ChromeBlobStorageContext* blob_context,
FetchResult* out_result,
blink::ServiceWorkerStatusCode actual_status,
ServiceWorkerFetchDispatcher::FetchEventResult actual_result,
blink::mojom::FetchAPIResponsePtr actual_response,
blink::mojom::ServiceWorkerStreamHandlePtr /* stream */,
+ blink::mojom::ServiceWorkerFetchEventTimingPtr /* timing */,
scoped_refptr<ServiceWorkerVersion> worker) {
ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
ASSERT_TRUE(fetch_dispatcher_);
@@ -983,21 +991,21 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
out_result->response->blob->uuid);
}
if (!quit.is_null())
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, quit);
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI}, std::move(quit));
}
ServiceWorkerFetchDispatcher::FetchCallback CreateResponseReceiver(
- const base::Closure& quit,
+ base::OnceClosure quit,
ChromeBlobStorageContext* blob_context,
FetchResult* result) {
return base::BindOnce(&self::ReceiveFetchResultOnIOThread,
- base::Unretained(this), quit,
+ base::Unretained(this), std::move(quit),
base::RetainedRef(blob_context), result);
}
- void StopOnIOThread(const base::Closure& done) {
+ void StopOnIOThread(base::OnceClosure done) {
ASSERT_TRUE(version_.get());
- version_->StopWorker(done);
+ version_->StopWorker(std::move(done));
}
protected:
@@ -1017,8 +1025,8 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, StartAndStop) {
// Start a worker.
base::Optional<blink::ServiceWorkerStatusCode> status;
base::RunLoop start_run_loop;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&self::StartOnIOThread, base::Unretained(this),
start_run_loop.QuitClosure(), &status));
start_run_loop.Run();
@@ -1026,8 +1034,8 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, StartAndStop) {
// Stop the worker.
base::RunLoop stop_run_loop;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&self::StopOnIOThread, base::Unretained(this),
stop_run_loop.QuitClosure()));
stop_run_loop.Run();
@@ -1044,8 +1052,8 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
// Start a worker.
base::Optional<blink::ServiceWorkerStatusCode> status;
base::RunLoop start_run_loop;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&self::StartOnIOThread, base::Unretained(this),
start_run_loop.QuitClosure(), &status));
start_run_loop.Run();
@@ -1057,8 +1065,8 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
// Stop the worker.
base::RunLoop stop_run_loop;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&self::StopOnIOThread, base::Unretained(this),
stop_run_loop.QuitClosure()));
stop_run_loop.Run();
@@ -1244,8 +1252,8 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
// Dispatch install on a worker.
base::Optional<blink::ServiceWorkerStatusCode> status;
base::RunLoop install_run_loop;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&self::InstallOnIOThread, base::Unretained(this),
install_run_loop.QuitClosure(), &status));
install_run_loop.Run();
@@ -1264,15 +1272,16 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
class WaitForLoaded : public EmbeddedWorkerInstance::Listener {
public:
- explicit WaitForLoaded(const base::Closure& quit) : quit_(quit) {}
+ explicit WaitForLoaded(base::OnceClosure quit) : quit_(std::move(quit)) {}
void OnScriptEvaluationStart() override {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, quit_);
+ DCHECK(quit_);
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI}, std::move(quit_));
}
private:
- base::Closure quit_;
+ base::OnceClosure quit_;
};
IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, TimeoutStartingWorker) {
@@ -1289,8 +1298,8 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, TimeoutStartingWorker) {
RunOnIOThread(base::BindOnce(&EmbeddedWorkerInstance::AddObserver,
base::Unretained(version_->embedded_worker()),
&wait_for_load));
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&self::StartOnIOThread, base::Unretained(this),
start_run_loop.QuitClosure(), &status));
load_run_loop.Run();
@@ -1321,8 +1330,8 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, TimeoutWorkerInEvent) {
// Start a worker.
base::Optional<blink::ServiceWorkerStatusCode> status;
base::RunLoop start_run_loop;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&self::StartOnIOThread, base::Unretained(this),
start_run_loop.QuitClosure(), &status));
start_run_loop.Run();
@@ -1330,8 +1339,8 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, TimeoutWorkerInEvent) {
// Dispatch an event.
base::RunLoop install_run_loop;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&self::InstallOnIOThread, base::Unretained(this),
install_run_loop.QuitClosure(), &status));
@@ -1466,6 +1475,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
// Make options. Set to kAll so updating exercises the browser cache.
blink::mojom::ServiceWorkerRegistrationOptions options(
embedded_test_server()->GetURL(kScope),
+ blink::mojom::ScriptType::kClassic,
blink::mojom::ServiceWorkerUpdateViaCache::kAll);
// Register and wait for activation.
@@ -1498,8 +1508,8 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
{
last_update_time = base::Time::Now() - base::TimeDelta::FromHours(24);
base::RunLoop time_run_loop;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&self::SetLastUpdateCheckOnIOThread,
base::Unretained(this), registration_id,
last_update_time, time_run_loop.QuitClosure()));
@@ -1598,6 +1608,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest, FetchPageWithSaveData) {
observer->Init();
blink::mojom::ServiceWorkerRegistrationOptions options(
embedded_test_server()->GetURL(kPageUrl),
+ blink::mojom::ScriptType::kClassic,
blink::mojom::ServiceWorkerUpdateViaCache::kImports);
public_context()->RegisterServiceWorker(
embedded_test_server()->GetURL(kWorkerUrl), options,
@@ -1642,6 +1653,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest, CrossOriginFetchWithSaveData) {
observer->Init();
blink::mojom::ServiceWorkerRegistrationOptions options(
embedded_test_server()->GetURL(kPageUrl),
+ blink::mojom::ScriptType::kClassic,
blink::mojom::ServiceWorkerUpdateViaCache::kImports);
public_context()->RegisterServiceWorker(
embedded_test_server()->GetURL(kWorkerUrl), options,
@@ -1687,6 +1699,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest,
blink::mojom::ServiceWorkerRegistrationOptions options(
embedded_test_server()->GetURL(kPageUrl),
+ blink::mojom::ScriptType::kClassic,
blink::mojom::ServiceWorkerUpdateViaCache::kImports);
public_context()->RegisterServiceWorker(
embedded_test_server()->GetURL(kWorkerUrl), options,
@@ -1715,6 +1728,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest, Reload) {
observer->Init();
blink::mojom::ServiceWorkerRegistrationOptions options(
embedded_test_server()->GetURL(kPageUrl),
+ blink::mojom::ScriptType::kClassic,
blink::mojom::ServiceWorkerUpdateViaCache::kImports);
public_context()->RegisterServiceWorker(
embedded_test_server()->GetURL(kWorkerUrl), options,
@@ -1766,7 +1780,8 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest, IdleTimerWithDevTools) {
"/service_worker/fetch_event_respond_with_fetch.js");
blink::mojom::ServiceWorkerRegistrationOptions options(
- scope, blink::mojom::ServiceWorkerUpdateViaCache::kNone);
+ scope, blink::mojom::ScriptType::kClassic,
+ blink::mojom::ServiceWorkerUpdateViaCache::kNone);
public_context()->RegisterServiceWorker(
worker_url, options,
base::BindOnce(&ExpectResultAndRun, true, base::DoNothing()));
@@ -1774,19 +1789,15 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest, IdleTimerWithDevTools) {
// Navigate to a new page and request a sub resource. This should succeed
// normally.
- {
- const GURL url = embedded_test_server()->GetURL(
- "/service_worker/fetch_from_page.html?url=/service_worker/empty.html");
- EXPECT_TRUE(NavigateToURL(shell(), url));
- const base::string16 title = base::ASCIIToUTF16("DONE");
- TitleWatcher watcher(shell()->web_contents(), title);
- EXPECT_EQ(title, watcher.WaitAndGetTitle());
- }
+ EXPECT_TRUE(NavigateToURL(
+ shell(),
+ embedded_test_server()->GetURL("/service_worker/fetch_from_page.html")));
+ EXPECT_EQ("Echo", EvalJs(shell(), "fetch_from_page('/echo');"));
// Simulate to attach DevTools.
base::RunLoop loop;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
[](base::OnceClosure done, ServiceWorkerContextWrapper* wrapper,
int64_t version_id) {
@@ -1816,12 +1827,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest, IdleTimerWithDevTools) {
// idle. However, the browser process notifies the renderer to let it continue
// to work because DevTools is attached, and it'll result in running all
// queued events.
- EXPECT_EQ(200, EvalJs(shell(), R"(
- (async () => {
- let response = await fetch(params.get('url'));
- return response.status;
- })()
- )"));
+ EXPECT_EQ("Echo", EvalJs(shell(), "fetch_from_page('/echo');"));
}
class ServiceWorkerNavigationPreloadTest : public ServiceWorkerBrowserTest {
@@ -1869,7 +1875,8 @@ class ServiceWorkerNavigationPreloadTest : public ServiceWorkerBrowserTest {
observer->Init();
blink::mojom::ServiceWorkerRegistrationOptions options(
- scope, blink::mojom::ServiceWorkerUpdateViaCache::kImports);
+ scope, blink::mojom::ScriptType::kClassic,
+ blink::mojom::ServiceWorkerUpdateViaCache::kImports);
public_context()->RegisterServiceWorker(
worker_url, options,
base::BindOnce(&ExpectResultAndRun, true, base::DoNothing()));
@@ -2255,6 +2262,130 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest, GetResponseText) {
EXPECT_EQ(1, GetRequestCount(kPageUrl));
}
+IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest,
+ GetLargeResponseText) {
+ const char kPageUrl[] = "/service_worker/navigation_preload.html";
+ const char kWorkerUrl[] = "/service_worker/navigation_preload.js";
+ std::string title = "<title>PASS</title>";
+ // A large body that exceeds the default size of a mojo::DataPipe.
+ constexpr size_t kBodySize = 128 * 1024;
+ // Randomly generate the body data
+ int index = 0;
+ std::string body;
+ for (size_t i = 0; i < kBodySize; ++i) {
+ body += static_cast<char>(index + 'a');
+ index = (37 * index + 11) % 26;
+ }
+ const std::string kScript =
+ kEnableNavigationPreloadScript +
+ "self.addEventListener('fetch', event => {\n"
+ " event.respondWith(\n"
+ " event.preloadResponse\n"
+ " .then(response => response.text())\n"
+ " .then(text =>\n"
+ " new Response(\n"
+ " text,\n"
+ " {headers: [['content-type', 'text/html']]})));\n"
+ " });";
+ const GURL page_url = embedded_test_server()->GetURL(kPageUrl);
+ const GURL worker_url = embedded_test_server()->GetURL(kWorkerUrl);
+ RegisterStaticFile(kPageUrl, title + body, "text/html");
+ RegisterStaticFile(kWorkerUrl, kScript, "text/javascript");
+
+ EXPECT_EQ(body, LoadNavigationPreloadTestPage(page_url, worker_url, "PASS"));
+
+ // The page request must be sent only once, since the worker responded with
+ // a synthetic Response.
+ EXPECT_EQ(1, GetRequestCount(kPageUrl));
+}
+
+IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest,
+ GetLargeResponseCloneText) {
+ const char kPageUrl[] = "/service_worker/navigation_preload.html";
+ const char kWorkerUrl[] = "/service_worker/navigation_preload.js";
+ std::string title = "<title>PASS</title>";
+ // A large body that exceeds the default size of a mojo::DataPipe.
+ constexpr size_t kBodySize = 128 * 1024;
+ // Randomly generate the body data
+ int index = 0;
+ std::string body;
+ for (size_t i = 0; i < kBodySize; ++i) {
+ body += static_cast<char>(index + 'a');
+ index = (37 * index + 11) % 26;
+ }
+ const std::string kScript =
+ kEnableNavigationPreloadScript +
+ "self.addEventListener('fetch', event => {\n"
+ " event.respondWith(\n"
+ " event.preloadResponse\n"
+ " .then(response => response.clone())\n"
+ " .then(response => response.text())\n"
+ " .then(text =>\n"
+ " new Response(\n"
+ " text,\n"
+ " {headers: [['content-type', 'text/html']]})));\n"
+ " });";
+ const GURL page_url = embedded_test_server()->GetURL(kPageUrl);
+ const GURL worker_url = embedded_test_server()->GetURL(kWorkerUrl);
+ RegisterStaticFile(kPageUrl, title + body, "text/html");
+ RegisterStaticFile(kWorkerUrl, kScript, "text/javascript");
+
+ EXPECT_EQ(body, LoadNavigationPreloadTestPage(page_url, worker_url, "PASS"));
+
+ // The page request must be sent only once, since the worker responded with
+ // a synthetic Response.
+ EXPECT_EQ(1, GetRequestCount(kPageUrl));
+}
+
+IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest,
+ GetLargeResponseReadableStream) {
+ const char kPageUrl[] = "/service_worker/navigation_preload.html";
+ const char kWorkerUrl[] = "/service_worker/navigation_preload.js";
+ std::string title = "<title>PASS</title>";
+ // A large body that exceeds the default size of a mojo::DataPipe.
+ constexpr size_t kBodySize = 128 * 1024;
+ // Randomly generate the body data
+ int index = 0;
+ std::string body;
+ for (size_t i = 0; i < kBodySize; ++i) {
+ body += static_cast<char>(index + 'a');
+ index = (37 * index + 11) % 26;
+ }
+ const std::string kScript =
+ kEnableNavigationPreloadScript +
+ "function drain(reader) {\n"
+ " var data = [];\n"
+ " var decoder = new TextDecoder();\n"
+ " function nextChunk(chunk) {\n"
+ " if (chunk.done)\n"
+ " return data.join();\n"
+ " data.push(decoder.decode(chunk.value));\n"
+ " return reader.read().then(nextChunk);\n"
+ " }\n"
+ " return reader.read().then(nextChunk);\n"
+ "}\n"
+ "self.addEventListener('fetch', event => {\n"
+ " event.respondWith(\n"
+ " event.preloadResponse\n"
+ " .then(response => response.body.getReader())\n"
+ " .then(reader => drain(reader))\n"
+ " .then(text =>\n"
+ " new Response(\n"
+ " text,\n"
+ " {headers: [['content-type', 'text/html']]})));\n"
+ " });";
+ const GURL page_url = embedded_test_server()->GetURL(kPageUrl);
+ const GURL worker_url = embedded_test_server()->GetURL(kWorkerUrl);
+ RegisterStaticFile(kPageUrl, title + body, "text/html");
+ RegisterStaticFile(kWorkerUrl, kScript, "text/javascript");
+
+ EXPECT_EQ(body, LoadNavigationPreloadTestPage(page_url, worker_url, "PASS"));
+
+ // The page request must be sent only once, since the worker responded with
+ // a synthetic Response.
+ EXPECT_EQ(1, GetRequestCount(kPageUrl));
+}
+
IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest, NetworkError) {
const char kPageUrl[] = "/service_worker/navigation_preload.html";
const char kWorkerUrl[] = "/service_worker/navigation_preload.js";
@@ -2303,6 +2434,10 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest,
return;
}
+ auto console_observer =
+ base::MakeRefCounted<ConsoleMessageContextObserver>(wrapper());
+ console_observer->Init();
+
content::ResourceDispatcherHost::Get()->RegisterInterceptor(
kNavigationPreloadHeaderName, "",
base::Bind(&CancellingInterceptorCallback));
@@ -2317,6 +2452,11 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest,
EXPECT_EQ(kNavigationPreloadAbortError,
LoadNavigationPreloadTestPage(page_url, worker_url, "REJECTED"));
+
+ console_observer->WaitForConsoleMessages(1);
+ const base::string16 expected = base::ASCIIToUTF16("request was cancelled");
+ std::vector<base::string16> messages = console_observer->messages();
+ EXPECT_NE(base::string16::npos, messages[0].find(expected));
}
IN_PROC_BROWSER_TEST_F(ServiceWorkerNavigationPreloadTest,
@@ -2615,7 +2755,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest,
new WorkerActivatedObserver(wrapper());
observer->Init();
blink::mojom::ServiceWorkerRegistrationOptions options(
- https_server.GetURL(kPageUrl),
+ https_server.GetURL(kPageUrl), blink::mojom::ScriptType::kClassic,
blink::mojom::ServiceWorkerUpdateViaCache::kImports);
public_context()->RegisterServiceWorker(
https_server.GetURL(kWorkerUrl), options,
@@ -2654,6 +2794,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest,
observer->Init();
blink::mojom::ServiceWorkerRegistrationOptions options(
embedded_test_server()->GetURL(kPageUrl),
+ blink::mojom::ScriptType::kClassic,
blink::mojom::ServiceWorkerUpdateViaCache::kImports);
public_context()->RegisterServiceWorker(
embedded_test_server()->GetURL(kWorkerUrl), options,
@@ -2705,16 +2846,19 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest, ImportsBustMemcache) {
// An observer that waits for the version to stop.
class StopObserver : public ServiceWorkerVersion::Observer {
public:
- explicit StopObserver(const base::Closure& quit_closure)
- : quit_closure_(quit_closure) {}
+ explicit StopObserver(base::OnceClosure quit_closure)
+ : quit_closure_(std::move(quit_closure)) {}
void OnRunningStateChanged(ServiceWorkerVersion* version) override {
- if (version->running_status() == EmbeddedWorkerStatus::STOPPED)
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, quit_closure_);
+ if (version->running_status() == EmbeddedWorkerStatus::STOPPED) {
+ DCHECK(quit_closure_);
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ std::move(quit_closure_));
+ }
}
private:
- base::Closure quit_closure_;
+ base::OnceClosure quit_closure_;
};
IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, RendererCrash) {
@@ -2745,22 +2889,23 @@ class ServiceWorkerBlackBoxBrowserTest : public ServiceWorkerBrowserTest {
void FindRegistrationOnIO(const GURL& document_url,
blink::ServiceWorkerStatusCode* status,
- const base::Closure& continuation) {
+ base::OnceClosure continuation) {
wrapper()->FindReadyRegistrationForDocument(
document_url,
- base::BindOnce(&ServiceWorkerBlackBoxBrowserTest::FindRegistrationOnIO2,
- base::Unretained(this), status, continuation));
+ base::BindOnce(
+ &ServiceWorkerBlackBoxBrowserTest::DidFindRegistrationOnIO,
+ base::Unretained(this), status, std::move(continuation)));
}
- void FindRegistrationOnIO2(
+ void DidFindRegistrationOnIO(
blink::ServiceWorkerStatusCode* out_status,
- const base::Closure& continuation,
+ base::OnceClosure continuation,
blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration) {
*out_status = status;
if (!registration.get())
EXPECT_NE(blink::ServiceWorkerStatusCode::kOk, status);
- continuation.Run();
+ std::move(continuation).Run();
}
};
@@ -2791,6 +2936,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerBlackBoxBrowserTest, Registration) {
base::RunLoop run_loop;
blink::mojom::ServiceWorkerRegistrationOptions options(
embedded_test_server()->GetURL(kScope),
+ blink::mojom::ScriptType::kClassic,
blink::mojom::ServiceWorkerUpdateViaCache::kImports);
public_context()->RegisterServiceWorker(
embedded_test_server()->GetURL("/does/not/exist"), options,
@@ -2804,6 +2950,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerBlackBoxBrowserTest, Registration) {
base::RunLoop run_loop;
blink::mojom::ServiceWorkerRegistrationOptions options(
embedded_test_server()->GetURL(kScope),
+ blink::mojom::ScriptType::kClassic,
blink::mojom::ServiceWorkerUpdateViaCache::kImports);
public_context()->RegisterServiceWorker(
embedded_test_server()->GetURL(kWorkerUrl), options,
@@ -2818,6 +2965,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerBlackBoxBrowserTest, Registration) {
base::RunLoop run_loop;
blink::mojom::ServiceWorkerRegistrationOptions options(
embedded_test_server()->GetURL(kScope),
+ blink::mojom::ScriptType::kClassic,
blink::mojom::ServiceWorkerUpdateViaCache::kImports);
public_context()->RegisterServiceWorker(
embedded_test_server()->GetURL(kWorkerUrl), options,
@@ -2911,28 +3059,45 @@ class ServiceWorkerVersionBrowserV8CacheTest
if (version_)
version_->RemoveObserver(this);
}
- void SetUpCommandLine(base::CommandLine* command_line) override {
- command_line->AppendSwitchASCII(switches::kV8CacheOptions, "code");
- }
void SetUpRegistrationAndListenerOnIOThread(const std::string& worker_url) {
SetUpRegistrationOnIOThread(worker_url);
version_->AddObserver(this);
}
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ command_line->AppendSwitchASCII(switches::kV8CacheOptions, "code");
+ }
+ void StartWorkerAndWaitUntilCachedMetadataUpdated(
+ blink::ServiceWorkerStatusCode status) {
+ DCHECK(!cache_updated_closure_);
+
+ base::RunLoop run_loop;
+ cache_updated_closure_ = run_loop.QuitClosure();
+
+ // Start a worker.
+ StartWorker(status);
+
+ // Wait for the metadata to be stored. This run loop should finish when
+ // OnCachedMetadataUpdated() is called.
+ run_loop.Run();
+ }
+ size_t metadata_size() { return metadata_size_; };
protected:
// ServiceWorkerVersion::Observer overrides
void OnCachedMetadataUpdated(ServiceWorkerVersion* version,
size_t size) override {
+ DCHECK(cache_updated_closure_);
+
metadata_size_ = size;
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- cache_updated_closure_);
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ std::move(cache_updated_closure_));
}
- base::Closure cache_updated_closure_;
- size_t metadata_size_ = 0;
-
private:
base::test::ScopedFeatureList scoped_feature_list_;
+
+ base::OnceClosure cache_updated_closure_;
+ size_t metadata_size_ = 0;
};
IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserV8CacheTest, Restart) {
@@ -2940,37 +3105,23 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserV8CacheTest, Restart) {
RunOnIOThread(base::BindOnce(&self::SetUpRegistrationAndListenerOnIOThread,
base::Unretained(this),
"/service_worker/worker.js"));
- {
- base::RunLoop cached_metadata_run_loop;
- cache_updated_closure_ = cached_metadata_run_loop.QuitClosure();
-
- // Start a worker.
- StartWorker(blink::ServiceWorkerStatusCode::kOk);
- // Wait for the metadata to be stored. This run loop should finish when
- // OnCachedMetadataUpdated() is called.
- cached_metadata_run_loop.Run();
- }
+ StartWorkerAndWaitUntilCachedMetadataUpdated(
+ blink::ServiceWorkerStatusCode::kOk);
// Time stamp data must be stored to the storage.
- EXPECT_EQ(kV8CacheTimeStampDataSize, static_cast<int>(metadata_size_));
+ EXPECT_EQ(kV8CacheTimeStampDataSize, static_cast<int>(metadata_size()));
// Stop the worker.
StopWorker();
- {
- base::RunLoop cached_metadata_run_loop;
- cache_updated_closure_ = cached_metadata_run_loop.QuitClosure();
- // Restart the worker.
- StartWorker(blink::ServiceWorkerStatusCode::kOk);
- // Wait for the matadata to be stored. This run loop should finish when
- // OnCachedMetadataUpdated() is called.
- cached_metadata_run_loop.Run();
- }
+ // Restart the worker.
+ StartWorkerAndWaitUntilCachedMetadataUpdated(
+ blink::ServiceWorkerStatusCode::kOk);
// The V8 code cache should be stored to the storage. It must have size
// greater than 16 bytes.
- EXPECT_GT(static_cast<int>(metadata_size_), kV8CacheTimeStampDataSize);
+ EXPECT_GT(static_cast<int>(metadata_size()), kV8CacheTimeStampDataSize);
// Stop the worker.
StopWorker();
@@ -2993,21 +3144,37 @@ class ServiceWorkerVersionBrowserV8FullCodeCacheTest
SetUpRegistrationOnIOThread(worker_url);
version_->AddObserver(this);
}
+ void StartWorkerAndWaitUntilCachedMetadataUpdated(
+ blink::ServiceWorkerStatusCode status) {
+ DCHECK(!cache_updated_closure_);
+
+ base::RunLoop run_loop;
+ cache_updated_closure_ = run_loop.QuitClosure();
+
+ // Start a worker.
+ StartWorker(status);
+
+ // Wait for the metadata to be stored. This run loop should finish when
+ // OnCachedMetadataUpdated() is called.
+ run_loop.Run();
+ }
+ size_t metadata_size() { return metadata_size_; };
protected:
// ServiceWorkerVersion::Observer overrides
void OnCachedMetadataUpdated(ServiceWorkerVersion* version,
size_t size) override {
+ DCHECK(cache_updated_closure_);
metadata_size_ = size;
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- cache_updated_closure_);
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ std::move(cache_updated_closure_));
}
- base::Closure cache_updated_closure_;
- size_t metadata_size_ = 0;
-
private:
base::test::ScopedFeatureList scoped_feature_list_;
+
+ base::OnceClosure cache_updated_closure_;
+ size_t metadata_size_ = 0;
};
IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserV8FullCodeCacheTest,
@@ -3016,19 +3183,13 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserV8FullCodeCacheTest,
RunOnIOThread(base::BindOnce(&self::SetUpRegistrationAndListenerOnIOThread,
base::Unretained(this),
"/service_worker/worker.js"));
- base::RunLoop cached_metadata_run_loop;
- cache_updated_closure_ = cached_metadata_run_loop.QuitClosure();
-
- // Start a worker.
- StartWorker(blink::ServiceWorkerStatusCode::kOk);
- // Wait for the metadata to be stored. This run loop should finish when
- // OnCachedMetadataUpdated() is called.
- cached_metadata_run_loop.Run();
+ StartWorkerAndWaitUntilCachedMetadataUpdated(
+ blink::ServiceWorkerStatusCode::kOk);
// The V8 code cache should be stored to the storage. It must have size
// greater than 16 bytes.
- EXPECT_GT(static_cast<int>(metadata_size_), kV8CacheTimeStampDataSize);
+ EXPECT_GT(static_cast<int>(metadata_size()), kV8CacheTimeStampDataSize);
// Stop the worker.
StopWorker();
@@ -3073,15 +3234,15 @@ class CacheStorageSideDataSizeChecker
return result;
}
- void OpenCacheOnIOThread(int* result, const base::Closure& continuation) {
+ void OpenCacheOnIOThread(int* result, base::OnceClosure continuation) {
cache_storage_context_->cache_manager()->OpenCache(
url::Origin::Create(origin_), CacheStorageOwner::kCacheAPI, cache_name_,
base::BindOnce(&self::OnCacheStorageOpenCallback, this, result,
- continuation));
+ std::move(continuation)));
}
void OnCacheStorageOpenCallback(int* result,
- const base::Closure& continuation,
+ base::OnceClosure continuation,
CacheStorageCacheHandle cache_handle,
CacheStorageError error) {
ASSERT_EQ(CacheStorageError::kSuccess, error);
@@ -3089,14 +3250,15 @@ class CacheStorageSideDataSizeChecker
new ServiceWorkerFetchRequest());
scoped_request->url = url_;
CacheStorageCache* cache = cache_handle.value();
- cache->Match(std::move(scoped_request), nullptr,
- base::BindOnce(&self::OnCacheStorageCacheMatchCallback, this,
- result, continuation, std::move(cache_handle)));
+ cache->Match(
+ std::move(scoped_request), nullptr,
+ base::BindOnce(&self::OnCacheStorageCacheMatchCallback, this, result,
+ std::move(continuation), std::move(cache_handle)));
}
void OnCacheStorageCacheMatchCallback(
int* result,
- const base::Closure& continuation,
+ base::OnceClosure continuation,
CacheStorageCacheHandle cache_handle,
CacheStorageError error,
blink::mojom::FetchAPIResponsePtr response) {
@@ -3105,13 +3267,15 @@ class CacheStorageSideDataSizeChecker
blink::mojom::BlobPtr blob_ptr(std::move(response->blob->blob));
auto blob_handle =
base::MakeRefCounted<storage::BlobHandle>(std::move(blob_ptr));
- blob_handle->get()->ReadSideData(base::BindLambdaForTesting(
- [blob_handle, result,
- continuation](const base::Optional<std::vector<uint8_t>>& data) {
+ blob_handle->get()->ReadSideData(base::BindOnce(
+ [](scoped_refptr<storage::BlobHandle> blob_handle, int* result,
+ base::OnceClosure continuation,
+ const base::Optional<std::vector<uint8_t>>& data) {
if (data)
*result = data->size();
- continuation.Run();
- }));
+ std::move(continuation).Run();
+ },
+ blob_handle, result, std::move(continuation)));
}
CacheStorageContextImpl* cache_storage_context_;
@@ -3140,6 +3304,7 @@ class ServiceWorkerV8CodeCacheForCacheStorageTest
observer->Init();
blink::mojom::ServiceWorkerRegistrationOptions options(
embedded_test_server()->GetURL(kPageUrl),
+ blink::mojom::ScriptType::kClassic,
blink::mojom::ServiceWorkerUpdateViaCache::kImports);
public_context()->RegisterServiceWorker(
embedded_test_server()->GetURL(kWorkerUrl), options,
@@ -3261,7 +3426,7 @@ class ServiceWorkerDisableWebSecurityTest : public ServiceWorkerBrowserTest {
new WorkerActivatedObserver(wrapper());
observer->Init();
blink::mojom::ServiceWorkerRegistrationOptions options(
- cross_origin_server_.GetURL(scope),
+ cross_origin_server_.GetURL(scope), blink::mojom::ScriptType::kClassic,
blink::mojom::ServiceWorkerUpdateViaCache::kImports);
public_context()->RegisterServiceWorker(
cross_origin_server_.GetURL(script), options,
@@ -3378,26 +3543,20 @@ class ServiceWorkerURLLoaderThrottleTest : public ServiceWorkerBrowserTest {
ServiceWorkerBrowserTest::TearDownOnMainThread();
}
- void NavigateAndWaitForDone(const GURL& url) {
- const base::string16 title = base::ASCIIToUTF16("DONE");
- TitleWatcher watcher(shell()->web_contents(), title);
- watcher.AlsoWaitForTitle(base::ASCIIToUTF16("ERROR"));
- EXPECT_TRUE(NavigateToURL(shell(), url));
- EXPECT_EQ(title, watcher.WaitAndGetTitle());
- }
-
void RegisterServiceWorker(const std::string& worker_url) {
- GURL url = embedded_test_server()->GetURL(
- "/service_worker/create_service_worker.html?worker_url=" + worker_url);
- NavigateAndWaitForDone(url);
+ EXPECT_TRUE(NavigateToURL(
+ shell(), embedded_test_server()->GetURL(
+ "/service_worker/create_service_worker.html")));
+ EXPECT_EQ("DONE", EvalJs(shell(), "register('" + worker_url + "');"));
}
void RegisterServiceWorkerWithScope(const std::string& worker_url,
const std::string& scope) {
- GURL url = embedded_test_server()->GetURL(
- "/service_worker/create_service_worker.html?worker_url=" + worker_url +
- "&scope=" + scope);
- NavigateAndWaitForDone(url);
+ EXPECT_TRUE(NavigateToURL(
+ shell(), embedded_test_server()->GetURL(
+ "/service_worker/create_service_worker.html")));
+ EXPECT_EQ("DONE", EvalJs(shell(), "register('" + worker_url + "', '" +
+ scope + "');"));
}
};
@@ -3526,21 +3685,9 @@ IN_PROC_BROWSER_TEST_F(
EXPECT_EQ(true, EvalJs(shell()->web_contents()->GetMainFrame(),
"!!navigator.serviceWorker.controller"));
- if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
- // The injected header should be present.
- EXPECT_EQ("injected value", EvalJs(shell()->web_contents()->GetMainFrame(),
- "document.body.textContent"));
- } else {
- // S13nServiceWorker: the injected header is not present. Throttle-modified
- // headers are not propagated to network requests through
- // ResourceDispatcherHost, because the legacy network code has its own code
- // path that applies the same throttling independent from the navigation's
- // URLLoaderThrottles.
- DCHECK(base::FeatureList::IsEnabled(
- blink::features::kServiceWorkerServicification));
- EXPECT_EQ("None", EvalJs(shell()->web_contents()->GetMainFrame(),
- "document.body.textContent"));
- }
+ // The injected header should be present.
+ EXPECT_EQ("injected value", EvalJs(shell()->web_contents()->GetMainFrame(),
+ "document.body.textContent"));
SetBrowserClientForTesting(old_content_browser_client);
}
diff --git a/chromium/content/browser/service_worker/service_worker_cache_writer.cc b/chromium/content/browser/service_worker/service_worker_cache_writer.cc
index 2d43b2ec095..7ff8cde2513 100644
--- a/chromium/content/browser/service_worker/service_worker_cache_writer.cc
+++ b/chromium/content/browser/service_worker/service_worker_cache_writer.cc
@@ -117,11 +117,12 @@ int ServiceWorkerCacheWriter::DoLoop(int status) {
ServiceWorkerCacheWriter::ServiceWorkerCacheWriter(
std::unique_ptr<ServiceWorkerResponseReader> compare_reader,
std::unique_ptr<ServiceWorkerResponseReader> copy_reader,
- std::unique_ptr<ServiceWorkerResponseWriter> writer)
+ std::unique_ptr<ServiceWorkerResponseWriter> writer,
+ bool pause_when_not_identical)
: state_(STATE_START),
io_pending_(false),
comparing_(false),
- did_replace_(false),
+ pause_when_not_identical_(pause_when_not_identical),
compare_reader_(std::move(compare_reader)),
copy_reader_(std::move(copy_reader)),
writer_(std::move(writer)),
@@ -136,12 +137,12 @@ net::Error ServiceWorkerCacheWriter::MaybeWriteHeaders(
headers_to_write_ = headers;
pending_callback_ = std::move(callback);
- DCHECK_EQ(state_, STATE_START);
+ DCHECK_EQ(STATE_START, state_);
int result = DoLoop(net::OK);
// Synchronous errors and successes always go to STATE_DONE.
if (result != net::ERR_IO_PENDING)
- DCHECK_EQ(state_, STATE_DONE);
+ DCHECK_EQ(STATE_DONE, state_);
// ERR_IO_PENDING has to have one of the STATE_*_DONE states as the next state
// (not STATE_DONE itself).
@@ -175,7 +176,7 @@ net::Error ServiceWorkerCacheWriter::MaybeWriteData(
// Synchronous completions are always STATE_DONE.
if (result != net::ERR_IO_PENDING)
- DCHECK_EQ(state_, STATE_DONE);
+ DCHECK_EQ(STATE_DONE, state_);
// Asynchronous completion means the state machine must be waiting in one of
// the Done states for an IO operation to complete:
@@ -185,6 +186,7 @@ net::Error ServiceWorkerCacheWriter::MaybeWriteData(
// STATE_WRITE_HEADERS_FOR_PASSTHROUGH_DONE is excluded because that write
// is done by MaybeWriteHeaders.
DCHECK(state_ == STATE_READ_DATA_FOR_COMPARE_DONE ||
+ state_ == STATE_PAUSING ||
state_ == STATE_READ_HEADERS_FOR_COPY_DONE ||
state_ == STATE_READ_DATA_FOR_COPY_DONE ||
state_ == STATE_WRITE_HEADERS_FOR_COPY_DONE ||
@@ -192,6 +194,38 @@ net::Error ServiceWorkerCacheWriter::MaybeWriteData(
state_ == STATE_WRITE_DATA_FOR_PASSTHROUGH_DONE)
<< "Unexpected state: " << state_;
}
+ return result >= 0 ? net::OK : static_cast<net::Error>(result);
+}
+
+net::Error ServiceWorkerCacheWriter::Resume(OnWriteCompleteCallback callback) {
+ DCHECK(pause_when_not_identical_);
+ DCHECK_EQ(STATE_PAUSING, state_);
+ DCHECK(io_pending_);
+
+ io_pending_ = false;
+ pending_callback_ = std::move(callback);
+ state_ = STATE_READ_HEADERS_FOR_COPY;
+
+ int result = DoLoop(net::OK);
+
+ // Synchronous completions are always STATE_DONE.
+ if (result != net::ERR_IO_PENDING)
+ DCHECK_EQ(STATE_DONE, state_);
+
+ // Asynchronous completion means the state machine must be waiting in one of
+ // the Done states for an IO operation to complete:
+ if (result == net::ERR_IO_PENDING) {
+ // Note that STATE_READ_HEADERS_FOR_COMPARE_DONE is excluded because the
+ // headers are compared in MaybeWriteHeaders, not here, and
+ // STATE_WRITE_HEADERS_FOR_PASSTHROUGH_DONE is excluded because that write
+ // is done by MaybeWriteHeaders.
+ DCHECK(state_ == STATE_READ_HEADERS_FOR_COPY_DONE ||
+ state_ == STATE_READ_DATA_FOR_COPY_DONE ||
+ state_ == STATE_WRITE_HEADERS_FOR_COPY_DONE ||
+ state_ == STATE_WRITE_DATA_FOR_COPY_DONE ||
+ state_ == STATE_WRITE_DATA_FOR_PASSTHROUGH_DONE)
+ << "Unexpected state: " << state_;
+ }
return result >= 0 ? net::OK : static_cast<net::Error>(result);
}
@@ -233,7 +267,7 @@ int ServiceWorkerCacheWriter::DoReadDataForCompare(int result) {
DCHECK_GE(result, 0);
DCHECK(data_to_write_);
- data_to_read_ = new net::IOBuffer(len_to_write_);
+ data_to_read_ = base::MakeRefCounted<net::IOBuffer>(len_to_write_);
len_to_read_ = len_to_write_;
state_ = STATE_READ_DATA_FOR_COMPARE_DONE;
compare_offset_ = 0;
@@ -259,8 +293,9 @@ int ServiceWorkerCacheWriter::DoReadDataForCompareDone(int result) {
// compare. Fail the comparison.
if (result == 0 && len_to_write_ != 0) {
comparing_ = false;
- state_ = STATE_READ_HEADERS_FOR_COPY;
- return net::OK;
+ state_ =
+ pause_when_not_identical_ ? STATE_PAUSING : STATE_READ_HEADERS_FOR_COPY;
+ return pause_when_not_identical_ ? net::ERR_IO_PENDING : net::OK;
}
// Compare the data from the ServiceWorker script cache to the data from the
@@ -271,8 +306,9 @@ int ServiceWorkerCacheWriter::DoReadDataForCompareDone(int result) {
// |bytes_compared_| were identical, so copy the first |bytes_compared_|
// over, then start writing network data back after the changed point.
comparing_ = false;
- state_ = STATE_READ_HEADERS_FOR_COPY;
- return net::OK;
+ state_ =
+ pause_when_not_identical_ ? STATE_PAUSING : STATE_READ_HEADERS_FOR_COPY;
+ return pause_when_not_identical_ ? net::ERR_IO_PENDING : net::OK;
}
compare_offset_ += result;
@@ -294,8 +330,9 @@ int ServiceWorkerCacheWriter::DoReadDataForCompareDone(int result) {
// just the prefix.
if (len_to_read_ == 0 && bytes_compared_ + compare_offset_ < cached_length_) {
comparing_ = false;
- state_ = STATE_READ_HEADERS_FOR_COPY;
- return net::OK;
+ state_ =
+ pause_when_not_identical_ ? STATE_PAUSING : STATE_READ_HEADERS_FOR_COPY;
+ return pause_when_not_identical_ ? net::ERR_IO_PENDING : net::OK;
}
bytes_compared_ += compare_offset_;
@@ -308,7 +345,7 @@ int ServiceWorkerCacheWriter::DoReadHeadersForCopy(int result) {
DCHECK(copy_reader_);
bytes_copied_ = 0;
headers_to_read_ = new HttpResponseInfoIOBuffer;
- data_to_copy_ = new net::IOBuffer(kCopyBufferSize);
+ data_to_copy_ = base::MakeRefCounted<net::IOBuffer>(kCopyBufferSize);
state_ = STATE_READ_HEADERS_FOR_COPY_DONE;
return ReadInfoHelper(copy_reader_, headers_to_read_.get());
}
@@ -492,10 +529,15 @@ void ServiceWorkerCacheWriter::AsyncDoLoop(int result) {
// later invocation of AsyncDoLoop.
if (result != net::ERR_IO_PENDING) {
OnWriteCompleteCallback callback = std::move(pending_callback_);
- pending_callback_.Reset();
net::Error error = result >= 0 ? net::OK : static_cast<net::Error>(result);
io_pending_ = false;
std::move(callback).Run(error);
+ return;
+ }
+ if (state_ == STATE_PAUSING) {
+ DCHECK(pause_when_not_identical_);
+ OnWriteCompleteCallback callback = std::move(pending_callback_);
+ std::move(callback).Run(net::ERR_IO_PENDING);
}
}
diff --git a/chromium/content/browser/service_worker/service_worker_cache_writer.h b/chromium/content/browser/service_worker/service_worker_cache_writer.h
index e357240657f..e8866e14f68 100644
--- a/chromium/content/browser/service_worker/service_worker_cache_writer.h
+++ b/chromium/content/browser/service_worker/service_worker_cache_writer.h
@@ -42,10 +42,16 @@ class CONTENT_EXPORT ServiceWorkerCacheWriter {
// The |compare_reader| may be null, in which case this instance will
// unconditionally write back data supplied to |MaybeWriteHeaders| and
// |MaybeWriteData|.
+ //
+ // When |pause_when_not_identical| is true and the cache writer detects a
+ // difference between bodies from the network and from the storage, the
+ // comparison stops immediately and the cache writer returns
+ // net::ERR_IO_PENDING, with nothing written to the storage.
ServiceWorkerCacheWriter(
std::unique_ptr<ServiceWorkerResponseReader> compare_reader,
std::unique_ptr<ServiceWorkerResponseReader> copy_reader,
- std::unique_ptr<ServiceWorkerResponseWriter> writer);
+ std::unique_ptr<ServiceWorkerResponseWriter> writer,
+ bool pause_when_not_identical);
~ServiceWorkerCacheWriter();
@@ -73,6 +79,13 @@ class CONTENT_EXPORT ServiceWorkerCacheWriter {
// Returns a count of bytes written back to the cache.
size_t bytes_written() const { return bytes_written_; }
bool did_replace() const { return did_replace_; }
+ bool is_pausing() const { return state_ == STATE_PAUSING; }
+
+ // Resumes a cache writer which were paused when a block of data from the
+ // network wasn't identical to the data in the storage. It is valid to call
+ // this method only when |pause_when_not_identical| is true in the constructor
+ // and |state_| is STATE_PAUSING.
+ net::Error Resume(OnWriteCompleteCallback callback);
private:
// States for the state machine.
@@ -102,6 +115,10 @@ class CONTENT_EXPORT ServiceWorkerCacheWriter {
STATE_READ_DATA_FOR_COMPARE,
STATE_READ_DATA_FOR_COMPARE_DONE,
+ // The cache writer is paused because the network data wasn't identical with
+ // the stored data, and |pause_when_not_identical| is true.
+ STATE_PAUSING,
+
// Control flows linearly through these states, with each pass from
// READ_DATA_FOR_COPY to WRITE_DATA_FOR_COPY_DONE copying one block of data
// at a time. Control loops from WRITE_DATA_FOR_COPY_DONE back to
@@ -219,7 +236,12 @@ class CONTENT_EXPORT ServiceWorkerCacheWriter {
// Count of bytes written back to |writer_|.
size_t bytes_written_;
- bool did_replace_;
+ bool did_replace_ = false;
+
+ // When the cache writer finds any differences between bodies from the network
+ // and from the storage, and the |pause_when_not_identical_| is true, the
+ // cache writer pauses immediately.
+ const bool pause_when_not_identical_;
std::unique_ptr<ServiceWorkerResponseReader> compare_reader_;
std::unique_ptr<ServiceWorkerResponseReader> copy_reader_;
diff --git a/chromium/content/browser/service_worker/service_worker_cache_writer_unittest.cc b/chromium/content/browser/service_worker/service_worker_cache_writer_unittest.cc
index 38d9f5c1f28..d37f40a4038 100644
--- a/chromium/content/browser/service_worker/service_worker_cache_writer_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_cache_writer_unittest.cc
@@ -19,306 +19,6 @@
namespace content {
namespace {
-// A test implementation of ServiceWorkerResponseReader.
-//
-// This class exposes the ability to expect reads (see ExpectRead*() below).
-// Each call to ReadInfo() or ReadData() consumes another expected read, in the
-// order those reads were expected, so:
-// reader->ExpectReadInfoOk(5, false);
-// reader->ExpectReadDataOk("abcdef", false);
-// reader->ExpectReadDataOk("ghijkl", false);
-// Expects these calls, in this order:
-// reader->ReadInfo(...); // reader writes 5 into
-// // |info_buf->response_data_size|
-// reader->ReadData(...); // reader writes "abcdef" into |buf|
-// reader->ReadData(...); // reader writes "ghijkl" into |buf|
-// If an unexpected call happens, this class DCHECKs.
-// If an expected read is marked "async", it will not complete immediately, but
-// must be completed by the test using CompletePendingRead().
-// These is a convenience method AllExpectedReadsDone() which returns whether
-// there are any expected reads that have not yet happened.
-class MockServiceWorkerResponseReader : public ServiceWorkerResponseReader {
- public:
- MockServiceWorkerResponseReader()
- : ServiceWorkerResponseReader(
- 0,
- base::WeakPtr<AppCacheDiskCacheInterface>()) {}
- ~MockServiceWorkerResponseReader() override {}
-
- // ServiceWorkerResponseReader overrides
- void ReadInfo(HttpResponseInfoIOBuffer* info_buf,
- OnceCompletionCallback callback) override;
- void ReadData(net::IOBuffer* buf,
- int buf_len,
- OnceCompletionCallback callback) override;
-
- // Test helpers. ExpectReadInfo() and ExpectReadData() give precise control
- // over both the data to be written and the result to return.
- // ExpectReadInfoOk() and ExpectReadDataOk() are convenience functions for
- // expecting successful reads, which always have their length as their result.
-
- // Expect a call to ReadInfo() on this reader. For these functions, |len| will
- // be used as |response_data_size|, not as the length of this particular read.
- void ExpectReadInfo(size_t len, bool async, int result);
- void ExpectReadInfoOk(size_t len, bool async);
-
- // Expect a call to ReadData() on this reader. For these functions, |len| is
- // the length of the data to be written back; in ExpectReadDataOk(), |len| is
- // implicitly the length of |data|.
- void ExpectReadData(const char* data, size_t len, bool async, int result);
- void ExpectReadDataOk(const std::string& data, bool async);
-
- // Complete a pending async read. It is an error to call this function without
- // a pending async read (ie, a previous call to ReadInfo() or ReadData()
- // having not run its callback yet).
- void CompletePendingRead();
-
- // Returns whether all expected reads have occurred.
- bool AllExpectedReadsDone() { return expected_reads_.size() == 0; }
-
- private:
- struct ExpectedRead {
- ExpectedRead(size_t len, bool async, int result)
- : data(nullptr), len(len), info(true), async(async), result(result) {}
- ExpectedRead(const char* data, size_t len, bool async, int result)
- : data(data), len(len), info(false), async(async), result(result) {}
- const char* data;
- size_t len;
- bool info;
- bool async;
- int result;
- };
-
- base::queue<ExpectedRead> expected_reads_;
- scoped_refptr<net::IOBuffer> pending_buffer_;
- size_t pending_buffer_len_;
- scoped_refptr<HttpResponseInfoIOBuffer> pending_info_;
- OnceCompletionCallback pending_callback_;
-
- DISALLOW_COPY_AND_ASSIGN(MockServiceWorkerResponseReader);
-};
-
-void MockServiceWorkerResponseReader::ReadInfo(
- HttpResponseInfoIOBuffer* info_buf,
- OnceCompletionCallback callback) {
- DCHECK(!expected_reads_.empty());
- ExpectedRead expected = expected_reads_.front();
- EXPECT_TRUE(expected.info);
- if (expected.async) {
- pending_info_ = info_buf;
- pending_callback_ = std::move(callback);
- } else {
- expected_reads_.pop();
- info_buf->response_data_size = expected.len;
- std::move(callback).Run(expected.result);
- }
-}
-
-void MockServiceWorkerResponseReader::ReadData(
- net::IOBuffer* buf,
- int buf_len,
- OnceCompletionCallback callback) {
- DCHECK(!expected_reads_.empty());
- ExpectedRead expected = expected_reads_.front();
- EXPECT_FALSE(expected.info);
- if (expected.async) {
- pending_callback_ = std::move(callback);
- pending_buffer_ = buf;
- pending_buffer_len_ = static_cast<size_t>(buf_len);
- } else {
- expected_reads_.pop();
- if (expected.len > 0) {
- size_t to_read = std::min(static_cast<size_t>(buf_len), expected.len);
- memcpy(buf->data(), expected.data, to_read);
- }
- std::move(callback).Run(expected.result);
- }
-}
-
-void MockServiceWorkerResponseReader::ExpectReadInfo(size_t len,
- bool async,
- int result) {
- expected_reads_.push(ExpectedRead(len, async, result));
-}
-
-void MockServiceWorkerResponseReader::ExpectReadInfoOk(size_t len, bool async) {
- expected_reads_.push(ExpectedRead(len, async, len));
-}
-
-void MockServiceWorkerResponseReader::ExpectReadData(const char* data,
- size_t len,
- bool async,
- int result) {
- expected_reads_.push(ExpectedRead(data, len, async, result));
-}
-
-void MockServiceWorkerResponseReader::ExpectReadDataOk(const std::string& data,
- bool async) {
- expected_reads_.push(
- ExpectedRead(data.data(), data.size(), async, data.size()));
-}
-
-void MockServiceWorkerResponseReader::CompletePendingRead() {
- DCHECK(!expected_reads_.empty());
- ExpectedRead expected = expected_reads_.front();
- expected_reads_.pop();
- EXPECT_TRUE(expected.async);
- if (expected.info) {
- pending_info_->response_data_size = expected.len;
- } else {
- size_t to_read = std::min(pending_buffer_len_, expected.len);
- if (to_read > 0)
- memcpy(pending_buffer_->data(), expected.data, to_read);
- }
- pending_info_ = nullptr;
- pending_buffer_ = nullptr;
- OnceCompletionCallback callback = std::move(pending_callback_);
- pending_callback_.Reset();
- std::move(callback).Run(expected.result);
-}
-
-// A test implementation of ServiceWorkerResponseWriter.
-//
-// This class exposes the ability to expect writes (see ExpectWrite*Ok() below).
-// Each write to this class via WriteInfo() or WriteData() consumes another
-// expected write, in the order they were added, so:
-// writer->ExpectWriteInfoOk(5, false);
-// writer->ExpectWriteDataOk(6, false);
-// writer->ExpectWriteDataOk(6, false);
-// Expects these calls, in this order:
-// writer->WriteInfo(...); // checks that |buf->response_data_size| == 5
-// writer->WriteData(...); // checks that 6 bytes are being written
-// writer->WriteData(...); // checks that another 6 bytes are being written
-// If this class receives an unexpected call to WriteInfo() or WriteData(), it
-// DCHECKs.
-// Expected writes marked async do not complete synchronously, but rather return
-// without running their callback and need to be completed with
-// CompletePendingWrite().
-// A convenience method AllExpectedWritesDone() is exposed so tests can ensure
-// that all expected writes have been consumed by matching calls to WriteInfo()
-// or WriteData().
-class MockServiceWorkerResponseWriter : public ServiceWorkerResponseWriter {
- public:
- MockServiceWorkerResponseWriter()
- : ServiceWorkerResponseWriter(
- 0,
- base::WeakPtr<AppCacheDiskCacheInterface>()),
- info_written_(0),
- data_written_(0) {}
- ~MockServiceWorkerResponseWriter() override {}
-
- // ServiceWorkerResponseWriter overrides
- void WriteInfo(HttpResponseInfoIOBuffer* info_buf,
- OnceCompletionCallback callback) override;
- void WriteData(net::IOBuffer* buf,
- int buf_len,
- OnceCompletionCallback callback) override;
-
- // Enqueue expected writes.
- void ExpectWriteInfoOk(size_t len, bool async);
- void ExpectWriteInfo(size_t len, bool async, int result);
- void ExpectWriteDataOk(size_t len, bool async);
- void ExpectWriteData(size_t len, bool async, int result);
-
- // Complete a pending asynchronous write. This method DCHECKs unless there is
- // a pending write (a write for which WriteInfo() or WriteData() has been
- // called but the callback has not yet been run).
- void CompletePendingWrite();
-
- // Returns whether all expected reads have been consumed.
- bool AllExpectedWritesDone() { return expected_writes_.size() == 0; }
-
- private:
- struct ExpectedWrite {
- ExpectedWrite(bool is_info, size_t length, bool async, int result)
- : is_info(is_info), length(length), async(async), result(result) {}
- bool is_info;
- size_t length;
- bool async;
- int result;
- };
-
- base::queue<ExpectedWrite> expected_writes_;
-
- size_t info_written_;
- size_t data_written_;
-
- OnceCompletionCallback pending_callback_;
-
- DISALLOW_COPY_AND_ASSIGN(MockServiceWorkerResponseWriter);
-};
-
-void MockServiceWorkerResponseWriter::WriteInfo(
- HttpResponseInfoIOBuffer* info_buf,
- OnceCompletionCallback callback) {
- DCHECK(!expected_writes_.empty());
- ExpectedWrite write = expected_writes_.front();
- EXPECT_TRUE(write.is_info);
- if (write.result > 0) {
- EXPECT_EQ(write.length, static_cast<size_t>(info_buf->response_data_size));
- info_written_ += info_buf->response_data_size;
- }
- if (!write.async) {
- expected_writes_.pop();
- std::move(callback).Run(write.result);
- } else {
- pending_callback_ = std::move(callback);
- }
-}
-
-void MockServiceWorkerResponseWriter::WriteData(
- net::IOBuffer* buf,
- int buf_len,
- OnceCompletionCallback callback) {
- DCHECK(!expected_writes_.empty());
- ExpectedWrite write = expected_writes_.front();
- EXPECT_FALSE(write.is_info);
- if (write.result > 0) {
- EXPECT_EQ(write.length, static_cast<size_t>(buf_len));
- data_written_ += buf_len;
- }
- if (!write.async) {
- expected_writes_.pop();
- std::move(callback).Run(write.result);
- } else {
- pending_callback_ = std::move(callback);
- }
-}
-
-void MockServiceWorkerResponseWriter::ExpectWriteInfoOk(size_t length,
- bool async) {
- ExpectWriteInfo(length, async, length);
-}
-
-void MockServiceWorkerResponseWriter::ExpectWriteDataOk(size_t length,
- bool async) {
- ExpectWriteData(length, async, length);
-}
-
-void MockServiceWorkerResponseWriter::ExpectWriteInfo(size_t length,
- bool async,
- int result) {
- DCHECK_NE(net::ERR_IO_PENDING, result);
- ExpectedWrite expected(true, length, async, result);
- expected_writes_.push(expected);
-}
-
-void MockServiceWorkerResponseWriter::ExpectWriteData(size_t length,
- bool async,
- int result) {
- DCHECK_NE(net::ERR_IO_PENDING, result);
- ExpectedWrite expected(false, length, async, result);
- expected_writes_.push(expected);
-}
-
-void MockServiceWorkerResponseWriter::CompletePendingWrite() {
- DCHECK(!expected_writes_.empty());
- ExpectedWrite write = expected_writes_.front();
- DCHECK(write.async);
- expected_writes_.pop();
- std::move(pending_callback_).Run(write.result);
-}
-
class ServiceWorkerCacheWriterTest : public ::testing::Test {
public:
ServiceWorkerCacheWriterTest() {}
@@ -341,12 +41,13 @@ class ServiceWorkerCacheWriterTest : public ::testing::Test {
}
// This should be called after ExpectReader() and ExpectWriter().
- void Initialize() {
+ void Initialize(bool pause_when_not_identical) {
std::unique_ptr<ServiceWorkerResponseReader> compare_reader(CreateReader());
std::unique_ptr<ServiceWorkerResponseReader> copy_reader(CreateReader());
std::unique_ptr<ServiceWorkerResponseWriter> writer(CreateWriter());
cache_writer_.reset(new ServiceWorkerCacheWriter(
- std::move(compare_reader), std::move(copy_reader), std::move(writer)));
+ std::move(compare_reader), std::move(copy_reader), std::move(writer),
+ pause_when_not_identical));
}
protected:
@@ -391,7 +92,8 @@ class ServiceWorkerCacheWriterTest : public ::testing::Test {
}
net::Error WriteData(const std::string& data) {
- scoped_refptr<net::IOBuffer> buf = new net::StringIOBuffer(data);
+ scoped_refptr<net::IOBuffer> buf =
+ base::MakeRefCounted<net::StringIOBuffer>(data);
return cache_writer_->MaybeWriteData(buf.get(), data.size(),
CreateWriteCallback());
}
@@ -410,7 +112,7 @@ TEST_F(ServiceWorkerCacheWriterTest, PassthroughHeadersSync) {
const size_t kHeaderSize = 16;
MockServiceWorkerResponseWriter* writer = ExpectWriter();
writer->ExpectWriteInfoOk(kHeaderSize, false);
- Initialize();
+ Initialize(false /* pause_when_not_identical */);
net::Error error = WriteHeaders(kHeaderSize);
EXPECT_EQ(net::OK, error);
@@ -423,7 +125,7 @@ TEST_F(ServiceWorkerCacheWriterTest, PassthroughHeadersAsync) {
size_t kHeaderSize = 16;
MockServiceWorkerResponseWriter* writer = ExpectWriter();
writer->ExpectWriteInfoOk(kHeaderSize, true);
- Initialize();
+ Initialize(false /* pause_when_not_identical */);
net::Error error = WriteHeaders(kHeaderSize);
EXPECT_EQ(net::ERR_IO_PENDING, error);
@@ -444,7 +146,7 @@ TEST_F(ServiceWorkerCacheWriterTest, PassthroughDataSync) {
writer->ExpectWriteInfoOk(response_size, false);
writer->ExpectWriteDataOk(data1.size(), false);
writer->ExpectWriteDataOk(data2.size(), false);
- Initialize();
+ Initialize(false /* pause_when_not_identical */);
net::Error error = WriteHeaders(response_size);
EXPECT_EQ(net::OK, error);
@@ -466,7 +168,7 @@ TEST_F(ServiceWorkerCacheWriterTest, PassthroughDataAsync) {
writer->ExpectWriteInfoOk(response_size, false);
writer->ExpectWriteDataOk(data1.size(), true);
writer->ExpectWriteDataOk(data2.size(), true);
- Initialize();
+ Initialize(false /* pause_when_not_identical */);
net::Error error = WriteHeaders(response_size);
EXPECT_EQ(net::OK, error);
@@ -489,7 +191,7 @@ TEST_F(ServiceWorkerCacheWriterTest, PassthroughHeadersFailSync) {
const size_t kHeaderSize = 16;
MockServiceWorkerResponseWriter* writer = ExpectWriter();
writer->ExpectWriteInfo(kHeaderSize, false, net::ERR_FAILED);
- Initialize();
+ Initialize(false /* pause_when_not_identical */);
net::Error error = WriteHeaders(kHeaderSize);
EXPECT_EQ(net::ERR_FAILED, error);
@@ -502,7 +204,7 @@ TEST_F(ServiceWorkerCacheWriterTest, PassthroughHeadersFailAsync) {
size_t kHeaderSize = 16;
MockServiceWorkerResponseWriter* writer = ExpectWriter();
writer->ExpectWriteInfo(kHeaderSize, true, net::ERR_FAILED);
- Initialize();
+ Initialize(false /* pause_when_not_identical */);
net::Error error = WriteHeaders(kHeaderSize);
EXPECT_EQ(net::ERR_IO_PENDING, error);
@@ -520,7 +222,7 @@ TEST_F(ServiceWorkerCacheWriterTest, PassthroughDataFailSync) {
MockServiceWorkerResponseWriter* writer = ExpectWriter();
writer->ExpectWriteInfoOk(data.size(), false);
writer->ExpectWriteData(data.size(), false, net::ERR_FAILED);
- Initialize();
+ Initialize(false /* pause_when_not_identical */);
EXPECT_EQ(net::OK, WriteHeaders(data.size()));
EXPECT_EQ(net::ERR_FAILED, WriteData(data));
@@ -533,7 +235,7 @@ TEST_F(ServiceWorkerCacheWriterTest, PassthroughDataFailAsync) {
MockServiceWorkerResponseWriter* writer = ExpectWriter();
writer->ExpectWriteInfoOk(data.size(), false);
writer->ExpectWriteData(data.size(), true, net::ERR_FAILED);
- Initialize();
+ Initialize(false /* pause_when_not_identical */);
EXPECT_EQ(net::OK, WriteHeaders(data.size()));
@@ -555,7 +257,7 @@ TEST_F(ServiceWorkerCacheWriterTest, CompareHeadersSync) {
MockServiceWorkerResponseReader* reader = ExpectReader();
reader->ExpectReadInfoOk(response_size, false);
- Initialize();
+ Initialize(false /* pause_when_not_identical */);
net::Error error = WriteHeaders(response_size);
EXPECT_EQ(net::OK, error);
@@ -572,7 +274,7 @@ TEST_F(ServiceWorkerCacheWriterTest, CompareDataOkSync) {
reader->ExpectReadInfoOk(response_size, false);
reader->ExpectReadDataOk(data1, false);
- Initialize();
+ Initialize(false /* pause_when_not_identical */);
net::Error error = WriteHeaders(response_size);
EXPECT_EQ(net::OK, error);
@@ -591,7 +293,7 @@ TEST_F(ServiceWorkerCacheWriterTest, CompareHeadersFailSync) {
MockServiceWorkerResponseReader* reader = ExpectReader();
reader->ExpectReadInfo(response_size, false, net::ERR_FAILED);
- Initialize();
+ Initialize(false /* pause_when_not_identical */);
EXPECT_EQ(net::ERR_FAILED, WriteHeaders(response_size));
EXPECT_TRUE(writer->AllExpectedWritesDone());
@@ -607,7 +309,7 @@ TEST_F(ServiceWorkerCacheWriterTest, CompareDataFailSync) {
reader->ExpectReadInfoOk(response_size, false);
reader->ExpectReadData(data1.c_str(), data1.length(), false, net::ERR_FAILED);
- Initialize();
+ Initialize(false /* pause_when_not_identical */);
net::Error error = WriteHeaders(response_size);
EXPECT_EQ(net::OK, error);
@@ -635,7 +337,7 @@ TEST_F(ServiceWorkerCacheWriterTest, CompareShortCacheReads) {
reader->ExpectReadDataOk(cache_data3, false);
reader->ExpectReadDataOk(cache_data4, false);
reader->ExpectReadDataOk(data5, false);
- Initialize();
+ Initialize(false /* pause_when_not_identical */);
net::Error error = WriteHeaders(kHeaderSize);
EXPECT_EQ(net::OK, error);
@@ -657,7 +359,7 @@ TEST_F(ServiceWorkerCacheWriterTest, CompareDataOkAsync) {
reader->ExpectReadInfoOk(response_size, true);
reader->ExpectReadDataOk(data1, true);
- Initialize();
+ Initialize(false /* pause_when_not_identical */);
net::Error error = WriteHeaders(response_size);
EXPECT_EQ(net::ERR_IO_PENDING, error);
@@ -685,7 +387,7 @@ TEST_F(ServiceWorkerCacheWriterTest, CompareDataManyOkAsync) {
for (size_t i = 0; i < arraysize(expected_data); ++i) {
reader->ExpectReadDataOk(expected_data[i], true);
}
- Initialize();
+ Initialize(false /* pause_when_not_identical */);
net::Error error = WriteHeaders(response_size);
EXPECT_EQ(net::ERR_IO_PENDING, error);
@@ -730,7 +432,7 @@ TEST_F(ServiceWorkerCacheWriterTest, CompareFailedCopySync) {
writer->ExpectWriteDataOk(net_data2.size(), false);
writer->ExpectWriteDataOk(data3.size(), false);
- Initialize();
+ Initialize(false /* pause_when_not_identical */);
net::Error error = WriteHeaders(net_response_size);
EXPECT_EQ(net::OK, error);
@@ -772,7 +474,7 @@ TEST_F(ServiceWorkerCacheWriterTest, CompareFailedCopyShort) {
writer->ExpectWriteDataOk(net_data2.size(), false);
writer->ExpectWriteDataOk(data3.size(), false);
- Initialize();
+ Initialize(false /* pause_when_not_identical */);
net::Error error = WriteHeaders(net_response_size);
EXPECT_EQ(net::OK, error);
@@ -816,7 +518,7 @@ TEST_F(ServiceWorkerCacheWriterTest, CompareFailedCopyLong) {
writer->ExpectWriteDataOk(data1.size(), false);
writer->ExpectWriteDataOk(net_data2.size(), false);
- Initialize();
+ Initialize(false /* pause_when_not_identical */);
net::Error error = WriteHeaders(net_size);
EXPECT_EQ(net::OK, error);
@@ -879,7 +581,7 @@ TEST_F(ServiceWorkerCacheWriterTest, MultipleComparisonInSingleWrite) {
for (const auto& data : data_expected)
writer->ExpectWriteDataOk(data.size(), false);
- Initialize();
+ Initialize(false /* pause_when_not_identical */);
net::Error error = WriteHeaders(bytes_from_net);
EXPECT_EQ(net::OK, error);
@@ -893,5 +595,175 @@ TEST_F(ServiceWorkerCacheWriterTest, MultipleComparisonInSingleWrite) {
EXPECT_TRUE(copy_reader->AllExpectedReadsDone());
}
+// Tests behavior when |pause_when_not_identical| is enabled and cache writer
+// finishes synchronously.
+TEST_F(ServiceWorkerCacheWriterTest, PauseWhenNotIdentical_SyncWriteData) {
+ // Data from |compare_reader|.
+ const std::vector<std::string> data_from_cache{"abcd"};
+
+ // Data for |writer|. The comparison should stop at the first block of the
+ // data.
+ const std::vector<std::string> data_from_net{"abxx"};
+
+ // We don't need |data_to_copy| because the network data and the cached data
+ // have no common blocks.
+
+ // The written data should be the same as |data_from_net|.
+ const std::vector<std::string> data_expected{"abxx"};
+
+ size_t bytes_cached = 0;
+ size_t bytes_from_net = 0;
+ size_t bytes_expected = 0;
+
+ for (const auto& data : data_from_cache)
+ bytes_cached += data.size();
+
+ for (const auto& data : data_from_net)
+ bytes_from_net += data.size();
+
+ for (const auto& data : data_expected)
+ bytes_expected += data.size();
+
+ MockServiceWorkerResponseWriter* writer = ExpectWriter();
+ MockServiceWorkerResponseReader* compare_reader = ExpectReader();
+ MockServiceWorkerResponseReader* copy_reader = ExpectReader();
+
+ compare_reader->ExpectReadInfoOk(bytes_cached, false);
+ for (const auto& data : data_from_cache)
+ compare_reader->ExpectReadDataOk(data, false);
+
+ copy_reader->ExpectReadInfoOk(bytes_cached, false);
+
+ writer->ExpectWriteInfoOk(bytes_expected, false);
+ for (const auto& data : data_expected)
+ writer->ExpectWriteDataOk(data.size(), false);
+
+ Initialize(true /* pause_when_not_identical */);
+
+ net::Error error = WriteHeaders(bytes_from_net);
+ EXPECT_EQ(net::OK, error);
+
+ // |cache_writer_| stops the comparison at the first block of the data.
+ // It should return net::ERR_IO_PENDING and |write_complete_| should remain
+ // false since |pause_when_not_identical| forbids proceeding to the next step.
+ write_complete_ = false;
+ error = WriteData(data_from_net[0]);
+ EXPECT_EQ(net::ERR_IO_PENDING, error);
+ EXPECT_FALSE(write_complete_);
+ EXPECT_EQ(0U, cache_writer_->bytes_written());
+
+ // Resume |cache_writer_| with a callback. The passed callback shouldn't be
+ // called because this is a synchronous write. This time, the result should be
+ // net::OK and the expected data should be written to the storage.
+ error =
+ cache_writer_->Resume(base::BindOnce([](net::Error) { NOTREACHED(); }));
+ EXPECT_EQ(net::OK, error);
+ EXPECT_EQ(bytes_expected, cache_writer_->bytes_written());
+
+ EXPECT_TRUE(writer->AllExpectedWritesDone());
+ EXPECT_TRUE(compare_reader->AllExpectedReadsDone());
+ EXPECT_TRUE(copy_reader->AllExpectedReadsDone());
+}
+
+// Tests behavior when |pause_when_not_identical| is enabled and cache writer
+// finishes asynchronously.
+TEST_F(ServiceWorkerCacheWriterTest, PauseWhenNotIdentical_AsyncWriteData) {
+ // Data from |compare_reader|.
+ const std::vector<std::string> data_from_cache{"abcd"};
+
+ // Data for |writer|. The comparison should stop at the first block of the
+ // data.
+ const std::vector<std::string> data_from_net{"abxx"};
+
+ // We don't need |data_to_copy| because the network data and the cached data
+ // have no common blocks.
+
+ // The written data should be the same as |data_from_net|.
+ const std::vector<std::string> data_expected{"abxx"};
+
+ size_t bytes_cached = 0;
+ size_t bytes_from_net = 0;
+ size_t bytes_expected = 0;
+
+ for (const auto& data : data_from_cache)
+ bytes_cached += data.size();
+
+ for (const auto& data : data_from_net)
+ bytes_from_net += data.size();
+
+ for (const auto& data : data_expected)
+ bytes_expected += data.size();
+
+ MockServiceWorkerResponseWriter* writer = ExpectWriter();
+ MockServiceWorkerResponseReader* compare_reader = ExpectReader();
+ MockServiceWorkerResponseReader* copy_reader = ExpectReader();
+
+ compare_reader->ExpectReadInfoOk(bytes_cached, true);
+ for (const auto& data : data_from_cache)
+ compare_reader->ExpectReadDataOk(data, true);
+
+ copy_reader->ExpectReadInfoOk(bytes_cached, true);
+
+ writer->ExpectWriteInfoOk(bytes_expected, true);
+ for (const auto& data : data_expected)
+ writer->ExpectWriteDataOk(data.size(), true);
+
+ Initialize(true /* pause_when_not_identical */);
+
+ write_complete_ = false;
+ net::Error error = WriteHeaders(bytes_from_net);
+ EXPECT_EQ(net::ERR_IO_PENDING, error);
+ EXPECT_FALSE(write_complete_);
+ compare_reader->CompletePendingRead();
+ EXPECT_TRUE(write_complete_);
+
+ // The comparison is suspended due to an asynchronous read of
+ // |compare_reader|, resulting in an early return. At this point, the callback
+ // shouldn't be called yet.
+ write_complete_ = false;
+ error = WriteData(data_from_net[0]);
+ EXPECT_EQ(net::ERR_IO_PENDING, error);
+ EXPECT_FALSE(write_complete_);
+
+ // When |compare_reader| succeeds in reading the stored data, |cache_writer_|
+ // then proceeds to the comparison phase.
+ // |cache_writer_| stops comparison at the first block of the data.
+ // Since |pause_when_not_identical| is enabled, it should subsequently trigger
+ // the callback and return net::ERR_IO_PENDING.
+ compare_reader->CompletePendingRead();
+ EXPECT_TRUE(write_complete_);
+ EXPECT_EQ(net::ERR_IO_PENDING, last_error_);
+ EXPECT_EQ(0U, cache_writer_->bytes_written());
+
+ // Resume |cache_writer_| with a callback which updates |write_complete_| and
+ // |last_error_| when it's called.
+ // |copy_reader| does an asynchronous read here.
+ write_complete_ = false;
+ error = cache_writer_->Resume(CreateWriteCallback());
+ EXPECT_EQ(net::ERR_IO_PENDING, error);
+ EXPECT_FALSE(write_complete_);
+
+ // Complete the asynchronous read of the header. Since there's nothing to copy
+ // from the storage, |copy_reader| should finish all its jobs here.
+ copy_reader->CompletePendingRead();
+ EXPECT_TRUE(copy_reader->AllExpectedReadsDone());
+
+ // Complete the asynchronous write of the header. This doesn't finish all the
+ // write to the storage, so the callback isn't called yet.
+ writer->CompletePendingWrite();
+ EXPECT_FALSE(write_complete_);
+ EXPECT_EQ(net::ERR_IO_PENDING, last_error_);
+
+ // Complete the asynchronous write of the body. This completes all the work of
+ // |cache_writer|, so the callback is triggered.
+ writer->CompletePendingWrite();
+ EXPECT_TRUE(write_complete_);
+ EXPECT_EQ(net::OK, last_error_);
+ EXPECT_EQ(bytes_expected, cache_writer_->bytes_written());
+
+ EXPECT_TRUE(writer->AllExpectedWritesDone());
+ EXPECT_TRUE(compare_reader->AllExpectedReadsDone());
+}
+
} // namespace
} // namespace content
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 c2252ec96fa..c83bf9eafb9 100644
--- a/chromium/content/browser/service_worker/service_worker_client_utils.cc
+++ b/chromium/content/browser/service_worker/service_worker_client_utils.cc
@@ -10,6 +10,7 @@
#include "base/location.h"
#include "base/macros.h"
#include "base/single_thread_task_runner.h"
+#include "base/task/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/frame_host/frame_tree_node.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
@@ -20,6 +21,7 @@
#include "content/browser/storage_partition_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/service_worker/service_worker_types.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/navigation_handle.h"
@@ -93,9 +95,10 @@ class OpenURLObserver : public WebContentsObserver {
DCHECK(web_contents());
DCHECK(callback_);
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::BindOnce(std::move(callback_),
- render_process_id, render_frame_id));
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(std::move(callback_), render_process_id,
+ render_frame_id));
Observe(nullptr);
base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this);
}
@@ -167,8 +170,8 @@ void DidOpenURLOnUI(WindowType type,
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (!web_contents) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(std::move(callback), ChildProcessHost::kInvalidUniqueID,
MSG_ROUTING_NONE));
return;
@@ -214,8 +217,8 @@ void OpenWindowOnUI(
RenderProcessHost* render_process_host =
RenderProcessHost::FromID(worker_process_id);
if (render_process_host->IsForGuestsOnly()) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(std::move(callback), ChildProcessHost::kInvalidUniqueID,
MSG_ROUTING_NONE));
return;
@@ -248,8 +251,8 @@ void NavigateClientOnUI(const GURL& url,
WebContents* web_contents = WebContents::FromRenderFrameHost(rfhi);
if (!rfhi || !web_contents) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(std::move(callback), ChildProcessHost::kInvalidUniqueID,
MSG_ROUTING_NONE));
return;
@@ -333,8 +336,8 @@ void OnGetWindowClientsOnUI(
out_clients->push_back(std::move(info));
}
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(std::move(callback), std::move(out_clients)));
}
@@ -432,8 +435,8 @@ void GetWindowClients(const base::WeakPtr<ServiceWorkerVersion>& controller,
return;
}
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&OnGetWindowClientsOnUI, clients_info,
controller->script_url(),
base::BindOnce(&DidGetWindowClients, controller,
@@ -448,8 +451,8 @@ void FocusWindowClient(ServiceWorkerProviderHost* provider_host,
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK_EQ(blink::mojom::ServiceWorkerClientType::kWindow,
provider_host->client_type());
- BrowserThread::PostTaskAndReplyWithResult(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraitsAndReplyWithResult(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&FocusOnUI, provider_host->process_id(),
provider_host->frame_id(), provider_host->create_time(),
provider_host->client_uuid()),
@@ -463,8 +466,8 @@ void OpenWindow(const GURL& url,
WindowType type,
NavigationCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(
&OpenWindowOnUI, url, script_url, worker_process_id,
base::WrapRefCounted(context->wrapper()), type,
@@ -479,8 +482,8 @@ void NavigateClient(const GURL& url,
const base::WeakPtr<ServiceWorkerContextCore>& context,
NavigationCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(
&NavigateClientOnUI, url, script_url, process_id, frame_id,
base::BindOnce(&DidNavigate, context, script_url.GetOrigin(),
@@ -498,8 +501,8 @@ void GetClient(const ServiceWorkerProviderHost* provider_host,
<< client_type;
if (client_type == blink::mojom::ServiceWorkerClientType::kWindow) {
- BrowserThread::PostTaskAndReplyWithResult(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraitsAndReplyWithResult(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&GetWindowClientInfoOnUI, provider_host->process_id(),
provider_host->route_id(), provider_host->create_time(),
provider_host->client_uuid()),
@@ -513,8 +516,8 @@ void GetClient(const ServiceWorkerProviderHost* provider_host,
false, // is_focused
network::mojom::RequestContextFrameType::kNone, base::TimeTicks(),
provider_host->create_time());
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(std::move(callback), std::move(client_info)));
}
@@ -570,8 +573,8 @@ void DidNavigate(const base::WeakPtr<ServiceWorkerContextCore>& context,
provider_host->frame_id() != render_frame_id) {
continue;
}
- BrowserThread::PostTaskAndReplyWithResult(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraitsAndReplyWithResult(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&GetWindowClientInfoOnUI, provider_host->process_id(),
provider_host->route_id(), provider_host->create_time(),
provider_host->client_uuid()),
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 3ba2c39cc15..f7baefc57cc 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
@@ -36,7 +36,7 @@ void ServiceWorkerContentSettingsProxyImpl::AllowIndexedDB(
std::move(callback).Run(false);
return;
}
- if (origin_.unique()) {
+ if (origin_.opaque()) {
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 df3b6835062..e7e9dfa000b 100644
--- a/chromium/content/browser/service_worker/service_worker_context_core.cc
+++ b/chromium/content/browser/service_worker/service_worker_context_core.cc
@@ -17,6 +17,7 @@
#include "base/memory/ptr_util.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string_util.h"
+#include "base/task/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/service_worker/embedded_worker_registry.h"
@@ -34,6 +35,7 @@
#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 "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/child_process_host.h"
#include "ipc/ipc_message.h"
@@ -162,7 +164,8 @@ class ClearAllServiceWorkersHelper
friend class base::RefCounted<ClearAllServiceWorkersHelper>;
~ClearAllServiceWorkersHelper() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, std::move(callback_));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ std::move(callback_));
}
base::OnceClosure callback_;
@@ -412,8 +415,8 @@ void ServiceWorkerContextCore::HasMainFrameProviderHost(
provider_host_iterator.Advance();
}
- BrowserThread::PostTaskAndReplyWithResult(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraitsAndReplyWithResult(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&FrameListContainsMainFrameOnUI, std::move(render_frames)),
std::move(callback));
}
@@ -604,7 +607,7 @@ bool ServiceWorkerContextCore::IsValidRegisterRequest(
ServiceWorkerRegistration* ServiceWorkerContextCore::GetLiveRegistration(
int64_t id) {
- RegistrationsMap::iterator it = live_registrations_.find(id);
+ auto it = live_registrations_.find(id);
return (it != live_registrations_.end()) ? it->second : nullptr;
}
@@ -622,7 +625,7 @@ void ServiceWorkerContextCore::RemoveLiveRegistration(int64_t id) {
}
ServiceWorkerVersion* ServiceWorkerContextCore::GetLiveVersion(int64_t id) {
- VersionMap::iterator it = live_versions_.find(id);
+ auto it = live_versions_.find(id);
return (it != live_versions_.end()) ? it->second : nullptr;
}
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 1570948c6ef..32af334ed62 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
@@ -101,17 +101,6 @@ net::URLRequestJob* ServiceWorkerContextRequestHandler::MaybeCreateJob(
// falling back to network. Otherwise the renderer may receive the response
// from network and start a service worker whose browser-side
// ServiceWorkerVersion is not properly initialized.
- //
- // As an exception, allow installed service workers to use importScripts()
- // to import non-installed scripts.
- // TODO(falken): This is a spec violation that should be deprecated and
- // removed. See https://github.com/w3c/ServiceWorker/issues/1021
- if (status == CreateJobStatus::ERROR_UNINSTALLED_SCRIPT_IMPORT) {
- // Fall back to network.
- ServiceWorkerMetrics::RecordUninstalledScriptImport(version_->script_url());
- return nullptr;
- }
-
std::string error_str(CreateJobStatusToString(status));
request->net_log().AddEvent(
net::NetLogEventType::SERVICE_WORKER_SCRIPT_LOAD_UNHANDLED_REQUEST_ERROR,
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 692d21dc1f8..086d9925e68 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
@@ -79,9 +79,9 @@ class ServiceWorkerContextRequestHandlerTest : public testing::Test {
options.scope = scope_;
registration_ = base::MakeRefCounted<ServiceWorkerRegistration>(
options, 1L, context()->AsWeakPtr());
- version_ = new ServiceWorkerVersion(registration_.get(), script_url_,
- context()->storage()->NewVersionId(),
- context()->AsWeakPtr());
+ version_ = new ServiceWorkerVersion(
+ registration_.get(), script_url_, blink::mojom::ScriptType::kClassic,
+ context()->storage()->NewVersionId(), context()->AsWeakPtr());
SetUpProvider();
std::unique_ptr<MockHttpProtocolHandler> handler(
@@ -131,7 +131,8 @@ class ServiceWorkerContextRequestHandlerTest : public testing::Test {
network::mojom::FetchCredentialsMode::kOmit,
network::mojom::FetchRedirectMode::kFollow,
std::string() /* integrity */, false /* keepalive */,
- RESOURCE_TYPE_SERVICE_WORKER, REQUEST_CONTEXT_TYPE_SERVICE_WORKER,
+ RESOURCE_TYPE_SERVICE_WORKER,
+ blink::mojom::RequestContextType::SERVICE_WORKER,
network::mojom::RequestContextFrameType::kNone, nullptr);
}
@@ -308,7 +309,7 @@ TEST_F(ServiceWorkerContextRequestHandlerTest,
network::mojom::FetchCredentialsMode::kOmit,
network::mojom::FetchRedirectMode::kFollow, std::string() /* integrity */,
false /* keepalive */, RESOURCE_TYPE_SERVICE_WORKER,
- REQUEST_CONTEXT_TYPE_SERVICE_WORKER,
+ blink::mojom::RequestContextType::SERVICE_WORKER,
network::mojom::RequestContextFrameType::kNone, nullptr);
// Verify a ServiceWorkerRequestHandler was created.
ServiceWorkerRequestHandler* handler =
@@ -398,8 +399,8 @@ TEST_F(ServiceWorkerContextRequestHandlerTest, InstalledWorker) {
TEST_F(ServiceWorkerContextRequestHandlerTest, Incumbent) {
// Make an incumbent version.
scoped_refptr<ServiceWorkerVersion> incumbent = new ServiceWorkerVersion(
- registration_.get(), script_url_, context()->storage()->NewVersionId(),
- context()->AsWeakPtr());
+ registration_.get(), script_url_, blink::mojom::ScriptType::kClassic,
+ context()->storage()->NewVersionId(), context()->AsWeakPtr());
incumbent->set_fetch_handler_existence(
ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
std::vector<ServiceWorkerDatabase::ResourceRecord> resources = {
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 7ca85191c7b..acf4e1d44a2 100644
--- a/chromium/content/browser/service_worker/service_worker_context_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_context_unittest.cc
@@ -93,7 +93,8 @@ class RejectInstallTestHelper : public EmbeddedWorkerTestHelper {
mojom::ServiceWorker::DispatchInstallEventCallback callback) override {
dispatched_events()->push_back(Event::Install);
std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::REJECTED,
- true /* has_fetch_handler */, base::Time::Now());
+ true /* has_fetch_handler */,
+ base::TimeTicks::Now());
}
};
@@ -105,7 +106,7 @@ class RejectActivateTestHelper : public EmbeddedWorkerTestHelper {
mojom::ServiceWorker::DispatchActivateEventCallback callback) override {
dispatched_events()->push_back(Event::Activate);
std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::REJECTED,
- base::Time::Now());
+ base::TimeTicks::Now());
}
};
@@ -307,8 +308,8 @@ TEST_F(ServiceWorkerContextTest, NoControlleesObserver) {
options, 1l /* dummy registration id */, context()->AsWeakPtr());
auto version = base::MakeRefCounted<ServiceWorkerVersion>(
- registration.get(), script_url, 2l /* dummy version id */,
- context()->AsWeakPtr());
+ registration.get(), script_url, blink::mojom::ScriptType::kClassic,
+ 2l /* dummy version id */, context()->AsWeakPtr());
ServiceWorkerRemoteProviderEndpoint endpoint;
std::unique_ptr<ServiceWorkerProviderHost> host =
@@ -341,8 +342,8 @@ TEST_F(ServiceWorkerContextTest, VersionActivatedObserver) {
options, 1l /* dummy registration id */, context()->AsWeakPtr());
auto version = base::MakeRefCounted<ServiceWorkerVersion>(
- registration.get(), script_url, 2l /* dummy version id */,
- context()->AsWeakPtr());
+ registration.get(), script_url, blink::mojom::ScriptType::kClassic,
+ 2l /* dummy version id */, context()->AsWeakPtr());
TestServiceWorkerContextObserver observer(context_wrapper());
@@ -368,8 +369,8 @@ TEST_F(ServiceWorkerContextTest, VersionRedundantObserver) {
options, 1l /* dummy registration id */, context()->AsWeakPtr());
auto version = base::MakeRefCounted<ServiceWorkerVersion>(
- registration.get(), script_url, 2l /* dummy version id */,
- context()->AsWeakPtr());
+ registration.get(), script_url, blink::mojom::ScriptType::kClassic,
+ 2l /* dummy version id */, context()->AsWeakPtr());
TestServiceWorkerContextObserver observer(context_wrapper());
@@ -850,7 +851,8 @@ TEST_F(ServiceWorkerContextTest, ProviderHostIterator) {
base::MakeRefCounted<ServiceWorkerVersion>(
registration.get(),
GURL("https://another-origin.example.net/test/script_url"),
- 1L /* version_id */, helper_->context()->AsWeakPtr());
+ blink::mojom::ScriptType::kClassic, 1L /* version_id */,
+ helper_->context()->AsWeakPtr());
remote_endpoints.emplace_back();
base::WeakPtr<ServiceWorkerProviderHost> host4 =
CreateProviderHostForServiceWorkerContext(
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 93255031e6d..594ed900fba 100644
--- a/chromium/content/browser/service_worker/service_worker_context_watcher.cc
+++ b/chromium/content/browser/service_worker/service_worker_context_watcher.cc
@@ -7,9 +7,11 @@
#include <utility>
#include "base/bind.h"
+#include "base/task/post_task.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_version.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/console_message_level.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom.h"
@@ -40,8 +42,8 @@ ServiceWorkerContextWatcher::ServiceWorkerContextWatcher(
void ServiceWorkerContextWatcher::Start() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&ServiceWorkerContextWatcher::GetStoredRegistrationsOnIOThread,
this));
@@ -50,8 +52,8 @@ void ServiceWorkerContextWatcher::Start() {
void ServiceWorkerContextWatcher::Stop() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
stop_called_ = true;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&ServiceWorkerContextWatcher::StopOnIOThread, this));
}
@@ -99,13 +101,13 @@ void ServiceWorkerContextWatcher::OnStoredRegistrationsOnIOThread(
++version_it;
}
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(
&ServiceWorkerContextWatcher::RunWorkerRegistrationUpdatedCallback,
this, std::move(registrations)));
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(
&ServiceWorkerContextWatcher::RunWorkerVersionUpdatedCallback, this,
std::move(versions)));
@@ -159,8 +161,8 @@ void ServiceWorkerContextWatcher::SendRegistrationInfo(
registrations->push_back(
ServiceWorkerRegistrationInfo(pattern, registration_id, delete_flag));
}
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(
&ServiceWorkerContextWatcher::RunWorkerRegistrationUpdatedCallback,
this, std::move(registrations)));
@@ -172,8 +174,8 @@ void ServiceWorkerContextWatcher::SendVersionInfo(
std::unique_ptr<std::vector<ServiceWorkerVersionInfo>> versions =
std::make_unique<std::vector<ServiceWorkerVersionInfo>>();
versions->push_back(version_info);
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(
&ServiceWorkerContextWatcher::RunWorkerVersionUpdatedCallback, this,
std::move(versions)));
@@ -304,8 +306,8 @@ void ServiceWorkerContextWatcher::OnErrorReported(int64_t version_id,
auto it = version_info_map_.find(version_id);
if (it != version_info_map_.end())
registration_id = it->second->registration_id;
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(
&ServiceWorkerContextWatcher::RunWorkerErrorReportedCallback, this,
registration_id, version_id, std::make_unique<ErrorInfo>(info)));
@@ -322,8 +324,8 @@ void ServiceWorkerContextWatcher::OnReportConsoleMessage(
if (it != version_info_map_.end())
registration_id = it->second->registration_id;
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(
&ServiceWorkerContextWatcher::RunWorkerErrorReportedCallback, this,
registration_id, version_id,
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 4203d20bd22..c0b46e12826 100644
--- a/chromium/content/browser/service_worker/service_worker_context_wrapper.cc
+++ b/chromium/content/browser/service_worker/service_worker_context_wrapper.cc
@@ -28,6 +28,7 @@
#include "content/browser/storage_partition_impl.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/service_worker_context_observer.h"
#include "content/public/common/content_features.h"
@@ -49,8 +50,8 @@ const int kActiveWorkerTimeoutDays = 999;
void WorkerStarted(ServiceWorkerContextWrapper::StatusCallback callback,
blink::ServiceWorkerStatusCode status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(std::move(callback), status));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(std::move(callback), status));
}
void StartActiveWorkerOnIO(
@@ -67,8 +68,8 @@ void StartActiveWorkerOnIO(
base::BindOnce(WorkerStarted, std::move(callback)));
return;
}
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(std::move(callback),
blink::ServiceWorkerStatusCode::kErrorNotFound));
}
@@ -143,8 +144,8 @@ void FinishRegistrationOnIO(ServiceWorkerContext::ResultCallback callback,
const std::string& status_message,
int64_t registration_id) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(std::move(callback),
status == blink::ServiceWorkerStatusCode::kOk));
}
@@ -152,8 +153,8 @@ void FinishRegistrationOnIO(ServiceWorkerContext::ResultCallback callback,
void FinishUnregistrationOnIO(ServiceWorkerContext::ResultCallback callback,
blink::ServiceWorkerStatusCode status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(std::move(callback),
status == blink::ServiceWorkerStatusCode::kOk));
}
@@ -229,8 +230,8 @@ void ServiceWorkerContextWrapper::Shutdown() {
storage_partition_ = nullptr;
process_manager_->Shutdown();
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&ServiceWorkerContextWrapper::ShutdownOnIO, this));
}
@@ -310,19 +311,20 @@ void ServiceWorkerContextWrapper::RegisterServiceWorker(
const blink::mojom::ServiceWorkerRegistrationOptions& options,
ResultCallback callback) {
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&ServiceWorkerContextWrapper::RegisterServiceWorker,
this, script_url, options, std::move(callback)));
return;
}
if (!context_core_) {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(std::move(callback), false));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(std::move(callback), false));
return;
}
blink::mojom::ServiceWorkerRegistrationOptions options_to_pass(
- net::SimplifyUrlForRequest(options.scope), options.update_via_cache);
+ net::SimplifyUrlForRequest(options.scope), options.type,
+ options.update_via_cache);
context()->RegisterServiceWorker(
net::SimplifyUrlForRequest(script_url), options_to_pass,
base::BindOnce(&FinishRegistrationOnIO, std::move(callback)));
@@ -332,15 +334,15 @@ void ServiceWorkerContextWrapper::UnregisterServiceWorker(
const GURL& pattern,
ResultCallback callback) {
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&ServiceWorkerContextWrapper::UnregisterServiceWorker,
this, pattern, std::move(callback)));
return;
}
if (!context_core_) {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(std::move(callback), false));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(std::move(callback), false));
return;
}
@@ -375,8 +377,8 @@ void ServiceWorkerContextWrapper::CountExternalRequestsForTest(
const GURL& origin,
CountExternalRequestsCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&ServiceWorkerContextWrapper::CountExternalRequests, this,
origin, std::move(callback)));
}
@@ -385,8 +387,8 @@ void ServiceWorkerContextWrapper::GetAllOriginsInfo(
GetUsageInfoCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (!context_core_) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(std::move(callback),
std::vector<ServiceWorkerUsageInfo>()));
return;
@@ -399,15 +401,15 @@ void ServiceWorkerContextWrapper::GetAllOriginsInfo(
void ServiceWorkerContextWrapper::DeleteForOrigin(const GURL& origin,
ResultCallback callback) {
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&ServiceWorkerContextWrapper::DeleteForOrigin, this,
origin, std::move(callback)));
return;
}
if (!context_core_) {
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::BindOnce(std::move(callback), false));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(std::move(callback), false));
return;
}
context()->DeleteForOrigin(
@@ -420,15 +422,15 @@ void ServiceWorkerContextWrapper::CheckHasServiceWorker(
const GURL& other_url,
CheckHasServiceWorkerCallback callback) {
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&ServiceWorkerContextWrapper::CheckHasServiceWorker,
this, url, other_url, std::move(callback)));
return;
}
if (!context_core_) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(std::move(callback),
ServiceWorkerCapability::NO_SERVICE_WORKER));
return;
@@ -442,15 +444,16 @@ void ServiceWorkerContextWrapper::CheckHasServiceWorker(
void ServiceWorkerContextWrapper::ClearAllServiceWorkersForTest(
base::OnceClosure callback) {
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&ServiceWorkerContextWrapper::ClearAllServiceWorkersForTest, this,
std::move(callback)));
return;
}
if (!context_core_) {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, std::move(callback));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ std::move(callback));
return;
}
context_core_->ClearAllServiceWorkersForTest(std::move(callback));
@@ -485,7 +488,7 @@ void ServiceWorkerContextWrapper::
return;
}
- context_core_->storage()->FindRegistrationForPattern(
+ FindReadyRegistrationForPattern(
net::SimplifyUrlForRequest(pattern),
base::BindOnce(&ServiceWorkerContextWrapper::
DidFindRegistrationForLongRunningMessage,
@@ -552,8 +555,8 @@ void ServiceWorkerContextWrapper::StartServiceWorkerForNavigationHint(
"document_url", document_url.spec());
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&ServiceWorkerContextWrapper::StartServiceWorkerForNavigationHintOnIO,
this, document_url,
@@ -565,8 +568,8 @@ void ServiceWorkerContextWrapper::StartServiceWorkerForNavigationHint(
void ServiceWorkerContextWrapper::StopAllServiceWorkersForOrigin(
const GURL& origin) {
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&ServiceWorkerContextWrapper::StopAllServiceWorkersForOrigin, this,
origin));
@@ -586,8 +589,8 @@ void ServiceWorkerContextWrapper::StopAllServiceWorkersForOrigin(
void ServiceWorkerContextWrapper::StopAllServiceWorkers(
base::OnceClosure callback) {
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&ServiceWorkerContextWrapper::StopAllServiceWorkersOnIO,
this, std::move(callback),
base::ThreadTaskRunnerHandle::Get()));
@@ -742,6 +745,22 @@ void ServiceWorkerContextWrapper::GetAllRegistrations(
context_core_->storage()->GetAllRegistrationsInfos(std::move(callback));
}
+void ServiceWorkerContextWrapper::GetRegistrationsForOrigin(
+ const url::Origin& origin,
+ GetRegistrationsCallback callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ if (!context_core_) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ std::move(callback), blink::ServiceWorkerStatusCode::kErrorAbort,
+ std::vector<scoped_refptr<ServiceWorkerRegistration>>()));
+ return;
+ }
+ context_core_->storage()->GetRegistrationsForOrigin(origin.GetURL(),
+ std::move(callback));
+}
+
void ServiceWorkerContextWrapper::GetRegistrationUserData(
int64_t registration_id,
const std::vector<std::string>& keys,
@@ -871,15 +890,15 @@ void ServiceWorkerContextWrapper::GetUserDataForAllRegistrationsByKeyPrefix(
void ServiceWorkerContextWrapper::StartServiceWorker(const GURL& pattern,
StatusCallback callback) {
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&ServiceWorkerContextWrapper::StartServiceWorker, this,
pattern, std::move(callback)));
return;
}
if (!context_core_) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(std::move(callback),
blink::ServiceWorkerStatusCode::kErrorAbort));
return;
@@ -891,8 +910,8 @@ void ServiceWorkerContextWrapper::StartServiceWorker(const GURL& pattern,
void ServiceWorkerContextWrapper::SkipWaitingWorker(const GURL& pattern) {
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&ServiceWorkerContextWrapper::SkipWaitingWorker, this,
pattern));
return;
@@ -906,8 +925,8 @@ void ServiceWorkerContextWrapper::SkipWaitingWorker(const GURL& pattern) {
void ServiceWorkerContextWrapper::UpdateRegistration(const GURL& pattern) {
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&ServiceWorkerContextWrapper::UpdateRegistration, this,
pattern));
return;
@@ -923,8 +942,8 @@ void ServiceWorkerContextWrapper::UpdateRegistration(const GURL& pattern) {
void ServiceWorkerContextWrapper::SetForceUpdateOnPageLoad(
bool force_update_on_page_load) {
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&ServiceWorkerContextWrapper::SetForceUpdateOnPageLoad,
this, force_update_on_page_load));
return;
@@ -970,8 +989,8 @@ void ServiceWorkerContextWrapper::InitInternal(
ChromeBlobStorageContext* blob_context,
URLLoaderFactoryGetter* loader_factory_getter) {
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&ServiceWorkerContextWrapper::InitInternal, this,
user_data_directory, std::move(database_task_runner),
base::RetainedRef(quota_manager_proxy),
@@ -1124,8 +1143,8 @@ void ServiceWorkerContextWrapper::DidCheckHasServiceWorker(
ServiceWorkerCapability capability) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(std::move(callback), capability));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(std::move(callback), capability));
}
void ServiceWorkerContextWrapper::DidFindRegistrationForUpdate(
@@ -1164,8 +1183,8 @@ void ServiceWorkerContextWrapper::CountExternalRequests(
}
}
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(std::move(callback), pending_external_request_count));
}
@@ -1244,8 +1263,8 @@ void ServiceWorkerContextWrapper::
StartServiceWorkerForNavigationHintResult result) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
ServiceWorkerMetrics::RecordStartServiceWorkerForNavigationHintResult(result);
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(std::move(callback), result));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(std::move(callback), result));
}
void ServiceWorkerContextWrapper::StopAllServiceWorkersOnIO(
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 7766bd2311a..a137985a0f1 100644
--- a/chromium/content/browser/service_worker/service_worker_context_wrapper.h
+++ b/chromium/content/browser/service_worker/service_worker_context_wrapper.h
@@ -31,6 +31,10 @@ class QuotaManagerProxy;
class SpecialStoragePolicy;
}
+namespace url {
+class Origin;
+} // namespace url
+
namespace content {
class BrowserContext;
@@ -54,6 +58,8 @@ class CONTENT_EXPORT ServiceWorkerContextWrapper
using BoolCallback = base::OnceCallback<void(bool)>;
using FindRegistrationCallback =
ServiceWorkerStorage::FindRegistrationCallback;
+ using GetRegistrationsCallback =
+ ServiceWorkerStorage::GetRegistrationsCallback;
using GetRegistrationsInfosCallback =
ServiceWorkerStorage::GetRegistrationsInfosCallback;
using GetUserDataCallback = ServiceWorkerStorage::GetUserDataCallback;
@@ -225,6 +231,8 @@ class CONTENT_EXPORT ServiceWorkerContextWrapper
// All these methods must be called from the IO thread.
void GetAllRegistrations(GetRegistrationsInfosCallback callback);
+ void GetRegistrationsForOrigin(const url::Origin& origin,
+ GetRegistrationsCallback callback);
void GetRegistrationUserData(int64_t registration_id,
const std::vector<std::string>& keys,
GetUserDataCallback callback);
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 8c7859bfbe6..f777411dc46 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
@@ -148,7 +148,7 @@ ServiceWorkerControlleeRequestHandler::ServiceWorkerControlleeRequestHandler(
const std::string& integrity,
bool keepalive,
ResourceType resource_type,
- RequestContextType request_context_type,
+ blink::mojom::RequestContextType request_context_type,
network::mojom::RequestContextFrameType frame_type,
scoped_refptr<network::ResourceRequestBody> body)
: ServiceWorkerRequestHandler(std::move(context),
@@ -243,10 +243,10 @@ net::URLRequestJob* ServiceWorkerControlleeRequestHandler::MaybeCreateJob(
// It's for original request (A) or redirect case (B-a or B-b).
auto job = std::make_unique<ServiceWorkerURLRequestJob>(
- request, network_delegate, provider_host_->client_uuid(),
- blob_storage_context_, resource_context, request_mode_, credentials_mode_,
- redirect_mode_, integrity_, keepalive_, resource_type_,
- request_context_type_, frame_type_, body_, this);
+ request, network_delegate, provider_host_, blob_storage_context_,
+ resource_context, request_mode_, credentials_mode_, redirect_mode_,
+ integrity_, keepalive_, resource_type_, request_context_type_,
+ frame_type_, body_, this);
url_job_ = std::make_unique<ServiceWorkerURLJobWrapper>(job->GetWeakPtr());
resource_context_ = resource_context;
@@ -310,7 +310,7 @@ void ServiceWorkerControlleeRequestHandler::MaybeCreateLoader(
url_job_ = std::make_unique<ServiceWorkerURLJobWrapper>(
std::make_unique<ServiceWorkerNavigationLoader>(
std::move(callback), std::move(fallback_callback), this,
- tentative_resource_request,
+ tentative_resource_request, provider_host_,
base::WrapRefCounted(context_->loader_factory_getter())));
resource_context_ = resource_context;
@@ -319,9 +319,7 @@ void ServiceWorkerControlleeRequestHandler::MaybeCreateLoader(
tentative_resource_request.site_for_cookies);
if (url_job_->ShouldFallbackToNetwork()) {
- // We're falling back to the next NavigationLoaderInterceptor, forward
- // the request and clear job now.
- url_job_->FallbackToNetwork();
+ // The job already fell back to network. Clear the job now.
ClearJob();
return;
}
@@ -356,6 +354,10 @@ ServiceWorkerControlleeRequestHandler::MaybeCreateSubresourceLoaderParams() {
controller_info->endpoint =
provider_host_->GetControllerServiceWorkerPtr().PassInterface();
controller_info->client_id = provider_host_->client_uuid();
+ if (provider_host_->fetch_request_window_id()) {
+ controller_info->fetch_request_window_id =
+ base::make_optional(provider_host_->fetch_request_window_id());
+ }
base::WeakPtr<ServiceWorkerObjectHost> object_host =
provider_host_->GetOrCreateServiceWorkerObjectHost(
provider_host_->controller());
@@ -370,15 +372,15 @@ ServiceWorkerControlleeRequestHandler::MaybeCreateSubresourceLoaderParams() {
void ServiceWorkerControlleeRequestHandler::PrepareForMainResource(
const GURL& url,
const GURL& site_for_cookies) {
- DCHECK(!JobWasCanceled());
+ DCHECK(IsJobAlive());
DCHECK(context_);
DCHECK(provider_host_);
tracker_ = std::make_unique<MainResourceRequestTracker>();
TRACE_EVENT_ASYNC_BEGIN1(
"ServiceWorker",
- "ServiceWorkerControlleeRequestHandler::PrepareForMainResource",
- url_job_.get(), "URL", url.spec());
+ "ServiceWorkerControlleeRequestHandler::PrepareForMainResource", this,
+ "URL", url.spec());
// The provider host may already have set a controller in redirect case,
// unset it now.
provider_host_->SetControllerRegistration(
@@ -405,8 +407,8 @@ void ServiceWorkerControlleeRequestHandler::
disallow_controller,
blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration) {
- // The job may have been canceled before this was invoked.
- if (JobWasCanceled())
+ // The job may have been destroyed before this was invoked.
+ if (!IsJobAlive())
return;
if (status != blink::ServiceWorkerStatusCode::kOk) {
@@ -416,8 +418,8 @@ void ServiceWorkerControlleeRequestHandler::
url_job_->FallbackToNetwork();
TRACE_EVENT_ASYNC_END1(
"ServiceWorker",
- "ServiceWorkerControlleeRequestHandler::PrepareForMainResource",
- url_job_.get(), "Status", blink::ServiceWorkerStatusToString(status));
+ "ServiceWorkerControlleeRequestHandler::PrepareForMainResource", this,
+ "Status", blink::ServiceWorkerStatusToString(status));
return;
}
DCHECK(registration);
@@ -429,8 +431,8 @@ void ServiceWorkerControlleeRequestHandler::
url_job_->FallbackToNetwork();
TRACE_EVENT_ASYNC_END1(
"ServiceWorker",
- "ServiceWorkerControlleeRequestHandler::PrepareForMainResource",
- url_job_.get(), "Info", "No Provider");
+ "ServiceWorkerControlleeRequestHandler::PrepareForMainResource", this,
+ "Info", "No Provider");
return;
}
provider_host_->AddMatchingRegistration(registration.get());
@@ -442,8 +444,8 @@ void ServiceWorkerControlleeRequestHandler::
url_job_->FallbackToNetwork();
TRACE_EVENT_ASYNC_END1(
"ServiceWorker",
- "ServiceWorkerControlleeRequestHandler::PrepareForMainResource",
- url_job_.get(), "Info", "No Context");
+ "ServiceWorkerControlleeRequestHandler::PrepareForMainResource", this,
+ "Info", "No Context");
return;
}
@@ -456,8 +458,8 @@ void ServiceWorkerControlleeRequestHandler::
url_job_->FallbackToNetwork();
TRACE_EVENT_ASYNC_END1(
"ServiceWorker",
- "ServiceWorkerControlleeRequestHandler::PrepareForMainResource",
- url_job_.get(), "Info", "ServiceWorker is blocked");
+ "ServiceWorkerControlleeRequestHandler::PrepareForMainResource", this,
+ "Info", "ServiceWorker is blocked");
return;
}
@@ -470,8 +472,8 @@ void ServiceWorkerControlleeRequestHandler::
url_job_->FallbackToNetwork();
TRACE_EVENT_ASYNC_END1(
"ServiceWorker",
- "ServiceWorkerControlleeRequestHandler::PrepareForMainResource",
- url_job_.get(), "Info", "Insecure context");
+ "ServiceWorkerControlleeRequestHandler::PrepareForMainResource", this,
+ "Info", "Insecure context");
return;
}
@@ -504,9 +506,8 @@ void ServiceWorkerControlleeRequestHandler::
url_job_->FallbackToNetwork();
TRACE_EVENT_ASYNC_END1(
"ServiceWorker",
- "ServiceWorkerControlleeRequestHandler::PrepareForMainResource",
- url_job_.get(), "Info",
- "No active version, so falling back to network");
+ "ServiceWorkerControlleeRequestHandler::PrepareForMainResource", this,
+ "Info", "No active version, so falling back to network");
return;
}
@@ -522,8 +523,8 @@ void ServiceWorkerControlleeRequestHandler::
std::move(disallow_controller)));
TRACE_EVENT_ASYNC_END1(
"ServiceWorker",
- "ServiceWorkerControlleeRequestHandler::PrepareForMainResource",
- url_job_.get(), "Info", "Wait until finished SW activation");
+ "ServiceWorkerControlleeRequestHandler::PrepareForMainResource", this,
+ "Info", "Wait until finished SW activation");
return;
}
@@ -538,15 +539,15 @@ void ServiceWorkerControlleeRequestHandler::
scoped_refptr<ServiceWorkerVersion> active_version,
std::unique_ptr<ScopedDisallowSetControllerRegistration>
disallow_controller) {
- // The job may have been canceled before this was invoked. In that
+ // The job may have been destroyed before this was invoked. In that
// case, |url_job_| can't be used, so return.
- if (JobWasCanceled()) {
+ if (!IsJobAlive()) {
tracker_->RecordDestination(
- ServiceWorkerMetrics::MainResourceRequestDestination::kJobWasCancelled);
+ ServiceWorkerMetrics::MainResourceRequestDestination::kJobWasDestroyed);
TRACE_EVENT_ASYNC_END1(
"ServiceWorker",
- "ServiceWorkerControlleeRequestHandler::PrepareForMainResource",
- url_job_.get(), "Info", "The job was canceled");
+ "ServiceWorkerControlleeRequestHandler::PrepareForMainResource", this,
+ "Info", "The job was destroyed");
return;
}
@@ -557,9 +558,8 @@ void ServiceWorkerControlleeRequestHandler::
url_job_->FallbackToNetwork();
TRACE_EVENT_ASYNC_END1(
"ServiceWorker",
- "ServiceWorkerControlleeRequestHandler::PrepareForMainResource",
- url_job_.get(), "Info",
- "The provider host is gone, so falling back to network");
+ "ServiceWorkerControlleeRequestHandler::PrepareForMainResource", this,
+ "Info", "The provider host is gone, so falling back to network");
return;
}
@@ -588,8 +588,8 @@ void ServiceWorkerControlleeRequestHandler::
url_job_->FallbackToNetwork();
TRACE_EVENT_ASYNC_END2(
"ServiceWorker",
- "ServiceWorkerControlleeRequestHandler::PrepareForMainResource",
- url_job_.get(), "Info",
+ "ServiceWorkerControlleeRequestHandler::PrepareForMainResource", this,
+ "Info",
"The expected active version is not ACTIVATED, so falling back to "
"network",
"Status",
@@ -622,8 +622,8 @@ void ServiceWorkerControlleeRequestHandler::
}
TRACE_EVENT_ASYNC_END1(
"ServiceWorker",
- "ServiceWorkerControlleeRequestHandler::PrepareForMainResource",
- url_job_.get(), "Info",
+ "ServiceWorkerControlleeRequestHandler::PrepareForMainResource", this,
+ "Info",
(is_forwarded) ? "Forwarded to the ServiceWorker"
: "Skipped the ServiceWorker which has no fetch handler");
}
@@ -637,8 +637,8 @@ void ServiceWorkerControlleeRequestHandler::DidUpdateRegistration(
int64_t registration_id) {
DCHECK(force_update_started_);
- // The job may have been canceled before this was invoked.
- if (JobWasCanceled())
+ // The job may have been destroyed before this was invoked.
+ if (!IsJobAlive())
return;
if (!context_) {
@@ -672,8 +672,8 @@ void ServiceWorkerControlleeRequestHandler::OnUpdatedVersionStatusChanged(
scoped_refptr<ServiceWorkerVersion> version,
std::unique_ptr<ScopedDisallowSetControllerRegistration>
disallow_controller) {
- // The job may have been canceled before this was invoked.
- if (JobWasCanceled())
+ // The job may have been destroyed before this was invoked.
+ if (!IsJobAlive())
return;
if (!context_) {
@@ -699,7 +699,7 @@ void ServiceWorkerControlleeRequestHandler::OnUpdatedVersionStatusChanged(
}
void ServiceWorkerControlleeRequestHandler::PrepareForSubResource() {
- DCHECK(!JobWasCanceled());
+ DCHECK(IsJobAlive());
DCHECK(context_);
// When this request handler was created, the provider host had a controller
@@ -776,8 +776,8 @@ void ServiceWorkerControlleeRequestHandler::ClearJob() {
url_job_.reset();
}
-bool ServiceWorkerControlleeRequestHandler::JobWasCanceled() const {
- return !url_job_ || url_job_->WasCanceled();
+bool ServiceWorkerControlleeRequestHandler::IsJobAlive() const {
+ return url_job_ && url_job_->IsAlive();
}
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_controllee_request_handler.h b/chromium/content/browser/service_worker/service_worker_controllee_request_handler.h
index 0ad6eed9b4b..d8ed84cd241 100644
--- a/chromium/content/browser/service_worker/service_worker_controllee_request_handler.h
+++ b/chromium/content/browser/service_worker/service_worker_controllee_request_handler.h
@@ -19,10 +19,10 @@
#include "content/browser/service_worker/service_worker_url_job_wrapper.h"
#include "content/browser/service_worker/service_worker_url_request_job.h"
#include "content/common/service_worker/service_worker_types.h"
-#include "content/public/common/request_context_type.h"
#include "content/public/common/resource_type.h"
#include "services/network/public/mojom/fetch_api.mojom.h"
#include "services/network/public/mojom/request_context_frame_type.mojom.h"
+#include "third_party/blink/public/platform/modules/fetch/fetch_api_request.mojom.h"
#include "url/gurl.h"
namespace net {
@@ -58,7 +58,7 @@ class CONTENT_EXPORT ServiceWorkerControlleeRequestHandler
const std::string& integrity,
bool keepalive,
ResourceType resource_type,
- RequestContextType request_context_type,
+ blink::mojom::RequestContextType request_context_type,
network::mojom::RequestContextFrameType frame_type,
scoped_refptr<network::ResourceRequestBody> body);
~ServiceWorkerControlleeRequestHandler() override;
@@ -144,7 +144,7 @@ class CONTENT_EXPORT ServiceWorkerControlleeRequestHandler
// that job, except for timing information.
void ClearJob();
- bool JobWasCanceled() const;
+ bool IsJobAlive() const;
// Schedules a service worker update to occur shortly after the page and its
// initial subresources load, if this handler was for a navigation.
@@ -158,7 +158,7 @@ class CONTENT_EXPORT ServiceWorkerControlleeRequestHandler
network::mojom::FetchRedirectMode redirect_mode_;
std::string integrity_;
const bool keepalive_;
- RequestContextType request_context_type_;
+ blink::mojom::RequestContextType request_context_type_;
network::mojom::RequestContextFrameType frame_type_;
scoped_refptr<network::ResourceRequestBody> body_;
ResourceContext* resource_context_;
diff --git a/chromium/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc b/chromium/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc
index 930165c99aa..e929e0d6884 100644
--- a/chromium/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc
@@ -23,7 +23,6 @@
#include "content/common/service_worker/service_worker_types.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/browser/resource_context.h"
-#include "content/public/common/request_context_type.h"
#include "content/public/common/resource_type.h"
#include "content/public/test/mock_resource_context.h"
#include "content/public/test/test_browser_thread_bundle.h"
@@ -36,6 +35,7 @@
#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_registration.mojom.h"
+#include "third_party/blink/public/platform/modules/fetch/fetch_api_request.mojom.h"
namespace content {
namespace service_worker_controllee_request_handler_unittest {
@@ -70,7 +70,7 @@ class ServiceWorkerControlleeRequestHandlerTest
std::string() /* integrity */,
false /* keepalive */,
type,
- REQUEST_CONTEXT_TYPE_HYPERLINK,
+ blink::mojom::RequestContextType::HYPERLINK,
network::mojom::RequestContextFrameType::kTopLevel,
scoped_refptr<network::ResourceRequestBody>())),
job_(nullptr) {}
@@ -145,8 +145,9 @@ class ServiceWorkerControlleeRequestHandlerTest
options.scope = scope_;
registration_ =
new ServiceWorkerRegistration(options, 1L, context()->AsWeakPtr());
- version_ = new ServiceWorkerVersion(
- registration_.get(), script_url_, 1L, context()->AsWeakPtr());
+ version_ = new ServiceWorkerVersion(registration_.get(), script_url_,
+ blink::mojom::ScriptType::kClassic, 1L,
+ context()->AsWeakPtr());
context()->storage()->LazyInitializeForTest(base::DoNothing());
base::RunLoop().RunUntilIdle();
diff --git a/chromium/content/browser/service_worker/service_worker_data_pipe_reader_unittest.cc b/chromium/content/browser/service_worker/service_worker_data_pipe_reader_unittest.cc
index 4b9a1d71457..33490cb1dc8 100644
--- a/chromium/content/browser/service_worker/service_worker_data_pipe_reader_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_data_pipe_reader_unittest.cc
@@ -33,7 +33,7 @@ class MockServiceWorkerURLRequestJob : public ServiceWorkerURLRequestJob {
: ServiceWorkerURLRequestJob(
nullptr,
nullptr,
- "",
+ nullptr,
nullptr,
nullptr,
network::mojom::FetchRequestMode::kNoCORS,
@@ -42,7 +42,7 @@ class MockServiceWorkerURLRequestJob : public ServiceWorkerURLRequestJob {
std::string() /* integrity */,
false /* keepalive */,
RESOURCE_TYPE_MAIN_FRAME,
- REQUEST_CONTEXT_TYPE_HYPERLINK,
+ blink::mojom::RequestContextType::HYPERLINK,
network::mojom::RequestContextFrameType::kTopLevel,
scoped_refptr<network::ResourceRequestBody>(),
delegate),
@@ -86,7 +86,8 @@ class ServiceWorkerDataPipeReaderTest
registration_ = new ServiceWorkerRegistration(
options, 1L, helper_->context()->AsWeakPtr());
version_ = new ServiceWorkerVersion(
- registration_.get(), GURL("https://example.com/service_worker.js"), 1L,
+ registration_.get(), GURL("https://example.com/service_worker.js"),
+ blink::mojom::ScriptType::kClassic, 1L,
helper_->context()->AsWeakPtr());
std::vector<ServiceWorkerDatabase::ResourceRecord> records;
records.push_back(
@@ -182,7 +183,8 @@ TEST_P(ServiceWorkerDataPipeReaderTestP, SyncRead) {
data_pipe_reader->Start();
EXPECT_TRUE(mock_url_request_job()->is_response_started());
const int buffer_size = sizeof(kTestData);
- scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(buffer_size);
+ scoped_refptr<net::IOBuffer> buffer =
+ base::MakeRefCounted<net::IOBuffer>(buffer_size);
buffer->data()[buffer_size - 1] = '\0';
// Read successfully.
@@ -238,7 +240,8 @@ TEST_P(ServiceWorkerDataPipeReaderTestP, SyncAbort) {
data_pipe_reader->Start();
EXPECT_TRUE(mock_url_request_job()->is_response_started());
const int buffer_size = sizeof(kTestData);
- scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(buffer_size);
+ scoped_refptr<net::IOBuffer> buffer =
+ base::MakeRefCounted<net::IOBuffer>(buffer_size);
buffer->data()[buffer_size - 1] = '\0';
// Read successfully.
@@ -276,7 +279,8 @@ TEST_P(ServiceWorkerDataPipeReaderTestP, AsyncRead) {
// Start to read.
data_pipe_reader->Start();
EXPECT_TRUE(mock_url_request_job()->is_response_started());
- scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(sizeof(kTestData));
+ scoped_refptr<net::IOBuffer> buffer =
+ base::MakeRefCounted<net::IOBuffer>(sizeof(kTestData));
buffer->data()[sizeof(kTestData) - 1] = '\0';
std::string expected_response;
std::string retrieved_response;
@@ -349,7 +353,8 @@ TEST_P(ServiceWorkerDataPipeReaderTestP, AsyncAbort) {
// Start to read.
data_pipe_reader->Start();
EXPECT_TRUE(mock_url_request_job()->is_response_started());
- scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(sizeof(kTestData));
+ scoped_refptr<net::IOBuffer> buffer =
+ base::MakeRefCounted<net::IOBuffer>(sizeof(kTestData));
buffer->data()[sizeof(kTestData) - 1] = '\0';
std::string expected_response;
std::string retrieved_response;
diff --git a/chromium/content/browser/service_worker/service_worker_database.cc b/chromium/content/browser/service_worker/service_worker_database.cc
index c7610f12b60..4f39ee07144 100644
--- a/chromium/content/browser/service_worker/service_worker_database.cc
+++ b/chromium/content/browser/service_worker/service_worker_database.cc
@@ -275,6 +275,7 @@ const char* ServiceWorkerDatabase::StatusToString(
ServiceWorkerDatabase::RegistrationData::RegistrationData()
: registration_id(blink::mojom::kInvalidServiceWorkerRegistrationId),
+ script_type(blink::mojom::ScriptType::kClassic),
update_via_cache(blink::mojom::ServiceWorkerUpdateViaCache::kImports),
version_id(blink::mojom::kInvalidServiceWorkerVersionId),
is_active(false),
@@ -575,8 +576,7 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::WriteRegistration(
// Used for avoiding multiple writes for the same resource id or url.
std::set<int64_t> pushed_resources;
std::set<GURL> pushed_urls;
- for (std::vector<ResourceRecord>::const_iterator itr = resources.begin();
- itr != resources.end(); ++itr) {
+ for (auto itr = resources.begin(); itr != resources.end(); ++itr) {
if (!itr->url.is_valid())
return STATUS_ERROR_FAILED;
@@ -1410,6 +1410,15 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::ParseRegistrationData(
for (uint32_t feature : data.used_features())
out->used_features.insert(feature);
+ if (data.has_script_type()) {
+ auto value = data.script_type();
+ if (!ServiceWorkerRegistrationData_ServiceWorkerScriptType_IsValid(value)) {
+ DLOG(ERROR) << "Worker script type '" << value << "' is not valid.";
+ return ServiceWorkerDatabase::STATUS_ERROR_CORRUPTED;
+ }
+ out->script_type = static_cast<blink::mojom::ScriptType>(value);
+ }
+
if (data.has_update_via_cache()) {
auto value = data.update_via_cache();
if (!ServiceWorkerRegistrationData_ServiceWorkerUpdateViaCacheType_IsValid(
@@ -1461,6 +1470,9 @@ void ServiceWorkerDatabase::WriteRegistrationDataInBatch(
for (uint32_t feature : registration.used_features)
data.add_used_features(feature);
+ data.set_script_type(
+ static_cast<ServiceWorkerRegistrationData_ServiceWorkerScriptType>(
+ registration.script_type));
data.set_update_via_cache(
static_cast<
ServiceWorkerRegistrationData_ServiceWorkerUpdateViaCacheType>(
@@ -1669,8 +1681,7 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::WriteResourceIdsInBatch(
if (ids.empty())
return STATUS_OK;
- for (std::set<int64_t>::const_iterator itr = ids.begin(); itr != ids.end();
- ++itr) {
+ for (auto itr = ids.begin(); itr != ids.end(); ++itr) {
// Value should be empty.
batch->Put(CreateResourceIdKey(id_key_prefix, *itr), "");
}
@@ -1692,8 +1703,7 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::DeleteResourceIdsInBatch(
if (status != STATUS_OK)
return status;
- for (std::set<int64_t>::const_iterator itr = ids.begin(); itr != ids.end();
- ++itr) {
+ for (auto itr = ids.begin(); itr != ids.end(); ++itr) {
batch->Delete(CreateResourceIdKey(id_key_prefix, *itr));
}
return STATUS_OK;
diff --git a/chromium/content/browser/service_worker/service_worker_database.h b/chromium/content/browser/service_worker/service_worker_database.h
index c99a3d88f66..31fee1851b2 100644
--- a/chromium/content/browser/service_worker/service_worker_database.h
+++ b/chromium/content/browser/service_worker/service_worker_database.h
@@ -72,6 +72,7 @@ class CONTENT_EXPORT ServiceWorkerDatabase {
// the waiting version. Then transition to the active version. The stored
// version may be in the ACTIVATED state or in the INSTALLED state.
GURL script;
+ blink::mojom::ScriptType script_type;
blink::mojom::ServiceWorkerUpdateViaCache update_via_cache;
int64_t version_id;
bool is_active;
diff --git a/chromium/content/browser/service_worker/service_worker_database.proto b/chromium/content/browser/service_worker/service_worker_database.proto
index 9502e2aefb3..767477cc8ca 100644
--- a/chromium/content/browser/service_worker/service_worker_database.proto
+++ b/chromium/content/browser/service_worker/service_worker_database.proto
@@ -23,6 +23,10 @@ message ServiceWorkerNavigationPreloadState {
}
message ServiceWorkerRegistrationData {
+ enum ServiceWorkerScriptType {
+ CLASSIC = 0;
+ MODULE = 1;
+ }
enum ServiceWorkerUpdateViaCacheType {
IMPORTS = 0;
ALL = 1;
@@ -63,6 +67,7 @@ message ServiceWorkerRegistrationData {
optional ServiceWorkerUpdateViaCacheType update_via_cache = 14
[default = IMPORTS];
+ optional ServiceWorkerScriptType script_type = 15 [default = CLASSIC];
}
message ServiceWorkerResourceRecord {
diff --git a/chromium/content/browser/service_worker/service_worker_database_unittest.cc b/chromium/content/browser/service_worker/service_worker_database_unittest.cc
index 8b0dca82d17..011e30bfbad 100644
--- a/chromium/content/browser/service_worker/service_worker_database_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_database_unittest.cc
@@ -9,7 +9,6 @@
#include <string>
-#include "base/command_line.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/macros.h"
@@ -17,7 +16,6 @@
#include "base/strings/string_number_conversions.h"
#include "content/browser/service_worker/service_worker_database.pb.h"
#include "content/common/service_worker/service_worker_types.h"
-#include "content/public/common/content_switches.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom.h"
@@ -72,14 +70,15 @@ void VerifyRegistrationData(const RegistrationData& expected,
EXPECT_EQ(expected.registration_id, actual.registration_id);
EXPECT_EQ(expected.scope, actual.scope);
EXPECT_EQ(expected.script, actual.script);
+ EXPECT_EQ(expected.script_type, actual.script_type);
+ EXPECT_EQ(expected.update_via_cache, actual.update_via_cache);
EXPECT_EQ(expected.version_id, actual.version_id);
EXPECT_EQ(expected.is_active, actual.is_active);
EXPECT_EQ(expected.has_fetch_handler, actual.has_fetch_handler);
EXPECT_EQ(expected.last_update_check, actual.last_update_check);
+ EXPECT_EQ(expected.used_features, actual.used_features);
EXPECT_EQ(expected.resources_total_size_bytes,
actual.resources_total_size_bytes);
- EXPECT_EQ(expected.used_features, actual.used_features);
- EXPECT_EQ(expected.update_via_cache, actual.update_via_cache);
}
void VerifyResourceRecords(const std::vector<Resource>& expected,
@@ -126,7 +125,7 @@ TEST(ServiceWorkerDatabaseTest, OpenDatabase_InMemory) {
}
TEST(ServiceWorkerDatabaseTest, DatabaseVersion_ValidSchemaVersion) {
- GURL origin("http://example.com");
+ GURL origin("https://example.com");
std::unique_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory());
EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, database->LazyOpen(true));
@@ -163,7 +162,7 @@ TEST(ServiceWorkerDatabaseTest, DatabaseVersion_ObsoleteSchemaVersion) {
// First writing triggers database initialization and bumps the schema
// version.
- GURL origin("http://example.com");
+ GURL origin("https://example.com");
std::vector<ServiceWorkerDatabase::ResourceRecord> resources;
resources.push_back(CreateResource(1, URL(origin, "/resource"), 10));
ServiceWorkerDatabase::RegistrationData deleted_version;
@@ -203,7 +202,7 @@ TEST(ServiceWorkerDatabaseTest, DatabaseVersion_CorruptedSchemaVersion) {
// First writing triggers database initialization and bumps the schema
// version.
- GURL origin("http://example.com");
+ GURL origin("https://example.com");
std::vector<ServiceWorkerDatabase::ResourceRecord> resources;
resources.push_back(CreateResource(1, URL(origin, "/resource"), 10));
ServiceWorkerDatabase::RegistrationData deleted_version;
@@ -239,7 +238,7 @@ TEST(ServiceWorkerDatabaseTest, GetNextAvailableIds) {
std::unique_ptr<ServiceWorkerDatabase> database(
CreateDatabase(database_dir.GetPath()));
- GURL origin("http://example.com");
+ GURL origin("https://example.com");
// The database has never been used, so returns initial values.
AvailableIds ids;
@@ -345,7 +344,7 @@ TEST(ServiceWorkerDatabaseTest, GetOriginsWithRegistrations) {
ServiceWorkerDatabase::RegistrationData deleted_version;
std::vector<int64_t> newly_purgeable_resources;
- GURL origin1("http://example.com");
+ GURL origin1("https://example.com");
RegistrationData data1;
data1.registration_id = 123;
data1.scope = URL(origin1, "/foo");
@@ -441,7 +440,7 @@ TEST(ServiceWorkerDatabaseTest, GetOriginsWithRegistrations) {
TEST(ServiceWorkerDatabaseTest, GetRegistrationsForOrigin) {
std::unique_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory());
- GURL origin1("http://example.com");
+ GURL origin1("https://example.com");
GURL origin2("https://www.example.com");
GURL origin3("https://example.org");
@@ -548,11 +547,6 @@ TEST(ServiceWorkerDatabaseTest, GetRegistrationsForOrigin) {
}
TEST(ServiceWorkerDatabaseTest, GetAllRegistrations) {
- // TODO(https://crbug.com/618076): Remove the following command line switch
- // when update_via_cache is shipped to stable.
- base::CommandLine::ForCurrentProcess()->AppendSwitch(
- switches::kEnableExperimentalWebPlatformFeatures);
-
std::unique_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory());
std::vector<RegistrationData> registrations;
@@ -563,7 +557,7 @@ TEST(ServiceWorkerDatabaseTest, GetAllRegistrations) {
ServiceWorkerDatabase::RegistrationData deleted_version;
std::vector<int64_t> newly_purgeable_resources;
- GURL origin1("http://www1.example.com");
+ GURL origin1("https://www1.example.com");
RegistrationData data1;
data1.registration_id = 100;
data1.scope = URL(origin1, "/foo");
@@ -576,7 +570,7 @@ TEST(ServiceWorkerDatabaseTest, GetAllRegistrations) {
database->WriteRegistration(data1, resources1, &deleted_version,
&newly_purgeable_resources));
- GURL origin2("http://www2.example.com");
+ GURL origin2("https://www2.example.com");
RegistrationData data2;
data2.registration_id = 200;
data2.scope = URL(origin2, "/bar");
@@ -590,7 +584,7 @@ TEST(ServiceWorkerDatabaseTest, GetAllRegistrations) {
database->WriteRegistration(data2, resources2, &deleted_version,
&newly_purgeable_resources));
- GURL origin3("http://www3.example.com");
+ GURL origin3("https://www3.example.com");
RegistrationData data3;
data3.registration_id = 300;
data3.scope = URL(origin3, "/hoge");
@@ -620,6 +614,7 @@ TEST(ServiceWorkerDatabaseTest, GetAllRegistrations) {
EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
database->GetAllRegistrations(&registrations));
EXPECT_EQ(4U, registrations.size());
+
VerifyRegistrationData(data1, registrations[0]);
VerifyRegistrationData(data2, registrations[1]);
VerifyRegistrationData(data3, registrations[2]);
@@ -629,7 +624,7 @@ TEST(ServiceWorkerDatabaseTest, GetAllRegistrations) {
TEST(ServiceWorkerDatabaseTest, Registration_Basic) {
std::unique_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory());
- GURL origin("http://example.com");
+ GURL origin("https://example.com");
RegistrationData data;
data.registration_id = 100;
data.scope = URL(origin, "/foo");
@@ -717,7 +712,7 @@ TEST(ServiceWorkerDatabaseTest, Registration_Basic) {
TEST(ServiceWorkerDatabaseTest, DeleteNonExistentRegistration) {
std::unique_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory());
- GURL origin("http://example.com");
+ GURL origin("https://example.com");
RegistrationData data;
data.registration_id = 100;
data.scope = URL(origin, "/foo");
@@ -758,24 +753,18 @@ TEST(ServiceWorkerDatabaseTest, DeleteNonExistentRegistration) {
deleted_version.version_id = kArbitraryVersionId;
newly_purgeable_resources.clear();
EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
- database->DeleteRegistration(kNonExistentRegistrationId,
- GURL("http://example.net"),
- &deleted_version,
- &newly_purgeable_resources));
+ database->DeleteRegistration(
+ kNonExistentRegistrationId, GURL("https://example.net"),
+ &deleted_version, &newly_purgeable_resources));
EXPECT_EQ(blink::mojom::kInvalidServiceWorkerVersionId,
deleted_version.version_id);
EXPECT_TRUE(newly_purgeable_resources.empty());
}
TEST(ServiceWorkerDatabaseTest, Registration_Overwrite) {
- // TODO(https://crbug.com/618076): Remove the following command line switch
- // when update_via_cache is shipped to stable.
- base::CommandLine::ForCurrentProcess()->AppendSwitch(
- switches::kEnableExperimentalWebPlatformFeatures);
-
std::unique_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory());
- GURL origin("http://example.com");
+ GURL origin("https://example.com");
RegistrationData data;
data.registration_id = 100;
data.scope = URL(origin, "/foo");
@@ -814,6 +803,7 @@ TEST(ServiceWorkerDatabaseTest, Registration_Overwrite) {
updated_data.version_id = data.version_id + 1;
updated_data.resources_total_size_bytes = 12 + 13;
updated_data.used_features = {109, 421, 9101};
+ updated_data.script_type = blink::mojom::ScriptType::kModule;
updated_data.update_via_cache =
blink::mojom::ServiceWorkerUpdateViaCache::kAll;
std::vector<Resource> resources2;
@@ -848,7 +838,7 @@ TEST(ServiceWorkerDatabaseTest, Registration_Overwrite) {
TEST(ServiceWorkerDatabaseTest, Registration_Multiple) {
std::unique_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory());
- GURL origin("http://example.com");
+ GURL origin("https://example.com");
ServiceWorkerDatabase::RegistrationData deleted_version;
std::vector<int64_t> newly_purgeable_resources;
@@ -953,7 +943,7 @@ TEST(ServiceWorkerDatabaseTest, Registration_Multiple) {
TEST(ServiceWorkerDatabaseTest, Registration_UninitializedDatabase) {
std::unique_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory());
- const GURL origin("http://example.com");
+ const GURL origin("https://example.com");
// Should be failed because the database does not exist.
RegistrationData data_out;
@@ -1001,9 +991,90 @@ TEST(ServiceWorkerDatabaseTest, Registration_UninitializedDatabase) {
EXPECT_TRUE(newly_purgeable_resources.empty());
}
+TEST(ServiceWorkerDatabaseTest, Registration_ScriptType) {
+ std::unique_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory());
+
+ ServiceWorkerDatabase::RegistrationData deleted_version;
+ std::vector<int64_t> newly_purgeable_resources;
+
+ // Default script type.
+ GURL origin1("https://www1.example.com");
+ RegistrationData data1;
+ data1.registration_id = 100;
+ data1.scope = URL(origin1, "/foo");
+ data1.script = URL(origin1, "/resource1");
+ data1.version_id = 100;
+ data1.resources_total_size_bytes = 10 + 10000;
+ EXPECT_EQ(blink::mojom::ScriptType::kClassic, data1.script_type);
+ std::vector<Resource> resources1;
+ resources1.push_back(CreateResource(1, URL(origin1, "/resource1"), 10));
+ resources1.push_back(CreateResource(2, URL(origin1, "/resource2"), 10000));
+ EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
+ database->WriteRegistration(data1, resources1, &deleted_version,
+ &newly_purgeable_resources));
+
+ // Classic script type.
+ GURL origin2("https://www2.example.com");
+ RegistrationData data2;
+ data2.registration_id = 200;
+ data2.scope = URL(origin2, "/bar");
+ data2.script = URL(origin2, "/resource3");
+ data2.version_id = 200;
+ data2.resources_total_size_bytes = 20 + 20000;
+ data2.script_type = blink::mojom::ScriptType::kClassic;
+ std::vector<Resource> resources2;
+ resources2.push_back(CreateResource(3, URL(origin2, "/resource3"), 20));
+ resources2.push_back(CreateResource(4, URL(origin2, "/resource4"), 20000));
+ EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
+ database->WriteRegistration(data2, resources2, &deleted_version,
+ &newly_purgeable_resources));
+
+ // Module script type.
+ GURL origin3("https://www3.example.com");
+ RegistrationData data3;
+ data3.registration_id = 300;
+ data3.scope = URL(origin3, "/baz");
+ data3.script = URL(origin3, "/resource5");
+ data3.version_id = 300;
+ data3.resources_total_size_bytes = 30 + 30000;
+ data3.script_type = blink::mojom::ScriptType::kModule;
+ std::vector<Resource> resources3;
+ resources3.push_back(CreateResource(5, URL(origin3, "/resource5"), 30));
+ resources3.push_back(CreateResource(6, URL(origin3, "/resource6"), 30000));
+ EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
+ database->WriteRegistration(data3, resources3, &deleted_version,
+ &newly_purgeable_resources));
+
+ RegistrationData data;
+ std::vector<Resource> resources;
+ EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
+ database->ReadRegistration(data1.registration_id, origin1, &data,
+ &resources));
+ VerifyRegistrationData(data1, data);
+ VerifyResourceRecords(resources1, resources);
+ EXPECT_EQ(2U, resources.size());
+ resources.clear();
+
+ EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
+ database->ReadRegistration(data2.registration_id, origin2, &data,
+ &resources));
+ VerifyRegistrationData(data2, data);
+ VerifyResourceRecords(resources2, resources);
+ EXPECT_EQ(2U, resources.size());
+ resources.clear();
+
+ EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
+ database->ReadRegistration(data3.registration_id, origin3, &data,
+ &resources));
+ VerifyRegistrationData(data3, data);
+ VerifyResourceRecords(resources3, resources);
+ EXPECT_EQ(2U, resources.size());
+ resources.clear();
+}
+
TEST(ServiceWorkerDatabaseTest, UserData_Basic) {
std::unique_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory());
- const GURL kOrigin("http://example.com");
+ const GURL kOrigin("https://example.com");
// Add a registration.
RegistrationData data;
@@ -1119,7 +1190,7 @@ TEST(ServiceWorkerDatabaseTest, UserData_Basic) {
TEST(ServiceWorkerDatabaseTest,
UserData_ReadUserDataForAllRegistrationsByKeyPrefix) {
std::unique_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory());
- const GURL kOrigin("http://example.com");
+ const GURL kOrigin("https://example.com");
// Add registration 1.
RegistrationData data1;
@@ -1196,7 +1267,7 @@ TEST(ServiceWorkerDatabaseTest,
TEST(ServiceWorkerDatabaseTest, ReadUserDataByKeyPrefix) {
std::unique_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory());
- const GURL kOrigin("http://example.com");
+ const GURL kOrigin("https://example.com");
// Add a registration.
RegistrationData data;
@@ -1242,7 +1313,7 @@ TEST(ServiceWorkerDatabaseTest, ReadUserDataByKeyPrefix) {
TEST(ServiceWorkerDatabaseTest, ReadUserKeysAndDataByKeyPrefix) {
std::unique_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory());
- const GURL kOrigin("http://example.com");
+ const GURL kOrigin("https://example.com");
// Add a registration.
RegistrationData data;
@@ -1292,7 +1363,7 @@ TEST(ServiceWorkerDatabaseTest, ReadUserKeysAndDataByKeyPrefix) {
TEST(ServiceWorkerDatabaseTest, UserData_DeleteUserDataByKeyPrefixes) {
std::unique_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory());
- const GURL kOrigin("http://example.com");
+ const GURL kOrigin("https://example.com");
// Add registration 1.
RegistrationData data1;
@@ -1392,7 +1463,7 @@ TEST(ServiceWorkerDatabaseTest, UserData_DeleteUserDataByKeyPrefixes) {
TEST(ServiceWorkerDatabaseTest, UserData_DataIsolation) {
std::unique_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory());
- const GURL kOrigin("http://example.com");
+ const GURL kOrigin("https://example.com");
// Add registration 1.
RegistrationData data1;
@@ -1488,7 +1559,7 @@ TEST(ServiceWorkerDatabaseTest, UserData_DataIsolation) {
TEST(ServiceWorkerDatabaseTest, UserData_DeleteRegistration) {
std::unique_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory());
- const GURL kOrigin("http://example.com");
+ const GURL kOrigin("https://example.com");
// Add registration 1.
RegistrationData data1;
@@ -1569,7 +1640,7 @@ TEST(ServiceWorkerDatabaseTest, UserData_DeleteRegistration) {
TEST(ServiceWorkerDatabaseTest, UserData_UninitializedDatabase) {
std::unique_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory());
- const GURL kOrigin("http://example.com");
+ const GURL kOrigin("https://example.com");
// Should be failed because the database does not exist.
std::vector<std::string> user_data_out;
@@ -1601,7 +1672,7 @@ TEST(ServiceWorkerDatabaseTest, UserData_UninitializedDatabase) {
TEST(ServiceWorkerDatabaseTest, UpdateVersionToActive) {
std::unique_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory());
- GURL origin("http://example.com");
+ GURL origin("https://example.com");
ServiceWorkerDatabase::RegistrationData deleted_version;
std::vector<int64_t> newly_purgeable_resources;
@@ -1662,7 +1733,7 @@ TEST(ServiceWorkerDatabaseTest, UpdateVersionToActive) {
TEST(ServiceWorkerDatabaseTest, UpdateLastCheckTime) {
std::unique_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory());
- GURL origin("http://example.com");
+ GURL origin("https://example.com");
ServiceWorkerDatabase::RegistrationData deleted_version;
std::vector<int64_t> newly_purgeable_resources;
@@ -1782,8 +1853,8 @@ TEST(ServiceWorkerDatabaseTest, DeleteAllDataForOrigin) {
std::vector<int64_t> newly_purgeable_resources;
// Data associated with |origin1| will be removed.
- GURL origin1("http://example.com");
- GURL origin2("http://example.org");
+ GURL origin1("https://example.com");
+ GURL origin2("https://example.org");
// |origin1| has two registrations (registration1 and registration2).
RegistrationData data1;
@@ -1942,7 +2013,7 @@ TEST(ServiceWorkerDatabaseTest, Corruption_NoMainResource) {
ServiceWorkerDatabase::RegistrationData deleted_version;
std::vector<int64_t> newly_purgeable_resources;
- GURL origin("http://example.com");
+ GURL origin("https://example.com");
RegistrationData data;
data.registration_id = 10;
diff --git a/chromium/content/browser/service_worker/service_worker_disk_cache.cc b/chromium/content/browser/service_worker/service_worker_disk_cache.cc
index 27989a034f7..4ec1b562ced 100644
--- a/chromium/content/browser/service_worker/service_worker_disk_cache.cc
+++ b/chromium/content/browser/service_worker/service_worker_disk_cache.cc
@@ -9,23 +9,21 @@
namespace content {
ServiceWorkerDiskCache::ServiceWorkerDiskCache()
- : AppCacheDiskCache(true /* use_simple_cache */) {
- uma_name_ = "DiskCache.ServiceWorker";
-}
+ : AppCacheDiskCache("DiskCache.ServiceWorker", /*use_simple_cache=*/true) {}
ServiceWorkerResponseReader::ServiceWorkerResponseReader(
int64_t resource_id,
- base::WeakPtr<AppCacheDiskCacheInterface> disk_cache)
+ base::WeakPtr<AppCacheDiskCache> disk_cache)
: AppCacheResponseReader(resource_id, std::move(disk_cache)) {}
ServiceWorkerResponseWriter::ServiceWorkerResponseWriter(
int64_t resource_id,
- base::WeakPtr<AppCacheDiskCacheInterface> disk_cache)
+ base::WeakPtr<AppCacheDiskCache> disk_cache)
: AppCacheResponseWriter(resource_id, std::move(disk_cache)) {}
ServiceWorkerResponseMetadataWriter::ServiceWorkerResponseMetadataWriter(
int64_t resource_id,
- base::WeakPtr<AppCacheDiskCacheInterface> disk_cache)
+ base::WeakPtr<AppCacheDiskCache> disk_cache)
: AppCacheResponseMetadataWriter(resource_id, std::move(disk_cache)) {}
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_disk_cache.h b/chromium/content/browser/service_worker/service_worker_disk_cache.h
index bfadf688bf3..df46478094d 100644
--- a/chromium/content/browser/service_worker/service_worker_disk_cache.h
+++ b/chromium/content/browser/service_worker/service_worker_disk_cache.h
@@ -8,6 +8,7 @@
#include <stdint.h>
#include "content/browser/appcache/appcache_disk_cache.h"
+#include "content/browser/appcache/appcache_response.h"
#include "content/common/content_export.h"
namespace content {
@@ -29,9 +30,8 @@ class CONTENT_EXPORT ServiceWorkerResponseReader
// Should only be constructed by the storage class.
friend class ServiceWorkerStorage;
- ServiceWorkerResponseReader(
- int64_t resource_id,
- base::WeakPtr<AppCacheDiskCacheInterface> disk_cache);
+ ServiceWorkerResponseReader(int64_t resource_id,
+ base::WeakPtr<AppCacheDiskCache> disk_cache);
};
class CONTENT_EXPORT ServiceWorkerResponseWriter
@@ -40,9 +40,8 @@ class CONTENT_EXPORT ServiceWorkerResponseWriter
// Should only be constructed by the storage class.
friend class ServiceWorkerStorage;
- ServiceWorkerResponseWriter(
- int64_t resource_id,
- base::WeakPtr<AppCacheDiskCacheInterface> disk_cache);
+ ServiceWorkerResponseWriter(int64_t resource_id,
+ base::WeakPtr<AppCacheDiskCache> disk_cache);
};
class CONTENT_EXPORT ServiceWorkerResponseMetadataWriter
@@ -53,7 +52,7 @@ class CONTENT_EXPORT ServiceWorkerResponseMetadataWriter
ServiceWorkerResponseMetadataWriter(
int64_t resource_id,
- base::WeakPtr<AppCacheDiskCacheInterface> disk_cache);
+ base::WeakPtr<AppCacheDiskCache> disk_cache);
};
} // namespace content
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 93a89c2faac..a1511aebbb8 100644
--- a/chromium/content/browser/service_worker/service_worker_dispatcher_host.cc
+++ b/chromium/content/browser/service_worker/service_worker_dispatcher_host.cc
@@ -6,10 +6,12 @@
#include <utility>
+#include "base/task/post_task.h"
#include "base/trace_event/trace_event.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/common/service_worker/service_worker_utils.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/common/child_process_host.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_provider_type.mojom.h"
@@ -41,8 +43,8 @@ void ServiceWorkerDispatcherHost::RenderProcessExited(
// renderer is destroyed. But if we don't remove the hosts immediately here,
// collisions of <process_id, provider_id> can occur if |this| is reused for
// another new renderer process due to reuse of the RenderProcessHost.
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&ServiceWorkerDispatcherHost::RemoveAllProviderHostsForProcess,
base::Unretained(this)));
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 7bdd0811226..ed9fb83a1d7 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
@@ -11,6 +11,7 @@
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/run_loop.h"
+#include "base/task/post_task.h"
#include "base/time/time.h"
#include "content/browser/service_worker/embedded_worker_instance.h"
#include "content/browser/service_worker/embedded_worker_registry.h"
@@ -22,6 +23,7 @@
#include "content/browser/service_worker/service_worker_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/browser/browser_task_traits.h"
#include "content/public/browser/child_process_termination_info.h"
#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/common/content_switches.h"
@@ -50,8 +52,8 @@ struct RemoteProviderInfo {
std::unique_ptr<ServiceWorkerNavigationHandleCore> CreateNavigationHandleCore(
ServiceWorkerContextWrapper* context_wrapper) {
std::unique_ptr<ServiceWorkerNavigationHandleCore> navigation_handle_core;
- BrowserThread::PostTaskAndReplyWithResult(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraitsAndReplyWithResult(
+ FROM_HERE, {BrowserThread::UI},
base::Bind(
[](ServiceWorkerContextWrapper* wrapper) {
return std::make_unique<ServiceWorkerNavigationHandleCore>(nullptr,
@@ -107,7 +109,8 @@ class ServiceWorkerDispatcherHostTest : public testing::Test {
options.scope = scope;
registration_ =
new ServiceWorkerRegistration(options, 1L, context()->AsWeakPtr());
- version_ = new ServiceWorkerVersion(registration_.get(), script_url, 1L,
+ version_ = new ServiceWorkerVersion(registration_.get(), script_url,
+ blink::mojom::ScriptType::kClassic, 1L,
context()->AsWeakPtr());
std::vector<ServiceWorkerDatabase::ResourceRecord> records;
records.push_back(
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 21e9f3cb7df..015e215aad1 100644
--- a/chromium/content/browser/service_worker/service_worker_fetch_dispatcher.cc
+++ b/chromium/content/browser/service_worker/service_worker_fetch_dispatcher.cc
@@ -11,6 +11,7 @@
#include "base/bind.h"
#include "base/containers/queue.h"
#include "base/feature_list.h"
+#include "base/task/post_task.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
#include "content/browser/devtools/service_worker_devtools_agent_host.h"
@@ -26,6 +27,7 @@
#include "content/browser/url_loader_factory_getter.h"
#include "content/common/service_worker/service_worker.mojom.h"
#include "content/common/service_worker/service_worker_types.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/common/content_features.h"
@@ -182,8 +184,8 @@ class DelegatingURLLoaderClient final : public network::mojom::URLLoaderClient {
if (!worker_id_ || !devtools_enabled_)
return;
while (!devtools_callbacks.empty()) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(std::move(devtools_callbacks.front()), *worker_id_,
devtools_request_id_));
devtools_callbacks.pop();
@@ -323,25 +325,27 @@ class ServiceWorkerFetchDispatcher::ResponseCallback
}
// Implements blink::mojom::ServiceWorkerFetchResponseCallback.
- void OnResponse(blink::mojom::FetchAPIResponsePtr response,
- base::Time dispatch_event_time) override {
+ void OnResponse(
+ blink::mojom::FetchAPIResponsePtr response,
+ blink::mojom::ServiceWorkerFetchEventTimingPtr timing) override {
HandleResponse(fetch_dispatcher_, version_, fetch_event_id_,
std::move(response), nullptr /* body_as_stream */,
- FetchEventResult::kGotResponse, dispatch_event_time);
+ FetchEventResult::kGotResponse, std::move(timing));
}
void OnResponseStream(
blink::mojom::FetchAPIResponsePtr response,
blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
- base::Time dispatch_event_time) override {
+ blink::mojom::ServiceWorkerFetchEventTimingPtr timing) override {
HandleResponse(fetch_dispatcher_, version_, fetch_event_id_,
std::move(response), std::move(body_as_stream),
- FetchEventResult::kGotResponse, dispatch_event_time);
+ FetchEventResult::kGotResponse, std::move(timing));
}
- void OnFallback(base::Time dispatch_event_time) override {
+ void OnFallback(
+ blink::mojom::ServiceWorkerFetchEventTimingPtr timing) override {
HandleResponse(fetch_dispatcher_, version_, fetch_event_id_,
blink::mojom::FetchAPIResponse::New(),
nullptr /* body_as_stream */,
- FetchEventResult::kShouldFallback, dispatch_event_time);
+ FetchEventResult::kShouldFallback, std::move(timing));
}
private:
@@ -354,16 +358,17 @@ class ServiceWorkerFetchDispatcher::ResponseCallback
blink::mojom::FetchAPIResponsePtr response,
blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
FetchEventResult fetch_result,
- base::Time dispatch_event_time) {
+ blink::mojom::ServiceWorkerFetchEventTimingPtr timing) {
if (!version->FinishRequest(fetch_event_id.value(),
fetch_result == FetchEventResult::kGotResponse,
- dispatch_event_time))
+ timing->dispatch_event_time))
NOTREACHED() << "Should only receive one reply per event";
// |fetch_dispatcher| is null if the URLRequest was killed.
if (!fetch_dispatcher)
return;
fetch_dispatcher->DidFinish(fetch_event_id.value(), fetch_result,
- std::move(response), std::move(body_as_stream));
+ std::move(response), std::move(body_as_stream),
+ std::move(timing));
}
mojo::Binding<blink::mojom::ServiceWorkerFetchResponseCallback> binding_;
@@ -563,24 +568,27 @@ void ServiceWorkerFetchDispatcher::DidFail(
blink::ServiceWorkerStatusCode status) {
DCHECK_NE(blink::ServiceWorkerStatusCode::kOk, status);
Complete(status, FetchEventResult::kShouldFallback,
- blink::mojom::FetchAPIResponse::New(), nullptr /* body_as_stream */);
+ blink::mojom::FetchAPIResponse::New(), nullptr /* body_as_stream */,
+ nullptr /* timing */);
}
void ServiceWorkerFetchDispatcher::DidFinish(
int request_id,
FetchEventResult fetch_result,
blink::mojom::FetchAPIResponsePtr response,
- blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream) {
+ blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
+ blink::mojom::ServiceWorkerFetchEventTimingPtr timing) {
net_log_.EndEvent(net::NetLogEventType::SERVICE_WORKER_FETCH_EVENT);
Complete(blink::ServiceWorkerStatusCode::kOk, fetch_result,
- std::move(response), std::move(body_as_stream));
+ std::move(response), std::move(body_as_stream), std::move(timing));
}
void ServiceWorkerFetchDispatcher::Complete(
blink::ServiceWorkerStatusCode status,
FetchEventResult fetch_result,
blink::mojom::FetchAPIResponsePtr response,
- blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream) {
+ blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
+ blink::mojom::ServiceWorkerFetchEventTimingPtr timing) {
DCHECK(fetch_callback_);
did_complete_ = true;
@@ -590,7 +598,7 @@ void ServiceWorkerFetchDispatcher::Complete(
std::move(fetch_callback_)
.Run(status, fetch_result, std::move(response), std::move(body_as_stream),
- version_);
+ std::move(timing), version_);
}
// Non-S13nServiceWorker
@@ -752,7 +760,7 @@ void ServiceWorkerFetchDispatcher::OnFetchEventFinished(
int event_finish_id,
scoped_refptr<URLLoaderAssets> url_loader_assets,
blink::mojom::ServiceWorkerEventStatus status,
- base::Time dispatch_event_time) {
+ base::TimeTicks dispatch_event_time) {
version->FinishRequest(
event_finish_id,
status != blink::mojom::ServiceWorkerEventStatus::ABORTED,
diff --git a/chromium/content/browser/service_worker/service_worker_fetch_dispatcher.h b/chromium/content/browser/service_worker/service_worker_fetch_dispatcher.h
index c8024ab6147..319cf6e6f70 100644
--- a/chromium/content/browser/service_worker/service_worker_fetch_dispatcher.h
+++ b/chromium/content/browser/service_worker/service_worker_fetch_dispatcher.h
@@ -51,6 +51,7 @@ class CONTENT_EXPORT ServiceWorkerFetchDispatcher {
FetchEventResult,
blink::mojom::FetchAPIResponsePtr,
blink::mojom::ServiceWorkerStreamHandlePtr,
+ blink::mojom::ServiceWorkerFetchEventTimingPtr,
scoped_refptr<ServiceWorkerVersion>)>;
// |request_body_*| and |client_id| are used in non-S13nServiceWorker only.
@@ -98,11 +99,13 @@ class CONTENT_EXPORT ServiceWorkerFetchDispatcher {
void DidFinish(int request_id,
FetchEventResult fetch_result,
blink::mojom::FetchAPIResponsePtr response,
- blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream);
+ blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
+ blink::mojom::ServiceWorkerFetchEventTimingPtr timing);
void Complete(blink::ServiceWorkerStatusCode status,
FetchEventResult fetch_result,
blink::mojom::FetchAPIResponsePtr response,
- blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream);
+ blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
+ blink::mojom::ServiceWorkerFetchEventTimingPtr timing);
// The fetch event stays open until all respondWith() and waitUntil() promises
// are settled. This function is called once the renderer signals that
@@ -113,7 +116,7 @@ class CONTENT_EXPORT ServiceWorkerFetchDispatcher {
int event_finish_id,
scoped_refptr<URLLoaderAssets> url_loader_assets,
blink::mojom::ServiceWorkerEventStatus status,
- base::Time dispatch_event_time);
+ base::TimeTicks dispatch_event_time);
ServiceWorkerMetrics::EventType GetEventType() const;
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 8c42abbd0ae..3b8c5c2cba2 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
@@ -11,6 +11,7 @@
#include "content/browser/service_worker/service_worker_metrics.h"
#include "net/http/http_response_headers.h"
#include "services/network/public/cpp/net_adapters.h"
+#include "third_party/blink/public/common/blob/blob_utils.h"
namespace content {
@@ -114,29 +115,43 @@ void ServiceWorkerInstalledScriptReader::OnReadInfoComplete(
DCHECK_GE(result, 0);
mojo::ScopedDataPipeConsumerHandle meta_data_consumer;
- mojo::ScopedDataPipeConsumerHandle body_consumer;
DCHECK_GE(http_info->response_data_size, 0);
uint64_t body_size = http_info->response_data_size;
uint64_t meta_data_size = 0;
- if (mojo::CreateDataPipe(nullptr, &body_handle_, &body_consumer) !=
- MOJO_RESULT_OK) {
+
+ MojoCreateDataPipeOptions options;
+ options.struct_size = sizeof(MojoCreateDataPipeOptions);
+ options.flags = MOJO_CREATE_DATA_PIPE_FLAG_NONE;
+ options.element_num_bytes = 1;
+ options.capacity_num_bytes = blink::BlobUtils::GetDataPipeCapacity(body_size);
+
+ mojo::ScopedDataPipeConsumerHandle body_consumer_handle;
+ MojoResult rv =
+ mojo::CreateDataPipe(&options, &body_handle_, &body_consumer_handle);
+ if (rv != MOJO_RESULT_OK) {
CompleteSendIfNeeded(FinishedReason::kCreateDataPipeError);
return;
}
+
// Start sending meta data (V8 code cache data).
if (http_info->http_info->metadata) {
- mojo::ScopedDataPipeProducerHandle meta_data_producer;
- if (mojo::CreateDataPipe(nullptr, &meta_data_producer,
- &meta_data_consumer) != MOJO_RESULT_OK) {
+ DCHECK_GE(http_info->http_info->metadata->size(), 0);
+ meta_data_size = http_info->http_info->metadata->size();
+
+ mojo::ScopedDataPipeProducerHandle meta_producer_handle;
+ options.capacity_num_bytes =
+ blink::BlobUtils::GetDataPipeCapacity(meta_data_size);
+ rv = mojo::CreateDataPipe(&options, &meta_producer_handle,
+ &meta_data_consumer);
+ if (rv != MOJO_RESULT_OK) {
CompleteSendIfNeeded(FinishedReason::kCreateDataPipeError);
return;
}
+
meta_data_sender_ = std::make_unique<MetaDataSender>(
- http_info->http_info->metadata, std::move(meta_data_producer));
+ http_info->http_info->metadata, std::move(meta_producer_handle));
meta_data_sender_->Start(base::BindOnce(
&ServiceWorkerInstalledScriptReader::OnMetaDataSent, AsWeakPtr()));
- DCHECK_GE(http_info->http_info->metadata->size(), 0);
- meta_data_size = http_info->http_info->metadata->size();
}
// Start sending body.
@@ -168,7 +183,7 @@ void ServiceWorkerInstalledScriptReader::OnReadInfoComplete(
}
client_->OnStarted(charset, std::move(header_strings),
- std::move(body_consumer), body_size,
+ std::move(body_consumer_handle), body_size,
std::move(meta_data_consumer), meta_data_size);
client_->OnHttpInfoRead(http_info);
}
@@ -181,6 +196,9 @@ void ServiceWorkerInstalledScriptReader::OnWritableBody(MojoResult) {
uint32_t num_bytes = 0;
MojoResult rv = network::NetToMojoPendingBuffer::BeginWrite(
&body_handle_, &body_pending_write_, &num_bytes);
+
+ num_bytes = std::min(num_bytes, blink::BlobUtils::GetDataPipeChunkSize());
+
switch (rv) {
case MOJO_RESULT_INVALID_ARGUMENT:
case MOJO_RESULT_BUSY:
diff --git a/chromium/content/browser/service_worker/service_worker_installed_scripts_sender_unittest.cc b/chromium/content/browser/service_worker/service_worker_installed_scripts_sender_unittest.cc
index db4c5af12d0..9a11be1b4a5 100644
--- a/chromium/content/browser/service_worker/service_worker_installed_scripts_sender_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_installed_scripts_sender_unittest.cc
@@ -7,11 +7,13 @@
#include "base/optional.h"
#include "base/run_loop.h"
#include "base/stl_util.h"
+#include "base/task/post_task.h"
#include "base/test/metrics/histogram_tester.h"
#include "content/browser/service_worker/embedded_worker_test_helper.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_disk_cache.h"
#include "content/browser/service_worker/service_worker_test_utils.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "net/base/io_buffer.h"
@@ -40,8 +42,8 @@ void ReadDataPipeInternal(mojo::DataPipeConsumerHandle handle,
std::move(quit_closure).Run();
return;
case MOJO_RESULT_SHOULD_WAIT:
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&ReadDataPipeInternal, handle, result,
std::move(quit_closure)));
return;
@@ -182,6 +184,7 @@ class ServiceWorkerInstalledScriptsSenderTest : public testing::Test {
version_ = base::MakeRefCounted<ServiceWorkerVersion>(
registration_.get(),
GURL("http://www.example.com/test/service_worker.js"),
+ blink::mojom::ScriptType::kClassic,
context()->storage()->NewVersionId(), context()->AsWeakPtr());
version_->set_fetch_handler_existence(
ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
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 3af388b83b0..926a0559406 100644
--- a/chromium/content/browser/service_worker/service_worker_internals_ui.cc
+++ b/chromium/content/browser/service_worker/service_worker_internals_ui.cc
@@ -13,6 +13,7 @@
#include "base/bind.h"
#include "base/strings/string_number_conversions.h"
+#include "base/task/post_task.h"
#include "base/values.h"
#include "content/browser/devtools/devtools_agent_host_impl.h"
#include "content/browser/devtools/service_worker_devtools_agent_host.h"
@@ -24,6 +25,7 @@
#include "content/browser/service_worker/service_worker_version.h"
#include "content/grit/content_resources.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/storage_partition.h"
@@ -52,9 +54,9 @@ void OperationCompleteCallback(WeakPtr<ServiceWorkerInternalsUI> internals,
int callback_id,
blink::ServiceWorkerStatusCode status) {
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(OperationCompleteCallback, internals,
- callback_id, status));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(OperationCompleteCallback,
+ internals, callback_id, status));
return;
}
DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -155,10 +157,7 @@ void UpdateVersionInfo(const ServiceWorkerVersionInfo& version,
std::unique_ptr<ListValue> GetRegistrationListValue(
const std::vector<ServiceWorkerRegistrationInfo>& registrations) {
auto result = std::make_unique<ListValue>();
- for (std::vector<ServiceWorkerRegistrationInfo>::const_iterator it =
- registrations.begin();
- it != registrations.end();
- ++it) {
+ for (auto it = registrations.begin(); it != registrations.end(); ++it) {
const ServiceWorkerRegistrationInfo& registration = *it;
auto registration_info = std::make_unique<DictionaryValue>();
registration_info->SetString("scope", registration.pattern.spec());
@@ -192,10 +191,7 @@ std::unique_ptr<ListValue> GetRegistrationListValue(
std::unique_ptr<ListValue> GetVersionListValue(
const std::vector<ServiceWorkerVersionInfo>& versions) {
auto result = std::make_unique<ListValue>();
- for (std::vector<ServiceWorkerVersionInfo>::const_iterator it =
- versions.begin();
- it != versions.end();
- ++it) {
+ for (auto it = versions.begin(); it != versions.end(); ++it) {
auto info = std::make_unique<DictionaryValue>();
UpdateVersionInfo(*it, info.get());
result->Append(std::move(info));
@@ -209,8 +205,8 @@ void DidGetStoredRegistrationsOnIOThread(
blink::ServiceWorkerStatusCode status,
const std::vector<ServiceWorkerRegistrationInfo>& stored_registrations) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(callback, context->GetAllLiveRegistrationInfo(),
context->GetAllLiveVersionInfo(), stored_registrations));
}
@@ -422,8 +418,8 @@ void ServiceWorkerInternalsUI::AddContextFromStoragePartition(
std::move(new_observer);
}
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
GetRegistrationsOnIOThread, context,
base::Bind(DidGetRegistrations, AsWeakPtr(), partition_id,
@@ -567,8 +563,8 @@ void ServiceWorkerInternalsUI::StopWorkerWithId(
int64_t version_id,
StatusCallback callback) {
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&ServiceWorkerInternalsUI::StopWorkerWithId,
base::Unretained(this), context, version_id,
std::move(callback)));
@@ -593,8 +589,8 @@ void ServiceWorkerInternalsUI::UnregisterWithScope(
const GURL& scope,
ServiceWorkerInternalsUI::StatusCallback callback) const {
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&ServiceWorkerInternalsUI::UnregisterWithScope,
base::Unretained(this), context, scope,
std::move(callback)));
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 9de6ec76b1f..5ff941b5a30 100644
--- a/chromium/content/browser/service_worker/service_worker_job_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_job_unittest.cc
@@ -33,6 +33,7 @@
#include "net/base/test_completion_callback.h"
#include "net/http/http_response_headers.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/service_worker/service_worker_utils.h"
#include "third_party/blink/public/mojom/service_worker/service_worker.mojom.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_object.mojom.h"
@@ -550,7 +551,8 @@ TEST_F(ServiceWorkerJobTest, ParallelRegNewScript) {
job_coordinator()->Register(
script_url1,
blink::mojom::ServiceWorkerRegistrationOptions(
- pattern, blink::mojom::ServiceWorkerUpdateViaCache::kNone),
+ pattern, blink::mojom::ScriptType::kClassic,
+ blink::mojom::ServiceWorkerUpdateViaCache::kNone),
SaveRegistration(blink::ServiceWorkerStatusCode::kOk,
&registration1_called, &registration1));
@@ -560,7 +562,8 @@ TEST_F(ServiceWorkerJobTest, ParallelRegNewScript) {
job_coordinator()->Register(
script_url2,
blink::mojom::ServiceWorkerRegistrationOptions(
- pattern, blink::mojom::ServiceWorkerUpdateViaCache::kAll),
+ pattern, blink::mojom::ScriptType::kClassic,
+ blink::mojom::ServiceWorkerUpdateViaCache::kAll),
SaveRegistration(blink::ServiceWorkerStatusCode::kOk,
&registration2_called, &registration2));
@@ -764,7 +767,8 @@ TEST_F(ServiceWorkerJobTest, UnregisterWaitingSetsRedundant) {
// Manually create the waiting worker since there is no way to become a
// waiting worker until Update is implemented.
scoped_refptr<ServiceWorkerVersion> version = new ServiceWorkerVersion(
- registration.get(), script_url, 1L, helper_->context()->AsWeakPtr());
+ registration.get(), script_url, blink::mojom::ScriptType::kClassic, 1L,
+ helper_->context()->AsWeakPtr());
base::Optional<blink::ServiceWorkerStatusCode> status;
version->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
CreateReceiverOnCurrentThread(&status));
@@ -884,7 +888,8 @@ void WriteResponse(ServiceWorkerStorage* storage,
void WriteStringResponse(ServiceWorkerStorage* storage,
int64_t id,
const std::string& body) {
- scoped_refptr<IOBuffer> body_buffer(new WrappedIOBuffer(body.data()));
+ scoped_refptr<IOBuffer> body_buffer =
+ base::MakeRefCounted<WrappedIOBuffer>(body.data());
const char kHttpHeaders[] = "HTTP/1.0 200 HONKYDORY\0\0";
std::string headers(kHttpHeaders, arraysize(kHttpHeaders));
WriteResponse(storage, id, headers, body_buffer.get(), body.length());
@@ -896,7 +901,7 @@ class UpdateJobTestHelper : public EmbeddedWorkerTestHelper,
public:
struct AttributeChangeLogEntry {
int64_t registration_id;
- ChangedVersionAttributesMask mask;
+ blink::mojom::ChangedServiceWorkerObjectsMaskPtr mask;
ServiceWorkerRegistrationInfo info;
};
@@ -905,7 +910,8 @@ class UpdateJobTestHelper : public EmbeddedWorkerTestHelper,
ServiceWorkerVersion::Status status;
};
- UpdateJobTestHelper() : EmbeddedWorkerTestHelper(base::FilePath()) {}
+ UpdateJobTestHelper()
+ : EmbeddedWorkerTestHelper(base::FilePath()), weak_factory_(this) {}
~UpdateJobTestHelper() override {
if (observed_registration_.get())
observed_registration_->RemoveListener(this);
@@ -922,6 +928,10 @@ class UpdateJobTestHelper : public EmbeddedWorkerTestHelper,
force_start_worker_failure_ = force_start_worker_failure;
}
+ const base::Optional<bool>& will_be_terminated() const {
+ return will_be_terminated_;
+ }
+
scoped_refptr<ServiceWorkerRegistration> SetupInitialRegistration(
const GURL& test_origin) {
blink::mojom::ServiceWorkerRegistrationOptions options;
@@ -942,6 +952,17 @@ class UpdateJobTestHelper : public EmbeddedWorkerTestHelper,
return registration;
}
+ void RequestTermination(int embedded_worker_id) {
+ GetEmbeddedWorkerInstanceHost(embedded_worker_id)
+ ->RequestTermination(
+ base::BindOnce(&UpdateJobTestHelper::OnRequestedTermination,
+ weak_factory_.GetWeakPtr()));
+ }
+
+ void OnRequestedTermination(bool will_be_terminated) {
+ will_be_terminated_ = will_be_terminated;
+ }
+
// EmbeddedWorkerTestHelper overrides
void OnStartWorker(
int embedded_worker_id,
@@ -1041,13 +1062,13 @@ class UpdateJobTestHelper : public EmbeddedWorkerTestHelper,
// ServiceWorkerRegistration::Listener overrides
void OnVersionAttributesChanged(
ServiceWorkerRegistration* registration,
- ChangedVersionAttributesMask changed_mask,
+ blink::mojom::ChangedServiceWorkerObjectsMaskPtr changed_mask,
const ServiceWorkerRegistrationInfo& info) override {
AttributeChangeLogEntry entry;
entry.registration_id = registration->id();
- entry.mask = changed_mask;
+ entry.mask = std::move(changed_mask);
entry.info = info;
- attribute_change_log_.push_back(entry);
+ attribute_change_log_.push_back(std::move(entry));
}
void OnRegistrationFailed(ServiceWorkerRegistration* registration) override {
@@ -1063,7 +1084,7 @@ class UpdateJobTestHelper : public EmbeddedWorkerTestHelper,
StateChangeLogEntry entry;
entry.version_id = version->version_id();
entry.status = version->status();
- state_change_log_.push_back(entry);
+ state_change_log_.push_back(std::move(entry));
}
scoped_refptr<ServiceWorkerRegistration> observed_registration_;
@@ -1074,6 +1095,9 @@ class UpdateJobTestHelper : public EmbeddedWorkerTestHelper,
std::set<int /* embedded_worker_id */> started_workers_;
bool update_found_ = false;
bool force_start_worker_failure_ = false;
+ base::Optional<bool> will_be_terminated_;
+
+ base::WeakPtrFactory<UpdateJobTestHelper> weak_factory_;
};
// Helper class for update tests that evicts the active version when the update
@@ -1231,39 +1255,47 @@ TEST_F(ServiceWorkerJobTest, Update_NewVersion) {
EXPECT_FALSE(registration->waiting_version());
ASSERT_EQ(3u, update_helper->attribute_change_log_.size());
- UpdateJobTestHelper::AttributeChangeLogEntry entry;
- entry = update_helper->attribute_change_log_[0];
- EXPECT_TRUE(entry.mask.installing_changed());
- EXPECT_FALSE(entry.mask.waiting_changed());
- EXPECT_FALSE(entry.mask.active_changed());
- EXPECT_NE(entry.info.installing_version.version_id,
- blink::mojom::kInvalidServiceWorkerVersionId);
- EXPECT_EQ(entry.info.waiting_version.version_id,
- blink::mojom::kInvalidServiceWorkerVersionId);
- EXPECT_NE(entry.info.active_version.version_id,
- blink::mojom::kInvalidServiceWorkerVersionId);
-
- entry = update_helper->attribute_change_log_[1];
- EXPECT_TRUE(entry.mask.installing_changed());
- EXPECT_TRUE(entry.mask.waiting_changed());
- EXPECT_FALSE(entry.mask.active_changed());
- EXPECT_EQ(entry.info.installing_version.version_id,
- blink::mojom::kInvalidServiceWorkerVersionId);
- EXPECT_NE(entry.info.waiting_version.version_id,
- blink::mojom::kInvalidServiceWorkerVersionId);
- EXPECT_NE(entry.info.active_version.version_id,
- blink::mojom::kInvalidServiceWorkerVersionId);
-
- entry = update_helper->attribute_change_log_[2];
- EXPECT_FALSE(entry.mask.installing_changed());
- EXPECT_TRUE(entry.mask.waiting_changed());
- EXPECT_TRUE(entry.mask.active_changed());
- EXPECT_EQ(entry.info.installing_version.version_id,
- blink::mojom::kInvalidServiceWorkerVersionId);
- EXPECT_EQ(entry.info.waiting_version.version_id,
- blink::mojom::kInvalidServiceWorkerVersionId);
- EXPECT_NE(entry.info.active_version.version_id,
- blink::mojom::kInvalidServiceWorkerVersionId);
+ {
+ const UpdateJobTestHelper::AttributeChangeLogEntry& entry =
+ update_helper->attribute_change_log_[0];
+ EXPECT_TRUE(entry.mask->installing);
+ EXPECT_FALSE(entry.mask->waiting);
+ EXPECT_FALSE(entry.mask->active);
+ EXPECT_NE(entry.info.installing_version.version_id,
+ blink::mojom::kInvalidServiceWorkerVersionId);
+ EXPECT_EQ(entry.info.waiting_version.version_id,
+ blink::mojom::kInvalidServiceWorkerVersionId);
+ EXPECT_NE(entry.info.active_version.version_id,
+ blink::mojom::kInvalidServiceWorkerVersionId);
+ }
+
+ {
+ const UpdateJobTestHelper::AttributeChangeLogEntry& entry =
+ update_helper->attribute_change_log_[1];
+ EXPECT_TRUE(entry.mask->installing);
+ EXPECT_TRUE(entry.mask->waiting);
+ EXPECT_FALSE(entry.mask->active);
+ EXPECT_EQ(entry.info.installing_version.version_id,
+ blink::mojom::kInvalidServiceWorkerVersionId);
+ EXPECT_NE(entry.info.waiting_version.version_id,
+ blink::mojom::kInvalidServiceWorkerVersionId);
+ EXPECT_NE(entry.info.active_version.version_id,
+ blink::mojom::kInvalidServiceWorkerVersionId);
+ }
+
+ {
+ const UpdateJobTestHelper::AttributeChangeLogEntry& entry =
+ update_helper->attribute_change_log_[2];
+ EXPECT_FALSE(entry.mask->installing);
+ EXPECT_TRUE(entry.mask->waiting);
+ EXPECT_TRUE(entry.mask->active);
+ EXPECT_EQ(entry.info.installing_version.version_id,
+ blink::mojom::kInvalidServiceWorkerVersionId);
+ EXPECT_EQ(entry.info.waiting_version.version_id,
+ blink::mojom::kInvalidServiceWorkerVersionId);
+ EXPECT_NE(entry.info.active_version.version_id,
+ blink::mojom::kInvalidServiceWorkerVersionId);
+ }
// expected version state transitions:
// new.installing, new.installed,
@@ -1314,8 +1346,8 @@ TEST_F(ServiceWorkerJobTest, Update_ScriptUrlChanged) {
// Add a waiting version with a new script.
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());
+ registration.get(), new_script, blink::mojom::ScriptType::kClassic,
+ 2L /* dummy version id */, helper_->context()->AsWeakPtr());
registration->SetWaitingVersion(version);
// Run the update job.
@@ -1612,18 +1644,18 @@ class EventCallbackHelper : public EmbeddedWorkerTestHelper {
void OnInstallEvent(
mojom::ServiceWorker::DispatchInstallEventCallback callback) override {
if (!install_callback_.is_null())
- install_callback_.Run();
+ std::move(install_callback_).Run();
std::move(callback).Run(install_event_result_, has_fetch_handler_,
- base::Time::Now());
+ base::TimeTicks::Now());
}
void OnActivateEvent(
mojom::ServiceWorker::DispatchActivateEventCallback callback) override {
- std::move(callback).Run(activate_event_result_, base::Time::Now());
+ std::move(callback).Run(activate_event_result_, base::TimeTicks::Now());
}
- void set_install_callback(const base::Closure& callback) {
- install_callback_ = callback;
+ void set_install_callback(base::OnceClosure callback) {
+ install_callback_ = std::move(callback);
}
void set_install_event_result(blink::mojom::ServiceWorkerEventStatus result) {
install_event_result_ = result;
@@ -1637,7 +1669,7 @@ class EventCallbackHelper : public EmbeddedWorkerTestHelper {
}
private:
- base::Closure install_callback_;
+ base::OnceClosure install_callback_;
blink::mojom::ServiceWorkerEventStatus install_event_result_;
blink::mojom::ServiceWorkerEventStatus activate_event_result_;
bool has_fetch_handler_ = true;
@@ -1664,8 +1696,8 @@ TEST_F(ServiceWorkerJobTest, RemoveControlleeDuringInstall) {
// Register another script. While installing, old_version loses controllee.
helper->set_install_callback(
- base::BindRepeating(&ServiceWorkerVersion::RemoveControllee, old_version,
- host->client_uuid()));
+ base::BindOnce(&ServiceWorkerVersion::RemoveControllee, old_version,
+ host->client_uuid()));
EXPECT_EQ(registration, RunRegisterJob(script2, options));
EXPECT_FALSE(registration->is_uninstalling());
@@ -1706,8 +1738,8 @@ TEST_F(ServiceWorkerJobTest, RemoveControlleeDuringRejectedInstall) {
// Register another script that fails to install. While installing,
// old_version loses controllee.
helper->set_install_callback(
- base::BindRepeating(&ServiceWorkerVersion::RemoveControllee, old_version,
- host->client_uuid()));
+ base::BindOnce(&ServiceWorkerVersion::RemoveControllee, old_version,
+ host->client_uuid()));
helper->set_install_event_result(
blink::mojom::ServiceWorkerEventStatus::REJECTED);
EXPECT_EQ(registration, RunRegisterJob(script2, options));
@@ -1745,8 +1777,8 @@ TEST_F(ServiceWorkerJobTest, RemoveControlleeDuringInstall_RejectActivate) {
// Register another script that fails to activate. While installing,
// old_version loses controllee.
helper->set_install_callback(
- base::BindRepeating(&ServiceWorkerVersion::RemoveControllee, old_version,
- host->client_uuid()));
+ base::BindOnce(&ServiceWorkerVersion::RemoveControllee, old_version,
+ host->client_uuid()));
helper->set_activate_event_result(
blink::mojom::ServiceWorkerEventStatus::REJECTED);
EXPECT_EQ(registration, RunRegisterJob(script2, options));
@@ -1879,6 +1911,17 @@ TEST_F(ServiceWorkerJobTest, ActivateCancelsOnShutdown) {
// until the runner runs again.
first_version->RemoveControllee(host->client_uuid());
base::RunLoop().RunUntilIdle();
+
+ if (blink::ServiceWorkerUtils::IsServicificationEnabled()) {
+ // S13nServiceWorker: Activating the new version won't happen until
+ // RequestTermination() is called.
+ EXPECT_EQ(first_version.get(), registration->active_version());
+ update_helper->RequestTermination(
+ first_version->embedded_worker()->embedded_worker_id());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(update_helper->will_be_terminated().value());
+ }
+
EXPECT_EQ(new_version.get(), registration->active_version());
EXPECT_EQ(ServiceWorkerVersion::ACTIVATING, new_version->status());
diff --git a/chromium/content/browser/service_worker/service_worker_metrics.cc b/chromium/content/browser/service_worker/service_worker_metrics.cc
index 19d807e0725..ffa5b01803c 100644
--- a/chromium/content/browser/service_worker/service_worker_metrics.cc
+++ b/chromium/content/browser/service_worker/service_worker_metrics.cc
@@ -11,8 +11,10 @@
#include "base/metrics/histogram_macros.h"
#include "base/strings/strcat.h"
#include "base/strings/string_util.h"
+#include "base/task/post_task.h"
#include "base/time/time.h"
#include "content/browser/service_worker/embedded_worker_status.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/common/content_client.h"
@@ -382,8 +384,8 @@ void ServiceWorkerMetrics::CountControlledPageLoad(Site site,
if (ShouldExcludeSiteFromHistogram(site))
return;
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&RecordURLMetricOnUI, "ServiceWorker.ControlledPageUrl",
url));
}
@@ -892,15 +894,6 @@ void ServiceWorkerMetrics::RecordRuntime(base::TimeDelta time) {
kBucketCount);
}
-void ServiceWorkerMetrics::RecordUninstalledScriptImport(const GURL& url) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::BindOnce(&RecordURLMetricOnUI,
- "ServiceWorker.ContextRequestHandlerStatus."
- "UninstalledScriptImport",
- url));
-}
-
void ServiceWorkerMetrics::RecordStartServiceWorkerForNavigationHintResult(
StartServiceWorkerForNavigationHintResult result) {
UMA_HISTOGRAM_ENUMERATION("ServiceWorker.StartForNavigationHint.Result",
diff --git a/chromium/content/browser/service_worker/service_worker_metrics.h b/chromium/content/browser/service_worker/service_worker_metrics.h
index a0898955023..4b64c16b04a 100644
--- a/chromium/content/browser/service_worker/service_worker_metrics.h
+++ b/chromium/content/browser/service_worker/service_worker_metrics.h
@@ -62,8 +62,8 @@ class ServiceWorkerMetrics {
// worker.
kAbortedWithoutDispatchingFetchEvent = 13,
- // The request was not routed because it was cancelled.
- kJobWasCancelled = 14,
+ // The request was not routed because the job was destroyed.
+ kJobWasDestroyed = 14,
kMaxValue = 14,
};
@@ -473,11 +473,6 @@ class ServiceWorkerMetrics {
static void RecordRuntime(base::TimeDelta time);
- // Records when an installed service worker imports a script that was not
- // previously installed.
- // TODO(falken): Remove after this is deprecated. https://crbug.com/737044
- static void RecordUninstalledScriptImport(const GURL& url);
-
// Records the result of starting service worker for a navigation hint.
static void RecordStartServiceWorkerForNavigationHintResult(
StartServiceWorkerForNavigationHintResult result);
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 c27a6b691bd..357d82e02f4 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
@@ -7,12 +7,14 @@
#include <utility>
#include "base/bind.h"
+#include "base/task/post_task.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#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_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/child_process_host.h"
@@ -54,8 +56,8 @@ void ServiceWorkerNavigationHandleCore::DidPreCreateProviderHost(
DCHECK(ServiceWorkerUtils::IsBrowserAssignedProviderId(provider_id));
provider_id_ = provider_id;
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(
&ServiceWorkerNavigationHandle::DidCreateServiceWorkerProviderHost,
ui_handle_, provider_id_));
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 79f9270e1c1..4e0a8c2a299 100644
--- a/chromium/content/browser/service_worker/service_worker_navigation_loader.cc
+++ b/chromium/content/browser/service_worker/service_worker_navigation_loader.cc
@@ -7,16 +7,17 @@
#include <sstream>
#include <utility>
+#include "base/metrics/histogram_macros.h"
#include "base/optional.h"
#include "base/trace_event/trace_event.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_loader_helpers.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/resource_request_info.h"
-#include "content/public/common/content_features.h"
-#include "content/public/common/content_switches.h"
+#include "services/network/public/cpp/features.h"
#include "services/network/public/mojom/fetch_api.mojom.h"
namespace content {
@@ -88,10 +89,12 @@ ServiceWorkerNavigationLoader::ServiceWorkerNavigationLoader(
NavigationLoaderInterceptor::FallbackCallback fallback_callback,
Delegate* delegate,
const network::ResourceRequest& tentative_resource_request,
+ base::WeakPtr<ServiceWorkerProviderHost> provider_host,
scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter)
: loader_callback_(std::move(callback)),
fallback_callback_(std::move(fallback_callback)),
delegate_(delegate),
+ provider_host_(std::move(provider_host)),
url_loader_factory_getter_(std::move(url_loader_factory_getter)),
binding_(this),
weak_factory_(this) {
@@ -124,21 +127,24 @@ void ServiceWorkerNavigationLoader::FallbackToNetwork() {
TRACE_EVENT_WITH_FLOW0(
"ServiceWorker", "ServiceWorkerNavigationLoader::FallbackToNetwork", this,
TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
+ // The URLJobWrapper only calls this if this loader never intercepted the
+ // request. Fallback to network after interception uses |fallback_callback_|
+ // instead.
+ DCHECK_EQ(status_, Status::kNotStarted);
+ DCHECK_EQ(response_type_, ResponseType::NOT_DETERMINED);
response_type_ = ResponseType::FALLBACK_TO_NETWORK;
- status_ = Status::kCompleted;
- // This could be called multiple times in some cases because we simply
- // call this synchronously here and don't wait for a separate async
- // StartRequest cue like what URLRequestJob case does.
- // TODO(kinuko): Make sure this is ok or we need to make this async.
- if (loader_callback_)
- std::move(loader_callback_).Run({});
+ TransitionToStatus(Status::kCompleted);
+ std::move(loader_callback_).Run({});
}
void ServiceWorkerNavigationLoader::ForwardToServiceWorker() {
TRACE_EVENT_WITH_FLOW0(
"ServiceWorker", "ServiceWorkerNavigationLoader::ForwardToServiceWorker",
this, TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
+ DCHECK_EQ(status_, Status::kNotStarted);
+ DCHECK_EQ(response_type_, ResponseType::NOT_DETERMINED);
+
response_type_ = ResponseType::FORWARD_TO_SERVICE_WORKER;
std::move(loader_callback_)
@@ -154,10 +160,6 @@ bool ServiceWorkerNavigationLoader::ShouldForwardToServiceWorker() {
return response_type_ == ResponseType::FORWARD_TO_SERVICE_WORKER;
}
-bool ServiceWorkerNavigationLoader::WasCanceled() const {
- return status_ == Status::kCancelled;
-}
-
void ServiceWorkerNavigationLoader::DetachedFromRequest() {
delegate_ = nullptr;
DeleteIfNeeded();
@@ -173,6 +175,10 @@ void ServiceWorkerNavigationLoader::StartRequest(
network::mojom::URLLoaderRequest request,
network::mojom::URLLoaderClientPtr client) {
resource_request_ = resource_request;
+ if (provider_host_ && provider_host_->fetch_request_window_id()) {
+ resource_request_.fetch_window_id =
+ base::make_optional(provider_host_->fetch_request_window_id());
+ }
DCHECK(delegate_);
DCHECK(!binding_.is_bound());
@@ -184,8 +190,7 @@ void ServiceWorkerNavigationLoader::StartRequest(
url_loader_client_ = std::move(client);
DCHECK_EQ(ResponseType::FORWARD_TO_SERVICE_WORKER, response_type_);
- DCHECK_EQ(Status::kNotStarted, status_);
- status_ = Status::kStarted;
+ TransitionToStatus(Status::kStarted);
TRACE_EVENT_WITH_FLOW0("ServiceWorker",
"ServiceWorkerNavigationLoader::StartRequest", this,
@@ -237,21 +242,21 @@ void ServiceWorkerNavigationLoader::StartRequest(
fetch_dispatcher_->MaybeStartNavigationPreloadWithURLLoader(
resource_request_, url_loader_factory_getter_.get(),
base::DoNothing(/* TODO(crbug/762357): metrics? */));
+
+ // Record worker start time here as |fetch_dispatcher_| will start a service
+ // worker if there is no running service worker.
response_head_.service_worker_start_time = base::TimeTicks::Now();
- response_head_.load_timing.send_start = base::TimeTicks::Now();
- response_head_.load_timing.send_end = base::TimeTicks::Now();
fetch_dispatcher_->Run();
}
void ServiceWorkerNavigationLoader::CommitResponseHeaders() {
- DCHECK_EQ(Status::kStarted, status_);
DCHECK(url_loader_client_.is_bound());
TRACE_EVENT_WITH_FLOW2(
"ServiceWorker", "ServiceWorkerNavigationLoader::CommitResponseHeaders",
this, TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
"response_code", response_head_.headers->response_code(), "status_text",
response_head_.headers->GetStatusText());
- status_ = Status::kSentHeader;
+ TransitionToStatus(Status::kSentHeader);
url_loader_client_->OnReceiveResponse(response_head_);
}
@@ -261,9 +266,10 @@ void ServiceWorkerNavigationLoader::CommitCompleted(int error_code) {
TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
"error_code", net::ErrorToString(error_code));
- DCHECK_LT(status_, Status::kCompleted);
DCHECK(url_loader_client_.is_bound());
- status_ = Status::kCompleted;
+ TransitionToStatus(Status::kCompleted);
+ if (error_code == net::OK)
+ RecordTimingMetrics(true);
// |stream_waiter_| calls this when done.
stream_waiter_.reset();
@@ -281,7 +287,14 @@ void ServiceWorkerNavigationLoader::DidPrepareFetchEvent(
"initial_worker_status",
EmbeddedWorkerInstance::StatusToString(initial_worker_status));
- response_head_.service_worker_ready_time = base::TimeTicks::Now();
+ // At this point a service worker is running and the fetch event is about
+ // to dispatch. Record some load timings.
+ base::TimeTicks now = base::TimeTicks::Now();
+ response_head_.service_worker_ready_time = now;
+ response_head_.load_timing.send_start = now;
+ response_head_.load_timing.send_end = now;
+
+ devtools_attached_ = version->embedded_worker()->devtools_attached();
// Note that we don't record worker preparation time in S13nServiceWorker
// path for now. If we want to measure worker preparation time we can
@@ -299,8 +312,10 @@ void ServiceWorkerNavigationLoader::DidDispatchFetchEvent(
ServiceWorkerFetchDispatcher::FetchEventResult fetch_result,
blink::mojom::FetchAPIResponsePtr response,
blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
+ blink::mojom::ServiceWorkerFetchEventTimingPtr timing,
scoped_refptr<ServiceWorkerVersion> version) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK_EQ(status_, Status::kStarted);
TRACE_EVENT_WITH_FLOW2(
"ServiceWorker", "ServiceWorkerNavigationLoader::DidDispatchFetchEvent",
@@ -323,6 +338,8 @@ void ServiceWorkerNavigationLoader::DidDispatchFetchEvent(
return;
}
+ fetch_event_timing_ = std::move(timing);
+
if (status != blink::ServiceWorkerStatusCode::kOk) {
// Dispatching the event to the service worker failed. Do a last resort
// attempt to load the page via network as if there was no service worker.
@@ -337,6 +354,8 @@ void ServiceWorkerNavigationLoader::DidDispatchFetchEvent(
if (fetch_result ==
ServiceWorkerFetchDispatcher::FetchEventResult::kShouldFallback) {
+ TransitionToStatus(Status::kCompleted);
+ RecordTimingMetrics(false);
// TODO(falken): Propagate the timing info to the renderer somehow, or else
// Navigation Timing etc APIs won't know about service worker.
std::move(fallback_callback_)
@@ -350,6 +369,7 @@ void ServiceWorkerNavigationLoader::DidDispatchFetchEvent(
// A response with status code 0 is Blink telling us to respond with
// network error.
if (response->status_code == 0) {
+ // TODO(falken): Use more specific errors. Or just add ERR_SERVICE_WORKER?
CommitCompleted(net::ERR_FAILED);
return;
}
@@ -362,6 +382,9 @@ void ServiceWorkerNavigationLoader::StartResponse(
blink::mojom::FetchAPIResponsePtr response,
scoped_refptr<ServiceWorkerVersion> version,
blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK_EQ(status_, Status::kStarted);
+
ServiceWorkerLoaderHelpers::SaveResponseInfo(*response, &response_head_);
ServiceWorkerLoaderHelpers::SaveResponseHeaders(
response->status_code, response->status_text, response->headers,
@@ -381,9 +404,8 @@ void ServiceWorkerNavigationLoader::StartResponse(
// Handle a redirect response. ComputeRedirectInfo returns non-null redirect
// info if the given response is a redirect.
base::Optional<net::RedirectInfo> redirect_info =
- ServiceWorkerLoaderHelpers::ComputeRedirectInfo(
- resource_request_, response_head_,
- response_head_.ssl_info->token_binding_negotiated);
+ ServiceWorkerLoaderHelpers::ComputeRedirectInfo(resource_request_,
+ response_head_);
if (redirect_info) {
TRACE_EVENT_WITH_FLOW2(
"ServiceWorker", "ServiceWorkerNavigationLoader::StartResponse", this,
@@ -394,7 +416,7 @@ void ServiceWorkerNavigationLoader::StartResponse(
url_loader_client_->OnReceiveRedirect(*redirect_info, response_head_);
// Our client is the navigation loader, which will start a new URLLoader for
// the redirect rather than calling FollowRedirect(), so we're done here.
- status_ = Status::kCompleted;
+ TransitionToStatus(Status::kCompleted);
return;
}
@@ -421,7 +443,7 @@ void ServiceWorkerNavigationLoader::StartResponse(
body_as_blob_.Bind(std::move(response->blob->blob));
mojo::ScopedDataPipeConsumerHandle data_pipe;
int error = ServiceWorkerLoaderHelpers::ReadBlobResponseBody(
- &body_as_blob_, resource_request_.headers,
+ &body_as_blob_, response->blob->size,
base::BindOnce(&ServiceWorkerNavigationLoader::OnBlobReadingComplete,
weak_factory_.GetWeakPtr()),
&data_pipe);
@@ -478,19 +500,24 @@ void ServiceWorkerNavigationLoader::OnBlobReadingComplete(int net_error) {
}
void ServiceWorkerNavigationLoader::OnConnectionClosed() {
+ TRACE_EVENT_WITH_FLOW0(
+ "ServiceWorker", "ServiceWorkerNavigationLoader::OnConnectionClosed",
+ this, TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
+
+ // The fetch dispatcher or stream waiter may still be running. Don't let them
+ // do callbacks back to this loader, since it is now done with the request.
+ // TODO(falken): Try to move this to CommitCompleted(), since the same
+ // justification applies there too.
weak_factory_.InvalidateWeakPtrs();
fetch_dispatcher_.reset();
stream_waiter_.reset();
binding_.Close();
- // Cancel the request if this loader hasn't yet responded to it.
- if (status_ != Status::kCompleted && status_ != Status::kCancelled) {
- status_ = Status::kCancelled;
- url_loader_client_->OnComplete(
- network::URLLoaderCompletionStatus(net::ERR_ABORTED));
- }
- url_loader_client_.reset();
+ // Respond to the request if it's not yet responded to.
+ if (status_ != Status::kCompleted)
+ CommitCompleted(net::ERR_ABORTED);
+ url_loader_client_.reset();
DeleteIfNeeded();
}
@@ -499,4 +526,101 @@ void ServiceWorkerNavigationLoader::DeleteIfNeeded() {
delete this;
}
+void ServiceWorkerNavigationLoader::RecordTimingMetrics(bool handled) {
+ DCHECK(fetch_event_timing_);
+ DCHECK(!completion_time_.is_null());
+
+ // We only record these metrics for top-level navigation.
+ if (resource_request_.resource_type != RESOURCE_TYPE_MAIN_FRAME)
+ return;
+
+ // |fetch_event_timing_| is recorded in renderer so we can get reasonable
+ // metrics only when TimeTicks are consistent across processes.
+ if (!base::TimeTicks::IsHighResolution() ||
+ !base::TimeTicks::IsConsistentAcrossProcesses())
+ return;
+
+ // Don't record metrics when DevTools is attached to reduce noise.
+ if (devtools_attached_)
+ return;
+
+ // Time between the request is made and the request is routed to this loader.
+ UMA_HISTOGRAM_TIMES(
+ "ServiceWorker.LoadTiming.MainFrame.MainResource."
+ "StartToForwardServiceWorker",
+ response_head_.service_worker_start_time -
+ response_head_.load_timing.request_start);
+
+ // Time spent for service worker startup.
+ UMA_HISTOGRAM_TIMES(
+ "ServiceWorker.LoadTiming.MainFrame.MainResource."
+ "ForwardServiceWorkerToWorkerReady",
+ response_head_.service_worker_ready_time -
+ response_head_.service_worker_start_time);
+
+ // Browser -> Renderer IPC delay.
+ UMA_HISTOGRAM_TIMES(
+ "ServiceWorker.LoadTiming.MainFrame.MainResource."
+ "WorkerReadyToFetchHandlerStart",
+ fetch_event_timing_->dispatch_event_time -
+ response_head_.service_worker_ready_time);
+
+ // Time spent by fetch handlers.
+ UMA_HISTOGRAM_TIMES(
+ "ServiceWorker.LoadTiming.MainFrame.MainResource."
+ "FetchHandlerStartToFetchHandlerEnd",
+ fetch_event_timing_->respond_with_settled_time -
+ fetch_event_timing_->dispatch_event_time);
+
+ if (handled) {
+ // Renderer -> Browser IPC delay.
+ UMA_HISTOGRAM_TIMES(
+ "ServiceWorker.LoadTiming.MainFrame.MainResource."
+ "FetchHandlerEndToResponseReceived",
+ response_head_.load_timing.receive_headers_end -
+ fetch_event_timing_->respond_with_settled_time);
+
+ // Time spent reading response body.
+ UMA_HISTOGRAM_TIMES(
+ "ServiceWorker.LoadTiming.MainFrame.MainResource."
+ "ResponseReceivedToCompleted",
+ completion_time_ - response_head_.load_timing.receive_headers_end);
+ } else {
+ // Renderer -> Browser IPC delay (network fallback case).
+ UMA_HISTOGRAM_TIMES(
+ "ServiceWorker.LoadTiming.MainFrame.MainResource."
+ "FetchHandlerEndToFallbackNetwork",
+ completion_time_ - fetch_event_timing_->respond_with_settled_time);
+ }
+}
+
+void ServiceWorkerNavigationLoader::TransitionToStatus(Status new_status) {
+#if DCHECK_IS_ON()
+ switch (new_status) {
+ case Status::kNotStarted:
+ NOTREACHED();
+ break;
+ case Status::kStarted:
+ DCHECK_EQ(status_, Status::kNotStarted);
+ break;
+ case Status::kSentHeader:
+ DCHECK_EQ(status_, Status::kStarted);
+ break;
+ case Status::kCompleted:
+ // kNotStarted -> kCompleted happens on network fallback before
+ // interception.
+ // kStarted -> kCompleted happens on error or network fallback after
+ // interception.
+ // kSentHeader -> kCompleted happens in the success case or error
+ // while sending the body.
+ DCHECK_NE(status_, Status::kCompleted);
+ break;
+ }
+#endif // DCHECK_IS_ON()
+
+ status_ = new_status;
+ if (new_status == Status::kCompleted)
+ completion_time_ = base::TimeTicks::Now();
+}
+
} // namespace content
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 f31dc270ae8..d2153bc10f1 100644
--- a/chromium/content/browser/service_worker/service_worker_navigation_loader.h
+++ b/chromium/content/browser/service_worker/service_worker_navigation_loader.h
@@ -80,6 +80,7 @@ class CONTENT_EXPORT ServiceWorkerNavigationLoader
NavigationLoaderInterceptor::FallbackCallback fallback_callback,
Delegate* delegate,
const network::ResourceRequest& tentative_resource_request,
+ base::WeakPtr<ServiceWorkerProviderHost> provider_host,
scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter);
~ServiceWorkerNavigationLoader() override;
@@ -89,7 +90,6 @@ class CONTENT_EXPORT ServiceWorkerNavigationLoader
void ForwardToServiceWorker();
bool ShouldFallbackToNetwork();
bool ShouldForwardToServiceWorker();
- bool WasCanceled() const;
// The navigation request that was holding this job is
// going away. Calling this internally calls |DeleteIfNeeded()|
@@ -102,6 +102,18 @@ class CONTENT_EXPORT ServiceWorkerNavigationLoader
private:
class StreamWaiter;
+ enum class Status {
+ kNotStarted,
+ // |binding_| is bound and the fetch event is being dispatched to the
+ // service worker.
+ kStarted,
+ // The response head has been sent to |url_loader_client_|. The response
+ // body is being streamed.
+ kSentHeader,
+ // OnComplete() was called on |url_loader_client_|, or fallback to network
+ // occurred so the request was not handled.
+ kCompleted,
+ };
// For FORWARD_TO_SERVICE_WORKER case.
void StartRequest(const network::ResourceRequest& resource_request,
@@ -114,6 +126,7 @@ class CONTENT_EXPORT ServiceWorkerNavigationLoader
ServiceWorkerFetchDispatcher::FetchEventResult fetch_result,
blink::mojom::FetchAPIResponsePtr response,
blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
+ blink::mojom::ServiceWorkerFetchEventTimingPtr timing,
scoped_refptr<ServiceWorkerVersion> version);
void StartResponse(blink::mojom::FetchAPIResponsePtr response,
@@ -144,6 +157,13 @@ class CONTENT_EXPORT ServiceWorkerNavigationLoader
void ReportDestination(
ServiceWorkerMetrics::MainResourceRequestDestination destination);
+ // Records loading milestones. Called only after ForwardToServiceWorker() is
+ // called and there was no error. |handled| is true when a fetch handler
+ // handled the request (i.e. non network fallback case).
+ void RecordTimingMetrics(bool handled);
+
+ void TransitionToStatus(Status new_status);
+
ResponseType response_type_ = ResponseType::NOT_DETERMINED;
NavigationLoaderInterceptor::LoaderCallback loader_callback_;
NavigationLoaderInterceptor::FallbackCallback fallback_callback_;
@@ -158,6 +178,7 @@ class CONTENT_EXPORT ServiceWorkerNavigationLoader
Delegate* delegate_ = nullptr;
network::ResourceRequest resource_request_;
+ base::WeakPtr<ServiceWorkerProviderHost> provider_host_;
scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter_;
std::unique_ptr<ServiceWorkerFetchDispatcher> fetch_dispatcher_;
std::unique_ptr<StreamWaiter> stream_waiter_;
@@ -167,17 +188,14 @@ class CONTENT_EXPORT ServiceWorkerNavigationLoader
bool did_navigation_preload_ = false;
network::ResourceResponseHead response_head_;
+ bool devtools_attached_ = false;
+ blink::mojom::ServiceWorkerFetchEventTimingPtr fetch_event_timing_;
+ base::TimeTicks completion_time_;
+
// Pointer to the URLLoaderClient (i.e. NavigationURLLoader).
network::mojom::URLLoaderClientPtr url_loader_client_;
mojo::Binding<network::mojom::URLLoader> binding_;
- enum class Status {
- kNotStarted,
- kStarted,
- kSentHeader,
- kCompleted,
- kCancelled
- };
Status status_ = Status::kNotStarted;
base::WeakPtrFactory<ServiceWorkerNavigationLoader> weak_factory_;
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 02010ab2c3e..5a4c5957f6f 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
@@ -4,7 +4,10 @@
#include "content/browser/service_worker/service_worker_navigation_loader.h"
+#include <string>
+#include <utility>
#include "base/run_loop.h"
+#include "base/strings/string_number_conversions.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "content/browser/loader/navigation_loader_interceptor.h"
@@ -51,6 +54,10 @@ blink::mojom::FetchAPIResponsePtr OkResponse(
response->status_text = "OK";
response->response_type = network::mojom::FetchResponseType::kDefault;
response->blob = std::move(blob_body);
+ if (response->blob) {
+ response->headers.emplace("Content-Length",
+ base::NumberToString(response->blob->size));
+ }
return response;
}
@@ -137,10 +144,11 @@ class NavigationPreloadLoaderClient final
response->status_text = response_head_.headers->GetStatusText();
response->response_type = response_head_.response_type;
response_callback_->OnResponseStream(
- std::move(response), std::move(stream_handle), base::Time::Now());
+ std::move(response), std::move(stream_handle),
+ blink::mojom::ServiceWorkerFetchEventTiming::New());
std::move(finish_callback_)
.Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
- base::Time::Now());
+ base::TimeTicks::Now());
stream_callback->OnCompleted();
delete this;
}
@@ -231,10 +239,23 @@ class Helper : public EmbeddedWorkerTestHelper {
void FinishWaitUntil() {
std::move(finish_callback_)
.Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
- base::Time::Now());
+ base::TimeTicks::Now());
base::RunLoop().RunUntilIdle();
}
+ // Tells this helper to wait for FinishRespondWith() to be called before
+ // providing the response to the fetch event.
+ void DeferResponse() { response_mode_ = ResponseMode::kDeferredResponse; }
+ void FinishRespondWith() {
+ response_callback_->OnResponse(
+ OkResponse(nullptr /* blob_body */),
+ blink::mojom::ServiceWorkerFetchEventTiming::New());
+ response_callback_.FlushForTesting();
+ std::move(finish_callback_)
+ .Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
+ base::TimeTicks::Now());
+ }
+
void ReadRequestBody(std::string* out_string) {
ASSERT_TRUE(request_body_);
const std::vector<network::DataElement>* elements =
@@ -246,6 +267,14 @@ class Helper : public EmbeddedWorkerTestHelper {
*out_string = std::string(element.bytes(), element.length());
}
+ void RunUntilFetchEvent() {
+ if (has_received_fetch_event_)
+ return;
+ base::RunLoop run_loop;
+ quit_closure_for_fetch_event_ = run_loop.QuitClosure();
+ run_loop.Run();
+ }
+
protected:
void OnFetchEvent(
int embedded_worker_id,
@@ -258,6 +287,7 @@ class Helper : public EmbeddedWorkerTestHelper {
EXPECT_TRUE(ServiceWorkerUtils::IsMainResourceType(
static_cast<ResourceType>(request.resource_type)));
+ has_received_fetch_event_ = true;
request_body_ = request.request_body;
switch (response_mode_) {
@@ -265,40 +295,44 @@ class Helper : public EmbeddedWorkerTestHelper {
EmbeddedWorkerTestHelper::OnFetchEvent(
embedded_worker_id, request, std::move(preload_handle),
std::move(response_callback), std::move(finish_callback));
- return;
+ break;
case ResponseMode::kBlob:
- response_callback->OnResponse(OkResponse(std::move(blob_body_)),
- base::Time::Now());
+ response_callback->OnResponse(
+ OkResponse(std::move(blob_body_)),
+ blink::mojom::ServiceWorkerFetchEventTiming::New());
std::move(finish_callback)
.Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
- base::Time::Now());
- return;
+ base::TimeTicks::Now());
+ break;
case ResponseMode::kStream:
- response_callback->OnResponseStream(OkResponse(nullptr /* blob_body */),
- std::move(stream_handle_),
- base::Time::Now());
+ response_callback->OnResponseStream(
+ OkResponse(nullptr /* blob_body */), std::move(stream_handle_),
+ blink::mojom::ServiceWorkerFetchEventTiming::New());
std::move(finish_callback)
.Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
- base::Time::Now());
- return;
+ base::TimeTicks::Now());
+ break;
case ResponseMode::kFallbackResponse:
- response_callback->OnFallback(base::Time::Now());
+ response_callback->OnFallback(
+ blink::mojom::ServiceWorkerFetchEventTiming::New());
std::move(finish_callback)
.Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
- base::Time::Now());
- return;
+ base::TimeTicks::Now());
+ break;
case ResponseMode::kErrorResponse:
- response_callback->OnResponse(ErrorResponse(), base::Time::Now());
+ response_callback->OnResponse(
+ ErrorResponse(),
+ blink::mojom::ServiceWorkerFetchEventTiming::New());
std::move(finish_callback)
.Run(blink::mojom::ServiceWorkerEventStatus::REJECTED,
- base::Time::Now());
- return;
+ base::TimeTicks::Now());
+ break;
case ResponseMode::kNavigationPreloadResponse:
// Deletes itself when done.
new NavigationPreloadLoaderClient(std::move(preload_handle),
std::move(response_callback),
std::move(finish_callback));
- return;
+ break;
case ResponseMode::kFailFetchEventDispatch:
// Simulate failure by stopping the worker before the event finishes.
// This causes ServiceWorkerVersion::StartRequest() to call its error
@@ -313,23 +347,32 @@ class Helper : public EmbeddedWorkerTestHelper {
// callbacks after an unexpected stop.
std::move(finish_callback)
.Run(blink::mojom::ServiceWorkerEventStatus::ABORTED,
- base::Time::Now());
- return;
+ base::TimeTicks::Now());
+ break;
+ case ResponseMode::kDeferredResponse:
+ finish_callback_ = std::move(finish_callback);
+ response_callback_ = std::move(response_callback);
+ // Now the caller must call FinishRespondWith() to finish the event.
+ break;
case ResponseMode::kEarlyResponse:
finish_callback_ = std::move(finish_callback);
- response_callback->OnResponse(OkResponse(nullptr /* blob_body */),
- base::Time::Now());
+ response_callback->OnResponse(
+ OkResponse(nullptr /* blob_body */),
+ blink::mojom::ServiceWorkerFetchEventTiming::New());
// Now the caller must call FinishWaitUntil() to finish the event.
- return;
+ break;
case ResponseMode::kRedirect:
- response_callback->OnResponse(RedirectResponse(redirected_url_.spec()),
- base::Time::Now());
+ response_callback->OnResponse(
+ RedirectResponse(redirected_url_.spec()),
+ blink::mojom::ServiceWorkerFetchEventTiming::New());
std::move(finish_callback)
.Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
- base::Time::Now());
- return;
+ base::TimeTicks::Now());
+ break;
}
- NOTREACHED();
+
+ if (quit_closure_for_fetch_event_)
+ std::move(quit_closure_for_fetch_event_).Run();
}
private:
@@ -341,6 +384,7 @@ class Helper : public EmbeddedWorkerTestHelper {
kErrorResponse,
kNavigationPreloadResponse,
kFailFetchEventDispatch,
+ kDeferredResponse,
kEarlyResponse,
kRedirect
};
@@ -354,12 +398,15 @@ class Helper : public EmbeddedWorkerTestHelper {
// For ResponseMode::kStream.
blink::mojom::ServiceWorkerStreamHandlePtr stream_handle_;
- // For ResponseMode::kEarlyResponse.
+ // For ResponseMode::kEarlyResponse and kDeferredResponse.
mojom::ServiceWorker::DispatchFetchEventCallback finish_callback_;
+ blink::mojom::ServiceWorkerFetchResponseCallbackPtr response_callback_;
// For ResponseMode::kRedirect.
GURL redirected_url_;
+ bool has_received_fetch_event_ = false;
+ base::OnceClosure quit_closure_for_fetch_event_;
DISALLOW_COPY_AND_ASSIGN(Helper);
};
@@ -415,7 +462,8 @@ class ServiceWorkerNavigationLoaderTest
helper_->context()->AsWeakPtr());
version_ = new ServiceWorkerVersion(
registration_.get(), GURL("https://example.com/service_worker.js"),
- storage()->NewVersionId(), helper_->context()->AsWeakPtr());
+ blink::mojom::ScriptType::kClassic, storage()->NewVersionId(),
+ helper_->context()->AsWeakPtr());
std::vector<ServiceWorkerDatabase::ResourceRecord> records;
records.push_back(WriteToDiskCacheSync(
storage(), version_->script_url(), storage()->NewResourceId(),
@@ -456,7 +504,7 @@ class ServiceWorkerNavigationLoaderTest
base::BindOnce(&ReceiveRequestHandler, &handler),
base::BindOnce(&ServiceWorkerNavigationLoaderTest::Fallback,
base::Unretained(this)),
- this, *request,
+ this, *request, nullptr,
base::WrapRefCounted<URLLoaderFactoryGetter>(
helper_->context()->loader_factory_getter()));
loader_->ForwardToServiceWorker();
@@ -539,6 +587,10 @@ class ServiceWorkerNavigationLoaderTest
void MainResourceLoadFailed() override {
was_main_resource_load_failed_called_ = true;
}
+
+ bool HasWorkInBrowser(ServiceWorkerVersion* version) const {
+ return version->HasWorkInBrowser();
+ }
// --------------------------------------------------------------------------
TestBrowserThreadBundle thread_bundle_;
@@ -573,6 +625,10 @@ TEST_F(ServiceWorkerNavigationLoaderTest, Basic) {
histogram_tester.ExpectUniqueSample(kHistogramMainResourceFetchEvent,
blink::ServiceWorkerStatusCode::kOk, 1);
+ histogram_tester.ExpectTotalCount(
+ "ServiceWorker.LoadTiming.MainFrame.MainResource."
+ "ResponseReceivedToCompleted",
+ 1);
}
TEST_F(ServiceWorkerNavigationLoaderTest, NoActiveWorker) {
@@ -590,6 +646,10 @@ TEST_F(ServiceWorkerNavigationLoaderTest, NoActiveWorker) {
// No fetch event was dispatched.
histogram_tester.ExpectTotalCount(kHistogramMainResourceFetchEvent, 0);
+ histogram_tester.ExpectTotalCount(
+ "ServiceWorker.LoadTiming.MainFrame.MainResource."
+ "StartToForwardServiceWorker",
+ 0);
}
// Test that the request body is passed to the fetch event.
@@ -615,6 +675,8 @@ TEST_F(ServiceWorkerNavigationLoaderTest, RequestBody) {
}
TEST_F(ServiceWorkerNavigationLoaderTest, BlobResponse) {
+ base::HistogramTester histogram_tester;
+
// Construct the blob to respond with.
const std::string kResponseBody = "Here is sample text for the blob.";
auto blob_data = std::make_unique<storage::BlobDataBuilder>("blob-id:myblob");
@@ -637,6 +699,7 @@ TEST_F(ServiceWorkerNavigationLoaderTest, BlobResponse) {
const network::ResourceResponseHead& info = client_.response_head();
EXPECT_EQ(200, info.headers->response_code());
ExpectResponseInfo(info, *CreateResponseInfoFromServiceWorker());
+ EXPECT_EQ(33, info.content_length);
// Test the body.
std::string body;
@@ -645,10 +708,18 @@ TEST_F(ServiceWorkerNavigationLoaderTest, BlobResponse) {
mojo::BlockingCopyToString(client_.response_body_release(), &body));
EXPECT_EQ(kResponseBody, body);
EXPECT_EQ(net::OK, client_.completion_status().error_code);
+
+ // Test histogram of reading body.
+ histogram_tester.ExpectTotalCount(
+ "ServiceWorker.LoadTiming.MainFrame.MainResource."
+ "ResponseReceivedToCompleted",
+ 1);
}
// Tell the helper to respond with a non-existent Blob.
TEST_F(ServiceWorkerNavigationLoaderTest, BrokenBlobResponse) {
+ base::HistogramTester histogram_tester;
+
const std::string kBrokenUUID = "broken_uuid";
// Create the broken blob.
@@ -675,9 +746,21 @@ TEST_F(ServiceWorkerNavigationLoaderTest, BrokenBlobResponse) {
// the body.
client_.RunUntilComplete();
EXPECT_EQ(net::ERR_OUT_OF_MEMORY, client_.completion_status().error_code);
+
+ // Timing histograms shouldn't be recorded on broken response.
+ histogram_tester.ExpectTotalCount(
+ "ServiceWorker.LoadTiming.MainFrame.MainResource."
+ "StartToForwardServiceWorker",
+ 0);
+ histogram_tester.ExpectTotalCount(
+ "ServiceWorker.LoadTiming.MainFrame.MainResource."
+ "ResponseReceivedToCompleted",
+ 0);
}
TEST_F(ServiceWorkerNavigationLoaderTest, StreamResponse) {
+ base::HistogramTester histogram_tester;
+
// Construct the Stream to respond with.
const char kResponseBody[] = "Here is sample text for the Stream.";
blink::mojom::ServiceWorkerStreamCallbackPtr stream_callback;
@@ -694,7 +777,7 @@ TEST_F(ServiceWorkerNavigationLoaderTest, StreamResponse) {
EXPECT_EQ(200, info.headers->response_code());
ExpectResponseInfo(info, *CreateResponseInfoFromServiceWorker());
- EXPECT_TRUE(version_->HasWorkInBrowser());
+ EXPECT_FALSE(version_->HasNoWork());
// Write the body stream.
uint32_t written_bytes = sizeof(kResponseBody) - 1;
@@ -714,10 +797,18 @@ TEST_F(ServiceWorkerNavigationLoaderTest, StreamResponse) {
EXPECT_TRUE(
mojo::BlockingCopyToString(client_.response_body_release(), &response));
EXPECT_EQ(kResponseBody, response);
+
+ // Test histogram of reading body.
+ histogram_tester.ExpectTotalCount(
+ "ServiceWorker.LoadTiming.MainFrame.MainResource."
+ "ResponseReceivedToCompleted",
+ 1);
}
// Test when a stream response body is aborted.
TEST_F(ServiceWorkerNavigationLoaderTest, StreamResponse_Abort) {
+ base::HistogramTester histogram_tester;
+
// Construct the Stream to respond with.
const char kResponseBody[] = "Here is sample text for the Stream.";
blink::mojom::ServiceWorkerStreamCallbackPtr stream_callback;
@@ -752,10 +843,22 @@ TEST_F(ServiceWorkerNavigationLoaderTest, StreamResponse_Abort) {
EXPECT_TRUE(
mojo::BlockingCopyToString(client_.response_body_release(), &response));
EXPECT_EQ(kResponseBody, response);
+
+ // Timing histograms shouldn't be recorded on abort.
+ histogram_tester.ExpectTotalCount(
+ "ServiceWorker.LoadTiming.MainFrame.MainResource."
+ "StartToForwardServiceWorker",
+ 0);
+ histogram_tester.ExpectTotalCount(
+ "ServiceWorker.LoadTiming.MainFrame.MainResource."
+ "ResponseReceivedToCompleted",
+ 0);
}
// Test when the loader is cancelled while a stream response is being written.
TEST_F(ServiceWorkerNavigationLoaderTest, StreamResponseAndCancel) {
+ base::HistogramTester histogram_tester;
+
// Construct the Stream to respond with.
const char kResponseBody[] = "Here is sample text for the Stream.";
blink::mojom::ServiceWorkerStreamCallbackPtr stream_callback;
@@ -772,22 +875,21 @@ TEST_F(ServiceWorkerNavigationLoaderTest, StreamResponseAndCancel) {
EXPECT_EQ(200, info.headers->response_code());
ExpectResponseInfo(info, *CreateResponseInfoFromServiceWorker());
- // Start writing the body stream, then cancel the loader before finishing.
+ // Start writing the body stream, then break the Mojo connection to the loader
+ // before finishing.
uint32_t written_bytes = sizeof(kResponseBody) - 1;
MojoResult mojo_result = data_pipe.producer_handle->WriteData(
kResponseBody, &written_bytes, MOJO_WRITE_DATA_FLAG_NONE);
ASSERT_EQ(MOJO_RESULT_OK, mojo_result);
EXPECT_EQ(sizeof(kResponseBody) - 1, written_bytes);
EXPECT_TRUE(data_pipe.producer_handle.is_valid());
- EXPECT_FALSE(loader_->WasCanceled());
- EXPECT_TRUE(version_->HasWorkInBrowser());
+ EXPECT_TRUE(HasWorkInBrowser(version_.get()));
loader_ptr_.reset();
base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(loader_->WasCanceled());
- EXPECT_FALSE(version_->HasWorkInBrowser());
+ EXPECT_FALSE(HasWorkInBrowser(version_.get()));
// Although ServiceWorkerNavigationLoader resets its URLLoaderClient pointer
- // in Cancel(), the URLLoaderClient still exists. In this test, it is
+ // on connection error, the URLLoaderClient still exists. In this test, it is
// |client_| which owns the data pipe, so it's still valid to write data to
// it.
mojo_result = data_pipe.producer_handle->WriteData(
@@ -798,6 +900,16 @@ TEST_F(ServiceWorkerNavigationLoaderTest, StreamResponseAndCancel) {
client_.RunUntilComplete();
EXPECT_FALSE(data_pipe.consumer_handle.is_valid());
EXPECT_EQ(net::ERR_ABORTED, client_.completion_status().error_code);
+
+ // Timing histograms shouldn't be recorded on cancel.
+ histogram_tester.ExpectTotalCount(
+ "ServiceWorker.LoadTiming.MainFrame.MainResource."
+ "StartToForwardServiceWorker",
+ 0);
+ histogram_tester.ExpectTotalCount(
+ "ServiceWorker.LoadTiming.MainFrame.MainResource."
+ "ResponseReceivedToCompleted",
+ 0);
}
// Test when the service worker responds with network fallback.
@@ -820,6 +932,12 @@ TEST_F(ServiceWorkerNavigationLoaderTest, FallbackResponse) {
EXPECT_FALSE(was_main_resource_load_failed_called_);
histogram_tester.ExpectUniqueSample(kHistogramMainResourceFetchEvent,
blink::ServiceWorkerStatusCode::kOk, 1);
+
+ // Test histogram of network fallback.
+ histogram_tester.ExpectTotalCount(
+ "ServiceWorker.LoadTiming.MainFrame.MainResource."
+ "FetchHandlerEndToFallbackNetwork",
+ 1);
}
// Test when the service worker rejects the FetchEvent.
@@ -837,6 +955,11 @@ TEST_F(ServiceWorkerNavigationLoaderTest, ErrorResponse) {
// Event dispatch still succeeded.
histogram_tester.ExpectUniqueSample(kHistogramMainResourceFetchEvent,
blink::ServiceWorkerStatusCode::kOk, 1);
+ // Timing UMAs shouldn't be recorded when we receive an error response.
+ histogram_tester.ExpectTotalCount(
+ "ServiceWorker.LoadTiming.MainFrame.MainResource."
+ "StartToForwardServiceWorker",
+ 0);
}
// Test when dispatching the fetch event to the service worker failed.
@@ -856,6 +979,11 @@ TEST_F(ServiceWorkerNavigationLoaderTest, FailFetchDispatch) {
histogram_tester.ExpectUniqueSample(
kHistogramMainResourceFetchEvent,
blink::ServiceWorkerStatusCode::kErrorFailed, 1);
+ // Timing UMAs shouldn't be recorded when failed to dispatch an event.
+ histogram_tester.ExpectTotalCount(
+ "ServiceWorker.LoadTiming.MainFrame.MainResource."
+ "StartToForwardServiceWorker",
+ 0);
}
// Test when the respondWith() promise resolves before the waitUntil() promise
@@ -874,9 +1002,9 @@ TEST_F(ServiceWorkerNavigationLoaderTest, EarlyResponse) {
// Although the response was already received, the event remains outstanding
// until waitUntil() resolves.
- EXPECT_TRUE(version_->HasWorkInBrowser());
+ EXPECT_TRUE(HasWorkInBrowser(version_.get()));
helper_->FinishWaitUntil();
- EXPECT_FALSE(version_->HasWorkInBrowser());
+ EXPECT_FALSE(HasWorkInBrowser(version_.get()));
}
// Test asking the loader to fallback to network. In production code, this
@@ -898,7 +1026,7 @@ TEST_F(ServiceWorkerNavigationLoaderTest, FallbackToNetwork) {
base::BindOnce(&ReceiveRequestHandler, &handler),
base::BindOnce(&ServiceWorkerNavigationLoaderTest::Fallback,
base::Unretained(this)),
- this, request,
+ this, request, nullptr,
base::WrapRefCounted<URLLoaderFactoryGetter>(
helper_->context()->loader_factory_getter()));
// Ask the loader to fallback to network. In production code,
@@ -909,6 +1037,10 @@ TEST_F(ServiceWorkerNavigationLoaderTest, FallbackToNetwork) {
// No fetch event was dispatched.
histogram_tester.ExpectTotalCount(kHistogramMainResourceFetchEvent, 0);
+ histogram_tester.ExpectTotalCount(
+ "ServiceWorker.LoadTiming.MainFrame.MainResource."
+ "StartToForwardServiceWorker",
+ 0);
}
// Test responding to the fetch event with the navigation preload response.
@@ -998,7 +1130,7 @@ TEST_F(ServiceWorkerNavigationLoaderTest, LifetimeAfterFallbackToNetwork) {
base::BindOnce(&ReceiveRequestHandler, &handler),
base::BindOnce(&ServiceWorkerNavigationLoaderTest::Fallback,
base::Unretained(this)),
- this, request,
+ this, request, nullptr,
base::WrapRefCounted<URLLoaderFactoryGetter>(
helper_->context()->loader_factory_getter()));
base::WeakPtr<ServiceWorkerNavigationLoader> loader_weakptr =
@@ -1015,6 +1147,27 @@ TEST_F(ServiceWorkerNavigationLoaderTest, LifetimeAfterFallbackToNetwork) {
EXPECT_FALSE(loader_weakptr);
}
+TEST_F(ServiceWorkerNavigationLoaderTest, ConnectionErrorDuringFetchEvent) {
+ helper_->DeferResponse();
+ LoaderResult result = StartRequest(CreateRequest());
+ EXPECT_EQ(LoaderResult::kHandledRequest, result);
+
+ // Wait for the fetch event to be dispatched.
+ helper_->RunUntilFetchEvent();
+
+ // Break the Mojo connection. The loader should return an aborted status.
+ loader_ptr_.reset();
+ client_.RunUntilComplete();
+ EXPECT_EQ(net::ERR_ABORTED, client_.completion_status().error_code);
+
+ // The loader is still alive. Finish the fetch event. It shouldn't crash or
+ // call any callbacks on |client_|, which would throw an error.
+ helper_->FinishRespondWith();
+ // There's no event to wait for, so just pump the message loop and the test
+ // passes if there is no error or crash.
+ base::RunLoop().RunUntilIdle();
+}
+
TEST_F(ServiceWorkerNavigationLoaderTest, DetachedDuringFetchEvent) {
LoaderResult result = StartRequest(CreateRequest());
EXPECT_EQ(LoaderResult::kHandledRequest, result);
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 fc38698dff6..71e2fea8961 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
@@ -90,6 +90,8 @@ ServiceWorkerNewScriptLoader::ServiceWorkerNewScriptLoader(
// may be used by ServiceWorkerNavigationLoader for navigations handled
// by this service worker.
options |= network::mojom::kURLLoadOptionSendSSLInfoWithResponse;
+
+ resource_request.headers.SetHeader("Service-Worker", "script");
}
// Bypass the browser cache if needed, e.g., updateViaCache demands it or 24
@@ -103,8 +105,6 @@ ServiceWorkerNewScriptLoader::ServiceWorkerNewScriptLoader(
resource_request.load_flags |= net::LOAD_BYPASS_CACHE;
}
- resource_request.headers.SetHeader("Service-Worker", "script");
-
// 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;
@@ -115,7 +115,8 @@ ServiceWorkerNewScriptLoader::ServiceWorkerNewScriptLoader(
}
cache_writer_ = std::make_unique<ServiceWorkerCacheWriter>(
std::move(compare_reader), std::move(copy_reader),
- storage->CreateResponseWriter(cache_resource_id));
+ storage->CreateResponseWriter(cache_resource_id),
+ false /* pause_when_not_identical */);
version_->script_cache_map()->NotifyStartedCaching(request_url_,
cache_resource_id);
@@ -247,6 +248,8 @@ void ServiceWorkerNewScriptLoader::OnReceiveResponse(
version_->SetMainScriptHttpResponseInfo(*response_info);
}
+ network_loader_state_ = NetworkLoaderState::kWaitingForBody;
+
WriteHeaders(
base::MakeRefCounted<HttpResponseInfoIOBuffer>(std::move(response_info)));
@@ -258,11 +261,9 @@ void ServiceWorkerNewScriptLoader::OnReceiveResponse(
network::ResourceResponseHead new_response_head = response_head;
new_response_head.ssl_info.reset();
client_->OnReceiveResponse(new_response_head);
- } else {
- client_->OnReceiveResponse(response_head);
+ return;
}
-
- network_loader_state_ = NetworkLoaderState::kWaitingForBody;
+ client_->OnReceiveResponse(response_head);
}
void ServiceWorkerNewScriptLoader::OnReceiveRedirect(
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 7494702698a..1016c4f6df0 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
@@ -173,7 +173,6 @@ class ServiceWorkerNewScriptLoaderTest : public testing::Test {
"this is an import script response body from the network")));
// Initialize URLLoaderFactory.
- network::mojom::URLLoaderFactoryPtr test_loader_factory;
mock_url_loader_factory_ =
std::make_unique<MockNetworkURLLoaderFactory>(mock_server_.get());
helper_->SetNetworkFactory(mock_url_loader_factory_.get());
@@ -217,8 +216,8 @@ class ServiceWorkerNewScriptLoaderTest : public testing::Test {
// possibly updating if registration has an installed worker.
void SetUpVersion(const GURL& script_url) {
version_ = base::MakeRefCounted<ServiceWorkerVersion>(
- registration_.get(), script_url, context()->storage()->NewVersionId(),
- context()->AsWeakPtr());
+ registration_.get(), script_url, blink::mojom::ScriptType::kClassic,
+ context()->storage()->NewVersionId(), context()->AsWeakPtr());
version_->SetStatus(ServiceWorkerVersion::NEW);
if (registration_->waiting_version() || registration_->active_version())
diff --git a/chromium/content/browser/service_worker/service_worker_object_host.cc b/chromium/content/browser/service_worker/service_worker_object_host.cc
index cd4f6ea5728..9989c75efcb 100644
--- a/chromium/content/browser/service_worker/service_worker_object_host.cc
+++ b/chromium/content/browser/service_worker/service_worker_object_host.cc
@@ -88,7 +88,7 @@ bool PrepareExtendableMessageEventFromClient(
DCHECK(source_client_info && !source_client_info->client_uuid.empty());
(*event)->source_info_for_client = std::move(source_client_info);
// Hide the client url if the client has a unique origin.
- if ((*event)->source_origin.unique())
+ if ((*event)->source_origin.opaque())
(*event)->source_info_for_client->url = GURL();
// Reset |registration->self_update_delay| iff postMessage is coming from a
@@ -130,7 +130,7 @@ bool PrepareExtendableMessageEventFromServiceWorker(
(*event)->source_info_for_service_worker = std::move(source_worker_info);
// Hide the service worker url if the service worker has a unique origin.
- if ((*event)->source_origin.unique())
+ if ((*event)->source_origin.opaque())
(*event)->source_info_for_service_worker->url = GURL();
return true;
}
diff --git a/chromium/content/browser/service_worker/service_worker_object_host_unittest.cc b/chromium/content/browser/service_worker/service_worker_object_host_unittest.cc
index fd1ca22f735..fbcb6c00497 100644
--- a/chromium/content/browser/service_worker/service_worker_object_host_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_object_host_unittest.cc
@@ -56,7 +56,7 @@ class ExtendableMessageEventTestHelper : public EmbeddedWorkerTestHelper {
override {
events_.push_back(std::move(event));
std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
- base::Time::Now());
+ base::TimeTicks::Now());
}
const std::vector<mojom::ExtendableMessageEventPtr>& events() {
@@ -130,10 +130,10 @@ class ServiceWorkerObjectHostTest : public testing::Test {
registration_ = new ServiceWorkerRegistration(
options, helper_->context()->storage()->NewRegistrationId(),
helper_->context()->AsWeakPtr());
- version_ =
- new ServiceWorkerVersion(registration_.get(), script_url,
- helper_->context()->storage()->NewVersionId(),
- helper_->context()->AsWeakPtr());
+ version_ = new ServiceWorkerVersion(
+ registration_.get(), script_url, blink::mojom::ScriptType::kClassic,
+ helper_->context()->storage()->NewVersionId(),
+ helper_->context()->AsWeakPtr());
std::vector<ServiceWorkerDatabase::ResourceRecord> records;
records.push_back(
ServiceWorkerDatabase::ResourceRecord(10, version_->script_url(), 100));
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 1f25d3eb9be..1309c7a5b57 100644
--- a/chromium/content/browser/service_worker/service_worker_provider_host.cc
+++ b/chromium/content/browser/service_worker/service_worker_provider_host.cc
@@ -11,6 +11,7 @@
#include "base/memory/ptr_util.h"
#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/task/post_task.h"
#include "base/time/time.h"
#include "content/browser/bad_message.h"
#include "content/browser/interface_provider_filtering.h"
@@ -26,9 +27,11 @@
#include "content/browser/service_worker/service_worker_type_converters.h"
#include "content/browser/service_worker/service_worker_version.h"
#include "content/browser/url_loader_factory_getter.h"
+#include "content/browser/web_contents/web_contents_getter_registry.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/service_worker/service_worker_types.h"
#include "content/common/service_worker/service_worker_utils.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/render_frame_host.h"
@@ -40,9 +43,10 @@
#include "mojo/public/cpp/bindings/message.h"
#include "mojo/public/cpp/bindings/strong_associated_binding.h"
#include "net/base/url_util.h"
+#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/resource_request_body.h"
#include "storage/browser/blob/blob_storage_context.h"
-#include "third_party/blink/public/common/message_port/message_port_channel.h"
+#include "third_party/blink/public/common/messaging/message_port_channel.h"
#include "third_party/blink/public/common/service_worker/service_worker_utils.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_client.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom.h"
@@ -323,6 +327,8 @@ ServiceWorkerProviderHost::~ServiceWorkerProviderHost() {
context_->UnregisterProviderHostByClientID(client_uuid_);
if (controller_)
controller_->RemoveControllee(client_uuid_);
+ if (fetch_request_window_id_)
+ WebContentsGetterRegistry::GetInstance()->Remove(fetch_request_window_id_);
// Remove |this| as an observer of ServiceWorkerRegistrations.
// TODO(falken): Use ScopedObserver instead of this explicit call.
@@ -393,11 +399,11 @@ ServiceWorkerProviderHost::GetControllerMode() const {
void ServiceWorkerProviderHost::OnVersionAttributesChanged(
ServiceWorkerRegistration* registration,
- ChangedVersionAttributesMask changed_mask,
+ blink::mojom::ChangedServiceWorkerObjectsMaskPtr changed_mask,
const ServiceWorkerRegistrationInfo& /* info */) {
if (!get_ready_callback_ || get_ready_callback_->is_null())
return;
- if (changed_mask.active_changed() && registration->active_version()) {
+ if (changed_mask->active && registration->active_version()) {
// Wait until the state change so we don't send the get for ready
// registration complete message before set version attributes message.
registration->active_version()->RegisterStatusChangeCallback(base::BindOnce(
@@ -445,7 +451,20 @@ ServiceWorkerProviderHost::GetControllerServiceWorkerPtr() {
void ServiceWorkerProviderHost::SetDocumentUrl(const GURL& url) {
DCHECK(!url.has_ref());
DCHECK(!controller());
+ if (document_url_ == url)
+ return;
document_url_ = url;
+
+ // Revoke the token on URL change since any service worker holding the token
+ // may no longer be the potential controller of this frame and shouldn't have
+ // the power to display SSL dialogs for it.
+ if (info_->type == blink::mojom::ServiceWorkerProviderType::kForWindow) {
+ auto* registry = WebContentsGetterRegistry::GetInstance();
+ registry->Remove(fetch_request_window_id_);
+ fetch_request_window_id_ = base::UnguessableToken::Create();
+ registry->Add(fetch_request_window_id_, web_contents_getter());
+ }
+
if (IsProviderForClient())
SyncMatchingRegistrations();
}
@@ -478,14 +497,30 @@ void ServiceWorkerProviderHost::UpdateController(bool notify_controllerchange) {
// SetController message should be sent only for clients.
DCHECK(IsProviderForClient());
- // If there is no connection to the renderer yet, |this| is hosting a reserved
- // client undergoing navigation. The controller will be sent on navigation
- // commit. See CommitNavigation in frame.mojom.
- if (!container_.is_bound()) {
- DCHECK_EQ(blink::mojom::ServiceWorkerClientType::kWindow, client_type());
- DCHECK(!is_execution_ready_);
- return;
+
+ // The final response hasn't been committed yet, so there's no reason to send
+ // the controller since it can be changed again before the final response.
+ if (!is_execution_ready_) {
+ if (client_type() == blink::mojom::ServiceWorkerClientType::kWindow) {
+ // |this| is hosting a reserved client undergoing navigation. The
+ // controller will be sent on navigation commit. See CommitNavigation in
+ // frame.mojom.
+ DCHECK(!container_.is_bound());
+ return;
+ }
+ DCHECK_EQ(blink::mojom::ServiceWorkerClientType::kSharedWorker,
+ client_type());
+
+ // NetworkService (PlzWorker):
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+ // When PlzWorker is enabled, the controller will be sent when the
+ // response is committed to the renderer at SharedWorkerHost::Start().
+ return;
+ }
+ // When NetworkService is disabled and the client is for a shared worker,
+ // the controller won't be sent on response commit, so send it here.
}
+
SendSetControllerServiceWorker(notify_controllerchange);
}
@@ -568,8 +603,7 @@ void ServiceWorkerProviderHost::RemoveMatchingRegistration(
ServiceWorkerRegistration*
ServiceWorkerProviderHost::MatchRegistration() const {
- ServiceWorkerRegistrationMap::const_reverse_iterator it =
- matching_registrations_.rbegin();
+ auto it = matching_registrations_.rbegin();
for (; it != matching_registrations_.rend(); ++it) {
if (it->second->is_uninstalled())
continue;
@@ -625,7 +659,7 @@ ServiceWorkerProviderHost::CreateRequestHandler(
const std::string& integrity,
bool keepalive,
ResourceType resource_type,
- RequestContextType request_context_type,
+ blink::mojom::RequestContextType request_context_type,
network::mojom::RequestContextFrameType frame_type,
base::WeakPtr<storage::BlobStorageContext> blob_storage_context,
scoped_refptr<network::ResourceRequestBody> body,
@@ -694,13 +728,29 @@ void ServiceWorkerProviderHost::PostMessageToClient(
void ServiceWorkerProviderHost::CountFeature(blink::mojom::WebFeature feature) {
// CountFeature message should be sent only for clients.
DCHECK(IsProviderForClient());
- // If there is no connection to the renderer yet, |this| is hosting a reserved
- // client undergoing navigation. The use counter will be sent correctly in
- // CompleteNavigationInitialized() later.
- if (!container_.is_bound()) {
- DCHECK_EQ(blink::mojom::ServiceWorkerClientType::kWindow, client_type());
- DCHECK(!is_execution_ready_);
- return;
+
+ // The final response hasn't been committed yet, so there's no reason to send
+ // the use counter since it can be changed again before the final response.
+ if (!is_execution_ready_) {
+ if (client_type() == blink::mojom::ServiceWorkerClientType::kWindow) {
+ // |this| is hosting a reserved client undergoing navigation. The use
+ // counter will be sent correctly in CompleteNavigationInitialized()
+ // later.
+ DCHECK(!container_.is_bound());
+ return;
+ }
+ DCHECK_EQ(blink::mojom::ServiceWorkerClientType::kSharedWorker,
+ client_type());
+
+ // NetworkService (PlzWorker):
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+ // When PlzWorker is enabled, the use counter will be sent when the
+ // response is committed to the renderer at SharedWorkerHost::Start().
+ // TODO(nhiroki): Send the use counter on starting the shared worker.
+ return;
+ }
+ // When NetworkService is disabled and the client is for a shared worker,
+ // the use counter won't be sent on response commit, so send it here.
}
container_->CountFeature(feature);
@@ -866,6 +916,10 @@ void ServiceWorkerProviderHost::SendSetControllerServiceWorker(
auto controller_info = mojom::ControllerServiceWorkerInfo::New();
controller_info->client_id = client_uuid();
+ if (fetch_request_window_id_) {
+ controller_info->fetch_request_window_id =
+ base::make_optional(fetch_request_window_id_);
+ }
if (!controller_) {
container_->SetController(std::move(controller_info),
@@ -1183,11 +1237,10 @@ void ServiceWorkerProviderHost::EnsureControllerServiceWorker(
AsWeakPtr(), std::move(controller_request)));
}
-void ServiceWorkerProviderHost::CloneForWorker(
+void ServiceWorkerProviderHost::CloneContainerHost(
mojom::ServiceWorkerContainerHostRequest container_host_request) {
DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled());
- bindings_for_worker_threads_.AddBinding(this,
- std::move(container_host_request));
+ additional_bindings_.AddBinding(this, std::move(container_host_request));
}
void ServiceWorkerProviderHost::Ping(PingCallback callback) {
@@ -1261,8 +1314,8 @@ void ServiceWorkerProviderHost::GetInterface(
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK_NE(kDocumentMainThreadId, render_thread_id_);
DCHECK(IsProviderForServiceWorker());
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(
&GetInterfaceImpl, interface_name, std::move(interface_pipe),
running_hosted_version_->script_origin(), render_process_id_));
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 2fe3e1ef2b8..ee6c66ecce8 100644
--- a/chromium/content/browser/service_worker/service_worker_provider_host.h
+++ b/chromium/content/browser/service_worker/service_worker_provider_host.h
@@ -19,13 +19,13 @@
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
+#include "base/unguessable_token.h"
#include "content/browser/service_worker/service_worker_object_host.h"
#include "content/browser/service_worker/service_worker_registration.h"
#include "content/common/content_export.h"
#include "content/common/service_worker/service_worker_container.mojom.h"
#include "content/common/service_worker/service_worker_provider.mojom.h"
#include "content/common/service_worker/service_worker_types.h"
-#include "content/public/common/request_context_type.h"
#include "content/public/common/resource_type.h"
#include "mojo/public/cpp/bindings/associated_binding.h"
#include "mojo/public/cpp/bindings/binding.h"
@@ -34,6 +34,7 @@
#include "services/network/public/mojom/request_context_frame_type.mojom.h"
#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/fetch/fetch_api_request.mojom.h"
#include "third_party/blink/public/platform/web_feature.mojom.h"
namespace network {
@@ -178,6 +179,9 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
~ServiceWorkerProviderHost() override;
const std::string& client_uuid() const { return client_uuid_; }
+ const base::UnguessableToken& fetch_request_window_id() const {
+ return fetch_request_window_id_;
+ }
base::TimeTicks create_time() const { return create_time_; }
int process_id() const { return render_process_id_; }
int provider_id() const { return info_->provider_id; }
@@ -326,7 +330,7 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
const std::string& integrity,
bool keepalive,
ResourceType resource_type,
- RequestContextType request_context_type,
+ blink::mojom::RequestContextType request_context_type,
network::mojom::RequestContextFrameType frame_type,
base::WeakPtr<storage::BlobStorageContext> blob_storage_context,
scoped_refptr<network::ResourceRequestBody> body,
@@ -494,7 +498,7 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
// ServiceWorkerRegistration::Listener overrides.
void OnVersionAttributesChanged(
ServiceWorkerRegistration* registration,
- ChangedVersionAttributesMask changed_mask,
+ blink::mojom::ChangedServiceWorkerObjectsMaskPtr changed_mask,
const ServiceWorkerRegistrationInfo& info) override;
void OnRegistrationFailed(ServiceWorkerRegistration* registration) override;
void OnRegistrationFinishedUninstalling(
@@ -541,7 +545,7 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
void EnsureControllerServiceWorker(
mojom::ControllerServiceWorkerRequest controller_request,
mojom::ControllerServiceWorkerPurpose purpose) override;
- void CloneForWorker(
+ void CloneContainerHost(
mojom::ServiceWorkerContainerHostRequest container_host_request) override;
void Ping(PingCallback callback) override;
void HintToUpdateServiceWorker() override;
@@ -594,7 +598,19 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
const char* error_prefix,
Args... args);
+ // A GUID that is web-exposed as FetchEvent.clientId.
const std::string client_uuid_;
+
+ // For window clients. A token used internally to identify this context in
+ // requests. Corresponds to the Fetch specification's concept of a request's
+ // associated window: https://fetch.spec.whatwg.org/#concept-request-window
+ // This gets reset on redirects, unlike |client_uuid_|.
+ //
+ // TODO(falken): Consider using this for |client_uuid_| as well. We can't
+ // right now because this gets reset on redirects, and potentially sites rely
+ // on the GUID format.
+ base::UnguessableToken fetch_request_window_id_;
+
const base::TimeTicks create_time_;
int render_process_id_;
@@ -673,17 +689,10 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
// content::ServiceWorkerProviderHost will be destroyed.
mojo::AssociatedBinding<mojom::ServiceWorkerContainerHost> binding_;
- // Mojo bindings for provider host pointers which are used from (dedicated or
- // shared) worker threads.
- // When this is hosting a shared worker, |bindings_for_worker_threads_|
- // contains exactly one element for the shared worker thread. This binding is
- // needed because the host pointer which is bound to |binding_| can only be
- // used from the main thread.
- // When this is hosting a document, |bindings_for_worker_threads_| contains
- // all dedicated workers associated with the document. This binding is needed
- // for the host pointers which are used from the dedicated worker threads.
- mojo::BindingSet<mojom::ServiceWorkerContainerHost>
- bindings_for_worker_threads_;
+ // Container host bindings other than the original |binding_|. These include
+ // bindings for container host pointers used from (dedicated or shared) worker
+ // threads, or from ServiceWorkerSubresourceLoaderFactory.
+ mojo::BindingSet<mojom::ServiceWorkerContainerHost> additional_bindings_;
// For service worker execution contexts.
mojo::Binding<service_manager::mojom::InterfaceProvider>
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 926cb6bedf1..a4c9a827e40 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
@@ -459,7 +459,8 @@ TEST_P(ServiceWorkerProviderHostTest, Controller) {
// Create an active version and then start the navigation.
scoped_refptr<ServiceWorkerVersion> version = new ServiceWorkerVersion(
registration1_.get(), GURL("https://www.example.com/sw.js"),
- 1 /* version_id */, helper_->context()->AsWeakPtr());
+ blink::mojom::ScriptType::kClassic, 1 /* version_id */,
+ helper_->context()->AsWeakPtr());
version->set_fetch_handler_existence(
ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
version->SetStatus(ServiceWorkerVersion::ACTIVATED);
@@ -494,7 +495,8 @@ TEST_P(ServiceWorkerProviderHostTest, UncontrolledWithMatchingRegistration) {
// Create an installing version and then start the navigation.
scoped_refptr<ServiceWorkerVersion> version = new ServiceWorkerVersion(
registration1_.get(), GURL("https://www.example.com/sw.js"),
- 1 /* version_id */, helper_->context()->AsWeakPtr());
+ blink::mojom::ScriptType::kClassic, 1 /* version_id */,
+ helper_->context()->AsWeakPtr());
registration1_->SetInstallingVersion(version);
// Finish the navigation.
@@ -559,7 +561,8 @@ TEST_P(ServiceWorkerProviderHostTest, AllowsServiceWorker) {
scoped_refptr<ServiceWorkerVersion> version =
base::MakeRefCounted<ServiceWorkerVersion>(
registration1_.get(), GURL("https://www.example.com/sw.js"),
- 1 /* version_id */, helper_->context()->AsWeakPtr());
+ blink::mojom::ScriptType::kClassic, 1 /* version_id */,
+ helper_->context()->AsWeakPtr());
registration1_->SetActiveVersion(version);
ServiceWorkerRemoteProviderEndpoint remote_endpoint;
@@ -870,90 +873,6 @@ TEST_P(ServiceWorkerProviderHostTest,
}
}
-// Regression test for https://crbug.com/860106. When a provider host
-// is destroyed, it removes itself as a controllee from its controller.
-// This can trigger the waiting version starting to activate. The
-// destructing host shouldn't try to change its controller to the new
-// active version.
-TEST_P(ServiceWorkerProviderHostTest, DontSetControllerInDestructor) {
- // This test requires the idle timeout mechanism of S13nSW to exercise the
- // desired code path.
- if (!IsServiceWorkerServicificationEnabled())
- return;
-
- // Make a window.
- ServiceWorkerProviderHost* provider_host1 =
- CreateProviderHost(GURL("https://www.example.com/example1.html"));
-
- // Make an active version.
- auto version1 = base::MakeRefCounted<ServiceWorkerVersion>(
- registration1_.get(), GURL("https://www.example.com/sw.js"),
- 1 /* version_id */, helper_->context()->AsWeakPtr());
- version1->set_fetch_handler_existence(
- ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
- version1->SetStatus(ServiceWorkerVersion::ACTIVATED);
- registration1_->SetActiveVersion(version1);
-
- // Make the registration findable via storage functions. This allows
- // the service worker to start, which will be needed later.
- base::RunLoop loop;
- helper_->context()->storage()->LazyInitializeForTest(loop.QuitClosure());
- loop.Run();
- std::vector<ServiceWorkerDatabase::ResourceRecord> records;
- records.push_back(WriteToDiskCacheSync(
- helper_->context()->storage(), version1->script_url(),
- helper_->context()->storage()->NewResourceId(), {} /* headers */,
- "I'm the body", "I'm the meta data"));
- version1->script_cache_map()->SetResources(records);
- version1->SetMainScriptHttpResponseInfo(
- EmbeddedWorkerTestHelper::CreateHttpResponseInfo());
- base::Optional<blink::ServiceWorkerStatusCode> status;
- helper_->context()->storage()->StoreRegistration(
- registration1_.get(), version1.get(),
- CreateReceiverOnCurrentThread(&status));
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status.value());
-
- // Make the active worker the controller and give it an ongoing request. This
- // way when a waiting worker calls SkipWaiting(), activation won't trigger
- // until we're ready.
- provider_host1->SetControllerRegistration(registration1_, false);
- EXPECT_EQ(version1.get(), provider_host1->controller());
- // The worker must be running to have a request.
- version1->StartWorker(ServiceWorkerMetrics::EventType::PUSH,
- base::DoNothing());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version1->running_status());
- int request = version1->StartRequest(ServiceWorkerMetrics::EventType::PUSH,
- base::DoNothing());
-
- // Make the waiting worker and have it call SkipWaiting().
- auto version2 = base::MakeRefCounted<ServiceWorkerVersion>(
- registration1_.get(), GURL("https://www.example.com/sw.js"),
- 2 /* version_id */, helper_->context()->AsWeakPtr());
- version2->set_fetch_handler_existence(
- ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
- version2->SetStatus(ServiceWorkerVersion::INSTALLED);
- registration1_->SetWaitingVersion(version2);
- version2->SkipWaiting(base::DoNothing());
-
- // Finish the request. Activation won't yet occur until as
- // |idle_time_fired_in_renderer_| isn't true.
- version1->FinishRequest(request, true, base::Time::Now());
-
- // Destroy the provider host. This triggers activation, and since
- // SkipWaiting() was called, the provider host is in danger
- // of receiving an OnSkippedWaiting() call during destruction.
- ASSERT_TRUE(remote_endpoints_.back().host_ptr()->is_bound());
- remote_endpoints_.back().host_ptr()->reset();
- base::RunLoop().RunUntilIdle();
-
- // No crash should occur, and the new version should be the active
- // one.
- EXPECT_EQ(version2.get(), registration1_->active_version());
- EXPECT_FALSE(version2->HasControllee());
-}
-
// Tests that the service worker involved with a navigation (via
// AddServiceWorkerToUpdate) is updated when the host for the navigation is
// destroyed.
@@ -969,7 +888,8 @@ TEST_P(ServiceWorkerProviderHostTest, UpdateServiceWorkerOnDestruction) {
// Make an active version.
auto version1 = base::MakeRefCounted<ServiceWorkerVersion>(
registration1_.get(), GURL("https://www.example.com/sw.js"),
- 1 /* version_id */, helper_->context()->AsWeakPtr());
+ blink::mojom::ScriptType::kClassic, 1 /* version_id */,
+ helper_->context()->AsWeakPtr());
version1->set_fetch_handler_existence(
ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
version1->SetStatus(ServiceWorkerVersion::ACTIVATED);
@@ -977,7 +897,8 @@ TEST_P(ServiceWorkerProviderHostTest, UpdateServiceWorkerOnDestruction) {
auto version2 = base::MakeRefCounted<ServiceWorkerVersion>(
registration2_.get(), GURL("https://www.example.com/sw.js"),
- 2 /* version_id */, helper_->context()->AsWeakPtr());
+ blink::mojom::ScriptType::kClassic, 2 /* version_id */,
+ helper_->context()->AsWeakPtr());
version2->set_fetch_handler_existence(
ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
version2->SetStatus(ServiceWorkerVersion::ACTIVATED);
@@ -1008,7 +929,8 @@ TEST_P(ServiceWorkerProviderHostTest, HintToUpdateServiceWorker) {
// Make an active version.
auto version1 = base::MakeRefCounted<ServiceWorkerVersion>(
registration1_.get(), GURL("https://www.example.com/sw.js"),
- 1 /* version_id */, helper_->context()->AsWeakPtr());
+ blink::mojom::ScriptType::kClassic, 1 /* version_id */,
+ helper_->context()->AsWeakPtr());
version1->set_fetch_handler_existence(
ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
version1->SetStatus(ServiceWorkerVersion::ACTIVATED);
@@ -1049,7 +971,8 @@ TEST_P(ServiceWorkerProviderHostTest,
// Make an active version.
auto version1 = base::MakeRefCounted<ServiceWorkerVersion>(
registration1_.get(), GURL("https://www.example.com/sw.js"),
- 1 /* version_id */, helper_->context()->AsWeakPtr());
+ blink::mojom::ScriptType::kClassic, 1 /* version_id */,
+ helper_->context()->AsWeakPtr());
version1->set_fetch_handler_existence(
ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
version1->SetStatus(ServiceWorkerVersion::ACTIVATED);
@@ -1079,7 +1002,8 @@ TEST_P(ServiceWorkerProviderHostTest, HintToUpdateServiceWorkerMultiple) {
// Make active versions.
auto version1 = base::MakeRefCounted<ServiceWorkerVersion>(
registration1_.get(), GURL("https://www.example.com/sw.js"),
- 1 /* version_id */, helper_->context()->AsWeakPtr());
+ blink::mojom::ScriptType::kClassic, 1 /* version_id */,
+ helper_->context()->AsWeakPtr());
version1->set_fetch_handler_existence(
ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
version1->SetStatus(ServiceWorkerVersion::ACTIVATED);
@@ -1087,7 +1011,8 @@ TEST_P(ServiceWorkerProviderHostTest, HintToUpdateServiceWorkerMultiple) {
auto version2 = base::MakeRefCounted<ServiceWorkerVersion>(
registration2_.get(), GURL("https://www.example.com/sw.js"),
- 2 /* version_id */, helper_->context()->AsWeakPtr());
+ blink::mojom::ScriptType::kClassic, 2 /* version_id */,
+ helper_->context()->AsWeakPtr());
version2->set_fetch_handler_existence(
ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
version2->SetStatus(ServiceWorkerVersion::ACTIVATED);
@@ -1095,7 +1020,8 @@ TEST_P(ServiceWorkerProviderHostTest, HintToUpdateServiceWorkerMultiple) {
auto version3 = base::MakeRefCounted<ServiceWorkerVersion>(
registration3_.get(), GURL("https://other.example.com/sw.js"),
- 3 /* version_id */, helper_->context()->AsWeakPtr());
+ blink::mojom::ScriptType::kClassic, 3 /* version_id */,
+ helper_->context()->AsWeakPtr());
version3->set_fetch_handler_existence(
ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
version3->SetStatus(ServiceWorkerVersion::ACTIVATED);
diff --git a/chromium/content/browser/service_worker/service_worker_read_from_cache_job_unittest.cc b/chromium/content/browser/service_worker/service_worker_read_from_cache_job_unittest.cc
index 150c6466381..188907a1fd2 100644
--- a/chromium/content/browser/service_worker/service_worker_read_from_cache_job_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_read_from_cache_job_unittest.cc
@@ -40,19 +40,19 @@ const int64_t kNonExistentResourceId = 12;
const int64_t kResourceSize = 100;
void DidStoreRegistration(blink::ServiceWorkerStatusCode* status_out,
- const base::Closure& quit_closure,
+ base::OnceClosure quit_closure,
blink::ServiceWorkerStatusCode status) {
*status_out = status;
- quit_closure.Run();
+ std::move(quit_closure).Run();
}
void DidFindRegistration(
blink::ServiceWorkerStatusCode* status_out,
- const base::Closure& quit_closure,
+ base::OnceClosure quit_closure,
blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration) {
*status_out = status;
- quit_closure.Run();
+ std::move(quit_closure).Run();
}
} // namespace
@@ -96,6 +96,7 @@ class ServiceWorkerReadFromCacheJobTest : public testing::Test {
registration_ = new ServiceWorkerRegistration(options, kRegistrationId,
context()->AsWeakPtr());
version_ = new ServiceWorkerVersion(registration_.get(), main_script_.url,
+ blink::mojom::ScriptType::kClassic,
kVersionId, context()->AsWeakPtr());
std::vector<ServiceWorkerDatabase::ResourceRecord> resources;
resources.push_back(main_script_);
@@ -113,7 +114,8 @@ class ServiceWorkerReadFromCacheJobTest : public testing::Test {
const char kHttpBody[] = "Hello";
const int length = arraysize(kHttpBody);
std::string headers(kHttpHeaders, arraysize(kHttpHeaders));
- scoped_refptr<net::IOBuffer> body(new net::WrappedIOBuffer(kHttpBody));
+ scoped_refptr<net::IOBuffer> body =
+ base::MakeRefCounted<net::WrappedIOBuffer>(kHttpBody);
std::unique_ptr<ServiceWorkerResponseWriter> writer =
context()->storage()->CreateResponseWriter(resource_id);
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 f832ed1c409..2c38456a810 100644
--- a/chromium/content/browser/service_worker/service_worker_register_job.cc
+++ b/chromium/content/browser/service_worker/service_worker_register_job.cc
@@ -19,6 +19,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/browser/url_loader_factory_getter.h"
#include "content/common/service_worker/service_worker.mojom.h"
#include "content/common/service_worker/service_worker_types.h"
#include "content/common/service_worker/service_worker_utils.h"
@@ -26,6 +27,7 @@
#include "mojo/public/cpp/bindings/associated_binding.h"
#include "net/base/net_errors.h"
#include "third_party/blink/public/common/service_worker/service_worker_type_converters.h"
+#include "third_party/blink/public/common/service_worker/service_worker_utils.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom.h"
namespace content {
@@ -40,6 +42,7 @@ ServiceWorkerRegisterJob::ServiceWorkerRegisterJob(
job_type_(REGISTRATION_JOB),
pattern_(options.scope),
script_url_(script_url),
+ worker_script_type_(options.type),
update_via_cache_(options.update_via_cache),
phase_(INITIAL),
doom_installing_worker_(false),
@@ -64,9 +67,15 @@ ServiceWorkerRegisterJob::ServiceWorkerRegisterJob(
is_promise_resolved_(false),
should_uninstall_on_failure_(false),
force_bypass_cache_(force_bypass_cache),
- skip_script_comparison_(skip_script_comparison),
promise_resolved_status_(blink::ServiceWorkerStatusCode::kOk),
weak_factory_(this) {
+ // |skip_script_comparison_| should be true when
+ // ServiceWorkerImportedScriptUpdateCheck is enabled, because then script
+ // comparison happens before starting a worker and it doesn't need to happen
+ // during the worker startup.
+ skip_script_comparison_ =
+ blink::ServiceWorkerUtils::IsImportedScriptUpdateCheckEnabled() ||
+ skip_script_comparison;
internal_.registration = registration;
}
@@ -225,10 +234,16 @@ void ServiceWorkerRegisterJob::ContinueWithRegistration(
}
DCHECK(existing_registration->GetNewestVersion());
- // "If scriptURL is equal to registration.[[ScriptURL]] and
- // "update_via_cache is equal to registration.[[update_via_cache]], then:"
+ // We also compare |script_type| here to proceed with registration when the
+ // script type is changed.
+ // TODO(asamidoi): Update the spec comment once
+ // https://github.com/w3c/ServiceWorker/issues/1359 is resolved.
+ // "If scriptURL is equal to registration.[[ScriptURL]] and "update_via_cache
+ // is equal to registration.[[update_via_cache]], then:"
if (existing_registration->GetNewestVersion()->script_url() == script_url_ &&
- existing_registration->update_via_cache() == update_via_cache_) {
+ existing_registration->update_via_cache() == update_via_cache_ &&
+ existing_registration->GetNewestVersion()->script_type() ==
+ worker_script_type_) {
// "Set registration.[[Uninstalling]] to false."
existing_registration->AbortPendingClear(base::BindOnce(
&ServiceWorkerRegisterJob::ContinueWithRegistrationForSameScriptUrl,
@@ -275,11 +290,47 @@ void ServiceWorkerRegisterJob::ContinueWithUpdate(
DCHECK(script_url_.is_empty());
script_url_ = registration()->GetNewestVersion()->script_url();
+ worker_script_type_ = registration()->GetNewestVersion()->script_type();
// TODO(michaeln): If the last update check was less than 24 hours
// ago, depending on the freshness of the cached worker script we
// may be able to complete the update job right here.
+ if (blink::ServiceWorkerUtils::IsImportedScriptUpdateCheckEnabled()) {
+ ServiceWorkerVersion* version_to_update =
+ registration()->GetNewestVersion();
+ std::vector<ServiceWorkerDatabase::ResourceRecord> resources;
+ version_to_update->script_cache_map()->GetResources(&resources);
+ update_checker_ = std::make_unique<ServiceWorkerUpdateChecker>(
+ resources, version_to_update,
+ context_->loader_factory_getter()->GetNetworkFactory());
+ update_checker_->Start(
+ base::BindOnce(&ServiceWorkerRegisterJob::OnUpdateCheckFinished,
+ weak_factory_.GetWeakPtr()));
+ return;
+ }
+
+ UpdateAndContinue();
+}
+
+void ServiceWorkerRegisterJob::OnUpdateCheckFinished(bool script_changed) {
+ DCHECK(blink::ServiceWorkerUtils::IsImportedScriptUpdateCheckEnabled());
+ if (!script_changed) {
+ // TODO(momohatt): Set phase correctly.
+ // TODO(momohatt): Update the last update check time correctly.
+ ServiceWorkerVersion* newest_version = registration()->GetNewestVersion();
+ if (newest_version->force_bypass_cache_for_scripts()) {
+ registration()->set_last_update_check(base::Time::Now());
+ }
+ context_->storage()->UpdateLastUpdateCheckTime(registration());
+ ResolvePromise(blink::ServiceWorkerStatusCode::kOk, std::string(),
+ registration());
+ // This terminates the current job (|this|).
+ Complete(blink::ServiceWorkerStatusCode::kErrorExists,
+ "The updated worker is identical to the incumbent.");
+ return;
+ }
+
UpdateAndContinue();
}
@@ -293,8 +344,8 @@ void ServiceWorkerRegisterJob::RegisterAndContinue() {
return;
}
- blink::mojom::ServiceWorkerRegistrationOptions options(pattern_,
- update_via_cache_);
+ blink::mojom::ServiceWorkerRegistrationOptions options(
+ pattern_, worker_script_type_, update_via_cache_);
set_registration(
new ServiceWorkerRegistration(options, registration_id, context_));
AddRegistrationToMatchingProviderHosts(registration());
@@ -355,8 +406,8 @@ void ServiceWorkerRegisterJob::UpdateAndContinue() {
// "Let worker be a new ServiceWorker object..." and start
// the worker.
- set_new_version(new ServiceWorkerVersion(registration(), script_url_,
- version_id, context_));
+ set_new_version(new ServiceWorkerVersion(
+ registration(), script_url_, worker_script_type_, version_id, context_));
new_version()->set_force_bypass_cache_for_scripts(force_bypass_cache_);
if (registration()->has_installed_version() && !skip_script_comparison_) {
new_version()->SetToPauseAfterDownload(
@@ -453,7 +504,7 @@ void ServiceWorkerRegisterJob::OnInstallFinished(
int request_id,
blink::mojom::ServiceWorkerEventStatus event_status,
bool has_fetch_handler,
- base::Time dispatch_event_time) {
+ base::TimeTicks dispatch_event_time) {
bool succeeded =
event_status == blink::mojom::ServiceWorkerEventStatus::COMPLETED;
new_version()->FinishRequest(request_id, succeeded, dispatch_event_time);
@@ -608,6 +659,7 @@ void ServiceWorkerRegisterJob::AddRegistrationToMatchingProviderHosts(
}
void ServiceWorkerRegisterJob::OnPausedAfterDownload() {
+ DCHECK(!blink::ServiceWorkerUtils::IsImportedScriptUpdateCheckEnabled());
net::URLRequestStatus status =
new_version()->script_cache_map()->main_script_status();
if (!status.is_success()) {
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 53814919752..1b9cca0be50 100644
--- a/chromium/content/browser/service_worker/service_worker_register_job.h
+++ b/chromium/content/browser/service_worker/service_worker_register_job.h
@@ -13,6 +13,7 @@
#include "base/time/time.h"
#include "content/browser/service_worker/service_worker_register_job_base.h"
#include "content/browser/service_worker/service_worker_registration.h"
+#include "content/browser/service_worker/service_worker_update_checker.h"
#include "third_party/blink/public/common/service_worker/service_worker_status_code.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"
@@ -105,6 +106,11 @@ class ServiceWorkerRegisterJob : public ServiceWorkerRegisterJobBase {
void ContinueWithUpdate(
blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration);
+
+ // This method is only called when ServiceWorkerImportedScriptUpdateCheck is
+ // enabled.
+ void OnUpdateCheckFinished(bool script_changed);
+
void RegisterAndContinue();
void ContinueWithUninstallingRegistration(
scoped_refptr<ServiceWorkerRegistration> existing_registration,
@@ -117,11 +123,10 @@ class ServiceWorkerRegisterJob : public ServiceWorkerRegisterJobBase {
void OnStoreRegistrationComplete(blink::ServiceWorkerStatusCode status);
void InstallAndContinue();
void DispatchInstallEvent(blink::ServiceWorkerStatusCode start_worker_status);
- void OnInstallFinished(
- int request_id,
- blink::mojom::ServiceWorkerEventStatus event_status,
- bool has_fetch_handler,
- base::Time dispatch_event_time);
+ void OnInstallFinished(int request_id,
+ blink::mojom::ServiceWorkerEventStatus event_status,
+ bool has_fetch_handler,
+ base::TimeTicks dispatch_event_time);
void OnInstallFailed(blink::ServiceWorkerStatusCode status);
void Complete(blink::ServiceWorkerStatusCode status);
void Complete(blink::ServiceWorkerStatusCode status,
@@ -142,9 +147,15 @@ class ServiceWorkerRegisterJob : public ServiceWorkerRegisterJobBase {
// The ServiceWorkerContextCore object should always outlive this.
base::WeakPtr<ServiceWorkerContextCore> context_;
+ std::unique_ptr<ServiceWorkerUpdateChecker> update_checker_;
+
RegistrationJobType job_type_;
const GURL pattern_;
GURL script_url_;
+ // "A job has a worker type ("classic" or "module")."
+ // https://w3c.github.io/ServiceWorker/#dfn-job-worker-type
+ blink::mojom::ScriptType worker_script_type_ =
+ blink::mojom::ScriptType::kClassic;
const blink::mojom::ServiceWorkerUpdateViaCache update_via_cache_;
std::vector<RegistrationCallback> callbacks_;
Phase phase_;
diff --git a/chromium/content/browser/service_worker/service_worker_registration.cc b/chromium/content/browser/service_worker/service_worker_registration.cc
index f215fd804ed..c7bec6f8845 100644
--- a/chromium/content/browser/service_worker/service_worker_registration.cc
+++ b/chromium/content/browser/service_worker/service_worker_registration.cc
@@ -94,10 +94,10 @@ void ServiceWorkerRegistration::NotifyUpdateFound() {
}
void ServiceWorkerRegistration::NotifyVersionAttributesChanged(
- ChangedVersionAttributesMask mask) {
+ blink::mojom::ChangedServiceWorkerObjectsMaskPtr mask) {
for (auto& observer : listeners_)
- observer.OnVersionAttributesChanged(this, mask, GetInfo());
- if (mask.active_changed() || mask.waiting_changed())
+ observer.OnVersionAttributesChanged(this, mask.Clone(), GetInfo());
+ if (mask->active || mask->waiting)
NotifyRegistrationFinished();
}
@@ -121,9 +121,10 @@ void ServiceWorkerRegistration::SetActiveVersion(
should_activate_when_ready_ = false;
- ChangedVersionAttributesMask mask;
+ auto mask =
+ blink::mojom::ChangedServiceWorkerObjectsMask::New(false, false, false);
if (version)
- UnsetVersionInternal(version.get(), &mask);
+ UnsetVersionInternal(version.get(), mask.get());
if (active_version_)
active_version_->RemoveObserver(this);
active_version_ = version;
@@ -131,9 +132,9 @@ void ServiceWorkerRegistration::SetActiveVersion(
active_version_->AddObserver(this);
active_version_->SetNavigationPreloadState(navigation_preload_state_);
}
- mask.add(ChangedVersionAttributesMask::ACTIVE_VERSION);
+ mask->active = true;
- NotifyVersionAttributesChanged(mask);
+ NotifyVersionAttributesChanged(std::move(mask));
}
void ServiceWorkerRegistration::SetWaitingVersion(
@@ -143,53 +144,55 @@ void ServiceWorkerRegistration::SetWaitingVersion(
should_activate_when_ready_ = false;
- ChangedVersionAttributesMask mask;
+ auto mask =
+ blink::mojom::ChangedServiceWorkerObjectsMask::New(false, false, false);
if (version)
- UnsetVersionInternal(version.get(), &mask);
+ UnsetVersionInternal(version.get(), mask.get());
waiting_version_ = version;
- mask.add(ChangedVersionAttributesMask::WAITING_VERSION);
+ mask->waiting = true;
- NotifyVersionAttributesChanged(mask);
+ NotifyVersionAttributesChanged(std::move(mask));
}
void ServiceWorkerRegistration::SetInstallingVersion(
const scoped_refptr<ServiceWorkerVersion>& version) {
if (installing_version_ == version)
return;
-
- ChangedVersionAttributesMask mask;
+ auto mask =
+ blink::mojom::ChangedServiceWorkerObjectsMask::New(false, false, false);
if (version)
- UnsetVersionInternal(version.get(), &mask);
+ UnsetVersionInternal(version.get(), mask.get());
installing_version_ = version;
- mask.add(ChangedVersionAttributesMask::INSTALLING_VERSION);
-
- NotifyVersionAttributesChanged(mask);
+ mask->installing = true;
+ NotifyVersionAttributesChanged(std::move(mask));
}
void ServiceWorkerRegistration::UnsetVersion(ServiceWorkerVersion* version) {
if (!version)
return;
- ChangedVersionAttributesMask mask;
- UnsetVersionInternal(version, &mask);
- if (mask.changed())
- NotifyVersionAttributesChanged(mask);
+ auto mask =
+ blink::mojom::ChangedServiceWorkerObjectsMask::New(false, false, false);
+ UnsetVersionInternal(version, mask.get());
+ if (mask->installing || mask->waiting || mask->active)
+ NotifyVersionAttributesChanged(std::move(mask));
}
void ServiceWorkerRegistration::UnsetVersionInternal(
ServiceWorkerVersion* version,
- ChangedVersionAttributesMask* mask) {
+ blink::mojom::ChangedServiceWorkerObjectsMask* mask) {
DCHECK(version);
+
if (installing_version_.get() == version) {
installing_version_ = nullptr;
- mask->add(ChangedVersionAttributesMask::INSTALLING_VERSION);
+ mask->installing = true;
} else if (waiting_version_.get() == version) {
waiting_version_ = nullptr;
should_activate_when_ready_ = false;
- mask->add(ChangedVersionAttributesMask::WAITING_VERSION);
+ mask->waiting = true;
} else if (active_version_.get() == version) {
active_version_->RemoveObserver(this);
active_version_ = nullptr;
- mask->add(ChangedVersionAttributesMask::ACTIVE_VERSION);
+ mask->active = true;
}
}
@@ -216,7 +219,7 @@ void ServiceWorkerRegistration::ActivateWaitingVersionWhenReady() {
// If the waiting worker is ready and the active worker needs to be
// swapped out, ask the active worker to trigger idle timer as soon as
// possible.
- active_version()->endpoint()->SetIdleTimerDelayToZero();
+ active_version()->TriggerIdleTerminationAsap();
}
StartLameDuckTimer();
}
@@ -299,7 +302,7 @@ void ServiceWorkerRegistration::OnNoControllees(ServiceWorkerVersion* version) {
// If the waiting worker is ready and the active worker needs to be
// swapped out, ask the active worker to trigger idle timer as soon as
// possible.
- active_version()->endpoint()->SetIdleTimerDelayToZero();
+ active_version()->TriggerIdleTerminationAsap();
}
StartLameDuckTimer();
}
@@ -310,7 +313,7 @@ void ServiceWorkerRegistration::OnNoWork(ServiceWorkerVersion* version) {
return;
DCHECK_EQ(active_version(), version);
if (IsReadyToActivate())
- ActivateWaitingVersion(false /* delay */);
+ ActivateWaitingVersion(true /* delay */);
}
bool ServiceWorkerRegistration::IsReadyToActivate() const {
@@ -324,7 +327,7 @@ bool ServiceWorkerRegistration::IsReadyToActivate() const {
return true;
}
if (IsLameDuckActiveVersion()) {
- return !active->HasWorkInBrowser() ||
+ return active->HasNoWork() ||
waiting->TimeSinceSkipWaiting() > kMaxLameDuckTime ||
active->TimeSinceNoControllees() > kMaxLameDuckTime;
}
@@ -462,10 +465,10 @@ void ServiceWorkerRegistration::DeleteVersion(
}
void ServiceWorkerRegistration::NotifyRegistrationFinished() {
- std::vector<base::Closure> callbacks;
+ std::vector<base::OnceClosure> callbacks;
callbacks.swap(registration_finished_callbacks_);
- for (const auto& callback : callbacks)
- callback.Run();
+ for (auto& callback : callbacks)
+ std::move(callback).Run();
}
void ServiceWorkerRegistration::SetTaskRunnerForTest(
@@ -487,11 +490,11 @@ void ServiceWorkerRegistration::SetNavigationPreloadHeader(
}
void ServiceWorkerRegistration::RegisterRegistrationFinishedCallback(
- const base::Closure& callback) {
+ base::OnceClosure callback) {
// This should only be called if the registration is in progress.
DCHECK(!active_version() && !waiting_version() && !is_uninstalled() &&
!is_uninstalling());
- registration_finished_callbacks_.push_back(callback);
+ registration_finished_callbacks_.push_back(std::move(callback));
}
void ServiceWorkerRegistration::DispatchActivateEvent(
@@ -568,26 +571,27 @@ void ServiceWorkerRegistration::Clear() {
context_->storage()->NotifyDoneUninstallingRegistration(this);
std::vector<scoped_refptr<ServiceWorkerVersion>> versions_to_doom;
- ChangedVersionAttributesMask mask;
+ auto mask =
+ blink::mojom::ChangedServiceWorkerObjectsMask::New(false, false, false);
if (installing_version_.get()) {
versions_to_doom.push_back(installing_version_);
installing_version_ = nullptr;
- mask.add(ChangedVersionAttributesMask::INSTALLING_VERSION);
+ mask->installing = true;
}
if (waiting_version_.get()) {
versions_to_doom.push_back(waiting_version_);
waiting_version_ = nullptr;
- mask.add(ChangedVersionAttributesMask::WAITING_VERSION);
+ mask->waiting = true;
}
if (active_version_.get()) {
versions_to_doom.push_back(active_version_);
active_version_->RemoveObserver(this);
active_version_ = nullptr;
- mask.add(ChangedVersionAttributesMask::ACTIVE_VERSION);
+ mask->active = true;
}
- if (mask.changed()) {
- NotifyVersionAttributesChanged(mask);
+ if (mask->installing || mask->waiting || mask->active) {
+ NotifyVersionAttributesChanged(std::move(mask));
// Doom only after notifying attributes changed, because the spec requires
// the attributes to be cleared by the time the statechange event is
diff --git a/chromium/content/browser/service_worker/service_worker_registration.h b/chromium/content/browser/service_worker/service_worker_registration.h
index e41fa4a0af3..1d4a5295c5e 100644
--- a/chromium/content/browser/service_worker/service_worker_registration.h
+++ b/chromium/content/browser/service_worker/service_worker_registration.h
@@ -46,7 +46,7 @@ class CONTENT_EXPORT ServiceWorkerRegistration
public:
virtual void OnVersionAttributesChanged(
ServiceWorkerRegistration* registration,
- ChangedVersionAttributesMask changed_mask,
+ blink::mojom::ChangedServiceWorkerObjectsMaskPtr changed_mask,
const ServiceWorkerRegistrationInfo& info) {}
virtual void OnUpdateViaCacheChanged(
ServiceWorkerRegistration* registation) {}
@@ -120,7 +120,8 @@ class CONTENT_EXPORT ServiceWorkerRegistration
virtual void RemoveListener(Listener* listener);
void NotifyRegistrationFailed();
void NotifyUpdateFound();
- void NotifyVersionAttributesChanged(ChangedVersionAttributesMask mask);
+ void NotifyVersionAttributesChanged(
+ blink::mojom::ChangedServiceWorkerObjectsMaskPtr mask);
ServiceWorkerRegistrationInfo GetInfo();
@@ -174,7 +175,7 @@ class CONTENT_EXPORT ServiceWorkerRegistration
// registration from storage if there is no longer a stored version.
void DeleteVersion(const scoped_refptr<ServiceWorkerVersion>& version);
- void RegisterRegistrationFinishedCallback(const base::Closure& callback);
+ void RegisterRegistrationFinishedCallback(base::OnceClosure callback);
void NotifyRegistrationFinished();
void SetTaskRunnerForTest(
@@ -193,7 +194,7 @@ class CONTENT_EXPORT ServiceWorkerRegistration
void UnsetVersionInternal(
ServiceWorkerVersion* version,
- ChangedVersionAttributesMask* mask);
+ blink::mojom::ChangedServiceWorkerObjectsMask* mask);
// ServiceWorkerVersion::Observer override.
void OnNoControllees(ServiceWorkerVersion* version) override;
@@ -244,7 +245,7 @@ class CONTENT_EXPORT ServiceWorkerRegistration
scoped_refptr<ServiceWorkerVersion> installing_version_;
base::ObserverList<Listener>::Unchecked listeners_;
- std::vector<base::Closure> registration_finished_callbacks_;
+ std::vector<base::OnceClosure> registration_finished_callbacks_;
base::WeakPtr<ServiceWorkerContextCore> context_;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
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 5466cd6ef11..cd59e49c117 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
@@ -4,12 +4,14 @@
#include "content/browser/service_worker/service_worker_registration_object_host.h"
+#include "base/task/post_task.h"
#include "base/time/time.h"
#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_object_host.h"
#include "content/browser/service_worker/service_worker_provider_host.h"
#include "content/common/service_worker/service_worker_utils.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "net/http/http_util.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
@@ -97,9 +99,16 @@ ServiceWorkerRegistrationObjectHost::~ServiceWorkerRegistrationObjectHost() {
blink::mojom::ServiceWorkerRegistrationObjectInfoPtr
ServiceWorkerRegistrationObjectHost::CreateObjectInfo() {
+ // |info->options->script_type| is never accessed anywhere, so just set it to
+ // kClassic.
+ // TODO(asamidoi, nhiroki): Remove |options| from
+ // ServiceWorkerRegistrationObjectInfo, since |script_type| is a
+ // non-per-registration property.
+ blink::mojom::ScriptType script_type = blink::mojom::ScriptType::kClassic;
+
auto info = blink::mojom::ServiceWorkerRegistrationObjectInfo::New();
info->options = blink::mojom::ServiceWorkerRegistrationOptions::New(
- registration_->pattern(), registration_->update_via_cache());
+ registration_->pattern(), script_type, registration_->update_via_cache());
info->registration_id = registration_->id();
bindings_.AddBinding(this, mojo::MakeRequest(&info->host_ptr_info));
info->request = mojo::MakeRequest(&remote_registration_);
@@ -115,12 +124,12 @@ ServiceWorkerRegistrationObjectHost::CreateObjectInfo() {
void ServiceWorkerRegistrationObjectHost::OnVersionAttributesChanged(
ServiceWorkerRegistration* registration,
- ChangedVersionAttributesMask changed_mask,
+ blink::mojom::ChangedServiceWorkerObjectsMaskPtr changed_mask,
const ServiceWorkerRegistrationInfo& info) {
DCHECK_EQ(registration->id(), registration_->id());
- SetVersionAttributes(changed_mask, registration->installing_version(),
- registration->waiting_version(),
- registration->active_version());
+ SetServiceWorkerObjects(
+ std::move(changed_mask), registration->installing_version(),
+ registration->waiting_version(), registration->active_version());
}
void ServiceWorkerRegistrationObjectHost::OnUpdateViaCacheChanged(
@@ -131,11 +140,9 @@ void ServiceWorkerRegistrationObjectHost::OnUpdateViaCacheChanged(
void ServiceWorkerRegistrationObjectHost::OnRegistrationFailed(
ServiceWorkerRegistration* registration) {
DCHECK_EQ(registration->id(), registration_->id());
- ChangedVersionAttributesMask changed_mask(
- ChangedVersionAttributesMask::INSTALLING_VERSION |
- ChangedVersionAttributesMask::WAITING_VERSION |
- ChangedVersionAttributesMask::ACTIVE_VERSION);
- SetVersionAttributes(changed_mask, nullptr, nullptr, nullptr);
+ auto changed_mask =
+ blink::mojom::ChangedServiceWorkerObjectsMask::New(true, true, true);
+ SetServiceWorkerObjects(std::move(changed_mask), nullptr, nullptr, nullptr);
}
void ServiceWorkerRegistrationObjectHost::OnUpdateFound(
@@ -205,8 +212,8 @@ void ServiceWorkerRegistrationObjectHost::DelayUpdate(
return;
}
- BrowserThread::PostDelayedTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostDelayedTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(std::move(update_function),
blink::ServiceWorkerStatusCode::kOk),
delay);
@@ -371,29 +378,30 @@ void ServiceWorkerRegistrationObjectHost::DidUpdateNavigationPreloadHeader(
base::nullopt);
}
-void ServiceWorkerRegistrationObjectHost::SetVersionAttributes(
- ChangedVersionAttributesMask changed_mask,
+void ServiceWorkerRegistrationObjectHost::SetServiceWorkerObjects(
+ blink::mojom::ChangedServiceWorkerObjectsMaskPtr changed_mask,
ServiceWorkerVersion* installing_version,
ServiceWorkerVersion* waiting_version,
ServiceWorkerVersion* active_version) {
- if (!changed_mask.changed())
+ if (!(changed_mask->installing || changed_mask->waiting ||
+ changed_mask->active))
return;
blink::mojom::ServiceWorkerObjectInfoPtr installing;
blink::mojom::ServiceWorkerObjectInfoPtr waiting;
blink::mojom::ServiceWorkerObjectInfoPtr active;
- if (changed_mask.installing_changed()) {
+ if (changed_mask->installing) {
installing =
CreateCompleteObjectInfoToSend(provider_host_, installing_version);
}
- if (changed_mask.waiting_changed())
+ if (changed_mask->waiting)
waiting = CreateCompleteObjectInfoToSend(provider_host_, waiting_version);
- if (changed_mask.active_changed())
+ if (changed_mask->active)
active = CreateCompleteObjectInfoToSend(provider_host_, active_version);
DCHECK(remote_registration_);
- remote_registration_->SetVersionAttributes(
- changed_mask.changed(), std::move(installing), std::move(waiting),
+ remote_registration_->SetServiceWorkerObjects(
+ std::move(changed_mask), std::move(installing), std::move(waiting),
std::move(active));
}
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 cfca9b43e02..db6c5f85ec3 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
@@ -58,7 +58,7 @@ class CONTENT_EXPORT ServiceWorkerRegistrationObjectHost
// ServiceWorkerRegistration::Listener overrides.
void OnVersionAttributesChanged(
ServiceWorkerRegistration* registration,
- ChangedVersionAttributesMask changed_mask,
+ blink::mojom::ChangedServiceWorkerObjectsMaskPtr changed_mask,
const ServiceWorkerRegistrationInfo& info) override;
void OnUpdateViaCacheChanged(
ServiceWorkerRegistration* registration) override;
@@ -115,10 +115,11 @@ class CONTENT_EXPORT ServiceWorkerRegistrationObjectHost
// Sets the corresponding version field to the given version or if the given
// version is nullptr, clears the field.
- void SetVersionAttributes(ChangedVersionAttributesMask changed_mask,
- ServiceWorkerVersion* installing_version,
- ServiceWorkerVersion* waiting_version,
- ServiceWorkerVersion* active_version);
+ void SetServiceWorkerObjects(
+ blink::mojom::ChangedServiceWorkerObjectsMaskPtr changed_mask,
+ ServiceWorkerVersion* installing_version,
+ ServiceWorkerVersion* waiting_version,
+ ServiceWorkerVersion* active_version);
void OnConnectionError();
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 62bf488958e..4c9120a1791 100644
--- a/chromium/content/browser/service_worker/service_worker_registration_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_registration_unittest.cc
@@ -11,6 +11,7 @@
#include "base/compiler_specific.h"
#include "base/files/scoped_temp_dir.h"
#include "base/logging.h"
+#include "base/memory/weak_ptr.h"
#include "base/run_loop.h"
#include "base/test/simple_test_tick_clock.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -27,6 +28,7 @@
#include "content/test/test_content_browser_client.h"
#include "mojo/core/embedder/embedder.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/service_worker/service_worker_utils.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 "url/gurl.h"
@@ -80,7 +82,9 @@ class MockServiceWorkerRegistrationObject
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::ChangedServiceWorkerObjectsMask& changed_mask() const {
+ return *changed_mask_;
+ }
const blink::mojom::ServiceWorkerObjectInfoPtr& installing() const {
return installing_;
}
@@ -96,13 +100,13 @@ class MockServiceWorkerRegistrationObject
private:
// Implements blink::mojom::ServiceWorkerRegistrationObject.
- void SetVersionAttributes(
- int changed_mask,
+ void SetServiceWorkerObjects(
+ blink::mojom::ChangedServiceWorkerObjectsMaskPtr changed_mask,
blink::mojom::ServiceWorkerObjectInfoPtr installing,
blink::mojom::ServiceWorkerObjectInfoPtr waiting,
blink::mojom::ServiceWorkerObjectInfoPtr active) override {
set_version_attributes_called_count_++;
- changed_mask_ = changed_mask;
+ changed_mask_ = std::move(changed_mask);
installing_ = std::move(installing);
waiting_ = std::move(waiting);
active_ = std::move(active);
@@ -117,7 +121,7 @@ class MockServiceWorkerRegistrationObject
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::ChangedServiceWorkerObjectsMaskPtr changed_mask_;
blink::mojom::ServiceWorkerObjectInfoPtr installing_;
blink::mojom::ServiceWorkerObjectInfoPtr waiting_;
blink::mojom::ServiceWorkerObjectInfoPtr active_;
@@ -132,14 +136,36 @@ class MockServiceWorkerRegistrationObject
// will be terminated when SetIdleTimerDelayToZero() is called.
class RegistrationTestHelper : public EmbeddedWorkerTestHelper {
public:
- RegistrationTestHelper() : EmbeddedWorkerTestHelper(base::FilePath()) {}
+ RegistrationTestHelper()
+ : EmbeddedWorkerTestHelper(base::FilePath()), weak_factory_(this) {}
~RegistrationTestHelper() override = default;
+ void RequestTermination(int embedded_worker_id) {
+ GetEmbeddedWorkerInstanceHost(embedded_worker_id)
+ ->RequestTermination(
+ base::BindOnce(&RegistrationTestHelper::OnRequestedTermination,
+ weak_factory_.GetWeakPtr()));
+ }
+
+ const base::Optional<bool>& will_be_terminated() const {
+ return will_be_terminated_;
+ }
+
+ bool is_zero_idle_timer_delay() const { return is_zero_idle_timer_delay_; }
+
protected:
void OnSetIdleTimerDelayToZero(int embedded_worker_id) override {
- GetEmbeddedWorkerInstanceHost(embedded_worker_id)
- ->RequestTermination(base::DoNothing());
+ is_zero_idle_timer_delay_ = true;
+ }
+
+ void OnRequestedTermination(bool will_be_terminated) {
+ will_be_terminated_ = will_be_terminated;
}
+
+ private:
+ bool is_zero_idle_timer_delay_ = false;
+ base::Optional<bool> will_be_terminated_;
+ base::WeakPtrFactory<RegistrationTestHelper> weak_factory_;
};
class ServiceWorkerRegistrationTest : public testing::Test {
@@ -172,10 +198,10 @@ class ServiceWorkerRegistrationTest : public testing::Test {
void OnVersionAttributesChanged(
ServiceWorkerRegistration* registration,
- ChangedVersionAttributesMask changed_mask,
+ blink::mojom::ChangedServiceWorkerObjectsMaskPtr changed_mask,
const ServiceWorkerRegistrationInfo& info) override {
observed_registration_ = registration;
- observed_changed_mask_ = changed_mask;
+ observed_changed_mask_ = std::move(changed_mask);
observed_info_ = info;
}
@@ -190,17 +216,17 @@ class ServiceWorkerRegistrationTest : public testing::Test {
void Reset() {
observed_registration_ = nullptr;
- observed_changed_mask_ = ChangedVersionAttributesMask();
+ observed_changed_mask_ = nullptr;
observed_info_ = ServiceWorkerRegistrationInfo();
}
scoped_refptr<ServiceWorkerRegistration> observed_registration_;
- ChangedVersionAttributesMask observed_changed_mask_;
+ blink::mojom::ChangedServiceWorkerObjectsMaskPtr observed_changed_mask_;
ServiceWorkerRegistrationInfo observed_info_;
};
protected:
- std::unique_ptr<EmbeddedWorkerTestHelper> helper_;
+ std::unique_ptr<RegistrationTestHelper> helper_;
TestBrowserThreadBundle thread_bundle_;
};
@@ -219,10 +245,12 @@ TEST_F(ServiceWorkerRegistrationTest, SetAndUnsetVersions) {
const int64_t version_2_id = 2L;
scoped_refptr<ServiceWorkerVersion> version_1 =
base::MakeRefCounted<ServiceWorkerVersion>(
- registration.get(), kScript, version_1_id, context()->AsWeakPtr());
+ registration.get(), kScript, blink::mojom::ScriptType::kClassic,
+ version_1_id, context()->AsWeakPtr());
scoped_refptr<ServiceWorkerVersion> version_2 =
base::MakeRefCounted<ServiceWorkerVersion>(
- registration.get(), kScript, version_2_id, context()->AsWeakPtr());
+ registration.get(), kScript, blink::mojom::ScriptType::kClassic,
+ version_2_id, context()->AsWeakPtr());
RegistrationListener listener;
registration->AddListener(&listener);
@@ -230,8 +258,7 @@ TEST_F(ServiceWorkerRegistrationTest, SetAndUnsetVersions) {
EXPECT_EQ(version_1.get(), registration->active_version());
EXPECT_EQ(registration, listener.observed_registration_);
- EXPECT_EQ(ChangedVersionAttributesMask::ACTIVE_VERSION,
- listener.observed_changed_mask_.changed());
+ EXPECT_TRUE(listener.observed_changed_mask_->active);
EXPECT_EQ(kScope, listener.observed_info_.pattern);
EXPECT_EQ(version_1_id, listener.observed_info_.active_version.version_id);
EXPECT_EQ(kScript, listener.observed_info_.active_version.script_url);
@@ -244,8 +271,7 @@ TEST_F(ServiceWorkerRegistrationTest, SetAndUnsetVersions) {
registration->SetInstallingVersion(version_2);
EXPECT_EQ(version_2.get(), registration->installing_version());
- EXPECT_EQ(ChangedVersionAttributesMask::INSTALLING_VERSION,
- listener.observed_changed_mask_.changed());
+ EXPECT_TRUE(listener.observed_changed_mask_->installing);
EXPECT_EQ(version_1_id, listener.observed_info_.active_version.version_id);
EXPECT_EQ(version_2_id,
listener.observed_info_.installing_version.version_id);
@@ -257,8 +283,8 @@ TEST_F(ServiceWorkerRegistrationTest, SetAndUnsetVersions) {
EXPECT_EQ(version_2.get(), registration->waiting_version());
EXPECT_FALSE(registration->installing_version());
- EXPECT_TRUE(listener.observed_changed_mask_.waiting_changed());
- EXPECT_TRUE(listener.observed_changed_mask_.installing_changed());
+ EXPECT_TRUE(listener.observed_changed_mask_->waiting);
+ EXPECT_TRUE(listener.observed_changed_mask_->installing);
EXPECT_EQ(version_1_id, listener.observed_info_.active_version.version_id);
EXPECT_EQ(version_2_id, listener.observed_info_.waiting_version.version_id);
EXPECT_EQ(listener.observed_info_.installing_version.version_id,
@@ -268,8 +294,7 @@ TEST_F(ServiceWorkerRegistrationTest, SetAndUnsetVersions) {
registration->UnsetVersion(version_2.get());
EXPECT_FALSE(registration->waiting_version());
- EXPECT_EQ(ChangedVersionAttributesMask::WAITING_VERSION,
- listener.observed_changed_mask_.changed());
+ EXPECT_TRUE(listener.observed_changed_mask_->waiting);
EXPECT_EQ(version_1_id, listener.observed_info_.active_version.version_id);
EXPECT_EQ(listener.observed_info_.waiting_version.version_id,
blink::mojom::kInvalidServiceWorkerVersionId);
@@ -316,17 +341,17 @@ TEST_F(ServiceWorkerRegistrationTest, NavigationPreload) {
base::MakeRefCounted<ServiceWorkerRegistration>(
options, storage()->NewRegistrationId(), context()->AsWeakPtr());
scoped_refptr<ServiceWorkerVersion> version_1 =
- base::MakeRefCounted<ServiceWorkerVersion>(registration.get(), kScript,
- storage()->NewVersionId(),
- context()->AsWeakPtr());
+ base::MakeRefCounted<ServiceWorkerVersion>(
+ registration.get(), kScript, blink::mojom::ScriptType::kClassic,
+ storage()->NewVersionId(), context()->AsWeakPtr());
version_1->set_fetch_handler_existence(
ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
registration->SetActiveVersion(version_1);
version_1->SetStatus(ServiceWorkerVersion::ACTIVATED);
scoped_refptr<ServiceWorkerVersion> version_2 =
- base::MakeRefCounted<ServiceWorkerVersion>(registration.get(), kScript,
- storage()->NewVersionId(),
- context()->AsWeakPtr());
+ base::MakeRefCounted<ServiceWorkerVersion>(
+ registration.get(), kScript, blink::mojom::ScriptType::kClassic,
+ storage()->NewVersionId(), context()->AsWeakPtr());
version_2->set_fetch_handler_existence(
ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
registration->SetWaitingVersion(version_2);
@@ -348,7 +373,8 @@ TEST_F(ServiceWorkerRegistrationTest, NavigationPreload) {
// Sets up a registration with a waiting worker, and an active worker
// with a controllee and an inflight request.
-class ServiceWorkerActivationTest : public ServiceWorkerRegistrationTest {
+class ServiceWorkerActivationTest : public ServiceWorkerRegistrationTest,
+ public testing::WithParamInterface<bool> {
public:
ServiceWorkerActivationTest() : ServiceWorkerRegistrationTest() {}
@@ -365,9 +391,9 @@ class ServiceWorkerActivationTest : public ServiceWorkerRegistrationTest {
// Create an active version.
scoped_refptr<ServiceWorkerVersion> version_1 =
- base::MakeRefCounted<ServiceWorkerVersion>(registration_.get(), kScript,
- storage()->NewVersionId(),
- context()->AsWeakPtr());
+ base::MakeRefCounted<ServiceWorkerVersion>(
+ registration_.get(), kScript, blink::mojom::ScriptType::kClassic,
+ storage()->NewVersionId(), context()->AsWeakPtr());
version_1->set_fetch_handler_existence(
ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
registration_->SetActiveVersion(version_1);
@@ -403,9 +429,9 @@ class ServiceWorkerActivationTest : public ServiceWorkerRegistrationTest {
// Create a waiting version.
scoped_refptr<ServiceWorkerVersion> version_2 =
- base::MakeRefCounted<ServiceWorkerVersion>(registration_.get(), kScript,
- storage()->NewVersionId(),
- context()->AsWeakPtr());
+ base::MakeRefCounted<ServiceWorkerVersion>(
+ registration_.get(), kScript, blink::mojom::ScriptType::kClassic,
+ storage()->NewVersionId(), context()->AsWeakPtr());
std::vector<ServiceWorkerDatabase::ResourceRecord> records_2;
records_2.push_back(WriteToDiskCacheSync(
helper_->context()->storage(), version_2->script_url(),
@@ -426,6 +452,12 @@ class ServiceWorkerActivationTest : public ServiceWorkerRegistrationTest {
registration_->ActivateWaitingVersionWhenReady();
base::RunLoop().RunUntilIdle();
EXPECT_EQ(version_1.get(), registration_->active_version());
+
+ if (devtools_should_be_attached()) {
+ // Attach DevTools to the active worker. This shouldn't prevent from
+ // promoting the waiting worker to active.
+ version_1->SetDevToolsAttached(true);
+ }
}
void TearDown() override {
@@ -433,6 +465,8 @@ class ServiceWorkerActivationTest : public ServiceWorkerRegistrationTest {
ServiceWorkerRegistrationTest::TearDown();
}
+ bool devtools_should_be_attached() const { return GetParam(); }
+
ServiceWorkerRegistration* registration() { return registration_.get(); }
ServiceWorkerProviderHost* controllee() { return host_.get(); }
int inflight_request_id() const { return inflight_request_id_; }
@@ -450,10 +484,19 @@ class ServiceWorkerActivationTest : public ServiceWorkerRegistrationTest {
// error like ServiceWorkerContext shutdown.
void SimulateSkipWaiting(ServiceWorkerVersion* version,
base::Optional<bool>* out_result) {
- version->SkipWaiting(
- base::BindOnce([](base::Optional<bool>* out_result,
- bool success) { *out_result = success; },
- out_result));
+ SimulateSkipWaitingWithCallback(version, out_result, base::DoNothing());
+ }
+
+ void SimulateSkipWaitingWithCallback(ServiceWorkerVersion* version,
+ base::Optional<bool>* out_result,
+ base::OnceClosure done_callback) {
+ version->SkipWaiting(base::BindOnce(
+ [](base::OnceClosure done_callback, base::Optional<bool>* out_result,
+ bool success) {
+ *out_result = success;
+ std::move(done_callback).Run();
+ },
+ std::move(done_callback), out_result));
base::RunLoop().RunUntilIdle();
}
@@ -465,26 +508,43 @@ class ServiceWorkerActivationTest : public ServiceWorkerRegistrationTest {
};
// Test activation triggered by finishing all requests.
-TEST_F(ServiceWorkerActivationTest, NoInflightRequest) {
+TEST_P(ServiceWorkerActivationTest, NoInflightRequest) {
scoped_refptr<ServiceWorkerRegistration> reg = registration();
scoped_refptr<ServiceWorkerVersion> version_1 = reg->active_version();
scoped_refptr<ServiceWorkerVersion> version_2 = reg->waiting_version();
// Remove the controllee. Since there is an in-flight request,
// activation should not yet happen.
+ // When S13nServiceWorker is on, the idle timer living in the renderer is
+ // requested to notify the browser the idle state ASAP.
version_1->RemoveControllee(controllee()->client_uuid());
base::RunLoop().RunUntilIdle();
EXPECT_EQ(version_1.get(), reg->active_version());
+ if (blink::ServiceWorkerUtils::IsServicificationEnabled())
+ EXPECT_TRUE(helper_->is_zero_idle_timer_delay());
// Finish the request. Activation should happen.
version_1->FinishRequest(inflight_request_id(), true /* was_handled */,
- base::Time::Now());
+ base::TimeTicks::Now());
base::RunLoop().RunUntilIdle();
+
+ if (blink::ServiceWorkerUtils::IsServicificationEnabled()) {
+ EXPECT_EQ(version_1.get(), reg->active_version());
+ helper_->RequestTermination(
+ version_1->embedded_worker()->embedded_worker_id());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(helper_->will_be_terminated().value());
+ }
+
EXPECT_EQ(version_2.get(), reg->active_version());
}
// Test activation triggered by loss of controllee.
-TEST_F(ServiceWorkerActivationTest, NoControllee) {
+TEST_P(ServiceWorkerActivationTest, NoControllee) {
+ // S13nServiceWorker: activation only happens when the service worker reports
+ // it's idle, so this test doesn't make sense.
+ if (blink::ServiceWorkerUtils::IsServicificationEnabled())
+ return;
scoped_refptr<ServiceWorkerRegistration> reg = registration();
scoped_refptr<ServiceWorkerVersion> version_1 = reg->active_version();
scoped_refptr<ServiceWorkerVersion> version_2 = reg->waiting_version();
@@ -492,7 +552,7 @@ TEST_F(ServiceWorkerActivationTest, NoControllee) {
// Finish the request. Since there is a controllee, activation should not yet
// happen.
version_1->FinishRequest(inflight_request_id(), true /* was_handled */,
- base::Time::Now());
+ base::TimeTicks::Now());
base::RunLoop().RunUntilIdle();
EXPECT_EQ(version_1.get(), reg->active_version());
@@ -502,50 +562,88 @@ TEST_F(ServiceWorkerActivationTest, NoControllee) {
EXPECT_EQ(version_2.get(), reg->active_version());
}
-// Test activation triggered by skipWaiting.
-TEST_F(ServiceWorkerActivationTest, SkipWaiting) {
+// Test activation triggered by skipWaiting and finishing requests.
+TEST_P(ServiceWorkerActivationTest, SkipWaitingWithInflightRequest) {
scoped_refptr<ServiceWorkerRegistration> reg = registration();
scoped_refptr<ServiceWorkerVersion> version_1 = reg->active_version();
scoped_refptr<ServiceWorkerVersion> version_2 = reg->waiting_version();
- // Finish the in-flight request. Since there is a controllee,
+ base::Optional<bool> result;
+ base::RunLoop skip_waiting_loop;
+ // Set skip waiting flag. Since there is still an in-flight request,
// activation should not happen.
- version_1->FinishRequest(inflight_request_id(), true /* was_handled */,
- base::Time::Now());
- base::RunLoop().RunUntilIdle();
+ SimulateSkipWaitingWithCallback(version_2.get(), &result,
+ skip_waiting_loop.QuitClosure());
+ EXPECT_FALSE(result.has_value());
EXPECT_EQ(version_1.get(), reg->active_version());
+ if (blink::ServiceWorkerUtils::IsServicificationEnabled())
+ EXPECT_TRUE(helper_->is_zero_idle_timer_delay());
+
+ // Finish the request.
+ // non-S13nServiceWorker: The service worker becomes idle.
+ // S13nServiceWorker: FinishRequest() doesn't immediately make the worker
+ // "no work" state. It needs to be notfied the idle state by
+ // RequestTermination().
+ version_1->FinishRequest(inflight_request_id(), true /* was_handled */,
+ base::TimeTicks::Now());
+
+ if (blink::ServiceWorkerUtils::IsServicificationEnabled()) {
+ EXPECT_EQ(version_1.get(), reg->active_version());
+ helper_->RequestTermination(
+ version_1->embedded_worker()->embedded_worker_id());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(helper_->will_be_terminated().value());
+ }
+
+ // Wait until SkipWaiting resolves.
+ skip_waiting_loop.Run();
- // Call skipWaiting. Activation should happen.
- base::Optional<bool> result;
- SimulateSkipWaiting(version_2.get(), &result);
EXPECT_TRUE(result.has_value());
EXPECT_TRUE(*result);
EXPECT_EQ(version_2.get(), reg->active_version());
}
-// Test activation triggered by skipWaiting and finishing requests.
-TEST_F(ServiceWorkerActivationTest, SkipWaitingWithInflightRequest) {
+// Test activation triggered by skipWaiting.
+TEST_P(ServiceWorkerActivationTest, SkipWaiting) {
scoped_refptr<ServiceWorkerRegistration> reg = registration();
scoped_refptr<ServiceWorkerVersion> version_1 = reg->active_version();
scoped_refptr<ServiceWorkerVersion> version_2 = reg->waiting_version();
- base::Optional<bool> result;
- // Set skip waiting flag. Since there is still an in-flight request,
+ // Finish the in-flight request. Since there is a controllee,
// activation should not happen.
- SimulateSkipWaiting(version_2.get(), &result);
- EXPECT_FALSE(result.has_value());
- EXPECT_EQ(version_1.get(), reg->active_version());
-
- // Finish the request. Activation should happen.
version_1->FinishRequest(inflight_request_id(), true /* was_handled */,
- base::Time::Now());
+ base::TimeTicks::Now());
base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(version_1.get(), reg->active_version());
+
+ // Call skipWaiting.
+ // non-S13nServiceWorker: Activation should happen.
+ // S13nServiceWorker: Activation should happen after RequestTermination is
+ // triggered.
+ base::Optional<bool> result;
+ base::RunLoop skip_waiting_loop;
+ SimulateSkipWaitingWithCallback(version_2.get(), &result,
+ skip_waiting_loop.QuitClosure());
+
+ if (blink::ServiceWorkerUtils::IsServicificationEnabled()) {
+ EXPECT_TRUE(helper_->is_zero_idle_timer_delay());
+ EXPECT_FALSE(result.has_value());
+ EXPECT_EQ(version_1.get(), reg->active_version());
+ helper_->RequestTermination(
+ version_1->embedded_worker()->embedded_worker_id());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(helper_->will_be_terminated().value());
+ }
+
+ // Wait until SkipWaiting resolves.
+ skip_waiting_loop.Run();
+
EXPECT_TRUE(result.has_value());
EXPECT_TRUE(*result);
EXPECT_EQ(version_2.get(), reg->active_version());
}
-TEST_F(ServiceWorkerActivationTest, TimeSinceSkipWaiting_Installing) {
+TEST_P(ServiceWorkerActivationTest, TimeSinceSkipWaiting_Installing) {
scoped_refptr<ServiceWorkerRegistration> reg = registration();
scoped_refptr<ServiceWorkerVersion> version = reg->waiting_version();
base::SimpleTestTickClock clock;
@@ -580,7 +678,7 @@ TEST_F(ServiceWorkerActivationTest, TimeSinceSkipWaiting_Installing) {
}
// Test lame duck timer triggered by skip waiting.
-TEST_F(ServiceWorkerActivationTest, LameDuckTime_SkipWaiting) {
+TEST_P(ServiceWorkerActivationTest, LameDuckTime_SkipWaiting) {
scoped_refptr<ServiceWorkerRegistration> reg = registration();
scoped_refptr<ServiceWorkerVersion> version_1 = reg->active_version();
scoped_refptr<ServiceWorkerVersion> version_2 = reg->waiting_version();
@@ -613,7 +711,7 @@ TEST_F(ServiceWorkerActivationTest, LameDuckTime_SkipWaiting) {
}
// Test lame duck timer triggered by loss of controllee.
-TEST_F(ServiceWorkerActivationTest, LameDuckTime_NoControllee) {
+TEST_P(ServiceWorkerActivationTest, LameDuckTime_NoControllee) {
scoped_refptr<ServiceWorkerRegistration> reg = registration();
scoped_refptr<ServiceWorkerVersion> version_1 = reg->active_version();
scoped_refptr<ServiceWorkerVersion> version_2 = reg->waiting_version();
@@ -667,6 +765,10 @@ TEST_F(ServiceWorkerActivationTest, LameDuckTime_NoControllee) {
EXPECT_FALSE(IsLameDuckTimerRunning());
}
+INSTANTIATE_TEST_CASE_P(ServiceWorkerActivationTestWithDevTools,
+ ServiceWorkerActivationTest,
+ testing::Bool());
+
// Sets up a registration with a ServiceWorkerRegistrationObjectHost to hold it.
class ServiceWorkerRegistrationObjectHostTest
: public ServiceWorkerRegistrationTest {
@@ -764,9 +866,9 @@ class ServiceWorkerRegistrationObjectHostTest
ServiceWorkerRegistration* registration,
const GURL& script_url) {
scoped_refptr<ServiceWorkerVersion> version =
- base::MakeRefCounted<ServiceWorkerVersion>(registration, script_url,
- storage()->NewVersionId(),
- context()->AsWeakPtr());
+ base::MakeRefCounted<ServiceWorkerVersion>(
+ registration, script_url, blink::mojom::ScriptType::kClassic,
+ storage()->NewVersionId(), context()->AsWeakPtr());
std::vector<ServiceWorkerDatabase::ResourceRecord> records;
records.push_back(WriteToDiskCacheSync(
storage(), version->script_url(), storage()->NewResourceId(),
@@ -1119,81 +1221,67 @@ TEST_F(ServiceWorkerRegistrationObjectHostTest, SetVersionAttributes) {
const int64_t version_2_id = 2L;
scoped_refptr<ServiceWorkerVersion> version_1 =
base::MakeRefCounted<ServiceWorkerVersion>(
- registration, kScriptUrl, version_1_id, context()->AsWeakPtr());
+ registration, kScriptUrl, blink::mojom::ScriptType::kClassic,
+ version_1_id, context()->AsWeakPtr());
scoped_refptr<ServiceWorkerVersion> version_2 =
base::MakeRefCounted<ServiceWorkerVersion>(
- registration, kScriptUrl, version_2_id, context()->AsWeakPtr());
+ registration, kScriptUrl, blink::mojom::ScriptType::kClassic,
+ version_2_id, context()->AsWeakPtr());
// Set an active worker.
- {
- registration->SetActiveVersion(version_1);
- EXPECT_EQ(version_1.get(), registration->active_version());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(1,
- mock_registration_object->set_version_attributes_called_count());
- ChangedVersionAttributesMask mask(mock_registration_object->changed_mask());
- EXPECT_FALSE(mask.installing_changed());
- EXPECT_FALSE(mock_registration_object->installing());
- EXPECT_FALSE(mask.waiting_changed());
- EXPECT_FALSE(mock_registration_object->waiting());
- EXPECT_TRUE(mask.active_changed());
- EXPECT_TRUE(mock_registration_object->active());
- EXPECT_EQ(version_1_id, mock_registration_object->active()->version_id);
- EXPECT_EQ(kScriptUrl, mock_registration_object->active()->url);
- }
+ registration->SetActiveVersion(version_1);
+ EXPECT_EQ(version_1.get(), registration->active_version());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(1, mock_registration_object->set_version_attributes_called_count());
+ EXPECT_FALSE(mock_registration_object->changed_mask().installing);
+ EXPECT_FALSE(mock_registration_object->installing());
+ EXPECT_FALSE(mock_registration_object->changed_mask().waiting);
+ EXPECT_FALSE(mock_registration_object->waiting());
+ EXPECT_TRUE(mock_registration_object->changed_mask().active);
+ EXPECT_TRUE(mock_registration_object->active());
+ EXPECT_EQ(version_1_id, mock_registration_object->active()->version_id);
+ EXPECT_EQ(kScriptUrl, mock_registration_object->active()->url);
// Set an installing worker.
- {
- registration->SetInstallingVersion(version_2);
- EXPECT_EQ(version_2.get(), registration->installing_version());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(2,
- mock_registration_object->set_version_attributes_called_count());
- ChangedVersionAttributesMask mask(mock_registration_object->changed_mask());
- EXPECT_TRUE(mask.installing_changed());
- EXPECT_TRUE(mock_registration_object->installing());
- EXPECT_FALSE(mask.waiting_changed());
- EXPECT_FALSE(mock_registration_object->waiting());
- EXPECT_FALSE(mask.active_changed());
- EXPECT_FALSE(mock_registration_object->active());
- EXPECT_EQ(version_2_id, mock_registration_object->installing()->version_id);
- EXPECT_EQ(kScriptUrl, mock_registration_object->installing()->url);
- }
+ registration->SetInstallingVersion(version_2);
+ EXPECT_EQ(version_2.get(), registration->installing_version());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(2, mock_registration_object->set_version_attributes_called_count());
+ EXPECT_TRUE(mock_registration_object->changed_mask().installing);
+ EXPECT_TRUE(mock_registration_object->installing());
+ EXPECT_FALSE(mock_registration_object->changed_mask().waiting);
+ EXPECT_FALSE(mock_registration_object->waiting());
+ EXPECT_FALSE(mock_registration_object->changed_mask().active);
+ EXPECT_FALSE(mock_registration_object->active());
+ EXPECT_EQ(version_2_id, mock_registration_object->installing()->version_id);
+ EXPECT_EQ(kScriptUrl, mock_registration_object->installing()->url);
// Promote the installing worker to waiting.
- {
- registration->SetWaitingVersion(version_2);
- EXPECT_EQ(version_2.get(), registration->waiting_version());
- EXPECT_FALSE(registration->installing_version());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(3,
- mock_registration_object->set_version_attributes_called_count());
- ChangedVersionAttributesMask mask(mock_registration_object->changed_mask());
- EXPECT_TRUE(mask.installing_changed());
- EXPECT_FALSE(mock_registration_object->installing());
- EXPECT_TRUE(mask.waiting_changed());
- EXPECT_TRUE(mock_registration_object->waiting());
- EXPECT_FALSE(mask.active_changed());
- EXPECT_FALSE(mock_registration_object->active());
- EXPECT_EQ(version_2_id, mock_registration_object->waiting()->version_id);
- EXPECT_EQ(kScriptUrl, mock_registration_object->waiting()->url);
- }
+ registration->SetWaitingVersion(version_2);
+ EXPECT_EQ(version_2.get(), registration->waiting_version());
+ EXPECT_FALSE(registration->installing_version());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(3, mock_registration_object->set_version_attributes_called_count());
+ EXPECT_TRUE(mock_registration_object->changed_mask().installing);
+ EXPECT_FALSE(mock_registration_object->installing());
+ EXPECT_TRUE(mock_registration_object->changed_mask().waiting);
+ EXPECT_TRUE(mock_registration_object->waiting());
+ EXPECT_FALSE(mock_registration_object->changed_mask().active);
+ EXPECT_FALSE(mock_registration_object->active());
+ EXPECT_EQ(version_2_id, mock_registration_object->waiting()->version_id);
+ EXPECT_EQ(kScriptUrl, mock_registration_object->waiting()->url);
// Remove the waiting worker.
- {
- registration->UnsetVersion(version_2.get());
- EXPECT_FALSE(registration->waiting_version());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(4,
- mock_registration_object->set_version_attributes_called_count());
- ChangedVersionAttributesMask mask(mock_registration_object->changed_mask());
- EXPECT_FALSE(mask.installing_changed());
- EXPECT_FALSE(mock_registration_object->installing());
- EXPECT_TRUE(mask.waiting_changed());
- EXPECT_FALSE(mock_registration_object->waiting());
- EXPECT_FALSE(mask.active_changed());
- EXPECT_FALSE(mock_registration_object->active());
- }
+ registration->UnsetVersion(version_2.get());
+ EXPECT_FALSE(registration->waiting_version());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(4, mock_registration_object->set_version_attributes_called_count());
+ EXPECT_FALSE(mock_registration_object->changed_mask().installing);
+ EXPECT_FALSE(mock_registration_object->installing());
+ EXPECT_TRUE(mock_registration_object->changed_mask().waiting);
+ EXPECT_FALSE(mock_registration_object->waiting());
+ EXPECT_FALSE(mock_registration_object->changed_mask().active);
+ EXPECT_FALSE(mock_registration_object->active());
}
TEST_F(ServiceWorkerRegistrationObjectHostTest, SetUpdateViaCache) {
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 e72645e490f..e768de507e1 100644
--- a/chromium/content/browser/service_worker/service_worker_request_handler.cc
+++ b/chromium/content/browser/service_worker/service_worker_request_handler.cc
@@ -78,7 +78,7 @@ void ServiceWorkerRequestHandler::InitializeForNavigation(
storage::BlobStorageContext* blob_storage_context,
bool skip_service_worker,
ResourceType resource_type,
- RequestContextType request_context_type,
+ blink::mojom::RequestContextType request_context_type,
network::mojom::RequestContextFrameType frame_type,
bool is_parent_frame_secure,
scoped_refptr<network::ResourceRequestBody> body,
@@ -142,17 +142,19 @@ ServiceWorkerRequestHandler::InitializeForNavigationNetworkService(
storage::BlobStorageContext* blob_storage_context,
bool skip_service_worker,
ResourceType resource_type,
- RequestContextType request_context_type,
+ blink::mojom::RequestContextType request_context_type,
network::mojom::RequestContextFrameType frame_type,
bool is_parent_frame_secure,
scoped_refptr<network::ResourceRequestBody> body,
- const base::Callback<WebContents*(void)>& web_contents_getter) {
+ const base::Callback<WebContents*(void)>& web_contents_getter,
+ base::WeakPtr<ServiceWorkerProviderHost>* out_provider_host) {
DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled());
DCHECK(navigation_handle_core);
// Create the handler even for insecure HTTP since it's used in the
// case of redirect to HTTPS.
- if (!url.SchemeIsHTTPOrHTTPS() && !OriginCanAccessServiceWorkers(url)) {
+ if (!url.SchemeIsHTTPOrHTTPS() && !OriginCanAccessServiceWorkers(url) &&
+ !SchemeMaySupportRedirectingToHTTPS(url)) {
return nullptr;
}
@@ -164,21 +166,22 @@ ServiceWorkerRequestHandler::InitializeForNavigationNetworkService(
return nullptr;
// Initialize the SWProviderHost.
- base::WeakPtr<ServiceWorkerProviderHost> provider_host =
+ *out_provider_host =
ServiceWorkerProviderHost::PreCreateNavigationHost(
context->AsWeakPtr(), is_parent_frame_secure, web_contents_getter);
std::unique_ptr<ServiceWorkerRequestHandler> handler(
- provider_host->CreateRequestHandler(
- network::mojom::FetchRequestMode::kNavigate,
- network::mojom::FetchCredentialsMode::kInclude,
- network::mojom::FetchRedirectMode::kManual,
- std::string() /* integrity */, false /* keepalive */, resource_type,
- request_context_type, frame_type, blob_storage_context->AsWeakPtr(),
- body, skip_service_worker));
+ (*out_provider_host)
+ ->CreateRequestHandler(
+ network::mojom::FetchRequestMode::kNavigate,
+ network::mojom::FetchCredentialsMode::kInclude,
+ network::mojom::FetchRedirectMode::kManual,
+ std::string() /* integrity */, false /* keepalive */,
+ resource_type, request_context_type, frame_type,
+ blob_storage_context->AsWeakPtr(), body, skip_service_worker));
navigation_handle_core->DidPreCreateProviderHost(
- provider_host->provider_id());
+ (*out_provider_host)->provider_id());
return base::WrapUnique<NavigationLoaderInterceptor>(handler.release());
}
@@ -203,7 +206,8 @@ ServiceWorkerRequestHandler::InitializeForSharedWorker(
resource_request.fetch_credentials_mode,
resource_request.fetch_redirect_mode,
resource_request.fetch_integrity, resource_request.keepalive,
- RESOURCE_TYPE_SHARED_WORKER, REQUEST_CONTEXT_TYPE_SHARED_WORKER,
+ RESOURCE_TYPE_SHARED_WORKER,
+ blink::mojom::RequestContextType::SHARED_WORKER,
resource_request.fetch_frame_type,
nullptr /* blob_storage_context: unused in S13n */,
resource_request.request_body, resource_request.skip_service_worker));
@@ -225,7 +229,7 @@ void ServiceWorkerRequestHandler::InitializeHandler(
const std::string& integrity,
bool keepalive,
ResourceType resource_type,
- RequestContextType request_context_type,
+ blink::mojom::RequestContextType request_context_type,
network::mojom::RequestContextFrameType frame_type,
scoped_refptr<network::ResourceRequestBody> body) {
// S13nServiceWorker enabled, NetworkService disabled:
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 41132905487..370fc7f36be 100644
--- a/chromium/content/browser/service_worker/service_worker_request_handler.h
+++ b/chromium/content/browser/service_worker/service_worker_request_handler.h
@@ -15,12 +15,12 @@
#include "content/browser/loader/navigation_loader_interceptor.h"
#include "content/common/content_export.h"
#include "content/common/service_worker/service_worker_types.h"
-#include "content/public/common/request_context_type.h"
#include "content/public/common/resource_type.h"
#include "net/url_request/url_request_job_factory.h"
#include "services/network/public/mojom/fetch_api.mojom.h"
#include "services/network/public/mojom/request_context_frame_type.mojom.h"
#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
+#include "third_party/blink/public/platform/modules/fetch/fetch_api_request.mojom.h"
namespace net {
class NetworkDelegate;
@@ -60,7 +60,7 @@ class CONTENT_EXPORT ServiceWorkerRequestHandler
storage::BlobStorageContext* blob_storage_context,
bool skip_service_worker,
ResourceType resource_type,
- RequestContextType request_context_type,
+ blink::mojom::RequestContextType request_context_type,
network::mojom::RequestContextFrameType frame_type,
bool is_parent_frame_secure,
scoped_refptr<network::ResourceRequestBody> body,
@@ -77,11 +77,12 @@ class CONTENT_EXPORT ServiceWorkerRequestHandler
storage::BlobStorageContext* blob_storage_context,
bool skip_service_worker,
ResourceType resource_type,
- RequestContextType request_context_type,
+ blink::mojom::RequestContextType request_context_type,
network::mojom::RequestContextFrameType frame_type,
bool is_parent_frame_secure,
scoped_refptr<network::ResourceRequestBody> body,
- const base::Callback<WebContents*(void)>& web_contents_getter);
+ const base::Callback<WebContents*(void)>& web_contents_getter,
+ base::WeakPtr<ServiceWorkerProviderHost>* out_provider_host);
static std::unique_ptr<NavigationLoaderInterceptor> InitializeForSharedWorker(
const network::ResourceRequest& resource_request,
@@ -106,7 +107,7 @@ class CONTENT_EXPORT ServiceWorkerRequestHandler
const std::string& integrity,
bool keepalive,
ResourceType resource_type,
- RequestContextType request_context_type,
+ blink::mojom::RequestContextType request_context_type,
network::mojom::RequestContextFrameType frame_type,
scoped_refptr<network::ResourceRequestBody> body);
diff --git a/chromium/content/browser/service_worker/service_worker_request_handler_unittest.cc b/chromium/content/browser/service_worker/service_worker_request_handler_unittest.cc
index 2aaa2c7e9ee..7c5d2c574de 100644
--- a/chromium/content/browser/service_worker/service_worker_request_handler_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_request_handler_unittest.cc
@@ -7,6 +7,7 @@
#include <utility>
#include "base/run_loop.h"
+#include "base/task/post_task.h"
#include "content/browser/service_worker/embedded_worker_test_helper.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
@@ -14,7 +15,7 @@
#include "content/browser/service_worker/service_worker_provider_host.h"
#include "content/browser/service_worker/service_worker_test_utils.h"
#include "content/common/service_worker/service_worker_utils.h"
-#include "content/public/common/request_context_type.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/common/resource_type.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
@@ -26,6 +27,7 @@
#include "storage/browser/blob/blob_storage_context.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/service_worker/service_worker_utils.h"
+#include "third_party/blink/public/platform/modules/fetch/fetch_api_request.mojom.h"
namespace content {
namespace service_worker_request_handler_unittest {
@@ -63,8 +65,8 @@ class ServiceWorkerRequestHandlerTest : public testing::Test {
static std::unique_ptr<ServiceWorkerNavigationHandleCore>
CreateNavigationHandleCore(ServiceWorkerContextWrapper* context_wrapper) {
std::unique_ptr<ServiceWorkerNavigationHandleCore> navigation_handle_core;
- BrowserThread::PostTaskAndReplyWithResult(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraitsAndReplyWithResult(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(
[](ServiceWorkerContextWrapper* wrapper) {
return std::make_unique<ServiceWorkerNavigationHandleCore>(
@@ -101,7 +103,7 @@ class ServiceWorkerRequestHandlerTest : public testing::Test {
network::mojom::FetchCredentialsMode::kOmit,
network::mojom::FetchRedirectMode::kFollow,
std::string() /* integrity */, false /* keepalive */, resource_type,
- REQUEST_CONTEXT_TYPE_HYPERLINK,
+ blink::mojom::RequestContextType::HYPERLINK,
network::mojom::RequestContextFrameType::kTopLevel, nullptr);
}
@@ -155,7 +157,7 @@ class ServiceWorkerRequestHandlerTest : public testing::Test {
ServiceWorkerRequestHandler::InitializeForNavigation(
request.get(), navigation_handle_core.get(), &blob_storage_context_,
false /* skip_service_worker */, RESOURCE_TYPE_MAIN_FRAME,
- REQUEST_CONTEXT_TYPE_HYPERLINK,
+ blink::mojom::RequestContextType::HYPERLINK,
network::mojom::RequestContextFrameType::kTopLevel,
true /* is_parent_frame_secure */, nullptr /* body */,
base::RepeatingCallback<WebContents*(void)>());
@@ -167,15 +169,17 @@ class ServiceWorkerRequestHandlerTest : public testing::Test {
bool expected_handler_created) {
std::unique_ptr<ServiceWorkerNavigationHandleCore> navigation_handle_core =
CreateNavigationHandleCore(helper_->context_wrapper());
+ base::WeakPtr<ServiceWorkerProviderHost> service_worker_provider_host;
std::unique_ptr<NavigationLoaderInterceptor> interceptor =
ServiceWorkerRequestHandler::InitializeForNavigationNetworkService(
GURL(url), nullptr /* resource_context */,
navigation_handle_core.get(), &blob_storage_context_,
false /* skip_service_worker */, RESOURCE_TYPE_MAIN_FRAME,
- REQUEST_CONTEXT_TYPE_HYPERLINK,
+ blink::mojom::RequestContextType::HYPERLINK,
network::mojom::RequestContextFrameType::kTopLevel,
true /* is_parent_frame_secure */, nullptr /* body */,
- base::RepeatingCallback<WebContents*(void)>());
+ base::RepeatingCallback<WebContents*(void)>(),
+ &service_worker_provider_host);
return !!interceptor.get();
}
diff --git a/chromium/content/browser/service_worker/service_worker_script_cache_map.cc b/chromium/content/browser/service_worker/service_worker_script_cache_map.cc
index 09f44ad00a1..6ac7fb16b2e 100644
--- a/chromium/content/browser/service_worker/service_worker_script_cache_map.cc
+++ b/chromium/content/browser/service_worker/service_worker_script_cache_map.cc
@@ -81,9 +81,7 @@ void ServiceWorkerScriptCacheMap::GetResources(
void ServiceWorkerScriptCacheMap::SetResources(
const std::vector<ServiceWorkerDatabase::ResourceRecord>& resources) {
DCHECK(resource_map_.empty());
- typedef std::vector<ServiceWorkerDatabase::ResourceRecord> RecordVector;
- for (RecordVector::const_iterator it = resources.begin();
- it != resources.end(); ++it) {
+ for (auto it = resources.begin(); it != resources.end(); ++it) {
resource_map_[it->url] = *it;
}
}
@@ -97,14 +95,15 @@ void ServiceWorkerScriptCacheMap::WriteMetadata(
return;
}
- ResourceMap::iterator found = resource_map_.find(url);
+ auto found = resource_map_.find(url);
if (found == resource_map_.end() ||
found->second.resource_id == kInvalidServiceWorkerResourceId) {
callback.Run(net::ERR_FILE_NOT_FOUND);
return;
}
- scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(data.size()));
+ scoped_refptr<net::IOBuffer> buffer =
+ base::MakeRefCounted<net::IOBuffer>(data.size());
if (data.size())
memmove(buffer->data(), &data[0], data.size());
std::unique_ptr<ServiceWorkerResponseMetadataWriter> writer;
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 e90b006c0fd..86b6e12b26d 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
@@ -51,10 +51,9 @@ void ServiceWorkerScriptLoaderFactory::CreateLoaderAndStart(
// (use ServceWorkerInstalledScriptLoader). Typically this case is handled
// by ServiceWorkerInstalledScriptsSender, but we can still get here when a
// new service worker starts up and becomes installed while it is running.
- // B) service worker is installed, script is not installed: serve from direct
- // network. This happens when the script is newly imported after
- // installation.
- // TODO(crbug.com/719052): deprecate this.
+ // B) service worker is installed, script is not installed: return a network
+ // error. This happens when the script is newly imported after
+ // installation, which is disallowed by the spec.
// C) service worker is not installed, script is installed: serve from
// storage (use ServceWorkerInstalledScriptLoader)
// D) service worker is not installed, script is not installed: serve from
@@ -78,11 +77,7 @@ void ServiceWorkerScriptLoaderFactory::CreateLoaderAndStart(
// Case B:
if (ServiceWorkerVersion::IsInstalled(version->status())) {
- // TODO(kinuko): Record the reason like what we do with netlog in
- // ServiceWorkerContextRequestHandler.
- loader_factory_->CreateLoaderAndStart(
- std::move(request), routing_id, request_id, options, resource_request,
- std::move(client), traffic_annotation);
+ client->OnComplete(network::URLLoaderCompletionStatus(net::ERR_FAILED));
return;
}
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 2eb05ea0815..38b60b9f6d2 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
@@ -27,7 +27,8 @@ class ServiceWorkerProviderHost;
// service worker. For installed workers, service worker script streaming
// (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).
+// non-installed script. In this case, this factory just returns a network
+// error as the spec disallows it.
//
// This factory creates either a ServiceWorkerNewScriptLoader or a
// ServiceWorkerInstalledScriptLoader to load a script.
diff --git a/chromium/content/browser/service_worker/service_worker_script_loader_factory_unittest.cc b/chromium/content/browser/service_worker/service_worker_script_loader_factory_unittest.cc
index c53cae17369..09a0579f561 100644
--- a/chromium/content/browser/service_worker/service_worker_script_loader_factory_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_script_loader_factory_unittest.cc
@@ -96,7 +96,8 @@ class ServiceWorkerScriptLoaderFactoryTest : public testing::Test {
options, 1L /* registration_id */, context->AsWeakPtr());
version_ = base::MakeRefCounted<ServiceWorkerVersion>(
registration_.get(), GURL("https://host/script.js"),
- context->storage()->NewVersionId(), context->AsWeakPtr());
+ blink::mojom::ScriptType::kClassic, context->storage()->NewVersionId(),
+ context->AsWeakPtr());
provider_host_ = CreateProviderHostForServiceWorkerContext(
helper_->mock_render_process_id(), true /* is_parent_frame_secure */,
diff --git a/chromium/content/browser/service_worker/service_worker_single_script_update_checker.cc b/chromium/content/browser/service_worker/service_worker_single_script_update_checker.cc
new file mode 100644
index 00000000000..a08ad96b927
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_single_script_update_checker.cc
@@ -0,0 +1,385 @@
+// 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_single_script_update_checker.h"
+
+#include "content/browser/appcache/appcache_response.h"
+#include "content/browser/service_worker/service_worker_cache_writer.h"
+#include "content/public/common/resource_type.h"
+#include "mojo/public/cpp/system/simple_watcher.h"
+#include "services/network/public/cpp/net_adapters.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "third_party/blink/public/common/mime_util/mime_util.h"
+
+// TODO(momohatt): Use ServiceWorkerMetrics for UMA.
+
+namespace {
+
+constexpr net::NetworkTrafficAnnotationTag kUpdateCheckTrafficAnnotation =
+ net::DefineNetworkTrafficAnnotation("service_worker_update_checker",
+ R"(
+ semantics {
+ sender: "ServiceWorker System"
+ description:
+ "This request is issued by an update check to fetch the content of "
+ "the new scripts."
+ trigger:
+ "ServiceWorker's update logic, which is triggered by a navigation to a "
+ "site controlled by a service worker."
+ data:
+ "No body. 'Service-Worker: script' header is attached when it's the "
+ "main worker script. Requests may include cookies and credentials."
+ destination: WEBSITE
+ }
+ policy {
+ cookies_allowed: YES
+ cookies_store: "user"
+ setting:
+ "Users can control this feature via the 'Cookies' setting under "
+ "'Privacy, Content settings'. If cookies are disabled for a single "
+ "site, serviceworkers are disabled for the site only. If they are "
+ "totally disabled, all serviceworker requests will be stopped."
+ chrome_policy {
+ URLBlacklist {
+ URLBlacklist: { entries: '*' }
+ }
+ }
+ chrome_policy {
+ URLWhitelist {
+ URLWhitelist { }
+ }
+ }
+ }
+ comments:
+ "Chrome would be unable to update service workers without this type of "
+ "request. Using either URLBlacklist or URLWhitelist policies (or a "
+ "combination of both) limits the scope of these requests."
+ )");
+
+} // namespace
+
+namespace content {
+
+ServiceWorkerSingleScriptUpdateChecker::ServiceWorkerSingleScriptUpdateChecker(
+ const GURL& url,
+ bool is_main_script,
+ scoped_refptr<network::SharedURLLoaderFactory> loader_factory,
+ std::unique_ptr<ServiceWorkerResponseReader> compare_reader,
+ std::unique_ptr<ServiceWorkerResponseReader> copy_reader,
+ std::unique_ptr<ServiceWorkerResponseWriter> writer,
+ ResultCallback callback)
+ : network_client_binding_(this),
+ network_watcher_(FROM_HERE,
+ mojo::SimpleWatcher::ArmingPolicy::MANUAL,
+ base::SequencedTaskRunnerHandle::Get()),
+ callback_(std::move(callback)),
+ weak_factory_(this) {
+ network::ResourceRequest resource_request;
+ resource_request.url = url;
+ resource_request.resource_type =
+ is_main_script ? RESOURCE_TYPE_SERVICE_WORKER : RESOURCE_TYPE_SCRIPT;
+ resource_request.do_not_prompt_for_login = true;
+ if (is_main_script)
+ resource_request.headers.SetHeader("Service-Worker", "script");
+
+ // TODO(momohatt): Handle cases where force_bypass_cache is enabled.
+
+ // |compare_reader| shouldn't be a nullptr, which forces
+ // ServiceWorkerCacheWriter to do the comparison.
+ DCHECK(compare_reader);
+ cache_writer_ = std::make_unique<ServiceWorkerCacheWriter>(
+ std::move(compare_reader), std::move(copy_reader), std::move(writer),
+ true /* pause_when_not_identical */);
+
+ network::mojom::URLLoaderClientPtr network_client;
+ network_client_binding_.Bind(mojo::MakeRequest(&network_client));
+
+ loader_factory->CreateLoaderAndStart(
+ mojo::MakeRequest(&network_loader_), -1 /* routing_id */,
+ -1 /* request_id */, network::mojom::kURLLoadOptionNone, resource_request,
+ std::move(network_client),
+ net::MutableNetworkTrafficAnnotationTag(kUpdateCheckTrafficAnnotation));
+ DCHECK_EQ(NetworkLoaderState::kNotStarted, network_loader_state_);
+ network_loader_state_ = NetworkLoaderState::kLoadingHeader;
+}
+
+ServiceWorkerSingleScriptUpdateChecker::
+ ~ServiceWorkerSingleScriptUpdateChecker() = default;
+
+// URLLoaderClient override ----------------------------------------------------
+
+void ServiceWorkerSingleScriptUpdateChecker::OnReceiveResponse(
+ const network::ResourceResponseHead& response_head) {
+ DCHECK_EQ(NetworkLoaderState::kLoadingHeader, network_loader_state_);
+
+ // We don't have complete info here, but fill in what we have now.
+ // At least we need headers and SSL info.
+ auto response_info = std::make_unique<net::HttpResponseInfo>();
+ response_info->headers = response_head.headers;
+ if (response_head.ssl_info.has_value())
+ response_info->ssl_info = *response_head.ssl_info;
+ response_info->was_fetched_via_spdy = response_head.was_fetched_via_spdy;
+ response_info->was_alpn_negotiated = response_head.was_alpn_negotiated;
+ response_info->alpn_negotiated_protocol =
+ response_head.alpn_negotiated_protocol;
+ response_info->connection_info = response_head.connection_info;
+ response_info->socket_address = response_head.socket_address;
+
+ // TODO(momohatt): Check for header errors.
+
+ network_loader_state_ = NetworkLoaderState::kWaitingForBody;
+
+ WriteHeaders(
+ base::MakeRefCounted<HttpResponseInfoIOBuffer>(std::move(response_info)));
+}
+
+void ServiceWorkerSingleScriptUpdateChecker::OnReceiveRedirect(
+ const net::RedirectInfo& redirect_info,
+ const network::ResourceResponseHead& response_head) {
+ // TODO(momohatt): Raise error and terminate the update check here, like
+ // ServiceWorkerNewScriptLoader does.
+ NOTIMPLEMENTED();
+}
+
+void ServiceWorkerSingleScriptUpdateChecker::OnUploadProgress(
+ int64_t current_position,
+ int64_t total_size,
+ OnUploadProgressCallback ack_callback) {
+ // The network request for update checking shouldn't have upload data.
+ NOTREACHED();
+}
+
+void ServiceWorkerSingleScriptUpdateChecker::OnReceiveCachedMetadata(
+ const std::vector<uint8_t>& data) {}
+
+void ServiceWorkerSingleScriptUpdateChecker::OnTransferSizeUpdated(
+ int32_t transfer_size_diff) {
+ NOTIMPLEMENTED();
+}
+
+void ServiceWorkerSingleScriptUpdateChecker::OnStartLoadingResponseBody(
+ mojo::ScopedDataPipeConsumerHandle consumer) {
+ DCHECK_EQ(NetworkLoaderState::kWaitingForBody, network_loader_state_);
+
+ network_consumer_ = std::move(consumer);
+ network_loader_state_ = NetworkLoaderState::kLoadingBody;
+ MaybeStartNetworkConsumerHandleWatcher();
+}
+
+void ServiceWorkerSingleScriptUpdateChecker::OnComplete(
+ const network::URLLoaderCompletionStatus& status) {
+ NetworkLoaderState previous_loader_state = network_loader_state_;
+ network_loader_state_ = NetworkLoaderState::kCompleted;
+ if (status.error_code != net::OK) {
+ Finish(false /* is_script_changed */);
+ return;
+ }
+
+ DCHECK(previous_loader_state == NetworkLoaderState::kWaitingForBody ||
+ previous_loader_state == NetworkLoaderState::kLoadingBody);
+
+ // Response body is empty.
+ if (previous_loader_state == NetworkLoaderState::kWaitingForBody) {
+ DCHECK_EQ(CacheWriterState::kNotStarted, body_writer_state_);
+ body_writer_state_ = CacheWriterState::kCompleted;
+ switch (header_writer_state_) {
+ case CacheWriterState::kNotStarted:
+ NOTREACHED()
+ << "Response header should be received before OnComplete()";
+ break;
+ case CacheWriterState::kWriting:
+ // Wait until it's written. OnWriteHeadersComplete() will call
+ // Finish().
+ return;
+ case CacheWriterState::kCompleted:
+ DCHECK(!network_consumer_.is_valid());
+ // Compare the cached data with an empty data to notify |cache_writer_|
+ // of the end of the comparison.
+ CompareData(nullptr /* pending_buffer */, 0 /* bytes_available */);
+ break;
+ }
+ }
+
+ // Response body exists.
+ if (previous_loader_state == NetworkLoaderState::kLoadingBody) {
+ switch (body_writer_state_) {
+ case CacheWriterState::kNotStarted:
+ DCHECK_EQ(CacheWriterState::kWriting, header_writer_state_);
+ return;
+ case CacheWriterState::kWriting:
+ DCHECK_EQ(CacheWriterState::kCompleted, header_writer_state_);
+ return;
+ case CacheWriterState::kCompleted:
+ DCHECK_EQ(CacheWriterState::kCompleted, header_writer_state_);
+ Finish(false /* is_script_changed */);
+ return;
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+
+void ServiceWorkerSingleScriptUpdateChecker::WriteHeaders(
+ scoped_refptr<HttpResponseInfoIOBuffer> info_buffer) {
+ DCHECK_EQ(CacheWriterState::kNotStarted, header_writer_state_);
+ header_writer_state_ = CacheWriterState::kWriting;
+
+ // Pass the header to the cache_writer_. This is written to the storage when
+ // the body had changes.
+ net::Error error = cache_writer_->MaybeWriteHeaders(
+ info_buffer.get(),
+ base::BindOnce(
+ &ServiceWorkerSingleScriptUpdateChecker::OnWriteHeadersComplete,
+ weak_factory_.GetWeakPtr()));
+ if (error == net::ERR_IO_PENDING) {
+ // OnWriteHeadersComplete() will be called asynchronously.
+ return;
+ }
+ // MaybeWriteHeaders() doesn't run the callback if it finishes synchronously,
+ // so explicitly call it here.
+ OnWriteHeadersComplete(error);
+}
+
+void ServiceWorkerSingleScriptUpdateChecker::OnWriteHeadersComplete(
+ net::Error error) {
+ DCHECK_EQ(CacheWriterState::kWriting, header_writer_state_);
+ DCHECK_NE(net::ERR_IO_PENDING, error);
+ header_writer_state_ = CacheWriterState::kCompleted;
+
+ if (error != net::OK) {
+ Finish(false /* is_script_changed */);
+ return;
+ }
+
+ // Response body is empty.
+ if (network_loader_state_ == NetworkLoaderState::kCompleted &&
+ body_writer_state_ == CacheWriterState::kCompleted) {
+ // Compare the cached data with an empty data to notify |cache_writer_|
+ // the end of the comparison.
+ CompareData(nullptr /* pending_buffer */, 0 /* bytes_available */);
+ return;
+ }
+
+ MaybeStartNetworkConsumerHandleWatcher();
+}
+
+void ServiceWorkerSingleScriptUpdateChecker::
+ MaybeStartNetworkConsumerHandleWatcher() {
+ if (network_loader_state_ == NetworkLoaderState::kWaitingForBody) {
+ // OnStartLoadingResponseBody() or OnComplete() will continue the sequence.
+ return;
+ }
+ if (header_writer_state_ != CacheWriterState::kCompleted) {
+ DCHECK_EQ(CacheWriterState::kWriting, header_writer_state_);
+ // OnWriteHeadersComplete() will continue the sequence.
+ return;
+ }
+
+ DCHECK_EQ(CacheWriterState::kNotStarted, body_writer_state_);
+ body_writer_state_ = CacheWriterState::kWriting;
+
+ network_watcher_.Watch(
+ network_consumer_.get(),
+ MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
+ base::BindRepeating(
+ &ServiceWorkerSingleScriptUpdateChecker::OnNetworkDataAvailable,
+ weak_factory_.GetWeakPtr()));
+ network_watcher_.ArmOrNotify();
+}
+
+void ServiceWorkerSingleScriptUpdateChecker::OnNetworkDataAvailable(
+ MojoResult,
+ const mojo::HandleSignalsState& state) {
+ DCHECK_EQ(CacheWriterState::kCompleted, header_writer_state_);
+ DCHECK(network_consumer_.is_valid());
+ scoped_refptr<network::MojoToNetPendingBuffer> pending_buffer;
+ uint32_t bytes_available = 0;
+ MojoResult result = network::MojoToNetPendingBuffer::BeginRead(
+ &network_consumer_, &pending_buffer, &bytes_available);
+ switch (result) {
+ case MOJO_RESULT_OK:
+ CompareData(std::move(pending_buffer), bytes_available);
+ return;
+ case MOJO_RESULT_FAILED_PRECONDITION:
+ // Closed by peer. This indicates all the data from the network service
+ // are read or there is an error. In the error case, the reason is
+ // notified via OnComplete().
+ if (network_loader_state_ == NetworkLoaderState::kCompleted) {
+ // Compare the cached data with an empty data to notify |cache_writer_|
+ // the end of the comparison.
+ CompareData(nullptr /* pending_buffer */, 0 /* bytes_available */);
+ }
+ return;
+ case MOJO_RESULT_SHOULD_WAIT:
+ network_watcher_.ArmOrNotify();
+ return;
+ }
+ NOTREACHED() << static_cast<int>(result);
+}
+
+void ServiceWorkerSingleScriptUpdateChecker::CompareData(
+ scoped_refptr<network::MojoToNetPendingBuffer> pending_buffer,
+ uint32_t bytes_to_compare) {
+ auto buffer = base::MakeRefCounted<net::WrappedIOBuffer>(
+ pending_buffer ? pending_buffer->buffer() : nullptr);
+
+ // Compare the network data and the stored data.
+ net::Error error = cache_writer_->MaybeWriteData(
+ buffer.get(), bytes_to_compare,
+ base::BindOnce(
+ &ServiceWorkerSingleScriptUpdateChecker::OnCompareDataComplete,
+ weak_factory_.GetWeakPtr(),
+ base::WrapRefCounted(pending_buffer.get()), bytes_to_compare));
+
+ if (pending_buffer) {
+ pending_buffer->CompleteRead(bytes_to_compare);
+ network_consumer_ = pending_buffer->ReleaseHandle();
+ }
+
+ if (error == net::ERR_IO_PENDING && !cache_writer_->is_pausing()) {
+ // OnCompareDataComplete() will be called asynchronously.
+ return;
+ }
+ // MaybeWriteData() doesn't run the callback if it finishes synchronously, so
+ // explicitly call it here.
+ OnCompareDataComplete(std::move(pending_buffer), bytes_to_compare, error);
+}
+
+void ServiceWorkerSingleScriptUpdateChecker::OnCompareDataComplete(
+ scoped_refptr<network::MojoToNetPendingBuffer> pending_buffer,
+ uint32_t bytes_written,
+ net::Error error) {
+ if (cache_writer_->is_pausing()) {
+ // |cache_writer_| can be pausing only when it finds difference between
+ // stored body and network body.
+ DCHECK_EQ(net::ERR_IO_PENDING, error);
+ Finish(true /* is_script_changed */);
+ return;
+ }
+ if (!pending_buffer || error != net::OK) {
+ Finish(false /* is_script_changed */);
+ return;
+ }
+ DCHECK(pending_buffer);
+ network_watcher_.ArmOrNotify();
+}
+
+void ServiceWorkerSingleScriptUpdateChecker::Finish(bool is_script_changed) {
+ if (is_script_changed) {
+ // TODO(momohatt): pass the necessary information to the version to update.
+ } else {
+ network_loader_.reset();
+ network_client_binding_.Close();
+ network_consumer_.reset();
+ }
+ network_watcher_.Cancel();
+ network_loader_state_ = NetworkLoaderState::kCompleted;
+ header_writer_state_ = CacheWriterState::kCompleted;
+ body_writer_state_ = CacheWriterState::kCompleted;
+
+ std::move(callback_).Run(is_script_changed);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_single_script_update_checker.h b/chromium/content/browser/service_worker/service_worker_single_script_update_checker.h
new file mode 100644
index 00000000000..d006ae26cc1
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_single_script_update_checker.h
@@ -0,0 +1,141 @@
+// 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_SINGLE_SCRIPT_UPDATE_CHECKER_H_
+#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_SINGLE_SCRIPT_UPDATE_CHECKER_H_
+
+#include "content/browser/service_worker/service_worker_disk_cache.h"
+#include "content/common/content_export.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "services/network/public/mojom/url_loader.mojom.h"
+
+namespace network {
+class MojoToNetPendingBuffer;
+class SharedURLLoaderFactory;
+} // namespace network
+
+namespace content {
+
+struct HttpResponseInfoIOBuffer;
+class ServiceWorkerCacheWriter;
+
+// Executes byte-for-byte update check of one script. This loads the script from
+// the network and compares it with the stored counterpart read from
+// |compare_reader|. The result will be passed as an argument of |callback|:
+// true when they are identical and false otherwise. When |callback| is
+// triggered, |cache_writer_| owned by |this| should be paused if the scripts
+// were not identical.
+class CONTENT_EXPORT ServiceWorkerSingleScriptUpdateChecker
+ : public network::mojom::URLLoaderClient {
+ public:
+ using ResultCallback = base::OnceCallback<void(bool)>;
+
+ // Both |compare_reader| and |copy_reader| should be created from the same
+ // resource ID, and this ID should locate where the script specified with
+ // |url| is stored. |writer| should be created with a new resource ID.
+ ServiceWorkerSingleScriptUpdateChecker(
+ const GURL& url,
+ bool is_main_script,
+ scoped_refptr<network::SharedURLLoaderFactory> loader_factory,
+ std::unique_ptr<ServiceWorkerResponseReader> compare_reader,
+ std::unique_ptr<ServiceWorkerResponseReader> copy_reader,
+ std::unique_ptr<ServiceWorkerResponseWriter> writer,
+ ResultCallback callback);
+
+ ~ServiceWorkerSingleScriptUpdateChecker() override;
+
+ // network::mojom::URLLoaderClient override:
+ void OnReceiveResponse(
+ const network::ResourceResponseHead& response_head) override;
+ void OnReceiveRedirect(
+ const net::RedirectInfo& redirect_info,
+ const network::ResourceResponseHead& response_head) override;
+ void OnUploadProgress(int64_t current_position,
+ int64_t total_size,
+ OnUploadProgressCallback ack_callback) override;
+ void OnReceiveCachedMetadata(const std::vector<uint8_t>& data) override;
+ void OnTransferSizeUpdated(int32_t transfer_size_diff) override;
+ void OnStartLoadingResponseBody(
+ mojo::ScopedDataPipeConsumerHandle consumer) override;
+ void OnComplete(const network::URLLoaderCompletionStatus& status) override;
+
+ private:
+ enum class NetworkLoaderState {
+ kNotStarted,
+ kLoadingHeader,
+ kWaitingForBody,
+ kLoadingBody,
+ kCompleted
+ };
+
+ enum class CacheWriterState { kNotStarted, kWriting, kCompleted };
+
+ void WriteHeaders(scoped_refptr<HttpResponseInfoIOBuffer> info_buffer);
+ void OnWriteHeadersComplete(net::Error error);
+
+ void MaybeStartNetworkConsumerHandleWatcher();
+ void OnNetworkDataAvailable(MojoResult,
+ const mojo::HandleSignalsState& state);
+ void CompareData(
+ scoped_refptr<network::MojoToNetPendingBuffer> pending_buffer,
+ uint32_t bytes_available);
+ void OnCompareDataComplete(
+ scoped_refptr<network::MojoToNetPendingBuffer> pending_buffer,
+ uint32_t bytes_written,
+ net::Error error);
+ void Finish(bool is_script_changed);
+
+ network::mojom::URLLoaderPtr network_loader_;
+ mojo::Binding<network::mojom::URLLoaderClient> network_client_binding_;
+ mojo::ScopedDataPipeConsumerHandle network_consumer_;
+ mojo::SimpleWatcher network_watcher_;
+
+ std::unique_ptr<ServiceWorkerCacheWriter> cache_writer_;
+ ResultCallback callback_;
+
+ // Represents the state of |network_loader_|.
+ // Corresponds to the steps described in the class comments.
+ //
+ // When response body exists:
+ // CreateLoaderAndStart(): kNotStarted -> kLoadingHeader
+ // OnReceiveResponse(): kLoadingHeader -> kWaitingForBody
+ // OnStartLoadingResponseBody(): kWaitingForBody -> kLoadingBody
+ // OnComplete(): kLoadingBody -> kCompleted
+ //
+ // When response body is empty:
+ // CreateLoaderAndStart(): kNotStarted -> kLoadingHeader
+ // OnReceiveResponse(): kLoadingHeader -> kWaitingForBody
+ // OnComplete(): kWaitingForBody -> kCompleted
+ NetworkLoaderState network_loader_state_ = NetworkLoaderState::kNotStarted;
+
+ // Represents the state of |cache_writer_|.
+ // Set to kWriting when it starts to send the header to |cache_writer_|, and
+ // set to kCompleted when the header has been sent.
+ //
+ // OnReceiveResponse(): kNotStarted -> kWriting (in WriteHeaders())
+ // OnWriteHeadersComplete(): kWriting -> kCompleted
+ CacheWriterState header_writer_state_ = CacheWriterState::kNotStarted;
+
+ // Represents the state of |cache_writer_| and |network_consumer_|.
+ // Set to kWriting when |this| starts watching |network_consumer_|, and set to
+ // kCompleted when |cache_writer_| reports any difference between the stored
+ // body and the network body, or the entire body is compared without any
+ // difference.
+ //
+ // When response body exists:
+ // OnStartLoadingResponseBody() && OnWriteHeadersComplete():
+ // kNotStarted -> kWriting
+ // OnNetworkDataAvailable() && MOJO_RESULT_FAILED_PRECONDITION:
+ // kWriting -> kCompleted
+ //
+ // When response body is empty:
+ // OnComplete(): kNotStarted -> kCompleted
+ CacheWriterState body_writer_state_ = CacheWriterState::kNotStarted;
+
+ base::WeakPtrFactory<ServiceWorkerSingleScriptUpdateChecker> weak_factory_;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_SINGLE_SCRIPT_UPDATE_CHECKER_H_
diff --git a/chromium/content/browser/service_worker/service_worker_single_script_update_checker_unittest.cc b/chromium/content/browser/service_worker/service_worker_single_script_update_checker_unittest.cc
new file mode 100644
index 00000000000..cc2188cdab5
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_single_script_update_checker_unittest.cc
@@ -0,0 +1,288 @@
+// 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_single_script_update_checker.h"
+
+#include <vector>
+#include "base/containers/queue.h"
+#include "base/run_loop.h"
+#include "content/browser/service_worker/embedded_worker_test_helper.h"
+#include "content/browser/service_worker/service_worker_context_core.h"
+#include "content/browser/service_worker/service_worker_storage.h"
+#include "content/browser/service_worker/service_worker_test_utils.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "net/http/http_util.h"
+#include "services/network/test/test_url_loader_factory.h"
+
+namespace content {
+namespace {
+
+constexpr char kScriptURL[] = "https://example.com/script.js";
+constexpr char kSuccessHeader[] =
+ "HTTP/1.1 200 OK\n"
+ "Content-Type: text/javascript\n\n";
+
+class ServiceWorkerSingleScriptUpdateCheckerTest : public testing::Test {
+ public:
+ ServiceWorkerSingleScriptUpdateCheckerTest()
+ : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {}
+ ~ServiceWorkerSingleScriptUpdateCheckerTest() override = default;
+
+ ServiceWorkerStorage* storage() { return helper_->context()->storage(); }
+
+ void SetUp() override {
+ helper_ = std::make_unique<EmbeddedWorkerTestHelper>(base::FilePath());
+ base::RunLoop run_loop;
+ storage()->LazyInitializeForTest(run_loop.QuitClosure());
+ run_loop.Run();
+ }
+
+ size_t TotalBytes(const std::vector<std::string>& data_chunks) {
+ size_t bytes = 0;
+ for (const auto& data : data_chunks)
+ bytes += data.size();
+ return bytes;
+ }
+
+ std::unique_ptr<ServiceWorkerSingleScriptUpdateChecker>
+ CreateSingleScriptUpdateChecker(
+ const char* url,
+ std::unique_ptr<ServiceWorkerResponseReader> compare_reader,
+ std::unique_ptr<ServiceWorkerResponseReader> copy_reader,
+ std::unique_ptr<ServiceWorkerResponseWriter> writer,
+ network::TestURLLoaderFactory* loader_factory,
+ base::Optional<bool>* out_script_changed) {
+ helper_->SetNetworkFactory(loader_factory);
+ return std::make_unique<ServiceWorkerSingleScriptUpdateChecker>(
+ GURL(url), true /* is_main_script */,
+ helper_->url_loader_factory_getter()->GetNetworkFactory(),
+ std::move(compare_reader), std::move(copy_reader), std::move(writer),
+ base::BindOnce(
+ [](base::Optional<bool>* out_script_changed, bool script_changed) {
+ *out_script_changed = script_changed;
+ },
+ out_script_changed));
+ }
+
+ std::unique_ptr<network::TestURLLoaderFactory> CreateLoaderFactoryWithRespone(
+ const GURL& url,
+ std::string header,
+ std::string body,
+ net::Error error) {
+ auto loader_factory = std::make_unique<network::TestURLLoaderFactory>();
+ network::ResourceResponseHead head;
+ head.headers = base::MakeRefCounted<net::HttpResponseHeaders>(
+ net::HttpUtil::AssembleRawHeaders(header.c_str(), header.size()));
+ network::URLLoaderCompletionStatus status(error);
+ status.decoded_body_length = body.size();
+ loader_factory->AddResponse(url, head, body, status);
+ return loader_factory;
+ }
+
+ protected:
+ TestBrowserThreadBundle thread_bundle_;
+ std::unique_ptr<EmbeddedWorkerTestHelper> helper_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ServiceWorkerSingleScriptUpdateCheckerTest);
+};
+
+TEST_F(ServiceWorkerSingleScriptUpdateCheckerTest, Identical_SingleSyncRead) {
+ // Response body from the network.
+ const std::string body_from_net("abcdef");
+
+ // Stored data for |kScriptURL|.
+ const std::vector<std::string> body_from_storage{body_from_net};
+
+ std::unique_ptr<network::TestURLLoaderFactory> loader_factory =
+ CreateLoaderFactoryWithRespone(GURL(kScriptURL), kSuccessHeader,
+ body_from_net, net::OK);
+
+ auto compare_reader = std::make_unique<MockServiceWorkerResponseReader>();
+ auto copy_reader = std::make_unique<MockServiceWorkerResponseReader>();
+ auto writer = std::make_unique<MockServiceWorkerResponseWriter>();
+ MockServiceWorkerResponseReader* compare_reader_rawptr = compare_reader.get();
+ compare_reader->ExpectReadOk(body_from_storage, TotalBytes(body_from_storage),
+ false /* async */);
+
+ base::Optional<bool> script_changed;
+ std::unique_ptr<ServiceWorkerSingleScriptUpdateChecker> checker =
+ CreateSingleScriptUpdateChecker(kScriptURL, std::move(compare_reader),
+ std::move(copy_reader), std::move(writer),
+ loader_factory.get(), &script_changed);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(script_changed.has_value());
+ EXPECT_FALSE(script_changed.value());
+ EXPECT_TRUE(compare_reader_rawptr->AllExpectedReadsDone());
+}
+
+TEST_F(ServiceWorkerSingleScriptUpdateCheckerTest, Different_SingleSyncRead) {
+ // Response body from the network.
+ const std::string body_from_net("abcdef");
+
+ // Stored data for |kScriptURL|.
+ const std::vector<std::string> body_from_storage{"abxx"};
+
+ std::unique_ptr<network::TestURLLoaderFactory> loader_factory =
+ CreateLoaderFactoryWithRespone(GURL(kScriptURL), kSuccessHeader,
+ body_from_net, net::OK);
+
+ auto compare_reader = std::make_unique<MockServiceWorkerResponseReader>();
+ auto copy_reader = std::make_unique<MockServiceWorkerResponseReader>();
+ auto writer = std::make_unique<MockServiceWorkerResponseWriter>();
+ MockServiceWorkerResponseReader* compare_reader_rawptr = compare_reader.get();
+ compare_reader->ExpectReadOk(body_from_storage, TotalBytes(body_from_storage),
+ false /* async */);
+
+ base::Optional<bool> script_changed;
+ std::unique_ptr<ServiceWorkerSingleScriptUpdateChecker> checker =
+ CreateSingleScriptUpdateChecker(kScriptURL, std::move(compare_reader),
+ std::move(copy_reader), std::move(writer),
+ loader_factory.get(), &script_changed);
+
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(script_changed.has_value());
+ EXPECT_TRUE(script_changed.value());
+ EXPECT_TRUE(compare_reader_rawptr->AllExpectedReadsDone());
+}
+
+TEST_F(ServiceWorkerSingleScriptUpdateCheckerTest, Different_MultipleSyncRead) {
+ // Response body from the network.
+ const std::string body_from_net("abcdef");
+
+ // Stored data for |kScriptURL| (the data for compare reader).
+ // The comparison should stop in the second block of data.
+ const std::vector<std::string> body_from_storage{"ab", "cx"};
+
+ std::unique_ptr<network::TestURLLoaderFactory> loader_factory =
+ CreateLoaderFactoryWithRespone(GURL(kScriptURL), kSuccessHeader,
+ body_from_net, net::OK);
+
+ auto compare_reader = std::make_unique<MockServiceWorkerResponseReader>();
+ auto copy_reader = std::make_unique<MockServiceWorkerResponseReader>();
+ auto writer = std::make_unique<MockServiceWorkerResponseWriter>();
+ MockServiceWorkerResponseReader* compare_reader_rawptr = compare_reader.get();
+ compare_reader->ExpectReadOk(body_from_storage, TotalBytes(body_from_storage),
+ false /* async */);
+
+ base::Optional<bool> script_changed;
+ std::unique_ptr<ServiceWorkerSingleScriptUpdateChecker> checker =
+ CreateSingleScriptUpdateChecker(kScriptURL, std::move(compare_reader),
+ std::move(copy_reader), std::move(writer),
+ loader_factory.get(), &script_changed);
+
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(script_changed.has_value());
+ EXPECT_TRUE(script_changed.value());
+ EXPECT_TRUE(compare_reader_rawptr->AllExpectedReadsDone());
+}
+
+TEST_F(ServiceWorkerSingleScriptUpdateCheckerTest, NetworkDataLong_SyncRead) {
+ // Response body from the network.
+ const std::string body_from_net("abcdef");
+
+ // Stored data for |kScriptURL| (the data for compare reader).
+ const std::vector<std::string> body_from_storage{"ab", "cd", ""};
+
+ std::unique_ptr<network::TestURLLoaderFactory> loader_factory =
+ CreateLoaderFactoryWithRespone(GURL(kScriptURL), kSuccessHeader,
+ body_from_net, net::OK);
+
+ auto compare_reader = std::make_unique<MockServiceWorkerResponseReader>();
+ auto copy_reader = std::make_unique<MockServiceWorkerResponseReader>();
+ auto writer = std::make_unique<MockServiceWorkerResponseWriter>();
+ MockServiceWorkerResponseReader* compare_reader_rawptr = compare_reader.get();
+ compare_reader->ExpectReadOk(body_from_storage, TotalBytes(body_from_storage),
+ false /* async */);
+
+ base::Optional<bool> script_changed;
+ std::unique_ptr<ServiceWorkerSingleScriptUpdateChecker> checker =
+ CreateSingleScriptUpdateChecker(kScriptURL, std::move(compare_reader),
+ std::move(copy_reader), std::move(writer),
+ loader_factory.get(), &script_changed);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(script_changed.has_value());
+ EXPECT_TRUE(script_changed.value());
+ EXPECT_TRUE(compare_reader_rawptr->AllExpectedReadsDone());
+}
+
+TEST_F(ServiceWorkerSingleScriptUpdateCheckerTest, NetworkDataShort_SyncRead) {
+ // Response body from the network.
+ const std::string body_from_net("abcdef");
+
+ // Stored data for |kScriptURL| (the data for compare reader).
+ const std::vector<std::string> body_in_storage{"ab", "cd", "ef", "gh"};
+
+ // Stored data that will actually be read from the compare reader.
+ // The last 2 bytes of |body_in_storage| won't be read.
+ const std::vector<std::string> body_read_from_storage{"ab", "cd", "ef"};
+
+ std::unique_ptr<network::TestURLLoaderFactory> loader_factory =
+ CreateLoaderFactoryWithRespone(GURL(kScriptURL), kSuccessHeader,
+ body_from_net, net::OK);
+
+ auto compare_reader = std::make_unique<MockServiceWorkerResponseReader>();
+ auto copy_reader = std::make_unique<MockServiceWorkerResponseReader>();
+ auto writer = std::make_unique<MockServiceWorkerResponseWriter>();
+ MockServiceWorkerResponseReader* compare_reader_rawptr = compare_reader.get();
+ compare_reader->ExpectReadOk(body_read_from_storage,
+ TotalBytes(body_in_storage), false /* async */);
+
+ base::Optional<bool> script_changed;
+ std::unique_ptr<ServiceWorkerSingleScriptUpdateChecker> checker =
+ CreateSingleScriptUpdateChecker(kScriptURL, std::move(compare_reader),
+ std::move(copy_reader), std::move(writer),
+ loader_factory.get(), &script_changed);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(script_changed.has_value());
+ EXPECT_TRUE(script_changed.value());
+ EXPECT_TRUE(compare_reader_rawptr->AllExpectedReadsDone());
+}
+
+TEST_F(ServiceWorkerSingleScriptUpdateCheckerTest, Identical_SingleAsyncRead) {
+ // Response body from the network.
+ const std::string body_from_net("abcdef");
+
+ // Stored data for |kScriptURL| (the data for compare reader).
+ const std::vector<std::string> body_from_storage{body_from_net};
+
+ std::unique_ptr<network::TestURLLoaderFactory> loader_factory =
+ CreateLoaderFactoryWithRespone(GURL(kScriptURL), kSuccessHeader,
+ body_from_net, net::OK);
+
+ auto compare_reader = std::make_unique<MockServiceWorkerResponseReader>();
+ auto copy_reader = std::make_unique<MockServiceWorkerResponseReader>();
+ auto writer = std::make_unique<MockServiceWorkerResponseWriter>();
+ MockServiceWorkerResponseReader* compare_reader_rawptr = compare_reader.get();
+ compare_reader->ExpectReadOk(body_from_storage, TotalBytes(body_from_storage),
+ true /* async */);
+
+ base::Optional<bool> script_changed;
+ std::unique_ptr<ServiceWorkerSingleScriptUpdateChecker> checker =
+ CreateSingleScriptUpdateChecker(kScriptURL, std::move(compare_reader),
+ std::move(copy_reader), std::move(writer),
+ loader_factory.get(), &script_changed);
+
+ // Update check stops in WriteHeader() due to the asynchronous read of the
+ // |compare_reader|.
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(script_changed.has_value());
+
+ // Continue the update check and trigger OnWriteHeadersComplete(). The resumed
+ // update check stops again at CompareData().
+ compare_reader_rawptr->CompletePendingRead();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(script_changed.has_value());
+
+ // Continue the update check and trigger OnCompareDataComplete(). This will
+ // finish the entire update check.
+ compare_reader_rawptr->CompletePendingRead();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(script_changed.has_value());
+ EXPECT_FALSE(script_changed.value());
+ EXPECT_TRUE(compare_reader_rawptr->AllExpectedReadsDone());
+}
+
+} // namespace
+} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_storage.cc b/chromium/content/browser/service_worker/service_worker_storage.cc
index 92b13a6c60e..ca3e8917c36 100644
--- a/chromium/content/browser/service_worker/service_worker_storage.cc
+++ b/chromium/content/browser/service_worker/service_worker_storage.cc
@@ -431,8 +431,9 @@ void ServiceWorkerStorage::StoreRegistration(
ServiceWorkerDatabase::RegistrationData data;
data.registration_id = registration->id();
data.scope = registration->pattern();
- data.update_via_cache = registration->update_via_cache();
data.script = version->script_url();
+ data.script_type = version->script_type();
+ data.update_via_cache = registration->update_via_cache();
data.has_fetch_handler = version->fetch_handler_existence() ==
ServiceWorkerVersion::FetchHandlerExistence::EXISTS;
data.version_id = version->version_id();
@@ -1537,8 +1538,8 @@ ServiceWorkerStorage::GetOrCreateRegistration(
if (registration)
return registration;
- blink::mojom::ServiceWorkerRegistrationOptions options(data.scope,
- data.update_via_cache);
+ blink::mojom::ServiceWorkerRegistrationOptions options(
+ data.scope, data.script_type, data.update_via_cache);
registration =
new ServiceWorkerRegistration(options, data.registration_id, context_);
registration->set_resources_total_size_bytes(data.resources_total_size_bytes);
@@ -1550,8 +1551,9 @@ ServiceWorkerStorage::GetOrCreateRegistration(
scoped_refptr<ServiceWorkerVersion> version =
context_->GetLiveVersion(data.version_id);
if (!version) {
- version = new ServiceWorkerVersion(
- registration.get(), data.script, data.version_id, context_);
+ version = base::MakeRefCounted<ServiceWorkerVersion>(
+ registration.get(), data.script, data.script_type, data.version_id,
+ context_);
version->set_fetch_handler_existence(
data.has_fetch_handler
? ServiceWorkerVersion::FetchHandlerExistence::EXISTS
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 9d1aab24ec6..818540eb154 100644
--- a/chromium/content/browser/service_worker/service_worker_storage_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_storage_unittest.cc
@@ -69,10 +69,10 @@ const uint8_t kTestPublicKey[] = {
};
void StatusAndQuitCallback(blink::ServiceWorkerStatusCode* result,
- const base::Closure& quit_closure,
+ base::OnceClosure quit_closure,
blink::ServiceWorkerStatusCode status) {
*result = status;
- quit_closure.Run();
+ std::move(quit_closure).Run();
}
void StatusCallback(bool* was_called,
@@ -200,7 +200,8 @@ int WriteStringResponse(ServiceWorkerStorage* storage,
int64_t id,
const std::string& headers,
const std::string& body) {
- scoped_refptr<IOBuffer> body_buffer(new WrappedIOBuffer(body.data()));
+ scoped_refptr<IOBuffer> body_buffer =
+ base::MakeRefCounted<WrappedIOBuffer>(body.data());
return WriteResponse(storage, id, headers, body_buffer.get(), body.length());
}
@@ -237,7 +238,8 @@ bool VerifyBasicResponse(ServiceWorkerStorage* storage,
std::string received_body;
const int kBigEnough = 512;
- scoped_refptr<net::IOBuffer> buffer = new IOBuffer(kBigEnough);
+ scoped_refptr<net::IOBuffer> buffer =
+ base::MakeRefCounted<IOBuffer>(kBigEnough);
TestCompletionCallback cb;
reader->ReadData(buffer.get(), kBigEnough, cb.callback());
rv = cb.WaitForResult();
@@ -259,7 +261,8 @@ bool VerifyBasicResponse(ServiceWorkerStorage* storage,
int WriteResponseMetadata(ServiceWorkerStorage* storage,
int64_t id,
const std::string& metadata) {
- scoped_refptr<IOBuffer> body_buffer(new WrappedIOBuffer(metadata.data()));
+ scoped_refptr<IOBuffer> body_buffer =
+ base::MakeRefCounted<WrappedIOBuffer>(metadata.data());
std::unique_ptr<ServiceWorkerResponseMetadataWriter> metadata_writer =
storage->CreateResponseMetadataWriter(id);
TestCompletionCallback cb;
@@ -368,8 +371,8 @@ class ServiceWorkerStorageTest : public testing::Test {
auto registration = base::MakeRefCounted<ServiceWorkerRegistration>(
options, storage()->NewRegistrationId(), context()->AsWeakPtr());
auto version = base::MakeRefCounted<ServiceWorkerVersion>(
- registration.get(), script, storage()->NewVersionId(),
- context()->AsWeakPtr());
+ registration.get(), script, blink::mojom::ScriptType::kClassic,
+ storage()->NewVersionId(), context()->AsWeakPtr());
std::vector<ResourceRecord> records = {
ResourceRecord(storage()->NewResourceId(), script, 100)};
version->script_cache_map()->SetResources(records);
@@ -646,7 +649,8 @@ TEST_F(ServiceWorkerStorageTest, DisabledStorage) {
new ServiceWorkerRegistration(options, kRegistrationId,
context()->AsWeakPtr());
scoped_refptr<ServiceWorkerVersion> live_version = new ServiceWorkerVersion(
- live_registration.get(), kScript, kVersionId, context()->AsWeakPtr());
+ live_registration.get(), kScript, blink::mojom::ScriptType::kClassic,
+ kVersionId, context()->AsWeakPtr());
EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorAbort,
StoreRegistration(live_registration, live_version));
@@ -734,7 +738,8 @@ TEST_F(ServiceWorkerStorageTest, StoreFindUpdateDeleteRegistration) {
new ServiceWorkerRegistration(options, kRegistrationId,
context()->AsWeakPtr());
scoped_refptr<ServiceWorkerVersion> live_version = new ServiceWorkerVersion(
- live_registration.get(), kResource1, kVersionId, context()->AsWeakPtr());
+ live_registration.get(), kResource1, blink::mojom::ScriptType::kClassic,
+ kVersionId, context()->AsWeakPtr());
live_version->set_fetch_handler_existence(
ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
live_version->SetStatus(ServiceWorkerVersion::INSTALLED);
@@ -904,7 +909,8 @@ TEST_F(ServiceWorkerStorageTest, InstallingRegistrationsAreFindable) {
new ServiceWorkerRegistration(options, kRegistrationId,
context()->AsWeakPtr());
scoped_refptr<ServiceWorkerVersion> live_version = new ServiceWorkerVersion(
- live_registration.get(), kScript, kVersionId, context()->AsWeakPtr());
+ live_registration.get(), kScript, blink::mojom::ScriptType::kClassic,
+ kVersionId, context()->AsWeakPtr());
live_version->SetStatus(ServiceWorkerVersion::INSTALLING);
live_registration->SetWaitingVersion(live_version);
@@ -1657,8 +1663,8 @@ TEST_F(ServiceWorkerResourceStorageTest, UpdateRegistration) {
// Make an updated registration.
scoped_refptr<ServiceWorkerVersion> live_version = new ServiceWorkerVersion(
- registration_.get(), script_, storage()->NewVersionId(),
- context()->AsWeakPtr());
+ registration_.get(), script_, blink::mojom::ScriptType::kClassic,
+ storage()->NewVersionId(), context()->AsWeakPtr());
live_version->SetStatus(ServiceWorkerVersion::NEW);
registration_->SetWaitingVersion(live_version);
std::vector<ResourceRecord> records;
@@ -1859,7 +1865,8 @@ TEST_F(ServiceWorkerStorageOriginTrialsDiskTest, FromMainScript) {
new ServiceWorkerRegistration(options, kRegistrationId,
context()->AsWeakPtr());
scoped_refptr<ServiceWorkerVersion> version = new ServiceWorkerVersion(
- registration.get(), kScript, kVersionId, context()->AsWeakPtr());
+ registration.get(), kScript, blink::mojom::ScriptType::kClassic,
+ kVersionId, context()->AsWeakPtr());
net::HttpResponseInfo http_info;
http_info.ssl_info.cert =
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 05e9cb72dea..ec53a3c6872 100644
--- a/chromium/content/browser/service_worker/service_worker_test_utils.cc
+++ b/chromium/content/browser/service_worker/service_worker_test_utils.cc
@@ -281,4 +281,175 @@ WriteToDiskCacheWithCustomResponseInfoAsync(
body.size());
}
+MockServiceWorkerResponseReader::MockServiceWorkerResponseReader()
+ : ServiceWorkerResponseReader(/* resource_id=*/0, /*disk_cache=*/nullptr) {}
+
+MockServiceWorkerResponseReader::~MockServiceWorkerResponseReader() {}
+
+void MockServiceWorkerResponseReader::ReadInfo(
+ HttpResponseInfoIOBuffer* info_buf,
+ OnceCompletionCallback callback) {
+ DCHECK(!expected_reads_.empty());
+ ExpectedRead expected = expected_reads_.front();
+ EXPECT_TRUE(expected.info);
+ if (expected.async) {
+ pending_info_ = info_buf;
+ pending_callback_ = std::move(callback);
+ } else {
+ expected_reads_.pop();
+ info_buf->response_data_size = expected.len;
+ std::move(callback).Run(expected.result);
+ }
+}
+
+void MockServiceWorkerResponseReader::ReadData(
+ net::IOBuffer* buf,
+ int buf_len,
+ OnceCompletionCallback callback) {
+ DCHECK(!expected_reads_.empty());
+ ExpectedRead expected = expected_reads_.front();
+ EXPECT_FALSE(expected.info);
+ if (expected.async) {
+ pending_callback_ = std::move(callback);
+ pending_buffer_ = buf;
+ pending_buffer_len_ = static_cast<size_t>(buf_len);
+ } else {
+ expected_reads_.pop();
+ if (expected.len > 0) {
+ size_t to_read = std::min(static_cast<size_t>(buf_len), expected.len);
+ memcpy(buf->data(), expected.data, to_read);
+ }
+ std::move(callback).Run(expected.result);
+ }
+}
+
+void MockServiceWorkerResponseReader::ExpectReadInfo(size_t len,
+ bool async,
+ int result) {
+ expected_reads_.push(ExpectedRead(len, async, result));
+}
+
+void MockServiceWorkerResponseReader::ExpectReadInfoOk(size_t len, bool async) {
+ expected_reads_.push(ExpectedRead(len, async, len));
+}
+
+void MockServiceWorkerResponseReader::ExpectReadData(const char* data,
+ size_t len,
+ bool async,
+ int result) {
+ expected_reads_.push(ExpectedRead(data, len, async, result));
+}
+
+void MockServiceWorkerResponseReader::ExpectReadDataOk(const std::string& data,
+ bool async) {
+ expected_reads_.push(
+ ExpectedRead(data.data(), data.size(), async, data.size()));
+}
+
+void MockServiceWorkerResponseReader::ExpectReadOk(
+ const std::vector<std::string>& stored_data,
+ const size_t bytes_stored,
+ const bool async) {
+ ExpectReadInfoOk(bytes_stored, async);
+ for (const auto& data : stored_data)
+ ExpectReadDataOk(data, async);
+}
+
+void MockServiceWorkerResponseReader::CompletePendingRead() {
+ DCHECK(!expected_reads_.empty());
+ ExpectedRead expected = expected_reads_.front();
+ expected_reads_.pop();
+ EXPECT_TRUE(expected.async);
+ if (expected.info) {
+ pending_info_->response_data_size = expected.len;
+ } else {
+ size_t to_read = std::min(pending_buffer_len_, expected.len);
+ if (to_read > 0)
+ memcpy(pending_buffer_->data(), expected.data, to_read);
+ }
+ pending_info_ = nullptr;
+ pending_buffer_ = nullptr;
+ OnceCompletionCallback callback = std::move(pending_callback_);
+ pending_callback_.Reset();
+ std::move(callback).Run(expected.result);
+}
+
+MockServiceWorkerResponseWriter::MockServiceWorkerResponseWriter()
+ : ServiceWorkerResponseWriter(/*resource_id=*/0, /*disk_cache=*/nullptr),
+ info_written_(0),
+ data_written_(0) {}
+
+MockServiceWorkerResponseWriter::~MockServiceWorkerResponseWriter() = default;
+
+void MockServiceWorkerResponseWriter::WriteInfo(
+ HttpResponseInfoIOBuffer* info_buf,
+ OnceCompletionCallback callback) {
+ DCHECK(!expected_writes_.empty());
+ ExpectedWrite write = expected_writes_.front();
+ EXPECT_TRUE(write.is_info);
+ if (write.result > 0) {
+ EXPECT_EQ(write.length, static_cast<size_t>(info_buf->response_data_size));
+ info_written_ += info_buf->response_data_size;
+ }
+ if (!write.async) {
+ expected_writes_.pop();
+ std::move(callback).Run(write.result);
+ } else {
+ pending_callback_ = std::move(callback);
+ }
+}
+
+void MockServiceWorkerResponseWriter::WriteData(
+ net::IOBuffer* buf,
+ int buf_len,
+ OnceCompletionCallback callback) {
+ DCHECK(!expected_writes_.empty());
+ ExpectedWrite write = expected_writes_.front();
+ EXPECT_FALSE(write.is_info);
+ if (write.result > 0) {
+ EXPECT_EQ(write.length, static_cast<size_t>(buf_len));
+ data_written_ += buf_len;
+ }
+ if (!write.async) {
+ expected_writes_.pop();
+ std::move(callback).Run(write.result);
+ } else {
+ pending_callback_ = std::move(callback);
+ }
+}
+
+void MockServiceWorkerResponseWriter::ExpectWriteInfoOk(size_t length,
+ bool async) {
+ ExpectWriteInfo(length, async, length);
+}
+
+void MockServiceWorkerResponseWriter::ExpectWriteDataOk(size_t length,
+ bool async) {
+ ExpectWriteData(length, async, length);
+}
+
+void MockServiceWorkerResponseWriter::ExpectWriteInfo(size_t length,
+ bool async,
+ int result) {
+ DCHECK_NE(net::ERR_IO_PENDING, result);
+ ExpectedWrite expected(true, length, async, result);
+ expected_writes_.push(expected);
+}
+
+void MockServiceWorkerResponseWriter::ExpectWriteData(size_t length,
+ bool async,
+ int result) {
+ DCHECK_NE(net::ERR_IO_PENDING, result);
+ ExpectedWrite expected(false, length, async, result);
+ expected_writes_.push(expected);
+}
+
+void MockServiceWorkerResponseWriter::CompletePendingWrite() {
+ DCHECK(!expected_writes_.empty());
+ ExpectedWrite write = expected_writes_.front();
+ DCHECK(write.async);
+ expected_writes_.pop();
+ std::move(pending_callback_).Run(write.result);
+}
+
} // namespace content
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 7b550c6efd0..aa81bbfca95 100644
--- a/chromium/content/browser/service_worker/service_worker_test_utils.h
+++ b/chromium/content/browser/service_worker/service_worker_test_utils.h
@@ -11,8 +11,11 @@
#include "base/callback.h"
#include "base/command_line.h"
#include "base/memory/weak_ptr.h"
+#include "base/task/post_task.h"
#include "content/browser/service_worker/service_worker_database.h"
+#include "content/browser/service_worker/service_worker_disk_cache.h"
#include "content/common/service_worker/service_worker_provider.mojom.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_switches.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -33,29 +36,30 @@ class ServiceWorkerVersion;
template <typename Arg>
void ReceiveResult(BrowserThread::ID run_quit_thread,
- const base::Closure& quit,
+ base::OnceClosure quit,
base::Optional<Arg>* out,
Arg actual) {
*out = actual;
if (!quit.is_null())
- BrowserThread::PostTask(run_quit_thread, FROM_HERE, quit);
+ base::PostTaskWithTraits(FROM_HERE, {run_quit_thread}, std::move(quit));
}
template <typename Arg>
base::OnceCallback<void(Arg)> CreateReceiver(BrowserThread::ID run_quit_thread,
- const base::RepeatingClosure& quit,
+ base::OnceClosure quit,
base::Optional<Arg>* out) {
- return base::BindOnce(&ReceiveResult<Arg>, run_quit_thread, quit, out);
+ return base::BindOnce(&ReceiveResult<Arg>, run_quit_thread, std::move(quit),
+ out);
}
template <typename Arg>
base::OnceCallback<void(Arg)> CreateReceiverOnCurrentThread(
base::Optional<Arg>* out,
- const base::Closure& quit = base::Closure()) {
+ base::OnceClosure quit = base::OnceClosure()) {
BrowserThread::ID id;
bool ret = BrowserThread::GetCurrentThreadIdentifier(&id);
DCHECK(ret);
- return CreateReceiver(id, quit, out);
+ return CreateReceiver(id, std::move(quit), out);
}
// Container for keeping the Mojo connection to the service worker provider on
@@ -162,6 +166,154 @@ WriteToDiskCacheWithCustomResponseInfoAsync(
const std::string& meta_data,
base::OnceClosure callback);
+// A test implementation of ServiceWorkerResponseReader.
+//
+// This class exposes the ability to expect reads (see ExpectRead*() below).
+// Each call to ReadInfo() or ReadData() consumes another expected read, in the
+// order those reads were expected, so:
+// reader->ExpectReadInfoOk(5, false);
+// reader->ExpectReadDataOk("abcdef", false);
+// reader->ExpectReadDataOk("ghijkl", false);
+// Expects these calls, in this order:
+// reader->ReadInfo(...); // reader writes 5 into
+// // |info_buf->response_data_size|
+// reader->ReadData(...); // reader writes "abcdef" into |buf|
+// reader->ReadData(...); // reader writes "ghijkl" into |buf|
+// If an unexpected call happens, this class DCHECKs.
+// If an expected read is marked "async", it will not complete immediately, but
+// must be completed by the test using CompletePendingRead().
+// These is a convenience method AllExpectedReadsDone() which returns whether
+// there are any expected reads that have not yet happened.
+class MockServiceWorkerResponseReader : public ServiceWorkerResponseReader {
+ public:
+ MockServiceWorkerResponseReader();
+ ~MockServiceWorkerResponseReader() override;
+
+ // ServiceWorkerResponseReader overrides
+ void ReadInfo(HttpResponseInfoIOBuffer* info_buf,
+ OnceCompletionCallback callback) override;
+ void ReadData(net::IOBuffer* buf,
+ int buf_len,
+ OnceCompletionCallback callback) override;
+
+ // Test helpers. ExpectReadInfo() and ExpectReadData() give precise control
+ // over both the data to be written and the result to return.
+ // ExpectReadInfoOk() and ExpectReadDataOk() are convenience functions for
+ // expecting successful reads, which always have their length as their result.
+
+ // Expect a call to ReadInfo() on this reader. For these functions, |len| will
+ // be used as |response_data_size|, not as the length of this particular read.
+ void ExpectReadInfo(size_t len, bool async, int result);
+ void ExpectReadInfoOk(size_t len, bool async);
+
+ // Expect a call to ReadData() on this reader. For these functions, |len| is
+ // the length of the data to be written back; in ExpectReadDataOk(), |len| is
+ // implicitly the length of |data|.
+ void ExpectReadData(const char* data, size_t len, bool async, int result);
+ void ExpectReadDataOk(const std::string& data, bool async);
+
+ // Convenient method for calling ExpectReadInfoOk() with the length being
+ // |bytes_stored|, and ExpectReadDataOk() for each element of |stored_data|.
+ void ExpectReadOk(const std::vector<std::string>& stored_data,
+ const size_t bytes_stored,
+ const bool async);
+
+ // Complete a pending async read. It is an error to call this function without
+ // a pending async read (ie, a previous call to ReadInfo() or ReadData()
+ // having not run its callback yet).
+ void CompletePendingRead();
+
+ // Returns whether all expected reads have occurred.
+ bool AllExpectedReadsDone() { return expected_reads_.size() == 0; }
+
+ private:
+ struct ExpectedRead {
+ ExpectedRead(size_t len, bool async, int result)
+ : data(nullptr), len(len), info(true), async(async), result(result) {}
+ ExpectedRead(const char* data, size_t len, bool async, int result)
+ : data(data), len(len), info(false), async(async), result(result) {}
+ const char* data;
+ size_t len;
+ bool info;
+ bool async;
+ int result;
+ };
+
+ base::queue<ExpectedRead> expected_reads_;
+ scoped_refptr<net::IOBuffer> pending_buffer_;
+ size_t pending_buffer_len_;
+ scoped_refptr<HttpResponseInfoIOBuffer> pending_info_;
+ OnceCompletionCallback pending_callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockServiceWorkerResponseReader);
+};
+
+// A test implementation of ServiceWorkerResponseWriter.
+//
+// This class exposes the ability to expect writes (see ExpectWrite*Ok() below).
+// Each write to this class via WriteInfo() or WriteData() consumes another
+// expected write, in the order they were added, so:
+// writer->ExpectWriteInfoOk(5, false);
+// writer->ExpectWriteDataOk(6, false);
+// writer->ExpectWriteDataOk(6, false);
+// Expects these calls, in this order:
+// writer->WriteInfo(...); // checks that |buf->response_data_size| == 5
+// writer->WriteData(...); // checks that 6 bytes are being written
+// writer->WriteData(...); // checks that another 6 bytes are being written
+// If this class receives an unexpected call to WriteInfo() or WriteData(), it
+// DCHECKs.
+// Expected writes marked async do not complete synchronously, but rather return
+// without running their callback and need to be completed with
+// CompletePendingWrite().
+// A convenience method AllExpectedWritesDone() is exposed so tests can ensure
+// that all expected writes have been consumed by matching calls to WriteInfo()
+// or WriteData().
+class MockServiceWorkerResponseWriter : public ServiceWorkerResponseWriter {
+ public:
+ MockServiceWorkerResponseWriter();
+ ~MockServiceWorkerResponseWriter() override;
+
+ // ServiceWorkerResponseWriter overrides
+ void WriteInfo(HttpResponseInfoIOBuffer* info_buf,
+ OnceCompletionCallback callback) override;
+ void WriteData(net::IOBuffer* buf,
+ int buf_len,
+ OnceCompletionCallback callback) override;
+
+ // Enqueue expected writes.
+ void ExpectWriteInfoOk(size_t len, bool async);
+ void ExpectWriteInfo(size_t len, bool async, int result);
+ void ExpectWriteDataOk(size_t len, bool async);
+ void ExpectWriteData(size_t len, bool async, int result);
+
+ // Complete a pending asynchronous write. This method DCHECKs unless there is
+ // a pending write (a write for which WriteInfo() or WriteData() has been
+ // called but the callback has not yet been run).
+ void CompletePendingWrite();
+
+ // Returns whether all expected reads have been consumed.
+ bool AllExpectedWritesDone() { return expected_writes_.size() == 0; }
+
+ private:
+ struct ExpectedWrite {
+ ExpectedWrite(bool is_info, size_t length, bool async, int result)
+ : is_info(is_info), length(length), async(async), result(result) {}
+ bool is_info;
+ size_t length;
+ bool async;
+ int result;
+ };
+
+ base::queue<ExpectedWrite> expected_writes_;
+
+ size_t info_written_;
+ size_t data_written_;
+
+ OnceCompletionCallback pending_callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockServiceWorkerResponseWriter);
+};
+
} // namespace content
#endif // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_TEST_UTILS_H_
diff --git a/chromium/content/browser/service_worker/service_worker_tls_browsertest.cc b/chromium/content/browser/service_worker/service_worker_tls_browsertest.cc
new file mode 100644
index 00000000000..42e9efdadd0
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_tls_browsertest.cc
@@ -0,0 +1,146 @@
+// 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 "base/bind.h"
+#include "base/logging.h"
+#include "base/test/scoped_feature_list.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 "content/shell/browser/shell_content_browser_client.h"
+#include "net/ssl/ssl_server_config.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "services/network/public/cpp/features.h"
+#include "third_party/blink/public/common/features.h"
+#include "url/gurl.h"
+
+namespace content {
+
+namespace {
+enum class ServicifiedFeatures { kNone, kServiceWorker, kNetwork };
+}
+
+// Tests TLS + service workers. Inspired by
+// content/browser/shared_worker/worker_browsertest.cc.
+class ServiceWorkerTlsTest
+ : public ContentBrowserTest,
+ public ::testing::WithParamInterface<ServicifiedFeatures> {
+ public:
+ ServiceWorkerTlsTest() = default;
+
+ void SetUp() override {
+ ServicifiedFeatures param = GetParam();
+ switch (param) {
+ case ServicifiedFeatures::kNone:
+ scoped_feature_list_.InitWithFeatures(
+ {}, {blink::features::kServiceWorkerServicification,
+ network::features::kNetworkService});
+ break;
+ case ServicifiedFeatures::kServiceWorker:
+ scoped_feature_list_.InitWithFeatures(
+ {blink::features::kServiceWorkerServicification},
+ {network::features::kNetworkService});
+ break;
+ case ServicifiedFeatures::kNetwork:
+ scoped_feature_list_.InitAndEnableFeature(
+ network::features::kNetworkService);
+ break;
+ }
+ ContentBrowserTest::SetUp();
+ }
+
+ void SetUpOnMainThread() override {
+ ShellContentBrowserClient::Get()->set_select_client_certificate_callback(
+ base::BindRepeating(&ServiceWorkerTlsTest::OnSelectClientCertificate,
+ base::Unretained(this)));
+ ASSERT_TRUE(embedded_test_server()->Start());
+ }
+
+ void TearDownOnMainThread() override {
+ ShellContentBrowserClient::Get()->set_select_client_certificate_callback(
+ base::RepeatingClosure());
+ }
+
+ int select_certificate_count() const { return select_certificate_count_; }
+
+ GURL GetTestURL(const std::string& test_case, const std::string& query) {
+ std::string url_string = "/workers/" + test_case + "?" + query;
+ return embedded_test_server()->GetURL(url_string);
+ }
+
+ private:
+ void OnSelectClientCertificate() { select_certificate_count_++; }
+
+ int select_certificate_count_ = 0;
+ base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+// Tests that TLS client auth prompts for a page controlled by a service
+// worker, when the service worker calls fetch() for the main resource.
+IN_PROC_BROWSER_TEST_P(ServiceWorkerTlsTest, ClientAuthFetchMainResource) {
+ // Start an HTTPS server which doesn't need client certs.
+ net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
+ https_server.ServeFilesFromSourceDirectory("content/test/data");
+ net::SSLServerConfig ssl_config;
+ ssl_config.client_cert_type =
+ net::SSLServerConfig::ClientCertType::NO_CLIENT_CERT;
+ https_server.SetSSLConfig(net::EmbeddedTestServer::CERT_OK, ssl_config);
+ ASSERT_TRUE(https_server.Start());
+
+ // Load a page that installs the service worker.
+ EXPECT_TRUE(NavigateToURL(
+ shell(), https_server.GetURL("/workers/service_worker_setup.html")));
+ EXPECT_EQ("ok", EvalJs(shell(), "setup();"));
+
+ // Set the HTTPS server to require client certs.
+ ssl_config.client_cert_type =
+ net::SSLServerConfig::ClientCertType::REQUIRE_CLIENT_CERT;
+ https_server.ResetSSLConfig(net::EmbeddedTestServer::CERT_OK, ssl_config);
+
+ // Load a page that the SW intercepts with respondWith(fetch()). It should
+ // prompt client certificate selection. (The navigation fails because
+ // this test doesn't select a client certificate.)
+ EXPECT_FALSE(NavigateToURL(
+ shell(), https_server.GetURL("/workers/simple.html?intercept")));
+ EXPECT_EQ(1, select_certificate_count());
+}
+
+// Tests that TLS client auth prompts for a page controlled by a service
+// worker, when the service worker calls fetch() for a subresource.
+IN_PROC_BROWSER_TEST_P(ServiceWorkerTlsTest, ClientAuthFetchSubResource) {
+ // Load a page that installs the service worker.
+ EXPECT_TRUE(NavigateToURL(
+ shell(), GetTestURL("service_worker_setup.html", std::string())));
+ EXPECT_EQ("ok", EvalJs(shell(), "setup();"));
+
+ // Load a page controlled by the service worker.
+ EXPECT_TRUE(NavigateToURL(shell(),
+ GetTestURL("simple.html?fallback", std::string())));
+
+ // Start HTTPS server.
+ net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
+ https_server.ServeFilesFromSourceDirectory("content/test/data");
+ net::SSLServerConfig ssl_config;
+ ASSERT_TRUE(https_server.Start());
+ ssl_config.client_cert_type =
+ net::SSLServerConfig::ClientCertType::REQUIRE_CLIENT_CERT;
+ https_server.ResetSSLConfig(net::EmbeddedTestServer::CERT_OK, ssl_config);
+
+ // Perform a fetch from the controlled page to the https server. It should
+ // prompt client certificate selection. (The fetch fails because this test
+ // doesn't select a client certificate.)
+ std::string url = https_server.GetURL("/?intercept").spec();
+ EXPECT_EQ("TypeError", EvalJs(shell(), "try_fetch('" + url + "');"));
+ EXPECT_EQ(1, select_certificate_count());
+}
+
+INSTANTIATE_TEST_CASE_P(/* no prefix */,
+ ServiceWorkerTlsTest,
+ ::testing::Values(ServicifiedFeatures::kNone,
+ ServicifiedFeatures::kServiceWorker,
+ ServicifiedFeatures::kNetwork));
+
+} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_update_checker.cc b/chromium/content/browser/service_worker/service_worker_update_checker.cc
new file mode 100644
index 00000000000..1156b0e4159
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_update_checker.cc
@@ -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.
+
+#include "content/browser/service_worker/service_worker_update_checker.h"
+
+#include "content/browser/service_worker/service_worker_context_core.h"
+#include "content/browser/service_worker/service_worker_storage.h"
+#include "content/browser/service_worker/service_worker_version.h"
+
+namespace content {
+
+ServiceWorkerUpdateChecker::ServiceWorkerUpdateChecker(
+ std::vector<ServiceWorkerDatabase::ResourceRecord> scripts_to_compare,
+ scoped_refptr<ServiceWorkerVersion> version_to_update,
+ scoped_refptr<network::SharedURLLoaderFactory> loader_factory)
+ : scripts_to_compare_(std::move(scripts_to_compare)),
+ version_to_update_(std::move(version_to_update)),
+ loader_factory_(std::move(loader_factory)),
+ weak_factory_(this) {}
+
+ServiceWorkerUpdateChecker::~ServiceWorkerUpdateChecker() = default;
+
+void ServiceWorkerUpdateChecker::Start(UpdateStatusCallback callback) {
+ DCHECK(!scripts_to_compare_.empty());
+ callback_ = std::move(callback);
+ CheckOneScript();
+}
+
+void ServiceWorkerUpdateChecker::OnOneUpdateCheckFinished(
+ bool is_script_changed) {
+ running_checker_.reset();
+ if (is_script_changed) {
+ // Found an updated script. Stop the comparison of scripts here and
+ // return to ServiceWorkerRegisterJob to continue the update.
+ // Note that running |callback_| will delete |this|.
+ std::move(callback_).Run(true);
+ return;
+ }
+ CheckOneScript();
+}
+
+void ServiceWorkerUpdateChecker::CheckOneScript() {
+ DCHECK_LE(scripts_compared_, scripts_to_compare_.size());
+ if (scripts_compared_ == scripts_to_compare_.size()) {
+ // None of the scripts that went through the comparison had any updates.
+ // Note that running |callback_| will delete |this|.
+ std::move(callback_).Run(false);
+ return;
+ }
+
+ ServiceWorkerDatabase::ResourceRecord script =
+ scripts_to_compare_[scripts_compared_++];
+ DCHECK_NE(kInvalidServiceWorkerResourceId, script.resource_id)
+ << "All the target scripts should be stored in the storage.";
+
+ bool is_main_script = script.url == version_to_update_->script_url();
+ ServiceWorkerStorage* storage = version_to_update_->context()->storage();
+
+ // We need two identical readers for comparing and reading the resource for
+ // |script.resource_id| from the storage.
+ auto compare_reader = storage->CreateResponseReader(script.resource_id);
+ auto copy_reader = storage->CreateResponseReader(script.resource_id);
+
+ auto writer = storage->CreateResponseWriter(storage->NewResourceId());
+
+ running_checker_ = std::make_unique<ServiceWorkerSingleScriptUpdateChecker>(
+ script.url, is_main_script, loader_factory_, std::move(compare_reader),
+ std::move(copy_reader), std::move(writer),
+ base::BindOnce(&ServiceWorkerUpdateChecker::OnOneUpdateCheckFinished,
+ weak_factory_.GetWeakPtr()));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_update_checker.h b/chromium/content/browser/service_worker/service_worker_update_checker.h
new file mode 100644
index 00000000000..2bd0b086b92
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_update_checker.h
@@ -0,0 +1,56 @@
+// 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_UPDATE_CHECKER_H_
+#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_UPDATE_CHECKER_H_
+
+#include "base/callback.h"
+#include "content/browser/service_worker/service_worker_database.h"
+#include "content/browser/service_worker/service_worker_single_script_update_checker.h"
+
+namespace network {
+class SharedURLLoaderFactory;
+}
+
+namespace content {
+
+class ServiceWorkerVersion;
+
+class ServiceWorkerUpdateChecker {
+ public:
+ using UpdateStatusCallback = base::OnceCallback<void(bool)>;
+
+ ServiceWorkerUpdateChecker(
+ std::vector<ServiceWorkerDatabase::ResourceRecord> scripts_to_compare,
+ scoped_refptr<ServiceWorkerVersion> version_to_update,
+ scoped_refptr<network::SharedURLLoaderFactory> loader_factory);
+ ~ServiceWorkerUpdateChecker();
+
+ // |callback| is always triggered when Start() finishes. If the scripts are
+ // found to have any changes, the argument of |callback| is true and otherwise
+ // false.
+ void Start(UpdateStatusCallback callback);
+
+ void OnOneUpdateCheckFinished(bool is_script_changed);
+
+ private:
+ void CheckOneScript();
+
+ std::vector<ServiceWorkerDatabase::ResourceRecord> scripts_to_compare_;
+ size_t scripts_compared_ = 0;
+
+ // The version which triggered this update.
+ scoped_refptr<ServiceWorkerVersion> version_to_update_;
+
+ std::unique_ptr<ServiceWorkerSingleScriptUpdateChecker> running_checker_;
+
+ UpdateStatusCallback callback_;
+
+ scoped_refptr<network::SharedURLLoaderFactory> loader_factory_;
+ base::WeakPtrFactory<ServiceWorkerUpdateChecker> weak_factory_;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_UPDATE_CHECKER_H_
diff --git a/chromium/content/browser/service_worker/service_worker_url_job_wrapper.cc b/chromium/content/browser/service_worker/service_worker_url_job_wrapper.cc
index eaf770dc02d..9df6d060839 100644
--- a/chromium/content/browser/service_worker/service_worker_url_job_wrapper.cc
+++ b/chromium/content/browser/service_worker/service_worker_url_job_wrapper.cc
@@ -79,12 +79,8 @@ void ServiceWorkerURLJobWrapper::FailDueToLostController() {
url_request_job_->FailDueToLostController();
}
-bool ServiceWorkerURLJobWrapper::WasCanceled() const {
- if (url_loader_job_) {
- return url_loader_job_->WasCanceled();
- } else {
- return !url_request_job_;
- }
+bool ServiceWorkerURLJobWrapper::IsAlive() const {
+ return url_loader_job_ || url_request_job_;
}
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_url_job_wrapper.h b/chromium/content/browser/service_worker/service_worker_url_job_wrapper.h
index c2cc39872ce..e6e84117b44 100644
--- a/chromium/content/browser/service_worker/service_worker_url_job_wrapper.h
+++ b/chromium/content/browser/service_worker/service_worker_url_job_wrapper.h
@@ -85,8 +85,10 @@ class CONTENT_EXPORT ServiceWorkerURLJobWrapper {
// if needed later.
void FailDueToLostController();
- // Returns true if the underlying job has been canceled or destroyed.
- bool WasCanceled() const;
+ // Returns true if the underlying job has not been destroyed. This only useful
+ // in the non-S13nServiceWorker case, since this wrapper owns the job in the
+ // S13nServiceWorker case.
+ bool IsAlive() const;
private:
enum class JobType { kURLRequest, kURLLoader };
diff --git a/chromium/content/browser/service_worker/service_worker_url_request_job.cc b/chromium/content/browser/service_worker/service_worker_url_request_job.cc
index 033f55cb8cd..1bb65c47c41 100644
--- a/chromium/content/browser/service_worker/service_worker_url_request_job.cc
+++ b/chromium/content/browser/service_worker/service_worker_url_request_job.cc
@@ -312,7 +312,7 @@ bool ServiceWorkerURLRequestJob::Delegate::RequestStillValid(
ServiceWorkerURLRequestJob::ServiceWorkerURLRequestJob(
net::URLRequest* request,
net::NetworkDelegate* network_delegate,
- const std::string& client_id,
+ base::WeakPtr<ServiceWorkerProviderHost> provider_host,
base::WeakPtr<storage::BlobStorageContext> blob_storage_context,
const ResourceContext* resource_context,
network::mojom::FetchRequestMode request_mode,
@@ -321,7 +321,7 @@ ServiceWorkerURLRequestJob::ServiceWorkerURLRequestJob(
const std::string& integrity,
bool keepalive,
ResourceType resource_type,
- RequestContextType request_context_type,
+ blink::mojom::RequestContextType request_context_type,
network::mojom::RequestContextFrameType frame_type,
scoped_refptr<network::ResourceRequestBody> body,
Delegate* delegate)
@@ -330,7 +330,9 @@ ServiceWorkerURLRequestJob::ServiceWorkerURLRequestJob(
response_type_(ResponseType::NOT_DETERMINED),
is_started_(false),
fetch_response_type_(network::mojom::FetchResponseType::kDefault),
- client_id_(client_id),
+ provider_host_(std::move(provider_host)),
+ client_id_(provider_host_ ? provider_host_->client_uuid()
+ : std::string()),
blob_storage_context_(blob_storage_context),
resource_context_(resource_context),
request_mode_(request_mode),
@@ -569,13 +571,20 @@ ServiceWorkerURLRequestJob::CreateResourceRequest() {
request->fetch_credentials_mode = credentials_mode_;
request->load_flags = request_->load_flags();
request->fetch_redirect_mode = redirect_mode_;
- request->fetch_request_context_type = request_context_type_;
+ request->fetch_request_context_type = static_cast<int>(request_context_type_);
request->fetch_frame_type = frame_type_;
const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request_);
if (info)
request->transition_type = info->GetPageTransition();
request->fetch_integrity = integrity_;
request->keepalive = keepalive_;
+ // Set the request window id if we have one. If we don't, or the provider
+ // host is gone, it just means client certification authentication may fail
+ // so continue on without it anyway.
+ if (provider_host_ && provider_host_->fetch_request_window_id()) {
+ request->fetch_window_id =
+ base::make_optional(provider_host_->fetch_request_window_id());
+ }
return request;
}
@@ -586,7 +595,7 @@ blink::mojom::BlobPtr ServiceWorkerURLRequestJob::CreateRequestBodyBlob(
auto blob_builder =
std::make_unique<storage::BlobDataBuilder>(base::GenerateGUID());
for (const network::DataElement& element : (*body_->elements())) {
- blob_builder->AppendIPCDataElement(element, nullptr,
+ blob_builder->AppendIPCDataElement(element,
blob_storage_context_->registry());
}
@@ -660,6 +669,7 @@ void ServiceWorkerURLRequestJob::DidDispatchFetchEvent(
ServiceWorkerFetchDispatcher::FetchEventResult fetch_result,
blink::mojom::FetchAPIResponsePtr response,
blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
+ blink::mojom::ServiceWorkerFetchEventTimingPtr timing,
scoped_refptr<ServiceWorkerVersion> version) {
// Do not clear |fetch_dispatcher_| if it has dispatched a navigation preload
// request to keep the network::mojom::URLLoader related objects in it,
diff --git a/chromium/content/browser/service_worker/service_worker_url_request_job.h b/chromium/content/browser/service_worker/service_worker_url_request_job.h
index ea2182bae3d..de3e85b0ca7 100644
--- a/chromium/content/browser/service_worker/service_worker_url_request_job.h
+++ b/chromium/content/browser/service_worker/service_worker_url_request_job.h
@@ -24,7 +24,6 @@
#include "content/browser/service_worker/service_worker_url_job_wrapper.h"
#include "content/common/content_export.h"
#include "content/common/service_worker/service_worker.mojom.h"
-#include "content/public/common/request_context_type.h"
#include "content/public/common/resource_type.h"
#include "mojo/public/cpp/system/data_pipe.h"
#include "net/http/http_byte_range.h"
@@ -37,6 +36,7 @@
#include "storage/common/blob_storage/blob_storage_constants.h"
#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_response.mojom.h"
+#include "third_party/blink/public/platform/modules/fetch/fetch_api_request.mojom.h"
#include "url/gurl.h"
namespace net {
@@ -77,7 +77,7 @@ class CONTENT_EXPORT ServiceWorkerURLRequestJob : public net::URLRequestJob {
ServiceWorkerURLRequestJob(
net::URLRequest* request,
net::NetworkDelegate* network_delegate,
- const std::string& client_id,
+ base::WeakPtr<ServiceWorkerProviderHost> provider_host,
base::WeakPtr<storage::BlobStorageContext> blob_storage_context,
const ResourceContext* resource_context,
network::mojom::FetchRequestMode request_mode,
@@ -86,7 +86,7 @@ class CONTENT_EXPORT ServiceWorkerURLRequestJob : public net::URLRequestJob {
const std::string& integrity,
bool keepalive,
ResourceType resource_type,
- RequestContextType request_context_type,
+ blink::mojom::RequestContextType request_context_type,
network::mojom::RequestContextFrameType frame_type,
scoped_refptr<network::ResourceRequestBody> body,
Delegate* delegate);
@@ -194,6 +194,7 @@ class CONTENT_EXPORT ServiceWorkerURLRequestJob : public net::URLRequestJob {
ServiceWorkerFetchDispatcher::FetchEventResult fetch_result,
blink::mojom::FetchAPIResponsePtr response,
blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
+ blink::mojom::ServiceWorkerFetchEventTimingPtr timing,
scoped_refptr<ServiceWorkerVersion> version);
void SetResponse(blink::mojom::FetchAPIResponsePtr response);
@@ -309,6 +310,7 @@ class CONTENT_EXPORT ServiceWorkerURLRequestJob : public net::URLRequestJob {
// Used when response type is FORWARD_TO_SERVICE_WORKER.
std::unique_ptr<ServiceWorkerFetchDispatcher> fetch_dispatcher_;
+ base::WeakPtr<ServiceWorkerProviderHost> provider_host_;
std::string client_id_;
base::WeakPtr<storage::BlobStorageContext> blob_storage_context_;
const ResourceContext* resource_context_;
@@ -322,7 +324,7 @@ class CONTENT_EXPORT ServiceWorkerURLRequestJob : public net::URLRequestJob {
std::string integrity_;
const bool keepalive_;
const ResourceType resource_type_;
- RequestContextType request_context_type_;
+ blink::mojom::RequestContextType request_context_type_;
network::mojom::RequestContextFrameType frame_type_;
bool fall_back_required_;
// ResourceRequestBody has a collection of BlobDataHandles attached to it
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 fef3544e4ba..5e3136dabb0 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
@@ -35,7 +35,6 @@
#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/browser/blob_handle.h"
#include "content/public/common/browser_side_navigation_policy.h"
-#include "content/public/common/request_context_type.h"
#include "content/public/common/resource_type.h"
#include "content/public/test/mock_resource_context.h"
#include "content/public/test/test_browser_context.h"
@@ -66,6 +65,7 @@
#include "third_party/blink/public/mojom/service_worker/service_worker_event_status.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_installed_scripts_manager.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
+#include "third_party/blink/public/platform/modules/fetch/fetch_api_request.mojom.h"
namespace content {
namespace service_worker_url_request_job_unittest {
@@ -115,13 +115,12 @@ class MockProtocolHandler : public net::URLRequestJobFactory::ProtocolHandler {
}
job_ = new ServiceWorkerURLRequestJob(
- request, network_delegate, provider_host_->client_uuid(),
- blob_storage_context_, resource_context_,
- network::mojom::FetchRequestMode::kNoCORS,
+ request, network_delegate, provider_host_, blob_storage_context_,
+ resource_context_, network::mojom::FetchRequestMode::kNoCORS,
network::mojom::FetchCredentialsMode::kOmit,
network::mojom::FetchRedirectMode::kFollow,
std::string() /* integrity */, false /* keepalive */, resource_type_,
- REQUEST_CONTEXT_TYPE_HYPERLINK,
+ blink::mojom::RequestContextType::HYPERLINK,
network::mojom::RequestContextFrameType::kTopLevel,
scoped_refptr<network::ResourceRequestBody>(), delegate_);
if (simulate_navigation_preload_) {
@@ -233,7 +232,8 @@ class ServiceWorkerURLRequestJobTest
registration_ = new ServiceWorkerRegistration(
options, 1L, helper_->context()->AsWeakPtr());
version_ = new ServiceWorkerVersion(
- registration_.get(), GURL("https://example.com/service_worker.js"), 1L,
+ registration_.get(), GURL("https://example.com/service_worker.js"),
+ blink::mojom::ScriptType::kClassic, 1L,
helper_->context()->AsWeakPtr());
std::vector<ServiceWorkerDatabase::ResourceRecord> records;
records.push_back(WriteToDiskCacheWithCustomResponseInfoSync(
@@ -342,7 +342,7 @@ class ServiceWorkerURLRequestJobTest
expected_response, expect_valid_ssl);
}
- bool HasWork() { return version_->HasWorkInBrowser(); }
+ bool HasWork() { return !version_->HasNoWork(); }
// Runs a request where the active worker starts a request in ACTIVATING state
// and fails to reach ACTIVATED.
@@ -490,10 +490,11 @@ class DelayHelper : public EmbeddedWorkerTestHelper {
}
void Respond() {
- response_callback_->OnResponse(MakeOkResponse(), base::Time::Now());
+ response_callback_->OnResponse(
+ MakeOkResponse(), blink::mojom::ServiceWorkerFetchEventTiming::New());
std::move(finish_callback_)
.Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
- base::Time::Now());
+ base::TimeTicks::Now());
}
protected:
@@ -707,10 +708,11 @@ class ProviderDeleteHelper : public EmbeddedWorkerTestHelper {
mojom::ServiceWorker::DispatchFetchEventCallback finish_callback)
override {
context()->RemoveProviderHost(mock_render_process_id(), kProviderID);
- response_callback->OnResponse(MakeOkResponse(), base::Time::Now());
+ response_callback->OnResponse(
+ MakeOkResponse(), blink::mojom::ServiceWorkerFetchEventTiming::New());
std::move(finish_callback)
.Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
- base::Time::Now());
+ base::TimeTicks::Now());
}
private:
@@ -794,10 +796,12 @@ class BlobResponder : public EmbeddedWorkerTestHelper {
// Mojo, we give it a dummy value.
auto dummy_request = mojo::MakeRequest(&response->blob->blob);
- response_callback->OnResponse(std::move(response), base::Time::Now());
+ response_callback->OnResponse(
+ std::move(response),
+ blink::mojom::ServiceWorkerFetchEventTiming::New());
std::move(finish_callback)
.Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
- base::Time::Now());
+ base::TimeTicks::Now());
}
std::string blob_uuid_;
@@ -889,10 +893,11 @@ class StreamResponder : public EmbeddedWorkerTestHelper {
blink::mojom::FetchAPIResponsePtr response = MakeOkResponse();
response->headers = MakeHeaders();
response_callback->OnResponseStream(
- std::move(response), std::move(stream_handle_), base::Time::Now());
+ std::move(response), std::move(stream_handle_),
+ blink::mojom::ServiceWorkerFetchEventTiming::New());
std::move(finish_callback)
.Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
- base::Time::Now());
+ base::TimeTicks::Now());
}
blink::mojom::ServiceWorkerStreamHandlePtr stream_handle_;
@@ -1272,7 +1277,7 @@ class FailFetchHelper : public EmbeddedWorkerTestHelper {
SimulateWorkerStopped(embedded_worker_id);
std::move(finish_callback)
.Run(blink::mojom::ServiceWorkerEventStatus::ABORTED,
- base::Time::Now());
+ base::TimeTicks::Now());
}
private:
@@ -1351,7 +1356,7 @@ class EarlyResponseHelper : public EmbeddedWorkerTestHelper {
void FinishWaitUntil() {
std::move(finish_callback_)
.Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
- base::Time::Now());
+ base::TimeTicks::Now());
}
protected:
@@ -1363,7 +1368,8 @@ class EarlyResponseHelper : public EmbeddedWorkerTestHelper {
mojom::ServiceWorker::DispatchFetchEventCallback finish_callback)
override {
finish_callback_ = std::move(finish_callback);
- response_callback->OnResponse(MakeOkResponse(), base::Time::Now());
+ response_callback->OnResponse(
+ MakeOkResponse(), blink::mojom::ServiceWorkerFetchEventTiming::New());
}
private:
@@ -1395,10 +1401,10 @@ TEST_F(ServiceWorkerURLRequestJobTest, EarlyResponse) {
EXPECT_FALSE(info->response_is_in_cache_storage());
EXPECT_EQ(std::string(), info->response_cache_storage_cache_name());
- EXPECT_TRUE(version_->HasWorkInBrowser());
+ EXPECT_FALSE(version_->HasNoWork());
helper->FinishWaitUntil();
base::RunLoop().RunUntilIdle();
- EXPECT_FALSE(version_->HasWorkInBrowser());
+ EXPECT_TRUE(version_->HasNoWork());
}
// Test cancelling the URLRequest while the fetch event is in flight.
@@ -1423,12 +1429,12 @@ TEST_F(ServiceWorkerURLRequestJobTest, CancelRequest) {
base::RunLoop().RunUntilIdle();
// Respond to the fetch event.
- EXPECT_TRUE(version_->HasWorkInBrowser());
+ EXPECT_FALSE(version_->HasNoWork());
helper->Respond();
base::RunLoop().RunUntilIdle();
// The fetch event request should no longer be in-flight.
- EXPECT_FALSE(version_->HasWorkInBrowser());
+ EXPECT_TRUE(version_->HasNoWork());
}
// TODO(kinuko): Add more tests with different response data and also for
diff --git a/chromium/content/browser/service_worker/service_worker_version.cc b/chromium/content/browser/service_worker/service_worker_version.cc
index 5d8213494b9..248382497e3 100644
--- a/chromium/content/browser/service_worker/service_worker_version.cc
+++ b/chromium/content/browser/service_worker/service_worker_version.cc
@@ -226,6 +226,7 @@ base::TimeDelta ServiceWorkerVersion::GetTickDuration(
ServiceWorkerVersion::ServiceWorkerVersion(
ServiceWorkerRegistration* registration,
const GURL& script_url,
+ blink::mojom::ScriptType script_type,
int64_t version_id,
base::WeakPtr<ServiceWorkerContextCore> context)
: version_id_(version_id),
@@ -233,6 +234,7 @@ ServiceWorkerVersion::ServiceWorkerVersion(
script_url_(script_url),
script_origin_(url::Origin::Create(script_url_)),
scope_(registration->pattern()),
+ script_type_(script_type),
fetch_handler_existence_(FetchHandlerExistence::UNKNOWN),
site_for_uma_(ServiceWorkerMetrics::SiteFromURL(scope_)),
binding_(this),
@@ -464,6 +466,39 @@ void ServiceWorkerVersion::StopWorker(base::OnceClosure callback) {
NOTREACHED();
}
+void ServiceWorkerVersion::TriggerIdleTerminationAsap() {
+ needs_to_be_terminated_asap_ = true;
+ endpoint()->SetIdleTimerDelayToZero();
+}
+
+bool ServiceWorkerVersion::OnRequestTermination() {
+ if (running_status() == EmbeddedWorkerStatus::STOPPING)
+ return true;
+ DCHECK_EQ(EmbeddedWorkerStatus::RUNNING, running_status());
+
+ worker_is_idle_on_renderer_ = true;
+
+ // Determine if the worker can be terminated.
+ bool will_be_terminated = HasNoWork();
+ if (embedded_worker_->devtools_attached()) {
+ // Basically the service worker won't be terminated if DevTools is attached.
+ // But when activation is happening and this worker needs to be terminated
+ // asap, it'll be terminated.
+ will_be_terminated = needs_to_be_terminated_asap_;
+ }
+
+ if (will_be_terminated) {
+ embedded_worker_->Stop();
+ } else {
+ // The worker needs to run more. The worker should start handling queued
+ // events dispatched to the worker directly (e.g. FetchEvent for
+ // subresources).
+ worker_is_idle_on_renderer_ = false;
+ }
+
+ return will_be_terminated;
+}
+
void ServiceWorkerVersion::ScheduleUpdate() {
if (!context_)
return;
@@ -570,7 +605,7 @@ int ServiceWorkerVersion::StartRequestWithCustomTimeout(
// be dispatched will reset the idle status. That means the worker can receive
// events directly from any clients, so we cannot trigger OnNoWork after this
// point.
- idle_timer_fired_in_renderer_ = false;
+ worker_is_idle_on_renderer_ = false;
return request_id;
}
@@ -597,7 +632,7 @@ bool ServiceWorkerVersion::StartExternalRequest(
bool ServiceWorkerVersion::FinishRequest(int request_id,
bool was_handled,
- base::Time dispatch_event_time) {
+ base::TimeTicks dispatch_event_time) {
InflightRequest* request = inflight_requests_.Lookup(request_id);
if (!request)
return false;
@@ -607,7 +642,7 @@ bool ServiceWorkerVersion::FinishRequest(int request_id,
request->event_type, tick_clock_->NowTicks() - request->start_time_ticks,
was_handled);
ServiceWorkerMetrics::RecordEventDispatchingDelay(
- request->event_type, dispatch_event_time - request->start_time);
+ request->event_type, dispatch_event_time - request->start_time_ticks);
RestartTick(&idle_time_);
TRACE_EVENT_ASYNC_END1("ServiceWorker", "ServiceWorkerVersion::Request",
@@ -630,12 +665,11 @@ bool ServiceWorkerVersion::FinishExternalRequest(
if (running_status() != EmbeddedWorkerStatus::RUNNING)
return false;
- RequestUUIDToRequestIDMap::iterator iter =
- external_request_uuid_to_request_id_.find(request_uuid);
+ auto iter = external_request_uuid_to_request_id_.find(request_uuid);
if (iter != external_request_uuid_to_request_id_.end()) {
int request_id = iter->second;
external_request_uuid_to_request_id_.erase(iter);
- return FinishRequest(request_id, true, clock_->Now());
+ return FinishRequest(request_id, true, tick_clock_->NowTicks());
}
// It is possible that the request was cancelled or timed out before and we
@@ -713,8 +747,10 @@ void ServiceWorkerVersion::OnStreamResponseStarted() {
void ServiceWorkerVersion::OnStreamResponseFinished() {
DCHECK_GT(inflight_stream_response_count_, 0);
inflight_stream_response_count_--;
- if (!HasWorkInBrowser())
+ if (!blink::ServiceWorkerUtils::IsServicificationEnabled() &&
+ !HasWorkInBrowser()) {
OnNoWorkInBrowser();
+ }
}
void ServiceWorkerVersion::AddObserver(Observer* observer) {
@@ -868,6 +904,12 @@ void ServiceWorkerVersion::SetClockForTesting(base::Clock* clock) {
clock_ = clock;
}
+bool ServiceWorkerVersion::HasNoWork() const {
+ if (!blink::ServiceWorkerUtils::IsServicificationEnabled())
+ return !HasWorkInBrowser();
+ return !HasWorkInBrowser() && worker_is_idle_on_renderer_;
+}
+
const net::HttpResponseInfo*
ServiceWorkerVersion::GetMainScriptHttpResponseInfo() {
return main_script_http_info_.get();
@@ -1335,10 +1377,15 @@ void ServiceWorkerVersion::OpenWindow(
base::BindOnce(&OnOpenWindowFinished, std::move(callback)));
}
+bool ServiceWorkerVersion::HasWorkInBrowser() const {
+ return !inflight_requests_.IsEmpty() || inflight_stream_response_count_ > 0 ||
+ !start_callbacks_.empty();
+}
+
void ServiceWorkerVersion::OnSimpleEventFinished(
int request_id,
blink::mojom::ServiceWorkerEventStatus status,
- base::Time dispatch_event_time) {
+ base::TimeTicks dispatch_event_time) {
InflightRequest* request = inflight_requests_.Lookup(request_id);
// |request| will be null when the request has been timed out.
if (!request)
@@ -1512,7 +1559,8 @@ void ServiceWorkerVersion::StartWorkerInternal() {
// again from OnStoppedInternal if StopWorker is called before OnStarted.
StartTimeoutTimer();
- idle_timer_fired_in_renderer_ = false;
+ worker_is_idle_on_renderer_ = false;
+ needs_to_be_terminated_asap_ = false;
auto provider_info = mojom::ServiceWorkerProviderInfoForStartWorker::New();
provider_host_ = ServiceWorkerProviderHost::PreCreateForController(
@@ -1522,6 +1570,7 @@ void ServiceWorkerVersion::StartWorkerInternal() {
params->service_worker_version_id = version_id_;
params->scope = scope_;
params->script_url = script_url_;
+ params->script_type = script_type_;
params->is_installed = IsInstalled(status_);
params->pause_after_download = pause_after_download();
@@ -1699,7 +1748,8 @@ void ServiceWorkerVersion::OnTimeoutTimer() {
// skip this check.
if (!blink::ServiceWorkerUtils::IsServicificationEnabled() &&
GetTickDuration(idle_time_) > kIdleWorkerTimeout) {
- StopWorkerIfIdle(false /* requested_from_renderer */);
+ if (HasNoWork())
+ embedded_worker_->StopIfNotAttachedToDevTools();
return;
}
@@ -1724,53 +1774,7 @@ void ServiceWorkerVersion::OnPingTimeout() {
// blink::ServiceWorkerStatusCode::kErrorTimeout.
embedded_worker_->AddMessageToConsole(blink::WebConsoleMessage::kLevelVerbose,
kNotRespondingErrorMesage);
- StopWorkerIfIdle(false /* requested_from_renderer */);
-}
-
-void ServiceWorkerVersion::StopWorkerIfIdle(bool requested_from_renderer) {
- if (running_status() == EmbeddedWorkerStatus::STOPPED ||
- running_status() == EmbeddedWorkerStatus::STOPPING ||
- !stop_callbacks_.empty()) {
- return;
- }
-
- if (!blink::ServiceWorkerUtils::IsServicificationEnabled()) {
- // StopWorkerIfIdle() may be called for two reasons: "idle-timeout" or
- // "ping-timeout". For idle-timeout (i.e. ping hasn't timed out), check if
- // the worker really is idle.
- if (!ping_controller_.IsTimedOut() && HasWorkInBrowser())
- return;
- embedded_worker_->StopIfNotAttachedToDevTools();
- return;
- }
-
- DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled());
- // Ping timeout
- if (ping_controller_.IsTimedOut()) {
- DCHECK(!requested_from_renderer);
- embedded_worker_->StopIfNotAttachedToDevTools();
- return;
- }
-
- // Idle timeout
- DCHECK(requested_from_renderer);
- DCHECK(start_callbacks_.empty());
- idle_timer_fired_in_renderer_ = true;
-
- // We may still have some work in the browser-side that are not
- // observable by the renderer, i.e. response streaming. In such case
- // we return here with setting |idle_timer_fired_in_renderer_| to true.
- // It will be checked later (i.e. when streaming finishes) to see if we
- // we should fire OnNoWork().
- if (HasWorkInBrowser())
- return;
embedded_worker_->StopIfNotAttachedToDevTools();
- OnNoWorkInBrowser();
-}
-
-bool ServiceWorkerVersion::HasWorkInBrowser() const {
- return !inflight_requests_.IsEmpty() || inflight_stream_response_count_ > 0 ||
- !start_callbacks_.empty();
}
void ServiceWorkerVersion::RecordStartWorkerResult(
@@ -1951,7 +1955,6 @@ void ServiceWorkerVersion::OnStoppedInternal(EmbeddedWorkerStatus old_status) {
should_restart);
ClearTick(&stop_time_);
}
- idle_timer_fired_in_renderer_ = false;
StopTimeoutTimer();
// Fire all stop callbacks.
@@ -1987,6 +1990,7 @@ void ServiceWorkerVersion::OnStoppedInternal(EmbeddedWorkerStatus old_status) {
installed_scripts_sender_.reset();
binding_.Close();
pending_external_requests_.clear();
+ worker_is_idle_on_renderer_ = true;
for (auto& observer : observers_)
observer.OnRunningStateChanged(this);
@@ -2020,14 +2024,10 @@ void ServiceWorkerVersion::OnNoWorkInBrowser() {
}
DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled());
- if (!idle_timer_fired_in_renderer_ &&
- running_status() != EmbeddedWorkerStatus::STOPPED) {
- return;
+ if (worker_is_idle_on_renderer_) {
+ for (auto& observer : observers_)
+ observer.OnNoWork(this);
}
-
- for (auto& observer : observers_)
- observer.OnNoWork(this);
- idle_timer_fired_in_renderer_ = false;
}
bool ServiceWorkerVersion::IsStartWorkerAllowed() const {
diff --git a/chromium/content/browser/service_worker/service_worker_version.h b/chromium/content/browser/service_worker/service_worker_version.h
index 166f9093530..014c8eaad5b 100644
--- a/chromium/content/browser/service_worker/service_worker_version.h
+++ b/chromium/content/browser/service_worker/service_worker_version.h
@@ -101,6 +101,10 @@ namespace service_worker_registration_unittest {
class ServiceWorkerActivationTest;
} // namespace service_worker_registration_unittest
+namespace service_worker_navigation_loader_unittest {
+class ServiceWorkerNavigationLoaderTest;
+} // namespace service_worker_navigation_loader_unittest
+
// This class corresponds to a specific version of a ServiceWorker
// script for a given pattern. When a script is upgraded, there may be
// more than one ServiceWorkerVersion "running" at a time, but only
@@ -117,7 +121,7 @@ class CONTENT_EXPORT ServiceWorkerVersion
base::OnceCallback<void(blink::ServiceWorkerStatusCode)>;
using SimpleEventCallback =
base::OnceCallback<void(blink::mojom::ServiceWorkerEventStatus,
- base::Time)>;
+ base::TimeTicks)>;
// Current version status; some of the status (e.g. INSTALLED and ACTIVATED)
// should be persisted unlike running status.
@@ -183,6 +187,7 @@ class CONTENT_EXPORT ServiceWorkerVersion
ServiceWorkerVersion(ServiceWorkerRegistration* registration,
const GURL& script_url,
+ blink::mojom::ScriptType script_type,
int64_t version_id,
base::WeakPtr<ServiceWorkerContextCore> context);
@@ -191,6 +196,7 @@ class CONTENT_EXPORT ServiceWorkerVersion
const GURL& script_url() const { return script_url_; }
const url::Origin& script_origin() const { return script_origin_; }
const GURL& scope() const { return scope_; }
+ blink::mojom::ScriptType script_type() const { return script_type_; }
EmbeddedWorkerStatus running_status() const {
return embedded_worker_->status();
}
@@ -246,13 +252,18 @@ class CONTENT_EXPORT ServiceWorkerVersion
// Stops an embedded worker for this version.
void StopWorker(base::OnceClosure callback);
- // Stops the worker if it is idle (has no in-flight requests) or timed out
- // ping.
- //
+ // Asks the renderer to notify the browser that it becomes idle as soon as
+ // possible, and it results in letting idle termination occur earlier. This is
+ // typically used for activation. An active worker needs to be swapped out
+ // soon after the service worker becomes idle if a waiting worker exists.
+ void TriggerIdleTerminationAsap();
+
// S13nServiceWorker:
- // |requested_from_renderer| should be true if StopWorkerIfIdle() is called by
- // mojom::EmbeddedWorkerInstanceHost::RequestTermination().
- void StopWorkerIfIdle(bool requested_from_renderer);
+ // Called when the renderer notifies the browser that the worker is now idle.
+ // Returns true if the worker will be terminated and the worker should not
+ // handle any events dispatched directly from clients (e.g. FetchEvents for
+ // subresources).
+ bool OnRequestTermination();
// Skips waiting and forces this version to become activated.
void SkipWaitingFromDevTools();
@@ -317,7 +328,7 @@ class CONTENT_EXPORT ServiceWorkerVersion
// TODO(mek): Use something other than a bool for event status.
bool FinishRequest(int request_id,
bool was_handled,
- base::Time dispatch_event_time);
+ base::TimeTicks dispatch_event_time);
// Finishes an external request that was started by StartExternalRequest().
// Returns false if there was an error finishing the request: e.g. the request
@@ -375,8 +386,12 @@ class CONTENT_EXPORT ServiceWorkerVersion
base::WeakPtr<ServiceWorkerContextCore> context() const { return context_; }
// Called when the browser process starts/finishes reading a fetch event
- // response via Mojo data pipe from the service worker. We try to not stop the
- // service worker while there is an ongoing response.
+ // response via Mojo data pipe from the service worker.
+ // Non-S13nServiceWorker: We try to not stop the service worker while there is
+ // an ongoing response.
+ // S13nServiceWorker: Renderer's idle timer recognizes stream responses, so we
+ // rely on it instead of keeping track of stream responses in the browser
+ // process.
void OnStreamResponseStarted();
void OnStreamResponseFinished();
@@ -459,17 +474,9 @@ class CONTENT_EXPORT ServiceWorkerVersion
// Used to allow tests to change wall clock for testing.
void SetClockForTesting(base::Clock* clock);
- // Non-S13nServiceWorker: returns true if the service worker has work to do:
- // it has inflight requests, in-progress streaming URLRequestJobs, or pending
- // start callbacks.
- //
- // S13nServiceWorker: returns true if the worker has work on the browser.
- // Note that this method may return false even when the service worker still
- // has work to do; clients may dispatch events to the service worker directly.
- // You can ensure no inflight requests exist when HasWorkInBrowser() returns
- // false and |idle_timer_fired_in_renderer_| is true, or when the worker is
- // stopped.
- bool HasWorkInBrowser() const;
+ // Returns true when the service worker isn't handling any events or stream
+ // responses, initiated from either the browser or the renderer.
+ bool HasNoWork() const;
// Returns the number of pending external request count of this worker.
size_t GetExternalRequestCountForTest() const {
@@ -521,6 +528,8 @@ class CONTENT_EXPORT ServiceWorkerVersion
friend class service_worker_registration_unittest::
ServiceWorkerActivationTest;
friend class service_worker_version_unittest::ServiceWorkerVersionTest;
+ friend class service_worker_navigation_loader_unittest::
+ ServiceWorkerNavigationLoaderTest;
FRIEND_TEST_ALL_PREFIXES(service_worker_controllee_request_handler_unittest::
ServiceWorkerControlleeRequestHandlerTest,
@@ -704,12 +713,30 @@ class CONTENT_EXPORT ServiceWorkerVersion
scoped_refptr<ServiceWorkerRegistration> registration);
void StartWorkerInternal();
+ // Stops the worker if it is idle (has no in-flight requests) or timed out
+ // ping.
+ void StopWorkerIfIdle();
+
+ // Non-S13nServiceWorker: returns true if the service worker has work to do:
+ // it has inflight requests, in-progress streaming URLRequestJobs, or pending
+ // start callbacks.
+ //
+ // S13nServiceWorker: returns true if the service worker has work to do:
+ // because the browser process initiated a request to the service worker which
+ // isn't done yet.
+ // Note that this method may return false even when the service worker still
+ // has work to do; clients may dispatch events to the service worker directly.
+ // You can ensure no inflight requests exist when HasWorkInBrowser() returns
+ // false and |worker_is_idle_on_renderer_| is true, or when the worker is
+ // stopped.
+ bool HasWorkInBrowser() const;
+
// Callback function for simple events dispatched through mojo interface
// mojom::ServiceWorker. Use CreateSimpleEventCallback() to
// create a callback for a given |request_id|.
void OnSimpleEventFinished(int request_id,
blink::mojom::ServiceWorkerEventStatus status,
- base::Time dispatch_event_time);
+ base::TimeTicks dispatch_event_time);
// The timeout timer periodically calls OnTimeoutTimer, which stops the worker
// if it is excessively idle or unresponsive to ping.
@@ -774,6 +801,10 @@ class CONTENT_EXPORT ServiceWorkerVersion
const GURL script_url_;
const url::Origin script_origin_;
const GURL scope_;
+ // A service worker has an associated type which is either
+ // "classic" or "module". Unless stated otherwise, it is "classic".
+ // https://w3c.github.io/ServiceWorker/#dfn-type
+ const blink::mojom::ScriptType script_type_;
FetchHandlerExistence fetch_handler_existence_;
// The source of truth for navigation preload state is the
// ServiceWorkerRegistration. |navigation_preload_state_| is essentially a
@@ -835,7 +866,11 @@ class CONTENT_EXPORT ServiceWorkerVersion
// Set to true if the worker has no inflight events and the idle timer has
// been triggered. Set back to false if another event starts since the worker
// is no longer idle.
- bool idle_timer_fired_in_renderer_ = false;
+ bool worker_is_idle_on_renderer_ = true;
+
+ // S13nServiceWorker: Set to true when the worker needs to be terminated as
+ // soon as possible (e.g. activation).
+ bool needs_to_be_terminated_asap_ = false;
// Keeps track of the provider hosting this running service worker for this
// version. |provider_host_| is always valid as long as this version is
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 fddd9d4ccef..5fbc9c59c10 100644
--- a/chromium/content/browser/service_worker/service_worker_version_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_version_unittest.cc
@@ -30,6 +30,7 @@
#include "content/public/test/test_utils.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/service_worker/service_worker_utils.h"
#include "third_party/blink/public/mojom/service_worker/service_worker.mojom.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_installed_scripts_manager.mojom.h"
@@ -155,6 +156,7 @@ class ServiceWorkerVersionTest : public testing::Test {
version_ = new ServiceWorkerVersion(
registration_.get(),
GURL("https://www.example.com/test/service_worker.js"),
+ blink::mojom::ScriptType::kClassic,
helper_->context()->storage()->NewVersionId(),
helper_->context()->AsWeakPtr());
EXPECT_EQ(url::Origin::Create(pattern_), version_->script_origin());
@@ -213,7 +215,7 @@ class ServiceWorkerVersionTest : public testing::Test {
// And finish request, as if a response to the event was received.
EXPECT_TRUE(version_->FinishRequest(request_id, true /* was_handled */,
- base::Time::Now()));
+ base::TimeTicks::Now()));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status.value());
}
@@ -445,17 +447,45 @@ TEST_F(ServiceWorkerVersionTest, DispatchEventToStoppedWorker) {
// Dispatch an event without starting the worker.
version_->SetStatus(ServiceWorkerVersion::INSTALLING);
+ EXPECT_TRUE(version_->HasNoWork());
SimulateDispatchEvent(ServiceWorkerMetrics::EventType::INSTALL);
+ if (blink::ServiceWorkerUtils::IsServicificationEnabled()) {
+ // The worker may still be handling events dispatched directly from
+ // controllees. We cannot say the version doesn't handle any tasks until the
+ // worker reports "No Work" (= ServiceWorkerVersion::OnRequestTermination()
+ // is called).
+ EXPECT_FALSE(version_->HasNoWork());
+ } else {
+ // In non-S13nServiceWorker case, ServiceWorkerVersion manages all of events
+ // dispatched to the service worker. Once all events have finished in the
+ // browser, the version should have no work.
+ EXPECT_TRUE(version_->HasNoWork());
+ }
+
// The worker should be now started.
EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
// Stop the worker, and then dispatch an event immediately after that.
bool has_stopped = false;
version_->StopWorker(base::BindOnce(&VerifyCalled, &has_stopped));
+ EXPECT_TRUE(version_->HasNoWork());
SimulateDispatchEvent(ServiceWorkerMetrics::EventType::INSTALL);
EXPECT_TRUE(has_stopped);
+ if (blink::ServiceWorkerUtils::IsServicificationEnabled()) {
+ // The worker may still be handling events dispatched directly from
+ // controllees. We cannot say the version doesn't handle any tasks until the
+ // worker reports "No Work" (= ServiceWorkerVersion::OnRequestTermination()
+ // is called).
+ EXPECT_FALSE(version_->HasNoWork());
+ } else {
+ // In non-S13nServiceWorker case, ServiceWorkerVersion manages all of events
+ // dispatched to the service worker. Once all events have finished in the
+ // browser, the version should have no work.
+ EXPECT_TRUE(version_->HasNoWork());
+ }
+
// The worker should be now started again.
EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
}
@@ -624,7 +654,7 @@ TEST_F(ServiceWorkerVersionTest, IdleTimeout) {
version_->StartRequest(ServiceWorkerMetrics::EventType::SYNC,
CreateReceiverOnCurrentThread(&status));
EXPECT_TRUE(version_->FinishRequest(request_id, true /* was_handled */,
- base::Time::Now()));
+ base::TimeTicks::Now()));
EXPECT_LT(idle_time, version_->idle_time_);
}
@@ -981,12 +1011,12 @@ TEST_F(ServiceWorkerRequestTimeoutTest, RequestTimeout) {
error_status.value());
// Calling FinishRequest should be no-op, since the request timed out.
EXPECT_FALSE(version_->FinishRequest(request_id, true /* was_handled */,
- base::Time::Now()));
+ base::TimeTicks::Now()));
// Simulate the renderer aborting the inflight event.
// This should not crash: https://crbug.com/676984.
TakeExtendableMessageEventCallback().Run(
- blink::mojom::ServiceWorkerEventStatus::ABORTED, base::Time::Now());
+ blink::mojom::ServiceWorkerEventStatus::ABORTED, base::TimeTicks::Now());
base::RunLoop().RunUntilIdle();
// Simulate the renderer stopping the worker.
@@ -1013,7 +1043,7 @@ TEST_F(ServiceWorkerVersionTest, RequestNowTimeout) {
EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorTimeout, status.value());
EXPECT_FALSE(version_->FinishRequest(request_id, true /* was_handled */,
- base::Time::Now()));
+ base::TimeTicks::Now()));
// CONTINUE_ON_TIMEOUT timeouts don't stop the service worker.
EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
@@ -1037,7 +1067,7 @@ TEST_F(ServiceWorkerVersionTest, RequestNowTimeoutKill) {
EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorTimeout, status.value());
EXPECT_FALSE(version_->FinishRequest(request_id, true /* was_handled */,
- base::Time::Now()));
+ base::TimeTicks::Now()));
// KILL_ON_TIMEOUT timeouts should stop the service worker.
EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, version_->running_status());
@@ -1095,10 +1125,10 @@ TEST_F(ServiceWorkerVersionTest, RequestCustomizedTimeout) {
second_status.value());
EXPECT_FALSE(version_->FinishRequest(first_request_id, true /* was_handled */,
- base::Time::Now()));
+ base::TimeTicks::Now()));
EXPECT_FALSE(version_->FinishRequest(
- second_request_id, true /* was_handled */, base::Time::Now()));
+ second_request_id, true /* was_handled */, base::TimeTicks::Now()));
// KILL_ON_TIMEOUT timeouts should stop the service worker.
EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, version_->running_status());
@@ -1135,7 +1165,7 @@ TEST_F(ServiceWorkerVersionTest, MixedRequestTimeouts) {
// Gracefully handle the sync event finishing after the timeout.
EXPECT_FALSE(version_->FinishRequest(sync_request_id, true /* was_handled */,
- base::Time::Now()));
+ base::TimeTicks::Now()));
// Verify that the fetch times out later.
version_->SetAllRequestExpirations(base::TimeTicks::Now());
@@ -1146,7 +1176,7 @@ TEST_F(ServiceWorkerVersionTest, MixedRequestTimeouts) {
// Fetch request should no longer exist.
EXPECT_FALSE(version_->FinishRequest(fetch_request_id, true /* was_handled */,
- base::Time::Now()));
+ base::TimeTicks::Now()));
// Other timeouts do stop the service worker.
EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, version_->running_status());
@@ -1282,7 +1312,7 @@ TEST_F(ServiceWorkerVersionTest, RendererCrashDuringEvent) {
// Request already failed, calling finsh should return false.
EXPECT_FALSE(version_->FinishRequest(request_id, true /* was_handled */,
- base::Time::Now()));
+ base::TimeTicks::Now()));
}
TEST_F(ServiceWorkerVersionTest, PingController) {
@@ -1312,6 +1342,7 @@ TEST_F(ServiceWorkerVersionTest, BadOrigin) {
auto version = base::MakeRefCounted<ServiceWorkerVersion>(
registration_.get(),
GURL("bad-origin://www.example.com/test/service_worker.js"),
+ blink::mojom::ScriptType::kClassic,
helper_->context()->storage()->NewVersionId(),
helper_->context()->AsWeakPtr());
base::Optional<blink::ServiceWorkerStatusCode> status;
diff --git a/chromium/content/browser/service_worker/service_worker_write_to_cache_job.cc b/chromium/content/browser/service_worker/service_worker_write_to_cache_job.cc
index 33975df1026..42494f91b5b 100644
--- a/chromium/content/browser/service_worker/service_worker_write_to_cache_job.cc
+++ b/chromium/content/browser/service_worker/service_worker_write_to_cache_job.cc
@@ -72,9 +72,26 @@ ServiceWorkerWriteToCacheJob::ServiceWorkerWriteToCacheJob(
version_(version),
weak_factory_(this) {
DCHECK(version_);
- DCHECK(resource_type_ == RESOURCE_TYPE_SCRIPT ||
- (resource_type_ == RESOURCE_TYPE_SERVICE_WORKER &&
- version_->script_url() == url_));
+
+#if DCHECK_IS_ON()
+ switch (version_->script_type()) {
+ case blink::mojom::ScriptType::kClassic:
+ // For classic scripts, the main service worker script should have the
+ // "service worker" resource type and imported scripts should have the
+ // "script" resource type.
+ DCHECK(resource_type_ == RESOURCE_TYPE_SCRIPT ||
+ (resource_type_ == RESOURCE_TYPE_SERVICE_WORKER &&
+ version_->script_url() == url_));
+ break;
+ case blink::mojom::ScriptType::kModule:
+ // For module scripts, both the main service worker script and
+ // static-imported scripts should have the "service worker" resource type
+ // because static import inherits the resource type of the top-level
+ // module script.
+ DCHECK_EQ(RESOURCE_TYPE_SERVICE_WORKER, resource_type_);
+ break;
+ }
+#endif // DCHECK_IS_ON()
InitNetRequest(extra_load_flags);
}
@@ -112,7 +129,8 @@ void ServiceWorkerWriteToCacheJob::StartAsync() {
}
cache_writer_ = std::make_unique<ServiceWorkerCacheWriter>(
std::move(compare_reader), std::move(copy_reader),
- context_->storage()->CreateResponseWriter(resource_id_));
+ context_->storage()->CreateResponseWriter(resource_id_),
+ false /* pause_when_not_identical */);
version_->script_cache_map()->NotifyStartedCaching(url_, resource_id_);
did_notify_started_ = true;
@@ -231,7 +249,9 @@ void ServiceWorkerWriteToCacheJob::InitNetRequest(
if (extra_load_flags)
net_request_->SetLoadFlags(net_request_->load_flags() | extra_load_flags);
- if (resource_type_ == RESOURCE_TYPE_SERVICE_WORKER) {
+ // Add the 'Service-Worker' header for the main script request.
+ // https://w3c.github.io/ServiceWorker/#service-worker-script-request
+ if (IsMainScript()) {
// This will get copied into net_request_ when URLRequest::StartJob calls
// ServiceWorkerWriteToCacheJob::SetExtraRequestHeaders.
request()->SetExtraRequestHeaderByName("Service-Worker", "script", true);
@@ -330,7 +350,7 @@ void ServiceWorkerWriteToCacheJob::OnResponseStarted(net::URLRequest* request,
return;
}
- if (resource_type_ == RESOURCE_TYPE_SERVICE_WORKER) {
+ if (IsMainScript()) {
std::string mime_type;
request->GetMimeType(&mime_type);
if (!blink::IsSupportedJavascriptMimeType(mime_type)) {
@@ -496,4 +516,9 @@ bool ServiceWorkerWriteToCacheJob::ShouldByteForByteCheck() const {
version_->pause_after_download();
}
+bool ServiceWorkerWriteToCacheJob::IsMainScript() const {
+ return url_ == version_->script_url() &&
+ resource_type_ == RESOURCE_TYPE_SERVICE_WORKER;
+}
+
} // namespace content
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 46572db78e5..5c18785aeee 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
@@ -132,6 +132,10 @@ class CONTENT_EXPORT ServiceWorkerWriteToCacheJob
// do the byte-for-byte check.
bool ShouldByteForByteCheck() const;
+ // Returns true if this writer is writing the main script for the service
+ // worker.
+ bool IsMainScript() const;
+
const ResourceType resource_type_; // Differentiate main script and imports
scoped_refptr<net::IOBuffer> io_buffer_;
int io_buffer_bytes_;
diff --git a/chromium/content/browser/service_worker/service_worker_write_to_cache_job_unittest.cc b/chromium/content/browser/service_worker/service_worker_write_to_cache_job_unittest.cc
index bf253b43748..db5b37740ba 100644
--- a/chromium/content/browser/service_worker/service_worker_write_to_cache_job_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_write_to_cache_job_unittest.cc
@@ -221,7 +221,7 @@ class ResponseVerifier : public base::RefCounted<ResponseVerifier> {
void Start() {
info_buffer_ = new HttpResponseInfoIOBuffer();
- io_buffer_ = new net::IOBuffer(kBlockSize);
+ io_buffer_ = base::MakeRefCounted<net::IOBuffer>(kBlockSize);
reader_->ReadInfo(
info_buffer_.get(),
base::BindOnce(&ResponseVerifier::OnReadInfoComplete, this));
@@ -323,7 +323,8 @@ class ServiceWorkerWriteToCacheJobTest : public testing::Test {
network::mojom::FetchCredentialsMode::kOmit,
network::mojom::FetchRedirectMode::kFollow,
std::string() /* integrity */, false /* keepalive */,
- RESOURCE_TYPE_SERVICE_WORKER, REQUEST_CONTEXT_TYPE_SERVICE_WORKER,
+ RESOURCE_TYPE_SERVICE_WORKER,
+ blink::mojom::RequestContextType::SERVICE_WORKER,
network::mojom::RequestContextFrameType::kNone,
scoped_refptr<network::ResourceRequestBody>());
}
@@ -338,9 +339,9 @@ class ServiceWorkerWriteToCacheJobTest : public testing::Test {
options.scope = scope_;
registration_ =
new ServiceWorkerRegistration(options, 1L, context()->AsWeakPtr());
- version_ =
- new ServiceWorkerVersion(registration_.get(), script_url_,
- NextVersionId(), context()->AsWeakPtr());
+ version_ = new ServiceWorkerVersion(
+ registration_.get(), script_url_, blink::mojom::ScriptType::kClassic,
+ NextVersionId(), context()->AsWeakPtr());
base::WeakPtr<ServiceWorkerProviderHost> host =
CreateHostForVersion(helper_->mock_render_process_id(), version_);
ASSERT_TRUE(host);
@@ -392,9 +393,9 @@ class ServiceWorkerWriteToCacheJobTest : public testing::Test {
// to the script |response|. Returns the new version.
scoped_refptr<ServiceWorkerVersion> UpdateScript(
const std::string& response) {
- scoped_refptr<ServiceWorkerVersion> new_version =
- new ServiceWorkerVersion(registration_.get(), script_url_,
- NextVersionId(), context()->AsWeakPtr());
+ scoped_refptr<ServiceWorkerVersion> new_version = new ServiceWorkerVersion(
+ registration_.get(), script_url_, blink::mojom::ScriptType::kClassic,
+ NextVersionId(), context()->AsWeakPtr());
new_version->SetToPauseAfterDownload(base::DoNothing());
base::WeakPtr<ServiceWorkerProviderHost> host =
CreateHostForVersion(helper_->mock_render_process_id(), new_version);
diff --git a/chromium/content/browser/shareable_file_reference_unittest.cc b/chromium/content/browser/shareable_file_reference_unittest.cc
index 5003f6c6e68..d2ec24e388f 100644
--- a/chromium/content/browser/shareable_file_reference_unittest.cc
+++ b/chromium/content/browser/shareable_file_reference_unittest.cc
@@ -6,9 +6,9 @@
#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"
#include "base/threading/thread_task_runner_handle.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -17,7 +17,7 @@ using storage::ShareableFileReference;
namespace content {
TEST(ShareableFileReferenceTest, TestReferences) {
- base::MessageLoop message_loop;
+ base::test::ScopedTaskEnvironment task_environment;
scoped_refptr<base::SingleThreadTaskRunner> task_runner =
base::ThreadTaskRunnerHandle::Get();
base::ScopedTempDir temp_dir;
diff --git a/chromium/content/browser/shared_worker/mock_shared_worker.cc b/chromium/content/browser/shared_worker/mock_shared_worker.cc
index b23879ffa4d..d6b17d1afcb 100644
--- a/chromium/content/browser/shared_worker/mock_shared_worker.cc
+++ b/chromium/content/browser/shared_worker/mock_shared_worker.cc
@@ -61,6 +61,7 @@ void MockSharedWorker::Terminate() {
}
void MockSharedWorker::BindDevToolsAgent(
+ blink::mojom::DevToolsAgentHostAssociatedPtrInfo host_ptr_info,
blink::mojom::DevToolsAgentAssociatedRequest request) {
NOTREACHED();
}
@@ -105,8 +106,10 @@ void MockSharedWorkerFactory::CreateSharedWorker(
service_worker_provider_info,
int appcache_host_id,
network::mojom::URLLoaderFactoryAssociatedPtrInfo
- script_loader_factory_ptr_info,
- std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loaders,
+ main_script_loader_factory,
+ blink::mojom::SharedWorkerMainScriptLoadParamsPtr main_sciript_load_params,
+ std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories,
+ mojom::ControllerServiceWorkerInfoPtr controller_info,
mojom::SharedWorkerHostPtr host,
mojom::SharedWorkerRequest request,
service_manager::mojom::InterfaceProviderPtr interface_provider) {
diff --git a/chromium/content/browser/shared_worker/mock_shared_worker.h b/chromium/content/browser/shared_worker/mock_shared_worker.h
index 954fbad4b54..7297a82f82a 100644
--- a/chromium/content/browser/shared_worker/mock_shared_worker.h
+++ b/chromium/content/browser/shared_worker/mock_shared_worker.h
@@ -17,7 +17,7 @@
#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"
+#include "third_party/blink/public/common/messaging/message_port_channel.h"
class GURL;
@@ -40,6 +40,7 @@ class MockSharedWorker : public mojom::SharedWorker {
mojo::ScopedMessagePipeHandle port) override;
void Terminate() override;
void BindDevToolsAgent(
+ blink::mojom::DevToolsAgentHostAssociatedPtrInfo host_ptr_info,
blink::mojom::DevToolsAgentAssociatedRequest request) override;
mojo::Binding<mojom::SharedWorker> binding_;
@@ -74,8 +75,10 @@ class MockSharedWorkerFactory : public mojom::SharedWorkerFactory {
service_worker_provider_info,
int appcache_host_id,
network::mojom::URLLoaderFactoryAssociatedPtrInfo
- script_loader_factory_ptr_info,
- std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loaders,
+ main_script_loader_factory,
+ blink::mojom::SharedWorkerMainScriptLoadParamsPtr main_script_load_params,
+ std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories,
+ mojom::ControllerServiceWorkerInfoPtr controller_info,
mojom::SharedWorkerHostPtr host,
mojom::SharedWorkerRequest request,
service_manager::mojom::InterfaceProviderPtr interface_provider) override;
diff --git a/chromium/content/browser/shared_worker/shared_worker_connector_impl.cc b/chromium/content/browser/shared_worker/shared_worker_connector_impl.cc
index 2fe70f50171..454febaba66 100644
--- a/chromium/content/browser/shared_worker/shared_worker_connector_impl.cc
+++ b/chromium/content/browser/shared_worker/shared_worker_connector_impl.cc
@@ -11,7 +11,7 @@
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
-#include "third_party/blink/public/common/message_port/message_port_channel.h"
+#include "third_party/blink/public/common/messaging/message_port_channel.h"
namespace content {
diff --git a/chromium/content/browser/shared_worker/shared_worker_content_settings_proxy_impl.cc b/chromium/content/browser/shared_worker/shared_worker_content_settings_proxy_impl.cc
index ba7feb60615..3626969ae8c 100644
--- a/chromium/content/browser/shared_worker/shared_worker_content_settings_proxy_impl.cc
+++ b/chromium/content/browser/shared_worker/shared_worker_content_settings_proxy_impl.cc
@@ -26,7 +26,7 @@ SharedWorkerContentSettingsProxyImpl::~SharedWorkerContentSettingsProxyImpl() =
void SharedWorkerContentSettingsProxyImpl::AllowIndexedDB(
const base::string16& name,
AllowIndexedDBCallback callback) {
- if (!origin_.unique()) {
+ if (!origin_.opaque()) {
owner_->AllowIndexedDB(origin_.GetURL(), name, std::move(callback));
} else {
std::move(callback).Run(false);
@@ -35,7 +35,7 @@ void SharedWorkerContentSettingsProxyImpl::AllowIndexedDB(
void SharedWorkerContentSettingsProxyImpl::RequestFileSystemAccessSync(
RequestFileSystemAccessSyncCallback callback) {
- if (!origin_.unique()) {
+ if (!origin_.opaque()) {
owner_->AllowFileSystem(origin_.GetURL(), std::move(callback));
} else {
std::move(callback).Run(false);
diff --git a/chromium/content/browser/shared_worker/shared_worker_host.cc b/chromium/content/browser/shared_worker/shared_worker_host.cc
index a2f6eea00a8..03f17983ff2 100644
--- a/chromium/content/browser/shared_worker/shared_worker_host.cc
+++ b/chromium/content/browser/shared_worker/shared_worker_host.cc
@@ -8,6 +8,7 @@
#include "base/feature_list.h"
#include "base/metrics/histogram_macros.h"
+#include "base/task/post_task.h"
#include "base/unguessable_token.h"
#include "content/browser/appcache/appcache_navigation_handle.h"
#include "content/browser/devtools/shared_worker_devtools_manager.h"
@@ -17,15 +18,18 @@
#include "content/browser/shared_worker/shared_worker_instance.h"
#include "content/browser/shared_worker/shared_worker_service_impl.h"
#include "content/browser/storage_partition_impl.h"
+#include "content/common/navigation_subresource_loader_params.h"
#include "content/common/url_loader_factory_bundle.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/common/content_client.h"
#include "content/public/common/renderer_preference_watcher.mojom.h"
#include "services/network/public/cpp/features.h"
-#include "third_party/blink/public/common/message_port/message_port_channel.h"
+#include "third_party/blink/public/common/features.h"
+#include "third_party/blink/public/common/messaging/message_port_channel.h"
#include "third_party/blink/public/common/service_worker/service_worker_utils.h"
#include "third_party/blink/public/platform/web_feature.mojom.h"
#include "third_party/blink/public/web/worker_content_settings_proxy.mojom.h"
@@ -36,8 +40,8 @@ namespace {
void AllowFileSystemOnIOThreadResponse(base::OnceCallback<void(bool)> callback,
bool result) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(std::move(callback), result));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(std::move(callback), result));
}
void AllowFileSystemOnIOThread(const GURL& url,
@@ -103,6 +107,12 @@ SharedWorkerHost::SharedWorkerHost(
// 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_);
+
+ // Keep the renderer process alive that will be hosting the shared worker.
+ RenderProcessHost* process_host = RenderProcessHost::FromID(process_id);
+ DCHECK(!IsShuttingDown(process_host));
+ process_host->IncrementKeepAliveRefCount(
+ RenderProcessHost::KeepAliveClientType::kSharedWorker);
}
SharedWorkerHost::~SharedWorkerHost() {
@@ -122,6 +132,12 @@ SharedWorkerHost::~SharedWorkerHost() {
case Phase::kTerminationSentAndClosed:
break;
}
+
+ RenderProcessHost* process_host = RenderProcessHost::FromID(process_id_);
+ if (!IsShuttingDown(process_host)) {
+ process_host->DecrementKeepAliveRefCount(
+ RenderProcessHost::KeepAliveClientType::kSharedWorker);
+ }
}
void SharedWorkerHost::Start(
@@ -130,10 +146,41 @@ void SharedWorkerHost::Start(
service_worker_provider_info,
network::mojom::URLLoaderFactoryAssociatedPtrInfo
main_script_loader_factory,
- std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories) {
+ blink::mojom::SharedWorkerMainScriptLoadParamsPtr main_script_load_params,
+ std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories,
+ base::Optional<SubresourceLoaderParams> subresource_loader_params) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
AdvanceTo(Phase::kStarted);
+#if DCHECK_IS_ON()
+ // Verify the combination of the given args based on the flags. See the
+ // function comment for details.
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+ // NetworkService (PlzWorker):
+ DCHECK(service_worker_provider_info);
+ DCHECK(!main_script_loader_factory);
+ DCHECK(main_script_load_params);
+ DCHECK(subresource_loader_factories);
+ DCHECK(!subresource_loader_factories->default_factory_info());
+ } else if (base::FeatureList::IsEnabled(
+ blink::features::kServiceWorkerServicification)) {
+ // S13nServiceWorker (non-NetworkService):
+ DCHECK(service_worker_provider_info);
+ DCHECK(main_script_loader_factory);
+ DCHECK(subresource_loader_factories);
+ DCHECK(subresource_loader_factories->default_factory_info());
+ DCHECK(!subresource_loader_params);
+ DCHECK(!main_script_load_params);
+ } else {
+ // Legacy case (to be deprecated):
+ DCHECK(!service_worker_provider_info);
+ DCHECK(!main_script_loader_factory);
+ DCHECK(!subresource_loader_factories);
+ DCHECK(!subresource_loader_params);
+ DCHECK(!main_script_load_params);
+ }
+#endif // DCHECK_IS_ON()
+
mojom::SharedWorkerInfoPtr info(mojom::SharedWorkerInfo::New(
instance_->url(), instance_->name(), instance_->content_security_policy(),
instance_->content_security_policy_type(),
@@ -173,29 +220,42 @@ void SharedWorkerHost::Start(
mojom::kNavigation_SharedWorkerSpec, process_id_,
mojo::MakeRequest(&interface_provider)));
- // Add the default factory to the bundle for subresource loading to pass to
- // the renderer. The bundle is only provided if
- // NetworkService/S13nServiceWorker is enabled.
- // TODO(nhiroki): We might need to set the default factory to AppCache
- // instead, as we do for frames, if requests from this shared worker are
- // supposed to go through AppCache. Currently, we set the default factory to a
- // direct network.
- if (blink::ServiceWorkerUtils::IsServicificationEnabled()) {
- DCHECK(subresource_loader_factories);
- DCHECK(!subresource_loader_factories->default_factory_info());
- if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
- network::mojom::URLLoaderFactoryPtrInfo network_factory_info;
- CreateNetworkFactory(mojo::MakeRequest(&network_factory_info));
- subresource_loader_factories->default_factory_info() =
- std::move(network_factory_info);
+ // Set the default factory to the bundle for subresource loading to pass to
+ // the renderer when NetworkService is on. When S13nServiceWorker is on, the
+ // default factory is already provided by SharedWorkerServiceImpl.
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+ // If the caller has supplied a default URLLoaderFactory override (for,
+ // e.g., AppCache), use that.
+ network::mojom::URLLoaderFactoryPtrInfo default_factory_info;
+ if (subresource_loader_params &&
+ subresource_loader_params->loader_factory_info.is_valid()) {
+ default_factory_info =
+ std::move(subresource_loader_params->loader_factory_info);
} else {
- // Use the non-NetworkService network factory for the process when
- // NetworkService is off.
- network::mojom::URLLoaderFactoryPtr default_factory;
- RenderProcessHost::FromID(process_id_)
- ->CreateURLLoaderFactory(mojo::MakeRequest(&default_factory));
- subresource_loader_factories->default_factory_info() =
- default_factory.PassInterface();
+ CreateNetworkFactory(mojo::MakeRequest(&default_factory_info));
+ }
+ subresource_loader_factories->default_factory_info() =
+ std::move(default_factory_info);
+ }
+
+ // NetworkService (PlzWorker):
+ // Prepare the controller service worker info to pass to the renderer. This is
+ // only provided if NetworkService is enabled. In the non-NetworkService case,
+ // the controller is sent in SetController IPCs during the request for the
+ // shared worker script.
+ mojom::ControllerServiceWorkerInfoPtr controller;
+ blink::mojom::ServiceWorkerObjectAssociatedPtrInfo remote_object;
+ blink::mojom::ServiceWorkerState sent_state;
+ if (subresource_loader_params &&
+ subresource_loader_params->controller_service_worker_info) {
+ DCHECK(base::FeatureList::IsEnabled(network::features::kNetworkService));
+ controller =
+ std::move(subresource_loader_params->controller_service_worker_info);
+ // |object_info| can be nullptr when the service worker context or the
+ // service worker version is gone during shared worker startup.
+ if (controller->object_info) {
+ controller->object_info->request = mojo::MakeRequest(&remote_object);
+ sent_state = controller->object_info->state;
}
}
@@ -207,9 +267,24 @@ void SharedWorkerHost::Start(
std::move(content_settings), std::move(service_worker_provider_info),
appcache_handle_ ? appcache_handle_->appcache_host_id()
: kAppCacheNoHostId,
- std::move(main_script_loader_factory),
- std::move(subresource_loader_factories), std::move(host),
- std::move(worker_request_), std::move(interface_provider));
+ std::move(main_script_loader_factory), std::move(main_script_load_params),
+ std::move(subresource_loader_factories), std::move(controller),
+ std::move(host), std::move(worker_request_),
+ std::move(interface_provider));
+
+ // NetworkService (PlzWorker):
+ // |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 ServiceWorkerObjectHost.
+ if (remote_object.is_valid()) {
+ DCHECK(base::FeatureList::IsEnabled(network::features::kNetworkService));
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(
+ &ServiceWorkerObjectHost::AddRemoteObjectPtrAndUpdateState,
+ subresource_loader_params->controller_service_worker_object_host,
+ std::move(remote_object), sent_state));
+ }
// Monitor the lifetime of the worker.
worker_.set_connection_error_handler(base::BindOnce(
@@ -217,7 +292,9 @@ void SharedWorkerHost::Start(
}
// This is similar to
-// RenderFrameHostImpl::CreateNetworkServiceDefaultFactoryAndObserve.
+// RenderFrameHostImpl::CreateNetworkServiceDefaultFactoryAndObserve, but this
+// host doesn't observe network service crashes. Instead, the renderer detects
+// the connection error and terminates the worker.
void SharedWorkerHost::CreateNetworkFactory(
network::mojom::URLLoaderFactoryRequest request) {
network::mojom::URLLoaderFactoryParamsPtr params =
@@ -228,16 +305,13 @@ void SharedWorkerHost::CreateNetworkFactory(
service_->storage_partition()->GetNetworkContext()->CreateURLLoaderFactory(
std::move(request), std::move(params));
-
- // TODO(crbug.com/848256): Detect connection error and send a IPC with a new
- // network factory like UpdateSubresourceLoaderFactories does for frames.
}
void SharedWorkerHost::AllowFileSystem(
const GURL& url,
base::OnceCallback<void(bool)> callback) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&AllowFileSystemOnIOThread, url,
RenderProcessHost::FromID(process_id_)
->GetBrowserContext()
@@ -248,8 +322,8 @@ void SharedWorkerHost::AllowFileSystem(
void SharedWorkerHost::AllowIndexedDB(const GURL& url,
const base::string16& name,
base::OnceCallback<void(bool)> callback) {
- BrowserThread::PostTaskAndReplyWithResult(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraitsAndReplyWithResult(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&AllowIndexedDBOnIOThread, url, name,
RenderProcessHost::FromID(process_id_)
->GetBrowserContext()
@@ -431,8 +505,9 @@ void SharedWorkerHost::AddClient(mojom::SharedWorkerClientPtr client,
}
void SharedWorkerHost::BindDevToolsAgent(
+ blink::mojom::DevToolsAgentHostAssociatedPtrInfo host,
blink::mojom::DevToolsAgentAssociatedRequest request) {
- worker_->BindDevToolsAgent(std::move(request));
+ worker_->BindDevToolsAgent(std::move(host), std::move(request));
}
void SharedWorkerHost::SetAppCacheHandle(
diff --git a/chromium/content/browser/shared_worker/shared_worker_host.h b/chromium/content/browser/shared_worker/shared_worker_host.h
index c75d9920a90..0bf7bbac4aa 100644
--- a/chromium/content/browser/shared_worker/shared_worker_host.h
+++ b/chromium/content/browser/shared_worker/shared_worker_host.h
@@ -25,6 +25,7 @@
#include "mojo/public/cpp/bindings/binding.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
#include "services/service_manager/public/mojom/interface_provider.mojom.h"
+#include "third_party/blink/public/mojom/shared_worker/shared_worker_main_script_load_params.mojom.h"
#include "third_party/blink/public/web/devtools_agent.mojom.h"
class GURL;
@@ -40,6 +41,7 @@ class SharedWorkerContentSettingsProxyImpl;
class SharedWorkerInstance;
class SharedWorkerServiceImpl;
class URLLoaderFactoryBundleInfo;
+struct SubresourceLoaderParams;
// The SharedWorkerHost is the interface that represents the browser side of
// the browser <-> worker communication channel. This is owned by
@@ -61,25 +63,41 @@ class CONTENT_EXPORT SharedWorkerHost
// information about its ServiceWorkerProviderHost, the browser-side host for
// supporting the shared worker as a service worker client.
//
- // S13nServiceWorker:
+ // S13nServiceWorker (non-NetworkService):
// |main_script_loader_factory| is sent to the renderer process and is to be
// used to request the shared worker's main script. Currently it's only
- // non-null when S13nServiceWorker is enabled, to allow service worker
- // machinery to observe the request, but other web platform features may also
- // use it someday.
+ // non-null when S13nServiceWorker is enabled but NetworkService is disabled,
+ // to allow service worker machinery to observe the request.
+ //
+ // NetworkService (PlzWorker):
+ // |main_script_load_params| is sent to the renderer process and to be used to
+ // load the shared worker main script pre-requested by the browser process.
+ // This is only non-null when NetworkService is enabled.
//
// NetworkService:
// |subresource_loader_factories| is sent to the renderer process and is to be
// used to request subresources where applicable. For example, this allows the
// shared worker to load chrome-extension:// URLs which the renderer's default
// loader factory can't load.
+ //
+ // NetworkService (PlzWorker):
+ // |subresource_loader_params| contains information about the default loader
+ // factory for |subresource_loader_factories_| and the service worker
+ // controller. The default loader factory can be associated with some request
+ // interceptor like AppCacheRequestHandler. This is only non-null when
+ // NetworkService is enabled.
+ // When S13nServiceWorker is enabled but NetworkService is disabled, the
+ // default network loader factory is created by the RenderFrameHost, and
+ // service worker controller is sent via ServiceWorkerContainer#SetController.
void Start(
mojom::SharedWorkerFactoryPtr factory,
mojom::ServiceWorkerProviderInfoForSharedWorkerPtr
service_worker_provider_info,
network::mojom::URLLoaderFactoryAssociatedPtrInfo
main_script_loader_factory,
- std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories);
+ blink::mojom::SharedWorkerMainScriptLoadParamsPtr main_script_load_params,
+ std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories,
+ base::Optional<SubresourceLoaderParams> subresource_loader_params);
void AllowFileSystem(const GURL& url,
base::OnceCallback<void(bool)> callback);
@@ -95,7 +113,8 @@ class CONTENT_EXPORT SharedWorkerHost
int frame_id,
const blink::MessagePortChannel& port);
- void BindDevToolsAgent(blink::mojom::DevToolsAgentAssociatedRequest request);
+ void BindDevToolsAgent(blink::mojom::DevToolsAgentHostAssociatedPtrInfo host,
+ blink::mojom::DevToolsAgentAssociatedRequest request);
void SetAppCacheHandle(
std::unique_ptr<AppCacheNavigationHandle> appcache_handle);
diff --git a/chromium/content/browser/shared_worker/shared_worker_host_unittest.cc b/chromium/content/browser/shared_worker/shared_worker_host_unittest.cc
index c5043d87b0f..402e6ef8d9b 100644
--- a/chromium/content/browser/shared_worker/shared_worker_host_unittest.cc
+++ b/chromium/content/browser/shared_worker/shared_worker_host_unittest.cc
@@ -11,35 +11,80 @@
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
#include "content/browser/appcache/chrome_appcache_service.h"
+#include "content/browser/service_worker/embedded_worker_test_helper.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/common/navigation_subresource_loader_params.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_storage_partition.h"
#include "content/public/test/test_utils.h"
#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/strong_associated_binding.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
#include "mojo/public/cpp/test_support/test_utils.h"
-#include "services/network/test/test_network_context.h"
+#include "services/network/public/cpp/features.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/common/message_port/message_port_channel.h"
+#include "third_party/blink/public/common/messaging/message_port_channel.h"
+#include "third_party/blink/public/common/service_worker/service_worker_utils.h"
#include "url/origin.h"
using blink::MessagePortChannel;
namespace content {
+namespace {
+
+// A mock URLLoaderFactory which just fails to create a loader. This is
+// sufficient because the tests don't exercise script loading.
+class NotImplementedNetworkURLLoaderFactory final
+ : public network::mojom::URLLoaderFactory {
+ public:
+ NotImplementedNetworkURLLoaderFactory() = default;
+
+ // network::mojom::URLLoaderFactory implementation.
+ void CreateLoaderAndStart(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) override {
+ network::URLLoaderCompletionStatus status;
+ status.error_code = net::ERR_NOT_IMPLEMENTED;
+ client->OnComplete(status);
+ }
+
+ void Clone(network::mojom::URLLoaderFactoryRequest request) override {
+ bindings_.AddBinding(this, std::move(request));
+ }
+
+ private:
+ mojo::BindingSet<network::mojom::URLLoaderFactory> bindings_;
+
+ DISALLOW_COPY_AND_ASSIGN(NotImplementedNetworkURLLoaderFactory);
+};
+
+} // namespace
+
class SharedWorkerHostTest : public testing::Test {
public:
+ void SetUp() override {
+ helper_.reset(new EmbeddedWorkerTestHelper(base::FilePath()));
+ mock_url_loader_factory_ =
+ std::make_unique<NotImplementedNetworkURLLoaderFactory>();
+ mock_render_process_host_.OverrideURLLoaderFactory(
+ mock_url_loader_factory_.get());
+ }
+
SharedWorkerHostTest()
: mock_render_process_host_(&browser_context_),
- service_(&storage_partition_,
+ service_(nullptr /* storage_partition */,
nullptr /* service_worker_context */,
- nullptr /* appcache_service */) {
- storage_partition_.set_network_context(&network_context_);
- }
+ nullptr /* appcache_service */) {}
base::WeakPtr<SharedWorkerHost> CreateHost() {
GURL url("http://www.example.com/w.js");
@@ -66,9 +111,59 @@ class SharedWorkerHostTest : public testing::Test {
void StartWorker(SharedWorkerHost* host,
mojom::SharedWorkerFactoryPtr factory) {
- host->Start(std::move(factory), nullptr /* service_worker_provider_info */,
- {} /* main_script_loader_factory */,
- nullptr /* subresource_loader_factories */);
+ mojom::ServiceWorkerProviderInfoForSharedWorkerPtr provider_info = nullptr;
+ network::mojom::URLLoaderFactoryAssociatedPtrInfo
+ main_script_loader_factory;
+ blink::mojom::SharedWorkerMainScriptLoadParamsPtr main_script_load_params;
+ std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories;
+ base::Optional<SubresourceLoaderParams> subresource_loader_params;
+
+ // Set up various mocks based on NetworkService/S13nServiceWorker
+ // configuration. See the comment on SharedWorkerHost::Start() for details.
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+ provider_info = mojom::ServiceWorkerProviderInfoForSharedWorker::New();
+ ServiceWorkerProviderHost::PreCreateForSharedWorker(
+ helper_->context()->AsWeakPtr(), mock_render_process_host_.GetID(),
+ &provider_info);
+
+ main_script_load_params =
+ blink::mojom::SharedWorkerMainScriptLoadParams::New();
+ subresource_loader_factories.reset(new URLLoaderFactoryBundleInfo());
+ subresource_loader_params = SubresourceLoaderParams();
+
+ network::mojom::URLLoaderFactoryPtr loader_factory_ptr;
+ mojo::MakeStrongBinding(
+ std::make_unique<NotImplementedNetworkURLLoaderFactory>(),
+ mojo::MakeRequest(&loader_factory_ptr));
+
+ subresource_loader_params->loader_factory_info =
+ loader_factory_ptr.PassInterface();
+ } else if (blink::ServiceWorkerUtils::IsServicificationEnabled()) {
+ provider_info = mojom::ServiceWorkerProviderInfoForSharedWorker::New();
+ ServiceWorkerProviderHost::PreCreateForSharedWorker(
+ helper_->context()->AsWeakPtr(), mock_render_process_host_.GetID(),
+ &provider_info);
+
+ mojo::MakeStrongAssociatedBinding(
+ std::make_unique<NotImplementedNetworkURLLoaderFactory>(),
+ mojo::MakeRequest(&main_script_loader_factory));
+
+ network::mojom::URLLoaderFactoryPtr default_factory_ptr;
+ mojo::MakeStrongBinding(
+ std::make_unique<NotImplementedNetworkURLLoaderFactory>(),
+ mojo::MakeRequest(&default_factory_ptr));
+ subresource_loader_factories.reset(new URLLoaderFactoryBundleInfo(
+ default_factory_ptr.PassInterface(),
+ URLLoaderFactoryBundleInfo::SchemeMap(),
+ URLLoaderFactoryBundleInfo::OriginMap(),
+ true /* bypass_redirect_checks */));
+ }
+
+ host->Start(std::move(factory), std::move(provider_info),
+ std::move(main_script_loader_factory),
+ std::move(main_script_load_params),
+ std::move(subresource_loader_factories),
+ std::move(subresource_loader_params));
}
MessagePortChannel AddClient(SharedWorkerHost* host,
@@ -83,10 +178,12 @@ class SharedWorkerHostTest : public testing::Test {
protected:
TestBrowserThreadBundle test_browser_thread_bundle_;
- TestStoragePartition storage_partition_;
- network::TestNetworkContext network_context_;
TestBrowserContext browser_context_;
+ // This URLLoaderFactory is used in MockRenderProcessHost.
+ std::unique_ptr<NotImplementedNetworkURLLoaderFactory>
+ mock_url_loader_factory_;
MockRenderProcessHost mock_render_process_host_;
+ std::unique_ptr<EmbeddedWorkerTestHelper> helper_;
SharedWorkerServiceImpl service_;
@@ -195,11 +292,8 @@ TEST_F(SharedWorkerHostTest, TerminateAfterStarting) {
// 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 */,
- {} /* main_script_loader_factory */,
- nullptr /* subresource_loader_factories */);
+ StartWorker(host.get(), std::move(factory));
// Add a client.
MockSharedWorkerClient client;
diff --git a/chromium/content/browser/shared_worker/shared_worker_script_fetcher.cc b/chromium/content/browser/shared_worker/shared_worker_script_fetcher.cc
new file mode 100644
index 00000000000..6c50fba1143
--- /dev/null
+++ b/chromium/content/browser/shared_worker/shared_worker_script_fetcher.cc
@@ -0,0 +1,205 @@
+// 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_script_fetcher.h"
+
+#include "base/feature_list.h"
+#include "content/browser/shared_worker/shared_worker_script_loader.h"
+#include "content/browser/shared_worker/shared_worker_script_loader_factory.h"
+#include "content/common/throttling_url_loader.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/common/url_loader_throttle.h"
+#include "net/traffic_annotation/network_traffic_annotation.h"
+#include "services/network/public/cpp/features.h"
+#include "services/network/public/cpp/resource_response.h"
+
+namespace content {
+
+namespace {
+
+const net::NetworkTrafficAnnotationTag
+ kSharedWorkerScriptLoadTrafficAnnotation =
+ net::DefineNetworkTrafficAnnotation("shared_worker_script_load",
+ R"(
+ semantics {
+ sender: "Shared Worker Script Load"
+ description:
+ "This request is issued by SharedWorker to fetch its main script."
+ trigger:
+ "Calling new SharedWorker()."
+ data: "Anything the initiator wants to send."
+ destination: OTHER
+ }
+ policy {
+ cookies_allowed: YES
+ cookies_store: "user"
+ setting: "This request can be prevented by disabling JavaScript."
+ chrome_policy {
+ URLBlacklist {
+ URLBlacklist: { entries: '*' }
+ }
+ }
+ chrome_policy {
+ URLWhitelist {
+ URLWhitelist { }
+ }
+ }
+ }
+)");
+
+} // namespace
+
+void SharedWorkerScriptFetcher::CreateAndStart(
+ std::unique_ptr<SharedWorkerScriptLoaderFactory> script_loader_factory,
+ std::vector<std::unique_ptr<URLLoaderThrottle>> throttles,
+ std::unique_ptr<network::ResourceRequest> resource_request,
+ CreateAndStartCallback callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(base::FeatureList::IsEnabled(network::features::kNetworkService));
+ // This fetcher will delete itself. See the class level comment.
+ (new SharedWorkerScriptFetcher(std::move(script_loader_factory),
+ std::move(resource_request),
+ std::move(callback)))
+ ->Start(std::move(throttles));
+}
+
+SharedWorkerScriptFetcher::SharedWorkerScriptFetcher(
+ std::unique_ptr<SharedWorkerScriptLoaderFactory> script_loader_factory,
+ std::unique_ptr<network::ResourceRequest> resource_request,
+ CreateAndStartCallback callback)
+ : script_loader_factory_(std::move(script_loader_factory)),
+ resource_request_(std::move(resource_request)),
+ callback_(std::move(callback)),
+ response_url_loader_binding_(this) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+}
+
+SharedWorkerScriptFetcher::~SharedWorkerScriptFetcher() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+}
+
+void SharedWorkerScriptFetcher::Start(
+ std::vector<std::unique_ptr<URLLoaderThrottle>> throttles) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ auto shared_url_loader_factory =
+ base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
+ script_loader_factory_.get());
+
+ // SharedWorker doesn't have a frame.
+ int32_t routing_id = MSG_ROUTING_NONE;
+
+ // NetworkService is not interested in the request ID.
+ int request_id = -1;
+
+ url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
+ std::move(shared_url_loader_factory), std::move(throttles), routing_id,
+ request_id, network::mojom::kURLLoadOptionNone, resource_request_.get(),
+ this, kSharedWorkerScriptLoadTrafficAnnotation,
+ base::ThreadTaskRunnerHandle::Get());
+}
+
+void SharedWorkerScriptFetcher::OnReceiveResponse(
+ const network::ResourceResponseHead& head) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ base::WeakPtr<SharedWorkerScriptLoader> script_loader =
+ script_loader_factory_->GetScriptLoader();
+ if (script_loader && script_loader->default_loader_used_) {
+ // If the default network loader was used to handle the URL load request we
+ // need to see if the request interceptors want to potentially create a new
+ // loader for the response, e.g. AppCache's fallback.
+ DCHECK(!response_url_loader_);
+ network::mojom::URLLoaderClientRequest response_client_request;
+ if (script_loader->MaybeCreateLoaderForResponse(head, &response_url_loader_,
+ &response_client_request,
+ url_loader_.get())) {
+ DCHECK(response_url_loader_);
+ response_url_loader_binding_.Bind(std::move(response_client_request));
+ subresource_loader_params_ = script_loader->TakeSubresourceLoaderParams();
+ url_loader_.reset();
+ // OnReceiveResponse() will be called again.
+ return;
+ }
+ }
+
+ blink::mojom::SharedWorkerMainScriptLoadParamsPtr main_script_load_params =
+ blink::mojom::SharedWorkerMainScriptLoadParams::New();
+
+ // Fill in params for loading shared worker's main script and subresources.
+ main_script_load_params->response_head = head;
+ if (url_loader_) {
+ // The main script was served by a request interceptor or the default
+ // network loader.
+ DCHECK(!response_url_loader_);
+ main_script_load_params->url_loader_client_endpoints =
+ url_loader_->Unbind();
+ subresource_loader_params_ = script_loader->TakeSubresourceLoaderParams();
+ } else {
+ // The main script was served by the default network loader first, and then
+ // a request interceptor created another loader |response_url_loader_| for
+ // serving an alternative response.
+ DCHECK(response_url_loader_);
+ DCHECK(response_url_loader_binding_.is_bound());
+ main_script_load_params->url_loader_client_endpoints =
+ network::mojom::URLLoaderClientEndpoints::New(
+ response_url_loader_.PassInterface(),
+ response_url_loader_binding_.Unbind());
+ }
+
+ for (size_t i = 0; i < redirect_infos_.size(); ++i) {
+ main_script_load_params->redirect_infos.emplace_back(redirect_infos_[i]);
+ main_script_load_params->redirect_response_heads.emplace_back(
+ redirect_response_heads_[i]);
+ }
+
+ std::move(callback_).Run(std::move(main_script_load_params),
+ std::move(subresource_loader_params_),
+ true /* success */);
+ delete this;
+}
+
+void SharedWorkerScriptFetcher::OnReceiveRedirect(
+ const net::RedirectInfo& redirect_info,
+ const network::ResourceResponseHead& head) {
+ redirect_infos_.push_back(redirect_info);
+ redirect_response_heads_.push_back(head);
+ url_loader_->FollowRedirect(base::nullopt);
+}
+
+void SharedWorkerScriptFetcher::OnUploadProgress(
+ int64_t current_position,
+ int64_t total_size,
+ OnUploadProgressCallback callback) {
+ NOTREACHED();
+}
+
+void SharedWorkerScriptFetcher::OnReceiveCachedMetadata(
+ const std::vector<uint8_t>& data) {
+ NOTREACHED();
+}
+
+void SharedWorkerScriptFetcher::OnTransferSizeUpdated(
+ int32_t transfer_size_diff) {
+ NOTREACHED();
+}
+
+void SharedWorkerScriptFetcher::OnStartLoadingResponseBody(
+ mojo::ScopedDataPipeConsumerHandle body) {
+ // Not reached. At this point, the loader and client endpoints must have
+ // been unbound and forwarded to the renderer.
+ NOTREACHED();
+}
+
+void SharedWorkerScriptFetcher::OnComplete(
+ const network::URLLoaderCompletionStatus& status) {
+ // We can reach here only when loading fails before receiving a response head.
+ DCHECK_NE(net::OK, status.error_code);
+ std::move(callback_).Run(nullptr /* main_script_load_params */,
+ base::nullopt /* subresource_loader_params */,
+ false /* success */);
+ delete this;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/shared_worker/shared_worker_script_fetcher.h b/chromium/content/browser/shared_worker/shared_worker_script_fetcher.h
new file mode 100644
index 00000000000..4117d0d73c2
--- /dev/null
+++ b/chromium/content/browser/shared_worker/shared_worker_script_fetcher.h
@@ -0,0 +1,97 @@
+// 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_SHARED_WORKER_SCRIPT_FETCHER_H_
+#define CONTENT_BROWSER_SHARED_WORKER_SHARED_WORKER_SCRIPT_FETCHER_H_
+
+#include "base/callback.h"
+#include "base/optional.h"
+#include "content/common/navigation_subresource_loader_params.h"
+#include "mojo/public/cpp/bindings/binding.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.mojom.h"
+#include "third_party/blink/public/mojom/shared_worker/shared_worker_main_script_load_params.mojom.h"
+
+namespace network {
+struct ResourceResponseHead;
+struct ResourceRequest;
+} // namespace network
+
+namespace content {
+
+class SharedWorkerScriptLoaderFactory;
+class ThrottlingURLLoader;
+class URLLoaderThrottle;
+
+// NetworkService (PlzWorker):
+// This is an implementation of the URLLoaderClient for shared worker's main
+// script fetch. The loader and client bounded with this class are to be unbound
+// and forwarded to the renderer process on OnReceiveResponse, and the resource
+// loader in the renderer process will take them over.
+//
+// SharedWorkerScriptFetcher deletes itself when the ownership of the loader and
+// client is passed to the renderer, or on failure. It lives on the IO thread.
+class SharedWorkerScriptFetcher : public network::mojom::URLLoaderClient {
+ public:
+ using CreateAndStartCallback =
+ base::OnceCallback<void(blink::mojom::SharedWorkerMainScriptLoadParamsPtr,
+ base::Optional<SubresourceLoaderParams>,
+ bool /* success */)>;
+
+ // Called on the IO thread, and calls |callback| on the IO thread when
+ // OnReceiveResponse is called on |this|.
+ static void CreateAndStart(
+ std::unique_ptr<SharedWorkerScriptLoaderFactory> script_loader_factory,
+ std::vector<std::unique_ptr<URLLoaderThrottle>> throttles,
+ std::unique_ptr<network::ResourceRequest> resource_request,
+ CreateAndStartCallback callback);
+
+ private:
+ SharedWorkerScriptFetcher(
+ std::unique_ptr<SharedWorkerScriptLoaderFactory> script_loader_factory,
+ std::unique_ptr<network::ResourceRequest> resource_request,
+ CreateAndStartCallback callback);
+
+ ~SharedWorkerScriptFetcher() override;
+
+ void Start(std::vector<std::unique_ptr<URLLoaderThrottle>> throttles);
+
+ // network::mojom::URLLoaderClient
+ void OnReceiveResponse(const network::ResourceResponseHead& head) override;
+ void OnReceiveRedirect(const net::RedirectInfo& redirect_info,
+ const network::ResourceResponseHead& head) 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 body) override;
+ void OnComplete(const network::URLLoaderCompletionStatus& status) override;
+
+ std::unique_ptr<SharedWorkerScriptLoaderFactory> script_loader_factory_;
+
+ std::unique_ptr<network::ResourceRequest> resource_request_;
+ CreateAndStartCallback callback_;
+
+ // URLLoader instance backed by a request interceptor (e.g.,
+ // AppCacheRequestHandler) or the network service.
+ std::unique_ptr<ThrottlingURLLoader> url_loader_;
+
+ // URLLoader instance for handling a response received from the default
+ // network loader. This can be provided by an interceptor. For example,
+ // AppCache's interceptor creates this for AppCache's fallback case.
+ network::mojom::URLLoaderPtr response_url_loader_;
+ mojo::Binding<network::mojom::URLLoaderClient> response_url_loader_binding_;
+
+ base::Optional<SubresourceLoaderParams> subresource_loader_params_;
+
+ std::vector<net::RedirectInfo> redirect_infos_;
+ std::vector<network::ResourceResponseHead> redirect_response_heads_;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_SHARED_WORKER_SHARED_WORKER_SCRIPT_FETCHER_H_
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 0ded2f6fabd..f8299e8ab95 100644
--- a/chromium/content/browser/shared_worker/shared_worker_script_loader.cc
+++ b/chromium/content/browser/shared_worker/shared_worker_script_loader.cc
@@ -62,6 +62,10 @@ SharedWorkerScriptLoader::SharedWorkerScriptLoader(
SharedWorkerScriptLoader::~SharedWorkerScriptLoader() = default;
+base::WeakPtr<SharedWorkerScriptLoader> SharedWorkerScriptLoader::GetWeakPtr() {
+ return weak_factory_.GetWeakPtr();
+}
+
void SharedWorkerScriptLoader::Start() {
if (interceptor_index_ < interceptors_.size()) {
auto* interceptor = interceptors_[interceptor_index_++].get();
@@ -82,13 +86,11 @@ void SharedWorkerScriptLoader::MaybeStartLoader(
SingleRequestURLLoaderFactory::RequestHandler single_request_handler) {
DCHECK(interceptor);
- // TODO(nhiroki): Create SubresourceLoaderParams for intercepting subresource
- // requests and populating the "controller" field in ServiceWorkerContainer,
- // and send the params to the renderer when we create the SharedWorker.
- // Note that we shouldn't try the next interceptor if this interceptor
- // provides SubresourceLoaderParams. See comments on
- // NavigationLoaderInterceptor::MaybeCreateSubresourceLoaderParams() for
- // details.
+ // Create SubresourceLoaderParams for intercepting subresource requests and
+ // populating the "controller" field in ServiceWorkerContainer. This can be
+ // null if the interceptor is not interested in this request.
+ subresource_loader_params_ =
+ interceptor->MaybeCreateSubresourceLoaderParams();
if (single_request_handler) {
// The interceptor elected to handle the request. Use it.
@@ -103,12 +105,19 @@ void SharedWorkerScriptLoader::MaybeStartLoader(
return;
}
+ // We shouldn't try the remaining interceptors if this interceptor provides
+ // SubresourceLoaderParams. For details, see comments on
+ // NavigationLoaderInterceptor::MaybeCreateSubresourceLoaderParams().
+ if (subresource_loader_params_)
+ interceptor_index_ = interceptors_.size();
+
// Continue until all the interceptors are tried.
Start();
}
void SharedWorkerScriptLoader::LoadFromNetwork(
bool reset_subresource_loader_params) {
+ default_loader_used_ = true;
network::mojom::URLLoaderClientPtr client;
if (url_loader_client_binding_)
url_loader_client_binding_.Unbind();
@@ -237,4 +246,26 @@ void SharedWorkerScriptLoader::OnComplete(
client_->OnComplete(status);
}
+bool SharedWorkerScriptLoader::MaybeCreateLoaderForResponse(
+ const network::ResourceResponseHead& response,
+ network::mojom::URLLoaderPtr* response_url_loader,
+ network::mojom::URLLoaderClientRequest* response_client_request,
+ ThrottlingURLLoader* url_loader) {
+ DCHECK(default_loader_used_);
+ for (auto& interceptor : interceptors_) {
+ bool skip_other_interceptors = false;
+ if (interceptor->MaybeCreateLoaderForResponse(
+ response, response_url_loader, response_client_request, url_loader,
+ &skip_other_interceptors)) {
+ // Both ServiceWorkerRequestHandler and AppCacheRequestHandler don't set
+ // skip_other_interceptors.
+ DCHECK(!skip_other_interceptors);
+ subresource_loader_params_ =
+ interceptor->MaybeCreateSubresourceLoaderParams();
+ return true;
+ }
+ }
+ return false;
+}
+
} // namespace content
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 e8a876e5ca7..017ca7f6a4c 100644
--- a/chromium/content/browser/shared_worker/shared_worker_script_loader.h
+++ b/chromium/content/browser/shared_worker/shared_worker_script_loader.h
@@ -6,6 +6,7 @@
#define CONTENT_BROWSER_SHARED_WORKER_SHARED_WORKER_SCRIPT_LOADER_H_
#include "base/macros.h"
+#include "content/common/navigation_subresource_loader_params.h"
#include "content/common/single_request_url_loader_factory.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
@@ -19,6 +20,7 @@ class SharedURLLoaderFactory;
namespace content {
class AppCacheHost;
+class ThrottlingURLLoader;
class NavigationLoaderInterceptor;
class ResourceContext;
class ServiceWorkerProviderHost;
@@ -82,6 +84,25 @@ class SharedWorkerScriptLoader : public network::mojom::URLLoader,
mojo::ScopedDataPipeConsumerHandle body) override;
void OnComplete(const network::URLLoaderCompletionStatus& status) override;
+ // Returns a URLLoader client endpoint 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,
+ network::mojom::URLLoaderPtr* response_url_loader,
+ network::mojom::URLLoaderClientRequest* response_client_request,
+ ThrottlingURLLoader* url_loader);
+
+ base::Optional<SubresourceLoaderParams> TakeSubresourceLoaderParams() {
+ return std::move(subresource_loader_params_);
+ }
+
+ base::WeakPtr<SharedWorkerScriptLoader> GetWeakPtr();
+
+ // Set to true if the default URLLoader (network service) was used for the
+ // current request.
+ bool default_loader_used_ = false;
+
private:
void Start();
void MaybeStartLoader(
@@ -94,6 +115,8 @@ class SharedWorkerScriptLoader : public network::mojom::URLLoader,
std::vector<std::unique_ptr<NavigationLoaderInterceptor>> interceptors_;
size_t interceptor_index_ = 0;
+ base::Optional<SubresourceLoaderParams> subresource_loader_params_;
+
const int process_id_;
const int32_t routing_id_;
const int32_t request_id_;
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 74eaef69a4b..bdbec0c41e5 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
@@ -5,6 +5,7 @@
#include "content/browser/shared_worker/shared_worker_script_loader_factory.h"
#include <memory>
+#include "base/feature_list.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_provider_host.h"
@@ -12,6 +13,7 @@
#include "content/browser/shared_worker/shared_worker_script_loader.h"
#include "content/public/browser/browser_thread.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/resource_response.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "third_party/blink/public/common/service_worker/service_worker_utils.h"
@@ -51,29 +53,40 @@ void SharedWorkerScriptLoaderFactory::CreateLoaderAndStart(
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- // Handle only the main script (RESOURCE_TYPE_SHARED_WORKER). Import scripts
- // should go to the network loader or controller.
- if (resource_request.resource_type != RESOURCE_TYPE_SHARED_WORKER) {
- mojo::ReportBadMessage(
- "SharedWorkerScriptLoaderFactory should only get requests for shared "
- "worker scripts");
- return;
+ // When NetworkService is not enabled, this function is called from the
+ // renderer process, so use ReportBadMessage() instead of DCHECK().
+ if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+ // Handle only the main script (RESOURCE_TYPE_SHARED_WORKER). Import scripts
+ // should go to the network loader or controller.
+ if (resource_request.resource_type != RESOURCE_TYPE_SHARED_WORKER) {
+ mojo::ReportBadMessage(
+ "SharedWorkerScriptLoaderFactory should only get requests for shared "
+ "worker scripts");
+ return;
+ }
+ if (script_loader_) {
+ mojo::ReportBadMessage(
+ "SharedWorkerScriptLoaderFactory should be used only one time");
+ return;
+ }
}
+ DCHECK_EQ(RESOURCE_TYPE_SHARED_WORKER, resource_request.resource_type);
+ DCHECK(!script_loader_);
// Create a SharedWorkerScriptLoader to load the script.
- mojo::MakeStrongBinding(
- std::make_unique<SharedWorkerScriptLoader>(
- process_id_, routing_id, request_id, options, resource_request,
- std::move(client), service_worker_provider_host_, appcache_host_,
- resource_context_, loader_factory_, traffic_annotation),
- std::move(request));
+ auto script_loader = std::make_unique<SharedWorkerScriptLoader>(
+ process_id_, routing_id, request_id, options, resource_request,
+ std::move(client), service_worker_provider_host_, appcache_host_,
+ resource_context_, loader_factory_, traffic_annotation);
+ script_loader_ = script_loader->GetWeakPtr();
+ mojo::MakeStrongBinding(std::move(script_loader), std::move(request));
}
void SharedWorkerScriptLoaderFactory::Clone(
network::mojom::URLLoaderFactoryRequest request) {
// This method is required to support synchronous requests, which shared
// worker script requests are not.
- NOTIMPLEMENTED();
+ NOTREACHED();
}
} // namespace content
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 f54949bad5b..58072e3a966 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
@@ -6,6 +6,7 @@
#define CONTENT_BROWSER_SHARED_WORKER_SHARED_WORKER_SCRIPT_LOADER_FACTORY_H_
#include "base/macros.h"
+#include "content/common/navigation_subresource_loader_params.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
namespace network {
@@ -17,6 +18,7 @@ namespace content {
class AppCacheHost;
class ServiceWorkerContextWrapper;
class ServiceWorkerProviderHost;
+class SharedWorkerScriptLoader;
class ResourceContext;
// S13nServiceWorker:
@@ -28,7 +30,8 @@ class ResourceContext;
//
// This creates a SharedWorkerScriptLoader to load the script, which follows
// redirects and sets the controller service worker on the shared worker if
-// needed.
+// needed. It's an error to call CreateLoaderAndStart() more than a total of one
+// time across this object or any of its clones.
class SharedWorkerScriptLoaderFactory
: public network::mojom::URLLoaderFactory {
public:
@@ -56,6 +59,10 @@ class SharedWorkerScriptLoaderFactory
traffic_annotation) override;
void Clone(network::mojom::URLLoaderFactoryRequest request) override;
+ base::WeakPtr<SharedWorkerScriptLoader> GetScriptLoader() {
+ return script_loader_;
+ }
+
private:
const int process_id_;
base::WeakPtr<ServiceWorkerProviderHost> service_worker_provider_host_;
@@ -63,6 +70,10 @@ class SharedWorkerScriptLoaderFactory
ResourceContext* resource_context_ = nullptr;
scoped_refptr<network::SharedURLLoaderFactory> loader_factory_;
+ // This is owned by StrongBinding associated with the given URLLoaderRequest,
+ // and invalidated after request completion or failure.
+ base::WeakPtr<SharedWorkerScriptLoader> script_loader_;
+
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 51f91bdd7e2..04d1913121e 100644
--- a/chromium/content/browser/shared_worker/shared_worker_service_impl.cc
+++ b/chromium/content/browser/shared_worker/shared_worker_service_impl.cc
@@ -8,58 +8,75 @@
#include <algorithm>
#include <iterator>
+#include <string>
+#include "base/bind.h"
#include "base/callback.h"
#include "base/feature_list.h"
#include "base/logging.h"
#include "base/macros.h"
+#include "base/metrics/field_trial_params.h"
#include "base/task/post_task.h"
#include "content/browser/appcache/appcache_navigation_handle.h"
#include "content/browser/appcache/appcache_navigation_handle_core.h"
#include "content/browser/file_url_loader_factory.h"
#include "content/browser/shared_worker/shared_worker_host.h"
#include "content/browser/shared_worker/shared_worker_instance.h"
+#include "content/browser/shared_worker/shared_worker_script_fetcher.h"
+#include "content/browser/shared_worker/shared_worker_script_loader.h"
#include "content/browser/shared_worker/shared_worker_script_loader_factory.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/common/content_constants_internal.h"
+#include "content/common/navigation_subresource_loader_params.h"
#include "content/common/service_worker/service_worker_provider.mojom.h"
#include "content/common/shared_worker/shared_worker_client.mojom.h"
+#include "content/common/throttling_url_loader.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/common/bind_interface_helpers.h"
+#include "content/public/common/content_features.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/common/renderer_preferences.h"
#include "mojo/public/cpp/bindings/strong_associated_binding.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "services/network/loader_util.h"
#include "services/network/public/cpp/features.h"
-#include "third_party/blink/public/common/message_port/message_port_channel.h"
+#include "third_party/blink/public/common/messaging/message_port_channel.h"
#include "third_party/blink/public/common/service_worker/service_worker_utils.h"
#include "url/origin.h"
namespace content {
namespace {
-bool IsShuttingDown(RenderProcessHost* host) {
- return !host || host->FastShutdownStarted() ||
- host->IsKeepAliveRefCountDisabled();
-}
+using StartLoaderCallback =
+ base::OnceCallback<void(mojom::ServiceWorkerProviderInfoForSharedWorkerPtr,
+ network::mojom::URLLoaderFactoryAssociatedPtrInfo,
+ std::unique_ptr<URLLoaderFactoryBundleInfo>,
+ blink::mojom::SharedWorkerMainScriptLoadParamsPtr,
+ base::Optional<SubresourceLoaderParams>,
+ bool)>;
std::unique_ptr<URLLoaderFactoryBundleInfo> CreateFactoryBundle(
int process_id,
StoragePartitionImpl* storage_partition,
bool file_support) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled());
- ContentBrowserClient::NonNetworkURLLoaderFactoryMap factories;
+ ContentBrowserClient::NonNetworkURLLoaderFactoryMap non_network_factories;
GetContentClient()
->browser()
->RegisterNonNetworkSubresourceURLLoaderFactories(
- process_id, MSG_ROUTING_NONE, &factories);
+ process_id, MSG_ROUTING_NONE, &non_network_factories);
auto factory_bundle = std::make_unique<URLLoaderFactoryBundleInfo>();
- for (auto& pair : factories) {
+ for (auto& pair : non_network_factories) {
const std::string& scheme = pair.first;
std::unique_ptr<network::mojom::URLLoaderFactory> factory =
std::move(pair.second);
@@ -67,8 +84,8 @@ std::unique_ptr<URLLoaderFactoryBundleInfo> CreateFactoryBundle(
network::mojom::URLLoaderFactoryPtr factory_ptr;
mojo::MakeStrongBinding(std::move(factory),
mojo::MakeRequest(&factory_ptr));
- factory_bundle->factories_info().emplace(scheme,
- factory_ptr.PassInterface());
+ factory_bundle->scheme_specific_factory_infos().emplace(
+ scheme, factory_ptr.PassInterface());
}
if (file_support) {
@@ -80,13 +97,51 @@ std::unique_ptr<URLLoaderFactoryBundleInfo> CreateFactoryBundle(
network::mojom::URLLoaderFactoryPtr file_factory_ptr;
mojo::MakeStrongBinding(std::move(file_factory),
mojo::MakeRequest(&file_factory_ptr));
- factory_bundle->factories_info().emplace(url::kFileScheme,
- file_factory_ptr.PassInterface());
+ factory_bundle->scheme_specific_factory_infos().emplace(
+ url::kFileScheme, file_factory_ptr.PassInterface());
+ }
+
+ // Use RenderProcessHost's network factory as the default factory if
+ // NetworkService is off. If NetworkService is on the default factory is
+ // set in CreateScriptLoaderOnIO().
+ if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+ // Using an opaque origin here should be safe - the URLLoaderFactory created
+ // for such origin shouldn't have any special privileges. Additionally, the
+ // origin should not be inspected at all in the legacy, non-NetworkService
+ // path.
+ const url::Origin kSafeOrigin = url::Origin();
+
+ network::mojom::URLLoaderFactoryPtr default_factory;
+ RenderProcessHost::FromID(process_id)
+ ->CreateURLLoaderFactory(kSafeOrigin,
+ mojo::MakeRequest(&default_factory));
+ factory_bundle->default_factory_info() = default_factory.PassInterface();
}
return factory_bundle;
}
+void DidCreateScriptLoaderOnIO(
+ StartLoaderCallback callback,
+ mojom::ServiceWorkerProviderInfoForSharedWorkerPtr
+ service_worker_provider_info,
+ network::mojom::URLLoaderFactoryAssociatedPtrInfo
+ main_script_loader_factory,
+ std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories,
+ blink::mojom::SharedWorkerMainScriptLoadParamsPtr main_script_load_params,
+ base::Optional<SubresourceLoaderParams> subresource_loader_params,
+ bool success) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(std::move(callback),
+ std::move(service_worker_provider_info),
+ std::move(main_script_loader_factory),
+ std::move(subresource_loader_factories),
+ std::move(main_script_load_params),
+ std::move(subresource_loader_params), success));
+}
+
void CreateScriptLoaderOnIO(
scoped_refptr<URLLoaderFactoryGetter> loader_factory_getter,
std::unique_ptr<URLLoaderFactoryBundleInfo> factory_bundle_for_browser_info,
@@ -95,12 +150,11 @@ void CreateScriptLoaderOnIO(
AppCacheNavigationHandleCore* appcache_handle_core,
std::unique_ptr<network::SharedURLLoaderFactoryInfo>
blob_url_loader_factory_info,
+ std::unique_ptr<network::ResourceRequest> resource_request,
int process_id,
- base::OnceCallback<void(mojom::ServiceWorkerProviderInfoForSharedWorkerPtr,
- network::mojom::URLLoaderFactoryAssociatedPtrInfo,
- std::unique_ptr<URLLoaderFactoryBundleInfo>)>
- callback) {
+ StartLoaderCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled());
// Set up for service worker.
auto provider_info = mojom::ServiceWorkerProviderInfoForSharedWorker::New();
@@ -116,22 +170,24 @@ void CreateScriptLoaderOnIO(
url_loader_factory = network::SharedURLLoaderFactory::Create(
std::move(blob_url_loader_factory_info));
} else {
- // Add the default factory to the bundle for browser.
- DCHECK(!factory_bundle_for_browser_info->default_factory_info());
-
// Create a factory bundle to use.
scoped_refptr<URLLoaderFactoryBundle> factory_bundle =
base::MakeRefCounted<URLLoaderFactoryBundle>(
std::move(factory_bundle_for_browser_info));
- // Get the direct network factory from |loader_factory_getter|. When
- // NetworkService is enabled, it returns a factory that 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));
+ // Add the default factory to the bundle for browser if NetworkService
+ // is on. When NetworkService is off, we already created the default factory
+ // in CreateFactoryBundle().
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+ // Get the direct network factory from |loader_factory_getter|. When
+ // NetworkService is enabled, it returns a factory that 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));
+ }
url_loader_factory = factory_bundle;
}
@@ -144,6 +200,31 @@ void CreateScriptLoaderOnIO(
appcache_handle_core ? appcache_handle_core->host()->GetWeakPtr()
: nullptr;
+ // NetworkService (PlzWorker):
+ // Start loading a shared worker main script.
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+ // TODO(nhiroki): Figure out what we should do in |wc_getter| for loading
+ // shared worker's main script.
+ base::RepeatingCallback<WebContents*()> wc_getter =
+ base::BindRepeating([]() -> WebContents* { return nullptr; });
+ std::vector<std::unique_ptr<URLLoaderThrottle>> throttles =
+ GetContentClient()->browser()->CreateURLLoaderThrottles(
+ *resource_request, context->resource_context(), wc_getter,
+ nullptr /* navigation_ui_data */, -1 /* frame_tree_node_id */);
+
+ SharedWorkerScriptFetcher::CreateAndStart(
+ std::make_unique<SharedWorkerScriptLoaderFactory>(
+ process_id, context.get(), host,
+ std::move(appcache_host), context->resource_context(),
+ std::move(url_loader_factory)),
+ std::move(throttles), std::move(resource_request),
+ base::BindOnce(DidCreateScriptLoaderOnIO, std::move(callback),
+ std::move(provider_info),
+ nullptr /* main_script_loader_factory */,
+ std::move(subresource_loader_factories)));
+ return;
+ }
+
// Create the SharedWorkerScriptLoaderFactory.
network::mojom::URLLoaderFactoryAssociatedPtrInfo main_script_loader_factory;
mojo::MakeStrongAssociatedBinding(
@@ -153,18 +234,23 @@ void CreateScriptLoaderOnIO(
std::move(url_loader_factory)),
mojo::MakeRequest(&main_script_loader_factory));
- // We continue in StartWorker.
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::BindOnce(std::move(callback), std::move(provider_info),
- std::move(main_script_loader_factory),
- std::move(subresource_loader_factories)));
+ DidCreateScriptLoaderOnIO(std::move(callback), std::move(provider_info),
+ std::move(main_script_loader_factory),
+ std::move(subresource_loader_factories),
+ nullptr /* main_script_load_params */,
+ base::nullopt /* subresource_loader_params */,
+ true /* success */);
}
} // namespace
+bool IsShuttingDown(RenderProcessHost* host) {
+ return !host || host->FastShutdownStarted() ||
+ host->IsKeepAliveRefCountDisabled();
+}
+
SharedWorkerServiceImpl::SharedWorkerServiceImpl(
- StoragePartition* storage_partition,
+ StoragePartitionImpl* storage_partition,
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
scoped_refptr<ChromeAppCacheService> appcache_service)
: storage_partition_(storage_partition),
@@ -203,12 +289,20 @@ void SharedWorkerServiceImpl::TerminateAllWorkersForTesting(
std::move(callback));
} else {
terminate_all_workers_callback_ = std::move(callback);
- for (auto& host : worker_hosts_)
- host->TerminateWorker();
- // Monitor for actual termination in DestroyHost.
+ // Use an explicit iterator and be careful because TerminateWorker() can
+ // call DestroyHost(), which removes the host from |worker_hosts_| and could
+ // invalidate the iterator.
+ for (auto it = worker_hosts_.begin(); it != worker_hosts_.end();)
+ (*it++)->TerminateWorker();
}
}
+void SharedWorkerServiceImpl::SetWorkerTerminationCallbackForTesting(
+ base::OnceClosure callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ terminate_all_workers_callback_ = std::move(callback);
+}
+
void SharedWorkerServiceImpl::ConnectToWorker(
int process_id,
int frame_id,
@@ -273,17 +367,60 @@ void SharedWorkerServiceImpl::ConnectToWorker(
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));
- // Complete the call to TerminateAllWorkersForTesting if no more workers.
+ // Run the termination callback if no more workers.
if (worker_hosts_.empty() && terminate_all_workers_callback_)
std::move(terminate_all_workers_callback_).Run();
+}
+
+// TODO(nhiroki): Align this function with AddAdditionalRequestHeaders() in
+// navigation_request.cc, FrameFetchContext, and WorkerFetchContext.
+void SharedWorkerServiceImpl::AddAdditionalRequestHeaders(
+ network::ResourceRequest* resource_request,
+ BrowserContext* browser_context) {
+ DCHECK(base::FeatureList::IsEnabled(network::features::kNetworkService));
+
+ // TODO(nhiroki): Return early when the request is neither HTTP nor HTTPS
+ // (i.e., Blob URL or Data URL). This should be checked by
+ // SchemeIsHTTPOrHTTPS(), but currently cross-origin workers on extensions
+ // are allowed and the check doesn't work well. See https://crbug.com/867302.
+
+ // Set the "Accept" header.
+ resource_request->headers.SetHeaderIfMissing(network::kAcceptHeader,
+ network::kDefaultAcceptHeader);
+
+ // Set the "DNT" header if necessary.
+ RendererPreferences renderer_preferences;
+ GetContentClient()->browser()->UpdateRendererPreferencesForWorker(
+ browser_context, &renderer_preferences);
+ if (renderer_preferences.enable_do_not_track)
+ resource_request->headers.SetHeaderIfMissing(kDoNotTrackHeader, "1");
+
+ // Set the "Save-Data" header if necessary.
+ if (GetContentClient()->browser()->IsDataSaverEnabled(browser_context) &&
+ !base::GetFieldTrialParamByFeatureAsBool(features::kDataSaverHoldback,
+ "holdback_web", false)) {
+ resource_request->headers.SetHeaderIfMissing("Save-Data", "on");
+ }
- if (!IsShuttingDown(process_host))
- process_host->DecrementKeepAliveRefCount(
- RenderProcessHost::KeepAliveClientType::kSharedWorker);
+ // Set the "Sec-Metadata" header if necessary.
+ if (base::FeatureList::IsEnabled(features::kSecMetadata) ||
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableExperimentalWebPlatformFeatures)) {
+ // The worker's origin can be different from the constructor's origin, for
+ // example, when the worker created from the extension.
+ // TODO(hiroshige): Add DCHECK to make sure the same-originness once the
+ // cross-origin workers are deprecated (https://crbug.com/867302).
+ std::string site_value = "cross-site";
+ if (resource_request->request_initiator->IsSameOriginWith(
+ url::Origin::Create(resource_request->url))) {
+ site_value = "same-origin";
+ }
+ std::string value = base::StringPrintf(
+ "destination=\"sharedworker\", site=\"%s\"", site_value.c_str());
+ resource_request->headers.SetHeaderIfMissing("Sec-Metadata", value);
+ }
}
void SharedWorkerServiceImpl::CreateWorker(
@@ -294,7 +431,6 @@ void SharedWorkerServiceImpl::CreateWorker(
const blink::MessagePortChannel& message_port,
scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
DCHECK(!blob_url_loader_factory || instance->url().SchemeIsBlob());
bool constructor_uses_file_url =
@@ -312,24 +448,37 @@ void SharedWorkerServiceImpl::CreateWorker(
// Bounce to the IO thread to setup service worker and appcache support in
// case the request for the worker script will need to be intercepted by them.
if (blink::ServiceWorkerUtils::IsServicificationEnabled()) {
- StoragePartitionImpl* storage_partition =
- service_worker_context_->storage_partition();
- if (!storage_partition) {
- // The context is shutting down. Just drop the request.
- return;
- }
-
// Set up the factory bundle for non-NetworkService URLs, e.g.,
// chrome-extension:// URLs. One factory bundle is consumed by the browser
// for SharedWorkerScriptLoaderFactory, and one is sent to the renderer for
// subresource loading.
std::unique_ptr<URLLoaderFactoryBundleInfo> factory_bundle_for_browser =
- CreateFactoryBundle(process_id, storage_partition,
+ CreateFactoryBundle(process_id, storage_partition_,
constructor_uses_file_url);
std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories =
- CreateFactoryBundle(process_id, storage_partition,
+ CreateFactoryBundle(process_id, storage_partition_,
constructor_uses_file_url);
+ // NetworkService (PlzWorker):
+ // Create a resource request for initiating shared worker script fetch from
+ // the browser process.
+ std::unique_ptr<network::ResourceRequest> resource_request;
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+ // TODO(nhiroki): Populate more fields like referrer.
+ // (https://crbug.com/715632)
+ resource_request = std::make_unique<network::ResourceRequest>();
+ resource_request->url = weak_host->instance()->url();
+ resource_request->request_initiator =
+ weak_host->instance()->constructor_origin();
+ resource_request->resource_type = RESOURCE_TYPE_SHARED_WORKER;
+
+ auto* render_process_host = RenderProcessHost::FromID(process_id);
+ DCHECK(!IsShuttingDown(render_process_host));
+ AddAdditionalRequestHeaders(resource_request.get(),
+ render_process_host->GetBrowserContext());
+ }
+
+ // NetworkService (PlzWorker):
// An appcache interceptor is available only when the network service is
// enabled.
AppCacheNavigationHandleCore* appcache_handle_core = nullptr;
@@ -340,27 +489,67 @@ void SharedWorkerServiceImpl::CreateWorker(
weak_host->SetAppCacheHandle(std::move(appcache_handle));
}
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&CreateScriptLoaderOnIO,
- service_worker_context_->storage_partition()
- ->url_loader_factory_getter(),
+ storage_partition_->url_loader_factory_getter(),
std::move(factory_bundle_for_browser),
std::move(subresource_loader_factories), service_worker_context_,
appcache_handle_core,
blob_url_loader_factory ? blob_url_loader_factory->Clone()
: nullptr,
- process_id,
- base::BindOnce(&SharedWorkerServiceImpl::StartWorker,
+ std::move(resource_request), process_id,
+ base::BindOnce(&SharedWorkerServiceImpl::DidCreateScriptLoader,
weak_factory_.GetWeakPtr(), std::move(instance),
weak_host, std::move(client), process_id, frame_id,
message_port)));
return;
}
+ // Legacy case (to be deprecated):
StartWorker(std::move(instance), weak_host, std::move(client), process_id,
- frame_id, message_port, nullptr, {}, nullptr);
+ frame_id, message_port,
+ nullptr /* service_worker_provider_info */,
+ {} /* main_script_loader_factory */,
+ nullptr /* subresource_loader_factories */,
+ nullptr /* main_script_load_params */,
+ base::nullopt /* subresource_loader_params */);
+}
+
+void SharedWorkerServiceImpl::DidCreateScriptLoader(
+ 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
+ main_script_loader_factory,
+ std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories,
+ blink::mojom::SharedWorkerMainScriptLoadParamsPtr main_script_load_params,
+ base::Optional<SubresourceLoaderParams> subresource_loader_params,
+ bool success) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled());
+
+ // NetworkService (PlzWorker):
+ // If the script fetcher fails to load shared worker's main script, notify the
+ // client of the failure and abort shared worker startup.
+ if (!success) {
+ DCHECK(base::FeatureList::IsEnabled(network::features::kNetworkService));
+ client->OnScriptLoadFailed();
+ return;
+ }
+
+ StartWorker(
+ std::move(instance), std::move(host), std::move(client), process_id,
+ frame_id, message_port, std::move(service_worker_provider_info),
+ std::move(main_script_loader_factory),
+ std::move(subresource_loader_factories),
+ std::move(main_script_load_params), std::move(subresource_loader_params));
}
void SharedWorkerServiceImpl::StartWorker(
@@ -374,7 +563,9 @@ void SharedWorkerServiceImpl::StartWorker(
service_worker_provider_info,
network::mojom::URLLoaderFactoryAssociatedPtrInfo
main_script_loader_factory,
- std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories) {
+ std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories,
+ blink::mojom::SharedWorkerMainScriptLoadParamsPtr main_script_load_params,
+ base::Optional<SubresourceLoaderParams> subresource_loader_params) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
// The host may already be gone if something forcibly terminated the worker
@@ -391,10 +582,6 @@ void SharedWorkerServiceImpl::StartWorker(
return;
}
- // Keep the renderer process alive that will be hosting the shared worker.
- process_host->IncrementKeepAliveRefCount(
- RenderProcessHost::KeepAliveClientType::kSharedWorker);
-
// Get the factory used to instantiate the new shared worker instance in
// the target process.
mojom::SharedWorkerFactoryPtr factory;
@@ -402,7 +589,9 @@ void SharedWorkerServiceImpl::StartWorker(
host->Start(std::move(factory), std::move(service_worker_provider_info),
std::move(main_script_loader_factory),
- std::move(subresource_loader_factories));
+ std::move(main_script_load_params),
+ std::move(subresource_loader_factories),
+ std::move(subresource_loader_params));
host->AddClient(std::move(client), process_id, frame_id, message_port);
}
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 219003f234e..1433f18361b 100644
--- a/chromium/content/browser/shared_worker/shared_worker_service_impl.h
+++ b/chromium/content/browser/shared_worker/shared_worker_service_impl.h
@@ -20,7 +20,9 @@
#include "content/common/shared_worker/shared_worker_connector.mojom.h"
#include "content/common/shared_worker/shared_worker_factory.mojom.h"
#include "content/public/browser/shared_worker_service.h"
+#include "services/network/public/cpp/resource_response.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
+#include "third_party/blink/public/mojom/shared_worker/shared_worker_main_script_load_params.mojom.h"
namespace blink {
class MessagePortChannel;
@@ -31,13 +33,17 @@ namespace content {
class ChromeAppCacheService;
class SharedWorkerInstance;
class SharedWorkerHost;
-class StoragePartition;
+class StoragePartitionImpl;
+struct SubresourceLoaderParams;
+
+// Shared helper function
+bool IsShuttingDown(RenderProcessHost* host);
// Created per StoragePartition.
class CONTENT_EXPORT SharedWorkerServiceImpl : public SharedWorkerService {
public:
SharedWorkerServiceImpl(
- StoragePartition* storage_partition,
+ StoragePartitionImpl* storage_partition,
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
scoped_refptr<ChromeAppCacheService> appcache_service);
~SharedWorkerServiceImpl() override;
@@ -48,6 +54,7 @@ class CONTENT_EXPORT SharedWorkerServiceImpl : public SharedWorkerService {
const url::Origin& constructor_origin) override;
void TerminateAllWorkersForTesting(base::OnceClosure callback);
+ void SetWorkerTerminationCallbackForTesting(base::OnceClosure callback);
// Creates the worker if necessary or connects to an already existing worker.
void ConnectToWorker(
@@ -61,11 +68,16 @@ class CONTENT_EXPORT SharedWorkerServiceImpl : public SharedWorkerService {
void DestroyHost(SharedWorkerHost* host);
- StoragePartition* storage_partition() { return storage_partition_; }
+ StoragePartitionImpl* storage_partition() { return storage_partition_; }
private:
friend class SharedWorkerServiceImplTest;
friend class SharedWorkerHostTest;
+ FRIEND_TEST_ALL_PREFIXES(NetworkServiceRestartBrowserTest, SharedWorker);
+
+ static void AddAdditionalRequestHeaders(
+ network::ResourceRequest* resource_request,
+ BrowserContext* browser_context);
void CreateWorker(
std::unique_ptr<SharedWorkerInstance> instance,
@@ -74,6 +86,21 @@ class CONTENT_EXPORT SharedWorkerServiceImpl : public SharedWorkerService {
int frame_id,
const blink::MessagePortChannel& message_port,
scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory);
+ void DidCreateScriptLoader(
+ 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
+ main_script_loader_factory,
+ std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories,
+ blink::mojom::SharedWorkerMainScriptLoadParamsPtr main_script_load_params,
+ base::Optional<SubresourceLoaderParams> subresource_loader_params,
+ bool success);
void StartWorker(
std::unique_ptr<SharedWorkerInstance> instance,
base::WeakPtr<SharedWorkerHost> host,
@@ -85,7 +112,9 @@ class CONTENT_EXPORT SharedWorkerServiceImpl : public SharedWorkerService {
service_worker_provider_info,
network::mojom::URLLoaderFactoryAssociatedPtrInfo
main_script_loader_factory,
- std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories);
+ std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories,
+ blink::mojom::SharedWorkerMainScriptLoadParamsPtr main_script_load_params,
+ base::Optional<SubresourceLoaderParams> subresource_loader_params);
// Returns nullptr if there is no such host.
SharedWorkerHost* FindSharedWorkerHost(int process_id, int route_id);
@@ -97,7 +126,7 @@ class CONTENT_EXPORT SharedWorkerServiceImpl : public SharedWorkerService {
base::OnceClosure terminate_all_workers_callback_;
// |storage_partition_| owns |this|.
- StoragePartition* const storage_partition_;
+ StoragePartitionImpl* const storage_partition_;
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context_;
scoped_refptr<ChromeAppCacheService> appcache_service_;
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 e5d67bd381d..5f04ca09b0a 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
@@ -24,7 +24,7 @@
#include "mojo/public/cpp/bindings/binding_set.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 "third_party/blink/public/common/messaging/message_port_channel.h"
using blink::MessagePortChannel;
diff --git a/chromium/content/browser/shared_worker/worker_browsertest.cc b/chromium/content/browser/shared_worker/worker_browsertest.cc
index 9c7ffc1364b..b0f78e91ec4 100644
--- a/chromium/content/browser/shared_worker/worker_browsertest.cc
+++ b/chromium/content/browser/shared_worker/worker_browsertest.cc
@@ -9,10 +9,12 @@
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/sys_info.h"
+#include "base/task/post_task.h"
#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/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/client_certificate_delegate.h"
#include "content/public/common/content_features.h"
@@ -95,7 +97,8 @@ class WorkerTest : public ContentBrowserTest {
}
static void QuitUIMessageLoop(base::Callback<void()> callback) {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, std::move(callback));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ std::move(callback));
}
void NavigateAndWaitForAuth(const GURL& url) {
diff --git a/chromium/content/browser/site_instance_impl.cc b/chromium/content/browser/site_instance_impl.cc
index 073dc2d4f99..c3b4522f4ee 100644
--- a/chromium/content/browser/site_instance_impl.cc
+++ b/chromium/content/browser/site_instance_impl.cc
@@ -273,11 +273,6 @@ bool SiteInstanceImpl::HasWrongProcessForURL(const GURL& url) {
origin_lock);
}
-scoped_refptr<SiteInstanceImpl>
-SiteInstanceImpl::GetDefaultSubframeSiteInstance() {
- return browsing_instance_->GetDefaultSubframeSiteInstance();
-}
-
bool SiteInstanceImpl::RequiresDedicatedProcess() {
if (!has_site_)
return false;
@@ -285,11 +280,6 @@ bool SiteInstanceImpl::RequiresDedicatedProcess() {
return DoesSiteRequireDedicatedProcess(GetBrowserContext(), site_);
}
-bool SiteInstanceImpl::IsDefaultSubframeSiteInstance() const {
- return process_reuse_policy_ ==
- ProcessReusePolicy::USE_DEFAULT_SUBFRAME_PROCESS;
-}
-
void SiteInstanceImpl::IncrementActiveFrameCount() {
active_frame_count_++;
}
@@ -401,7 +391,11 @@ bool SiteInstanceImpl::IsSameWebSite(BrowserContext* browser_context,
}
// If the sites are the same, check isolated origins. If either URL matches
- // an isolated origin, compare origins rather than sites.
+ // an isolated origin, compare origins rather than sites. As an optimization
+ // to avoid unneeded isolated origin lookups, shortcut this check if the two
+ // origins are the same.
+ if (src_origin == dest_origin)
+ return true;
auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
url::Origin src_isolated_origin;
url::Origin dest_isolated_origin;
@@ -449,27 +443,21 @@ GURL SiteInstanceImpl::GetSiteForURL(BrowserContext* browser_context,
: real_url;
url::Origin origin = url::Origin::Create(url);
- // Isolated origins should use the full origin as their site URL. A subdomain
- // of an isolated origin should also use that isolated origin's site URL. It
- // is important to check |url| rather than |real_url| here, since some
- // effective URLs (such as for NTP) need to be resolved prior to the isolated
- // origin lookup.
- auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
- url::Origin isolated_origin;
- if (policy->GetMatchingIsolatedOrigin(origin, &isolated_origin))
- return isolated_origin.GetURL();
-
// If the url has a host, then determine the site. Skip file URLs to avoid a
// situation where site URL of file://localhost/ would mismatch Blink's origin
// (which ignores the hostname in this case - see https://crbug.com/776160).
if (!origin.host().empty() && origin.scheme() != url::kFileScheme) {
- // Only keep the scheme and registered domain of |origin|.
- std::string domain = net::registry_controlled_domains::GetDomainAndRegistry(
- origin.host(),
- net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
- std::string site = origin.scheme();
- site += url::kStandardSchemeSeparator;
- site += domain.empty() ? origin.host() : domain;
+ GURL site_url(GetSiteForOrigin(origin));
+
+ // Isolated origins should use the full origin as their site URL. A
+ // subdomain of an isolated origin should also use that isolated origin's
+ // site URL. It is important to check |origin| (based on |url|) rather than
+ // |real_url| here, since some effective URLs (such as for NTP) need to be
+ // resolved prior to the isolated origin lookup.
+ auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
+ url::Origin isolated_origin;
+ if (policy->GetMatchingIsolatedOrigin(origin, site_url, &isolated_origin))
+ return isolated_origin.GetURL();
// If an effective URL was used, augment the effective site URL with the
// underlying web site in the hash. This is needed to keep
@@ -479,17 +467,21 @@ GURL SiteInstanceImpl::GetSiteForURL(BrowserContext* browser_context,
// TODO(https://crbug.com/734722): Consider replacing this hack with
// a proper security principal.
if (should_use_effective_urls && url != real_url) {
- site += "#" + GetSiteForURL(browser_context, real_url,
- false /* should_use_effective_urls */)
- .spec();
+ std::string non_translated_site_url(
+ GetSiteForURL(browser_context, real_url,
+ false /* should_use_effective_urls */)
+ .spec());
+ GURL::Replacements replacements;
+ replacements.SetRefStr(non_translated_site_url.c_str());
+ site_url = site_url.ReplaceComponents(replacements);
}
- return GURL(site);
+ return site_url;
}
// If there is no host but there is a scheme, return the scheme.
// This is useful for cases like file URLs.
- if (!origin.unique()) {
+ if (!origin.opaque()) {
// Prefer to use the scheme of |origin| rather than |url|, to correctly
// cover blob:file: and filesystem:file: URIs (see also
// https://crbug.com/697111).
@@ -536,6 +528,18 @@ GURL SiteInstanceImpl::GetSiteForURL(BrowserContext* browser_context,
}
// static
+GURL SiteInstanceImpl::GetSiteForOrigin(const url::Origin& origin) {
+ // Only keep the scheme and registered domain of |origin|.
+ std::string domain = net::registry_controlled_domains::GetDomainAndRegistry(
+ origin.host(),
+ net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
+ std::string site = origin.scheme();
+ site += url::kStandardSchemeSeparator;
+ site += domain.empty() ? origin.host() : domain;
+ return GURL(site);
+}
+
+// static
GURL SiteInstanceImpl::GetEffectiveURL(BrowserContext* browser_context,
const GURL& url) {
return GetContentClient()->browser()->GetEffectiveURL(browser_context, url);
@@ -555,16 +559,21 @@ bool SiteInstanceImpl::DoesSiteRequireDedicatedProcess(
if (SiteIsolationPolicy::UseDedicatedProcessesForAllSites())
return true;
+ // Always require a dedicated process for isolated origins.
+ GURL site_url = SiteInstance::GetSiteForURL(browser_context, url);
+ auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
+ if (policy->IsIsolatedOrigin(url::Origin::Create(site_url)))
+ 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))
+ if (site_url.SchemeIs(kChromeErrorScheme))
return true;
- // Always require a dedicated process for isolated origins.
- GURL site_url = SiteInstance::GetSiteForURL(browser_context, url);
- auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
- if (policy->IsIsolatedOrigin(url::Origin::Create(site_url)))
+ // Isolate kChromeUIScheme pages from one another and from other kinds of
+ // schemes.
+ if (site_url.SchemeIs(content::kChromeUIScheme))
return true;
// Let the content embedder enable site isolation for specific URLs. Use the
@@ -597,12 +606,6 @@ bool SiteInstanceImpl::ShouldLockToOrigin(BrowserContext* browser_context,
if (site_url.SchemeIs(content::kGuestScheme))
return false;
- // TODO(creis, nick) https://crbug.com/510588 Chrome UI pages use the same
- // site (chrome://chrome), so they can't be locked because the site being
- // loaded doesn't match the SiteInstance.
- if (site_url.SchemeIs(content::kChromeUIScheme))
- return false;
-
// TODO(creis, nick): Until we can handle sites with effective URLs at the
// call sites of ChildProcessSecurityPolicy::CanAccessDataForOrigin, we
// must give the embedder a chance to exempt some sites to avoid process
diff --git a/chromium/content/browser/site_instance_impl.h b/chromium/content/browser/site_instance_impl.h
index b53db35063a..d72334b0b57 100644
--- a/chromium/content/browser/site_instance_impl.h
+++ b/chromium/content/browser/site_instance_impl.h
@@ -64,7 +64,6 @@ class CONTENT_EXPORT SiteInstanceImpl final : public SiteInstance,
bool IsRelatedSiteInstance(const SiteInstance* instance) override;
size_t GetRelatedActiveContentsCount() override;
bool RequiresDedicatedProcess() override;
- bool IsDefaultSubframeSiteInstance() const override;
// The policy to apply when selecting a RenderProcessHost for the
// SiteInstance. If no suitable RenderProcessHost for the SiteInstance exists
@@ -79,9 +78,6 @@ class CONTENT_EXPORT SiteInstanceImpl final : public SiteInstance,
// RenderProcessHost.
PROCESS_PER_SITE,
- // In this mode, subframes will be hosted in a designated RenderProcessHost.
- USE_DEFAULT_SUBFRAME_PROCESS,
-
// In this mode, the site will be rendered in a RenderProcessHost that is
// already in use for the site, either for a pending navigation or a
// committed navigation. If multiple such processes exist, ones that have
@@ -127,24 +123,25 @@ class CONTENT_EXPORT SiteInstanceImpl final : public SiteInstance,
// Returns the site for the given URL, which includes only the scheme and
// registered domain. Returns an empty GURL if the URL has no host.
- // |use_effective_urls| specifies whether to resolve |url| to an effective
- // URL (via ContentBrowserClient::GetEffectiveURL()) before determining the
- // site.
+ // |should_use_effective_urls| specifies whether to resolve |url| to an
+ // effective URL (via ContentBrowserClient::GetEffectiveURL()) before
+ // determining the site.
static GURL GetSiteForURL(BrowserContext* context,
const GURL& url,
- bool use_effective_urls);
+ bool should_use_effective_urls);
+
+ // Returns the site of a given |origin|. Unlike GetSiteForURL(), this does
+ // not utilize effective URLs, isolated origins, or other special logic. It
+ // only translates an origin into a site (i.e., scheme and eTLD+1) and is
+ // used internally by GetSiteForURL(). For making process model decisions,
+ // GetSiteForURL() should be used instead.
+ static GURL GetSiteForOrigin(const url::Origin& origin);
// Returns the URL to which a process should be locked for the given URL.
// This is computed similarly to the site URL (see GetSiteForURL), but
// without resolving effective URLs.
static GURL DetermineProcessLockURL(BrowserContext* context, const GURL& url);
- // Returns the SiteInstance, related to this one, that should be used
- // for subframes when an oopif is required, but a dedicated process is not.
- // This SiteInstance will be created if it doesn't already exist. There is
- // at most one of these per BrowsingInstance.
- scoped_refptr<SiteInstanceImpl> GetDefaultSubframeSiteInstance();
-
// Set the web site that this SiteInstance is rendering pages for.
// This includes the scheme and registered domain, but not the port. If the
// URL does not have a valid registered domain, then the full hostname is
@@ -225,12 +222,12 @@ class CONTENT_EXPORT SiteInstanceImpl final : public SiteInstance,
// true here also implies that |site_url| requires a dedicated process.
// However, the converse does not hold: this might still return false for
// certain special cases where an origin lock can't be applied even when
- // |site_url| requires a dedicated process (e.g., with
- // --site-per-process). Examples of those cases include <webview> guests,
- // WebUI, single-process mode, or extensions where a process is currently
- // allowed to be reused for different extensions. Most of these special
- // cases should eventually be removed, and this function should become
- // equivalent to DoesSiteRequireDedicatedProcess().
+ // |site_url| requires a dedicated process (e.g., with --site-per-process).
+ // Examples of those cases include <webview> guests, single-process mode, or
+ // extensions where a process is currently allowed to be reused for different
+ // extensions. Most of these special cases should eventually be removed, and
+ // this function should become equivalent to
+ // DoesSiteRequireDedicatedProcess().
static bool ShouldLockToOrigin(BrowserContext* browser_context,
GURL site_url);
@@ -252,11 +249,6 @@ class CONTENT_EXPORT SiteInstanceImpl final : public SiteInstance,
// Used to restrict a process' origin access rights.
void LockToOriginIfNeeded();
- // This gets the render process to use for default subframe site instances.
- RenderProcessHost* GetDefaultSubframeProcessHost(
- BrowserContext* browser_context,
- bool is_for_guests_only);
-
// An object used to construct RenderProcessHosts.
static const RenderProcessHostFactory* g_render_process_host_factory_;
diff --git a/chromium/content/browser/site_instance_impl_unittest.cc b/chromium/content/browser/site_instance_impl_unittest.cc
index ec3fa59c538..901f65023eb 100644
--- a/chromium/content/browser/site_instance_impl_unittest.cc
+++ b/chromium/content/browser/site_instance_impl_unittest.cc
@@ -676,79 +676,6 @@ TEST_F(SiteInstanceTest, OneSiteInstancePerSiteInBrowserContext) {
DrainMessageLoop();
}
-static scoped_refptr<SiteInstanceImpl> CreateSiteInstance(
- BrowserContext* browser_context,
- const GURL& url) {
- return SiteInstanceImpl::CreateForURL(browser_context, url);
-}
-
-// Test to ensure that pages that require certain privileges are grouped
-// in processes with similar pages.
-// TODO(nasko): Remove. See https://crbug.com/847127.
-TEST_F(SiteInstanceTest, ProcessSharingByType) {
- // This test shouldn't run with --site-per-process mode, which prohibits
- // the renderer process reuse this test explicitly exercises.
- if (AreAllSitesIsolatedForTesting())
- return;
-
- ChildProcessSecurityPolicyImpl* policy =
- ChildProcessSecurityPolicyImpl::GetInstance();
-
- // Make a bunch of mock renderers so that we hit the limit.
- std::unique_ptr<TestBrowserContext> browser_context(new TestBrowserContext());
- std::vector<std::unique_ptr<MockRenderProcessHost>> hosts;
- for (size_t i = 0; i < kMaxRendererProcessCount; ++i) {
- hosts.push_back(
- std::make_unique<MockRenderProcessHost>(browser_context.get()));
- hosts[i]->SetIsUsed();
- }
-
- // On Android by default the number of renderer hosts is unlimited and process
- // sharing doesn't happen. We set the override so that the test can run
- // everywhere.
- RenderProcessHost::SetMaxRendererProcessCount(kMaxRendererProcessCount);
-
- // Create some extension instances and make sure they share a process.
- scoped_refptr<SiteInstanceImpl> extension1_instance(
- CreateSiteInstance(browser_context.get(),
- GURL(kPrivilegedScheme + std::string("://foo/bar"))));
- set_privileged_process_id(extension1_instance->GetProcess()->GetID());
-
- scoped_refptr<SiteInstanceImpl> extension2_instance(
- CreateSiteInstance(browser_context.get(),
- GURL(kPrivilegedScheme + std::string("://baz/bar"))));
-
- std::unique_ptr<RenderProcessHost> extension_host(
- extension1_instance->GetProcess());
- EXPECT_EQ(extension1_instance->GetProcess(),
- extension2_instance->GetProcess());
-
- // Create some WebUI instances and make sure they share a process.
- scoped_refptr<SiteInstanceImpl> webui1_instance(
- CreateSiteInstance(browser_context.get(), GetWebUIURL(kChromeUIGpuHost)));
- policy->GrantWebUIBindings(webui1_instance->GetProcess()->GetID(),
- BINDINGS_POLICY_WEB_UI);
-
- scoped_refptr<SiteInstanceImpl> webui2_instance(CreateSiteInstance(
- browser_context.get(), GetWebUIURL(kChromeUIMediaInternalsHost)));
-
- std::unique_ptr<RenderProcessHost> dom_host(webui1_instance->GetProcess());
- EXPECT_EQ(webui1_instance->GetProcess(), webui2_instance->GetProcess());
-
- // Make sure none of differing privilege processes are mixed.
- EXPECT_NE(extension1_instance->GetProcess(), webui1_instance->GetProcess());
-
- for (size_t i = 0; i < kMaxRendererProcessCount; ++i) {
- EXPECT_NE(extension1_instance->GetProcess(), hosts[i].get());
- EXPECT_NE(webui1_instance->GetProcess(), hosts[i].get());
- }
-
- DrainMessageLoop();
-
- // Disable the process limit override.
- RenderProcessHost::SetMaxRendererProcessCount(0u);
-}
-
// Test to ensure that HasWrongProcessForURL behaves properly for different
// types of URLs.
TEST_F(SiteInstanceTest, HasWrongProcessForURL) {
@@ -945,55 +872,6 @@ TEST_F(SiteInstanceTest, IsSameWebsiteForNestedURLs) {
EXPECT_FALSE(SiteInstance::IsSameWebSite(nullptr, https_bar_url, fs_bar_url));
}
-TEST_F(SiteInstanceTest, DefaultSubframeSiteInstance) {
- if (AreAllSitesIsolatedForTesting())
- return; // --top-document-isolation is not possible.
-
- base::test::ScopedFeatureList scoped_feature_list;
- scoped_feature_list.InitAndEnableFeature(features::kTopDocumentIsolation);
-
- std::unique_ptr<TestBrowserContext> browser_context(new TestBrowserContext());
- scoped_refptr<SiteInstanceImpl> main_instance =
- SiteInstanceImpl::Create(browser_context.get());
- scoped_refptr<SiteInstanceImpl> subframe_instance =
- main_instance->GetDefaultSubframeSiteInstance();
- int subframe_instance_id = subframe_instance->GetId();
-
- EXPECT_NE(main_instance, subframe_instance);
- EXPECT_EQ(subframe_instance, main_instance->GetDefaultSubframeSiteInstance());
- EXPECT_FALSE(main_instance->IsDefaultSubframeSiteInstance());
- EXPECT_TRUE(subframe_instance->IsDefaultSubframeSiteInstance());
-
- EXPECT_EQ(0, browser_client()->GetAndClearSiteInstanceDeleteCount());
- EXPECT_EQ(0, browser_client()->GetAndClearBrowsingInstanceDeleteCount());
-
- // Free the subframe instance.
- subframe_instance = nullptr;
- EXPECT_EQ(1, browser_client()->GetAndClearSiteInstanceDeleteCount());
- EXPECT_EQ(0, browser_client()->GetAndClearBrowsingInstanceDeleteCount());
-
- // Calling GetDefaultSubframeSiteInstance again should return a new
- // SiteInstance with a different ID from the original.
- subframe_instance = main_instance->GetDefaultSubframeSiteInstance();
- EXPECT_NE(subframe_instance->GetId(), subframe_instance_id);
- EXPECT_FALSE(main_instance->IsDefaultSubframeSiteInstance());
- EXPECT_TRUE(subframe_instance->IsDefaultSubframeSiteInstance());
- EXPECT_EQ(subframe_instance->GetDefaultSubframeSiteInstance(),
- subframe_instance);
- EXPECT_EQ(0, browser_client()->GetAndClearSiteInstanceDeleteCount());
- EXPECT_EQ(0, browser_client()->GetAndClearBrowsingInstanceDeleteCount());
-
- // Free the main instance.
- main_instance = nullptr;
- EXPECT_EQ(1, browser_client()->GetAndClearSiteInstanceDeleteCount());
- EXPECT_EQ(0, browser_client()->GetAndClearBrowsingInstanceDeleteCount());
-
- // Free the subframe instance, which should free the browsing instance.
- subframe_instance = nullptr;
- EXPECT_EQ(1, browser_client()->GetAndClearSiteInstanceDeleteCount());
- EXPECT_EQ(1, browser_client()->GetAndClearBrowsingInstanceDeleteCount());
-}
-
TEST_F(SiteInstanceTest, IsolatedOrigins) {
GURL foo_url("http://www.foo.com");
GURL isolated_foo_url("http://isolated.foo.com");
diff --git a/chromium/content/browser/site_per_process_browsertest.cc b/chromium/content/browser/site_per_process_browsertest.cc
index 396d50ce3cf..5068b4b8091 100644
--- a/chromium/content/browser/site_per_process_browsertest.cc
+++ b/chromium/content/browser/site_per_process_browsertest.cc
@@ -32,6 +32,7 @@
#include "base/strings/string_split.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/task/post_task.h"
#include "base/test/bind_test_util.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/test_timeouts.h"
@@ -65,6 +66,7 @@
#include "content/common/renderer.mojom.h"
#include "content/common/view_messages.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/interstitial_page_delegate.h"
#include "content/public/browser/navigation_handle.h"
@@ -72,7 +74,6 @@
#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"
#include "content/public/common/content_switches.h"
@@ -206,9 +207,9 @@ void SimulateMouseClick(RenderWidgetHost* rwh, int x, int y) {
rwh->ForwardMouseEvent(mouse_event);
}
-// Retrieve document.origin for the frame |ftn|.
-EvalJsResult GetDocumentOrigin(FrameTreeNode* ftn) {
- return EvalJs(ftn, "document.origin;");
+// Retrieve self.origin for the frame |ftn|.
+EvalJsResult GetOriginFromRenderer(FrameTreeNode* ftn) {
+ return EvalJs(ftn, "self.origin;");
}
double GetFrameDeviceScaleFactor(const ToRenderFrameHost& adapter) {
@@ -577,8 +578,8 @@ class UpdateViewportIntersectionMessageFilter
// OnUpdateViewportIntersection returns. This additional post on the IO
// thread guarantees that by the time OnUpdateViewportIntersectionOnUI runs,
// the message has been handled on the UI thread.
- content::BrowserThread::PostTask(
- content::BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {content::BrowserThread::IO},
base::BindOnce(&UpdateViewportIntersectionMessageFilter::
OnUpdateViewportIntersectionPostOnIO,
this, viewport_intersection, compositing_rect,
@@ -588,8 +589,8 @@ class UpdateViewportIntersectionMessageFilter
const gfx::Rect& viewport_intersection,
const gfx::Rect& compositing_rect,
bool occluded_or_obscured) {
- content::BrowserThread::PostTask(
- content::BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {content::BrowserThread::UI},
base::BindOnce(&UpdateViewportIntersectionMessageFilter::
OnUpdateViewportIntersectionOnUI,
this, viewport_intersection, compositing_rect,
@@ -1141,7 +1142,12 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// Verify that applying a CSS scale transform does not impact the size of the
// content of the nested iframe.
- EXPECT_EQ(gfx::Size(50, 50), connector->screen_space_rect_in_dip().size());
+ // The screen_space_rect_in_dip may be off by 1 due to rounding. There is no
+ // good way to avoid this due to various device-scale-factor. (e.g. when
+ // dsf=3.375, ceil(round(50 * 3.375) / 3.375) = 51. Thus, we allow the screen
+ // size in dip to be off by 1 here.
+ EXPECT_NEAR(50, connector->screen_space_rect_in_dip().size().width(), 1);
+ EXPECT_NEAR(50, connector->screen_space_rect_in_dip().size().height(), 1);
EXPECT_EQ(gfx::Size(100, 100), rwhv_nested->GetViewBounds().size());
EXPECT_EQ(gfx::Size(100, 100), connector->local_frame_size_in_dip());
EXPECT_EQ(connector->local_frame_size_in_pixels(),
@@ -1837,19 +1843,10 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
scroll_observer->Wait();
}
-#if defined(OS_CHROMEOS) || defined(OS_MACOSX)
-// Flaky: https://crbug.com/836200.
-// Flaky timeouts on Mac: https://crbug.com/863971.
-#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,
- MAYBE_ScrollBubblingFromOOPIFWithBodyOverflowHidden) {
+ ScrollBubblingFromOOPIFWithBodyOverflowHidden) {
GURL url_domain_a(embedded_test_server()->GetURL(
"a.com", "/scrollable_page_with_iframe.html"));
EXPECT_TRUE(NavigateToURL(shell(), url_domain_a));
@@ -5036,26 +5033,28 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, NavigatePopupToIllegalURL) {
EXPECT_NE(popup->web_contents()->GetSiteInstance(),
shell()->web_contents()->GetSiteInstance());
- // From the opener, navigate the popup to a file:/// URL. This should be
- // disallowed and result in an about:blank navigation.
+ ConsoleObserverDelegate console_delegate(
+ web_contents(), "Not allowed to load local resource:*");
+ web_contents()->SetDelegate(&console_delegate);
+
+ // From the opener, navigate the popup to a file:/// URL. This should result
+ // in a console error and stay on the old page.
GURL file_url("file:///");
NavigateNamedFrame(shell(), file_url, "foo");
EXPECT_TRUE(WaitForLoadStop(popup->web_contents()));
- EXPECT_EQ(GURL(url::kAboutBlankURL),
- popup->web_contents()->GetLastCommittedURL());
-
- // Navigate popup back to a cross-site URL.
- EXPECT_TRUE(NavigateToURLFromRenderer(popup, popup_url));
- EXPECT_NE(popup->web_contents()->GetSiteInstance(),
- shell()->web_contents()->GetSiteInstance());
+ EXPECT_EQ(popup_url, popup->web_contents()->GetLastCommittedURL());
+ EXPECT_TRUE(base::MatchPattern(console_delegate.message(),
+ "Not allowed to load local resource: file:*"));
// Now try the same test with a chrome:// URL.
GURL chrome_url(std::string(kChromeUIScheme) + "://" +
std::string(kChromeUIGpuHost));
NavigateNamedFrame(shell(), chrome_url, "foo");
EXPECT_TRUE(WaitForLoadStop(popup->web_contents()));
- EXPECT_EQ(GURL(url::kAboutBlankURL),
- popup->web_contents()->GetLastCommittedURL());
+ EXPECT_EQ(popup_url, popup->web_contents()->GetLastCommittedURL());
+ EXPECT_TRUE(
+ base::MatchPattern(console_delegate.message(),
+ "Not allowed to load local resource: chrome:*"));
}
// Verify that named frames are discoverable from their opener's ancestors.
@@ -5938,13 +5937,13 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// Navigate to the site of the parent, but to a page that will not commit.
GURL same_site_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
- NavigationStallDelegate stall_delegate(same_site_url);
- ResourceDispatcherHost::Get()->SetDelegate(&stall_delegate);
+ TestNavigationManager stalled_navigation(web_contents(), same_site_url);
{
NavigationController::LoadURLParams params(same_site_url);
params.transition_type = ui::PAGE_TRANSITION_LINK;
params.frame_tree_node_id = node->frame_tree_node_id();
node->navigator()->GetController()->LoadURLWithParams(params);
+ EXPECT_TRUE(stalled_navigation.WaitForResponse());
}
// Grab the routing id of the pending RenderFrameHost and set up a process
@@ -5990,8 +5989,6 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
shell(), embedded_test_server()->GetURL("d.com", "/title3.html")));
watcher.Wait();
EXPECT_TRUE(watcher.did_exit_normally());
-
- ResourceDispatcherHost::Get()->SetDelegate(nullptr);
}
// This test ensures that the RenderFrame isn't leaked in the renderer process
@@ -6419,9 +6416,9 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, SandboxFlagsInheritance) {
// Check whether each frame is sandboxed on the renderer side, by seeing if
// each frame's origin is unique ("null").
- EXPECT_EQ("null", GetDocumentOrigin(b_child));
- EXPECT_EQ("null", GetDocumentOrigin(c_child));
- EXPECT_EQ("null", GetDocumentOrigin(d_child));
+ EXPECT_EQ("null", GetOriginFromRenderer(b_child));
+ EXPECT_EQ("null", GetOriginFromRenderer(c_child));
+ EXPECT_EQ("null", GetOriginFromRenderer(d_child));
}
// Check that sandbox flags are not inherited before they take effect. Create
@@ -6473,7 +6470,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// Check that the grandchild frame isn't sandboxed on the renderer side. If
// sandboxed, its origin would be unique ("null").
std::string expected_origin = url::Origin::Create(frame_url).Serialize();
- EXPECT_EQ(expected_origin, GetDocumentOrigin(grandchild));
+ EXPECT_EQ(expected_origin, GetOriginFromRenderer(grandchild));
}
// Verify that popups opened from sandboxed frames inherit sandbox flags from
@@ -6513,7 +6510,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// Verify that they've also taken effect on the renderer side. The sandboxed
// frame's origin should be unique.
- EXPECT_EQ("null", GetDocumentOrigin(root->child_at(0)));
+ EXPECT_EQ("null", GetOriginFromRenderer(root->child_at(0)));
// Open a popup named "foo" from the sandboxed child frame.
Shell* foo_shell =
@@ -6530,7 +6527,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
EXPECT_EQ(expected_flags, foo_root->effective_frame_policy().sandbox_flags);
// The popup's origin should be unique, since it's sandboxed.
- EXPECT_EQ("null", GetDocumentOrigin(foo_root));
+ EXPECT_EQ("null", GetOriginFromRenderer(foo_root));
// Navigate the popup cross-site. This should keep the unique origin and the
// inherited sandbox flags.
@@ -6546,7 +6543,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// Confirm that the popup is still sandboxed, both on browser and renderer
// sides.
EXPECT_EQ(expected_flags, foo_root->effective_frame_policy().sandbox_flags);
- EXPECT_EQ("null", GetDocumentOrigin(foo_root));
+ EXPECT_EQ("null", GetOriginFromRenderer(foo_root));
// Navigate the popup back to b.com. The popup should perform a
// remote-to-local navigation in the b.com process, and keep the unique
@@ -6562,7 +6559,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// Confirm that the popup is still sandboxed, both on browser and renderer
// sides.
EXPECT_EQ(expected_flags, foo_root->effective_frame_policy().sandbox_flags);
- EXPECT_EQ("null", GetDocumentOrigin(foo_root));
+ EXPECT_EQ("null", GetOriginFromRenderer(foo_root));
}
// Verify that popups opened from frames sandboxed with the
@@ -6620,7 +6617,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// The popup's origin should match |b_url|, since it's not sandboxed.
EXPECT_EQ(url::Origin::Create(b_url).Serialize(),
- EvalJs(foo_root, "document.origin;"));
+ EvalJs(foo_root, "self.origin;"));
}
// Tests that the WebContents is notified when passive mixed content is
@@ -7191,7 +7188,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// Test for https://crbug.com/568836. From an A-embed-B page, navigate the
// subframe from B to A. This cleans up the process for B, but the test delays
// the browser side from killing the B process right away. This allows the
-// B process to process two ViewMsg_Close messages sent to the subframe's
+// B process to process two WidgetMsg_Close messages sent to the subframe's
// RenderWidget and to the RenderView, in that order. In the bug, the latter
// crashed while detaching the subframe's LocalFrame (triggered as part of
// closing the RenderView), because this tried to access the subframe's
@@ -7720,15 +7717,15 @@ class PendingWidgetMessageFilter : public BrowserMessageFilter {
WindowOpenDisposition disposition,
const gfx::Rect& initial_rect,
bool user_gesture) {
- content::BrowserThread::PostTask(
- content::BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {content::BrowserThread::UI},
base::BindOnce(&PendingWidgetMessageFilter::OnReceivedRoutingIDOnUI,
this, pending_widget_routing_id));
}
void OnShowWidget(int routing_id, const gfx::Rect& initial_rect) {
- content::BrowserThread::PostTask(
- content::BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {content::BrowserThread::UI},
base::BindOnce(&PendingWidgetMessageFilter::OnReceivedRoutingIDOnUI,
this, routing_id));
}
@@ -8704,9 +8701,9 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessFeaturePolicyJavaScriptBrowserTest,
EXPECT_TRUE(root->child_at(0)
->current_frame_host()
->GetLastCommittedOrigin()
- .unique());
+ .opaque());
// And verify that the origin in the replication state is also opaque.
- EXPECT_TRUE(root->child_at(0)->current_origin().unique());
+ EXPECT_TRUE(root->child_at(0)->current_origin().opaque());
// Ask the sandboxed iframe to report the enabled state of the geolocation
// feature. If the declared policy was correctly flagged as referring to the
@@ -8731,9 +8728,9 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessFeaturePolicyJavaScriptBrowserTest,
EXPECT_TRUE(root->child_at(0)
->current_frame_host()
->GetLastCommittedOrigin()
- .unique());
+ .opaque());
// And verify that the origin in the replication state is also opaque.
- EXPECT_TRUE(root->child_at(0)->current_origin().unique());
+ EXPECT_TRUE(root->child_at(0)->current_origin().opaque());
EXPECT_TRUE(ExecuteScriptAndExtractBool(
root->child_at(0),
@@ -8765,9 +8762,9 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessFeaturePolicyJavaScriptBrowserTest,
EXPECT_TRUE(root->child_at(0)
->current_frame_host()
->GetLastCommittedOrigin()
- .unique());
+ .opaque());
// And verify that the origin in the replication state is also opaque.
- EXPECT_TRUE(root->child_at(0)->current_origin().unique());
+ EXPECT_TRUE(root->child_at(0)->current_origin().opaque());
// Verify that geolocation is enabled in the document.
bool success = false;
@@ -8787,9 +8784,9 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessFeaturePolicyJavaScriptBrowserTest,
EXPECT_FALSE(root->child_at(0)
->current_frame_host()
->GetLastCommittedOrigin()
- .unique());
+ .opaque());
// Verify that the origin in the replication state is also no longer opaque.
- EXPECT_FALSE(root->child_at(0)->current_origin().unique());
+ EXPECT_FALSE(root->child_at(0)->current_origin().opaque());
// Verify that the new document does not have geolocation enabled.
EXPECT_TRUE(ExecuteScriptAndExtractBool(
@@ -9014,7 +9011,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
const blink::ParsedFeaturePolicy initial_effective_policy =
root->child_at(2)->effective_frame_policy().container_policy;
EXPECT_EQ(1UL, initial_effective_policy[0].origins.size());
- EXPECT_FALSE(initial_effective_policy[0].origins[0].unique());
+ EXPECT_FALSE(initial_effective_policy[0].origins[0].opaque());
// Set the "sandbox" attribute; pending policy should update, and should now
// be flagged as matching the opaque origin of the frame (without containing
@@ -9027,7 +9024,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
const blink::ParsedFeaturePolicy updated_pending_policy =
root->child_at(2)->pending_frame_policy().container_policy;
EXPECT_EQ(1UL, updated_effective_policy[0].origins.size());
- EXPECT_FALSE(updated_effective_policy[0].origins[0].unique());
+ EXPECT_FALSE(updated_effective_policy[0].origins[0].opaque());
EXPECT_TRUE(updated_pending_policy[0].matches_opaque_src);
EXPECT_EQ(0UL, updated_pending_policy[0].origins.size());
@@ -9625,8 +9622,8 @@ class SetIsInertMessageFilter : public content::BrowserMessageFilter {
~SetIsInertMessageFilter() override {}
void OnSetIsInert(bool is_inert) {
- content::BrowserThread::PostTask(
- content::BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {content::BrowserThread::UI},
base::BindOnce(&SetIsInertMessageFilter::OnSetIsInertOnUI, this,
is_inert));
}
@@ -10488,6 +10485,27 @@ IN_PROC_BROWSER_TEST_F(TouchSelectionControllerClientAndroidSiteIsolationTest,
EXPECT_EQ(ui::TouchSelectionController::SELECTION_ACTIVE,
parent_view->touch_selection_controller()->active_status());
+ // Check that selection handles are close to the selection range.
+ ui::TouchSelectionController* touch_selection_controller =
+ parent_view->touch_selection_controller();
+
+ gfx::PointF selection_start = touch_selection_controller->GetStartPosition();
+ gfx::PointF selection_end = touch_selection_controller->GetEndPosition();
+ gfx::RectF handle_start = touch_selection_controller->GetStartHandleRect();
+ gfx::RectF handle_end = touch_selection_controller->GetEndHandleRect();
+
+ // Not all Android bots seem to actually show the handle, so check first.
+ if (!handle_start.IsEmpty()) {
+ EXPECT_FALSE(touch_selection_controller->GetEndHandleRect().IsEmpty());
+ // handle_start.y() defined the top of the handle's rect, and x() is left.
+ EXPECT_NEAR(selection_start.y(), handle_start.y(), 3.f);
+ EXPECT_GE(selection_start.x(), handle_start.x());
+ EXPECT_LE(selection_start.x(), handle_start.right());
+ EXPECT_NEAR(selection_end.y(), handle_end.y(), 3.f);
+ EXPECT_GE(selection_end.x(), handle_end.x());
+ EXPECT_LE(selection_end.x(), handle_end.right());
+ }
+
// Tap inside/outside the iframe and make sure the selection handles go away.
selection_controller_client->InitWaitForSelectionEvent(
ui::SELECTION_HANDLES_CLEARED);
@@ -12113,8 +12131,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// Test to verify that viewport intersection is propagated to nested OOPIFs
// even when a parent OOPIF has been throttled.
-// TODO(crbug.com/869758) The test is flaky on android
-#if defined(OS_ANDROID)
+// TODO(crbug.com/869758) The test is flaky on android and Linux.
+#if defined(OS_ANDROID) || defined(OS_LINUX)
#define MAYBE_NestedFrameViewportIntersectionUpdated \
DISABLED_NestedFrameViewportIntersectionUpdated
#else
@@ -12253,7 +12271,8 @@ class SitePerProcessBrowserTouchActionTest : public SitePerProcessBrowserTest {
RenderWidgetHostInputEventRouter* router,
RenderWidgetHostViewBase* rwhv_root,
RenderWidgetHostViewBase* rwhv_child,
- const gfx::Point& event_position) {
+ const gfx::Point& event_position,
+ base::Optional<cc::TouchAction>& whitelisted_touch_action) {
InputEventAckWaiter ack_observer(
rwhv_child->GetRenderWidgetHost(),
base::BindRepeating([](content::InputEventAckSource source,
@@ -12276,6 +12295,14 @@ class SitePerProcessBrowserTouchActionTest : public SitePerProcessBrowserTest {
static_cast<RenderWidgetHostImpl*>(rwhv_child->GetRenderWidgetHost())
->input_router()
->AllowedTouchAction();
+ // Whitelisted touch action is sent from a separate IPC channel, so it is
+ // not guaranteed to have value when the ACK for the touch start arrived
+ // because the ACK is from the main thread.
+ whitelisted_touch_action =
+ static_cast<InputRouterImpl*>(static_cast<RenderWidgetHostImpl*>(
+ rwhv_child->GetRenderWidgetHost())
+ ->input_router())
+ ->touch_action_filter_.white_listed_touch_action_;
// Send a touch move and touch end to complete the sequence, this also
// avoids triggering DCHECKs when sending followup events.
@@ -12354,22 +12381,31 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTouchActionTest,
WaitForTouchActionUpdated(root_thread_observer.get(),
child_thread_observer.get());
+ base::Optional<cc::TouchAction> whitelisted_touch_action;
+ cc::TouchAction expected_touch_action = cc::kTouchActionPan;
// 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,
+ EXPECT_EQ(expected_touch_action,
GetEffectiveTouchActionForChild(router, rwhv_root, rwhv_child,
- point_inside_child));
+ point_inside_child,
+ whitelisted_touch_action));
+ if (whitelisted_touch_action.has_value())
+ EXPECT_EQ(expected_touch_action, whitelisted_touch_action.value());
EXPECT_TRUE(
ExecuteScript(shell(), "document.body.style.touchAction = 'auto'"));
WaitForTouchActionUpdated(root_thread_observer.get(),
child_thread_observer.get());
- EXPECT_EQ(cc::TouchAction::kTouchActionAuto,
+ expected_touch_action = cc::kTouchActionAuto;
+ EXPECT_EQ(expected_touch_action,
GetEffectiveTouchActionForChild(router, rwhv_root, rwhv_child,
- point_inside_child));
+ point_inside_child,
+ whitelisted_touch_action));
+ if (whitelisted_touch_action.has_value())
+ EXPECT_EQ(expected_touch_action, whitelisted_touch_action.value());
}
IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTouchActionTest,
@@ -12424,9 +12460,14 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTouchActionTest,
// Child should inherit effective touch action none from root.
WaitForTouchActionUpdated(root_thread_observer.get(),
child_thread_observer.get());
- EXPECT_EQ(cc::TouchAction::kTouchActionPan,
+ base::Optional<cc::TouchAction> whitelisted_touch_action;
+ cc::TouchAction expected_touch_action = cc::kTouchActionPan;
+ EXPECT_EQ(expected_touch_action,
GetEffectiveTouchActionForChild(router, rwhv_root, rwhv_child,
- point_inside_child));
+ point_inside_child,
+ whitelisted_touch_action));
+ if (whitelisted_touch_action.has_value())
+ EXPECT_EQ(expected_touch_action, whitelisted_touch_action.value());
// Child should inherit effective touch action none from parent.
EXPECT_TRUE(
@@ -12436,9 +12477,12 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTouchActionTest,
"document.getElementById('parent-div').style.touchAction = 'none';"));
WaitForTouchActionUpdated(root_thread_observer.get(),
child_thread_observer.get());
- EXPECT_EQ(cc::TouchAction::kTouchActionPan,
+ EXPECT_EQ(expected_touch_action,
GetEffectiveTouchActionForChild(router, rwhv_root, rwhv_child,
- point_inside_child));
+ point_inside_child,
+ whitelisted_touch_action));
+ if (whitelisted_touch_action.has_value())
+ EXPECT_EQ(expected_touch_action, whitelisted_touch_action.value());
// Child should inherit effective touch action auto from root and parent.
EXPECT_TRUE(ExecuteScript(
@@ -12446,9 +12490,13 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTouchActionTest,
"document.getElementById('parent-div').style.touchAction = 'auto'"));
WaitForTouchActionUpdated(root_thread_observer.get(),
child_thread_observer.get());
- EXPECT_EQ(cc::TouchAction::kTouchActionAuto,
+ expected_touch_action = cc::kTouchActionAuto;
+ EXPECT_EQ(expected_touch_action,
GetEffectiveTouchActionForChild(router, rwhv_root, rwhv_child,
- point_inside_child));
+ point_inside_child,
+ whitelisted_touch_action));
+ if (whitelisted_touch_action.has_value())
+ EXPECT_EQ(expected_touch_action, whitelisted_touch_action.value());
}
IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTouchActionTest,
@@ -12497,9 +12545,14 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTouchActionTest,
// Child should inherit effective touch action none from root.
WaitForTouchActionUpdated(root_thread_observer.get(),
child_thread_observer.get());
- EXPECT_EQ(cc::TouchAction::kTouchActionPan,
+ base::Optional<cc::TouchAction> whitelisted_touch_action;
+ cc::TouchAction expected_touch_action = cc::kTouchActionPan;
+ EXPECT_EQ(expected_touch_action,
GetEffectiveTouchActionForChild(router, rwhv_root, rwhv_child,
- point_inside_child));
+ point_inside_child,
+ whitelisted_touch_action));
+ if (whitelisted_touch_action.has_value())
+ EXPECT_EQ(expected_touch_action, whitelisted_touch_action.value());
// After navigation, child should still inherit effective touch action none
// from parent.
@@ -12519,9 +12572,12 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTouchActionTest,
WaitForTouchActionUpdated(root_thread_observer.get(),
child_thread_observer.get());
- EXPECT_EQ(cc::TouchAction::kTouchActionPan,
+ EXPECT_EQ(expected_touch_action,
GetEffectiveTouchActionForChild(router, rwhv_root, rwhv_child,
- point_inside_child));
+ point_inside_child,
+ whitelisted_touch_action));
+ if (whitelisted_touch_action.has_value())
+ EXPECT_EQ(expected_touch_action, whitelisted_touch_action.value());
}
IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
@@ -12606,13 +12662,17 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// Verify that no child frame metrics got logged (yet - while WebContents are
// hidden).
histograms.ExpectTotalCount("Stability.ChildFrameCrash.Visibility", 0);
+ histograms.ExpectTotalCount(
+ "Stability.ChildFrameCrash.ShownAfterCrashingReason", 0);
- // Show the web contents.
- // and verify that the expected metrics got logged.
+ // 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);
+ histograms.ExpectUniqueSample(
+ "Stability.ChildFrameCrash.ShownAfterCrashingReason",
+ CrossProcessFrameConnector::ShownAfterCrashingReason::kTabWasShown, 10);
// Hide and show the web contents again and verify that no more metrics got
// logged.
@@ -12621,6 +12681,9 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
histograms.ExpectUniqueSample(
"Stability.ChildFrameCrash.Visibility",
CrossProcessFrameConnector::CrashVisibility::kShownAfterCrashing, 10);
+ histograms.ExpectUniqueSample(
+ "Stability.ChildFrameCrash.ShownAfterCrashingReason",
+ CrossProcessFrameConnector::ShownAfterCrashingReason::kTabWasShown, 10);
}
IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
@@ -12690,6 +12753,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// 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);
+ histograms.ExpectTotalCount(
+ "Stability.ChildFrameCrash.ShownAfterCrashingReason", 0);
// Scroll the subframe into view and wait until the scrolled frame draws
// itself.
@@ -12704,6 +12769,83 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
histograms.ExpectUniqueSample(
"Stability.ChildFrameCrash.Visibility",
CrossProcessFrameConnector::CrashVisibility::kShownAfterCrashing, 1);
+ histograms.ExpectUniqueSample(
+ "Stability.ChildFrameCrash.ShownAfterCrashingReason",
+ CrossProcessFrameConnector::ShownAfterCrashingReason::
+ kViewportIntersection,
+ 1);
+}
+
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ ChildFrameCrashMetrics_ScrolledIntoViewAfterTabIsShown) {
+ // Start on a page that has a single iframe, which is positioned out of
+ // view, and navigate that iframe cross-site.
+ GURL main_url(
+ embedded_test_server()->GetURL("a.com", "/iframe_out_of_view.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+ FrameTreeNode* root = web_contents()->GetFrameTree()->root();
+ NavigateFrameToURL(root->child_at(0),
+ embedded_test_server()->GetURL("b.com", "/title1.html"));
+
+ // 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 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 crash metrics got logged yet.
+ histograms.ExpectTotalCount("Stability.ChildFrameCrash.Visibility", 0);
+ histograms.ExpectTotalCount(
+ "Stability.ChildFrameCrash.ShownAfterCrashingReason", 0);
+
+ // Show the web contents. The crash metrics still shouldn't be logged, since
+ // the crashed frame is out of view.
+ web_contents()->UpdateWebContentsVisibility(Visibility::VISIBLE);
+ histograms.ExpectTotalCount("Stability.ChildFrameCrash.Visibility", 0);
+ histograms.ExpectTotalCount(
+ "Stability.ChildFrameCrash.ShownAfterCrashingReason", 0);
+
+ // Scroll the subframe into view and wait until the scrolled frame draws
+ // itself.
+ MainThreadFrameObserver main_widget_observer(
+ root->current_frame_host()->GetRenderWidgetHost());
+ std::string scrolling_script = R"(
+ var frame = document.body.querySelector("iframe");
+ 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);
+ histograms.ExpectUniqueSample(
+ "Stability.ChildFrameCrash.ShownAfterCrashingReason",
+ CrossProcessFrameConnector::ShownAfterCrashingReason::
+ kViewportIntersectionAfterTabWasShown,
+ 1);
+
+ // 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, 1);
+ histograms.ExpectUniqueSample(
+ "Stability.ChildFrameCrash.ShownAfterCrashingReason",
+ CrossProcessFrameConnector::ShownAfterCrashingReason::
+ kViewportIntersectionAfterTabWasShown,
+ 1);
}
// Check that when a frame changes a subframe's size twice and then sends a
@@ -13225,4 +13367,32 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, ProcessSwapOnInnerContents) {
EXPECT_NE(a_view, b_view);
}
+// Check that a web frame can't navigate a remote subframe to a file: URL. The
+// frame should stay at the old URL, and the navigation attempt should produce
+// a console error message. See https://crbug.com/894399.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ FileURLBlockedWithConsoleErrorInRemoteFrameNavigation) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b)"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+ FrameTreeNode* child = web_contents()->GetFrameTree()->root()->child_at(0);
+ GURL original_frame_url(child->current_frame_host()->GetLastCommittedURL());
+ EXPECT_EQ("b.com", original_frame_url.host());
+
+ ConsoleObserverDelegate console_delegate(
+ web_contents(), "Not allowed to load local resource: file:*");
+ web_contents()->SetDelegate(&console_delegate);
+
+ GURL file_url("file:///");
+ EXPECT_TRUE(
+ ExecJs(web_contents(),
+ JsReplace("document.querySelector('iframe').src = $1", file_url)));
+ console_delegate.Wait();
+
+ // The iframe should've stayed at the original URL.
+ EXPECT_EQ(original_frame_url,
+ child->current_frame_host()->GetLastCommittedURL());
+}
+
} // 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 dc73deb2e4c..8cf8f90eede 100644
--- a/chromium/content/browser/site_per_process_hit_test_browsertest.cc
+++ b/chromium/content/browser/site_per_process_hit_test_browsertest.cc
@@ -9,6 +9,7 @@
#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/json/json_reader.h"
+#include "base/task/post_task.h"
#include "base/test/bind_test_util.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/test_timeouts.h"
@@ -23,6 +24,8 @@
#include "content/browser/renderer_host/render_widget_host_view_child_frame.h"
#include "content/common/frame_messages.h"
#include "content/common/view_messages.h"
+#include "content/common/widget_messages.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
@@ -58,10 +61,6 @@
#include "content/test/mock_overscroll_refresh_handler_android.h"
#endif
-#if defined(OS_WIN)
-#include "base/debug/stack_trace.h"
-#endif
-
namespace content {
namespace {
@@ -664,20 +663,18 @@ class SetMouseCaptureInterceptor
};
#if defined(USE_AURA)
-// A class to allow intercepting and discarding of system-level mouse events
+// A class to allow intercepting and discarding of all system-level events
// that might otherwise cause unpredictable behaviour in tests.
-class MouseEventRewriter : public ui::EventRewriter {
+class SystemEventRewriter : public ui::EventRewriter {
public:
- MouseEventRewriter() = default;
- ~MouseEventRewriter() override {}
+ SystemEventRewriter() = default;
+ ~SystemEventRewriter() override {}
private:
ui::EventRewriteStatus RewriteEvent(
const ui::Event& event,
std::unique_ptr<ui::Event>* new_event) override {
- if (event.IsMouseEvent())
- return ui::EVENT_REWRITE_DISCARD;
- return ui::EVENT_REWRITE_CONTINUE;
+ return ui::EVENT_REWRITE_DISCARD;
}
ui::EventRewriteStatus NextDispatchEvent(
@@ -687,7 +684,7 @@ class MouseEventRewriter : public ui::EventRewriter {
return ui::EVENT_REWRITE_CONTINUE;
}
- DISALLOW_COPY_AND_ASSIGN(MouseEventRewriter);
+ DISALLOW_COPY_AND_ASSIGN(SystemEventRewriter);
};
#endif
@@ -728,7 +725,7 @@ class SitePerProcessHitTestBrowserTest
base::test::ScopedFeatureList feature_list_;
#if defined(USE_AURA)
- MouseEventRewriter event_rewriter;
+ SystemEventRewriter event_rewriter;
#endif
};
@@ -1093,20 +1090,11 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessInternalsHitTestBrowserTest,
}
#endif // defined(USE_AURA)
-#if defined(OS_CHROMEOS)
-// Times out flakily on Chrome OS. crbug.com/833380
-#define MAYBE_CancelWheelScrollBubblingOnWheelTargetDeletion \
- DISABLED_CancelWheelScrollBubblingOnWheelTargetDeletion
-#else
-#define MAYBE_CancelWheelScrollBubblingOnWheelTargetDeletion \
- CancelWheelScrollBubblingOnWheelTargetDeletion
-#endif
-
// Tests that wheel scroll bubbling gets cancelled when the wheel target view
// gets destroyed in the middle of a wheel scroll seqeunce. This happens in
// cases like overscroll navigation from inside an oopif.
IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
- MAYBE_CancelWheelScrollBubblingOnWheelTargetDeletion) {
+ CancelWheelScrollBubblingOnWheelTargetDeletion) {
ui::GestureConfiguration::GetInstance()->set_scroll_debounce_interval_in_ms(
0);
GURL main_url(embedded_test_server()->GetURL(
@@ -1180,6 +1168,194 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
scroll_end_observer.Wait();
}
+IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
+ CSSTransformedIframeTouchEventCoordinates) {
+ // This test only makes sense if viz hit testing is enabled.
+ if (std::get<0>(GetParam()) == 0)
+ return;
+
+ GURL url(embedded_test_server()->GetURL(
+ "/frame_tree/page_with_positioned_scaled_frame.html"));
+ ASSERT_TRUE(NavigateToURL(shell(), url));
+
+ RenderFrameSubmissionObserver render_frame_submission_observer(
+ shell()->web_contents());
+
+ FrameTreeNode* root_frame_tree_node = web_contents()->GetFrameTree()->root();
+ ASSERT_EQ(1U, root_frame_tree_node->child_count());
+ FrameTreeNode* child_frame_tree_node = root_frame_tree_node->child_at(0);
+ GURL child_url(embedded_test_server()->GetURL("baz.com", "/title1.html"));
+ EXPECT_EQ(child_url, child_frame_tree_node->current_url());
+
+ auto* root_rwhv = static_cast<RenderWidgetHostViewBase*>(
+ root_frame_tree_node->current_frame_host()
+ ->GetRenderWidgetHost()
+ ->GetView());
+ auto* child_rwhv = static_cast<RenderWidgetHostViewBase*>(
+ child_frame_tree_node->current_frame_host()
+ ->GetRenderWidgetHost()
+ ->GetView());
+
+ WaitForHitTestDataOrChildSurfaceReady(
+ child_frame_tree_node->current_frame_host());
+
+ const float scale_factor =
+ render_frame_submission_observer.LastRenderFrameMetadata()
+ .page_scale_factor;
+
+ // Some basic tests on the transforms between child and root. These assume
+ // a CSS scale of 0.5 on the child, though should be robust to placement of
+ // the iframe.
+ float kScaleTolerance = 0.0001f;
+ gfx::Transform transform_to_child;
+ ASSERT_TRUE(
+ root_rwhv->GetTransformToViewCoordSpace(child_rwhv, &transform_to_child));
+ EXPECT_TRUE(transform_to_child.IsScaleOrTranslation());
+ EXPECT_NEAR(2.f / scale_factor, transform_to_child.matrix().getFloat(0, 0),
+ kScaleTolerance);
+ EXPECT_NEAR(2.f / scale_factor, transform_to_child.matrix().getFloat(1, 1),
+ kScaleTolerance);
+
+ gfx::PointF child_origin =
+ child_rwhv->TransformPointToRootCoordSpaceF(gfx::PointF());
+
+ gfx::Transform transform_from_child;
+ ASSERT_TRUE(child_rwhv->GetTransformToViewCoordSpace(root_rwhv,
+ &transform_from_child));
+ EXPECT_TRUE(transform_from_child.IsScaleOrTranslation());
+ EXPECT_NEAR(0.5f * scale_factor, transform_from_child.matrix().getFloat(0, 0),
+ kScaleTolerance);
+ EXPECT_NEAR(0.5f * scale_factor, transform_from_child.matrix().getFloat(1, 1),
+ kScaleTolerance);
+ EXPECT_EQ(child_origin.x(), transform_from_child.matrix().getFloat(0, 3));
+ EXPECT_EQ(child_origin.y(), transform_from_child.matrix().getFloat(1, 3));
+
+ gfx::Transform transform_child_to_child =
+ transform_from_child * transform_to_child;
+ // If the scale factor is 1.f, then this multiplication of the transform with
+ // its inverse will be exact, and IsIdentity will indicate that. However, if
+ // the scale is an arbitrary float (as on Android), then we instead compare
+ // element by element using EXPECT_NEAR.
+ if (scale_factor == 1.f) {
+ EXPECT_TRUE(transform_child_to_child.IsIdentity());
+ } else {
+ const float kTolerance = 0.001f;
+ const int kDim = 4;
+ for (int row = 0; row < kDim; ++row) {
+ for (int col = 0; col < kDim; ++col) {
+ EXPECT_NEAR(row == col ? 1.f : 0.f,
+ transform_child_to_child.matrix().getFloat(row, col),
+ kTolerance);
+ }
+ }
+ }
+
+ gfx::Transform transform_root_to_root;
+ ASSERT_TRUE(root_rwhv->GetTransformToViewCoordSpace(root_rwhv,
+ &transform_root_to_root));
+ EXPECT_TRUE(transform_root_to_root.IsIdentity());
+
+ // Select two points inside child, one for the touch start and a different
+ // one for a touch move.
+ gfx::PointF touch_start_point_in_child(6, 6);
+ gfx::PointF touch_move_point_in_child(10, 10);
+
+ gfx::PointF touch_start_point =
+ child_rwhv->TransformPointToRootCoordSpaceF(touch_start_point_in_child);
+ gfx::PointF touch_move_point =
+ child_rwhv->TransformPointToRootCoordSpaceF(touch_move_point_in_child);
+
+ // Install InputEventObserver on child, and collect the three events.
+ TestInputEventObserver child_event_observer(
+ child_rwhv->GetRenderWidgetHost());
+ InputEventAckWaiter child_touch_start_waiter(
+ child_rwhv->GetRenderWidgetHost(), blink::WebInputEvent::kTouchStart);
+ InputEventAckWaiter child_touch_move_waiter(child_rwhv->GetRenderWidgetHost(),
+ blink::WebInputEvent::kTouchMove);
+ InputEventAckWaiter child_touch_end_waiter(child_rwhv->GetRenderWidgetHost(),
+ blink::WebInputEvent::kTouchEnd);
+
+ // Send events and verify each one was sent to the child with correctly
+ // transformed event coordinates.
+ auto* router = web_contents()->GetInputEventRouter();
+ const float kCoordinateTolerance = 0.1f;
+
+ // TouchStart.
+ blink::WebTouchEvent touch_start_event(
+ blink::WebInputEvent::kTouchStart, blink::WebInputEvent::kNoModifiers,
+ blink::WebInputEvent::GetStaticTimeStampForTests());
+ touch_start_event.touches_length = 1;
+ touch_start_event.touches[0].state = blink::WebTouchPoint::kStatePressed;
+ SetWebEventPositions(&touch_start_event.touches[0], touch_start_point,
+ root_rwhv);
+ touch_start_event.unique_touch_event_id = 1;
+ router->RouteTouchEvent(root_rwhv, &touch_start_event,
+ ui::LatencyInfo(ui::SourceEventType::TOUCH));
+ child_touch_start_waiter.Wait();
+
+ ASSERT_EQ(1U, child_event_observer.events_received().size());
+ ASSERT_EQ(blink::WebInputEvent::kTouchStart,
+ child_event_observer.event().GetType());
+ const blink::WebTouchEvent& touch_start_event_received =
+ static_cast<const blink::WebTouchEvent&>(child_event_observer.event());
+ EXPECT_NEAR(touch_start_point_in_child.x(),
+ touch_start_event_received.touches[0].PositionInWidget().x,
+ kCoordinateTolerance);
+ EXPECT_NEAR(touch_start_point_in_child.y(),
+ touch_start_event_received.touches[0].PositionInWidget().y,
+ kCoordinateTolerance);
+
+ // TouchMove.
+ blink::WebTouchEvent touch_move_event(
+ blink::WebInputEvent::kTouchMove, blink::WebInputEvent::kNoModifiers,
+ blink::WebInputEvent::GetStaticTimeStampForTests());
+ touch_move_event.touches_length = 1;
+ touch_move_event.touches[0].state = blink::WebTouchPoint::kStateMoved;
+ SetWebEventPositions(&touch_move_event.touches[0], touch_move_point,
+ root_rwhv);
+ touch_move_event.unique_touch_event_id = 2;
+ router->RouteTouchEvent(root_rwhv, &touch_move_event,
+ ui::LatencyInfo(ui::SourceEventType::TOUCH));
+ child_touch_move_waiter.Wait();
+
+ ASSERT_EQ(2U, child_event_observer.events_received().size());
+ ASSERT_EQ(blink::WebInputEvent::kTouchMove,
+ child_event_observer.event().GetType());
+ const blink::WebTouchEvent& touch_move_event_received =
+ static_cast<const blink::WebTouchEvent&>(child_event_observer.event());
+ EXPECT_NEAR(touch_move_point_in_child.x(),
+ touch_move_event_received.touches[0].PositionInWidget().x,
+ kCoordinateTolerance);
+ EXPECT_NEAR(touch_move_point_in_child.y(),
+ touch_move_event_received.touches[0].PositionInWidget().y,
+ kCoordinateTolerance);
+
+ // TouchEnd.
+ blink::WebTouchEvent touch_end_event(
+ blink::WebInputEvent::kTouchEnd, blink::WebInputEvent::kNoModifiers,
+ blink::WebInputEvent::GetStaticTimeStampForTests());
+ touch_end_event.touches_length = 1;
+ touch_end_event.touches[0].state = blink::WebTouchPoint::kStateReleased;
+ SetWebEventPositions(&touch_end_event.touches[0], touch_move_point,
+ root_rwhv);
+ touch_end_event.unique_touch_event_id = 3;
+ router->RouteTouchEvent(root_rwhv, &touch_end_event,
+ ui::LatencyInfo(ui::SourceEventType::TOUCH));
+ child_touch_end_waiter.Wait();
+
+ ASSERT_EQ(3U, child_event_observer.events_received().size());
+ ASSERT_EQ(blink::WebInputEvent::kTouchEnd,
+ child_event_observer.event().GetType());
+ const blink::WebTouchEvent& touch_end_event_received =
+ static_cast<const blink::WebTouchEvent&>(child_event_observer.event());
+ EXPECT_NEAR(touch_move_point_in_child.x(),
+ touch_end_event_received.touches[0].PositionInWidget().x,
+ kCoordinateTolerance);
+ EXPECT_NEAR(touch_move_point_in_child.y(),
+ touch_end_event_received.touches[0].PositionInWidget().y,
+ kCoordinateTolerance);
+}
+
// When a scroll event is bubbled, ensure that the bubbled event's coordinates
// are correctly updated to the ancestor's coordinate space. In particular,
// ensure that the transformation considers CSS scaling of the child where
@@ -1255,48 +1431,6 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
root_scroll_begin_observer.Wait();
}
-#if defined(OS_WIN)
-// Add temporary TouchMove event observer to detect spurious TouchMove events
-// leading to test flake.
-// https://crbug.com/833380.
-class EmulatedTouchTouchMoveInputObserver
- : public RenderWidgetHost::InputEventObserver {
- public:
- explicit EmulatedTouchTouchMoveInputObserver(RenderWidgetHost* host)
- : host_(host), first_touch_move_seen_(false) {
- host_->AddInputEventObserver(this);
- }
- ~EmulatedTouchTouchMoveInputObserver() override {
- host_->RemoveInputEventObserver(this);
- }
-
- void OnInputEvent(const blink::WebInputEvent& event) override {
- if (event.GetType() != blink::WebInputEvent::kTouchMove)
- return;
-
- const blink::WebTouchEvent& touch_event =
- static_cast<const blink::WebTouchEvent&>(event);
- blink::WebFloatPoint pos_in_widget =
- touch_event.touches[0].PositionInWidget();
- blink::WebFloatPoint pos_in_screen =
- touch_event.touches[0].PositionInScreen();
- LOG(ERROR) << "TouchMove seen: widget @ (" << pos_in_widget.x << ","
- << pos_in_widget.y << "), screen @ (" << pos_in_screen.x << ","
- << pos_in_screen.y << ")";
-
- if (first_touch_move_seen_)
- return;
-
- first_touch_move_seen_ = true;
- base::debug::StackTrace().Print();
- }
-
- private:
- RenderWidgetHost* host_;
- bool first_touch_move_seen_;
-};
-#endif
-
class SitePerProcessEmulatedTouchBrowserTest
: public SitePerProcessHitTestBrowserTest {
public:
@@ -1344,17 +1478,6 @@ class SitePerProcessEmulatedTouchBrowserTest
[](blink::WebInputEvent::Type expected_type,
const gfx::Point& expected_position, content::InputEventAckSource,
content::InputEventAckState, const blink::WebInputEvent& event) {
-#if defined(OS_WIN)
- // Add some logging to diagnose a potential source of flake:
- // the hypothesis is that something is causing the gesture
- // stream to cancel before kGestureShowPress is generated, so
- // we'll dump the event stream that we actually see in this case.
- // https://crbug.com/833380.
- if (expected_type == blink::WebInputEvent::kGestureShowPress) {
- LOG(ERROR) << "Waiting for: kGestureShowPress: ack seen for "
- << blink::WebInputEvent::GetName(event.GetType());
- }
-#endif
if (event.GetType() != expected_type)
return false;
@@ -1455,17 +1578,6 @@ class SitePerProcessEmulatedTouchBrowserTest
simulated_event_time += simulated_event_time_delta;
mouse_up_event.SetTimeStamp(simulated_event_time);
-#if defined(OS_WIN)
- // Add temporary TouchMove event observer to detect spurious TouchMove
- // events leading to test flake.
- // https://crbug.com/833380.
- std::unique_ptr<EmulatedTouchTouchMoveInputObserver> touch_move_observer;
- if (test_type == ShowPressHasTouchID) {
- touch_move_observer.reset(new EmulatedTouchTouchMoveInputObserver(
- child_rwhv->GetRenderWidgetHost()));
- }
-#endif
-
// 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());
@@ -1473,9 +1585,6 @@ class SitePerProcessEmulatedTouchBrowserTest
// Wait for child to receive GestureShowPress. If this test fails, it
// will either DCHECK or time out.
child_gesture_event_observer.Wait();
-#if defined(OS_WIN)
- touch_move_observer.reset();
-#endif
return;
}
router->RouteMouseEvent(root_rwhv, &mouse_drag_event, ui::LatencyInfo());
@@ -1515,35 +1624,12 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessEmulatedTouchBrowserTest,
RunTest(TouchActionBubbling);
}
-#if defined(OS_ANDROID) || defined(USE_AURA)
-namespace {
-// This function is used in TouchActionAckTimeout and
-// SubframeGestureEventRouting, which is defined either under Android or Aura.
-void OnSyntheticGestureCompleted(scoped_refptr<MessageLoopRunner> runner,
- SyntheticGesture::Result result) {
- EXPECT_EQ(SyntheticGesture::GESTURE_FINISHED, result);
- runner->Quit();
-}
-
-#if defined(OS_ANDROID)
-void GiveItSomeTime(int t) {
- base::RunLoop run_loop;
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, run_loop.QuitClosure(), base::TimeDelta::FromMilliseconds(t));
- run_loop.Run();
-}
-#endif // defined(OS_ANDROID)
-
-} // namespace
-#endif // defined(OS_ANDROID) || defined(USE_AURA)
-
// Regression test for https://crbug.com/851644. The test passes as long as it
// doesn't crash.
// Touch action ack timeout is enabled on Android only.
-// Flaky, see https://crbug.com/871062.
#if defined(OS_ANDROID)
IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
- DISABLED_TouchActionAckTimeout) {
+ TouchActionAckTimeout) {
GURL main_url(
embedded_test_server()->GetURL("/frame_tree/page_with_janky_frame.html"));
ASSERT_TRUE(NavigateToURL(shell(), main_url));
@@ -1577,41 +1663,29 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT;
params.anchor = gfx::PointF(point_in_child.x(), point_in_child.y());
params.distances.push_back(gfx::Vector2dF(0, -10));
- // Make this scroll slow so that the second scroll will be queued even before
- // this one ends.
- params.speed_in_pixels_s = 1000;
+ // The JS jank from the "page_with_touch_start_janking_main_thread.html"
+ // causes the touch ack timeout. Set the speed high so that the gesture can be
+ // completed quickly and so does this test.
+ params.speed_in_pixels_s = 100000;
std::unique_ptr<SyntheticSmoothScrollGesture> gesture(
new SyntheticSmoothScrollGesture(params));
- scoped_refptr<MessageLoopRunner> runner = new MessageLoopRunner();
+ InputEventAckWaiter ack_observer(
+ child_frame_host->GetRenderWidgetHost(),
+ base::BindRepeating([](content::InputEventAckSource source,
+ content::InputEventAckState state,
+ const blink::WebInputEvent& event) {
+ return event.GetType() == blink::WebGestureEvent::kGestureScrollEnd;
+ }));
+ ack_observer.Reset();
+
RenderWidgetHostImpl* render_widget_host =
root->current_frame_host()->GetRenderWidgetHost();
render_widget_host->QueueSyntheticGesture(
- std::move(gesture), base::BindOnce(OnSyntheticGestureCompleted, runner));
- // The first gesture takes 100ms, so wait for 120ms to ensure that it has
- // finished.
- runner->Run();
- GiveItSomeTime(120);
-
- SyntheticSmoothScrollGestureParams params2;
- params2.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT;
- params2.anchor = gfx::PointF(point_in_child.x(), point_in_child.y());
- params2.distances.push_back(gfx::Vector2dF(0, -10));
- params2.speed_in_pixels_s = 100000;
- std::unique_ptr<SyntheticSmoothScrollGesture> gesture2(
- new SyntheticSmoothScrollGesture(params2));
- render_widget_host->QueueSyntheticGesture(
- std::move(gesture2), base::BindOnce(OnSyntheticGestureCompleted, runner));
-
- runner->Run();
- runner = nullptr;
-
- // Give enough time to make sure all gesture are flushed and handled.
- base::RunLoop run_loop;
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, run_loop.QuitClosure(),
- base::TimeDelta::FromMilliseconds(2500));
- run_loop.Run();
+ std::move(gesture), base::BindOnce([](SyntheticGesture::Result result) {
+ EXPECT_EQ(SyntheticGesture::GESTURE_FINISHED, result);
+ }));
+ ack_observer.Wait();
}
#endif // defined(OS_ANDROID)
@@ -1834,15 +1908,7 @@ 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)
-
-#if defined(THREAD_SANITIZER) || defined(OS_CHROMEOS)
-// Flaky: https://crbug.com/833380
-#define MAYBE_ScrollEventToOOPIF DISABLED_ScrollEventToOOPIF
-#else
-#define MAYBE_ScrollEventToOOPIF ScrollEventToOOPIF
-#endif
-IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
- MAYBE_ScrollEventToOOPIF) {
+IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest, ScrollEventToOOPIF) {
GURL main_url(embedded_test_server()->GetURL(
"/frame_tree/page_with_positioned_frame.html"));
EXPECT_TRUE(NavigateToURL(shell(), main_url));
@@ -1890,17 +1956,8 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
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,
- MAYBE_InputEventRouterWheelCoalesceTest) {
+ InputEventRouterWheelCoalesceTest) {
GURL main_url(embedded_test_server()->GetURL(
"/frame_tree/page_with_positioned_frame.html"));
EXPECT_TRUE(NavigateToURL(shell(), main_url));
@@ -1989,16 +2046,7 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
// Test that mouse events are being routed to the correct RenderWidgetHostView
// based on coordinates.
-#if defined(THREAD_SANITIZER) || defined(OS_CHROMEOS)
-// The test times out often on TSAN bot.
-// https://crbug.com/591170.
-// Also times out flakily on Chrome OS. crbug.com/833380
-#define MAYBE_SurfaceHitTestTest DISABLED_SurfaceHitTestTest
-#else
-#define MAYBE_SurfaceHitTestTest SurfaceHitTestTest
-#endif
-IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
- MAYBE_SurfaceHitTestTest) {
+IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest, SurfaceHitTestTest) {
SurfaceHitTestTestHelper(shell(), embedded_test_server());
}
@@ -2011,9 +2059,6 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
// coordinate calculations. Android uses fixed device scale factor.
// Windows is disabled because of https://crbug.com/545547.
#define MAYBE_HighDPISurfaceHitTestTest DISABLED_HighDPISurfaceHitTestTest
-#elif defined(THREAD_SANITIZER)
-// Flaky: https://crbug.com/833380
-#define MAYBE_HighDPISurfaceHitTestTest DISABLED_HighDPISurfaceHitTestTest
#else
#define MAYBE_HighDPISurfaceHitTestTest HighDPISurfaceHitTestTest
#endif
@@ -2075,46 +2120,32 @@ 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_HitTestLayerSquashing DISABLED_HitTestLayerSquashing
-#else
-#define MAYBE_HitTestLayerSquashing HitTestLayerSquashing
-#endif
IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
- MAYBE_HitTestLayerSquashing) {
+ HitTestLayerSquashing) {
HitTestLayerSquashing(shell(), embedded_test_server());
}
IN_PROC_BROWSER_TEST_P(SitePerProcessHighDPIHitTestBrowserTest,
- MAYBE_HitTestLayerSquashing) {
+ HitTestLayerSquashing) {
HitTestLayerSquashing(shell(), embedded_test_server());
}
-#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) {
+IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest, HitTestWatermark) {
HitTestWatermark(shell(), embedded_test_server());
}
IN_PROC_BROWSER_TEST_P(SitePerProcessHighDPIHitTestBrowserTest,
- MAYBE_HitTestWatermark) {
+ HitTestWatermark) {
HitTestWatermark(shell(), embedded_test_server());
}
#if defined(USE_AURA)
-IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
- DISABLED_RootWindowTransform) {
+IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest, RootWindowTransform) {
HitTestRootWindowTransform(shell(), embedded_test_server());
}
IN_PROC_BROWSER_TEST_P(SitePerProcessHighDPIHitTestBrowserTest,
- DISABLED_RootWindowTransform) {
+ RootWindowTransform) {
HitTestRootWindowTransform(shell(), embedded_test_server());
}
#endif // defined(USE_AURA)
@@ -2199,43 +2230,34 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
EXPECT_EQ(result.target_location.value(), parent_location);
}
-#if defined(THREAD_SANITIZER) || defined(OS_LINUX)
-// 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,
- MAYBE_SurfaceHitTestPointerEventsNone) {
- // TODO(sunxd): Fix pointer-events none for surface layer viz hit testing. See
- // https://crbug.com/841358.
- if (features::IsVizHitTestingSurfaceLayerEnabled()) {
- LOG(INFO) << "Skipping test due to https://crbug.com/841358";
- return;
- }
+ SurfaceHitTestPointerEventsNoneChanged) {
+ // In /2 hit testing, OOPIFs with pointer-events: none are ignored and no hit
+ // test data is submitted. To make sure we wait enough time until child frame
+ // fully loaded, we add a 1x1 pixel OOPIF for the test to track the process of
+ // /2 hit testing.
GURL main_url(embedded_test_server()->GetURL(
"/frame_tree/page_with_positioned_frame_pointer-events_none.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 = web_contents()->GetFrameTree()->root();
- ASSERT_EQ(1U, root->child_count());
+ ASSERT_EQ(2U, 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());
+ FrameTreeNode* child_node1 = root->child_at(0);
+ FrameTreeNode* child_node2 = root->child_at(1);
+ GURL site_url(embedded_test_server()->GetURL("bar.com", "/title1.html"));
+ EXPECT_EQ(site_url, child_node2->current_url());
EXPECT_NE(shell()->web_contents()->GetSiteInstance(),
- child_node->current_frame_host()->GetSiteInstance());
+ child_node2->current_frame_host()->GetSiteInstance());
// Create listeners for mouse events.
RenderWidgetHostMouseEventMonitor main_frame_monitor(
root->current_frame_host()->GetRenderWidgetHost());
RenderWidgetHostMouseEventMonitor child_frame_monitor(
- child_node->current_frame_host()->GetRenderWidgetHost());
+ child_node1->current_frame_host()->GetRenderWidgetHost());
RenderWidgetHostInputEventRouter* router =
web_contents()->GetInputEventRouter();
@@ -2243,9 +2265,9 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
RenderWidgetHostViewBase* root_view = static_cast<RenderWidgetHostViewBase*>(
root->current_frame_host()->GetRenderWidgetHost()->GetView());
- WaitForHitTestDataOrChildSurfaceReady(child_node->current_frame_host());
+ WaitForHitTestDataOrChildSurfaceReady(child_node2->current_frame_host());
- // Target input event to child frame.
+ // Target input event to child1 frame.
blink::WebMouseEvent child_event(
blink::WebInputEvent::kMouseDown, blink::WebInputEvent::kNoModifiers,
blink::WebInputEvent::GetStaticTimeStampForTests());
@@ -2263,20 +2285,49 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
EXPECT_NEAR(75, main_frame_monitor.event().PositionInWidget().x, 2);
EXPECT_NEAR(75, main_frame_monitor.event().PositionInWidget().y, 2);
EXPECT_FALSE(child_frame_monitor.EventWasReceived());
-}
-#if defined(OS_CHROMEOS)
-// Flaky on Chrome OS. crbug.com/833380
-#define MAYBE_AsynchronousHitTestChildTimeout \
- DISABLED_AsynchronousHitTestChildTimeout
-#else
-#define MAYBE_AsynchronousHitTestChildTimeout AsynchronousHitTestChildTimeout
-#endif
+ // Surface hit test can only learn about pointer-events changes when
+ // submitting compositing frame, so we disable the second half of the test for
+ // surface hit test.
+ if (!features::IsVizHitTestingEnabled())
+ return;
+
+ // Remove pointer-events: none property from iframe, also remove child2 to
+ // properly notify the observer the update.
+ // Wait for the confirmation of the deletion so that surface hit test is aware
+ // of the change of pointer-events property. When viz hit testing is enabled,
+ // we do not need to wait.
+ EXPECT_TRUE(ExecuteScript(web_contents(),
+ "document.getElementsByTagName('iframe')[0].style."
+ "pointerEvents = 'auto';\n"));
+
+ ASSERT_EQ(2U, root->child_count());
+
+ {
+ MainThreadFrameObserver observer(
+ root->current_frame_host()->GetRenderWidgetHost());
+ observer.Wait();
+ }
+
+ WaitForHitTestDataOrChildSurfaceReady(child_node1->current_frame_host());
+ WaitForHitTestDataOrChildSurfaceReady(child_node2->current_frame_host());
+ main_frame_monitor.ResetEventReceived();
+ child_frame_monitor.ResetEventReceived();
+ InputEventAckWaiter child_waiter(
+ child_node1->current_frame_host()->GetRenderWidgetHost(),
+ blink::WebInputEvent::kMouseDown);
+ router->RouteMouseEvent(root_view, &child_event, ui::LatencyInfo());
+ child_waiter.Wait();
+
+ EXPECT_TRUE(child_frame_monitor.EventWasReceived());
+ EXPECT_NEAR(23, child_frame_monitor.event().PositionInWidget().x, 2);
+ EXPECT_NEAR(23, child_frame_monitor.event().PositionInWidget().y, 2);
+}
// Verify that an event is properly retargeted to the main frame when an
// asynchronous hit test to the child frame times out.
IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
- MAYBE_AsynchronousHitTestChildTimeout) {
+ AsynchronousHitTestChildTimeout) {
GURL main_url(embedded_test_server()->GetURL(
"/frame_tree/page_with_positioned_busy_frame.html"));
EXPECT_TRUE(NavigateToURL(shell(), main_url));
@@ -2684,12 +2735,10 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
EXPECT_TRUE(d_frame_monitor.EventWasReceived());
}
-// 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.
+// Verify that mouse capture works on a RenderWidgetHostView level.
+// This test checks that a MouseDown triggers mouse capture when it hits
+// a scrollbar thumb or a subframe, and does not trigger mouse
+// capture if it hits an element in the main frame.
#if defined(OS_CHROMEOS)
// TODO: Flaky on Chrome OS. crbug.com/868409
#define MAYBE_CrossProcessMouseCapture DISABLED_CrossProcessMouseCapture
@@ -2746,6 +2795,10 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
int child_frame_target_y = gfx::ToCeiledInt(
(bounds.y() - root_view->GetViewBounds().y() + 5) * scale_factor);
+ scoped_refptr<SetMouseCaptureInterceptor> child_interceptor =
+ new SetMouseCaptureInterceptor(static_cast<RenderWidgetHostImpl*>(
+ child_node->current_frame_host()->GetRenderWidgetHost()));
+
// Target MouseDown to child frame.
blink::WebMouseEvent mouse_event(
blink::WebInputEvent::kMouseDown, blink::WebInputEvent::kNoModifiers,
@@ -2763,16 +2816,46 @@ 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 be routed to the main frame
- // because the child frame is not capturing input.
+ // Wait for the mouse capture message.
+ child_interceptor->Wait();
+ EXPECT_TRUE(child_interceptor->Capturing());
+ // Yield the thread, in order to let the capture message be processed by its
+ // actual handler.
+ base::RunLoop().RunUntilIdle();
+
+ // Target MouseMove at main frame. The child frame is now capturing input,
+ // so it should receive the event instead.
mouse_event.SetType(blink::WebInputEvent::kMouseMove);
mouse_event.SetModifiers(blink::WebInputEvent::kLeftButtonDown);
SetWebEventPositions(&mouse_event, gfx::Point(1, 1), root_view);
- RouteMouseEventAndWaitUntilDispatch(router, root_view, root_view,
+ RouteMouseEventAndWaitUntilDispatch(router, root_view, rwhv_child,
&mouse_event);
// Dispatch twice because the router generates an extra MouseLeave for the
- // child frame.
+ // main frame.
+ main_frame_monitor.ResetEventReceived();
+ child_frame_monitor.ResetEventReceived();
+ RouteMouseEventAndWaitUntilDispatch(router, root_view, rwhv_child,
+ &mouse_event);
+ EXPECT_FALSE(main_frame_monitor.EventWasReceived());
+ EXPECT_TRUE(child_frame_monitor.EventWasReceived());
+
+ // MouseUp releases capture.
+ mouse_event.SetType(blink::WebInputEvent::kMouseUp);
+ mouse_event.SetModifiers(blink::WebInputEvent::kNoModifiers);
+ SetWebEventPositions(&mouse_event, gfx::Point(1, 1), root_view);
+ RouteMouseEventAndWaitUntilDispatch(router, root_view, rwhv_child,
+ &mouse_event);
+
+ child_interceptor->Wait();
+ EXPECT_FALSE(child_interceptor->Capturing());
+
+ // Targeting a MouseDown to the main frame should not initiate capture.
+ mouse_event.SetType(blink::WebInputEvent::kMouseDown);
+ mouse_event.SetModifiers(blink::WebInputEvent::kLeftButtonDown);
+ mouse_event.button = blink::WebPointerProperties::Button::kLeft;
+ SetWebEventPositions(&mouse_event, gfx::Point(1, 1), root_view);
+ mouse_event.click_count = 1;
main_frame_monitor.ResetEventReceived();
child_frame_monitor.ResetEventReceived();
RouteMouseEventAndWaitUntilDispatch(router, root_view, root_view,
@@ -2781,32 +2864,55 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
EXPECT_TRUE(main_frame_monitor.EventWasReceived());
EXPECT_FALSE(child_frame_monitor.EventWasReceived());
+ // Target MouseMove at child frame. Without capture, this should be
+ // dispatched to the child frame.
+ mouse_event.SetType(blink::WebInputEvent::kMouseMove);
+ SetWebEventPositions(&mouse_event,
+ gfx::Point(child_frame_target_x, child_frame_target_y),
+ root_view);
+ RouteMouseEventAndWaitUntilDispatch(router, root_view, rwhv_child,
+ &mouse_event);
+
+ main_frame_monitor.ResetEventReceived();
+ child_frame_monitor.ResetEventReceived();
+ // Again, twice because of the transition MouseMove sent to the main
+ // frame.
+ RouteMouseEventAndWaitUntilDispatch(router, root_view, rwhv_child,
+ &mouse_event);
+ EXPECT_FALSE(main_frame_monitor.EventWasReceived());
+ EXPECT_TRUE(child_frame_monitor.EventWasReceived());
+
+ // A MouseUp sent anywhere 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);
+ RouteMouseEventAndWaitUntilDispatch(router, root_view, rwhv_child,
+ &mouse_event);
+
+ child_interceptor->Wait();
+ base::RunLoop().RunUntilIdle();
+
// Targeting a scrollbar with a click doesn't work on Mac or Android.
#if !defined(OS_MACOSX) && !defined(OS_ANDROID)
- scoped_refptr<SetMouseCaptureInterceptor> interceptor =
+ scoped_refptr<SetMouseCaptureInterceptor> root_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);
+ mouse_event.SetModifiers(blink::WebInputEvent::kLeftButtonDown);
SetWebEventPositions(&mouse_event, gfx::Point(100, 25), root_view);
- router->RouteMouseEvent(root_view, &mouse_event, ui::LatencyInfo());
-
+ RouteMouseEventAndWaitUntilDispatch(router, root_view, root_view,
+ &mouse_event);
EXPECT_TRUE(main_frame_monitor.EventWasReceived());
// 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();
- }
+ root_interceptor->Wait();
+ EXPECT_TRUE(root_interceptor->Capturing());
+ base::RunLoop().RunUntilIdle();
main_frame_monitor.ResetEventReceived();
child_frame_monitor.ResetEventReceived();
@@ -2819,21 +2925,24 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
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();
+ RouteMouseEventAndWaitUntilDispatch(router, root_view, root_view,
+ &mouse_event);
+ 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);
+ mouse_event.SetModifiers(blink::WebInputEvent::kNoModifiers);
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());
+ root_interceptor->Wait();
+ EXPECT_FALSE(root_interceptor->Capturing());
#endif // !defined(OS_MACOSX) && !defined(OS_ANDROID)
}
@@ -2949,16 +3058,15 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
class CursorMessageFilter : public content::BrowserMessageFilter {
public:
CursorMessageFilter()
- : content::BrowserMessageFilter(ViewMsgStart),
+ : content::BrowserMessageFilter(WidgetMsgStart),
message_loop_runner_(new content::MessageLoopRunner),
last_set_cursor_routing_id_(MSG_ROUTING_NONE) {}
bool OnMessageReceived(const IPC::Message& message) override {
- if (message.type() == ViewHostMsg_SetCursor::ID) {
- content::BrowserThread::PostTask(
- content::BrowserThread::UI, FROM_HERE,
- base::BindOnce(&CursorMessageFilter::OnSetCursor, this,
- message.routing_id()));
+ if (message.type() == WidgetHostMsg_SetCursor::ID) {
+ base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI},
+ base::BindOnce(&CursorMessageFilter::OnSetCursor,
+ this, message.routing_id()));
}
return false;
}
@@ -3050,7 +3158,7 @@ void CursorUpdateReceivedFromCrossSiteIframeHelper(
EXPECT_EQ(60, root_monitor.event().PositionInWidget().y);
// CursorMessageFilter::Wait() implicitly tests whether we receive a
- // ViewHostMsg_SetCursor message from the renderer process, because it does
+ // WidgetHostMsg_SetCursor message from the renderer process, because it does
// does not return otherwise.
filter->Wait();
EXPECT_EQ(filter->last_set_cursor_routing_id(), rwh_child->GetRoutingID());
@@ -3078,16 +3186,22 @@ void CursorUpdateReceivedFromCrossSiteIframeHelper(
} // namespace
-// Flaky: https://crbug.com/833380
+#if defined(OS_WIN)
+// https://crbug.com/882458
+#define MAYBE_CursorUpdateReceivedFromCrossSiteIframe \
+ DISABLED_CursorUpdateReceivedFromCrossSiteIframe
+#else
+#define MAYBE_CursorUpdateReceivedFromCrossSiteIframe \
+ CursorUpdateReceivedFromCrossSiteIframe
+#endif
IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
- DISABLED_CursorUpdateReceivedFromCrossSiteIframe) {
+ MAYBE_CursorUpdateReceivedFromCrossSiteIframe) {
CursorUpdateReceivedFromCrossSiteIframeHelper(shell(),
embedded_test_server());
}
-// Flaky: https://crbug.com/833380
IN_PROC_BROWSER_TEST_P(SitePerProcessHighDPIHitTestBrowserTest,
- DISABLED_CursorUpdateReceivedFromCrossSiteIframe) {
+ CursorUpdateReceivedFromCrossSiteIframe) {
CursorUpdateReceivedFromCrossSiteIframeHelper(shell(),
embedded_test_server());
}
@@ -3481,9 +3595,8 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
render_widget_host->input_router()->AllowedTouchAction());
}
-// https://crbug.com/592320
IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
- DISABLED_SubframeGestureEventRouting) {
+ SubframeGestureEventRouting) {
GURL main_url(embedded_test_server()->GetURL(
"/frame_tree/page_with_positioned_nested_frames.html"));
EXPECT_TRUE(NavigateToURL(shell(), main_url));
@@ -3517,19 +3630,19 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
params.duration_ms = 100;
std::unique_ptr<SyntheticTapGesture> gesture(new SyntheticTapGesture(params));
- scoped_refptr<MessageLoopRunner> runner = new MessageLoopRunner();
-
RenderWidgetHostImpl* render_widget_host =
root->current_frame_host()->GetRenderWidgetHost();
- // TODO(wjmaclean): Convert the call to base::Bind() to a lambda someday.
+ InputEventAckWaiter ack_waiter(child_frame_host->GetRenderWidgetHost(),
+ blink::WebInputEvent::kGestureTap);
+
render_widget_host->QueueSyntheticGesture(
- std::move(gesture), base::BindOnce(OnSyntheticGestureCompleted, runner));
+ std::move(gesture), base::BindOnce([](SyntheticGesture::Result result) {
+ EXPECT_EQ(SyntheticGesture::GESTURE_FINISHED, result);
+ }));
- // We need to run the message loop while we wait for the synthetic gesture
- // to be processed; the callback registered above will get us out of the
- // message loop when that happens.
- runner->Run();
- runner = nullptr;
+ // We must wait for the kGestureTap ack to come back before querying the click
+ // handler in the subframe.
+ ack_waiter.Wait();
// Verify click handler in subframe was invoked
{
@@ -3772,16 +3885,8 @@ void SendTouchpadFlingSequenceWithExpectedTarget(
} // 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,
- MAYBE_InputEventRouterGestureTargetMapTest) {
+ InputEventRouterGestureTargetMapTest) {
GURL main_url(embedded_test_server()->GetURL(
"/frame_tree/page_with_positioned_nested_frames.html"));
EXPECT_TRUE(NavigateToURL(shell(), main_url));
@@ -4047,7 +4152,7 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
// wheel events to the child and causes the page scale factor to change for
// the main frame (given that the child did not consume the wheel).
IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
- MAYBE_TouchpadPinchOverOOPIF) {
+ TouchpadPinchOverOOPIF) {
GURL main_url(embedded_test_server()->GetURL(
"/frame_tree/page_with_positioned_frame.html"));
EXPECT_TRUE(NavigateToURL(shell(), main_url));
@@ -4209,13 +4314,9 @@ void CreateContextMenuTestHelper(
EXPECT_NEAR(point.y(), params.y, 2);
}
-#if defined(OS_ANDROID) || defined(OS_WIN) || defined(OS_LINUX)
+#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.
-// The test is flaky on Linux: https://crbug.com/833380.
-#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
@@ -4984,7 +5085,7 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest, HitTestNestedFrames) {
DCHECK_NE(child_node->current_frame_host()->GetInputTargetClient(),
nullptr);
child_node->current_frame_host()->GetInputTargetClient()->FrameSinkIdAt(
- point_in_child,
+ point_in_child, 0,
base::BindLambdaForTesting(
[&](const viz::FrameSinkId& id, const gfx::PointF& point) {
received_frame_sink_id = id;
@@ -5006,7 +5107,7 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest, HitTestNestedFrames) {
DCHECK_NE(child_node->current_frame_host()->GetInputTargetClient(),
nullptr);
child_node->current_frame_host()->GetInputTargetClient()->FrameSinkIdAt(
- gfx::ToCeiledPoint(point_in_nested_child),
+ gfx::ToCeiledPoint(point_in_nested_child), 0,
base::BindLambdaForTesting(
[&](const viz::FrameSinkId& id, const gfx::PointF& point) {
received_frame_sink_id = id;
@@ -5029,7 +5130,8 @@ class SitePerProcessHitTestDataGenerationBrowserTest
protected:
// Load the page |host_name| and retrieve the hit test data from HitTestQuery.
std::vector<viz::AggregatedHitTestRegion> SetupAndGetHitTestData(
- const std::string& host_name) {
+ const std::string& host_name,
+ unsigned skipped_child = -1) {
GURL main_url(embedded_test_server()->GetURL(host_name));
EXPECT_TRUE(NavigateToURL(shell(), main_url));
@@ -5042,8 +5144,12 @@ class SitePerProcessHitTestDataGenerationBrowserTest
root->current_frame_host()->GetRenderWidgetHost()->GetView());
for (unsigned i = 0; i < root->child_count(); i++) {
- WaitForHitTestDataOrChildSurfaceReady(
- root->child_at(i)->current_frame_host());
+ // Child with pointer-events: none property will never submit a hit test
+ // region in /2 hit testing.
+ if (i != skipped_child) {
+ WaitForHitTestDataOrChildSurfaceReady(
+ root->child_at(i)->current_frame_host());
+ }
}
HitTestRegionObserver observer(rwhv_root->GetRootFrameSinkId());
@@ -5351,6 +5457,74 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestDataGenerationBrowserTest,
EXPECT_EQ(kSlowHitTestFlags, hit_test_data[2].flags);
}
+IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestDataGenerationBrowserTest,
+ PointerEventsNoneOOPIF) {
+ if (!features::IsVizHitTestingSurfaceLayerEnabled())
+ return;
+ auto hit_test_data = SetupAndGetHitTestData(
+ "/frame_tree/page_with_positioned_frame_pointer-events_none.html", 0);
+ float device_scale_factor = current_device_scale_factor();
+ gfx::Transform expected_transform;
+ gfx::Rect expected_region = gfx::ScaleToEnclosingRect(
+ gfx::Rect(1, 1), device_scale_factor, device_scale_factor);
+ expected_transform.Translate(-2 * device_scale_factor,
+ -2 * device_scale_factor);
+
+ // We should not submit hit test region for iframes with pointer-events: none
+ // in /2 hit testing.
+ DCHECK(hit_test_data.size() == 3);
+ EXPECT_EQ(expected_region.ToString(), hit_test_data[2].rect.ToString());
+ EXPECT_TRUE(
+ expected_transform.ApproximatelyEqual(hit_test_data[2].transform()));
+ EXPECT_EQ(kFastHitTestFlags, hit_test_data[2].flags);
+
+ // Check that an update on the css property can trigger an update in submitted
+ // hit test data.
+ EXPECT_TRUE(ExecuteScript(web_contents(),
+ "document.getElementsByTagName('iframe')[0].style."
+ "pointerEvents = 'auto';\n"));
+
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+
+ ASSERT_EQ(2U, root->child_count());
+ RenderWidgetHostViewBase* rwhv_root = static_cast<RenderWidgetHostViewBase*>(
+ root->current_frame_host()->GetRenderWidgetHost()->GetView());
+
+ {
+ MainThreadFrameObserver observer(
+ root->current_frame_host()->GetRenderWidgetHost());
+ observer.Wait();
+ }
+
+ WaitForHitTestDataOrChildSurfaceReady(
+ root->child_at(0)->current_frame_host());
+ WaitForHitTestDataOrChildSurfaceReady(
+ root->child_at(1)->current_frame_host());
+
+ HitTestRegionObserver observer(rwhv_root->GetRootFrameSinkId());
+ observer.WaitForHitTestData();
+ hit_test_data = observer.GetHitTestData();
+
+ gfx::Rect expected_region2 = gfx::ScaleToEnclosingRect(
+ gfx::Rect(100, 100), device_scale_factor, device_scale_factor);
+ gfx::Transform expected_transform2;
+ expected_transform2.Translate(-52 * device_scale_factor,
+ -52 * device_scale_factor);
+
+ DCHECK(hit_test_data.size() == 4);
+ EXPECT_EQ(expected_region.ToString(), hit_test_data[2].rect.ToString());
+ EXPECT_TRUE(
+ expected_transform.ApproximatelyEqual(hit_test_data[2].transform()));
+ EXPECT_EQ(kFastHitTestFlags, hit_test_data[2].flags);
+
+ EXPECT_EQ(expected_region2.ToString(), hit_test_data[3].rect.ToString());
+ EXPECT_TRUE(
+ expected_transform2.ApproximatelyEqual(hit_test_data[3].transform()));
+ EXPECT_EQ(kFastHitTestFlags, hit_test_data[3].flags);
+}
+
static const int kHitTestOption[] = {0, 1, 2};
static const float kOneScale[] = {1.f};
diff --git a/chromium/content/browser/site_per_process_mac_browsertest.mm b/chromium/content/browser/site_per_process_mac_browsertest.mm
index ca814f4d223..e2e97649a9d 100644
--- a/chromium/content/browser/site_per_process_mac_browsertest.mm
+++ b/chromium/content/browser/site_per_process_mac_browsertest.mm
@@ -7,8 +7,10 @@
#include <Cocoa/Cocoa.h>
#include "base/mac/mac_util.h"
+#include "base/task/post_task.h"
#include "content/browser/renderer_host/render_widget_host_input_event_router.h"
#include "content/browser/renderer_host/render_widget_host_view_mac.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test_utils.h"
@@ -49,8 +51,8 @@ class TextInputClientMacHelper {
private:
void OnResult(const std::string& string, const gfx::Point& point) {
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::Bind(&TextInputClientMacHelper::OnResult,
base::Unretained(this), string, point));
return;
diff --git a/chromium/content/browser/speech/speech_recognition_browsertest.cc b/chromium/content/browser/speech/speech_recognition_browsertest.cc
index 3288ddad032..2ccefdd702a 100644
--- a/chromium/content/browser/speech/speech_recognition_browsertest.cc
+++ b/chromium/content/browser/speech/speech_recognition_browsertest.cc
@@ -17,12 +17,14 @@
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/sys_byteorder.h"
+#include "base/task/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "content/browser/speech/proto/google_streaming_api.pb.h"
#include "content/browser/speech/speech_recognition_engine.h"
#include "content/browser/speech/speech_recognition_manager_impl.h"
#include "content/browser/speech/speech_recognizer_impl.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/web_contents.h"
@@ -58,8 +60,8 @@ class MockAudioSystem : public media::AudioSystem {
// 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::PostTaskWithTraits(
+ FROM_HERE, {content::BrowserThread::IO},
base::BindOnce(std::move(on_params_cb),
media::AudioParameters::UnavailableDeviceParams()));
}
@@ -227,8 +229,8 @@ class SpeechRecognitionBrowserTest : public ContentBrowserTest {
// AudioCaptureSourcer::Stop() again.
SpeechRecognizerImpl::SetAudioEnvironmentForTesting(nullptr, nullptr);
- content::BrowserThread::PostTask(
- content::BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {content::BrowserThread::UI},
base::BindOnce(&SpeechRecognitionBrowserTest::SendResponse,
base::Unretained(this)));
}
diff --git a/chromium/content/browser/speech/speech_recognition_dispatcher_host.cc b/chromium/content/browser/speech/speech_recognition_dispatcher_host.cc
index 1658119876a..e898a430e1d 100644
--- a/chromium/content/browser/speech/speech_recognition_dispatcher_host.cc
+++ b/chromium/content/browser/speech/speech_recognition_dispatcher_host.cc
@@ -9,6 +9,7 @@
#include "base/bind.h"
#include "base/command_line.h"
#include "base/lazy_instance.h"
+#include "base/task/post_task.h"
#include "content/browser/browser_plugin/browser_plugin_guest.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/frame_host/frame_tree_node.h"
@@ -16,6 +17,7 @@
#include "content/browser/speech/speech_recognition_manager_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/speech_recognition_manager_delegate.h"
@@ -65,7 +67,7 @@ void SpeechRecognitionDispatcherHost::Start(
// Check that the origin specified by the renderer process is one
// that it is allowed to access.
- if (!params->origin.unique() &&
+ if (!params->origin.opaque() &&
!ChildProcessSecurityPolicyImpl::GetInstance()->CanRequestURL(
render_process_id_, params->origin.GetURL())) {
LOG(ERROR) << "SRDH::OnStartRequest, disallowed origin: "
@@ -73,8 +75,8 @@ void SpeechRecognitionDispatcherHost::Start(
return;
}
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&SpeechRecognitionDispatcherHost::StartRequestOnUI,
AsWeakPtr(), render_process_id_, render_frame_id_,
std::move(params)));
@@ -137,8 +139,8 @@ void SpeechRecognitionDispatcherHost::StartRequestOnUI(
StoragePartition* storage_partition = BrowserContext::GetStoragePartition(
browser_context, web_contents->GetSiteInstance());
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&SpeechRecognitionDispatcherHost::StartSessionOnIO,
speech_recognition_dispatcher_host, std::move(params),
diff --git a/chromium/content/browser/speech/speech_recognition_engine_unittest.cc b/chromium/content/browser/speech/speech_recognition_engine_unittest.cc
index e67d2517559..a0ef4596294 100644
--- a/chromium/content/browser/speech/speech_recognition_engine_unittest.cc
+++ b/chromium/content/browser/speech/speech_recognition_engine_unittest.cc
@@ -11,10 +11,11 @@
#include "base/big_endian.h"
#include "base/containers/queue.h"
-#include "base/message_loop/message_loop.h"
#include "base/numerics/safe_conversions.h"
+#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "base/sys_byteorder.h"
+#include "base/test/scoped_task_environment.h"
#include "content/browser/speech/audio_buffer.h"
#include "content/browser/speech/proto/google_streaming_api.pb.h"
#include "net/base/net_errors.h"
@@ -99,7 +100,7 @@ class SpeechRecognitionEngineTest
std::string ConsumeChunkedUploadData();
void CloseMockDownstream(DownstreamError error);
- base::MessageLoop message_loop_;
+ base::test::ScopedTaskEnvironment task_environment_;
network::TestURLLoaderFactory url_loader_factory_;
mojo::ScopedDataPipeProducerHandle downstream_data_pipe_;
@@ -666,10 +667,8 @@ bool SpeechRecognitionEngineTest::ResultsAreEqual(
if (a.size() != b.size())
return false;
- std::vector<blink::mojom::SpeechRecognitionResultPtr>::const_iterator it_a =
- a.begin();
- std::vector<blink::mojom::SpeechRecognitionResultPtr>::const_iterator it_b =
- b.begin();
+ auto it_a = a.begin();
+ auto it_b = b.begin();
for (; it_a != a.end() && it_b != b.end(); ++it_a, ++it_b) {
if ((*it_a)->is_provisional != (*it_b)->is_provisional ||
(*it_a)->hypotheses.size() != (*it_b)->hypotheses.size()) {
diff --git a/chromium/content/browser/speech/speech_recognition_manager_impl.cc b/chromium/content/browser/speech/speech_recognition_manager_impl.cc
index 08bcec68559..08c233315c2 100644
--- a/chromium/content/browser/speech/speech_recognition_manager_impl.cc
+++ b/chromium/content/browser/speech/speech_recognition_manager_impl.cc
@@ -14,6 +14,7 @@
#include "base/memory/ref_counted_delete_on_sequence.h"
#include "base/sequenced_task_runner.h"
#include "base/single_thread_task_runner.h"
+#include "base/task/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "content/browser/browser_main_loop.h"
@@ -22,6 +23,7 @@
#include "content/browser/speech/speech_recognition_engine.h"
#include "content/browser/speech/speech_recognizer_impl.h"
#include "content/browser/storage_partition_impl.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/render_frame_host.h"
@@ -190,7 +192,7 @@ void SpeechRecognitionManagerImpl::FrameDeletionObserver::ContentsObserver::
RenderFrameDeleted(RenderFrameHost* render_frame_host) {
auto iters = observed_frames_.equal_range(render_frame_host);
for (auto it = iters.first; it != iters.second; ++it) {
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO})
->PostTask(FROM_HERE,
base::BindOnce(parent_observer_->frame_deleted_callback_,
it->second));
@@ -297,7 +299,7 @@ int SpeechRecognitionManagerImpl::CreateSession(
// The deletion observer is owned by this class, so it's safe to use
// Unretained.
- BrowserThread::GetTaskRunnerForThread(BrowserThread::UI)
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::UI})
->PostTask(
FROM_HERE,
base::BindOnce(&SpeechRecognitionManagerImpl::FrameDeletionObserver::
@@ -407,7 +409,7 @@ void SpeechRecognitionManagerImpl::AbortSession(int session_id) {
// The deletion observer is owned by this class, so it's safe to use
// Unretained.
- BrowserThread::GetTaskRunnerForThread(BrowserThread::UI)
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::UI})
->PostTask(
FROM_HERE,
base::BindOnce(&SpeechRecognitionManagerImpl::FrameDeletionObserver::
diff --git a/chromium/content/browser/speech/speech_recognizer_impl.cc b/chromium/content/browser/speech/speech_recognizer_impl.cc
index 95b6834df4d..e915ff1d7a9 100644
--- a/chromium/content/browser/speech/speech_recognizer_impl.cc
+++ b/chromium/content/browser/speech/speech_recognizer_impl.cc
@@ -10,12 +10,14 @@
#include "base/bind.h"
#include "base/macros.h"
+#include "base/task/post_task.h"
#include "base/time/time.h"
#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_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/speech_recognition_event_listener.h"
#include "media/audio/audio_system.h"
@@ -229,20 +231,20 @@ void SpeechRecognizerImpl::StartRecognition(const std::string& device_id) {
DCHECK(!device_id.empty());
device_id_ = device_id;
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::BindOnce(&SpeechRecognizerImpl::DispatchEvent,
- this, FSMEventArgs(EVENT_PREPARE)));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(&SpeechRecognizerImpl::DispatchEvent,
+ this, FSMEventArgs(EVENT_PREPARE)));
}
void SpeechRecognizerImpl::AbortRecognition() {
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::BindOnce(&SpeechRecognizerImpl::DispatchEvent,
- this, FSMEventArgs(EVENT_ABORT)));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(&SpeechRecognizerImpl::DispatchEvent,
+ this, FSMEventArgs(EVENT_ABORT)));
}
void SpeechRecognizerImpl::StopAudioCapture() {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&SpeechRecognizerImpl::DispatchEvent, this,
FSMEventArgs(EVENT_STOP_CAPTURE)));
}
@@ -282,15 +284,15 @@ void SpeechRecognizerImpl::Capture(const AudioBus* data,
// 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);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&SpeechRecognizerImpl::DispatchEvent, this, event_args));
// See http://crbug.com/506051 regarding why one extra convert call can
// sometimes be required. It should be a rare case.
if (!audio_converter_->data_was_converted()) {
event_args.audio_data = audio_converter_->Convert(data);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&SpeechRecognizerImpl::DispatchEvent, this, event_args));
}
// Something is seriously wrong here and we are most likely missing some
@@ -300,8 +302,8 @@ void SpeechRecognizerImpl::Capture(const AudioBus* data,
void SpeechRecognizerImpl::OnCaptureError(const std::string& message) {
FSMEventArgs event_args(EVENT_AUDIO_ERROR);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&SpeechRecognizerImpl::DispatchEvent, this, event_args));
}
@@ -309,8 +311,8 @@ void SpeechRecognizerImpl::OnSpeechRecognitionEngineResults(
const std::vector<blink::mojom::SpeechRecognitionResultPtr>& results) {
FSMEventArgs event_args(EVENT_ENGINE_RESULT);
event_args.engine_results = mojo::Clone(results);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&SpeechRecognizerImpl::DispatchEvent, this, event_args));
}
@@ -323,8 +325,8 @@ void SpeechRecognizerImpl::OnSpeechRecognitionEngineError(
const blink::mojom::SpeechRecognitionError& error) {
FSMEventArgs event_args(EVENT_ENGINE_ERROR);
event_args.engine_error = error;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&SpeechRecognizerImpl::DispatchEvent, this, event_args));
}
@@ -782,8 +784,7 @@ SpeechRecognizerImpl::FSMState
SpeechRecognizerImpl::ProcessFinalResult(const FSMEventArgs& event_args) {
const std::vector<blink::mojom::SpeechRecognitionResultPtr>& results =
event_args.engine_results;
- std::vector<blink::mojom::SpeechRecognitionResultPtr>::const_iterator i =
- results.begin();
+ auto i = results.begin();
bool provisional_results_pending = false;
bool results_are_empty = true;
for (; i != results.end(); ++i) {
diff --git a/chromium/content/browser/speech/speech_recognizer_impl_android.cc b/chromium/content/browser/speech/speech_recognizer_impl_android.cc
index a2f7a606f30..a4b95f678a0 100644
--- a/chromium/content/browser/speech/speech_recognizer_impl_android.cc
+++ b/chromium/content/browser/speech/speech_recognizer_impl_android.cc
@@ -12,6 +12,8 @@
#include "base/android/scoped_java_ref.h"
#include "base/bind.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/task/post_task.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/speech_recognition_event_listener.h"
#include "content/public/browser/speech_recognition_manager.h"
@@ -40,14 +42,14 @@ 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::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&SpeechRecognitionEventListener::OnRecognitionStart,
base::Unretained(listener()), session_id()));
SpeechRecognitionSessionConfig config =
SpeechRecognitionManager::GetInstance()->GetSessionConfig(session_id());
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(
&content::SpeechRecognizerImplAndroid::StartRecognitionOnUIThread,
this, config.language, config.continuous, config.interim_results));
@@ -69,8 +71,8 @@ void SpeechRecognizerImplAndroid::StartRecognitionOnUIThread(
void SpeechRecognizerImplAndroid::AbortRecognition() {
if (BrowserThread::CurrentlyOn(BrowserThread::IO)) {
state_ = STATE_IDLE;
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&content::SpeechRecognizerImplAndroid::AbortRecognition,
this));
return;
@@ -83,8 +85,8 @@ void SpeechRecognizerImplAndroid::AbortRecognition() {
void SpeechRecognizerImplAndroid::StopAudioCapture() {
if (BrowserThread::CurrentlyOn(BrowserThread::IO)) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&content::SpeechRecognizerImplAndroid::StopAudioCapture,
this));
return;
@@ -109,8 +111,8 @@ void SpeechRecognizerImplAndroid::OnAudioStart(
JNIEnv* env,
const JavaParamRef<jobject>& obj) {
if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&SpeechRecognizerImplAndroid::OnAudioStart, this,
nullptr, nullptr));
return;
@@ -124,8 +126,8 @@ void SpeechRecognizerImplAndroid::OnSoundStart(
JNIEnv* env,
const JavaParamRef<jobject>& obj) {
if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&SpeechRecognizerImplAndroid::OnSoundStart, this,
nullptr, nullptr));
return;
@@ -137,8 +139,8 @@ void SpeechRecognizerImplAndroid::OnSoundStart(
void SpeechRecognizerImplAndroid::OnSoundEnd(JNIEnv* env,
const JavaParamRef<jobject>& obj) {
if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&SpeechRecognizerImplAndroid::OnSoundEnd, this, nullptr,
nullptr));
return;
@@ -150,8 +152,8 @@ 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::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&SpeechRecognizerImplAndroid::OnAudioEnd, this, nullptr,
nullptr));
return;
@@ -183,8 +185,8 @@ void SpeechRecognizerImplAndroid::OnRecognitionResults(
options[i], static_cast<double>(scores[i])));
}
result->is_provisional = provisional;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&SpeechRecognizerImplAndroid::OnRecognitionResultsOnIOThread, this,
std::move(results)));
@@ -201,8 +203,8 @@ void SpeechRecognizerImplAndroid::OnRecognitionError(
const JavaParamRef<jobject>& obj,
jint error) {
if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&SpeechRecognizerImplAndroid::OnRecognitionError, this,
nullptr, nullptr, error));
return;
@@ -219,8 +221,8 @@ void SpeechRecognizerImplAndroid::OnRecognitionEnd(
JNIEnv* env,
const JavaParamRef<jobject>& obj) {
if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&SpeechRecognizerImplAndroid::OnRecognitionEnd, this,
nullptr, nullptr));
return;
diff --git a/chromium/content/browser/ssl/ssl_client_auth_handler.cc b/chromium/content/browser/ssl/ssl_client_auth_handler.cc
index 34e9bb57534..29bafea3645 100644
--- a/chromium/content/browser/ssl/ssl_client_auth_handler.cc
+++ b/chromium/content/browser/ssl/ssl_client_auth_handler.cc
@@ -9,6 +9,8 @@
#include "base/bind.h"
#include "base/logging.h"
#include "base/macros.h"
+#include "base/task/post_task.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/client_certificate_delegate.h"
#include "content/public/browser/content_browser_client.h"
@@ -29,8 +31,8 @@ class ClientCertificateDelegateImpl : public ClientCertificateDelegate {
~ClientCertificateDelegateImpl() override {
if (!continue_called_) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&SSLClientAuthHandler::CancelCertificateSelection,
handler_));
}
@@ -41,8 +43,8 @@ class ClientCertificateDelegateImpl : public ClientCertificateDelegate {
scoped_refptr<net::SSLPrivateKey> key) override {
DCHECK(!continue_called_);
continue_called_ = true;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&SSLClientAuthHandler::ContinueWithCertificate, handler_,
std::move(cert), std::move(key)));
}
@@ -175,15 +177,15 @@ void SSLClientAuthHandler::DidGetClientCerts(
// before checking ClientCertStore; ClientCertStore itself should probably
// be handled by the embedder (https://crbug.com/394131), especially since
// this doesn't work on Android (https://crbug.com/345641).
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&SSLClientAuthHandler::ContinueWithCertificate,
weak_factory_.GetWeakPtr(), nullptr, nullptr));
return;
}
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&SelectCertificateOnUIThread, web_contents_getter_,
base::RetainedRef(cert_request_info_),
std::move(client_certs), weak_factory_.GetWeakPtr()));
diff --git a/chromium/content/browser/ssl/ssl_error_handler.cc b/chromium/content/browser/ssl/ssl_error_handler.cc
index 6145e9b7673..5fc0b3cae44 100644
--- a/chromium/content/browser/ssl/ssl_error_handler.cc
+++ b/chromium/content/browser/ssl/ssl_error_handler.cc
@@ -5,9 +5,11 @@
#include "content/browser/ssl/ssl_error_handler.h"
#include "base/bind.h"
+#include "base/task/post_task.h"
#include "content/browser/frame_host/navigation_controller_impl.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_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/resource_request_info.h"
#include "net/base/net_errors.h"
@@ -68,9 +70,9 @@ void SSLErrorHandler::CancelRequest() {
delegate_->CancelSSLRequest(net::ERR_ABORTED, &ssl_info());
return;
}
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::BindOnce(&CompleteCancelRequest, delegate_,
- ssl_info(), net::ERR_ABORTED));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(&CompleteCancelRequest, delegate_,
+ ssl_info(), net::ERR_ABORTED));
}
void SSLErrorHandler::DenyRequest() {
@@ -80,9 +82,9 @@ void SSLErrorHandler::DenyRequest() {
delegate_->CancelSSLRequest(cert_error_, &ssl_info());
return;
}
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::BindOnce(&CompleteCancelRequest, delegate_,
- ssl_info(), cert_error_));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(&CompleteCancelRequest, delegate_,
+ ssl_info(), cert_error_));
}
void SSLErrorHandler::ContinueRequest() {
@@ -92,8 +94,8 @@ void SSLErrorHandler::ContinueRequest() {
delegate_->ContinueSSLRequest();
return;
}
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::BindOnce(&CompleteContinueRequest, delegate_));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(&CompleteContinueRequest, delegate_));
}
} // namespace content
diff --git a/chromium/content/browser/ssl/ssl_manager.cc b/chromium/content/browser/ssl/ssl_manager.cc
index 235a0c00803..b669d0d339e 100644
--- a/chromium/content/browser/ssl/ssl_manager.cc
+++ b/chromium/content/browser/ssl/ssl_manager.cc
@@ -10,8 +10,10 @@
#include "base/bind.h"
#include "base/macros.h"
#include "base/metrics/histogram_macros.h"
+#include "base/metrics/ukm_source_id.h"
#include "base/strings/utf_string_conversions.h"
#include "base/supports_user_data.h"
+#include "base/task/post_task.h"
#include "content/browser/devtools/devtools_agent_host_impl.h"
#include "content/browser/frame_host/navigation_entry_impl.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
@@ -19,6 +21,7 @@
#include "content/browser/ssl/ssl_error_handler.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/certificate_request_result_type.h"
#include "content/public/browser/content_browser_client.h"
@@ -27,6 +30,8 @@
#include "content/public/browser/ssl_host_state_delegate.h"
#include "content/public/common/console_message_level.h"
#include "net/url_request/url_request.h"
+#include "services/metrics/public/cpp/ukm_builders.h"
+#include "services/metrics/public/cpp/ukm_recorder.h"
namespace content {
@@ -34,6 +39,17 @@ namespace {
const char kSSLManagerKeyName[] = "content_ssl_manager";
+// Used to log type of mixed content displayed/ran, matches histogram enum
+// (MixedContentType). DO NOT REORDER.
+enum class MixedContentType {
+ kDisplayMixedContent = 0,
+ kDisplayWithCertErrors = 1,
+ kMixedForm = 2,
+ kScriptingMixedContent = 3,
+ kScriptingWithCertErrors = 4,
+ kMaxValue = kScriptingWithCertErrors,
+};
+
void OnAllowCertificateWithRecordDecision(
bool record_decision,
const base::Callback<void(bool, content::CertificateRequestResultType)>&
@@ -121,6 +137,15 @@ void HandleSSLErrorOnUI(
manager->OnCertError(std::move(handler));
}
+void LogMixedContentMetrics(MixedContentType type,
+ ukm::SourceId source_id,
+ ukm::UkmRecorder* recorder) {
+ UMA_HISTOGRAM_ENUMERATION("SSL.MixedContentShown", type);
+ ukm::builders::SSL_MixedContentShown(source_id)
+ .SetType(static_cast<int64_t>(type))
+ .Record(recorder);
+}
+
} // namespace
// static
@@ -146,8 +171,8 @@ void SSLManager::OnSSLCertificateError(
// TODO(jam): remove the logic to call this from IO thread once the
// network service code path is the only one.
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&HandleSSLErrorOnUI, web_contents_getter, delegate,
BrowserThread::IO, resource_type, url, ssl_info, fatal));
}
@@ -223,10 +248,28 @@ void SSLManager::DidCommitProvisionalLoad(const LoadCommittedDetails& details) {
}
void SSLManager::DidDisplayMixedContent() {
+ NavigationEntryImpl* entry = controller_->GetLastCommittedEntry();
+ if (entry && entry->GetURL().SchemeIsCryptographic() &&
+ entry->GetSSL().certificate) {
+ WebContentsImpl* contents = static_cast<WebContentsImpl*>(
+ controller_->delegate()->GetWebContents());
+ ukm::SourceId source_id = contents->GetUkmSourceIdForLastCommittedSource();
+ LogMixedContentMetrics(MixedContentType::kDisplayMixedContent, source_id,
+ ukm::UkmRecorder::Get());
+ }
UpdateLastCommittedEntry(SSLStatus::DISPLAYED_INSECURE_CONTENT, 0);
}
void SSLManager::DidContainInsecureFormAction() {
+ NavigationEntryImpl* entry = controller_->GetLastCommittedEntry();
+ if (entry && entry->GetURL().SchemeIsCryptographic() &&
+ entry->GetSSL().certificate) {
+ WebContentsImpl* contents = static_cast<WebContentsImpl*>(
+ controller_->delegate()->GetWebContents());
+ ukm::SourceId source_id = contents->GetUkmSourceIdForLastCommittedSource();
+ LogMixedContentMetrics(MixedContentType::kMixedForm, source_id,
+ ukm::UkmRecorder::Get());
+ }
UpdateLastCommittedEntry(SSLStatus::DISPLAYED_FORM_WITH_INSECURE_ACTION, 0);
}
@@ -237,6 +280,11 @@ void SSLManager::DidDisplayContentWithCertErrors() {
// Only record information about subresources with cert errors if the
// main page is HTTPS with a certificate.
if (entry->GetURL().SchemeIsCryptographic() && entry->GetSSL().certificate) {
+ WebContentsImpl* contents = static_cast<WebContentsImpl*>(
+ controller_->delegate()->GetWebContents());
+ ukm::SourceId source_id = contents->GetUkmSourceIdForLastCommittedSource();
+ LogMixedContentMetrics(MixedContentType::kDisplayWithCertErrors, source_id,
+ ukm::UkmRecorder::Get());
UpdateLastCommittedEntry(SSLStatus::DISPLAYED_CONTENT_WITH_CERT_ERRORS, 0);
}
}
@@ -246,6 +294,14 @@ void SSLManager::DidRunMixedContent(const GURL& security_origin) {
if (!entry)
return;
+ if (entry->GetURL().SchemeIsCryptographic() && entry->GetSSL().certificate) {
+ WebContentsImpl* contents = static_cast<WebContentsImpl*>(
+ controller_->delegate()->GetWebContents());
+ ukm::SourceId source_id = contents->GetUkmSourceIdForLastCommittedSource();
+ LogMixedContentMetrics(MixedContentType::kScriptingMixedContent, source_id,
+ ukm::UkmRecorder::Get());
+ }
+
SiteInstance* site_instance = entry->site_instance();
if (!site_instance)
return;
@@ -264,6 +320,14 @@ void SSLManager::DidRunContentWithCertErrors(const GURL& security_origin) {
if (!entry)
return;
+ if (entry->GetURL().SchemeIsCryptographic() && entry->GetSSL().certificate) {
+ WebContentsImpl* contents = static_cast<WebContentsImpl*>(
+ controller_->delegate()->GetWebContents());
+ ukm::SourceId source_id = contents->GetUkmSourceIdForLastCommittedSource();
+ LogMixedContentMetrics(MixedContentType::kScriptingWithCertErrors,
+ source_id, ukm::UkmRecorder::Get());
+ }
+
SiteInstance* site_instance = entry->site_instance();
if (!site_instance)
return;
@@ -411,8 +475,7 @@ void SSLManager::NotifySSLInternalStateChanged(BrowserContext* context) {
SSLManagerSet* managers =
static_cast<SSLManagerSet*>(context->GetUserData(kSSLManagerKeyName));
- for (std::set<SSLManager*>::iterator i = managers->get().begin();
- i != managers->get().end(); ++i) {
+ for (auto i = managers->get().begin(); i != managers->get().end(); ++i) {
(*i)->UpdateEntry((*i)->controller()->GetLastCommittedEntry(), 0, 0);
}
}
diff --git a/chromium/content/browser/startup_helper.cc b/chromium/content/browser/startup_helper.cc
new file mode 100644
index 00000000000..204b3305a8c
--- /dev/null
+++ b/chromium/content/browser/startup_helper.cc
@@ -0,0 +1,110 @@
+// 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/startup_helper.h"
+
+#include "base/base_switches.h"
+#include "base/command_line.h"
+#include "base/sys_info.h"
+#include "base/task/task_scheduler/initialization_util.h"
+#include "base/task/task_scheduler/task_scheduler.h"
+#include "build/build_config.h"
+#include "content/common/task_scheduler.h"
+#include "content/public/browser/content_browser_client.h"
+#include "content/public/common/content_switches.h"
+
+namespace content {
+
+namespace {
+
+std::unique_ptr<base::TaskScheduler::InitParams>
+GetDefaultTaskSchedulerInitParams() {
+#if defined(OS_ANDROID)
+ // Mobile config, for iOS see ios/web/app/web_main_loop.cc.
+ return std::make_unique<base::TaskScheduler::InitParams>(
+ base::SchedulerWorkerPoolParams(
+ base::RecommendedMaxNumberOfThreadsInPool(2, 8, 0.1, 0),
+ base::TimeDelta::FromSeconds(30)),
+ base::SchedulerWorkerPoolParams(
+ base::RecommendedMaxNumberOfThreadsInPool(2, 8, 0.1, 0),
+ base::TimeDelta::FromSeconds(30)),
+ base::SchedulerWorkerPoolParams(
+ base::RecommendedMaxNumberOfThreadsInPool(3, 8, 0.3, 0),
+ base::TimeDelta::FromSeconds(30)),
+ base::SchedulerWorkerPoolParams(
+ base::RecommendedMaxNumberOfThreadsInPool(3, 8, 0.3, 0),
+ base::TimeDelta::FromSeconds(60)));
+#else
+ // Desktop config.
+ return std::make_unique<base::TaskScheduler::InitParams>(
+ base::SchedulerWorkerPoolParams(
+ base::RecommendedMaxNumberOfThreadsInPool(3, 8, 0.1, 0),
+ base::TimeDelta::FromSeconds(30)),
+ base::SchedulerWorkerPoolParams(
+ base::RecommendedMaxNumberOfThreadsInPool(3, 8, 0.1, 0),
+ base::TimeDelta::FromSeconds(40)),
+ base::SchedulerWorkerPoolParams(
+ base::RecommendedMaxNumberOfThreadsInPool(8, 32, 0.3, 0),
+ base::TimeDelta::FromSeconds(30)),
+ base::SchedulerWorkerPoolParams(
+ base::RecommendedMaxNumberOfThreadsInPool(8, 32, 0.3, 0),
+ base::TimeDelta::FromSeconds(60))
+#if defined(OS_WIN)
+ ,
+ base::TaskScheduler::InitParams::SharedWorkerPoolEnvironment::COM_MTA
+#endif // defined(OS_WIN)
+ );
+#endif
+}
+
+} // namespace
+
+std::unique_ptr<base::FieldTrialList> SetUpFieldTrialsAndFeatureList() {
+ auto field_trial_list = std::make_unique<base::FieldTrialList>(nullptr);
+ const base::CommandLine* command_line =
+ base::CommandLine::ForCurrentProcess();
+
+ // Ensure any field trials specified on the command line are initialized.
+ if (command_line->HasSwitch(::switches::kForceFieldTrials)) {
+ // Create field trials without activating them, so that this behaves in a
+ // consistent manner with field trials created from the server.
+ bool result = base::FieldTrialList::CreateTrialsFromString(
+ command_line->GetSwitchValueASCII(::switches::kForceFieldTrials),
+ std::set<std::string>());
+ CHECK(result) << "Invalid --" << ::switches::kForceFieldTrials
+ << " list specified.";
+ }
+
+ base::FeatureList::InitializeInstance(
+ command_line->GetSwitchValueASCII(switches::kEnableFeatures),
+ command_line->GetSwitchValueASCII(switches::kDisableFeatures));
+ return field_trial_list;
+}
+
+void StartBrowserTaskScheduler() {
+ auto task_scheduler_init_params =
+ GetContentClient()->browser()->GetTaskSchedulerInitParams();
+ if (!task_scheduler_init_params)
+ task_scheduler_init_params = GetDefaultTaskSchedulerInitParams();
+ DCHECK(task_scheduler_init_params);
+
+ // If a renderer lives in the browser process, adjust the number of
+ // threads in the foreground pool.
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kSingleProcess)) {
+ const base::SchedulerWorkerPoolParams&
+ current_foreground_worker_pool_params(
+ task_scheduler_init_params->foreground_worker_pool_params);
+ task_scheduler_init_params->foreground_worker_pool_params =
+ base::SchedulerWorkerPoolParams(
+ std::max(GetMinThreadsInRendererTaskSchedulerForegroundPool(),
+ current_foreground_worker_pool_params.max_tasks()),
+ current_foreground_worker_pool_params.suggested_reclaim_time(),
+ current_foreground_worker_pool_params.backward_compatibility());
+ }
+
+ base::TaskScheduler::GetInstance()->Start(*task_scheduler_init_params.get());
+}
+
+} // namespace content
diff --git a/chromium/content/browser/startup_helper.h b/chromium/content/browser/startup_helper.h
new file mode 100644
index 00000000000..9259f9cabdc
--- /dev/null
+++ b/chromium/content/browser/startup_helper.h
@@ -0,0 +1,23 @@
+// 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_STARTUP_HELPER_H_
+#define CONTENT_BROWSER_STARTUP_HELPER_H_
+
+#include "base/metrics/field_trial.h"
+#include "content/common/content_export.h"
+
+namespace content {
+
+// Setups fields trials and the FeatureList, and returns the unique pointer of
+// the field trials.
+std::unique_ptr<base::FieldTrialList> CONTENT_EXPORT
+SetUpFieldTrialsAndFeatureList();
+
+// Starts the task scheduler.
+void CONTENT_EXPORT StartBrowserTaskScheduler();
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_STARTUP_HELPER_H_
diff --git a/chromium/content/browser/startup_task_runner.cc b/chromium/content/browser/startup_task_runner.cc
index 319bc8f10b4..51c98506b14 100644
--- a/chromium/content/browser/startup_task_runner.cc
+++ b/chromium/content/browser/startup_task_runner.cc
@@ -37,9 +37,7 @@ void StartupTaskRunner::StartRunningTasksAsync() {
void StartupTaskRunner::RunAllTasksNow() {
int result = 0;
- for (std::list<StartupTask>::iterator it = task_list_.begin();
- it != task_list_.end();
- it++) {
+ for (auto it = task_list_.begin(); it != task_list_.end(); it++) {
result = it->Run();
if (result > 0) break;
}
diff --git a/chromium/content/browser/storage_partition_impl.cc b/chromium/content/browser/storage_partition_impl.cc
index ee48d130400..c5307b0a921 100644
--- a/chromium/content/browser/storage_partition_impl.cc
+++ b/chromium/content/browser/storage_partition_impl.cc
@@ -13,12 +13,15 @@
#include "base/barrier_closure.h"
#include "base/bind.h"
+#include "base/callback_helpers.h"
#include "base/command_line.h"
#include "base/location.h"
+#include "base/optional.h"
#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 "base/task/post_task.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"
@@ -35,6 +38,7 @@
#include "content/common/dom_storage/dom_storage_types.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/dom_storage_context.h"
@@ -47,6 +51,7 @@
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "net/base/completion_callback.h"
+#include "net/base/features.h"
#include "net/base/net_errors.h"
#include "net/cookies/canonical_cookie.h"
#include "net/url_request/url_request_context.h"
@@ -85,8 +90,8 @@ base::LazyInstance<StoragePartitionImpl::CreateNetworkFactoryCallback>::Leaky
void OnClearedCookies(base::OnceClosure callback, uint32_t num_deleted) {
// The final callback needs to happen from UI thread.
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&OnClearedCookies, std::move(callback), num_deleted));
return;
}
@@ -95,18 +100,18 @@ void OnClearedCookies(base::OnceClosure callback, uint32_t num_deleted) {
}
void CheckQuotaManagedDataDeletionStatus(size_t* deletion_task_count,
- const base::Closure& callback) {
+ base::OnceClosure callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (*deletion_task_count == 0) {
delete deletion_task_count;
- callback.Run();
+ std::move(callback).Run();
}
}
-void OnQuotaManagedOriginDeleted(const GURL& origin,
+void OnQuotaManagedOriginDeleted(const url::Origin& origin,
blink::mojom::StorageType type,
size_t* deletion_task_count,
- const base::Closure& callback,
+ base::OnceClosure callback,
blink::mojom::QuotaStatusCode status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK_GT(*deletion_task_count, 0u);
@@ -117,25 +122,27 @@ void OnQuotaManagedOriginDeleted(const GURL& origin,
}
(*deletion_task_count)--;
- CheckQuotaManagedDataDeletionStatus(deletion_task_count, callback);
+ CheckQuotaManagedDataDeletionStatus(deletion_task_count, std::move(callback));
}
-void ClearedShaderCache(const base::Closure& callback) {
+void ClearedShaderCache(base::OnceClosure callback) {
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(&ClearedShaderCache, callback));
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(&ClearedShaderCache, std::move(callback)));
return;
}
- callback.Run();
+ std::move(callback).Run();
}
void ClearShaderCacheOnIOThread(const base::FilePath& path,
const base::Time begin,
const base::Time end,
- const base::Closure& callback) {
+ base::OnceClosure callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
GetShaderCacheFactorySingleton()->ClearByPath(
- path, begin, end, base::Bind(&ClearedShaderCache, callback));
+ path, begin, end,
+ base::BindOnce(&ClearedShaderCache, std::move(callback)));
}
void OnLocalStorageUsageInfo(
@@ -144,11 +151,12 @@ void OnLocalStorageUsageInfo(
const StoragePartition::OriginMatcherFunction& origin_matcher,
const base::Time delete_begin,
const base::Time delete_end,
- const base::Closure& callback,
+ base::OnceClosure callback,
const std::vector<LocalStorageUsageInfo>& infos) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- base::RepeatingClosure barrier = base::BarrierClosure(infos.size(), callback);
+ base::RepeatingClosure barrier =
+ base::BarrierClosure(infos.size(), std::move(callback));
for (size_t i = 0; i < infos.size(); ++i) {
if (!origin_matcher.is_null() &&
!origin_matcher.Run(infos[i].origin, special_storage_policy.get())) {
@@ -169,7 +177,7 @@ void OnSessionStorageUsageInfo(
const scoped_refptr<DOMStorageContextWrapper>& dom_storage_context,
const scoped_refptr<storage::SpecialStoragePolicy>& special_storage_policy,
const StoragePartition::OriginMatcherFunction& origin_matcher,
- const base::Closure& callback,
+ base::OnceClosure callback,
const std::vector<SessionStorageUsageInfo>& infos) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -181,7 +189,7 @@ void OnSessionStorageUsageInfo(
dom_storage_context->DeleteSessionStorage(infos[i]);
}
- callback.Run();
+ std::move(callback).Run();
}
void ClearLocalStorageOnUIThread(
@@ -191,7 +199,7 @@ void ClearLocalStorageOnUIThread(
const GURL& storage_origin,
const base::Time begin,
const base::Time end,
- const base::Closure& callback) {
+ base::OnceClosure callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (!storage_origin.is_empty()) {
@@ -199,29 +207,29 @@ void ClearLocalStorageOnUIThread(
origin_matcher.Run(storage_origin,
special_storage_policy.get());
if (can_delete) {
- dom_storage_context->DeleteLocalStorage(storage_origin, callback);
+ dom_storage_context->DeleteLocalStorage(storage_origin,
+ std::move(callback));
} else {
- callback.Run();
+ std::move(callback).Run();
}
return;
}
- dom_storage_context->GetLocalStorageUsage(
- base::Bind(&OnLocalStorageUsageInfo,
- dom_storage_context, special_storage_policy, origin_matcher,
- begin, end, callback));
+ dom_storage_context->GetLocalStorageUsage(base::BindOnce(
+ &OnLocalStorageUsageInfo, dom_storage_context, special_storage_policy,
+ origin_matcher, begin, end, std::move(callback)));
}
void ClearSessionStorageOnUIThread(
const scoped_refptr<DOMStorageContextWrapper>& dom_storage_context,
const scoped_refptr<storage::SpecialStoragePolicy>& special_storage_policy,
const StoragePartition::OriginMatcherFunction& origin_matcher,
- const base::Closure& callback) {
+ base::OnceClosure callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- dom_storage_context->GetSessionStorageUsage(
- base::BindOnce(&OnSessionStorageUsageInfo, dom_storage_context,
- special_storage_policy, origin_matcher, callback));
+ dom_storage_context->GetSessionStorageUsage(base::BindOnce(
+ &OnSessionStorageUsageInfo, dom_storage_context, special_storage_policy,
+ origin_matcher, std::move(callback)));
}
} // namespace
@@ -349,15 +357,19 @@ void StoragePartitionImpl::
// Most of the operations in this class are done on IO thread.
class StoragePartitionImpl::QuotaManagedDataDeletionHelper {
public:
- QuotaManagedDataDeletionHelper(uint32_t remove_mask,
- uint32_t quota_storage_remove_mask,
- const GURL& storage_origin,
- const base::Closure& callback)
+ QuotaManagedDataDeletionHelper(
+ uint32_t remove_mask,
+ uint32_t quota_storage_remove_mask,
+ const base::Optional<url::Origin>& storage_origin,
+ base::OnceClosure callback)
: remove_mask_(remove_mask),
quota_storage_remove_mask_(quota_storage_remove_mask),
storage_origin_(storage_origin),
- callback_(callback),
- task_count_(0) {}
+ callback_(std::move(callback)),
+ task_count_(0) {
+ DCHECK(!storage_origin_.has_value() ||
+ !storage_origin_->GetURL().is_empty());
+ }
void IncrementTaskCountOnIO();
void DecrementTaskCountOnIO();
@@ -374,16 +386,16 @@ class StoragePartitionImpl::QuotaManagedDataDeletionHelper {
const scoped_refptr<storage::SpecialStoragePolicy>&
special_storage_policy,
const StoragePartition::OriginMatcherFunction& origin_matcher,
- const base::Closure& callback,
- const std::set<GURL>& origins,
+ base::OnceClosure callback,
+ const std::set<url::Origin>& origins,
blink::mojom::StorageType quota_storage_type);
private:
// All of these data are accessed on IO thread.
uint32_t remove_mask_;
uint32_t quota_storage_remove_mask_;
- GURL storage_origin_;
- const base::Closure callback_;
+ base::Optional<url::Origin> storage_origin_;
+ base::OnceClosure callback_;
int task_count_;
DISALLOW_COPY_AND_ASSIGN(QuotaManagedDataDeletionHelper);
@@ -459,7 +471,7 @@ class StoragePartitionImpl::DataDeletionHelper {
const scoped_refptr<storage::SpecialStoragePolicy>&
special_storage_policy,
const StoragePartition::OriginMatcherFunction& origin_matcher,
- const base::Closure& callback);
+ base::OnceClosure callback);
private:
uint32_t remove_mask_;
@@ -479,12 +491,16 @@ void StoragePartitionImpl::DataDeletionHelper::ClearQuotaManagedDataOnIOThread(
const GURL& storage_origin,
const scoped_refptr<storage::SpecialStoragePolicy>& special_storage_policy,
const StoragePartition::OriginMatcherFunction& origin_matcher,
- const base::Closure& callback) {
+ base::OnceClosure callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
StoragePartitionImpl::QuotaManagedDataDeletionHelper* helper =
new StoragePartitionImpl::QuotaManagedDataDeletionHelper(
- remove_mask_, quota_storage_remove_mask_, storage_origin, callback);
+ remove_mask_, quota_storage_remove_mask_,
+ storage_origin.is_empty()
+ ? base::nullopt
+ : base::make_optional(url::Origin::Create(storage_origin)),
+ std::move(callback));
helper->ClearDataOnIOThread(quota_manager, begin, special_storage_policy,
origin_matcher);
}
@@ -541,8 +557,8 @@ StoragePartitionImpl::~StoragePartitionImpl() {
GetBackgroundFetchContext()->Shutdown();
if (GetAppCacheService()) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&ChromeAppCacheService::Shutdown, appcache_service_));
}
@@ -577,10 +593,10 @@ std::unique_ptr<StoragePartitionImpl> StoragePartitionImpl::Create(
// that utilizes the QuotaManager.
partition->quota_manager_ = new storage::QuotaManager(
in_memory, partition_path,
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO).get(),
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO}).get(),
context->GetSpecialStoragePolicy(),
- base::Bind(&StoragePartitionImpl::GetQuotaSettings,
- partition->weak_factory_.GetWeakPtr()));
+ base::BindRepeating(&StoragePartitionImpl::GetQuotaSettings,
+ partition->weak_factory_.GetWeakPtr()));
scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy =
partition->quota_manager_->proxy();
@@ -675,7 +691,7 @@ std::unique_ptr<StoragePartitionImpl> StoragePartitionImpl::Create(
partition->cookie_store_context_->Initialize(
partition->service_worker_context_, base::DoNothing());
- if (base::FeatureList::IsEnabled(features::kIsolatedCodeCache)) {
+ if (base::FeatureList::IsEnabled(net::features::kIsolatedCodeCache)) {
// TODO(crbug.com/867552): Currently we misuse GetCachePath to check if
// code caching is enabled. Fix this by having a better API.
@@ -945,7 +961,7 @@ void StoragePartitionImpl::
if (task_count_)
return;
- callback_.Run();
+ std::move(callback_).Run();
delete this;
}
@@ -955,7 +971,7 @@ void StoragePartitionImpl::QuotaManagedDataDeletionHelper::ClearDataOnIOThread(
const scoped_refptr<storage::SpecialStoragePolicy>& special_storage_policy,
const StoragePartition::OriginMatcherFunction& origin_matcher) {
IncrementTaskCountOnIO();
- base::Closure decrement_callback = base::Bind(
+ base::RepeatingClosure decrement_callback = base::BindRepeating(
&QuotaManagedDataDeletionHelper::DecrementTaskCountOnIO,
base::Unretained(this));
@@ -991,7 +1007,7 @@ void StoragePartitionImpl::QuotaManagedDataDeletionHelper::ClearDataOnIOThread(
base::BindOnce(&QuotaManagedDataDeletionHelper::ClearOriginsOnIOThread,
base::Unretained(this), base::RetainedRef(quota_manager),
special_storage_policy, origin_matcher,
- std::move(decrement_callback)));
+ decrement_callback));
}
DecrementTaskCountOnIO();
@@ -1003,41 +1019,45 @@ void StoragePartitionImpl::QuotaManagedDataDeletionHelper::
const scoped_refptr<storage::SpecialStoragePolicy>&
special_storage_policy,
const StoragePartition::OriginMatcherFunction& origin_matcher,
- const base::Closure& callback,
- const std::set<GURL>& origins,
+ base::OnceClosure callback,
+ const std::set<url::Origin>& origins,
blink::mojom::StorageType quota_storage_type) {
// The QuotaManager manages all storage other than cookies, LocalStorage,
// and SessionStorage. This loop wipes out most HTML5 storage for the given
// origins.
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (origins.empty()) {
- callback.Run();
+ std::move(callback).Run();
return;
}
+ // The logic below (via CheckQuotaManagedDataDeletionStatus) only
+ // invokes the callback when all processing is complete.
+ base::RepeatingClosure completion =
+ base::AdaptCallbackForRepeating(std::move(callback));
+
size_t* deletion_task_count = new size_t(0u);
(*deletion_task_count)++;
- for (std::set<GURL>::const_iterator origin = origins.begin();
- origin != origins.end(); ++origin) {
+ for (const auto& origin : origins) {
// TODO(mkwst): Clean this up, it's slow. http://crbug.com/130746
- if (!storage_origin_.is_empty() && origin->GetOrigin() != storage_origin_)
+ if (storage_origin_.has_value() && origin != *storage_origin_)
continue;
if (!origin_matcher.is_null() &&
- !origin_matcher.Run(*origin, special_storage_policy.get())) {
+ !origin_matcher.Run(origin.GetURL(), special_storage_policy.get())) {
continue;
}
(*deletion_task_count)++;
quota_manager->DeleteOriginData(
- *origin, quota_storage_type,
+ origin, quota_storage_type,
StoragePartitionImpl::GenerateQuotaClientMask(remove_mask_),
- base::BindOnce(&OnQuotaManagedOriginDeleted, origin->GetOrigin(),
- quota_storage_type, deletion_task_count, callback));
+ base::BindOnce(&OnQuotaManagedOriginDeleted, origin, quota_storage_type,
+ deletion_task_count, completion));
}
(*deletion_task_count)--;
- CheckQuotaManagedDataDeletionStatus(deletion_task_count, callback);
+ CheckQuotaManagedDataDeletionStatus(deletion_task_count, completion);
}
void StoragePartitionImpl::DataDeletionHelper::IncrementTaskCountOnUI() {
@@ -1047,8 +1067,8 @@ void StoragePartitionImpl::DataDeletionHelper::IncrementTaskCountOnUI() {
void StoragePartitionImpl::DataDeletionHelper::DecrementTaskCount() {
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&DataDeletionHelper::DecrementTaskCount,
base::Unretained(this)));
return;
@@ -1078,7 +1098,7 @@ void StoragePartitionImpl::DataDeletionHelper::ClearDataOnUIThread(
DCHECK(!callback_.is_null());
IncrementTaskCountOnUI();
- base::Closure decrement_callback = base::Bind(
+ base::RepeatingClosure decrement_callback = base::BindRepeating(
&DataDeletionHelper::DecrementTaskCount, base::Unretained(this));
if (remove_mask_ & REMOVE_DATA_MASK_COOKIES) {
@@ -1111,8 +1131,8 @@ void StoragePartitionImpl::DataDeletionHelper::ClearDataOnUIThread(
remove_mask_ & REMOVE_DATA_MASK_SERVICE_WORKERS ||
remove_mask_ & REMOVE_DATA_MASK_CACHE_STORAGE) {
IncrementTaskCountOnUI();
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&DataDeletionHelper::ClearQuotaManagedDataOnIOThread,
base::Unretained(this), base::WrapRefCounted(quota_manager), begin,
@@ -1141,9 +1161,9 @@ void StoragePartitionImpl::DataDeletionHelper::ClearDataOnUIThread(
if (remove_mask_ & REMOVE_DATA_MASK_SHADER_CACHE) {
IncrementTaskCountOnUI();
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::BindOnce(&ClearShaderCacheOnIOThread, path,
- begin, end, decrement_callback));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(&ClearShaderCacheOnIOThread, path,
+ begin, end, decrement_callback));
}
#if BUILDFLAG(ENABLE_PLUGINS)
@@ -1297,8 +1317,8 @@ void StoragePartitionImpl::InitNetworkContext() {
DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
DCHECK(!network_context_owner_);
network_context_owner_ = std::make_unique<NetworkContextOwner>();
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&NetworkContextOwner::Initialize,
base::Unretained(network_context_owner_.get()),
MakeRequest(&network_context_), url_request_context_));
@@ -1331,12 +1351,6 @@ StoragePartitionImpl::GetURLLoaderFactoryForBrowserProcessInternal() {
switches::kDisableWebSecurity);
if (g_url_loader_factory_callback_for_test.Get().is_null()) {
auto request = mojo::MakeRequest(&url_loader_factory_for_browser_process_);
-
- if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
- GetContentClient()->browser()->WillCreateURLLoaderFactory(
- browser_context(), nullptr, false /* is_navigation */, GURL(),
- &request);
- }
GetNetworkContext()->CreateURLLoaderFactory(std::move(request),
std::move(params));
is_test_url_loader_factory_for_browser_process_ = false;
diff --git a/chromium/content/browser/storage_partition_impl_map.cc b/chromium/content/browser/storage_partition_impl_map.cc
index c93fd1e67ba..173d8a0d25d 100644
--- a/chromium/content/browser/storage_partition_impl_map.cc
+++ b/chromium/content/browser/storage_partition_impl_map.cc
@@ -41,6 +41,7 @@
#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_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/storage_partition.h"
@@ -187,9 +188,7 @@ void ObliterateOneDirectory(const base::FilePath& current_dir,
// Enum tracking which of the 3 possible actions to take for |to_delete|.
enum { kSkip, kEnqueue, kDelete } action = kDelete;
- for (std::vector<base::FilePath>::const_iterator to_keep =
- paths_to_keep.begin();
- to_keep != paths_to_keep.end();
+ for (auto to_keep = paths_to_keep.begin(); to_keep != paths_to_keep.end();
++to_keep) {
if (to_delete == *to_keep) {
action = kSkip;
@@ -245,9 +244,7 @@ void BlockingObliteratePath(
// Reduce |paths_to_keep| set to those under the root and actually on disk.
std::vector<base::FilePath> valid_paths_to_keep;
- for (std::vector<base::FilePath>::const_iterator it = paths_to_keep.begin();
- it != paths_to_keep.end();
- ++it) {
+ for (auto it = paths_to_keep.begin(); it != paths_to_keep.end(); ++it) {
if (root.IsParent(*it) && base::PathExists(*it))
valid_paths_to_keep.push_back(*it);
}
@@ -277,8 +274,7 @@ void NormalizeActivePaths(const base::FilePath& storage_root,
base::hash_set<base::FilePath>* active_paths) {
base::hash_set<base::FilePath> normalized_active_paths;
- for (base::hash_set<base::FilePath>::iterator iter = active_paths->begin();
- iter != active_paths->end(); ++iter) {
+ for (auto iter = active_paths->begin(); iter != active_paths->end(); ++iter) {
base::FilePath relative_path;
if (!storage_root.AppendRelativePath(*iter, &relative_path))
continue;
@@ -556,8 +552,8 @@ void StoragePartitionImplMap::PostCreateInitialization(
// Check first to avoid memory leak in unittests.
if (BrowserThread::IsThreadInitialized(BrowserThread::IO)) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&ChromeAppCacheService::InitializeOnIOThread,
partition->GetAppCacheService(),
@@ -567,29 +563,29 @@ void StoragePartitionImplMap::PostCreateInitialization(
base::RetainedRef(partition->GetURLRequestContext()),
base::RetainedRef(browser_context_->GetSpecialStoragePolicy())));
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&CacheStorageContextImpl::SetBlobParametersForCache,
partition->GetCacheStorageContext(),
base::RetainedRef(partition->GetURLRequestContext()),
base::RetainedRef(ChromeBlobStorageContext::GetFor(
browser_context_))));
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&ServiceWorkerContextWrapper::InitializeResourceContext,
partition->GetServiceWorkerContext(),
browser_context_->GetResourceContext()));
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&PrefetchURLLoaderService::InitializeResourceContext,
partition->GetPrefetchURLLoaderService(),
browser_context_->GetResourceContext(),
base::RetainedRef(partition->GetURLRequestContext())));
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&BackgroundFetchContext::InitializeOnIOThread,
partition->GetBackgroundFetchContext()));
diff --git a/chromium/content/browser/storage_partition_impl_unittest.cc b/chromium/content/browser/storage_partition_impl_unittest.cc
index d58a94c0a62..d0942e106f5 100644
--- a/chromium/content/browser/storage_partition_impl_unittest.cc
+++ b/chromium/content/browser/storage_partition_impl_unittest.cc
@@ -10,6 +10,8 @@
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
+#include "base/task/post_task.h"
+#include "base/test/scoped_feature_list.h"
#include "base/threading/thread.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/services/leveldb/public/cpp/util.h"
@@ -18,13 +20,16 @@
#include "content/browser/dom_storage/local_storage_database.pb.h"
#include "content/browser/gpu/shader_cache_factory.h"
#include "content/browser/storage_partition_impl.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/local_storage_usage_info.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/common/content_features.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 "content/public/test/test_utils.h"
#include "content/test/fake_leveldb_database.h"
+#include "net/base/features.h"
#include "net/base/test_completion_callback.h"
#include "net/cookies/canonical_cookie.h"
#include "net/cookies/cookie_store.h"
@@ -68,10 +73,12 @@ const char kWidevineCdmPluginId[] = "application_x-ppapi-widevine-cdm";
const char kClearKeyCdmPluginId[] = "application_x-ppapi-clearkey-cdm";
#endif // BUILDFLAG(ENABLE_PLUGINS)
-const GURL kOrigin1(kTestOrigin1);
-const GURL kOrigin2(kTestOrigin2);
-const GURL kOrigin3(kTestOrigin3);
-const GURL kOriginDevTools(kTestOriginDevTools);
+// TODO(crbug.com/889590): Use helper for url::Origin creation from string.
+const url::Origin kOrigin1 = url::Origin::Create(GURL(kTestOrigin1));
+const url::Origin kOrigin2 = url::Origin::Create(GURL(kTestOrigin2));
+const url::Origin kOrigin3 = url::Origin::Create(GURL(kTestOrigin3));
+const url::Origin kOriginDevTools =
+ url::Origin::Create(GURL(kTestOriginDevTools));
const GURL kResourceURL(kTestURL);
const blink::mojom::StorageType kTemporary =
@@ -135,7 +142,7 @@ class RemoveCookieTester {
bool ContainsCookie() {
get_cookie_success_ = false;
cookie_store_->GetCookieListWithOptionsAsync(
- kOrigin1, net::CookieOptions(),
+ kOrigin1.GetURL(), net::CookieOptions(),
base::BindOnce(&RemoveCookieTester::GetCookieListCallback,
base::Unretained(this)));
await_completion_.BlockUntilNotified();
@@ -144,7 +151,7 @@ class RemoveCookieTester {
void AddCookie() {
cookie_store_->SetCookieWithOptionsAsync(
- kOrigin1, "A=1", net::CookieOptions(),
+ kOrigin1.GetURL(), "A=1", net::CookieOptions(),
base::BindOnce(&RemoveCookieTester::SetCookieCallback,
base::Unretained(this)));
await_completion_.BlockUntilNotified();
@@ -187,11 +194,11 @@ class RemoveLocalStorageTester {
}
// Returns true, if the given origin URL exists.
- bool DOMStorageExistsForOrigin(const GURL& origin) {
+ bool DOMStorageExistsForOrigin(const url::Origin& origin) {
GetLocalStorageUsage();
await_completion_.BlockUntilNotified();
for (size_t i = 0; i < infos_.size(); ++i) {
- if (origin == infos_[i].origin)
+ if (origin == url::Origin::Create(infos_[i].origin))
return true;
}
return false;
@@ -212,21 +219,21 @@ class RemoveLocalStorageTester {
base::Time now = base::Time::Now();
data.set_last_modified(now.ToInternalValue());
data.set_size_bytes(16);
- mock_data_[CreateMetaDataKey(url::Origin::Create(kOrigin1))] =
+ mock_data_[CreateMetaDataKey(kOrigin1)] =
leveldb::StdStringToUint8Vector(data.SerializeAsString());
- mock_data_[CreateDataKey(url::Origin::Create(kOrigin1))] = {};
+ mock_data_[CreateDataKey(kOrigin1)] = {};
base::Time one_day_ago = now - base::TimeDelta::FromDays(1);
data.set_last_modified(one_day_ago.ToInternalValue());
- mock_data_[CreateMetaDataKey(url::Origin::Create(kOrigin2))] =
+ mock_data_[CreateMetaDataKey(kOrigin2)] =
leveldb::StdStringToUint8Vector(data.SerializeAsString());
- mock_data_[CreateDataKey(url::Origin::Create(kOrigin2))] = {};
+ mock_data_[CreateDataKey(kOrigin2)] = {};
base::Time sixty_days_ago = now - base::TimeDelta::FromDays(60);
data.set_last_modified(sixty_days_ago.ToInternalValue());
- mock_data_[CreateMetaDataKey(url::Origin::Create(kOrigin3))] =
+ mock_data_[CreateMetaDataKey(kOrigin3)] =
leveldb::StdStringToUint8Vector(data.SerializeAsString());
- mock_data_[CreateDataKey(url::Origin::Create(kOrigin3))] = {};
+ mock_data_[CreateDataKey(kOrigin3)] = {};
}
private:
@@ -282,26 +289,39 @@ class RemoveCodeCacheTester {
explicit RemoveCodeCacheTester(GeneratedCodeCacheContext* code_cache_context)
: code_cache_context_(code_cache_context) {}
- bool ContainsEntry(GURL url, url::Origin origin) {
+ enum Cache { kJs, kWebAssembly };
+
+ bool ContainsEntry(Cache cache, GURL url, url::Origin origin) {
entry_exists_ = false;
GeneratedCodeCache::ReadDataCallback callback = base::BindRepeating(
&RemoveCodeCacheTester::FetchEntryCallback, base::Unretained(this));
- code_cache_context_->generated_code_cache()->FetchEntry(url, origin,
- callback);
+ GetCache(cache)->FetchEntry(url, origin, callback);
await_completion_.BlockUntilNotified();
return entry_exists_;
}
- void AddEntry(GURL url, url::Origin origin, const std::string& data) {
+ void AddEntry(Cache cache,
+ GURL url,
+ url::Origin origin,
+ const std::string& data) {
std::vector<uint8_t> data_vector(data.begin(), data.end());
- code_cache_context_->generated_code_cache()->WriteData(
- url, origin, base::Time::Now(), data_vector);
+ GetCache(cache)->WriteData(url, origin, base::Time::Now(), data_vector);
base::RunLoop().RunUntilIdle();
+ // TODO(crbug.com/886892): Remove this once we update GeneratedCodeCache
+ // to serialize operations corresponding to each entry.
+ content::RunAllTasksUntilIdle();
}
std::string received_data() { return received_data_; }
private:
+ GeneratedCodeCache* GetCache(Cache cache) {
+ if (cache == kJs)
+ return code_cache_context_->generated_js_code_cache();
+ else
+ return code_cache_context_->generated_wasm_code_cache();
+ }
+
void FetchEntryCallback(const base::Time& response_time,
const std::vector<uint8_t>& data) {
if (!response_time.is_null()) {
@@ -338,18 +358,18 @@ class RemovePluginPrivateDataTester {
// Create a PluginPrivateFileSystem for ClearKey and add a single file
// with a timestamp of 1 day ago.
std::string clearkey_fsid =
- CreateFileSystem(kClearKeyCdmPluginId, kOrigin1);
- clearkey_file_ = CreateFile(kOrigin1, clearkey_fsid, "foo");
+ CreateFileSystem(kClearKeyCdmPluginId, kOrigin1.GetURL());
+ clearkey_file_ = CreateFile(kOrigin1.GetURL(), clearkey_fsid, "foo");
SetFileTimestamp(clearkey_file_, ten_days_ago);
// Create a second PluginPrivateFileSystem for Widevine and add two files
// with different times.
std::string widevine_fsid =
- CreateFileSystem(kWidevineCdmPluginId, kOrigin2);
+ CreateFileSystem(kWidevineCdmPluginId, kOrigin2.GetURL());
storage::FileSystemURL widevine_file1 =
- CreateFile(kOrigin2, widevine_fsid, "bar1");
+ CreateFile(kOrigin2.GetURL(), widevine_fsid, "bar1");
storage::FileSystemURL widevine_file2 =
- CreateFile(kOrigin2, widevine_fsid, "bar2");
+ CreateFile(kOrigin2.GetURL(), widevine_fsid, "bar2");
SetFileTimestamp(widevine_file1, now);
SetFileTimestamp(widevine_file2, sixty_days_ago);
}
@@ -357,7 +377,7 @@ class RemovePluginPrivateDataTester {
void DeleteClearKeyTestData() { DeleteFile(clearkey_file_); }
// Returns true, if the given origin exists in a PluginPrivateFileSystem.
- bool DataExistsForOrigin(const GURL& origin) {
+ bool DataExistsForOrigin(const url::Origin& origin) {
AwaitCompletionHelper await_completion;
bool data_exists_for_origin = false;
filesystem_context_->default_file_task_runner()->PostTask(
@@ -505,7 +525,7 @@ class RemovePluginPrivateDataTester {
// If |origin| exists in the PluginPrivateFileSystem, set
// |data_exists_for_origin| to true, false otherwise.
void CheckIfDataExistsForOriginOnFileTaskRunner(
- const GURL& origin,
+ const url::Origin& origin,
bool* data_exists_for_origin,
AwaitCompletionHelper* await_completion) {
storage::FileSystemBackend* backend =
@@ -517,13 +537,14 @@ class RemovePluginPrivateDataTester {
std::set<GURL> origins;
quota_util->GetOriginsForTypeOnFileTaskRunner(
storage::kFileSystemTypePluginPrivate, &origins);
- *data_exists_for_origin = origins.find(origin) != origins.end();
+ *data_exists_for_origin = origins.find(origin.GetURL()) != origins.end();
// AwaitCompletionHelper and MessageLoop don't work on a
// SequencedTaskRunner, so post a task on the IO thread.
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::BindOnce(&AwaitCompletionHelper::Notify,
- base::Unretained(await_completion)));
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(&AwaitCompletionHelper::Notify,
+ base::Unretained(await_completion)));
}
// We don't own this pointer.
@@ -693,7 +714,8 @@ class StoragePartitionImplTest : public testing::Test {
if (!quota_manager_.get()) {
quota_manager_ = new MockQuotaManager(
browser_context_->IsOffTheRecord(), browser_context_->GetPath(),
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO).get(),
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO})
+ .get(),
browser_context_->GetSpecialStoragePolicy());
}
return quota_manager_.get();
@@ -795,7 +817,7 @@ TEST_F(StoragePartitionImplTest, QuotaClientMaskGeneration) {
void PopulateTestQuotaManagedPersistentData(MockQuotaManager* manager) {
manager->AddOrigin(kOrigin2, kPersistent, kClientFile, base::Time());
manager->AddOrigin(kOrigin3, kPersistent, kClientFile,
- base::Time::Now() - base::TimeDelta::FromDays(1));
+ base::Time::Now() - base::TimeDelta::FromDays(1));
EXPECT_FALSE(manager->OriginHasData(kOrigin1, kPersistent, kClientFile));
EXPECT_TRUE(manager->OriginHasData(kOrigin2, kPersistent, kClientFile));
@@ -805,7 +827,7 @@ void PopulateTestQuotaManagedPersistentData(MockQuotaManager* manager) {
void PopulateTestQuotaManagedTemporaryData(MockQuotaManager* manager) {
manager->AddOrigin(kOrigin1, kTemporary, kClientFile, base::Time::Now());
manager->AddOrigin(kOrigin3, kTemporary, kClientFile,
- base::Time::Now() - base::TimeDelta::FromDays(1));
+ base::Time::Now() - base::TimeDelta::FromDays(1));
EXPECT_TRUE(manager->OriginHasData(kOrigin1, kTemporary, kClientFile));
EXPECT_FALSE(manager->OriginHasData(kOrigin2, kTemporary, kClientFile));
@@ -839,18 +861,18 @@ TEST_F(StoragePartitionImplTest, RemoveQuotaManagedDataForeverBoth) {
FROM_HERE, base::BindOnce(&ClearQuotaData, partition, &run_loop));
run_loop.Run();
- EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin1, kTemporary,
- kClientFile));
- EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin2, kTemporary,
- kClientFile));
- EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin3, kTemporary,
- kClientFile));
- EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin1, kPersistent,
- kClientFile));
- EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin2, kPersistent,
- kClientFile));
- EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin3, kPersistent,
- kClientFile));
+ EXPECT_FALSE(
+ GetMockManager()->OriginHasData(kOrigin1, kTemporary, kClientFile));
+ EXPECT_FALSE(
+ GetMockManager()->OriginHasData(kOrigin2, kTemporary, kClientFile));
+ EXPECT_FALSE(
+ GetMockManager()->OriginHasData(kOrigin3, kTemporary, kClientFile));
+ EXPECT_FALSE(
+ GetMockManager()->OriginHasData(kOrigin1, kPersistent, kClientFile));
+ EXPECT_FALSE(
+ GetMockManager()->OriginHasData(kOrigin2, kPersistent, kClientFile));
+ EXPECT_FALSE(
+ GetMockManager()->OriginHasData(kOrigin3, kPersistent, kClientFile));
}
TEST_F(StoragePartitionImplTest, RemoveQuotaManagedDataForeverOnlyTemporary) {
@@ -866,18 +888,18 @@ TEST_F(StoragePartitionImplTest, RemoveQuotaManagedDataForeverOnlyTemporary) {
FROM_HERE, base::BindOnce(&ClearQuotaData, partition, &run_loop));
run_loop.Run();
- EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin1, kTemporary,
- kClientFile));
- EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin2, kTemporary,
- kClientFile));
- EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin3, kTemporary,
- kClientFile));
- EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin1, kPersistent,
- kClientFile));
- EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin2, kPersistent,
- kClientFile));
- EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin3, kPersistent,
- kClientFile));
+ EXPECT_FALSE(
+ GetMockManager()->OriginHasData(kOrigin1, kTemporary, kClientFile));
+ EXPECT_FALSE(
+ GetMockManager()->OriginHasData(kOrigin2, kTemporary, kClientFile));
+ EXPECT_FALSE(
+ GetMockManager()->OriginHasData(kOrigin3, kTemporary, kClientFile));
+ EXPECT_FALSE(
+ GetMockManager()->OriginHasData(kOrigin1, kPersistent, kClientFile));
+ EXPECT_FALSE(
+ GetMockManager()->OriginHasData(kOrigin2, kPersistent, kClientFile));
+ EXPECT_FALSE(
+ GetMockManager()->OriginHasData(kOrigin3, kPersistent, kClientFile));
}
TEST_F(StoragePartitionImplTest, RemoveQuotaManagedDataForeverOnlyPersistent) {
@@ -893,18 +915,18 @@ TEST_F(StoragePartitionImplTest, RemoveQuotaManagedDataForeverOnlyPersistent) {
FROM_HERE, base::BindOnce(&ClearQuotaData, partition, &run_loop));
run_loop.Run();
- EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin1, kTemporary,
- kClientFile));
- EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin2, kTemporary,
- kClientFile));
- EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin3, kTemporary,
- kClientFile));
- EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin1, kPersistent,
- kClientFile));
- EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin2, kPersistent,
- kClientFile));
- EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin3, kPersistent,
- kClientFile));
+ EXPECT_FALSE(
+ GetMockManager()->OriginHasData(kOrigin1, kTemporary, kClientFile));
+ EXPECT_FALSE(
+ GetMockManager()->OriginHasData(kOrigin2, kTemporary, kClientFile));
+ EXPECT_FALSE(
+ GetMockManager()->OriginHasData(kOrigin3, kTemporary, kClientFile));
+ EXPECT_FALSE(
+ GetMockManager()->OriginHasData(kOrigin1, kPersistent, kClientFile));
+ EXPECT_FALSE(
+ GetMockManager()->OriginHasData(kOrigin2, kPersistent, kClientFile));
+ EXPECT_FALSE(
+ GetMockManager()->OriginHasData(kOrigin3, kPersistent, kClientFile));
}
TEST_F(StoragePartitionImplTest, RemoveQuotaManagedDataForeverNeither) {
@@ -918,18 +940,18 @@ TEST_F(StoragePartitionImplTest, RemoveQuotaManagedDataForeverNeither) {
FROM_HERE, base::BindOnce(&ClearQuotaData, partition, &run_loop));
run_loop.Run();
- EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin1, kTemporary,
- kClientFile));
- EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin2, kTemporary,
- kClientFile));
- EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin3, kTemporary,
- kClientFile));
- EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin1, kPersistent,
- kClientFile));
- EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin2, kPersistent,
- kClientFile));
- EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin3, kPersistent,
- kClientFile));
+ EXPECT_FALSE(
+ GetMockManager()->OriginHasData(kOrigin1, kTemporary, kClientFile));
+ EXPECT_FALSE(
+ GetMockManager()->OriginHasData(kOrigin2, kTemporary, kClientFile));
+ EXPECT_FALSE(
+ GetMockManager()->OriginHasData(kOrigin3, kTemporary, kClientFile));
+ EXPECT_FALSE(
+ GetMockManager()->OriginHasData(kOrigin1, kPersistent, kClientFile));
+ EXPECT_FALSE(
+ GetMockManager()->OriginHasData(kOrigin2, kPersistent, kClientFile));
+ EXPECT_FALSE(
+ GetMockManager()->OriginHasData(kOrigin3, kPersistent, kClientFile));
}
TEST_F(StoragePartitionImplTest, RemoveQuotaManagedDataForeverSpecificOrigin) {
@@ -942,22 +964,22 @@ TEST_F(StoragePartitionImplTest, RemoveQuotaManagedDataForeverSpecificOrigin) {
base::RunLoop run_loop;
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(&ClearQuotaDataForOrigin, partition, kOrigin1,
- base::Time(), &run_loop));
+ FROM_HERE, base::BindOnce(&ClearQuotaDataForOrigin, partition,
+ kOrigin1.GetURL(), base::Time(), &run_loop));
run_loop.Run();
- EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin1, kTemporary,
- kClientFile));
- EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin2, kTemporary,
- kClientFile));
- EXPECT_TRUE(GetMockManager()->OriginHasData(kOrigin3, kTemporary,
- kClientFile));
- EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin1, kPersistent,
- kClientFile));
- EXPECT_TRUE(GetMockManager()->OriginHasData(kOrigin2, kPersistent,
- kClientFile));
- EXPECT_TRUE(GetMockManager()->OriginHasData(kOrigin3, kPersistent,
- kClientFile));
+ EXPECT_FALSE(
+ GetMockManager()->OriginHasData(kOrigin1, kTemporary, kClientFile));
+ EXPECT_FALSE(
+ GetMockManager()->OriginHasData(kOrigin2, kTemporary, kClientFile));
+ EXPECT_TRUE(
+ GetMockManager()->OriginHasData(kOrigin3, kTemporary, kClientFile));
+ EXPECT_FALSE(
+ GetMockManager()->OriginHasData(kOrigin1, kPersistent, kClientFile));
+ EXPECT_TRUE(
+ GetMockManager()->OriginHasData(kOrigin2, kPersistent, kClientFile));
+ EXPECT_TRUE(
+ GetMockManager()->OriginHasData(kOrigin3, kPersistent, kClientFile));
}
TEST_F(StoragePartitionImplTest, RemoveQuotaManagedDataForLastHour) {
@@ -976,18 +998,18 @@ TEST_F(StoragePartitionImplTest, RemoveQuotaManagedDataForLastHour) {
&run_loop));
run_loop.Run();
- EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin1, kTemporary,
- kClientFile));
- EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin2, kTemporary,
- kClientFile));
- EXPECT_TRUE(GetMockManager()->OriginHasData(kOrigin3, kTemporary,
- kClientFile));
- EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin1, kPersistent,
- kClientFile));
- EXPECT_TRUE(GetMockManager()->OriginHasData(kOrigin2, kPersistent,
- kClientFile));
- EXPECT_TRUE(GetMockManager()->OriginHasData(kOrigin3, kPersistent,
- kClientFile));
+ EXPECT_FALSE(
+ GetMockManager()->OriginHasData(kOrigin1, kTemporary, kClientFile));
+ EXPECT_FALSE(
+ GetMockManager()->OriginHasData(kOrigin2, kTemporary, kClientFile));
+ EXPECT_TRUE(
+ GetMockManager()->OriginHasData(kOrigin3, kTemporary, kClientFile));
+ EXPECT_FALSE(
+ GetMockManager()->OriginHasData(kOrigin1, kPersistent, kClientFile));
+ EXPECT_TRUE(
+ GetMockManager()->OriginHasData(kOrigin2, kPersistent, kClientFile));
+ EXPECT_TRUE(
+ GetMockManager()->OriginHasData(kOrigin3, kPersistent, kClientFile));
}
TEST_F(StoragePartitionImplTest, RemoveQuotaManagedDataForLastWeek) {
@@ -1005,25 +1027,25 @@ TEST_F(StoragePartitionImplTest, RemoveQuotaManagedDataForLastWeek) {
&run_loop));
run_loop.Run();
- EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin1, kTemporary,
- kClientFile));
- EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin2, kTemporary,
- kClientFile));
- EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin3, kTemporary,
- kClientFile));
- EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin1, kPersistent,
- kClientFile));
- EXPECT_TRUE(GetMockManager()->OriginHasData(kOrigin2, kPersistent,
- kClientFile));
- EXPECT_TRUE(GetMockManager()->OriginHasData(kOrigin3, kPersistent,
- kClientFile));
+ EXPECT_FALSE(
+ GetMockManager()->OriginHasData(kOrigin1, kTemporary, kClientFile));
+ EXPECT_FALSE(
+ GetMockManager()->OriginHasData(kOrigin2, kTemporary, kClientFile));
+ EXPECT_FALSE(
+ GetMockManager()->OriginHasData(kOrigin3, kTemporary, kClientFile));
+ EXPECT_FALSE(
+ GetMockManager()->OriginHasData(kOrigin1, kPersistent, kClientFile));
+ EXPECT_TRUE(
+ GetMockManager()->OriginHasData(kOrigin2, kPersistent, kClientFile));
+ EXPECT_TRUE(
+ GetMockManager()->OriginHasData(kOrigin3, kPersistent, kClientFile));
}
TEST_F(StoragePartitionImplTest, RemoveQuotaManagedUnprotectedOrigins) {
// Protect kOrigin1.
scoped_refptr<MockSpecialStoragePolicy> mock_policy =
new MockSpecialStoragePolicy;
- mock_policy->AddProtected(kOrigin1.GetOrigin());
+ mock_policy->AddProtected(kOrigin1.GetURL());
PopulateTestQuotaManagedData(GetMockManager());
@@ -1037,29 +1059,29 @@ TEST_F(StoragePartitionImplTest, RemoveQuotaManagedUnprotectedOrigins) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::BindOnce(&ClearQuotaDataWithOriginMatcher, partition, GURL(),
- base::Bind(&DoesOriginMatchForUnprotectedWeb),
+ base::BindRepeating(&DoesOriginMatchForUnprotectedWeb),
base::Time(), &run_loop));
run_loop.Run();
- EXPECT_TRUE(GetMockManager()->OriginHasData(kOrigin1, kTemporary,
- kClientFile));
- EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin2, kTemporary,
- kClientFile));
- EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin3, kTemporary,
- kClientFile));
- EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin1, kPersistent,
- kClientFile));
- EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin2, kPersistent,
- kClientFile));
- EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin3, kPersistent,
- kClientFile));
+ EXPECT_TRUE(
+ GetMockManager()->OriginHasData(kOrigin1, kTemporary, kClientFile));
+ EXPECT_FALSE(
+ GetMockManager()->OriginHasData(kOrigin2, kTemporary, kClientFile));
+ EXPECT_FALSE(
+ GetMockManager()->OriginHasData(kOrigin3, kTemporary, kClientFile));
+ EXPECT_FALSE(
+ GetMockManager()->OriginHasData(kOrigin1, kPersistent, kClientFile));
+ EXPECT_FALSE(
+ GetMockManager()->OriginHasData(kOrigin2, kPersistent, kClientFile));
+ EXPECT_FALSE(
+ GetMockManager()->OriginHasData(kOrigin3, kPersistent, kClientFile));
}
TEST_F(StoragePartitionImplTest, RemoveQuotaManagedProtectedSpecificOrigin) {
// Protect kOrigin1.
scoped_refptr<MockSpecialStoragePolicy> mock_policy =
new MockSpecialStoragePolicy;
- mock_policy->AddProtected(kOrigin1.GetOrigin());
+ mock_policy->AddProtected(kOrigin1.GetURL());
PopulateTestQuotaManagedData(GetMockManager());
@@ -1073,30 +1095,31 @@ TEST_F(StoragePartitionImplTest, RemoveQuotaManagedProtectedSpecificOrigin) {
base::RunLoop run_loop;
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
- base::BindOnce(&ClearQuotaDataWithOriginMatcher, partition, kOrigin1,
- base::Bind(&DoesOriginMatchForUnprotectedWeb),
+ base::BindOnce(&ClearQuotaDataWithOriginMatcher, partition,
+ kOrigin1.GetURL(),
+ base::BindRepeating(&DoesOriginMatchForUnprotectedWeb),
base::Time(), &run_loop));
run_loop.Run();
- EXPECT_TRUE(GetMockManager()->OriginHasData(kOrigin1, kTemporary,
- kClientFile));
- EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin2, kTemporary,
- kClientFile));
- EXPECT_TRUE(GetMockManager()->OriginHasData(kOrigin3, kTemporary,
- kClientFile));
- EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin1, kPersistent,
- kClientFile));
- EXPECT_TRUE(GetMockManager()->OriginHasData(kOrigin2, kPersistent,
- kClientFile));
- EXPECT_TRUE(GetMockManager()->OriginHasData(kOrigin3, kPersistent,
- kClientFile));
+ EXPECT_TRUE(
+ GetMockManager()->OriginHasData(kOrigin1, kTemporary, kClientFile));
+ EXPECT_FALSE(
+ GetMockManager()->OriginHasData(kOrigin2, kTemporary, kClientFile));
+ EXPECT_TRUE(
+ GetMockManager()->OriginHasData(kOrigin3, kTemporary, kClientFile));
+ EXPECT_FALSE(
+ GetMockManager()->OriginHasData(kOrigin1, kPersistent, kClientFile));
+ EXPECT_TRUE(
+ GetMockManager()->OriginHasData(kOrigin2, kPersistent, kClientFile));
+ EXPECT_TRUE(
+ GetMockManager()->OriginHasData(kOrigin3, kPersistent, kClientFile));
}
TEST_F(StoragePartitionImplTest, RemoveQuotaManagedProtectedOrigins) {
// Protect kOrigin1.
scoped_refptr<MockSpecialStoragePolicy> mock_policy =
new MockSpecialStoragePolicy;
- mock_policy->AddProtected(kOrigin1.GetOrigin());
+ mock_policy->AddProtected(kOrigin1.GetURL());
PopulateTestQuotaManagedData(GetMockManager());
@@ -1109,24 +1132,24 @@ TEST_F(StoragePartitionImplTest, RemoveQuotaManagedProtectedOrigins) {
partition->OverrideSpecialStoragePolicyForTesting(mock_policy.get());
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
- base::BindOnce(
- &ClearQuotaDataWithOriginMatcher, partition, GURL(),
- base::Bind(&DoesOriginMatchForBothProtectedAndUnprotectedWeb),
- base::Time(), &run_loop));
+ base::BindOnce(&ClearQuotaDataWithOriginMatcher, partition, GURL(),
+ base::BindRepeating(
+ &DoesOriginMatchForBothProtectedAndUnprotectedWeb),
+ base::Time(), &run_loop));
run_loop.Run();
- EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin1, kTemporary,
- kClientFile));
- EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin2, kTemporary,
- kClientFile));
- EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin3, kTemporary,
- kClientFile));
- EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin1, kPersistent,
- kClientFile));
- EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin2, kPersistent,
- kClientFile));
- EXPECT_FALSE(GetMockManager()->OriginHasData(kOrigin3, kPersistent,
- kClientFile));
+ EXPECT_FALSE(
+ GetMockManager()->OriginHasData(kOrigin1, kTemporary, kClientFile));
+ EXPECT_FALSE(
+ GetMockManager()->OriginHasData(kOrigin2, kTemporary, kClientFile));
+ EXPECT_FALSE(
+ GetMockManager()->OriginHasData(kOrigin3, kTemporary, kClientFile));
+ EXPECT_FALSE(
+ GetMockManager()->OriginHasData(kOrigin1, kPersistent, kClientFile));
+ EXPECT_FALSE(
+ GetMockManager()->OriginHasData(kOrigin2, kPersistent, kClientFile));
+ EXPECT_FALSE(
+ GetMockManager()->OriginHasData(kOrigin3, kPersistent, kClientFile));
}
TEST_F(StoragePartitionImplTest, RemoveQuotaManagedIgnoreDevTools) {
@@ -1138,16 +1161,17 @@ TEST_F(StoragePartitionImplTest, RemoveQuotaManagedIgnoreDevTools) {
partition->OverrideQuotaManagerForTesting(
GetMockManager());
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(&ClearQuotaDataWithOriginMatcher, partition,
- GURL(), base::Bind(&DoesOriginMatchUnprotected),
- base::Time(), &run_loop));
+ FROM_HERE,
+ base::BindOnce(&ClearQuotaDataWithOriginMatcher, partition, GURL(),
+ base::BindRepeating(&DoesOriginMatchUnprotected),
+ base::Time(), &run_loop));
run_loop.Run();
// Check that devtools data isn't removed.
EXPECT_TRUE(GetMockManager()->OriginHasData(kOriginDevTools, kTemporary,
- kClientFile));
+ kClientFile));
EXPECT_TRUE(GetMockManager()->OriginHasData(kOriginDevTools, kPersistent,
- kClientFile));
+ kClientFile));
}
TEST_F(StoragePartitionImplTest, RemoveCookieForever) {
@@ -1211,7 +1235,7 @@ TEST_F(StoragePartitionImplTest, RemoveUnprotectedLocalStorageForever) {
// Protect kOrigin1.
scoped_refptr<MockSpecialStoragePolicy> mock_policy =
new MockSpecialStoragePolicy;
- mock_policy->AddProtected(kOrigin1.GetOrigin());
+ mock_policy->AddProtected(kOrigin1.GetURL());
RemoveLocalStorageTester tester(browser_context());
@@ -1227,10 +1251,10 @@ TEST_F(StoragePartitionImplTest, RemoveUnprotectedLocalStorageForever) {
base::RunLoop run_loop;
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
- base::BindOnce(&ClearStuff,
- StoragePartitionImpl::REMOVE_DATA_MASK_LOCAL_STORAGE,
- partition, base::Time(), base::Time::Max(),
- base::Bind(&DoesOriginMatchForUnprotectedWeb), &run_loop));
+ base::BindOnce(
+ &ClearStuff, StoragePartitionImpl::REMOVE_DATA_MASK_LOCAL_STORAGE,
+ partition, base::Time(), base::Time::Max(),
+ base::BindRepeating(&DoesOriginMatchForUnprotectedWeb), &run_loop));
run_loop.Run();
// ClearData only guarantees that tasks to delete data are scheduled when its
// callback is invoked. It doesn't guarantee data has actually been cleared.
@@ -1246,7 +1270,7 @@ TEST_F(StoragePartitionImplTest, RemoveProtectedLocalStorageForever) {
// Protect kOrigin1.
scoped_refptr<MockSpecialStoragePolicy> mock_policy =
new MockSpecialStoragePolicy;
- mock_policy->AddProtected(kOrigin1.GetOrigin());
+ mock_policy->AddProtected(kOrigin1.GetURL());
RemoveLocalStorageTester tester(browser_context());
@@ -1262,11 +1286,12 @@ TEST_F(StoragePartitionImplTest, RemoveProtectedLocalStorageForever) {
base::RunLoop run_loop;
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
- base::BindOnce(
- &ClearStuff, StoragePartitionImpl::REMOVE_DATA_MASK_LOCAL_STORAGE,
- partition, base::Time(), base::Time::Max(),
- base::Bind(&DoesOriginMatchForBothProtectedAndUnprotectedWeb),
- &run_loop));
+ base::BindOnce(&ClearStuff,
+ StoragePartitionImpl::REMOVE_DATA_MASK_LOCAL_STORAGE,
+ partition, base::Time(), base::Time::Max(),
+ base::BindRepeating(
+ &DoesOriginMatchForBothProtectedAndUnprotectedWeb),
+ &run_loop));
run_loop.Run();
// ClearData only guarantees that tasks to delete data are scheduled when its
// callback is invoked. It doesn't guarantee data has actually been cleared.
@@ -1295,11 +1320,12 @@ TEST_F(StoragePartitionImplTest, RemoveLocalStorageForLastWeek) {
base::RunLoop run_loop;
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
- base::BindOnce(
- &ClearStuff, StoragePartitionImpl::REMOVE_DATA_MASK_LOCAL_STORAGE,
- partition, a_week_ago, base::Time::Max(),
- base::Bind(&DoesOriginMatchForBothProtectedAndUnprotectedWeb),
- &run_loop));
+ base::BindOnce(&ClearStuff,
+ StoragePartitionImpl::REMOVE_DATA_MASK_LOCAL_STORAGE,
+ partition, a_week_ago, base::Time::Max(),
+ base::BindRepeating(
+ &DoesOriginMatchForBothProtectedAndUnprotectedWeb),
+ &run_loop));
run_loop.Run();
// ClearData only guarantees that tasks to delete data are scheduled when its
// callback is invoked. It doesn't guarantee data has actually been cleared.
@@ -1313,29 +1339,83 @@ TEST_F(StoragePartitionImplTest, RemoveLocalStorageForLastWeek) {
}
TEST_F(StoragePartitionImplTest, ClearCodeCache) {
- // Run this test only when the IsolatedCodeCache feature is enabled
- if (!base::FeatureList::IsEnabled(features::kIsolatedCodeCache))
- return;
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitAndEnableFeature(net::features::kIsolatedCodeCache);
+ ASSERT_TRUE(base::FeatureList::IsEnabled(net::features::kIsolatedCodeCache));
StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
BrowserContext::GetDefaultStoragePartition(browser_context()));
// Ensure code cache is initialized.
base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(partition->GetGeneratedCodeCacheContext() != nullptr);
RemoveCodeCacheTester tester(partition->GetGeneratedCodeCacheContext());
- url::Origin origin = url::Origin::Create(kOrigin1);
+ url::Origin origin = kOrigin1;
std::string data("SomeData");
- tester.AddEntry(kResourceURL, origin, data);
- EXPECT_TRUE(tester.ContainsEntry(kResourceURL, origin));
+ std::string data2("SomeData.wasm");
+ tester.AddEntry(RemoveCodeCacheTester::kJs, kResourceURL, origin, data);
+ tester.AddEntry(RemoveCodeCacheTester::kWebAssembly, kResourceURL, origin,
+ data2);
+ EXPECT_TRUE(
+ tester.ContainsEntry(RemoveCodeCacheTester::kJs, kResourceURL, origin));
EXPECT_EQ(tester.received_data(), data);
+ EXPECT_TRUE(tester.ContainsEntry(RemoveCodeCacheTester::kWebAssembly,
+ kResourceURL, origin));
+ EXPECT_EQ(tester.received_data(), data2);
base::RunLoop run_loop;
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(&ClearCodeCache, partition, &run_loop));
run_loop.Run();
- EXPECT_FALSE(tester.ContainsEntry(kResourceURL, origin));
+ EXPECT_FALSE(
+ tester.ContainsEntry(RemoveCodeCacheTester::kJs, kResourceURL, origin));
+ EXPECT_FALSE(tester.ContainsEntry(RemoveCodeCacheTester::kWebAssembly,
+ kResourceURL, origin));
+
+ // Make sure there isn't a second invalid callback sitting in the queue.
+ // (this used to be a bug).
+ base::RunLoop().RunUntilIdle();
+}
+
+TEST_F(StoragePartitionImplTest, ClearCodeCacheNoIsolatedCodeCache) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitAndDisableFeature(net::features::kIsolatedCodeCache);
+ ASSERT_FALSE(base::FeatureList::IsEnabled(net::features::kIsolatedCodeCache));
+
+ StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
+ BrowserContext::GetDefaultStoragePartition(browser_context()));
+ base::RunLoop().RunUntilIdle();
+ // We should not create GeneratedCodeCacheContext when IsolatedCodeCache
+ // is disabled.
+ EXPECT_EQ(nullptr, partition->GetGeneratedCodeCacheContext());
+
+ base::RunLoop run_loop;
+ // This shouldn't crash.
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(&ClearCodeCache, partition, &run_loop));
+ run_loop.Run();
+}
+
+TEST_F(StoragePartitionImplTest, ClearCodeCacheIncognito) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitAndEnableFeature(net::features::kIsolatedCodeCache);
+ ASSERT_TRUE(base::FeatureList::IsEnabled(net::features::kIsolatedCodeCache));
+
+ browser_context()->set_is_off_the_record(true);
+
+ StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
+ BrowserContext::GetDefaultStoragePartition(browser_context()));
+ base::RunLoop().RunUntilIdle();
+ // We should not create GeneratedCodeCacheContext for off the record mode.
+ EXPECT_EQ(nullptr, partition->GetGeneratedCodeCacheContext());
+
+ base::RunLoop run_loop;
+ // This shouldn't crash.
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(&ClearCodeCache, partition, &run_loop));
+ run_loop.Run();
}
#if BUILDFLAG(ENABLE_PLUGINS)
@@ -1392,8 +1472,9 @@ TEST_F(StoragePartitionImplTest, RemovePluginPrivateDataForOrigin) {
base::RunLoop run_loop;
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(&ClearPluginPrivateData, partition, kOrigin1,
- base::Time(), base::Time::Max(), &run_loop));
+ FROM_HERE,
+ base::BindOnce(&ClearPluginPrivateData, partition, kOrigin1.GetURL(),
+ base::Time(), base::Time::Max(), &run_loop));
run_loop.Run();
// Only Origin1 should be deleted.
diff --git a/chromium/content/browser/streams/stream.cc b/chromium/content/browser/streams/stream.cc
index 8ce10de0d94..a0dcc1c87de 100644
--- a/chromium/content/browser/streams/stream.cc
+++ b/chromium/content/browser/streams/stream.cc
@@ -118,7 +118,8 @@ void Stream::AddData(const char* data, size_t size) {
if (!writer_.get())
return;
- scoped_refptr<net::IOBuffer> io_buffer(new net::IOBuffer(size));
+ scoped_refptr<net::IOBuffer> io_buffer =
+ base::MakeRefCounted<net::IOBuffer>(size);
memcpy(io_buffer->data(), data, size);
AddData(io_buffer, size);
}
diff --git a/chromium/content/browser/streams/stream_context.cc b/chromium/content/browser/streams/stream_context.cc
index 0ab6a2d6f96..9ed67fe1550 100644
--- a/chromium/content/browser/streams/stream_context.cc
+++ b/chromium/content/browser/streams/stream_context.cc
@@ -5,8 +5,10 @@
#include "content/browser/streams/stream_context.h"
#include "base/bind.h"
+#include "base/task/post_task.h"
#include "content/browser/streams/stream_registry.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
using base::UserDataAdapter;
@@ -29,8 +31,8 @@ StreamContext* StreamContext::GetFor(BrowserContext* context) {
std::make_unique<UserDataAdapter<StreamContext>>(stream.get()));
// Check first to avoid memory leak in unittests.
if (BrowserThread::IsThreadInitialized(BrowserThread::IO)) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&StreamContext::InitializeOnIOThread, stream));
}
}
diff --git a/chromium/content/browser/streams/stream_registry.cc b/chromium/content/browser/streams/stream_registry.cc
index ca6baee32f1..a905f484891 100644
--- a/chromium/content/browser/streams/stream_registry.cc
+++ b/chromium/content/browser/streams/stream_registry.cc
@@ -63,7 +63,7 @@ bool StreamRegistry::CloneStream(const GURL& url, const GURL& src_url) {
void StreamRegistry::UnregisterStream(const GURL& url) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- StreamMap::iterator iter = streams_.find(url);
+ auto iter = streams_.find(url);
if (iter == streams_.end())
return;
@@ -83,7 +83,7 @@ bool StreamRegistry::UpdateMemoryUsage(const GURL& url,
size_t increase) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- StreamMap::iterator iter = streams_.find(url);
+ auto iter = streams_.find(url);
// A Stream must be registered with its parent registry to get memory.
if (iter == streams_.end())
return false;
diff --git a/chromium/content/browser/streams/stream_unittest.cc b/chromium/content/browser/streams/stream_unittest.cc
index b6a6be36ad2..e25694479e0 100644
--- a/chromium/content/browser/streams/stream_unittest.cc
+++ b/chromium/content/browser/streams/stream_unittest.cc
@@ -4,8 +4,8 @@
#include <stddef.h>
-#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
+#include "base/test/scoped_task_environment.h"
#include "base/test/test_simple_task_runner.h"
#include "content/browser/streams/stream.h"
#include "content/browser/streams/stream_read_observer.h"
@@ -26,7 +26,8 @@ class StreamTest : public testing::Test {
// Create a new IO buffer of the given |buffer_size| and fill it with random
// data.
scoped_refptr<net::IOBuffer> NewIOBuffer(size_t buffer_size) {
- scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(buffer_size));
+ scoped_refptr<net::IOBuffer> buffer =
+ base::MakeRefCounted<net::IOBuffer>(buffer_size);
char *bufferp = buffer->data();
for (size_t i = 0; i < buffer_size; i++)
bufferp[i] = (i + producing_seed_key_) % (1 << sizeof(char));
@@ -35,7 +36,7 @@ class StreamTest : public testing::Test {
}
protected:
- base::MessageLoop message_loop_;
+ base::test::ScopedTaskEnvironment task_environment_;
std::unique_ptr<StreamRegistry> registry_;
private:
@@ -44,12 +45,13 @@ class StreamTest : public testing::Test {
class TestStreamReader : public StreamReadObserver {
public:
- TestStreamReader() : buffer_(new net::GrowableIOBuffer()) {}
+ TestStreamReader() : buffer_(base::MakeRefCounted<net::GrowableIOBuffer>()) {}
~TestStreamReader() override {}
void Read(Stream* stream) {
const size_t kBufferSize = 32768;
- scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize));
+ scoped_refptr<net::IOBuffer> buffer =
+ base::MakeRefCounted<net::IOBuffer>(kBufferSize);
int bytes_read = 0;
while (true) {
diff --git a/chromium/content/browser/streams/stream_url_request_job_unittest.cc b/chromium/content/browser/streams/stream_url_request_job_unittest.cc
index 82fc52257da..6d3cd75dd3f 100644
--- a/chromium/content/browser/streams/stream_url_request_job_unittest.cc
+++ b/chromium/content/browser/streams/stream_url_request_job_unittest.cc
@@ -4,8 +4,8 @@
#include "content/browser/streams/stream_url_request_job.h"
-#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
+#include "base/test/scoped_task_environment.h"
#include "base/test/test_simple_task_runner.h"
#include "content/browser/streams/stream.h"
#include "content/browser/streams/stream_metadata.h"
@@ -55,7 +55,9 @@ class StreamURLRequestJobTest : public testing::Test {
StreamRegistry* registry_;
};
- StreamURLRequestJobTest() {}
+ StreamURLRequestJobTest()
+ : task_environment_(
+ base::test::ScopedTaskEnvironment::MainThreadType::IO) {}
void SetUp() override {
registry_.reset(new StreamRegistry());
@@ -107,7 +109,7 @@ class StreamURLRequestJobTest : public testing::Test {
}
protected:
- base::MessageLoopForIO message_loop_;
+ base::test::ScopedTaskEnvironment task_environment_;
std::unique_ptr<StreamRegistry> registry_;
net::URLRequestContext url_request_context_;
@@ -120,8 +122,8 @@ TEST_F(StreamURLRequestJobTest, TestGetSimpleDataRequest) {
new Stream(registry_.get(), nullptr, kStreamURL));
stream->OnResponseStarted(*BuildResponseInfo());
- scoped_refptr<net::StringIOBuffer> buffer(
- new net::StringIOBuffer(kTestData1));
+ scoped_refptr<net::StringIOBuffer> buffer =
+ base::MakeRefCounted<net::StringIOBuffer>(kTestData1);
stream->AddData(buffer, buffer->size());
stream->Finalize(net::OK);
@@ -139,8 +141,8 @@ TEST_F(StreamURLRequestJobTest, TestGetLargeStreamRequest) {
for (int i = 0; i < kBufferSize * 5; ++i)
large_data.append(1, static_cast<char>(i % 256));
- scoped_refptr<net::StringIOBuffer> buffer(
- new net::StringIOBuffer(large_data));
+ scoped_refptr<net::StringIOBuffer> buffer =
+ base::MakeRefCounted<net::StringIOBuffer>(large_data);
stream->AddData(buffer, buffer->size());
stream->Finalize(net::OK);
@@ -166,8 +168,8 @@ TEST_F(StreamURLRequestJobTest, TestRangeDataRequest) {
new Stream(registry_.get(), nullptr, kStreamURL));
stream->OnResponseStarted(*BuildResponseInfo());
- scoped_refptr<net::StringIOBuffer> buffer(
- new net::StringIOBuffer(kTestData2));
+ scoped_refptr<net::StringIOBuffer> buffer =
+ base::MakeRefCounted<net::StringIOBuffer>(kTestData2);
stream->AddData(buffer, buffer->size());
stream->Finalize(net::OK);
@@ -183,8 +185,8 @@ TEST_F(StreamURLRequestJobTest, TestInvalidRangeDataRequest) {
scoped_refptr<Stream> stream(
new Stream(registry_.get(), nullptr, kStreamURL));
stream->OnResponseStarted(*BuildResponseInfo());
- scoped_refptr<net::StringIOBuffer> buffer(
- new net::StringIOBuffer(kTestData2));
+ scoped_refptr<net::StringIOBuffer> buffer =
+ base::MakeRefCounted<net::StringIOBuffer>(kTestData2);
stream->AddData(buffer, buffer->size());
stream->Finalize(net::OK);
diff --git a/chromium/content/browser/top_document_isolation_browsertest.cc b/chromium/content/browser/top_document_isolation_browsertest.cc
deleted file mode 100644
index 6f6e7bef494..00000000000
--- a/chromium/content/browser/top_document_isolation_browsertest.cc
+++ /dev/null
@@ -1,616 +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 <string>
-
-#include "base/command_line.h"
-#include "base/test/scoped_feature_list.h"
-#include "content/browser/frame_host/frame_tree_node.h"
-#include "content/browser/web_contents/web_contents_impl.h"
-#include "content/public/common/content_features.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_frame_navigation_observer.h"
-#include "content/public/test/test_navigation_observer.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 "url/gurl.h"
-
-namespace content {
-
-class TopDocumentIsolationTest : public ContentBrowserTest {
- public:
- TopDocumentIsolationTest() {}
-
- protected:
- std::string DepictFrameTree(FrameTreeNode* node) {
- return visualizer_.DepictFrameTree(node);
- }
-
- void SetUp() override {
- scoped_feature_list_.InitAndEnableFeature(features::kTopDocumentIsolation);
- ContentBrowserTest::SetUp();
- }
-
- void SetUpOnMainThread() override {
- host_resolver()->AddRule("*", "127.0.0.1");
- SetupCrossSiteRedirector(embedded_test_server());
- ASSERT_TRUE(embedded_test_server()->Start());
- }
-
- FrameTreeNode* root() {
- return static_cast<WebContentsImpl*>(shell()->web_contents())
- ->GetFrameTree()
- ->root();
- }
-
- void GoBack() {
- TestNavigationObserver back_load_observer(shell()->web_contents());
- shell()->web_contents()->GetController().GoBack();
- back_load_observer.Wait();
- }
-
- Shell* OpenPopup(FrameTreeNode* opener, const std::string& url) {
- GURL gurl =
- opener->current_frame_host()->GetLastCommittedURL().Resolve(url);
- return content::OpenPopup(opener, gurl, "_blank");
- }
-
- void RendererInitiatedNavigateToURL(FrameTreeNode* node, const GURL& url) {
- TestFrameNavigationObserver nav_observer(node);
- ASSERT_TRUE(
- ExecuteScript(node, "window.location.href='" + url.spec() + "'"));
- nav_observer.Wait();
- }
-
- private:
- FrameTreeVisualizer visualizer_;
- base::test::ScopedFeatureList scoped_feature_list_;
-
- DISALLOW_COPY_AND_ASSIGN(TopDocumentIsolationTest);
-};
-
-IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest, SameSiteDeeplyNested) {
- if (content::AreAllSitesIsolatedForTesting())
- return; // Top Document Isolation is disabled in this mode.
-
- GURL main_url(embedded_test_server()->GetURL(
- "a.com", "/cross_site_iframe_factory.html?a(a,a(a,a(a)))"));
-
- NavigateToURL(shell(), main_url);
-
- EXPECT_EQ(
- " Site A\n"
- " |--Site A\n"
- " +--Site A\n"
- " |--Site A\n"
- " +--Site A\n"
- " +--Site A\n"
- "Where A = http://a.com/",
- DepictFrameTree(root()));
-}
-
-IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest, CrossSiteDeeplyNested) {
- if (content::AreAllSitesIsolatedForTesting())
- return; // Top Document Isolation is disabled in this mode.
-
- GURL main_url(embedded_test_server()->GetURL(
- "a.com", "/cross_site_iframe_factory.html?a(b(c(d(b))))"));
-
- NavigateToURL(shell(), main_url);
-
- EXPECT_EQ(
- " Site A ------------ proxies for B\n"
- " +--Site B ------- proxies for A\n"
- " +--Site B -- proxies for A\n"
- " +--Site B -- proxies for A\n"
- " +--Site B -- proxies for A\n"
- "Where A = http://a.com/\n"
- " B = default subframe process",
- DepictFrameTree(root()));
-}
-
-IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest, ReturnToTopSite) {
- if (content::AreAllSitesIsolatedForTesting())
- return; // Top Document Isolation is disabled in this mode.
-
- GURL main_url(embedded_test_server()->GetURL(
- "a.com", "/cross_site_iframe_factory.html?a(b(a(c)))"));
-
- NavigateToURL(shell(), main_url);
-
- EXPECT_EQ(
- " Site A ------------ proxies for B\n"
- " +--Site B ------- proxies for A\n"
- " +--Site A -- proxies for B\n"
- " +--Site B -- proxies for A\n"
- "Where A = http://a.com/\n"
- " B = default subframe process",
- DepictFrameTree(root()));
-}
-
-IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest, NavigateSubframeToTopSite) {
- if (content::AreAllSitesIsolatedForTesting())
- return; // Top Document Isolation is disabled in this mode.
-
- GURL main_url(embedded_test_server()->GetURL(
- "a.com", "/cross_site_iframe_factory.html?a(b(c(d)))"));
-
- NavigateToURL(shell(), main_url);
-
- EXPECT_EQ(
- " Site A ------------ proxies for B\n"
- " +--Site B ------- proxies for A\n"
- " +--Site B -- proxies for A\n"
- " +--Site B -- proxies for A\n"
- "Where A = http://a.com/\n"
- " B = default subframe process",
- DepictFrameTree(root()));
-
- GURL ada_url(embedded_test_server()->GetURL(
- "a.com", "/cross_site_iframe_factory.html?a(d(a))"));
- RendererInitiatedNavigateToURL(root()->child_at(0)->child_at(0), ada_url);
-
- EXPECT_EQ(
- " Site A ------------ proxies for B\n"
- " +--Site B ------- proxies for A\n"
- " +--Site A -- proxies for B\n"
- " +--Site B -- proxies for A\n"
- " +--Site A -- proxies for B\n"
- "Where A = http://a.com/\n"
- " B = default subframe process",
- DepictFrameTree(root()));
-}
-
-IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest, NavigateToSubframeSite) {
- if (content::AreAllSitesIsolatedForTesting())
- return; // Top Document Isolation is disabled in this mode.
-
- GURL ab_url(embedded_test_server()->GetURL(
- "a.com", "/cross_site_iframe_factory.html?a(b)"));
- GURL ba_url(embedded_test_server()->GetURL(
- "b.com", "/cross_site_iframe_factory.html?b(a, c)"));
-
- NavigateToURL(shell(), ab_url);
-
- EXPECT_EQ(
- " Site A ------------ proxies for B\n"
- " +--Site B ------- proxies for A\n"
- "Where A = http://a.com/\n"
- " B = default subframe process",
- DepictFrameTree(root()));
-
- NavigateToURL(shell(), ba_url);
-
- EXPECT_EQ(
- " Site C ------------ proxies for D\n"
- " |--Site D ------- proxies for C\n"
- " +--Site D ------- proxies for C\n"
- "Where C = http://b.com/\n"
- " D = default subframe process",
- DepictFrameTree(root()));
-}
-
-IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest,
- NavigateToSubframeSiteWithPopup) {
- if (content::AreAllSitesIsolatedForTesting())
- return; // Top Document Isolation is disabled in this mode.
-
- // A(B) -> B(A), but while a separate B(A) popup exists.
- GURL ab_url(embedded_test_server()->GetURL(
- "a.com", "/cross_site_iframe_factory.html?a(b)"));
-
- NavigateToURL(shell(), ab_url);
-
- EXPECT_EQ(
- " Site A ------------ proxies for B\n"
- " +--Site B ------- proxies for A\n"
- "Where A = http://a.com/\n"
- " B = default subframe process",
- DepictFrameTree(root()));
-
- Shell* popup =
- OpenPopup(root()->child_at(0), "/cross_site_iframe_factory.html?b(a)");
- FrameTreeNode* popup_root =
- static_cast<WebContentsImpl*>(popup->web_contents())
- ->GetFrameTree()
- ->root();
-
- // This popup's main frame must stay in the default subframe siteinstance,
- // since its opener (the b.com subframe) may synchronously script it. Note
- // that the popup's subframe is same-site with window.top.opener.top, the
- // a.com main frame of the tab. But --top-document-isolation does not
- // currently place the popup subframe in the a.com process in this case.
- EXPECT_EQ(
- " Site B\n"
- " +--Site B\n"
- "Where B = default subframe process",
- DepictFrameTree(popup_root));
-
- GURL ba_url(embedded_test_server()->GetURL(
- "b.com", "/cross_site_iframe_factory.html?b(a, c)"));
- EXPECT_TRUE(NavigateToURLInSameBrowsingInstance(shell(), ba_url));
-
- // This navigation destroys the popup's opener, so we allow the main frame to
- // commit in a top level process for b.com, in spite of the b.com popup in the
- // default subframe process.
- EXPECT_EQ(
- " Site C ------------ proxies for B\n"
- " |--Site B ------- proxies for C\n"
- " +--Site B ------- proxies for C\n"
- "Where B = default subframe process\n"
- " C = http://b.com/",
- DepictFrameTree(root()));
- EXPECT_EQ(
- " Site B\n"
- " +--Site B\n"
- "Where B = default subframe process",
- DepictFrameTree(popup_root));
-
- // Navigate the popup to a new site.
- GURL c_url(embedded_test_server()->GetURL(
- "c.com", "/cross_site_iframe_factory.html?c(c, c, c, c)"));
- EXPECT_TRUE(NavigateToURLInSameBrowsingInstance(popup, c_url));
- EXPECT_EQ(
- " Site D ------------ proxies for B\n"
- " |--Site D ------- proxies for B\n"
- " |--Site D ------- proxies for B\n"
- " |--Site D ------- proxies for B\n"
- " +--Site D ------- proxies for B\n"
- "Where B = default subframe process\n"
- " D = http://c.com/",
- DepictFrameTree(popup_root));
- EXPECT_TRUE(NavigateToURLInSameBrowsingInstance(shell(), c_url));
- EXPECT_EQ(
- " Site D\n"
- " |--Site D\n"
- " |--Site D\n"
- " |--Site D\n"
- " +--Site D\n"
- "Where D = http://c.com/",
- DepictFrameTree(popup_root));
- EXPECT_EQ(
- " Site D\n"
- " |--Site D\n"
- " |--Site D\n"
- " |--Site D\n"
- " +--Site D\n"
- "Where D = http://c.com/",
- DepictFrameTree(root()));
-}
-
-IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest,
- NavigateToSubframeSiteWithPopup2) {
- if (content::AreAllSitesIsolatedForTesting())
- return; // Top Document Isolation is disabled in this mode.
-
- // A(B, C) -> C(A, B), but while a separate C(A) popup exists.
- //
- // This test is constructed so that c.com is the second site to commit in the
- // default subframe SiteInstance, so the default subframe SiteInstance does
- // not have a "c.com" as the value of GetSiteURL().
- GURL abb_url(embedded_test_server()->GetURL(
- "a.com", "/cross_site_iframe_factory.html?a(b, b)"));
-
- NavigateToURL(shell(), abb_url);
-
- EXPECT_EQ(
- " Site A ------------ proxies for B\n"
- " |--Site B ------- proxies for A\n"
- " +--Site B ------- proxies for A\n"
- "Where A = http://a.com/\n"
- " B = default subframe process",
- DepictFrameTree(root()));
-
- // A(B, B) -> A(B, C)
- GURL c_url(embedded_test_server()->GetURL(
- "c.com", "/cross_site_iframe_factory.html?c"));
- NavigateFrameToURL(root()->child_at(1), c_url);
-
- EXPECT_EQ(
- " Site A ------------ proxies for B\n"
- " |--Site B ------- proxies for A\n"
- " +--Site B ------- proxies for A\n"
- "Where A = http://a.com/\n"
- " B = default subframe process",
- DepictFrameTree(root()));
-
- // This test exercises what happens when the SiteURL of the default subframe
- // siteinstance doesn't match the subframe site.
- EXPECT_NE("c.com", root()
- ->child_at(1)
- ->current_frame_host()
- ->GetSiteInstance()
- ->GetSiteURL()
- .host());
-
- // Subframe C creates C(A) popup.
- Shell* popup =
- OpenPopup(root()->child_at(1), "/cross_site_iframe_factory.html?c(a)");
-
- FrameTreeNode* popup_root =
- static_cast<WebContentsImpl*>(popup->web_contents())
- ->GetFrameTree()
- ->root();
-
- // The popup must stay with its opener, in the default subframe process.
- EXPECT_EQ(
- " Site B\n"
- " +--Site B\n"
- "Where B = default subframe process",
- DepictFrameTree(popup_root));
-
- GURL cab_url(embedded_test_server()->GetURL(
- "c.com", "/cross_site_iframe_factory.html?c(a, b)"));
- {
- RenderFrameDeletedObserver deleted_observer(root()->current_frame_host());
- EXPECT_TRUE(NavigateToURLInSameBrowsingInstance(shell(), cab_url));
- deleted_observer.WaitUntilDeleted();
- }
-
- // This c.com navigation currently breaks out of the default subframe process,
- // even though that process houses a c.com pop-up.
- EXPECT_EQ(
- " Site C ------------ proxies for B\n"
- " |--Site B ------- proxies for C\n"
- " +--Site B ------- proxies for C\n"
- "Where B = default subframe process\n"
- " C = http://c.com/",
- DepictFrameTree(root()));
-
- // c.com popup should remain where it was, in the subframe process.
- EXPECT_EQ(
- " Site B\n"
- " +--Site B\n"
- "Where B = default subframe process",
- DepictFrameTree(popup_root));
- EXPECT_EQ(nullptr, popup_root->opener());
-
- // If we navigate the popup to a new site, it ought to transfer processes.
- GURL d_url(embedded_test_server()->GetURL(
- "d.com", "/cross_site_iframe_factory.html?d"));
- {
- RenderFrameDeletedObserver deleted_observer(
- popup_root->current_frame_host());
- EXPECT_TRUE(NavigateToURLInSameBrowsingInstance(popup, d_url));
- deleted_observer.WaitUntilDeleted();
- }
- EXPECT_EQ(
- " Site D ------------ proxies for B\n"
- "Where B = default subframe process\n"
- " D = http://d.com/",
- DepictFrameTree(popup_root));
- {
- RenderFrameDeletedObserver deleted_observer(root()->current_frame_host());
- EXPECT_TRUE(NavigateToURLInSameBrowsingInstance(shell(), d_url));
- deleted_observer.WaitUntilDeleted();
- }
- EXPECT_EQ(
- " Site D\n"
- "Where D = http://d.com/",
- DepictFrameTree(popup_root));
- EXPECT_EQ(
- " Site D\n"
- "Where D = http://d.com/",
- DepictFrameTree(root()));
-}
-
-IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest, FramesForSitesInHistory) {
- if (content::AreAllSitesIsolatedForTesting())
- return; // Top Document Isolation is disabled in this mode.
-
- // First, do a series of navigations.
- GURL a_url = embedded_test_server()->GetURL(
- "a.com", "/cross_site_iframe_factory.html?a");
- GURL b_url = embedded_test_server()->GetURL(
- "b.com", "/cross_site_iframe_factory.html?b");
- GURL c_url = embedded_test_server()->GetURL(
- "c.com", "/cross_site_iframe_factory.html?c");
-
- // Browser-initiated navigation to a.com.
- NavigateToURL(shell(), a_url);
- EXPECT_EQ(
- " Site A\n"
- "Where A = http://a.com/",
- DepictFrameTree(root()));
-
- // Browser-initiated navigation to b.com.
- {
- // For any cross-process navigations, we must wait for the old RenderFrame
- // to be deleted before calling DepictFrameTree, or else there's a chance
- // the old SiteInstance could be listed while pending deletion.
- RenderFrameDeletedObserver deleted_observer(root()->current_frame_host());
- NavigateToURL(shell(), b_url);
- deleted_observer.WaitUntilDeleted();
- }
- EXPECT_EQ(
- " Site B\n"
- "Where B = http://b.com/",
- DepictFrameTree(root()));
-
- // Renderer-initiated navigation back to a.com. This shouldn't swap processes.
- RendererInitiatedNavigateToURL(root(), a_url);
- EXPECT_EQ(
- " Site B\n"
- "Where B = http://b.com/",
- DepictFrameTree(root()));
-
- // Browser-initiated navigation to c.com.
- {
- RenderFrameDeletedObserver deleted_observer(root()->current_frame_host());
- NavigateToURL(shell(), c_url);
- deleted_observer.WaitUntilDeleted();
- }
- EXPECT_EQ(
- " Site C\n"
- "Where C = http://c.com/",
- DepictFrameTree(root()));
-
- // Now, navigate to a fourth site with iframes to the sites in the history.
- {
- RenderFrameDeletedObserver deleted_observer(root()->current_frame_host());
- NavigateToURL(shell(),
- embedded_test_server()->GetURL(
- "d.com", "/cross_site_iframe_factory.html?d(a,b,c)"));
- deleted_observer.WaitUntilDeleted();
- }
-
- EXPECT_EQ(
- " Site D ------------ proxies for E\n"
- " |--Site E ------- proxies for D\n"
- " |--Site E ------- proxies for D\n"
- " +--Site E ------- proxies for D\n"
- "Where D = http://d.com/\n"
- " E = default subframe process",
- DepictFrameTree(root()));
-
- // Now try going back.
- {
- RenderFrameDeletedObserver deleted_observer(root()->current_frame_host());
- GoBack();
- deleted_observer.WaitUntilDeleted();
- }
- EXPECT_EQ(
- " Site C\n"
- "Where C = http://c.com/",
- DepictFrameTree(root()));
- {
- RenderFrameDeletedObserver deleted_observer(root()->current_frame_host());
- GoBack();
- deleted_observer.WaitUntilDeleted();
- }
- EXPECT_EQ(
- " Site B\n"
- "Where B = http://b.com/",
- DepictFrameTree(root()));
- GoBack();
- EXPECT_EQ(
- " Site B\n"
- "Where B = http://b.com/",
- DepictFrameTree(root()));
- {
- RenderFrameDeletedObserver deleted_observer(root()->current_frame_host());
- GoBack();
- deleted_observer.WaitUntilDeleted();
- }
- EXPECT_EQ(
- " Site A\n"
- "Where A = http://a.com/",
- DepictFrameTree(root()));
-}
-
-IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest, CrossSiteAtLevelTwo) {
- if (content::AreAllSitesIsolatedForTesting())
- return; // Top Document Isolation is disabled in this mode.
-
- GURL main_url(embedded_test_server()->GetURL(
- "a.com", "/cross_site_iframe_factory.html?a(a(b, a))"));
-
- NavigateToURL(shell(), main_url);
-
- EXPECT_EQ(
- " Site A ------------ proxies for B\n"
- " +--Site A ------- proxies for B\n"
- " |--Site B -- proxies for A\n"
- " +--Site A -- proxies for B\n"
- "Where A = http://a.com/\n"
- " B = default subframe process",
- DepictFrameTree(root()));
-
- GURL c_url(embedded_test_server()->GetURL(
- "c.com", "/cross_site_iframe_factory.html?c"));
- NavigateFrameToURL(root()->child_at(0)->child_at(1), c_url);
-
- // This navigation should complete in the default subframe siteinstance.
- EXPECT_EQ(
- " Site A ------------ proxies for B\n"
- " +--Site A ------- proxies for B\n"
- " |--Site B -- proxies for A\n"
- " +--Site B -- proxies for A\n"
- "Where A = http://a.com/\n"
- " B = default subframe process",
- DepictFrameTree(root()));
-}
-
-IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest, PopupAndRedirection) {
- if (content::AreAllSitesIsolatedForTesting())
- return; // Top Document Isolation is disabled in this mode.
-
- GURL main_url(embedded_test_server()->GetURL(
- "page.com", "/cross_site_iframe_factory.html?page(adnetwork)"));
-
- // User opens page on page.com which contains a subframe from adnetwork.com.
- NavigateToURL(shell(), main_url);
-
- EXPECT_EQ(
- " Site A ------------ proxies for B\n"
- " +--Site B ------- proxies for A\n"
- "Where A = http://page.com/\n"
- " B = default subframe process",
- DepictFrameTree(root()));
-
- GURL ad_url(embedded_test_server()->GetURL(
- "ad.com", "/cross_site_iframe_factory.html?ad"));
-
- // adnetwork.com retrieves an ad from advertiser (ad.com) and redirects the
- // subframe to ad.com.
- RendererInitiatedNavigateToURL(root()->child_at(0), ad_url);
-
- // The subframe still uses the default subframe SiteInstance after navigation.
- EXPECT_EQ(
- " Site A ------------ proxies for B\n"
- " +--Site B ------- proxies for A\n"
- "Where A = http://page.com/\n"
- " B = default subframe process",
- DepictFrameTree(root()));
-
- // User clicks the ad in the subframe, which opens a popup on the ad
- // network's domain.
- GURL popup_url(embedded_test_server()->GetURL(
- "adnetwork.com", "/cross_site_iframe_factory.html?adnetwork"));
- Shell* popup = OpenPopup(root()->child_at(0), popup_url.spec());
-
- FrameTreeNode* popup_root =
- static_cast<WebContentsImpl*>(popup->web_contents())
- ->GetFrameTree()
- ->root();
-
- // It's ok for the popup to break out of the subframe process because it's
- // currently cross-site from its opener frame.
- EXPECT_EQ(
- " Site C ------------ proxies for B\n"
- "Where B = default subframe process\n"
- " C = http://adnetwork.com/",
- DepictFrameTree(popup_root));
-
- EXPECT_EQ(
- " Site A ------------ proxies for B C\n"
- " +--Site B ------- proxies for A C\n"
- "Where A = http://page.com/\n"
- " B = default subframe process\n"
- " C = http://adnetwork.com/",
- DepictFrameTree(root()));
-
- // The popup redirects itself to the advertiser's website (ad.com).
- RenderFrameDeletedObserver deleted_observer(popup_root->current_frame_host());
- RendererInitiatedNavigateToURL(popup_root, ad_url);
- deleted_observer.WaitUntilDeleted();
-
- // This must join its same-site opener, in the default subframe SiteInstance.
- EXPECT_EQ(
- " Site A ------------ proxies for B\n"
- " +--Site B ------- proxies for A\n"
- "Where A = http://page.com/\n"
- " B = default subframe process",
- DepictFrameTree(root()));
- EXPECT_EQ(
- " Site B\n"
- "Where B = default subframe process",
- DepictFrameTree(popup_root));
-}
-
-} // namespace content
diff --git a/chromium/content/browser/tracing/background_startup_tracing_observer.cc b/chromium/content/browser/tracing/background_startup_tracing_observer.cc
index 307e5e5f44e..da485b3d1a5 100644
--- a/chromium/content/browser/tracing/background_startup_tracing_observer.cc
+++ b/chromium/content/browser/tracing/background_startup_tracing_observer.cc
@@ -4,8 +4,10 @@
#include "content/browser/tracing/background_startup_tracing_observer.h"
+#include "base/task/post_task.h"
#include "components/tracing/common/trace_startup_config.h"
#include "content/browser/tracing/background_tracing_rule.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
namespace content {
@@ -63,8 +65,8 @@ void BackgroundStartupTracingObserver::OnScenarioActivated(
const BackgroundTracingRule* startup_rule = FindStartupRuleInConfig(*config);
DCHECK(startup_rule);
// Post task to avoid reentrancy.
- content::BrowserThread::PostTask(
- content::BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {content::BrowserThread::UI},
base::BindOnce(
&BackgroundTracingManagerImpl::OnRuleTriggered,
base::Unretained(BackgroundTracingManagerImpl::GetInstance()),
diff --git a/chromium/content/browser/tracing/background_tracing_config_unittest.cc b/chromium/content/browser/tracing/background_tracing_config_unittest.cc
index 12de19fa40d..3d2520c42e9 100644
--- a/chromium/content/browser/tracing/background_tracing_config_unittest.cc
+++ b/chromium/content/browser/tracing/background_tracing_config_unittest.cc
@@ -6,7 +6,7 @@
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
-#include "base/message_loop/message_loop.h"
+#include "base/test/scoped_task_environment.h"
#include "base/values.h"
#include "content/browser/tracing/background_tracing_config_impl.h"
#include "content/browser/tracing/background_tracing_rule.h"
@@ -18,10 +18,11 @@ namespace content {
class BackgroundTracingConfigTest : public testing::Test {
public:
BackgroundTracingConfigTest()
- : ui_thread_(BrowserThread::UI, &message_loop_) {}
+ : ui_thread_(BrowserThread::UI,
+ task_environment_.GetMainThreadTaskRunner()) {}
protected:
- base::MessageLoop message_loop_;
+ base::test::ScopedTaskEnvironment task_environment_;
TestBrowserThread ui_thread_;
};
diff --git a/chromium/content/browser/tracing/background_tracing_manager_browsertest.cc b/chromium/content/browser/tracing/background_tracing_manager_browsertest.cc
index cea17d06e49..9dd2cb9c00f 100644
--- a/chromium/content/browser/tracing/background_tracing_manager_browsertest.cc
+++ b/chromium/content/browser/tracing/background_tracing_manager_browsertest.cc
@@ -15,10 +15,12 @@
#include "base/metrics/histogram_macros.h"
#include "base/run_loop.h"
#include "base/strings/pattern.h"
+#include "base/task/post_task.h"
#include "base/trace_event/trace_event.h"
#include "content/browser/tracing/background_startup_tracing_observer.h"
#include "content/browser/tracing/background_tracing_manager_impl.h"
#include "content/browser/tracing/background_tracing_rule.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/content_browser_test.h"
@@ -152,10 +154,11 @@ class BackgroundTracingManagerUploadConfigWrapper {
EXPECT_EQ(Z_STREAM_END, result);
last_file_contents_.assign(output_str.data(), bytes_written);
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(std::move(done_callback), true));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(std::move(done_callback), true));
CHECK(callback_);
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, std::move(callback_));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ std::move(callback_));
}
void SetUploadCallback(base::OnceClosure callback) {
@@ -583,6 +586,18 @@ IN_PROC_BROWSER_TEST_F(BackgroundTracingManagerBrowserTest,
IN_PROC_BROWSER_TEST_F(BackgroundTracingManagerBrowserTest,
MAYBE_ToggleBlinkScenarios) {
{
+ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+ ASSERT_TRUE(command_line);
+
+ // Early bailout in the case command line arguments have been explicitly set
+ // for the runner.
+ if (!command_line->GetSwitchValueASCII(switches::kEnableBlinkFeatures)
+ .empty() ||
+ !command_line->GetSwitchValueASCII(switches::kDisableBlinkFeatures)
+ .empty()) {
+ return;
+ }
+
SetupBackgroundTracingManager();
base::RunLoop run_loop;
@@ -616,10 +631,6 @@ IN_PROC_BROWSER_TEST_F(BackgroundTracingManagerBrowserTest,
BackgroundTracingManager::NO_DATA_FILTERING);
EXPECT_TRUE(scenario_activated);
-
- base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
- EXPECT_TRUE(command_line);
-
EXPECT_EQ(command_line->GetSwitchValueASCII(switches::kEnableBlinkFeatures),
"FasterWeb1,FasterWeb2");
EXPECT_EQ(
diff --git a/chromium/content/browser/tracing/background_tracing_manager_impl.cc b/chromium/content/browser/tracing/background_tracing_manager_impl.cc
index 444fb27438d..5f488fcd064 100644
--- a/chromium/content/browser/tracing/background_tracing_manager_impl.cc
+++ b/chromium/content/browser/tracing/background_tracing_manager_impl.cc
@@ -13,6 +13,7 @@
#include "base/metrics/histogram_macros.h"
#include "base/rand_util.h"
#include "base/single_thread_task_runner.h"
+#include "base/task/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "base/values.h"
@@ -22,6 +23,7 @@
#include "content/browser/tracing/background_tracing_rule.h"
#include "content/browser/tracing/trace_message_filter.h"
#include "content/browser/tracing/tracing_controller_impl.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/tracing_delegate.h"
@@ -343,8 +345,8 @@ BackgroundTracingManagerImpl::GetRuleAbleToTriggerTracing(
void BackgroundTracingManagerImpl::OnHistogramTrigger(
const std::string& histogram_name) {
if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) {
- content::BrowserThread::PostTask(
- content::BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {content::BrowserThread::UI},
base::BindOnce(&BackgroundTracingManagerImpl::OnHistogramTrigger,
base::Unretained(this), histogram_name));
return;
@@ -363,8 +365,8 @@ void BackgroundTracingManagerImpl::TriggerNamedEvent(
BackgroundTracingManagerImpl::TriggerHandle handle,
StartedFinalizingCallback callback) {
if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) {
- content::BrowserThread::PostTask(
- content::BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {content::BrowserThread::UI},
base::BindOnce(&BackgroundTracingManagerImpl::TriggerNamedEvent,
base::Unretained(this), handle, std::move(callback)));
return;
@@ -532,8 +534,8 @@ void BackgroundTracingManagerImpl::OnFinalizeStarted(
void BackgroundTracingManagerImpl::OnFinalizeComplete(bool success) {
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&BackgroundTracingManagerImpl::OnFinalizeComplete,
base::Unretained(this), success));
return;
@@ -652,7 +654,10 @@ TraceConfig BackgroundTracingManagerImpl::GetConfigForCategoryPreset(
"disabled-by-default-v8.runtime_stats",
record_mode);
case BackgroundTracingConfigImpl::CategoryPreset::BENCHMARK_GPU:
- return TraceConfig("benchmark,toplevel,gpu", record_mode);
+ return TraceConfig(
+ "benchmark,toplevel,gpu,base,mojom,ipc,"
+ "disabled-by-default-system_stats,disabled-by-default-cpu_profiler",
+ record_mode);
case BackgroundTracingConfigImpl::CategoryPreset::BENCHMARK_IPC:
return TraceConfig("benchmark,toplevel,ipc", record_mode);
case BackgroundTracingConfigImpl::CategoryPreset::BENCHMARK_STARTUP: {
@@ -668,8 +673,10 @@ TraceConfig BackgroundTracingManagerImpl::GetConfigForCategoryPreset(
return TraceConfig("blink.console,v8", record_mode);
case BackgroundTracingConfigImpl::CategoryPreset::BENCHMARK_NAVIGATION: {
auto config = TraceConfig(
- "benchmark,toplevel,ipc,base,browser,navigation,omnibox,"
- "safe_browsing,disabled-by-default-system_stats",
+ "benchmark,toplevel,ipc,base,browser,navigation,omnibox,ui,shutdown,"
+ "safe_browsing,task_scheduler,"
+ "disabled-by-default-task_scheduler_diagnostics,"
+ "disabled-by-default-system_stats,disabled-by-default-cpu_profiler",
record_mode);
// Filter only browser process events.
base::trace_event::TraceConfig::ProcessFilterConfig process_config(
diff --git a/chromium/content/browser/tracing/background_tracing_rule.cc b/chromium/content/browser/tracing/background_tracing_rule.cc
index 88b260a0bcf..a262e9000b7 100644
--- a/chromium/content/browser/tracing/background_tracing_rule.cc
+++ b/chromium/content/browser/tracing/background_tracing_rule.cc
@@ -11,10 +11,12 @@
#include "base/metrics/statistics_recorder.h"
#include "base/rand_util.h"
#include "base/strings/safe_sprintf.h"
+#include "base/task/post_task.h"
#include "base/values.h"
#include "components/tracing/common/tracing_messages.h"
#include "content/browser/tracing/background_tracing_manager_impl.h"
#include "content/browser/tracing/trace_message_filter.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
namespace {
@@ -228,8 +230,8 @@ class HistogramRule
if (histogram_name != histogram_name_)
return;
- content::BrowserThread::PostTask(
- content::BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {content::BrowserThread::UI},
base::BindOnce(
&BackgroundTracingManagerImpl::OnRuleTriggered,
base::Unretained(BackgroundTracingManagerImpl::GetInstance()), this,
@@ -237,8 +239,8 @@ class HistogramRule
}
void AbortTracing() {
- content::BrowserThread::PostTask(
- content::BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {content::BrowserThread::UI},
base::BindOnce(
&BackgroundTracingManagerImpl::AbortScenario,
base::Unretained(BackgroundTracingManagerImpl::GetInstance())));
diff --git a/chromium/content/browser/tracing/etw_tracing_agent_win.cc b/chromium/content/browser/tracing/etw_tracing_agent_win.cc
index 94dba186e96..eaeac5f5b3f 100644
--- a/chromium/content/browser/tracing/etw_tracing_agent_win.cc
+++ b/chromium/content/browser/tracing/etw_tracing_agent_win.cc
@@ -13,11 +13,13 @@
#include "base/lazy_instance.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/stringprintf.h"
+#include "base/task/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "base/trace_event/trace_config.h"
#include "base/trace_event/trace_event_impl.h"
#include "base/values.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "services/service_manager/public/cpp/connector.h"
@@ -250,9 +252,9 @@ void EtwTracingAgent::FlushOnThread() {
// Tracing agents, e.g. this, live as long as BrowserMainLoop lives and so
// using base::Unretained here is safe.
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(&EtwTracingAgent::OnStopSystemTracingDone,
- base::Unretained(this), output));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ base::Bind(&EtwTracingAgent::OnStopSystemTracingDone,
+ base::Unretained(this), output));
}
} // namespace content
diff --git a/chromium/content/browser/tracing/trace_message_filter.cc b/chromium/content/browser/tracing/trace_message_filter.cc
index 5716a8bbf7b..dbc18f8a87a 100644
--- a/chromium/content/browser/tracing/trace_message_filter.cc
+++ b/chromium/content/browser/tracing/trace_message_filter.cc
@@ -6,9 +6,11 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
+#include "base/task/post_task.h"
#include "components/tracing/common/tracing_messages.h"
#include "content/browser/tracing/background_tracing_manager_impl.h"
#include "content/common/child_process_host_impl.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
namespace content {
@@ -28,9 +30,9 @@ void TraceMessageFilter::OnChannelConnected(int32_t peer_pid) {
void TraceMessageFilter::OnChannelClosing() {
if (has_child_) {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(&TraceMessageFilter::Unregister,
- base::RetainedRef(this)));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(&TraceMessageFilter::Unregister,
+ base::RetainedRef(this)));
}
}
@@ -51,8 +53,8 @@ bool TraceMessageFilter::OnMessageReceived(const IPC::Message& message) {
void TraceMessageFilter::OnChildSupportsTracing() {
has_child_ = true;
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&TraceMessageFilter::Register, base::RetainedRef(this)));
}
diff --git a/chromium/content/browser/tracing/tracing_controller_browsertest.cc b/chromium/content/browser/tracing/tracing_controller_browsertest.cc
index 40ee6778dd5..24677e65902 100644
--- a/chromium/content/browser/tracing/tracing_controller_browsertest.cc
+++ b/chromium/content/browser/tracing/tracing_controller_browsertest.cc
@@ -11,10 +11,12 @@
#include "base/memory/ref_counted_memory.h"
#include "base/run_loop.h"
#include "base/strings/pattern.h"
+#include "base/task/post_task.h"
#include "base/threading/thread_restrictions.h"
#include "base/values.h"
#include "build/build_config.h"
#include "content/browser/tracing/tracing_controller_impl.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/trace_uploader.h"
#include "content/public/browser/tracing_controller.h"
@@ -81,9 +83,9 @@ class TracingControllerTestEndpoint
scoped_refptr<base::RefCountedString> chunk_ptr =
base::RefCountedString::TakeString(&trace_);
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(done_callback_, std::move(metadata),
- base::RetainedRef(chunk_ptr)));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(done_callback_, std::move(metadata),
+ base::RetainedRef(chunk_ptr)));
}
protected:
diff --git a/chromium/content/browser/tracing/tracing_controller_impl.cc b/chromium/content/browser/tracing/tracing_controller_impl.cc
index 424c2447cc0..f6d26a83c09 100644
--- a/chromium/content/browser/tracing/tracing_controller_impl.cc
+++ b/chromium/content/browser/tracing/tracing_controller_impl.cc
@@ -193,21 +193,11 @@ TracingControllerImpl::GenerateMetadataDict() const {
// OS
#if defined(OS_CHROMEOS)
metadata_dict->SetString("os-name", "CrOS");
- int32_t major_version;
- int32_t minor_version;
- int32_t bugfix_version;
- // OperatingSystemVersion only has a POSIX implementation which returns the
- // wrong versions for CrOS.
- base::SysInfo::OperatingSystemVersionNumbers(&major_version, &minor_version,
- &bugfix_version);
- metadata_dict->SetString(
- "os-version", base::StringPrintf("%d.%d.%d", major_version, minor_version,
- bugfix_version));
#else
metadata_dict->SetString("os-name", base::SysInfo::OperatingSystemName());
+#endif
metadata_dict->SetString("os-version",
base::SysInfo::OperatingSystemVersion());
-#endif
metadata_dict->SetString("os-arch",
base::SysInfo::OperatingSystemArchitecture());
@@ -284,11 +274,10 @@ TracingControllerImpl* TracingControllerImpl::GetInstance() {
return g_tracing_controller;
}
-bool TracingControllerImpl::GetCategories(
- const GetCategoriesDoneCallback& callback) {
+bool TracingControllerImpl::GetCategories(GetCategoriesDoneCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- coordinator_->GetCategories(base::BindRepeating(
- [](const GetCategoriesDoneCallback& callback, bool success,
+ coordinator_->GetCategories(base::BindOnce(
+ [](GetCategoriesDoneCallback callback, bool success,
const std::string& categories) {
const std::vector<std::string> split = base::SplitString(
categories, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
@@ -296,9 +285,9 @@ bool TracingControllerImpl::GetCategories(
for (const auto& category : split) {
category_set.insert(category);
}
- callback.Run(category_set);
+ std::move(callback).Run(category_set);
},
- callback));
+ std::move(callback)));
// TODO(chiniforooshan): The actual success value should be sent by the
// callback asynchronously.
return true;
@@ -306,7 +295,7 @@ bool TracingControllerImpl::GetCategories(
bool TracingControllerImpl::StartTracing(
const base::trace_event::TraceConfig& trace_config,
- const StartTracingDoneCallback& callback) {
+ StartTracingDoneCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
// TODO(chiniforooshan): The actual value should be received by callback and
// this function should return void.
@@ -331,12 +320,12 @@ bool TracingControllerImpl::StartTracing(
std::make_unique<base::trace_event::TraceConfig>(trace_config);
coordinator_->StartTracing(
trace_config.ToString(),
- base::BindRepeating(
- [](const StartTracingDoneCallback& callback, bool success) {
+ base::BindOnce(
+ [](StartTracingDoneCallback callback, bool success) {
if (!callback.is_null())
- callback.Run();
+ std::move(callback).Run();
},
- callback));
+ std::move(callback)));
// TODO(chiniforooshan): The actual success value should be sent by the
// callback asynchronously.
return true;
@@ -379,15 +368,15 @@ bool TracingControllerImpl::StopTracing(
}
bool TracingControllerImpl::GetTraceBufferUsage(
- const GetTraceBufferUsageCallback& callback) {
+ GetTraceBufferUsageCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- coordinator_->RequestBufferUsage(base::BindRepeating(
- [](const GetTraceBufferUsageCallback& callback, bool success,
- float percent_full, uint32_t approximate_count) {
- callback.Run(percent_full, approximate_count);
+ coordinator_->RequestBufferUsage(base::BindOnce(
+ [](GetTraceBufferUsageCallback callback, bool success, float percent_full,
+ uint32_t approximate_count) {
+ std::move(callback).Run(percent_full, approximate_count);
},
- callback));
+ std::move(callback)));
// TODO(chiniforooshan): The actual success value should be sent by the
// callback asynchronously.
return true;
@@ -403,7 +392,7 @@ void TracingControllerImpl::RegisterTracingUI(TracingUI* tracing_ui) {
}
void TracingControllerImpl::UnregisterTracingUI(TracingUI* tracing_ui) {
- std::set<TracingUI*>::iterator it = tracing_uis_.find(tracing_ui);
+ auto it = tracing_uis_.find(tracing_ui);
DCHECK(it != tracing_uis_.end());
tracing_uis_.erase(it);
}
diff --git a/chromium/content/browser/tracing/tracing_controller_impl.h b/chromium/content/browser/tracing/tracing_controller_impl.h
index 356253a594b..cd8cca3e80e 100644
--- a/chromium/content/browser/tracing/tracing_controller_impl.h
+++ b/chromium/content/browser/tracing/tracing_controller_impl.h
@@ -53,14 +53,13 @@ class TracingControllerImpl : public TracingController,
TracingControllerImpl();
// TracingController implementation.
- bool GetCategories(const GetCategoriesDoneCallback& callback) override;
+ bool GetCategories(GetCategoriesDoneCallback callback) override;
bool StartTracing(const base::trace_event::TraceConfig& trace_config,
- const StartTracingDoneCallback& callback) override;
+ StartTracingDoneCallback callback) override;
bool StopTracing(const scoped_refptr<TraceDataEndpoint>& endpoint) override;
bool StopTracing(const scoped_refptr<TraceDataEndpoint>& endpoint,
const std::string& agent_label) override;
- bool GetTraceBufferUsage(
- const GetTraceBufferUsageCallback& callback) override;
+ bool GetTraceBufferUsage(GetTraceBufferUsageCallback callback) override;
bool IsTracing() const override;
void RegisterTracingUI(TracingUI* tracing_ui);
diff --git a/chromium/content/browser/tracing/tracing_controller_impl_data_endpoint.cc b/chromium/content/browser/tracing/tracing_controller_impl_data_endpoint.cc
index 6f3d4facd74..32670ed9627 100644
--- a/chromium/content/browser/tracing/tracing_controller_impl_data_endpoint.cc
+++ b/chromium/content/browser/tracing/tracing_controller_impl_data_endpoint.cc
@@ -12,6 +12,7 @@
#include "base/strings/pattern.h"
#include "base/task/post_task.h"
#include "content/browser/tracing/tracing_controller_impl.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/tracing_controller.h"
#include "third_party/zlib/zlib.h"
@@ -37,8 +38,8 @@ class StringTraceDataEndpoint : public TracingController::TraceDataEndpoint {
scoped_refptr<base::RefCountedString> str =
base::RefCountedString::TakeString(&tmp);
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(completion_callback_, std::move(metadata),
base::RetainedRef(str)));
}
@@ -106,8 +107,8 @@ class FileTraceDataEndpoint : public TracingController::TraceDataEndpoint {
file_ = nullptr;
}
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&FileTraceDataEndpoint::FinalizeOnUIThread, this));
}
diff --git a/chromium/content/browser/tracing/tracing_ui.cc b/chromium/content/browser/tracing/tracing_ui.cc
index dec9a194057..aa9a16917fb 100644
--- a/chromium/content/browser/tracing/tracing_ui.cc
+++ b/chromium/content/browser/tracing/tracing_ui.cc
@@ -46,8 +46,7 @@ namespace {
void OnGotCategories(const WebUIDataSource::GotDataCallback& callback,
const std::set<std::string>& categorySet) {
base::ListValue category_list;
- for (std::set<std::string>::const_iterator it = categorySet.begin();
- it != categorySet.end(); it++) {
+ for (auto it = categorySet.begin(); it != categorySet.end(); it++) {
category_list.AppendString(*it);
}
diff --git a/chromium/content/browser/url_loader_factory_getter.cc b/chromium/content/browser/url_loader_factory_getter.cc
index abcd580a115..972e2652e60 100644
--- a/chromium/content/browser/url_loader_factory_getter.cc
+++ b/chromium/content/browser/url_loader_factory_getter.cc
@@ -11,8 +11,10 @@
#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/lazy_instance.h"
+#include "base/task/post_task.h"
#include "content/browser/storage_partition_impl.h"
#include "content/common/service_worker/service_worker_utils.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/common/content_switches.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
@@ -131,8 +133,8 @@ void URLLoaderFactoryGetter::Initialize(StoragePartitionImpl* partition) {
if (base::FeatureList::IsEnabled(network::features::kNetworkService))
HandleFactoryRequests();
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&URLLoaderFactoryGetter::InitializeOnIOThread, this,
network_factory.PassInterface()));
}
@@ -171,8 +173,8 @@ URLLoaderFactoryGetter::GetURLLoaderFactory() {
// is only needed by unit tests.
if (network_factory_.encountered_error() || !network_factory_.is_bound()) {
network::mojom::URLLoaderFactoryPtr network_factory;
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(
&URLLoaderFactoryGetter::HandleNetworkFactoryRequestOnUIThread,
this, mojo::MakeRequest(&network_factory)));
@@ -213,8 +215,8 @@ void URLLoaderFactoryGetter::SetGetNetworkFactoryCallbackForTesting(
void URLLoaderFactoryGetter::FlushNetworkInterfaceOnIOThreadForTesting() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
base::RunLoop run_loop;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&URLLoaderFactoryGetter::FlushNetworkInterfaceForTesting,
this, run_loop.QuitClosure()));
run_loop.Run();
diff --git a/chromium/content/browser/url_loader_factory_getter.h b/chromium/content/browser/url_loader_factory_getter.h
index dc998f3e6ad..99db7e64592 100644
--- a/chromium/content/browser/url_loader_factory_getter.h
+++ b/chromium/content/browser/url_loader_factory_getter.h
@@ -60,9 +60,16 @@ class URLLoaderFactoryGetter
CONTENT_EXPORT std::unique_ptr<network::SharedURLLoaderFactoryInfo>
GetNetworkFactoryInfo();
- // Called on the IO thread. Will clone the internal factory to the network
- // service which doesn't support auto-reconnect after crash. Useful for
- // one-off requests (e.g. A single navigation) to avoid additional mojo hop.
+ // Called on the IO thread. The factory obtained from here can only be used
+ // from the browser process. It must NOT be sent to a renderer process.
+ //
+ // When NetworkService is enabled, this clones the internal factory to the
+ // network service, which doesn't support auto-reconnect after crash. Useful
+ // for one-off requests (e.g. a single navigation) to avoid an additional Mojo
+ // hop.
+ //
+ // When NetworkService is disabled, this clones the non-NetworkService direct
+ // network factory.
CONTENT_EXPORT void CloneNetworkFactory(
network::mojom::URLLoaderFactoryRequest network_factory_request);
diff --git a/chromium/content/browser/utility_process_host.cc b/chromium/content/browser/utility_process_host.cc
index da650c76a0a..a17f803d6c6 100644
--- a/chromium/content/browser/utility_process_host.cc
+++ b/chromium/content/browser/utility_process_host.cc
@@ -14,6 +14,7 @@
#include "base/i18n/base_i18n_switches.h"
#include "base/sequenced_task_runner.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/task/post_task.h"
#include "components/network_session_configurator/common/network_switches.h"
#include "content/browser/browser_child_process_host_impl.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
@@ -22,6 +23,7 @@
#include "content/common/child_process_host_impl.h"
#include "content/common/in_process_child_thread_params.h"
#include "content/common/service_manager/child_connection.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/common/content_switches.h"
@@ -34,6 +36,7 @@
#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/features.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"
@@ -59,18 +62,21 @@ class UtilitySandboxedProcessLauncherDelegate
public:
UtilitySandboxedProcessLauncherDelegate(
service_manager::SandboxType sandbox_type,
- const base::EnvironmentMap& env)
+ const base::EnvironmentMap& env,
+ const base::CommandLine& cmd_line)
:
#if defined(OS_POSIX)
env_(env),
#endif
- sandbox_type_(sandbox_type) {
+ sandbox_type_(sandbox_type),
+ cmd_line_(cmd_line) {
#if DCHECK_IS_ON()
bool supported_sandbox_type =
sandbox_type_ == service_manager::SANDBOX_TYPE_NO_SANDBOX ||
#if defined(OS_WIN)
sandbox_type_ ==
service_manager::SANDBOX_TYPE_NO_SANDBOX_AND_ELEVATED_PRIVILEGES ||
+ sandbox_type_ == service_manager::SANDBOX_TYPE_XRCOMPOSITING ||
#endif
sandbox_type_ == service_manager::SANDBOX_TYPE_UTILITY ||
sandbox_type_ == service_manager::SANDBOX_TYPE_NETWORK ||
@@ -86,10 +92,27 @@ class UtilitySandboxedProcessLauncherDelegate
~UtilitySandboxedProcessLauncherDelegate() override {}
#if defined(OS_WIN)
+ bool GetAppContainerId(std::string* appcontainer_id) override {
+ if (sandbox_type_ == service_manager::SANDBOX_TYPE_XRCOMPOSITING &&
+ base::FeatureList::IsEnabled(service_manager::features::kXRSandbox)) {
+ *appcontainer_id = base::WideToUTF8(cmd_line_.GetProgram().value());
+ return true;
+ }
+ return false;
+ }
+
bool DisableDefaultPolicy() override {
- // Default policy is disabled for audio process to allow audio drivers
- // to read device properties (https://crbug.com/883326).
- return sandbox_type_ == service_manager::SANDBOX_TYPE_AUDIO;
+ switch (sandbox_type_) {
+ case service_manager::SANDBOX_TYPE_AUDIO:
+ // Default policy is disabled for audio process to allow audio drivers
+ // to read device properties (https://crbug.com/883326).
+ return true;
+ case service_manager::SANDBOX_TYPE_XRCOMPOSITING:
+ return base::FeatureList::IsEnabled(
+ service_manager::features::kXRSandbox);
+ default:
+ return false;
+ }
}
bool ShouldLaunchElevated() override {
@@ -104,6 +127,32 @@ class UtilitySandboxedProcessLauncherDelegate
if (sandbox_type_ == service_manager::SANDBOX_TYPE_AUDIO)
return audio::AudioPreSpawnTarget(policy);
+ if (sandbox_type_ == service_manager::SANDBOX_TYPE_XRCOMPOSITING &&
+ base::FeatureList::IsEnabled(service_manager::features::kXRSandbox)) {
+ // There were issues with some mitigations, causing an inability
+ // to load OpenVR and Oculus APIs.
+ // TODO(https://crbug.com/881919): Try to harden the XR Compositor sandbox
+ // to use mitigations and restrict the token.
+ policy->SetProcessMitigations(0);
+ policy->SetDelayedProcessMitigations(0);
+
+ std::string appcontainer_id;
+ if (!GetAppContainerId(&appcontainer_id)) {
+ return false;
+ }
+ sandbox::ResultCode result =
+ service_manager::SandboxWin::AddAppContainerProfileToPolicy(
+ cmd_line_, sandbox_type_, appcontainer_id, policy);
+ if (result != sandbox::SBOX_ALL_OK) {
+ return false;
+ }
+
+ // Unprotected token/job.
+ policy->SetTokenLevel(sandbox::USER_UNPROTECTED,
+ sandbox::USER_UNPROTECTED);
+ service_manager::SandboxWin::SetJobLevel(
+ cmd_line_, sandbox::JOB_UNPROTECTED, 0, policy);
+ }
return true;
}
#endif // OS_WIN
@@ -132,6 +181,7 @@ class UtilitySandboxedProcessLauncherDelegate
base::EnvironmentMap env_;
#endif // OS_WIN
service_manager::SandboxType sandbox_type_;
+ base::CommandLine cmd_line_;
};
UtilityMainThreadFactoryFunction g_utility_main_thread_factory = nullptr;
@@ -235,7 +285,7 @@ bool UtilityProcessHost::StartProcess() {
// support single process mode this way.
in_process_thread_.reset(
g_utility_main_thread_factory(InProcessChildThreadParams(
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO),
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO}),
process_->GetInProcessMojoInvitation(),
process_->child_connection()->service_token())));
in_process_thread_->Start();
@@ -298,9 +348,11 @@ bool UtilityProcessHost::StartProcess() {
#if defined(OS_MACOSX)
service_manager::switches::kEnableSandboxLogging,
#endif
+ switches::kEnableLogging,
switches::kForceTextDirection,
switches::kForceUIDirection,
switches::kIgnoreCertificateErrors,
+ switches::kLoggingLevel,
switches::kOverrideUseSoftwareGLForTests,
switches::kOverrideEnabledCdmInterfaceVersion,
switches::kProxyServer,
@@ -311,6 +363,8 @@ bool UtilityProcessHost::StartProcess() {
switches::kUseMockCertVerifierForTesting,
switches::kUtilityStartupDialog,
switches::kUseGL,
+ switches::kV,
+ switches::kVModule,
#if defined(OS_ANDROID)
switches::kOrderfileMemoryOptimization,
#endif
@@ -332,6 +386,7 @@ bool UtilityProcessHost::StartProcess() {
switches::kForceWaveAudio,
switches::kTrySupportedChannelLayouts,
switches::kWaveOutBuffers,
+ service_manager::switches::kAddXrAppContainerCaps,
#endif
};
cmd_line->CopySwitchesFrom(browser_command_line, kSwitchNames,
@@ -353,9 +408,10 @@ bool UtilityProcessHost::StartProcess() {
*service_identity_, cmd_line.get());
}
- process_->Launch(std::make_unique<UtilitySandboxedProcessLauncherDelegate>(
- sandbox_type_, env_),
- std::move(cmd_line), true);
+ std::unique_ptr<UtilitySandboxedProcessLauncherDelegate> delegate =
+ std::make_unique<UtilitySandboxedProcessLauncherDelegate>(
+ sandbox_type_, env_, *cmd_line);
+ process_->Launch(std::move(delegate), std::move(cmd_line), true);
}
return true;
diff --git a/chromium/content/browser/utility_process_host_browsertest.cc b/chromium/content/browser/utility_process_host_browsertest.cc
index 670a457de87..efbc93a631d 100644
--- a/chromium/content/browser/utility_process_host_browsertest.cc
+++ b/chromium/content/browser/utility_process_host_browsertest.cc
@@ -5,10 +5,12 @@
#include "base/bind.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/task/post_task.h"
#include "build/build_config.h"
#include "content/browser/utility_process_host.h"
#include "content/browser/utility_process_host_client.h"
#include "content/public/browser/browser_child_process_observer.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/child_process_data.h"
#include "content/public/browser/child_process_termination_info.h"
@@ -45,8 +47,8 @@ class UtilityProcessHostBrowserTest : public BrowserChildProcessObserver,
done_closure_ =
base::BindOnce(&UtilityProcessHostBrowserTest::DoneRunning,
base::Unretained(this), run_loop.QuitClosure(), crash);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&UtilityProcessHostBrowserTest::RunUtilityProcessOnIOThread,
base::Unretained(this), elevated, crash));
@@ -98,8 +100,8 @@ class UtilityProcessHostBrowserTest : public BrowserChildProcessObserver,
// If service crashes then this never gets called.
ASSERT_EQ(false, expect_crash);
ResetServiceOnIOThread();
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- std::move(done_closure_));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ std::move(done_closure_));
}
mojom::TestServicePtr service_;
@@ -138,8 +140,8 @@ class UtilityProcessHostBrowserTest : public BrowserChildProcessObserver,
EXPECT_EQ(kTestProcessName, data.metrics_name);
EXPECT_EQ(false, has_crashed);
has_crashed = true;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&UtilityProcessHostBrowserTest::ResetServiceOnIOThread,
base::Unretained(this)));
std::move(done_closure_).Run();
@@ -160,7 +162,14 @@ IN_PROC_BROWSER_TEST_F(UtilityProcessHostBrowserTest, LaunchProcess) {
RunUtilityProcess(false, false);
}
-IN_PROC_BROWSER_TEST_F(UtilityProcessHostBrowserTest, LaunchProcessAndCrash) {
+// Flaky on Windows, crbug.com/879555
+#if defined(OS_WIN)
+#define MAYBE_LaunchProcessAndCrash DISABLED_LaunchProcessAndCrash
+#else
+#define MAYBE_LaunchProcessAndCrash LaunchProcessAndCrash
+#endif
+IN_PROC_BROWSER_TEST_F(UtilityProcessHostBrowserTest,
+ MAYBE_LaunchProcessAndCrash) {
RunUtilityProcess(false, true);
}
diff --git a/chromium/content/browser/web_contents/aura/overscroll_navigation_overlay.cc b/chromium/content/browser/web_contents/aura/overscroll_navigation_overlay.cc
index dd4de01dc30..ac90d333381 100644
--- a/chromium/content/browser/web_contents/aura/overscroll_navigation_overlay.cc
+++ b/chromium/content/browser/web_contents/aura/overscroll_navigation_overlay.cc
@@ -38,9 +38,7 @@ bool DoesEntryMatchURL(NavigationEntry* entry, const GURL& url) {
if (entry->GetURL() == url)
return true;
const std::vector<GURL>& redirect_chain = entry->GetRedirectChain();
- for (std::vector<GURL>::const_iterator it = redirect_chain.begin();
- it != redirect_chain.end();
- it++) {
+ for (auto it = redirect_chain.begin(); it != redirect_chain.end(); it++) {
if (*it == url)
return true;
}
diff --git a/chromium/content/browser/web_contents/web_contents_android.cc b/chromium/content/browser/web_contents/web_contents_android.cc
index b0d3fea4d0f..7a4d8d9d248 100644
--- a/chromium/content/browser/web_contents/web_contents_android.cc
+++ b/chromium/content/browser/web_contents/web_contents_android.cc
@@ -470,13 +470,23 @@ void WebContentsAndroid::ScrollFocusedEditableNodeIntoView(
frame->GetFrameInputHandler()->ScrollFocusedEditableNodeIntoRect(gfx::Rect());
}
+void WebContentsAndroid::SelectWordAroundCaretAck(bool did_select,
+ int start_adjust,
+ int end_adjust) {
+ RenderWidgetHostViewAndroid* rwhva = GetRenderWidgetHostViewAndroid();
+ if (rwhva)
+ rwhva->SelectWordAroundCaretAck(did_select, start_adjust, end_adjust);
+}
+
void WebContentsAndroid::SelectWordAroundCaret(
JNIEnv* env,
const JavaParamRef<jobject>& obj) {
- RenderViewHost* host = web_contents_->GetRenderViewHost();
- if (!host)
+ RenderFrameHostImpl* frame = web_contents_->GetFocusedFrame();
+ if (!frame)
return;
- host->SelectWordAroundCaret();
+ frame->GetFrameInputHandler()->SelectWordAroundCaret(
+ base::BindOnce(&WebContentsAndroid::SelectWordAroundCaretAck,
+ weak_factory_.GetWeakPtr()));
}
void WebContentsAndroid::AdjustSelectionByCharacterOffset(
diff --git a/chromium/content/browser/web_contents/web_contents_android.h b/chromium/content/browser/web_contents/web_contents_android.h
index 6e55efc61f7..6223f76ee0b 100644
--- a/chromium/content/browser/web_contents/web_contents_android.h
+++ b/chromium/content/browser/web_contents/web_contents_android.h
@@ -265,6 +265,9 @@ class CONTENT_EXPORT WebContentsAndroid
const GURL& url,
const std::vector<SkBitmap>& bitmaps,
const std::vector<gfx::Size>& sizes);
+ void SelectWordAroundCaretAck(bool did_select,
+ int start_adjust,
+ int end_adjust);
WebContentsImpl* web_contents_;
diff --git a/chromium/content/browser/web_contents/web_contents_getter_registry.cc b/chromium/content/browser/web_contents/web_contents_getter_registry.cc
new file mode 100644
index 00000000000..ec363066a5d
--- /dev/null
+++ b/chromium/content/browser/web_contents/web_contents_getter_registry.cc
@@ -0,0 +1,51 @@
+// 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_contents/web_contents_getter_registry.h"
+
+#include "base/no_destructor.h"
+
+namespace content {
+
+using WebContentsGetter = WebContentsGetterRegistry::WebContentsGetter;
+
+// static
+WebContentsGetterRegistry* WebContentsGetterRegistry::GetInstance() {
+ static base::NoDestructor<WebContentsGetterRegistry> instance;
+ return instance.get();
+}
+
+void WebContentsGetterRegistry::Add(
+ const base::UnguessableToken& id,
+ const WebContentsGetter& web_contents_getter) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ bool inserted = (map_.emplace(id, web_contents_getter)).second;
+ CHECK(inserted);
+}
+
+void WebContentsGetterRegistry::Remove(const base::UnguessableToken& id) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ map_.erase(id);
+}
+
+const WebContentsGetter& WebContentsGetterRegistry::Get(
+ const base::UnguessableToken& id) const {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ auto iter = map_.find(id);
+ if (iter == map_.end())
+ return GetNullGetter();
+ return iter->second;
+}
+
+WebContentsGetterRegistry::WebContentsGetterRegistry() = default;
+
+WebContentsGetterRegistry::~WebContentsGetterRegistry() = default;
+
+// static
+const WebContentsGetter& WebContentsGetterRegistry::GetNullGetter() {
+ static const base::NoDestructor<WebContentsGetter> null_getter;
+ return *null_getter;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/web_contents/web_contents_getter_registry.h b/chromium/content/browser/web_contents/web_contents_getter_registry.h
new file mode 100644
index 00000000000..de6ad4491de
--- /dev/null
+++ b/chromium/content/browser/web_contents/web_contents_getter_registry.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_WEB_CONTENTS_WEB_CONTENTS_GETTER_REGISTRY_H_
+#define CONTENT_BROWSER_WEB_CONTENTS_WEB_CONTENTS_GETTER_REGISTRY_H_
+
+#include "base/callback_forward.h"
+#include "base/containers/flat_map.h"
+#include "base/sequence_checker.h"
+#include "base/unguessable_token.h"
+#include "content/public/browser/web_contents.h"
+
+namespace content {
+
+// A global map of UnguessableToken to WebContentsGetter. Unlike most other
+// WebContents related objects, this registry lives and is used only on the IO
+// thread, as it's convenient for the current user of the class
+// (ServiceWorkerProviderHost, which should move to the UI thread eventually).
+// However, the WebContentsGetter callbacks must only be run on the UI thread.
+class WebContentsGetterRegistry {
+ public:
+ using WebContentsGetter = base::RepeatingCallback<WebContents*()>;
+
+ static WebContentsGetterRegistry* GetInstance();
+
+ void Add(const base::UnguessableToken& id,
+ const WebContentsGetter& web_contents_getter);
+ void Remove(const base::UnguessableToken&);
+ // Returns null getter if not found.
+ const WebContentsGetter& Get(const base::UnguessableToken& id) const;
+
+ private:
+ friend class base::NoDestructor<WebContentsGetterRegistry>;
+
+ WebContentsGetterRegistry();
+ ~WebContentsGetterRegistry();
+
+ static const WebContentsGetter& GetNullGetter();
+
+ base::flat_map<base::UnguessableToken, WebContentsGetter> map_;
+
+ SEQUENCE_CHECKER(sequence_checker_);
+ DISALLOW_COPY_AND_ASSIGN(WebContentsGetterRegistry);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_WEB_CONTENTS_WEB_CONTENTS_GETTER_REGISTRY_H_
diff --git a/chromium/content/browser/web_contents/web_contents_impl.cc b/chromium/content/browser/web_contents/web_contents_impl.cc
index 499c8c0a2e8..c9d8ca8da49 100644
--- a/chromium/content/browser/web_contents/web_contents_impl.cc
+++ b/chromium/content/browser/web_contents/web_contents_impl.cc
@@ -22,12 +22,16 @@
#include "base/memory/ref_counted.h"
#include "base/metrics/histogram_macros.h"
#include "base/metrics/user_metrics.h"
+#include "base/no_destructor.h"
#include "base/process/process.h"
#include "base/single_thread_task_runner.h"
+#include "base/stl_util.h"
#include "base/strings/string16.h"
#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/task/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
@@ -39,6 +43,7 @@
#include "content/browser/accessibility/accessibility_tree_formatter_blink.h"
#include "content/browser/accessibility/browser_accessibility_state_impl.h"
#include "content/browser/bad_message.h"
+#include "content/browser/browser_main_loop.h"
#include "content/browser/browser_plugin/browser_plugin_embedder.h"
#include "content/browser/browser_plugin/browser_plugin_guest.h"
#include "content/browser/child_process_security_policy_impl.h"
@@ -93,12 +98,15 @@
#include "content/common/page_state_serialization.h"
#include "content/common/render_message_filter.mojom.h"
#include "content/common/view_messages.h"
+#include "content/common/widget_messages.h"
#include "content/public/browser/ax_event_notification_details.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_plugin_guest_manager.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/download_manager.h"
+#include "content/public/browser/file_select_listener.h"
#include "content/public/browser/focused_node_details.h"
#include "content/public/browser/guest_mode.h"
#include "content/public/browser/invalidate_type.h"
@@ -129,6 +137,7 @@
#include "content/public/common/service_manager_connection.h"
#include "content/public/common/url_utils.h"
#include "content/public/common/web_preferences.h"
+#include "media/base/user_input_monitor.h"
#include "net/base/url_util.h"
#include "net/http/http_cache.h"
#include "net/http/http_transaction_factory.h"
@@ -286,6 +295,50 @@ class CloseDialogCallbackWrapper
CloseCallback callback_;
};
+bool FrameCompareDepth(RenderFrameHostImpl* a, RenderFrameHostImpl* b) {
+ return a->frame_tree_node()->depth() < b->frame_tree_node()->depth();
+}
+
+// TODO(tkent): This will be merged into FileChooserImpl in
+// render_frame_host_impl.cc.
+class ViewFileSelectListener : public FileSelectListener,
+ private WebContentsObserver {
+ public:
+ ViewFileSelectListener(WebContents* web_contents, int request_id)
+ : web_contents_(web_contents), request_id_(request_id) {
+ Observe(web_contents);
+ }
+ ~ViewFileSelectListener() override = default;
+
+ private:
+ // content::FileSelectListener overrides:
+
+ void FileSelected(std::vector<blink::mojom::FileChooserFileInfoPtr> files,
+ blink::mojom::FileChooserParams::Mode mode) override {
+ if (!web_contents_)
+ return;
+ std::vector<base::FilePath> file_path_list;
+ for (const auto& file_info : files) {
+ file_path_list.push_back(file_info->get_native_file()->file_path);
+ }
+ web_contents_->GetRenderViewHost()->DirectoryEnumerationFinished(
+ request_id_, file_path_list);
+ }
+
+ void FileSelectionCanceled() override {
+ if (!web_contents_)
+ return;
+ web_contents_->GetRenderViewHost()->DirectoryEnumerationFinished(
+ request_id_, std::vector<base::FilePath>());
+ }
+
+ // content::WebContentsObserver override:
+ void WebContentsDestroyed() override { web_contents_ = nullptr; }
+
+ WebContents* web_contents_;
+ int request_id_;
+};
+
} // namespace
std::unique_ptr<WebContents> WebContents::Create(
@@ -304,10 +357,8 @@ std::unique_ptr<WebContents> WebContents::CreateWithSessionStorage(
opener = opener_rfh->frame_tree_node();
new_contents->SetOpenerForNewContents(opener, params.opener_suppressed);
- for (SessionStorageNamespaceMap::const_iterator it =
- session_storage_namespace_map.begin();
- it != session_storage_namespace_map.end();
- ++it) {
+ for (auto it = session_storage_namespace_map.begin();
+ it != session_storage_namespace_map.end(); ++it) {
new_contents->GetController()
.SetSessionStorageNamespace(it->first, it->second.get());
}
@@ -625,6 +676,7 @@ WebContentsImpl::~WebContentsImpl() {
}
color_chooser_.reset();
+ find_request_manager_.reset();
NotifyDisconnected();
@@ -1388,6 +1440,10 @@ const std::string& WebContentsImpl::GetEncoding() const {
return canonical_encoding_;
}
+bool WebContentsImpl::WasDiscarded() {
+ return GetFrameTree()->root()->was_discarded();
+}
+
void WebContentsImpl::SetWasDiscarded(bool was_discarded) {
GetFrameTree()->root()->set_was_discarded();
}
@@ -1619,12 +1675,7 @@ void WebContentsImpl::WasShown() {
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);
- }
+ parent->cross_process_frame_connector()->DelegateWasShown();
}
}
@@ -1724,9 +1775,11 @@ bool WebContentsImpl::NeedToFireBeforeUnload() {
true /* check_subframes_only */);
}
-void WebContentsImpl::DispatchBeforeUnload() {
- GetMainFrame()->DispatchBeforeUnload(
- RenderFrameHostImpl::BeforeUnloadType::TAB_CLOSE, false);
+void WebContentsImpl::DispatchBeforeUnload(bool auto_cancel) {
+ auto before_unload_type =
+ auto_cancel ? RenderFrameHostImpl::BeforeUnloadType::DISCARD
+ : RenderFrameHostImpl::BeforeUnloadType::TAB_CLOSE;
+ GetMainFrame()->DispatchBeforeUnload(before_unload_type, false);
}
void WebContentsImpl::AttachToOuterWebContentsFrame(
@@ -2084,6 +2137,32 @@ ukm::SourceId WebContentsImpl::GetUkmSourceIdForLastCommittedSource() const {
return last_committed_source_id_;
}
+void WebContentsImpl::SetTopControlsShownRatio(
+ RenderWidgetHostImpl* render_widget_host,
+ float ratio) {
+ if (!delegate_)
+ return;
+
+ RenderFrameHostImpl* rfh = GetMainFrame();
+ if (!rfh || render_widget_host != rfh->GetRenderWidgetHost())
+ return;
+
+ delegate_->SetTopControlsShownRatio(this, ratio);
+}
+
+bool WebContentsImpl::DoBrowserControlsShrinkRendererSize() const {
+ return delegate_ && delegate_->DoBrowserControlsShrinkRendererSize(this);
+}
+
+int WebContentsImpl::GetTopControlsHeight() const {
+ return delegate_ ? delegate_->GetTopControlsHeight() : 0;
+}
+
+void WebContentsImpl::SetTopControlsGestureScrollInProgress(bool in_progress) {
+ if (delegate_)
+ delegate_->SetTopControlsGestureScrollInProgress(in_progress);
+}
+
void WebContentsImpl::RenderWidgetCreated(
RenderWidgetHostImpl* render_widget_host) {
created_widgets_.insert(render_widget_host);
@@ -2176,7 +2255,7 @@ bool WebContentsImpl::HandleWheelEvent(
// (i.e. control+tab) then the OS's buffered scroll events will come in
// with control key set which isn't what the user wants
if (delegate_ && event.wheel_ticks_y &&
- !ui::WebInputEventTraits::CanCauseScroll(event)) {
+ event.event_action == blink::WebMouseWheelEvent::EventAction::kPageZoom) {
// Count only integer cumulative scrolls as zoom events; this handles
// smooth scroll and regular scroll device behavior.
zoom_scroll_remainder_ += event.wheel_ticks_y;
@@ -2328,8 +2407,7 @@ void WebContentsImpl::ExitFullscreenMode(bool will_cause_resize) {
}
}
- // Clear the current fullscreen frame ID.
- current_fullscreen_frame_tree_node_id_ = RenderFrameHost::kNoFrameTreeNodeId;
+ current_fullscreen_frame_ = nullptr;
for (auto& observer : observers_) {
observer.DidToggleFullscreenModeForTab(IsFullscreenForCurrentTab(),
@@ -2342,75 +2420,59 @@ void WebContentsImpl::ExitFullscreenMode(bool will_cause_resize) {
void WebContentsImpl::FullscreenStateChanged(RenderFrameHost* rfh,
bool is_fullscreen) {
- int frame_tree_node_id = rfh->GetFrameTreeNodeId();
- auto it = fullscreen_frame_tree_nodes_.find(frame_tree_node_id);
- bool changed = false;
+ RenderFrameHostImpl* frame = static_cast<RenderFrameHostImpl*>(rfh);
if (is_fullscreen) {
- // If we are fullscreen then add the FrameTreeNode ID to the set.
- if (it == fullscreen_frame_tree_nodes_.end()) {
- fullscreen_frame_tree_nodes_.insert(frame_tree_node_id);
- changed = true;
- }
- } else {
- FrameTreeNode* ancestor =
- static_cast<RenderFrameHostImpl*>(rfh)->frame_tree_node();
- DCHECK(ancestor);
-
- // If we are not fullscreen then remove this frame and any descendants
- // from the set.
- for (it = fullscreen_frame_tree_nodes_.begin();
- it != fullscreen_frame_tree_nodes_.end();) {
- FrameTreeNode* node = FrameTreeNode::GloballyFindByID(*it);
-
- if (!node || frame_tree_node_id == *it ||
- node->IsDescendantOf(ancestor)) {
- it = fullscreen_frame_tree_nodes_.erase(it);
- changed = true;
- } else {
- ++it;
- }
+ if (!base::ContainsKey(fullscreen_frames_, frame)) {
+ fullscreen_frames_.insert(frame);
+ FullscreenFrameSetUpdated();
}
+ return;
}
- // If we have changed then find the current fullscreen FrameTreeNode
- // and call the observers. If we have exited fullscreen then this
- // will be the last frame that was fullscreen.
- if (changed && fullscreen_frame_tree_nodes_.size() > 0) {
- unsigned int max_depth = 0;
- RenderFrameHost* max_depth_rfh = nullptr;
+ // If |frame| is no longer in fullscreen, remove it and any descendants.
+ // See https://fullscreen.spec.whatwg.org.
+ size_t size_before_deletion = fullscreen_frames_.size();
+ base::EraseIf(fullscreen_frames_, [&](RenderFrameHostImpl* current) {
+ return (current == frame || current->IsDescendantOf(frame));
+ });
- for (auto node_id : fullscreen_frame_tree_nodes_) {
- FrameTreeNode* fullscreen_node = FrameTreeNode::GloballyFindByID(node_id);
- DCHECK(fullscreen_node);
+ if (size_before_deletion != fullscreen_frames_.size())
+ FullscreenFrameSetUpdated();
+}
- if (max_depth_rfh == nullptr || fullscreen_node->depth() > max_depth) {
- max_depth = fullscreen_node->depth();
- max_depth_rfh = fullscreen_node->current_frame_host();
- }
- }
+void WebContentsImpl::FullscreenFrameSetUpdated() {
+ if (fullscreen_frames_.empty()) {
+ current_fullscreen_frame_ = nullptr;
+ return;
+ }
- // If we have already notified observers about this frame then we should not
- // fire the observers again.
- DCHECK(max_depth_rfh);
- if (max_depth_rfh->GetFrameTreeNodeId() ==
- current_fullscreen_frame_tree_node_id_)
- return;
+ // Find the current fullscreen frame and call the observers.
+ // If frame A is fullscreen, then frame B goes into inner fullscreen, then B
+ // exits fullscreen - that will result in A being fullscreen.
+ RenderFrameHostImpl* new_fullscreen_frame = *std::max_element(
+ fullscreen_frames_.begin(), fullscreen_frames_.end(), FrameCompareDepth);
- current_fullscreen_frame_tree_node_id_ =
- max_depth_rfh->GetFrameTreeNodeId();
+ // If we have already notified observers about this frame then we should not
+ // fire the observers again.
+ if (new_fullscreen_frame == current_fullscreen_frame_)
+ return;
+ current_fullscreen_frame_ = new_fullscreen_frame;
- for (auto& observer : observers_)
- observer.DidAcquireFullscreen(max_depth_rfh);
+ for (auto& observer : observers_)
+ observer.DidAcquireFullscreen(new_fullscreen_frame);
- if (display_cutout_host_impl_)
- display_cutout_host_impl_->DidAcquireFullscreen(max_depth_rfh);
- } else if (fullscreen_frame_tree_nodes_.size() == 0) {
- current_fullscreen_frame_tree_node_id_ =
- RenderFrameHost::kNoFrameTreeNodeId;
- }
+ if (display_cutout_host_impl_)
+ display_cutout_host_impl_->DidAcquireFullscreen(new_fullscreen_frame);
}
+#if defined(OS_ANDROID)
+void WebContentsImpl::UpdateUserGestureCarryoverInfo() {
+ if (delegate_)
+ delegate_->UpdateUserGestureCarryoverInfo(this);
+}
+#endif
+
bool WebContentsImpl::IsFullscreenForCurrentTab() const {
return delegate_ ? delegate_->IsFullscreenForTabOrPending(this) : false;
}
@@ -2489,15 +2551,18 @@ bool WebContentsImpl::HasMouseLock(RenderWidgetHostImpl* render_widget_host) {
// To verify if the mouse is locked, the mouse_lock_widget_ needs to be
// assigned to the widget that requested the mouse lock, and the top-level
// platform RenderWidgetHostView needs to hold the mouse lock from the OS.
- return mouse_lock_widget_ == render_widget_host &&
- GetTopLevelRenderWidgetHostView()->IsMouseLocked();
+ auto* widget_host = GetTopLevelRenderWidgetHostView();
+ return mouse_lock_widget_ == render_widget_host && widget_host &&
+ widget_host->IsMouseLocked();
}
RenderWidgetHostImpl* WebContentsImpl::GetMouseLockWidget() {
- if (GetTopLevelRenderWidgetHostView()->IsMouseLocked() ||
+ auto* widget_host = GetTopLevelRenderWidgetHostView();
+ if ((widget_host && widget_host->IsMouseLocked()) ||
(GetFullscreenRenderWidgetHostView() &&
- GetFullscreenRenderWidgetHostView()->IsMouseLocked()))
+ GetFullscreenRenderWidgetHostView()->IsMouseLocked())) {
return mouse_lock_widget_;
+ }
return nullptr;
}
@@ -2646,9 +2711,11 @@ void WebContentsImpl::CreateNewWindow(
new_contents = base::WrapUnique(
GetBrowserPluginGuest()->CreateNewGuestWindow(create_params));
}
- WebContentsImpl* raw_new_contents =
- static_cast<WebContentsImpl*>(new_contents.get());
- raw_new_contents->GetController().SetSessionStorageNamespace(
+ auto owning_contents_impl =
+ base::WrapUnique(static_cast<WebContentsImpl*>(new_contents.release()));
+ auto* new_contents_impl = owning_contents_impl.get();
+
+ new_contents_impl->GetController().SetSessionStorageNamespace(
partition_id, session_storage_namespace);
// If the new frame has a name, make sure any SiteInstances that can find
@@ -2656,18 +2723,18 @@ void WebContentsImpl::CreateNewWindow(
// SetSessionStorageNamespace, since this calls CreateRenderView, which uses
// GetSessionStorageNamespace.
if (!params.frame_name.empty())
- raw_new_contents->GetRenderManager()->CreateProxiesForNewNamedFrame();
+ new_contents_impl->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 = raw_new_contents->view_.get();
+ WebContentsView* new_view = new_contents_impl->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.
new_view->CreateViewForWidget(
- new_contents->GetRenderViewHost()->GetWidget(), false);
+ new_contents_impl->GetRenderViewHost()->GetWidget(), false);
}
// Save the created window associated with the route so we can show it
// later.
@@ -2676,20 +2743,19 @@ void WebContentsImpl::CreateNewWindow(
// FrameTreeNode id instead of the routing id of the Widget for the main
// frame. https://crbug.com/545684
DCHECK_NE(MSG_ROUTING_NONE, main_frame_widget_route_id);
- pending_contents_[GlobalRoutingID(render_process_id,
- main_frame_widget_route_id)] =
- std::move(new_contents);
- AddDestructionObserver(raw_new_contents);
+ GlobalRoutingID id(render_process_id, main_frame_widget_route_id);
+ pending_contents_[id] = std::move(owning_contents_impl);
+ AddDestructionObserver(new_contents_impl);
}
if (delegate_) {
delegate_->WebContentsCreated(this, render_process_id,
opener->GetRoutingID(), params.frame_name,
- params.target_url, raw_new_contents);
+ params.target_url, new_contents_impl);
}
for (auto& observer : observers_) {
- observer.DidOpenRequestedURL(raw_new_contents, opener, params.target_url,
+ observer.DidOpenRequestedURL(new_contents_impl, opener, params.target_url,
params.referrer, params.disposition,
ui::PAGE_TRANSITION_LINK,
false, // started_from_context_menu
@@ -2705,16 +2771,17 @@ void WebContentsImpl::CreateNewWindow(
// 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_impl->weak_factory_.GetWeakPtr();
- delegate_->AddNewContents(this, std::move(new_contents),
+ gfx::Rect initial_rect; // Report an empty initial rect.
+ delegate_->AddNewContents(this, std::move(owning_contents_impl),
params.disposition, initial_rect,
params.mimic_user_gesture, &was_blocked);
+ // The delegate may delete |new_contents_impl| during AddNewContents().
if (!weak_new_contents)
- return; // The delegate deleted |new_contents| during AddNewContents().
+ return;
}
if (!was_blocked) {
@@ -2726,37 +2793,34 @@ void WebContentsImpl::CreateNewWindow(
if (delegate_ && !is_guest &&
!delegate_->ShouldResumeRequestsForCreatedWindow()) {
- DCHECK(weak_new_contents);
// We are in asynchronous add new contents path, delay opening url
- weak_new_contents->delayed_open_url_params_.reset(
+ new_contents_impl->delayed_open_url_params_.reset(
new OpenURLParams(open_params));
} else {
- weak_new_contents->OpenURL(open_params);
+ new_contents_impl->OpenURL(open_params);
}
}
}
}
void WebContentsImpl::CreateNewWidget(int32_t render_process_id,
- int32_t route_id,
- mojom::WidgetPtr widget,
- blink::WebPopupType popup_type) {
- CreateNewWidget(render_process_id, route_id, false, std::move(widget),
- popup_type);
+ int32_t widget_route_id,
+ mojom::WidgetPtr widget) {
+ CreateNewWidget(render_process_id, widget_route_id, /*is_fullscreen=*/false,
+ std::move(widget));
}
void WebContentsImpl::CreateNewFullscreenWidget(int32_t render_process_id,
- int32_t route_id,
+ int32_t widget_route_id,
mojom::WidgetPtr widget) {
- CreateNewWidget(render_process_id, route_id, true, std::move(widget),
- blink::kWebPopupTypeNone);
+ CreateNewWidget(render_process_id, widget_route_id, /*is_fullscreen=*/true,
+ std::move(widget));
}
void WebContentsImpl::CreateNewWidget(int32_t render_process_id,
int32_t route_id,
bool is_fullscreen,
- mojom::WidgetPtr widget,
- blink::WebPopupType popup_type) {
+ mojom::WidgetPtr widget) {
RenderProcessHost* process = RenderProcessHost::FromID(render_process_id);
// A message to create a new widget can only come from an active process for
// this WebContentsImpl instance. If any other process sends the request,
@@ -2771,13 +2835,13 @@ void WebContentsImpl::CreateNewWidget(int32_t render_process_id,
RenderWidgetHostViewBase* widget_view =
static_cast<RenderWidgetHostViewBase*>(
- view_->CreateViewForPopupWidget(widget_host));
+ view_->CreateViewForChildWidget(widget_host));
if (!widget_view)
return;
- if (!is_fullscreen) {
- // Popups should not get activated.
- widget_view->SetPopupType(popup_type);
- }
+ // Fullscreen child widgets are frames, other child widgets are popups, and
+ // popups should not get activated.
+ if (!is_fullscreen)
+ widget_view->SetWidgetType(WidgetType::kPopup);
// Save the created widget associated with the route so we can show it later.
pending_widget_views_[GlobalRoutingID(render_process_id, route_id)] =
widget_view;
@@ -2788,40 +2852,57 @@ void WebContentsImpl::ShowCreatedWindow(int process_id,
WindowOpenDisposition disposition,
const gfx::Rect& initial_rect,
bool user_gesture) {
- std::unique_ptr<WebContents> popup =
+ // This method is the renderer requesting an existing top level window to
+ // show a new top level window that the renderer created. Each top level
+ // window is associated with a WebContents. In this case it was created
+ // earlier but showing it was deferred until the renderer requested for it
+ // to be shown. We find that previously created WebContents here.
+ // TODO(danakj): Why do we defer this show step until the renderer asks for it
+ // when it will always do so. What needs to happen in the renderer before we
+ // reach here?
+ std::unique_ptr<WebContentsImpl> owned_created =
GetCreatedWindow(process_id, main_frame_widget_route_id);
- if (popup) {
- WebContentsImpl* raw_popup = static_cast<WebContentsImpl*>(popup.get());
- WebContentsDelegate* delegate = GetDelegate();
- raw_popup->is_resume_pending_ = true;
- if (!delegate || delegate->ShouldResumeRequestsForCreatedWindow())
- raw_popup->ResumeLoadingCreatedWebContents();
-
- base::WeakPtr<WebContentsImpl> weak_popup =
- raw_popup->weak_factory_.GetWeakPtr();
- if (delegate) {
- delegate->AddNewContents(this, std::move(popup), disposition,
- initial_rect, user_gesture, nullptr);
- if (!weak_popup)
- return; // The delegate deleted |popup| during AddNewContents().
- }
+ WebContentsImpl* created = owned_created.get();
+ // The browser may have rejected the request to make a new window, or the
+ // renderer could be sending an invalid route id. Ignore the request then.
+ if (!created)
+ return;
- RenderWidgetHostImpl* rwh =
- weak_popup->GetMainFrame()->GetRenderWidgetHost();
- DCHECK_EQ(main_frame_widget_route_id, rwh->GetRoutingID());
- rwh->Send(new ViewMsg_SetBounds_ACK(rwh->GetRoutingID()));
+ // This uses the delegate for the WebContents where the window was created
+ // from, to control how to show the newly created window.
+ WebContentsDelegate* delegate = GetDelegate();
+
+ // The delegate can be null in tests, so we must check for it :(.
+ if (delegate) {
+ // Mark the web contents as pending resume, then immediately do
+ // the resume if the delegate wants it.
+ created->is_resume_pending_ = true;
+ if (delegate->ShouldResumeRequestsForCreatedWindow())
+ created->ResumeLoadingCreatedWebContents();
+
+ base::WeakPtr<WebContentsImpl> weak_created =
+ created->weak_factory_.GetWeakPtr();
+ delegate->AddNewContents(this, std::move(owned_created), disposition,
+ initial_rect, user_gesture, nullptr);
+ // The delegate may delete |created| during AddNewContents().
+ if (!weak_created)
+ return;
}
+
+ RenderWidgetHostImpl* rwh = created->GetMainFrame()->GetRenderWidgetHost();
+ DCHECK_EQ(main_frame_widget_route_id, rwh->GetRoutingID());
+ rwh->Send(new WidgetMsg_SetBounds_ACK(rwh->GetRoutingID()));
}
void WebContentsImpl::ShowCreatedWidget(int process_id,
- int route_id,
+ int widget_route_id,
const gfx::Rect& initial_rect) {
- ShowCreatedWidget(process_id, route_id, false, initial_rect);
+ ShowCreatedWidget(process_id, widget_route_id, false, initial_rect);
}
void WebContentsImpl::ShowCreatedFullscreenWidget(int process_id,
- int route_id) {
- ShowCreatedWidget(process_id, route_id, true, gfx::Rect());
+ int widget_route_id) {
+ ShowCreatedWidget(process_id, widget_route_id, true, gfx::Rect());
}
void WebContentsImpl::ShowCreatedWidget(int process_id,
@@ -2841,6 +2922,7 @@ void WebContentsImpl::ShowCreatedWidget(int process_id,
view = GetRenderWidgetHostView();
}
+ // Fullscreen child widgets are frames, other child widgets are popups.
if (is_fullscreen) {
DCHECK_EQ(MSG_ROUTING_NONE, fullscreen_widget_routing_id_);
view_->StoreFocus();
@@ -2869,7 +2951,7 @@ void WebContentsImpl::ShowCreatedWidget(int process_id,
render_widget_host_impl->set_allow_privileged_mouse_lock(is_fullscreen);
}
-std::unique_ptr<WebContents> WebContentsImpl::GetCreatedWindow(
+std::unique_ptr<WebContentsImpl> WebContentsImpl::GetCreatedWindow(
int process_id,
int main_frame_widget_route_id) {
auto key = GlobalRoutingID(process_id, main_frame_widget_route_id);
@@ -2880,14 +2962,12 @@ std::unique_ptr<WebContents> WebContentsImpl::GetCreatedWindow(
if (iter == pending_contents_.end())
return nullptr;
- std::unique_ptr<WebContents> new_contents = std::move(iter->second);
+ std::unique_ptr<WebContentsImpl> new_contents = std::move(iter->second);
pending_contents_.erase(key);
- WebContentsImpl* raw_new_contents =
- static_cast<WebContentsImpl*>(new_contents.get());
- RemoveDestructionObserver(raw_new_contents);
+ RemoveDestructionObserver(new_contents.get());
// Don't initialize the guest WebContents immediately.
- if (BrowserPluginGuest::IsGuest(raw_new_contents))
+ if (BrowserPluginGuest::IsGuest(new_contents.get()))
return new_contents;
if (!new_contents->GetMainFrame()->GetProcess()->IsInitializedAndNotDead() ||
@@ -3403,6 +3483,8 @@ void WebContentsImpl::ReloadFocusedFrame(bool bypass_cache) {
void WebContentsImpl::ReloadLoFiImages() {
SendToAllFrames(new FrameMsg_ReloadLoFiImages(MSG_ROUTING_NONE));
+ for (auto& observer : observers_)
+ observer.DidReloadLoFiImages();
}
std::vector<blink::mojom::PauseSubresourceLoadingHandlePtr>
@@ -3672,8 +3754,6 @@ void WebContentsImpl::SaveFrameWithHeaders(
bool is_main_frame = (url == GetLastCommittedURL());
RenderFrameHost* frame_host = GetMainFrame();
- StoragePartition* storage_partition = BrowserContext::GetStoragePartition(
- GetBrowserContext(), frame_host->GetSiteInstance());
int64_t post_id = -1;
if (is_main_frame) {
const NavigationEntry* entry = controller_.GetLastCommittedEntry();
@@ -3703,8 +3783,7 @@ void WebContentsImpl::SaveFrameWithHeaders(
auto params = std::make_unique<download::DownloadUrlParameters>(
url, frame_host->GetProcess()->GetID(),
frame_host->GetRenderViewHost()->GetRoutingID(),
- frame_host->GetRoutingID(), storage_partition->GetURLRequestContext(),
- traffic_annotation);
+ frame_host->GetRoutingID(), traffic_annotation);
params->set_referrer(referrer.url);
params->set_referrer_policy(
Referrer::ReferrerPolicyForUrlRequest(referrer.policy));
@@ -3935,8 +4014,8 @@ int WebContentsImpl::DownloadImage(
// Android), the downloader service will be invalid. Pre-Mojo, this would
// hang the callback indefinitely since the IPC would be dropped. Now,
// respond with a 400 HTTP error code to indicate that something went wrong.
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&WebContentsImpl::OnDidDownloadImage,
weak_factory_.GetWeakPtr(), std::move(callback),
download_id, url, 400, std::vector<SkBitmap>(),
@@ -3954,14 +4033,15 @@ int WebContentsImpl::DownloadImage(
void WebContentsImpl::Find(int request_id,
const base::string16& search_text,
- const blink::WebFindOptions& options) {
+ blink::mojom::FindOptionsPtr options) {
// Cowardly refuse to search for no text.
if (search_text.empty()) {
NOTREACHED();
return;
}
- GetOrCreateFindRequestManager()->Find(request_id, search_text, options);
+ GetOrCreateFindRequestManager()->Find(request_id, search_text,
+ std::move(options));
}
void WebContentsImpl::StopFinding(StopFindAction action) {
@@ -4283,8 +4363,8 @@ void WebContentsImpl::OnDidLoadResourceFromMemoryCache(
resource_type == RESOURCE_TYPE_MEDIA
? partition->GetMediaURLRequestContext()
: partition->GetURLRequestContext());
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&NotifyCacheOnIO, request_context, url, http_method));
}
}
@@ -4498,7 +4578,23 @@ void WebContentsImpl::OnDidFinishLoad(RenderFrameHostImpl* source,
}
void WebContentsImpl::OnGoToEntryAtOffset(RenderViewHostImpl* source,
- int offset) {
+ int offset,
+ bool has_user_gesture) {
+ // Non-user initiated navigations coming from the renderer should be ignored
+ // if there is an ongoing browser-initiated navigation.
+ // See https://crbug.com/879965.
+ // TODO(arthursonzogni): See if this should check for ongoing navigations in
+ // the frame(s) affected by the session history navigation, rather than just
+ // the main frame.
+ if (!has_user_gesture) {
+ NavigationRequest* ongoing_navigation_request =
+ frame_tree_.root()->navigation_request();
+ if (ongoing_navigation_request &&
+ ongoing_navigation_request->browser_initiated()) {
+ return;
+ }
+ }
+
// All frames are allowed to navigate the global history.
if (!delegate_ || delegate_->OnGoToEntryOffset(offset))
controller_.GoToOffset(offset);
@@ -4543,10 +4639,11 @@ void WebContentsImpl::OnEnumerateDirectory(RenderViewHostImpl* source,
ChildProcessSecurityPolicyImpl* policy =
ChildProcessSecurityPolicyImpl::GetInstance();
- if (policy->CanReadFile(source->GetProcess()->GetID(), path)) {
- // TODO(nick): |this| param in the call below ought to be a RenderFrameHost.
- delegate_->EnumerateDirectory(this, request_id, path);
- }
+ if (!policy->CanReadFile(source->GetProcess()->GetID(), path))
+ return;
+ auto listener = std::make_unique<ViewFileSelectListener>(this, request_id);
+ // TODO(nick): |this| param in the call below ought to be a RenderFrameHost.
+ delegate_->EnumerateDirectory(this, std::move(listener), path);
}
void WebContentsImpl::OnRegisterProtocolHandler(RenderFrameHostImpl* source,
@@ -4663,7 +4760,7 @@ void WebContentsImpl::OnPepperPluginHung(RenderFrameHostImpl* source,
int plugin_child_id,
const base::FilePath& path,
bool is_hung) {
- UMA_HISTOGRAM_COUNTS("Pepper.PluginHung", 1);
+ UMA_HISTOGRAM_COUNTS_1M("Pepper.PluginHung", 1);
for (auto& observer : observers_)
observer.PluginHungStatusChanged(plugin_child_id, path, is_hung);
@@ -5046,6 +5143,31 @@ void WebContentsImpl::ShowContextMenu(RenderFrameHost* render_frame_host,
context_menu_params);
}
+namespace {
+// Normalizes the line endings: \r\n -> \n, lone \r -> \n.
+base::string16 NormalizeLineBreaks(const base::string16& source) {
+ static const base::NoDestructor<base::string16> kReturnNewline(
+ base::ASCIIToUTF16("\r\n"));
+ static const base::NoDestructor<base::string16> kReturn(
+ base::ASCIIToUTF16("\r"));
+ static const base::NoDestructor<base::string16> kNewline(
+ base::ASCIIToUTF16("\n"));
+
+ std::vector<base::StringPiece16> pieces;
+
+ for (const auto& rn_line : base::SplitStringPieceUsingSubstr(
+ source, *kReturnNewline, base::KEEP_WHITESPACE,
+ base::SPLIT_WANT_ALL)) {
+ auto r_lines = base::SplitStringPieceUsingSubstr(
+ rn_line, *kReturn, base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
+ std::move(std::begin(r_lines), std::end(r_lines),
+ std::back_inserter(pieces));
+ }
+
+ return base::JoinString(pieces, *kNewline);
+}
+} // namespace
+
void WebContentsImpl::RunJavaScriptDialog(RenderFrameHost* render_frame_host,
const base::string16& message,
const base::string16& default_prompt,
@@ -5095,16 +5217,19 @@ void WebContentsImpl::RunJavaScriptDialog(RenderFrameHost* render_frame_host,
is_showing_javascript_dialog_ = true;
+ base::string16 normalized_message = NormalizeLineBreaks(message);
+
for (auto* handler : page_handlers) {
handler->DidRunJavaScriptDialog(
- render_frame_host->GetLastCommittedURL(), message, default_prompt,
- dialog_type, has_non_devtools_handlers,
+ render_frame_host->GetLastCommittedURL(), normalized_message,
+ default_prompt, dialog_type, has_non_devtools_handlers,
base::BindOnce(&CloseDialogCallbackWrapper::Run, wrapper, false));
}
if (dialog_manager_) {
dialog_manager_->RunJavaScriptDialog(
- this, render_frame_host, dialog_type, message, default_prompt,
+ this, render_frame_host, dialog_type, normalized_message,
+ default_prompt,
base::BindOnce(&CloseDialogCallbackWrapper::Run, wrapper, false),
&suppress_this_message);
}
@@ -5178,14 +5303,18 @@ void WebContentsImpl::RunBeforeUnloadConfirm(
}
}
-void WebContentsImpl::RunFileChooser(RenderFrameHost* render_frame_host,
- const FileChooserParams& params) {
+void WebContentsImpl::RunFileChooser(
+ RenderFrameHost* render_frame_host,
+ std::unique_ptr<content::FileSelectListener> listener,
+ const blink::mojom::FileChooserParams& params) {
// Any explicit focusing of another window while this WebContents is in
// fullscreen can be used to confuse the user, so drop fullscreen.
ForSecurityDropFullscreen();
if (delegate_)
- delegate_->RunFileChooser(render_frame_host, params);
+ delegate_->RunFileChooser(render_frame_host, std::move(listener), params);
+ else
+ listener->FileSelectionCanceled();
}
WebContents* WebContentsImpl::GetAsWebContents() {
@@ -5543,7 +5672,6 @@ WebContentsImpl::CreateThrottlesForNavigation(
std::unique_ptr<NavigationUIData> WebContentsImpl::GetNavigationUIData(
NavigationHandle* navigation_handle) {
- DCHECK(IsBrowserSideNavigationEnabled());
return GetContentClient()->browser()->GetNavigationUIData(navigation_handle);
}
@@ -5958,7 +6086,7 @@ void WebContentsImpl::BeforeUnloadFiredFromRenderManager(
bool proceed, const base::TimeTicks& proceed_time,
bool* proceed_to_fire_unload) {
for (auto& observer : observers_)
- observer.BeforeUnloadFired(proceed_time);
+ observer.BeforeUnloadFired(proceed, proceed_time);
if (delegate_)
delegate_->BeforeUnloadFired(this, proceed, proceed_to_fire_unload);
// Note: |this| might be deleted at this point.
@@ -6155,16 +6283,6 @@ service_manager::InterfaceProvider* WebContentsImpl::GetJavaInterfaces() {
return java_interfaces_.get();
}
-#elif defined(OS_MACOSX)
-
-void WebContentsImpl::SetAllowOtherViews(bool allow) {
- view_->SetAllowOtherViews(allow);
-}
-
-bool WebContentsImpl::GetAllowOtherViews() {
- return view_->GetAllowOtherViews();
-}
-
#endif
bool WebContentsImpl::CompletedFirstVisuallyNonEmptyPaint() const {
@@ -6462,6 +6580,11 @@ ForwardingAudioStreamFactory* WebContentsImpl::GetAudioStreamFactory() {
if (!audio_stream_factory_) {
audio_stream_factory_.emplace(
this,
+ // BrowserMainLoop::GetInstance() may be null in unit tests.
+ BrowserMainLoop::GetInstance()
+ ? static_cast<media::UserInputMonitorBase*>(
+ BrowserMainLoop::GetInstance()->user_input_monitor())
+ : nullptr,
content::ServiceManagerConnection::GetForProcess()
->GetConnector()
->Clone(),
diff --git a/chromium/content/browser/web_contents/web_contents_impl.h b/chromium/content/browser/web_contents/web_contents_impl.h
index 2687e87ea2d..83f287513d9 100644
--- a/chromium/content/browser/web_contents/web_contents_impl.h
+++ b/chromium/content/browser/web_contents/web_contents_impl.h
@@ -60,7 +60,7 @@
#include "third_party/blink/public/mojom/color_chooser/color_chooser.mojom.h"
#include "third_party/blink/public/mojom/page/display_cutout.mojom.h"
#include "third_party/blink/public/platform/web_drag_operation.h"
-#include "ui/accessibility/ax_modes.h"
+#include "ui/accessibility/ax_mode.h"
#include "ui/base/page_transition_types.h"
#include "ui/gfx/geometry/rect_f.h"
#include "ui/gfx/geometry/size.h"
@@ -333,6 +333,7 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
uint64_t GetUploadSize() const override;
uint64_t GetUploadPosition() const override;
const std::string& GetEncoding() const override;
+ bool WasDiscarded() override;
void SetWasDiscarded(bool was_discarded) override;
void IncrementCapturerCount(const gfx::Size& capture_size) override;
void DecrementCapturerCount() override;
@@ -355,7 +356,7 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
void WasOccluded() override;
Visibility GetVisibility() const override;
bool NeedToFireBeforeUnload() override;
- void DispatchBeforeUnload() override;
+ void DispatchBeforeUnload(bool auto_cancel) override;
void AttachToOuterWebContentsFrame(
WebContents* outer_web_contents,
RenderFrameHost* outer_contents_frame) override;
@@ -441,7 +442,7 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
ImageDownloadCallback callback) override;
void Find(int request_id,
const base::string16& search_text,
- const blink::WebFindOptions& options) override;
+ blink::mojom::FindOptionsPtr options) override;
void StopFinding(StopFindAction action) override;
bool WasEverAudible() override;
void GetManifest(GetManifestCallback callback) override;
@@ -463,9 +464,6 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
void ActivateNearestFindResult(float x, float y) override;
void RequestFindMatchRects(int current_version) override;
service_manager::InterfaceProvider* GetJavaInterfaces() override;
-#elif defined(OS_MACOSX)
- void SetAllowOtherViews(bool allow) override;
- bool GetAllowOtherViews() override;
#endif
bool HasRecentInteractiveInputEvent() const override;
@@ -500,7 +498,8 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
bool is_reload,
IPC::Message* reply_msg) override;
void RunFileChooser(RenderFrameHost* render_frame_host,
- const FileChooserParams& params) override;
+ std::unique_ptr<content::FileSelectListener> listener,
+ const blink::mojom::FileChooserParams& params) override;
void DidCancelLoading() override;
void DidAccessInitialDocument() override;
void DidChangeName(RenderFrameHost* render_frame_host,
@@ -537,6 +536,9 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
void ExitFullscreenMode(bool will_cause_resize) override;
void FullscreenStateChanged(RenderFrameHost* rfh,
bool is_fullscreen) override;
+#if defined(OS_ANDROID)
+ void UpdateUserGestureCarryoverInfo() override;
+#endif
bool ShouldRouteMessageEvent(
RenderFrameHost* target_rfh,
SiteInstance* source_site_instance) const override;
@@ -625,15 +627,15 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
void UpdatePreferredSize(const gfx::Size& pref_size) override;
void CreateNewWidget(int32_t render_process_id,
int32_t route_id,
- mojom::WidgetPtr widget,
- blink::WebPopupType popup_type) override;
+ mojom::WidgetPtr widget) override;
void CreateNewFullscreenWidget(int32_t render_process_id,
- int32_t route_id,
+ int32_t widget_route_id,
mojom::WidgetPtr widget) override;
void ShowCreatedWidget(int process_id,
- int route_id,
+ int widget_route_id,
const gfx::Rect& initial_rect) override;
- void ShowCreatedFullscreenWidget(int process_id, int route_id) override;
+ void ShowCreatedFullscreenWidget(int process_id,
+ int widget_route_id) override;
void RequestMediaAccessPermission(const MediaStreamRequest& request,
MediaResponseCallback callback) override;
bool CheckMediaAccessPermission(RenderFrameHost* render_frame_host,
@@ -689,6 +691,11 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
// RenderWidgetHostDelegate --------------------------------------------------
ukm::SourceId GetUkmSourceIdForLastCommittedSource() const override;
+ void SetTopControlsShownRatio(RenderWidgetHostImpl* render_widget_host,
+ float ratio) override;
+ bool DoBrowserControlsShrinkRendererSize() const override;
+ int GetTopControlsHeight() const override;
+ void SetTopControlsGestureScrollInProgress(bool in_progress) override;
void RenderWidgetCreated(RenderWidgetHostImpl* render_widget_host) override;
void RenderWidgetDeleted(RenderWidgetHostImpl* render_widget_host) override;
void RenderWidgetGotFocus(RenderWidgetHostImpl* render_widget_host) override;
@@ -1031,6 +1038,8 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
FRIEND_TEST_ALL_PREFIXES(WebContentsImplBrowserTest,
JavaScriptDialogsInMainAndSubframes);
FRIEND_TEST_ALL_PREFIXES(WebContentsImplBrowserTest,
+ JavaScriptDialogsNormalizeText);
+ FRIEND_TEST_ALL_PREFIXES(WebContentsImplBrowserTest,
DialogsFromJavaScriptEndFullscreen);
FRIEND_TEST_ALL_PREFIXES(WebContentsImplBrowserTest,
DialogsFromJavaScriptEndFullscreenEvenInInnerWC);
@@ -1046,6 +1055,10 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
BeforeUnloadDialogRequiresGesture);
FRIEND_TEST_ALL_PREFIXES(RenderFrameHostImplBrowserTest,
CancelBeforeUnloadResetsURL);
+ FRIEND_TEST_ALL_PREFIXES(RenderFrameHostImplBrowserTest,
+ BeforeUnloadDialogSuppressedForDiscard);
+ FRIEND_TEST_ALL_PREFIXES(RenderFrameHostImplBrowserTest,
+ PendingDialogMakesDiscardUnloadReturnFalse);
FRIEND_TEST_ALL_PREFIXES(DevToolsProtocolTest, JavaScriptDialogNotifications);
FRIEND_TEST_ALL_PREFIXES(DevToolsProtocolTest, JavaScriptDialogInterop);
FRIEND_TEST_ALL_PREFIXES(DevToolsProtocolTest, BeforeUnloadDialog);
@@ -1054,6 +1067,7 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
PageDisableWithNoDialogManager);
FRIEND_TEST_ALL_PREFIXES(PointerLockBrowserTest,
PointerLockInnerContentsCrashes);
+ FRIEND_TEST_ALL_PREFIXES(PointerLockBrowserTest, PointerLockOopifCrashes);
// So |find_request_manager_| can be accessed for testing.
friend class FindRequestManagerTest;
@@ -1180,7 +1194,9 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
void OnDidRunContentWithCertificateErrors(RenderFrameHostImpl* source);
void OnDocumentLoadedInFrame(RenderFrameHostImpl* source);
void OnDidFinishLoad(RenderFrameHostImpl* source, const GURL& url);
- void OnGoToEntryAtOffset(RenderViewHostImpl* source, int offset);
+ void OnGoToEntryAtOffset(RenderViewHostImpl* source,
+ int offset,
+ bool has_user_gesture);
void OnUpdateZoomLimits(RenderViewHostImpl* source,
int minimum_percent,
int maximum_percent);
@@ -1288,8 +1304,7 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
void CreateNewWidget(int32_t render_process_id,
int32_t route_id,
bool is_fullscreen,
- mojom::WidgetPtr widget,
- blink::WebPopupType popup_type);
+ mojom::WidgetPtr widget);
// Helper for ShowCreatedWidget/ShowCreatedFullscreenWidget.
void ShowCreatedWidget(int process_id,
@@ -1304,8 +1319,9 @@ 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.
- std::unique_ptr<WebContents> GetCreatedWindow(int process_id,
- int main_frame_widget_route_id);
+ std::unique_ptr<WebContentsImpl> GetCreatedWindow(
+ int process_id,
+ int main_frame_widget_route_id);
// Sends a Page message IPC.
void SendPageMessage(IPC::Message* msg);
@@ -1407,6 +1423,10 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
AXTreeSnapshotCombiner* combiner,
ui::AXMode ax_mode);
+ // Called each time |fullscreen_frames_| is updated. Find the new
+ // |current_fullscreen_frame_| and notify observers whenever it changes.
+ void FullscreenFrameSetUpdated();
+
// Data for core operation ---------------------------------------------------
// Delegate for notifying our owner about stuff. Not owned by us.
@@ -1425,7 +1445,7 @@ 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.
- std::map<GlobalRoutingID, std::unique_ptr<WebContents>> pending_contents_;
+ std::map<GlobalRoutingID, std::unique_ptr<WebContentsImpl>> pending_contents_;
// This map holds widgets that were created on behalf of the renderer but
// haven't been shown yet.
@@ -1773,14 +1793,12 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
// Gets notified about changes in viewport fit events.
std::unique_ptr<DisplayCutoutHostImpl> display_cutout_host_impl_;
- // Stores a set of FrameTreeNode ids that are fullscreen.
- using FullscreenFrameNodes = std::set<int>;
- FullscreenFrameNodes fullscreen_frame_tree_nodes_;
+ // Stores a set of frames that are fullscreen.
+ // See https://fullscreen.spec.whatwg.org.
+ std::set<RenderFrameHostImpl*> fullscreen_frames_;
- // Stores the ID of the current fullscreen |FrameTreeNode| or
- // |kNoFrameTreeNodeId| if the tab is not currently fullscreen.
- int current_fullscreen_frame_tree_node_id_ =
- RenderFrameHost::kNoFrameTreeNodeId;
+ // Store the frame that is currently fullscreen, nullptr if there is none.
+ RenderFrameHostImpl* current_fullscreen_frame_ = nullptr;
base::WeakPtrFactory<WebContentsImpl> loading_weak_factory_;
base::WeakPtrFactory<WebContentsImpl> weak_factory_;
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 78857bccaea..b814f649123 100644
--- a/chromium/content/browser/web_contents/web_contents_impl_browsertest.cc
+++ b/chromium/content/browser/web_contents/web_contents_impl_browsertest.cc
@@ -27,6 +27,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/file_select_listener.h"
#include "content/public/browser/invalidate_type.h"
#include "content/public/browser/javascript_dialog_manager.h"
#include "content/public/browser/load_notification_details.h"
@@ -37,7 +38,6 @@
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host_view.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_delegate.h"
@@ -124,11 +124,10 @@ class WebContentsImplBrowserTest : public ContentBrowserTest {
host_resolver()->AddRule("*", "127.0.0.1");
}
- bool CurrentFullscreenFrameTreeNodeIsEmpty() {
+ bool IsInFullscreen() {
WebContentsImpl* web_contents =
static_cast<WebContentsImpl*>(shell()->web_contents());
- return web_contents->current_fullscreen_frame_tree_node_id_ ==
- RenderFrameHost::kNoFrameTreeNodeId;
+ return web_contents->current_fullscreen_frame_;
}
private:
@@ -1109,11 +1108,11 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
// Simulate a navigation that has not completed.
const GURL kURL2 = embedded_test_server()->GetURL("/title2.html");
- NavigationStallDelegate stall_delegate(kURL2);
- ResourceDispatcherHost::Get()->SetDelegate(&stall_delegate);
+ TestNavigationManager navigation(shell()->web_contents(), kURL2);
std::unique_ptr<LoadProgressDelegateAndObserver> delegate(
new LoadProgressDelegateAndObserver(shell()));
shell()->LoadURL(kURL2);
+ EXPECT_TRUE(navigation.WaitForResponse());
EXPECT_TRUE(delegate->did_start_loading);
EXPECT_FALSE(delegate->did_stop_loading);
@@ -1135,8 +1134,6 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
// We should have gotten to DidStopLoading.
EXPECT_TRUE(delegate->did_stop_loading);
-
- ResourceDispatcherHost::Get()->SetDelegate(nullptr);
}
struct FirstVisuallyNonEmptyPaintObserver : public WebContentsObserver {
@@ -1641,6 +1638,14 @@ class TestWCDelegateForDialogsAndFullscreen : public JavaScriptDialogManager,
DISALLOW_COPY_AND_ASSIGN(TestWCDelegateForDialogsAndFullscreen);
};
+class MockFileSelectListener : public FileSelectListener {
+ public:
+ MockFileSelectListener() {}
+ void FileSelected(std::vector<blink::mojom::FileChooserFileInfoPtr> files,
+ blink::mojom::FileChooserParams::Mode mode) override {}
+ void FileSelectionCanceled() override {}
+};
+
} // namespace
IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
@@ -1734,6 +1739,26 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
}
IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
+ JavaScriptDialogsNormalizeText) {
+ WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell()->web_contents());
+ TestWCDelegateForDialogsAndFullscreen test_delegate;
+ wc->SetDelegate(&test_delegate);
+
+ GURL url("about:blank");
+ EXPECT_TRUE(NavigateToURL(shell(), url));
+
+ // A dialog with mixed linebreaks.
+ std::string alert = "alert('1\\r2\\r\\n3\\n4')";
+ test_delegate.WillWaitForDialog();
+ EXPECT_TRUE(content::ExecuteScript(wc, alert));
+ test_delegate.Wait();
+ EXPECT_EQ("1\n2\n3\n4", test_delegate.last_message());
+
+ wc->SetDelegate(nullptr);
+ wc->SetJavaScriptDialogManagerForTesting(nullptr);
+}
+
+IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
CreateWebContentsWithRendererProcess) {
ASSERT_TRUE(embedded_test_server()->Start());
WebContents* base_web_contents = shell()->web_contents();
@@ -2200,7 +2225,9 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, FileChooserEndsFullscreen) {
wc->EnterFullscreenMode(url, blink::WebFullscreenOptions());
EXPECT_TRUE(wc->IsFullscreenForCurrentTab());
- wc->RunFileChooser(wc->GetMainFrame(), FileChooserParams());
+ wc->RunFileChooser(wc->GetMainFrame(),
+ std::make_unique<MockFileSelectListener>(),
+ blink::mojom::FileChooserParams());
EXPECT_FALSE(wc->IsFullscreenForCurrentTab());
wc->SetDelegate(nullptr);
@@ -2659,15 +2686,13 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, NotifyFullscreenAcquired) {
GURL url = embedded_test_server()->GetURL(
"a.com", "/cross_site_iframe_factory.html?a(b{allowfullscreen})");
EXPECT_TRUE(NavigateToURL(shell(), url));
- RenderFrameHost* main_frame = web_contents->GetMainFrame();
- int main_frame_id = main_frame->GetFrameTreeNodeId();
-
- RenderFrameHost* child_frame = ChildFrameAt(main_frame, 0);
- int child_frame_id = child_frame->GetFrameTreeNodeId();
+ RenderFrameHostImpl* main_frame = web_contents->GetMainFrame();
+ RenderFrameHostImpl* child_frame =
+ static_cast<RenderFrameHostImpl*>(ChildFrameAt(main_frame, 0));
- WebContentsImpl::FullscreenFrameNodes nodes;
- EXPECT_EQ(nodes, web_contents->fullscreen_frame_tree_nodes_);
- EXPECT_TRUE(CurrentFullscreenFrameTreeNodeIsEmpty());
+ std::set<RenderFrameHostImpl*> fullscreen_frames;
+ EXPECT_EQ(fullscreen_frames, web_contents->fullscreen_frames_);
+ EXPECT_FALSE(IsInFullscreen());
// Make the top page fullscreen.
{
@@ -2677,10 +2702,9 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, NotifyFullscreenAcquired) {
observer.Wait();
}
- nodes.insert(main_frame_id);
- EXPECT_EQ(nodes, web_contents->fullscreen_frame_tree_nodes_);
- EXPECT_EQ(main_frame_id,
- web_contents->current_fullscreen_frame_tree_node_id_);
+ fullscreen_frames.insert(main_frame);
+ EXPECT_EQ(fullscreen_frames, web_contents->fullscreen_frames_);
+ EXPECT_EQ(main_frame, web_contents->current_fullscreen_frame_);
// Make the child frame fullscreen.
{
@@ -2690,10 +2714,9 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, NotifyFullscreenAcquired) {
observer.Wait();
}
- nodes.insert(child_frame_id);
- EXPECT_EQ(nodes, web_contents->fullscreen_frame_tree_nodes_);
- EXPECT_EQ(child_frame_id,
- web_contents->current_fullscreen_frame_tree_node_id_);
+ fullscreen_frames.insert(child_frame);
+ EXPECT_EQ(fullscreen_frames, web_contents->fullscreen_frames_);
+ EXPECT_EQ(child_frame, web_contents->current_fullscreen_frame_);
// Exit fullscreen on the child frame.
// This will not work with --site-per-process until crbug.com/617369
@@ -2706,10 +2729,9 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, NotifyFullscreenAcquired) {
observer.Wait();
}
- nodes.erase(child_frame_id);
- EXPECT_EQ(nodes, web_contents->fullscreen_frame_tree_nodes_);
- EXPECT_EQ(main_frame_id,
- web_contents->current_fullscreen_frame_tree_node_id_);
+ fullscreen_frames.erase(child_frame);
+ EXPECT_EQ(fullscreen_frames, web_contents->fullscreen_frames_);
+ EXPECT_EQ(main_frame, web_contents->current_fullscreen_frame_);
}
}
@@ -2727,14 +2749,14 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, FullscreenAfterFrameSwap) {
EXPECT_TRUE(NavigateToURL(shell(), url_a));
RenderFrameHostImpl* main_frame =
static_cast<RenderFrameHostImpl*>(web_contents->GetMainFrame());
- EXPECT_EQ(0u, web_contents->fullscreen_frame_tree_nodes_.size());
+ EXPECT_EQ(0u, web_contents->fullscreen_frames_.size());
// 2) Make it fullscreen.
FullscreenWebContentsObserver observer(web_contents, main_frame);
EXPECT_TRUE(
ExecuteScript(main_frame, "document.body.webkitRequestFullscreen();"));
observer.Wait();
- EXPECT_EQ(1u, web_contents->fullscreen_frame_tree_nodes_.size());
+ EXPECT_EQ(1u, web_contents->fullscreen_frames_.size());
// 3) Navigate cross origin. Act as if the old frame was very slow delivering
// the swapout ack and stayed in pending deletion for a while. Even if the
@@ -2744,7 +2766,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, FullscreenAfterFrameSwap) {
main_frame->GetProcess()->AddFilter(filter.get());
main_frame->DisableSwapOutTimerForTesting();
EXPECT_TRUE(NavigateToURL(shell(), url_b));
- EXPECT_EQ(0u, web_contents->fullscreen_frame_tree_nodes_.size());
+ EXPECT_EQ(0u, web_contents->fullscreen_frames_.size());
}
IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
@@ -2759,15 +2781,13 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
GURL url = embedded_test_server()->GetURL(
"a.com", "/cross_site_iframe_factory.html?a(b{allowfullscreen})");
EXPECT_TRUE(NavigateToURL(shell(), url));
- RenderFrameHost* main_frame = web_contents->GetMainFrame();
- int main_frame_id = main_frame->GetFrameTreeNodeId();
+ RenderFrameHostImpl* main_frame = web_contents->GetMainFrame();
+ RenderFrameHostImpl* child_frame =
+ static_cast<RenderFrameHostImpl*>(ChildFrameAt(main_frame, 0));
- RenderFrameHost* child_frame = ChildFrameAt(main_frame, 0);
- int child_frame_id = child_frame->GetFrameTreeNodeId();
-
- WebContentsImpl::FullscreenFrameNodes nodes;
- EXPECT_EQ(nodes, web_contents->fullscreen_frame_tree_nodes_);
- EXPECT_TRUE(CurrentFullscreenFrameTreeNodeIsEmpty());
+ std::set<RenderFrameHostImpl*> nodes;
+ EXPECT_EQ(nodes, web_contents->fullscreen_frames_);
+ EXPECT_FALSE(IsInFullscreen());
// Make the top page fullscreen.
{
@@ -2777,10 +2797,9 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
observer.Wait();
}
- nodes.insert(main_frame_id);
- EXPECT_EQ(nodes, web_contents->fullscreen_frame_tree_nodes_);
- EXPECT_EQ(main_frame_id,
- web_contents->current_fullscreen_frame_tree_node_id_);
+ nodes.insert(main_frame);
+ EXPECT_EQ(nodes, web_contents->fullscreen_frames_);
+ EXPECT_EQ(main_frame, web_contents->current_fullscreen_frame_);
// Make the child frame fullscreen.
{
@@ -2790,17 +2809,16 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
observer.Wait();
}
- nodes.insert(child_frame_id);
- EXPECT_EQ(nodes, web_contents->fullscreen_frame_tree_nodes_);
- EXPECT_EQ(child_frame_id,
- web_contents->current_fullscreen_frame_tree_node_id_);
+ nodes.insert(child_frame);
+ EXPECT_EQ(nodes, web_contents->fullscreen_frames_);
+ EXPECT_EQ(child_frame, web_contents->current_fullscreen_frame_);
// Perform a cross origin navigation on the main frame.
EXPECT_TRUE(
NavigateToURL(shell(), embedded_test_server()->GetURL(
"c.com", "/cross_site_iframe_factory.html")));
- EXPECT_EQ(0u, web_contents->fullscreen_frame_tree_nodes_.size());
- EXPECT_TRUE(CurrentFullscreenFrameTreeNodeIsEmpty());
+ EXPECT_EQ(0u, web_contents->fullscreen_frames_.size());
+ EXPECT_FALSE(IsInFullscreen());
}
IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
@@ -2814,15 +2832,13 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
GURL url = embedded_test_server()->GetURL(
"a.com", "/cross_site_iframe_factory.html?a(a{allowfullscreen})");
EXPECT_TRUE(NavigateToURL(shell(), url));
- RenderFrameHost* main_frame = web_contents->GetMainFrame();
- int main_frame_id = main_frame->GetFrameTreeNodeId();
-
- RenderFrameHost* child_frame = ChildFrameAt(main_frame, 0);
- int child_frame_id = child_frame->GetFrameTreeNodeId();
+ RenderFrameHostImpl* main_frame = web_contents->GetMainFrame();
+ RenderFrameHostImpl* child_frame =
+ static_cast<RenderFrameHostImpl*>(ChildFrameAt(main_frame, 0));
- WebContentsImpl::FullscreenFrameNodes nodes;
- EXPECT_EQ(nodes, web_contents->fullscreen_frame_tree_nodes_);
- EXPECT_TRUE(CurrentFullscreenFrameTreeNodeIsEmpty());
+ std::set<RenderFrameHostImpl*> fullscreen_frames;
+ EXPECT_EQ(fullscreen_frames, web_contents->fullscreen_frames_);
+ EXPECT_FALSE(IsInFullscreen());
// Make the top page fullscreen.
{
@@ -2832,10 +2848,9 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
observer.Wait();
}
- nodes.insert(main_frame_id);
- EXPECT_EQ(nodes, web_contents->fullscreen_frame_tree_nodes_);
- EXPECT_EQ(main_frame_id,
- web_contents->current_fullscreen_frame_tree_node_id_);
+ fullscreen_frames.insert(main_frame);
+ EXPECT_EQ(fullscreen_frames, web_contents->fullscreen_frames_);
+ EXPECT_EQ(main_frame, web_contents->current_fullscreen_frame_);
// Make the child frame fullscreen.
{
@@ -2845,10 +2860,9 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
observer.Wait();
}
- nodes.insert(child_frame_id);
- EXPECT_EQ(nodes, web_contents->fullscreen_frame_tree_nodes_);
- EXPECT_EQ(child_frame_id,
- web_contents->current_fullscreen_frame_tree_node_id_);
+ fullscreen_frames.insert(child_frame);
+ EXPECT_EQ(fullscreen_frames, web_contents->fullscreen_frames_);
+ EXPECT_EQ(child_frame, web_contents->current_fullscreen_frame_);
// Exit fullscreen on the child frame.
{
@@ -2857,10 +2871,9 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
observer.Wait();
}
- nodes.erase(child_frame_id);
- EXPECT_EQ(nodes, web_contents->fullscreen_frame_tree_nodes_);
- EXPECT_EQ(main_frame_id,
- web_contents->current_fullscreen_frame_tree_node_id_);
+ fullscreen_frames.erase(child_frame);
+ EXPECT_EQ(fullscreen_frames, web_contents->fullscreen_frames_);
+ EXPECT_EQ(main_frame, web_contents->current_fullscreen_frame_);
}
class MockDidOpenRequestedURLObserver : public WebContentsObserver {
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 aa74c714540..d712e197d9c 100644
--- a/chromium/content/browser/web_contents/web_contents_impl_unittest.cc
+++ b/chromium/content/browser/web_contents/web_contents_impl_unittest.cc
@@ -455,10 +455,6 @@ TEST_F(WebContentsImplTest, DirectNavigationToViewSourceWebUI) {
InitNavigateParams(&params, entry_id, true, kRewrittenURL,
ui::PAGE_TRANSITION_TYPED);
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->OnMessageReceived(
- FrameHostMsg_DidStartProvisionalLoad(1, kRewrittenURL,
- std::vector<GURL>(),
- base::TimeTicks::Now()));
main_test_rfh()->SimulateCommitProcessed(
request->navigation_handle()->GetNavigationId(),
true /* was_successful */);
@@ -2003,15 +1999,7 @@ TEST_F(WebContentsImplTest, CreateInterstitialForClosingTab) {
DeleteContents();
EXPECT_EQ(TestInterstitialPage::CANCELED, state);
- // The interstitial page triggers a DidStartNavigation after the tab is gone,
- // but before the interstitial page itself is deleted. This should not crash.
- Navigator* interstitial_navigator =
- interstitial_rfh->frame_tree_node()->navigator();
- interstitial_navigator->DidStartProvisionalLoad(
- interstitial_rfh, url2, std::vector<GURL>(), base::TimeTicks::Now());
- EXPECT_FALSE(deleted);
-
- // Simulate a commit in the interstitial page, which should also not crash.
+ // Simulate a commit in the interstitial page, which should not crash.
interstitial_rfh->SimulateNavigationCommit(url2);
RunAllPendingInMessageLoop();
@@ -2518,28 +2506,25 @@ 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<WebContentsImpl> other_contents(
- static_cast<WebContentsImpl*>(CreateTestWebContents().release()));
- content::TestWebContents* raw_other_contents =
- static_cast<TestWebContents*>(other_contents.get());
+ auto other_contents = base::WrapUnique(
+ static_cast<TestWebContents*>(CreateTestWebContents().release()));
+ content::TestWebContents* test_web_contents = other_contents.get();
contents()->AddPendingContents(std::move(other_contents));
RenderWidgetHost* widget =
- raw_other_contents->GetMainFrame()->GetRenderWidgetHost();
+ test_web_contents->GetMainFrame()->GetRenderWidgetHost();
int process_id = widget->GetProcess()->GetID();
int widget_id = widget->GetRoutingID();
// 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;
+ delete test_web_contents;
EXPECT_EQ(nullptr, contents()->GetCreatedWindow(process_id, widget_id));
}
TEST_F(WebContentsImplTest, PendingContentsShown) {
- 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());
+ auto other_contents = base::WrapUnique(
+ static_cast<TestWebContents*>(CreateTestWebContents().release()));
+ content::TestWebContents* test_web_contents = other_contents.get();
contents()->AddPendingContents(std::move(other_contents));
RenderWidgetHost* widget =
@@ -2548,7 +2533,7 @@ TEST_F(WebContentsImplTest, PendingContentsShown) {
int widget_id = widget->GetRoutingID();
// The first call to GetCreatedWindow pops it off the pending list.
- EXPECT_EQ(raw_other_contents,
+ EXPECT_EQ(test_web_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));
@@ -3152,59 +3137,51 @@ TEST_F(WebContentsImplTestWithSiteIsolation, IsLoadingToDifferentDocument) {
// Ensure that WebContentsImpl does not stop loading too early when there still
// is a pending renderer. This can happen if a same-process non user-initiated
// navigation completes while there is an ongoing cross-process navigation.
-// TODO(fdegans): Rewrite the test for PlzNavigate when DidStartLoading and
-// DidStopLoading are properly called.
-TEST_F(WebContentsImplTest, NoEarlyStop) {
+// TODO(clamy): Rewrite that test when the renderer-initiated non-user-initiated
+// navigation no longer kills the speculative RenderFrameHost. See
+// https://crbug.com/889039.
+TEST_F(WebContentsImplTest, DISABLED_NoEarlyStop) {
const GURL kUrl1("http://www.chromium.org");
const GURL kUrl2("http://www.google.com");
- const GURL kUrl3("http://www.wikipedia.org");
+ const GURL kUrl3("http://www.chromium.org/foo");
contents()->NavigateAndCommit(kUrl1);
TestRenderFrameHost* current_rfh = main_test_rfh();
- // Start a browser-initiated cross-process navigation to |kUrl2|. There should
- // be a pending RenderFrameHost and the WebContents should be loading.
- controller().LoadURL(
- kUrl2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
- int entry_id = controller().GetPendingEntry()->GetUniqueID();
- EXPECT_TRUE(contents()->CrossProcessNavigationPending());
+ // Start a browser-initiated cross-process navigation to |kUrl2|. The
+ // WebContents should be loading.
+ auto cross_process_navigation =
+ NavigationSimulator::CreateBrowserInitiated(kUrl2, contents());
+ cross_process_navigation->ReadyToCommit();
TestRenderFrameHost* pending_rfh = contents()->GetPendingMainFrame();
- ASSERT_TRUE(pending_rfh);
EXPECT_TRUE(contents()->IsLoading());
// The current RenderFrameHost starts a non user-initiated render-initiated
- // navigation and sends a DidStartLoading IPC. The WebContents should still be
- // loading.
- current_rfh->OnMessageReceived(
- FrameHostMsg_DidStartLoading(current_rfh->GetRoutingID(), false));
- EXPECT_TRUE(contents()->IsLoading());
-
- // Simulate the pending RenderFrameHost DidStartLoading. There should still be
- // a pending RenderFrameHost and the WebContents should still be loading.
- pending_rfh->PrepareForCommit();
- pending_rfh->OnMessageReceived(
- FrameHostMsg_DidStartLoading(pending_rfh->GetRoutingID(), false));
- EXPECT_EQ(contents()->GetPendingMainFrame(), pending_rfh);
+ // navigation. The WebContents should still be loading.
+ auto same_process_navigation =
+ NavigationSimulator::CreateRendererInitiated(kUrl3, current_rfh);
+ same_process_navigation->SetHasUserGesture(false);
+ same_process_navigation->Start();
EXPECT_TRUE(contents()->IsLoading());
// Simulate the commit and DidStopLoading from the renderer-initiated
// navigation in the current RenderFrameHost. There should still be a pending
// RenderFrameHost and the WebContents should still be loading.
- current_rfh->SendNavigateWithModificationCallback(
- 0, true, kUrl3, base::Bind(SetAsNonUserGesture));
+ same_process_navigation->Commit();
current_rfh->OnMessageReceived(
FrameHostMsg_DidStopLoading(current_rfh->GetRoutingID()));
EXPECT_EQ(contents()->GetPendingMainFrame(), pending_rfh);
EXPECT_TRUE(contents()->IsLoading());
- // It should commit.
+
+ // The same-process navigation should have committed.
ASSERT_EQ(2, controller().GetEntryCount());
EXPECT_EQ(kUrl3, controller().GetLastCommittedEntry()->GetURL());
- // Commit the navigation. The formerly pending RenderFrameHost should now be
- // the current RenderFrameHost and the WebContents should still be loading.
- contents()->TestDidNavigate(pending_rfh, entry_id, true, kUrl2,
- ui::PAGE_TRANSITION_TYPED);
+ // Commit the cross-process navigation. The formerly pending RenderFrameHost
+ // should now be the current RenderFrameHost and the WebContents should still
+ // be loading.
+ cross_process_navigation->Commit();
EXPECT_FALSE(contents()->GetPendingMainFrame());
TestRenderFrameHost* new_current_rfh = main_test_rfh();
EXPECT_EQ(new_current_rfh, pending_rfh);
@@ -3332,7 +3309,7 @@ TEST_F(WebContentsImplTest, MediaWakeLock) {
// on.
rfh->OnMessageReceived(
MediaPlayerDelegateHostMsg_OnPictureInPictureModeStarted(
- 0, kPlayerAudioVideoId, surface_id, gfx::Size(), 0));
+ 0, kPlayerAudioVideoId, surface_id, gfx::Size(), 0, true));
EXPECT_TRUE(has_video_wake_lock());
EXPECT_FALSE(has_audio_wake_lock());
@@ -3424,6 +3401,7 @@ class TestOverlayWindow : public OverlayWindow {
gfx::Rect GetBounds() const override { return gfx::Rect(); }
void UpdateVideoSize(const gfx::Size& natural_size) override {}
void SetPlaybackState(PlaybackState playback_state) override {}
+ void SetAlwaysHidePlayPauseButton(bool is_visible) override {}
ui::Layer* GetWindowBackgroundLayer() override { return nullptr; }
ui::Layer* GetVideoLayer() override { return nullptr; }
gfx::Rect GetVideoBounds() override { return gfx::Rect(); }
@@ -3478,7 +3456,8 @@ TEST_F(WebContentsImplTest, EnterPictureInPicture) {
rfh->OnMessageReceived(
MediaPlayerDelegateHostMsg_OnPictureInPictureModeStarted(
rfh->GetRoutingID(), kPlayerVideoOnlyId, surface_id /* surface_id */,
- gfx::Size(42, 42) /* natural_size */, 1 /* request_id */));
+ gfx::Size(42, 42) /* natural_size */, 1 /* request_id */,
+ true /* show_play_pause_button */));
EXPECT_TRUE(observer->GetPictureInPictureVideoMediaPlayerId().has_value());
EXPECT_EQ(kPlayerVideoOnlyId,
observer->GetPictureInPictureVideoMediaPlayerId()->delegate_id);
diff --git a/chromium/content/browser/web_contents/web_contents_ns_view_bridge.h b/chromium/content/browser/web_contents/web_contents_ns_view_bridge.h
new file mode 100644
index 00000000000..cb9f1f75093
--- /dev/null
+++ b/chromium/content/browser/web_contents/web_contents_ns_view_bridge.h
@@ -0,0 +1,54 @@
+// 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_CONTENTS_WEB_CONTENTS_NS_VIEW_BRIDGE_H_
+#define CONTENT_BROWSER_WEB_CONTENTS_WEB_CONTENTS_NS_VIEW_BRIDGE_H_
+
+#import <Cocoa/Cocoa.h>
+
+#include <memory>
+
+#import "base/mac/scoped_nsobject.h"
+#include "base/macros.h"
+#include "content/common/content_export.h"
+#include "content/public/common/web_contents_ns_view_bridge.mojom.h"
+#include "mojo/public/cpp/bindings/associated_binding.h"
+#include "ui/base/cocoa/ns_view_ids.h"
+
+namespace content {
+
+// A C++ wrapper around a WebContentsView's NSView in a non-browser process.
+class CONTENT_EXPORT WebContentsNSViewBridge
+ : public mojom::WebContentsNSViewBridge {
+ public:
+ // Create a bridge that will access its client in another process via a mojo
+ // interface. This object will be deleted when |bridge_request|'s connection
+ // closes.
+ WebContentsNSViewBridge(
+ uint64_t view_id,
+ mojom::WebContentsNSViewClientAssociatedPtr client,
+ mojom::WebContentsNSViewBridgeAssociatedRequest bridge_request);
+
+ // mojom::WebContentsNSViewBridge:
+ void SetParentViewsNSView(uint64_t parent_ns_view_id) override;
+ void Show(const gfx::Rect& bounds_in_window) override;
+ void Hide() override;
+ void MakeFirstResponder() override;
+
+ private:
+ ~WebContentsNSViewBridge() override;
+ void OnConnectionError();
+
+ base::scoped_nsobject<NSView> cocoa_view_;
+ mojom::WebContentsNSViewClientAssociatedPtr client_;
+ mojo::AssociatedBinding<mojom::WebContentsNSViewBridge> binding_;
+
+ std::unique_ptr<ui::ScopedNSViewIdMapping> view_id_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebContentsNSViewBridge);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_WEB_CONTENTS_WEB_CONTENTS_NS_VIEW_BRIDGE_H_
diff --git a/chromium/content/browser/web_contents/web_contents_ns_view_bridge.mm b/chromium/content/browser/web_contents/web_contents_ns_view_bridge.mm
new file mode 100644
index 00000000000..90181ae5896
--- /dev/null
+++ b/chromium/content/browser/web_contents/web_contents_ns_view_bridge.mm
@@ -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.
+
+#include "content/browser/web_contents/web_contents_ns_view_bridge.h"
+
+#include "ui/accelerated_widget_mac/window_resize_helper_mac.h"
+
+namespace content {
+
+WebContentsNSViewBridge::WebContentsNSViewBridge(
+ uint64_t view_id,
+ mojom::WebContentsNSViewClientAssociatedPtr client,
+ mojom::WebContentsNSViewBridgeAssociatedRequest bridge_request)
+ : client_(std::move(client)), binding_(this) {
+ binding_.Bind(std::move(bridge_request),
+ ui::WindowResizeHelperMac::Get()->task_runner());
+ // This object will be destroyed when its connection is closed.
+ binding_.set_connection_error_handler(base::BindOnce(
+ &WebContentsNSViewBridge::OnConnectionError, base::Unretained(this)));
+
+ // Note that this is an ordinary NSView (as opposed to a full
+ // WebContentsViewCocoa).
+ cocoa_view_.reset([[NSView alloc] initWithFrame:NSZeroRect]);
+ view_id_ =
+ std::make_unique<ui::ScopedNSViewIdMapping>(view_id, cocoa_view_.get());
+}
+
+WebContentsNSViewBridge::~WebContentsNSViewBridge() {
+ [cocoa_view_ removeFromSuperview];
+}
+
+void WebContentsNSViewBridge::OnConnectionError() {
+ delete this;
+}
+
+void WebContentsNSViewBridge::SetParentViewsNSView(uint64_t parent_ns_view_id) {
+ NSView* parent_ns_view = ui::NSViewIds::GetNSView(parent_ns_view_id);
+ // If the browser passed an invalid handle, then there is no recovery.
+ CHECK(parent_ns_view);
+ [parent_ns_view addSubview:cocoa_view_];
+}
+
+void WebContentsNSViewBridge::Show(const gfx::Rect& bounds_in_window) {
+ NSRect ns_bounds_in_window =
+ NSMakeRect(bounds_in_window.x(),
+ [[[cocoa_view_ window] contentView] frame].size.height -
+ bounds_in_window.y() - bounds_in_window.height(),
+ bounds_in_window.width(), bounds_in_window.height());
+ NSRect ns_bounds_in_superview =
+ [[cocoa_view_ superview] convertRect:ns_bounds_in_window fromView:nil];
+ [cocoa_view_ setFrame:ns_bounds_in_superview];
+ [cocoa_view_ setHidden:NO];
+}
+
+void WebContentsNSViewBridge::Hide() {
+ [cocoa_view_ setHidden:YES];
+}
+
+void WebContentsNSViewBridge::MakeFirstResponder() {
+ if ([cocoa_view_ acceptsFirstResponder])
+ [[cocoa_view_ window] makeFirstResponder:cocoa_view_];
+}
+
+} // namespace content
diff --git a/chromium/content/browser/web_contents/web_contents_view.h b/chromium/content/browser/web_contents/web_contents_view.h
index 41e44d5d658..5426d600906 100644
--- a/chromium/content/browser/web_contents/web_contents_view.h
+++ b/chromium/content/browser/web_contents/web_contents_view.h
@@ -96,8 +96,9 @@ class WebContentsView {
virtual RenderWidgetHostViewBase* CreateViewForWidget(
RenderWidgetHost* render_widget_host, bool is_guest_view_hack) = 0;
- // Creates a new View that holds a popup and receives messages for it.
- virtual RenderWidgetHostViewBase* CreateViewForPopupWidget(
+ // Creates a new View that holds a non-top-level widget and receives messages
+ // for it.
+ virtual RenderWidgetHostViewBase* CreateViewForChildWidget(
RenderWidgetHost* render_widget_host) = 0;
// Sets the page title for the native widgets corresponding to the view. This
@@ -122,13 +123,6 @@ class WebContentsView {
virtual void SetOverscrollControllerEnabled(bool enabled) = 0;
#if defined(OS_MACOSX)
- // Allowing other views disables optimizations which assume that only a single
- // WebContents is present.
- virtual void SetAllowOtherViews(bool allow) = 0;
-
- // Returns true if other views are allowed, false otherwise.
- virtual bool GetAllowOtherViews() const = 0;
-
// If we close the tab while a UI control is in an event-tracking
// loop, the control may message freed objects and crash.
// WebContents::Close() calls IsEventTracking(), and if it returns
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 fe977804cb8..097eb030c7e 100644
--- a/chromium/content/browser/web_contents/web_contents_view_android.cc
+++ b/chromium/content/browser/web_contents/web_contents_view_android.cc
@@ -255,7 +255,7 @@ RenderWidgetHostViewBase* WebContentsViewAndroid::CreateViewForWidget(
return rwhv;
}
-RenderWidgetHostViewBase* WebContentsViewAndroid::CreateViewForPopupWidget(
+RenderWidgetHostViewBase* WebContentsViewAndroid::CreateViewForChildWidget(
RenderWidgetHost* render_widget_host) {
RenderWidgetHostImpl* rwhi = RenderWidgetHostImpl::From(render_widget_host);
return new RenderWidgetHostViewAndroid(rwhi, nullptr);
@@ -521,9 +521,10 @@ int WebContentsViewAndroid::GetBottomControlsHeight() const {
return delegate ? delegate->GetBottomControlsHeight() : 0;
}
-bool WebContentsViewAndroid::DoBrowserControlsShrinkBlinkSize() const {
+bool WebContentsViewAndroid::DoBrowserControlsShrinkRendererSize() const {
auto* delegate = web_contents_->GetDelegate();
- return delegate ? delegate->DoBrowserControlsShrinkBlinkSize() : false;
+ return delegate &&
+ delegate->DoBrowserControlsShrinkRendererSize(web_contents_);
}
bool WebContentsViewAndroid::OnTouchEvent(const ui::MotionEventAndroid& event) {
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 53d1898347c..37358129a48 100644
--- a/chromium/content/browser/web_contents/web_contents_view_android.h
+++ b/chromium/content/browser/web_contents/web_contents_view_android.h
@@ -73,7 +73,7 @@ class WebContentsViewAndroid : public WebContentsView,
RenderWidgetHostViewBase* CreateViewForWidget(
RenderWidgetHost* render_widget_host,
bool is_guest_view_hack) override;
- RenderWidgetHostViewBase* CreateViewForPopupWidget(
+ RenderWidgetHostViewBase* CreateViewForChildWidget(
RenderWidgetHost* render_widget_host) override;
void SetPageTitle(const base::string16& title) override;
void RenderViewCreated(RenderViewHost* host) override;
@@ -107,7 +107,7 @@ class WebContentsViewAndroid : public WebContentsView,
void TakeFocus(bool reverse) override;
int GetTopControlsHeight() const override;
int GetBottomControlsHeight() const override;
- bool DoBrowserControlsShrinkBlinkSize() const override;
+ bool DoBrowserControlsShrinkRendererSize() const override;
// ui::EventHandlerAndroid implementation.
bool OnTouchEvent(const ui::MotionEventAndroid& event) override;
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 e471459007a..ce5602b1cc3 100644
--- a/chromium/content/browser/web_contents/web_contents_view_aura.cc
+++ b/chromium/content/browser/web_contents/web_contents_view_aura.cc
@@ -12,6 +12,7 @@
#include "base/files/file_util.h"
#include "base/macros.h"
#include "base/message_loop/message_loop_current.h"
+#include "base/no_destructor.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "components/viz/common/features.h"
@@ -59,7 +60,6 @@
#include "ui/aura/env.h"
#include "ui/aura/window.h"
#include "ui/aura/window_observer.h"
-#include "ui/aura/window_occlusion_tracker.h"
#include "ui/aura/window_tree_host.h"
#include "ui/aura/window_tree_host_observer.h"
#include "ui/base/clipboard/clipboard.h"
@@ -230,11 +230,9 @@ void PrepareDragForDownload(
// Returns the FormatType to store file system files.
const ui::Clipboard::FormatType& GetFileSystemFileFormatType() {
- static const char kFormatString[] = "chromium/x-file-system-files";
- CR_DEFINE_STATIC_LOCAL(ui::Clipboard::FormatType,
- format,
- (ui::Clipboard::GetFormatType(kFormatString)));
- return format;
+ static base::NoDestructor<ui::Clipboard::FormatType> format(
+ ui::Clipboard::GetFormatType("chromium/x-file-system-files"));
+ return *format;
}
@@ -480,7 +478,7 @@ WebContentsViewAura::WebContentsViewAura(WebContentsImpl* web_contents,
WebContentsViewDelegate* delegate)
: is_mus_browser_plugin_guest_(web_contents->GetBrowserPluginGuest() !=
nullptr &&
- features::IsUsingWindowService()),
+ features::IsMultiProcessMash()),
web_contents_(web_contents),
delegate_(delegate),
current_drag_op_(blink::kWebDragOperationNone),
@@ -763,7 +761,7 @@ void WebContentsViewAura::CreateAuraWindow(aura::Window* context) {
root_window->GetBoundsInScreen());
}
window_->layer()->SetMasksToBounds(true);
- aura::WindowOcclusionTracker::Track(window_.get());
+ window_->TrackOcclusionState();
// WindowObserver is not interesting and is problematic for Browser Plugin
// guests.
@@ -852,7 +850,7 @@ RenderWidgetHostViewBase* WebContentsViewAura::CreateViewForWidget(
return view;
}
-RenderWidgetHostViewBase* WebContentsViewAura::CreateViewForPopupWidget(
+RenderWidgetHostViewBase* WebContentsViewAura::CreateViewForChildWidget(
RenderWidgetHost* render_widget_host) {
// Popups are not created as embedded windows in mus, so
// |is_mus_browser_plugin_guest| is always false for them.
diff --git a/chromium/content/browser/web_contents/web_contents_view_aura.h b/chromium/content/browser/web_contents/web_contents_view_aura.h
index 212da86e253..0c4a3d2e0d7 100644
--- a/chromium/content/browser/web_contents/web_contents_view_aura.h
+++ b/chromium/content/browser/web_contents/web_contents_view_aura.h
@@ -122,7 +122,7 @@ class CONTENT_EXPORT WebContentsViewAura
RenderWidgetHostViewBase* CreateViewForWidget(
RenderWidgetHost* render_widget_host,
bool is_guest_view_hack) override;
- RenderWidgetHostViewBase* CreateViewForPopupWidget(
+ RenderWidgetHostViewBase* CreateViewForChildWidget(
RenderWidgetHost* render_widget_host) override;
void SetPageTitle(const base::string16& title) override;
void RenderViewCreated(RenderViewHost* host) override;
diff --git a/chromium/content/browser/web_contents/web_contents_view_child_frame.cc b/chromium/content/browser/web_contents/web_contents_view_child_frame.cc
index 688540cea25..7b339bf9407 100644
--- a/chromium/content/browser/web_contents/web_contents_view_child_frame.cc
+++ b/chromium/content/browser/web_contents/web_contents_view_child_frame.cc
@@ -88,9 +88,9 @@ RenderWidgetHostViewBase* WebContentsViewChildFrame::CreateViewForWidget(
return RenderWidgetHostViewChildFrame::Create(render_widget_host);
}
-RenderWidgetHostViewBase* WebContentsViewChildFrame::CreateViewForPopupWidget(
+RenderWidgetHostViewBase* WebContentsViewChildFrame::CreateViewForChildWidget(
RenderWidgetHost* render_widget_host) {
- return GetOuterView()->CreateViewForPopupWidget(render_widget_host);
+ return GetOuterView()->CreateViewForChildWidget(render_widget_host);
}
void WebContentsViewChildFrame::SetPageTitle(const base::string16& title) {
@@ -117,15 +117,6 @@ bool WebContentsViewChildFrame::IsEventTracking() const {
void WebContentsViewChildFrame::CloseTabAfterEventTracking() {
NOTREACHED();
}
-
-void WebContentsViewChildFrame::SetAllowOtherViews(bool allow) {
- NOTREACHED();
-}
-
-bool WebContentsViewChildFrame::GetAllowOtherViews() const {
- NOTREACHED();
- return false;
-}
#endif
void WebContentsViewChildFrame::RestoreFocus() {
diff --git a/chromium/content/browser/web_contents/web_contents_view_child_frame.h b/chromium/content/browser/web_contents/web_contents_view_child_frame.h
index e5485f5609c..e82cced4364 100644
--- a/chromium/content/browser/web_contents/web_contents_view_child_frame.h
+++ b/chromium/content/browser/web_contents/web_contents_view_child_frame.h
@@ -41,7 +41,7 @@ class WebContentsViewChildFrame : public WebContentsView,
RenderWidgetHostViewBase* CreateViewForWidget(
RenderWidgetHost* render_widget_host,
bool is_guest_view_hack) override;
- RenderWidgetHostViewBase* CreateViewForPopupWidget(
+ RenderWidgetHostViewBase* CreateViewForChildWidget(
RenderWidgetHost* render_widget_host) override;
void SetPageTitle(const base::string16& title) override;
void RenderViewCreated(RenderViewHost* host) override;
@@ -50,8 +50,6 @@ class WebContentsViewChildFrame : public WebContentsView,
RenderViewHost* new_host) override;
void SetOverscrollControllerEnabled(bool enabled) override;
#if defined(OS_MACOSX)
- void SetAllowOtherViews(bool allow) override;
- bool GetAllowOtherViews() const override;
bool IsEventTracking() const override;
void CloseTabAfterEventTracking() override;
#endif
diff --git a/chromium/content/browser/web_contents/web_contents_view_guest.cc b/chromium/content/browser/web_contents/web_contents_view_guest.cc
index 12f6817499e..5de4d7cf8a7 100644
--- a/chromium/content/browser/web_contents/web_contents_view_guest.cc
+++ b/chromium/content/browser/web_contents/web_contents_view_guest.cc
@@ -17,6 +17,7 @@
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/drag_messages.h"
+#include "content/public/browser/guest_mode.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/common/context_menu_params.h"
#include "content/public/common/drop_data.h"
@@ -45,6 +46,7 @@ WebContentsViewGuest::WebContentsViewGuest(
platform_view_(std::move(platform_view)),
platform_view_delegate_view_(*delegate_view) {
*delegate_view = this;
+ DCHECK(!GuestMode::IsCrossProcessFrameGuest(web_contents));
}
WebContentsViewGuest::~WebContentsViewGuest() {
@@ -72,14 +74,14 @@ void WebContentsViewGuest::OnGuestAttached(WebContentsView* parent_view) {
// view hierarchy. We add this view as embedder's child here.
// This would go in WebContentsViewGuest::CreateView, but that is too early to
// access embedder_web_contents(). Therefore, we do it here.
- if (!features::IsUsingWindowService())
+ if (!features::IsMultiProcessMash())
parent_view->GetNativeView()->AddChild(platform_view_->GetNativeView());
#endif // defined(USE_AURA)
}
void WebContentsViewGuest::OnGuestDetached(WebContentsView* old_parent_view) {
#if defined(USE_AURA)
- if (!features::IsUsingWindowService()) {
+ if (!features::IsMultiProcessMash()) {
old_parent_view->GetNativeView()->RemoveChild(
platform_view_->GetNativeView());
}
@@ -115,16 +117,6 @@ gfx::Rect WebContentsViewGuest::GetViewBounds() const {
return gfx::Rect(size_);
}
-#if defined(OS_MACOSX)
-void WebContentsViewGuest::SetAllowOtherViews(bool allow) {
- platform_view_->SetAllowOtherViews(allow);
-}
-
-bool WebContentsViewGuest::GetAllowOtherViews() const {
- return platform_view_->GetAllowOtherViews();
-}
-#endif
-
void WebContentsViewGuest::CreateView(const gfx::Size& initial_size,
gfx::NativeView context) {
platform_view_->CreateView(initial_size, context);
@@ -151,9 +143,9 @@ RenderWidgetHostViewBase* WebContentsViewGuest::CreateViewForWidget(
platform_widget->GetWeakPtr());
}
-RenderWidgetHostViewBase* WebContentsViewGuest::CreateViewForPopupWidget(
+RenderWidgetHostViewBase* WebContentsViewGuest::CreateViewForChildWidget(
RenderWidgetHost* render_widget_host) {
- return platform_view_->CreateViewForPopupWidget(render_widget_host);
+ return platform_view_->CreateViewForChildWidget(render_widget_host);
}
void WebContentsViewGuest::SetPageTitle(const base::string16& title) {
diff --git a/chromium/content/browser/web_contents/web_contents_view_guest.h b/chromium/content/browser/web_contents/web_contents_view_guest.h
index 9e3511a9dab..1f0e661628a 100644
--- a/chromium/content/browser/web_contents/web_contents_view_guest.h
+++ b/chromium/content/browser/web_contents/web_contents_view_guest.h
@@ -59,7 +59,7 @@ class WebContentsViewGuest : public WebContentsView,
RenderWidgetHostViewBase* CreateViewForWidget(
RenderWidgetHost* render_widget_host,
bool is_guest_view_hack) override;
- RenderWidgetHostViewBase* CreateViewForPopupWidget(
+ RenderWidgetHostViewBase* CreateViewForChildWidget(
RenderWidgetHost* render_widget_host) override;
void SetPageTitle(const base::string16& title) override;
void RenderViewCreated(RenderViewHost* host) override;
@@ -68,8 +68,6 @@ class WebContentsViewGuest : public WebContentsView,
RenderViewHost* new_host) override;
void SetOverscrollControllerEnabled(bool enabled) override;
#if defined(OS_MACOSX)
- void SetAllowOtherViews(bool allow) override;
- bool GetAllowOtherViews() const override;
bool IsEventTracking() const override;
void CloseTabAfterEventTracking() override;
#endif
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 7f80c1b1d82..d08876fc503 100644
--- a/chromium/content/browser/web_contents/web_contents_view_mac.h
+++ b/chromium/content/browser/web_contents/web_contents_view_mac.h
@@ -19,8 +19,10 @@
#include "content/browser/web_contents/web_contents_view.h"
#include "content/common/content_export.h"
#include "content/common/drag_event_source_info.h"
-#import "ui/base/cocoa/accessibility_hostable.h"
+#include "content/public/common/web_contents_ns_view_bridge.mojom.h"
+#include "mojo/public/cpp/bindings/associated_binding.h"
#import "ui/base/cocoa/base_view.h"
+#import "ui/base/cocoa/views_hostable.h"
#include "ui/gfx/geometry/size.h"
@class WebDragDest;
@@ -37,12 +39,8 @@ namespace gfx {
class Vector2d;
}
-namespace ui {
-class Layer;
-}
-
CONTENT_EXPORT
-@interface WebContentsViewCocoa : BaseView<AccessibilityHostable> {
+@interface WebContentsViewCocoa : BaseView<ViewsHostable> {
@private
// Instances of this class are owned by both webContentsView_ and AppKit. It
// is possible for an instance to outlive its webContentsView_. The
@@ -56,6 +54,12 @@ CONTENT_EXPORT
- (void)setMouseDownCanMoveWindow:(BOOL)canMove;
+// Sets |accessibilityParent| as the object returned when the
+// receiver is queried for its accessibility parent.
+// TODO(lgrey/ellyjones): Remove this in favor of setAccessibilityParent:
+// when we switch to the new accessibility API.
+- (void)setAccessibilityParentElement:(id)accessibilityParent;
+
// Returns the available drag operations. This is a required method for
// NSDraggingSource. It is supposedly deprecated, but the non-deprecated API
// -[NSWindow dragImage:...] still relies on it.
@@ -69,7 +73,9 @@ namespace content {
// contains all of the contents of the tab and associated child views.
class WebContentsViewMac : public WebContentsView,
public RenderViewHostDelegateView,
- public PopupMenuHelper::Delegate {
+ public PopupMenuHelper::Delegate,
+ public mojom::WebContentsNSViewClient,
+ public ui::ViewsHostableView {
public:
// The corresponding WebContentsImpl is passed in the constructor, and manages
// our lifetime. This doesn't need to be the case, but is this way currently
@@ -91,14 +97,12 @@ class WebContentsViewMac : public WebContentsView,
void FocusThroughTabTraversal(bool reverse) override;
DropData* GetDropData() const override;
gfx::Rect GetViewBounds() const override;
- void SetAllowOtherViews(bool allow) override;
- bool GetAllowOtherViews() const override;
void CreateView(const gfx::Size& initial_size,
gfx::NativeView context) override;
RenderWidgetHostViewBase* CreateViewForWidget(
RenderWidgetHost* render_widget_host,
bool is_guest_view_hack) override;
- RenderWidgetHostViewBase* CreateViewForPopupWidget(
+ RenderWidgetHostViewBase* CreateViewForChildWidget(
RenderWidgetHost* render_widget_host) override;
void SetPageTitle(const base::string16& title) override;
void RenderViewCreated(RenderViewHost* host) override;
@@ -134,12 +138,17 @@ class WebContentsViewMac : public WebContentsView,
// PopupMenuHelper::Delegate:
void OnMenuClosed() override;
+ // ViewsHostableView:
+ void OnViewsHostableAttached(ViewsHostableView::Host* host) override;
+ void OnViewsHostableDetached() override;
+ void OnViewsHostableShow(const gfx::Rect& bounds_in_window) override;
+ void OnViewsHostableHide() override;
+ void OnViewsHostableMakeFirstResponder() override;
+
// A helper method for closing the tab in the
// CloseTabAfterEventTracking() implementation.
void CloseTab();
- void SetParentUiLayer(ui::Layer* parent_ui_layer);
-
WebContentsImpl* web_contents() { return web_contents_; }
WebContentsViewDelegate* delegate() { return delegate_.get(); }
@@ -151,6 +160,10 @@ class WebContentsViewMac : public WebContentsView,
RenderWidgetHostViewCreateFunction create_render_widget_host_view);
private:
+ // Return the list of child RenderWidgetHostViewMacs. This will remove any
+ // destroyed instances before returning.
+ std::list<RenderWidgetHostViewMac*> GetChildViews();
+
// Returns the fullscreen view, if one exists; otherwise, returns the content
// native view. This ensures that the view currently attached to a NSWindow is
// being used to query or set first responder state.
@@ -165,9 +178,6 @@ class WebContentsViewMac : public WebContentsView,
// Our optional delegate.
std::unique_ptr<WebContentsViewDelegate> delegate_;
- // Whether to allow other views.
- bool allow_other_views_;
-
// This contains all RenderWidgetHostViewMacs that have been added as child
// NSViews to this NSView. Note that this list may contain RWHVMacs besides
// just |web_contents_->GetRenderWidgetHostView()|. The only time that the
@@ -175,10 +185,19 @@ class WebContentsViewMac : public WebContentsView,
// destroyed.
std::list<base::WeakPtr<RenderWidgetHostViewBase>> child_views_;
- ui::Layer* parent_ui_layer_ = nullptr;
+ // Interface to the views::View host of this view.
+ ViewsHostableView::Host* views_host_ = nullptr;
std::unique_ptr<PopupMenuHelper> popup_menu_helper_;
+ // The id that may be used to look up this NSView.
+ const uint64_t ns_view_id_;
+
+ // Mojo bindings for an out of process instance of this NSView.
+ mojom::WebContentsNSViewBridgeAssociatedPtr ns_view_bridge_remote_;
+ mojo::AssociatedBinding<mojom::WebContentsNSViewClient>
+ ns_view_client_binding_;
+
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 94848b56836..3374d2b122d 100644
--- a/chromium/content/browser/web_contents/web_contents_view_mac.mm
+++ b/chromium/content/browser/web_contents/web_contents_view_mac.mm
@@ -23,12 +23,15 @@
#import "content/browser/web_contents/web_drag_source_mac.h"
#include "content/common/view_messages.h"
#include "content/public/browser/interstitial_page.h"
+#include "content/public/browser/ns_view_bridge_factory_host.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/browser/web_contents_view_delegate.h"
+#include "mojo/public/cpp/bindings/interface_request.h"
#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/cocoa/ns_view_ids.h"
#include "ui/base/dragdrop/cocoa_dnd_util.h"
#include "ui/display/screen.h"
#include "ui/gfx/image/image_skia_util_mac.h"
@@ -107,10 +110,13 @@ WebContentsViewMac::WebContentsViewMac(WebContentsImpl* web_contents,
WebContentsViewDelegate* delegate)
: web_contents_(web_contents),
delegate_(delegate),
- allow_other_views_(false) {
-}
+ ns_view_id_(ui::NSViewIds::GetNewId()),
+ ns_view_client_binding_(this) {}
WebContentsViewMac::~WebContentsViewMac() {
+ if (views_host_)
+ views_host_->OnHostableViewDestroying();
+ DCHECK(!views_host_);
// This handles the case where a renderer close call was deferred
// while the user was operating a UI control which resulted in a
// close. In that case, the Cocoa view outlives the
@@ -322,21 +328,6 @@ gfx::Rect WebContentsViewMac::GetViewBounds() const {
return gfx::ScreenRectFromNSRect(window_bounds);
}
-void WebContentsViewMac::SetAllowOtherViews(bool allow) {
- if (allow_other_views_ == allow)
- return;
-
- allow_other_views_ = allow;
- RenderWidgetHostViewMac* view = static_cast<RenderWidgetHostViewMac*>(
- web_contents_->GetRenderWidgetHostView());
- if (view)
- view->SetAllowPauseForResizeOrRepaint(!allow_other_views_);
-}
-
-bool WebContentsViewMac::GetAllowOtherViews() const {
- return allow_other_views_;
-}
-
void WebContentsViewMac::CreateView(
const gfx::Size& initial_size, gfx::NativeView context) {
WebContentsViewCocoa* view =
@@ -369,11 +360,17 @@ RenderWidgetHostViewBase* WebContentsViewMac::CreateViewForWidget(
view->SetDelegate(rw_delegate.get());
}
- view->SetAllowPauseForResizeOrRepaint(!allow_other_views_);
// Add the RenderWidgetHostView to the ui::Layer heirarchy.
child_views_.push_back(view->GetWeakPtr());
- SetParentUiLayer(parent_ui_layer_);
+ if (views_host_) {
+ NSViewBridgeFactoryHost* factory_host =
+ NSViewBridgeFactoryHost::GetFromHostId(
+ views_host_->GetViewsFactoryHostId());
+
+ view->MigrateNSViewBridge(factory_host, ns_view_id_);
+ view->SetParentUiLayer(views_host_->GetUiLayer());
+ }
// 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
@@ -397,7 +394,7 @@ RenderWidgetHostViewBase* WebContentsViewMac::CreateViewForWidget(
return view;
}
-RenderWidgetHostViewBase* WebContentsViewMac::CreateViewForPopupWidget(
+RenderWidgetHostViewBase* WebContentsViewMac::CreateViewForChildWidget(
RenderWidgetHost* render_widget_host) {
RenderWidgetHostViewMac* view =
new RenderWidgetHostViewMac(render_widget_host, false);
@@ -449,19 +446,91 @@ void WebContentsViewMac::CloseTab() {
web_contents_->Close(web_contents_->GetRenderViewHost());
}
-void WebContentsViewMac::SetParentUiLayer(ui::Layer* parent_ui_layer) {
- parent_ui_layer_ = parent_ui_layer;
+std::list<RenderWidgetHostViewMac*> WebContentsViewMac::GetChildViews() {
// Remove any child NSViews that have been destroyed.
+ std::list<RenderWidgetHostViewMac*> result;
for (auto iter = child_views_.begin(); iter != child_views_.end();) {
- if (*iter)
- (*iter++)->SetParentUiLayer(parent_ui_layer);
- else
+ if (*iter) {
+ result.push_back(reinterpret_cast<RenderWidgetHostViewMac*>(iter->get()));
+ iter++;
+ } else {
iter = child_views_.erase(iter);
+ }
+ }
+ return result;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// WebContentsViewMac, ViewsHostableView:
+
+void WebContentsViewMac::OnViewsHostableAttached(
+ ViewsHostableView::Host* host) {
+ views_host_ = host;
+ [cocoa_view_
+ setAccessibilityParentElement:views_host_->GetAccessibilityElement()];
+
+ // Create an NSView in the target process, if one exists.
+ uint64_t factory_host_id = views_host_->GetViewsFactoryHostId();
+ NSViewBridgeFactoryHost* factory_host =
+ NSViewBridgeFactoryHost::GetFromHostId(factory_host_id);
+ if (factory_host) {
+ mojom::WebContentsNSViewClientAssociatedPtr client;
+ ns_view_client_binding_.Bind(mojo::MakeRequest(&client));
+ mojom::WebContentsNSViewBridgeAssociatedRequest bridge_request =
+ mojo::MakeRequest(&ns_view_bridge_remote_);
+
+ factory_host->GetFactory()->CreateWebContentsNSViewBridge(
+ ns_view_id_, client.PassInterface(), std::move(bridge_request));
+
+ ns_view_bridge_remote_->SetParentViewsNSView(views_host_->GetNSViewId());
+ } else if (factory_host_id != NSViewBridgeFactoryHost::kLocalDirectHostId) {
+ LOG(ERROR) << "Failed to look up NSViewBridgeFactoryHost!";
+ }
+
+ for (auto* rwhv_mac : GetChildViews()) {
+ rwhv_mac->MigrateNSViewBridge(factory_host, ns_view_id_);
+ rwhv_mac->SetParentUiLayer(views_host_->GetUiLayer());
}
}
+void WebContentsViewMac::OnViewsHostableDetached() {
+ DCHECK(views_host_);
+ views_host_ = nullptr;
+
+ for (auto* rwhv_mac : GetChildViews()) {
+ rwhv_mac->MigrateNSViewBridge(nullptr, 0);
+ rwhv_mac->SetParentUiLayer(nullptr);
+ }
+
+ [cocoa_view_ setAccessibilityParentElement:nil];
+
+ // Disconnect from the bridge. This will have the effect of destroying the
+ // associated bridge instance with its NSView.
+ ns_view_client_binding_.Close();
+ ns_view_bridge_remote_.reset();
+}
+
+void WebContentsViewMac::OnViewsHostableShow(
+ const gfx::Rect& bounds_in_window) {
+ if (ns_view_bridge_remote_)
+ ns_view_bridge_remote_->Show(bounds_in_window);
+}
+
+void WebContentsViewMac::OnViewsHostableHide() {
+ if (ns_view_bridge_remote_)
+ ns_view_bridge_remote_->Hide();
+}
+
+void WebContentsViewMac::OnViewsHostableMakeFirstResponder() {
+ if (ns_view_bridge_remote_)
+ ns_view_bridge_remote_->MakeFirstResponder();
+}
+
} // namespace content
+////////////////////////////////////////////////////////////////////////////////
+// WebContentsViewCocoa
+
@implementation WebContentsViewCocoa
- (id)initWithWebContentsViewMac:(WebContentsViewMac*)w {
@@ -674,11 +743,6 @@ void WebContentsViewMac::SetParentUiLayer(ui::Layer* parent_ui_layer) {
FocusThroughTabTraversal(direction == NSSelectingPrevious);
}
-- (void)cr_setParentUiLayer:(ui::Layer*)parentUiLayer {
- if (webContentsView_)
- webContentsView_->SetParentUiLayer(parentUiLayer);
-}
-
- (void)updateWebContentsVisibility {
WebContentsImpl* webContents = [self webContents];
if (!webContents || webContents->IsBeingDestroyed())
@@ -743,11 +807,15 @@ void WebContentsViewMac::SetParentUiLayer(ui::Layer* parent_ui_layer) {
[self updateWebContentsVisibility];
}
-// AccessibilityHostable protocol implementation.
- (void)setAccessibilityParentElement:(id)accessibilityParent {
accessibilityParent_.reset([accessibilityParent retain]);
}
+// ViewsHostable protocol implementation.
+- (ui::ViewsHostableView*)viewsHostableView {
+ return webContentsView_;
+}
+
// NSAccessibility informal protocol implementation.
- (id)accessibilityAttributeValue:(NSString*)attribute {
if (accessibilityParent_ &&
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 1ebcedb0875..32f12c77378 100644
--- a/chromium/content/browser/web_contents/web_drag_source_mac.mm
+++ b/chromium/content/browser/web_contents/web_drag_source_mac.mm
@@ -31,6 +31,7 @@
#include "net/base/escape.h"
#include "net/base/filename_util.h"
#include "net/base/mime_util.h"
+#include "ui/base/clipboard/clipboard_util_mac.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"
@@ -49,10 +50,6 @@ using content::RenderViewHostImpl;
namespace {
-// An unofficial standard pasteboard title type to be provided alongside the
-// |NSURLPboardType|.
-NSString* const kNSURLTitlePboardType = @"public.url-name";
-
// This helper's sole task is to write out data for a promised file; the caller
// is responsible for opening the file. It takes the drop data and an open file
// stream.
@@ -154,9 +151,9 @@ void PromiseWriterHelper(const DropData& drop_data,
}
[url writeToPasteboard:pboard];
// URL title.
- } else if ([type isEqualToString:kNSURLTitlePboardType]) {
+ } else if ([type isEqualToString:ui::kUTTypeURLName]) {
[pboard setString:SysUTF16ToNSString(dropData_->url_title)
- forType:kNSURLTitlePboardType];
+ forType:ui::kUTTypeURLName];
// File contents.
} else if ([type isEqualToString:base::mac::CFToNSCast(fileUTI_)]) {
@@ -348,7 +345,7 @@ void PromiseWriterHelper(const DropData& drop_data,
// URL (and title).
if (dropData_->url.is_valid()) {
- [pasteboard_ addTypes:@[ NSURLPboardType, kNSURLTitlePboardType ]
+ [pasteboard_ addTypes:@[ NSURLPboardType, ui::kUTTypeURLName ]
owner:contentsView_];
}
diff --git a/chromium/content/browser/web_package/mock_signed_exchange_handler.cc b/chromium/content/browser/web_package/mock_signed_exchange_handler.cc
index 2381c3b9e62..808e695ec5a 100644
--- a/chromium/content/browser/web_package/mock_signed_exchange_handler.cc
+++ b/chromium/content/browser/web_package/mock_signed_exchange_handler.cc
@@ -14,6 +14,7 @@
namespace content {
MockSignedExchangeHandler::MockSignedExchangeHandler(
+ SignedExchangeLoadResult result,
net::Error error,
const GURL& request_url,
const std::string& mime_type,
@@ -31,18 +32,20 @@ MockSignedExchangeHandler::MockSignedExchangeHandler(
head.headers->AddHeader(header);
}
base::SequencedTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(std::move(headers_callback), error, request_url,
- "GET", head, std::move(body)));
+ FROM_HERE, base::BindOnce(std::move(headers_callback), result, error,
+ request_url, "GET", head, std::move(body)));
}
MockSignedExchangeHandler::~MockSignedExchangeHandler() {}
MockSignedExchangeHandlerFactory::MockSignedExchangeHandlerFactory(
+ SignedExchangeLoadResult result,
net::Error error,
const GURL& request_url,
const std::string& mime_type,
std::vector<std::string> response_headers)
- : error_(error),
+ : result_(result),
+ error_(error),
request_url_(request_url),
mime_type_(mime_type),
response_headers_(std::move(response_headers)) {}
@@ -54,8 +57,8 @@ std::unique_ptr<SignedExchangeHandler> MockSignedExchangeHandlerFactory::Create(
ExchangeHeadersCallback headers_callback,
std::unique_ptr<SignedExchangeCertFetcherFactory> cert_fetcher_factory) {
return std::make_unique<MockSignedExchangeHandler>(
- error_, request_url_, mime_type_, response_headers_, std::move(body),
- std::move(headers_callback));
+ result_, error_, request_url_, mime_type_, response_headers_,
+ std::move(body), std::move(headers_callback));
}
} // namespace content
diff --git a/chromium/content/browser/web_package/mock_signed_exchange_handler.h b/chromium/content/browser/web_package/mock_signed_exchange_handler.h
index 6c7bf97cd14..2b8d6e4042f 100644
--- a/chromium/content/browser/web_package/mock_signed_exchange_handler.h
+++ b/chromium/content/browser/web_package/mock_signed_exchange_handler.h
@@ -17,7 +17,8 @@ class SignedExchangeCertFetcherFactory;
class MockSignedExchangeHandler final : public SignedExchangeHandler {
public:
- MockSignedExchangeHandler(net::Error error,
+ MockSignedExchangeHandler(SignedExchangeLoadResult result,
+ net::Error error,
const GURL& request_url,
const std::string& mime_type,
const std::vector<std::string>& response_headers,
@@ -36,11 +37,12 @@ class MockSignedExchangeHandlerFactory final
SignedExchangeHandler::ExchangeHeadersCallback;
// Creates a factory that creates SignedExchangeHandler which always fires
- // a headers callback with the given |error|, |request_url|, |mime_type|
- // and |response_headers|.
+ // a headers callback with the given |result|, |error|, |request_url|,
+ // |mime_type| and |response_headers|.
// |mime_type| and |response_headers| are ignored if |error| is not
// net::OK.
- MockSignedExchangeHandlerFactory(net::Error error,
+ MockSignedExchangeHandlerFactory(SignedExchangeLoadResult result,
+ net::Error error,
const GURL& request_url,
const std::string& mime_type,
std::vector<std::string> response_headers);
@@ -53,6 +55,7 @@ class MockSignedExchangeHandlerFactory final
override;
private:
+ const SignedExchangeLoadResult result_;
const net::Error error_;
const GURL request_url_;
const std::string mime_type_;
diff --git a/chromium/content/browser/web_package/origins_list.cc b/chromium/content/browser/web_package/origins_list.cc
new file mode 100644
index 00000000000..05faed760c2
--- /dev/null
+++ b/chromium/content/browser/web_package/origins_list.cc
@@ -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.
+
+#include "content/browser/web_package/origins_list.h"
+
+#include "base/strings/string_split.h"
+#include "url/gurl.h"
+
+namespace content {
+namespace signed_exchange_utils {
+
+constexpr char kSubdomainMatchPrefix[] = "*.";
+
+OriginsList::OriginsList() = default;
+
+OriginsList::OriginsList(base::StringPiece str) {
+ std::vector<base::StringPiece> elements = base::SplitStringPiece(
+ str, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+
+ for (base::StringPiece element : elements) {
+ bool subdomain_match = false;
+ if (base::StartsWith(element, kSubdomainMatchPrefix,
+ base::CompareCase::SENSITIVE)) {
+ subdomain_match = true;
+ element.remove_prefix(sizeof(kSubdomainMatchPrefix) - 1);
+ }
+ if (base::StartsWith(element,
+ "https:", base::CompareCase::INSENSITIVE_ASCII)) {
+ LOG(ERROR) << "OriginsList entry should omit https scheme: \"" << element
+ << "\"";
+ continue;
+ }
+
+ std::string url_str("https://");
+ element.AppendToString(&url_str);
+ GURL url(url_str);
+ if (!url.is_valid()) {
+ LOG(ERROR) << "Failed to parse an OriginsList entry to a valid Origin: \""
+ << element << "\"";
+ continue;
+ }
+ DCHECK(url.SchemeIs("https"));
+
+ url::Origin origin = url::Origin::Create(url);
+ if (subdomain_match) {
+ subdomain_match_origins_.push_back(origin);
+ } else {
+ exact_match_origins_.insert(origin);
+ }
+ }
+}
+
+OriginsList::OriginsList(OriginsList&&) = default;
+OriginsList::~OriginsList() = default;
+
+bool OriginsList::IsEmpty() const {
+ return exact_match_origins_.empty() && subdomain_match_origins_.empty();
+}
+
+bool OriginsList::Match(const url::Origin& origin) const {
+ // OriginsList only contains HTTPS scheme origins.
+ if (origin.scheme() != url::kHttpsScheme) {
+ return false;
+ }
+
+ if (exact_match_origins_.find(origin) != exact_match_origins_.end()) {
+ return true;
+ }
+
+ for (const auto& subdomain_match_origin : subdomain_match_origins_) {
+ if (origin.DomainIs(subdomain_match_origin.host()) &&
+ origin.port() == subdomain_match_origin.port()) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+} // namespace signed_exchange_utils
+} // namespace content
diff --git a/chromium/content/browser/web_package/origins_list.h b/chromium/content/browser/web_package/origins_list.h
new file mode 100644
index 00000000000..4bd3cff8cac
--- /dev/null
+++ b/chromium/content/browser/web_package/origins_list.h
@@ -0,0 +1,52 @@
+// 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_ORIGINS_LIST_H_
+#define CONTENT_BROWSER_WEB_PACKAGE_ORIGINS_LIST_H_
+
+#include <vector>
+
+#include "base/containers/flat_set.h"
+#include "base/strings/string_piece.h"
+#include "content/common/content_export.h"
+#include "url/origin.h"
+
+namespace content {
+namespace signed_exchange_utils {
+
+// OriginsList can query if a particular origin |Match|.
+// OriginsList can only match HTTPS origins.
+class CONTENT_EXPORT OriginsList {
+ public:
+ OriginsList();
+
+ // Creates an OriginsList from comma-separated list of hosts.
+ //
+ // Entries starting with "*." will match with subdomains.
+ //
+ // For example, "example.com,*.google.com" will create an
+ // OriginsList that match exactly "example.com" but not its
+ // subdomains, and all subdomains of "google.com".
+ //
+ // Note: Entries should NOT start with "https://", but start from hostname.
+ explicit OriginsList(base::StringPiece str);
+
+ OriginsList(OriginsList&&);
+ ~OriginsList();
+
+ // Returns true when |this| has an empty list to match
+ // (i.e. no origins would match).
+ bool IsEmpty() const;
+
+ bool Match(const url::Origin& origin) const;
+
+ private:
+ base::flat_set<url::Origin> exact_match_origins_;
+ std::vector<url::Origin> subdomain_match_origins_;
+};
+
+} // namespace signed_exchange_utils
+} // namespace content
+
+#endif // CONTENT_BROWSER_WEB_PACKAGE_ORIGINS_LIST_H_
diff --git a/chromium/content/browser/web_package/origins_list_unittest.cc b/chromium/content/browser/web_package/origins_list_unittest.cc
new file mode 100644
index 00000000000..3338a3b978d
--- /dev/null
+++ b/chromium/content/browser/web_package/origins_list_unittest.cc
@@ -0,0 +1,77 @@
+// 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/origins_list.h"
+
+#include "base/callback.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+#include "url/origin.h"
+
+namespace content {
+namespace signed_exchange_utils {
+
+TEST(OriginsList, IsEmpty) {
+ OriginsList origins_list;
+ EXPECT_TRUE(origins_list.IsEmpty());
+}
+
+TEST(OriginsList, ExactMatch) {
+ OriginsList origins_list(
+ "example.com,test.example.com,https://invalid.entry,example.net:1234");
+
+ EXPECT_FALSE(origins_list.IsEmpty());
+
+ static constexpr const char* kShouldMatchList[] = {
+ "https://example.com", "https://test.example.com",
+ "https://example.net:1234",
+ };
+
+ for (const char* should_match : kShouldMatchList) {
+ EXPECT_TRUE(origins_list.Match(url::Origin::Create(GURL(should_match))))
+ << "OriginList should match url: " << should_match;
+ }
+
+ static constexpr const char* kShouldNotMatchList[] = {
+ "http://example.com", "https://subdomain.example.com",
+ "https://notexample.com", "https://invalid.entry",
+ "https://example.net", "https://example.net:5432",
+ };
+
+ for (const char* should_not_match : kShouldNotMatchList) {
+ EXPECT_FALSE(
+ origins_list.Match(url::Origin::Create(GURL(should_not_match))))
+ << "OriginList should not match url: " << should_not_match;
+ }
+}
+
+TEST(OriginsList, SubdomainMatch) {
+ OriginsList origins_list("*.example.com,*.example.net:1234");
+
+ EXPECT_FALSE(origins_list.IsEmpty());
+
+ static constexpr const char* kShouldMatchList[] = {
+ "https://example.com", "https://test.example.com",
+ "https://test.test2.example.com", "https://test.example.net:1234",
+ };
+
+ for (const char* should_match : kShouldMatchList) {
+ EXPECT_TRUE(origins_list.Match(url::Origin::Create(GURL(should_match))))
+ << "OriginList should match url: " << should_match;
+ }
+
+ static constexpr const char* kShouldNotMatchList[] = {
+ "http://example.com", "https://notexample.com",
+ "https://test.example.net", "https://test.example.net:5432",
+ };
+
+ for (const char* should_not_match : kShouldNotMatchList) {
+ EXPECT_FALSE(
+ origins_list.Match(url::Origin::Create(GURL(should_not_match))))
+ << "OriginList should not match url: " << should_not_match;
+ }
+}
+
+} // namespace signed_exchange_utils
+} // namespace content
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 90dd7610d3e..123e653bff7 100644
--- a/chromium/content/browser/web_package/signed_exchange_cert_fetcher.cc
+++ b/chromium/content/browser/web_package/signed_exchange_cert_fetcher.cc
@@ -5,6 +5,7 @@
#include "content/browser/web_package/signed_exchange_cert_fetcher.h"
#include "base/format_macros.h"
+#include "base/metrics/histogram_macros.h"
#include "base/numerics/safe_conversions.h"
#include "base/strings/string_piece.h"
#include "base/strings/stringprintf.h"
@@ -147,7 +148,7 @@ void SignedExchangeCertFetcher::Abort() {
handle_watcher_ = nullptr;
body_string_.clear();
devtools_proxy_ = nullptr;
- std::move(callback_).Run(nullptr);
+ std::move(callback_).Run(SignedExchangeLoadResult::kCertFetchError, nullptr);
}
void SignedExchangeCertFetcher::OnHandleReady(MojoResult result) {
@@ -191,10 +192,12 @@ void SignedExchangeCertFetcher::OnDataComplete() {
if (!cert_chain) {
signed_exchange_utils::ReportErrorAndTraceEvent(
devtools_proxy_, "Failed to get certificate chain from message.");
- std::move(callback_).Run(nullptr);
+ std::move(callback_).Run(SignedExchangeLoadResult::kCertParseError,
+ nullptr);
return;
}
- std::move(callback_).Run(std::move(cert_chain));
+ std::move(callback_).Run(SignedExchangeLoadResult::kSuccess,
+ std::move(cert_chain));
}
// network::mojom::URLLoaderClient
@@ -243,6 +246,9 @@ void SignedExchangeCertFetcher::OnReceiveResponse(
}
body_string_.reserve(head.content_length);
}
+
+ UMA_HISTOGRAM_BOOLEAN("SignedExchange.CertificateFetch.CacheHit",
+ head.was_fetched_via_cache);
}
void SignedExchangeCertFetcher::OnReceiveRedirect(
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 679ed5f7eba..d3fdbc631fe 100644
--- a/chromium/content/browser/web_package/signed_exchange_cert_fetcher.h
+++ b/chromium/content/browser/web_package/signed_exchange_cert_fetcher.h
@@ -14,6 +14,7 @@
#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_error.h"
#include "content/common/content_export.h"
#include "services/network/public/mojom/url_loader.mojom.h"
#include "url/origin.h"
@@ -36,7 +37,8 @@ class CONTENT_EXPORT SignedExchangeCertFetcher
: public network::mojom::URLLoaderClient {
public:
using CertificateCallback =
- base::OnceCallback<void(std::unique_ptr<SignedExchangeCertificateChain>)>;
+ base::OnceCallback<void(SignedExchangeLoadResult,
+ std::unique_ptr<SignedExchangeCertificateChain>)>;
// Starts fetching the certificate using a ThrottlingURLLoader created with
// the |shared_url_loader_factory| and the |throttles|. The |callback| will
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 104dbe1498c..f25ee99ca6f 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
@@ -137,8 +137,11 @@ class URLLoaderFactoryForMockLoader final
void ForwardCertificateCallback(
bool* called,
+ SignedExchangeLoadResult* out_result,
std::unique_ptr<SignedExchangeCertificateChain>* out_cert,
+ SignedExchangeLoadResult result,
std::unique_ptr<SignedExchangeCertificateChain> cert_chain) {
+ *out_result = result;
*called = true;
*out_cert = std::move(cert_chain);
}
@@ -206,7 +209,7 @@ class SignedExchangeCertFetcherTest : public testing::Test {
bool force_fetch) {
SignedExchangeCertFetcher::CertificateCallback callback = base::BindOnce(
&ForwardCertificateCallback, base::Unretained(&callback_called_),
- base::Unretained(&cert_result_));
+ base::Unretained(&result_), base::Unretained(&cert_result_));
return SignedExchangeCertFetcher::CreateAndStart(
base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
@@ -240,6 +243,7 @@ class SignedExchangeCertFetcherTest : public testing::Test {
const GURL url_;
const url::Origin request_initiator_;
bool callback_called_ = false;
+ SignedExchangeLoadResult result_;
std::unique_ptr<SignedExchangeCertificateChain> cert_result_;
URLLoaderFactoryForMockLoader mock_loader_factory_;
std::vector<std::unique_ptr<URLLoaderThrottle>> throttles_;
@@ -275,6 +279,7 @@ TEST_F(SignedExchangeCertFetcherTest, Simple) {
network::URLLoaderCompletionStatus(net::OK));
RunUntilIdle();
EXPECT_TRUE(callback_called_);
+ EXPECT_EQ(SignedExchangeLoadResult::kSuccess, result_);
ASSERT_TRUE(cert_result_);
EXPECT_EQ(GetTestDataCertFingerprint256(),
cert_result_->cert()->CalculateChainFingerprint256());
@@ -301,6 +306,7 @@ TEST_F(SignedExchangeCertFetcherTest, MultipleChunked) {
RunUntilIdle();
EXPECT_TRUE(callback_called_);
+ EXPECT_EQ(SignedExchangeLoadResult::kSuccess, result_);
ASSERT_TRUE(cert_result_);
EXPECT_EQ(certificate->CalculateChainFingerprint256(),
cert_result_->cert()->CalculateChainFingerprint256());
@@ -325,6 +331,7 @@ TEST_F(SignedExchangeCertFetcherTest, ForceFetchAndFail) {
RunUntilIdle();
EXPECT_TRUE(callback_called_);
+ EXPECT_EQ(SignedExchangeLoadResult::kCertFetchError, result_);
EXPECT_FALSE(cert_result_);
}
@@ -348,6 +355,7 @@ TEST_F(SignedExchangeCertFetcherTest, MaxCertSize_Exceeds) {
RunUntilIdle();
EXPECT_TRUE(callback_called_);
+ EXPECT_EQ(SignedExchangeLoadResult::kCertFetchError, result_);
EXPECT_FALSE(cert_result_);
}
@@ -371,6 +379,7 @@ TEST_F(SignedExchangeCertFetcherTest, MaxCertSize_SameSize) {
RunUntilIdle();
EXPECT_TRUE(callback_called_);
+ EXPECT_EQ(SignedExchangeLoadResult::kSuccess, result_);
EXPECT_TRUE(cert_result_);
}
@@ -398,6 +407,7 @@ TEST_F(SignedExchangeCertFetcherTest, MaxCertSize_MultipleChunked) {
RunUntilIdle();
EXPECT_TRUE(callback_called_);
+ EXPECT_EQ(SignedExchangeLoadResult::kCertFetchError, result_);
EXPECT_FALSE(cert_result_);
}
@@ -425,6 +435,7 @@ TEST_F(SignedExchangeCertFetcherTest, MaxCertSize_ContentLengthCheck) {
RunUntilIdle();
EXPECT_TRUE(callback_called_);
+ EXPECT_EQ(SignedExchangeLoadResult::kCertFetchError, result_);
EXPECT_FALSE(cert_result_);
}
@@ -438,6 +449,7 @@ TEST_F(SignedExchangeCertFetcherTest, Abort_Redirect) {
RunUntilIdle();
EXPECT_TRUE(callback_called_);
+ EXPECT_EQ(SignedExchangeLoadResult::kCertFetchError, result_);
EXPECT_FALSE(cert_result_);
}
@@ -451,6 +463,7 @@ TEST_F(SignedExchangeCertFetcherTest, Abort_404) {
RunUntilIdle();
EXPECT_TRUE(callback_called_);
+ EXPECT_EQ(SignedExchangeLoadResult::kCertFetchError, result_);
EXPECT_FALSE(cert_result_);
}
@@ -467,6 +480,7 @@ TEST_F(SignedExchangeCertFetcherTest, WrongMimeType) {
RunUntilIdle();
EXPECT_TRUE(callback_called_);
+ EXPECT_EQ(SignedExchangeLoadResult::kCertFetchError, result_);
EXPECT_FALSE(cert_result_);
}
@@ -485,6 +499,7 @@ TEST_F(SignedExchangeCertFetcherTest, Invalid_CertData) {
RunUntilIdle();
EXPECT_TRUE(callback_called_);
+ EXPECT_EQ(SignedExchangeLoadResult::kCertParseError, result_);
EXPECT_FALSE(cert_result_);
}
@@ -506,6 +521,7 @@ TEST_F(SignedExchangeCertFetcherTest, Invalid_CertMessage) {
RunUntilIdle();
EXPECT_TRUE(callback_called_);
+ EXPECT_EQ(SignedExchangeLoadResult::kCertParseError, result_);
EXPECT_FALSE(cert_result_);
}
@@ -541,6 +557,7 @@ TEST_F(SignedExchangeCertFetcherTest, Throttle_Simple) {
RunUntilIdle();
EXPECT_TRUE(callback_called_);
+ EXPECT_EQ(SignedExchangeLoadResult::kSuccess, result_);
ASSERT_TRUE(cert_result_);
EXPECT_EQ(GetTestDataCertFingerprint256(),
cert_result_->cert()->CalculateChainFingerprint256());
@@ -557,6 +574,7 @@ TEST_F(SignedExchangeCertFetcherTest, Throttle_AbortsOnRequest) {
RunUntilIdle();
EXPECT_TRUE(callback_called_);
+ EXPECT_EQ(SignedExchangeLoadResult::kCertFetchError, result_);
EXPECT_FALSE(cert_result_);
}
@@ -583,6 +601,7 @@ TEST_F(SignedExchangeCertFetcherTest, Throttle_AbortsOnRedirect) {
RunUntilIdle();
EXPECT_TRUE(callback_called_);
+ EXPECT_EQ(SignedExchangeLoadResult::kCertFetchError, result_);
EXPECT_FALSE(cert_result_);
}
@@ -615,6 +634,7 @@ TEST_F(SignedExchangeCertFetcherTest, Throttle_AbortsOnResponse) {
RunUntilIdle();
EXPECT_TRUE(callback_called_);
+ EXPECT_EQ(SignedExchangeLoadResult::kCertFetchError, result_);
EXPECT_FALSE(cert_result_);
}
@@ -694,6 +714,7 @@ TEST_F(SignedExchangeCertFetcherTest, CloseClientPipe_BeforeReceiveResponse) {
RunUntilIdle();
EXPECT_TRUE(callback_called_);
+ EXPECT_EQ(SignedExchangeLoadResult::kCertFetchError, result_);
EXPECT_FALSE(cert_result_);
}
@@ -706,6 +727,7 @@ TEST_F(SignedExchangeCertFetcherTest, CloseClientPipe_BeforeResponseBody) {
RunUntilIdle();
EXPECT_TRUE(callback_called_);
+ EXPECT_EQ(SignedExchangeLoadResult::kCertFetchError, result_);
EXPECT_FALSE(cert_result_);
}
@@ -727,6 +749,8 @@ TEST_F(SignedExchangeCertFetcherTest, CloseClientPipe_WhileReceivingBody) {
data_pipe.producer_handle.reset();
RunUntilIdle();
EXPECT_TRUE(callback_called_);
+ // SignedExchangeCertFetcher receives a truncated cert cbor.
+ EXPECT_EQ(SignedExchangeLoadResult::kCertParseError, result_);
EXPECT_FALSE(cert_result_);
}
@@ -748,6 +772,7 @@ TEST_F(SignedExchangeCertFetcherTest, CloseClientPipe_AfterReceivingBody) {
RunUntilIdle();
EXPECT_TRUE(callback_called_);
+ EXPECT_EQ(SignedExchangeLoadResult::kSuccess, result_);
ASSERT_TRUE(cert_result_);
EXPECT_EQ(certificate->CalculateChainFingerprint256(),
cert_result_->cert()->CalculateChainFingerprint256());
@@ -769,6 +794,7 @@ TEST_F(SignedExchangeCertFetcherTest, DataURL) {
network::URLLoaderCompletionStatus(net::OK));
RunUntilIdle();
EXPECT_TRUE(callback_called_);
+ EXPECT_EQ(SignedExchangeLoadResult::kSuccess, result_);
ASSERT_TRUE(cert_result_);
EXPECT_EQ(GetTestDataCertFingerprint256(),
cert_result_->cert()->CalculateChainFingerprint256());
@@ -786,6 +812,7 @@ TEST_F(SignedExchangeCertFetcherTest, DataURLWithWrongMimeType) {
RunUntilIdle();
EXPECT_TRUE(callback_called_);
+ EXPECT_EQ(SignedExchangeLoadResult::kCertFetchError, result_);
}
} // namespace content
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 b20f7349a38..62ce9d5178d 100644
--- a/chromium/content/browser/web_package/signed_exchange_certificate_chain.h
+++ b/chromium/content/browser/web_package/signed_exchange_certificate_chain.h
@@ -46,7 +46,6 @@ class CONTENT_EXPORT SignedExchangeCertificateChain {
private:
scoped_refptr<net::X509Certificate> cert_;
- // Version b1 specific fields:
std::string ocsp_;
std::string sct_;
};
diff --git a/chromium/content/browser/web_package/signed_exchange_consts.h b/chromium/content/browser/web_package/signed_exchange_consts.h
index 4f18d332992..34335031540 100644
--- a/chromium/content/browser/web_package/signed_exchange_consts.h
+++ b/chromium/content/browser/web_package/signed_exchange_consts.h
@@ -10,7 +10,7 @@ namespace content {
constexpr char kAcceptHeaderSignedExchangeSuffix[] =
",application/signed-exchange;v=b2";
-enum class SignedExchangeVersion { kB2 };
+enum class SignedExchangeVersion { kUnknown, kB2 };
// 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
diff --git a/chromium/content/browser/web_package/signed_exchange_devtools_proxy.cc b/chromium/content/browser/web_package/signed_exchange_devtools_proxy.cc
index 44f40ccf461..918b99c9e8d 100644
--- a/chromium/content/browser/web_package/signed_exchange_devtools_proxy.cc
+++ b/chromium/content/browser/web_package/signed_exchange_devtools_proxy.cc
@@ -4,11 +4,13 @@
#include "content/browser/web_package/signed_exchange_devtools_proxy.h"
+#include "base/task/post_task.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_envelope.h"
#include "content/browser/web_package/signed_exchange_error.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
@@ -112,8 +114,8 @@ void SignedExchangeDevToolsProxy::ReportError(
base::Optional<SignedExchangeError::FieldIndexPair> error_field) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
errors_.push_back(SignedExchangeError(message, std::move(error_field)));
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&AddErrorMessageToConsoleOnUI, frame_tree_node_id_getter_,
std::move(message)));
}
@@ -124,8 +126,8 @@ void SignedExchangeDevToolsProxy::CertificateRequestSent(
if (!devtools_enabled_)
return;
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(
&CertificateRequestSentOnUI, frame_tree_node_id_getter_, request_id,
devtools_navigation_token_ ? *devtools_navigation_token_ : request_id,
@@ -143,8 +145,8 @@ void SignedExchangeDevToolsProxy::CertificateResponseReceived(
auto resource_response = base::MakeRefCounted<network::ResourceResponse>();
resource_response->head = head;
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(
&CertificateResponseReceivedOnUI, frame_tree_node_id_getter_,
request_id,
@@ -157,8 +159,8 @@ void SignedExchangeDevToolsProxy::CertificateRequestCompleted(
const network::URLLoaderCompletionStatus& status) {
if (!devtools_enabled_)
return;
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&CertificateRequestCompletedOnUI,
frame_tree_node_id_getter_, request_id, status));
}
@@ -178,8 +180,8 @@ void SignedExchangeDevToolsProxy::OnSignedExchangeReceived(
auto resource_response = base::MakeRefCounted<network::ResourceResponse>();
resource_response->head = outer_response_;
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&OnSignedExchangeReceivedOnUI, frame_tree_node_id_getter_,
outer_request_url_, resource_response->DeepCopy(),
devtools_navigation_token_, envelope, certificate,
diff --git a/chromium/content/browser/web_package/signed_exchange_envelope.cc b/chromium/content/browser/web_package/signed_exchange_envelope.cc
index 96f2750eadc..1b2d42e855c 100644
--- a/chromium/content/browser/web_package/signed_exchange_envelope.cc
+++ b/chromium/content/browser/web_package/signed_exchange_envelope.cc
@@ -23,7 +23,7 @@ namespace content {
namespace {
-// IsStateful{Request,Response}Header return true if |name| is a stateful
+// IsStateful{Request,Response}Header returns true if |name| is a stateful
// header field. Stateful header fields will cause validation failure of
// signed exchanges.
// Note that |name| must be lower-cased.
@@ -180,20 +180,6 @@ bool ParseResponseMap(const cbor::CBORValue& value,
devtools_proxy, "Failed to parse status code to integer.");
return false;
}
- // https://wicg.github.io/webpackage/loading.html#parsing-b1
- // Step 26. If parsedExchange’s response's status is a redirect status or the
- // signed exchange version of parsedExchange’s response is not
- // undefined, return a failure. [spec text]
- // TODO(crbug.com/803774): Reject if inner response is a signed exchange.
- if (net::HttpResponseHeaders::IsRedirectResponseCode(response_code)) {
- signed_exchange_utils::ReportErrorAndTraceEvent(
- devtools_proxy,
- base::StringPrintf(
- "Exchange's response status must not be a redirect status. "
- "status: %d",
- response_code));
- return false;
- }
out->set_response_code(static_cast<net::HttpStatusCode>(response_code));
for (const auto& it : response_map) {
@@ -224,7 +210,7 @@ bool ParseResponseMap(const cbor::CBORValue& value,
return false;
}
- // 4. If exchange’s headers contain a stateful header field, as defined in
+ // 4. If exchange’s headers contains a stateful header field, as defined in
// Section 4.1, return “invalid”. [spec text]
if (IsStatefulResponseHeader(name_str)) {
signed_exchange_utils::ReportErrorAndTraceEvent(
@@ -249,6 +235,37 @@ bool ParseResponseMap(const cbor::CBORValue& value,
return false;
}
}
+
+ // https://wicg.github.io/webpackage/loading.html#parsing-b1
+ // Step 26. If parsedExchange’s response's status is a redirect status or the
+ // signed exchange version of parsedExchange’s response is not
+ // undefined, return a failure. [spec text]
+ if (net::HttpResponseHeaders::IsRedirectResponseCode(out->response_code())) {
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy,
+ base::StringPrintf(
+ "Exchange's response status must not be a redirect status. "
+ "status: %d",
+ response_code));
+ return false;
+ }
+ // Note: This does not reject content-type like "application/signed-exchange"
+ // (no "v=" parameter). In that case, SignedExchangeRequestHandler does not
+ // handle the inner response and UA just downloads it.
+ // See https://github.com/WICG/webpackage/issues/299 for details.
+ auto found = out->response_headers().find("content-type");
+ if (found != out->response_headers().end() &&
+ signed_exchange_utils::GetSignedExchangeVersion(found->second)
+ .has_value()) {
+ signed_exchange_utils::ReportErrorAndTraceEvent(
+ devtools_proxy,
+ base::StringPrintf(
+ "Exchange's inner response must not be a signed-exchange. "
+ "conetent-type: %s",
+ found->second.c_str()));
+ return false;
+ }
+
return true;
}
diff --git a/chromium/content/browser/web_package/signed_exchange_envelope.h b/chromium/content/browser/web_package/signed_exchange_envelope.h
index 6903b8eb536..1b7026dd8e7 100644
--- a/chromium/content/browser/web_package/signed_exchange_envelope.h
+++ b/chromium/content/browser/web_package/signed_exchange_envelope.h
@@ -33,7 +33,7 @@ class CONTENT_EXPORT SignedExchangeEnvelope {
// Parse headers from the application/signed-exchange;v=b2 format.
// https://wicg.github.io/webpackage/draft-yasskin-httpbis-origin-signed-exchanges-impl.html#application-signed-exchange
//
- // This also performs the step 1, 3 and 4 of "Cross-origin trust" validation.
+ // This also performs the steps 1, 3 and 4 of "Cross-origin trust" validation.
// https://wicg.github.io/webpackage/draft-yasskin-httpbis-origin-signed-exchanges-impl.html#cross-origin-trust
static base::Optional<SignedExchangeEnvelope> Parse(
const GURL& fallback_url,
diff --git a/chromium/content/browser/web_package/signed_exchange_envelope_unittest.cc b/chromium/content/browser/web_package/signed_exchange_envelope_unittest.cc
index 919019bdfdf..99c7963f889 100644
--- a/chromium/content/browser/web_package/signed_exchange_envelope_unittest.cc
+++ b/chromium/content/browser/web_package/signed_exchange_envelope_unittest.cc
@@ -229,4 +229,15 @@ TEST(SignedExchangeEnvelopeTest, InvalidValidityURLHeader) {
ASSERT_FALSE(header.has_value());
}
+TEST(SignedExchangeEnvelopeTest, InnerResponseIsSXG) {
+ auto header = GenerateHeaderAndParse(
+ GURL("https://test.example.org/test/"), kSignatureString,
+ {
+ {kMethodKey, "GET"},
+ },
+ {{kStatusKey, "200"},
+ {"content-type", "application/signed-exchange;v=b2"}});
+ ASSERT_FALSE(header.has_value());
+}
+
} // namespace content
diff --git a/chromium/content/browser/web_package/signed_exchange_error.h b/chromium/content/browser/web_package/signed_exchange_error.h
index 50856c66d4b..36343ce4c77 100644
--- a/chromium/content/browser/web_package/signed_exchange_error.h
+++ b/chromium/content/browser/web_package/signed_exchange_error.h
@@ -13,6 +13,37 @@
namespace content {
+// This enum is used for recording histograms. Treat as append-only.
+enum class SignedExchangeLoadResult {
+ kSuccess,
+ // SXG was served from non-secure origin.
+ kSXGServedFromNonHTTPS,
+ // SXG parse error (couldn't extract fallback URL).
+ kFallbackURLParseError,
+ // Unsupported version of SXG (could extract fallback URL).
+ kVersionMismatch,
+ // SXG parse error (could extract fallback URL).
+ kHeaderParseError,
+ // Network error occurred while loading SXG header.
+ kSXGHeaderNetError,
+ // Failed to fetch certificate chain.
+ kCertFetchError,
+ // Failed to parse certificate chain.
+ kCertParseError,
+ // Signature verification failed.
+ kSignatureVerificationError,
+ // Cert verification failed.
+ kCertVerificationError,
+ // CT verification failed.
+ kCTVerificationError,
+ // OCSP check failed.
+ kOCSPError,
+ // Certificate Requirements aren't met.
+ // https://wicg.github.io/webpackage/draft-yasskin-http-origin-signed-responses.html#cross-origin-cert-req
+ kCertRequirementsNotMet,
+ kMaxValue = kCertRequirementsNotMet
+};
+
struct SignedExchangeError {
public:
enum class Field {
diff --git a/chromium/content/browser/web_package/signed_exchange_handler.cc b/chromium/content/browser/web_package/signed_exchange_handler.cc
index a2c5fb82f99..cca3568de10 100644
--- a/chromium/content/browser/web_package/signed_exchange_handler.cc
+++ b/chromium/content/browser/web_package/signed_exchange_handler.cc
@@ -4,7 +4,10 @@
#include "content/browser/web_package/signed_exchange_handler.h"
+#include "base/metrics/histogram_functions.h"
+#include "base/metrics/histogram_macros.h"
#include "base/strings/stringprintf.h"
+#include "base/task/post_task.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
#include "content/browser/frame_host/frame_tree_node.h"
@@ -18,6 +21,7 @@
#include "content/browser/web_package/signed_exchange_prologue.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_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/storage_partition.h"
@@ -46,6 +50,16 @@ namespace content {
namespace {
constexpr char kDigestHeader[] = "Digest";
+constexpr char kHistogramSignatureVerificationResult[] =
+ "SignedExchange.SignatureVerificationResult";
+constexpr char kHistogramCertVerificationResult[] =
+ "SignedExchange.CertVerificationResult";
+constexpr char kHistogramCTVerificationResult[] =
+ "SignedExchange.CTVerificationResult";
+constexpr char kHistogramOCSPResponseStatus[] =
+ "SignedExchange.OCSPResponseStatus";
+constexpr char kHistogramOCSPRevocationStatus[] =
+ "SignedExchange.OCSPRevocationStatus";
network::mojom::NetworkContext* g_network_context_for_testing = nullptr;
@@ -70,8 +84,8 @@ void OnVerifyCertUI(VerifyCallback callback,
int32_t error_code,
const net::CertVerifyResult& cv_result,
const net::ct::CTVerifyResult& ct_result) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(std::move(callback), error_code, cv_result, ct_result));
}
@@ -103,6 +117,43 @@ void VerifyCert(const scoped_refptr<net::X509Certificate>& certificate,
certificate, url, ocsp_result, sct_list, std::move(wrapped_callback));
}
+std::string OCSPErrorToString(const net::OCSPVerifyResult& ocsp_result) {
+ switch (ocsp_result.response_status) {
+ case net::OCSPVerifyResult::PROVIDED:
+ break;
+ case net::OCSPVerifyResult::NOT_CHECKED:
+ // This happens only in tests.
+ return "OCSP verification was not performed.";
+ case net::OCSPVerifyResult::MISSING:
+ return "No OCSP Response was stapled.";
+ case net::OCSPVerifyResult::ERROR_RESPONSE:
+ return "OCSP response did not have a SUCCESSFUL status.";
+ case net::OCSPVerifyResult::BAD_PRODUCED_AT:
+ return "OCSP Response was produced at outside the certificate "
+ "validity period.";
+ case net::OCSPVerifyResult::NO_MATCHING_RESPONSE:
+ return "OCSP Response did not match the certificate.";
+ case net::OCSPVerifyResult::INVALID_DATE:
+ return "OCSP Response was expired or not yet valid.";
+ case net::OCSPVerifyResult::PARSE_RESPONSE_ERROR:
+ return "OCSPResponse structure could not be parsed.";
+ case net::OCSPVerifyResult::PARSE_RESPONSE_DATA_ERROR:
+ return "OCSP ResponseData structure could not be parsed.";
+ }
+
+ switch (ocsp_result.revocation_status) {
+ case net::OCSPRevocationStatus::GOOD:
+ NOTREACHED();
+ break;
+ case net::OCSPRevocationStatus::REVOKED:
+ return "OCSP response indicates that the certificate is revoked.";
+ case net::OCSPRevocationStatus::UNKNOWN:
+ return "OCSP responder doesn't know about the certificate.";
+ }
+ NOTREACHED();
+ return std::string();
+}
+
} // namespace
// static
@@ -136,12 +187,11 @@ SignedExchangeHandler::SignedExchangeHandler(
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("loading"),
"SignedExchangeHandler::SignedExchangeHandler");
- if (!SignedExchangeSignatureHeaderField::GetVersionParamFromContentType(
- content_type, &version_) ||
- !IsSupportedSignedExchangeVersion(version_)) {
+ version_ = signed_exchange_utils::GetSignedExchangeVersion(content_type);
+ if (!IsSupportedSignedExchangeVersion(version_)) {
signed_exchange_utils::ReportErrorAndTraceEvent(
devtools_proxy_.get(),
- base::StringPrintf("Unsupported version of the content type. Currentry "
+ base::StringPrintf("Unsupported version of the content type. Currently "
"content type must be "
"\"application/signed-exchange;v=b2\". But the "
"response content type was \"%s\"",
@@ -184,53 +234,56 @@ void SignedExchangeHandler::DoHeaderLoop() {
DidReadHeader(true /* sync */, rv);
}
-void SignedExchangeHandler::DidReadHeader(bool completed_syncly, int result) {
+void SignedExchangeHandler::DidReadHeader(bool completed_syncly,
+ int read_result) {
DCHECK(state_ == State::kReadingPrologueBeforeFallbackUrl ||
state_ == State::kReadingPrologueFallbackUrlAndAfter ||
state_ == State::kReadingHeaders);
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("loading"),
"SignedExchangeHandler::DidReadHeader");
- if (result < 0) {
+ if (read_result < 0) {
signed_exchange_utils::ReportErrorAndTraceEvent(
devtools_proxy_.get(),
- base::StringPrintf("Error reading body stream. result: %d", result));
- RunErrorCallback(static_cast<net::Error>(result));
+ base::StringPrintf("Error reading body stream. result: %d",
+ read_result));
+ RunErrorCallback(SignedExchangeLoadResult::kSXGHeaderNetError,
+ static_cast<net::Error>(read_result));
return;
}
- if (result == 0) {
+ if (read_result == 0) {
signed_exchange_utils::ReportErrorAndTraceEvent(
devtools_proxy_.get(),
"Stream ended while reading signed exchange header.");
- RunErrorCallback(net::ERR_INVALID_SIGNED_EXCHANGE);
+ SignedExchangeLoadResult result =
+ GetFallbackUrl().is_valid()
+ ? SignedExchangeLoadResult::kHeaderParseError
+ : SignedExchangeLoadResult::kFallbackURLParseError;
+ RunErrorCallback(result, net::ERR_INVALID_SIGNED_EXCHANGE);
return;
}
- header_read_buf_->DidConsume(result);
+ header_read_buf_->DidConsume(read_result);
if (header_read_buf_->BytesRemaining() == 0) {
+ SignedExchangeLoadResult result = SignedExchangeLoadResult::kSuccess;
switch (state_) {
case State::kReadingPrologueBeforeFallbackUrl:
- if (!ParsePrologueBeforeFallbackUrl()) {
- RunErrorCallback(net::ERR_INVALID_SIGNED_EXCHANGE);
- return;
- }
+ result = ParsePrologueBeforeFallbackUrl();
break;
case State::kReadingPrologueFallbackUrlAndAfter:
- if (!ParsePrologueFallbackUrlAndAfter()) {
- RunErrorCallback(net::ERR_INVALID_SIGNED_EXCHANGE);
- return;
- }
+ result = ParsePrologueFallbackUrlAndAfter();
break;
case State::kReadingHeaders:
- if (!ParseHeadersAndFetchCertificate()) {
- RunErrorCallback(net::ERR_INVALID_SIGNED_EXCHANGE);
- return;
- }
+ result = ParseHeadersAndFetchCertificate();
break;
default:
NOTREACHED();
}
+ if (result != SignedExchangeLoadResult::kSuccess) {
+ RunErrorCallback(result, net::ERR_INVALID_SIGNED_EXCHANGE);
+ return;
+ }
}
// We have finished reading headers, so return without queueing the next read.
@@ -250,7 +303,8 @@ void SignedExchangeHandler::DidReadHeader(bool completed_syncly, int result) {
}
}
-bool SignedExchangeHandler::ParsePrologueBeforeFallbackUrl() {
+SignedExchangeLoadResult
+SignedExchangeHandler::ParsePrologueBeforeFallbackUrl() {
DCHECK_EQ(state_, State::kReadingPrologueBeforeFallbackUrl);
prologue_before_fallback_url_ =
@@ -268,10 +322,11 @@ bool SignedExchangeHandler::ParsePrologueBeforeFallbackUrl() {
SetupBuffers(
prologue_before_fallback_url_.ComputeFallbackUrlAndAfterLength());
state_ = State::kReadingPrologueFallbackUrlAndAfter;
- return true;
+ return SignedExchangeLoadResult::kSuccess;
}
-bool SignedExchangeHandler::ParsePrologueFallbackUrlAndAfter() {
+SignedExchangeLoadResult
+SignedExchangeHandler::ParsePrologueFallbackUrlAndAfter() {
DCHECK_EQ(state_, State::kReadingPrologueFallbackUrlAndAfter);
prologue_fallback_url_and_after_ =
@@ -280,24 +335,30 @@ bool SignedExchangeHandler::ParsePrologueFallbackUrlAndAfter() {
reinterpret_cast<uint8_t*>(header_buf_->data()),
prologue_before_fallback_url_.ComputeFallbackUrlAndAfterLength()),
prologue_before_fallback_url_, devtools_proxy_.get());
- if (!prologue_fallback_url_and_after_.is_valid()) {
- return false;
- }
- // If the signed exchange version from content-type is unsupported, abort
- // parsing and redirect to the fallback URL.
- if (!IsSupportedSignedExchangeVersion(version_))
- return false;
+ if (!GetFallbackUrl().is_valid())
+ return SignedExchangeLoadResult::kFallbackURLParseError;
+
+ // If the signed exchange version from content-type is unsupported or the
+ // prologue's magic string is incorrect, abort parsing and redirect to the
+ // fallback URL.
+ if (!IsSupportedSignedExchangeVersion(version_) ||
+ !prologue_before_fallback_url_.is_valid())
+ return SignedExchangeLoadResult::kVersionMismatch;
+
+ if (!prologue_fallback_url_and_after_.is_valid())
+ return SignedExchangeLoadResult::kHeaderParseError;
// Set up a new buffer for reading the Signature header field and CBOR-encoded
// headers.
SetupBuffers(
prologue_fallback_url_and_after_.ComputeFollowingSectionsLength());
state_ = State::kReadingHeaders;
- return true;
+ return SignedExchangeLoadResult::kSuccess;
}
-bool SignedExchangeHandler::ParseHeadersAndFetchCertificate() {
+SignedExchangeLoadResult
+SignedExchangeHandler::ParseHeadersAndFetchCertificate() {
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("loading"),
"SignedExchangeHandler::ParseHeadersAndFetchCertificate");
DCHECK_EQ(state_, State::kReadingHeaders);
@@ -317,7 +378,7 @@ bool SignedExchangeHandler::ParseHeadersAndFetchCertificate() {
if (!envelope_) {
signed_exchange_utils::ReportErrorAndTraceEvent(
devtools_proxy_.get(), "Failed to parse SignedExchange header.");
- return false;
+ return SignedExchangeLoadResult::kHeaderParseError;
}
const GURL cert_url = envelope_->signature().cert_url;
@@ -330,6 +391,7 @@ bool SignedExchangeHandler::ParseHeadersAndFetchCertificate() {
const bool force_fetch = load_flags_ & net::LOAD_BYPASS_CACHE;
+ cert_fetch_start_time_ = base::TimeTicks::Now();
cert_fetcher_ = std::move(cert_fetcher_factory_)
->CreateFetcherAndStart(
cert_url, force_fetch, *version_,
@@ -338,10 +400,11 @@ bool SignedExchangeHandler::ParseHeadersAndFetchCertificate() {
devtools_proxy_.get());
state_ = State::kFetchingCertificate;
- return true;
+ return SignedExchangeLoadResult::kSuccess;
}
-void SignedExchangeHandler::RunErrorCallback(net::Error error) {
+void SignedExchangeHandler::RunErrorCallback(SignedExchangeLoadResult result,
+ net::Error error) {
DCHECK_NE(state_, State::kHeadersCallbackCalled);
if (devtools_proxy_) {
devtools_proxy_->OnSignedExchangeReceived(
@@ -351,31 +414,41 @@ void SignedExchangeHandler::RunErrorCallback(net::Error error) {
nullptr);
}
std::move(headers_callback_)
- .Run(error, GetFallbackUrl(), std::string(),
+ .Run(result, error, GetFallbackUrl(), std::string(),
network::ResourceResponseHead(), nullptr);
state_ = State::kHeadersCallbackCalled;
}
void SignedExchangeHandler::OnCertReceived(
+ SignedExchangeLoadResult result,
std::unique_ptr<SignedExchangeCertificateChain> cert_chain) {
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("loading"),
"SignedExchangeHandler::OnCertReceived");
+ base::TimeDelta cert_fetch_duration =
+ base::TimeTicks::Now() - cert_fetch_start_time_;
DCHECK_EQ(state_, State::kFetchingCertificate);
- if (!cert_chain) {
+ if (result != SignedExchangeLoadResult::kSuccess) {
+ UMA_HISTOGRAM_MEDIUM_TIMES("SignedExchange.Time.CertificateFetch.Failure",
+ cert_fetch_duration);
+
signed_exchange_utils::ReportErrorAndTraceEvent(
devtools_proxy_.get(), "Failed to fetch the certificate.",
std::make_pair(0 /* signature_index */,
SignedExchangeError::Field::kSignatureCertUrl));
- RunErrorCallback(net::ERR_INVALID_SIGNED_EXCHANGE);
+ RunErrorCallback(result, net::ERR_INVALID_SIGNED_EXCHANGE);
return;
}
+ UMA_HISTOGRAM_MEDIUM_TIMES("SignedExchange.Time.CertificateFetch.Success",
+ cert_fetch_duration);
unverified_cert_chain_ = std::move(cert_chain);
const SignedExchangeSignatureVerifier::Result verify_result =
SignedExchangeSignatureVerifier::Verify(
*envelope_, unverified_cert_chain_->cert(), GetVerificationTime(),
devtools_proxy_.get());
+ UMA_HISTOGRAM_ENUMERATION(kHistogramSignatureVerificationResult,
+ verify_result);
if (verify_result != SignedExchangeSignatureVerifier::Result::kSuccess) {
base::Optional<SignedExchangeError::Field> error_field =
SignedExchangeError::GetFieldFromSignatureVerifierResult(verify_result);
@@ -384,7 +457,8 @@ void SignedExchangeHandler::OnCertReceived(
error_field ? base::make_optional(
std::make_pair(0 /* signature_index */, *error_field))
: base::nullopt);
- RunErrorCallback(net::ERR_INVALID_SIGNED_EXCHANGE);
+ RunErrorCallback(SignedExchangeLoadResult::kSignatureVerificationError,
+ net::ERR_INVALID_SIGNED_EXCHANGE);
return;
}
@@ -401,8 +475,8 @@ void SignedExchangeHandler::OnCertReceived(
// property, or
const std::string& stapled_ocsp_response = unverified_cert_chain_->ocsp();
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&VerifyCert, certificate, url, stapled_ocsp_response,
sct_list_from_cert_cbor, frame_tree_node_id_getter_,
base::BindOnce(&SignedExchangeHandler::OnVerifyCert,
@@ -431,12 +505,21 @@ bool SignedExchangeHandler::CheckOCSPStatus(
//
// OCSP verification is done in CertVerifier::Verify(), so we just check the
// result here.
-
- if (ocsp_result.response_status != net::OCSPVerifyResult::PROVIDED ||
- ocsp_result.revocation_status != net::OCSPRevocationStatus::GOOD)
- return false;
-
- return true;
+ UMA_HISTOGRAM_ENUMERATION(kHistogramOCSPResponseStatus,
+ ocsp_result.response_status,
+ static_cast<base::HistogramBase::Sample>(
+ net::OCSPVerifyResult::RESPONSE_STATUS_MAX) +
+ 1);
+ if (ocsp_result.response_status == net::OCSPVerifyResult::PROVIDED) {
+ UMA_HISTOGRAM_ENUMERATION(kHistogramOCSPRevocationStatus,
+ ocsp_result.revocation_status,
+ static_cast<base::HistogramBase::Sample>(
+ net::OCSPRevocationStatus::MAX_VALUE) +
+ 1);
+ if (ocsp_result.revocation_status == net::OCSPRevocationStatus::GOOD)
+ return true;
+ }
+ return false;
}
void SignedExchangeHandler::OnVerifyCert(
@@ -445,24 +528,32 @@ void SignedExchangeHandler::OnVerifyCert(
const net::ct::CTVerifyResult& ct_result) {
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("loading"),
"SignedExchangeHandler::OnCertVerifyComplete");
+ // net::Error codes are negative, so we put - in front of it.
+ base::UmaHistogramSparse(kHistogramCertVerificationResult, -error_code);
+ UMA_HISTOGRAM_ENUMERATION(kHistogramCTVerificationResult,
+ ct_result.policy_compliance,
+ net::ct::CTPolicyCompliance::CT_POLICY_COUNT);
if (error_code != net::OK) {
+ SignedExchangeLoadResult result;
std::string error_message;
if (error_code == net::ERR_CERTIFICATE_TRANSPARENCY_REQUIRED) {
error_message = base::StringPrintf(
"CT verification failed. result: %s, policy compliance: %d",
net::ErrorToShortString(error_code).c_str(),
ct_result.policy_compliance);
+ result = SignedExchangeLoadResult::kCTVerificationError;
} else {
error_message =
base::StringPrintf("Certificate verification error: %s",
net::ErrorToShortString(error_code).c_str());
+ result = SignedExchangeLoadResult::kCertVerificationError;
}
signed_exchange_utils::ReportErrorAndTraceEvent(
devtools_proxy_.get(), error_message,
std::make_pair(0 /* signature_index */,
SignedExchangeError::Field::kSignatureCertUrl));
- RunErrorCallback(net::ERR_INVALID_SIGNED_EXCHANGE);
+ RunErrorCallback(result, net::ERR_INVALID_SIGNED_EXCHANGE);
return;
}
@@ -474,24 +565,26 @@ void SignedExchangeHandler::OnVerifyCert(
"chrome://flags/#allow-sxg-certs-without-extension.",
std::make_pair(0 /* signature_index */,
SignedExchangeError::Field::kSignatureCertUrl));
- RunErrorCallback(net::ERR_INVALID_SIGNED_EXCHANGE);
+ RunErrorCallback(SignedExchangeLoadResult::kCertRequirementsNotMet,
+ net::ERR_INVALID_SIGNED_EXCHANGE);
return;
}
if (!CheckOCSPStatus(cv_result.ocsp_result)) {
signed_exchange_utils::ReportErrorAndTraceEvent(
devtools_proxy_.get(),
- base::StringPrintf(
- "OCSP check failed. response status: %d, revocation status: %d",
- cv_result.ocsp_result.response_status,
- cv_result.ocsp_result.revocation_status),
+ base::StringPrintf("OCSP check failed: %s",
+ OCSPErrorToString(cv_result.ocsp_result).c_str()),
std::make_pair(0 /* signature_index */,
SignedExchangeError::Field::kSignatureCertUrl));
- RunErrorCallback(net::ERR_INVALID_SIGNED_EXCHANGE);
+ RunErrorCallback(SignedExchangeLoadResult::kOCSPError,
+ net::ERR_INVALID_SIGNED_EXCHANGE);
return;
}
network::ResourceResponseHead response_head;
+ response_head.is_signed_exchange_inner_response = true;
+
response_head.headers = envelope_->BuildHttpResponseHeaders();
response_head.headers->GetMimeTypeAndCharset(&response_head.mime_type,
&response_head.charset);
@@ -508,9 +601,12 @@ void SignedExchangeHandler::OnVerifyCert(
std::string digest_header_value;
if (!response_head.headers->EnumerateHeader(nullptr, kDigestHeader,
&digest_header_value)) {
+ // TODO(https://crbug.com/803774): Detect this error in
+ // SignedExchangeEnvelope::Parse().
signed_exchange_utils::ReportErrorAndTraceEvent(
devtools_proxy_.get(), "Signed exchange has no Digest: header");
- RunErrorCallback(net::ERR_INVALID_SIGNED_EXCHANGE);
+ RunErrorCallback(SignedExchangeLoadResult::kHeaderParseError,
+ net::ERR_INVALID_SIGNED_EXCHANGE);
return;
}
auto mi_stream = std::make_unique<MerkleIntegritySourceStream>(
@@ -535,8 +631,9 @@ void SignedExchangeHandler::OnVerifyCert(
response_head.ssl_info = std::move(ssl_info);
std::move(headers_callback_)
- .Run(net::OK, envelope_->request_url(), envelope_->request_method(),
- response_head, std::move(mi_stream));
+ .Run(SignedExchangeLoadResult::kSuccess, net::OK,
+ envelope_->request_url(), envelope_->request_method(), response_head,
+ std::move(mi_stream));
state_ = State::kHeadersCallbackCalled;
}
diff --git a/chromium/content/browser/web_package/signed_exchange_handler.h b/chromium/content/browser/web_package/signed_exchange_handler.h
index 122ac720be3..0465a06ea97 100644
--- a/chromium/content/browser/web_package/signed_exchange_handler.h
+++ b/chromium/content/browser/web_package/signed_exchange_handler.h
@@ -12,6 +12,7 @@
#include "base/time/time.h"
#include "content/browser/web_package/signed_exchange_consts.h"
#include "content/browser/web_package/signed_exchange_envelope.h"
+#include "content/browser/web_package/signed_exchange_error.h"
#include "content/browser/web_package/signed_exchange_prologue.h"
#include "content/common/content_export.h"
#include "mojo/public/cpp/system/data_pipe.h"
@@ -45,20 +46,33 @@ class SignedExchangeCertificateChain;
class SignedExchangeDevToolsProxy;
// SignedExchangeHandler reads "application/signed-exchange" format from a
-// net::SourceStream, parse and verify the signed exchange, and report
+// net::SourceStream, parses and verifies the signed exchange, and reports
// the result asynchronously via SignedExchangeHandler::ExchangeHeadersCallback.
//
// Note that verifying a signed exchange requires an associated certificate
// chain. SignedExchangeHandler creates a SignedExchangeCertFetcher to
-// fetch the certificate chain over network, and verify it with the
+// fetch the certificate chain over the network, and verifies it with the
// net::CertVerifier.
class CONTENT_EXPORT SignedExchangeHandler {
public:
+ // Callback that will be called when SXG header is parsed and its signature is
+ // validated against a verified certificate, or on failure.
+ // On success:
+ // - |result| is kSuccess.
+ // - |request_url| and |request_method| are the exchange's request's URL and
+ // method.
+ // - |resource_response| contains inner response's headers.
+ // - The payload stream can be read from |payload_stream|.
+ // On failure:
+ // - |result| indicates the failure reason.
+ // - |error| indicates the net::Error if |result| is kSXGHeaderNetError.
+ // - |request_url| may refer to the fallback URL.
using ExchangeHeadersCallback = base::OnceCallback<void(
+ SignedExchangeLoadResult result,
net::Error error,
const GURL& request_url,
const std::string& request_method,
- const network::ResourceResponseHead&,
+ const network::ResourceResponseHead& resource_response,
std::unique_ptr<net::SourceStream> payload_stream)>;
static void SetNetworkContextForTesting(
@@ -98,12 +112,13 @@ class CONTENT_EXPORT SignedExchangeHandler {
void SetupBuffers(size_t size);
void DoHeaderLoop();
void DidReadHeader(bool completed_syncly, int result);
- bool ParsePrologueBeforeFallbackUrl();
- bool ParsePrologueFallbackUrlAndAfter();
- bool ParseHeadersAndFetchCertificate();
- void RunErrorCallback(net::Error);
+ SignedExchangeLoadResult ParsePrologueBeforeFallbackUrl();
+ SignedExchangeLoadResult ParsePrologueFallbackUrlAndAfter();
+ SignedExchangeLoadResult ParseHeadersAndFetchCertificate();
+ void RunErrorCallback(SignedExchangeLoadResult result, net::Error);
void OnCertReceived(
+ SignedExchangeLoadResult result,
std::unique_ptr<SignedExchangeCertificateChain> cert_chain);
bool CheckCertExtension(const net::X509Certificate* verified_cert);
bool CheckOCSPStatus(const net::OCSPVerifyResult& ocsp_result);
@@ -137,6 +152,8 @@ class CONTENT_EXPORT SignedExchangeHandler {
base::RepeatingCallback<int(void)> frame_tree_node_id_getter_;
+ base::TimeTicks cert_fetch_start_time_;
+
base::WeakPtrFactory<SignedExchangeHandler> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(SignedExchangeHandler);
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 43578473a64..d4661c46d38 100644
--- a/chromium/content/browser/web_package/signed_exchange_handler_unittest.cc
+++ b/chromium/content/browser/web_package/signed_exchange_handler_unittest.cc
@@ -11,9 +11,11 @@
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/path_service.h"
+#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.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_signature_verifier.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_paths.h"
#include "content/public/test/test_browser_thread_bundle.h"
@@ -100,7 +102,9 @@ class MockSignedExchangeCertFetcherFactory
EXPECT_TRUE(cert_chain);
base::SequencedTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(std::move(callback), std::move(cert_chain)));
+ FROM_HERE,
+ base::BindOnce(std::move(callback), SignedExchangeLoadResult::kSuccess,
+ std::move(cert_chain)));
return nullptr;
}
@@ -207,7 +211,7 @@ class SignedExchangeHandlerTest
// read to it.
int ReadStream(net::SourceStream* stream, std::string* output) {
scoped_refptr<net::IOBuffer> output_buffer =
- new net::IOBuffer(kOutputBufferSize);
+ base::MakeRefCounted<net::IOBuffer>(kOutputBufferSize);
int bytes_read = 0;
while (true) {
net::TestCompletionCallback callback;
@@ -235,6 +239,7 @@ class SignedExchangeHandlerTest
}
bool read_header() const { return read_header_; }
+ SignedExchangeLoadResult result() const { return result_; }
net::Error error() const { return error_; }
const GURL& inner_url() const { return inner_url_; }
const network::ResourceResponseHead& resource_response() const {
@@ -276,7 +281,30 @@ class SignedExchangeHandlerTest
}
}
+ void ExpectHistogramValues(
+ base::Optional<SignedExchangeSignatureVerifier::Result> signature_result,
+ base::Optional<int32_t> cert_result,
+ base::Optional<net::ct::CTPolicyCompliance> ct_result,
+ base::Optional<net::OCSPVerifyResult::ResponseStatus>
+ ocsp_response_status,
+ base::Optional<net::OCSPRevocationStatus> ocsp_revocation_status) {
+ // CertVerificationResult histogram records negated net::Error code.
+ if (cert_result.has_value())
+ *cert_result = -*cert_result;
+
+ ExpectZeroOrUniqueSample("SignedExchange.SignatureVerificationResult",
+ signature_result);
+ ExpectZeroOrUniqueSample("SignedExchange.CertVerificationResult",
+ cert_result);
+ ExpectZeroOrUniqueSample("SignedExchange.CTVerificationResult", ct_result);
+ ExpectZeroOrUniqueSample("SignedExchange.OCSPResponseStatus",
+ ocsp_response_status);
+ ExpectZeroOrUniqueSample("SignedExchange.OCSPRevocationStatus",
+ ocsp_revocation_status);
+ }
+
protected:
+ const base::HistogramTester histogram_tester_;
MockSignedExchangeCertFetcherFactory* mock_cert_fetcher_factory_;
std::unique_ptr<net::CertVerifier> cert_verifier_;
std::unique_ptr<MockCTVerifier> mock_ct_verifier_;
@@ -285,18 +313,29 @@ class SignedExchangeHandlerTest
std::unique_ptr<SignedExchangeHandler> handler_;
private:
- void OnHeaderFound(net::Error error,
+ void OnHeaderFound(SignedExchangeLoadResult result,
+ net::Error error,
const GURL& url,
const std::string&,
const network::ResourceResponseHead& resource_response,
std::unique_ptr<net::SourceStream> payload_stream) {
read_header_ = true;
+ result_ = result;
error_ = error;
inner_url_ = url;
resource_response_ = resource_response;
payload_stream_ = std::move(payload_stream);
}
+ template <typename T>
+ void ExpectZeroOrUniqueSample(const std::string& histogram_name,
+ base::Optional<T> expected_value) {
+ if (expected_value.has_value())
+ histogram_tester_.ExpectUniqueSample(histogram_name, *expected_value, 1);
+ else
+ histogram_tester_.ExpectTotalCount(histogram_name, 0);
+ }
+
base::test::ScopedFeatureList feature_list_;
content::TestBrowserThreadBundle browser_thread_bundle_;
std::unique_ptr<net::TestURLRequestContext> url_request_context_;
@@ -307,6 +346,7 @@ class SignedExchangeHandlerTest
std::unique_ptr<MockSignedExchangeCertFetcherFactory> cert_fetcher_factory_;
bool read_header_ = false;
+ SignedExchangeLoadResult result_;
net::Error error_;
GURL inner_url_;
network::ResourceResponseHead resource_response_;
@@ -320,6 +360,7 @@ TEST_P(SignedExchangeHandlerTest, Empty) {
WaitForHeader();
ASSERT_TRUE(read_header());
+ EXPECT_EQ(SignedExchangeLoadResult::kFallbackURLParseError, result());
EXPECT_EQ(net::ERR_INVALID_SIGNED_EXCHANGE, error());
EXPECT_TRUE(inner_url().is_empty());
}
@@ -351,6 +392,7 @@ TEST_P(SignedExchangeHandlerTest, Simple) {
WaitForHeader();
ASSERT_TRUE(read_header());
+ EXPECT_EQ(SignedExchangeLoadResult::kSuccess, result());
EXPECT_EQ(net::OK, error());
EXPECT_EQ(kTestSxgInnerURL, inner_url());
EXPECT_EQ(200, resource_response().headers->response_code());
@@ -369,6 +411,10 @@ TEST_P(SignedExchangeHandlerTest, Simple) {
EXPECT_EQ(payload, expected_payload);
EXPECT_EQ(rv, static_cast<int>(expected_payload.size()));
+ ExpectHistogramValues(
+ SignedExchangeSignatureVerifier::Result::kSuccess, net::OK,
+ net::ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS,
+ net::OCSPVerifyResult::PROVIDED, net::OCSPRevocationStatus::GOOD);
}
TEST_P(SignedExchangeHandlerTest, MimeType) {
@@ -398,6 +444,7 @@ TEST_P(SignedExchangeHandlerTest, MimeType) {
WaitForHeader();
ASSERT_TRUE(read_header());
+ EXPECT_EQ(SignedExchangeLoadResult::kSuccess, result());
EXPECT_EQ(net::OK, error());
EXPECT_EQ(200, resource_response().headers->response_code());
EXPECT_EQ("text/plain", resource_response().mime_type);
@@ -421,13 +468,14 @@ TEST_P(SignedExchangeHandlerTest, HeaderParseError) {
WaitForHeader();
ASSERT_TRUE(read_header());
+ EXPECT_EQ(SignedExchangeLoadResult::kFallbackURLParseError, result());
EXPECT_EQ(net::ERR_INVALID_SIGNED_EXCHANGE, error());
EXPECT_TRUE(inner_url().is_empty());
}
-TEST_P(SignedExchangeHandlerTest, TruncatedInHeader) {
+TEST_P(SignedExchangeHandlerTest, TruncatedAfterFallbackUrl) {
std::string contents = GetTestFileContents("test.example.org_test.sxg");
- contents.resize(30);
+ contents.resize(50);
source_->AddReadResult(contents.data(), contents.size(), net::OK, GetParam());
source_->AddReadResult(nullptr, 0, net::OK, GetParam());
@@ -435,8 +483,9 @@ TEST_P(SignedExchangeHandlerTest, TruncatedInHeader) {
WaitForHeader();
ASSERT_TRUE(read_header());
+ EXPECT_EQ(SignedExchangeLoadResult::kHeaderParseError, result());
EXPECT_EQ(net::ERR_INVALID_SIGNED_EXCHANGE, error());
- EXPECT_TRUE(inner_url().is_empty());
+ EXPECT_TRUE(inner_url().is_valid());
}
TEST_P(SignedExchangeHandlerTest, CertWithoutExtensionShouldBeRejected) {
@@ -466,6 +515,7 @@ TEST_P(SignedExchangeHandlerTest, CertWithoutExtensionShouldBeRejected) {
WaitForHeader();
ASSERT_TRUE(read_header());
+ EXPECT_EQ(SignedExchangeLoadResult::kCertRequirementsNotMet, result());
EXPECT_EQ(net::ERR_INVALID_SIGNED_EXCHANGE, error());
EXPECT_EQ(kTestSxgInnerURL, inner_url());
// Drain the MockSourceStream, otherwise its destructer causes DCHECK failure.
@@ -503,6 +553,7 @@ TEST_P(SignedExchangeHandlerTest, CertWithoutExtensionAllowedByFeatureFlag) {
WaitForHeader();
ASSERT_TRUE(read_header());
+ EXPECT_EQ(SignedExchangeLoadResult::kSuccess, result());
EXPECT_EQ(net::OK, error());
std::string payload;
int rv = ReadPayloadStream(&payload);
@@ -534,8 +585,15 @@ TEST_P(SignedExchangeHandlerTest, CertSha256Mismatch) {
WaitForHeader();
ASSERT_TRUE(read_header());
+ EXPECT_EQ(SignedExchangeLoadResult::kSignatureVerificationError, result());
EXPECT_EQ(net::ERR_INVALID_SIGNED_EXCHANGE, error());
EXPECT_EQ(kTestSxgInnerURL, inner_url());
+ ExpectHistogramValues(
+ SignedExchangeSignatureVerifier::Result::kErrCertificateSHA256Mismatch,
+ base::nullopt /* cert_result */, base::nullopt /* ct_result */,
+ base::nullopt /* ocsp_response_status */,
+ base::nullopt /* ocsp_revocation_status */);
+
// Drain the MockSourceStream, otherwise its destructer causes DCHECK failure.
ReadStream(source_, nullptr);
}
@@ -569,8 +627,15 @@ TEST_P(SignedExchangeHandlerTest, VerifyCertFailure) {
WaitForHeader();
ASSERT_TRUE(read_header());
+ EXPECT_EQ(SignedExchangeLoadResult::kCertVerificationError, result());
EXPECT_EQ(net::ERR_INVALID_SIGNED_EXCHANGE, error());
EXPECT_EQ("https://test.example.com/test/", inner_url());
+ ExpectHistogramValues(
+ SignedExchangeSignatureVerifier::Result::kSuccess, net::ERR_CERT_INVALID,
+ net::ct::CTPolicyCompliance::CT_POLICY_COMPLIANCE_DETAILS_NOT_AVAILABLE,
+ base::nullopt /* ocsp_response_status */,
+ base::nullopt /* ocsp_revocation_status */);
+
// Drain the MockSourceStream, otherwise its destructer causes DCHECK failure.
ReadStream(source_, nullptr);
}
@@ -601,6 +666,7 @@ TEST_P(SignedExchangeHandlerTest, OCSPNotChecked) {
WaitForHeader();
ASSERT_TRUE(read_header());
+ EXPECT_EQ(SignedExchangeLoadResult::kOCSPError, result());
EXPECT_EQ(net::ERR_INVALID_SIGNED_EXCHANGE, error());
EXPECT_EQ(kTestSxgInnerURL, inner_url());
// Drain the MockSourceStream, otherwise its destructer causes DCHECK failure.
@@ -633,6 +699,7 @@ TEST_P(SignedExchangeHandlerTest, OCSPNotProvided) {
WaitForHeader();
ASSERT_TRUE(read_header());
+ EXPECT_EQ(SignedExchangeLoadResult::kOCSPError, result());
EXPECT_EQ(net::ERR_INVALID_SIGNED_EXCHANGE, error());
EXPECT_EQ(kTestSxgInnerURL, inner_url());
// Drain the MockSourceStream, otherwise its destructer causes DCHECK failure.
@@ -666,6 +733,7 @@ TEST_P(SignedExchangeHandlerTest, OCSPInvalid) {
WaitForHeader();
ASSERT_TRUE(read_header());
+ EXPECT_EQ(SignedExchangeLoadResult::kOCSPError, result());
EXPECT_EQ(net::ERR_INVALID_SIGNED_EXCHANGE, error());
EXPECT_EQ(kTestSxgInnerURL, inner_url());
// Drain the MockSourceStream, otherwise its destructer causes DCHECK failure.
@@ -700,6 +768,7 @@ TEST_P(SignedExchangeHandlerTest, OCSPRevoked) {
WaitForHeader();
ASSERT_TRUE(read_header());
+ EXPECT_EQ(SignedExchangeLoadResult::kOCSPError, result());
EXPECT_EQ(net::ERR_INVALID_SIGNED_EXCHANGE, error());
EXPECT_EQ(kTestSxgInnerURL, inner_url());
// Drain the MockSourceStream, otherwise its destructer causes DCHECK failure.
@@ -745,6 +814,7 @@ TEST_P(SignedExchangeHandlerTest, CertVerifierParams) {
WaitForHeader();
ASSERT_TRUE(read_header());
+ EXPECT_EQ(SignedExchangeLoadResult::kSuccess, result());
EXPECT_EQ(net::OK, error());
std::string payload;
int rv = ReadPayloadStream(&payload);
@@ -786,8 +856,14 @@ TEST_P(SignedExchangeHandlerTest, NotEnoughSCTsFromPubliclyTrustedCert) {
WaitForHeader();
ASSERT_TRUE(read_header());
+ EXPECT_EQ(SignedExchangeLoadResult::kCTVerificationError, result());
EXPECT_EQ(net::ERR_INVALID_SIGNED_EXCHANGE, error());
EXPECT_EQ(kTestSxgInnerURL, inner_url());
+ ExpectHistogramValues(SignedExchangeSignatureVerifier::Result::kSuccess,
+ net::ERR_CERTIFICATE_TRANSPARENCY_REQUIRED,
+ net::ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS,
+ base::nullopt /* ocsp_response_status */,
+ base::nullopt /* ocsp_revocation_status */);
// Drain the MockSourceStream, otherwise its destructer causes DCHECK failure.
ReadStream(source_, nullptr);
}
@@ -823,6 +899,7 @@ TEST_P(SignedExchangeHandlerTest, CTRequirementsMetForPubliclyTrustedCert) {
WaitForHeader();
ASSERT_TRUE(read_header());
+ EXPECT_EQ(SignedExchangeLoadResult::kSuccess, result());
EXPECT_EQ(net::OK, error());
// EV status should be preserved.
EXPECT_TRUE(resource_response().ssl_info->cert_status &
@@ -832,6 +909,10 @@ TEST_P(SignedExchangeHandlerTest, CTRequirementsMetForPubliclyTrustedCert) {
EXPECT_TRUE(resource_response().ssl_info->ct_policy_compliance_required);
EXPECT_EQ(net::ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS,
resource_response().ssl_info->ct_policy_compliance);
+ ExpectHistogramValues(
+ SignedExchangeSignatureVerifier::Result::kSuccess, net::OK,
+ net::ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS,
+ net::OCSPVerifyResult::PROVIDED, net::OCSPRevocationStatus::GOOD);
std::string payload;
int rv = ReadPayloadStream(&payload);
@@ -874,6 +955,7 @@ TEST_P(SignedExchangeHandlerTest, CTNotRequiredForLocalAnchors) {
WaitForHeader();
ASSERT_TRUE(read_header());
+ EXPECT_EQ(SignedExchangeLoadResult::kSuccess, result());
EXPECT_EQ(net::OK, error());
// EV status should be removed.
EXPECT_FALSE(resource_response().ssl_info->cert_status &
@@ -883,6 +965,10 @@ TEST_P(SignedExchangeHandlerTest, CTNotRequiredForLocalAnchors) {
EXPECT_FALSE(resource_response().ssl_info->ct_policy_compliance_required);
EXPECT_EQ(net::ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS,
resource_response().ssl_info->ct_policy_compliance);
+ ExpectHistogramValues(
+ SignedExchangeSignatureVerifier::Result::kSuccess, net::OK,
+ net::ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS,
+ net::OCSPVerifyResult::PROVIDED, net::OCSPRevocationStatus::GOOD);
std::string payload;
int rv = ReadPayloadStream(&payload);
@@ -948,6 +1034,7 @@ TEST_P(SignedExchangeHandlerTest, CTVerifierParams) {
WaitForHeader();
ASSERT_TRUE(read_header());
+ EXPECT_EQ(SignedExchangeLoadResult::kSuccess, result());
EXPECT_EQ(net::OK, error());
std::string payload;
int rv = ReadPayloadStream(&payload);
diff --git a/chromium/content/browser/web_package/signed_exchange_loader.cc b/chromium/content/browser/web_package/signed_exchange_loader.cc
index d03dd7f2947..85a3ced159b 100644
--- a/chromium/content/browser/web_package/signed_exchange_loader.cc
+++ b/chromium/content/browser/web_package/signed_exchange_loader.cc
@@ -8,15 +8,18 @@
#include "base/callback.h"
#include "base/feature_list.h"
+#include "base/metrics/histogram_macros.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_prefetch_metric_recorder.h"
#include "content/browser/web_package/signed_exchange_utils.h"
#include "content/public/common/content_features.h"
#include "content/public/common/origin_util.h"
+#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
#include "net/cert/cert_status_flags.h"
#include "net/http/http_util.h"
@@ -29,6 +32,8 @@ namespace content {
namespace {
+constexpr char kLoadResultHistogram[] = "SignedExchange.LoadResult";
+
net::RedirectInfo CreateRedirectInfo(const GURL& new_url,
const GURL& outer_request_url) {
net::RedirectInfo redirect_info;
@@ -102,7 +107,8 @@ SignedExchangeLoader::SignedExchangeLoader(
std::unique_ptr<SignedExchangeDevToolsProxy> devtools_proxy,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
URLLoaderThrottlesGetter url_loader_throttles_getter,
- base::RepeatingCallback<int(void)> frame_tree_node_id_getter)
+ base::RepeatingCallback<int(void)> frame_tree_node_id_getter,
+ scoped_refptr<SignedExchangePrefetchMetricRecorder> metric_recorder)
: outer_request_url_(outer_request_url),
outer_response_timing_info_(
std::make_unique<ResponseTimingInfo>(outer_response)),
@@ -118,6 +124,7 @@ SignedExchangeLoader::SignedExchangeLoader(
url_loader_factory_(std::move(url_loader_factory)),
url_loader_throttles_getter_(std::move(url_loader_throttles_getter)),
frame_tree_node_id_getter_(frame_tree_node_id_getter),
+ metric_recorder_(std::move(metric_recorder)),
weak_factory_(this) {
DCHECK(signed_exchange_utils::IsSignedExchangeHandlingEnabled());
DCHECK(outer_request_url_.is_valid());
@@ -129,6 +136,8 @@ SignedExchangeLoader::SignedExchangeLoader(
// transport layer, and MUST NOT accept exchanges transferred over plain HTTP
// without TLS. [spec text]
if (!IsOriginSecure(outer_request_url)) {
+ UMA_HISTOGRAM_ENUMERATION(kLoadResultHistogram,
+ SignedExchangeLoadResult::kSXGServedFromNonHTTPS);
devtools_proxy_->ReportError(
"Signed exchange response from non secure origin is not supported.",
base::nullopt /* error_field */);
@@ -266,11 +275,18 @@ void SignedExchangeLoader::ConnectToClient(
}
void SignedExchangeLoader::OnHTTPExchangeFound(
+ SignedExchangeLoadResult result,
net::Error error,
const GURL& request_url,
const std::string& request_method,
const network::ResourceResponseHead& resource_response,
std::unique_ptr<net::SourceStream> payload_stream) {
+ UMA_HISTOGRAM_ENUMERATION(kLoadResultHistogram, result);
+
+ if (load_flags_ & net::LOAD_PREFETCH) {
+ metric_recorder_->OnSignedExchangePrefetchFinished(request_url, error);
+ }
+
if (error) {
if (error != net::ERR_INVALID_SIGNED_EXCHANGE ||
!should_redirect_on_failure_ || !request_url.is_valid()) {
@@ -305,15 +321,15 @@ void SignedExchangeLoader::OnHTTPExchangeFound(
!net::IsCertStatusMinorError(ssl_info->cert_status)) {
ssl_info_ = ssl_info;
}
+
+ network::ResourceResponseHead inner_response_head_shown_to_client =
+ resource_response;
if (ssl_info.has_value() &&
!(url_loader_options_ &
network::mojom::kURLLoadOptionSendSSLInfoWithResponse)) {
- network::ResourceResponseHead response_info = resource_response;
- response_info.ssl_info = base::nullopt;
- client_->OnReceiveResponse(response_info);
- } else {
- client_->OnReceiveResponse(resource_response);
+ inner_response_head_shown_to_client.ssl_info = base::nullopt;
}
+ client_->OnReceiveResponse(inner_response_head_shown_to_client);
// Currently we always assume that we have body.
// TODO(https://crbug.com/80374): Add error handling and bail out
diff --git a/chromium/content/browser/web_package/signed_exchange_loader.h b/chromium/content/browser/web_package/signed_exchange_loader.h
index 47cdeccf490..210c3bc13d2 100644
--- a/chromium/content/browser/web_package/signed_exchange_loader.h
+++ b/chromium/content/browser/web_package/signed_exchange_loader.h
@@ -8,6 +8,7 @@
#include "base/callback.h"
#include "base/optional.h"
#include "base/unguessable_token.h"
+#include "content/browser/web_package/signed_exchange_error.h"
#include "content/common/content_export.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/system/simple_watcher.h"
@@ -30,6 +31,7 @@ namespace content {
class SignedExchangeDevToolsProxy;
class SignedExchangeHandler;
class SignedExchangeHandlerFactory;
+class SignedExchangePrefetchMetricRecorder;
class URLLoaderThrottle;
class SourceStreamToDataPipe;
@@ -59,7 +61,8 @@ class SignedExchangeLoader final : public network::mojom::URLLoaderClient,
std::unique_ptr<SignedExchangeDevToolsProxy> devtools_proxy,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
URLLoaderThrottlesGetter url_loader_throttles_getter,
- base::RepeatingCallback<int(void)> frame_tree_node_id_getter);
+ base::RepeatingCallback<int(void)> frame_tree_node_id_getter,
+ scoped_refptr<SignedExchangePrefetchMetricRecorder> metric_recorder);
~SignedExchangeLoader() override;
bool HasRedirectedToFallbackURL() const {
@@ -105,6 +108,7 @@ class SignedExchangeLoader final : public network::mojom::URLLoaderClient,
// Called from |signed_exchange_handler_| when it finds an origin-signed HTTP
// exchange.
void OnHTTPExchangeFound(
+ SignedExchangeLoadResult result,
net::Error error,
const GURL& request_url,
const std::string& request_method,
@@ -152,6 +156,7 @@ class SignedExchangeLoader final : public network::mojom::URLLoaderClient,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
URLLoaderThrottlesGetter url_loader_throttles_getter_;
base::RepeatingCallback<int(void)> frame_tree_node_id_getter_;
+ scoped_refptr<SignedExchangePrefetchMetricRecorder> metric_recorder_;
base::Optional<net::SSLInfo> ssl_info_;
diff --git a/chromium/content/browser/web_package/signed_exchange_prefetch_handler.cc b/chromium/content/browser/web_package/signed_exchange_prefetch_handler.cc
index abf10c2ed0a..46efa0e5150 100644
--- a/chromium/content/browser/web_package/signed_exchange_prefetch_handler.cc
+++ b/chromium/content/browser/web_package/signed_exchange_prefetch_handler.cc
@@ -8,6 +8,7 @@
#include "base/feature_list.h"
#include "content/browser/web_package/signed_exchange_devtools_proxy.h"
#include "content/browser/web_package/signed_exchange_loader.h"
+#include "content/browser/web_package/signed_exchange_prefetch_metric_recorder.h"
#include "content/browser/web_package/signed_exchange_url_loader_factory_for_non_network_service.h"
#include "content/public/common/content_features.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
@@ -32,8 +33,11 @@ SignedExchangePrefetchHandler::SignedExchangePrefetchHandler(
URLLoaderThrottlesGetter loader_throttles_getter,
ResourceContext* resource_context,
scoped_refptr<net::URLRequestContextGetter> request_context_getter,
- network::mojom::URLLoaderClient* forwarding_client)
- : loader_client_binding_(this), forwarding_client_(forwarding_client) {
+ network::mojom::URLLoaderClient* forwarding_client,
+ scoped_refptr<SignedExchangePrefetchMetricRecorder> metric_recorder)
+ : loader_client_binding_(this),
+ forwarding_client_(forwarding_client),
+ outer_request_url_(outer_request_url) {
network::mojom::URLLoaderClientEndpointsPtr endpoints =
network::mojom::URLLoaderClientEndpoints::New(
std::move(network_loader).PassInterface(),
@@ -49,15 +53,15 @@ SignedExchangePrefetchHandler::SignedExchangePrefetchHandler(
url_loader_factory = std::move(network_loader_factory);
}
signed_exchange_loader_ = std::make_unique<SignedExchangeLoader>(
- outer_request_url, response, std::move(client), std::move(endpoints),
+ outer_request_url_, response, std::move(client), std::move(endpoints),
std::move(request_initiator), network::mojom::kURLLoadOptionNone,
load_flags, false /* should_redirect_to_fallback */,
throttling_profile_id,
std::make_unique<SignedExchangeDevToolsProxy>(
- outer_request_url, response, frame_tree_node_id_getter,
+ outer_request_url_, response, frame_tree_node_id_getter,
base::nullopt /* devtools_navigation_token */, report_raw_headers),
std::move(url_loader_factory), loader_throttles_getter,
- frame_tree_node_id_getter);
+ frame_tree_node_id_getter, std::move(metric_recorder));
}
SignedExchangePrefetchHandler::~SignedExchangePrefetchHandler() = default;
@@ -109,6 +113,10 @@ void SignedExchangePrefetchHandler::OnStartLoadingResponseBody(
void SignedExchangePrefetchHandler::OnComplete(
const network::URLLoaderCompletionStatus& status) {
+ // We only reach here on error, since successful completion of the
+ // outer sxg load should trigger redirect and land on ::OnReceiveRedirect.
+ DCHECK_NE(net::OK, status.error_code);
+
forwarding_client_->OnComplete(status);
}
diff --git a/chromium/content/browser/web_package/signed_exchange_prefetch_handler.h b/chromium/content/browser/web_package/signed_exchange_prefetch_handler.h
index 0c3551f4108..200ce6b9a5d 100644
--- a/chromium/content/browser/web_package/signed_exchange_prefetch_handler.h
+++ b/chromium/content/browser/web_package/signed_exchange_prefetch_handler.h
@@ -25,6 +25,7 @@ namespace content {
class ResourceContext;
class URLLoaderThrottle;
class SignedExchangeLoader;
+class SignedExchangePrefetchMetricRecorder;
// Attached to each PrefetchURLLoader if the prefetch is for a signed exchange.
class SignedExchangePrefetchHandler final
@@ -51,7 +52,8 @@ class SignedExchangePrefetchHandler final
URLLoaderThrottlesGetter loader_throttles_getter,
ResourceContext* resource_context,
scoped_refptr<net::URLRequestContextGetter> request_context_getter,
- network::mojom::URLLoaderClient* forwarding_client);
+ network::mojom::URLLoaderClient* forwarding_client,
+ scoped_refptr<SignedExchangePrefetchMetricRecorder> metric_recorder);
~SignedExchangePrefetchHandler() override;
@@ -83,6 +85,8 @@ class SignedExchangePrefetchHandler final
network::mojom::URLLoaderClient* forwarding_client_;
+ const GURL outer_request_url_;
+
DISALLOW_COPY_AND_ASSIGN(SignedExchangePrefetchHandler);
};
diff --git a/chromium/content/browser/web_package/signed_exchange_prefetch_metric_recorder.cc b/chromium/content/browser/web_package/signed_exchange_prefetch_metric_recorder.cc
new file mode 100644
index 00000000000..e83902c7e3c
--- /dev/null
+++ b/chromium/content/browser/web_package/signed_exchange_prefetch_metric_recorder.cc
@@ -0,0 +1,23 @@
+// 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_prefetch_metric_recorder.h"
+
+#include "content/public/browser/browser_thread.h"
+
+namespace content {
+
+SignedExchangePrefetchMetricRecorder::SignedExchangePrefetchMetricRecorder() =
+ default;
+SignedExchangePrefetchMetricRecorder::~SignedExchangePrefetchMetricRecorder() =
+ default;
+
+void SignedExchangePrefetchMetricRecorder::OnSignedExchangePrefetchFinished(
+ const GURL& outer_url,
+ net::Error error) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ // TODO(crbug.com/890180): Actually Report UMA.
+}
+
+} // namespace content
diff --git a/chromium/content/browser/web_package/signed_exchange_prefetch_metric_recorder.h b/chromium/content/browser/web_package/signed_exchange_prefetch_metric_recorder.h
new file mode 100644
index 00000000000..00566617c65
--- /dev/null
+++ b/chromium/content/browser/web_package/signed_exchange_prefetch_metric_recorder.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_WEB_PACKAGE_SIGNED_EXCHANGE_PREFETCH_METRIC_RECORDER_H_
+#define CONTENT_BROWSER_WEB_PACKAGE_SIGNED_EXCHANGE_PREFETCH_METRIC_RECORDER_H_
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "net/base/net_errors.h"
+
+class GURL;
+
+namespace content {
+
+// SignedExchangePrefetchMetricRecorder records signed exchange prefetch and
+// its usage metrics.
+class SignedExchangePrefetchMetricRecorder final
+ : public base::RefCountedThreadSafe<SignedExchangePrefetchMetricRecorder> {
+ public:
+ SignedExchangePrefetchMetricRecorder();
+
+ void OnSignedExchangePrefetchFinished(const GURL& outer_url,
+ net::Error error);
+
+ private:
+ friend class base::RefCountedThreadSafe<SignedExchangePrefetchMetricRecorder>;
+ ~SignedExchangePrefetchMetricRecorder();
+
+ DISALLOW_COPY_AND_ASSIGN(SignedExchangePrefetchMetricRecorder);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_WEB_PACKAGE_SIGNED_EXCHANGE_PREFETCH_METRIC_RECORDER_H_
diff --git a/chromium/content/browser/web_package/signed_exchange_request_handler.cc b/chromium/content/browser/web_package/signed_exchange_request_handler.cc
index 97e0b1e0765..921124aae28 100644
--- a/chromium/content/browser/web_package/signed_exchange_request_handler.cc
+++ b/chromium/content/browser/web_package/signed_exchange_request_handler.cc
@@ -10,6 +10,7 @@
#include "base/feature_list.h"
#include "content/browser/web_package/signed_exchange_devtools_proxy.h"
#include "content/browser/web_package/signed_exchange_loader.h"
+#include "content/browser/web_package/signed_exchange_prefetch_metric_recorder.h"
#include "content/browser/web_package/signed_exchange_utils.h"
#include "content/common/throttling_url_loader.h"
#include "content/public/common/content_features.h"
@@ -38,7 +39,8 @@ SignedExchangeRequestHandler::SignedExchangeRequestHandler(
bool report_raw_headers,
int load_flags,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
- URLLoaderThrottlesGetter url_loader_throttles_getter)
+ URLLoaderThrottlesGetter url_loader_throttles_getter,
+ scoped_refptr<SignedExchangePrefetchMetricRecorder> metric_recorder)
: request_initiator_(std::move(request_initiator)),
url_(url),
url_loader_options_(url_loader_options),
@@ -49,6 +51,7 @@ SignedExchangeRequestHandler::SignedExchangeRequestHandler(
load_flags_(load_flags),
url_loader_factory_(url_loader_factory),
url_loader_throttles_getter_(std::move(url_loader_throttles_getter)),
+ metric_recorder_(std::move(metric_recorder)),
weak_factory_(this) {
DCHECK(signed_exchange_utils::IsSignedExchangeHandlingEnabled());
}
@@ -66,7 +69,8 @@ void SignedExchangeRequestHandler::MaybeCreateLoader(
}
if (signed_exchange_loader_->HasRedirectedToFallbackURL()) {
signed_exchange_loader_ = nullptr;
- std::move(callback).Run({});
+ std::move(fallback_callback)
+ .Run(false /* reset_subresource_loader_params */);
return;
}
@@ -79,7 +83,8 @@ bool SignedExchangeRequestHandler::MaybeCreateLoaderForResponse(
const network::ResourceResponseHead& response,
network::mojom::URLLoaderPtr* loader,
network::mojom::URLLoaderClientRequest* client_request,
- ThrottlingURLLoader* url_loader) {
+ ThrottlingURLLoader* url_loader,
+ bool* skip_other_interceptors) {
DCHECK(!signed_exchange_loader_);
if (!signed_exchange_utils::ShouldHandleAsSignedHTTPExchange(
request_initiator_.GetURL(), response)) {
@@ -103,7 +108,10 @@ bool SignedExchangeRequestHandler::MaybeCreateLoaderForResponse(
base::BindRepeating([](int id) { return id; }, frame_tree_node_id_),
devtools_navigation_token_, report_raw_headers_),
url_loader_factory_, url_loader_throttles_getter_,
- base::BindRepeating([](int id) { return id; }, frame_tree_node_id_));
+ base::BindRepeating([](int id) { return id; }, frame_tree_node_id_),
+ metric_recorder_);
+
+ *skip_other_interceptors = true;
return true;
}
diff --git a/chromium/content/browser/web_package/signed_exchange_request_handler.h b/chromium/content/browser/web_package/signed_exchange_request_handler.h
index b0037c69d84..5b9548429a9 100644
--- a/chromium/content/browser/web_package/signed_exchange_request_handler.h
+++ b/chromium/content/browser/web_package/signed_exchange_request_handler.h
@@ -20,6 +20,7 @@ namespace content {
class URLLoaderThrottle;
class SignedExchangeLoader;
+class SignedExchangePrefetchMetricRecorder;
class SignedExchangeRequestHandler final : public NavigationLoaderInterceptor {
public:
@@ -38,7 +39,8 @@ class SignedExchangeRequestHandler final : public NavigationLoaderInterceptor {
bool report_raw_headers,
int load_flags,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
- URLLoaderThrottlesGetter url_loader_throttles_getter);
+ URLLoaderThrottlesGetter url_loader_throttles_getter,
+ scoped_refptr<SignedExchangePrefetchMetricRecorder> metric_recorder);
~SignedExchangeRequestHandler() override;
// NavigationLoaderInterceptor implementation
@@ -51,7 +53,8 @@ class SignedExchangeRequestHandler final : public NavigationLoaderInterceptor {
const network::ResourceResponseHead& response,
network::mojom::URLLoaderPtr* loader,
network::mojom::URLLoaderClientRequest* client_request,
- ThrottlingURLLoader* url_loader) override;
+ ThrottlingURLLoader* url_loader,
+ bool* skip_other_interceptors) override;
private:
void StartResponse(const network::ResourceRequest& resource_request,
@@ -73,6 +76,7 @@ class SignedExchangeRequestHandler final : public NavigationLoaderInterceptor {
const int load_flags_;
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
URLLoaderThrottlesGetter url_loader_throttles_getter_;
+ scoped_refptr<SignedExchangePrefetchMetricRecorder> metric_recorder_;
base::WeakPtrFactory<SignedExchangeRequestHandler> weak_factory_;
diff --git a/chromium/content/browser/web_package/signed_exchange_request_handler_browsertest.cc b/chromium/content/browser/web_package/signed_exchange_request_handler_browsertest.cc
index 03a54596795..b2d7d4825b8 100644
--- a/chromium/content/browser/web_package/signed_exchange_request_handler_browsertest.cc
+++ b/chromium/content/browser/web_package/signed_exchange_request_handler_browsertest.cc
@@ -6,10 +6,15 @@
#include "base/path_service.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/task/post_task.h"
+#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/threading/thread_restrictions.h"
#include "base/time/time.h"
+#include "content/browser/frame_host/navigation_handle_impl.h"
#include "content/browser/web_package/signed_exchange_handler.h"
+#include "content/browser/web_package/signed_exchange_utils.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_entry.h"
@@ -28,21 +33,30 @@
#include "content/shell/browser/shell.h"
#include "net/cert/cert_verify_result.h"
#include "net/cert/mock_cert_verifier.h"
+#include "net/dns/mock_host_resolver.h"
#include "net/test/cert_test_util.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 "net/test/test_data_directory.h"
#include "net/test/url_request/url_request_mock_http_job.h"
#include "net/url_request/url_request_filter.h"
#include "net/url_request/url_request_interceptor.h"
+#include "services/network/loader_util.h"
#include "services/network/public/cpp/features.h"
#include "testing/gmock/include/gmock/gmock-matchers.h"
+#include "third_party/blink/public/common/features.h"
+#include "third_party/blink/public/common/service_worker/service_worker_utils.h"
namespace content {
namespace {
const uint64_t kSignatureHeaderDate = 1520834000; // 2018-03-12T05:53:20Z
+const uint64_t kSignatureHeaderExpires = 1520837600; // 2018-03-12T06:53:20Z
+
+constexpr char kExpectedSXGEnabledAcceptHeaderForPrefetch[] =
+ "application/signed-exchange;v=b2;q=0.9,*/*;q=0.8";
class RedirectObserver : public WebContentsObserver {
public:
@@ -64,11 +78,26 @@ class RedirectObserver : public WebContentsObserver {
DISALLOW_COPY_AND_ASSIGN(RedirectObserver);
};
+class AssertNavigationHandleFlagObserver : public WebContentsObserver {
+ public:
+ explicit AssertNavigationHandleFlagObserver(WebContents* web_contents)
+ : WebContentsObserver(web_contents) {}
+ ~AssertNavigationHandleFlagObserver() override = default;
+
+ void DidFinishNavigation(NavigationHandle* handle) override {
+ EXPECT_TRUE(static_cast<NavigationHandleImpl*>(handle)->IsSignedExchangeInnerResponse());
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(AssertNavigationHandleFlagObserver);
+};
+
} // namespace
-class SignedExchangeRequestHandlerBrowserTest : public CertVerifierBrowserTest {
+class SignedExchangeRequestHandlerBrowserTestBase
+ : public CertVerifierBrowserTest {
public:
- SignedExchangeRequestHandlerBrowserTest() {
+ SignedExchangeRequestHandlerBrowserTestBase() {
// This installs "root_ca_cert.pem" from which our test certificates are
// created. (Needed for the tests that use real certificate, i.e.
// RealCertVerifier)
@@ -79,7 +108,7 @@ class SignedExchangeRequestHandlerBrowserTest : public CertVerifierBrowserTest {
SignedExchangeHandler::SetVerificationTimeForTesting(
base::Time::UnixEpoch() +
base::TimeDelta::FromSeconds(kSignatureHeaderDate));
- SetUpFeatures();
+ feature_list_.InitWithFeatures({features::kSignedHTTPExchange}, {});
CertVerifierBrowserTest::SetUp();
}
@@ -90,10 +119,6 @@ class SignedExchangeRequestHandlerBrowserTest : public CertVerifierBrowserTest {
}
protected:
- virtual void SetUpFeatures() {
- feature_list_.InitWithFeatures({features::kSignedHTTPExchange}, {});
- }
-
static scoped_refptr<net::X509Certificate> LoadCertificate(
const std::string& cert_file) {
base::ScopedAllowBlockingForTesting allow_io;
@@ -108,20 +133,45 @@ class SignedExchangeRequestHandlerBrowserTest : public CertVerifierBrowserTest {
void InstallUrlInterceptor(const GURL& url, const std::string& data_path) {
if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
if (!interceptor_) {
- interceptor_ =
- std::make_unique<URLLoaderInterceptor>(base::BindRepeating(
- &SignedExchangeRequestHandlerBrowserTest::OnInterceptCallback,
- base::Unretained(this)));
+ interceptor_ = std::make_unique<
+ URLLoaderInterceptor>(base::BindRepeating(
+ &SignedExchangeRequestHandlerBrowserTestBase::OnInterceptCallback,
+ base::Unretained(this)));
}
interceptor_data_path_map_[url] = data_path;
} else {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&InstallMockInterceptors, url, data_path));
}
}
- base::test::ScopedFeatureList feature_list_;
+ void InstallMockCert() {
+ // Make the MockCertVerifier treat the certificate
+ // "prime256v1-sha256.public.pem" as valid for "test.example.org".
+ scoped_refptr<net::X509Certificate> original_cert =
+ LoadCertificate("prime256v1-sha256.public.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;
+ mock_cert_verifier()->AddResultForCertAndHost(
+ original_cert, "test.example.org", dummy_result, net::OK);
+ }
+
+ void TriggerPrefetch(const GURL& url, bool expect_success) {
+ const GURL prefetch_html_url = embedded_test_server()->GetURL(
+ std::string("/sxg/prefetch.html#") + url.spec());
+ base::string16 expected_title =
+ base::ASCIIToUTF16(expect_success ? "OK" : "FAIL");
+ TitleWatcher title_watcher(shell()->web_contents(), expected_title);
+ NavigateToURL(shell(), prefetch_html_url);
+ EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
+ }
+
+ const base::HistogramTester histogram_tester_;
private:
static void InstallMockInterceptors(const GURL& url,
@@ -141,43 +191,52 @@ class SignedExchangeRequestHandlerBrowserTest : public CertVerifierBrowserTest {
return true;
}
+ base::test::ScopedFeatureList feature_list_;
std::unique_ptr<URLLoaderInterceptor> interceptor_;
std::map<GURL, std::string> interceptor_data_path_map_;
+ DISALLOW_COPY_AND_ASSIGN(SignedExchangeRequestHandlerBrowserTestBase);
+};
+
+enum class SignedExchangeRequestHandlerBrowserTestPrefetchParam {
+ kPrefetchDisabled,
+ kPrefetchEnabled
+};
+
+class SignedExchangeRequestHandlerBrowserTest
+ : public SignedExchangeRequestHandlerBrowserTestBase,
+ public testing::WithParamInterface<
+ SignedExchangeRequestHandlerBrowserTestPrefetchParam> {
+ public:
+ SignedExchangeRequestHandlerBrowserTest() = default;
+
+ protected:
+ bool PrefetchIsEnabled() {
+ return GetParam() == SignedExchangeRequestHandlerBrowserTestPrefetchParam::
+ kPrefetchEnabled;
+ }
+
+ private:
DISALLOW_COPY_AND_ASSIGN(SignedExchangeRequestHandlerBrowserTest);
};
-IN_PROC_BROWSER_TEST_F(SignedExchangeRequestHandlerBrowserTest, Simple) {
+IN_PROC_BROWSER_TEST_P(SignedExchangeRequestHandlerBrowserTest, Simple) {
InstallUrlInterceptor(
GURL("https://cert.example.org/cert.msg"),
"content/test/data/sxg/test.example.org.public.pem.cbor");
+ InstallMockCert();
- // Make the MockCertVerifier treat the certificate
- // "prime256v1-sha256.public.pem" as valid for "test.example.org".
- scoped_refptr<net::X509Certificate> original_cert =
- LoadCertificate("prime256v1-sha256.public.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;
- mock_cert_verifier()->AddResultForCertAndHost(
- original_cert, "test.example.org", dummy_result, net::OK);
-
- embedded_test_server()->RegisterRequestMonitor(
- base::BindRepeating([](const net::test_server::HttpRequest& request) {
- if (request.relative_url == "/sxg/test.example.org_test.sxg") {
- const auto& accept_value = request.headers.find("accept")->second;
- EXPECT_THAT(accept_value,
- ::testing::HasSubstr("application/signed-exchange;v=b2"));
- }
- }));
embedded_test_server()->ServeFilesFromSourceDirectory("content/test/data");
ASSERT_TRUE(embedded_test_server()->Start());
GURL url = embedded_test_server()->GetURL("/sxg/test.example.org_test.sxg");
+ if (PrefetchIsEnabled())
+ TriggerPrefetch(url, true);
+
base::string16 title = base::ASCIIToUTF16("https://test.example.org/test/");
TitleWatcher title_watcher(shell()->web_contents(), title);
RedirectObserver redirect_observer(shell()->web_contents());
+ AssertNavigationHandleFlagObserver assert_navigation_handle_flag_observer(
+ shell()->web_contents());
NavigateToURL(shell(), url);
EXPECT_EQ(title, title_watcher.WaitAndGetTitle());
@@ -196,36 +255,35 @@ IN_PROC_BROWSER_TEST_F(SignedExchangeRequestHandlerBrowserTest, Simple) {
const net::SHA256HashValue fingerprint =
net::X509Certificate::CalculateFingerprint256(
entry->GetSSL().certificate->cert_buffer());
+ scoped_refptr<net::X509Certificate> original_cert =
+ LoadCertificate("prime256v1-sha256.public.pem");
const net::SHA256HashValue original_fingerprint =
net::X509Certificate::CalculateFingerprint256(
original_cert->cert_buffer());
EXPECT_EQ(original_fingerprint, fingerprint);
+ histogram_tester_.ExpectUniqueSample("SignedExchange.LoadResult",
+ SignedExchangeLoadResult::kSuccess,
+ PrefetchIsEnabled() ? 2 : 1);
+ histogram_tester_.ExpectTotalCount(
+ "SignedExchange.Time.CertificateFetch.Success",
+ PrefetchIsEnabled() ? 2 : 1);
}
-IN_PROC_BROWSER_TEST_F(SignedExchangeRequestHandlerBrowserTest,
+IN_PROC_BROWSER_TEST_P(SignedExchangeRequestHandlerBrowserTest,
InvalidContentType) {
InstallUrlInterceptor(
GURL("https://cert.example.org/cert.msg"),
"content/test/data/sxg/test.example.org.public.pem.cbor");
InstallUrlInterceptor(GURL("https://test.example.org/test/"),
"content/test/data/sxg/fallback.html");
-
- // Make the MockCertVerifier treat the certificate
- // "prime256v1-sha256.public.pem" as valid for "test.example.org".
- scoped_refptr<net::X509Certificate> original_cert =
- LoadCertificate("prime256v1-sha256.public.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;
- mock_cert_verifier()->AddResultForCertAndHost(
- original_cert, "test.example.org", dummy_result, net::OK);
+ InstallMockCert();
embedded_test_server()->ServeFilesFromSourceDirectory("content/test/data");
ASSERT_TRUE(embedded_test_server()->Start());
GURL url = embedded_test_server()->GetURL(
"/sxg/test.example.org_test_invalid_content_type.sxg");
+ if (PrefetchIsEnabled())
+ TriggerPrefetch(url, false);
base::string16 title = base::ASCIIToUTF16("Fallback URL response");
TitleWatcher title_watcher(shell()->web_contents(), title);
@@ -233,9 +291,42 @@ IN_PROC_BROWSER_TEST_F(SignedExchangeRequestHandlerBrowserTest,
NavigateToURL(shell(), url);
EXPECT_EQ(title, title_watcher.WaitAndGetTitle());
EXPECT_EQ(303, redirect_observer.response_code());
+ histogram_tester_.ExpectUniqueSample(
+ "SignedExchange.LoadResult", SignedExchangeLoadResult::kVersionMismatch,
+ PrefetchIsEnabled() ? 2 : 1);
}
-IN_PROC_BROWSER_TEST_F(SignedExchangeRequestHandlerBrowserTest,
+IN_PROC_BROWSER_TEST_P(SignedExchangeRequestHandlerBrowserTest, Expired) {
+ SignedExchangeHandler::SetVerificationTimeForTesting(
+ base::Time::UnixEpoch() +
+ base::TimeDelta::FromSeconds(kSignatureHeaderExpires + 1));
+
+ InstallUrlInterceptor(
+ GURL("https://cert.example.org/cert.msg"),
+ "content/test/data/sxg/test.example.org.public.pem.cbor");
+ InstallUrlInterceptor(GURL("https://test.example.org/test/"),
+ "content/test/data/sxg/fallback.html");
+ InstallMockCert();
+
+ embedded_test_server()->ServeFilesFromSourceDirectory("content/test/data");
+ ASSERT_TRUE(embedded_test_server()->Start());
+ GURL url = embedded_test_server()->GetURL("/sxg/test.example.org_test.sxg");
+
+ base::string16 title = base::ASCIIToUTF16("Fallback URL response");
+ TitleWatcher title_watcher(shell()->web_contents(), title);
+ RedirectObserver redirect_observer(shell()->web_contents());
+ NavigateToURL(shell(), url);
+ EXPECT_EQ(title, title_watcher.WaitAndGetTitle());
+ EXPECT_EQ(303, redirect_observer.response_code());
+ histogram_tester_.ExpectUniqueSample(
+ "SignedExchange.LoadResult",
+ SignedExchangeLoadResult::kSignatureVerificationError, 1);
+ histogram_tester_.ExpectUniqueSample(
+ "SignedExchange.SignatureVerificationResult",
+ SignedExchangeSignatureVerifier::Result::kErrInvalidTimestamp, 1);
+}
+
+IN_PROC_BROWSER_TEST_P(SignedExchangeRequestHandlerBrowserTest,
RedirectBrokenSignedExchanges) {
InstallUrlInterceptor(GURL("https://test.example.org/test/"),
"content/test/data/sxg/fallback.html");
@@ -254,14 +345,25 @@ IN_PROC_BROWSER_TEST_F(SignedExchangeRequestHandlerBrowserTest,
GURL url = embedded_test_server()->GetURL(broken_exchange);
+ if (PrefetchIsEnabled())
+ TriggerPrefetch(url, false);
+
base::string16 title = base::ASCIIToUTF16("Fallback URL response");
TitleWatcher title_watcher(shell()->web_contents(), title);
NavigateToURL(shell(), url);
EXPECT_EQ(title, title_watcher.WaitAndGetTitle());
}
+ histogram_tester_.ExpectTotalCount("SignedExchange.LoadResult",
+ PrefetchIsEnabled() ? 4 : 2);
+ histogram_tester_.ExpectBucketCount(
+ "SignedExchange.LoadResult", SignedExchangeLoadResult::kVersionMismatch,
+ PrefetchIsEnabled() ? 2 : 1);
+ histogram_tester_.ExpectBucketCount(
+ "SignedExchange.LoadResult", SignedExchangeLoadResult::kHeaderParseError,
+ PrefetchIsEnabled() ? 2 : 1);
}
-IN_PROC_BROWSER_TEST_F(SignedExchangeRequestHandlerBrowserTest, CertNotFound) {
+IN_PROC_BROWSER_TEST_P(SignedExchangeRequestHandlerBrowserTest, CertNotFound) {
InstallUrlInterceptor(GURL("https://cert.example.org/cert.msg"),
"content/test/data/sxg/404.msg");
InstallUrlInterceptor(GURL("https://test.example.org/test/"),
@@ -271,14 +373,31 @@ IN_PROC_BROWSER_TEST_F(SignedExchangeRequestHandlerBrowserTest, CertNotFound) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL url = embedded_test_server()->GetURL("/sxg/test.example.org_test.sxg");
+ if (PrefetchIsEnabled())
+ TriggerPrefetch(url, false);
+
base::string16 title = base::ASCIIToUTF16("Fallback URL response");
TitleWatcher title_watcher(shell()->web_contents(), title);
NavigateToURL(shell(), url);
EXPECT_EQ(title, title_watcher.WaitAndGetTitle());
+ histogram_tester_.ExpectUniqueSample(
+ "SignedExchange.LoadResult", SignedExchangeLoadResult::kCertFetchError,
+ PrefetchIsEnabled() ? 2 : 1);
+ histogram_tester_.ExpectTotalCount(
+ "SignedExchange.Time.CertificateFetch.Failure",
+ PrefetchIsEnabled() ? 2 : 1);
}
+INSTANTIATE_TEST_CASE_P(
+ SignedExchangeRequestHandlerBrowserTest,
+ SignedExchangeRequestHandlerBrowserTest,
+ testing::Values(
+ SignedExchangeRequestHandlerBrowserTestPrefetchParam::kPrefetchDisabled,
+ SignedExchangeRequestHandlerBrowserTestPrefetchParam::
+ kPrefetchEnabled));
+
class SignedExchangeRequestHandlerRealCertVerifierBrowserTest
- : public SignedExchangeRequestHandlerBrowserTest {
+ : public SignedExchangeRequestHandlerBrowserTestBase {
public:
SignedExchangeRequestHandlerRealCertVerifierBrowserTest() {
// Use "real" CertVerifier.
@@ -294,14 +413,6 @@ IN_PROC_BROWSER_TEST_F(SignedExchangeRequestHandlerRealCertVerifierBrowserTest,
InstallUrlInterceptor(GURL("https://test.example.org/test/"),
"content/test/data/sxg/fallback.html");
- embedded_test_server()->RegisterRequestMonitor(
- base::BindRepeating([](const net::test_server::HttpRequest& request) {
- if (request.relative_url == "/sxg/test.example.org_test.sxg") {
- const auto& accept_value = request.headers.find("accept")->second;
- EXPECT_THAT(accept_value,
- ::testing::HasSubstr("application/signed-exchange;v=b2"));
- }
- }));
embedded_test_server()->ServeFilesFromSourceDirectory("content/test/data");
ASSERT_TRUE(embedded_test_server()->Start());
GURL url = embedded_test_server()->GetURL("/sxg/test.example.org_test.sxg");
@@ -312,23 +423,666 @@ IN_PROC_BROWSER_TEST_F(SignedExchangeRequestHandlerRealCertVerifierBrowserTest,
// TODO(https://crbug.com/815024): Make this test pass the OCSP check. We'll
// need to either generate an OCSP response on the fly, or override the OCSP
// verification time.
- content::ConsoleObserverDelegate console_observer(shell()->web_contents(),
- "*OCSP*");
- shell()->web_contents()->SetDelegate(&console_observer);
-
base::string16 title = base::ASCIIToUTF16("Fallback URL response");
TitleWatcher title_watcher(shell()->web_contents(), title);
NavigateToURL(shell(), url);
EXPECT_EQ(title, title_watcher.WaitAndGetTitle());
-
// Verify that it failed at the OCSP check step.
- // TODO(https://crbug.com/803774): Find a better way than matching against the
- // error message. We can probably make DevToolsProxy derive some context from
- // StoragePartition so that we can record and extract the detailed error
- // status for testing via that.
- console_observer.Wait();
- EXPECT_TRUE(base::StartsWith(console_observer.message(), "OCSP check failed.",
- base::CompareCase::SENSITIVE));
+ histogram_tester_.ExpectUniqueSample("SignedExchange.LoadResult",
+ SignedExchangeLoadResult::kOCSPError, 1);
+}
+
+enum class SignedExchangeRequestHandlerWithServiceWorkerBrowserTestParam {
+ kLegacy,
+ kServiceWorkerServicification,
+ kNetworkService
+};
+
+class SignedExchangeRequestHandlerWithServiceWorkerBrowserTest
+ : public SignedExchangeRequestHandlerBrowserTestBase,
+ public testing::WithParamInterface<
+ SignedExchangeRequestHandlerWithServiceWorkerBrowserTestParam> {
+ public:
+ SignedExchangeRequestHandlerWithServiceWorkerBrowserTest() = default;
+ void SetUp() override {
+ switch (GetParam()) {
+ case SignedExchangeRequestHandlerWithServiceWorkerBrowserTestParam::
+ kLegacy:
+ feature_list_.InitWithFeatures(
+ {}, {blink::features::kServiceWorkerServicification,
+ network::features::kNetworkService});
+ break;
+ case SignedExchangeRequestHandlerWithServiceWorkerBrowserTestParam::
+ kServiceWorkerServicification:
+ feature_list_.InitWithFeatures(
+ {blink::features::kServiceWorkerServicification},
+ {network::features::kNetworkService});
+ break;
+ case SignedExchangeRequestHandlerWithServiceWorkerBrowserTestParam::
+ kNetworkService:
+ feature_list_.InitAndEnableFeature(network::features::kNetworkService);
+ break;
+ }
+ SignedExchangeRequestHandlerBrowserTestBase::SetUp();
+ }
+
+ private:
+ base::test::ScopedFeatureList feature_list_;
+
+ DISALLOW_COPY_AND_ASSIGN(
+ SignedExchangeRequestHandlerWithServiceWorkerBrowserTest);
+};
+
+IN_PROC_BROWSER_TEST_P(SignedExchangeRequestHandlerWithServiceWorkerBrowserTest,
+ LogicalUrlInServiceWorkerScope) {
+ // SW-scope: https://test.example.org/test/
+ // SXG physical URL: http://127.0.0.1:PORT/sxg/test.example.org_test.sxg
+ // SXG logical URL: https://test.example.org/test/
+ InstallUrlInterceptor(
+ GURL("https://cert.example.org/cert.msg"),
+ "content/test/data/sxg/test.example.org.public.pem.cbor");
+ InstallMockCert();
+
+ const GURL install_sw_url =
+ GURL("https://test.example.org/test/publisher-service-worker.html");
+
+ InstallUrlInterceptor(install_sw_url,
+ "content/test/data/sxg/publisher-service-worker.html");
+ InstallUrlInterceptor(
+ GURL("https://test.example.org/test/publisher-service-worker.js"),
+ "content/test/data/sxg/publisher-service-worker.js");
+ {
+ base::string16 title = base::ASCIIToUTF16("Done");
+ TitleWatcher title_watcher(shell()->web_contents(), title);
+ NavigateToURL(shell(), install_sw_url);
+ EXPECT_EQ(title, title_watcher.WaitAndGetTitle());
+ }
+ embedded_test_server()->ServeFilesFromSourceDirectory("content/test/data");
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ GURL url = embedded_test_server()->GetURL("/sxg/test.example.org_test.sxg");
+
+ base::string16 title = base::ASCIIToUTF16("https://test.example.org/test/");
+ TitleWatcher title_watcher(shell()->web_contents(), title);
+ title_watcher.AlsoWaitForTitle(base::ASCIIToUTF16("Generated"));
+ NavigateToURL(shell(), url);
+ // The page content shoud be served from the signed exchange.
+ EXPECT_EQ(title, title_watcher.WaitAndGetTitle());
+}
+
+IN_PROC_BROWSER_TEST_P(SignedExchangeRequestHandlerWithServiceWorkerBrowserTest,
+ NotControlledByDistributorsSW) {
+ // SW-scope: http://127.0.0.1:PORT/sxg/
+ // SXG physical URL: http://127.0.0.1:PORT/sxg/test.example.org_test.sxg
+ // SXG logical URL: https://test.example.org/test/
+ InstallUrlInterceptor(
+ GURL("https://cert.example.org/cert.msg"),
+ "content/test/data/sxg/test.example.org.public.pem.cbor");
+ InstallMockCert();
+ embedded_test_server()->ServeFilesFromSourceDirectory("content/test/data");
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ const GURL install_sw_url = embedded_test_server()->GetURL(
+ "/sxg/no-respond-with-service-worker.html");
+
+ {
+ base::string16 title = base::ASCIIToUTF16("Done");
+ TitleWatcher title_watcher(shell()->web_contents(), title);
+ NavigateToURL(shell(), install_sw_url);
+ EXPECT_EQ(title, title_watcher.WaitAndGetTitle());
+ }
+
+ base::string16 title = base::ASCIIToUTF16("https://test.example.org/test/");
+ TitleWatcher title_watcher(shell()->web_contents(), title);
+ NavigateToURL(shell(), embedded_test_server()->GetURL(
+ "/sxg/test.example.org_test.sxg"));
+ EXPECT_EQ(title, title_watcher.WaitAndGetTitle());
+
+ // The page must not be controlled by the service worker of the physical URL.
+ EXPECT_EQ(false, EvalJs(shell(), "!!navigator.serviceWorker.controller"));
+}
+
+IN_PROC_BROWSER_TEST_P(SignedExchangeRequestHandlerWithServiceWorkerBrowserTest,
+ NotControlledBySameOriginDistributorsSW) {
+ // SW-scope: https://test.example.org/scope/
+ // SXG physical URL: https://test.example.org/scope/test.example.org_test.sxg
+ // SXG logical URL: https://test.example.org/test/
+ InstallUrlInterceptor(
+ GURL("https://cert.example.org/cert.msg"),
+ "content/test/data/sxg/test.example.org.public.pem.cbor");
+ InstallMockCert();
+
+ InstallUrlInterceptor(GURL("https://test.example.org/scope/test.sxg"),
+ "content/test/data/sxg/test.example.org_test.sxg");
+
+ const GURL install_sw_url = GURL(
+ "https://test.example.org/scope/no-respond-with-service-worker.html");
+
+ InstallUrlInterceptor(
+ install_sw_url,
+ "content/test/data/sxg/no-respond-with-service-worker.html");
+ InstallUrlInterceptor(
+ GURL("https://test.example.org/scope/no-respond-with-service-worker.js"),
+ "content/test/data/sxg/no-respond-with-service-worker.js");
+
+ {
+ base::string16 title = base::ASCIIToUTF16("Done");
+ TitleWatcher title_watcher(shell()->web_contents(), title);
+ NavigateToURL(shell(), install_sw_url);
+ EXPECT_EQ(title, title_watcher.WaitAndGetTitle());
+ }
+
+ base::string16 title = base::ASCIIToUTF16("https://test.example.org/test/");
+ TitleWatcher title_watcher(shell()->web_contents(), title);
+ NavigateToURL(shell(), GURL("https://test.example.org/scope/test.sxg"));
+ EXPECT_EQ(title, title_watcher.WaitAndGetTitle());
+
+ // The page must not be controlled by the service worker of the physical URL.
+ EXPECT_EQ(false, EvalJs(shell(), "!!navigator.serviceWorker.controller"));
+}
+
+IN_PROC_BROWSER_TEST_P(SignedExchangeRequestHandlerWithServiceWorkerBrowserTest,
+ RegisterServiceWorkerFromSignedExchange) {
+ // SXG physical URL: http://127.0.0.1:PORT/sxg/test.example.org_test.sxg
+ // SXG logical URL: https://test.example.org/test/
+ InstallUrlInterceptor(
+ GURL("https://cert.example.org/cert.msg"),
+ "content/test/data/sxg/test.example.org.public.pem.cbor");
+ InstallMockCert();
+
+ InstallUrlInterceptor(
+ GURL("https://test.example.org/test/publisher-service-worker.js"),
+ "content/test/data/sxg/publisher-service-worker.js");
+
+ embedded_test_server()->ServeFilesFromSourceDirectory("content/test/data");
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ GURL url = embedded_test_server()->GetURL("/sxg/test.example.org_test.sxg");
+
+ {
+ base::string16 title = base::ASCIIToUTF16("https://test.example.org/test/");
+ TitleWatcher title_watcher(shell()->web_contents(), title);
+ NavigateToURL(shell(), url);
+ EXPECT_EQ(title, title_watcher.WaitAndGetTitle());
+ }
+
+ const std::string register_sw_script =
+ "(async function() {"
+ " try {"
+ " const registration = await navigator.serviceWorker.register("
+ " 'publisher-service-worker.js', {scope: './'});"
+ " window.domAutomationController.send(true);"
+ " } catch (e) {"
+ " window.domAutomationController.send(false);"
+ " }"
+ "})();";
+ bool result = false;
+ EXPECT_TRUE(ExecuteScriptAndExtractBool(shell()->web_contents(),
+ register_sw_script, &result));
+ // serviceWorker.register() fails because the document URL of
+ // ServiceWorkerProviderHost is empty.
+ EXPECT_FALSE(result);
+}
+
+INSTANTIATE_TEST_CASE_P(
+ SignedExchangeRequestHandlerWithServiceWorkerBrowserTest,
+ SignedExchangeRequestHandlerWithServiceWorkerBrowserTest,
+ testing::Values(
+ SignedExchangeRequestHandlerWithServiceWorkerBrowserTestParam::kLegacy,
+ SignedExchangeRequestHandlerWithServiceWorkerBrowserTestParam::
+ kServiceWorkerServicification,
+ SignedExchangeRequestHandlerWithServiceWorkerBrowserTestParam::
+ kNetworkService));
+
+struct SignedExchangeAcceptHeaderBrowserTestParam {
+ SignedExchangeAcceptHeaderBrowserTestParam(
+ bool sxg_enabled,
+ bool sxg_origin_trial_enabled,
+ bool sxg_accept_header_enabled,
+ bool service_worker_servicification_enabled)
+ : sxg_enabled(sxg_enabled),
+ sxg_origin_trial_enabled(sxg_origin_trial_enabled),
+ sxg_accept_header_enabled(sxg_accept_header_enabled),
+ service_worker_servicification_enabled(
+ service_worker_servicification_enabled) {}
+ const bool sxg_enabled;
+ const bool sxg_origin_trial_enabled;
+ const bool sxg_accept_header_enabled;
+ const bool service_worker_servicification_enabled;
+};
+
+class SignedExchangeAcceptHeaderBrowserTest
+ : public ContentBrowserTest,
+ public testing::WithParamInterface<
+ SignedExchangeAcceptHeaderBrowserTestParam> {
+ public:
+ using self = SignedExchangeAcceptHeaderBrowserTest;
+ SignedExchangeAcceptHeaderBrowserTest()
+ : enabled_https_server_(net::EmbeddedTestServer::TYPE_HTTPS),
+ disabled_https_server_(net::EmbeddedTestServer::TYPE_HTTPS) {}
+ ~SignedExchangeAcceptHeaderBrowserTest() override = default;
+
+ protected:
+ void SetUp() override {
+ std::vector<base::Feature> enable_features;
+ std::vector<base::Feature> disable_features;
+ if (GetParam().sxg_enabled) {
+ enable_features.push_back(features::kSignedHTTPExchange);
+ } else {
+ disable_features.push_back(features::kSignedHTTPExchange);
+ }
+ if (GetParam().sxg_origin_trial_enabled) {
+ enable_features.push_back(features::kSignedHTTPExchangeOriginTrial);
+ } else {
+ disable_features.push_back(features::kSignedHTTPExchangeOriginTrial);
+ }
+ if (GetParam().service_worker_servicification_enabled) {
+ enable_features.push_back(blink::features::kServiceWorkerServicification);
+ } else {
+ disable_features.push_back(
+ blink::features::kServiceWorkerServicification);
+ }
+ feature_list_.InitWithFeatures(enable_features, disable_features);
+
+ enabled_https_server_.ServeFilesFromSourceDirectory("content/test/data");
+ enabled_https_server_.RegisterRequestHandler(
+ base::BindRepeating(&self::RedirectResponseHandler));
+ enabled_https_server_.RegisterRequestMonitor(
+ base::BindRepeating(&self::MonitorRequest, base::Unretained(this)));
+ ASSERT_TRUE(enabled_https_server_.Start());
+
+ disabled_https_server_.ServeFilesFromSourceDirectory("content/test/data");
+ disabled_https_server_.RegisterRequestHandler(
+ base::BindRepeating(&self::RedirectResponseHandler));
+ disabled_https_server_.RegisterRequestMonitor(
+ base::BindRepeating(&self::MonitorRequest, base::Unretained(this)));
+ ASSERT_TRUE(disabled_https_server_.Start());
+
+ if (GetParam().sxg_accept_header_enabled) {
+ std::map<std::string, std::string> feature_parameters;
+ feature_parameters["OriginsList"] =
+ base::StringPrintf("127.0.0.1:%u", enabled_https_server_.port());
+ feature_list_for_accept_header_.InitAndEnableFeatureWithParameters(
+ features::kSignedHTTPExchangeAcceptHeader, feature_parameters);
+ }
+ ContentBrowserTest::SetUp();
+ }
+
+ void NavigateAndWaitForTitle(const GURL& url, const std::string title) {
+ base::string16 expected_title = base::ASCIIToUTF16(title);
+ TitleWatcher title_watcher(shell()->web_contents(), expected_title);
+ NavigateToURL(shell(), url);
+ EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
+ }
+
+ bool ShouldHaveSXGAcceptHeaderInEnabledOrigin() const {
+ return GetParam().sxg_enabled || (GetParam().sxg_origin_trial_enabled &&
+ GetParam().sxg_accept_header_enabled);
+ }
+
+ bool ShouldHaveSXGAcceptHeaderInDisabledOrigin() const {
+ return GetParam().sxg_enabled;
+ }
+
+ void CheckAcceptHeader(const GURL& url, bool is_navigation) {
+ const bool is_enabled_origin =
+ url.IntPort() == enabled_https_server_.port();
+ const bool should_have_sxg =
+ is_enabled_origin ? ShouldHaveSXGAcceptHeaderInEnabledOrigin()
+ : ShouldHaveSXGAcceptHeaderInDisabledOrigin();
+ const auto accept_header = GetInterceptedAcceptHeader(url);
+ ASSERT_TRUE(accept_header);
+ EXPECT_EQ(
+ *accept_header,
+ should_have_sxg
+ ? (is_navigation
+ ? std::string(network::kFrameAcceptHeader) +
+ std::string(kAcceptHeaderSignedExchangeSuffix)
+ : std::string(kExpectedSXGEnabledAcceptHeaderForPrefetch))
+ : (is_navigation ? std::string(network::kFrameAcceptHeader)
+ : std::string(network::kDefaultAcceptHeader)));
+ }
+
+ void CheckNavigationAcceptHeader(const std::vector<GURL>& urls) {
+ for (const auto& url : urls) {
+ SCOPED_TRACE(url);
+ CheckAcceptHeader(url, true /* is_navigation */);
+ }
+ }
+
+ void CheckPrefetchAcceptHeader(const std::vector<GURL>& urls) {
+ for (const auto& url : urls) {
+ SCOPED_TRACE(url);
+ CheckAcceptHeader(url, false /* is_navigation */);
+ }
+ }
+
+ base::Optional<std::string> GetInterceptedAcceptHeader(
+ const GURL& url) const {
+ const auto it = url_accept_header_map_.find(url);
+ if (it == url_accept_header_map_.end())
+ return base::nullopt;
+ return it->second;
+ }
+
+ void ClearInterceptedAcceptHeaders() { url_accept_header_map_.clear(); }
+
+ net::EmbeddedTestServer enabled_https_server_;
+ net::EmbeddedTestServer disabled_https_server_;
+
+ private:
+ static std::unique_ptr<net::test_server::HttpResponse>
+ RedirectResponseHandler(const net::test_server::HttpRequest& request) {
+ if (!base::StartsWith(request.relative_url, "/r?",
+ base::CompareCase::SENSITIVE)) {
+ return std::unique_ptr<net::test_server::HttpResponse>();
+ }
+ std::unique_ptr<net::test_server::BasicHttpResponse> http_response(
+ new net::test_server::BasicHttpResponse);
+ http_response->set_code(net::HTTP_MOVED_PERMANENTLY);
+ http_response->AddCustomHeader("Location", request.relative_url.substr(3));
+ http_response->AddCustomHeader("Cache-Control", "no-cache");
+ return std::move(http_response);
+ }
+
+ void MonitorRequest(const net::test_server::HttpRequest& request) {
+ const auto it = request.headers.find(std::string(network::kAcceptHeader));
+ if (it == request.headers.end())
+ return;
+ url_accept_header_map_[request.base_url.Resolve(request.relative_url)] =
+ it->second;
+ }
+
+ base::test::ScopedFeatureList feature_list_;
+ base::test::ScopedFeatureList feature_list_for_accept_header_;
+
+ std::map<GURL, std::string> url_accept_header_map_;
+};
+
+IN_PROC_BROWSER_TEST_P(SignedExchangeAcceptHeaderBrowserTest, EnabledOrigin) {
+ const GURL enabled_test_url = enabled_https_server_.GetURL("/sxg/test.html");
+ EXPECT_EQ(ShouldHaveSXGAcceptHeaderInEnabledOrigin(),
+ signed_exchange_utils::ShouldAdvertiseAcceptHeader(
+ url::Origin::Create(enabled_test_url)));
+ NavigateAndWaitForTitle(enabled_test_url, enabled_test_url.spec());
+ CheckNavigationAcceptHeader({enabled_test_url});
+}
+
+IN_PROC_BROWSER_TEST_P(SignedExchangeAcceptHeaderBrowserTest, DisabledOrigin) {
+ const GURL disabled_test_url =
+ disabled_https_server_.GetURL("/sxg/test.html");
+ EXPECT_EQ(GetParam().sxg_enabled,
+ signed_exchange_utils::ShouldAdvertiseAcceptHeader(
+ url::Origin::Create(disabled_test_url)));
+
+ NavigateAndWaitForTitle(disabled_test_url, disabled_test_url.spec());
+ CheckNavigationAcceptHeader({disabled_test_url});
}
+IN_PROC_BROWSER_TEST_P(SignedExchangeAcceptHeaderBrowserTest,
+ RedirectEnabledToDisabledToEnabled) {
+ const GURL enabled_test_url = enabled_https_server_.GetURL("/sxg/test.html");
+ const GURL redirect_disabled_to_enabled_url =
+ disabled_https_server_.GetURL("/r?" + enabled_test_url.spec());
+ const GURL redirect_enabled_to_disabled_to_enabled_url =
+ enabled_https_server_.GetURL("/r?" +
+ redirect_disabled_to_enabled_url.spec());
+ NavigateAndWaitForTitle(redirect_enabled_to_disabled_to_enabled_url,
+ enabled_test_url.spec());
+
+ CheckNavigationAcceptHeader({redirect_enabled_to_disabled_to_enabled_url,
+ redirect_disabled_to_enabled_url,
+ enabled_test_url});
+}
+
+IN_PROC_BROWSER_TEST_P(SignedExchangeAcceptHeaderBrowserTest,
+ RedirectDisabledToEnabledToDisabled) {
+ const GURL disabled_test_url =
+ disabled_https_server_.GetURL("/sxg/test.html");
+ const GURL redirect_enabled_to_disabled_url =
+ enabled_https_server_.GetURL("/r?" + disabled_test_url.spec());
+ const GURL redirect_disabled_to_enabled_to_disabled_url =
+ disabled_https_server_.GetURL("/r?" +
+ redirect_enabled_to_disabled_url.spec());
+ NavigateAndWaitForTitle(redirect_disabled_to_enabled_to_disabled_url,
+ disabled_test_url.spec());
+
+ CheckNavigationAcceptHeader({redirect_disabled_to_enabled_to_disabled_url,
+ redirect_enabled_to_disabled_url,
+ disabled_test_url});
+}
+
+IN_PROC_BROWSER_TEST_P(SignedExchangeAcceptHeaderBrowserTest,
+ PrefetchEnabledPageEnabledTarget) {
+ const GURL enabled_target = enabled_https_server_.GetURL("/sxg/hello.txt");
+ const GURL enabled_page_url = enabled_https_server_.GetURL(
+ std::string("/sxg/prefetch.html#") + enabled_target.spec());
+ NavigateAndWaitForTitle(enabled_page_url, "OK");
+ CheckPrefetchAcceptHeader({enabled_target});
+}
+
+IN_PROC_BROWSER_TEST_P(SignedExchangeAcceptHeaderBrowserTest,
+ PrefetchEnabledPageDisabledTarget) {
+ const GURL disabled_target = disabled_https_server_.GetURL("/sxg/hello.txt");
+ const GURL enabled_page_url = enabled_https_server_.GetURL(
+ std::string("/sxg/prefetch.html#") + disabled_target.spec());
+ NavigateAndWaitForTitle(enabled_page_url, "OK");
+ CheckPrefetchAcceptHeader({disabled_target});
+}
+
+IN_PROC_BROWSER_TEST_P(SignedExchangeAcceptHeaderBrowserTest,
+ PrefetchDisabledPageEnabledTarget) {
+ const GURL enabled_target = enabled_https_server_.GetURL("/sxg/hello.txt");
+ const GURL disabled_page_url = disabled_https_server_.GetURL(
+ std::string("/sxg/prefetch.html#") + enabled_target.spec());
+ NavigateAndWaitForTitle(disabled_page_url, "OK");
+ CheckPrefetchAcceptHeader({enabled_target});
+}
+
+IN_PROC_BROWSER_TEST_P(SignedExchangeAcceptHeaderBrowserTest,
+ PrefetchDisabledPageDisabledTarget) {
+ const GURL disabled_target = disabled_https_server_.GetURL("/sxg/hello.txt");
+ const GURL disabled_page_url = disabled_https_server_.GetURL(
+ std::string("/sxg/prefetch.html#") + disabled_target.spec());
+ NavigateAndWaitForTitle(disabled_page_url, "OK");
+ CheckPrefetchAcceptHeader({disabled_target});
+}
+
+IN_PROC_BROWSER_TEST_P(
+ SignedExchangeAcceptHeaderBrowserTest,
+ PrefetchEnabledPageRedirectFromDisabledToEnabledToDisabledTarget) {
+ const GURL disabled_target = disabled_https_server_.GetURL("/sxg/hello.txt");
+ const GURL redirect_enabled_to_disabled_url =
+ enabled_https_server_.GetURL("/r?" + disabled_target.spec());
+ const GURL redirect_disabled_to_enabled_to_disabled_url =
+ disabled_https_server_.GetURL("/r?" +
+ redirect_enabled_to_disabled_url.spec());
+
+ const GURL enabled_page_url = enabled_https_server_.GetURL(
+ std::string("/sxg/prefetch.html#") +
+ redirect_disabled_to_enabled_to_disabled_url.spec());
+
+ NavigateAndWaitForTitle(enabled_page_url, "OK");
+
+ CheckPrefetchAcceptHeader({redirect_disabled_to_enabled_to_disabled_url,
+ redirect_enabled_to_disabled_url,
+ disabled_target});
+}
+
+IN_PROC_BROWSER_TEST_P(SignedExchangeAcceptHeaderBrowserTest, ServiceWorker) {
+ NavigateAndWaitForTitle(
+ enabled_https_server_.GetURL("/sxg/service-worker.html"), "Done");
+ NavigateAndWaitForTitle(
+ disabled_https_server_.GetURL("/sxg/service-worker.html"), "Done");
+
+ const std::string frame_accept = std::string(network::kFrameAcceptHeader);
+ const std::string frame_accept_with_sxg =
+ frame_accept + std::string(kAcceptHeaderSignedExchangeSuffix);
+ const std::vector<std::string> scopes = {"/sxg/sw-scope-generated/",
+ "/sxg/sw-scope-navigation-preload/",
+ "/sxg/sw-scope-no-respond-with/"};
+ for (const auto& scope : scopes) {
+ SCOPED_TRACE(scope);
+ const bool is_generated_scope =
+ scope == std::string("/sxg/sw-scope-generated/");
+ const GURL enabled_target_url =
+ enabled_https_server_.GetURL(scope + "test.html");
+ const GURL disabled_target_url =
+ disabled_https_server_.GetURL(scope + "test.html");
+ const GURL redirect_disabled_to_enabled_target_url =
+ disabled_https_server_.GetURL("/r?" + enabled_target_url.spec());
+ const GURL redirect_enabled_to_disabled_to_enabled_target_url =
+ enabled_https_server_.GetURL(
+ "/r?" + redirect_disabled_to_enabled_target_url.spec());
+ const GURL redirect_enabled_to_disabled_target_url =
+ enabled_https_server_.GetURL("/r?" + disabled_target_url.spec());
+ const GURL redirect_disabled_to_enabled_to_disabled_target_url =
+ disabled_https_server_.GetURL(
+ "/r?" + redirect_enabled_to_disabled_target_url.spec());
+
+ const std::string expected_enabled_title =
+ is_generated_scope ? (ShouldHaveSXGAcceptHeaderInEnabledOrigin()
+ ? frame_accept_with_sxg
+ : frame_accept)
+ : "Done";
+ const std::string expected_disabled_title =
+ is_generated_scope ? (ShouldHaveSXGAcceptHeaderInDisabledOrigin()
+ ? frame_accept_with_sxg
+ : frame_accept)
+ : "Done";
+ const base::Optional<std::string> expected_enabled_target_accept_header =
+ is_generated_scope ? base::nullopt
+ : base::Optional<std::string>(
+ ShouldHaveSXGAcceptHeaderInEnabledOrigin()
+ ? frame_accept_with_sxg
+ : frame_accept);
+ const base::Optional<std::string> expected_disabled_target_accept_header =
+ is_generated_scope ? base::nullopt
+ : base::Optional<std::string>(
+ ShouldHaveSXGAcceptHeaderInDisabledOrigin()
+ ? frame_accept_with_sxg
+ : frame_accept);
+
+ NavigateAndWaitForTitle(enabled_target_url, expected_enabled_title);
+ EXPECT_EQ(expected_enabled_target_accept_header,
+ GetInterceptedAcceptHeader(enabled_target_url));
+ ClearInterceptedAcceptHeaders();
+
+ NavigateAndWaitForTitle(disabled_target_url, expected_disabled_title);
+ EXPECT_EQ(expected_disabled_target_accept_header,
+ GetInterceptedAcceptHeader(disabled_target_url));
+ ClearInterceptedAcceptHeaders();
+
+ NavigateAndWaitForTitle(redirect_disabled_to_enabled_target_url,
+ expected_enabled_title);
+ CheckNavigationAcceptHeader({redirect_disabled_to_enabled_target_url});
+ EXPECT_EQ(expected_enabled_target_accept_header,
+ GetInterceptedAcceptHeader(enabled_target_url));
+ ClearInterceptedAcceptHeaders();
+
+ NavigateAndWaitForTitle(redirect_enabled_to_disabled_target_url,
+ expected_disabled_title);
+ CheckNavigationAcceptHeader({redirect_enabled_to_disabled_target_url});
+ EXPECT_EQ(expected_disabled_target_accept_header,
+ GetInterceptedAcceptHeader(disabled_target_url));
+ ClearInterceptedAcceptHeaders();
+
+ NavigateAndWaitForTitle(redirect_enabled_to_disabled_to_enabled_target_url,
+ expected_enabled_title);
+ CheckNavigationAcceptHeader(
+ {redirect_enabled_to_disabled_to_enabled_target_url,
+ redirect_disabled_to_enabled_target_url});
+ EXPECT_EQ(expected_enabled_target_accept_header,
+ GetInterceptedAcceptHeader(enabled_target_url));
+ ClearInterceptedAcceptHeaders();
+
+ NavigateAndWaitForTitle(redirect_disabled_to_enabled_to_disabled_target_url,
+ expected_disabled_title);
+ CheckNavigationAcceptHeader(
+ {redirect_disabled_to_enabled_to_disabled_target_url,
+ redirect_enabled_to_disabled_target_url});
+ EXPECT_EQ(expected_disabled_target_accept_header,
+ GetInterceptedAcceptHeader(disabled_target_url));
+ }
+}
+
+IN_PROC_BROWSER_TEST_P(SignedExchangeAcceptHeaderBrowserTest,
+ ServiceWorkerPrefetch) {
+ NavigateAndWaitForTitle(
+ enabled_https_server_.GetURL("/sxg/service-worker-prefetch.html"),
+ "Done");
+ NavigateAndWaitForTitle(
+ disabled_https_server_.GetURL("/sxg/service-worker-prefetch.html"),
+ "Done");
+ const std::string scope = "/sxg/sw-prefetch-scope/";
+ const GURL enabled_target_url =
+ enabled_https_server_.GetURL(scope + "test.html");
+ const GURL disabled_target_url =
+ disabled_https_server_.GetURL(scope + "test.html");
+
+ const GURL enabled_prefetch_target =
+ enabled_https_server_.GetURL(std::string("/sxg/hello.txt"));
+ const GURL disabled_prefetch_target =
+ disabled_https_server_.GetURL(std::string("/sxg/hello.txt"));
+ const std::string load_prefetch_script = base::StringPrintf(
+ "(function loadPrefetch(urls) {"
+ " for (let url of urls) {"
+ " let link = document.createElement('link');"
+ " link.rel = 'prefetch';"
+ " link.href = url;"
+ " document.body.appendChild(link);"
+ " }"
+ " function check() {"
+ " const entries = performance.getEntriesByType('resource');"
+ " const url_set = new Set(urls);"
+ " for (let entry of entries) {"
+ " url_set.delete(entry.name);"
+ " }"
+ " if (!url_set.size) {"
+ " window.domAutomationController.send(true);"
+ " } else {"
+ " setTimeout(check, 100);"
+ " }"
+ " }"
+ " check();"
+ "})(['%s','%s'])",
+ enabled_prefetch_target.spec().c_str(),
+ disabled_prefetch_target.spec().c_str());
+ bool unused = false;
+
+ NavigateAndWaitForTitle(enabled_target_url, "Done");
+ EXPECT_TRUE(ExecuteScriptAndExtractBool(shell()->web_contents(),
+ load_prefetch_script, &unused));
+ CheckPrefetchAcceptHeader(
+ {enabled_prefetch_target, disabled_prefetch_target});
+ ClearInterceptedAcceptHeaders();
+
+ NavigateAndWaitForTitle(disabled_target_url, "Done");
+ EXPECT_TRUE(ExecuteScriptAndExtractBool(shell()->web_contents(),
+ load_prefetch_script, &unused));
+ CheckPrefetchAcceptHeader(
+ {enabled_prefetch_target, disabled_prefetch_target});
+}
+
+INSTANTIATE_TEST_CASE_P(
+ SignedExchangeAcceptHeaderBrowserTest,
+ SignedExchangeAcceptHeaderBrowserTest,
+ testing::Values(
+ SignedExchangeAcceptHeaderBrowserTestParam(false, false, false, false),
+ SignedExchangeAcceptHeaderBrowserTestParam(false, false, false, true),
+ SignedExchangeAcceptHeaderBrowserTestParam(false, false, true, false),
+ SignedExchangeAcceptHeaderBrowserTestParam(false, false, true, true),
+ SignedExchangeAcceptHeaderBrowserTestParam(false, true, false, false),
+ SignedExchangeAcceptHeaderBrowserTestParam(false, true, false, true),
+ SignedExchangeAcceptHeaderBrowserTestParam(false, true, true, false),
+ SignedExchangeAcceptHeaderBrowserTestParam(false, true, true, true),
+ SignedExchangeAcceptHeaderBrowserTestParam(true, false, false, false),
+ SignedExchangeAcceptHeaderBrowserTestParam(true, false, false, true),
+ SignedExchangeAcceptHeaderBrowserTestParam(true, false, true, false),
+ SignedExchangeAcceptHeaderBrowserTestParam(true, false, true, true),
+ SignedExchangeAcceptHeaderBrowserTestParam(true, true, false, false),
+ SignedExchangeAcceptHeaderBrowserTestParam(true, true, false, true),
+ SignedExchangeAcceptHeaderBrowserTestParam(true, true, true, false),
+ SignedExchangeAcceptHeaderBrowserTestParam(true, true, true, true)));
+
} // namespace content
diff --git a/chromium/content/browser/web_package/signed_exchange_signature_header_field.cc b/chromium/content/browser/web_package/signed_exchange_signature_header_field.cc
index f6e3cfdeb81..907e09efa94 100644
--- a/chromium/content/browser/web_package/signed_exchange_signature_header_field.cc
+++ b/chromium/content/browser/web_package/signed_exchange_signature_header_field.cc
@@ -280,28 +280,6 @@ SignedExchangeSignatureHeaderField::ParseSignature(
return signatures;
}
-// static
-bool SignedExchangeSignatureHeaderField::GetVersionParamFromContentType(
- base::StringPiece content_type,
- base::Optional<SignedExchangeVersion>* version_param) {
- DCHECK(version_param);
- StructuredHeaderParser parser(content_type);
- ParameterisedIdentifier parameterised_identifier;
- parser.ParseParameterisedIdentifier(&parameterised_identifier);
- if (!parser.ParsedSuccessfully())
- return false;
- const auto it = parameterised_identifier.params.find("v");
- if (it == parameterised_identifier.params.end()) {
- *version_param = base::nullopt;
- } else {
- if (it->second == "b2")
- *version_param = SignedExchangeVersion::kB2;
- else
- return false;
- }
- return true;
-}
-
SignedExchangeSignatureHeaderField::Signature::Signature() = default;
SignedExchangeSignatureHeaderField::Signature::Signature(
const Signature& other) = default;
diff --git a/chromium/content/browser/web_package/signed_exchange_signature_header_field.h b/chromium/content/browser/web_package/signed_exchange_signature_header_field.h
index 166850ce21d..c2603c4d444 100644
--- a/chromium/content/browser/web_package/signed_exchange_signature_header_field.h
+++ b/chromium/content/browser/web_package/signed_exchange_signature_header_field.h
@@ -13,7 +13,6 @@
#include "base/macros.h"
#include "base/optional.h"
#include "base/strings/string_piece.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"
@@ -22,7 +21,7 @@ namespace content {
class SignedExchangeDevToolsProxy;
-// SignedExchangeSignatureHeaderField provides parser for signed exchange's
+// SignedExchangeSignatureHeaderField provides a parser for signed exchange's
// `Signature` header field.
// https://wicg.github.io/webpackage/draft-yasskin-httpbis-origin-signed-exchanges-impl.html
class CONTENT_EXPORT SignedExchangeSignatureHeaderField {
@@ -49,14 +48,6 @@ class CONTENT_EXPORT SignedExchangeSignatureHeaderField {
static base::Optional<std::vector<Signature>> ParseSignature(
base::StringPiece signature_str,
SignedExchangeDevToolsProxy* devtools_proxy);
-
- // TODO(kouhei): Move this to another class.
- // Parses |content_type| to get the value of "v=" parameter of the signed
- // exchange, and converts to SignedExchangeVersion. Returns false if failed to
- // parse.
- static bool GetVersionParamFromContentType(
- base::StringPiece content_type,
- base::Optional<SignedExchangeVersion>* version_param);
};
} // namespace content
diff --git a/chromium/content/browser/web_package/signed_exchange_signature_header_field_unittest.cc b/chromium/content/browser/web_package/signed_exchange_signature_header_field_unittest.cc
index e34fd133926..b6cacc14c51 100644
--- a/chromium/content/browser/web_package/signed_exchange_signature_header_field_unittest.cc
+++ b/chromium/content/browser/web_package/signed_exchange_signature_header_field_unittest.cc
@@ -274,60 +274,4 @@ TEST_F(SignedExchangeSignatureHeaderFieldTest, AsteriskInTheMiddleOfBinary) {
EXPECT_FALSE(signatures.has_value());
}
-TEST_F(SignedExchangeSignatureHeaderFieldTest, VersionParam_None) {
- const char content_type[] = "application/signed-exchange";
- base::Optional<SignedExchangeVersion> version;
- EXPECT_TRUE(
- SignedExchangeSignatureHeaderField::GetVersionParamFromContentType(
- content_type, &version));
- EXPECT_FALSE(version);
-}
-
-TEST_F(SignedExchangeSignatureHeaderFieldTest, VersionParam_NoneWithSemicolon) {
- const char content_type[] = "application/signed-exchange;";
- base::Optional<SignedExchangeVersion> version;
- EXPECT_FALSE(
- SignedExchangeSignatureHeaderField::GetVersionParamFromContentType(
- content_type, &version));
-}
-
-TEST_F(SignedExchangeSignatureHeaderFieldTest, VersionParam_EmptyString) {
- const char content_type[] = "application/signed-exchange;v=";
- base::Optional<SignedExchangeVersion> version;
- EXPECT_FALSE(
- SignedExchangeSignatureHeaderField::GetVersionParamFromContentType(
- content_type, &version));
-}
-
-TEST_F(SignedExchangeSignatureHeaderFieldTest, VersionParam_Simple) {
- const char content_type[] = "application/signed-exchange;v=b2";
- base::Optional<SignedExchangeVersion> version;
- EXPECT_TRUE(
- SignedExchangeSignatureHeaderField::GetVersionParamFromContentType(
- content_type, &version));
- ASSERT_TRUE(version);
- EXPECT_EQ(*version, SignedExchangeVersion::kB2);
-}
-
-TEST_F(SignedExchangeSignatureHeaderFieldTest, VersionParam_SimpleWithSpace) {
- const char content_type[] = "application/signed-exchange; v=b2";
- base::Optional<SignedExchangeVersion> version;
- EXPECT_TRUE(
- SignedExchangeSignatureHeaderField::GetVersionParamFromContentType(
- content_type, &version));
- ASSERT_TRUE(version);
- EXPECT_EQ(*version, SignedExchangeVersion::kB2);
-}
-
-TEST_F(SignedExchangeSignatureHeaderFieldTest,
- VersionParam_SimpleWithDoublequotes) {
- const char content_type[] = "application/signed-exchange;v=\"b2\"";
- base::Optional<SignedExchangeVersion> version;
- EXPECT_TRUE(
- SignedExchangeSignatureHeaderField::GetVersionParamFromContentType(
- content_type, &version));
- ASSERT_TRUE(version);
- EXPECT_EQ(*version, SignedExchangeVersion::kB2);
-}
-
} // namespace content
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 f19306b6f9a..3e5960ef526 100644
--- a/chromium/content/browser/web_package/signed_exchange_signature_verifier.cc
+++ b/chromium/content/browser/web_package/signed_exchange_signature_verifier.cc
@@ -4,23 +4,31 @@
#include "content/browser/web_package/signed_exchange_signature_verifier.h"
+#include <string>
+#include <vector>
+
#include "base/big_endian.h"
+#include "base/command_line.h"
#include "base/containers/span.h"
#include "base/format_macros.h"
-#include "base/strings/string_number_conversions.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/no_destructor.h"
#include "base/strings/string_piece.h"
+#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
-#include "components/cbor/cbor_writer.h"
#include "content/browser/web_package/signed_exchange_consts.h"
#include "content/browser/web_package/signed_exchange_envelope.h"
#include "content/browser/web_package/signed_exchange_signature_header_field.h"
#include "content/browser/web_package/signed_exchange_utils.h"
+#include "content/public/browser/content_browser_client.h"
+#include "crypto/sha2.h"
#include "crypto/signature_verifier.h"
#include "net/cert/asn1_util.h"
#include "net/cert/x509_util.h"
+#include "services/network/public/cpp/network_switches.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"
@@ -46,54 +54,8 @@ constexpr uint8_t kMessageHeader[] =
// 5.3. "A single 0 byte which serves as a separator." [spec text]
"HTTP Exchange 1 b2";
-base::Optional<cbor::CBORValue> GenerateCanonicalRequestCBOR(
- const SignedExchangeEnvelope& envelope) {
- cbor::CBORValue::MapValue map;
- map.insert_or_assign(
- cbor::CBORValue(kMethodKey, cbor::CBORValue::Type::BYTE_STRING),
- cbor::CBORValue(envelope.request_method(),
- cbor::CBORValue::Type::BYTE_STRING));
- map.insert_or_assign(
- cbor::CBORValue(kUrlKey, cbor::CBORValue::Type::BYTE_STRING),
- cbor::CBORValue(envelope.request_url().spec(),
- cbor::CBORValue::Type::BYTE_STRING));
-
- return cbor::CBORValue(map);
-}
-
-base::Optional<cbor::CBORValue> GenerateCanonicalResponseCBOR(
- const SignedExchangeEnvelope& envelope) {
- const auto& headers = envelope.response_headers();
- cbor::CBORValue::MapValue map;
- std::string response_code_str =
- base::NumberToString(envelope.response_code());
- map.insert_or_assign(
- cbor::CBORValue(kStatusKey, cbor::CBORValue::Type::BYTE_STRING),
- cbor::CBORValue(response_code_str, cbor::CBORValue::Type::BYTE_STRING));
- for (const auto& pair : headers) {
- map.insert_or_assign(
- cbor::CBORValue(pair.first, cbor::CBORValue::Type::BYTE_STRING),
- cbor::CBORValue(pair.second, cbor::CBORValue::Type::BYTE_STRING));
- }
- return cbor::CBORValue(map);
-}
-
-// Generate CBORValue from |envelope| as specified in:
-// https://wicg.github.io/webpackage/draft-yasskin-httpbis-origin-signed-exchanges-impl.html#cbor-representation
-base::Optional<cbor::CBORValue> GenerateCanonicalExchangeHeadersCBOR(
- const SignedExchangeEnvelope& envelope) {
- auto req_val = GenerateCanonicalRequestCBOR(envelope);
- if (!req_val)
- return base::nullopt;
- auto res_val = GenerateCanonicalResponseCBOR(envelope);
- if (!res_val)
- return base::nullopt;
-
- cbor::CBORValue::ArrayValue array;
- array.push_back(std::move(*req_val));
- array.push_back(std::move(*res_val));
- return cbor::CBORValue(array);
-}
+constexpr int kFourWeeksInSeconds = base::TimeDelta::FromDays(28).InSeconds();
+constexpr int kOneWeekInSeconds = base::TimeDelta::FromDays(7).InSeconds();
base::Optional<crypto::SignatureVerifier::SignatureAlgorithm>
GetSignatureAlgorithm(scoped_refptr<net::X509Certificate> cert,
@@ -244,17 +206,43 @@ bool VerifyTimestamps(const SignedExchangeEnvelope& envelope,
// 3. "If expires is more than 7 days (604800 seconds) after date, return
// "invalid"." [spec text]
- if ((expires_time - creation_time).InSeconds() > 604800)
+ if ((expires_time - creation_time).InSeconds() > kOneWeekInSeconds)
return false;
// 4. "If the current time is before date or after expires, return
// "invalid"."
- if (verification_time < creation_time || expires_time < verification_time)
+ if (verification_time < creation_time) {
+ UMA_HISTOGRAM_CUSTOM_COUNTS(
+ "SignedExchange.SignatureVerificationError.NotYetValid",
+ (creation_time - verification_time).InSeconds(), 1, kFourWeeksInSeconds,
+ 50);
return false;
+ }
+ if (expires_time < verification_time) {
+ UMA_HISTOGRAM_CUSTOM_COUNTS(
+ "SignedExchange.SignatureVerificationError.Expired",
+ (verification_time - expires_time).InSeconds(), 1, kFourWeeksInSeconds,
+ 50);
+ return false;
+ }
+ UMA_HISTOGRAM_CUSTOM_COUNTS("SignedExchange.TimeUntilExpiration",
+ (expires_time - verification_time).InSeconds(), 1,
+ kOneWeekInSeconds, 50);
return true;
}
+// Returns true if SPKI hash of |certificate| is included in the
+// --ignore-certificate-errors-spki-list command line flag, and
+// ContentBrowserClient::CanIgnoreCertificateErrorIfNeeded() returns true.
+bool ShouldIgnoreTimestampError(
+ scoped_refptr<net::X509Certificate> certificate) {
+ static base::NoDestructor<
+ SignedExchangeSignatureVerifier::IgnoreErrorsSPKIList>
+ instance(*base::CommandLine::ForCurrentProcess());
+ return instance->ShouldIgnoreError(certificate);
+}
+
} // namespace
SignedExchangeSignatureVerifier::Result SignedExchangeSignatureVerifier::Verify(
@@ -262,10 +250,12 @@ SignedExchangeSignatureVerifier::Result SignedExchangeSignatureVerifier::Verify(
scoped_refptr<net::X509Certificate> certificate,
const base::Time& verification_time,
SignedExchangeDevToolsProxy* devtools_proxy) {
+ SCOPED_UMA_HISTOGRAM_TIMER("SignedExchange.Time.SignatureVerify");
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("loading"),
"SignedExchangeSignatureVerifier::Verify");
- if (!VerifyTimestamps(envelope, verification_time)) {
+ if (!VerifyTimestamps(envelope, verification_time) &&
+ !ShouldIgnoreTimestampError(certificate)) {
signed_exchange_utils::ReportErrorAndTraceEvent(
devtools_proxy,
base::StringPrintf(
@@ -330,15 +320,43 @@ SignedExchangeSignatureVerifier::Result SignedExchangeSignatureVerifier::Verify(
return Result::kSuccess;
}
-base::Optional<std::vector<uint8_t>>
-SignedExchangeSignatureVerifier::EncodeCanonicalExchangeHeaders(
- const SignedExchangeEnvelope& envelope) {
- base::Optional<cbor::CBORValue> cbor_val =
- GenerateCanonicalExchangeHeadersCBOR(envelope);
- if (!cbor_val)
- return base::nullopt;
+SignedExchangeSignatureVerifier::IgnoreErrorsSPKIList::IgnoreErrorsSPKIList(
+ const std::string& spki_list) {
+ Parse(spki_list);
+}
+
+SignedExchangeSignatureVerifier::IgnoreErrorsSPKIList::IgnoreErrorsSPKIList(
+ const base::CommandLine& command_line) {
+ if (!GetContentClient()->browser()->CanIgnoreCertificateErrorIfNeeded())
+ return;
+ Parse(command_line.GetSwitchValueASCII(
+ network::switches::kIgnoreCertificateErrorsSPKIList));
+}
+
+void SignedExchangeSignatureVerifier::IgnoreErrorsSPKIList::Parse(
+ const std::string& spki_list) {
+ hash_set_ =
+ network::IgnoreErrorsCertVerifier::MakeWhitelist(base::SplitString(
+ spki_list, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL));
+}
- return cbor::CBORWriter::Write(*cbor_val);
+SignedExchangeSignatureVerifier::IgnoreErrorsSPKIList::~IgnoreErrorsSPKIList() =
+ default;
+
+bool SignedExchangeSignatureVerifier::IgnoreErrorsSPKIList::ShouldIgnoreError(
+ scoped_refptr<net::X509Certificate> certificate) {
+ if (hash_set_.empty())
+ return false;
+
+ base::StringPiece spki;
+ if (!net::asn1::ExtractSPKIFromDERCert(
+ net::x509_util::CryptoBufferAsStringPiece(certificate->cert_buffer()),
+ &spki)) {
+ return false;
+ }
+ net::SHA256HashValue hash;
+ crypto::SHA256HashString(spki, &hash, sizeof(net::SHA256HashValue));
+ return hash_set_.find(hash) != hash_set_.end();
}
} // namespace content
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 cca2ea786f5..b34a54ae224 100644
--- a/chromium/content/browser/web_package/signed_exchange_signature_verifier.h
+++ b/chromium/content/browser/web_package/signed_exchange_signature_verifier.h
@@ -5,17 +5,14 @@
#ifndef CONTENT_BROWSER_WEB_PACKAGE_SIGNED_EXCHANGE_SIGNATURE_VERIFIER_H_
#define CONTENT_BROWSER_WEB_PACKAGE_SIGNED_EXCHANGE_SIGNATURE_VERIFIER_H_
-#include <map>
-#include <string>
-#include <vector>
-
-#include "base/callback.h"
#include "base/memory/ref_counted.h"
#include "base/optional.h"
#include "content/common/content_export.h"
#include "net/cert/x509_certificate.h"
+#include "services/network/ignore_errors_cert_verifier.h"
namespace base {
+class CommandLine;
class Time;
} // namespace base
@@ -36,6 +33,7 @@ class SignedExchangeDevToolsProxy;
// https://wicg.github.io/webpackage/draft-yasskin-httpbis-origin-signed-exchanges-impl.html#signature-validity
class CONTENT_EXPORT SignedExchangeSignatureVerifier final {
public:
+ // This enum is used for recording histograms. Treat as append-only.
enum class Result {
kSuccess,
kErrNoCertificate,
@@ -45,16 +43,35 @@ class CONTENT_EXPORT SignedExchangeSignatureVerifier final {
kErrSignatureVerificationFailed,
kErrInvalidSignatureIntegrity,
kErrInvalidTimestamp,
- kErrUnsupportedCertType
+ kErrUnsupportedCertType,
+ kMaxValue = kErrUnsupportedCertType
+ };
+
+ // An utility class which holds a set of certificates which errors should be
+ // ignored. It parses a comma-delimited list of base64-encoded SHA-256 SPKI
+ // fingerprints, and can query if a certificate is included in the set.
+ // CONTENT_EXPORT since it is used from the unit test.
+ class CONTENT_EXPORT IgnoreErrorsSPKIList {
+ public:
+ explicit IgnoreErrorsSPKIList(const base::CommandLine& command_line);
+ ~IgnoreErrorsSPKIList();
+ bool ShouldIgnoreError(scoped_refptr<net::X509Certificate> certificate);
+
+ private:
+ FRIEND_TEST_ALL_PREFIXES(SignedExchangeSignatureVerifierTest,
+ IgnoreErrorsSPKIList);
+
+ explicit IgnoreErrorsSPKIList(const std::string& spki_list);
+ void Parse(const std::string& spki_list);
+
+ network::IgnoreErrorsCertVerifier::SPKIHashSet hash_set_;
+ DISALLOW_COPY_AND_ASSIGN(IgnoreErrorsSPKIList);
};
static Result Verify(const SignedExchangeEnvelope& envelope,
scoped_refptr<net::X509Certificate> certificate,
const base::Time& verification_time,
SignedExchangeDevToolsProxy* devtools_proxy);
-
- static base::Optional<std::vector<uint8_t>> EncodeCanonicalExchangeHeaders(
- const SignedExchangeEnvelope& envelope);
};
} // namespace content
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 25a6ab70296..41cfa75719f 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
@@ -4,62 +4,15 @@
#include "content/browser/web_package/signed_exchange_signature_verifier.h"
-#include "base/callback.h"
+#include "base/test/metrics/histogram_tester.h"
#include "content/browser/web_package/signed_exchange_envelope.h"
#include "content/browser/web_package/signed_exchange_signature_header_field.h"
#include "net/cert/x509_certificate.h"
-#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
namespace {
-TEST(SignedExchangeSignatureVerifier, EncodeCanonicalExchangeHeaders) {
- SignedExchangeEnvelope envelope;
- envelope.set_request_method("GET");
- envelope.set_request_url(GURL("https://example.com/index.html"));
- envelope.set_response_code(net::HTTP_OK);
- envelope.AddResponseHeader("content-type", "text/html; charset=utf-8");
- envelope.AddResponseHeader("content-encoding", "mi-sha256-03");
-
- base::Optional<std::vector<uint8_t>> encoded =
- SignedExchangeSignatureVerifier::EncodeCanonicalExchangeHeaders(envelope);
- ASSERT_TRUE(encoded.has_value());
-
- static const uint8_t kExpected[] = {
- // clang-format off
- 0x82, // array(2)
- 0xa2, // map(2)
- 0x44, 0x3a, 0x75, 0x72, 0x6c, // bytes ":url"
- 0x58, 0x1e, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x65,
- 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
- 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c,
- // bytes "https://example.com/index.html"
-
- 0x47, 0x3a, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, // bytes ":method"
- 0x43, 0x47, 0x45, 0x54, // bytes "GET"
-
- 0xa3, // map(3)
- 0x47, 0x3a, 0x73,0x74, 0x61, 0x74, 0x75, 0x73, // bytes ":status"
- 0x43, 0x32, 0x30, 0x30, // bytes "200"
-
- 0x4c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79,
- 0x70, 0x65, // bytes "content-type"
- 0x58, 0x18, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c,
- 0x3b, 0x20, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, 0x74, 0x3d, 0x75,
- 0x74, 0x66, 0x2d, 0x38, // bytes "text/html; charset=utf-8"
-
- 0x50, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x65, 0x6e,
- 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, // bytes "content-encoding"
- 0x4c, 0x6d, 0x69, 0x2d, 0x73, 0x68, 0x61, 0x32, 0x35, 0x36, 0x2d,
- 0x30, 0x33
- // bytes "mi-sha256-03"
- // clang-format on
- };
- EXPECT_THAT(*encoded,
- testing::ElementsAreArray(kExpected, arraysize(kExpected)));
-}
-
const uint64_t kSignatureHeaderDate = 1517892341;
const uint64_t kSignatureHeaderExpires = 1517895941;
@@ -165,6 +118,13 @@ DGC2vA1lb2Uy9bgLCYYkZoESjb/JYRQjCmqlwYKOozU7ZbIe3zJPjRWYP1Tuany5
Xhe5DP7VATeQq3yGV3ps+rCTHDP6qSHDEWP7DqHQdSsxtI0E
-----END CERTIFICATE-----)";
+constexpr char kPEMECDSAP256SPKIHash[] =
+ "iwtEGagHhL9HbHI38aoFstFPEyB+lzZO5H2ZZAJlYOo=";
+constexpr char kPEMECDSAP384SPKIHash[] =
+ "aGcf7fF/2+mXuHjYen7FZ8HZPR0B6sK6zIsyrCoB6Y8=";
+
+} // namespace
+
class SignedExchangeSignatureVerifierTest : public ::testing::Test {
protected:
SignedExchangeSignatureVerifierTest() {}
@@ -177,34 +137,69 @@ class SignedExchangeSignatureVerifierTest : public ::testing::Test {
void TestVerifierGivenValidInput(
const SignedExchangeEnvelope& envelope,
scoped_refptr<net::X509Certificate> certificate) {
- EXPECT_EQ(SignedExchangeSignatureVerifier::Result::kSuccess,
- SignedExchangeSignatureVerifier::Verify(
- envelope, certificate, VerificationTime(),
- nullptr /* devtools_proxy */));
-
- EXPECT_EQ(SignedExchangeSignatureVerifier::Result::kErrInvalidTimestamp,
- SignedExchangeSignatureVerifier::Verify(
- envelope, certificate,
- base::Time::UnixEpoch() +
- base::TimeDelta::FromSeconds(kSignatureHeaderDate - 1),
- nullptr /* devtools_proxy */
- ));
-
- EXPECT_EQ(SignedExchangeSignatureVerifier::Result::kSuccess,
- SignedExchangeSignatureVerifier::Verify(
- envelope, certificate,
- base::Time::UnixEpoch() +
- base::TimeDelta::FromSeconds(kSignatureHeaderExpires),
- nullptr /* devtools_proxy */
- ));
-
- EXPECT_EQ(SignedExchangeSignatureVerifier::Result::kErrInvalidTimestamp,
- SignedExchangeSignatureVerifier::Verify(
- envelope, certificate,
- base::Time::UnixEpoch() +
- base::TimeDelta::FromSeconds(kSignatureHeaderExpires + 1),
- nullptr /* devtools_proxy */
- ));
+ {
+ base::HistogramTester histogram_tester;
+ EXPECT_EQ(SignedExchangeSignatureVerifier::Result::kSuccess,
+ SignedExchangeSignatureVerifier::Verify(
+ envelope, certificate, VerificationTime(),
+ nullptr /* devtools_proxy */));
+ histogram_tester.ExpectUniqueSample(
+ "SignedExchange.TimeUntilExpiration",
+ kSignatureHeaderExpires - kSignatureHeaderDate, 1);
+ histogram_tester.ExpectTotalCount(
+ "SignedExchange.SignatureVerificationError.NotYetValid", 0);
+ histogram_tester.ExpectTotalCount(
+ "SignedExchange.SignatureVerificationError.Expired", 0);
+ }
+ {
+ base::HistogramTester histogram_tester;
+ EXPECT_EQ(SignedExchangeSignatureVerifier::Result::kErrInvalidTimestamp,
+ SignedExchangeSignatureVerifier::Verify(
+ envelope, certificate,
+ base::Time::UnixEpoch() +
+ base::TimeDelta::FromSeconds(kSignatureHeaderDate - 1),
+ nullptr /* devtools_proxy */
+ ));
+ histogram_tester.ExpectTotalCount("SignedExchange.TimeUntilExpiration",
+ 0);
+ histogram_tester.ExpectUniqueSample(
+ "SignedExchange.SignatureVerificationError.NotYetValid", 1, 1);
+ histogram_tester.ExpectTotalCount(
+ "SignedExchange.SignatureVerificationError.Expired", 0);
+ }
+
+ {
+ base::HistogramTester histogram_tester;
+ EXPECT_EQ(SignedExchangeSignatureVerifier::Result::kSuccess,
+ SignedExchangeSignatureVerifier::Verify(
+ envelope, certificate,
+ base::Time::UnixEpoch() +
+ base::TimeDelta::FromSeconds(kSignatureHeaderExpires),
+ nullptr /* devtools_proxy */
+ ));
+ histogram_tester.ExpectUniqueSample("SignedExchange.TimeUntilExpiration",
+ 0, 1);
+ histogram_tester.ExpectTotalCount(
+ "SignedExchange.SignatureVerificationError.NotYetValid", 0);
+ histogram_tester.ExpectTotalCount(
+ "SignedExchange.SignatureVerificationError.Expired", 0);
+ }
+ {
+ base::HistogramTester histogram_tester;
+ EXPECT_EQ(SignedExchangeSignatureVerifier::Result::kErrInvalidTimestamp,
+ SignedExchangeSignatureVerifier::Verify(
+ envelope, certificate,
+ base::Time::UnixEpoch() + base::TimeDelta::FromSeconds(
+ kSignatureHeaderExpires + 1),
+ nullptr /* devtools_proxy */
+ ));
+ histogram_tester.ExpectTotalCount("SignedExchange.TimeUntilExpiration",
+ 0);
+ histogram_tester.ExpectTotalCount(
+ "SignedExchange.SignatureVerificationError.NotYetValid", 0);
+ histogram_tester.ExpectUniqueSample(
+ "SignedExchange.SignatureVerificationError.Expired", 1, 1);
+ }
SignedExchangeEnvelope invalid_expires_envelope(envelope);
auto invalid_expires_signature =
@@ -338,5 +333,32 @@ TEST_F(SignedExchangeSignatureVerifierTest, VerifyECDSAP384) {
nullptr /* devtools_proxy */));
}
-} // namespace
+TEST_F(SignedExchangeSignatureVerifierTest, IgnoreErrorsSPKIList) {
+ SignedExchangeSignatureVerifier::IgnoreErrorsSPKIList ignore_nothing("");
+ SignedExchangeSignatureVerifier::IgnoreErrorsSPKIList ignore_ecdsap256(
+ kPEMECDSAP256SPKIHash);
+ SignedExchangeSignatureVerifier::IgnoreErrorsSPKIList ignore_ecdsap384(
+ kPEMECDSAP384SPKIHash);
+ SignedExchangeSignatureVerifier::IgnoreErrorsSPKIList ignore_both(
+ std::string(kPEMECDSAP256SPKIHash) + "," + kPEMECDSAP384SPKIHash);
+
+ scoped_refptr<net::X509Certificate> cert_ecdsap256 =
+ net::X509Certificate::CreateCertificateListFromBytes(
+ kCertPEMECDSAP256, base::size(kCertPEMECDSAP256),
+ net::X509Certificate::FORMAT_AUTO)[0];
+ scoped_refptr<net::X509Certificate> cert_ecdsap384 =
+ net::X509Certificate::CreateCertificateListFromBytes(
+ kCertPEMECDSAP384, base::size(kCertPEMECDSAP384),
+ net::X509Certificate::FORMAT_AUTO)[0];
+
+ EXPECT_FALSE(ignore_nothing.ShouldIgnoreError(cert_ecdsap256));
+ EXPECT_FALSE(ignore_nothing.ShouldIgnoreError(cert_ecdsap384));
+ EXPECT_TRUE(ignore_ecdsap256.ShouldIgnoreError(cert_ecdsap256));
+ EXPECT_FALSE(ignore_ecdsap256.ShouldIgnoreError(cert_ecdsap384));
+ EXPECT_FALSE(ignore_ecdsap384.ShouldIgnoreError(cert_ecdsap256));
+ EXPECT_TRUE(ignore_ecdsap384.ShouldIgnoreError(cert_ecdsap384));
+ EXPECT_TRUE(ignore_both.ShouldIgnoreError(cert_ecdsap256));
+ EXPECT_TRUE(ignore_both.ShouldIgnoreError(cert_ecdsap384));
+}
+
} // namespace content
diff --git a/chromium/content/browser/web_package/signed_exchange_utils.cc b/chromium/content/browser/web_package/signed_exchange_utils.cc
index bc1a1af246a..d6f8c7232e5 100644
--- a/chromium/content/browser/web_package/signed_exchange_utils.cc
+++ b/chromium/content/browser/web_package/signed_exchange_utils.cc
@@ -5,12 +5,18 @@
#include "content/browser/web_package/signed_exchange_utils.h"
#include "base/feature_list.h"
+#include "base/metrics/field_trial_params.h"
+#include "base/no_destructor.h"
+#include "base/strings/string_piece.h"
+#include "base/strings/string_util.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
+#include "content/browser/web_package/origins_list.h"
#include "content/browser/web_package/signed_exchange_devtools_proxy.h"
#include "content/browser/web_package/signed_exchange_error.h"
#include "content/browser/web_package/signed_exchange_request_handler.h"
#include "content/public/common/content_features.h"
+#include "net/http/http_util.h"
#include "services/network/public/cpp/resource_response.h"
#include "third_party/blink/public/common/origin_trials/trial_token_validator.h"
@@ -28,6 +34,51 @@ void ReportErrorAndTraceEvent(
devtools_proxy->ReportError(error_message, std::move(error_field));
}
+namespace {
+
+OriginsList CreateAdvertiseAcceptHeaderOriginsList() {
+ std::string param = base::GetFieldTrialParamValueByFeature(
+ features::kSignedHTTPExchangeAcceptHeader,
+ features::kSignedHTTPExchangeAcceptHeaderFieldTrialParamName);
+ if (param.empty())
+ DLOG(ERROR) << "The Accept-SXG origins list param is empty.";
+
+ return OriginsList(param);
+}
+
+} // namespace
+
+bool NeedToCheckRedirectedURLForAcceptHeader() {
+ // When SignedHTTPExchange is enabled, the SignedExchange accept header must
+ // be sent to all origins. So we don't need to check the redirected URL.
+ return !base::FeatureList::IsEnabled(features::kSignedHTTPExchange) &&
+ base::FeatureList::IsEnabled(
+ features::kSignedHTTPExchangeOriginTrial) &&
+ base::FeatureList::IsEnabled(
+ features::kSignedHTTPExchangeAcceptHeader);
+}
+
+bool ShouldAdvertiseAcceptHeader(const url::Origin& origin) {
+ // When SignedHTTPExchange is enabled, we must send the SignedExchange accept
+ // header to all origins.
+ if (base::FeatureList::IsEnabled(features::kSignedHTTPExchange))
+ return true;
+ // When SignedHTTPExchangeOriginTrial is not enabled or
+ // SignedHTTPExchangeAcceptHeader is not enabled, we must not send the
+ // SignedExchange accept header.
+ if (!base::FeatureList::IsEnabled(features::kSignedHTTPExchangeOriginTrial) ||
+ !base::FeatureList::IsEnabled(
+ features::kSignedHTTPExchangeAcceptHeader)) {
+ return false;
+ }
+
+ // |origins_list| is initialized in a thread-safe manner.
+ // Querying OriginsList::Match() should be safe since it's read-only access.
+ static base::NoDestructor<OriginsList> origins_list(
+ CreateAdvertiseAcceptHeaderOriginsList());
+ return origins_list->Match(origin);
+}
+
bool IsSignedExchangeHandlingEnabled() {
return base::FeatureList::IsEnabled(features::kSignedHTTPExchange) ||
base::FeatureList::IsEnabled(features::kSignedHTTPExchangeOriginTrial);
@@ -49,9 +100,46 @@ bool ShouldHandleAsSignedHTTPExchange(
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());
+ return validator->RequestEnablesFeature(
+ request_url, head.headers.get(),
+ features::kSignedHTTPExchangeOriginTrial.name, base::Time::Now());
+}
+
+base::Optional<SignedExchangeVersion> GetSignedExchangeVersion(
+ const std::string& content_type) {
+ // https://wicg.github.io/webpackage/loading.html#signed-exchange-version
+ // Step 1. Let mimeType be the supplied MIME type of response. [spec text]
+ // |content_type| is the supplied MIME type.
+ // Step 2. If mimeType is undefined, return undefined. [spec text]
+ // Step 3. If mimeType's essence is not "application/signed-exchange", return
+ // undefined. [spec text]
+ const std::string::size_type semicolon = content_type.find(';');
+ const std::string essence = base::ToLowerASCII(base::TrimWhitespaceASCII(
+ content_type.substr(0, semicolon), base::TRIM_ALL));
+ if (essence != "application/signed-exchange")
+ return base::nullopt;
+
+ // Step 4.Let params be mimeType's parameters. [spec text]
+ std::map<std::string, std::string> params;
+ if (semicolon != base::StringPiece::npos) {
+ net::HttpUtil::NameValuePairsIterator parser(
+ content_type.begin() + semicolon + 1, content_type.end(), ';');
+ while (parser.GetNext()) {
+ const base::StringPiece name(parser.name_begin(), parser.name_end());
+ params[base::ToLowerASCII(name)] = parser.value();
+ }
+ if (!parser.valid())
+ return base::nullopt;
+ }
+ // Step 5. If params["v"] exists, return it. Otherwise, return undefined.
+ // [spec text]
+ auto iter = params.find("v");
+ if (iter != params.end()) {
+ if (iter->second == "b2")
+ return base::make_optional(SignedExchangeVersion::kB2);
+ return base::make_optional(SignedExchangeVersion::kUnknown);
+ }
+ return base::nullopt;
}
} // 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 105cd892da7..bbcad0a2d08 100644
--- a/chromium/content/browser/web_package/signed_exchange_utils.h
+++ b/chromium/content/browser/web_package/signed_exchange_utils.h
@@ -8,10 +8,17 @@
#include <string>
#include "base/optional.h"
+#include "content/browser/web_package/origins_list.h"
+#include "content/browser/web_package/signed_exchange_consts.h"
#include "content/browser/web_package/signed_exchange_error.h"
+#include "content/common/content_export.h"
class GURL;
+namespace url {
+class Origin;
+} // namespace url
+
namespace network {
struct ResourceResponseHead;
} // namespace network
@@ -31,6 +38,15 @@ void ReportErrorAndTraceEvent(
base::Optional<SignedExchangeError::FieldIndexPair> error_field =
base::nullopt);
+// Returns true when SignedHTTPExchange feature is NOT enabled and
+// SignedHTTPExchangeOriginTrial and SignedHTTPExchangeAcceptHeader features are
+// enabled.
+bool NeedToCheckRedirectedURLForAcceptHeader();
+
+// Returns true if Accept headers should be sent with
+// "application/signed-exchange".
+CONTENT_EXPORT bool ShouldAdvertiseAcceptHeader(const url::Origin& origin);
+
// Returns true when SignedHTTPExchange feature or SignedHTTPExchangeOriginTrial
// feature is enabled.
bool IsSignedExchangeHandlingEnabled();
@@ -43,7 +59,15 @@ bool ShouldHandleAsSignedHTTPExchange(
const GURL& request_url,
const network::ResourceResponseHead& head);
-} // namespace signed_exchange_utils
+// Extracts the signed exchange version [1] from |content_type|, and converts it
+// to SignedExchanveVersion. Returns nullopt if the mime type is not a variant
+// of application/signed-exchange. Returns SignedExchangeVersion::kUnknown if an
+// unsupported signed exchange version is found.
+// [1] https://wicg.github.io/webpackage/loading.html#signed-exchange-version
+CONTENT_EXPORT base::Optional<SignedExchangeVersion> GetSignedExchangeVersion(
+ const std::string& content_type);
+
+} // namespace signed_exchange_utils
} // namespace content
#endif // CONTENT_BROWSER_WEB_PACKAGE_SIGNED_EXCHANGE_UTILS_H_
diff --git a/chromium/content/browser/web_package/signed_exchange_utils_unittest.cc b/chromium/content/browser/web_package/signed_exchange_utils_unittest.cc
new file mode 100644
index 00000000000..95822755e9d
--- /dev/null
+++ b/chromium/content/browser/web_package/signed_exchange_utils_unittest.cc
@@ -0,0 +1,97 @@
+// 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_utils.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+namespace signed_exchange_utils {
+
+TEST(SignedExchangeUtilsTest, VersionParam_WrongEssence) {
+ base::Optional<SignedExchangeVersion> version =
+ GetSignedExchangeVersion("application/signed-foo");
+ EXPECT_FALSE(version.has_value());
+}
+
+TEST(SignedExchangeUtilsTest, VersionParam_None) {
+ base::Optional<SignedExchangeVersion> version =
+ GetSignedExchangeVersion("application/signed-exchange");
+ EXPECT_FALSE(version.has_value());
+}
+
+TEST(SignedExchangeUtilsTest, VersionParam_NoneWithSemicolon) {
+ base::Optional<SignedExchangeVersion> version =
+ GetSignedExchangeVersion("application/signed-exchange;");
+ EXPECT_FALSE(version.has_value());
+}
+
+TEST(SignedExchangeUtilsTest, VersionParam_Empty) {
+ base::Optional<SignedExchangeVersion> version =
+ GetSignedExchangeVersion("application/signed-exchange;v=");
+ EXPECT_FALSE(version.has_value());
+}
+
+TEST(SignedExchangeUtilsTest, VersionParam_EmptyString) {
+ base::Optional<SignedExchangeVersion> version =
+ GetSignedExchangeVersion("application/signed-exchange;v=\"\"");
+ EXPECT_EQ(version, SignedExchangeVersion::kUnknown);
+}
+
+TEST(SignedExchangeUtilsTest, VersionParam_UnknownVersion) {
+ base::Optional<SignedExchangeVersion> version =
+ GetSignedExchangeVersion("application/signed-exchange;v=foobar");
+ EXPECT_EQ(version, SignedExchangeVersion::kUnknown);
+}
+
+TEST(SignedExchangeUtilsTest, VersionParam_Simple) {
+ base::Optional<SignedExchangeVersion> version =
+ GetSignedExchangeVersion("application/signed-exchange;v=b2");
+ EXPECT_EQ(version, SignedExchangeVersion::kB2);
+}
+
+TEST(SignedExchangeUtilsTest, VersionParam_WithSpace) {
+ base::Optional<SignedExchangeVersion> version =
+ GetSignedExchangeVersion("application/signed-exchange ; v=b2");
+ EXPECT_EQ(version, SignedExchangeVersion::kB2);
+}
+
+TEST(SignedExchangeUtilsTest, VersionParam_ExtraParam) {
+ base::Optional<SignedExchangeVersion> version =
+ GetSignedExchangeVersion("application/signed-exchange;v=b2;foo=bar");
+ EXPECT_EQ(version, SignedExchangeVersion::kB2);
+}
+
+TEST(SignedExchangeUtilsTest, VersionParam_Quoted) {
+ base::Optional<SignedExchangeVersion> version =
+ GetSignedExchangeVersion("application/signed-exchange;v=\"b2\"");
+ EXPECT_EQ(version, SignedExchangeVersion::kB2);
+}
+
+TEST(SignedExchangeUtilsTest, VersionParam_QuotesOpen) {
+ base::Optional<SignedExchangeVersion> version =
+ GetSignedExchangeVersion("application/signed-exchange;v=\"b2");
+ EXPECT_EQ(version, SignedExchangeVersion::kB2);
+}
+
+TEST(SignedExchangeUtilsTest, VersionParam_QuotesOpenNonV) {
+ base::Optional<SignedExchangeVersion> version =
+ GetSignedExchangeVersion("application/signed-exchange;v=\"b2;r=\"b2");
+ EXPECT_EQ(version, SignedExchangeVersion::kUnknown);
+}
+
+TEST(SignedExchangeUtilsTest, VersionParam_QuotesOpenNonV2) {
+ base::Optional<SignedExchangeVersion> version =
+ GetSignedExchangeVersion("application/signed-exchange;v=\"b2\";r=\"b2");
+ EXPECT_EQ(version, SignedExchangeVersion::kB2);
+}
+
+TEST(SignedExchangeUtilsTest, VersionParam_UseCaseInsensitiveMatch) {
+ base::Optional<SignedExchangeVersion> version =
+ GetSignedExchangeVersion("Application/Signed-Exchange;V=b2");
+ EXPECT_EQ(version, SignedExchangeVersion::kB2);
+}
+
+} // namespace signed_exchange_utils
+} // namespace content
diff --git a/chromium/content/browser/webauth/authenticator_impl.cc b/chromium/content/browser/webauth/authenticator_impl.cc
index b2ffb181123..0bbb8c099e2 100644
--- a/chromium/content/browser/webauth/authenticator_impl.cc
+++ b/chromium/content/browser/webauth/authenticator_impl.cc
@@ -12,7 +12,9 @@
#include "base/base64url.h"
#include "base/json/json_writer.h"
#include "base/logging.h"
+#include "base/metrics/histogram_macros.h"
#include "base/rand_util.h"
+#include "base/strings/string_piece.h"
#include "base/timer/timer.h"
#include "build/build_config.h"
#include "content/browser/bad_message.h"
@@ -32,6 +34,7 @@
#include "crypto/sha2.h"
#include "device/base/features.h"
#include "device/bluetooth/bluetooth_adapter_factory.h"
+#include "device/fido/attestation_statement.h"
#include "device/fido/authenticator_selection_criteria.h"
#include "device/fido/ctap_get_assertion_request.h"
#include "device/fido/ctap_make_credential_request.h"
@@ -43,6 +46,10 @@
#include "device/fido/public_key_credential_descriptor.h"
#include "device/fido/public_key_credential_params.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
+#include "net/cert/asn1_util.h"
+#include "net/der/input.h"
+#include "net/der/parse_values.h"
+#include "net/der/parser.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
#include "services/service_manager/public/cpp/connector.h"
@@ -62,12 +69,35 @@ const char kGetType[] = "webauthn.get";
namespace {
+// AttestationPromptResult enumerates events related to attestation prompts.
+// These values are recorded in an UMA histogram and so should not be
+// reassigned.
+enum class AttestationPromptResult {
+ // kQueried indicates that the embedder was queried in order to determine
+ // whether attestation information should be returned to the origin.
+ kQueried = 0,
+ // kTimeout indicates that a timeout occured while awaiting the result of an
+ // attestation query.
+ kTimeout = 1,
+ // kAllowed indicates that the query to the embedder was resolved positively.
+ // (E.g. the user clicked to allow, or the embedded allowed immediately by
+ // policy.)
+ kAllowed = 2,
+ // kBlocked indicates that the query to the embedder was resolved negatively.
+ // (E.g. the user clicked to block, or closed the dialog.)
+ kBlocked = 3,
+ // kAbandoned indications that the user closed the tab or navigated away while
+ // the attestation prompt was showing.
+ kAbandoned = 4,
+ kMaxValue = kAbandoned,
+};
+
// Ensure that the origin's effective domain is a valid domain.
// Only the domain format of host is valid.
// Reference https://url.spec.whatwg.org/#valid-domain-string and
// https://html.spec.whatwg.org/multipage/origin.html#concept-origin-effective-domain.
bool HasValidEffectiveDomain(url::Origin caller_origin) {
- return !caller_origin.unique() &&
+ return !caller_origin.opaque() &&
!url::HostIsIPAddress(caller_origin.host()) &&
content::IsOriginSecure(caller_origin.GetURL()) &&
// Additionally, the scheme is required to be HTTP(S). Other schemes
@@ -262,10 +292,63 @@ ProcessAppIdExtension(std::string appid, const url::Origin& caller_origin) {
return CreateApplicationParameter(appid);
}
+// Parses the FIDO transport types extension from the DER-encoded, X.509
+// certificate in |der_cert| and appends any unique transport types found to
+// |out_transports|.
+void AppendUniqueTransportsFromCertificate(
+ base::span<const uint8_t> der_cert,
+ std::vector<device::FidoTransportProtocol>* out_transports) {
+ // See
+ // https://fidoalliance.org/specs/fido-u2f-v1.2-ps-20170411/fido-u2f-authenticator-transports-extension-v1.2-ps-20170411.html#fido-u2f-certificate-transports-extension
+ static constexpr uint8_t kTransportTypesOID[] = {
+ 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0xe5, 0x1c, 0x02, 0x01, 0x01};
+ bool present, critical;
+ base::StringPiece contents;
+ if (!net::asn1::ExtractExtensionFromDERCert(
+ base::StringPiece(reinterpret_cast<const char*>(der_cert.data()),
+ der_cert.size()),
+ base::StringPiece(reinterpret_cast<const char*>(kTransportTypesOID),
+ sizeof(kTransportTypesOID)),
+ &present, &critical, &contents) ||
+ !present) {
+ return;
+ }
+
+ const net::der::Input contents_der(contents);
+ net::der::Parser contents_parser(contents_der);
+ net::der::BitString transport_bits;
+ if (!contents_parser.ReadBitString(&transport_bits)) {
+ return;
+ }
+
+ // The certificate extension contains a BIT STRING where different bits
+ // indicate support for different transports. The following array maps
+ // between these bit indexes and the FidoTransportProtocol enum.
+ static constexpr struct {
+ uint8_t bit_index;
+ device::FidoTransportProtocol transport;
+ } kTransportMapping[] = {
+ // Bit 0 is "Bluetooth Classic", not BLE. Since webauthn doesn't define a
+ // transport type for this we ignore it.
+ {1, device::FidoTransportProtocol::kBluetoothLowEnergy},
+ {2, device::FidoTransportProtocol::kUsbHumanInterfaceDevice},
+ {3, device::FidoTransportProtocol::kNearFieldCommunication},
+ {4, device::FidoTransportProtocol::kInternal},
+ };
+
+ for (const auto& mapping : kTransportMapping) {
+ if (transport_bits.AssertsBit(mapping.bit_index) &&
+ !base::ContainsValue(*out_transports, mapping.transport)) {
+ out_transports->push_back(mapping.transport);
+ }
+ }
+}
+
blink::mojom::MakeCredentialAuthenticatorResponsePtr
CreateMakeCredentialResponse(
const std::string& client_data_json,
- device::AuthenticatorMakeCredentialResponse response_data) {
+ device::AuthenticatorMakeCredentialResponse response_data,
+ bool preserve_attestation) {
auto response = blink::mojom::MakeCredentialAuthenticatorResponse::New();
auto common_info = blink::mojom::CommonCredentialInfo::New();
common_info->client_data_json.assign(client_data_json.begin(),
@@ -273,8 +356,32 @@ CreateMakeCredentialResponse(
common_info->raw_id = response_data.raw_credential_id();
common_info->id = response_data.GetId();
response->info = std::move(common_info);
+
+ // The transport list must not contain duplicates but the order doesn't matter
+ // because Blink will sort the resulting strings before returning them.
+ std::vector<device::FidoTransportProtocol> transports = {
+ response_data.transport_used()};
+ // If the attestation certificate specifies that the token supports any other
+ // transports, include them in the list.
+ base::Optional<base::span<const uint8_t>> leaf_cert =
+ response_data.attestation_object()
+ .attestation_statement()
+ .GetLeafCertificate();
+ if (leaf_cert) {
+ AppendUniqueTransportsFromCertificate(*leaf_cert, &transports);
+ }
+
+ for (auto transport : transports) {
+ response->transports.push_back(
+ mojo::ConvertTo<blink::mojom::AuthenticatorTransport>(transport));
+ }
+
+ if (!preserve_attestation) {
+ response_data.EraseAttestationStatement();
+ }
response->attestation_object =
response_data.GetCBOREncodedAttestationObject();
+
return response;
}
@@ -461,6 +568,16 @@ void AuthenticatorImpl::MakeCredential(
return;
}
+ if (options->authenticator_selection &&
+ options->authenticator_selection->require_resident_key) {
+ // Disallow the creation of resident credentials.
+ InvokeCallbackAndCleanup(
+ std::move(callback),
+ blink::mojom::AuthenticatorStatus::RESIDENT_CREDENTIALS_UNSUPPORTED,
+ nullptr, Focus::kDontCheck);
+ return;
+ }
+
DCHECK(make_credential_response_callback_.is_null());
make_credential_response_callback_ = std::move(callback);
@@ -506,7 +623,10 @@ void AuthenticatorImpl::MakeCredential(
request_->GetWeakPtr()) /* request_callback */,
base::BindRepeating(
&device::FidoRequestHandlerBase::PowerOnBluetoothAdapter,
- request_->GetWeakPtr()) /* bluetooth_adapter_power_on_callback */);
+ request_->GetWeakPtr()) /* bluetooth_adapter_power_on_callback */,
+ base::BindRepeating(
+ &device::FidoRequestHandlerBase::InitiatePairingWithDevice,
+ request_->GetWeakPtr()) /* ble_pairing_callback*/);
request_->set_observer(request_delegate_.get());
request_->SetPlatformAuthenticatorOrMarkUnavailable(
@@ -551,6 +671,15 @@ void AuthenticatorImpl::GetAssertion(
return;
}
+ if (options->allow_credentials.empty()) {
+ // Chrome currently does not support any resident keys.
+ InvokeCallbackAndCleanup(
+ std::move(callback),
+ blink::mojom::AuthenticatorStatus::RESIDENT_CREDENTIALS_UNSUPPORTED,
+ nullptr);
+ return;
+ }
+
if (options->appid) {
alternative_application_parameter_ =
ProcessAppIdExtension(*options->appid, caller_origin);
@@ -597,7 +726,10 @@ void AuthenticatorImpl::GetAssertion(
request_->GetWeakPtr()) /* request_callback */,
base::BindRepeating(
&device::FidoRequestHandlerBase::PowerOnBluetoothAdapter,
- request_->GetWeakPtr()) /* bluetooth_adapter_power_on_callback */);
+ request_->GetWeakPtr()) /* bluetooth_adapter_power_on_callback */,
+ base::BindRepeating(
+ &device::FidoRequestHandlerBase::InitiatePairingWithDevice,
+ request_->GetWeakPtr()) /* ble_pairing_callback*/);
request_->set_observer(request_delegate_.get());
request_->SetPlatformAuthenticatorOrMarkUnavailable(
@@ -695,6 +827,9 @@ void AuthenticatorImpl::OnRegisterResponse(
if (attestation_preference_ !=
blink::mojom::AttestationConveyancePreference::NONE) {
+ UMA_HISTOGRAM_ENUMERATION("WebAuthentication.AttestationPromptResult",
+ AttestationPromptResult::kQueried);
+ awaiting_attestation_response_ = true;
request_delegate_->ShouldReturnAttestation(
relying_party_id_,
base::BindOnce(
@@ -703,15 +838,13 @@ void AuthenticatorImpl::OnRegisterResponse(
return;
}
- if (!response_data->IsSelfAttestation()) {
- response_data->EraseAttestationStatement();
- }
-
+ const bool include_attestation = response_data->IsSelfAttestation();
InvokeCallbackAndCleanup(
std::move(make_credential_response_callback_),
blink::mojom::AuthenticatorStatus::SUCCESS,
CreateMakeCredentialResponse(std::move(client_data_json_),
- std::move(*response_data)),
+ std::move(*response_data),
+ include_attestation),
Focus::kDoCheck);
return;
}
@@ -721,6 +854,7 @@ void AuthenticatorImpl::OnRegisterResponse(
void AuthenticatorImpl::OnRegisterResponseAttestationDecided(
device::AuthenticatorMakeCredentialResponse response_data,
bool attestation_permitted) {
+ awaiting_attestation_response_ = false;
if (!request_) {
// The request has already been cleaned up, probably because a navigation
// occured while the permissions prompt was pending.
@@ -731,6 +865,8 @@ void AuthenticatorImpl::OnRegisterResponseAttestationDecided(
blink::mojom::AttestationConveyancePreference::NONE);
if (!attestation_permitted) {
+ UMA_HISTOGRAM_ENUMERATION("WebAuthentication.AttestationPromptResult",
+ AttestationPromptResult::kBlocked);
InvokeCallbackAndCleanup(
std::move(make_credential_response_callback_),
blink::mojom::AuthenticatorStatus::NOT_ALLOWED_ERROR, nullptr,
@@ -738,6 +874,10 @@ void AuthenticatorImpl::OnRegisterResponseAttestationDecided(
return;
}
+ UMA_HISTOGRAM_ENUMERATION("WebAuthentication.AttestationPromptResult",
+ AttestationPromptResult::kAllowed);
+ bool include_attestation = true;
+
// The check for IsAttestationCertificateInappropriatelyIdentifying is
// performed after the permissions prompt, even though we know the answer
// before, because this still effectively discloses the make & model of the
@@ -755,15 +895,15 @@ void AuthenticatorImpl::OnRegisterResponseAttestationDecided(
// The only way to get the underlying attestation will be to list the RP ID
// in the enterprise policy, because that enables the individual attestation
// bit in the register request and permits individual attestation generally.
- response_data.EraseAttestationStatement();
+ include_attestation = false;
}
- InvokeCallbackAndCleanup(
- std::move(make_credential_response_callback_),
- blink::mojom::AuthenticatorStatus::SUCCESS,
- CreateMakeCredentialResponse(std::move(client_data_json_),
- std::move(response_data)),
- Focus::kDoCheck);
+ InvokeCallbackAndCleanup(std::move(make_credential_response_callback_),
+ blink::mojom::AuthenticatorStatus::SUCCESS,
+ CreateMakeCredentialResponse(
+ std::move(client_data_json_),
+ std::move(response_data), include_attestation),
+ Focus::kDoCheck);
}
void AuthenticatorImpl::OnSignResponse(
@@ -841,6 +981,12 @@ void AuthenticatorImpl::FailWithNotAllowedErrorAndCleanup() {
void AuthenticatorImpl::OnTimeout() {
DCHECK(request_delegate_);
+ if (awaiting_attestation_response_) {
+ UMA_HISTOGRAM_ENUMERATION("WebAuthentication.AttestationPromptResult",
+ AttestationPromptResult::kTimeout);
+ awaiting_attestation_response_ = false;
+ }
+
request_delegate_->DidFailWithInterestingReason(
AuthenticatorRequestClientDelegate::InterestingFailureReason::kTimeout);
@@ -881,6 +1027,12 @@ void AuthenticatorImpl::InvokeCallbackAndCleanup(
}
void AuthenticatorImpl::Cleanup() {
+ if (awaiting_attestation_response_) {
+ UMA_HISTOGRAM_ENUMERATION("WebAuthentication.AttestationPromptResult",
+ AttestationPromptResult::kAbandoned);
+ awaiting_attestation_response_ = false;
+ }
+
timer_->Stop();
request_.reset();
request_delegate_.reset();
@@ -948,4 +1100,4 @@ base::Optional<device::PlatformAuthenticatorInfo> AuthenticatorImpl::
#endif
}
-} // namespace content
+} // namespace content \ No newline at end of file
diff --git a/chromium/content/browser/webauth/authenticator_impl.h b/chromium/content/browser/webauth/authenticator_impl.h
index df8cdf26eb4..effdf9ccb26 100644
--- a/chromium/content/browser/webauth/authenticator_impl.h
+++ b/chromium/content/browser/webauth/authenticator_impl.h
@@ -186,6 +186,9 @@ class CONTENT_EXPORT AuthenticatorImpl : public blink::mojom::Authenticator,
// retried with this value.
base::Optional<std::array<uint8_t, crypto::kSHA256Length>>
alternative_application_parameter_;
+ // awaiting_attestation_response_ is true if the embedder has been queried
+ // about an attestsation decision and the response is still pending.
+ bool awaiting_attestation_response_ = false;
// Owns pipes to this Authenticator from |render_frame_host_|.
mojo::Binding<blink::mojom::Authenticator> binding_;
diff --git a/chromium/content/browser/webauth/authenticator_impl_unittest.cc b/chromium/content/browser/webauth/authenticator_impl_unittest.cc
index fdb9b181f0e..12568cb60d2 100644
--- a/chromium/content/browser/webauth/authenticator_impl_unittest.cc
+++ b/chromium/content/browser/webauth/authenticator_impl_unittest.cc
@@ -399,6 +399,11 @@ class AuthenticatorImplTest : public content::RenderViewHostTestHarness {
scoped_feature_list_->InitAndEnableFeature(feature);
}
+ void DisableFeature(const base::Feature& feature) {
+ scoped_feature_list_.emplace();
+ scoped_feature_list_->InitAndDisableFeature(feature);
+ }
+
protected:
std::unique_ptr<AuthenticatorImpl> authenticator_impl_;
service_manager::mojom::ConnectorRequest request_;
@@ -526,8 +531,8 @@ TEST_F(AuthenticatorImplTest, MakeCredentialUserVerification) {
EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, callback_receiver.status());
}
-// Test that MakeCredential request times out with NOT_ALLOWED_ERROR if resident
-// key is requested for U2F devices on create().
+// Test that MakeCredential request returns if resident
+// key is requested on create().
TEST_F(AuthenticatorImplTest, MakeCredentialResidentKey) {
SimulateNavigation(GURL(kTestOrigin1));
device::test::ScopedVirtualFidoDevice scoped_virtual_device;
@@ -546,7 +551,10 @@ TEST_F(AuthenticatorImplTest, MakeCredentialResidentKey) {
base::RunLoop().RunUntilIdle();
task_runner->FastForwardBy(base::TimeDelta::FromMinutes(1));
callback_receiver.WaitForCallback();
- EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, callback_receiver.status());
+ EXPECT_EQ(AuthenticatorStatus::RESIDENT_CREDENTIALS_UNSUPPORTED,
+ callback_receiver.status());
+
+ // TODO add CTAP device
}
// Test that MakeCredential request times out with NOT_ALLOWED_ERROR if a
@@ -830,22 +838,16 @@ TEST_F(AuthenticatorImplTest, OversizedCredentialId) {
TEST_F(AuthenticatorImplTest, TestCableDiscoveryByDefault) {
auto authenticator = ConnectToAuthenticator();
-// On Windows caBLE should be disabled by default regardless of version.
-#if defined(OS_WIN)
- EXPECT_FALSE(SupportsTransportProtocol(
- device::FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy));
-// Otherwise, it should be enabled by default if BLE is supported.
-#else
+
+ // caBLE should be enabled by default if BLE is supported.
EXPECT_EQ(
device::BluetoothAdapterFactory::Get().IsLowEnergySupported(),
SupportsTransportProtocol(
device::FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy));
-#endif
}
TEST_F(AuthenticatorImplTest, TestCableDiscoveryDisabledWithFlag) {
- scoped_feature_list_.emplace();
- scoped_feature_list_->InitAndDisableFeature(features::kWebAuthCable);
+ DisableFeature(features::kWebAuthCable);
auto authenticator = ConnectToAuthenticator();
EXPECT_FALSE(SupportsTransportProtocol(
@@ -931,7 +933,7 @@ TEST_F(AuthenticatorImplTest, GetAssertionWithEmptyAllowCredentials) {
base::RunLoop().RunUntilIdle();
task_runner->FastForwardBy(base::TimeDelta::FromMinutes(1));
callback_receiver.WaitForCallback();
- EXPECT_EQ(AuthenticatorStatus::CREDENTIAL_NOT_RECOGNIZED,
+ EXPECT_EQ(AuthenticatorStatus::RESIDENT_CREDENTIALS_UNSUPPORTED,
callback_receiver.status());
}
@@ -1124,7 +1126,9 @@ class TestAuthenticatorRequestDelegate
void RegisterActionCallbacks(
base::OnceClosure cancel_callback,
device::FidoRequestHandlerBase::RequestCallback request_callback,
- base::RepeatingClosure bluetooth_adapter_power_on_callback) override {
+ base::RepeatingClosure bluetooth_adapter_power_on_callback,
+ device::FidoRequestHandlerBase::BlePairingCallback ble_pairing_callback)
+ override {
ASSERT_TRUE(action_callbacks_registered_callback_)
<< "RegisterActionCallbacks called twice.";
std::move(action_callbacks_registered_callback_).Run();
@@ -1704,6 +1708,7 @@ TEST_F(AuthenticatorContentBrowserClientTest,
TEST_F(AuthenticatorContentBrowserClientTest, IsUVPAAFalseIfFeatureFlagOff) {
if (__builtin_available(macOS 10.12.2, *)) {
// Touch ID is hardware-supported and embedder-enabled, but the flag is off.
+ DisableFeature(device::kWebAuthTouchId);
device::fido::mac::ScopedTouchIdTestEnvironment touch_id_test_environment;
touch_id_test_environment.SetTouchIdAvailable(true);
test_client_.supports_touch_id = true;
@@ -2009,4 +2014,34 @@ TEST_F(AuthenticatorImplRequestDelegateTest,
std::get<0>(*failure_reason_receiver.result()));
}
+TEST_F(AuthenticatorImplTest, Transports) {
+ TestServiceManagerContext smc;
+ NavigateAndCommit(GURL(kTestOrigin1));
+
+ for (auto protocol :
+ {device::ProtocolVersion::kU2f, device::ProtocolVersion::kCtap}) {
+ SCOPED_TRACE(static_cast<int>(protocol));
+
+ device::test::ScopedVirtualFidoDevice scoped_virtual_device;
+ scoped_virtual_device.SetSupportedProtocol(protocol);
+
+ AuthenticatorPtr authenticator = ConnectToAuthenticator();
+ PublicKeyCredentialCreationOptionsPtr options =
+ GetTestPublicKeyCredentialCreationOptions();
+ TestMakeCredentialCallback callback_receiver;
+ authenticator->MakeCredential(std::move(options),
+ callback_receiver.callback());
+ callback_receiver.WaitForCallback();
+ EXPECT_EQ(AuthenticatorStatus::SUCCESS, callback_receiver.status());
+
+ const std::vector<blink::mojom::AuthenticatorTransport>& transports(
+ callback_receiver.value()->transports);
+ ASSERT_EQ(2u, transports.size());
+ EXPECT_EQ(blink::mojom::AuthenticatorTransport::USB, transports[0]);
+ // VirtualFidoDevice generates an attestation certificate that asserts NFC
+ // support via an extension.
+ EXPECT_EQ(blink::mojom::AuthenticatorTransport::NFC, transports[1]);
+ }
+}
+
} // namespace content
diff --git a/chromium/content/browser/webauth/authenticator_type_converters.cc b/chromium/content/browser/webauth/authenticator_type_converters.cc
index b916b86a15c..68b7878a755 100644
--- a/chromium/content/browser/webauth/authenticator_type_converters.cc
+++ b/chromium/content/browser/webauth/authenticator_type_converters.cc
@@ -44,6 +44,25 @@ TypeConverter<::device::FidoTransportProtocol, AuthenticatorTransport>::Convert(
return ::device::FidoTransportProtocol::kUsbHumanInterfaceDevice;
}
+AuthenticatorTransport
+TypeConverter<AuthenticatorTransport, ::device::FidoTransportProtocol>::Convert(
+ const ::device::FidoTransportProtocol& input) {
+ switch (input) {
+ case ::device::FidoTransportProtocol::kUsbHumanInterfaceDevice:
+ return AuthenticatorTransport::USB;
+ case ::device::FidoTransportProtocol::kNearFieldCommunication:
+ return AuthenticatorTransport::NFC;
+ case ::device::FidoTransportProtocol::kBluetoothLowEnergy:
+ return AuthenticatorTransport::BLE;
+ case ::device::FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy:
+ return AuthenticatorTransport::CABLE;
+ case ::device::FidoTransportProtocol::kInternal:
+ return AuthenticatorTransport::INTERNAL;
+ }
+ NOTREACHED();
+ return AuthenticatorTransport::USB;
+}
+
// static
::device::CredentialType
TypeConverter<::device::CredentialType, PublicKeyCredentialType>::Convert(
diff --git a/chromium/content/browser/webauth/authenticator_type_converters.h b/chromium/content/browser/webauth/authenticator_type_converters.h
index 90fd80fb7c6..5c5e7136a4a 100644
--- a/chromium/content/browser/webauth/authenticator_type_converters.h
+++ b/chromium/content/browser/webauth/authenticator_type_converters.h
@@ -30,6 +30,13 @@ struct TypeConverter<::device::FidoTransportProtocol,
};
template <>
+struct TypeConverter<::blink::mojom::AuthenticatorTransport,
+ ::device::FidoTransportProtocol> {
+ static ::blink::mojom::AuthenticatorTransport Convert(
+ const ::device::FidoTransportProtocol& input);
+};
+
+template <>
struct TypeConverter<::device::CredentialType,
::blink::mojom::PublicKeyCredentialType> {
static ::device::CredentialType Convert(
diff --git a/chromium/content/browser/webauth/scoped_virtual_authenticator_environment.cc b/chromium/content/browser/webauth/scoped_virtual_authenticator_environment.cc
index 3f3d4a2df33..482b3f01ba2 100644
--- a/chromium/content/browser/webauth/scoped_virtual_authenticator_environment.cc
+++ b/chromium/content/browser/webauth/scoped_virtual_authenticator_environment.cc
@@ -96,7 +96,7 @@ void ScopedVirtualAuthenticatorEnvironment::ClearAuthenticators(
std::move(callback).Run();
}
-std::unique_ptr<::device::FidoDiscovery>
+std::unique_ptr<::device::FidoDeviceDiscovery>
ScopedVirtualAuthenticatorEnvironment::CreateFidoDiscovery(
device::FidoTransportProtocol transport,
::service_manager::Connector* connector) {
diff --git a/chromium/content/browser/webauth/scoped_virtual_authenticator_environment.h b/chromium/content/browser/webauth/scoped_virtual_authenticator_environment.h
index 0c0bf6f47b9..663738c7cc9 100644
--- a/chromium/content/browser/webauth/scoped_virtual_authenticator_environment.h
+++ b/chromium/content/browser/webauth/scoped_virtual_authenticator_environment.h
@@ -13,7 +13,7 @@
#include "base/macros.h"
#include "base/no_destructor.h"
#include "content/common/content_export.h"
-#include "device/fido/fido_discovery.h"
+#include "device/fido/fido_device_discovery.h"
#include "mojo/public/cpp/bindings/binding_set.h"
#include "third_party/blink/public/platform/modules/webauthn/virtual_authenticator.mojom.h"
@@ -53,7 +53,7 @@ class CONTENT_EXPORT ScopedVirtualAuthenticatorEnvironment
void ClearAuthenticators(ClearAuthenticatorsCallback callback) override;
// ScopedFidoDiscoveryFactory:
- std::unique_ptr<::device::FidoDiscovery> CreateFidoDiscovery(
+ std::unique_ptr<::device::FidoDeviceDiscovery> CreateFidoDiscovery(
device::FidoTransportProtocol transport,
::service_manager::Connector* connector) override;
diff --git a/chromium/content/browser/webauth/virtual_discovery.cc b/chromium/content/browser/webauth/virtual_discovery.cc
index 1f37ee855ba..82e022b48ed 100644
--- a/chromium/content/browser/webauth/virtual_discovery.cc
+++ b/chromium/content/browser/webauth/virtual_discovery.cc
@@ -17,7 +17,7 @@ namespace content {
VirtualFidoDiscovery::VirtualFidoDiscovery(
ScopedVirtualAuthenticatorEnvironment* environment,
::device::FidoTransportProtocol transport)
- : FidoDiscovery(transport), environment_(environment) {}
+ : FidoDeviceDiscovery(transport), environment_(environment) {}
VirtualFidoDiscovery::~VirtualFidoDiscovery() {
environment_->OnDiscoveryDestroyed(this);
@@ -28,7 +28,7 @@ void VirtualFidoDiscovery::AddVirtualDevice(
// The real implementation would never notify the client's observer about
// devices before the client calls Start(), mimic the same behavior.
if (is_start_requested()) {
- FidoDiscovery::AddDevice(std::move(device));
+ FidoDeviceDiscovery::AddDevice(std::move(device));
} else {
devices_pending_discovery_start_.push_back(std::move(device));
}
@@ -36,12 +36,12 @@ void VirtualFidoDiscovery::AddVirtualDevice(
bool VirtualFidoDiscovery::RemoveVirtualDevice(base::StringPiece device_id) {
DCHECK(is_start_requested());
- return ::device::FidoDiscovery::RemoveDevice(device_id);
+ return ::device::FidoDeviceDiscovery::RemoveDevice(device_id);
}
void VirtualFidoDiscovery::StartInternal() {
for (auto& device : devices_pending_discovery_start_)
- FidoDiscovery::AddDevice(std::move(device));
+ FidoDeviceDiscovery::AddDevice(std::move(device));
devices_pending_discovery_start_.clear();
base::ThreadTaskRunnerHandle::Get()->PostTask(
diff --git a/chromium/content/browser/webauth/virtual_discovery.h b/chromium/content/browser/webauth/virtual_discovery.h
index 7c57b042ff9..b4c14fc205a 100644
--- a/chromium/content/browser/webauth/virtual_discovery.h
+++ b/chromium/content/browser/webauth/virtual_discovery.h
@@ -11,7 +11,7 @@
#include "base/macros.h"
#include "base/strings/string_piece.h"
#include "content/common/content_export.h"
-#include "device/fido/fido_discovery.h"
+#include "device/fido/fido_device_discovery.h"
namespace device {
class FidoDevice;
@@ -21,9 +21,10 @@ namespace content {
class ScopedVirtualAuthenticatorEnvironment;
-// A fully automated FidoDiscovery implementation, which is disconnected from
-// the real world, and discovers VirtualFidoDevice instances.
-class CONTENT_EXPORT VirtualFidoDiscovery : public ::device::FidoDiscovery {
+// A fully automated FidoDeviceDiscovery implementation, which is disconnected
+// from the real world, and discovers VirtualFidoDevice instances.
+class CONTENT_EXPORT VirtualFidoDiscovery
+ : public ::device::FidoDeviceDiscovery {
public:
// The |environment| must outlive this instance.
VirtualFidoDiscovery(ScopedVirtualAuthenticatorEnvironment* environment,
@@ -36,7 +37,7 @@ class CONTENT_EXPORT VirtualFidoDiscovery : public ::device::FidoDiscovery {
bool RemoveVirtualDevice(base::StringPiece device_id);
protected:
- // FidoDiscovery:
+ // FidoDeviceDiscovery:
void StartInternal() override;
private:
diff --git a/chromium/content/browser/webauth/webauth_browsertest.cc b/chromium/content/browser/webauth/webauth_browsertest.cc
index 57bc30c924b..b78d7129899 100644
--- a/chromium/content/browser/webauth/webauth_browsertest.cc
+++ b/chromium/content/browser/webauth/webauth_browsertest.cc
@@ -67,9 +67,9 @@ constexpr char kTimeoutErrorMessage[] =
"webauth: NotAllowedError: The operation either timed out or was not "
"allowed. See: https://w3c.github.io/webauthn/#sec-assertion-privacy.";
-constexpr char kInvalidStateErrorMessage[] =
- "webauth: InvalidStateError: The user attempted to use an authenticator "
- "that recognized none of the provided credentials.";
+constexpr char kResidentCredentialsErrorMessage[] =
+ "webauth: NotSupportedError: Resident credentials or empty "
+ "'allowCredentials' lists are not supported at this time.";
constexpr char kRelyingPartySecurityErrorMessage[] =
"webauth: SecurityError: The relying party ID 'localhost' is not a "
@@ -590,7 +590,7 @@ IN_PROC_BROWSER_TEST_F(WebAuthLocalClientBrowserTest,
// factory as one of the first steps. Here, the request should not have been
// serviced at all, so the fake request should still be pending on the fake
// factory.
- auto hid_discovery = ::device::FidoDiscovery::Create(
+ auto hid_discovery = ::device::FidoDeviceDiscovery::Create(
::device::FidoTransportProtocol::kUsbHumanInterfaceDevice, nullptr);
ASSERT_TRUE(!!hid_discovery);
@@ -735,7 +735,7 @@ IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
shell()->web_contents()->GetMainFrame(),
BuildCreateCallWithParameters(parameters), &result));
- ASSERT_EQ(kTimeoutErrorMessage, result);
+ ASSERT_EQ(kResidentCredentialsErrorMessage, result);
}
}
@@ -806,7 +806,7 @@ IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
ASSERT_TRUE(content::ExecuteScriptAndExtractString(
shell()->web_contents()->GetMainFrame(),
BuildGetCallWithParameters(parameters), &result));
- ASSERT_EQ(kInvalidStateErrorMessage, result);
+ ASSERT_EQ(kResidentCredentialsErrorMessage, result);
}
// WebAuthBrowserBleDisabledTest
diff --git a/chromium/content/browser/webrtc/webrtc_audio_browsertest.cc b/chromium/content/browser/webrtc/webrtc_audio_browsertest.cc
index 308f749f75d..538577a8ba9 100644
--- a/chromium/content/browser/webrtc/webrtc_audio_browsertest.cc
+++ b/chromium/content/browser/webrtc/webrtc_audio_browsertest.cc
@@ -18,73 +18,25 @@
#include "media/base/media_switches.h"
#include "media/webrtc/webrtc_switches.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
-#include "services/service_manager/sandbox/features.h"
#include "testing/gtest/include/gtest/gtest-param-test.h"
namespace content {
-namespace {
-
-// Temporary enum, used for running the tests with different combination of
-// flags while audio service is under experiment.
-// TODO(https://crbug.com/850878) Remove after enabling sandboxing on all
-// platforms.
-enum class AudioServiceFeatures {
- kDisabled,
- kOutOfProcess,
-#if defined(OS_WIN)
- kSandboxed,
-#endif
-#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)
- kSandboxedWithAudioServiceAPM
-#endif
-};
-} // namespace
-
// This class tests the scenario when permission to access mic or camera is
// granted.
-class WebRtcAudioBrowserTest
- : public WebRtcContentBrowserTestBase,
- public testing::WithParamInterface<AudioServiceFeatures> {
+class WebRtcAudioBrowserTest : public WebRtcContentBrowserTestBase,
+ public testing::WithParamInterface<bool> {
public:
WebRtcAudioBrowserTest() {
std::vector<base::Feature> audio_service_oop_features = {
features::kAudioServiceAudioStreams,
features::kAudioServiceOutOfProcess};
- switch (GetParam()) {
- case AudioServiceFeatures::kDisabled:
- // Force audio service out of process to disabled.
- audio_service_features_.InitWithFeatures({},
- audio_service_oop_features);
- break;
- case AudioServiceFeatures::kOutOfProcess:
- // Force audio service out of process to enabled.
- audio_service_features_.InitWithFeatures(
- audio_service_oop_features,
-#if defined(OS_WIN)
- // Force audio service sandboxing (available only on Windows) to
- // disabled.
- {service_manager::features::kAudioServiceSandbox});
-#else
- {});
-#endif
- break;
-#if defined(OS_WIN)
- case AudioServiceFeatures::kSandboxed:
- // Force audio service out of process and sandboxing to enabled.
- audio_service_oop_features.push_back(
- service_manager::features::kAudioServiceSandbox);
- audio_service_features_.InitWithFeatures(audio_service_oop_features,
- {});
- break;
-#endif
-#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)
- case AudioServiceFeatures::kSandboxedWithAudioServiceAPM:
- audio_service_oop_features.push_back(
- service_manager::features::kAudioServiceSandbox);
- audio_service_oop_features.push_back(
- features::kWebRtcApmInAudioService);
-#endif
+ 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 {}
@@ -178,30 +130,14 @@ IN_PROC_BROWSER_TEST_P(WebRtcAudioBrowserTest,
// 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)
+#if defined(OS_LINUX) || defined(OS_MACOSX) || defined(OS_WIN)
// Supported platforms.
-INSTANTIATE_TEST_CASE_P(
- ,
- WebRtcAudioBrowserTest,
- ::testing::Values(AudioServiceFeatures::kDisabled,
- AudioServiceFeatures::kOutOfProcess,
- AudioServiceFeatures::kSandboxedWithAudioServiceAPM));
-#elif defined(OS_WIN)
-// On Windows, also run in sandboxed mode.
-INSTANTIATE_TEST_CASE_P(
- ,
- WebRtcAudioBrowserTest,
- ::testing::Values(AudioServiceFeatures::kDisabled,
- AudioServiceFeatures::kOutOfProcess,
- AudioServiceFeatures::kSandboxed,
- AudioServiceFeatures::kSandboxedWithAudioServiceAPM));
+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(AudioServiceFeatures::kDisabled));
+INSTANTIATE_TEST_CASE_P(, WebRtcAudioBrowserTest, ::testing::Values(false));
#endif
} // namespace content
diff --git a/chromium/content/browser/webrtc/webrtc_browsertest.cc b/chromium/content/browser/webrtc/webrtc_browsertest.cc
index cbbb5ee815c..74c2b7d8c58 100644
--- a/chromium/content/browser/webrtc/webrtc_browsertest.cc
+++ b/chromium/content/browser/webrtc/webrtc_browsertest.cc
@@ -17,6 +17,7 @@
#include "media/base/media_switches.h"
#include "media/media_buildflags.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "services/network/public/cpp/features.h"
namespace content {
@@ -58,6 +59,14 @@ IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest, CanSetupAudioAndVideoCall) {
MakeTypicalPeerConnectionCall("call({video: true, audio: true});");
}
+IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest, NetworkProcessCrashRecovery) {
+ if (!base::FeatureList::IsEnabled(network::features::kNetworkService))
+ return;
+ MakeTypicalPeerConnectionCall("call({video: true, audio: true});");
+ SimulateNetworkServiceCrash();
+ MakeTypicalPeerConnectionCall("call({video: true, audio: true});");
+}
+
IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,
CanSetupDefaultVideoCallWithOldGetUserMedia) {
MakeTypicalPeerConnectionCall("oldStyleCall();");
diff --git a/chromium/content/browser/webrtc/webrtc_content_browsertest_base.cc b/chromium/content/browser/webrtc/webrtc_content_browsertest_base.cc
index 6c1cd8c7d72..d79ccc7549b 100644
--- a/chromium/content/browser/webrtc/webrtc_content_browsertest_base.cc
+++ b/chromium/content/browser/webrtc/webrtc_content_browsertest_base.cc
@@ -76,7 +76,8 @@ std::string WebRtcContentBrowserTestBase::ExecuteJavascriptAndReturnResult(
void WebRtcContentBrowserTestBase::MakeTypicalCall(
const std::string& javascript,
const std::string& html_file) {
- ASSERT_TRUE(embedded_test_server()->Start());
+ if (!embedded_test_server()->Started())
+ ASSERT_TRUE(embedded_test_server()->Start());
GURL url(embedded_test_server()->GetURL(html_file));
NavigateToURL(shell(), url);
diff --git a/chromium/content/browser/webrtc/webrtc_depth_capture_browsertest.cc b/chromium/content/browser/webrtc/webrtc_depth_capture_browsertest.cc
index f2936a8bcc0..6ac469bdde7 100644
--- a/chromium/content/browser/webrtc/webrtc_depth_capture_browsertest.cc
+++ b/chromium/content/browser/webrtc/webrtc_depth_capture_browsertest.cc
@@ -5,6 +5,7 @@
#include <stddef.h>
#include "base/command_line.h"
+#include "base/stl_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "content/browser/webrtc/webrtc_content_browsertest_base.h"
@@ -34,12 +35,10 @@ void RemoveSwitchFromCommandLine(base::CommandLine* command_line,
#else
switch_value;
#endif
- argv.erase(std::remove_if(
- argv.begin(), argv.end(),
- [switch_string](const base::CommandLine::StringType& value) {
- return value.find(switch_string) != std::string::npos;
- }),
- argv.end());
+ base::EraseIf(argv,
+ [switch_string](const base::CommandLine::StringType& value) {
+ return value.find(switch_string) != std::string::npos;
+ });
command_line->InitFromArgv(argv);
}
diff --git a/chromium/content/browser/webrtc/webrtc_getusermedia_browsertest.cc b/chromium/content/browser/webrtc/webrtc_getusermedia_browsertest.cc
index 5a997c3dcd8..c9dc8a33c09 100644
--- a/chromium/content/browser/webrtc/webrtc_getusermedia_browsertest.cc
+++ b/chromium/content/browser/webrtc/webrtc_getusermedia_browsertest.cc
@@ -34,7 +34,6 @@
#if defined(OS_WIN)
#include "base/win/windows_version.h"
-#include "services/service_manager/sandbox/features.h"
#endif
namespace {
@@ -58,18 +57,6 @@ static const char kRenderDuplicatedMediastreamAndStop[] =
// Results returned by JS.
static const char kOK[] = "OK";
-// Temporary enum, used for running the tests with different combination of
-// flags while audio service is under experiment.
-// TODO(https://crbug.com/850878) Remove after enabling sandboxing on all
-// platforms.
-enum class AudioServiceFeatures {
- kDisabled,
- kOutOfProcess,
-#if defined(OS_WIN)
- kSandboxed,
-#endif
-};
-
std::string GenerateGetUserMediaWithMandatorySourceID(
const std::string& function_name,
const std::string& audio_source_id,
@@ -115,9 +102,8 @@ bool VerifyDisableLocalEcho(bool expect_value,
namespace content {
-class WebRtcGetUserMediaBrowserTest
- : public WebRtcContentBrowserTestBase,
- public testing::WithParamInterface<AudioServiceFeatures> {
+class WebRtcGetUserMediaBrowserTest : public WebRtcContentBrowserTestBase,
+ public testing::WithParamInterface<bool> {
public:
WebRtcGetUserMediaBrowserTest() {
// Automatically grant device permission.
@@ -125,33 +111,12 @@ class WebRtcGetUserMediaBrowserTest
std::vector<base::Feature> audio_service_oop_features = {
features::kAudioServiceAudioStreams,
features::kAudioServiceOutOfProcess};
- switch (GetParam()) {
- case AudioServiceFeatures::kDisabled:
- // Force audio service out of process to disabled.
- audio_service_features_.InitWithFeatures({},
- audio_service_oop_features);
- break;
- case AudioServiceFeatures::kOutOfProcess:
- // Force audio service out of process to enabled.
- audio_service_features_.InitWithFeatures(
- audio_service_oop_features,
-#if defined(OS_WIN)
- // Force audio service sandboxing (available only on Windows) to
- // disabled.
- {service_manager::features::kAudioServiceSandbox});
-#else
- {});
-#endif
- break;
-#if defined(OS_WIN)
- case AudioServiceFeatures::kSandboxed:
- // Force audio service out of process and sandboxing to enabled.
- audio_service_oop_features.push_back(
- service_manager::features::kAudioServiceSandbox);
- audio_service_features_.InitWithFeatures(audio_service_oop_features,
- {});
- break;
-#endif
+ 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 {}
@@ -193,8 +158,7 @@ class WebRtcGetUserMediaBrowserTest
base::ListValue* values;
ASSERT_TRUE(value->GetAsList(&values));
- for (base::ListValue::iterator it = values->begin();
- it != values->end(); ++it) {
+ for (auto it = values->begin(); it != values->end(); ++it) {
const base::DictionaryValue* dict;
std::string kind;
std::string device_id;
@@ -729,7 +693,7 @@ IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest, SrcObjectAddVideoTrack) {
// TODO(crbug.com/848330) Flaky on all platforms
IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
- DISABLE_SrcObjectReplaceInactiveTracks) {
+ DISABLED_SrcObjectReplaceInactiveTracks) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
NavigateToURL(shell(), url);
@@ -825,7 +789,7 @@ 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() != AudioServiceFeatures::kDisabled)
+ if (GetParam())
return;
ASSERT_TRUE(embedded_test_server()->Start());
@@ -854,7 +818,7 @@ 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() != AudioServiceFeatures::kDisabled)
+ if (GetParam())
return;
ASSERT_TRUE(embedded_test_server()->Start());
@@ -884,7 +848,7 @@ IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
RecoverFromCrashInAudioService) {
// This test only makes sense with the audio service running out of process,
// with or without sandbox.
- if (GetParam() == AudioServiceFeatures::kDisabled)
+ if (!GetParam())
return;
ASSERT_TRUE(embedded_test_server()->Start());
@@ -907,24 +871,15 @@ IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
// 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)
+#if (defined(OS_LINUX) && !defined(CHROME_OS)) || defined(OS_MACOSX) || \
+ defined(OS_WIN)
// Supported platforms.
-INSTANTIATE_TEST_CASE_P(,
- WebRtcGetUserMediaBrowserTest,
- ::testing::Values(AudioServiceFeatures::kDisabled,
- AudioServiceFeatures::kOutOfProcess));
-#elif defined(OS_WIN)
-// On Windows, also run in sandboxed mode.
-INSTANTIATE_TEST_CASE_P(,
- WebRtcGetUserMediaBrowserTest,
- ::testing::Values(AudioServiceFeatures::kDisabled,
- AudioServiceFeatures::kOutOfProcess,
- AudioServiceFeatures::kSandboxed));
+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(AudioServiceFeatures::kDisabled));
+ ::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 89f968cb9a9..71666e4a6e7 100644
--- a/chromium/content/browser/webrtc/webrtc_internals.cc
+++ b/chromium/content/browser/webrtc/webrtc_internals.cc
@@ -11,10 +11,12 @@
#include "base/command_line.h"
#include "base/strings/string_number_conversions.h"
+#include "base/task/post_task.h"
#include "build/build_config.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/web_contents/web_contents_view.h"
#include "content/browser/webrtc/webrtc_internals_ui_observer.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/web_contents.h"
@@ -421,8 +423,8 @@ void WebRTCInternals::SendUpdate(const char* command,
pending_updates_.push(PendingUpdate(command, std::move(value)));
if (queue_was_empty) {
- BrowserThread::PostDelayedTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostDelayedTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&WebRTCInternals::ProcessPendingUpdates,
weak_factory_.GetWeakPtr()),
base::TimeDelta::FromMilliseconds(aggregate_updates_ms_));
diff --git a/chromium/content/browser/webrtc/webrtc_internals_unittest.cc b/chromium/content/browser/webrtc/webrtc_internals_unittest.cc
index 8e4dd0a0687..bad42e39fda 100644
--- a/chromium/content/browser/webrtc/webrtc_internals_unittest.cc
+++ b/chromium/content/browser/webrtc/webrtc_internals_unittest.cc
@@ -8,8 +8,10 @@
#include <string>
#include "base/run_loop.h"
+#include "base/task/post_task.h"
#include "base/values.h"
#include "content/browser/webrtc/webrtc_internals_ui_observer.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/test/test_browser_thread.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "mojo/public/cpp/bindings/binding.h"
@@ -144,7 +146,7 @@ TEST_F(WebRtcInternalsTest, AddRemoveObserver) {
webrtc_internals.OnAddPeerConnection(0, 3, 4, kUrl, kRtcConfiguration,
kContraints);
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, loop.QuitClosure());
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI}, loop.QuitClosure());
loop.Run();
EXPECT_EQ("", observer.command());
@@ -160,7 +162,7 @@ TEST_F(WebRtcInternalsTest, EnsureNoLogWhenNoObserver) {
webrtc_internals.OnAddPeerConnection(0, 3, 4, kUrl, kRtcConfiguration,
kContraints);
webrtc_internals.OnUpdatePeerConnection(3, 4, "update_type", "update_value");
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, loop.QuitClosure());
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI}, loop.QuitClosure());
loop.Run();
// Make sure we don't have a log entry since there was no observer.
@@ -189,7 +191,7 @@ TEST_F(WebRtcInternalsTest, EnsureLogIsRemovedWhenObserverIsRemoved) {
webrtc_internals.OnAddPeerConnection(0, 3, 4, kUrl, kRtcConfiguration,
kContraints);
webrtc_internals.OnUpdatePeerConnection(3, 4, "update_type", "update_value");
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, loop.QuitClosure());
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI}, loop.QuitClosure());
loop.Run();
// Make sure we have a log entry since there was an observer.
diff --git a/chromium/content/browser/webrtc/webrtc_video_capture_browsertest.cc b/chromium/content/browser/webrtc/webrtc_video_capture_browsertest.cc
index 75ceb0e923c..9e38210316a 100644
--- a/chromium/content/browser/webrtc/webrtc_video_capture_browsertest.cc
+++ b/chromium/content/browser/webrtc/webrtc_video_capture_browsertest.cc
@@ -36,7 +36,7 @@ namespace {
static const char kVideoCaptureHtmlFile[] = "/media/video_capture_test.html";
static const char kStartVideoCaptureAndVerifySize[] =
- "startVideoCaptureAndVerifySize()";
+ "startVideoCaptureAndVerifySize(320, 200)";
static const char kWaitForVideoToTurnBlack[] = "waitForVideoToTurnBlack()";
static const char kVerifyHasReceivedTrackEndedEvent[] =
"verifyHasReceivedTrackEndedEvent()";
diff --git a/chromium/content/browser/webrtc/webrtc_video_capture_service_browsertest.cc b/chromium/content/browser/webrtc/webrtc_video_capture_service_browsertest.cc
index 032f909449b..337c91dd2d0 100644
--- a/chromium/content/browser/webrtc/webrtc_video_capture_service_browsertest.cc
+++ b/chromium/content/browser/webrtc/webrtc_video_capture_service_browsertest.cc
@@ -6,6 +6,7 @@
#include "base/run_loop.h"
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
+#include "cc/base/math_util.h"
#include "components/viz/common/gpu/context_provider.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_features.h"
@@ -55,13 +56,15 @@ class InvokeClosureOnDelete
};
static const char kVideoCaptureHtmlFile[] = "/media/video_capture_test.html";
-static const char kStartVideoCaptureAndVerifySize[] =
- "startVideoCaptureFromDeviceNamedVirtualDeviceAndVerifySize()";
+static const char kStartVideoCaptureAndVerify[] =
+ "startVideoCaptureFromVirtualDeviceAndVerifyUniformColorVideoWithSize(%d, "
+ "%d)";
static const char kVirtualDeviceId[] = "/virtual/device";
static const char kVirtualDeviceName[] = "Virtual Device";
-static const gfx::Size kDummyFrameDimensions(320, 200);
+static const gfx::Size kDummyFrameCodedSize(320, 200);
+static const gfx::Rect kDummyFrameVisibleRect(94, 36, 178, 150);
static const int kDummyFrameRate = 5;
} // namespace
@@ -76,6 +79,7 @@ class VirtualDeviceExerciser {
virtual void RegisterVirtualDeviceAtFactory(
video_capture::mojom::DeviceFactoryPtr* factory,
const media::VideoCaptureDeviceInfo& info) = 0;
+ virtual gfx::Size GetVideoSize() = 0;
virtual void PushNextFrame(base::TimeDelta timestamp) = 0;
virtual void ShutDown() = 0;
};
@@ -123,6 +127,8 @@ class TextureDeviceExerciser : public VirtualDeviceExerciser {
frame_being_consumed_[1] = false;
}
+ gfx::Size GetVideoSize() override { return kDummyFrameCodedSize; }
+
void PushNextFrame(base::TimeDelta timestamp) override {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (frame_being_consumed_[dummy_frame_index_]) {
@@ -145,9 +151,8 @@ class TextureDeviceExerciser : public VirtualDeviceExerciser {
media::mojom::VideoFrameInfoPtr info = media::mojom::VideoFrameInfo::New();
info->timestamp = timestamp;
info->pixel_format = media::PIXEL_FORMAT_ARGB;
- info->coded_size = kDummyFrameDimensions;
- info->visible_rect = gfx::Rect(kDummyFrameDimensions.width(),
- kDummyFrameDimensions.height());
+ info->coded_size = kDummyFrameCodedSize;
+ info->visible_rect = gfx::Rect(kDummyFrameCodedSize);
info->metadata = metadata.GetInternalValues().Clone();
frame_being_consumed_[dummy_frame_index_] = true;
@@ -169,8 +174,8 @@ class TextureDeviceExerciser : public VirtualDeviceExerciser {
uint8_t value_for_all_rgb_bytes,
std::vector<gpu::MailboxHolder>* target) {
const int32_t kBytesPerRGBPixel = 3;
- int32_t frame_size_in_bytes = kDummyFrameDimensions.width() *
- kDummyFrameDimensions.height() *
+ int32_t frame_size_in_bytes = kDummyFrameCodedSize.width() *
+ kDummyFrameCodedSize.height() *
kBytesPerRGBPixel;
std::unique_ptr<uint8_t[]> dummy_frame_data(
new uint8_t[frame_size_in_bytes]);
@@ -191,9 +196,9 @@ class TextureDeviceExerciser : public VirtualDeviceExerciser {
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- gl->TexImage2D(GL_TEXTURE_2D, 0, GL_RGB, kDummyFrameDimensions.width(),
- kDummyFrameDimensions.height(), 0, GL_RGB,
- GL_UNSIGNED_BYTE, dummy_frame_data.get());
+ gl->TexImage2D(GL_TEXTURE_2D, 0, GL_RGB, kDummyFrameCodedSize.width(),
+ kDummyFrameCodedSize.height(), 0, GL_RGB, GL_UNSIGNED_BYTE,
+ dummy_frame_data.get());
gl->BindTexture(GL_TEXTURE_2D, 0);
gpu::Mailbox mailbox;
@@ -225,12 +230,15 @@ class TextureDeviceExerciser : public VirtualDeviceExerciser {
// A VirtualDeviceExerciser for exercising
// DeviceFactory.AddSharedMemoryVirtualDevice().
// It generates (dummy) I420 frame data by setting all bytes equal to the
-// current frame count.
+// current frame count. Padding bytes are set to 0.
class SharedMemoryDeviceExerciser : public VirtualDeviceExerciser,
public video_capture::mojom::Producer {
public:
- SharedMemoryDeviceExerciser()
- : producer_binding_(this), weak_factory_(this) {}
+ explicit SharedMemoryDeviceExerciser(
+ media::mojom::PlaneStridesPtr strides = nullptr)
+ : strides_(std::move(strides)),
+ producer_binding_(this),
+ weak_factory_(this) {}
// VirtualDeviceExerciser implementation.
void Initialize() override {}
@@ -245,9 +253,14 @@ class SharedMemoryDeviceExerciser : public VirtualDeviceExerciser,
kSendBufferHandlesToProducerAsRawFileDescriptors,
mojo::MakeRequest(&virtual_device_));
}
+ gfx::Size GetVideoSize() override {
+ return gfx::Size(kDummyFrameVisibleRect.width(),
+ kDummyFrameVisibleRect.height());
+ }
void PushNextFrame(base::TimeDelta timestamp) override {
virtual_device_->RequestFrameBuffer(
- kDummyFrameDimensions, media::VideoPixelFormat::PIXEL_FORMAT_I420,
+ kDummyFrameCodedSize, media::VideoPixelFormat::PIXEL_FORMAT_I420,
+ strides_.Clone(),
base::BindOnce(&SharedMemoryDeviceExerciser::OnFrameBufferReceived,
weak_factory_.GetWeakPtr(), timestamp));
}
@@ -287,22 +300,91 @@ class SharedMemoryDeviceExerciser : public VirtualDeviceExerciser,
media::mojom::VideoFrameInfoPtr info = media::mojom::VideoFrameInfo::New();
info->timestamp = timestamp;
info->pixel_format = media::PIXEL_FORMAT_I420;
- info->coded_size = kDummyFrameDimensions;
- info->visible_rect = gfx::Rect(kDummyFrameDimensions.width(),
- kDummyFrameDimensions.height());
+ info->coded_size = kDummyFrameCodedSize;
+ info->visible_rect = kDummyFrameVisibleRect;
info->metadata = metadata.GetInternalValues().Clone();
+ info->strides = strides_.Clone();
auto outgoing_buffer = outgoing_buffer_id_to_buffer_map_.at(buffer_id)
->GetHandleForInProcessAccess();
static int frame_count = 0;
frame_count++;
- memset(outgoing_buffer->data(), frame_count % 256,
- outgoing_buffer->mapped_size());
+ const uint8_t dummy_value = frame_count % 256;
+
+ // Reset the whole buffer to 0
+ memset(outgoing_buffer->data(), 0, outgoing_buffer->mapped_size());
+
+ // Set all bytes affecting |info->visible_rect| to |dummy_value|.
+ const int kYStride = info->strides ? info->strides->stride_by_plane[0]
+ : info->coded_size.width();
+ const int kYColsToSkipAtStart = info->visible_rect.x();
+ const int kYVisibleColCount = info->visible_rect.width();
+ const int kYCodedRowCount = info->coded_size.height();
+ const int kYRowsToSkipAtStart = info->visible_rect.y();
+ const int kYVisibleRowCount = info->visible_rect.height();
+
+ const int kUStride = info->strides ? info->strides->stride_by_plane[1]
+ : info->coded_size.width() / 2;
+ const int kUColsToSkipAtStart =
+ cc::MathUtil::UncheckedRoundDown(info->visible_rect.x(), 2) / 2;
+ const int kUVisibleColCount =
+ (cc::MathUtil::UncheckedRoundUp(info->visible_rect.right(), 2) / 2) -
+ kUColsToSkipAtStart;
+ const int kUCodedRowCount = info->coded_size.height() / 2;
+ const int kURowsToSkipAtStart =
+ cc::MathUtil::UncheckedRoundDown(info->visible_rect.y(), 2) / 2;
+ const int kUVisibleRowCount =
+ (cc::MathUtil::UncheckedRoundUp(info->visible_rect.bottom(), 2) / 2) -
+ kURowsToSkipAtStart;
+
+ const int kVStride = info->strides ? info->strides->stride_by_plane[2]
+ : info->coded_size.width() / 2;
+
+ uint8_t* write_ptr = outgoing_buffer->data();
+ FillVisiblePortionOfPlane(&write_ptr, dummy_value, kYCodedRowCount,
+ kYRowsToSkipAtStart, kYVisibleRowCount, kYStride,
+ kYColsToSkipAtStart, kYVisibleColCount);
+ FillVisiblePortionOfPlane(&write_ptr, dummy_value, kUCodedRowCount,
+ kURowsToSkipAtStart, kUVisibleRowCount, kUStride,
+ kUColsToSkipAtStart, kUVisibleColCount);
+ FillVisiblePortionOfPlane(&write_ptr, dummy_value, kUCodedRowCount,
+ kURowsToSkipAtStart, kUVisibleRowCount, kVStride,
+ kUColsToSkipAtStart, kUVisibleColCount);
virtual_device_->OnFrameReadyInBuffer(buffer_id, std::move(info));
}
+ void FillVisiblePortionOfPlane(uint8_t** write_ptr,
+ uint8_t fill_value,
+ int row_count,
+ int rows_to_skip_at_start,
+ int visible_row_count,
+ int col_count,
+ int cols_to_skip_at_start,
+ int visible_col_count) {
+ const int kColsToSkipAtEnd =
+ col_count - visible_col_count - cols_to_skip_at_start;
+ const int kRowsToSkipAtEnd =
+ row_count - visible_row_count - rows_to_skip_at_start;
+
+ // Skip rows at start
+ (*write_ptr) += col_count * rows_to_skip_at_start;
+ // Fill rows
+ for (int i = 0; i < visible_row_count; i++) {
+ // Skip cols at start
+ (*write_ptr) += cols_to_skip_at_start;
+ // Fill visible bytes
+ memset(*write_ptr, fill_value, visible_col_count);
+ (*write_ptr) += visible_col_count;
+ // Skip cols at end
+ (*write_ptr) += kColsToSkipAtEnd;
+ }
+ // Skip rows at end
+ (*write_ptr) += col_count * kRowsToSkipAtEnd;
+ }
+
+ media::mojom::PlaneStridesPtr strides_;
mojo::Binding<video_capture::mojom::Producer> producer_binding_;
video_capture::mojom::SharedMemoryVirtualDevicePtr virtual_device_;
std::map<int32_t /*buffer_id*/,
@@ -337,6 +419,7 @@ class WebRtcVideoCaptureServiceBrowserTest : public ContentBrowserTest {
info.descriptor.set_display_name(kVirtualDeviceName);
info.descriptor.capture_api = media::VideoCaptureApi::VIRTUAL_DEVICE;
+ video_size_ = device_exerciser->GetVideoSize();
device_exerciser->RegisterVirtualDeviceAtFactory(&factory_, info);
main_task_runner_->PostTask(
@@ -384,10 +467,12 @@ class WebRtcVideoCaptureServiceBrowserTest : public ContentBrowserTest {
GURL url(embedded_test_server()->GetURL(kVideoCaptureHtmlFile));
NavigateToURL(shell(), url);
+ std::string javascript_to_execute = base::StringPrintf(
+ kStartVideoCaptureAndVerify, video_size_.width(), video_size_.height());
std::string result;
// Start video capture and wait until it started rendering
- ASSERT_TRUE(ExecuteScriptAndExtractString(
- shell(), kStartVideoCaptureAndVerifySize, &result));
+ ASSERT_TRUE(
+ ExecuteScriptAndExtractString(shell(), javascript_to_execute, &result));
ASSERT_EQ("OK", result);
std::move(finish_test_cb).Run();
@@ -433,6 +518,7 @@ class WebRtcVideoCaptureServiceBrowserTest : public ContentBrowserTest {
base::test::ScopedFeatureList scoped_feature_list_;
video_capture::mojom::DeviceFactoryProviderPtr provider_;
video_capture::mojom::DeviceFactoryPtr factory_;
+ gfx::Size video_size_;
base::TimeTicks first_frame_time_;
base::WeakPtrFactory<WebRtcVideoCaptureServiceBrowserTest> weak_factory_;
@@ -473,6 +559,25 @@ IN_PROC_BROWSER_TEST_F(
run_loop.Run();
}
+IN_PROC_BROWSER_TEST_F(
+ WebRtcVideoCaptureServiceBrowserTest,
+ PaddedI420FramesSentThroughSharedMemoryVirtualDeviceGetDisplayedOnPage) {
+ Initialize();
+ auto device_exerciser = std::make_unique<SharedMemoryDeviceExerciser>(
+ media::mojom::PlaneStrides::New(
+ std::vector<uint32_t>({1024u, 512u, 1024u, 0u})));
+ device_exerciser->Initialize();
+
+ base::RunLoop run_loop;
+ virtual_device_thread_.task_runner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&WebRtcVideoCaptureServiceBrowserTest::
+ AddVirtualDeviceAndStartCapture,
+ base::Unretained(this), device_exerciser.get(),
+ media::BindToCurrentLoop(run_loop.QuitClosure())));
+ run_loop.Run();
+}
+
} // namespace content
#endif // defined(CAN_USE_IMAGE_TRANSPORT_FACTORY)
diff --git a/chromium/content/browser/webrtc/webrtc_video_capture_service_enumeration_browsertest.cc b/chromium/content/browser/webrtc/webrtc_video_capture_service_enumeration_browsertest.cc
new file mode 100644
index 00000000000..c3957b2a9f8
--- /dev/null
+++ b/chromium/content/browser/webrtc/webrtc_video_capture_service_enumeration_browsertest.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 "base/command_line.h"
+#include "base/test/scoped_feature_list.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/common/content_features.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/common/service_manager_connection.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/shell/browser/shell.h"
+#include "media/base/media_switches.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "services/service_manager/public/cpp/connector.h"
+#include "services/video_capture/public/mojom/constants.mojom.h"
+#include "services/video_capture/public/mojom/device_factory_provider.mojom.h"
+
+namespace content {
+
+namespace {
+
+static const char kVideoCaptureHtmlFile[] = "/media/video_capture_test.html";
+static const std::string kEnumerateVideoCaptureDevicesAndVerify =
+ "enumerateVideoCaptureDevicesAndVerifyCount";
+
+} // anonymous namespace
+
+// Integration test that obtains a connection to the video capture service via
+// the Browser process' service manager. It then registers and unregisters
+// virtual devices at the service and checks in JavaScript that the list of
+// enumerated devices changes correspondingly.
+class WebRtcVideoCaptureServiceEnumerationBrowserTest
+ : public ContentBrowserTest {
+ public:
+ WebRtcVideoCaptureServiceEnumerationBrowserTest() {
+ scoped_feature_list_.InitAndEnableFeature(features::kMojoVideoCapture);
+ }
+
+ ~WebRtcVideoCaptureServiceEnumerationBrowserTest() override {}
+
+ void ConnectToService() {
+ connector_->BindInterface(video_capture::mojom::kServiceName, &provider_);
+ provider_->ConnectToDeviceFactory(mojo::MakeRequest(&factory_));
+ }
+
+ void AddVirtualDevice(const std::string& device_id) {
+ media::VideoCaptureDeviceInfo info;
+ info.descriptor.device_id = device_id;
+ info.descriptor.set_display_name(device_id);
+ info.descriptor.capture_api = media::VideoCaptureApi::VIRTUAL_DEVICE;
+
+ video_capture::mojom::TextureVirtualDevicePtr virtual_device;
+ factory_->AddTextureVirtualDevice(info, mojo::MakeRequest(&virtual_device));
+ virtual_devices_by_id_.insert(
+ std::make_pair(device_id, std::move(virtual_device)));
+ }
+
+ void RemoveVirtualDevice(const std::string& device_id) {
+ virtual_devices_by_id_.erase(device_id);
+ }
+
+ void DisconnectFromService() {
+ factory_ = nullptr;
+ provider_ = nullptr;
+ }
+
+ void EnumerateDevicesInRendererAndVerifyDeviceCount(
+ int expected_device_count) {
+ NavigateToURL(shell(),
+ GURL(embedded_test_server()->GetURL(kVideoCaptureHtmlFile)));
+
+ const std::string javascript_to_execute = base::StringPrintf(
+ (kEnumerateVideoCaptureDevicesAndVerify + "(%d)").c_str(),
+ expected_device_count);
+ std::string result;
+ ASSERT_TRUE(
+ ExecuteScriptAndExtractString(shell(), javascript_to_execute, &result));
+ ASSERT_EQ("OK", result);
+ }
+
+ protected:
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ // Note: We are not planning to actually use any fake device, but we want
+ // to avoid enumerating or otherwise calling into real capture devices.
+ command_line->AppendSwitchASCII(switches::kUseFakeDeviceForMediaStream,
+ "device-count=0");
+ command_line->AppendSwitch(switches::kUseFakeUIForMediaStream);
+ }
+
+ void Initialize() {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+
+ ASSERT_TRUE(embedded_test_server()->InitializeAndListen());
+ embedded_test_server()->StartAcceptingConnections();
+
+ auto* connection = content::ServiceManagerConnection::GetForProcess();
+ ASSERT_TRUE(connection);
+ auto* connector = connection->GetConnector();
+ ASSERT_TRUE(connector);
+ connector_ = connector->Clone();
+ }
+
+ std::unique_ptr<service_manager::Connector> connector_;
+ std::map<std::string, video_capture::mojom::TextureVirtualDevicePtr>
+ virtual_devices_by_id_;
+
+ private:
+ base::test::ScopedFeatureList scoped_feature_list_;
+ video_capture::mojom::DeviceFactoryProviderPtr provider_;
+ video_capture::mojom::DeviceFactoryPtr factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebRtcVideoCaptureServiceEnumerationBrowserTest);
+};
+
+IN_PROC_BROWSER_TEST_F(WebRtcVideoCaptureServiceEnumerationBrowserTest,
+ SingleAddedVirtualDeviceGetsEnumerated) {
+ Initialize();
+ ConnectToService();
+
+ // Exercise
+ // TODO(chfremer): It is probably not guaranteed that the Mojo IPC call to
+ // AddVirtualDevice arrives at the service before the request to enumerate
+ // devices triggered by JavaScript. To guarantee this, we would have to add
+ // a done-callback to AddVirtualDevice() and wait for that to arrive before
+ // doing the enumeration.
+ AddVirtualDevice("test");
+ EnumerateDevicesInRendererAndVerifyDeviceCount(1);
+
+ // Tear down
+ RemoveVirtualDevice("test");
+ DisconnectFromService();
+}
+
+IN_PROC_BROWSER_TEST_F(WebRtcVideoCaptureServiceEnumerationBrowserTest,
+ RemoveVirtualDeviceAfterItHasBeenEnumerated) {
+ // TODO(chfremer): Remove this when https://crbug.com/876892 is resolved.
+ if (base::FeatureList::IsEnabled(features::kMediaDevicesSystemMonitorCache)) {
+ LOG(WARNING) << "Skipping test, because feature not yet supported when "
+ "device monitoring is enabled.";
+ return;
+ }
+ Initialize();
+ ConnectToService();
+
+ AddVirtualDevice("test_1");
+ AddVirtualDevice("test_2");
+ EnumerateDevicesInRendererAndVerifyDeviceCount(2);
+ RemoveVirtualDevice("test_1");
+ EnumerateDevicesInRendererAndVerifyDeviceCount(1);
+ RemoveVirtualDevice("test_2");
+ EnumerateDevicesInRendererAndVerifyDeviceCount(0);
+
+ // Tear down
+ DisconnectFromService();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/webrtc/webrtc_webcam_browsertest.cc b/chromium/content/browser/webrtc/webrtc_webcam_browsertest.cc
index 867d6dd33cb..353cc98189d 100644
--- a/chromium/content/browser/webrtc/webrtc_webcam_browsertest.cc
+++ b/chromium/content/browser/webrtc/webrtc_webcam_browsertest.cc
@@ -5,6 +5,7 @@
#include "content/browser/webrtc/webrtc_webcam_browsertest.h"
#include "base/command_line.h"
+#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "content/browser/web_contents/web_contents_impl.h"
@@ -32,9 +33,7 @@ bool IsUseFakeDeviceForMediaStream(const base::CommandLine::StringType& arg) {
void RemoveFakeDeviceFromCommandLine(base::CommandLine* command_line) {
base::CommandLine::StringVector argv = command_line->argv();
- argv.erase(std::remove_if(argv.begin(), argv.end(),
- IsUseFakeDeviceForMediaStream),
- argv.end());
+ base::EraseIf(argv, IsUseFakeDeviceForMediaStream);
command_line->InitFromArgv(argv);
}
diff --git a/chromium/content/browser/websockets/websocket_manager.cc b/chromium/content/browser/websockets/websocket_manager.cc
index 13db9a3a2df..3f51142864c 100644
--- a/chromium/content/browser/websockets/websocket_manager.cc
+++ b/chromium/content/browser/websockets/websocket_manager.cc
@@ -14,11 +14,13 @@
#include "base/memory/ptr_util.h"
#include "base/memory/weak_ptr.h"
#include "base/numerics/safe_conversions.h"
+#include "base/task/post_task.h"
#include "content/browser/bad_message.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/ssl/ssl_error_handler.h"
#include "content/browser/ssl/ssl_manager.h"
#include "content/browser/websockets/websocket_handshake_request_info_impl.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
@@ -194,8 +196,8 @@ void WebSocketManager::CreateWebSocket(
DCHECK(handle->manager());
}
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&WebSocketManager::DoCreateWebSocket,
base::Unretained(handle->manager()), frame_id,
std::move(origin), std::move(request)));
@@ -210,8 +212,8 @@ WebSocketManager::WebSocketManager(int process_id,
// This unretained pointer is safe because we destruct a WebSocketManager
// only via WebSocketManager::Handle::RenderProcessHostDestroyed which
// posts a deletion task to the IO thread.
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&WebSocketManager::ObserveURLRequestContextGetter,
base::Unretained(this)));
}
diff --git a/chromium/content/browser/webui/shared_resources_data_source.cc b/chromium/content/browser/webui/shared_resources_data_source.cc
index b00558bd012..0e81e4c6244 100644
--- a/chromium/content/browser/webui/shared_resources_data_source.cc
+++ b/chromium/content/browser/webui/shared_resources_data_source.cc
@@ -13,7 +13,9 @@
#include "base/memory/ref_counted_memory.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
+#include "base/task/post_task.h"
#include "build/build_config.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_features.h"
@@ -25,6 +27,11 @@
#include "ui/resources/grit/webui_resources.h"
#include "ui/resources/grit/webui_resources_map.h"
+#if defined(OS_CHROMEOS)
+#include "chromeos/grit/chromeos_resources.h"
+#include "chromeos/grit/chromeos_resources_map.h"
+#endif
+
#if defined(OS_WIN)
#include "base/strings/utf_string_conversions.h"
#endif
@@ -39,7 +46,7 @@ struct IdrGzipped {
};
using ResourcesMap = base::hash_map<std::string, IdrGzipped>;
-const std::map<std::string, std::string> CreateAliasesMap() {
+const std::map<std::string, std::string> CreatePathPrefixAliasesMap() {
// TODO(rkc): Once we have a separate source for apps, remove '*/apps/'
// aliases.
std::map<std::string, std::string> aliases = {
@@ -62,6 +69,28 @@ const std::map<std::string, std::string> CreateAliasesMap() {
return aliases;
}
+const std::map<int, std::string> CreateMojoResourceIdToAliasMap() {
+ return std::map<int, std::string> {
+ {IDR_MOJO_MOJO_BINDINGS_JS, "js/mojo_bindings.js"},
+#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)
+ {IDR_MOJO_TIME_MOJOM_JS, "js/time.mojom.js"},
+#endif // defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)
+ };
+}
+
+#if defined(OS_CHROMEOS)
+const std::map<int, std::string> CreateChromeosMojoResourceIdToAliasMap() {
+ return std::map<int, std::string>{
+ {IDR_MULTIDEVICE_DEVICE_SYNC_MOJOM_JS,
+ "js/chromeos/device_sync.mojom.js"},
+ {IDR_MULTIDEVICE_MULTIDEVICE_SETUP_MOJOM_JS,
+ "js/chromeos/multidevice_setup.mojom.js"},
+ {IDR_MULTIDEVICE_MULTIDEVICE_SETUP_CONSTANTS_MOJOM_JS,
+ "js/chromeos/multidevice_setup_constants.mojom.js"},
+ };
+}
+#endif // !defined(OS_CHROMEOS)
+
#if !defined(OS_ANDROID)
bool ShouldIgnore(std::string resource) {
if (base::FeatureList::IsEnabled(features::kWebUIPolymer2) &&
@@ -93,10 +122,10 @@ void AddResource(const std::string& path,
NOTREACHED() << "Redefinition of '" << path << "'";
}
-const ResourcesMap* CreateResourcesMap() {
- std::map<std::string, std::string> aliases = CreateAliasesMap();
+void AddResourcesToMap(ResourcesMap* resources_map) {
+ const std::map<std::string, std::string> aliases =
+ CreatePathPrefixAliasesMap();
- ResourcesMap* result = new ResourcesMap();
for (size_t i = 0; i < kWebuiResourcesSize; ++i) {
const auto& resource = kWebuiResources[i];
@@ -105,25 +134,48 @@ const ResourcesMap* CreateResourcesMap() {
continue;
#endif // !defined(OS_ANDROID)
- AddResource(resource.name, resource.value, resource.gzipped, result);
+ AddResource(resource.name, resource.value, resource.gzipped, resources_map);
for (auto it = aliases.begin(); it != aliases.end(); ++it) {
if (base::StartsWith(resource.name, it->first,
base::CompareCase::SENSITIVE)) {
std::string resource_name(resource.name);
AddResource(it->second + resource_name.substr(it->first.length()),
- resource.value, resource.gzipped, result);
+ resource.value, resource.gzipped, resources_map);
}
}
}
- for (size_t i = 0; i < kMojoBindingsResourcesSize; ++i) {
- const auto& resource = kMojoBindingsResources[i];
- if (resource.value == IDR_MOJO_BINDINGS_JS) {
- AddResource("js/mojo_bindings.js", resource.value, resource.gzipped,
- result);
- break;
- }
+}
+
+// Adds |resources| to |resources_map|, but renames each resource according to
+// the scheme in |resource_aliases|, which maps from resource ID to resource
+// alias. Note that resources which do not have an alias will not be added.
+void AddAliasedResourcesToMap(
+ const std::map<int, std::string>& resource_aliases,
+ const GzippedGritResourceMap resources[],
+ size_t resources_size,
+ ResourcesMap* resources_map) {
+ for (size_t i = 0; i < resources_size; ++i) {
+ const auto& resource = resources[i];
+
+ const auto it = resource_aliases.find(resource.value);
+ if (it == resource_aliases.end())
+ continue;
+
+ AddResource(it->second, resource.value, resource.gzipped, resources_map);
}
+}
+
+const ResourcesMap* CreateResourcesMap() {
+ ResourcesMap* result = new ResourcesMap();
+ AddResourcesToMap(result);
+ AddAliasedResourcesToMap(CreateMojoResourceIdToAliasMap(),
+ kMojoBindingsResources, kMojoBindingsResourcesSize,
+ result);
+#if defined(OS_CHROMEOS)
+ AddAliasedResourcesToMap(CreateChromeosMojoResourceIdToAliasMap(),
+ kChromeosResources, kChromeosResourcesSize, result);
+#endif // !defined(OS_CHROMEOS)
return result;
}
@@ -227,7 +279,7 @@ SharedResourcesDataSource::TaskRunnerForRequestPath(
idr == IDR_WEBUI_CSS_TEXT_DEFAULTS_MD) {
// Use UI thread to load CSS since its construction touches non-thread-safe
// gfx::Font names in ui::ResourceBundle.
- return BrowserThread::GetTaskRunnerForThread(BrowserThread::UI);
+ return base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::UI});
}
return nullptr;
diff --git a/chromium/content/browser/webui/url_data_manager.cc b/chromium/content/browser/webui/url_data_manager.cc
index fca1d4aa616..a9f5cfc95d4 100644
--- a/chromium/content/browser/webui/url_data_manager.cc
+++ b/chromium/content/browser/webui/url_data_manager.cc
@@ -15,11 +15,14 @@
#include "base/memory/ref_counted_memory.h"
#include "base/strings/string_util.h"
#include "base/synchronization/lock.h"
+#include "base/task/post_task.h"
+#include "base/thread_annotations.h"
#include "content/browser/resource_context_impl.h"
#include "content/browser/webui/url_data_manager_backend.h"
#include "content/browser/webui/url_data_source_impl.h"
#include "content/browser/webui/web_ui_data_source_impl.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/url_data_source.h"
@@ -59,7 +62,8 @@ static void UpdateWebUIDataSourceOnIOThread(
} // namespace
// static
-URLDataManager::URLDataSources* URLDataManager::data_sources_ = nullptr;
+URLDataManager::URLDataSources* URLDataManager::data_sources_ PT_GUARDED_BY(
+ g_delete_lock.Get()) = nullptr;
URLDataManager::URLDataManager(BrowserContext* browser_context)
: browser_context_(browser_context) {
@@ -70,18 +74,19 @@ URLDataManager::~URLDataManager() {
void URLDataManager::AddDataSource(URLDataSourceImpl* source) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::BindOnce(&AddDataSourceOnIOThread,
- browser_context_->GetResourceContext(),
- base::WrapRefCounted(source)));
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(&AddDataSourceOnIOThread,
+ browser_context_->GetResourceContext(),
+ base::WrapRefCounted(source)));
}
void URLDataManager::UpdateWebUIDataSource(
const std::string& source_name,
std::unique_ptr<base::DictionaryValue> update) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&UpdateWebUIDataSourceOnIOThread,
browser_context_->GetResourceContext(), source_name,
base::Owned(update.release())));
@@ -122,8 +127,9 @@ void URLDataManager::DeleteDataSource(const URLDataSourceImpl* data_source) {
}
if (schedule_delete) {
// Schedule a task to delete the DataSource back on the UI thread.
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(&URLDataManager::DeleteDataSources));
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(&URLDataManager::DeleteDataSources));
}
}
diff --git a/chromium/content/browser/webui/url_data_manager_backend.cc b/chromium/content/browser/webui/url_data_manager_backend.cc
index 9a2cb49cf5a..9df29806e05 100644
--- a/chromium/content/browser/webui/url_data_manager_backend.cc
+++ b/chromium/content/browser/webui/url_data_manager_backend.cc
@@ -28,6 +28,7 @@
#include "content/browser/webui/url_data_source_impl.h"
#include "content/browser/webui/web_ui_data_source_impl.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/render_process_host.h"
@@ -195,8 +196,8 @@ void URLRequestChromeJob::Start() {
// TODO(caseq): Fix the race condition and remove this thread hop in
// https://crbug.com/616641.
if (url.SchemeIs(kChromeDevToolsScheme)) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
base::BindOnce(&URLRequestChromeJob::DelayStartForDevTools,
weak_factory_.GetWeakPtr()));
return;
@@ -338,8 +339,8 @@ int URLRequestChromeJob::PostReadTask(scoped_refptr<net::IOBuffer> buf,
void URLRequestChromeJob::DelayStartForDevTools(
const base::WeakPtr<URLRequestChromeJob>& job) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&URLRequestChromeJob::StartAsync, job));
}
@@ -444,7 +445,7 @@ void URLDataManagerBackend::AddDataSource(
URLDataSourceImpl* source) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (!source->source()->ShouldReplaceExistingSource()) {
- DataSourceMap::iterator i = data_sources_.find(source->source_name());
+ auto i = data_sources_.find(source->source_name());
if (i != data_sources_.end())
return;
}
@@ -455,7 +456,7 @@ void URLDataManagerBackend::AddDataSource(
void URLDataManagerBackend::UpdateWebUIDataSource(
const std::string& source_name,
const base::DictionaryValue& update) {
- DataSourceMap::iterator it = data_sources_.find(source_name);
+ auto it = data_sources_.find(source_name);
if (it == data_sources_.end() || !it->second->IsWebUIDataSourceImpl()) {
NOTREACHED();
return;
@@ -466,8 +467,7 @@ void URLDataManagerBackend::UpdateWebUIDataSource(
bool URLDataManagerBackend::HasPendingJob(
URLRequestChromeJob* job) const {
- for (PendingRequestMap::const_iterator i = pending_requests_.begin();
- i != pending_requests_.end(); ++i) {
+ for (auto i = pending_requests_.begin(); i != pending_requests_.end(); ++i) {
if (i->second == job)
return true;
}
@@ -539,7 +539,7 @@ URLDataSourceImpl* URLDataManagerBackend::GetDataSourceFromURL(
const GURL& url) {
// The input usually looks like: chrome://source_name/extra_bits?foo
// so do a lookup using the host of the URL.
- DataSourceMap::iterator i = data_sources_.find(url.host());
+ auto i = data_sources_.find(url.host());
if (i != data_sources_.end())
return i->second.get();
@@ -568,8 +568,7 @@ void URLDataManagerBackend::RemoveRequest(URLRequestChromeJob* job) {
// Remove the request from our list of pending requests.
// If/when the source sends the data that was requested, the data will just
// be thrown away.
- for (PendingRequestMap::iterator i = pending_requests_.begin();
- i != pending_requests_.end(); ++i) {
+ for (auto i = pending_requests_.begin(); i != pending_requests_.end(); ++i) {
if (i->second == job) {
pending_requests_.erase(i);
return;
@@ -580,7 +579,7 @@ void URLDataManagerBackend::RemoveRequest(URLRequestChromeJob* job) {
void URLDataManagerBackend::DataAvailable(RequestID request_id,
base::RefCountedMemory* bytes) {
// Forward this data on to the pending net::URLRequest, if it exists.
- PendingRequestMap::iterator i = pending_requests_.find(request_id);
+ auto i = pending_requests_.find(request_id);
if (i != pending_requests_.end()) {
URLRequestChromeJob* job = i->second;
pending_requests_.erase(i);
diff --git a/chromium/content/browser/webui/url_data_source_impl.cc b/chromium/content/browser/webui/url_data_source_impl.cc
index 1a38e0b9c1d..13953766bf6 100644
--- a/chromium/content/browser/webui/url_data_source_impl.cc
+++ b/chromium/content/browser/webui/url_data_source_impl.cc
@@ -9,7 +9,9 @@
#include "base/bind.h"
#include "base/memory/ref_counted_memory.h"
#include "base/strings/string_util.h"
+#include "base/task/post_task.h"
#include "content/browser/webui/url_data_manager_backend.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/url_data_source.h"
@@ -39,8 +41,8 @@ void URLDataSourceImpl::SendResponse(
// when the object is deleted.
return;
}
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&URLDataSourceImpl::SendResponseOnIOThread, this,
request_id, std::move(bytes)));
}
diff --git a/chromium/content/browser/webui/web_ui_message_handler_unittest.cc b/chromium/content/browser/webui/web_ui_message_handler_unittest.cc
index e940e5c9395..ba1bb02755b 100644
--- a/chromium/content/browser/webui/web_ui_message_handler_unittest.cc
+++ b/chromium/content/browser/webui/web_ui_message_handler_unittest.cc
@@ -14,10 +14,13 @@ namespace content {
TEST(WebUIMessageHandlerTest, ExtractIntegerValue) {
base::ListValue list;
- int value, zero_value = 0, neg_value = -1234, pos_value = 1234;
- base::string16 zero_string(base::UTF8ToUTF16("0"));
- base::string16 neg_string(base::UTF8ToUTF16("-1234"));
- base::string16 pos_string(base::UTF8ToUTF16("1234"));
+ int value;
+ constexpr int zero_value = 0;
+ constexpr int neg_value = -1234;
+ constexpr int pos_value = 1234;
+ static const char zero_string[] = "0";
+ static const char neg_string[] = "-1234";
+ static const char pos_string[] = "1234";
list.AppendInteger(zero_value);
EXPECT_TRUE(WebUIMessageHandler::ExtractIntegerValue(&list, &value));
@@ -51,10 +54,13 @@ TEST(WebUIMessageHandlerTest, ExtractIntegerValue) {
TEST(WebUIMessageHandlerTest, ExtractDoubleValue) {
base::ListValue list;
- double value, zero_value = 0.0, neg_value = -1234.5, pos_value = 1234.5;
- base::string16 zero_string(base::UTF8ToUTF16("0"));
- base::string16 neg_string(base::UTF8ToUTF16("-1234.5"));
- base::string16 pos_string(base::UTF8ToUTF16("1234.5"));
+ double value;
+ constexpr double zero_value = 0.0;
+ constexpr double neg_value = -1234.5;
+ constexpr double pos_value = 1234.5;
+ static const char zero_string[] = "0";
+ static const char neg_string[] = "-1234.5";
+ static const char pos_string[] = "1234.5";
list.AppendDouble(zero_value);
EXPECT_TRUE(WebUIMessageHandler::ExtractDoubleValue(&list, &value));
@@ -88,19 +94,16 @@ TEST(WebUIMessageHandlerTest, ExtractDoubleValue) {
TEST(WebUIMessageHandlerTest, ExtractStringValue) {
base::ListValue list;
- base::string16 in_string(base::UTF8ToUTF16(
- "The facts, though interesting, are irrelevant."));
+ static const char in_string[] =
+ "The facts, though interesting, are irrelevant.";
list.AppendString(in_string);
base::string16 out_string = WebUIMessageHandler::ExtractStringValue(&list);
- EXPECT_EQ(in_string, out_string);
+ EXPECT_EQ(base::ASCIIToUTF16(in_string), out_string);
}
class TestWebUIMessageHandler : public WebUIMessageHandler {
public:
- TestWebUIMessageHandler()
- : on_javascript_allowed_calls_(0), on_javascript_disallowed_calls_(0) {
- set_web_ui(&test_web_ui_);
- }
+ TestWebUIMessageHandler() { set_web_ui(&test_web_ui_); }
~TestWebUIMessageHandler() override {
// The test handler unusually owns its own TestWebUI, so we make sure to
@@ -121,8 +124,8 @@ class TestWebUIMessageHandler : public WebUIMessageHandler {
void OnJavascriptAllowed() override { ++on_javascript_allowed_calls_; }
void OnJavascriptDisallowed() override { ++on_javascript_disallowed_calls_; }
- int on_javascript_allowed_calls_;
- int on_javascript_disallowed_calls_;
+ int on_javascript_allowed_calls_ = 0;
+ int on_javascript_disallowed_calls_ = 0;
};
TEST(WebUIMessageHandlerTest, AllowAndDisallowJavascript) {
diff --git a/chromium/content/browser/webui/web_ui_mojo_browsertest.cc b/chromium/content/browser/webui/web_ui_mojo_browsertest.cc
index 3f4031598fa..0425adabad2 100644
--- a/chromium/content/browser/webui/web_ui_mojo_browsertest.cc
+++ b/chromium/content/browser/webui/web_ui_mojo_browsertest.cc
@@ -110,10 +110,23 @@ class TestWebUIController : public WebUIController {
int bindings = BINDINGS_POLICY_MOJO_WEB_UI)
: WebUIController(web_ui), run_loop_(run_loop) {
web_ui->SetBindings(bindings);
- WebUIDataSource* data_source = WebUIDataSource::Create("mojo-web-ui");
- data_source->SetRequestFilter(base::Bind(&GetResource));
- WebUIDataSource::Add(web_ui->GetWebContents()->GetBrowserContext(),
- data_source);
+ {
+ WebUIDataSource* data_source = WebUIDataSource::Create("mojo-web-ui");
+ data_source->SetRequestFilter(base::BindRepeating(&GetResource));
+ WebUIDataSource::Add(web_ui->GetWebContents()->GetBrowserContext(),
+ data_source);
+ }
+ {
+ WebUIDataSource* data_source = WebUIDataSource::Create("dummy-web-ui");
+ data_source->SetRequestFilter(base::BindRepeating(
+ [](const std::string& id,
+ const WebUIDataSource::GotDataCallback& callback) {
+ callback.Run(new base::RefCountedString);
+ return true;
+ }));
+ WebUIDataSource::Add(web_ui->GetWebContents()->GetBrowserContext(),
+ data_source);
+ }
}
protected:
@@ -246,9 +259,9 @@ class WebUIMojoTest : public ContentBrowserTest {
TestWebUIControllerFactory* factory() { return &factory_; }
void NavigateWithNewWebUI(const std::string& path) {
- // Load an invalid URL first so that a new WebUI is set up when we load
+ // Load a dummy WebUI URL first so that a new WebUI is set up when we load
// the URL we're actually interested in.
- EXPECT_FALSE(NavigateToURL(shell(), GURL()));
+ EXPECT_TRUE(NavigateToURL(shell(), GURL("chrome://dummy-web-ui")));
constexpr char kChromeUIMojoWebUIOrigin[] = "chrome://mojo-web-ui/";
EXPECT_TRUE(NavigateToURL(shell(), GURL(kChromeUIMojoWebUIOrigin + 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 a0e39809838..63fe0125ca1 100644
--- a/chromium/content/browser/webui/web_ui_url_loader_factory.cc
+++ b/chromium/content/browser/webui/web_ui_url_loader_factory.cc
@@ -24,6 +24,7 @@
#include "content/browser/webui/url_data_manager_backend.h"
#include "content/browser/webui/url_data_source_impl.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h"
@@ -270,8 +271,8 @@ class WebUIURLLoaderFactory : public network::mojom::URLLoaderFactory,
}
if (request.url.host_piece() == kChromeUIBlobInternalsHost) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(&StartBlobInternalsURLLoader, request,
client.PassInterface(),
base::Unretained(ChromeBlobStorageContext::GetFor(
@@ -289,8 +290,8 @@ class WebUIURLLoaderFactory : public network::mojom::URLLoaderFactory,
// from frames can happen while the RFH is changed for a cross-process
// navigation. The URLDataSources just need the WebContents; the specific
// frame doesn't matter.
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&StartURLLoader, request, render_frame_host_->GetFrameTreeNodeId(),
client.PassInterface(),