summaryrefslogtreecommitdiff
path: root/chromium/content/browser
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2017-11-20 10:33:36 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2017-11-22 11:45:12 +0000
commitbe59a35641616a4cf23c4a13fa0632624b021c1b (patch)
tree9da183258bdf9cc413f7562079d25ace6955467f /chromium/content/browser
parentd702e4b6a64574e97fc7df8fe3238cde70242080 (diff)
downloadqtwebengine-chromium-be59a35641616a4cf23c4a13fa0632624b021c1b.tar.gz
BASELINE: Update Chromium to 62.0.3202.101
Change-Id: I2d5eca8117600df6d331f6166ab24d943d9814ac Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Diffstat (limited to 'chromium/content/browser')
-rw-r--r--chromium/content/browser/BUILD.gn136
-rw-r--r--chromium/content/browser/DEPS17
-rw-r--r--chromium/content/browser/accessibility/OWNERS4
-rw-r--r--chromium/content/browser/accessibility/accessibility_action_browsertest.cc39
-rw-r--r--chromium/content/browser/accessibility/accessibility_event_recorder_win.cc12
-rw-r--r--chromium/content/browser/accessibility/accessibility_ipc_error_browsertest.cc17
-rw-r--r--chromium/content/browser/accessibility/accessibility_mode_browsertest.cc35
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter_android.cc3
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter_mac.mm3
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter_utils_win.cc521
-rw-r--r--chromium/content/browser/accessibility/accessibility_ui.cc70
-rw-r--r--chromium/content/browser/accessibility/accessibility_win_browsertest.cc75
-rw-r--r--chromium/content/browser/accessibility/android_granularity_movement_browsertest.cc6
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility.cc33
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility.h3
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_android.cc139
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_android.h12
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_auralinux.cc2
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_cocoa.h29
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_cocoa.mm221
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_com_win.cc561
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_com_win.h195
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_event.cc1
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_event_win.cc3
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_mac_unittest.mm109
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager.cc25
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager.h28
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_android.cc35
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_mac.h13
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_mac.mm92
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_win.cc136
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_win.h15
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_state_impl.cc39
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_state_impl.h17
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_win.cc1
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_win_unittest.cc43
-rw-r--r--chromium/content/browser/accessibility/cross_platform_accessibility_browsertest.cc8
-rw-r--r--chromium/content/browser/accessibility/dump_accessibility_browsertest_base.cc6
-rw-r--r--chromium/content/browser/accessibility/dump_accessibility_events_browsertest.cc4
-rw-r--r--chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc36
-rw-r--r--chromium/content/browser/accessibility/hit_testing_browsertest.cc22
-rw-r--r--chromium/content/browser/accessibility/one_shot_accessibility_tree_search.cc14
-rw-r--r--chromium/content/browser/accessibility/one_shot_accessibility_tree_search_unittest.cc3
-rw-r--r--chromium/content/browser/accessibility/site_per_process_accessibility_browsertest.cc2
-rw-r--r--chromium/content/browser/accessibility/touch_accessibility_aura_browsertest.cc6
-rw-r--r--chromium/content/browser/accessibility/web_contents_accessibility_android.cc140
-rw-r--r--chromium/content/browser/accessibility/web_contents_accessibility_android.h34
-rw-r--r--chromium/content/browser/after_startup_task_utils.cc25
-rw-r--r--chromium/content/browser/after_startup_task_utils.h21
-rw-r--r--chromium/content/browser/android/app_web_message_port.cc30
-rw-r--r--chromium/content/browser/android/app_web_message_port.h2
-rw-r--r--chromium/content/browser/android/background_sync_network_observer_android.cc6
-rw-r--r--chromium/content/browser/android/background_sync_network_observer_android.h2
-rw-r--r--chromium/content/browser/android/browser_startup_controller.cc4
-rw-r--r--chromium/content/browser/android/browser_startup_controller.h4
-rw-r--r--chromium/content/browser/android/content_feature_list.cc4
-rw-r--r--chromium/content/browser/android/content_feature_list.h4
-rw-r--r--chromium/content/browser/android/content_video_view.cc4
-rw-r--r--chromium/content/browser/android/content_video_view.h2
-rw-r--r--chromium/content/browser/android/content_view_core.cc71
-rw-r--r--chromium/content/browser/android/content_view_core.h14
-rw-r--r--chromium/content/browser/android/content_view_core_observer.h3
-rw-r--r--chromium/content/browser/android/content_view_render_view.cc5
-rw-r--r--chromium/content/browser/android/content_view_render_view.h3
-rw-r--r--chromium/content/browser/android/content_view_statics.cc9
-rw-r--r--chromium/content/browser/android/content_view_statics.h14
-rw-r--r--chromium/content/browser/android/date_time_chooser_android.cc7
-rw-r--r--chromium/content/browser/android/date_time_chooser_android.h3
-rw-r--r--chromium/content/browser/android/dialog_overlay_impl.cc88
-rw-r--r--chromium/content/browser/android/dialog_overlay_impl.h20
-rw-r--r--chromium/content/browser/android/gpu_process_callback.cc6
-rw-r--r--chromium/content/browser/android/gpu_process_callback.h16
-rw-r--r--chromium/content/browser/android/ime_adapter_android.cc81
-rw-r--r--chromium/content/browser/android/ime_adapter_android.h6
-rw-r--r--chromium/content/browser/android/interstitial_page_delegate_android.cc6
-rw-r--r--chromium/content/browser/android/interstitial_page_delegate_android.h2
-rw-r--r--chromium/content/browser/android/java/gin_java_bridge_dispatcher_host.cc12
-rw-r--r--chromium/content/browser/android/java/gin_java_bridge_dispatcher_host.h2
-rw-r--r--chromium/content/browser/android/java_interfaces_impl.cc4
-rw-r--r--chromium/content/browser/android/load_url_params.cc6
-rw-r--r--chromium/content/browser/android/load_url_params.h16
-rw-r--r--chromium/content/browser/android/nfc_host.cc2
-rw-r--r--chromium/content/browser/android/overscroll_controller_android.cc102
-rw-r--r--chromium/content/browser/android/overscroll_controller_android.h18
-rw-r--r--chromium/content/browser/android/overscroll_controller_android_unittest.cc210
-rw-r--r--chromium/content/browser/android/popup_zoomer.cc105
-rw-r--r--chromium/content/browser/android/popup_zoomer.h57
-rw-r--r--chromium/content/browser/android/selection_popup_controller.cc4
-rw-r--r--chromium/content/browser/android/selection_popup_controller.h2
-rw-r--r--chromium/content/browser/android/smart_selection_client.cc4
-rw-r--r--chromium/content/browser/android/smart_selection_client.h2
-rw-r--r--chromium/content/browser/android/string_message_codec.cc17
-rw-r--r--chromium/content/browser/android/string_message_codec.h9
-rw-r--r--chromium/content/browser/android/string_message_codec_unittest.cc23
-rw-r--r--chromium/content/browser/android/synchronous_compositor_host.cc2
-rw-r--r--chromium/content/browser/android/synchronous_compositor_host.h2
-rw-r--r--chromium/content/browser/android/text_suggestion_host_android.cc198
-rw-r--r--chromium/content/browser/android/text_suggestion_host_android.h100
-rw-r--r--chromium/content/browser/android/text_suggestion_host_mojo_impl_android.cc38
-rw-r--r--chromium/content/browser/android/text_suggestion_host_mojo_impl_android.h39
-rw-r--r--chromium/content/browser/android/tracing_controller_android.cc4
-rw-r--r--chromium/content/browser/android/tracing_controller_android.h3
-rw-r--r--chromium/content/browser/android/web_contents_observer_proxy.cc9
-rw-r--r--chromium/content/browser/android/web_contents_observer_proxy.h4
-rw-r--r--chromium/content/browser/appcache/appcache_backend_impl.cc21
-rw-r--r--chromium/content/browser/appcache/appcache_backend_impl.h9
-rw-r--r--chromium/content/browser/appcache/appcache_browsertest.cc107
-rw-r--r--chromium/content/browser/appcache/appcache_disk_cache.cc34
-rw-r--r--chromium/content/browser/appcache/appcache_disk_cache.h18
-rw-r--r--chromium/content/browser/appcache/appcache_disk_cache_unittest.cc45
-rw-r--r--chromium/content/browser/appcache/appcache_dispatcher_host.cc27
-rw-r--r--chromium/content/browser/appcache/appcache_dispatcher_host.h3
-rw-r--r--chromium/content/browser/appcache/appcache_host.cc25
-rw-r--r--chromium/content/browser/appcache/appcache_host.h14
-rw-r--r--chromium/content/browser/appcache/appcache_host_unittest.cc33
-rw-r--r--chromium/content/browser/appcache/appcache_interceptor.cc3
-rw-r--r--chromium/content/browser/appcache/appcache_internals_ui.cc43
-rw-r--r--chromium/content/browser/appcache/appcache_job.cc15
-rw-r--r--chromium/content/browser/appcache/appcache_job.h12
-rw-r--r--chromium/content/browser/appcache/appcache_manifest_parser.cc2
-rw-r--r--chromium/content/browser/appcache/appcache_manifest_parser_unittest.cc3
-rw-r--r--chromium/content/browser/appcache/appcache_navigation_handle.cc7
-rw-r--r--chromium/content/browser/appcache/appcache_quota_client.cc4
-rw-r--r--chromium/content/browser/appcache/appcache_quota_client.h2
-rw-r--r--chromium/content/browser/appcache/appcache_request.h2
-rw-r--r--chromium/content/browser/appcache/appcache_request_handler.cc94
-rw-r--r--chromium/content/browser/appcache/appcache_request_handler.h36
-rw-r--r--chromium/content/browser/appcache/appcache_request_handler_unittest.cc610
-rw-r--r--chromium/content/browser/appcache/appcache_response.cc4
-rw-r--r--chromium/content/browser/appcache/appcache_response_unittest.cc191
-rw-r--r--chromium/content/browser/appcache/appcache_service_impl.cc11
-rw-r--r--chromium/content/browser/appcache/appcache_service_impl.h24
-rw-r--r--chromium/content/browser/appcache/appcache_service_unittest.cc5
-rw-r--r--chromium/content/browser/appcache/appcache_storage_impl.cc110
-rw-r--r--chromium/content/browser/appcache/appcache_storage_impl.h24
-rw-r--r--chromium/content/browser/appcache/appcache_storage_impl_unittest.cc133
-rw-r--r--chromium/content/browser/appcache/appcache_subresource_url_factory.cc65
-rw-r--r--chromium/content/browser/appcache/appcache_subresource_url_factory.h45
-rw-r--r--chromium/content/browser/appcache/appcache_update_job.cc416
-rw-r--r--chromium/content/browser/appcache/appcache_update_job.h63
-rw-r--r--chromium/content/browser/appcache/appcache_update_job_unittest.cc688
-rw-r--r--chromium/content/browser/appcache/appcache_update_request_base.cc71
-rw-r--r--chromium/content/browser/appcache/appcache_update_request_base.h96
-rw-r--r--chromium/content/browser/appcache/appcache_update_url_fetcher.cc252
-rw-r--r--chromium/content/browser/appcache/appcache_update_url_fetcher.h82
-rw-r--r--chromium/content/browser/appcache/appcache_update_url_loader_request.cc237
-rw-r--r--chromium/content/browser/appcache/appcache_update_url_loader_request.h124
-rw-r--r--chromium/content/browser/appcache/appcache_update_url_request.cc126
-rw-r--r--chromium/content/browser/appcache/appcache_update_url_request.h69
-rw-r--r--chromium/content/browser/appcache/appcache_url_loader_job.cc102
-rw-r--r--chromium/content/browser/appcache/appcache_url_loader_job.h47
-rw-r--r--chromium/content/browser/appcache/appcache_url_loader_request.cc14
-rw-r--r--chromium/content/browser/appcache/appcache_url_loader_request.h2
-rw-r--r--chromium/content/browser/appcache/appcache_url_request.cc4
-rw-r--r--chromium/content/browser/appcache/appcache_url_request.h2
-rw-r--r--chromium/content/browser/appcache/appcache_url_request_job.cc10
-rw-r--r--chromium/content/browser/appcache/appcache_url_request_job.h6
-rw-r--r--chromium/content/browser/appcache/appcache_url_request_job_unittest.cc44
-rw-r--r--chromium/content/browser/appcache/chrome_appcache_service.cc3
-rw-r--r--chromium/content/browser/appcache/chrome_appcache_service.h4
-rw-r--r--chromium/content/browser/appcache/chrome_appcache_service_unittest.cc8
-rw-r--r--chromium/content/browser/appcache/mock_appcache_service.cc4
-rw-r--r--chromium/content/browser/appcache/mock_appcache_storage.cc4
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_context.cc26
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_context.h12
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_cross_origin_filter_unittest.cc6
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_data_manager.cc286
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_data_manager.h35
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_data_manager_unittest.cc129
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_delegate_proxy.cc289
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_delegate_proxy.h44
-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_embedded_worker_test_helper.h12
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_event_dispatcher.cc35
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_event_dispatcher.h2
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_event_dispatcher_unittest.cc54
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_job_controller.cc16
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_job_controller.h16
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_job_controller_unittest.cc19
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_registration_id.cc10
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_registration_id.h6
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_request_info.cc66
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_request_info.h41
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_response.cc23
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_response.h50
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_service_impl.cc58
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_service_impl.h18
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_service_unittest.cc169
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_test_base.cc12
-rw-r--r--chromium/content/browser/background_sync/background_sync_browsertest.cc1
-rw-r--r--chromium/content/browser/background_sync/background_sync_manager.cc7
-rw-r--r--chromium/content/browser/background_sync/background_sync_manager.h2
-rw-r--r--chromium/content/browser/background_sync/background_sync_manager_unittest.cc26
-rw-r--r--chromium/content/browser/background_sync/background_sync_service_impl.h4
-rw-r--r--chromium/content/browser/bad_message.cc7
-rw-r--r--chromium/content/browser/bad_message.h7
-rw-r--r--chromium/content/browser/blob_storage/blob_dispatcher_host.cc17
-rw-r--r--chromium/content/browser/blob_storage/blob_internals_url_loader.cc7
-rw-r--r--chromium/content/browser/blob_storage/blob_registry_wrapper.cc5
-rw-r--r--chromium/content/browser/blob_storage/blob_url_loader_factory.cc275
-rw-r--r--chromium/content/browser/blob_storage/blob_url_loader_factory.h9
-rw-r--r--chromium/content/browser/blob_storage/blob_url_unittest.cc12
-rw-r--r--chromium/content/browser/blob_storage/chrome_blob_storage_context.cc14
-rw-r--r--chromium/content/browser/bluetooth/bluetooth_device_chooser_controller.cc6
-rw-r--r--chromium/content/browser/bluetooth/web_bluetooth_service_impl.cc7
-rw-r--r--chromium/content/browser/bluetooth/web_bluetooth_service_impl.h2
-rw-r--r--chromium/content/browser/browser_associated_interface_unittest.cc4
-rw-r--r--chromium/content/browser/browser_child_process_host_impl.cc47
-rw-r--r--chromium/content/browser/browser_child_process_host_impl.h4
-rw-r--r--chromium/content/browser/browser_context.cc23
-rw-r--r--chromium/content/browser/browser_main_loop.cc129
-rw-r--r--chromium/content/browser/browser_main_loop.h6
-rw-r--r--chromium/content/browser/browser_main_loop_unittest.cc6
-rw-r--r--chromium/content/browser/browser_main_runner.cc12
-rw-r--r--chromium/content/browser/browser_plugin/browser_plugin_guest.cc65
-rw-r--r--chromium/content/browser/browser_plugin/browser_plugin_guest.h13
-rw-r--r--chromium/content/browser/browser_shutdown_profile_dumper.cc6
-rw-r--r--chromium/content/browser/browser_side_navigation_browsertest.cc2
-rw-r--r--chromium/content/browser/browser_thread_impl.cc2
-rw-r--r--chromium/content/browser/browser_thread_unittest.cc18
-rw-r--r--chromium/content/browser/browser_url_handler_impl.cc1
-rw-r--r--chromium/content/browser/browsing_data/browsing_data_remover_impl.cc3
-rw-r--r--chromium/content/browser/browsing_data/browsing_data_remover_impl_unittest.cc84
-rw-r--r--chromium/content/browser/browsing_data/clear_site_data_throttle.cc5
-rw-r--r--chromium/content/browser/browsing_data/clear_site_data_throttle_browsertest.cc23
-rw-r--r--chromium/content/browser/browsing_data/clear_site_data_throttle_unittest.cc55
-rw-r--r--chromium/content/browser/browsing_data/conditional_cache_deletion_helper.cc2
-rw-r--r--chromium/content/browser/browsing_data/conditional_cache_deletion_helper_browsertest.cc8
-rw-r--r--chromium/content/browser/browsing_data/storage_partition_http_cache_data_remover.cc7
-rw-r--r--chromium/content/browser/byte_stream.cc20
-rw-r--r--chromium/content/browser/byte_stream.h2
-rw-r--r--chromium/content/browser/cache_storage/cache_storage.cc16
-rw-r--r--chromium/content/browser/cache_storage/cache_storage.h12
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_blob_to_disk_cache_unittest.cc3
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_cache.cc88
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_cache.h9
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_cache_unittest.cc33
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_context_impl.cc15
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_context_impl.h21
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_manager.cc29
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_manager.h9
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_manager_unittest.cc153
-rw-r--r--chromium/content/browser/child_process_launcher.cc19
-rw-r--r--chromium/content/browser/child_process_launcher.h19
-rw-r--r--chromium/content/browser/child_process_launcher_helper.cc12
-rw-r--r--chromium/content/browser/child_process_launcher_helper.h21
-rw-r--r--chromium/content/browser/child_process_launcher_helper_android.cc28
-rw-r--r--chromium/content/browser/child_process_launcher_helper_android.h16
-rw-r--r--chromium/content/browser/child_process_launcher_helper_fuchsia.cc115
-rw-r--r--chromium/content/browser/child_process_launcher_helper_linux.cc17
-rw-r--r--chromium/content/browser/child_process_launcher_helper_mac.cc29
-rw-r--r--chromium/content/browser/child_process_launcher_helper_posix.cc8
-rw-r--r--chromium/content/browser/child_process_launcher_helper_posix.h4
-rw-r--r--chromium/content/browser/child_process_launcher_helper_win.cc6
-rw-r--r--chromium/content/browser/child_process_security_policy_impl.cc4
-rw-r--r--chromium/content/browser/child_process_security_policy_impl.h2
-rw-r--r--chromium/content/browser/child_process_security_policy_unittest.cc2
-rw-r--r--chromium/content/browser/compositor/DEPS14
-rw-r--r--chromium/content/browser/compositor/browser_compositor_output_surface.cc4
-rw-r--r--chromium/content/browser/compositor/browser_compositor_output_surface.h2
-rw-r--r--chromium/content/browser/compositor/gpu_browser_compositor_output_surface.cc4
-rw-r--r--chromium/content/browser/compositor/gpu_process_transport_factory.cc142
-rw-r--r--chromium/content/browser/compositor/gpu_process_transport_factory.h14
-rw-r--r--chromium/content/browser/compositor/gpu_vsync_begin_frame_source.cc55
-rw-r--r--chromium/content/browser/compositor/gpu_vsync_begin_frame_source.h19
-rw-r--r--chromium/content/browser/compositor/gpu_vsync_begin_frame_source_unittest.cc190
-rw-r--r--chromium/content/browser/compositor/reflector_impl.cc3
-rw-r--r--chromium/content/browser/compositor/reflector_impl_unittest.cc15
-rw-r--r--chromium/content/browser/compositor/software_browser_compositor_output_surface.cc10
-rw-r--r--chromium/content/browser/compositor/software_browser_compositor_output_surface_unittest.cc11
-rw-r--r--chromium/content/browser/compositor/software_output_device_ozone_unittest.cc3
-rw-r--r--chromium/content/browser/compositor/surface_utils.cc26
-rw-r--r--chromium/content/browser/compositor/surface_utils.h7
-rw-r--r--chromium/content/browser/cross_site_transfer_browsertest.cc10
-rw-r--r--chromium/content/browser/device_sensors/device_sensor_browsertest.cc312
-rw-r--r--chromium/content/browser/devtools/BUILD.gn2
-rw-r--r--chromium/content/browser/devtools/browser_devtools_agent_host.cc7
-rw-r--r--chromium/content/browser/devtools/devtools_agent_host_impl.cc42
-rw-r--r--chromium/content/browser/devtools/devtools_agent_host_impl.h4
-rw-r--r--chromium/content/browser/devtools/devtools_http_handler.cc182
-rw-r--r--chromium/content/browser/devtools/devtools_http_handler.h7
-rw-r--r--chromium/content/browser/devtools/devtools_http_handler_unittest.cc18
-rw-r--r--chromium/content/browser/devtools/devtools_io_context.cc437
-rw-r--r--chromium/content/browser/devtools/devtools_io_context.h70
-rw-r--r--chromium/content/browser/devtools/devtools_manager.cc14
-rw-r--r--chromium/content/browser/devtools/devtools_manager_unittest.cc22
-rw-r--r--chromium/content/browser/devtools/devtools_url_interceptor_request_job.cc144
-rw-r--r--chromium/content/browser/devtools/devtools_url_interceptor_request_job.h2
-rw-r--r--chromium/content/browser/devtools/devtools_url_request_interceptor.cc220
-rw-r--r--chromium/content/browser/devtools/devtools_url_request_interceptor.h63
-rw-r--r--chromium/content/browser/devtools/page_navigation_throttle.cc83
-rw-r--r--chromium/content/browser/devtools/page_navigation_throttle.h56
-rw-r--r--chromium/content/browser/devtools/protocol/browser_handler.cc38
-rw-r--r--chromium/content/browser/devtools/protocol/browser_handler.h37
-rw-r--r--chromium/content/browser/devtools/protocol/devtools_download_manager_delegate.cc186
-rw-r--r--chromium/content/browser/devtools/protocol/devtools_download_manager_delegate.h80
-rw-r--r--chromium/content/browser/devtools/protocol/devtools_download_manager_helper.cc47
-rw-r--r--chromium/content/browser/devtools/protocol/devtools_download_manager_helper.h53
-rw-r--r--chromium/content/browser/devtools/protocol/devtools_protocol_browsertest.cc1050
-rw-r--r--chromium/content/browser/devtools/protocol/emulation_handler.cc42
-rw-r--r--chromium/content/browser/devtools/protocol/emulation_handler.h5
-rw-r--r--chromium/content/browser/devtools/protocol/input_handler.cc315
-rw-r--r--chromium/content/browser/devtools/protocol/input_handler.h14
-rw-r--r--chromium/content/browser/devtools/protocol/io_handler.cc40
-rw-r--r--chromium/content/browser/devtools/protocol/io_handler.h5
-rw-r--r--chromium/content/browser/devtools/protocol/native_input_event_builder.h30
-rw-r--r--chromium/content/browser/devtools/protocol/native_input_event_builder_mac.mm49
-rw-r--r--chromium/content/browser/devtools/protocol/network_handler.cc542
-rw-r--r--chromium/content/browser/devtools/protocol/network_handler.h50
-rw-r--r--chromium/content/browser/devtools/protocol/page_handler.cc304
-rw-r--r--chromium/content/browser/devtools/protocol/page_handler.h35
-rw-r--r--chromium/content/browser/devtools/protocol/schema_handler.cc3
-rw-r--r--chromium/content/browser/devtools/protocol/security_handler.cc42
-rw-r--r--chromium/content/browser/devtools/protocol/security_handler.h1
-rw-r--r--chromium/content/browser/devtools/protocol/service_worker_handler.cc16
-rw-r--r--chromium/content/browser/devtools/protocol/storage_handler.cc154
-rw-r--r--chromium/content/browser/devtools/protocol/storage_handler.h18
-rw-r--r--chromium/content/browser/devtools/protocol/system_info_handler.cc14
-rw-r--r--chromium/content/browser/devtools/protocol/target_auto_attacher.cc12
-rw-r--r--chromium/content/browser/devtools/protocol/target_handler.cc2
-rw-r--r--chromium/content/browser/devtools/protocol/tethering_handler.cc52
-rw-r--r--chromium/content/browser/devtools/protocol/tracing_handler.cc76
-rw-r--r--chromium/content/browser/devtools/protocol/tracing_handler.h29
-rw-r--r--chromium/content/browser/devtools/protocol/tracing_handler_unittest.cc44
-rw-r--r--chromium/content/browser/devtools/protocol_config.json22
-rw-r--r--chromium/content/browser/devtools/protocol_string.cc12
-rw-r--r--chromium/content/browser/devtools/protocol_string.h7
-rw-r--r--chromium/content/browser/devtools/render_frame_devtools_agent_host.cc213
-rw-r--r--chromium/content/browser/devtools/render_frame_devtools_agent_host.h14
-rw-r--r--chromium/content/browser/devtools/service_worker_devtools_agent_host.cc23
-rw-r--r--chromium/content/browser/devtools/shared_worker_devtools_agent_host.cc5
-rw-r--r--chromium/content/browser/devtools/site_per_process_devtools_browsertest.cc5
-rw-r--r--chromium/content/browser/discardable_shared_memory_manager.cc17
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_area.cc25
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_area_unittest.cc9
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_browsertest.cc1
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_context_impl.cc48
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_context_wrapper.cc69
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_context_wrapper.h8
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_host.cc55
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_host.h13
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_message_filter.cc29
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_message_filter.h11
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_namespace.cc17
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_namespace.h2
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_session.cc17
-rw-r--r--chromium/content/browser/dom_storage/local_storage_context_mojo.cc135
-rw-r--r--chromium/content/browser/dom_storage/local_storage_context_mojo_unittest.cc220
-rw-r--r--chromium/content/browser/dom_storage/session_storage_database.cc6
-rw-r--r--chromium/content/browser/dom_storage/session_storage_namespace_impl.h3
-rw-r--r--chromium/content/browser/download/base_file.cc25
-rw-r--r--chromium/content/browser/download/base_file.h5
-rw-r--r--chromium/content/browser/download/docs/save-page-as.md8
-rw-r--r--chromium/content/browser/download/download_browsertest.cc161
-rw-r--r--chromium/content/browser/download/download_create_info.h4
-rw-r--r--chromium/content/browser/download/download_file.h19
-rw-r--r--chromium/content/browser/download/download_file_impl.cc387
-rw-r--r--chromium/content/browser/download/download_file_impl.h114
-rw-r--r--chromium/content/browser/download/download_file_unittest.cc2
-rw-r--r--chromium/content/browser/download/download_item_impl.cc129
-rw-r--r--chromium/content/browser/download/download_item_impl.h11
-rw-r--r--chromium/content/browser/download/download_item_impl_unittest.cc206
-rw-r--r--chromium/content/browser/download/download_job.cc31
-rw-r--r--chromium/content/browser/download/download_job_factory.cc11
-rw-r--r--chromium/content/browser/download/download_manager_impl.cc126
-rw-r--r--chromium/content/browser/download/download_manager_impl.h21
-rw-r--r--chromium/content/browser/download/download_manager_impl_unittest.cc14
-rw-r--r--chromium/content/browser/download/download_request_core.cc311
-rw-r--r--chromium/content/browser/download/download_request_core.h10
-rw-r--r--chromium/content/browser/download/download_request_handle.cc6
-rw-r--r--chromium/content/browser/download/download_resource_handler.cc18
-rw-r--r--chromium/content/browser/download/download_response_handler.cc71
-rw-r--r--chromium/content/browser/download/download_response_handler.h58
-rw-r--r--chromium/content/browser/download/download_stats.cc7
-rw-r--r--chromium/content/browser/download/download_stats.h5
-rw-r--r--chromium/content/browser/download/download_task_runner.cc33
-rw-r--r--chromium/content/browser/download/download_task_runner.h18
-rw-r--r--chromium/content/browser/download/download_utils.cc376
-rw-r--r--chromium/content/browser/download/download_utils.h43
-rw-r--r--chromium/content/browser/download/download_worker.cc37
-rw-r--r--chromium/content/browser/download/download_worker.h16
-rw-r--r--chromium/content/browser/download/drag_download_file.cc25
-rw-r--r--chromium/content/browser/download/drag_download_file_browsertest.cc2
-rw-r--r--chromium/content/browser/download/drag_download_util.cc10
-rw-r--r--chromium/content/browser/download/mhtml_generation_browsertest.cc38
-rw-r--r--chromium/content/browser/download/mhtml_generation_manager.cc20
-rw-r--r--chromium/content/browser/download/mock_download_file.cc21
-rw-r--r--chromium/content/browser/download/mock_download_file.h9
-rw-r--r--chromium/content/browser/download/parallel_download_job.cc16
-rw-r--r--chromium/content/browser/download/parallel_download_job_unittest.cc66
-rw-r--r--chromium/content/browser/download/resource_downloader.cc73
-rw-r--r--chromium/content/browser/download/resource_downloader.h73
-rw-r--r--chromium/content/browser/download/save_file.cc6
-rw-r--r--chromium/content/browser/download/save_file.h10
-rw-r--r--chromium/content/browser/download/save_file_manager.cc73
-rw-r--r--chromium/content/browser/download/save_file_manager.h8
-rw-r--r--chromium/content/browser/download/save_file_resource_handler.cc26
-rw-r--r--chromium/content/browser/download/save_package.cc87
-rw-r--r--chromium/content/browser/download/save_package.h4
-rw-r--r--chromium/content/browser/download/save_package_browsertest.cc2
-rw-r--r--chromium/content/browser/download/url_download_handler.cc19
-rw-r--r--chromium/content/browser/download/url_download_handler.h49
-rw-r--r--chromium/content/browser/download/url_downloader.cc37
-rw-r--r--chromium/content/browser/download/url_downloader.h24
-rw-r--r--chromium/content/browser/file_descriptor_info_impl.cc107
-rw-r--r--chromium/content/browser/fileapi/browser_file_system_helper.cc20
-rw-r--r--chromium/content/browser/fileapi/file_system_browsertest.cc2
-rw-r--r--chromium/content/browser/fileapi/file_system_operation_runner_unittest.cc10
-rw-r--r--chromium/content/browser/fileapi/fileapi_message_filter.cc17
-rw-r--r--chromium/content/browser/fileapi/fileapi_message_filter.h4
-rw-r--r--chromium/content/browser/fileapi/upload_file_system_file_element_reader.h4
-rw-r--r--chromium/content/browser/fileapi/upload_file_system_file_element_reader_unittest.cc7
-rw-r--r--chromium/content/browser/frame_host/cross_process_frame_connector.cc55
-rw-r--r--chromium/content/browser/frame_host/cross_process_frame_connector.h129
-rw-r--r--chromium/content/browser/frame_host/debug_urls.cc4
-rw-r--r--chromium/content/browser/frame_host/frame_tree.cc1
-rw-r--r--chromium/content/browser/frame_host/frame_tree_node.cc29
-rw-r--r--chromium/content/browser/frame_host/input/input_injector_impl.cc82
-rw-r--r--chromium/content/browser/frame_host/input/input_injector_impl.h45
-rw-r--r--chromium/content/browser/frame_host/input/legacy_ipc_frame_input_handler.cc41
-rw-r--r--chromium/content/browser/frame_host/input/legacy_ipc_frame_input_handler.h4
-rw-r--r--chromium/content/browser/frame_host/interstitial_page_impl.cc8
-rw-r--r--chromium/content/browser/frame_host/interstitial_page_impl.h15
-rw-r--r--chromium/content/browser/frame_host/interstitial_page_impl_browsertest.cc7
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_android.cc5
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_android.h2
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_delegate.h4
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_impl.cc29
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_impl.h3
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_impl_browsertest.cc156
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_impl_unittest.cc376
-rw-r--r--chromium/content/browser/frame_host/navigation_entry_impl.cc2
-rw-r--r--chromium/content/browser/frame_host/navigation_entry_impl.h5
-rw-r--r--chromium/content/browser/frame_host/navigation_entry_impl_unittest.cc47
-rw-r--r--chromium/content/browser/frame_host/navigation_entry_screenshot_manager.cc3
-rw-r--r--chromium/content/browser/frame_host/navigation_handle_impl.cc56
-rw-r--r--chromium/content/browser/frame_host/navigation_handle_impl.h9
-rw-r--r--chromium/content/browser/frame_host/navigation_handle_impl_browsertest.cc5
-rw-r--r--chromium/content/browser/frame_host/navigation_request.cc102
-rw-r--r--chromium/content/browser/frame_host/navigation_request.h17
-rw-r--r--chromium/content/browser/frame_host/navigation_request_info.cc4
-rw-r--r--chromium/content/browser/frame_host/navigation_request_info.h4
-rw-r--r--chromium/content/browser/frame_host/navigator.h10
-rw-r--r--chromium/content/browser/frame_host/navigator_delegate.h10
-rw-r--r--chromium/content/browser/frame_host/navigator_impl.cc21
-rw-r--r--chromium/content/browser/frame_host/navigator_impl.h3
-rw-r--r--chromium/content/browser/frame_host/navigator_impl_unittest.cc179
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_android.cc5
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_android.h2
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_delegate.cc6
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_delegate.h10
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_impl.cc328
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_impl.h64
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_impl_browsertest.cc270
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_manager.cc168
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_manager_browsertest.cc19
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_manager_unittest.cc32
-rw-r--r--chromium/content/browser/frame_host/render_frame_message_filter.cc124
-rw-r--r--chromium/content/browser/frame_host/render_frame_message_filter.h15
-rw-r--r--chromium/content/browser/frame_host/render_frame_message_filter_browsertest.cc27
-rw-r--r--chromium/content/browser/frame_host/render_frame_proxy_host.cc4
-rw-r--r--chromium/content/browser/frame_host/render_widget_host_view_guest.cc36
-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.cc71
-rw-r--r--chromium/content/browser/generic_sensor/OWNERS4
-rw-r--r--chromium/content/browser/generic_sensor/sensor_provider_proxy_impl.cc76
-rw-r--r--chromium/content/browser/generic_sensor/sensor_provider_proxy_impl.h46
-rw-r--r--chromium/content/browser/generic_sensor_browsertest.cc26
-rw-r--r--chromium/content/browser/geolocation/geolocation_service_impl.cc108
-rw-r--r--chromium/content/browser/geolocation/geolocation_service_impl.h85
-rw-r--r--chromium/content/browser/geolocation/geolocation_service_impl_unittest.cc323
-rw-r--r--chromium/content/browser/gpu.sb4
-rw-r--r--chromium/content/browser/gpu/DEPS10
-rw-r--r--chromium/content/browser/gpu/browser_gpu_channel_host_factory.cc19
-rw-r--r--chromium/content/browser/gpu/browser_gpu_memory_buffer_manager.cc12
-rw-r--r--chromium/content/browser/gpu/gpu_client.cc10
-rw-r--r--chromium/content/browser/gpu/gpu_client.h5
-rw-r--r--chromium/content/browser/gpu/gpu_data_manager_impl.h3
-rw-r--r--chromium/content/browser/gpu/gpu_data_manager_impl_private.cc225
-rw-r--r--chromium/content/browser/gpu/gpu_data_manager_impl_private.h11
-rw-r--r--chromium/content/browser/gpu/gpu_data_manager_impl_private_unittest.cc27
-rw-r--r--chromium/content/browser/gpu/gpu_feature_checker_impl.h5
-rw-r--r--chromium/content/browser/gpu/gpu_internals_ui.cc6
-rw-r--r--chromium/content/browser/gpu/gpu_ipc_browsertests.cc2
-rw-r--r--chromium/content/browser/gpu/gpu_process_host.cc111
-rw-r--r--chromium/content/browser/gpu/gpu_process_host.h10
-rw-r--r--chromium/content/browser/gpu/shader_cache_factory.cc13
-rw-r--r--chromium/content/browser/gpu/shader_cache_factory.h5
-rw-r--r--chromium/content/browser/host_zoom_map_impl.cc28
-rw-r--r--chromium/content/browser/host_zoom_map_impl.h16
-rw-r--r--chromium/content/browser/image_capture/image_capture_impl.cc79
-rw-r--r--chromium/content/browser/indexed_db/database_impl.cc3
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_backing_store.cc154
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_backing_store.h53
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_backing_store_unittest.cc37
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_browsertest.cc4
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_context_impl.cc4
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_context_impl.h6
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_database.h2
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc1
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_factory.h5
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_factory_impl.cc101
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_factory_impl.h8
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_internals_ui.cc2
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_leveldb_coding.cc16
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_leveldb_coding.h27
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_leveldb_coding_unittest.cc31
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_pre_close_task_queue.cc121
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_pre_close_task_queue.h109
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_pre_close_task_queue_unittest.cc414
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_quota_client_unittest.cc1
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_tombstone_sweeper.cc465
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_tombstone_sweeper.h194
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_tombstone_sweeper_unittest.cc601
-rw-r--r--chromium/content/browser/indexed_db/leveldb/leveldb_database.cc212
-rw-r--r--chromium/content/browser/indexed_db/leveldb/leveldb_database.h28
-rw-r--r--chromium/content/browser/indexed_db/leveldb/mock_level_db.cc17
-rw-r--r--chromium/content/browser/indexed_db/leveldb/mock_level_db.h67
-rw-r--r--chromium/content/browser/indexed_db/mock_indexed_db_factory.h3
-rw-r--r--chromium/content/browser/isolated_origin_browsertest.cc79
-rw-r--r--chromium/content/browser/keyboard_lock/keyboard_lock_service_impl.h2
-rw-r--r--chromium/content/browser/leveldb_wrapper_impl.cc30
-rw-r--r--chromium/content/browser/leveldb_wrapper_impl.h5
-rw-r--r--chromium/content/browser/leveldb_wrapper_impl_unittest.cc30
-rw-r--r--chromium/content/browser/loader/DEPS1
-rw-r--r--chromium/content/browser/loader/async_resource_handler.cc10
-rw-r--r--chromium/content/browser/loader/cross_site_resource_handler_browsertest.cc18
-rw-r--r--chromium/content/browser/loader/detachable_resource_handler.cc5
-rw-r--r--chromium/content/browser/loader/intercepting_resource_handler.cc9
-rw-r--r--chromium/content/browser/loader/loader_io_thread_notifier.cc6
-rw-r--r--chromium/content/browser/loader/mime_sniffing_resource_handler.cc17
-rw-r--r--chromium/content/browser/loader/mime_sniffing_resource_handler_unittest.cc1
-rw-r--r--chromium/content/browser/loader/mock_resource_loader.cc5
-rw-r--r--chromium/content/browser/loader/mojo_async_resource_handler.cc37
-rw-r--r--chromium/content/browser/loader/mojo_async_resource_handler.h13
-rw-r--r--chromium/content/browser/loader/mojo_async_resource_handler_unittest.cc83
-rw-r--r--chromium/content/browser/loader/navigation_resource_handler.cc41
-rw-r--r--chromium/content/browser/loader/navigation_resource_throttle.cc48
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_delegate.h15
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_impl.cc31
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_impl.h12
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_impl_core.cc28
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_impl_core.h5
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_network_service.cc166
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_network_service.h5
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_unittest.cc66
-rw-r--r--chromium/content/browser/loader/netlog_observer.cc213
-rw-r--r--chromium/content/browser/loader/netlog_observer.h74
-rw-r--r--chromium/content/browser/loader/netlog_observer_unittest.cc180
-rw-r--r--chromium/content/browser/loader/null_resource_controller.cc4
-rw-r--r--chromium/content/browser/loader/null_resource_controller.h1
-rw-r--r--chromium/content/browser/loader/redirect_to_file_resource_handler.cc41
-rw-r--r--chromium/content/browser/loader/redirect_to_file_resource_handler.h13
-rw-r--r--chromium/content/browser/loader/redirect_to_file_resource_handler_unittest.cc110
-rw-r--r--chromium/content/browser/loader/resource_controller.h1
-rw-r--r--chromium/content/browser/loader/resource_dispatcher_host_browsertest.cc39
-rw-r--r--chromium/content/browser/loader/resource_dispatcher_host_impl.cc117
-rw-r--r--chromium/content/browser/loader/resource_dispatcher_host_impl.h40
-rw-r--r--chromium/content/browser/loader/resource_dispatcher_host_unittest.cc154
-rw-r--r--chromium/content/browser/loader/resource_handler.cc4
-rw-r--r--chromium/content/browser/loader/resource_handler.h1
-rw-r--r--chromium/content/browser/loader/resource_hints_impl.cc4
-rw-r--r--chromium/content/browser/loader/resource_loader.cc81
-rw-r--r--chromium/content/browser/loader/resource_loader.h8
-rw-r--r--chromium/content/browser/loader/resource_loader_unittest.cc13
-rw-r--r--chromium/content/browser/loader/resource_message_filter.cc17
-rw-r--r--chromium/content/browser/loader/resource_message_filter.h12
-rw-r--r--chromium/content/browser/loader/resource_request_info_impl.cc15
-rw-r--r--chromium/content/browser/loader/resource_request_info_impl.h11
-rw-r--r--chromium/content/browser/loader/resource_scheduler.cc285
-rw-r--r--chromium/content/browser/loader/resource_scheduler.h135
-rw-r--r--chromium/content/browser/loader/resource_scheduler_browsertest.cc90
-rw-r--r--chromium/content/browser/loader/resource_scheduler_unittest.cc1170
-rw-r--r--chromium/content/browser/loader/sync_resource_handler.cc5
-rw-r--r--chromium/content/browser/loader/throttling_resource_handler.cc9
-rw-r--r--chromium/content/browser/loader/throttling_resource_handler.h1
-rw-r--r--chromium/content/browser/loader/upload_progress_tracker.h2
-rw-r--r--chromium/content/browser/loader/url_loader_factory_impl.cc70
-rw-r--r--chromium/content/browser/loader/url_loader_factory_impl.h21
-rw-r--r--chromium/content/browser/loader/url_loader_factory_impl_unittest.cc26
-rw-r--r--chromium/content/browser/loader/url_loader_request_handler.cc7
-rw-r--r--chromium/content/browser/loader/url_loader_request_handler.h12
-rw-r--r--chromium/content/browser/mach_broker_mac_unittest.cc24
-rw-r--r--chromium/content/browser/manifest/manifest_icon_selector.cc4
-rw-r--r--chromium/content/browser/manifest/manifest_manager_host.h4
-rw-r--r--chromium/content/browser/media/OWNERS2
-rw-r--r--chromium/content/browser/media/android/browser_media_player_manager.cc3
-rw-r--r--chromium/content/browser/media/android/browser_surface_view_manager.h2
-rw-r--r--chromium/content/browser/media/android/media_player_renderer.cc9
-rw-r--r--chromium/content/browser/media/android/media_resource_getter_impl.cc18
-rw-r--r--chromium/content/browser/media/android/media_resource_getter_impl.h2
-rw-r--r--chromium/content/browser/media/audio_stream_monitor.cc21
-rw-r--r--chromium/content/browser/media/capture/OWNERS4
-rw-r--r--chromium/content/browser/media/capture/aura_window_capture_machine.cc54
-rw-r--r--chromium/content/browser/media/capture/aura_window_capture_machine.h11
-rw-r--r--chromium/content/browser/media/capture/desktop_capture_device.cc119
-rw-r--r--chromium/content/browser/media/capture/desktop_capture_device_aura.cc2
-rw-r--r--chromium/content/browser/media/capture/web_contents_audio_input_stream.cc34
-rw-r--r--chromium/content/browser/media/capture/web_contents_audio_input_stream.h2
-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.cc23
-rw-r--r--chromium/content/browser/media/capture/web_contents_tracker.cc16
-rw-r--r--chromium/content/browser/media/capture/web_contents_video_capture_device.cc27
-rw-r--r--chromium/content/browser/media/capture/web_contents_video_capture_device_unittest.cc35
-rw-r--r--chromium/content/browser/media/cdm_registry_impl.h2
-rw-r--r--chromium/content/browser/media/encrypted_media_browsertest.cc18
-rw-r--r--chromium/content/browser/media/media_browsertest.cc18
-rw-r--r--chromium/content/browser/media/media_canplaytype_browsertest.cc34
-rw-r--r--chromium/content/browser/media/media_capabilities_browsertest.cc5
-rw-r--r--chromium/content/browser/media/media_devices_permission_checker_unittest.cc5
-rw-r--r--chromium/content/browser/media/media_interface_proxy.cc8
-rw-r--r--chromium/content/browser/media/media_internals.cc289
-rw-r--r--chromium/content/browser/media/media_internals.h13
-rw-r--r--chromium/content/browser/media/media_internals_proxy.cc2
-rw-r--r--chromium/content/browser/media/media_internals_unittest.cc652
-rw-r--r--chromium/content/browser/media/media_source_browsertest.cc32
-rw-r--r--chromium/content/browser/media/media_web_contents_observer.cc20
-rw-r--r--chromium/content/browser/media/media_web_contents_observer.h3
-rw-r--r--chromium/content/browser/media/session/audio_focus_delegate_android.cc5
-rw-r--r--chromium/content/browser/media/session/audio_focus_delegate_android.h2
-rw-r--r--chromium/content/browser/media/session/media_session_android.cc5
-rw-r--r--chromium/content/browser/media/session/media_session_android.h2
-rw-r--r--chromium/content/browser/media/session/media_session_controller.h2
-rw-r--r--chromium/content/browser/media/session/media_session_impl.cc36
-rw-r--r--chromium/content/browser/media/session/media_session_impl.h18
-rw-r--r--chromium/content/browser/media/session/media_session_impl_visibility_browsertest.cc1
-rw-r--r--chromium/content/browser/media/url_provision_fetcher.cc2
-rw-r--r--chromium/content/browser/memory/memory_coordinator_impl_unittest.cc8
-rw-r--r--chromium/content/browser/memory/memory_monitor_android.cc5
-rw-r--r--chromium/content/browser/memory/memory_monitor_android.h2
-rw-r--r--chromium/content/browser/memory/memory_monitor_fuchsia.cc17
-rw-r--r--chromium/content/browser/memory/swap_metrics_delegate_uma.cc43
-rw-r--r--chromium/content/browser/memory/swap_metrics_delegate_uma.h33
-rw-r--r--chromium/content/browser/memory/swap_metrics_driver_impl.cc98
-rw-r--r--chromium/content/browser/memory/swap_metrics_driver_impl.h78
-rw-r--r--chromium/content/browser/memory/swap_metrics_driver_impl_linux.cc66
-rw-r--r--chromium/content/browser/memory/swap_metrics_driver_impl_linux.h32
-rw-r--r--chromium/content/browser/memory/swap_metrics_driver_impl_mac.cc67
-rw-r--r--chromium/content/browser/memory/swap_metrics_driver_impl_mac.h38
-rw-r--r--chromium/content/browser/memory/swap_metrics_driver_impl_unittest.cc189
-rw-r--r--chromium/content/browser/memory/swap_metrics_driver_impl_win.cc22
-rw-r--r--chromium/content/browser/memory/swap_metrics_observer.cc43
-rw-r--r--chromium/content/browser/memory/swap_metrics_observer.h53
-rw-r--r--chromium/content/browser/memory/swap_metrics_observer_linux.cc55
-rw-r--r--chromium/content/browser/memory/swap_metrics_observer_linux.h27
-rw-r--r--chromium/content/browser/memory/swap_metrics_observer_mac.cc60
-rw-r--r--chromium/content/browser/memory/swap_metrics_observer_mac.h33
-rw-r--r--chromium/content/browser/memory/swap_metrics_observer_win.cc16
-rw-r--r--chromium/content/browser/net/quota_policy_cookie_store.cc13
-rw-r--r--chromium/content/browser/net/quota_policy_cookie_store.h1
-rw-r--r--chromium/content/browser/net_info_browsertest.cc211
-rw-r--r--chromium/content/browser/notifications/notification_database.cc6
-rw-r--r--chromium/content/browser/notifications/notification_event_dispatcher_impl.cc4
-rw-r--r--chromium/content/browser/notifications/platform_notification_context_impl.h4
-rw-r--r--chromium/content/browser/payments/payment_app.proto13
-rw-r--r--chromium/content/browser/payments/payment_app_browsertest.cc188
-rw-r--r--chromium/content/browser/payments/payment_app_content_unittest_base.cc65
-rw-r--r--chromium/content/browser/payments/payment_app_context_impl.cc12
-rw-r--r--chromium/content/browser/payments/payment_app_database.cc64
-rw-r--r--chromium/content/browser/payments/payment_app_database.h13
-rw-r--r--chromium/content/browser/payments/payment_app_info_fetcher.cc37
-rw-r--r--chromium/content/browser/payments/payment_app_info_fetcher.h15
-rw-r--r--chromium/content/browser/payments/payment_app_provider_impl.cc325
-rw-r--r--chromium/content/browser/payments/payment_app_provider_impl.h9
-rw-r--r--chromium/content/browser/payments/payment_app_provider_impl_unittest.cc137
-rw-r--r--chromium/content/browser/payments/payment_instrument_icon_fetcher.cc4
-rw-r--r--chromium/content/browser/payments/payment_manager.cc4
-rw-r--r--chromium/content/browser/payments/payment_manager.h3
-rw-r--r--chromium/content/browser/payments/payment_manager_unittest.cc19
-rw-r--r--chromium/content/browser/pepper_flash_settings_helper_impl.h2
-rw-r--r--chromium/content/browser/permissions/permission_service_context.cc18
-rw-r--r--chromium/content/browser/permissions/permission_service_context.h2
-rw-r--r--chromium/content/browser/permissions/permission_service_impl.cc24
-rw-r--r--chromium/content/browser/permissions/permission_service_impl.h4
-rw-r--r--chromium/content/browser/plugin_private_storage_helper.cc8
-rw-r--r--chromium/content/browser/plugin_service_impl.h3
-rw-r--r--chromium/content/browser/pointer_lock_browsertest.cc15
-rw-r--r--chromium/content/browser/posix_file_descriptor_info_impl.cc111
-rw-r--r--chromium/content/browser/posix_file_descriptor_info_impl.h (renamed from chromium/content/browser/file_descriptor_info_impl.h)24
-rw-r--r--chromium/content/browser/posix_file_descriptor_info_impl_unittest.cc (renamed from chromium/content/browser/file_descriptor_info_impl_unittest.cc)27
-rw-r--r--chromium/content/browser/ppapi_plugin_process_host.cc8
-rw-r--r--chromium/content/browser/ppapi_plugin_process_host.h5
-rw-r--r--chromium/content/browser/presentation/presentation_service_impl.cc29
-rw-r--r--chromium/content/browser/presentation/presentation_service_impl.h7
-rw-r--r--chromium/content/browser/presentation/presentation_service_impl_unittest.cc92
-rw-r--r--chromium/content/browser/push_messaging/push_messaging_router.cc6
-rw-r--r--chromium/content/browser/quota_dispatcher_host.h4
-rw-r--r--chromium/content/browser/renderer_host/DEPS11
-rw-r--r--chromium/content/browser/renderer_host/OWNERS3
-rw-r--r--chromium/content/browser/renderer_host/browser_compositor_view_mac.h17
-rw-r--r--chromium/content/browser/renderer_host/browser_compositor_view_mac.mm24
-rw-r--r--chromium/content/browser/renderer_host/clipboard_message_filter.cc6
-rw-r--r--chromium/content/browser/renderer_host/compositor_impl_android.cc75
-rw-r--r--chromium/content/browser/renderer_host/compositor_impl_android.h15
-rw-r--r--chromium/content/browser/renderer_host/compositor_resize_lock.h3
-rw-r--r--chromium/content/browser/renderer_host/compositor_resize_lock_unittest.cc5
-rw-r--r--chromium/content/browser/renderer_host/cursor_manager_unittest.cc59
-rw-r--r--chromium/content/browser/renderer_host/database_message_filter.cc83
-rw-r--r--chromium/content/browser/renderer_host/database_message_filter.h18
-rw-r--r--chromium/content/browser/renderer_host/delegated_frame_host.cc105
-rw-r--r--chromium/content/browser/renderer_host/delegated_frame_host.h39
-rw-r--r--chromium/content/browser/renderer_host/delegated_frame_host_client_aura.h2
-rw-r--r--chromium/content/browser/renderer_host/dwrite_font_proxy_message_filter_win.cc15
-rw-r--r--chromium/content/browser/renderer_host/dwrite_font_proxy_message_filter_win.h9
-rw-r--r--chromium/content/browser/renderer_host/dwrite_font_proxy_message_filter_win_unittest.cc14
-rw-r--r--chromium/content/browser/renderer_host/file_utilities_message_filter.cc17
-rw-r--r--chromium/content/browser/renderer_host/file_utilities_message_filter.h4
-rw-r--r--chromium/content/browser/renderer_host/frame_connector_delegate.cc61
-rw-r--r--chromium/content/browser/renderer_host/frame_connector_delegate.h165
-rw-r--r--chromium/content/browser/renderer_host/frame_sink_provider_impl.cc4
-rw-r--r--chromium/content/browser/renderer_host/frame_sink_provider_impl.h7
-rw-r--r--chromium/content/browser/renderer_host/input/fling_controller.cc90
-rw-r--r--chromium/content/browser/renderer_host/input/fling_controller.h67
-rw-r--r--chromium/content/browser/renderer_host/input/gesture_event_queue.cc165
-rw-r--r--chromium/content/browser/renderer_host/input/gesture_event_queue.h101
-rw-r--r--chromium/content/browser/renderer_host/input/gesture_event_queue_unittest.cc82
-rw-r--r--chromium/content/browser/renderer_host/input/input_disposition_handler.h (renamed from chromium/content/browser/renderer_host/input/input_ack_handler.h)14
-rw-r--r--chromium/content/browser/renderer_host/input/input_router.h5
-rw-r--r--chromium/content/browser/renderer_host/input/input_router_config_helper.cc16
-rw-r--r--chromium/content/browser/renderer_host/input/input_router_impl.cc564
-rw-r--r--chromium/content/browser/renderer_host/input/input_router_impl.h234
-rw-r--r--chromium/content/browser/renderer_host/input/input_router_impl_unittest.cc2364
-rw-r--r--chromium/content/browser/renderer_host/input/legacy_input_router_impl.cc70
-rw-r--r--chromium/content/browser/renderer_host/input/legacy_input_router_impl.h23
-rw-r--r--chromium/content/browser/renderer_host/input/legacy_input_router_impl_perftest.cc26
-rw-r--r--chromium/content/browser/renderer_host/input/legacy_input_router_impl_unittest.cc217
-rw-r--r--chromium/content/browser/renderer_host/input/legacy_ipc_widget_input_handler.cc50
-rw-r--r--chromium/content/browser/renderer_host/input/legacy_ipc_widget_input_handler.h13
-rw-r--r--chromium/content/browser/renderer_host/input/mock_input_disposition_handler.cc (renamed from chromium/content/browser/renderer_host/input/mock_input_ack_handler.cc)28
-rw-r--r--chromium/content/browser/renderer_host/input/mock_input_disposition_handler.h (renamed from chromium/content/browser/renderer_host/input/mock_input_ack_handler.h)16
-rw-r--r--chromium/content/browser/renderer_host/input/mock_widget_input_handler.cc93
-rw-r--r--chromium/content/browser/renderer_host/input/mock_widget_input_handler.h68
-rw-r--r--chromium/content/browser/renderer_host/input/mouse_latency_browsertest.cc4
-rw-r--r--chromium/content/browser/renderer_host/input/mouse_wheel_event_queue.cc10
-rw-r--r--chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker.cc50
-rw-r--r--chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker.h2
-rw-r--r--chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker_unittest.cc92
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_gesture_controller.cc8
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_gesture_controller.h17
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_gesture_target_android.cc103
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_gesture_target_android.h40
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_gesture_target_aura.cc11
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_pointer_action.cc5
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_pointer_action_unittest.cc9
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_smooth_move_gesture.cc20
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_smooth_move_gesture.h2
-rw-r--r--chromium/content/browser/renderer_host/input/touch_action_filter.cc6
-rw-r--r--chromium/content/browser/renderer_host/input/touch_action_filter.h5
-rw-r--r--chromium/content/browser/renderer_host/input/touch_action_filter_unittest.cc220
-rw-r--r--chromium/content/browser/renderer_host/input/touch_emulator.cc76
-rw-r--r--chromium/content/browser/renderer_host/input/touch_emulator.h31
-rw-r--r--chromium/content/browser/renderer_host/input/touch_emulator_unittest.cc49
-rw-r--r--chromium/content/browser/renderer_host/input/touch_selection_controller_client_aura.cc15
-rw-r--r--chromium/content/browser/renderer_host/input/touch_selection_controller_client_aura.h1
-rw-r--r--chromium/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc2
-rw-r--r--chromium/content/browser/renderer_host/input/touch_selection_controller_client_child_frame.cc6
-rw-r--r--chromium/content/browser/renderer_host/input/touch_selection_controller_client_child_frame.h1
-rw-r--r--chromium/content/browser/renderer_host/input/touch_selection_controller_client_manager_android.cc4
-rw-r--r--chromium/content/browser/renderer_host/input/touch_selection_controller_client_manager_android.h1
-rw-r--r--chromium/content/browser/renderer_host/input/web_input_event_builders_mac_unittest.mm29
-rw-r--r--chromium/content/browser/renderer_host/input/wheel_scroll_latching_browsertest.cc3
-rw-r--r--chromium/content/browser/renderer_host/legacy_render_widget_host_win.cc6
-rw-r--r--chromium/content/browser/renderer_host/legacy_render_widget_host_win.h9
-rw-r--r--chromium/content/browser/renderer_host/media/OWNERS2
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_device_manager.cc114
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_device_manager.h44
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc13
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_renderer_host.cc74
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_renderer_host.h20
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_renderer_host_unittest.cc9
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_sync_writer.cc17
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_sync_writer.h8
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_sync_writer_unittest.cc37
-rw-r--r--chromium/content/browser/renderer_host/media/audio_output_authorization_handler.cc9
-rw-r--r--chromium/content/browser/renderer_host/media/audio_output_authorization_handler_unittest.cc4
-rw-r--r--chromium/content/browser/renderer_host/media/audio_output_delegate_impl_unittest.cc120
-rw-r--r--chromium/content/browser/renderer_host/media/audio_renderer_host.cc4
-rw-r--r--chromium/content/browser/renderer_host/media/audio_renderer_host_unittest.cc8
-rw-r--r--chromium/content/browser/renderer_host/media/audio_sync_reader.cc18
-rw-r--r--chromium/content/browser/renderer_host/media/audio_sync_reader.h2
-rw-r--r--chromium/content/browser/renderer_host/media/in_process_launched_video_capture_device.cc50
-rw-r--r--chromium/content/browser/renderer_host/media/media_capture_devices_impl.cc23
-rw-r--r--chromium/content/browser/renderer_host/media/media_devices_dispatcher_host.cc18
-rw-r--r--chromium/content/browser/renderer_host/media/media_devices_dispatcher_host_unittest.cc73
-rw-r--r--chromium/content/browser/renderer_host/media/media_devices_manager.cc20
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_dispatcher_host.cc254
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_dispatcher_host.h95
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc213
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_manager.cc40
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_manager.h7
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_manager_unittest.cc4
-rw-r--r--chromium/content/browser/renderer_host/media/peer_connection_tracker_host.cc6
-rw-r--r--chromium/content/browser/renderer_host/media/render_frame_audio_output_stream_factory_unittest.cc6
-rw-r--r--chromium/content/browser/renderer_host/media/renderer_audio_output_stream_factory_context_impl_unittest.cc380
-rw-r--r--chromium/content/browser/renderer_host/media/service_launched_video_capture_device.cc27
-rw-r--r--chromium/content/browser/renderer_host/media/service_video_capture_device_launcher.cc64
-rw-r--r--chromium/content/browser/renderer_host/media/service_video_capture_device_launcher.h12
-rw-r--r--chromium/content/browser/renderer_host/media/service_video_capture_device_launcher_unittest.cc51
-rw-r--r--chromium/content/browser/renderer_host/media/service_video_capture_provider.cc27
-rw-r--r--chromium/content/browser/renderer_host/media/service_video_capture_provider.h6
-rw-r--r--chromium/content/browser/renderer_host/media/service_video_capture_provider_unittest.cc44
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_browsertest.cc15
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_controller.cc4
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_controller_unittest.cc18
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_factory_delegate.cc28
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_factory_delegate.h42
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.cc9
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_host.cc32
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_manager.cc24
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_unittest.cc4
-rw-r--r--chromium/content/browser/renderer_host/native_web_keyboard_event_android.cc31
-rw-r--r--chromium/content/browser/renderer_host/native_web_keyboard_event_aura.cc79
-rw-r--r--chromium/content/browser/renderer_host/native_web_keyboard_event_mac.mm64
-rw-r--r--chromium/content/browser/renderer_host/offscreen_canvas_provider_impl.cc4
-rw-r--r--chromium/content/browser/renderer_host/offscreen_canvas_provider_impl.h4
-rw-r--r--chromium/content/browser/renderer_host/offscreen_canvas_provider_impl_unittest.cc32
-rw-r--r--chromium/content/browser/renderer_host/offscreen_canvas_surface_impl.cc30
-rw-r--r--chromium/content/browser/renderer_host/offscreen_canvas_surface_impl.h13
-rw-r--r--chromium/content/browser/renderer_host/overscroll_configuration.cc2
-rw-r--r--chromium/content/browser/renderer_host/overscroll_controller.cc122
-rw-r--r--chromium/content/browser/renderer_host/overscroll_controller.h5
-rw-r--r--chromium/content/browser/renderer_host/overscroll_controller_delegate.h3
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.cc19
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host.cc11
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_tcp.cc4
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_test_utils.cc8
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_file_io_host.cc6
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_file_system_browser_host.cc19
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_host_resolver_message_filter.cc12
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.cc9
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.h2
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.cc10
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.cc53
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.cc28
-rw-r--r--chromium/content/browser/renderer_host/pepper/quota_reservation.cc7
-rw-r--r--chromium/content/browser/renderer_host/pepper/quota_reservation_unittest.cc4
-rw-r--r--chromium/content/browser/renderer_host/render_message_filter.cc10
-rw-r--r--chromium/content/browser/renderer_host/render_process_host_browsertest.cc79
-rw-r--r--chromium/content/browser/renderer_host/render_process_host_impl.cc410
-rw-r--r--chromium/content/browser/renderer_host/render_process_host_impl.h77
-rw-r--r--chromium/content/browser/renderer_host/render_process_host_unittest.cc54
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_factory.cc2
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_impl.cc53
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_impl.h4
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_unittest.cc14
-rw-r--r--chromium/content/browser/renderer_host/render_widget_helper.cc12
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_impl.cc244
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_impl.h105
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_input_event_router.cc63
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_input_event_router.h5
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_input_event_router_unittest.cc282
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_unittest.cc813
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_android.cc151
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_android.h62
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_aura.cc61
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_aura.h19
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc372
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_base.cc2
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_base.h19
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_child_frame.cc (renamed from chromium/content/browser/frame_host/render_widget_host_view_child_frame.cc)275
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_child_frame.h (renamed from chromium/content/browser/frame_host/render_widget_host_view_child_frame.h)61
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_child_frame_browsertest.cc (renamed from chromium/content/browser/frame_host/render_widget_host_view_child_frame_browsertest.cc)18
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc (renamed from chromium/content/browser/frame_host/render_widget_host_view_child_frame_unittest.cc)83
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_event_handler.cc4
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_event_handler.h4
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_frame_subscriber.h2
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_mac.h39
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_mac.mm139
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm8
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm231
-rw-r--r--chromium/content/browser/renderer_host/sandbox_ipc_linux.cc2
-rw-r--r--chromium/content/browser/renderer_host/text_input_client_mac_unittest.mm9
-rw-r--r--chromium/content/browser/resource_loading_browsertest.cc4
-rw-r--r--chromium/content/browser/resources/accessibility/OWNERS5
-rw-r--r--chromium/content/browser/resources/accessibility/accessibility.js38
-rw-r--r--chromium/content/browser/resources/media/dump_creator.js8
-rw-r--r--chromium/content/browser/resources/media/media_internals.css2
-rw-r--r--chromium/content/browser/resources/media/media_internals.html1
-rw-r--r--chromium/content/browser/resources/media/stats_graph_helper.js4
-rw-r--r--chromium/content/browser/resources/media/webrtc_internals.js21
-rw-r--r--chromium/content/browser/screen_orientation/screen_orientation_provider.h2
-rw-r--r--chromium/content/browser/security_exploit_browsertest.cc97
-rw-r--r--chromium/content/browser/service_manager/service_manager_context.cc15
-rw-r--r--chromium/content/browser/service_worker/DEPS1
-rw-r--r--chromium/content/browser/service_worker/browser_side_service_worker_event_dispatcher.cc340
-rw-r--r--chromium/content/browser/service_worker/browser_side_service_worker_event_dispatcher.h143
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_instance.cc197
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_instance.h55
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_instance_unittest.cc143
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_registry.cc23
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_registry.h22
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_test_helper.cc310
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_test_helper.h50
-rw-r--r--chromium/content/browser/service_worker/foreign_fetch_request_handler.cc2
-rw-r--r--chromium/content/browser/service_worker/foreign_fetch_request_handler_unittest.cc33
-rw-r--r--chromium/content/browser/service_worker/link_header_support.cc7
-rw-r--r--chromium/content/browser/service_worker/link_header_support_unittest.cc21
-rw-r--r--chromium/content/browser/service_worker/service_worker_browsertest.cc144
-rw-r--r--chromium/content/browser/service_worker/service_worker_client_utils.cc24
-rw-r--r--chromium/content/browser/service_worker/service_worker_content_settings_proxy_impl.cc51
-rw-r--r--chromium/content/browser/service_worker/service_worker_content_settings_proxy_impl.h50
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_core.cc53
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_core.h27
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_core_observer.h5
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_request_handler.cc27
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_request_handler_unittest.cc7
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_unittest.cc79
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_watcher.cc119
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_watcher.h18
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_watcher_unittest.cc386
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_wrapper.cc174
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_wrapper.h15
-rw-r--r--chromium/content/browser/service_worker/service_worker_controllee_request_handler.cc20
-rw-r--r--chromium/content/browser/service_worker/service_worker_controllee_request_handler.h4
-rw-r--r--chromium/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc14
-rw-r--r--chromium/content/browser/service_worker/service_worker_data_pipe_reader.cc11
-rw-r--r--chromium/content/browser/service_worker/service_worker_data_pipe_reader_unittest.cc20
-rw-r--r--chromium/content/browser/service_worker/service_worker_database.cc5
-rw-r--r--chromium/content/browser/service_worker/service_worker_database_task_manager.cc72
-rw-r--r--chromium/content/browser/service_worker/service_worker_database_task_manager.h79
-rw-r--r--chromium/content/browser/service_worker/service_worker_dispatcher_host.cc236
-rw-r--r--chromium/content/browser/service_worker/service_worker_dispatcher_host.h46
-rw-r--r--chromium/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc160
-rw-r--r--chromium/content/browser/service_worker/service_worker_fetch_dispatcher.cc178
-rw-r--r--chromium/content/browser/service_worker/service_worker_fetch_dispatcher.h11
-rw-r--r--chromium/content/browser/service_worker/service_worker_handle.h2
-rw-r--r--chromium/content/browser/service_worker/service_worker_installed_scripts_sender.cc461
-rw-r--r--chromium/content/browser/service_worker/service_worker_installed_scripts_sender.h70
-rw-r--r--chromium/content/browser/service_worker/service_worker_installed_scripts_sender_unittest.cc566
-rw-r--r--chromium/content/browser/service_worker/service_worker_internals_ui.cc34
-rw-r--r--chromium/content/browser/service_worker/service_worker_job_coordinator.cc2
-rw-r--r--chromium/content/browser/service_worker/service_worker_job_unittest.cc178
-rw-r--r--chromium/content/browser/service_worker/service_worker_metrics.cc41
-rw-r--r--chromium/content/browser/service_worker/service_worker_metrics.h7
-rw-r--r--chromium/content/browser/service_worker/service_worker_navigation_handle_core.cc2
-rw-r--r--chromium/content/browser/service_worker/service_worker_process_manager.cc29
-rw-r--r--chromium/content/browser/service_worker/service_worker_process_manager_unittest.cc34
-rw-r--r--chromium/content/browser/service_worker/service_worker_provider_host.cc517
-rw-r--r--chromium/content/browser/service_worker/service_worker_provider_host.h175
-rw-r--r--chromium/content/browser/service_worker/service_worker_provider_host_unittest.cc106
-rw-r--r--chromium/content/browser/service_worker/service_worker_read_from_cache_job.cc4
-rw-r--r--chromium/content/browser/service_worker/service_worker_register_job.cc14
-rw-r--r--chromium/content/browser/service_worker/service_worker_registration.cc13
-rw-r--r--chromium/content/browser/service_worker/service_worker_registration.h6
-rw-r--r--chromium/content/browser/service_worker/service_worker_registration_handle.h5
-rw-r--r--chromium/content/browser/service_worker/service_worker_registration_status.cc19
-rw-r--r--chromium/content/browser/service_worker/service_worker_registration_status.h2
-rw-r--r--chromium/content/browser/service_worker/service_worker_registration_unittest.cc2
-rw-r--r--chromium/content/browser/service_worker/service_worker_response_info.cc4
-rw-r--r--chromium/content/browser/service_worker/service_worker_response_info.h10
-rw-r--r--chromium/content/browser/service_worker/service_worker_script_url_loader.cc114
-rw-r--r--chromium/content/browser/service_worker/service_worker_script_url_loader.h79
-rw-r--r--chromium/content/browser/service_worker/service_worker_script_url_loader_factory.cc130
-rw-r--r--chromium/content/browser/service_worker/service_worker_script_url_loader_factory.h59
-rw-r--r--chromium/content/browser/service_worker/service_worker_storage.cc375
-rw-r--r--chromium/content/browser/service_worker/service_worker_storage.h40
-rw-r--r--chromium/content/browser/service_worker/service_worker_storage_unittest.cc5
-rw-r--r--chromium/content/browser/service_worker/service_worker_test_utils.cc31
-rw-r--r--chromium/content/browser/service_worker/service_worker_test_utils.h17
-rw-r--r--chromium/content/browser/service_worker/service_worker_url_loader_job.cc37
-rw-r--r--chromium/content/browser/service_worker/service_worker_url_loader_job.h8
-rw-r--r--chromium/content/browser/service_worker/service_worker_url_loader_job_unittest.cc553
-rw-r--r--chromium/content/browser/service_worker/service_worker_url_request_job.cc72
-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.cc336
-rw-r--r--chromium/content/browser/service_worker/service_worker_version.cc211
-rw-r--r--chromium/content/browser/service_worker/service_worker_version.h71
-rw-r--r--chromium/content/browser/service_worker/service_worker_version_unittest.cc106
-rw-r--r--chromium/content/browser/service_worker/service_worker_write_to_cache_job.cc43
-rw-r--r--chromium/content/browser/service_worker/service_worker_write_to_cache_job.h19
-rw-r--r--chromium/content/browser/service_worker/service_worker_write_to_cache_job_unittest.cc30
-rw-r--r--chromium/content/browser/shared_worker/DEPS3
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_content_settings_proxy_impl.cc44
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_content_settings_proxy_impl.h52
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_host.cc50
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_host.h12
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_message_filter.cc20
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_message_filter.h8
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_service_impl.cc55
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_service_impl.h16
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_service_impl_unittest.cc28
-rw-r--r--chromium/content/browser/shared_worker/worker_browsertest.cc1
-rw-r--r--chromium/content/browser/site_instance_impl.cc36
-rw-r--r--chromium/content/browser/site_instance_impl.h19
-rw-r--r--chromium/content/browser/site_per_process_browsertest.cc892
-rw-r--r--chromium/content/browser/site_per_process_mac_browsertest.mm12
-rw-r--r--chromium/content/browser/speech/speech_recognition_browsertest.cc3
-rw-r--r--chromium/content/browser/speech/speech_recognition_engine.cc4
-rw-r--r--chromium/content/browser/speech/speech_recognition_manager_impl.h6
-rw-r--r--chromium/content/browser/speech/speech_recognizer_impl.cc6
-rw-r--r--chromium/content/browser/speech/speech_recognizer_impl.h4
-rw-r--r--chromium/content/browser/speech/speech_recognizer_impl_android.cc5
-rw-r--r--chromium/content/browser/speech/speech_recognizer_impl_android.h2
-rw-r--r--chromium/content/browser/speech/speech_recognizer_impl_unittest.cc2
-rw-r--r--chromium/content/browser/ssl/ssl_manager.cc76
-rw-r--r--chromium/content/browser/ssl/ssl_manager.h16
-rw-r--r--chromium/content/browser/ssl/ssl_manager_unittest.cc59
-rw-r--r--chromium/content/browser/storage_partition_impl.cc90
-rw-r--r--chromium/content/browser/storage_partition_impl.h30
-rw-r--r--chromium/content/browser/storage_partition_impl_browsertest.cc99
-rw-r--r--chromium/content/browser/storage_partition_impl_map.cc5
-rw-r--r--chromium/content/browser/storage_partition_impl_unittest.cc7
-rw-r--r--chromium/content/browser/streams/stream.cc4
-rw-r--r--chromium/content/browser/streams/stream_context.cc2
-rw-r--r--chromium/content/browser/streams/stream_handle_impl.cc4
-rw-r--r--chromium/content/browser/streams/stream_url_request_job.cc4
-rw-r--r--chromium/content/browser/theme_helper_mac.mm11
-rw-r--r--chromium/content/browser/top_document_isolation_browsertest.cc36
-rw-r--r--chromium/content/browser/tracing/background_memory_tracing_observer.cc53
-rw-r--r--chromium/content/browser/tracing/background_memory_tracing_observer.h3
-rw-r--r--chromium/content/browser/tracing/background_tracing_manager_browsertest.cc14
-rw-r--r--chromium/content/browser/tracing/background_tracing_manager_impl.cc19
-rw-r--r--chromium/content/browser/tracing/background_tracing_manager_impl.h3
-rw-r--r--chromium/content/browser/tracing/background_tracing_rule.cc12
-rw-r--r--chromium/content/browser/tracing/background_tracing_rule.h10
-rw-r--r--chromium/content/browser/tracing/etw_tracing_agent_win.cc15
-rw-r--r--chromium/content/browser/tracing/memory_tracing_browsertest.cc28
-rw-r--r--chromium/content/browser/tracing/power_tracing_agent.cc41
-rw-r--r--chromium/content/browser/tracing/trace_message_filter.cc8
-rw-r--r--chromium/content/browser/tracing/tracing_controller_browsertest.cc4
-rw-r--r--chromium/content/browser/tracing/tracing_controller_impl.cc68
-rw-r--r--chromium/content/browser/tracing/tracing_controller_impl_data_sinks.cc20
-rw-r--r--chromium/content/browser/url_loader_factory_getter.cc22
-rw-r--r--chromium/content/browser/url_loader_factory_getter.h2
-rw-r--r--chromium/content/browser/utility_process_host_impl.cc43
-rw-r--r--chromium/content/browser/utility_process_host_impl.h6
-rw-r--r--chromium/content/browser/wake_lock/wake_lock_browsertest.cc3
-rw-r--r--chromium/content/browser/web_contents/aura/gesture_nav_simple.cc462
-rw-r--r--chromium/content/browser/web_contents/aura/gesture_nav_simple.h15
-rw-r--r--chromium/content/browser/web_contents/aura/overscroll_navigation_overlay.cc47
-rw-r--r--chromium/content/browser/web_contents/aura/overscroll_navigation_overlay.h3
-rw-r--r--chromium/content/browser/web_contents/aura/overscroll_navigation_overlay_unittest.cc22
-rw-r--r--chromium/content/browser/web_contents/aura/overscroll_window_animation.cc14
-rw-r--r--chromium/content/browser/web_contents/aura/overscroll_window_animation.h4
-rw-r--r--chromium/content/browser/web_contents/aura/overscroll_window_delegate.cc7
-rw-r--r--chromium/content/browser/web_contents/aura/overscroll_window_delegate.h3
-rw-r--r--chromium/content/browser/web_contents/aura/overscroll_window_delegate_unittest.cc13
-rw-r--r--chromium/content/browser/web_contents/aura/types.cc31
-rw-r--r--chromium/content/browser/web_contents/aura/types.h38
-rw-r--r--chromium/content/browser/web_contents/aura/uma_navigation_type.h18
-rw-r--r--chromium/content/browser/web_contents/web_contents_android.cc30
-rw-r--r--chromium/content/browser/web_contents/web_contents_android.h7
-rw-r--r--chromium/content/browser/web_contents/web_contents_impl.cc317
-rw-r--r--chromium/content/browser/web_contents/web_contents_impl.h76
-rw-r--r--chromium/content/browser/web_contents/web_contents_impl_browsertest.cc176
-rw-r--r--chromium/content/browser/web_contents/web_contents_impl_unittest.cc175
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_android.cc3
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_android.h3
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_aura.cc45
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_aura.h5
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_aura_browsertest.cc186
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_aura_unittest.cc26
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_child_frame.cc2
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_mac.h1
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_mac.mm14
-rw-r--r--chromium/content/browser/web_contents_binding_set_browsertest.cc1
-rw-r--r--chromium/content/browser/webauth/authenticator_impl.cc22
-rw-r--r--chromium/content/browser/webauth/authenticator_impl.h9
-rw-r--r--chromium/content/browser/webauth/authenticator_impl_unittest.cc85
-rw-r--r--chromium/content/browser/webrtc/webrtc_audio_browsertest.cc10
-rw-r--r--chromium/content/browser/webrtc/webrtc_browsertest.cc10
-rw-r--r--chromium/content/browser/webrtc/webrtc_capture_from_element_browsertest.cc2
-rw-r--r--chromium/content/browser/webrtc/webrtc_content_browsertest_base.cc1
-rw-r--r--chromium/content/browser/webrtc/webrtc_depth_capture_browsertest.cc8
-rw-r--r--chromium/content/browser/webrtc/webrtc_eventlog_host_unittest.cc86
-rw-r--r--chromium/content/browser/webrtc/webrtc_getusermedia_browsertest.cc38
-rw-r--r--chromium/content/browser/webrtc/webrtc_internals.cc16
-rw-r--r--chromium/content/browser/webrtc/webrtc_internals_message_handler.cc25
-rw-r--r--chromium/content/browser/webrtc/webrtc_internals_message_handler.h5
-rw-r--r--chromium/content/browser/webrtc/webrtc_internals_message_handler_unittest.cc2
-rw-r--r--chromium/content/browser/webrtc/webrtc_internals_unittest.cc2
-rw-r--r--chromium/content/browser/websockets/websocket_impl.cc57
-rw-r--r--chromium/content/browser/websockets/websocket_impl.h11
-rw-r--r--chromium/content/browser/websockets/websocket_manager.cc28
-rw-r--r--chromium/content/browser/websockets/websocket_manager.h7
-rw-r--r--chromium/content/browser/webui/OWNERS2
-rw-r--r--chromium/content/browser/webui/shared_resources_data_source.cc4
-rw-r--r--chromium/content/browser/webui/url_data_manager_backend.cc44
-rw-r--r--chromium/content/browser/webui/url_data_manager_backend.h4
-rw-r--r--chromium/content/browser/webui/web_ui_data_source_impl.h5
-rw-r--r--chromium/content/browser/webui/web_ui_message_handler_unittest.cc61
-rw-r--r--chromium/content/browser/webui/web_ui_mojo_browsertest.cc28
-rw-r--r--chromium/content/browser/webui/web_ui_url_loader_factory.cc37
-rw-r--r--chromium/content/browser/zygote_host/zygote_communication_linux.cc6
-rw-r--r--chromium/content/browser/zygote_host/zygote_communication_linux.h4
-rw-r--r--chromium/content/browser/zygote_host/zygote_host_impl_linux.cc28
1086 files changed, 41650 insertions, 19433 deletions
diff --git a/chromium/content/browser/BUILD.gn b/chromium/content/browser/BUILD.gn
index 41318159a2a..d9c97df39c0 100644
--- a/chromium/content/browser/BUILD.gn
+++ b/chromium/content/browser/BUILD.gn
@@ -37,7 +37,6 @@ source_set("browser") {
"//cc",
"//cc/animation",
"//cc/paint",
- "//cc/surfaces",
"//components/discardable_memory/common",
"//components/discardable_memory/service",
"//components/filesystem:lib",
@@ -45,7 +44,6 @@ source_set("browser") {
"//components/link_header_util",
"//components/metrics",
"//components/metrics:single_sample_metrics",
- "//components/mime_util",
"//components/network_session_configurator/browser",
"//components/offline_pages/core/request_header",
"//components/offline_pages/features:features",
@@ -72,6 +70,7 @@ source_set("browser") {
"//content/common",
"//content/common:features",
"//content/common:mojo_bindings",
+ "//content/network:network_sources",
"//content/public/common:common_sources",
"//crypto",
"//device/bluetooth",
@@ -89,6 +88,7 @@ source_set("browser") {
"//gpu/ipc/host",
"//gpu/vulkan:features",
"//media",
+ "//media:media_features",
"//media/capture",
"//media/capture/mojo:image_capture",
"//media/gpu/ipc/client",
@@ -119,6 +119,8 @@ source_set("browser") {
"//services/file:lib",
"//services/file/public/interfaces",
"//services/metrics/public/cpp:metrics_cpp",
+ "//services/network/public/cpp",
+ "//services/network/public/interfaces",
"//services/resource_coordinator:lib",
"//services/resource_coordinator/public/cpp:resource_coordinator_cpp",
"//services/service_manager",
@@ -138,11 +140,12 @@ source_set("browser") {
"//sql",
"//storage/browser",
"//storage/common",
+ "//third_party/WebKit/common:blink_common",
"//third_party/WebKit/public:blink_headers",
"//third_party/WebKit/public:features",
- "//third_party/WebKit/public:image_resources",
"//third_party/WebKit/public:mojo_bindings",
"//third_party/WebKit/public:resources",
+ "//third_party/WebKit/public:scaled_resources",
"//third_party/angle:angle_common",
"//third_party/brotli:dec",
"//third_party/icu",
@@ -185,6 +188,8 @@ source_set("browser") {
]
sources = [
+ "$target_gen_dir/devtools/protocol/browser.cc",
+ "$target_gen_dir/devtools/protocol/browser.h",
"$target_gen_dir/devtools/protocol/dom.cc",
"$target_gen_dir/devtools/protocol/dom.h",
"$target_gen_dir/devtools/protocol/emulation.cc",
@@ -268,14 +273,14 @@ source_set("browser") {
"accessibility/one_shot_accessibility_tree_search.cc",
"accessibility/one_shot_accessibility_tree_search.h",
"accessibility/web_contents_accessibility.h",
+ "after_startup_task_utils.cc",
+ "after_startup_task_utils.h",
"android/android_overlay_provider_impl.cc",
"android/android_overlay_provider_impl.h",
"android/app_web_message_port.cc",
"android/app_web_message_port.h",
"android/background_sync_network_observer_android.cc",
"android/background_sync_network_observer_android.h",
- "android/browser_jni_registrar.cc",
- "android/browser_jni_registrar.h",
"android/browser_startup_controller.cc",
"android/browser_startup_controller.h",
"android/content_feature_list.cc",
@@ -290,7 +295,6 @@ source_set("browser") {
"android/dialog_overlay_impl.cc",
"android/dialog_overlay_impl.h",
"android/gpu_process_callback.cc",
- "android/gpu_process_callback.h",
"android/java_interfaces_impl.cc",
"android/java_interfaces_impl.h",
"android/launcher_thread.cc",
@@ -299,6 +303,10 @@ source_set("browser") {
"android/scoped_surface_request_manager.h",
"android/string_message_codec.cc",
"android/string_message_codec.h",
+ "android/text_suggestion_host_android.cc",
+ "android/text_suggestion_host_android.h",
+ "android/text_suggestion_host_mojo_impl_android.cc",
+ "android/text_suggestion_host_mojo_impl_android.h",
"android/url_request_content_job.cc",
"android/url_request_content_job.h",
"appcache/appcache.cc",
@@ -352,6 +360,14 @@ source_set("browser") {
"appcache/appcache_subresource_url_factory.h",
"appcache/appcache_update_job.cc",
"appcache/appcache_update_job.h",
+ "appcache/appcache_update_request_base.cc",
+ "appcache/appcache_update_request_base.h",
+ "appcache/appcache_update_url_fetcher.cc",
+ "appcache/appcache_update_url_fetcher.h",
+ "appcache/appcache_update_url_loader_request.cc",
+ "appcache/appcache_update_url_loader_request.h",
+ "appcache/appcache_update_url_request.cc",
+ "appcache/appcache_update_url_request.h",
"appcache/appcache_url_loader_job.cc",
"appcache/appcache_url_loader_job.h",
"appcache/appcache_url_loader_request.cc",
@@ -380,6 +396,8 @@ source_set("browser") {
"background_fetch/background_fetch_registration_id.h",
"background_fetch/background_fetch_request_info.cc",
"background_fetch/background_fetch_request_info.h",
+ "background_fetch/background_fetch_response.cc",
+ "background_fetch/background_fetch_response.h",
"background_fetch/background_fetch_service_impl.cc",
"background_fetch/background_fetch_service_impl.h",
"background_sync/background_sync_context.cc",
@@ -496,11 +514,8 @@ source_set("browser") {
"child_process_launcher_helper.cc",
"child_process_launcher_helper.h",
"child_process_launcher_helper_android.cc",
- "child_process_launcher_helper_android.h",
"child_process_launcher_helper_linux.cc",
"child_process_launcher_helper_mac.cc",
- "child_process_launcher_helper_posix.cc",
- "child_process_launcher_helper_posix.h",
"child_process_launcher_helper_win.cc",
"child_process_security_policy_impl.cc",
"child_process_security_policy_impl.h",
@@ -534,10 +549,14 @@ source_set("browser") {
"devtools/devtools_url_request_interceptor.h",
"devtools/forwarding_agent_host.cc",
"devtools/forwarding_agent_host.h",
- "devtools/page_navigation_throttle.cc",
- "devtools/page_navigation_throttle.h",
+ "devtools/protocol/browser_handler.cc",
+ "devtools/protocol/browser_handler.h",
"devtools/protocol/devtools_domain_handler.cc",
"devtools/protocol/devtools_domain_handler.h",
+ "devtools/protocol/devtools_download_manager_delegate.cc",
+ "devtools/protocol/devtools_download_manager_delegate.h",
+ "devtools/protocol/devtools_download_manager_helper.cc",
+ "devtools/protocol/devtools_download_manager_helper.h",
"devtools/protocol/dom_handler.cc",
"devtools/protocol/dom_handler.h",
"devtools/protocol/emulation_handler.cc",
@@ -550,6 +569,8 @@ source_set("browser") {
"devtools/protocol/io_handler.h",
"devtools/protocol/memory_handler.cc",
"devtools/protocol/memory_handler.h",
+ "devtools/protocol/native_input_event_builder.h",
+ "devtools/protocol/native_input_event_builder_mac.mm",
"devtools/protocol/network_handler.cc",
"devtools/protocol/network_handler.h",
"devtools/protocol/page_handler.cc",
@@ -586,6 +607,7 @@ source_set("browser") {
"devtools/shared_worker_devtools_manager.h",
"devtools/worker_devtools_agent_host.cc",
"devtools/worker_devtools_agent_host.h",
+ "discardable_shared_memory_manager.cc",
"dom_storage/dom_storage_area.cc",
"dom_storage/dom_storage_area.h",
"dom_storage/dom_storage_context_impl.cc",
@@ -650,8 +672,14 @@ source_set("browser") {
"download/download_request_handle.h",
"download/download_resource_handler.cc",
"download/download_resource_handler.h",
+ "download/download_response_handler.cc",
+ "download/download_response_handler.h",
"download/download_stats.cc",
"download/download_stats.h",
+ "download/download_task_runner.cc",
+ "download/download_task_runner.h",
+ "download/download_utils.cc",
+ "download/download_utils.h",
"download/download_worker.cc",
"download/download_worker.h",
"download/drag_download_file.cc",
@@ -668,6 +696,8 @@ source_set("browser") {
"download/parallel_download_utils.h",
"download/rate_estimator.cc",
"download/rate_estimator.h",
+ "download/resource_downloader.cc",
+ "download/resource_downloader.h",
"download/save_file.cc",
"download/save_file.h",
"download/save_file_manager.cc",
@@ -682,6 +712,8 @@ source_set("browser") {
"download/save_package_download_job.h",
"download/save_types.cc",
"download/save_types.h",
+ "download/url_download_handler.cc",
+ "download/url_download_handler.h",
"download/url_downloader.cc",
"download/url_downloader.h",
"field_trial_recorder.cc",
@@ -713,6 +745,8 @@ source_set("browser") {
"frame_host/frame_tree_node.h",
"frame_host/frame_tree_node_blame_context.cc",
"frame_host/frame_tree_node_blame_context.h",
+ "frame_host/input/input_injector_impl.cc",
+ "frame_host/input/input_injector_impl.h",
"frame_host/input/legacy_ipc_frame_input_handler.cc",
"frame_host/input/legacy_ipc_frame_input_handler.h",
"frame_host/interstitial_page_impl.cc",
@@ -756,10 +790,12 @@ source_set("browser") {
"frame_host/render_frame_message_filter.h",
"frame_host/render_frame_proxy_host.cc",
"frame_host/render_frame_proxy_host.h",
- "frame_host/render_widget_host_view_child_frame.cc",
- "frame_host/render_widget_host_view_child_frame.h",
"frame_host/render_widget_host_view_guest.cc",
"frame_host/render_widget_host_view_guest.h",
+ "generic_sensor/sensor_provider_proxy_impl.cc",
+ "generic_sensor/sensor_provider_proxy_impl.h",
+ "geolocation/geolocation_service_impl.cc",
+ "geolocation/geolocation_service_impl.h",
"gpu/browser_gpu_channel_host_factory.cc",
"gpu/browser_gpu_channel_host_factory.h",
"gpu/browser_gpu_memory_buffer_manager.cc",
@@ -840,9 +876,13 @@ source_set("browser") {
"indexed_db/indexed_db_observer.h",
"indexed_db/indexed_db_pending_connection.cc",
"indexed_db/indexed_db_pending_connection.h",
+ "indexed_db/indexed_db_pre_close_task_queue.cc",
+ "indexed_db/indexed_db_pre_close_task_queue.h",
"indexed_db/indexed_db_quota_client.cc",
"indexed_db/indexed_db_quota_client.h",
"indexed_db/indexed_db_return_value.h",
+ "indexed_db/indexed_db_tombstone_sweeper.cc",
+ "indexed_db/indexed_db_tombstone_sweeper.h",
"indexed_db/indexed_db_tracing.h",
"indexed_db/indexed_db_transaction.cc",
"indexed_db/indexed_db_transaction.h",
@@ -905,8 +945,6 @@ source_set("browser") {
"loader/navigation_url_loader_impl_core.h",
"loader/navigation_url_loader_network_service.cc",
"loader/navigation_url_loader_network_service.h",
- "loader/netlog_observer.cc",
- "loader/netlog_observer.h",
"loader/null_resource_controller.cc",
"loader/null_resource_controller.h",
"loader/redirect_to_file_resource_handler.cc",
@@ -1041,13 +1079,15 @@ source_set("browser") {
"memory/memory_monitor_android.h",
"memory/memory_monitor_win.cc",
"memory/memory_monitor_win.h",
- "memory/swap_metrics_observer.cc",
- "memory/swap_metrics_observer.h",
- "memory/swap_metrics_observer_linux.cc",
- "memory/swap_metrics_observer_linux.h",
- "memory/swap_metrics_observer_mac.cc",
- "memory/swap_metrics_observer_mac.h",
- "memory/swap_metrics_observer_win.cc",
+ "memory/swap_metrics_delegate_uma.cc",
+ "memory/swap_metrics_delegate_uma.h",
+ "memory/swap_metrics_driver_impl.cc",
+ "memory/swap_metrics_driver_impl.h",
+ "memory/swap_metrics_driver_impl_linux.cc",
+ "memory/swap_metrics_driver_impl_linux.h",
+ "memory/swap_metrics_driver_impl_mac.cc",
+ "memory/swap_metrics_driver_impl_mac.h",
+ "memory/swap_metrics_driver_impl_win.cc",
"message_port_provider.cc",
"mime_registry_impl.cc",
"mime_registry_impl.h",
@@ -1129,19 +1169,25 @@ source_set("browser") {
"renderer_host/file_utilities_message_filter.h",
"renderer_host/font_utils_linux.cc",
"renderer_host/font_utils_linux.h",
+ "renderer_host/frame_connector_delegate.cc",
+ "renderer_host/frame_connector_delegate.h",
"renderer_host/frame_metadata_util.cc",
"renderer_host/frame_metadata_util.h",
"renderer_host/frame_sink_provider_impl.cc",
"renderer_host/frame_sink_provider_impl.h",
+ "renderer_host/input/fling_controller.cc",
+ "renderer_host/input/fling_controller.h",
"renderer_host/input/gesture_event_queue.cc",
"renderer_host/input/gesture_event_queue.h",
- "renderer_host/input/input_ack_handler.h",
"renderer_host/input/input_device_change_observer.cc",
"renderer_host/input/input_device_change_observer.h",
+ "renderer_host/input/input_disposition_handler.h",
"renderer_host/input/input_router.h",
"renderer_host/input/input_router_client.h",
"renderer_host/input/input_router_config_helper.cc",
"renderer_host/input/input_router_config_helper.h",
+ "renderer_host/input/input_router_impl.cc",
+ "renderer_host/input/input_router_impl.h",
"renderer_host/input/legacy_input_router_impl.cc",
"renderer_host/input/legacy_input_router_impl.h",
"renderer_host/input/legacy_ipc_widget_input_handler.cc",
@@ -1275,6 +1321,8 @@ source_set("browser") {
"renderer_host/media/video_capture_controller.h",
"renderer_host/media/video_capture_controller_event_handler.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",
"renderer_host/media/video_capture_gpu_jpeg_decoder.cc",
"renderer_host/media/video_capture_gpu_jpeg_decoder.h",
"renderer_host/media/video_capture_host.cc",
@@ -1323,6 +1371,8 @@ source_set("browser") {
"renderer_host/render_widget_host_view_base.h",
"renderer_host/render_widget_host_view_base_observer.cc",
"renderer_host/render_widget_host_view_base_observer.h",
+ "renderer_host/render_widget_host_view_child_frame.cc",
+ "renderer_host/render_widget_host_view_child_frame.h",
"renderer_host/render_widget_host_view_frame_subscriber.h",
"renderer_host/render_widget_host_view_mac.h",
"renderer_host/render_widget_host_view_mac.mm",
@@ -1354,6 +1404,8 @@ source_set("browser") {
"service_manager/common_browser_interfaces.h",
"service_manager/service_manager_context.cc",
"service_manager/service_manager_context.h",
+ "service_worker/browser_side_service_worker_event_dispatcher.cc",
+ "service_worker/browser_side_service_worker_event_dispatcher.h",
"service_worker/embedded_worker_instance.cc",
"service_worker/embedded_worker_instance.h",
"service_worker/embedded_worker_registry.cc",
@@ -1369,6 +1421,8 @@ source_set("browser") {
"service_worker/service_worker_cache_writer.h",
"service_worker/service_worker_client_utils.cc",
"service_worker/service_worker_client_utils.h",
+ "service_worker/service_worker_content_settings_proxy_impl.cc",
+ "service_worker/service_worker_content_settings_proxy_impl.h",
"service_worker/service_worker_context_core.cc",
"service_worker/service_worker_context_core.h",
"service_worker/service_worker_context_core_observer.h",
@@ -1384,8 +1438,6 @@ source_set("browser") {
"service_worker/service_worker_data_pipe_reader.h",
"service_worker/service_worker_database.cc",
"service_worker/service_worker_database.h",
- "service_worker/service_worker_database_task_manager.cc",
- "service_worker/service_worker_database_task_manager.h",
"service_worker/service_worker_disk_cache.cc",
"service_worker/service_worker_disk_cache.h",
"service_worker/service_worker_dispatcher_host.cc",
@@ -1433,6 +1485,10 @@ source_set("browser") {
"service_worker/service_worker_response_info.h",
"service_worker/service_worker_script_cache_map.cc",
"service_worker/service_worker_script_cache_map.h",
+ "service_worker/service_worker_script_url_loader.cc",
+ "service_worker/service_worker_script_url_loader.h",
+ "service_worker/service_worker_script_url_loader_factory.cc",
+ "service_worker/service_worker_script_url_loader_factory.h",
"service_worker/service_worker_storage.cc",
"service_worker/service_worker_storage.h",
"service_worker/service_worker_unregister_job.cc",
@@ -1447,6 +1503,8 @@ source_set("browser") {
"service_worker/service_worker_version.h",
"service_worker/service_worker_write_to_cache_job.cc",
"service_worker/service_worker_write_to_cache_job.h",
+ "shared_worker/shared_worker_content_settings_proxy_impl.cc",
+ "shared_worker/shared_worker_content_settings_proxy_impl.h",
"shared_worker/shared_worker_host.cc",
"shared_worker/shared_worker_host.h",
"shared_worker/shared_worker_instance.cc",
@@ -1531,7 +1589,8 @@ source_set("browser") {
"web_contents/aura/overscroll_window_delegate.h",
"web_contents/aura/shadow_layer_delegate.cc",
"web_contents/aura/shadow_layer_delegate.h",
- "web_contents/aura/uma_navigation_type.h",
+ "web_contents/aura/types.cc",
+ "web_contents/aura/types.h",
"web_contents/web_contents_impl.cc",
"web_contents/web_contents_impl.h",
"web_contents/web_contents_view.h",
@@ -1606,10 +1665,17 @@ source_set("browser") {
]
}
- if (!is_win) {
+ if (is_fuchsia) {
sources += [
- "file_descriptor_info_impl.cc",
- "file_descriptor_info_impl.h",
+ "child_process_launcher_helper_fuchsia.cc",
+ "memory/memory_monitor_fuchsia.cc",
+ ]
+ } else if (is_posix) {
+ sources += [
+ "child_process_launcher_helper_posix.cc",
+ "child_process_launcher_helper_posix.h",
+ "posix_file_descriptor_info_impl.cc",
+ "posix_file_descriptor_info_impl.h",
]
}
@@ -1666,7 +1732,6 @@ source_set("browser") {
"//third_party/webrtc/media:rtc_media_base",
"//third_party/webrtc/modules/desktop_capture:primitives",
"//third_party/webrtc/rtc_base:rtc_base",
- "//third_party/webrtc_overrides:init_webrtc",
]
}
@@ -1709,6 +1774,7 @@ source_set("browser") {
"media/capture/desktop_capture_device.h",
]
deps += [ "//third_party/webrtc/modules/desktop_capture" ]
+ public_deps += [ "//third_party/webrtc_overrides:init_webrtc" ]
}
}
@@ -1890,7 +1956,6 @@ source_set("browser") {
"android/content_view_render_view.cc",
"android/content_view_render_view.h",
"android/content_view_statics.cc",
- "android/content_view_statics.h",
"android/date_time_chooser_android.cc",
"android/date_time_chooser_android.h",
"android/gesture_event_type.h",
@@ -1919,11 +1984,12 @@ source_set("browser") {
"android/java/jni_helper.cc",
"android/java/jni_helper.h",
"android/load_url_params.cc",
- "android/load_url_params.h",
"android/nfc_host.cc",
"android/nfc_host.h",
"android/overscroll_controller_android.cc",
"android/overscroll_controller_android.h",
+ "android/popup_zoomer.cc",
+ "android/popup_zoomer.h",
"android/render_widget_host_connector.cc",
"android/render_widget_host_connector.h",
"android/selection_popup_controller.cc",
@@ -1961,8 +2027,8 @@ source_set("browser") {
set_sources_assignment_filter([])
sources += [
- "memory/swap_metrics_observer_linux.cc",
- "memory/swap_metrics_observer_linux.h",
+ "memory/swap_metrics_driver_impl_linux.cc",
+ "memory/swap_metrics_driver_impl_linux.h",
]
set_sources_assignment_filter(sources_assignment_filter)
@@ -2143,7 +2209,7 @@ source_set("browser") {
]
}
deps += [
- "//cc/surfaces:surfaces",
+ "//components/viz/service",
"//ui/compositor",
]
}
diff --git a/chromium/content/browser/DEPS b/chromium/content/browser/DEPS
index ed953694ab8..8feb727eb7e 100644
--- a/chromium/content/browser/DEPS
+++ b/chromium/content/browser/DEPS
@@ -8,7 +8,6 @@ include_rules = [
"+components/link_header_util",
"+components/metrics",
"+components/metrics:single_sample_metrics",
- "+components/mime_util",
"+components/network_session_configurator/common",
"+components/offline_pages/features/features.h",
"+components/offline_pages/core/request_header",
@@ -39,6 +38,7 @@ include_rules = [
"+ui/aura_extra",
"+components/vector_icons",
"+ui/webui",
+ "+storage/public/interfaces",
# In general, //content shouldn't depend on //device.
# This is the an exception.
@@ -59,6 +59,10 @@ include_rules = [
"+chromeos",
"+third_party/cros_system_api",
+ # Temporary include to allow easier transition to using a network service.
+ # TODO(mmenke): Remove this when the network service ships.
+ "+content/network",
+
# No inclusion of WebKit from the browser, other than strictly enum/POD,
# header-only types, and some selected common code.
"-third_party/WebKit",
@@ -84,6 +88,8 @@ include_rules = [
"+third_party/WebKit/public/platform/WebSuddenTerminationDisablerType.h",
"+third_party/WebKit/public/platform/WebTouchEvent.h",
"+third_party/WebKit/public/platform/WebTextInputType.h",
+ "+third_party/WebKit/public/platform/input_host.mojom.h",
+ "+third_party/WebKit/public/platform/input_messages.mojom.h",
"+third_party/WebKit/public/platform/mac/WebScrollbarTheme.h",
"+third_party/WebKit/public/platform/mime_registry.mojom.h",
"+third_party/WebKit/public/platform/modules/background_sync/background_sync.mojom.h",
@@ -112,8 +118,8 @@ include_rules = [
"+third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerError.h",
"+third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerEventResult.h",
"+third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerResponseError.h",
- "+third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerResponseType.h",
"+third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerState.h",
+ "+third_party/WebKit/public/platform/modules/serviceworker/service_worker_error_type.mojom.h",
"+third_party/WebKit/public/platform/modules/serviceworker/service_worker_event_status.mojom.h",
"+third_party/WebKit/public/platform/modules/serviceworker/service_worker_stream_handle.mojom.h",
"+third_party/WebKit/public/platform/modules/webauth/authenticator.mojom.h",
@@ -121,13 +127,13 @@ include_rules = [
"+third_party/WebKit/public/platform/reporting.mojom.h",
"+third_party/WebKit/public/public_features.h",
"+third_party/WebKit/public/web/WebAXEnums.h",
- "+third_party/WebKit/public/web/WebCompositionUnderline.h",
"+third_party/WebKit/public/web/WebConsoleMessage.h",
"+third_party/WebKit/public/web/WebContextMenuData.h",
"+third_party/WebKit/public/web/WebDeviceEmulationParams.h",
"+third_party/WebKit/public/web/WebDragStatus.h",
"+third_party/WebKit/public/web/WebFindOptions.h",
"+third_party/WebKit/public/web/WebFrameSerializerCacheControlPolicy.h",
+ "+third_party/WebKit/public/web/WebImeTextSpan.h",
"+third_party/WebKit/public/web/WebMediaPlayerAction.h",
"+third_party/WebKit/public/web/WebPluginAction.h",
"+third_party/WebKit/public/web/WebPopupType.h",
@@ -139,6 +145,11 @@ include_rules = [
"+third_party/WebKit/public/web/WebTreeScopeType.h",
"+third_party/WebKit/public/web/WebTriggeringEventInfo.h",
+ # Unlike other WebKit directories WebKit/common is for the files that
+ # are commonly referenced by renderer-side and browser-side code, and
+ # does not use Blink types like WTF.
+ "+third_party/WebKit/common",
+
# DO NOT ADD ANY CHROME OR COMPONENTS INCLUDES HERE!!!
# See https://sites.google.com/a/chromium.org/dev/developers/content-module
# for more information.
diff --git a/chromium/content/browser/accessibility/OWNERS b/chromium/content/browser/accessibility/OWNERS
index 2f05ed92783..2c85844e32c 100644
--- a/chromium/content/browser/accessibility/OWNERS
+++ b/chromium/content/browser/accessibility/OWNERS
@@ -1,6 +1,4 @@
-aboxhall@chromium.org
-dmazzoni@chromium.org
-dtseng@chromium.org
+file://ui/accessibility/OWNERS
# TEAM: chromium-accessibility@chromium.org
# COMPONENT: UI>Accessibility
diff --git a/chromium/content/browser/accessibility/accessibility_action_browsertest.cc b/chromium/content/browser/accessibility/accessibility_action_browsertest.cc
index fc7022157d1..a413c18423a 100644
--- a/chromium/content/browser/accessibility/accessibility_action_browsertest.cc
+++ b/chromium/content/browser/accessibility/accessibility_action_browsertest.cc
@@ -78,9 +78,8 @@ class AccessibilityActionBrowserTest : public ContentBrowserTest {
IN_PROC_BROWSER_TEST_F(AccessibilityActionBrowserTest, FocusAction) {
NavigateToURL(shell(), GURL(url::kAboutBlankURL));
- AccessibilityNotificationWaiter waiter(shell()->web_contents(),
- kAccessibilityModeComplete,
- ui::AX_EVENT_LOAD_COMPLETE);
+ AccessibilityNotificationWaiter waiter(
+ shell()->web_contents(), ui::kAXModeComplete, ui::AX_EVENT_LOAD_COMPLETE);
GURL url("data:text/html,"
"<button>One</button>"
"<button>Two</button>"
@@ -92,7 +91,7 @@ IN_PROC_BROWSER_TEST_F(AccessibilityActionBrowserTest, FocusAction) {
ASSERT_NE(nullptr, target);
AccessibilityNotificationWaiter waiter2(
- shell()->web_contents(), kAccessibilityModeComplete, ui::AX_EVENT_FOCUS);
+ shell()->web_contents(), ui::kAXModeComplete, ui::AX_EVENT_FOCUS);
GetManager()->SetFocus(*target);
waiter2.WaitForNotification();
@@ -104,9 +103,8 @@ IN_PROC_BROWSER_TEST_F(AccessibilityActionBrowserTest,
IncrementDecrementActions) {
NavigateToURL(shell(), GURL(url::kAboutBlankURL));
- AccessibilityNotificationWaiter waiter(shell()->web_contents(),
- kAccessibilityModeComplete,
- ui::AX_EVENT_LOAD_COMPLETE);
+ AccessibilityNotificationWaiter waiter(
+ shell()->web_contents(), ui::kAXModeComplete, ui::AX_EVENT_LOAD_COMPLETE);
GURL url("data:text/html,"
"<input type=range min=2 value=8 max=10 step=2>");
NavigateToURL(shell(), url);
@@ -119,7 +117,7 @@ IN_PROC_BROWSER_TEST_F(AccessibilityActionBrowserTest,
// Increment, should result in value changing from 8 to 10.
{
AccessibilityNotificationWaiter waiter2(shell()->web_contents(),
- kAccessibilityModeComplete,
+ ui::kAXModeComplete,
ui::AX_EVENT_VALUE_CHANGED);
GetManager()->Increment(*target);
waiter2.WaitForNotification();
@@ -129,7 +127,7 @@ IN_PROC_BROWSER_TEST_F(AccessibilityActionBrowserTest,
// Increment, should result in value staying the same (max).
{
AccessibilityNotificationWaiter waiter2(shell()->web_contents(),
- kAccessibilityModeComplete,
+ ui::kAXModeComplete,
ui::AX_EVENT_VALUE_CHANGED);
GetManager()->Increment(*target);
waiter2.WaitForNotification();
@@ -139,7 +137,7 @@ IN_PROC_BROWSER_TEST_F(AccessibilityActionBrowserTest,
// Decrement, should result in value changing from 10 to 8.
{
AccessibilityNotificationWaiter waiter2(shell()->web_contents(),
- kAccessibilityModeComplete,
+ ui::kAXModeComplete,
ui::AX_EVENT_VALUE_CHANGED);
GetManager()->Decrement(*target);
waiter2.WaitForNotification();
@@ -150,9 +148,8 @@ IN_PROC_BROWSER_TEST_F(AccessibilityActionBrowserTest,
IN_PROC_BROWSER_TEST_F(AccessibilityActionBrowserTest, CanvasGetImage) {
NavigateToURL(shell(), GURL(url::kAboutBlankURL));
- AccessibilityNotificationWaiter waiter(shell()->web_contents(),
- kAccessibilityModeComplete,
- ui::AX_EVENT_LOAD_COMPLETE);
+ AccessibilityNotificationWaiter waiter(
+ shell()->web_contents(), ui::kAXModeComplete, ui::AX_EVENT_LOAD_COMPLETE);
GURL url("data:text/html,"
"<body>"
"<canvas aria-label='canvas' id='c' width='4' height='2'></canvas>"
@@ -178,7 +175,7 @@ IN_PROC_BROWSER_TEST_F(AccessibilityActionBrowserTest, CanvasGetImage) {
ASSERT_NE(nullptr, target);
AccessibilityNotificationWaiter waiter2(shell()->web_contents(),
- kAccessibilityModeComplete,
+ ui::kAXModeComplete,
ui::AX_EVENT_IMAGE_FRAME_UPDATED);
GetManager()->GetImageData(*target, gfx::Size());
waiter2.WaitForNotification();
@@ -200,9 +197,8 @@ IN_PROC_BROWSER_TEST_F(AccessibilityActionBrowserTest, CanvasGetImage) {
IN_PROC_BROWSER_TEST_F(AccessibilityActionBrowserTest, CanvasGetImageScale) {
NavigateToURL(shell(), GURL(url::kAboutBlankURL));
- AccessibilityNotificationWaiter waiter(shell()->web_contents(),
- kAccessibilityModeComplete,
- ui::AX_EVENT_LOAD_COMPLETE);
+ AccessibilityNotificationWaiter waiter(
+ shell()->web_contents(), ui::kAXModeComplete, ui::AX_EVENT_LOAD_COMPLETE);
GURL url("data:text/html,"
"<body>"
"<canvas aria-label='canvas' id='c' width='40' height='20'></canvas>"
@@ -222,7 +218,7 @@ IN_PROC_BROWSER_TEST_F(AccessibilityActionBrowserTest, CanvasGetImageScale) {
ASSERT_NE(nullptr, target);
AccessibilityNotificationWaiter waiter2(shell()->web_contents(),
- kAccessibilityModeComplete,
+ ui::kAXModeComplete,
ui::AX_EVENT_IMAGE_FRAME_UPDATED);
GetManager()->GetImageData(*target, gfx::Size(4, 4));
waiter2.WaitForNotification();
@@ -244,9 +240,8 @@ IN_PROC_BROWSER_TEST_F(AccessibilityActionBrowserTest, CanvasGetImageScale) {
IN_PROC_BROWSER_TEST_F(AccessibilityActionBrowserTest, ImgElementGetImage) {
NavigateToURL(shell(), GURL(url::kAboutBlankURL));
- AccessibilityNotificationWaiter waiter(shell()->web_contents(),
- kAccessibilityModeComplete,
- ui::AX_EVENT_LOAD_COMPLETE);
+ AccessibilityNotificationWaiter waiter(
+ shell()->web_contents(), ui::kAXModeComplete, ui::AX_EVENT_LOAD_COMPLETE);
GURL url("data:text/html,"
"<body>"
"<img src='data:image/gif;base64,R0lGODdhAgADAKEDAAAA//"
@@ -260,7 +255,7 @@ IN_PROC_BROWSER_TEST_F(AccessibilityActionBrowserTest, ImgElementGetImage) {
ASSERT_NE(nullptr, target);
AccessibilityNotificationWaiter waiter2(shell()->web_contents(),
- kAccessibilityModeComplete,
+ ui::kAXModeComplete,
ui::AX_EVENT_IMAGE_FRAME_UPDATED);
GetManager()->GetImageData(*target, gfx::Size());
waiter2.WaitForNotification();
diff --git a/chromium/content/browser/accessibility/accessibility_event_recorder_win.cc b/chromium/content/browser/accessibility/accessibility_event_recorder_win.cc
index c2366712e56..7f3e626c11a 100644
--- a/chromium/content/browser/accessibility/accessibility_event_recorder_win.cc
+++ b/chromium/content/browser/accessibility/accessibility_event_recorder_win.cc
@@ -180,7 +180,7 @@ void AccessibilityEventRecorderWin::OnWinEventHook(
hr = browser_accessible->get_accChild(childid_variant,
dispatch.GetAddressOf());
if (!SUCCEEDED(hr) || !dispatch) {
- VLOG(1) << "Ignoring result " << hr << " and result " << dispatch
+ VLOG(1) << "Ignoring result " << hr << " and result " << dispatch.Get()
<< " from get_accChild";
return;
}
@@ -250,19 +250,17 @@ void AccessibilityEventRecorderWin::OnWinEventHook(
if (event == IA2_EVENT_TEXT_REMOVED) {
IA2TextSegment old_text;
if (SUCCEEDED(accessible_text->get_oldText(&old_text))) {
- log += base::StringPrintf(" old_text={'%s' start=%d end=%d}",
+ log += base::StringPrintf(" old_text={'%s' start=%ld end=%ld}",
BstrToUTF8(old_text.text).c_str(),
- old_text.start,
- old_text.end);
+ old_text.start, old_text.end);
}
}
if (event == IA2_EVENT_TEXT_INSERTED) {
IA2TextSegment new_text;
if (SUCCEEDED(accessible_text->get_newText(&new_text))) {
- log += base::StringPrintf(" new_text={'%s' start=%d end=%d}",
+ log += base::StringPrintf(" new_text={'%s' start=%ld end=%ld}",
BstrToUTF8(new_text.text).c_str(),
- new_text.start,
- new_text.end);
+ new_text.start, new_text.end);
}
}
}
diff --git a/chromium/content/browser/accessibility/accessibility_ipc_error_browsertest.cc b/chromium/content/browser/accessibility/accessibility_ipc_error_browsertest.cc
index c793ab172bb..71007e60979 100644
--- a/chromium/content/browser/accessibility/accessibility_ipc_error_browsertest.cc
+++ b/chromium/content/browser/accessibility/accessibility_ipc_error_browsertest.cc
@@ -60,11 +60,11 @@ IN_PROC_BROWSER_TEST_F(AccessibilityIpcErrorBrowserTest,
ASSERT_EQ(nullptr, frame->GetOrCreateBrowserAccessibilityManager());
{
- // Enable accessibility (passing kAccessibilityModeComplete to
+ // Enable accessibility (passing ui::kAXModeComplete to
// AccessibilityNotificationWaiter does this automatically) and wait for
// the first event.
AccessibilityNotificationWaiter waiter(shell()->web_contents(),
- kAccessibilityModeComplete,
+ ui::kAXModeComplete,
ui::AX_EVENT_LAYOUT_COMPLETE);
waiter.WaitForNotification();
}
@@ -85,7 +85,7 @@ IN_PROC_BROWSER_TEST_F(AccessibilityIpcErrorBrowserTest,
// Hide one of the elements on the page, and wait for an accessibility
// notification triggered by the hide.
AccessibilityNotificationWaiter waiter(shell()->web_contents(),
- kAccessibilityModeComplete,
+ ui::kAXModeComplete,
ui::AX_EVENT_LIVE_REGION_CHANGED);
ASSERT_TRUE(ExecuteScript(
shell(), "document.getElementById('p1').style.display = 'none';"));
@@ -101,9 +101,8 @@ IN_PROC_BROWSER_TEST_F(AccessibilityIpcErrorBrowserTest,
frame->set_no_create_browser_accessibility_manager_for_testing(false);
const ui::AXTree* tree = nullptr;
{
- AccessibilityNotificationWaiter waiter(shell()->web_contents(),
- kAccessibilityModeComplete,
- ui::AX_EVENT_FOCUS);
+ AccessibilityNotificationWaiter waiter(
+ shell()->web_contents(), ui::kAXModeComplete, ui::AX_EVENT_FOCUS);
ASSERT_TRUE(
ExecuteScript(shell(), "document.getElementById('button').focus();"));
waiter.WaitForNotification();
@@ -149,11 +148,11 @@ IN_PROC_BROWSER_TEST_F(AccessibilityIpcErrorBrowserTest,
shell()->web_contents()->GetMainFrame());
{
- // Enable accessibility (passing kAccessibilityModeComplete to
+ // Enable accessibility (passing ui::kAXModeComplete to
// AccessibilityNotificationWaiter does this automatically) and wait for
// the first event.
AccessibilityNotificationWaiter waiter(shell()->web_contents(),
- kAccessibilityModeComplete,
+ ui::kAXModeComplete,
ui::AX_EVENT_LAYOUT_COMPLETE);
waiter.WaitForNotification();
}
@@ -182,7 +181,7 @@ IN_PROC_BROWSER_TEST_F(AccessibilityIpcErrorBrowserTest,
break;
AccessibilityNotificationWaiter waiter(shell()->web_contents(),
- kAccessibilityModeComplete,
+ ui::kAXModeComplete,
ui::AX_EVENT_LOAD_COMPLETE);
waiter.WaitForNotification();
}
diff --git a/chromium/content/browser/accessibility/accessibility_mode_browsertest.cc b/chromium/content/browser/accessibility/accessibility_mode_browsertest.cc
index 00ee8711f96..e53abd0235c 100644
--- a/chromium/content/browser/accessibility/accessibility_mode_browsertest.cc
+++ b/chromium/content/browser/accessibility/accessibility_mode_browsertest.cc
@@ -7,7 +7,6 @@
#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/accessibility_mode.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host.h"
#include "content/public/browser/render_widget_host_view.h"
@@ -18,6 +17,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"
namespace content {
@@ -73,9 +73,8 @@ IN_PROC_BROWSER_TEST_F(AccessibilityModeTest, AccessibilityModeComplete) {
ASSERT_TRUE(web_contents()->GetAccessibilityMode().is_mode_off());
AccessibilityNotificationWaiter waiter(shell()->web_contents());
- web_contents()->AddAccessibilityMode(kAccessibilityModeComplete);
- EXPECT_TRUE(web_contents()->GetAccessibilityMode() ==
- kAccessibilityModeComplete);
+ web_contents()->AddAccessibilityMode(ui::kAXModeComplete);
+ EXPECT_TRUE(web_contents()->GetAccessibilityMode() == ui::kAXModeComplete);
waiter.WaitForNotification();
EXPECT_NE(nullptr, GetManager());
}
@@ -86,9 +85,9 @@ IN_PROC_BROWSER_TEST_F(AccessibilityModeTest,
ASSERT_TRUE(web_contents()->GetAccessibilityMode().is_mode_off());
AccessibilityNotificationWaiter waiter(shell()->web_contents());
- web_contents()->AddAccessibilityMode(kAccessibilityModeWebContentsOnly);
+ web_contents()->AddAccessibilityMode(ui::kAXModeWebContentsOnly);
EXPECT_TRUE(web_contents()->GetAccessibilityMode() ==
- kAccessibilityModeWebContentsOnly);
+ ui::kAXModeWebContentsOnly);
waiter.WaitForNotification();
// No BrowserAccessibilityManager expected for this mode.
EXPECT_EQ(nullptr, GetManager());
@@ -98,16 +97,15 @@ IN_PROC_BROWSER_TEST_F(AccessibilityModeTest, AddingModes) {
NavigateToURL(shell(), GURL(kMinimalPageDataURL));
AccessibilityNotificationWaiter waiter(shell()->web_contents());
- web_contents()->AddAccessibilityMode(kAccessibilityModeWebContentsOnly);
+ web_contents()->AddAccessibilityMode(ui::kAXModeWebContentsOnly);
EXPECT_TRUE(web_contents()->GetAccessibilityMode() ==
- kAccessibilityModeWebContentsOnly);
+ ui::kAXModeWebContentsOnly);
waiter.WaitForNotification();
EXPECT_EQ(nullptr, GetManager());
AccessibilityNotificationWaiter waiter2(shell()->web_contents());
- web_contents()->AddAccessibilityMode(kAccessibilityModeComplete);
- EXPECT_TRUE(web_contents()->GetAccessibilityMode() ==
- kAccessibilityModeComplete);
+ web_contents()->AddAccessibilityMode(ui::kAXModeComplete);
+ EXPECT_TRUE(web_contents()->GetAccessibilityMode() == ui::kAXModeComplete);
waiter2.WaitForNotification();
EXPECT_NE(nullptr, GetManager());
}
@@ -119,9 +117,8 @@ IN_PROC_BROWSER_TEST_F(AccessibilityModeTest,
#if !defined(OS_ANDROID)
NavigateToURL(shell(), GURL(url::kAboutBlankURL));
- AccessibilityNotificationWaiter waiter(shell()->web_contents(),
- kAccessibilityModeComplete,
- ui::AX_EVENT_LOAD_COMPLETE);
+ AccessibilityNotificationWaiter waiter(
+ shell()->web_contents(), ui::kAXModeComplete, ui::AX_EVENT_LOAD_COMPLETE);
GURL url("data:text/html,<p>Para</p>");
NavigateToURL(shell(), url);
waiter.WaitForNotification();
@@ -144,7 +141,7 @@ IN_PROC_BROWSER_TEST_F(AccessibilityModeTest,
AccessibilityNotificationWaiter waiter(
shell()->web_contents(),
- AccessibilityMode::kNativeAPIs | AccessibilityMode::kWebContents,
+ ui::AXMode::kNativeAPIs | ui::AXMode::kWebContents,
ui::AX_EVENT_LOAD_COMPLETE);
GURL url("data:text/html,<p>Para</p>");
NavigateToURL(shell(), url);
@@ -161,7 +158,7 @@ IN_PROC_BROWSER_TEST_F(AccessibilityModeTest, AddScreenReaderModeFlag) {
AccessibilityNotificationWaiter waiter(
shell()->web_contents(),
- AccessibilityMode::kNativeAPIs | AccessibilityMode::kWebContents,
+ ui::AXMode::kNativeAPIs | ui::AXMode::kWebContents,
ui::AX_EVENT_LOAD_COMPLETE);
GURL url("data:text/html,<input aria-label=Foo placeholder=Bar>");
NavigateToURL(shell(), url);
@@ -172,10 +169,10 @@ IN_PROC_BROWSER_TEST_F(AccessibilityModeTest, AddScreenReaderModeFlag) {
EXPECT_FALSE(textbox->HasStringAttribute(ui::AX_ATTR_PLACEHOLDER));
int original_id = textbox->GetId();
- AccessibilityNotificationWaiter waiter2(
- shell()->web_contents(), AccessibilityMode(), ui::AX_EVENT_LOAD_COMPLETE);
+ AccessibilityNotificationWaiter waiter2(shell()->web_contents(), ui::AXMode(),
+ ui::AX_EVENT_LOAD_COMPLETE);
BrowserAccessibilityStateImpl::GetInstance()->AddAccessibilityModeFlags(
- AccessibilityMode::kScreenReader);
+ ui::AXMode::kScreenReader);
waiter2.WaitForNotification();
const BrowserAccessibility* textbox2 = FindNode(
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter_android.cc b/chromium/content/browser/accessibility/accessibility_tree_formatter_android.cc
index 40bca53d0d0..eb7f6fb952d 100644
--- a/chromium/content/browser/accessibility/accessibility_tree_formatter_android.cc
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter_android.cc
@@ -48,7 +48,7 @@ const char* const BOOL_ATTRIBUTES[] = {
};
const char* const STRING_ATTRIBUTES[] = {
- "name"
+ "name", "hint",
};
const char* const INT_ATTRIBUTES[] = {
@@ -131,6 +131,7 @@ void AccessibilityTreeFormatterAndroid::AddProperties(
// String attributes.
dict->SetString("name", android_node->GetText());
+ dict->SetString("hint", android_node->GetHint());
dict->SetString("role_description", android_node->GetRoleDescription());
// Int attributes.
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter_mac.mm b/chromium/content/browser/accessibility/accessibility_tree_formatter_mac.mm
index 6ef7033dfec..607d882976b 100644
--- a/chromium/content/browser/accessibility/accessibility_tree_formatter_mac.mm
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter_mac.mm
@@ -173,11 +173,14 @@ NSArray* BuildAllAttributesArray() {
NSAccessibilityColumnIndexRangeAttribute,
@"AXDOMIdentifier",
@"AXDropEffects",
+ @"AXEditableAncestor",
NSAccessibilityEnabledAttribute,
NSAccessibilityExpandedAttribute,
NSAccessibilityFocusedAttribute,
@"AXGrabbed",
+ @"AXHighestEditableAncestor",
NSAccessibilityIndexAttribute,
+ @"AXLanguage",
@"AXLoaded",
@"AXLoadingProcess",
NSAccessibilityNumberOfCharactersAttribute,
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter_utils_win.cc b/chromium/content/browser/accessibility/accessibility_tree_formatter_utils_win.cc
index 19e58a9a3c9..9d32091c650 100644
--- a/chromium/content/browser/accessibility/accessibility_tree_formatter_utils_win.cc
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter_utils_win.cc
@@ -17,300 +17,227 @@
namespace content {
namespace {
-
-class AccessibilityEnumMap {
- public:
- static AccessibilityEnumMap* GetInstance();
-
- std::map<int32_t, base::string16> ia_role_string_map;
- std::map<int32_t, base::string16> ia2_role_string_map;
- std::map<int32_t, base::string16> ia_state_string_map;
- std::map<int32_t, base::string16> ia2_state_string_map;
- std::map<int32_t, base::string16> event_string_map;
-
- private:
- AccessibilityEnumMap();
- virtual ~AccessibilityEnumMap() {}
-
- friend struct base::DefaultSingletonTraits<AccessibilityEnumMap>;
-
- DISALLOW_COPY_AND_ASSIGN(AccessibilityEnumMap);
+struct PlatformConstantToNameEntry {
+ int32_t value;
+ const char* name;
};
-// static
-AccessibilityEnumMap* AccessibilityEnumMap::GetInstance() {
- return base::Singleton<
- AccessibilityEnumMap,
- base::LeakySingletonTraits<AccessibilityEnumMap>>::get();
+base::string16 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 base::ASCIIToUTF16(entry.name);
+ }
+ return L"";
+}
}
-AccessibilityEnumMap::AccessibilityEnumMap() {
-// Convenience macros for generating readable strings.
-#define IA_ROLE_MAP(x) ia_role_string_map[x] = L###x; \
- ia2_role_string_map[x] = L###x;
-#define IA2_ROLE_MAP(x) ia2_role_string_map[x] = L###x;
-#define IA_STATE_MAP(x) ia_state_string_map[STATE_SYSTEM_##x] = L###x;
-#define IA2_STATE_MAP(x) ia2_state_string_map[x] = L###x;
-#define EVENT_MAP(x) event_string_map[x] = L###x;
+#define QUOTE(X) \
+ { X, #X }
+CONTENT_EXPORT base::string16 IAccessibleRoleToString(int32_t ia_role) {
// MSAA / IAccessible roles. Each one of these is also a valid
- // IAccessible2 role, the IA_ROLE_MAP macro adds it to both.
- IA_ROLE_MAP(ROLE_SYSTEM_ALERT)
- IA_ROLE_MAP(ROLE_SYSTEM_ANIMATION)
- IA_ROLE_MAP(ROLE_SYSTEM_APPLICATION)
- IA_ROLE_MAP(ROLE_SYSTEM_BORDER)
- IA_ROLE_MAP(ROLE_SYSTEM_BUTTONDROPDOWN)
- IA_ROLE_MAP(ROLE_SYSTEM_BUTTONDROPDOWNGRID)
- IA_ROLE_MAP(ROLE_SYSTEM_BUTTONMENU)
- IA_ROLE_MAP(ROLE_SYSTEM_CARET)
- IA_ROLE_MAP(ROLE_SYSTEM_CELL)
- IA_ROLE_MAP(ROLE_SYSTEM_CHARACTER)
- IA_ROLE_MAP(ROLE_SYSTEM_CHART)
- IA_ROLE_MAP(ROLE_SYSTEM_CHECKBUTTON)
- IA_ROLE_MAP(ROLE_SYSTEM_CLIENT)
- IA_ROLE_MAP(ROLE_SYSTEM_CLOCK)
- IA_ROLE_MAP(ROLE_SYSTEM_COLUMN)
- IA_ROLE_MAP(ROLE_SYSTEM_COLUMNHEADER)
- IA_ROLE_MAP(ROLE_SYSTEM_COMBOBOX)
- IA_ROLE_MAP(ROLE_SYSTEM_CURSOR)
- IA_ROLE_MAP(ROLE_SYSTEM_DIAGRAM)
- IA_ROLE_MAP(ROLE_SYSTEM_DIAL)
- IA_ROLE_MAP(ROLE_SYSTEM_DIALOG)
- IA_ROLE_MAP(ROLE_SYSTEM_DOCUMENT)
- IA_ROLE_MAP(ROLE_SYSTEM_DROPLIST)
- IA_ROLE_MAP(ROLE_SYSTEM_EQUATION)
- IA_ROLE_MAP(ROLE_SYSTEM_GRAPHIC)
- IA_ROLE_MAP(ROLE_SYSTEM_GRIP)
- IA_ROLE_MAP(ROLE_SYSTEM_GROUPING)
- IA_ROLE_MAP(ROLE_SYSTEM_HELPBALLOON)
- IA_ROLE_MAP(ROLE_SYSTEM_HOTKEYFIELD)
- IA_ROLE_MAP(ROLE_SYSTEM_INDICATOR)
- IA_ROLE_MAP(ROLE_SYSTEM_IPADDRESS)
- IA_ROLE_MAP(ROLE_SYSTEM_LINK)
- IA_ROLE_MAP(ROLE_SYSTEM_LIST)
- IA_ROLE_MAP(ROLE_SYSTEM_LISTITEM)
- IA_ROLE_MAP(ROLE_SYSTEM_MENUBAR)
- IA_ROLE_MAP(ROLE_SYSTEM_MENUITEM)
- IA_ROLE_MAP(ROLE_SYSTEM_MENUPOPUP)
- IA_ROLE_MAP(ROLE_SYSTEM_OUTLINE)
- IA_ROLE_MAP(ROLE_SYSTEM_OUTLINEBUTTON)
- IA_ROLE_MAP(ROLE_SYSTEM_OUTLINEITEM)
- IA_ROLE_MAP(ROLE_SYSTEM_PAGETAB)
- IA_ROLE_MAP(ROLE_SYSTEM_PAGETABLIST)
- IA_ROLE_MAP(ROLE_SYSTEM_PANE)
- IA_ROLE_MAP(ROLE_SYSTEM_PROGRESSBAR)
- IA_ROLE_MAP(ROLE_SYSTEM_PROPERTYPAGE)
- IA_ROLE_MAP(ROLE_SYSTEM_PUSHBUTTON)
- IA_ROLE_MAP(ROLE_SYSTEM_RADIOBUTTON)
- IA_ROLE_MAP(ROLE_SYSTEM_ROW)
- IA_ROLE_MAP(ROLE_SYSTEM_ROWHEADER)
- IA_ROLE_MAP(ROLE_SYSTEM_SCROLLBAR)
- IA_ROLE_MAP(ROLE_SYSTEM_SEPARATOR)
- IA_ROLE_MAP(ROLE_SYSTEM_SLIDER)
- IA_ROLE_MAP(ROLE_SYSTEM_SOUND)
- IA_ROLE_MAP(ROLE_SYSTEM_SPINBUTTON)
- IA_ROLE_MAP(ROLE_SYSTEM_SPLITBUTTON)
- IA_ROLE_MAP(ROLE_SYSTEM_STATICTEXT)
- IA_ROLE_MAP(ROLE_SYSTEM_STATUSBAR)
- IA_ROLE_MAP(ROLE_SYSTEM_TABLE)
- IA_ROLE_MAP(ROLE_SYSTEM_TEXT)
- IA_ROLE_MAP(ROLE_SYSTEM_TITLEBAR)
- IA_ROLE_MAP(ROLE_SYSTEM_TOOLBAR)
- IA_ROLE_MAP(ROLE_SYSTEM_TOOLTIP)
- IA_ROLE_MAP(ROLE_SYSTEM_WHITESPACE)
- IA_ROLE_MAP(ROLE_SYSTEM_WINDOW)
-
- // IAccessible2 roles.
- IA2_ROLE_MAP(IA2_ROLE_CANVAS)
- IA2_ROLE_MAP(IA2_ROLE_CAPTION)
- IA2_ROLE_MAP(IA2_ROLE_CHECK_MENU_ITEM)
- IA2_ROLE_MAP(IA2_ROLE_COLOR_CHOOSER)
- IA2_ROLE_MAP(IA2_ROLE_DATE_EDITOR)
- IA2_ROLE_MAP(IA2_ROLE_DESKTOP_ICON)
- IA2_ROLE_MAP(IA2_ROLE_DESKTOP_PANE)
- IA2_ROLE_MAP(IA2_ROLE_DIRECTORY_PANE)
- IA2_ROLE_MAP(IA2_ROLE_EDITBAR)
- IA2_ROLE_MAP(IA2_ROLE_EMBEDDED_OBJECT)
- IA2_ROLE_MAP(IA2_ROLE_ENDNOTE)
- IA2_ROLE_MAP(IA2_ROLE_FILE_CHOOSER)
- IA2_ROLE_MAP(IA2_ROLE_FONT_CHOOSER)
- IA2_ROLE_MAP(IA2_ROLE_FOOTER)
- IA2_ROLE_MAP(IA2_ROLE_FOOTNOTE)
- IA2_ROLE_MAP(IA2_ROLE_FORM)
- IA2_ROLE_MAP(IA2_ROLE_FRAME)
- IA2_ROLE_MAP(IA2_ROLE_GLASS_PANE)
- IA2_ROLE_MAP(IA2_ROLE_HEADER)
- IA2_ROLE_MAP(IA2_ROLE_HEADING)
- IA2_ROLE_MAP(IA2_ROLE_ICON)
- IA2_ROLE_MAP(IA2_ROLE_IMAGE_MAP)
- IA2_ROLE_MAP(IA2_ROLE_INPUT_METHOD_WINDOW)
- IA2_ROLE_MAP(IA2_ROLE_INTERNAL_FRAME)
- IA2_ROLE_MAP(IA2_ROLE_LABEL)
- IA2_ROLE_MAP(IA2_ROLE_LAYERED_PANE)
- IA2_ROLE_MAP(IA2_ROLE_NOTE)
- IA2_ROLE_MAP(IA2_ROLE_OPTION_PANE)
- IA2_ROLE_MAP(IA2_ROLE_PAGE)
- IA2_ROLE_MAP(IA2_ROLE_PARAGRAPH)
- IA2_ROLE_MAP(IA2_ROLE_RADIO_MENU_ITEM)
- IA2_ROLE_MAP(IA2_ROLE_REDUNDANT_OBJECT)
- IA2_ROLE_MAP(IA2_ROLE_ROOT_PANE)
- IA2_ROLE_MAP(IA2_ROLE_RULER)
- IA2_ROLE_MAP(IA2_ROLE_SCROLL_PANE)
- IA2_ROLE_MAP(IA2_ROLE_SECTION)
- IA2_ROLE_MAP(IA2_ROLE_SHAPE)
- IA2_ROLE_MAP(IA2_ROLE_SPLIT_PANE)
- IA2_ROLE_MAP(IA2_ROLE_TEAR_OFF_MENU)
- IA2_ROLE_MAP(IA2_ROLE_TERMINAL)
- IA2_ROLE_MAP(IA2_ROLE_TEXT_FRAME)
- IA2_ROLE_MAP(IA2_ROLE_TOGGLE_BUTTON)
- IA2_ROLE_MAP(IA2_ROLE_UNKNOWN)
- IA2_ROLE_MAP(IA2_ROLE_VIEW_PORT)
+ // IAccessible2 role.
+ static const PlatformConstantToNameEntry ia_table[] = {
+ QUOTE(ROLE_SYSTEM_ALERT), QUOTE(ROLE_SYSTEM_ANIMATION),
+ QUOTE(ROLE_SYSTEM_APPLICATION), QUOTE(ROLE_SYSTEM_BORDER),
+ QUOTE(ROLE_SYSTEM_BUTTONDROPDOWN), QUOTE(ROLE_SYSTEM_BUTTONDROPDOWNGRID),
+ QUOTE(ROLE_SYSTEM_BUTTONMENU), QUOTE(ROLE_SYSTEM_CARET),
+ QUOTE(ROLE_SYSTEM_CELL), QUOTE(ROLE_SYSTEM_CHARACTER),
+ QUOTE(ROLE_SYSTEM_CHART), QUOTE(ROLE_SYSTEM_CHECKBUTTON),
+ QUOTE(ROLE_SYSTEM_CLIENT), QUOTE(ROLE_SYSTEM_CLOCK),
+ QUOTE(ROLE_SYSTEM_COLUMN), QUOTE(ROLE_SYSTEM_COLUMNHEADER),
+ QUOTE(ROLE_SYSTEM_COMBOBOX), QUOTE(ROLE_SYSTEM_CURSOR),
+ QUOTE(ROLE_SYSTEM_DIAGRAM), QUOTE(ROLE_SYSTEM_DIAL),
+ QUOTE(ROLE_SYSTEM_DIALOG), QUOTE(ROLE_SYSTEM_DOCUMENT),
+ QUOTE(ROLE_SYSTEM_DROPLIST), QUOTE(ROLE_SYSTEM_EQUATION),
+ QUOTE(ROLE_SYSTEM_GRAPHIC), QUOTE(ROLE_SYSTEM_GRIP),
+ QUOTE(ROLE_SYSTEM_GROUPING), QUOTE(ROLE_SYSTEM_HELPBALLOON),
+ QUOTE(ROLE_SYSTEM_HOTKEYFIELD), QUOTE(ROLE_SYSTEM_INDICATOR),
+ QUOTE(ROLE_SYSTEM_IPADDRESS), QUOTE(ROLE_SYSTEM_LINK),
+ QUOTE(ROLE_SYSTEM_LIST), QUOTE(ROLE_SYSTEM_LISTITEM),
+ QUOTE(ROLE_SYSTEM_MENUBAR), QUOTE(ROLE_SYSTEM_MENUITEM),
+ QUOTE(ROLE_SYSTEM_MENUPOPUP), QUOTE(ROLE_SYSTEM_OUTLINE),
+ QUOTE(ROLE_SYSTEM_OUTLINEBUTTON), QUOTE(ROLE_SYSTEM_OUTLINEITEM),
+ QUOTE(ROLE_SYSTEM_PAGETAB), QUOTE(ROLE_SYSTEM_PAGETABLIST),
+ QUOTE(ROLE_SYSTEM_PANE), QUOTE(ROLE_SYSTEM_PROGRESSBAR),
+ QUOTE(ROLE_SYSTEM_PROPERTYPAGE), QUOTE(ROLE_SYSTEM_PUSHBUTTON),
+ QUOTE(ROLE_SYSTEM_RADIOBUTTON), QUOTE(ROLE_SYSTEM_ROW),
+ QUOTE(ROLE_SYSTEM_ROWHEADER), QUOTE(ROLE_SYSTEM_SCROLLBAR),
+ QUOTE(ROLE_SYSTEM_SEPARATOR), QUOTE(ROLE_SYSTEM_SLIDER),
+ QUOTE(ROLE_SYSTEM_SOUND), QUOTE(ROLE_SYSTEM_SPINBUTTON),
+ QUOTE(ROLE_SYSTEM_SPLITBUTTON), QUOTE(ROLE_SYSTEM_STATICTEXT),
+ QUOTE(ROLE_SYSTEM_STATUSBAR), QUOTE(ROLE_SYSTEM_TABLE),
+ QUOTE(ROLE_SYSTEM_TEXT), QUOTE(ROLE_SYSTEM_TITLEBAR),
+ QUOTE(ROLE_SYSTEM_TOOLBAR), QUOTE(ROLE_SYSTEM_TOOLTIP),
+ QUOTE(ROLE_SYSTEM_WHITESPACE), QUOTE(ROLE_SYSTEM_WINDOW),
+ };
- // MSAA / IAccessible states. Unlike roles, these are not also IA2 states.
- IA_STATE_MAP(ALERT_HIGH)
- IA_STATE_MAP(ALERT_LOW)
- IA_STATE_MAP(ALERT_MEDIUM)
- IA_STATE_MAP(ANIMATED)
- IA_STATE_MAP(BUSY)
- IA_STATE_MAP(CHECKED)
- IA_STATE_MAP(COLLAPSED)
- IA_STATE_MAP(DEFAULT)
- IA_STATE_MAP(EXPANDED)
- IA_STATE_MAP(EXTSELECTABLE)
- IA_STATE_MAP(FLOATING)
- IA_STATE_MAP(FOCUSABLE)
- IA_STATE_MAP(FOCUSED)
- IA_STATE_MAP(HASPOPUP)
- IA_STATE_MAP(HOTTRACKED)
- IA_STATE_MAP(INVISIBLE)
- IA_STATE_MAP(LINKED)
- IA_STATE_MAP(MARQUEED)
- IA_STATE_MAP(MIXED)
- IA_STATE_MAP(MOVEABLE)
- IA_STATE_MAP(MULTISELECTABLE)
- IA_STATE_MAP(OFFSCREEN)
- IA_STATE_MAP(PRESSED)
- IA_STATE_MAP(PROTECTED)
- IA_STATE_MAP(READONLY)
- IA_STATE_MAP(SELECTABLE)
- IA_STATE_MAP(SELECTED)
- IA_STATE_MAP(SELFVOICING)
- IA_STATE_MAP(SIZEABLE)
- IA_STATE_MAP(TRAVERSED)
- IA_STATE_MAP(UNAVAILABLE)
+ return GetNameForPlatformConstant(ia_table, arraysize(ia_table), ia_role);
+}
- // IAccessible2 states.
- IA2_STATE_MAP(IA2_STATE_ACTIVE)
- IA2_STATE_MAP(IA2_STATE_ARMED)
- IA2_STATE_MAP(IA2_STATE_CHECKABLE)
- IA2_STATE_MAP(IA2_STATE_DEFUNCT)
- IA2_STATE_MAP(IA2_STATE_EDITABLE)
- IA2_STATE_MAP(IA2_STATE_HORIZONTAL)
- IA2_STATE_MAP(IA2_STATE_ICONIFIED)
- IA2_STATE_MAP(IA2_STATE_INVALID_ENTRY)
- IA2_STATE_MAP(IA2_STATE_MANAGES_DESCENDANTS)
- IA2_STATE_MAP(IA2_STATE_MODAL)
- IA2_STATE_MAP(IA2_STATE_MULTI_LINE)
- IA2_STATE_MAP(IA2_STATE_REQUIRED)
- IA2_STATE_MAP(IA2_STATE_SELECTABLE_TEXT)
- IA2_STATE_MAP(IA2_STATE_SINGLE_LINE)
- IA2_STATE_MAP(IA2_STATE_STALE)
- IA2_STATE_MAP(IA2_STATE_SUPPORTS_AUTOCOMPLETION)
- IA2_STATE_MAP(IA2_STATE_TRANSIENT)
- IA2_STATE_MAP(IA2_STATE_VERTICAL)
+CONTENT_EXPORT base::string16 IAccessible2RoleToString(int32_t ia2_role) {
+ base::string16 result = IAccessibleRoleToString(ia2_role);
+ if (!result.empty())
+ return result;
- // Untested states include those that would be repeated on nearly every node,
- // or would vary based on window size.
- // IA2_STATE_MAP(IA2_STATE_OPAQUE) // Untested.
+ static const PlatformConstantToNameEntry ia2_table[] = {
+ QUOTE(IA2_ROLE_CANVAS),
+ QUOTE(IA2_ROLE_CAPTION),
+ QUOTE(IA2_ROLE_CHECK_MENU_ITEM),
+ QUOTE(IA2_ROLE_COLOR_CHOOSER),
+ QUOTE(IA2_ROLE_DATE_EDITOR),
+ QUOTE(IA2_ROLE_DESKTOP_ICON),
+ QUOTE(IA2_ROLE_DESKTOP_PANE),
+ QUOTE(IA2_ROLE_DIRECTORY_PANE),
+ QUOTE(IA2_ROLE_EDITBAR),
+ QUOTE(IA2_ROLE_EMBEDDED_OBJECT),
+ QUOTE(IA2_ROLE_ENDNOTE),
+ QUOTE(IA2_ROLE_FILE_CHOOSER),
+ QUOTE(IA2_ROLE_FONT_CHOOSER),
+ QUOTE(IA2_ROLE_FOOTER),
+ QUOTE(IA2_ROLE_FOOTNOTE),
+ QUOTE(IA2_ROLE_FORM),
+ QUOTE(IA2_ROLE_FRAME),
+ QUOTE(IA2_ROLE_GLASS_PANE),
+ QUOTE(IA2_ROLE_HEADER),
+ QUOTE(IA2_ROLE_HEADING),
+ QUOTE(IA2_ROLE_ICON),
+ QUOTE(IA2_ROLE_IMAGE_MAP),
+ QUOTE(IA2_ROLE_INPUT_METHOD_WINDOW),
+ QUOTE(IA2_ROLE_INTERNAL_FRAME),
+ QUOTE(IA2_ROLE_LABEL),
+ QUOTE(IA2_ROLE_LAYERED_PANE),
+ QUOTE(IA2_ROLE_NOTE),
+ QUOTE(IA2_ROLE_OPTION_PANE),
+ QUOTE(IA2_ROLE_PAGE),
+ QUOTE(IA2_ROLE_PARAGRAPH),
+ QUOTE(IA2_ROLE_RADIO_MENU_ITEM),
+ QUOTE(IA2_ROLE_REDUNDANT_OBJECT),
+ QUOTE(IA2_ROLE_ROOT_PANE),
+ QUOTE(IA2_ROLE_RULER),
+ QUOTE(IA2_ROLE_SCROLL_PANE),
+ QUOTE(IA2_ROLE_SECTION),
+ QUOTE(IA2_ROLE_SHAPE),
+ QUOTE(IA2_ROLE_SPLIT_PANE),
+ QUOTE(IA2_ROLE_TEAR_OFF_MENU),
+ QUOTE(IA2_ROLE_TERMINAL),
+ QUOTE(IA2_ROLE_TEXT_FRAME),
+ QUOTE(IA2_ROLE_TOGGLE_BUTTON),
+ QUOTE(IA2_ROLE_UNKNOWN),
+ QUOTE(IA2_ROLE_VIEW_PORT),
+ };
- EVENT_MAP(EVENT_OBJECT_CREATE)
- EVENT_MAP(EVENT_OBJECT_DESTROY)
- EVENT_MAP(EVENT_OBJECT_SHOW)
- EVENT_MAP(EVENT_OBJECT_HIDE)
- EVENT_MAP(EVENT_OBJECT_REORDER)
- EVENT_MAP(EVENT_OBJECT_FOCUS)
- EVENT_MAP(EVENT_OBJECT_SELECTION)
- EVENT_MAP(EVENT_OBJECT_SELECTIONADD)
- EVENT_MAP(EVENT_OBJECT_SELECTIONREMOVE)
- EVENT_MAP(EVENT_OBJECT_SELECTIONWITHIN)
- EVENT_MAP(EVENT_OBJECT_STATECHANGE)
- EVENT_MAP(EVENT_OBJECT_LOCATIONCHANGE)
- EVENT_MAP(EVENT_OBJECT_NAMECHANGE)
- EVENT_MAP(EVENT_OBJECT_DESCRIPTIONCHANGE)
- EVENT_MAP(EVENT_OBJECT_VALUECHANGE)
- EVENT_MAP(EVENT_OBJECT_PARENTCHANGE)
- EVENT_MAP(EVENT_OBJECT_HELPCHANGE)
- EVENT_MAP(EVENT_OBJECT_DEFACTIONCHANGE)
- EVENT_MAP(EVENT_OBJECT_ACCELERATORCHANGE)
- EVENT_MAP(EVENT_OBJECT_INVOKED)
- EVENT_MAP(EVENT_OBJECT_TEXTSELECTIONCHANGED)
- EVENT_MAP(EVENT_OBJECT_CONTENTSCROLLED)
- EVENT_MAP(EVENT_OBJECT_LIVEREGIONCHANGED)
- EVENT_MAP(EVENT_OBJECT_HOSTEDOBJECTSINVALIDATED)
- EVENT_MAP(EVENT_OBJECT_DRAGSTART)
- EVENT_MAP(EVENT_OBJECT_DRAGCANCEL)
- EVENT_MAP(EVENT_OBJECT_DRAGCOMPLETE)
- EVENT_MAP(EVENT_OBJECT_DRAGENTER)
- EVENT_MAP(EVENT_OBJECT_DRAGLEAVE)
- EVENT_MAP(EVENT_OBJECT_DRAGDROPPED)
- EVENT_MAP(EVENT_SYSTEM_ALERT)
- EVENT_MAP(EVENT_SYSTEM_SCROLLINGSTART)
- EVENT_MAP(EVENT_SYSTEM_SCROLLINGEND)
- EVENT_MAP(IA2_EVENT_ACTION_CHANGED)
- EVENT_MAP(IA2_EVENT_ACTIVE_DECENDENT_CHANGED)
- EVENT_MAP(IA2_EVENT_ACTIVE_DESCENDANT_CHANGED)
- EVENT_MAP(IA2_EVENT_DOCUMENT_ATTRIBUTE_CHANGED)
- EVENT_MAP(IA2_EVENT_DOCUMENT_CONTENT_CHANGED)
- EVENT_MAP(IA2_EVENT_DOCUMENT_LOAD_COMPLETE)
- EVENT_MAP(IA2_EVENT_DOCUMENT_LOAD_STOPPED)
- EVENT_MAP(IA2_EVENT_DOCUMENT_RELOAD)
- EVENT_MAP(IA2_EVENT_HYPERLINK_END_INDEX_CHANGED)
- EVENT_MAP(IA2_EVENT_HYPERLINK_NUMBER_OF_ANCHORS_CHANGED)
- EVENT_MAP(IA2_EVENT_HYPERLINK_SELECTED_LINK_CHANGED)
- EVENT_MAP(IA2_EVENT_HYPERTEXT_LINK_ACTIVATED)
- EVENT_MAP(IA2_EVENT_HYPERTEXT_LINK_SELECTED)
- EVENT_MAP(IA2_EVENT_HYPERLINK_START_INDEX_CHANGED)
- EVENT_MAP(IA2_EVENT_HYPERTEXT_CHANGED)
- EVENT_MAP(IA2_EVENT_HYPERTEXT_NLINKS_CHANGED)
- EVENT_MAP(IA2_EVENT_OBJECT_ATTRIBUTE_CHANGED)
- EVENT_MAP(IA2_EVENT_PAGE_CHANGED)
- EVENT_MAP(IA2_EVENT_SECTION_CHANGED)
- EVENT_MAP(IA2_EVENT_TABLE_CAPTION_CHANGED)
- EVENT_MAP(IA2_EVENT_TABLE_COLUMN_DESCRIPTION_CHANGED)
- EVENT_MAP(IA2_EVENT_TABLE_COLUMN_HEADER_CHANGED)
- EVENT_MAP(IA2_EVENT_TABLE_MODEL_CHANGED)
- EVENT_MAP(IA2_EVENT_TABLE_ROW_DESCRIPTION_CHANGED)
- EVENT_MAP(IA2_EVENT_TABLE_ROW_HEADER_CHANGED)
- EVENT_MAP(IA2_EVENT_TABLE_SUMMARY_CHANGED)
- EVENT_MAP(IA2_EVENT_TEXT_ATTRIBUTE_CHANGED)
- EVENT_MAP(IA2_EVENT_TEXT_CARET_MOVED)
- EVENT_MAP(IA2_EVENT_TEXT_CHANGED)
- EVENT_MAP(IA2_EVENT_TEXT_COLUMN_CHANGED)
- EVENT_MAP(IA2_EVENT_TEXT_INSERTED)
- EVENT_MAP(IA2_EVENT_TEXT_REMOVED)
- EVENT_MAP(IA2_EVENT_TEXT_UPDATED)
- EVENT_MAP(IA2_EVENT_TEXT_SELECTION_CHANGED)
- EVENT_MAP(IA2_EVENT_VISIBLE_DATA_CHANGED)
+ return GetNameForPlatformConstant(ia2_table, arraysize(ia2_table), ia2_role);
}
-} // namespace.
-
-base::string16 IAccessibleRoleToString(int32_t ia_role) {
- return AccessibilityEnumMap::GetInstance()->ia_role_string_map[ia_role];
-}
+CONTENT_EXPORT base::string16 AccessibilityEventToString(int32_t event) {
+ static const PlatformConstantToNameEntry event_table[] = {
+ QUOTE(EVENT_OBJECT_CREATE),
+ QUOTE(EVENT_OBJECT_DESTROY),
+ QUOTE(EVENT_OBJECT_SHOW),
+ QUOTE(EVENT_OBJECT_HIDE),
+ QUOTE(EVENT_OBJECT_REORDER),
+ QUOTE(EVENT_OBJECT_FOCUS),
+ QUOTE(EVENT_OBJECT_SELECTION),
+ QUOTE(EVENT_OBJECT_SELECTIONADD),
+ QUOTE(EVENT_OBJECT_SELECTIONREMOVE),
+ QUOTE(EVENT_OBJECT_SELECTIONWITHIN),
+ QUOTE(EVENT_OBJECT_STATECHANGE),
+ QUOTE(EVENT_OBJECT_LOCATIONCHANGE),
+ QUOTE(EVENT_OBJECT_NAMECHANGE),
+ QUOTE(EVENT_OBJECT_DESCRIPTIONCHANGE),
+ QUOTE(EVENT_OBJECT_VALUECHANGE),
+ QUOTE(EVENT_OBJECT_PARENTCHANGE),
+ QUOTE(EVENT_OBJECT_HELPCHANGE),
+ QUOTE(EVENT_OBJECT_DEFACTIONCHANGE),
+ QUOTE(EVENT_OBJECT_ACCELERATORCHANGE),
+ QUOTE(EVENT_OBJECT_INVOKED),
+ QUOTE(EVENT_OBJECT_TEXTSELECTIONCHANGED),
+ QUOTE(EVENT_OBJECT_CONTENTSCROLLED),
+ QUOTE(EVENT_OBJECT_LIVEREGIONCHANGED),
+ QUOTE(EVENT_OBJECT_HOSTEDOBJECTSINVALIDATED),
+ QUOTE(EVENT_OBJECT_DRAGSTART),
+ QUOTE(EVENT_OBJECT_DRAGCANCEL),
+ QUOTE(EVENT_OBJECT_DRAGCOMPLETE),
+ QUOTE(EVENT_OBJECT_DRAGENTER),
+ QUOTE(EVENT_OBJECT_DRAGLEAVE),
+ QUOTE(EVENT_OBJECT_DRAGDROPPED),
+ QUOTE(EVENT_SYSTEM_ALERT),
+ QUOTE(EVENT_SYSTEM_SCROLLINGSTART),
+ QUOTE(EVENT_SYSTEM_SCROLLINGEND),
+ QUOTE(IA2_EVENT_ACTION_CHANGED),
+ QUOTE(IA2_EVENT_ACTIVE_DESCENDANT_CHANGED),
+ QUOTE(IA2_EVENT_DOCUMENT_ATTRIBUTE_CHANGED),
+ QUOTE(IA2_EVENT_DOCUMENT_CONTENT_CHANGED),
+ QUOTE(IA2_EVENT_DOCUMENT_LOAD_COMPLETE),
+ QUOTE(IA2_EVENT_DOCUMENT_LOAD_STOPPED),
+ QUOTE(IA2_EVENT_DOCUMENT_RELOAD),
+ QUOTE(IA2_EVENT_HYPERLINK_END_INDEX_CHANGED),
+ QUOTE(IA2_EVENT_HYPERLINK_NUMBER_OF_ANCHORS_CHANGED),
+ QUOTE(IA2_EVENT_HYPERLINK_SELECTED_LINK_CHANGED),
+ QUOTE(IA2_EVENT_HYPERTEXT_LINK_ACTIVATED),
+ QUOTE(IA2_EVENT_HYPERTEXT_LINK_SELECTED),
+ QUOTE(IA2_EVENT_HYPERLINK_START_INDEX_CHANGED),
+ QUOTE(IA2_EVENT_HYPERTEXT_CHANGED),
+ QUOTE(IA2_EVENT_HYPERTEXT_NLINKS_CHANGED),
+ QUOTE(IA2_EVENT_OBJECT_ATTRIBUTE_CHANGED),
+ QUOTE(IA2_EVENT_PAGE_CHANGED),
+ QUOTE(IA2_EVENT_SECTION_CHANGED),
+ QUOTE(IA2_EVENT_TABLE_CAPTION_CHANGED),
+ QUOTE(IA2_EVENT_TABLE_COLUMN_DESCRIPTION_CHANGED),
+ QUOTE(IA2_EVENT_TABLE_COLUMN_HEADER_CHANGED),
+ QUOTE(IA2_EVENT_TABLE_MODEL_CHANGED),
+ QUOTE(IA2_EVENT_TABLE_ROW_DESCRIPTION_CHANGED),
+ QUOTE(IA2_EVENT_TABLE_ROW_HEADER_CHANGED),
+ QUOTE(IA2_EVENT_TABLE_SUMMARY_CHANGED),
+ QUOTE(IA2_EVENT_TEXT_ATTRIBUTE_CHANGED),
+ QUOTE(IA2_EVENT_TEXT_CARET_MOVED),
+ QUOTE(IA2_EVENT_TEXT_CHANGED),
+ QUOTE(IA2_EVENT_TEXT_COLUMN_CHANGED),
+ QUOTE(IA2_EVENT_TEXT_INSERTED),
+ QUOTE(IA2_EVENT_TEXT_REMOVED),
+ QUOTE(IA2_EVENT_TEXT_UPDATED),
+ QUOTE(IA2_EVENT_TEXT_SELECTION_CHANGED),
+ QUOTE(IA2_EVENT_VISIBLE_DATA_CHANGED),
+ };
-base::string16 IAccessible2RoleToString(int32_t ia_role) {
- return AccessibilityEnumMap::GetInstance()->ia2_role_string_map[ia_role];
+ return GetNameForPlatformConstant(event_table, arraysize(event_table), event);
}
void IAccessibleStateToStringVector(int32_t ia_state,
std::vector<base::string16>* result) {
- const std::map<int32_t, base::string16>& state_string_map =
- AccessibilityEnumMap::GetInstance()->ia_state_string_map;
- std::map<int32_t, base::string16>::const_iterator it;
- for (it = state_string_map.begin(); it != state_string_map.end(); ++it) {
- if (it->first & ia_state)
- result->push_back(it->second);
+#define QUOTE_STATE(X) \
+ { STATE_SYSTEM_##X, #X }
+ // MSAA / IAccessible states. Unlike roles, these are not also IA2 states.
+ //
+ // Note: for historical reasons these are in numerical order rather than
+ // alphabetical order. Changing the order would change the order in which
+ // the states are printed, which would affect a bunch of tests.
+ static const PlatformConstantToNameEntry ia_table[] = {
+ QUOTE_STATE(UNAVAILABLE), QUOTE_STATE(SELECTED),
+ QUOTE_STATE(FOCUSED), QUOTE_STATE(PRESSED),
+ QUOTE_STATE(CHECKED), QUOTE_STATE(MIXED),
+ QUOTE_STATE(READONLY), QUOTE_STATE(HOTTRACKED),
+ QUOTE_STATE(DEFAULT), QUOTE_STATE(EXPANDED),
+ QUOTE_STATE(COLLAPSED), QUOTE_STATE(BUSY),
+ QUOTE_STATE(FLOATING), QUOTE_STATE(MARQUEED),
+ QUOTE_STATE(ANIMATED), QUOTE_STATE(INVISIBLE),
+ QUOTE_STATE(OFFSCREEN), QUOTE_STATE(SIZEABLE),
+ QUOTE_STATE(MOVEABLE), QUOTE_STATE(SELFVOICING),
+ QUOTE_STATE(FOCUSABLE), QUOTE_STATE(SELECTABLE),
+ QUOTE_STATE(LINKED), QUOTE_STATE(TRAVERSED),
+ QUOTE_STATE(MULTISELECTABLE), QUOTE_STATE(EXTSELECTABLE),
+ QUOTE_STATE(ALERT_LOW), QUOTE_STATE(ALERT_MEDIUM),
+ QUOTE_STATE(ALERT_HIGH), QUOTE_STATE(PROTECTED),
+ QUOTE_STATE(HASPOPUP),
+ };
+ for (auto& entry : ia_table) {
+ if (entry.value & ia_state)
+ result->push_back(base::ASCIIToUTF16(entry.name));
}
}
@@ -322,12 +249,36 @@ base::string16 IAccessibleStateToString(int32_t ia_state) {
void IAccessible2StateToStringVector(int32_t ia2_state,
std::vector<base::string16>* result) {
- const std::map<int32_t, base::string16>& state_string_map =
- AccessibilityEnumMap::GetInstance()->ia2_state_string_map;
- std::map<int32_t, base::string16>::const_iterator it;
- for (it = state_string_map.begin(); it != state_string_map.end(); ++it) {
- if (it->first & ia2_state)
- result->push_back(it->second);
+ // Note: for historical reasons these are in numerical order rather than
+ // alphabetical order. Changing the order would change the order in which
+ // the states are printed, which would affect a bunch of tests.
+ static const PlatformConstantToNameEntry ia2_table[] = {
+ QUOTE(IA2_STATE_ACTIVE),
+ QUOTE(IA2_STATE_ARMED),
+ QUOTE(IA2_STATE_CHECKABLE),
+ QUOTE(IA2_STATE_DEFUNCT),
+ QUOTE(IA2_STATE_EDITABLE),
+ QUOTE(IA2_STATE_HORIZONTAL),
+ QUOTE(IA2_STATE_ICONIFIED),
+ QUOTE(IA2_STATE_INVALID_ENTRY),
+ QUOTE(IA2_STATE_MANAGES_DESCENDANTS),
+ QUOTE(IA2_STATE_MODAL),
+ QUOTE(IA2_STATE_MULTI_LINE),
+ QUOTE(IA2_STATE_REQUIRED),
+ QUOTE(IA2_STATE_SELECTABLE_TEXT),
+ QUOTE(IA2_STATE_SINGLE_LINE),
+ QUOTE(IA2_STATE_STALE),
+ QUOTE(IA2_STATE_SUPPORTS_AUTOCOMPLETION),
+ QUOTE(IA2_STATE_TRANSIENT),
+ QUOTE(IA2_STATE_VERTICAL),
+ // Untested states include those that would be repeated on nearly
+ // every node or would vary based on window size.
+ // QUOTE(IA2_STATE_OPAQUE) // Untested.
+ };
+
+ for (auto& entry : ia2_table) {
+ if (entry.value & ia2_state)
+ result->push_back(base::ASCIIToUTF16(entry.name));
}
}
@@ -337,8 +288,4 @@ base::string16 IAccessible2StateToString(int32_t ia2_state) {
return base::JoinString(strings, base::ASCIIToUTF16(","));
}
-base::string16 AccessibilityEventToString(int32_t event_id) {
- return AccessibilityEnumMap::GetInstance()->event_string_map[event_id];
-}
-
} // namespace content
diff --git a/chromium/content/browser/accessibility/accessibility_ui.cc b/chromium/content/browser/accessibility/accessibility_ui.cc
index 4600f8465b1..79d5cd8c8d8 100644
--- a/chromium/content/browser/accessibility/accessibility_ui.cc
+++ b/chromium/content/browser/accessibility/accessibility_ui.cc
@@ -72,7 +72,7 @@ std::unique_ptr<base::DictionaryValue> BuildTargetDescriptor(
const GURL& favicon_url,
int process_id,
int route_id,
- AccessibilityMode accessibility_mode,
+ ui::AXMode accessibility_mode,
base::ProcessHandle handle = base::kNullProcessHandle) {
std::unique_ptr<base::DictionaryValue> target_data(
new base::DictionaryValue());
@@ -90,7 +90,7 @@ std::unique_ptr<base::DictionaryValue> BuildTargetDescriptor(
RenderViewHost* rvh) {
WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(
WebContents::FromRenderViewHost(rvh));
- AccessibilityMode accessibility_mode;
+ ui::AXMode accessibility_mode;
std::string title;
GURL url;
@@ -144,15 +144,15 @@ bool HandleRequestCallback(BrowserContext* current_context,
base::DictionaryValue data;
data.Set("list", std::move(rvh_list));
- AccessibilityMode mode =
+ ui::AXMode mode =
BrowserAccessibilityStateImpl::GetInstance()->accessibility_mode();
bool disabled = base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableRendererAccessibility);
- bool native = mode.has_mode(AccessibilityMode::kNativeAPIs);
- bool web = mode.has_mode(AccessibilityMode::kWebContents);
- bool text = mode.has_mode(AccessibilityMode::kInlineTextBoxes);
- bool screenreader = mode.has_mode(AccessibilityMode::kScreenReader);
- bool html = mode.has_mode(AccessibilityMode::kHTML);
+ bool native = mode.has_mode(ui::AXMode::kNativeAPIs);
+ bool web = mode.has_mode(ui::AXMode::kWebContents);
+ bool text = mode.has_mode(ui::AXMode::kInlineTextBoxes);
+ bool screenreader = mode.has_mode(ui::AXMode::kScreenReader);
+ bool html = mode.has_mode(ui::AXMode::kHTML);
// The "native" and "web" flags are disabled if
// --disable-renderer-accessibility is set.
@@ -234,22 +234,22 @@ void AccessibilityUI::ToggleAccessibility(const base::ListValue* args) {
return;
auto* web_contents =
static_cast<WebContentsImpl*>(WebContents::FromRenderViewHost(rvh));
- AccessibilityMode current_mode = web_contents->GetAccessibilityMode();
+ ui::AXMode current_mode = web_contents->GetAccessibilityMode();
- if (mode & AccessibilityMode::kNativeAPIs)
- current_mode.set_mode(AccessibilityMode::kNativeAPIs, true);
+ if (mode & ui::AXMode::kNativeAPIs)
+ current_mode.set_mode(ui::AXMode::kNativeAPIs, true);
- if (mode & AccessibilityMode::kWebContents)
- current_mode.set_mode(AccessibilityMode::kWebContents, true);
+ if (mode & ui::AXMode::kWebContents)
+ current_mode.set_mode(ui::AXMode::kWebContents, true);
- if (mode & AccessibilityMode::kInlineTextBoxes)
- current_mode.set_mode(AccessibilityMode::kInlineTextBoxes, true);
+ if (mode & ui::AXMode::kInlineTextBoxes)
+ current_mode.set_mode(ui::AXMode::kInlineTextBoxes, true);
- if (mode & AccessibilityMode::kScreenReader)
- current_mode.set_mode(AccessibilityMode::kScreenReader, true);
+ if (mode & ui::AXMode::kScreenReader)
+ current_mode.set_mode(ui::AXMode::kScreenReader, true);
- if (mode & AccessibilityMode::kHTML)
- current_mode.set_mode(AccessibilityMode::kHTML, true);
+ if (mode & ui::AXMode::kHTML)
+ current_mode.set_mode(ui::AXMode::kHTML, true);
web_contents->SetAccessibilityMode(current_mode);
}
@@ -267,17 +267,17 @@ void AccessibilityUI::SetGlobalFlag(const base::ListValue* args) {
return;
}
- AccessibilityMode new_mode;
+ ui::AXMode new_mode;
if (flag_name_str == kNative) {
- new_mode = AccessibilityMode::kNativeAPIs;
+ new_mode = ui::AXMode::kNativeAPIs;
} else if (flag_name_str == kWeb) {
- new_mode = AccessibilityMode::kWebContents;
+ new_mode = ui::AXMode::kWebContents;
} else if (flag_name_str == kText) {
- new_mode = AccessibilityMode::kInlineTextBoxes;
+ new_mode = ui::AXMode::kInlineTextBoxes;
} else if (flag_name_str == kScreenReader) {
- new_mode = AccessibilityMode::kScreenReader;
+ new_mode = ui::AXMode::kScreenReader;
} else if (flag_name_str == kHTML) {
- new_mode = AccessibilityMode::kHTML;
+ new_mode = ui::AXMode::kHTML;
} else {
NOTREACHED();
return;
@@ -285,18 +285,18 @@ void AccessibilityUI::SetGlobalFlag(const base::ListValue* args) {
// It doesn't make sense to enable one of the flags that depends on
// web contents without enabling web contents accessibility too.
- if (enabled && (new_mode.has_mode(AccessibilityMode::kInlineTextBoxes) ||
- new_mode.has_mode(AccessibilityMode::kScreenReader) ||
- new_mode.has_mode(AccessibilityMode::kHTML))) {
- new_mode.set_mode(AccessibilityMode::kWebContents, true);
+ if (enabled && (new_mode.has_mode(ui::AXMode::kInlineTextBoxes) ||
+ new_mode.has_mode(ui::AXMode::kScreenReader) ||
+ new_mode.has_mode(ui::AXMode::kHTML))) {
+ new_mode.set_mode(ui::AXMode::kWebContents, true);
}
// Similarly if you disable web accessibility we should remove all
// flags that depend on it.
- if (!enabled && new_mode.has_mode(AccessibilityMode::kWebContents)) {
- new_mode.set_mode(AccessibilityMode::kInlineTextBoxes, true);
- new_mode.set_mode(AccessibilityMode::kScreenReader, true);
- new_mode.set_mode(AccessibilityMode::kHTML, true);
+ if (!enabled && new_mode.has_mode(ui::AXMode::kWebContents)) {
+ new_mode.set_mode(ui::AXMode::kInlineTextBoxes, true);
+ new_mode.set_mode(ui::AXMode::kScreenReader, true);
+ new_mode.set_mode(ui::AXMode::kHTML, true);
}
BrowserAccessibilityStateImpl* state =
@@ -334,8 +334,8 @@ void AccessibilityUI::RequestAccessibilityTree(const base::ListValue* args) {
static_cast<WebContentsImpl*>(WebContents::FromRenderViewHost(rvh));
// No matter the state of the current web_contents, we want to force the mode
// because we are about to show the accessibility tree
- web_contents->SetAccessibilityMode(AccessibilityMode(
- AccessibilityMode::kNativeAPIs | AccessibilityMode::kWebContents));
+ web_contents->SetAccessibilityMode(
+ ui::AXMode(ui::AXMode::kNativeAPIs | ui::AXMode::kWebContents));
std::unique_ptr<AccessibilityTreeFormatter> formatter;
if (g_show_internal_accessibility_tree)
diff --git a/chromium/content/browser/accessibility/accessibility_win_browsertest.cc b/chromium/content/browser/accessibility/accessibility_win_browsertest.cc
index 94a5140ce98..f7939492f20 100644
--- a/chromium/content/browser/accessibility/accessibility_win_browsertest.cc
+++ b/chromium/content/browser/accessibility/accessibility_win_browsertest.cc
@@ -64,7 +64,7 @@ class AccessibilityWinBrowserTest : public ContentBrowserTest {
class AccessibleChecker;
void LoadInitialAccessibilityTreeFromHtml(
const std::string& html,
- AccessibilityMode accessibility_mode = kAccessibilityModeComplete);
+ ui::AXMode accessibility_mode = ui::kAXModeComplete);
IAccessible* GetRendererAccessible();
void ExecuteScript(const std::wstring& script);
void SetUpInputField(
@@ -73,7 +73,7 @@ class AccessibilityWinBrowserTest : public ContentBrowserTest {
base::win::ScopedComPtr<IAccessibleText>* textarea_text);
void SetUpSampleParagraph(
base::win::ScopedComPtr<IAccessibleText>* accessible_text,
- AccessibilityMode accessibility_mode = kAccessibilityModeComplete);
+ ui::AXMode accessibility_mode = ui::kAXModeComplete);
static base::win::ScopedComPtr<IAccessible> GetAccessibleFromVariant(
IAccessible* parent,
@@ -107,7 +107,7 @@ AccessibilityWinBrowserTest::~AccessibilityWinBrowserTest() {
void AccessibilityWinBrowserTest::LoadInitialAccessibilityTreeFromHtml(
const std::string& html,
- AccessibilityMode accessibility_mode) {
+ ui::AXMode accessibility_mode) {
AccessibilityNotificationWaiter waiter(
shell()->web_contents(), accessibility_mode, ui::AX_EVENT_LOAD_COMPLETE);
GURL html_data_url("data:text/html," + html);
@@ -166,7 +166,7 @@ void AccessibilityWinBrowserTest::SetUpInputField(
// Set the caret on the last character.
AccessibilityNotificationWaiter waiter(shell()->web_contents(),
- kAccessibilityModeComplete,
+ ui::kAXModeComplete,
ui::AX_EVENT_TEXT_SELECTION_CHANGED);
std::wstring caret_offset = base::UTF16ToWide(base::IntToString16(
static_cast<int>(CONTENTS_LENGTH - 1)));
@@ -218,7 +218,7 @@ void AccessibilityWinBrowserTest::SetUpTextareaField(
// Set the caret on the last character.
AccessibilityNotificationWaiter waiter(shell()->web_contents(),
- kAccessibilityModeComplete,
+ ui::kAXModeComplete,
ui::AX_EVENT_TEXT_SELECTION_CHANGED);
std::wstring caret_offset = base::UTF16ToWide(base::IntToString16(
static_cast<int>(CONTENTS_LENGTH - 1)));
@@ -233,7 +233,7 @@ void AccessibilityWinBrowserTest::SetUpTextareaField(
// Loads a page with a paragraph of sample text.
void AccessibilityWinBrowserTest::SetUpSampleParagraph(
base::win::ScopedComPtr<IAccessibleText>* accessible_text,
- AccessibilityMode accessibility_mode) {
+ ui::AXMode accessibility_mode) {
ASSERT_NE(nullptr, accessible_text);
LoadInitialAccessibilityTreeFromHtml(
"<!DOCTYPE html><html>"
@@ -676,9 +676,8 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
// Set focus to the radio group.
std::unique_ptr<AccessibilityNotificationWaiter> waiter(
- new AccessibilityNotificationWaiter(shell()->web_contents(),
- kAccessibilityModeComplete,
- ui::AX_EVENT_FOCUS));
+ new AccessibilityNotificationWaiter(
+ shell()->web_contents(), ui::kAXModeComplete, ui::AX_EVENT_FOCUS));
ExecuteScript(L"document.body.children[0].focus()");
waiter->WaitForNotification();
@@ -689,7 +688,7 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
// Set the active descendant of the radio group
waiter.reset(new AccessibilityNotificationWaiter(
- shell()->web_contents(), kAccessibilityModeComplete, ui::AX_EVENT_FOCUS));
+ shell()->web_contents(), ui::kAXModeComplete, ui::AX_EVENT_FOCUS));
ExecuteScript(
L"document.body.children[0].setAttribute('aria-activedescendant', 'li')");
waiter->WaitForNotification();
@@ -721,7 +720,7 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
// Check the checkbox.
std::unique_ptr<AccessibilityNotificationWaiter> waiter(
new AccessibilityNotificationWaiter(shell()->web_contents(),
- kAccessibilityModeComplete,
+ ui::kAXModeComplete,
ui::AX_EVENT_CHECKED_STATE_CHANGED));
ExecuteScript(L"document.body.children[0].checked=true");
waiter->WaitForNotification();
@@ -748,7 +747,7 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
// Change the children of the document body.
std::unique_ptr<AccessibilityNotificationWaiter> waiter(
new AccessibilityNotificationWaiter(shell()->web_contents(),
- kAccessibilityModeComplete,
+ ui::kAXModeComplete,
ui::AX_EVENT_CHILDREN_CHANGED));
ExecuteScript(L"document.body.innerHTML='<b>new text</b>'");
waiter->WaitForNotification();
@@ -774,7 +773,7 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
// Change the children of the document body.
std::unique_ptr<AccessibilityNotificationWaiter> waiter(
new AccessibilityNotificationWaiter(shell()->web_contents(),
- kAccessibilityModeComplete,
+ ui::kAXModeComplete,
ui::AX_EVENT_CHILDREN_CHANGED));
ExecuteScript(L"document.body.children[0].style.visibility='visible'");
waiter->WaitForNotification();
@@ -806,9 +805,8 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
// Focus the div in the document
std::unique_ptr<AccessibilityNotificationWaiter> waiter(
- new AccessibilityNotificationWaiter(shell()->web_contents(),
- kAccessibilityModeComplete,
- ui::AX_EVENT_FOCUS));
+ new AccessibilityNotificationWaiter(
+ shell()->web_contents(), ui::kAXModeComplete, ui::AX_EVENT_FOCUS));
ExecuteScript(L"document.body.children[0].focus()");
waiter->WaitForNotification();
@@ -820,7 +818,7 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
// Focus the document accessible. This will un-focus the current node.
waiter.reset(new AccessibilityNotificationWaiter(
- shell()->web_contents(), kAccessibilityModeComplete, ui::AX_EVENT_BLUR));
+ shell()->web_contents(), ui::kAXModeComplete, ui::AX_EVENT_BLUR));
base::win::ScopedComPtr<IAccessible> document_accessible(
GetRendererAccessible());
ASSERT_NE(document_accessible.Get(), reinterpret_cast<IAccessible*>(NULL));
@@ -855,7 +853,7 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
// Set the value of the text control
std::unique_ptr<AccessibilityNotificationWaiter> waiter(
new AccessibilityNotificationWaiter(shell()->web_contents(),
- kAccessibilityModeComplete,
+ ui::kAXModeComplete,
ui::AX_EVENT_VALUE_CHANGED));
ExecuteScript(L"document.body.children[0].value='new value'");
waiter->WaitForNotification();
@@ -1084,20 +1082,20 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, TestCharacterExtents) {
IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
TestCharacterExtentsWithAccessibilityModeChange) {
base::win::ScopedComPtr<IAccessibleText> paragraph_text;
- SetUpSampleParagraph(&paragraph_text, AccessibilityMode::kNativeAPIs |
- AccessibilityMode::kWebContents |
- AccessibilityMode::kScreenReader);
+ SetUpSampleParagraph(&paragraph_text, ui::AXMode::kNativeAPIs |
+ ui::AXMode::kWebContents |
+ ui::AXMode::kScreenReader);
LONG x, y, width, height;
AccessibilityNotificationWaiter waiter(shell()->web_contents(),
- AccessibilityMode::kNativeAPIs |
- AccessibilityMode::kWebContents |
- AccessibilityMode::kScreenReader,
+ ui::AXMode::kNativeAPIs |
+ ui::AXMode::kWebContents |
+ ui::AXMode::kScreenReader,
ui::AX_EVENT_LOAD_COMPLETE);
EXPECT_HRESULT_SUCCEEDED(paragraph_text->get_characterExtents(
0, IA2_COORDTYPE_SCREEN_RELATIVE, &x, &y, &width, &height));
// X and y coordinates should be available without
- // |AccessibilityMode::kInlineTextBoxes|.
+ // |ui::AXMode::kInlineTextBoxes|.
EXPECT_LT(0, x);
EXPECT_LT(0, y);
// Width and height should be unavailable at this point.
@@ -1125,7 +1123,7 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, TestScrollToPoint) {
ASSERT_HRESULT_SUCCEEDED(
paragraph->accLocation(&prev_x, &prev_y, &width, &height, childid_self));
AccessibilityNotificationWaiter location_changed_waiter(
- shell()->web_contents(), kAccessibilityModeComplete,
+ shell()->web_contents(), ui::kAXModeComplete,
ui::AX_EVENT_LOCATION_CHANGED);
EXPECT_HRESULT_SUCCEEDED(
paragraph->scrollToPoint(IA2_COORDTYPE_PARENT_RELATIVE, 0, 0));
@@ -1157,7 +1155,7 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, TestSetCaretOffset) {
EXPECT_EQ(CONTENTS_LENGTH - 1, caret_offset);
AccessibilityNotificationWaiter waiter(shell()->web_contents(),
- kAccessibilityModeComplete,
+ ui::kAXModeComplete,
ui::AX_EVENT_TEXT_SELECTION_CHANGED);
caret_offset = 0;
hr = input_text->setCaretOffset(caret_offset);
@@ -1180,7 +1178,7 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
EXPECT_EQ(CONTENTS_LENGTH - 1, caret_offset);
AccessibilityNotificationWaiter waiter(shell()->web_contents(),
- kAccessibilityModeComplete,
+ ui::kAXModeComplete,
ui::AX_EVENT_TEXT_SELECTION_CHANGED);
caret_offset = 0;
hr = textarea_text->setCaretOffset(caret_offset);
@@ -1204,7 +1202,7 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, TestSetSelection) {
EXPECT_EQ(E_INVALIDARG, hr);
AccessibilityNotificationWaiter waiter(shell()->web_contents(),
- kAccessibilityModeComplete,
+ ui::kAXModeComplete,
ui::AX_EVENT_TEXT_SELECTION_CHANGED);
start_offset = 0;
end_offset = CONTENTS_LENGTH;
@@ -1243,7 +1241,7 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, TestMultiLineSetSelection) {
EXPECT_EQ(E_INVALIDARG, hr);
AccessibilityNotificationWaiter waiter(shell()->web_contents(),
- kAccessibilityModeComplete,
+ ui::kAXModeComplete,
ui::AX_EVENT_TEXT_SELECTION_CHANGED);
start_offset = 0;
end_offset = CONTENTS_LENGTH;
@@ -1281,7 +1279,7 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
ASSERT_LT(0, n_characters);
AccessibilityNotificationWaiter waiter(
- shell()->web_contents(), kAccessibilityModeComplete,
+ shell()->web_contents(), ui::kAXModeComplete,
ui::AX_EVENT_DOCUMENT_SELECTION_CHANGED);
LONG start_offset = 0;
LONG end_offset = n_characters;
@@ -1898,9 +1896,8 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, TestIAccessibleAction) {
image_name.Release();
// Cllicking the image will change its name.
EXPECT_HRESULT_SUCCEEDED(image_action->doAction(0));
- AccessibilityNotificationWaiter waiter(shell()->web_contents(),
- kAccessibilityModeComplete,
- ui::AX_EVENT_TEXT_CHANGED);
+ AccessibilityNotificationWaiter waiter(
+ shell()->web_contents(), ui::kAXModeComplete, ui::AX_EVENT_TEXT_CHANGED);
waiter.WaitForNotification();
EXPECT_HRESULT_SUCCEEDED(
image->get_accName(childid_self, image_name.Receive()));
@@ -1925,9 +1922,8 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, HasHWNDAfterNavigation) {
web_contents_view_aura->set_init_rwhv_with_null_parent_for_testing(true);
// Navigate to a new page and wait for the accessibility tree to load.
- AccessibilityNotificationWaiter waiter(shell()->web_contents(),
- kAccessibilityModeComplete,
- ui::AX_EVENT_LOAD_COMPLETE);
+ AccessibilityNotificationWaiter waiter(
+ shell()->web_contents(), ui::kAXModeComplete, ui::AX_EVENT_LOAD_COMPLETE);
NavigateToURL(shell(), embedded_test_server()->GetURL(
"/accessibility/html/article.html"));
waiter.WaitForNotification();
@@ -1948,9 +1944,8 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, HasHWNDAfterNavigation) {
IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, TestAccNavigateInTables) {
ASSERT_TRUE(embedded_test_server()->Start());
- AccessibilityNotificationWaiter waiter(shell()->web_contents(),
- kAccessibilityModeComplete,
- ui::AX_EVENT_LOAD_COMPLETE);
+ AccessibilityNotificationWaiter waiter(
+ shell()->web_contents(), ui::kAXModeComplete, ui::AX_EVENT_LOAD_COMPLETE);
NavigateToURL(shell(), embedded_test_server()->GetURL(
"/accessibility/html/table-spans.html"));
waiter.WaitForNotification();
diff --git a/chromium/content/browser/accessibility/android_granularity_movement_browsertest.cc b/chromium/content/browser/accessibility/android_granularity_movement_browsertest.cc
index 4e7d6eb2d1f..fffbd1da712 100644
--- a/chromium/content/browser/accessibility/android_granularity_movement_browsertest.cc
+++ b/chromium/content/browser/accessibility/android_granularity_movement_browsertest.cc
@@ -40,7 +40,7 @@ class AndroidGranularityMovementBrowserTest : public ContentBrowserTest {
// Load the page.
AccessibilityNotificationWaiter waiter(shell()->web_contents(),
- kAccessibilityModeComplete,
+ ui::kAXModeComplete,
ui::AX_EVENT_LOAD_COMPLETE);
NavigateToURL(shell(), url);
waiter.WaitForNotification();
@@ -70,9 +70,9 @@ class AndroidGranularityMovementBrowserTest : public ContentBrowserTest {
BrowserAccessibility* node,
int granularity) {
AccessibilityNotificationWaiter waiter(shell()->web_contents(),
- kAccessibilityModeComplete,
+ ui::kAXModeComplete,
ui::AX_EVENT_TREE_CHANGED);
- node->manager()->SetAccessibilityFocus(*node);
+ node->manager()->LoadInlineTextBoxes(*node);
waiter.WaitForNotification();
int start_index = -1;
diff --git a/chromium/content/browser/accessibility/browser_accessibility.cc b/chromium/content/browser/accessibility/browser_accessibility.cc
index 3824914ff94..27c92a92733 100644
--- a/chromium/content/browser/accessibility/browser_accessibility.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility.cc
@@ -17,20 +17,11 @@
#include "content/common/accessibility_messages.h"
#include "ui/accessibility/ax_role_properties.h"
#include "ui/accessibility/ax_text_utils.h"
-#include "ui/accessibility/platform/ax_platform_unique_id.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/geometry/rect_f.h"
namespace content {
-namespace {
-
-// Map from unique_id to BrowserAccessibility
-using UniqueIDMap = base::hash_map<int32_t, BrowserAccessibility*>;
-base::LazyInstance<UniqueIDMap>::DestructorAtExit g_unique_id_map =
- LAZY_INSTANCE_INITIALIZER;
-}
-
#if !defined(PLATFORM_HAS_NATIVE_ACCESSIBILITY_IMPL)
// static
BrowserAccessibility* BrowserAccessibility::Create() {
@@ -39,24 +30,9 @@ BrowserAccessibility* BrowserAccessibility::Create() {
#endif
BrowserAccessibility::BrowserAccessibility()
- : manager_(nullptr),
- node_(nullptr),
- unique_id_(ui::GetNextAXPlatformNodeUniqueId()) {
- g_unique_id_map.Get()[unique_id_] = this;
-}
+ : manager_(nullptr), node_(nullptr) {}
BrowserAccessibility::~BrowserAccessibility() {
- if (unique_id_)
- g_unique_id_map.Get().erase(unique_id_);
-}
-
-// static
-BrowserAccessibility* BrowserAccessibility::GetFromUniqueID(int32_t unique_id) {
- auto iter = g_unique_id_map.Get().find(unique_id);
- if (iter == g_unique_id_map.Get().end())
- return nullptr;
-
- return iter->second;
}
void BrowserAccessibility::Init(BrowserAccessibilityManager* manager,
@@ -573,10 +549,6 @@ void BrowserAccessibility::Destroy() {
node_ = NULL;
manager_ = NULL;
- if (unique_id_)
- g_unique_id_map.Get().erase(unique_id_);
- unique_id_ = 0;
-
NativeReleaseReference();
}
@@ -904,6 +876,9 @@ gfx::Rect BrowserAccessibility::RelativeToAbsoluteBounds(
}
}
+ if (frame_only)
+ break;
+
node = root->PlatformGetParent();
}
diff --git a/chromium/content/browser/accessibility/browser_accessibility.h b/chromium/content/browser/accessibility/browser_accessibility.h
index e790989dff6..7801e01305c 100644
--- a/chromium/content/browser/accessibility/browser_accessibility.h
+++ b/chromium/content/browser/accessibility/browser_accessibility.h
@@ -75,8 +75,6 @@ class CONTENT_EXPORT BrowserAccessibility : public ui::AXPlatformNodeDelegate {
virtual ~BrowserAccessibility();
- static BrowserAccessibility* GetFromUniqueID(int32_t unique_id);
-
// Called only once, immediately after construction. The constructor doesn't
// take any arguments because in the Windows subclass we use a special
// function to construct a COM object.
@@ -207,7 +205,6 @@ class CONTENT_EXPORT BrowserAccessibility : public ui::AXPlatformNodeDelegate {
BrowserAccessibilityManager* manager() const { return manager_; }
bool instance_active() const { return node_ && manager_; }
ui::AXNode* node() const { return node_; }
- int32_t unique_id() const { return unique_id_; }
// These access the internal accessibility tree, which doesn't necessarily
// reflect the accessibility tree that should be exposed on each platform.
diff --git a/chromium/content/browser/accessibility/browser_accessibility_android.cc b/chromium/content/browser/accessibility/browser_accessibility_android.cc
index 66c5910cc35..556bed4ff5d 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_android.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_android.cc
@@ -4,7 +4,9 @@
#include "content/browser/accessibility/browser_accessibility_android.h"
+#include "base/containers/hash_tables.h"
#include "base/i18n/break_iterator.h"
+#include "base/lazy_instance.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
@@ -16,6 +18,7 @@
#include "third_party/skia/include/core/SkColor.h"
#include "ui/accessibility/ax_role_properties.h"
#include "ui/accessibility/platform/ax_android_constants.h"
+#include "ui/accessibility/platform/ax_platform_unique_id.h"
#include "ui/accessibility/platform/ax_snapshot_node_android_platform.h"
namespace aria_strings {
@@ -62,10 +65,33 @@ BrowserAccessibility* BrowserAccessibility::Create() {
return new BrowserAccessibilityAndroid();
}
-BrowserAccessibilityAndroid::BrowserAccessibilityAndroid() {
+using UniqueIdMap = base::hash_map<int32_t, BrowserAccessibilityAndroid*>;
+// Map from each AXPlatformNode's unique id to its instance.
+base::LazyInstance<UniqueIdMap>::DestructorAtExit g_unique_id_map =
+ LAZY_INSTANCE_INITIALIZER;
+
+// static
+BrowserAccessibilityAndroid* BrowserAccessibilityAndroid::GetFromUniqueId(
+ int32_t unique_id) {
+ UniqueIdMap* unique_ids = g_unique_id_map.Pointer();
+ auto iter = unique_ids->find(unique_id);
+ if (iter != unique_ids->end())
+ return iter->second;
+
+ return nullptr;
+}
+
+BrowserAccessibilityAndroid::BrowserAccessibilityAndroid()
+ : unique_id_(ui::GetNextAXPlatformNodeUniqueId()) {
+ g_unique_id_map.Get()[unique_id_] = this;
first_time_ = true;
}
+BrowserAccessibilityAndroid::~BrowserAccessibilityAndroid() {
+ if (unique_id_)
+ g_unique_id_map.Get().erase(unique_id_);
+}
+
bool BrowserAccessibilityAndroid::IsNative() const {
return true;
}
@@ -198,7 +224,11 @@ bool BrowserAccessibilityAndroid::IsDismissable() const {
}
bool BrowserAccessibilityAndroid::IsEditableText() const {
- return GetRole() == ui::AX_ROLE_TEXT_FIELD;
+ // TODO(dmazzoni): Use utility function in ax_role_properties, and
+ // handle different types of combo boxes correctly.
+ return GetRole() == ui::AX_ROLE_TEXT_FIELD ||
+ GetRole() == ui::AX_ROLE_SEARCH_BOX ||
+ GetRole() == ui::AX_ROLE_COMBO_BOX;
}
bool BrowserAccessibilityAndroid::IsEnabled() const {
@@ -264,8 +294,7 @@ bool BrowserAccessibilityAndroid::IsRangeType() const {
}
bool BrowserAccessibilityAndroid::IsScrollable() const {
- return (HasIntAttribute(ui::AX_ATTR_SCROLL_X_MAX) &&
- GetRole() != ui::AX_ROLE_SCROLL_AREA);
+ return HasIntAttribute(ui::AX_ATTR_SCROLL_X_MAX);
}
bool BrowserAccessibilityAndroid::IsSelected() const {
@@ -322,6 +351,23 @@ const BrowserAccessibilityAndroid*
return sole_interesting_node;
}
+bool BrowserAccessibilityAndroid::AreInlineTextBoxesLoaded() const {
+ if (GetRole() == ui::AX_ROLE_STATIC_TEXT)
+ return InternalChildCount() > 0;
+
+ // Return false if any descendant needs to load inline text boxes.
+ for (uint32_t i = 0; i < InternalChildCount(); ++i) {
+ BrowserAccessibilityAndroid* child =
+ static_cast<BrowserAccessibilityAndroid*>(InternalGetChild(i));
+ if (!child->AreInlineTextBoxesLoaded())
+ return false;
+ }
+
+ // Otherwise return true - either they're all loaded, or there aren't
+ // any descendants that need to load inline text boxes.
+ return true;
+}
+
bool BrowserAccessibilityAndroid::CanOpenPopup() const {
return HasState(ui::AX_STATE_HASPOPUP);
}
@@ -337,25 +383,11 @@ base::string16 BrowserAccessibilityAndroid::GetText() const {
return base::string16();
}
- // We can only expose one accessible name on Android,
- // not 2 or 3 like on Windows or Mac.
-
// First, always return the |value| attribute if this is an
// input field.
base::string16 value = GetValue();
- if (!value.empty()) {
- if (HasState(ui::AX_STATE_EDITABLE))
- return value;
-
- switch (GetRole()) {
- case ui::AX_ROLE_COMBO_BOX:
- case ui::AX_ROLE_POP_UP_BUTTON:
- case ui::AX_ROLE_TEXT_FIELD:
- return value;
- default:
- break;
- }
- }
+ if (ShouldExposeValueAsName())
+ return value;
// For color wells, the color is stored in separate attributes.
// Perhaps we could return color names in the future?
@@ -370,13 +402,6 @@ base::string16 BrowserAccessibilityAndroid::GetText() const {
}
base::string16 text = GetString16Attribute(ui::AX_ATTR_NAME);
- base::string16 description = GetString16Attribute(ui::AX_ATTR_DESCRIPTION);
- if (!description.empty()) {
- if (!text.empty())
- text += base::ASCIIToUTF16(" ");
- text += description;
- }
-
if (text.empty())
text = value;
@@ -406,6 +431,22 @@ base::string16 BrowserAccessibilityAndroid::GetText() const {
return text;
}
+base::string16 BrowserAccessibilityAndroid::GetHint() const {
+ base::string16 description = GetString16Attribute(ui::AX_ATTR_DESCRIPTION);
+
+ // If we're returning the value as the main text, then return both the
+ // accessible name and description as the hint.
+ if (ShouldExposeValueAsName()) {
+ base::string16 name = GetString16Attribute(ui::AX_ATTR_NAME);
+ if (!name.empty() && !description.empty())
+ return name + base::ASCIIToUTF16(" ") + description;
+ else if (!name.empty())
+ return name;
+ }
+
+ return description;
+}
+
base::string16 BrowserAccessibilityAndroid::GetRoleDescription() const {
content::ContentClient* content_client = content::GetContentClient();
@@ -454,9 +495,6 @@ base::string16 BrowserAccessibilityAndroid::GetRoleDescription() const {
case ui::AX_ROLE_BLOCKQUOTE:
message_id = IDS_AX_ROLE_BLOCKQUOTE;
break;
- case ui::AX_ROLE_BUSY_INDICATOR:
- message_id = IDS_AX_ROLE_BUSY_INDICATOR;
- break;
case ui::AX_ROLE_BUTTON:
message_id = IDS_AX_ROLE_BUTTON;
break;
@@ -576,9 +614,6 @@ base::string16 BrowserAccessibilityAndroid::GetRoleDescription() const {
case ui::AX_ROLE_IGNORED:
// No role description.
break;
- case ui::AX_ROLE_IMAGE_MAP_LINK:
- message_id = IDS_AX_ROLE_LINK;
- break;
case ui::AX_ROLE_IMAGE_MAP:
message_id = IDS_AX_ROLE_GRAPHIC;
break;
@@ -669,9 +704,6 @@ base::string16 BrowserAccessibilityAndroid::GetRoleDescription() const {
case ui::AX_ROLE_NOTE:
message_id = IDS_AX_ROLE_NOTE;
break;
- case ui::AX_ROLE_OUTLINE:
- message_id = IDS_AX_ROLE_OUTLINE;
- break;
case ui::AX_ROLE_PANE:
// No role description.
break;
@@ -711,21 +743,12 @@ base::string16 BrowserAccessibilityAndroid::GetRoleDescription() const {
case ui::AX_ROLE_RUBY:
// No role description.
break;
- case ui::AX_ROLE_RULER:
- message_id = IDS_AX_ROLE_RULER;
- break;
case ui::AX_ROLE_SVG_ROOT:
message_id = IDS_AX_ROLE_GRAPHIC;
break;
- case ui::AX_ROLE_SCROLL_AREA:
- // No role description.
- break;
case ui::AX_ROLE_SCROLL_BAR:
message_id = IDS_AX_ROLE_SCROLL_BAR;
break;
- case ui::AX_ROLE_SEAMLESS_WEB_AREA:
- // No role description.
- break;
case ui::AX_ROLE_SEARCH:
message_id = IDS_AX_ROLE_SEARCH;
break;
@@ -756,9 +779,6 @@ base::string16 BrowserAccessibilityAndroid::GetRoleDescription() const {
case ui::AX_ROLE_SWITCH:
message_id = IDS_AX_ROLE_SWITCH;
break;
- case ui::AX_ROLE_TAB_GROUP:
- // No role description.
- break;
case ui::AX_ROLE_TAB_LIST:
message_id = IDS_AX_ROLE_TAB_LIST;
break;
@@ -1062,6 +1082,9 @@ size_t BrowserAccessibilityAndroid::CommonSuffixLength(
return i;
}
+// TODO(nektar): Merge this function with
+// |BrowserAccessibilityCocoa::computeTextEdit|.
+//
// static
size_t BrowserAccessibilityAndroid::CommonEndLengths(
const base::string16 a,
@@ -1361,6 +1384,26 @@ bool BrowserAccessibilityAndroid::IsIframe() const {
GetRole() == ui::AX_ROLE_IFRAME_PRESENTATIONAL);
}
+bool BrowserAccessibilityAndroid::ShouldExposeValueAsName() const {
+ base::string16 value = GetValue();
+ if (value.empty())
+ return false;
+
+ if (HasState(ui::AX_STATE_EDITABLE))
+ return true;
+
+ switch (GetRole()) {
+ case ui::AX_ROLE_COMBO_BOX:
+ case ui::AX_ROLE_POP_UP_BUTTON:
+ case ui::AX_ROLE_TEXT_FIELD:
+ return true;
+ default:
+ break;
+ }
+
+ return false;
+}
+
void BrowserAccessibilityAndroid::OnDataChanged() {
BrowserAccessibility::OnDataChanged();
diff --git a/chromium/content/browser/accessibility/browser_accessibility_android.h b/chromium/content/browser/accessibility/browser_accessibility_android.h
index d9e5ad05e3a..b8f6e56b82e 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_android.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_android.h
@@ -11,11 +11,15 @@
#include "base/android/scoped_java_ref.h"
#include "base/macros.h"
#include "content/browser/accessibility/browser_accessibility.h"
+#include "ui/accessibility/platform/ax_platform_node.h"
namespace content {
class CONTENT_EXPORT BrowserAccessibilityAndroid : public BrowserAccessibility {
public:
+ static BrowserAccessibilityAndroid* GetFromUniqueId(int32_t unique_id);
+ int32_t unique_id() const { return unique_id_; }
+
// Overrides from BrowserAccessibility.
void OnDataChanged() override;
bool IsNative() const override;
@@ -60,6 +64,10 @@ class CONTENT_EXPORT BrowserAccessibilityAndroid : public BrowserAccessibility {
// if more than one is interesting, returns nullptr.
const BrowserAccessibilityAndroid* GetSoleInterestingNodeFromSubtree() const;
+ // Returns true if the given subtree has inline text box data, or if there
+ // aren't any to load.
+ bool AreInlineTextBoxesLoaded() const;
+
bool CanOpenPopup() const;
bool HasFocusableNonOptionChild() const;
@@ -67,6 +75,7 @@ class CONTENT_EXPORT BrowserAccessibilityAndroid : public BrowserAccessibility {
const char* GetClassName() const;
base::string16 GetText() const override;
+ base::string16 GetHint() const;
base::string16 GetRoleDescription() const;
@@ -137,10 +146,12 @@ class CONTENT_EXPORT BrowserAccessibilityAndroid : public BrowserAccessibility {
friend class BrowserAccessibility;
BrowserAccessibilityAndroid();
+ ~BrowserAccessibilityAndroid() override;
bool HasOnlyTextChildren() const;
bool HasOnlyTextAndImageChildren() const;
bool IsIframe() const;
+ bool ShouldExposeValueAsName() const;
void NotifyLiveRegionUpdate(base::string16& aria_live);
@@ -157,6 +168,7 @@ class CONTENT_EXPORT BrowserAccessibilityAndroid : public BrowserAccessibility {
bool first_time_;
base::string16 old_value_;
base::string16 new_value_;
+ int32_t unique_id_;
DISALLOW_COPY_AND_ASSIGN(BrowserAccessibilityAndroid);
};
diff --git a/chromium/content/browser/accessibility/browser_accessibility_auralinux.cc b/chromium/content/browser/accessibility/browser_accessibility_auralinux.cc
index 9caccec3edb..11d709daf89 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_auralinux.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_auralinux.cc
@@ -571,7 +571,7 @@ static AtkStateSet* browser_accessibility_ref_state_set(AtkObject* atk_object) {
// it's best to leave this out rather than break people's builds:
#if defined(ATK_CHECK_VERSION)
#if ATK_CHECK_VERSION(2, 16, 0)
- atk_state_set_add_state(atk_state_set, ATK_STATE_READ_ONLY);
+ atk_state_set_add_state(state_set, ATK_STATE_READ_ONLY);
#endif
#endif
break;
diff --git a/chromium/content/browser/accessibility/browser_accessibility_cocoa.h b/chromium/content/browser/accessibility/browser_accessibility_cocoa.h
index 39d89e11830..e7743707caf 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_cocoa.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_cocoa.h
@@ -8,9 +8,27 @@
#import <Cocoa/Cocoa.h>
#import "base/mac/scoped_nsobject.h"
+#include "base/strings/string16.h"
#include "content/browser/accessibility/browser_accessibility.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
+namespace content {
+
+// Used to store changes in edit fields, required by VoiceOver in order to
+// support character echo and other announcements during editing.
+struct AXTextEdit {
+ AXTextEdit() = default;
+ AXTextEdit(base::string16 inserted_text, base::string16 deleted_text)
+ : inserted_text(inserted_text), deleted_text(deleted_text) {}
+
+ bool IsEmpty() const { return inserted_text.empty() && deleted_text.empty(); }
+
+ base::string16 inserted_text;
+ base::string16 deleted_text;
+};
+
+} // namespace content
+
// BrowserAccessibilityCocoa is a cocoa wrapper around the BrowserAccessibility
// object. The renderer converts webkit's accessibility tree into a
// WebAccessibility tree and passes it to the browser process over IPC.
@@ -19,6 +37,8 @@
@private
content::BrowserAccessibility* browserAccessibility_;
base::scoped_nsobject<NSMutableArray> children_;
+ // Stores the previous value of an edit field.
+ base::string16 oldValue_;
}
// This creates a cocoa browser accessibility object around
@@ -37,10 +57,6 @@
// from browserAccessibility_.
- (ui::AXRole)internalRole;
-// Convenience method to determine if this object should expose its
-// accessible name in AXValue (as opposed to AXTitle/AXDescription).
-- (BOOL)shouldExposeNameInAXValue;
-
// Convenience method to get the BrowserAccessibilityDelegate from
// the manager.
- (content::BrowserAccessibilityDelegate*)delegate;
@@ -48,6 +64,9 @@
// Get the BrowserAccessibility that this object wraps.
- (content::BrowserAccessibility*)browserAccessibility;
+// Computes the text that was added or deleted in a text field after an edit.
+- (content::AXTextEdit)computeTextEdit;
+
// Determines if this object is alive, i.e. it hasn't been detached.
- (BOOL)instanceActive;
@@ -84,6 +103,8 @@
@property(nonatomic, readonly) NSNumber* disclosureLevel;
@property(nonatomic, readonly) id disclosedRows;
@property(nonatomic, readonly) NSString* dropEffects;
+// Returns the object at the root of the current edit field, if any.
+@property(nonatomic, readonly) id editableAncestor;
@property(nonatomic, readonly) NSNumber* enabled;
// Returns a text marker that points to the last character in the document that
// can be selected with Voiceover.
diff --git a/chromium/content/browser/accessibility/browser_accessibility_cocoa.mm b/chromium/content/browser/accessibility/browser_accessibility_cocoa.mm
index 0cc1795731d..825d2609dbf 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_cocoa.mm
+++ b/chromium/content/browser/accessibility/browser_accessibility_cocoa.mm
@@ -16,7 +16,7 @@
#include "base/mac/availability.h"
#include "base/mac/foundation_util.h"
#include "base/mac/scoped_cftyperef.h"
-#include "base/strings/string16.h"
+#include "base/strings/string_util.h"
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "content/app/strings/grit/content_strings.h"
@@ -65,7 +65,11 @@ NSString* const NSAccessibilityARIASetSizeAttribute = @"AXARIASetSize";
NSString* const NSAccessibilityAccessKeyAttribute = @"AXAccessKey";
NSString* const NSAccessibilityDOMIdentifierAttribute = @"AXDOMIdentifier";
NSString* const NSAccessibilityDropEffectsAttribute = @"AXDropEffects";
+NSString* const NSAccessibilityEditableAncestorAttribute =
+ @"AXEditableAncestor";
NSString* const NSAccessibilityGrabbedAttribute = @"AXGrabbed";
+NSString* const NSAccessibilityHighestEditableAncestorAttribute =
+ @"AXHighestEditableAncestor";
NSString* const NSAccessibilityInvalidAttribute = @"AXInvalid";
NSString* const NSAccessibilityIsMultiSelectableAttribute =
@"AXIsMultiSelectable";
@@ -533,6 +537,11 @@ extern "C" {
NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
}
+// Not defined in current versions of library, but may be in the future:
+#ifndef NSAccessibilityLanguageAttribute
+#define NSAccessibilityLanguageAttribute @"AXLanguage"
+#endif
+
@implementation BrowserAccessibilityCocoa
+ (void)initialize {
@@ -563,6 +572,7 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
{NSAccessibilityDisclosedRowsAttribute, @"disclosedRows"},
{NSAccessibilityDropEffectsAttribute, @"dropEffects"},
{NSAccessibilityDOMIdentifierAttribute, @"domIdentifier"},
+ {NSAccessibilityEditableAncestorAttribute, @"editableAncestor"},
{NSAccessibilityEnabledAttribute, @"enabled"},
{NSAccessibilityEndTextMarkerAttribute, @"endTextMarker"},
{NSAccessibilityExpandedAttribute, @"expanded"},
@@ -570,11 +580,14 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
{NSAccessibilityGrabbedAttribute, @"grabbed"},
{NSAccessibilityHeaderAttribute, @"header"},
{NSAccessibilityHelpAttribute, @"help"},
+ {NSAccessibilityHighestEditableAncestorAttribute,
+ @"highestEditableAncestor"},
{NSAccessibilityIndexAttribute, @"index"},
{NSAccessibilityInsertionPointLineNumberAttribute,
@"insertionPointLineNumber"},
{NSAccessibilityInvalidAttribute, @"invalid"},
{NSAccessibilityIsMultiSelectableAttribute, @"isMultiSelectable"},
+ {NSAccessibilityLanguageAttribute, @"language"},
{NSAccessibilityLinkedUIElementsAttribute, @"linkedUIElements"},
{NSAccessibilityLoadingProgressAttribute, @"loadingProgress"},
{NSAccessibilityMaxValueAttribute, @"maxValue"},
@@ -662,8 +675,8 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
- (NSNumber*)ariaBusy {
if (![self instanceActive])
return nil;
- return [NSNumber numberWithBool:
- GetState(browserAccessibility_, ui::AX_STATE_BUSY)];
+ return [NSNumber
+ numberWithBool:browserAccessibility_->GetBoolAttribute(ui::AX_ATTR_BUSY)];
}
- (NSNumber*)ariaColumnCount {
@@ -841,7 +854,7 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
return nil;
// Mac OS X wants static text exposed in AXValue.
- if ([self shouldExposeNameInAXValue])
+ if (ui::IsNameExposedInAXValueForRole([self internalRole]))
return @"";
// If we're exposing the title in TitleUIElement, don't also redundantly
@@ -869,8 +882,6 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
// Given an image where there's no other title, return the base part
// of the filename as the description.
if ([[self role] isEqualToString:NSAccessibilityImageRole]) {
- if (browserAccessibility_->HasExplicitlyEmptyName())
- return @"";
if ([self titleUIElement])
return @"";
@@ -968,6 +979,23 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
return nil;
}
+- (id)editableAncestor {
+ if (![self instanceActive])
+ return nil;
+
+ BrowserAccessibilityCocoa* editableRoot = self;
+ while (![editableRoot browserAccessibility]->GetBoolAttribute(
+ ui::AX_ATTR_EDITABLE_ROOT)) {
+ BrowserAccessibilityCocoa* parent = [editableRoot parent];
+ if (!parent || ![parent isKindOfClass:[self class]] ||
+ ![parent instanceActive]) {
+ return nil;
+ }
+ editableRoot = parent;
+ }
+ return editableRoot;
+}
+
- (NSNumber*)enabled {
if (![self instanceActive])
return nil;
@@ -1046,6 +1074,26 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
browserAccessibility_, ui::AX_ATTR_DESCRIPTION);
}
+- (id)highestEditableAncestor {
+ if (![self instanceActive])
+ return nil;
+
+ BrowserAccessibilityCocoa* highestEditableAncestor = [self editableAncestor];
+ while (highestEditableAncestor) {
+ BrowserAccessibilityCocoa* ancestorParent =
+ [highestEditableAncestor parent];
+ if (!ancestorParent || ![ancestorParent isKindOfClass:[self class]]) {
+ break;
+ }
+ BrowserAccessibilityCocoa* higherAncestor =
+ [ancestorParent editableAncestor];
+ if (!higherAncestor)
+ break;
+ highestEditableAncestor = higherAncestor;
+ }
+ return highestEditableAncestor;
+}
+
- (NSNumber*)index {
if (![self instanceActive])
return nil;
@@ -1158,6 +1206,13 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
browserAccessibility_, ui::AX_ATTR_PLACEHOLDER);
}
+- (NSString*)language {
+ if (![self instanceActive])
+ return nil;
+ return NSStringForStringAttribute(browserAccessibility_,
+ ui::AX_ATTR_LANGUAGE);
+}
+
// private
- (void)addLinkedUIElementsFromAttribute:(ui::AXIntListAttribute)attribute
addTo:(NSMutableArray*)outArray {
@@ -1290,20 +1345,6 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
return static_cast<ui::AXRole>(browserAccessibility_->GetRole());
}
-// Returns true if this should expose its accessible name in AXValue.
-// internal
-- (BOOL)shouldExposeNameInAXValue {
- switch ([self internalRole]) {
- case ui::AX_ROLE_LIST_BOX_OPTION:
- case ui::AX_ROLE_LIST_MARKER:
- case ui::AX_ROLE_MENU_LIST_OPTION:
- case ui::AX_ROLE_STATIC_TEXT:
- return true;
- default:
- return false;
- }
-}
-
// Returns true if this object should expose its accessible name using
// AXTitleUIElement rather than AXTitle or AXDescription. We only do
// this if it's a control, if there's a single label, and the label has
@@ -1343,6 +1384,45 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
return browserAccessibility_;
}
+// Assumes that there is at most one insertion, deletion or replacement at once.
+// TODO(nektar): Merge this method with
+// |BrowserAccessibilityAndroid::CommonEndLengths|.
+- (content::AXTextEdit)computeTextEdit {
+ // Starting from macOS 10.11, if the user has edited some text we need to
+ // dispatch the actual text that changed on the value changed notification.
+ // We run this code on all macOS versions to get the highest test coverage.
+ base::string16 oldValue = oldValue_;
+ base::string16 newValue = browserAccessibility_->GetValue();
+ oldValue_ = newValue;
+ if (oldValue.empty() && newValue.empty())
+ return content::AXTextEdit();
+
+ size_t i;
+ size_t j;
+ // Sometimes Blink doesn't use the same UTF16 characters to represent
+ // whitespace.
+ for (i = 0;
+ i < oldValue.length() && i < newValue.length() &&
+ (oldValue[i] == newValue[i] || (base::IsUnicodeWhitespace(oldValue[i]) &&
+ base::IsUnicodeWhitespace(newValue[i])));
+ ++i) {
+ }
+ for (j = 0;
+ (i + j) < oldValue.length() && (i + j) < newValue.length() &&
+ (oldValue[oldValue.length() - j - 1] ==
+ newValue[newValue.length() - j - 1] ||
+ (base::IsUnicodeWhitespace(oldValue[oldValue.length() - j - 1]) &&
+ base::IsUnicodeWhitespace(newValue[newValue.length() - j - 1])));
+ ++j) {
+ }
+ DCHECK_LE(i + j, oldValue.length());
+ DCHECK_LE(i + j, newValue.length());
+
+ base::string16 deletedText = oldValue.substr(i, oldValue.length() - i - j);
+ base::string16 insertedText = newValue.substr(i, newValue.length() - i - j);
+ return content::AXTextEdit(insertedText, deletedText);
+}
+
- (BOOL)instanceActive {
return browserAccessibility_ && browserAccessibility_->instance_active();
}
@@ -1384,6 +1464,10 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
return NSAccessibilityTextAreaRole;
}
+ if (role == ui::AX_ROLE_IMAGE &&
+ browserAccessibility_->HasExplicitlyEmptyName())
+ return NSAccessibilityUnknownRole;
+
// If this is a web area for a presentational iframe, give it a role of
// something other than WebArea so that the fact that it's a separate doc
// is not exposed to AT.
@@ -1797,7 +1881,7 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
if (![self instanceActive])
return nil;
// Mac OS X wants static text exposed in AXValue.
- if ([self shouldExposeNameInAXValue])
+ if (ui::IsNameExposedInAXValueForRole([self internalRole]))
return @"";
// If we're exposing the title in TitleUIElement, don't also redundantly
@@ -1859,11 +1943,12 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
- (id)value {
if (![self instanceActive])
return nil;
+
+ if (ui::IsNameExposedInAXValueForRole([self internalRole]))
+ return NSStringForStringAttribute(browserAccessibility_, ui::AX_ATTR_NAME);
+
NSString* role = [self role];
- if ([self shouldExposeNameInAXValue]) {
- return NSStringForStringAttribute(
- browserAccessibility_, ui::AX_ATTR_NAME);
- } else if ([role isEqualToString:@"AXHeading"]) {
+ if ([role isEqualToString:@"AXHeading"]) {
int level = 0;
if (browserAccessibility_->GetIntAttribute(
ui::AX_ATTR_HIERARCHICAL_LEVEL, &level)) {
@@ -1954,7 +2039,10 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
for (uint32_t index = 0; index < childCount; ++index) {
BrowserAccessibilityCocoa* child = ToBrowserAccessibilityCocoa(
browserAccessibility_->PlatformGetChild(index));
- [ret addObject:child];
+ if ([child isIgnored])
+ [ret addObjectsFromArray:[child visibleChildren]];
+ else
+ [ret addObject:child];
}
return ret;
}
@@ -2014,15 +2102,23 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
if (![self instanceActive])
return nil;
+ base::string16 text = browserAccessibility_->GetValue();
+ if (browserAccessibility_->IsTextOnlyObject() && text.empty())
+ text = browserAccessibility_->GetText();
+
// We need to get the whole text because a spelling mistake might start or end
// outside our range.
- NSString* value = base::SysUTF16ToNSString(browserAccessibility_->GetValue());
+ NSString* value = base::SysUTF16ToNSString(text);
NSMutableAttributedString* attributedValue =
[[[NSMutableAttributedString alloc] initWithString:value] autorelease];
- std::vector<const BrowserAccessibility*> textOnlyObjects =
- BrowserAccessibilityManager::FindTextOnlyObjectsInRange(
- *browserAccessibility_, *browserAccessibility_);
- AddMisspelledTextAttributes(textOnlyObjects, attributedValue);
+
+ if (!browserAccessibility_->IsTextOnlyObject()) {
+ std::vector<const BrowserAccessibility*> textOnlyObjects =
+ BrowserAccessibilityManager::FindTextOnlyObjectsInRange(
+ *browserAccessibility_, *browserAccessibility_);
+ AddMisspelledTextAttributes(textOnlyObjects, attributedValue);
+ }
+
return [attributedValue attributedSubstringFromRange:range];
}
@@ -2172,7 +2268,8 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
CreatePositionFromTextMarker(parameter);
if (position->IsNullPosition())
return nil;
- return CreateTextMarker(position->CreateNextCharacterPosition());
+ return CreateTextMarker(position->CreateNextCharacterPosition(
+ ui::AXBoundaryBehavior::CrossBoundary));
}
if ([attribute isEqualToString:@"AXPreviousTextMarkerForTextMarker"]) {
@@ -2180,7 +2277,8 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
CreatePositionFromTextMarker(parameter);
if (position->IsNullPosition())
return nil;
- return CreateTextMarker(position->CreatePreviousCharacterPosition());
+ return CreateTextMarker(position->CreatePreviousCharacterPosition(
+ ui::AXBoundaryBehavior::CrossBoundary));
}
if ([attribute isEqualToString:@"AXLeftWordTextMarkerRangeForTextMarker"]) {
@@ -2190,9 +2288,11 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
return nil;
AXPlatformPositionInstance startWordPosition =
- endPosition->CreatePreviousWordStartPosition();
+ endPosition->CreatePreviousWordStartPosition(
+ ui::AXBoundaryBehavior::StopAtAnchorBoundary);
AXPlatformPositionInstance endWordPosition =
- endPosition->CreatePreviousWordEndPosition();
+ endPosition->CreatePreviousWordEndPosition(
+ ui::AXBoundaryBehavior::StopAtAnchorBoundary);
AXPlatformPositionInstance startPosition =
*startWordPosition <= *endWordPosition ? std::move(endWordPosition)
: std::move(startWordPosition);
@@ -2207,9 +2307,11 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
return nil;
AXPlatformPositionInstance endWordPosition =
- startPosition->CreateNextWordEndPosition();
+ startPosition->CreateNextWordEndPosition(
+ ui::AXBoundaryBehavior::StopAtAnchorBoundary);
AXPlatformPositionInstance startWordPosition =
- startPosition->CreateNextWordStartPosition();
+ startPosition->CreateNextWordStartPosition(
+ ui::AXBoundaryBehavior::StopAtAnchorBoundary);
AXPlatformPositionInstance endPosition =
*startWordPosition <= *endWordPosition ? std::move(startWordPosition)
: std::move(endWordPosition);
@@ -2222,7 +2324,8 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
CreatePositionFromTextMarker(parameter);
if (position->IsNullPosition())
return nil;
- return CreateTextMarker(position->CreateNextWordEndPosition());
+ return CreateTextMarker(position->CreateNextWordEndPosition(
+ ui::AXBoundaryBehavior::CrossBoundary));
}
if ([attribute
@@ -2231,7 +2334,8 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
CreatePositionFromTextMarker(parameter);
if (position->IsNullPosition())
return nil;
- return CreateTextMarker(position->CreatePreviousWordStartPosition());
+ return CreateTextMarker(position->CreatePreviousWordStartPosition(
+ ui::AXBoundaryBehavior::CrossBoundary));
}
if ([attribute isEqualToString:@"AXTextMarkerRangeForLine"]) {
@@ -2241,9 +2345,11 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
return nil;
AXPlatformPositionInstance startPosition =
- position->CreatePreviousLineStartPosition();
+ position->CreatePreviousLineStartPosition(
+ ui::AXBoundaryBehavior::StopIfAlreadyAtBoundary);
AXPlatformPositionInstance endPosition =
- position->CreateNextLineEndPosition();
+ position->CreateNextLineEndPosition(
+ ui::AXBoundaryBehavior::StopIfAlreadyAtBoundary);
AXPlatformRange range(std::move(startPosition), std::move(endPosition));
return CreateTextMarkerRange(std::move(range));
}
@@ -2255,9 +2361,11 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
return nil;
AXPlatformPositionInstance startLinePosition =
- endPosition->CreatePreviousLineStartPosition();
+ endPosition->CreatePreviousLineStartPosition(
+ ui::AXBoundaryBehavior::CrossBoundary);
AXPlatformPositionInstance endLinePosition =
- endPosition->CreatePreviousLineEndPosition();
+ endPosition->CreatePreviousLineEndPosition(
+ ui::AXBoundaryBehavior::CrossBoundary);
AXPlatformPositionInstance startPosition =
*startLinePosition <= *endLinePosition ? std::move(endLinePosition)
: std::move(startLinePosition);
@@ -2272,9 +2380,11 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
return nil;
AXPlatformPositionInstance startLinePosition =
- startPosition->CreateNextLineStartPosition();
+ startPosition->CreateNextLineStartPosition(
+ ui::AXBoundaryBehavior::CrossBoundary);
AXPlatformPositionInstance endLinePosition =
- startPosition->CreateNextLineEndPosition();
+ startPosition->CreateNextLineEndPosition(
+ ui::AXBoundaryBehavior::CrossBoundary);
AXPlatformPositionInstance endPosition =
*startLinePosition <= *endLinePosition ? std::move(startLinePosition)
: std::move(endLinePosition);
@@ -2287,7 +2397,8 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
CreatePositionFromTextMarker(parameter);
if (position->IsNullPosition())
return nil;
- return CreateTextMarker(position->CreateNextLineEndPosition());
+ return CreateTextMarker(position->CreateNextLineEndPosition(
+ ui::AXBoundaryBehavior::CrossBoundary));
}
if ([attribute
@@ -2296,7 +2407,8 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
CreatePositionFromTextMarker(parameter);
if (position->IsNullPosition())
return nil;
- return CreateTextMarker(position->CreatePreviousLineStartPosition());
+ return CreateTextMarker(position->CreatePreviousLineStartPosition(
+ ui::AXBoundaryBehavior::CrossBoundary));
}
if ([attribute isEqualToString:@"AXLengthForTextMarkerRange"]) {
@@ -2347,8 +2459,10 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
if (position->IsNullPosition())
return nil;
- AXPlatformRange range(position->CreatePreviousLineStartPosition(),
- position->CreateNextLineEndPosition());
+ AXPlatformRange range(position->CreatePreviousLineStartPosition(
+ ui::AXBoundaryBehavior::StopIfAlreadyAtBoundary),
+ position->CreateNextLineEndPosition(
+ ui::AXBoundaryBehavior::StopIfAlreadyAtBoundary));
return CreateTextMarkerRange(std::move(range));
}
@@ -2573,10 +2687,12 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
NSAccessibilityChildrenAttribute,
NSAccessibilityDescriptionAttribute,
NSAccessibilityDOMIdentifierAttribute,
+ NSAccessibilityEditableAncestorAttribute,
NSAccessibilityEnabledAttribute,
NSAccessibilityEndTextMarkerAttribute,
NSAccessibilityFocusedAttribute,
NSAccessibilityHelpAttribute,
+ NSAccessibilityHighestEditableAncestorAttribute,
NSAccessibilityInvalidAttribute,
NSAccessibilityLinkedUIElementsAttribute,
NSAccessibilityParentAttribute,
@@ -2705,8 +2821,7 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
ui::AX_ATTR_LIVE_ATOMIC)) {
[ret addObjectsFromArray:@[ NSAccessibilityARIAAtomicAttribute ]];
}
- if (browserAccessibility_->HasBoolAttribute(
- ui::AX_ATTR_LIVE_BUSY)) {
+ if (browserAccessibility_->HasBoolAttribute(ui::AX_ATTR_BUSY)) {
[ret addObjectsFromArray:@[ NSAccessibilityARIABusyAttribute ]];
}
@@ -2739,6 +2854,10 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
[ret addObjectsFromArray:@[ @"AXRequired" ]];
}
+ if (browserAccessibility_->HasStringAttribute(ui::AX_ATTR_LANGUAGE)) {
+ [ret addObjectsFromArray:@[ NSAccessibilityLanguageAttribute ]];
+ }
+
// Title UI Element.
if (browserAccessibility_->HasIntListAttribute(ui::AX_ATTR_LABELLEDBY_IDS) &&
browserAccessibility_->GetIntListAttribute(ui::AX_ATTR_LABELLEDBY_IDS)
diff --git a/chromium/content/browser/accessibility/browser_accessibility_com_win.cc b/chromium/content/browser/accessibility/browser_accessibility_com_win.cc
index bf705ee55fd..3a7d8db33a6 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_com_win.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_com_win.cc
@@ -23,9 +23,9 @@
#include "content/browser/accessibility/browser_accessibility_state_impl.h"
#include "content/browser/accessibility/browser_accessibility_win.h"
#include "content/common/accessibility_messages.h"
-#include "content/common/accessibility_mode.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_role_properties.h"
#include "ui/accessibility/ax_text_utils.h"
#include "ui/base/win/accessibility_ids_win.h"
@@ -36,8 +36,7 @@
// modes when Windows screen readers are used. For example, certain roles use
// the HTML tag name. Input fields require their type attribute to be exposed.
const uint32_t kScreenReaderAndHTMLAccessibilityModes =
- content::AccessibilityMode::kScreenReader |
- content::AccessibilityMode::kHTML;
+ ui::AXMode::kScreenReader | ui::AXMode::kHTML;
namespace content {
@@ -59,7 +58,7 @@ const GUID GUID_IAccessibleContentDocument = {
const base::char16 BrowserAccessibilityComWin::kEmbeddedCharacter = L'\xfffc';
-void AddAccessibilityModeFlags(AccessibilityMode mode_flags) {
+void AddAccessibilityModeFlags(ui::AXMode mode_flags) {
BrowserAccessibilityStateImpl::GetInstance()->AddAccessibilityModeFlags(
mode_flags);
}
@@ -86,112 +85,12 @@ BrowserAccessibilityComWin::~BrowserAccessibilityComWin() {
}
//
-// IAccessible overrides:
-//
-
-STDMETHODIMP BrowserAccessibilityComWin::get_accDefaultAction(
- VARIANT var_id,
- BSTR* def_action) {
- AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- return AXPlatformNodeWin::get_accDefaultAction(var_id, def_action);
-}
-
-//
// IAccessible2 overrides:
//
STDMETHODIMP BrowserAccessibilityComWin::get_attributes(BSTR* attributes) {
- WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_IA2_GET_ATTRIBUTES);
- if (!owner())
- return E_FAIL;
- AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- if (!attributes)
- return E_INVALIDARG;
- *attributes = nullptr;
-
- if (!owner())
- return E_FAIL;
-
- base::string16 str;
- for (const base::string16& attribute : ia2_attributes())
- str += attribute + L';';
-
- if (str.empty())
- return S_FALSE;
-
- *attributes = SysAllocString(str.c_str());
- DCHECK(*attributes);
- return S_OK;
-}
-
-STDMETHODIMP BrowserAccessibilityComWin::get_states(AccessibleStates* states) {
- AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- return AXPlatformNodeWin::get_states(states);
-}
-
-STDMETHODIMP BrowserAccessibilityComWin::get_uniqueID(LONG* unique_id) {
- WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_UNIQUE_ID);
- if (!owner())
- return E_FAIL;
-
- if (!unique_id)
- return E_INVALIDARG;
-
- *unique_id = -owner()->unique_id();
- return S_OK;
-}
-
-STDMETHODIMP BrowserAccessibilityComWin::get_windowHandle(HWND* window_handle) {
- WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_WINDOW_HANDLE);
- if (!owner())
- return E_FAIL;
-
- if (!window_handle)
- return E_INVALIDARG;
-
- *window_handle =
- Manager()->ToBrowserAccessibilityManagerWin()->GetParentHWND();
- if (!*window_handle)
- return E_FAIL;
-
- return S_OK;
-}
-
-STDMETHODIMP BrowserAccessibilityComWin::get_indexInParent(
- LONG* index_in_parent) {
- WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_INDEX_IN_PARENT);
- if (!owner())
- return E_FAIL;
-
- if (!index_in_parent)
- return E_INVALIDARG;
-
- *index_in_parent = GetIndexInParent();
- return S_OK;
-}
-
-STDMETHODIMP BrowserAccessibilityComWin::get_nRelations(LONG* n_relations) {
- WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_N_RELATIONS);
- AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- return AXPlatformNodeWin::get_nRelations(n_relations);
-}
-
-STDMETHODIMP BrowserAccessibilityComWin::get_relation(
- LONG relation_index,
- IAccessibleRelation** relation) {
- WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_RELATION);
- AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- return AXPlatformNodeWin::get_relation(relation_index, relation);
-}
-
-STDMETHODIMP BrowserAccessibilityComWin::get_relations(
- LONG max_relations,
- IAccessibleRelation** relations,
- LONG* n_relations) {
- WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_RELATIONS);
- AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- return AXPlatformNodeWin::get_relations(max_relations, relations,
- n_relations);
+ // This can be removed once the rest of the interface has been removed.
+ return AXPlatformNodeWin::get_attributes(attributes);
}
STDMETHODIMP BrowserAccessibilityComWin::scrollTo(IA2ScrollType scroll_type) {
@@ -268,42 +167,6 @@ STDMETHODIMP BrowserAccessibilityComWin::scrollToPoint(
return S_OK;
}
-STDMETHODIMP BrowserAccessibilityComWin::get_groupPosition(
- LONG* group_level,
- LONG* similar_items_in_group,
- LONG* position_in_group) {
- WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_GROUP_POSITION);
- AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- if (!owner())
- return E_FAIL;
-
- if (!group_level || !similar_items_in_group || !position_in_group)
- return E_INVALIDARG;
-
- *group_level = owner()->GetIntAttribute(ui::AX_ATTR_HIERARCHICAL_LEVEL);
- *similar_items_in_group = owner()->GetIntAttribute(ui::AX_ATTR_SET_SIZE);
- *position_in_group = owner()->GetIntAttribute(ui::AX_ATTR_POS_IN_SET);
-
- if (*group_level == *similar_items_in_group == *position_in_group == 0)
- return S_FALSE;
- return S_OK;
-}
-
-STDMETHODIMP
-BrowserAccessibilityComWin::get_localizedExtendedRole(
- BSTR* localized_extended_role) {
- WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_LOCALIZED_EXTENDED_ROLE);
- AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- if (!owner())
- return E_FAIL;
-
- if (!localized_extended_role)
- return E_INVALIDARG;
-
- return GetStringAttributeAsBstr(ui::AX_ATTR_ROLE_DESCRIPTION,
- localized_extended_role);
-}
-
//
// IAccessibleApplication methods.
//
@@ -438,304 +301,13 @@ STDMETHODIMP BrowserAccessibilityComWin::get_imageSize(LONG* height,
}
//
-// IAccessibleTable methods.
-//
-
-STDMETHODIMP BrowserAccessibilityComWin::get_accessibleAt(
- long row,
- long column,
- IUnknown** accessible) {
- AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- return AXPlatformNodeWin::get_accessibleAt(row, column, accessible);
-}
-
-STDMETHODIMP BrowserAccessibilityComWin::get_caption(IUnknown** accessible) {
- AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- return AXPlatformNodeWin::get_caption(accessible);
-}
-
-STDMETHODIMP BrowserAccessibilityComWin::get_childIndex(long row,
- long column,
- long* cell_index) {
- AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- return AXPlatformNodeWin::get_childIndex(row, column, cell_index);
-}
-
-STDMETHODIMP BrowserAccessibilityComWin::get_columnDescription(
- long column,
- BSTR* description) {
- AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- return AXPlatformNodeWin::get_columnDescription(column, description);
-}
-
-STDMETHODIMP BrowserAccessibilityComWin::get_columnExtentAt(
- long row,
- long column,
- long* n_columns_spanned) {
- AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- return AXPlatformNodeWin::get_columnExtentAt(row, column, n_columns_spanned);
-}
-
-STDMETHODIMP BrowserAccessibilityComWin::get_columnHeader(
- IAccessibleTable** accessible_table,
- long* starting_row_index) {
- AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- return AXPlatformNodeWin::get_columnHeader(accessible_table,
- starting_row_index);
-}
-
-STDMETHODIMP BrowserAccessibilityComWin::get_columnIndex(long cell_index,
- long* column_index) {
- AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- return AXPlatformNodeWin::get_columnIndex(cell_index, column_index);
-}
-
-STDMETHODIMP BrowserAccessibilityComWin::get_nColumns(long* column_count) {
- AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- return AXPlatformNodeWin::get_nColumns(column_count);
-}
-
-STDMETHODIMP BrowserAccessibilityComWin::get_nRows(long* row_count) {
- AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- return AXPlatformNodeWin::get_nRows(row_count);
-}
-
-STDMETHODIMP BrowserAccessibilityComWin::get_nSelectedChildren(
- long* cell_count) {
- AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- return AXPlatformNodeWin::get_nSelectedChildren(cell_count);
-}
-
-STDMETHODIMP BrowserAccessibilityComWin::get_nSelectedColumns(
- long* column_count) {
- AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- return AXPlatformNodeWin::get_nSelectedColumns(column_count);
-}
-
-STDMETHODIMP BrowserAccessibilityComWin::get_nSelectedRows(long* row_count) {
- AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- return AXPlatformNodeWin::get_nSelectedRows(row_count);
-}
-
-STDMETHODIMP BrowserAccessibilityComWin::get_rowDescription(long row,
- BSTR* description) {
- AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- return AXPlatformNodeWin::get_rowDescription(row, description);
-}
-
-STDMETHODIMP BrowserAccessibilityComWin::get_rowExtentAt(long row,
- long column,
- long* n_rows_spanned) {
- AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- return AXPlatformNodeWin::get_rowExtentAt(row, column, n_rows_spanned);
-}
-
-STDMETHODIMP BrowserAccessibilityComWin::get_rowHeader(
- IAccessibleTable** accessible_table,
- long* starting_column_index) {
- AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- return AXPlatformNodeWin::get_rowHeader(accessible_table,
- starting_column_index);
-}
-
-STDMETHODIMP BrowserAccessibilityComWin::get_rowIndex(long cell_index,
- long* row_index) {
- AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- return AXPlatformNodeWin::get_rowIndex(cell_index, row_index);
-}
-
-STDMETHODIMP BrowserAccessibilityComWin::get_selectedChildren(
- long max_children,
- long** children,
- long* n_children) {
- AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- return AXPlatformNodeWin::get_selectedChildren(max_children, children,
- n_children);
-}
-
-STDMETHODIMP BrowserAccessibilityComWin::get_selectedColumns(long max_columns,
- long** columns,
- long* n_columns) {
- AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- return AXPlatformNodeWin::get_selectedColumns(max_columns, columns,
- n_columns);
-}
-
-STDMETHODIMP BrowserAccessibilityComWin::get_selectedRows(long max_rows,
- long** rows,
- long* n_rows) {
- AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- return AXPlatformNodeWin::get_selectedRows(max_rows, rows, n_rows);
-}
-
-STDMETHODIMP BrowserAccessibilityComWin::get_summary(IUnknown** accessible) {
- AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- return AXPlatformNodeWin::get_summary(accessible);
-}
-
-STDMETHODIMP BrowserAccessibilityComWin::get_isColumnSelected(
- long column,
- boolean* is_selected) {
- AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- return AXPlatformNodeWin::get_isColumnSelected(column, is_selected);
-}
-
-STDMETHODIMP BrowserAccessibilityComWin::get_isRowSelected(
- long row,
- boolean* is_selected) {
- AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- return AXPlatformNodeWin::get_isRowSelected(row, is_selected);
-}
-
-STDMETHODIMP BrowserAccessibilityComWin::get_isSelected(long row,
- long column,
- boolean* is_selected) {
- AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- return AXPlatformNodeWin::get_isSelected(row, column, is_selected);
-}
-
-STDMETHODIMP BrowserAccessibilityComWin::get_rowColumnExtentsAtIndex(
- long index,
- long* row,
- long* column,
- long* row_extents,
- long* column_extents,
- boolean* is_selected) {
- AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- return AXPlatformNodeWin::get_rowColumnExtentsAtIndex(
- index, row, column, row_extents, column_extents, is_selected);
-}
-
-STDMETHODIMP BrowserAccessibilityComWin::selectRow(long row) {
- AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- return AXPlatformNodeWin::selectRow(row);
-}
-
-STDMETHODIMP BrowserAccessibilityComWin::selectColumn(long column) {
- AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- return AXPlatformNodeWin::selectColumn(column);
-}
-
-STDMETHODIMP BrowserAccessibilityComWin::unselectRow(long row) {
- AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- return AXPlatformNodeWin::unselectRow(row);
-}
-
-STDMETHODIMP BrowserAccessibilityComWin::unselectColumn(long column) {
- AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- return AXPlatformNodeWin::unselectColumn(column);
-}
-
-STDMETHODIMP
-BrowserAccessibilityComWin::get_modelChange(IA2TableModelChange* model_change) {
- return AXPlatformNodeWin::get_modelChange(model_change);
-}
-
-//
-// IAccessibleTable2 methods.
-//
-
-STDMETHODIMP BrowserAccessibilityComWin::get_cellAt(long row,
- long column,
- IUnknown** cell) {
- AddAccessibilityModeFlags(AccessibilityMode::kScreenReader);
- return AXPlatformNodeWin::get_cellAt(row, column, cell);
-}
-
-STDMETHODIMP BrowserAccessibilityComWin::get_nSelectedCells(long* cell_count) {
- AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- return AXPlatformNodeWin::get_nSelectedCells(cell_count);
-}
-
-STDMETHODIMP BrowserAccessibilityComWin::get_selectedCells(
- IUnknown*** cells,
- long* n_selected_cells) {
- AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- return AXPlatformNodeWin::get_selectedCells(cells, n_selected_cells);
-}
-
-STDMETHODIMP BrowserAccessibilityComWin::get_selectedColumns(long** columns,
- long* n_columns) {
- AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- return AXPlatformNodeWin::get_selectedColumns(columns, n_columns);
-}
-
-STDMETHODIMP BrowserAccessibilityComWin::get_selectedRows(long** rows,
- long* n_rows) {
- AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- return AXPlatformNodeWin::get_selectedRows(rows, n_rows);
-}
-
-//
-// IAccessibleTableCell methods.
-//
-
-STDMETHODIMP BrowserAccessibilityComWin::get_columnExtent(
- long* n_columns_spanned) {
- AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- return AXPlatformNodeWin::get_columnExtent(n_columns_spanned);
-}
-
-STDMETHODIMP BrowserAccessibilityComWin::get_columnHeaderCells(
- IUnknown*** cell_accessibles,
- long* n_column_header_cells) {
- AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- return AXPlatformNodeWin::get_columnHeaderCells(cell_accessibles,
- n_column_header_cells);
-}
-
-STDMETHODIMP BrowserAccessibilityComWin::get_columnIndex(long* column_index) {
- AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- return AXPlatformNodeWin::get_columnIndex(column_index);
-}
-
-STDMETHODIMP BrowserAccessibilityComWin::get_rowExtent(long* n_rows_spanned) {
- AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- return AXPlatformNodeWin::get_rowExtent(n_rows_spanned);
-}
-
-STDMETHODIMP BrowserAccessibilityComWin::get_rowHeaderCells(
- IUnknown*** cell_accessibles,
- long* n_row_header_cells) {
- AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- return AXPlatformNodeWin::get_rowHeaderCells(cell_accessibles,
- n_row_header_cells);
-}
-
-STDMETHODIMP BrowserAccessibilityComWin::get_rowIndex(long* row_index) {
- AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- return AXPlatformNodeWin::get_rowIndex(row_index);
-}
-
-STDMETHODIMP BrowserAccessibilityComWin::get_isSelected(boolean* is_selected) {
- AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- return AXPlatformNodeWin::get_isSelected(is_selected);
-}
-
-STDMETHODIMP BrowserAccessibilityComWin::get_rowColumnExtents(
- long* row_index,
- long* column_index,
- long* row_extents,
- long* column_extents,
- boolean* is_selected) {
- AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- return AXPlatformNodeWin::get_rowColumnExtents(
- row_index, column_index, row_extents, column_extents, is_selected);
-}
-
-STDMETHODIMP BrowserAccessibilityComWin::get_table(IUnknown** table) {
- AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes);
- return AXPlatformNodeWin::get_table(table);
-}
-
-//
// IAccessibleText methods.
//
STDMETHODIMP BrowserAccessibilityComWin::get_nCharacters(LONG* n_characters) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_N_CHARACTERS);
AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes |
- AccessibilityMode::kInlineTextBoxes);
+ ui::AXMode::kInlineTextBoxes);
if (!owner())
return E_FAIL;
@@ -777,7 +349,7 @@ STDMETHODIMP BrowserAccessibilityComWin::get_characterExtents(
LONG* out_height) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_CHARACTER_EXTENTS);
AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes |
- AccessibilityMode::kInlineTextBoxes);
+ ui::AXMode::kInlineTextBoxes);
if (!owner())
return E_FAIL;
@@ -911,7 +483,7 @@ STDMETHODIMP BrowserAccessibilityComWin::get_textAtOffset(
BSTR* text) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_TEXT_AT_OFFSET);
AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes |
- AccessibilityMode::kInlineTextBoxes);
+ ui::AXMode::kInlineTextBoxes);
if (!owner())
return E_FAIL;
@@ -959,7 +531,7 @@ STDMETHODIMP BrowserAccessibilityComWin::get_textBeforeOffset(
BSTR* text) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_TEXT_BEFORE_OFFSET);
AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes |
- AccessibilityMode::kInlineTextBoxes);
+ ui::AXMode::kInlineTextBoxes);
if (!owner())
return E_FAIL;
@@ -993,7 +565,7 @@ STDMETHODIMP BrowserAccessibilityComWin::get_textAfterOffset(
BSTR* text) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_TEXT_AFTER_OFFSET);
AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes |
- AccessibilityMode::kInlineTextBoxes);
+ ui::AXMode::kInlineTextBoxes);
if (!owner())
return E_FAIL;
@@ -1075,7 +647,7 @@ STDMETHODIMP BrowserAccessibilityComWin::get_offsetAtPoint(
LONG* offset) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_OFFSET_AT_POINT);
AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes |
- AccessibilityMode::kInlineTextBoxes);
+ ui::AXMode::kInlineTextBoxes);
if (!owner())
return E_FAIL;
@@ -1095,7 +667,7 @@ STDMETHODIMP BrowserAccessibilityComWin::scrollSubstringTo(
IA2ScrollType scroll_type) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_SCROLL_SUBSTRING_TO);
AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes |
- AccessibilityMode::kInlineTextBoxes);
+ ui::AXMode::kInlineTextBoxes);
// TODO(dmazzoni): adjust this for the start and end index, too.
return scrollTo(scroll_type);
}
@@ -1108,7 +680,7 @@ STDMETHODIMP BrowserAccessibilityComWin::scrollSubstringToPoint(
LONG y) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_SCROLL_SUBSTRING_TO_POINT);
AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes |
- AccessibilityMode::kInlineTextBoxes);
+ ui::AXMode::kInlineTextBoxes);
if (!owner())
return E_FAIL;
@@ -1249,8 +821,8 @@ STDMETHODIMP BrowserAccessibilityComWin::get_hyperlink(
}
int32_t id = hyperlinks()[index];
- BrowserAccessibilityComWin* link =
- ToBrowserAccessibilityComWin(owner()->GetFromUniqueID(id));
+ auto* link = static_cast<BrowserAccessibilityComWin*>(
+ AXPlatformNodeWin::GetFromUniqueId(id));
if (!link)
return E_FAIL;
@@ -1708,7 +1280,7 @@ STDMETHODIMP BrowserAccessibilityComWin::get_nodeInfo(
*name_space_id = 0;
*node_value = SysAllocString(value().c_str());
*num_children = owner()->PlatformChildCount();
- *unique_id = -owner()->unique_id();
+ *unique_id = -AXPlatformNodeWin::unique_id();
if (owner()->IsDocument()) {
*node_type = NODETYPE_DOCUMENT;
@@ -2032,7 +1604,7 @@ STDMETHODIMP BrowserAccessibilityComWin::get_clippedSubstringBounds(
int* out_height) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_CLIPPED_SUBSTRING_BOUNDS);
AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes |
- AccessibilityMode::kInlineTextBoxes);
+ ui::AXMode::kInlineTextBoxes);
// TODO(dmazzoni): fully support this API by intersecting the
// rect with the container's rect.
return get_unclippedSubstringBounds(start_index, end_index, out_x, out_y,
@@ -2048,7 +1620,7 @@ STDMETHODIMP BrowserAccessibilityComWin::get_unclippedSubstringBounds(
int* out_height) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_UNCLIPPED_SUBSTRING_BOUNDS);
AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes |
- AccessibilityMode::kInlineTextBoxes);
+ ui::AXMode::kInlineTextBoxes);
if (!owner())
return E_FAIL;
@@ -2076,7 +1648,7 @@ STDMETHODIMP BrowserAccessibilityComWin::scrollToSubstring(
unsigned int end_index) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_SCROLL_TO_SUBSTRING);
AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes |
- AccessibilityMode::kInlineTextBoxes);
+ ui::AXMode::kInlineTextBoxes);
if (!owner())
return E_FAIL;
@@ -2370,40 +1942,19 @@ void BrowserAccessibilityComWin::ComputeStylesIfNeeded() {
// |offset| could either be a text character or a child index in case of
// non-text objects.
-// TODO(nektar): Remove this function once selection bugs are fixed in Blink.
+// Currently, to be safe, we convert to text leaf equivalents and we don't use
+// tree positions.
+// TODO(nektar): Remove this function once selection fixes in Blink are
+// thoroughly tested and convert to tree positions.
AXPlatformPosition::AXPositionInstance
BrowserAccessibilityComWin::CreatePositionForSelectionAt(int offset) const {
- if (!owner()->IsNativeTextControl() && !owner()->IsTextOnlyObject()) {
- auto* manager = Manager();
- DCHECK(manager);
- const BrowserAccessibilityComWin* child = this;
- // TODO(nektar): Make parents of text-only objects not include the text of
- // children in their hypertext.
- for (size_t i = 0; i < owner()->InternalChildCount(); ++i) {
- int new_offset = offset;
- child = ToBrowserAccessibilityComWin(owner()->InternalGetChild(i));
- DCHECK(child);
- if (child->owner()->IsTextOnlyObject()) {
- new_offset -= child->owner()->GetText().length();
- } else {
- new_offset -= 1;
- }
- if (new_offset <= 0)
- break;
- offset = new_offset;
- }
- AXPlatformPositionInstance position =
- AXPlatformPosition::CreateTextPosition(manager->ax_tree_id(),
- child->owner()->GetId(), offset,
- ui::AX_TEXT_AFFINITY_DOWNSTREAM)
- ->AsLeafTextPosition();
- if (position->GetAnchor() &&
- position->GetAnchor()->GetRole() == ui::AX_ROLE_INLINE_TEXT_BOX) {
- return position->CreateParentPosition();
+ AXPlatformPositionInstance position =
+ owner()->CreatePositionAt(offset)->AsLeafTextPosition();
+ if (position->GetAnchor() &&
+ position->GetAnchor()->GetRole() == ui::AX_ROLE_INLINE_TEXT_BOX) {
+ return position->CreateParentPosition();
}
return position;
- }
- return owner()->CreatePositionAt(offset);
}
//
@@ -2483,7 +2034,7 @@ void BrowserAccessibilityComWin::UpdateStep2ComputeHypertext() {
win_attributes_->hypertext += child->name();
} else {
int32_t char_offset = static_cast<int32_t>(owner()->GetText().size());
- int32_t child_unique_id = child->owner()->unique_id();
+ int32_t child_unique_id = child->unique_id();
int32_t index = hyperlinks().size();
win_attributes_->hyperlink_offset_to_index[char_offset] = index;
win_attributes_->hyperlinks.push_back(child_unique_id);
@@ -2598,12 +2149,6 @@ void BrowserAccessibilityComWin::Init(ui::AXPlatformNodeDelegate* delegate) {
AXPlatformNodeBase::Init(delegate);
}
-ui::AXPlatformNode* BrowserAccessibilityComWin::GetFromUniqueId(
- int32_t unique_id) {
- return ToBrowserAccessibilityComWin(
- BrowserAccessibility::GetFromUniqueID(unique_id));
-}
-
std::vector<base::string16> BrowserAccessibilityComWin::ComputeTextAttributes()
const {
std::vector<base::string16> attributes;
@@ -2852,8 +2397,8 @@ BrowserAccessibilityComWin* BrowserAccessibilityComWin::GetTargetFromChildID(
return ToBrowserAccessibilityComWin(
owner()->PlatformGetChild(child_id - 1));
- BrowserAccessibilityComWin* child = ToBrowserAccessibilityComWin(
- BrowserAccessibility::GetFromUniqueID(-child_id));
+ auto* child = static_cast<BrowserAccessibilityComWin*>(
+ AXPlatformNodeWin::GetFromUniqueId(-child_id));
if (child && child->owner()->IsDescendantOf(owner()))
return child;
@@ -2899,8 +2444,8 @@ void BrowserAccessibilityComWin::SetIA2HypertextSelection(LONG start_offset,
CreatePositionForSelectionAt(static_cast<int>(start_offset));
AXPlatformPositionInstance end_position =
CreatePositionForSelectionAt(static_cast<int>(end_offset));
- Manager()->SetSelection(AXPlatformRange(start_position->AsTextPosition(),
- end_position->AsTextPosition()));
+ Manager()->SetSelection(
+ AXPlatformRange(std::move(start_position), std::move(end_position)));
}
bool BrowserAccessibilityComWin::IsHyperlink() const {
@@ -2927,8 +2472,8 @@ BrowserAccessibilityComWin::GetHyperlinkFromHypertextOffset(int offset) const {
DCHECK_GE(index, 0);
DCHECK_LT(index, static_cast<int32_t>(hyperlinks().size()));
int32_t id = hyperlinks()[index];
- BrowserAccessibilityComWin* hyperlink =
- ToBrowserAccessibilityComWin(owner()->GetFromUniqueID(id));
+ auto* hyperlink = static_cast<BrowserAccessibilityComWin*>(
+ AXPlatformNodeWin::GetFromUniqueId(id));
if (!hyperlink)
return nullptr;
return hyperlink;
@@ -2939,8 +2484,8 @@ int32_t BrowserAccessibilityComWin::GetHyperlinkIndexFromChild(
if (hyperlinks().empty())
return -1;
- auto iterator = std::find(hyperlinks().begin(), hyperlinks().end(),
- child.owner()->unique_id());
+ auto iterator =
+ std::find(hyperlinks().begin(), hyperlinks().end(), child.unique_id());
if (iterator == hyperlinks().end())
return -1;
@@ -3273,22 +2818,16 @@ LONG BrowserAccessibilityComWin::FindBoundary(
AXPlatformPositionInstance position =
owner()->CreatePositionAt(static_cast<int>(start_offset), affinity);
AXPlatformPositionInstance next_word =
- position->CreateNextWordStartPosition();
- if (next_word->anchor_id() != owner()->GetId())
- next_word = position->CreatePositionAtEndOfAnchor();
+ position->CreateNextWordStartPosition(
+ ui::AXBoundaryBehavior::StopAtAnchorBoundary);
return next_word->text_offset();
}
case ui::BACKWARDS_DIRECTION: {
AXPlatformPositionInstance position =
owner()->CreatePositionAt(static_cast<int>(start_offset), affinity);
- AXPlatformPositionInstance previous_word;
- if (!position->AtStartOfWord()) {
- previous_word = position->CreatePreviousWordStartPosition();
- if (previous_word->anchor_id() != owner()->GetId())
- previous_word = position->CreatePositionAtStartOfAnchor();
- } else {
- previous_word = std::move(position);
- }
+ AXPlatformPositionInstance previous_word =
+ position->CreatePreviousWordStartPosition(
+ ui::AXBoundaryBehavior::StopIfAlreadyAtBoundary);
return previous_word->text_offset();
}
}
@@ -3300,22 +2839,16 @@ LONG BrowserAccessibilityComWin::FindBoundary(
AXPlatformPositionInstance position =
owner()->CreatePositionAt(static_cast<int>(start_offset), affinity);
AXPlatformPositionInstance next_line =
- position->CreateNextLineStartPosition();
- if (next_line->anchor_id() != owner()->GetId())
- next_line = position->CreatePositionAtEndOfAnchor();
+ position->CreateNextLineStartPosition(
+ ui::AXBoundaryBehavior::StopAtAnchorBoundary);
return next_line->text_offset();
}
case ui::BACKWARDS_DIRECTION: {
AXPlatformPositionInstance position =
owner()->CreatePositionAt(static_cast<int>(start_offset), affinity);
- AXPlatformPositionInstance previous_line;
- if (!position->AtStartOfLine()) {
- previous_line = position->CreatePreviousLineStartPosition();
- if (previous_line->anchor_id() != owner()->GetId())
- previous_line = position->CreatePositionAtStartOfAnchor();
- } else {
- previous_line = std::move(position);
- }
+ AXPlatformPositionInstance previous_line =
+ position->CreatePreviousLineStartPosition(
+ ui::AXBoundaryBehavior::StopIfAlreadyAtBoundary);
return previous_line->text_offset();
}
}
diff --git a/chromium/content/browser/accessibility/browser_accessibility_com_win.h b/chromium/content/browser/accessibility/browser_accessibility_com_win.h
index 22e13a60020..585da1d9896 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_com_win.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_com_win.h
@@ -67,9 +67,6 @@ class __declspec(uuid("562072fe-3390-43b1-9e2c-dd4118f5ac79"))
COM_INTERFACE_ENTRY(IAccessibleHyperlink)
COM_INTERFACE_ENTRY(IAccessibleHypertext)
COM_INTERFACE_ENTRY(IAccessibleImage)
- COM_INTERFACE_ENTRY(IAccessibleTable)
- COM_INTERFACE_ENTRY(IAccessibleTable2)
- COM_INTERFACE_ENTRY(IAccessibleTableCell)
COM_INTERFACE_ENTRY(IAccessibleValue)
COM_INTERFACE_ENTRY(IRawElementProviderSimple)
COM_INTERFACE_ENTRY(ISimpleDOMDocument)
@@ -99,43 +96,10 @@ class __declspec(uuid("562072fe-3390-43b1-9e2c-dd4118f5ac79"))
CONTENT_EXPORT void UpdateStep3FireEvents(bool is_subtree_creation);
//
- // IAccessible methods.
- //
-
- // Retrieves a string that describes the object's default action.
- CONTENT_EXPORT STDMETHODIMP
- get_accDefaultAction(VARIANT var_id, BSTR* default_action) override;
-
- //
// IAccessible2 methods.
//
-
- // Returns the state bitmask from a larger set of possible states.
- CONTENT_EXPORT STDMETHODIMP get_states(AccessibleStates* states) override;
-
- // Returns the attributes specific to this IAccessible2 object,
- // such as a cell's formula.
CONTENT_EXPORT STDMETHODIMP get_attributes(BSTR* attributes) override;
- // Get the unique ID of this object so that the client knows if it's
- // been encountered previously.
- CONTENT_EXPORT STDMETHODIMP get_uniqueID(LONG* unique_id) override;
-
- // Get the window handle of the enclosing window.
- CONTENT_EXPORT STDMETHODIMP get_windowHandle(HWND* window_handle) override;
-
- // Get this object's index in its parent object.
- CONTENT_EXPORT STDMETHODIMP get_indexInParent(LONG* index_in_parent) override;
-
- CONTENT_EXPORT STDMETHODIMP get_nRelations(LONG* n_relations) override;
-
- CONTENT_EXPORT STDMETHODIMP
- get_relation(LONG relation_index, IAccessibleRelation** relation) override;
-
- CONTENT_EXPORT STDMETHODIMP get_relations(LONG max_relations,
- IAccessibleRelation** relations,
- LONG* n_relations) override;
-
CONTENT_EXPORT STDMETHODIMP scrollTo(enum IA2ScrollType scroll_type) override;
CONTENT_EXPORT STDMETHODIMP
@@ -143,14 +107,6 @@ class __declspec(uuid("562072fe-3390-43b1-9e2c-dd4118f5ac79"))
LONG x,
LONG y) override;
- CONTENT_EXPORT STDMETHODIMP
- get_groupPosition(LONG* group_level,
- LONG* similar_items_in_group,
- LONG* position_in_group) override;
-
- CONTENT_EXPORT STDMETHODIMP
- get_localizedExtendedRole(BSTR* localized_extended_role) override;
-
//
// IAccessibleApplication methods.
//
@@ -176,156 +132,6 @@ class __declspec(uuid("562072fe-3390-43b1-9e2c-dd4118f5ac79"))
CONTENT_EXPORT STDMETHODIMP get_imageSize(LONG* height, LONG* width) override;
//
- // IAccessibleTable methods.
- //
-
- // get_description - also used by IAccessibleImage
-
- CONTENT_EXPORT STDMETHODIMP get_accessibleAt(long row,
- long column,
- IUnknown** accessible) override;
-
- CONTENT_EXPORT STDMETHODIMP get_caption(IUnknown** accessible) override;
-
- CONTENT_EXPORT STDMETHODIMP get_childIndex(long row_index,
- long column_index,
- long* cell_index) override;
-
- CONTENT_EXPORT STDMETHODIMP get_columnDescription(long column,
- BSTR* description) override;
-
- CONTENT_EXPORT STDMETHODIMP
- get_columnExtentAt(long row, long column, long* n_columns_spanned) override;
-
- CONTENT_EXPORT STDMETHODIMP
- get_columnHeader(IAccessibleTable** accessible_table,
- long* starting_row_index) override;
-
- CONTENT_EXPORT STDMETHODIMP get_columnIndex(long cell_index,
- long* column_index) override;
-
- CONTENT_EXPORT STDMETHODIMP get_nColumns(long* column_count) override;
-
- CONTENT_EXPORT STDMETHODIMP get_nRows(long* row_count) override;
-
- CONTENT_EXPORT STDMETHODIMP get_nSelectedChildren(long* cell_count) override;
-
- CONTENT_EXPORT STDMETHODIMP get_nSelectedColumns(long* column_count) override;
-
- CONTENT_EXPORT STDMETHODIMP get_nSelectedRows(long* row_count) override;
-
- CONTENT_EXPORT STDMETHODIMP get_rowDescription(long row,
- BSTR* description) override;
-
- CONTENT_EXPORT STDMETHODIMP get_rowExtentAt(long row,
- long column,
- long* n_rows_spanned) override;
-
- CONTENT_EXPORT STDMETHODIMP
- get_rowHeader(IAccessibleTable** accessible_table,
- long* starting_column_index) override;
-
- CONTENT_EXPORT STDMETHODIMP get_rowIndex(long cell_index,
- long* row_index) override;
-
- CONTENT_EXPORT STDMETHODIMP get_selectedChildren(long max_children,
- long** children,
- long* n_children) override;
-
- CONTENT_EXPORT STDMETHODIMP get_selectedColumns(long max_columns,
- long** columns,
- long* n_columns) override;
-
- CONTENT_EXPORT STDMETHODIMP get_selectedRows(long max_rows,
- long** rows,
- long* n_rows) override;
-
- CONTENT_EXPORT STDMETHODIMP get_summary(IUnknown** accessible) override;
-
- CONTENT_EXPORT STDMETHODIMP
- get_isColumnSelected(long column, boolean* is_selected) override;
-
- CONTENT_EXPORT STDMETHODIMP get_isRowSelected(long row,
- boolean* is_selected) override;
-
- CONTENT_EXPORT STDMETHODIMP get_isSelected(long row,
- long column,
- boolean* is_selected) override;
-
- CONTENT_EXPORT STDMETHODIMP
- get_rowColumnExtentsAtIndex(long index,
- long* row,
- long* column,
- long* row_extents,
- long* column_extents,
- boolean* is_selected) override;
-
- CONTENT_EXPORT STDMETHODIMP selectRow(long row) override;
-
- CONTENT_EXPORT STDMETHODIMP selectColumn(long column) override;
-
- CONTENT_EXPORT STDMETHODIMP unselectRow(long row) override;
-
- CONTENT_EXPORT STDMETHODIMP unselectColumn(long column) override;
-
- CONTENT_EXPORT STDMETHODIMP
- get_modelChange(IA2TableModelChange* model_change) override;
-
- //
- // IAccessibleTable2 methods.
- //
- // (Most of these are duplicates of IAccessibleTable methods, only the
- // unique ones are included here.)
- //
-
- CONTENT_EXPORT STDMETHODIMP get_cellAt(long row,
- long column,
- IUnknown** cell) override;
-
- CONTENT_EXPORT STDMETHODIMP get_nSelectedCells(long* cell_count) override;
-
- CONTENT_EXPORT STDMETHODIMP
- get_selectedCells(IUnknown*** cells, long* n_selected_cells) override;
-
- CONTENT_EXPORT STDMETHODIMP get_selectedColumns(long** columns,
- long* n_columns) override;
-
- CONTENT_EXPORT STDMETHODIMP get_selectedRows(long** rows,
- long* n_rows) override;
-
- //
- // IAccessibleTableCell methods.
- //
-
- CONTENT_EXPORT STDMETHODIMP
- get_columnExtent(long* n_columns_spanned) override;
-
- CONTENT_EXPORT STDMETHODIMP
- get_columnHeaderCells(IUnknown*** cell_accessibles,
- long* n_column_header_cells) override;
-
- CONTENT_EXPORT STDMETHODIMP get_columnIndex(long* column_index) override;
-
- CONTENT_EXPORT STDMETHODIMP get_rowExtent(long* n_rows_spanned) override;
-
- CONTENT_EXPORT STDMETHODIMP
- get_rowHeaderCells(IUnknown*** cell_accessibles,
- long* n_row_header_cells) override;
-
- CONTENT_EXPORT STDMETHODIMP get_rowIndex(long* row_index) override;
-
- CONTENT_EXPORT STDMETHODIMP get_isSelected(boolean* is_selected) override;
-
- CONTENT_EXPORT STDMETHODIMP
- get_rowColumnExtents(long* row,
- long* column,
- long* row_extents,
- long* column_extents,
- boolean* is_selected) override;
-
- CONTENT_EXPORT STDMETHODIMP get_table(IUnknown** table) override;
-
- //
// IAccessibleText methods.
//
@@ -654,7 +460,6 @@ class __declspec(uuid("562072fe-3390-43b1-9e2c-dd4118f5ac79"))
//
void Destroy() override;
void Init(ui::AXPlatformNodeDelegate* delegate) override;
- AXPlatformNode* GetFromUniqueId(int32_t unique_id) override;
// Returns the IA2 text attributes for this object.
std::vector<base::string16> ComputeTextAttributes() const;
diff --git a/chromium/content/browser/accessibility/browser_accessibility_event.cc b/chromium/content/browser/accessibility/browser_accessibility_event.cc
index 24fa9eda213..555688d7ff2 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_event.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_event.cc
@@ -140,7 +140,6 @@ void BrowserAccessibilityEvent::VerboseLog(Result result) {
<< " " << event_name
<< " result=" << result_str
<< " source=" << source_str
- << " unique_id=" << target_->unique_id()
<< " target=[["
<< ReplaceNewlines(target_->GetData().ToString()) << "]]"
<< original_target_str;
diff --git a/chromium/content/browser/accessibility/browser_accessibility_event_win.cc b/chromium/content/browser/accessibility/browser_accessibility_event_win.cc
index 3dcae6bc6b1..ed5f2e55f69 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_event_win.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_event_win.cc
@@ -24,9 +24,6 @@ BrowserAccessibilityEvent* BrowserAccessibilityEvent::Create(
case ui::AX_EVENT_ALERT:
win_event_type = EVENT_SYSTEM_ALERT;
break;
- case ui::AX_EVENT_AUTOCORRECTION_OCCURED:
- win_event_type = IA2_EVENT_OBJECT_ATTRIBUTE_CHANGED;
- break;
case ui::AX_EVENT_CHILDREN_CHANGED:
win_event_type = EVENT_OBJECT_REORDER;
break;
diff --git a/chromium/content/browser/accessibility/browser_accessibility_mac_unittest.mm b/chromium/content/browser/accessibility/browser_accessibility_mac_unittest.mm
index dac10fe91f2..45bec904a26 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_mac_unittest.mm
+++ b/chromium/content/browser/accessibility/browser_accessibility_mac_unittest.mm
@@ -7,14 +7,18 @@
#import <Cocoa/Cocoa.h>
#include <memory>
+#include <string>
+#include <vector>
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "content/browser/accessibility/browser_accessibility_cocoa.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
#include "content/browser/accessibility/browser_accessibility_manager_mac.h"
+#include "content/public/browser/ax_event_notification_details.h"
#include "testing/gtest/include/gtest/gtest.h"
#import "testing/gtest_mac.h"
+#include "ui/accessibility/ax_tree_update.h"
#import "ui/gfx/test/ui_cocoa_test_helper.h"
namespace content {
@@ -28,14 +32,16 @@ class BrowserAccessibilityTest : public ui::CocoaTest {
protected:
void RebuildAccessibilityTree() {
- ui::AXNodeData root;
- root.id = 1000;
- root.location.set_width(500);
- root.location.set_height(100);
- root.role = ui::AX_ROLE_ROOT_WEB_AREA;
- root.AddStringAttribute(ui::AX_ATTR_DESCRIPTION, "HelpText");
- root.child_ids.push_back(1001);
- root.child_ids.push_back(1002);
+ // Clean out the existing root data in case this method is called multiple
+ // times in a test.
+ root_ = ui::AXNodeData();
+ root_.id = 1000;
+ root_.location.set_width(500);
+ root_.location.set_height(100);
+ root_.role = ui::AX_ROLE_ROOT_WEB_AREA;
+ root_.AddStringAttribute(ui::AX_ATTR_DESCRIPTION, "HelpText");
+ root_.child_ids.push_back(1001);
+ root_.child_ids.push_back(1002);
ui::AXNodeData child1;
child1.id = 1001;
@@ -51,14 +57,25 @@ class BrowserAccessibilityTest : public ui::CocoaTest {
child2.location.set_height(100);
child2.role = ui::AX_ROLE_HEADING;
- manager_.reset(
- new BrowserAccessibilityManagerMac(
- MakeAXTreeUpdate(root, child1, child2),
- NULL));
+ manager_.reset(new BrowserAccessibilityManagerMac(
+ MakeAXTreeUpdate(root_, child1, child2), nullptr));
accessibility_.reset([ToBrowserAccessibilityCocoa(manager_->GetRoot())
retain]);
}
+ void SetRootValue(std::string value) {
+ if (!manager_)
+ return;
+ root_.SetValue(value);
+ AXEventNotificationDetails param;
+ param.update.nodes.push_back(root_);
+ param.event_type = ui::AX_EVENT_VALUE_CHANGED;
+ param.id = root_.id;
+ std::vector<AXEventNotificationDetails> events{param};
+ manager_->OnAccessibilityEvents(events);
+ }
+
+ ui::AXNodeData root_;
base::scoped_nsobject<BrowserAccessibilityCocoa> accessibility_;
std::unique_ptr<BrowserAccessibilityManager> manager_;
};
@@ -126,4 +143,72 @@ TEST_F(BrowserAccessibilityTest, RetainedDetachedObjectsReturnNil) {
[retainedFirstChild release];
}
+TEST_F(BrowserAccessibilityTest, TestComputeTextEdit) {
+ BrowserAccessibility* wrapper = [accessibility_ browserAccessibility];
+ ASSERT_NE(nullptr, wrapper);
+
+ // Insertion but no deletion.
+
+ SetRootValue("text");
+ AXTextEdit text_edit = [accessibility_ computeTextEdit];
+ EXPECT_EQ(base::UTF8ToUTF16("text"), text_edit.inserted_text);
+ EXPECT_TRUE(text_edit.deleted_text.empty());
+
+ SetRootValue("new text");
+ text_edit = [accessibility_ computeTextEdit];
+ EXPECT_EQ(base::UTF8ToUTF16("new "), text_edit.inserted_text);
+ EXPECT_TRUE(text_edit.deleted_text.empty());
+
+ SetRootValue("new text hello");
+ text_edit = [accessibility_ computeTextEdit];
+ EXPECT_EQ(base::UTF8ToUTF16(" hello"), text_edit.inserted_text);
+ EXPECT_TRUE(text_edit.deleted_text.empty());
+
+ SetRootValue("newer text hello");
+ text_edit = [accessibility_ computeTextEdit];
+ EXPECT_EQ(base::UTF8ToUTF16("er"), text_edit.inserted_text);
+ EXPECT_TRUE(text_edit.deleted_text.empty());
+
+ // Deletion but no insertion.
+
+ SetRootValue("new text hello");
+ text_edit = [accessibility_ computeTextEdit];
+ EXPECT_EQ(base::UTF8ToUTF16("er"), text_edit.deleted_text);
+ EXPECT_TRUE(text_edit.inserted_text.empty());
+
+ SetRootValue("new text");
+ text_edit = [accessibility_ computeTextEdit];
+ EXPECT_EQ(base::UTF8ToUTF16(" hello"), text_edit.deleted_text);
+ EXPECT_TRUE(text_edit.inserted_text.empty());
+
+ SetRootValue("text");
+ text_edit = [accessibility_ computeTextEdit];
+ EXPECT_EQ(base::UTF8ToUTF16("new "), text_edit.deleted_text);
+ EXPECT_TRUE(text_edit.inserted_text.empty());
+
+ SetRootValue("");
+ text_edit = [accessibility_ computeTextEdit];
+ EXPECT_EQ(base::UTF8ToUTF16("text"), text_edit.deleted_text);
+ EXPECT_TRUE(text_edit.inserted_text.empty());
+
+ // Both insertion and deletion.
+
+ SetRootValue("new text hello");
+ text_edit = [accessibility_ computeTextEdit];
+ SetRootValue("new word hello");
+ text_edit = [accessibility_ computeTextEdit];
+ EXPECT_EQ(base::UTF8ToUTF16("text"), text_edit.deleted_text);
+ EXPECT_EQ(base::UTF8ToUTF16("word"), text_edit.inserted_text);
+
+ SetRootValue("new word there");
+ text_edit = [accessibility_ computeTextEdit];
+ EXPECT_EQ(base::UTF8ToUTF16("hello"), text_edit.deleted_text);
+ EXPECT_EQ(base::UTF8ToUTF16("there"), text_edit.inserted_text);
+
+ SetRootValue("old word there");
+ text_edit = [accessibility_ computeTextEdit];
+ EXPECT_EQ(base::UTF8ToUTF16("new"), text_edit.deleted_text);
+ EXPECT_EQ(base::UTF8ToUTF16("old"), text_edit.inserted_text);
+}
+
} // namespace content
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager.cc b/chromium/content/browser/accessibility/browser_accessibility_manager.cc
index 30099107b33..38269319de3 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager.cc
@@ -137,7 +137,6 @@ BrowserAccessibilityManager::BrowserAccessibilityManager(
factory_(factory),
tree_(new ui::AXSerializableTree()),
user_is_navigating_away_(false),
- osk_state_(OSK_ALLOWED),
last_focused_node_(nullptr),
last_focused_manager_(nullptr),
connected_to_parent_tree_node_(false),
@@ -156,7 +155,6 @@ BrowserAccessibilityManager::BrowserAccessibilityManager(
factory_(factory),
tree_(new ui::AXSerializableTree()),
user_is_navigating_away_(false),
- osk_state_(OSK_ALLOWED),
last_focused_node_(nullptr),
last_focused_manager_(nullptr),
ax_tree_id_(ui::AXTreeIDRegistry::kNoAXTreeID),
@@ -225,10 +223,9 @@ void BrowserAccessibilityManager::FireFocusEventsIfNeeded(
// Don't allow the document to be focused if it has no children and
// hasn't finished loading yet. Wait for at least a tiny bit of content,
// or for the document to actually finish loading.
- if (focus &&
- focus == focus->manager()->GetRoot() &&
+ if (focus && focus == focus->manager()->GetRoot() &&
focus->PlatformChildCount() == 0 &&
- !focus->HasState(ui::AX_STATE_BUSY) &&
+ !focus->GetBoolAttribute(ui::AX_ATTR_BUSY) &&
!focus->manager()->GetTreeData().loaded) {
focus = nullptr;
}
@@ -434,18 +431,18 @@ void BrowserAccessibilityManager::OnAccessibilityEvents(
ui::AXEvent event_type = detail.event_type;
-#if defined(OS_MACOSX)
- if (event_type != ui::AX_EVENT_HOVER)
+// On Mac and Windows, nearly all events are now fired implicitly,
+// so we should ignore most events from the renderer.
+#if defined(OS_MACOSX) || defined(OS_WIN)
+ if (event_type != ui::AX_EVENT_HOVER &&
+ event_type != ui::AX_EVENT_LOCATION_CHANGED &&
+ event_type != ui::AX_EVENT_SCROLLED_TO_ANCHOR) {
continue;
+ }
#endif // !defined(OS_MACOSX)
if (event_type == ui::AX_EVENT_FOCUS ||
event_type == ui::AX_EVENT_BLUR) {
- if (osk_state_ != OSK_DISALLOWED_BECAUSE_TAB_HIDDEN &&
- osk_state_ != OSK_DISALLOWED_BECAUSE_TAB_JUST_APPEARED) {
- osk_state_ = OSK_ALLOWED;
- }
-
// We already handled all focus events above.
continue;
}
@@ -763,13 +760,13 @@ void BrowserAccessibilityManager::SetSelection(AXPlatformRange range) {
delegate_->AccessibilityPerformAction(action_data);
}
-void BrowserAccessibilityManager::SetAccessibilityFocus(
+void BrowserAccessibilityManager::LoadInlineTextBoxes(
const BrowserAccessibility& node) {
if (!delegate_)
return;
ui::AXActionData action_data;
- action_data.action = ui::AX_ACTION_SET_ACCESSIBILITY_FOCUS;
+ action_data.action = ui::AX_ACTION_LOAD_INLINE_TEXT_BOXES;
action_data.target_node_id = node.GetId();
delegate_->AccessibilityPerformAction(action_data);
}
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager.h b/chromium/content/browser/accessibility/browser_accessibility_manager.h
index 47338156051..9486d9f761d 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager.h
@@ -202,6 +202,7 @@ class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXTreeDelegate {
const gfx::Size& max_size);
void HitTest(const gfx::Point& point);
void Increment(const BrowserAccessibility& node);
+ void LoadInlineTextBoxes(const BrowserAccessibility& node);
void ScrollToMakeVisible(
const BrowserAccessibility& node, gfx::Rect subfocus);
void ScrollToPoint(
@@ -212,7 +213,6 @@ class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXTreeDelegate {
const BrowserAccessibility& node, const base::string16& value);
void SetSelection(
ui::AXRange<AXPlatformPosition::AXPositionInstance::element_type> range);
- void SetAccessibilityFocus(const BrowserAccessibility& node);
void ShowContextMenu(const BrowserAccessibility& node);
// Retrieve the bounds of the parent View in screen coordinates.
@@ -411,29 +411,6 @@ class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXTreeDelegate {
virtual void SendLocationChangeEvents(
const std::vector<AccessibilityHostMsg_LocationChangeParams>& params);
- private:
- // The following states keep track of whether or not the
- // on-screen keyboard is allowed to be shown.
- enum OnScreenKeyboardState {
- // Never show the on-screen keyboard because this tab is hidden.
- OSK_DISALLOWED_BECAUSE_TAB_HIDDEN,
-
- // This tab was just shown, so don't pop-up the on-screen keyboard if a
- // text field gets focus that wasn't the result of an explicit touch.
- OSK_DISALLOWED_BECAUSE_TAB_JUST_APPEARED,
-
- // A touch event has occurred within the window, but focus has not
- // explicitly changed. Allow the on-screen keyboard to be shown if the
- // touch event was within the bounds of the currently focused object.
- // Otherwise we'll just wait to see if focus changes.
- OSK_ALLOWED_WITHIN_FOCUSED_OBJECT,
-
- // Focus has changed within a tab that's already visible. Allow the
- // on-screen keyboard to show anytime that a touch event leads to an
- // editable text control getting focus.
- OSK_ALLOWED
- };
-
protected:
// The object that can perform actions on our behalf.
BrowserAccessibilityDelegate* delegate_;
@@ -455,9 +432,6 @@ class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXTreeDelegate {
// True if the user has initiated a navigation to another page.
bool user_is_navigating_away_;
- // The on-screen keyboard state.
- OnScreenKeyboardState osk_state_;
-
BrowserAccessibilityFindInPageInfo find_in_page_info_;
// These are only used by the root BrowserAccessibilityManager of a
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_android.cc b/chromium/content/browser/accessibility/browser_accessibility_manager_android.cc
index 3ad07c1315d..284c4019b1f 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_android.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_android.cc
@@ -65,7 +65,14 @@ bool BrowserAccessibilityManagerAndroid::ShouldExposePasswordText() {
BrowserAccessibility* BrowserAccessibilityManagerAndroid::GetFocus() {
BrowserAccessibility* focus = BrowserAccessibilityManager::GetFocus();
- return GetActiveDescendant(focus);
+ BrowserAccessibilityAndroid* android_focus =
+ static_cast<BrowserAccessibilityAndroid*>(focus);
+ // This is a temporary workaround because we're not distinguishing
+ // between text fields with a role of combobox, and pop-up menu buttons.
+ // TODO(dmazzoni): Handle different types of combo boxes correctly.
+ if (!android_focus->IsEditableText())
+ return GetActiveDescendant(focus);
+ return focus;
}
void BrowserAccessibilityManagerAndroid::NotifyAccessibilityEvent(
@@ -113,7 +120,7 @@ void BrowserAccessibilityManagerAndroid::NotifyAccessibilityEvent(
// Always send AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED to notify
// the Android system that the accessibility hierarchy rooted at this
// node has changed.
- wcax->HandleContentChanged(node->unique_id());
+ wcax->HandleContentChanged(android_node->unique_id());
// Ignore load complete events on iframes.
if (event_type == ui::AX_EVENT_LOAD_COMPLETE &&
@@ -122,23 +129,25 @@ void BrowserAccessibilityManagerAndroid::NotifyAccessibilityEvent(
}
switch (event_type) {
- case ui::AX_EVENT_LOAD_COMPLETE:
- wcax->HandlePageLoaded(GetFocus()->unique_id());
- break;
+ case ui::AX_EVENT_LOAD_COMPLETE: {
+ auto* android_focused =
+ static_cast<BrowserAccessibilityAndroid*>(GetFocus());
+ wcax->HandlePageLoaded(android_focused->unique_id());
+ } break;
case ui::AX_EVENT_FOCUS:
- wcax->HandleFocusChanged(node->unique_id());
+ wcax->HandleFocusChanged(android_node->unique_id());
break;
case ui::AX_EVENT_CHECKED_STATE_CHANGED:
- wcax->HandleCheckStateChanged(node->unique_id());
+ wcax->HandleCheckStateChanged(android_node->unique_id());
break;
case ui::AX_EVENT_CLICKED:
- wcax->HandleClicked(node->unique_id());
+ wcax->HandleClicked(android_node->unique_id());
break;
case ui::AX_EVENT_SCROLL_POSITION_CHANGED:
- wcax->HandleScrollPositionChanged(node->unique_id());
+ wcax->HandleScrollPositionChanged(android_node->unique_id());
break;
case ui::AX_EVENT_SCROLLED_TO_ANCHOR:
- wcax->HandleScrolledToAnchor(node->unique_id());
+ wcax->HandleScrolledToAnchor(android_node->unique_id());
break;
case ui::AX_EVENT_ALERT:
// An alert is a special case of live region. Fall through to the
@@ -151,14 +160,14 @@ void BrowserAccessibilityManagerAndroid::NotifyAccessibilityEvent(
break;
}
case ui::AX_EVENT_TEXT_SELECTION_CHANGED:
- wcax->HandleTextSelectionChanged(node->unique_id());
+ wcax->HandleTextSelectionChanged(android_node->unique_id());
break;
case ui::AX_EVENT_TEXT_CHANGED:
case ui::AX_EVENT_VALUE_CHANGED:
if (android_node->IsEditableText() && GetFocus() == node) {
- wcax->HandleEditableTextChanged(node->unique_id());
+ wcax->HandleEditableTextChanged(android_node->unique_id());
} else if (android_node->IsSlider()) {
- wcax->HandleSliderChanged(node->unique_id());
+ wcax->HandleSliderChanged(android_node->unique_id());
}
break;
default:
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_mac.h b/chromium/content/browser/accessibility/browser_accessibility_manager_mac.h
index 0bb8d824d32..d5508ba09af 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_mac.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_mac.h
@@ -49,9 +49,6 @@ class CONTENT_EXPORT BrowserAccessibilityManagerMac
void OnTreeDataChanged(ui::AXTree* tree,
const ui::AXTreeData& old_tree_data,
const ui::AXTreeData& new_tree_data) override;
- void OnNodeDataWillChange(ui::AXTree* tree,
- const ui::AXNodeData& old_node_data,
- const ui::AXNodeData& new_node_data) override;
void OnStateChanged(ui::AXTree* tree,
ui::AXNode* node,
ui::AXState state,
@@ -84,15 +81,15 @@ class CONTENT_EXPORT BrowserAccessibilityManagerMac
const base::string16& deleted_text,
const base::string16& inserted_text) const;
+ // Keeps track of any edits that have been made by the user during a tree
+ // update. Used by NSAccessibilityValueChangedNotification.
+ // Maps AXNode IDs to value attribute changes.
+ std::map<int32_t, AXTextEdit> text_edits_;
+
// This gives BrowserAccessibilityManager::Create access to the class
// constructor.
friend class BrowserAccessibilityManager;
- // Keeps track of any edits that have been made by the user during a tree
- // update. Used by NSAccessibilityValueChangedNotification.
- // Maps AXNode IDs to name or value attribute changes.
- std::map<int32_t, base::string16> text_edits_;
-
DISALLOW_COPY_AND_ASSIGN(BrowserAccessibilityManagerMac);
};
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_mac.mm b/chromium/content/browser/accessibility/browser_accessibility_manager_mac.mm
index 592560c0291..f798789bf05 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_mac.mm
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_mac.mm
@@ -218,7 +218,8 @@ void BrowserAccessibilityManagerMac::NotifyAccessibilityEvent(
break;
case ui::AX_EVENT_DOCUMENT_SELECTION_CHANGED: {
mac_notification = NSAccessibilitySelectedTextChangedNotification;
- // WebKit fires a notification both on the focused object and the root.
+ // WebKit fires a notification both on the focused object and the page
+ // root.
BrowserAccessibility* focus = GetFocus();
if (!focus)
break; // Just fire a notification on the root.
@@ -231,7 +232,10 @@ void BrowserAccessibilityManagerMac::NotifyAccessibilityEvent(
NSDictionary* user_info =
GetUserInfoForSelectedTextChangedNotification();
- BrowserAccessibility* root = GetRoot();
+ BrowserAccessibilityManager* root_manager = GetRootManager();
+ if (!root_manager)
+ return;
+ BrowserAccessibility* root = root_manager->GetRoot();
if (!root)
return;
@@ -251,15 +255,17 @@ void BrowserAccessibilityManagerMac::NotifyAccessibilityEvent(
break;
case ui::AX_EVENT_VALUE_CHANGED:
mac_notification = NSAccessibilityValueChangedNotification;
- if (base::mac::IsAtLeastOS10_11() && text_edits_.size()) {
- // It seems that we don't need to distinguish between deleted and
- // inserted text for now.
+ if (base::mac::IsAtLeastOS10_11() && !text_edits_.empty()) {
base::string16 deleted_text;
base::string16 inserted_text;
int32_t id = node->GetId();
const auto iterator = text_edits_.find(id);
- if (iterator != text_edits_.end())
- inserted_text = iterator->second;
+ if (iterator != text_edits_.end()) {
+ AXTextEdit text_edit = iterator->second;
+ deleted_text = text_edit.deleted_text;
+ inserted_text = text_edit.inserted_text;
+ }
+
NSDictionary* user_info = GetUserInfoForValueChangedNotification(
native_node, deleted_text, inserted_text);
@@ -382,55 +388,6 @@ void BrowserAccessibilityManagerMac::OnTreeDataChanged(
}
}
-void BrowserAccessibilityManagerMac::OnNodeDataWillChange(
- ui::AXTree* tree,
- const ui::AXNodeData& old_node_data,
- const ui::AXNodeData& new_node_data) {
- BrowserAccessibilityManager::OnNodeDataWillChange(tree, old_node_data,
- new_node_data);
-
- // Starting from OS X 10.11, if the user has edited some text we need to
- // dispatch the actual text that changed on the value changed notification.
- // We run this code on all OS X versions to get the highest test coverage.
- base::string16 old_text, new_text;
- ui::AXRole role = new_node_data.role;
- if (role == ui::AX_ROLE_COMBO_BOX || role == ui::AX_ROLE_SEARCH_BOX ||
- role == ui::AX_ROLE_TEXT_FIELD) {
- old_text = old_node_data.GetString16Attribute(ui::AX_ATTR_VALUE);
- new_text = new_node_data.GetString16Attribute(ui::AX_ATTR_VALUE);
- } else if (new_node_data.HasState(ui::AX_STATE_EDITABLE)) {
- old_text = old_node_data.GetString16Attribute(ui::AX_ATTR_NAME);
- new_text = new_node_data.GetString16Attribute(ui::AX_ATTR_NAME);
- }
-
- if ((old_text.empty() && new_text.empty()) ||
- old_text.length() == new_text.length()) {
- return;
- }
-
- if (old_text.length() < new_text.length()) {
- // Insertion.
- size_t i = 0;
- while (i < old_text.length() && i < new_text.length() &&
- old_text[i] == new_text[i]) {
- ++i;
- }
- size_t length = (new_text.length() - i) - (old_text.length() - i);
- base::string16 inserted_text = new_text.substr(i, length);
- text_edits_[new_node_data.id] = inserted_text;
- } else {
- // Deletion.
- size_t i = 0;
- while (i < old_text.length() && i < new_text.length() &&
- old_text[i] == new_text[i]) {
- ++i;
- }
- size_t length = (old_text.length() - i) - (new_text.length() - i);
- base::string16 deleted_text = old_text.substr(i, length);
- text_edits_[new_node_data.id] = deleted_text;
- }
-}
-
void BrowserAccessibilityManagerMac::OnStateChanged(ui::AXTree* tree,
ui::AXNode* node,
ui::AXState state,
@@ -527,7 +484,17 @@ void BrowserAccessibilityManagerMac::OnAtomicUpdateFinished(
const std::vector<Change>& changes) {
BrowserAccessibilityManager::OnAtomicUpdateFinished(tree, root_changed,
changes);
+
+ std::set<const BrowserAccessibilityCocoa*> changed_editable_roots;
for (const auto& change : changes) {
+ const BrowserAccessibility* obj = GetFromAXNode(change.node);
+ if (obj && obj->IsNative() && obj->HasState(ui::AX_STATE_EDITABLE)) {
+ const BrowserAccessibilityCocoa* editable_root =
+ [ToBrowserAccessibilityCocoa(obj) editableAncestor];
+ if (editable_root && [editable_root instanceActive])
+ changed_editable_roots.insert(editable_root);
+ }
+
if ((change.type == NODE_CREATED || change.type == SUBTREE_CREATED) &&
change.node->data().HasStringAttribute(ui::AX_ATTR_LIVE_STATUS)) {
if (change.node->data().role == ui::AX_ROLE_ALERT)
@@ -548,6 +515,13 @@ void BrowserAccessibilityManagerMac::OnAtomicUpdateFinished(
}
}
+ for (const BrowserAccessibilityCocoa* obj : changed_editable_roots) {
+ DCHECK(obj);
+ const AXTextEdit text_edit = [obj computeTextEdit];
+ if (!text_edit.IsEmpty())
+ text_edits_[[obj browserAccessibility]->GetId()] = text_edit;
+ }
+
if (root_changed && tree->data().loaded)
tree_events_[tree->root()->id()].insert(ui::AX_EVENT_LOAD_COMPLETE);
}
@@ -597,14 +571,16 @@ BrowserAccessibilityManagerMac::GetUserInfoForValueChangedNotification(
NSMutableArray* changes = [[[NSMutableArray alloc] init] autorelease];
if (!deleted_text.empty()) {
[changes addObject:@{
- NSAccessibilityTextEditType : @(AXTextEditTypeUnknown),
+ NSAccessibilityTextEditType : @(AXTextEditTypeDelete),
NSAccessibilityTextChangeValueLength : @(deleted_text.length()),
NSAccessibilityTextChangeValue : base::SysUTF16ToNSString(deleted_text)
}];
}
if (!inserted_text.empty()) {
+ // TODO(nektar): Figure out if this is a paste operation instead of typing.
+ // Changes to Blink would be required.
[changes addObject:@{
- NSAccessibilityTextEditType : @(AXTextEditTypeUnknown),
+ NSAccessibilityTextEditType : @(AXTextEditTypeTyping),
NSAccessibilityTextChangeValueLength : @(inserted_text.length()),
NSAccessibilityTextChangeValue : base::SysUTF16ToNSString(inserted_text)
}];
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_win.cc b/chromium/content/browser/accessibility/browser_accessibility_manager_win.cc
index bc7c0747547..92bd3041a77 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_win.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_win.cc
@@ -21,6 +21,28 @@
namespace content {
+namespace {
+
+bool IsContainerWithSelectableChildrenRole(ui::AXRole role) {
+ switch (role) {
+ case ui::AX_ROLE_COMBO_BOX:
+ case ui::AX_ROLE_GRID:
+ case ui::AX_ROLE_LIST_BOX:
+ case ui::AX_ROLE_MENU:
+ case ui::AX_ROLE_MENU_BAR:
+ case ui::AX_ROLE_RADIO_GROUP:
+ case ui::AX_ROLE_TAB_LIST:
+ case ui::AX_ROLE_TOOLBAR:
+ case ui::AX_ROLE_TREE:
+ case ui::AX_ROLE_TREE_GRID:
+ return true;
+ default:
+ return false;
+ }
+}
+
+} // namespace
+
// static
BrowserAccessibilityManager* BrowserAccessibilityManager::Create(
const ui::AXTreeUpdate& initial_tree,
@@ -59,7 +81,7 @@ ui::AXTreeUpdate
ui::AXNodeData empty_document;
empty_document.id = 0;
empty_document.role = ui::AX_ROLE_ROOT_WEB_AREA;
- empty_document.AddState(ui::AX_STATE_BUSY);
+ empty_document.AddBoolAttribute(ui::AX_ATTR_BUSY, true);
ui::AXTreeUpdate update;
update.root_id = empty_document.id;
@@ -86,7 +108,7 @@ void BrowserAccessibilityManagerWin::OnIAccessible2Used() {
// enable basic web accessibility support. (Full screen reader support is
// detected later when specific more advanced APIs are accessed.)
BrowserAccessibilityStateImpl::GetInstance()->AddAccessibilityModeFlags(
- AccessibilityMode::kNativeAPIs | AccessibilityMode::kWebContents);
+ ui::AXMode::kNativeAPIs | ui::AXMode::kWebContents);
}
void BrowserAccessibilityManagerWin::UserIsReloading() {
@@ -175,6 +197,9 @@ BrowserAccessibilityEvent::Result
if (user_is_navigating_away_)
return BrowserAccessibilityEvent::DiscardedBecauseUserNavigatingAway;
+ if (!target)
+ return BrowserAccessibilityEvent::FailedBecauseNoFocus;
+
// Inline text boxes are an internal implementation detail, we don't
// expose them to Windows.
if (target->GetRole() == ui::AX_ROLE_INLINE_TEXT_BOX)
@@ -186,9 +211,6 @@ BrowserAccessibilityEvent::Result
return BrowserAccessibilityEvent::DiscardedBecauseLiveRegionBusy;
}
- if (!target)
- return BrowserAccessibilityEvent::FailedBecauseNoFocus;
-
event->set_target(target);
// It doesn't make sense to fire a REORDER event on a leaf node; that
@@ -202,7 +224,7 @@ BrowserAccessibilityEvent::Result
// argument to NotifyWinEvent; the AT client will then call get_accChild
// on the HWND's accessibility object and pass it that same id, which
// we can use to retrieve the IAccessible for this node.
- LONG child_id = -target->unique_id();
+ LONG child_id = -(ToBrowserAccessibilityWin(target)->GetCOM()->unique_id());
::NotifyWinEvent(win_event_type, hwnd, OBJID_CLIENT, child_id);
return BrowserAccessibilityEvent::Sent;
}
@@ -243,6 +265,26 @@ gfx::Rect BrowserAccessibilityManagerWin::GetViewBounds() {
return gfx::Rect();
}
+void BrowserAccessibilityManagerWin::OnTreeDataChanged(
+ ui::AXTree* tree,
+ const ui::AXTreeData& old_tree_data,
+ const ui::AXTreeData& new_tree_data) {
+ BrowserAccessibilityManager::OnTreeDataChanged(tree, old_tree_data,
+ new_tree_data);
+ if (new_tree_data.loaded && !old_tree_data.loaded)
+ tree_events_[tree->root()->id()].insert(ui::AX_EVENT_LOAD_COMPLETE);
+ if (new_tree_data.sel_anchor_object_id !=
+ old_tree_data.sel_anchor_object_id ||
+ new_tree_data.sel_anchor_offset != old_tree_data.sel_anchor_offset ||
+ new_tree_data.sel_anchor_affinity != old_tree_data.sel_anchor_affinity ||
+ new_tree_data.sel_focus_object_id != old_tree_data.sel_focus_object_id ||
+ new_tree_data.sel_focus_offset != old_tree_data.sel_focus_offset ||
+ new_tree_data.sel_focus_affinity != old_tree_data.sel_focus_affinity) {
+ tree_events_[tree->root()->id()].insert(
+ ui::AX_EVENT_DOCUMENT_SELECTION_CHANGED);
+ }
+}
+
void BrowserAccessibilityManagerWin::OnNodeCreated(ui::AXTree* tree,
ui::AXNode* node) {
DCHECK(node);
@@ -254,6 +296,53 @@ void BrowserAccessibilityManagerWin::OnNodeCreated(ui::AXTree* tree,
return;
}
+void BrowserAccessibilityManagerWin::OnNodeDataWillChange(
+ ui::AXTree* tree,
+ const ui::AXNodeData& old_node_data,
+ const ui::AXNodeData& new_node_data) {
+ if (new_node_data.child_ids != old_node_data.child_ids &&
+ new_node_data.role != ui::AX_ROLE_STATIC_TEXT) {
+ tree_events_[new_node_data.id].insert(ui::AX_EVENT_CHILDREN_CHANGED);
+ }
+}
+
+void BrowserAccessibilityManagerWin::OnStateChanged(ui::AXTree* tree,
+ ui::AXNode* node,
+ ui::AXState state,
+ bool new_value) {
+ if (state == ui::AX_STATE_SELECTED) {
+ ui::AXNode* container = node;
+ while (container &&
+ !IsContainerWithSelectableChildrenRole(container->data().role))
+ container = container->parent();
+ if (container) {
+ tree_events_[container->id()].insert(
+ ui::AX_EVENT_SELECTED_CHILDREN_CHANGED);
+ }
+ }
+}
+
+void BrowserAccessibilityManagerWin::OnIntAttributeChanged(
+ ui::AXTree* tree,
+ ui::AXNode* node,
+ ui::AXIntAttribute attr,
+ int32_t old_value,
+ int32_t new_value) {
+ BrowserAccessibilityManager::OnIntAttributeChanged(tree, node, attr,
+ old_value, new_value);
+ switch (attr) {
+ case ui::AX_ATTR_ACTIVEDESCENDANT_ID:
+ tree_events_[node->id()].insert(ui::AX_EVENT_ACTIVEDESCENDANTCHANGED);
+ break;
+ case ui::AX_ATTR_SCROLL_X:
+ case ui::AX_ATTR_SCROLL_Y:
+ tree_events_[node->id()].insert(ui::AX_EVENT_SCROLL_POSITION_CHANGED);
+ break;
+ default:
+ break;
+ }
+}
+
void BrowserAccessibilityManagerWin::OnAtomicUpdateFinished(
ui::AXTree* tree,
bool root_changed,
@@ -261,25 +350,44 @@ void BrowserAccessibilityManagerWin::OnAtomicUpdateFinished(
BrowserAccessibilityManager::OnAtomicUpdateFinished(
tree, root_changed, changes);
+ if (root_changed && tree->data().loaded)
+ tree_events_[tree->root()->id()].insert(ui::AX_EVENT_LOAD_COMPLETE);
+
+ // Handle live region changes.
+ for (size_t i = 0; i < changes.size(); ++i) {
+ const ui::AXNode* node = changes[i].node;
+ DCHECK(node);
+ if (node->data().HasStringAttribute(ui::AX_ATTR_CONTAINER_LIVE_STATUS)) {
+ const ui::AXNode* container = node;
+ while (container &&
+ !container->data().HasStringAttribute(ui::AX_ATTR_LIVE_STATUS)) {
+ container = container->parent();
+ }
+ if (container)
+ tree_events_[container->id()].insert(ui::AX_EVENT_LIVE_REGION_CHANGED);
+ }
+ }
+
// Do a sequence of Windows-specific updates on each node. Each one is
// done in a single pass that must complete before the next step starts.
// The first step moves win_attributes_ to old_win_attributes_ and then
// recomputes all of win_attributes_ other than IAccessibleText.
- for (size_t i = 0; i < changes.size(); ++i) {
- const ui::AXNode* changed_node = changes[i].node;
+ for (const auto& change : changes) {
+ const ui::AXNode* changed_node = change.node;
DCHECK(changed_node);
BrowserAccessibility* obj = GetFromAXNode(changed_node);
- if (obj && obj->IsNative() && !obj->PlatformIsChildOfLeaf())
+ if (obj && obj->IsNative() && !obj->PlatformIsChildOfLeaf()) {
ToBrowserAccessibilityWin(obj)
->GetCOM()
->UpdateStep1ComputeWinAttributes();
+ }
}
// The next step updates the hypertext of each node, which is a
// concatenation of all of its child text nodes, so it can't run until
// the text of all of the nodes was computed in the previous step.
- for (size_t i = 0; i < changes.size(); ++i) {
- const ui::AXNode* changed_node = changes[i].node;
+ for (const auto& change : changes) {
+ const ui::AXNode* changed_node = change.node;
DCHECK(changed_node);
BrowserAccessibility* obj = GetFromAXNode(changed_node);
if (obj && obj->IsNative() && !obj->PlatformIsChildOfLeaf())
@@ -294,13 +402,13 @@ void BrowserAccessibilityManagerWin::OnAtomicUpdateFinished(
// client may walk the tree when it receives any of these events.
// At the end, it deletes old_win_attributes_ since they're not needed
// anymore.
- for (size_t i = 0; i < changes.size(); ++i) {
- const ui::AXNode* changed_node = changes[i].node;
+ for (const auto& change : changes) {
+ const ui::AXNode* changed_node = change.node;
DCHECK(changed_node);
BrowserAccessibility* obj = GetFromAXNode(changed_node);
if (obj && obj->IsNative() && !obj->PlatformIsChildOfLeaf()) {
ToBrowserAccessibilityWin(obj)->GetCOM()->UpdateStep3FireEvents(
- changes[i].type == AXTreeDelegate::SUBTREE_CREATED);
+ change.type == AXTreeDelegate::SUBTREE_CREATED);
}
}
}
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_win.h b/chromium/content/browser/accessibility/browser_accessibility_manager_win.h
index a2bb57ebd10..c13c1644469 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_win.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_win.h
@@ -66,7 +66,22 @@ class CONTENT_EXPORT BrowserAccessibilityManagerWin
protected:
// AXTreeDelegate methods.
+ void OnTreeDataChanged(ui::AXTree* tree,
+ const ui::AXTreeData& old_tree_data,
+ const ui::AXTreeData& new_tree_data) override;
void OnNodeCreated(ui::AXTree* tree, ui::AXNode* node) override;
+ void OnNodeDataWillChange(ui::AXTree* tree,
+ const ui::AXNodeData& old_node_data,
+ const ui::AXNodeData& new_node_data) override;
+ void OnStateChanged(ui::AXTree* tree,
+ ui::AXNode* node,
+ ui::AXState state,
+ bool new_value) override;
+ void OnIntAttributeChanged(ui::AXTree* tree,
+ ui::AXNode* node,
+ ui::AXIntAttribute attr,
+ int32_t old_value,
+ int32_t new_value) override;
void OnAtomicUpdateFinished(
ui::AXTree* tree,
bool root_changed,
diff --git a/chromium/content/browser/accessibility/browser_accessibility_state_impl.cc b/chromium/content/browser/accessibility/browser_accessibility_state_impl.cc
index f55c5b9e150..b403657f0ba 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_state_impl.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_state_impl.cc
@@ -14,6 +14,7 @@
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_switches.h"
+#include "ui/accessibility/platform/ax_platform_node.h"
#include "ui/gfx/color_utils.h"
namespace content {
@@ -63,6 +64,9 @@ BrowserAccessibilityStateImpl::BrowserAccessibilityStateImpl()
// delete it prematurely.
AddRef();
+ // Hook ourselves up to observe ax mode changes.
+ ui::AXPlatformNode::AddAXModeObserver(this);
+
#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
@@ -76,12 +80,14 @@ BrowserAccessibilityStateImpl::BrowserAccessibilityStateImpl()
// thread because it needs to be able to access PrefService.
BrowserThread::PostDelayedTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&BrowserAccessibilityStateImpl::UpdateHistograms, this),
+ base::BindOnce(&BrowserAccessibilityStateImpl::UpdateHistograms, this),
base::TimeDelta::FromSeconds(ACCESSIBILITY_HISTOGRAM_DELAY_SECS));
#endif
}
BrowserAccessibilityStateImpl::~BrowserAccessibilityStateImpl() {
+ // Remove ourselves from the AXMode global observer list.
+ ui::AXPlatformNode::RemoveAXModeObserver(this);
}
void BrowserAccessibilityStateImpl::OnScreenReaderDetected() {
@@ -93,7 +99,7 @@ void BrowserAccessibilityStateImpl::OnScreenReaderDetected() {
}
void BrowserAccessibilityStateImpl::EnableAccessibility() {
- AddAccessibilityModeFlags(kAccessibilityModeComplete);
+ AddAccessibilityModeFlags(ui::kAXModeComplete);
}
void BrowserAccessibilityStateImpl::DisableAccessibility() {
@@ -101,10 +107,10 @@ void BrowserAccessibilityStateImpl::DisableAccessibility() {
}
void BrowserAccessibilityStateImpl::ResetAccessibilityModeValue() {
- accessibility_mode_ = AccessibilityMode();
+ accessibility_mode_ = ui::AXMode();
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kForceRendererAccessibility)) {
- accessibility_mode_ = kAccessibilityModeComplete;
+ accessibility_mode_ = ui::kAXModeComplete;
}
}
@@ -118,7 +124,7 @@ void BrowserAccessibilityStateImpl::ResetAccessibilityMode() {
}
bool BrowserAccessibilityStateImpl::IsAccessibleBrowser() {
- return accessibility_mode_ == kAccessibilityModeComplete;
+ return accessibility_mode_ == ui::kAXModeComplete;
}
void BrowserAccessibilityStateImpl::AddHistogramCallback(
@@ -147,34 +153,37 @@ void BrowserAccessibilityStateImpl::UpdateHistograms() {
switches::kForceRendererAccessibility));
}
+void BrowserAccessibilityStateImpl::OnAXModeAdded(ui::AXMode mode) {
+ AddAccessibilityModeFlags(mode);
+}
+
#if !defined(OS_WIN) && !defined(OS_MACOSX)
void BrowserAccessibilityStateImpl::UpdatePlatformSpecificHistograms() {
}
#endif
-void BrowserAccessibilityStateImpl::AddAccessibilityModeFlags(
- AccessibilityMode mode) {
+void BrowserAccessibilityStateImpl::AddAccessibilityModeFlags(ui::AXMode mode) {
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableRendererAccessibility)) {
return;
}
- AccessibilityMode previous_mode = accessibility_mode_;
+ ui::AXMode previous_mode = accessibility_mode_;
accessibility_mode_ |= mode;
if (accessibility_mode_ == previous_mode)
return;
// Retrieve only newly added modes for the purposes of logging.
int new_mode_flags = mode.mode() & (~previous_mode.mode());
- if (new_mode_flags & AccessibilityMode::kNativeAPIs)
+ if (new_mode_flags & ui::AXMode::kNativeAPIs)
RecordNewAccessibilityModeFlags(UMA_AX_MODE_NATIVE_APIS);
- if (new_mode_flags & AccessibilityMode::kWebContents)
+ if (new_mode_flags & ui::AXMode::kWebContents)
RecordNewAccessibilityModeFlags(UMA_AX_MODE_WEB_CONTENTS);
- if (new_mode_flags & AccessibilityMode::kInlineTextBoxes)
+ if (new_mode_flags & ui::AXMode::kInlineTextBoxes)
RecordNewAccessibilityModeFlags(UMA_AX_MODE_INLINE_TEXT_BOXES);
- if (new_mode_flags & AccessibilityMode::kScreenReader)
+ if (new_mode_flags & ui::AXMode::kScreenReader)
RecordNewAccessibilityModeFlags(UMA_AX_MODE_SCREEN_READER);
- if (new_mode_flags & AccessibilityMode::kHTML)
+ if (new_mode_flags & ui::AXMode::kHTML)
RecordNewAccessibilityModeFlags(UMA_AX_MODE_HTML);
std::vector<WebContentsImpl*> web_contents_vector =
@@ -184,10 +193,10 @@ void BrowserAccessibilityStateImpl::AddAccessibilityModeFlags(
}
void BrowserAccessibilityStateImpl::RemoveAccessibilityModeFlags(
- AccessibilityMode mode) {
+ ui::AXMode mode) {
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kForceRendererAccessibility) &&
- mode == kAccessibilityModeComplete) {
+ mode == ui::kAXModeComplete) {
return;
}
diff --git a/chromium/content/browser/accessibility/browser_accessibility_state_impl.h b/chromium/content/browser/accessibility/browser_accessibility_state_impl.h
index f330fc243e9..1eb3033e6d8 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_state_impl.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_state_impl.h
@@ -10,8 +10,9 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/singleton.h"
-#include "content/common/accessibility_mode.h"
#include "content/public/browser/browser_accessibility_state.h"
+#include "ui/accessibility/ax_mode_observer.h"
+#include "ui/accessibility/ax_modes.h"
namespace content {
@@ -34,7 +35,8 @@ namespace content {
// mechanism).
class CONTENT_EXPORT BrowserAccessibilityStateImpl
: public base::RefCountedThreadSafe<BrowserAccessibilityStateImpl>,
- public BrowserAccessibilityState {
+ public BrowserAccessibilityState,
+ public ui::AXModeObserver {
public:
BrowserAccessibilityStateImpl();
@@ -49,15 +51,18 @@ class CONTENT_EXPORT BrowserAccessibilityStateImpl
void UpdateHistogramsForTesting() override;
- AccessibilityMode accessibility_mode() const { return accessibility_mode_; };
+ // AXModeObserver
+ void OnAXModeAdded(ui::AXMode mode) override;
+
+ ui::AXMode accessibility_mode() const { return accessibility_mode_; };
// Adds the given accessibility mode flags to the current accessibility
// mode bitmap.
- void AddAccessibilityModeFlags(AccessibilityMode mode);
+ void AddAccessibilityModeFlags(ui::AXMode mode);
// Remove the given accessibility mode flags from the current accessibility
// mode bitmap.
- void RemoveAccessibilityModeFlags(AccessibilityMode mode);
+ void RemoveAccessibilityModeFlags(ui::AXMode mode);
// Accessibility objects can have the "hot tracked" state set when
// the mouse is hovering over them, but this makes tests flaky because
@@ -87,7 +92,7 @@ class CONTENT_EXPORT BrowserAccessibilityStateImpl
void UpdatePlatformSpecificHistograms();
- AccessibilityMode accessibility_mode_;
+ ui::AXMode accessibility_mode_;
std::vector<base::Closure> histogram_callbacks_;
diff --git a/chromium/content/browser/accessibility/browser_accessibility_win.cc b/chromium/content/browser/accessibility/browser_accessibility_win.cc
index 7e9341c5e0b..604c4f910c2 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_win.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_win.cc
@@ -4,6 +4,7 @@
#include "content/browser/accessibility/browser_accessibility_win.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
+#include "content/browser/accessibility/browser_accessibility_state_impl.h"
#include "ui/base/win/atl_module.h"
diff --git a/chromium/content/browser/accessibility/browser_accessibility_win_unittest.cc b/chromium/content/browser/accessibility/browser_accessibility_win_unittest.cc
index c3b96724cdb..cac0cf8943b 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_win_unittest.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_win_unittest.cc
@@ -22,6 +22,7 @@
#include "content/common/accessibility_messages.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/accessibility/platform/ax_platform_node_win.h"
#include "ui/base/win/atl_module.h"
namespace content {
@@ -630,7 +631,6 @@ TEST_F(BrowserAccessibilityTest, TestComplexHypertext) {
TEST_F(BrowserAccessibilityTest, TestCreateEmptyDocument) {
// Try creating an empty document with busy state. Readonly is
// set automatically.
- const int32_t busy_state = 1 << ui::AX_STATE_BUSY;
std::unique_ptr<BrowserAccessibilityManager> manager(
new BrowserAccessibilityManagerWin(
BrowserAccessibilityManagerWin::GetEmptyDocument(), nullptr,
@@ -640,7 +640,8 @@ TEST_F(BrowserAccessibilityTest, TestCreateEmptyDocument) {
BrowserAccessibility* root = manager->GetRoot();
EXPECT_EQ(0, root->GetId());
EXPECT_EQ(ui::AX_ROLE_ROOT_WEB_AREA, root->GetRole());
- EXPECT_EQ(busy_state, root->GetState());
+ EXPECT_EQ(0, root->GetState());
+ EXPECT_EQ(true, root->GetBoolAttribute(ui::AX_ATTR_BUSY));
// Tree with a child textfield.
ui::AXNodeData tree1_1;
@@ -704,6 +705,11 @@ TEST_F(BrowserAccessibilityTest, TestCreateEmptyDocument) {
manager.reset();
}
+int32_t GetUniqueId(BrowserAccessibility* accessibility) {
+ BrowserAccessibilityWin* win_root = ToBrowserAccessibilityWin(accessibility);
+ return win_root->GetCOM()->unique_id();
+}
+
// This is a regression test for a bug where the initial empty document
// loaded by a BrowserAccessibilityManagerWin couldn't be looked up by
// its UniqueIDWin, because the AX Tree was loaded in
@@ -719,10 +725,17 @@ TEST_F(BrowserAccessibilityTest, EmptyDocHasUniqueIdWin) {
BrowserAccessibility* root = manager->GetRoot();
EXPECT_EQ(0, root->GetId());
EXPECT_EQ(ui::AX_ROLE_ROOT_WEB_AREA, root->GetRole());
- EXPECT_EQ(1 << ui::AX_STATE_BUSY, root->GetState());
+ EXPECT_EQ(0, root->GetState());
+ EXPECT_EQ(true, root->GetBoolAttribute(ui::AX_ATTR_BUSY));
+
+ BrowserAccessibilityWin* win_root = ToBrowserAccessibilityWin(root);
+
+ ui::AXPlatformNode* node = static_cast<ui::AXPlatformNode*>(
+ ui::AXPlatformNodeWin::GetFromUniqueId(GetUniqueId(win_root)));
- int32_t unique_id = ToBrowserAccessibilityWin(root)->unique_id();
- ASSERT_EQ(root, BrowserAccessibility::GetFromUniqueID(unique_id));
+ ui::AXPlatformNode* other_node =
+ static_cast<ui::AXPlatformNode*>(win_root->GetCOM());
+ ASSERT_EQ(node, other_node);
}
TEST_F(BrowserAccessibilityTest, TestIA2Attributes) {
@@ -2177,18 +2190,18 @@ TEST_F(BrowserAccessibilityTest, UniqueIdWinInvalidAfterDeletingTree) {
new BrowserAccessibilityFactory()));
BrowserAccessibility* root = manager->GetRoot();
- int32_t root_unique_id = root->unique_id();
+ int32_t root_unique_id = GetUniqueId(root);
BrowserAccessibility* child = root->PlatformGetChild(0);
- int32_t child_unique_id = child->unique_id();
+ int32_t child_unique_id = GetUniqueId(child);
// Now destroy that original tree and create a new tree.
manager.reset(new BrowserAccessibilityManagerWin(
MakeAXTreeUpdate(root_node, child_node), nullptr,
new BrowserAccessibilityFactory()));
root = manager->GetRoot();
- int32_t root_unique_id_2 = root->unique_id();
+ int32_t root_unique_id_2 = GetUniqueId(root);
child = root->PlatformGetChild(0);
- int32_t child_unique_id_2 = child->unique_id();
+ int32_t child_unique_id_2 = GetUniqueId(child);
// The nodes in the new tree should not have the same ids.
EXPECT_NE(root_unique_id, root_unique_id_2);
@@ -2238,13 +2251,13 @@ TEST_F(BrowserAccessibilityTest, AccChildOnlyReturnsDescendants) {
BrowserAccessibility* root = manager->GetRoot();
BrowserAccessibility* child = root->PlatformGetChild(0);
- base::win::ScopedVariant root_unique_id_variant(-root->unique_id());
+ base::win::ScopedVariant root_unique_id_variant(-GetUniqueId(root));
base::win::ScopedComPtr<IDispatch> result;
EXPECT_EQ(E_INVALIDARG,
ToBrowserAccessibilityWin(child)->GetCOM()->get_accChild(
root_unique_id_variant, result.GetAddressOf()));
- base::win::ScopedVariant child_unique_id_variant(-child->unique_id());
+ base::win::ScopedVariant child_unique_id_variant(-GetUniqueId(child));
EXPECT_EQ(S_OK, ToBrowserAccessibilityWin(root)->GetCOM()->get_accChild(
child_unique_id_variant, result.GetAddressOf()));
}
@@ -2308,7 +2321,7 @@ TEST_F(BrowserAccessibilityTest, TestIAccessible2Relations) {
describedby_relation->get_target(0, target.GetAddressOf()));
target.CopyTo(ax_target.GetAddressOf());
EXPECT_HRESULT_SUCCEEDED(ax_target->get_uniqueID(&unique_id));
- EXPECT_EQ(-ax_child1->unique_id(), unique_id);
+ EXPECT_EQ(-GetUniqueId(ax_child1), unique_id);
ax_target.Reset();
target.Reset();
@@ -2316,7 +2329,7 @@ TEST_F(BrowserAccessibilityTest, TestIAccessible2Relations) {
describedby_relation->get_target(1, target.GetAddressOf()));
target.CopyTo(ax_target.GetAddressOf());
EXPECT_HRESULT_SUCCEEDED(ax_target->get_uniqueID(&unique_id));
- EXPECT_EQ(-ax_child2->unique_id(), unique_id);
+ EXPECT_EQ(-GetUniqueId(ax_child2), unique_id);
ax_target.Reset();
target.Reset();
describedby_relation.Reset();
@@ -2339,7 +2352,7 @@ TEST_F(BrowserAccessibilityTest, TestIAccessible2Relations) {
description_for_relation->get_target(0, target.GetAddressOf()));
target.CopyTo(ax_target.GetAddressOf());
EXPECT_HRESULT_SUCCEEDED(ax_target->get_uniqueID(&unique_id));
- EXPECT_EQ(-ax_root->unique_id(), unique_id);
+ EXPECT_EQ(-GetUniqueId(ax_root), unique_id);
ax_target.Reset();
target.Reset();
description_for_relation.Reset();
@@ -2361,7 +2374,7 @@ TEST_F(BrowserAccessibilityTest, TestIAccessible2Relations) {
description_for_relation->get_target(0, target.GetAddressOf()));
target.CopyTo(ax_target.GetAddressOf());
EXPECT_HRESULT_SUCCEEDED(ax_target->get_uniqueID(&unique_id));
- EXPECT_EQ(-ax_root->unique_id(), unique_id);
+ EXPECT_EQ(-GetUniqueId(ax_root), unique_id);
ax_target.Reset();
target.Reset();
diff --git a/chromium/content/browser/accessibility/cross_platform_accessibility_browsertest.cc b/chromium/content/browser/accessibility/cross_platform_accessibility_browsertest.cc
index 5fd760e3b84..4fb7c11c68c 100644
--- a/chromium/content/browser/accessibility/cross_platform_accessibility_browsertest.cc
+++ b/chromium/content/browser/accessibility/cross_platform_accessibility_browsertest.cc
@@ -45,7 +45,7 @@ class CrossPlatformAccessibilityBrowserTest : public ContentBrowserTest {
// Tell the renderer to send an accessibility tree, then wait for the
// notification that it's been received.
const ui::AXTree& GetAXTree(
- AccessibilityMode accessibility_mode = kAccessibilityModeComplete) {
+ ui::AXMode accessibility_mode = ui::kAXModeComplete) {
AccessibilityNotificationWaiter waiter(
shell()->web_contents(),
accessibility_mode,
@@ -364,11 +364,7 @@ IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest,
GetAttr(iframe, ui::AX_ATTR_HTML_TAG).c_str());
ASSERT_EQ(1, iframe->child_count());
- const ui::AXNode* scroll_area = iframe->ChildAtIndex(0);
- EXPECT_EQ(ui::AX_ROLE_SCROLL_AREA, scroll_area->data().role);
- ASSERT_EQ(1, scroll_area->child_count());
-
- const ui::AXNode* sub_document = scroll_area->ChildAtIndex(0);
+ const ui::AXNode* sub_document = iframe->ChildAtIndex(0);
EXPECT_EQ(ui::AX_ROLE_WEB_AREA, sub_document->data().role);
ASSERT_EQ(1, sub_document->child_count());
diff --git a/chromium/content/browser/accessibility/dump_accessibility_browsertest_base.cc b/chromium/content/browser/accessibility/dump_accessibility_browsertest_base.cc
index 90025bcd076..b282d948032 100644
--- a/chromium/content/browser/accessibility/dump_accessibility_browsertest_base.cc
+++ b/chromium/content/browser/accessibility/dump_accessibility_browsertest_base.cc
@@ -23,7 +23,7 @@
#include "content/browser/accessibility/browser_accessibility.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
#include "content/browser/accessibility/browser_accessibility_state_impl.h"
-#include "content/browser/frame_host/render_widget_host_view_child_frame.h"
+#include "content/browser/renderer_host/render_widget_host_view_child_frame.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_paths.h"
@@ -263,13 +263,13 @@ void DumpAccessibilityTestBase::RunTestForPlatform(
// Load the url, then enable accessibility.
NavigateToURL(shell(), url);
AccessibilityNotificationWaiter accessibility_waiter(
- web_contents, kAccessibilityModeComplete, ui::AX_EVENT_NONE);
+ web_contents, ui::kAXModeComplete, ui::AX_EVENT_NONE);
accessibility_waiter.WaitForNotification();
} else {
// Enable accessibility, then load the test html and wait for the
// "load complete" AX event.
AccessibilityNotificationWaiter accessibility_waiter(
- web_contents, kAccessibilityModeComplete, ui::AX_EVENT_LOAD_COMPLETE);
+ web_contents, ui::kAXModeComplete, ui::AX_EVENT_LOAD_COMPLETE);
NavigateToURL(shell(), url);
accessibility_waiter.WaitForNotification();
}
diff --git a/chromium/content/browser/accessibility/dump_accessibility_events_browsertest.cc b/chromium/content/browser/accessibility/dump_accessibility_events_browsertest.cc
index b9d545a24e8..4f90267e539 100644
--- a/chromium/content/browser/accessibility/dump_accessibility_events_browsertest.cc
+++ b/chromium/content/browser/accessibility/dump_accessibility_events_browsertest.cc
@@ -91,7 +91,7 @@ std::vector<std::string> DumpAccessibilityEventsTest::Dump() {
// a result of this function.
std::unique_ptr<AccessibilityNotificationWaiter> waiter;
waiter.reset(new AccessibilityNotificationWaiter(
- shell()->web_contents(), kAccessibilityModeComplete, ui::AX_EVENT_NONE));
+ shell()->web_contents(), ui::kAXModeComplete, ui::AX_EVENT_NONE));
web_contents->GetMainFrame()->ExecuteJavaScriptForTests(
base::ASCIIToUTF16("go()"));
@@ -105,7 +105,7 @@ std::vector<std::string> DumpAccessibilityEventsTest::Dump() {
// sentinel by calling AccessibilityHitTest and waiting for a HOVER
// event in response.
waiter.reset(new AccessibilityNotificationWaiter(
- shell()->web_contents(), kAccessibilityModeComplete, ui::AX_EVENT_HOVER));
+ shell()->web_contents(), ui::kAXModeComplete, ui::AX_EVENT_HOVER));
BrowserAccessibilityManager* manager =
web_contents->GetRootBrowserAccessibilityManager();
manager->HitTest(gfx::Point(0, 0));
diff --git a/chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc b/chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
index 71650703256..da886abe0d8 100644
--- a/chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
+++ b/chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
@@ -192,7 +192,6 @@ void DumpAccessibilityTreeTest::AddDefaultFilters(
// States
AddFilter(filters, "check*");
AddFilter(filters, "descript*");
- AddFilter(filters, "busy");
AddFilter(filters, "collapsed");
AddFilter(filters, "default");
AddFilter(filters, "haspopup");
@@ -205,6 +204,7 @@ void DumpAccessibilityTreeTest::AddDefaultFilters(
AddFilter(filters, "select*");
AddFilter(filters, "visited");
// Other attributes
+ AddFilter(filters, "busy=true");
AddFilter(filters, "valueForRange*");
AddFilter(filters, "minValueForRange*");
AddFilter(filters, "maxValueForRange*");
@@ -228,6 +228,12 @@ void DumpAccessibilityTreeTest::AddDefaultFilters(
AddFilter(filters, "roleDescription=*");
//
+ // Android
+ //
+
+ AddFilter(filters, "hint=*");
+
+ //
// General
//
@@ -301,10 +307,16 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAOnclick) {
#if defined(THREAD_SANITIZER)
// See (crbug.com/708759).
+#define MAYBE_AccessibilityAomBusy DISABLED_AccessibilityAomBusy
#define MAYBE_AccessibilityAomChecked DISABLED_AccessibilityAomChecked
#else
+#define MAYBE_AccessibilityAomBusy AccessibilityAomBusy
#define MAYBE_AccessibilityAomChecked AccessibilityAomChecked
#endif
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, MAYBE_AccessibilityAomBusy) {
+ RunAomTest(FILE_PATH_LITERAL("aom-busy.html"));
+}
+
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
MAYBE_AccessibilityAomChecked) {
RunAomTest(FILE_PATH_LITERAL("aom-checked.html"));
@@ -484,6 +496,10 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaGrid) {
RunAriaTest(FILE_PATH_LITERAL("aria-grid.html"));
}
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
+ AccessibilityAriaGridExtraWrapElems) {
+ RunAriaTest(FILE_PATH_LITERAL("aria-grid-extra-wrap-elems.html"));
+}
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaGridCell) {
RunAriaTest(FILE_PATH_LITERAL("aria-gridcell.html"));
}
@@ -492,6 +508,10 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaGroup) {
RunAriaTest(FILE_PATH_LITERAL("aria-group.html"));
}
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaIllegalVal) {
+ RunAriaTest(FILE_PATH_LITERAL("aria-illegal-val.html"));
+}
+
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaImg) {
RunAriaTest(FILE_PATH_LITERAL("aria-img.html"));
}
@@ -821,6 +841,20 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaTreeGrid) {
RunAriaTest(FILE_PATH_LITERAL("aria-treegrid.html"));
}
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaUndefined) {
+ RunAriaTest(FILE_PATH_LITERAL("aria-undefined.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
+ AccessibilityAriaUndefinedLiteral) {
+ RunAriaTest(FILE_PATH_LITERAL("aria-undefined-literal.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
+ AccessibilityAriaEmptyString) {
+ RunAriaTest(FILE_PATH_LITERAL("aria-empty-string.html"));
+}
+
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
DISABLED_AccessibilityAriaValueMin) {
RunAriaTest(FILE_PATH_LITERAL("aria-valuemin.html"));
diff --git a/chromium/content/browser/accessibility/hit_testing_browsertest.cc b/chromium/content/browser/accessibility/hit_testing_browsertest.cc
index ad3cc5134da..11e32bf32f0 100644
--- a/chromium/content/browser/accessibility/hit_testing_browsertest.cc
+++ b/chromium/content/browser/accessibility/hit_testing_browsertest.cc
@@ -33,7 +33,7 @@ class AccessibilityHitTestingBrowserTest : public ContentBrowserTest {
web_contents->GetRootBrowserAccessibilityManager();
AccessibilityNotificationWaiter event_waiter(
- shell()->web_contents(), kAccessibilityModeComplete, event_to_fire);
+ shell()->web_contents(), ui::kAXModeComplete, event_to_fire);
for (FrameTreeNode* node : frame_tree->Nodes())
event_waiter.ListenToAdditionalFrame(node->current_frame_host());
ui::AXActionData action_data;
@@ -66,9 +66,8 @@ class AccessibilityHitTestingBrowserTest : public ContentBrowserTest {
// Each call to CachingAsyncHitTest results in at least one HOVER
// event received. Block until we receive it.
- AccessibilityNotificationWaiter hover_waiter(shell()->web_contents(),
- kAccessibilityModeComplete,
- ui::AX_EVENT_HOVER);
+ AccessibilityNotificationWaiter hover_waiter(
+ shell()->web_contents(), ui::kAXModeComplete, ui::AX_EVENT_HOVER);
for (FrameTreeNode* node : frame_tree->Nodes())
hover_waiter.ListenToAdditionalFrame(node->current_frame_host());
BrowserAccessibility* result = manager->CachingAsyncHitTest(screen_point);
@@ -82,9 +81,8 @@ IN_PROC_BROWSER_TEST_F(AccessibilityHitTestingBrowserTest,
NavigateToURL(shell(), GURL(url::kAboutBlankURL));
// Load the page.
- AccessibilityNotificationWaiter waiter(shell()->web_contents(),
- kAccessibilityModeComplete,
- ui::AX_EVENT_LOAD_COMPLETE);
+ AccessibilityNotificationWaiter waiter(
+ shell()->web_contents(), ui::kAXModeComplete, ui::AX_EVENT_LOAD_COMPLETE);
const char url_str[] =
"data:text/html,"
"<!doctype html>"
@@ -109,9 +107,8 @@ IN_PROC_BROWSER_TEST_F(AccessibilityHitTestingBrowserTest,
NavigateToURL(shell(), GURL(url::kAboutBlankURL));
- AccessibilityNotificationWaiter waiter(shell()->web_contents(),
- kAccessibilityModeComplete,
- ui::AX_EVENT_LOAD_COMPLETE);
+ AccessibilityNotificationWaiter waiter(
+ shell()->web_contents(), ui::kAXModeComplete, ui::AX_EVENT_LOAD_COMPLETE);
GURL url(embedded_test_server()->GetURL(
"/accessibility/html/iframe-coordinates.html"));
NavigateToURL(shell(), url);
@@ -169,9 +166,8 @@ IN_PROC_BROWSER_TEST_F(AccessibilityHitTestingBrowserTest,
NavigateToURL(shell(), GURL(url::kAboutBlankURL));
- AccessibilityNotificationWaiter waiter(shell()->web_contents(),
- kAccessibilityModeComplete,
- ui::AX_EVENT_LOAD_COMPLETE);
+ AccessibilityNotificationWaiter waiter(
+ shell()->web_contents(), ui::kAXModeComplete, ui::AX_EVENT_LOAD_COMPLETE);
GURL url(embedded_test_server()->GetURL(
"/accessibility/hit_testing/hit_testing.html"));
NavigateToURL(shell(), url);
diff --git a/chromium/content/browser/accessibility/one_shot_accessibility_tree_search.cc b/chromium/content/browser/accessibility/one_shot_accessibility_tree_search.cc
index ff9c44d50b8..16694f6cfb6 100644
--- a/chromium/content/browser/accessibility/one_shot_accessibility_tree_search.cc
+++ b/chromium/content/browser/accessibility/one_shot_accessibility_tree_search.cc
@@ -258,7 +258,6 @@ bool AccessibilityControlPredicate(
if (node->HasState(ui::AX_STATE_FOCUSABLE) &&
node->GetRole() != ui::AX_ROLE_IFRAME &&
node->GetRole() != ui::AX_ROLE_IFRAME_PRESENTATIONAL &&
- node->GetRole() != ui::AX_ROLE_IMAGE_MAP_LINK &&
node->GetRole() != ui::AX_ROLE_LINK &&
node->GetRole() != ui::AX_ROLE_WEB_AREA &&
node->GetRole() != ui::AX_ROLE_ROOT_WEB_AREA) {
@@ -363,8 +362,7 @@ bool AccessibilityLandmarkPredicate(
bool AccessibilityLinkPredicate(
BrowserAccessibility* start, BrowserAccessibility* node) {
- return (node->GetRole() == ui::AX_ROLE_LINK ||
- node->GetRole() == ui::AX_ROLE_IMAGE_MAP_LINK);
+ return node->GetRole() == ui::AX_ROLE_LINK;
}
bool AccessibilityListPredicate(
@@ -443,16 +441,14 @@ bool AccessibilityTreePredicate(
bool AccessibilityUnvisitedLinkPredicate(
BrowserAccessibility* start, BrowserAccessibility* node) {
- return ((node->GetRole() == ui::AX_ROLE_LINK ||
- node->GetRole() == ui::AX_ROLE_IMAGE_MAP_LINK) &&
- !node->HasState(ui::AX_STATE_VISITED));
+ return node->GetRole() == ui::AX_ROLE_LINK &&
+ !node->HasState(ui::AX_STATE_VISITED);
}
bool AccessibilityVisitedLinkPredicate(
BrowserAccessibility* start, BrowserAccessibility* node) {
- return ((node->GetRole() == ui::AX_ROLE_LINK ||
- node->GetRole() == ui::AX_ROLE_IMAGE_MAP_LINK) &&
- node->HasState(ui::AX_STATE_VISITED));
+ return node->GetRole() == ui::AX_ROLE_LINK &&
+ node->HasState(ui::AX_STATE_VISITED);
}
} // namespace content
diff --git a/chromium/content/browser/accessibility/one_shot_accessibility_tree_search_unittest.cc b/chromium/content/browser/accessibility/one_shot_accessibility_tree_search_unittest.cc
index 92fd8cdd032..6fc5415ebbe 100644
--- a/chromium/content/browser/accessibility/one_shot_accessibility_tree_search_unittest.cc
+++ b/chromium/content/browser/accessibility/one_shot_accessibility_tree_search_unittest.cc
@@ -7,6 +7,7 @@
#include <memory>
#include "base/macros.h"
+#include "base/test/scoped_task_environment.h"
#include "content/browser/accessibility/browser_accessibility.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -40,6 +41,8 @@ class MAYBE_OneShotAccessibilityTreeSearchTest : public testing::Test {
protected:
void SetUp() override;
+ base::test::ScopedTaskEnvironment scoped_task_environment_;
+
std::unique_ptr<BrowserAccessibilityManager> tree_;
private:
diff --git a/chromium/content/browser/accessibility/site_per_process_accessibility_browsertest.cc b/chromium/content/browser/accessibility/site_per_process_accessibility_browsertest.cc
index 0249862607c..554d64a1646 100644
--- a/chromium/content/browser/accessibility/site_per_process_accessibility_browsertest.cc
+++ b/chromium/content/browser/accessibility/site_per_process_accessibility_browsertest.cc
@@ -12,8 +12,8 @@
#include "content/browser/frame_host/cross_process_frame_connector.h"
#include "content/browser/frame_host/frame_tree.h"
#include "content/browser/frame_host/render_frame_proxy_host.h"
-#include "content/browser/frame_host/render_widget_host_view_child_frame.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
+#include "content/browser/renderer_host/render_widget_host_view_child_frame.h"
#include "content/browser/site_per_process_browsertest.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/notification_observer.h"
diff --git a/chromium/content/browser/accessibility/touch_accessibility_aura_browsertest.cc b/chromium/content/browser/accessibility/touch_accessibility_aura_browsertest.cc
index 7eb67c3ba04..db03887f46b 100644
--- a/chromium/content/browser/accessibility/touch_accessibility_aura_browsertest.cc
+++ b/chromium/content/browser/accessibility/touch_accessibility_aura_browsertest.cc
@@ -5,7 +5,7 @@
#include "base/macros.h"
#include "base/strings/string_number_conversions.h"
#include "content/browser/accessibility/browser_accessibility.h"
-#include "content/browser/frame_host/render_widget_host_view_child_frame.h"
+#include "content/browser/renderer_host/render_widget_host_view_child_frame.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
@@ -37,7 +37,7 @@ class TouchAccessibilityBrowserTest : public ContentBrowserTest {
void NavigateToUrlAndWaitForAccessibilityTree(const GURL& url) {
AccessibilityNotificationWaiter waiter(shell()->web_contents(),
- kAccessibilityModeComplete,
+ ui::kAXModeComplete,
ui::AX_EVENT_LOAD_COMPLETE);
NavigateToURL(shell(), url);
waiter.WaitForNotification();
@@ -94,7 +94,7 @@ IN_PROC_BROWSER_TEST_F(TouchAccessibilityBrowserTest,
// touch exploration event in the center of that cell, and assert that we
// get an accessibility hover event fired in the correct cell.
AccessibilityNotificationWaiter waiter(
- shell()->web_contents(), kAccessibilityModeComplete, ui::AX_EVENT_HOVER);
+ shell()->web_contents(), ui::kAXModeComplete, ui::AX_EVENT_HOVER);
for (int row = 0; row < 5; ++row) {
for (int col = 0; col < 7; ++col) {
std::string expected_cell_text = base::IntToString(row * 7 + col);
diff --git a/chromium/content/browser/accessibility/web_contents_accessibility_android.cc b/chromium/content/browser/accessibility/web_contents_accessibility_android.cc
index 82b82293122..e1e559278bb 100644
--- a/chromium/content/browser/accessibility/web_contents_accessibility_android.cc
+++ b/chromium/content/browser/accessibility/web_contents_accessibility_android.cc
@@ -5,6 +5,7 @@
#include "content/browser/accessibility/web_contents_accessibility_android.h"
#include "base/android/jni_android.h"
+#include "base/android/jni_array.h"
#include "base/android/jni_string.h"
#include "base/feature_list.h"
#include "base/macros.h"
@@ -291,6 +292,13 @@ void DeleteAutofillPopupProxy() {
}
}
+// The most common use of the EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY
+// API is to retrieve character bounds for one word at a time. There
+// should never need to be a reason to return more than this many
+// character bounding boxes at once. Set the limit much higher than needed
+// but small enough to prevent wasting memory and cpu if abused.
+const int kMaxCharacterBoundingBoxLen = 1024;
+
} // anonymous namespace
class WebContentsAccessibilityAndroid::Connector
@@ -298,8 +306,9 @@ class WebContentsAccessibilityAndroid::Connector
public:
Connector(WebContents* web_contents,
WebContentsAccessibilityAndroid* accessibility);
+ ~Connector() override;
- // RendetWidgetHostConnector implementation.
+ // RenderWidgetHostConnector:
void UpdateRenderProcessConnection(
RenderWidgetHostViewAndroid* old_rwhva,
RenderWidgetHostViewAndroid* new_rhwva) override;
@@ -315,6 +324,10 @@ WebContentsAccessibilityAndroid::Connector::Connector(
Initialize();
}
+WebContentsAccessibilityAndroid::Connector::~Connector() {
+ accessibility_->UpdateEnabledState(false);
+}
+
void WebContentsAccessibilityAndroid::Connector::UpdateRenderProcessConnection(
RenderWidgetHostViewAndroid* old_rwhva,
RenderWidgetHostViewAndroid* new_rwhva) {
@@ -327,11 +340,9 @@ void WebContentsAccessibilityAndroid::Connector::UpdateRenderProcessConnection(
WebContentsAccessibilityAndroid::WebContentsAccessibilityAndroid(
JNIEnv* env,
const JavaParamRef<jobject>& obj,
- WebContents* web_contents,
- bool should_focus_on_page_load)
+ WebContents* web_contents)
: java_ref_(env, obj),
web_contents_(static_cast<WebContentsImpl*>(web_contents)),
- should_focus_on_page_load_(should_focus_on_page_load),
frame_info_initialized_(false),
root_manager_(nullptr),
connector_(new Connector(web_contents, this)) {
@@ -364,9 +375,10 @@ void WebContentsAccessibilityAndroid::Enable(JNIEnv* env,
void WebContentsAccessibilityAndroid::UpdateEnabledState(bool enabled) {
BrowserAccessibilityStateImpl* accessibility_state =
BrowserAccessibilityStateImpl::GetInstance();
+ auto* manager = static_cast<BrowserAccessibilityManagerAndroid*>(
+ web_contents_->GetRootBrowserAccessibilityManager());
+
if (enabled) {
- auto* manager = static_cast<BrowserAccessibilityManagerAndroid*>(
- web_contents_->GetRootBrowserAccessibilityManager());
// First check if we already have a BrowserAccessibilityManager that
// that needs to be connected to this instance. This can happen if
// BAM creation precedes render view updates for the associated
@@ -382,8 +394,13 @@ void WebContentsAccessibilityAndroid::UpdateEnabledState(bool enabled) {
// this WebContents if that succeeded.
accessibility_state->OnScreenReaderDetected();
if (accessibility_state->IsAccessibleBrowser())
- web_contents_->AddAccessibilityMode(kAccessibilityModeComplete);
+ web_contents_->AddAccessibilityMode(ui::kAXModeComplete);
} else {
+ // Remove accessibility from the BrowserAccessibilityManager or it may
+ // continue to reference this object which is no longer active (and may be
+ // about to be destroyed).
+ if (manager)
+ manager->set_web_contents_accessibility(nullptr);
// Note that disabling part is not useful at this moment since the mode will
// be enabled again almost immediately for the renderer process that just
// got swapped in. This boolean enable/disable logic will be expanded
@@ -412,8 +429,6 @@ bool WebContentsAccessibilityAndroid::ShouldExposePasswordText() {
}
void WebContentsAccessibilityAndroid::HandlePageLoaded(int32_t unique_id) {
- if (!should_focus_on_page_load_)
- return;
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
if (obj.is_null())
@@ -564,7 +579,8 @@ jint WebContentsAccessibilityAndroid::GetRootId(
JNIEnv* env,
const JavaParamRef<jobject>& obj) {
if (root_manager_) {
- auto* root = root_manager_->GetRoot();
+ auto* root =
+ static_cast<BrowserAccessibilityAndroid*>(root_manager_->GetRoot());
if (root)
return static_cast<jint>(root->unique_id());
}
@@ -640,12 +656,16 @@ jboolean WebContentsAccessibilityAndroid::PopulateAccessibilityNodeInfo(
return false;
if (node->PlatformGetParent()) {
+ auto* android_node =
+ static_cast<BrowserAccessibilityAndroid*>(node->PlatformGetParent());
Java_WebContentsAccessibility_setAccessibilityNodeInfoParent(
- env, obj, info, node->PlatformGetParent()->unique_id());
+ env, obj, info, android_node->unique_id());
}
for (unsigned i = 0; i < node->PlatformChildCount(); ++i) {
+ auto* android_node =
+ static_cast<BrowserAccessibilityAndroid*>(node->PlatformGetChild(i));
Java_WebContentsAccessibility_addAccessibilityNodeInfoChild(
- env, obj, info, node->PlatformGetChild(i)->unique_id());
+ env, obj, info, android_node->unique_id());
}
Java_WebContentsAccessibility_setAccessibilityNodeInfoBooleanAttributes(
env, obj, info, unique_id, node->IsCheckable(), node->IsChecked(),
@@ -690,6 +710,7 @@ jboolean WebContentsAccessibilityAndroid::PopulateAccessibilityNodeInfo(
Java_WebContentsAccessibility_setAccessibilityNodeInfoKitKatAttributes(
env, obj, info, is_root, node->IsEditableText(),
base::android::ConvertUTF16ToJavaString(env, node->GetRoleDescription()),
+ base::android::ConvertUTF16ToJavaString(env, node->GetHint()),
node->GetIntAttribute(ui::AX_ATTR_TEXT_SEL_START),
node->GetIntAttribute(ui::AX_ATTR_TEXT_SEL_END));
@@ -697,6 +718,12 @@ jboolean WebContentsAccessibilityAndroid::PopulateAccessibilityNodeInfo(
env, obj, info, node->CanOpenPopup(), node->IsContentInvalid(),
node->IsDismissable(), node->IsMultiLine(), node->AndroidInputType(),
node->AndroidLiveRegionType());
+
+ bool has_character_locations = node->GetRole() == ui::AX_ROLE_STATIC_TEXT ||
+ node->IsInterestingOnAndroid();
+ Java_WebContentsAccessibility_setAccessibilityNodeInfoOAttributes(
+ env, obj, info, has_character_locations);
+
if (node->IsCollection()) {
Java_WebContentsAccessibility_setAccessibilityNodeInfoCollectionInfo(
env, obj, info, node->RowCount(), node->ColumnCount(),
@@ -925,7 +952,9 @@ jint WebContentsAccessibilityAndroid::FindElementType(
if (tree_search.CountMatches() == 0)
return 0;
- int32_t element_id = tree_search.GetMatchAtIndex(0)->unique_id();
+ auto* android_node =
+ static_cast<BrowserAccessibilityAndroid*>(tree_search.GetMatchAtIndex(0));
+ int32_t element_id = android_node->unique_id();
// Navigate forwards to the autofill popup's proxy node if focus is currently
// on the element hosting the autofill popup. Once within the popup, a back
@@ -936,7 +965,9 @@ jint WebContentsAccessibilityAndroid::FindElementType(
if (forwards && start_id == g_element_hosting_autofill_popup_unique_id &&
g_autofill_popup_proxy_node) {
g_element_after_element_hosting_autofill_popup_unique_id = element_id;
- return g_autofill_popup_proxy_node->unique_id();
+ auto* android_node =
+ static_cast<BrowserAccessibilityAndroid*>(g_autofill_popup_proxy_node);
+ return android_node->unique_id();
}
return element_id;
@@ -997,9 +1028,12 @@ void WebContentsAccessibilityAndroid::SetAccessibilityFocus(
JNIEnv* env,
const JavaParamRef<jobject>& obj,
jint unique_id) {
+ // When Android sets accessibility focus to a node, we load inline text
+ // boxes for that node so that subsequent requests for character bounding
+ // boxes will succeed.
BrowserAccessibilityAndroid* node = GetAXFromUniqueID(unique_id);
if (node)
- node->manager()->SetAccessibilityFocus(*node);
+ node->manager()->LoadInlineTextBoxes(*node);
}
bool WebContentsAccessibilityAndroid::IsSlider(JNIEnv* env,
@@ -1039,7 +1073,9 @@ void WebContentsAccessibilityAndroid::OnAutofillPopupDisplayed(
g_autofill_popup_proxy_node->Init(root_manager_,
g_autofill_popup_proxy_node_ax_node);
- g_element_hosting_autofill_popup_unique_id = current_focus->unique_id();
+ auto* android_node = static_cast<BrowserAccessibilityAndroid*>(current_focus);
+
+ g_element_hosting_autofill_popup_unique_id = android_node->unique_id();
}
void WebContentsAccessibilityAndroid::OnAutofillPopupDismissed(
@@ -1067,8 +1103,10 @@ jboolean WebContentsAccessibilityAndroid::IsAutofillPopupNode(
JNIEnv* env,
const JavaParamRef<jobject>& obj,
jint unique_id) {
- return g_autofill_popup_proxy_node &&
- g_autofill_popup_proxy_node->unique_id() == unique_id;
+ auto* android_node =
+ static_cast<BrowserAccessibilityAndroid*>(g_autofill_popup_proxy_node);
+
+ return g_autofill_popup_proxy_node && android_node->unique_id() == unique_id;
}
bool WebContentsAccessibilityAndroid::Scroll(JNIEnv* env,
@@ -1082,10 +1120,63 @@ bool WebContentsAccessibilityAndroid::Scroll(JNIEnv* env,
return node->Scroll(direction);
}
+jboolean WebContentsAccessibilityAndroid::AreInlineTextBoxesLoaded(
+ JNIEnv* env,
+ const JavaParamRef<jobject>& obj,
+ jint unique_id) {
+ BrowserAccessibilityAndroid* node = GetAXFromUniqueID(unique_id);
+ if (!node)
+ return false;
+
+ return node->AreInlineTextBoxesLoaded();
+}
+
+void WebContentsAccessibilityAndroid::LoadInlineTextBoxes(
+ JNIEnv* env,
+ const JavaParamRef<jobject>& obj,
+ jint unique_id) {
+ BrowserAccessibilityAndroid* node = GetAXFromUniqueID(unique_id);
+ if (node)
+ node->manager()->LoadInlineTextBoxes(*node);
+}
+
+base::android::ScopedJavaLocalRef<jintArray>
+WebContentsAccessibilityAndroid::GetCharacterBoundingBoxes(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj,
+ jint unique_id,
+ jint start,
+ jint len) {
+ BrowserAccessibilityAndroid* node = GetAXFromUniqueID(unique_id);
+ if (!node)
+ return nullptr;
+
+ if (len <= 0 || len > kMaxCharacterBoundingBoxLen) {
+ LOG(ERROR) << "Trying to request EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY "
+ << "with a length of " << len << ". Valid values are between 1 "
+ << "and " << kMaxCharacterBoundingBoxLen;
+ return nullptr;
+ }
+
+ gfx::Rect object_bounds = node->GetPageBoundsRect();
+ int coords[4 * len];
+ for (int i = 0; i < len; i++) {
+ gfx::Rect char_bounds = node->GetPageBoundsForRange(start + i, 1);
+ if (char_bounds.IsEmpty())
+ char_bounds = object_bounds;
+ coords[4 * i + 0] = char_bounds.x();
+ coords[4 * i + 1] = char_bounds.y();
+ coords[4 * i + 2] = char_bounds.right();
+ coords[4 * i + 3] = char_bounds.bottom();
+ }
+ return base::android::ToJavaIntArray(env, coords,
+ static_cast<size_t>(4 * len));
+}
+
BrowserAccessibilityAndroid* WebContentsAccessibilityAndroid::GetAXFromUniqueID(
int32_t unique_id) {
return static_cast<BrowserAccessibilityAndroid*>(
- BrowserAccessibility::GetFromUniqueID(unique_id));
+ BrowserAccessibilityAndroid::GetFromUniqueId(unique_id));
}
void WebContentsAccessibilityAndroid::UpdateFrameInfo() {
@@ -1169,19 +1260,14 @@ void WebContentsAccessibilityAndroid::CollectStats() {
CAPABILITY_TYPE_HISTOGRAM(capabilities_mask, CAN_PERFORM_GESTURES);
}
-bool RegisterWebContentsAccessibilityAndroid(JNIEnv* env) {
- return RegisterNativesImpl(env);
-}
-
jlong Init(JNIEnv* env,
const JavaParamRef<jobject>& obj,
- const JavaParamRef<jobject>& jweb_contents,
- jboolean should_focus_on_page_load) {
+ const JavaParamRef<jobject>& jweb_contents) {
WebContents* web_contents = WebContents::FromJavaWebContents(jweb_contents);
DCHECK(web_contents);
- return reinterpret_cast<intptr_t>(new WebContentsAccessibilityAndroid(
- env, obj, web_contents, should_focus_on_page_load));
+ return reinterpret_cast<intptr_t>(
+ new WebContentsAccessibilityAndroid(env, obj, web_contents));
}
} // namespace content
diff --git a/chromium/content/browser/accessibility/web_contents_accessibility_android.h b/chromium/content/browser/accessibility/web_contents_accessibility_android.h
index 77fc9db9d03..1770297b18d 100644
--- a/chromium/content/browser/accessibility/web_contents_accessibility_android.h
+++ b/chromium/content/browser/accessibility/web_contents_accessibility_android.h
@@ -35,8 +35,7 @@ class CONTENT_EXPORT WebContentsAccessibilityAndroid
WebContentsAccessibilityAndroid(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
- WebContents* web_contents,
- bool should_focus_on_page_load);
+ WebContents* web_contents);
~WebContentsAccessibilityAndroid() override;
// --------------------------------------------------------------------------
@@ -185,16 +184,36 @@ class CONTENT_EXPORT WebContentsAccessibilityAndroid
jint id,
int direction);
+ // Returns true if the given subtree has inline text box data, or if there
+ // aren't any to load.
+ jboolean AreInlineTextBoxesLoaded(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj,
+ jint id);
+
+ // Request loading inline text boxes for a given node.
+ void LoadInlineTextBoxes(JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj,
+ jint id);
+
+ // Get the bounds of each character for a given static text node,
+ // starting from index |start| with length |len|. The resulting array
+ // of ints is 4 times the length |len|, with the bounds being returned
+ // as (left, top, right, bottom) in that order corresponding to a
+ // android.graphics.RectF.
+ base::android::ScopedJavaLocalRef<jintArray> GetCharacterBoundingBoxes(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj,
+ jint id,
+ jint start,
+ jint len);
+
void UpdateFrameInfo();
void set_root_manager(BrowserAccessibilityManagerAndroid* manager) {
root_manager_ = manager;
}
- void set_should_focus_on_page_load(bool focus) {
- should_focus_on_page_load_ = focus;
- }
-
// --------------------------------------------------------------------------
// Methods called from the BrowserAccessibilityManager
// --------------------------------------------------------------------------
@@ -229,8 +248,6 @@ class CONTENT_EXPORT WebContentsAccessibilityAndroid
WebContentsImpl* const web_contents_;
- bool should_focus_on_page_load_;
-
bool frame_info_initialized_;
BrowserAccessibilityManagerAndroid* root_manager_;
@@ -244,7 +261,6 @@ class CONTENT_EXPORT WebContentsAccessibilityAndroid
DISALLOW_COPY_AND_ASSIGN(WebContentsAccessibilityAndroid);
};
-bool RegisterWebContentsAccessibilityAndroid(JNIEnv* env);
}
#endif // CONTENT_BROWSER_ACCESSIBILITY_WEB_CONTENTS_ACCESSIBILITY_ANDROID_H_
diff --git a/chromium/content/browser/after_startup_task_utils.cc b/chromium/content/browser/after_startup_task_utils.cc
new file mode 100644
index 00000000000..c9d74f38d4a
--- /dev/null
+++ b/chromium/content/browser/after_startup_task_utils.cc
@@ -0,0 +1,25 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/after_startup_task_utils.h"
+
+#include "content/public/browser/content_browser_client.h"
+#include "content/public/common/content_client.h"
+
+namespace content {
+
+void SetBrowserStartupIsCompleteForTesting() {
+ // Forward the message to ContentBrowserClient if one is registered (there are
+ // many tests where one isn't but that's fine as that also means they get the
+ // default ContentBrowserClient::IsBrowserStartupComplete() which is always
+ // true).
+ ContentClient* content_client = GetContentClient();
+ if (content_client) {
+ ContentBrowserClient* content_browser_client = content_client->browser();
+ if (content_browser_client)
+ content_browser_client->SetBrowserStartupIsCompleteForTesting();
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/browser/after_startup_task_utils.h b/chromium/content/browser/after_startup_task_utils.h
new file mode 100644
index 00000000000..7debbad170c
--- /dev/null
+++ b/chromium/content/browser/after_startup_task_utils.h
@@ -0,0 +1,21 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_AFTER_STARTUP_TASK_UTILS_H_
+#define CONTENT_BROWSER_AFTER_STARTUP_TASK_UTILS_H_
+
+#include "content/common/content_export.h"
+
+namespace content {
+
+// An indirection to
+// ContentBrowserClient::SetBrowserStartupIsCompleteForTesting() as that can
+// only be called from the content implementation and including content/test in
+// the content implementation is a whole other can of worms. TODO(gab): Clean
+// this up when AfterStartupTasks go away in favor of TaskScheduler.
+void CONTENT_EXPORT SetBrowserStartupIsCompleteForTesting();
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_AFTER_STARTUP_TASK_UTILS_H_
diff --git a/chromium/content/browser/android/app_web_message_port.cc b/chromium/content/browser/android/app_web_message_port.cc
index 2e7622cf541..692570583a3 100644
--- a/chromium/content/browser/android/app_web_message_port.cc
+++ b/chromium/content/browser/android/app_web_message_port.cc
@@ -61,9 +61,10 @@ void AppWebMessagePort::PostMessage(
const base::android::JavaParamRef<jobject>& jcaller,
const base::android::JavaParamRef<jstring>& jmessage,
const base::android::JavaParamRef<jobjectArray>& jports) {
- port_.PostMessage(
- EncodeStringMessage(base::android::ConvertJavaStringToUTF16(jmessage)),
- UnwrapJavaArray(env, jports));
+ std::vector<uint8_t> encoded_message =
+ EncodeStringMessage(base::android::ConvertJavaStringToUTF16(jmessage));
+ port_.PostMessage(encoded_message.data(), encoded_message.size(),
+ UnwrapJavaArray(env, jports));
}
jboolean AppWebMessagePort::DispatchNextMessage(
@@ -75,9 +76,10 @@ jboolean AppWebMessagePort::DispatchNextMessage(
jmethodID app_web_message_port_constructor =
base::android::MethodID::Get<base::android::MethodID::TYPE_INSTANCE>(
- env, AppWebMessagePort_clazz(env), "<init>", "()V");
+ env, org_chromium_content_browser_AppWebMessagePort_clazz(env),
+ "<init>", "()V");
- base::string16 encoded_message;
+ std::vector<uint8_t> encoded_message;
std::vector<MessagePort> ports;
if (!port_.GetMessage(&encoded_message, &ports))
return false;
@@ -92,17 +94,17 @@ jboolean AppWebMessagePort::DispatchNextMessage(
base::android::ScopedJavaLocalRef<jobjectArray> jports;
if (ports.size() > 0) {
jports = base::android::ScopedJavaLocalRef<jobjectArray>(
- env,
- env->NewObjectArray(ports.size(),
- AppWebMessagePort_clazz(env),
- nullptr));
+ env, env->NewObjectArray(
+ ports.size(),
+ org_chromium_content_browser_AppWebMessagePort_clazz(env),
+ nullptr));
// Instantiate the Java and C++ wrappers for the transferred ports.
for (size_t i = 0; i < ports.size(); ++i) {
base::android::ScopedJavaLocalRef<jobject> jport(
- env,
- env->NewObject(AppWebMessagePort_clazz(env),
- app_web_message_port_constructor));
+ env, env->NewObject(
+ org_chromium_content_browser_AppWebMessagePort_clazz(env),
+ app_web_message_port_constructor));
CreateAndBindToJavaObject(env, ports[i].ReleaseHandle(), jport);
env->SetObjectArrayElement(jports.obj(), i, jport.obj());
@@ -141,10 +143,6 @@ void AppWebMessagePort::OnMessagesAvailable() {
Java_AppWebMessagePort_onMessagesAvailable(env, obj);
}
-bool RegisterAppWebMessagePort(JNIEnv* env) {
- return RegisterNativesImpl(env);
-}
-
void InitializeAppWebMessagePortPair(
JNIEnv* env,
const base::android::JavaParamRef<jclass>& jcaller,
diff --git a/chromium/content/browser/android/app_web_message_port.h b/chromium/content/browser/android/app_web_message_port.h
index 147c9f6fefc..c7847366bd8 100644
--- a/chromium/content/browser/android/app_web_message_port.h
+++ b/chromium/content/browser/android/app_web_message_port.h
@@ -52,8 +52,6 @@ class AppWebMessagePort {
DISALLOW_COPY_AND_ASSIGN(AppWebMessagePort);
};
-bool RegisterAppWebMessagePort(JNIEnv* env);
-
} // namespace content
#endif // CONTENT_BROWSER_ANDROID_APP_WEB_MESSAGE_PORT_H_
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 04484f2864f..c1c514c7f4b 100644
--- a/chromium/content/browser/android/background_sync_network_observer_android.cc
+++ b/chromium/content/browser/android/background_sync_network_observer_android.cc
@@ -11,12 +11,6 @@ using base::android::JavaParamRef;
namespace content {
// static
-bool BackgroundSyncNetworkObserverAndroid::Observer::RegisterNetworkObserver(
- JNIEnv* env) {
- return RegisterNativesImpl(env);
-}
-
-// static
scoped_refptr<BackgroundSyncNetworkObserverAndroid::Observer>
BackgroundSyncNetworkObserverAndroid::Observer::Create(
base::Callback<void(net::NetworkChangeNotifier::ConnectionType)> callback) {
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 1c1a46e51ea..ace3b9b4f17 100644
--- a/chromium/content/browser/android/background_sync_network_observer_android.h
+++ b/chromium/content/browser/android/background_sync_network_observer_android.h
@@ -41,8 +41,6 @@ class BackgroundSyncNetworkObserverAndroid
base::Callback<void(net::NetworkChangeNotifier::ConnectionType)>
callback);
- static bool RegisterNetworkObserver(JNIEnv* env);
-
// Called from BackgroundSyncNetworkObserver.java over JNI whenever the
// connection type changes. This updates the current connection type seen by
// this class and calls the |network_changed_callback| provided to the
diff --git a/chromium/content/browser/android/browser_startup_controller.cc b/chromium/content/browser/android/browser_startup_controller.cc
index 87f0462a0fd..37df3a3fe54 100644
--- a/chromium/content/browser/android/browser_startup_controller.cc
+++ b/chromium/content/browser/android/browser_startup_controller.cc
@@ -27,10 +27,6 @@ bool ShouldStartGpuProcessOnBrowserStartup() {
env);
}
-bool RegisterBrowserStartupController(JNIEnv* env) {
- return RegisterNativesImpl(env);
-}
-
static void SetCommandLineFlags(
JNIEnv* env,
const JavaParamRef<jclass>& clazz,
diff --git a/chromium/content/browser/android/browser_startup_controller.h b/chromium/content/browser/android/browser_startup_controller.h
index d4f2556f54a..162f1e82501 100644
--- a/chromium/content/browser/android/browser_startup_controller.h
+++ b/chromium/content/browser/android/browser_startup_controller.h
@@ -5,14 +5,10 @@
#ifndef CONTENT_BROWSER_ANDROID_BROWSER_STARTUP_CONTROLLER_H_
#define CONTENT_BROWSER_ANDROID_BROWSER_STARTUP_CONTROLLER_H_
-#include <jni.h>
-
namespace content {
void BrowserStartupComplete(int result);
bool ShouldStartGpuProcessOnBrowserStartup();
-bool RegisterBrowserStartupController(JNIEnv* env);
-
} // namespace content
#endif // CONTENT_BROWSER_ANDROID_BROWSER_STARTUP_CONTROLLER_H_
diff --git a/chromium/content/browser/android/content_feature_list.cc b/chromium/content/browser/android/content_feature_list.cc
index ee10efb2509..eb1965722d4 100644
--- a/chromium/content/browser/android/content_feature_list.cc
+++ b/chromium/content/browser/android/content_feature_list.cc
@@ -49,9 +49,5 @@ static jboolean IsEnabled(JNIEnv* env,
return base::FeatureList::IsEnabled(*feature);
}
-bool RegisterContentFeatureListJni(JNIEnv* env) {
- return RegisterNativesImpl(env);
-}
-
} // namespace android
} // namespace content
diff --git a/chromium/content/browser/android/content_feature_list.h b/chromium/content/browser/android/content_feature_list.h
index 20ec97a6fe2..8c8b856ef57 100644
--- a/chromium/content/browser/android/content_feature_list.h
+++ b/chromium/content/browser/android/content_feature_list.h
@@ -5,8 +5,6 @@
#ifndef CONTENT_BROWSER_ANDROID_CONTENT_FEATURE_LIST_H_
#define CONTENT_BROWSER_ANDROID_CONTENT_FEATURE_LIST_H_
-#include <jni.h>
-
#include "base/feature_list.h"
namespace content {
@@ -15,8 +13,6 @@ namespace android {
// Alphabetical:
extern const base::Feature kRequestUnbufferedDispatch;
-bool RegisterContentFeatureListJni(JNIEnv* env);
-
} // namespace android
} // namespace content
diff --git a/chromium/content/browser/android/content_video_view.cc b/chromium/content/browser/android/content_video_view.cc
index 056060e076b..13940c8b5a6 100644
--- a/chromium/content/browser/android/content_video_view.cc
+++ b/chromium/content/browser/android/content_video_view.cc
@@ -31,10 +31,6 @@ static ScopedJavaLocalRef<jobject> GetSingletonJavaContentVideoView(
return ScopedJavaLocalRef<jobject>();
}
-bool ContentVideoView::RegisterContentVideoView(JNIEnv* env) {
- return RegisterNativesImpl(env);
-}
-
ContentVideoView* ContentVideoView::GetInstance() {
return g_content_video_view;
}
diff --git a/chromium/content/browser/android/content_video_view.h b/chromium/content/browser/android/content_video_view.h
index 3d9ca1dd6e1..6d10e88cd3b 100644
--- a/chromium/content/browser/android/content_video_view.h
+++ b/chromium/content/browser/android/content_video_view.h
@@ -21,8 +21,6 @@ namespace content {
// This class must be used on the UI thread.
class ContentVideoView {
public:
- static bool RegisterContentVideoView(JNIEnv* env);
-
// Returns the singleton object or NULL.
static ContentVideoView* GetInstance();
diff --git a/chromium/content/browser/android/content_view_core.cc b/chromium/content/browser/android/content_view_core.cc
index 04f45cb5bf8..4ec9060ea6d 100644
--- a/chromium/content/browser/android/content_view_core.cc
+++ b/chromium/content/browser/android/content_view_core.cc
@@ -20,11 +20,10 @@
#include "base/values.h"
#include "cc/layers/layer.h"
#include "cc/layers/solid_color_layer.h"
-#include "cc/output/begin_frame_args.h"
+#include "components/viz/common/frame_sinks/begin_frame_args.h"
#include "content/browser/android/gesture_event_type.h"
#include "content/browser/android/interstitial_page_delegate_android.h"
#include "content/browser/android/java/gin_java_bridge_dispatcher_host.h"
-#include "content/browser/android/load_url_params.h"
#include "content/browser/frame_host/interstitial_page_impl.h"
#include "content/browser/media/media_web_contents_observer.h"
#include "content/browser/renderer_host/compositor_impl_android.h"
@@ -102,12 +101,6 @@ int GetRenderProcessIdFromRenderViewHost(RenderViewHost* host) {
return 0;
}
-ScopedJavaLocalRef<jobject> CreateJavaRect(JNIEnv* env, const gfx::Rect& rect) {
- return ScopedJavaLocalRef<jobject>(Java_ContentViewCore_createRect(
- env, static_cast<int>(rect.x()), static_cast<int>(rect.y()),
- static_cast<int>(rect.right()), static_cast<int>(rect.bottom())));
-}
-
int ToGestureEventType(WebInputEvent::Type type) {
switch (type) {
case WebInputEvent::kGestureScrollBegin:
@@ -241,21 +234,16 @@ void ContentViewCore::UpdateWindowAndroid(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
jlong window_android) {
- ui::ViewAndroid* view = GetViewAndroid();
- ui::WindowAndroid* window =
- reinterpret_cast<ui::WindowAndroid*>(window_android);
- if (window == GetWindowAndroid())
+ auto* window = reinterpret_cast<ui::WindowAndroid*>(window_android);
+ auto* old_window = GetWindowAndroid();
+ if (window == old_window)
return;
- if (GetWindowAndroid()) {
- for (auto& observer : observer_list_)
- observer.OnDetachedFromWindow();
+
+ auto* view = GetViewAndroid();
+ if (old_window)
view->RemoveFromParent();
- }
- if (window) {
+ if (window)
window->AddChild(view);
- for (auto& observer : observer_list_)
- observer.OnAttachedToWindow();
- }
}
base::android::ScopedJavaLocalRef<jobject>
@@ -336,7 +324,7 @@ void ContentViewCore::RenderViewHostChanged(RenderViewHost* old_host,
}
}
- SetFocusInternal(HasFocus());
+ SetFocusInternal(GetViewAndroid()->HasFocus());
}
RenderWidgetHostViewAndroid* ContentViewCore::GetRenderWidgetHostViewAndroid()
@@ -526,7 +514,7 @@ bool ContentViewCore::FilterInputEvent(const blink::WebInputEvent& event) {
if (j_obj.is_null())
return false;
- Java_ContentViewCore_requestFocus(env, j_obj);
+ GetViewAndroid()->RequestFocus();
if (event.GetType() == WebInputEvent::kMouseDown)
return false;
@@ -539,14 +527,6 @@ bool ContentViewCore::FilterInputEvent(const blink::WebInputEvent& event) {
gesture.y * dpi_scale());
}
-bool ContentViewCore::HasFocus() {
- JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
- if (obj.is_null())
- return false;
- return Java_ContentViewCore_hasFocus(env, obj);
-}
-
void ContentViewCore::RequestDisallowInterceptTouchEvent() {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
@@ -554,33 +534,6 @@ void ContentViewCore::RequestDisallowInterceptTouchEvent() {
Java_ContentViewCore_requestDisallowInterceptTouchEvent(env, obj);
}
-void ContentViewCore::ShowDisambiguationPopup(const gfx::Rect& rect_pixels,
- const SkBitmap& zoomed_bitmap) {
- JNIEnv* env = AttachCurrentThread();
-
- ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
- if (obj.is_null())
- return;
-
- ScopedJavaLocalRef<jobject> rect_object(CreateJavaRect(env, rect_pixels));
-
- ScopedJavaLocalRef<jobject> java_bitmap =
- gfx::ConvertToJavaBitmap(&zoomed_bitmap);
- DCHECK(!java_bitmap.is_null());
-
- Java_ContentViewCore_showDisambiguationPopup(env, obj, rect_object,
- java_bitmap);
-}
-
-ScopedJavaLocalRef<jobject> ContentViewCore::CreateMotionEventSynthesizer() {
- JNIEnv* env = AttachCurrentThread();
-
- ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
- if (obj.is_null())
- return ScopedJavaLocalRef<jobject>();
- return Java_ContentViewCore_createMotionEventSynthesizer(env, obj);
-}
-
void ContentViewCore::DidStopFlinging() {
JNIEnv* env = AttachCurrentThread();
@@ -1103,8 +1056,4 @@ static ScopedJavaLocalRef<jobject> FromWebContentsAndroid(
return view->GetJavaObject();
}
-bool RegisterContentViewCore(JNIEnv* env) {
- return RegisterNativesImpl(env);
-}
-
} // namespace content
diff --git a/chromium/content/browser/android/content_view_core.h b/chromium/content/browser/android/content_view_core.h
index 43d7ea05f8a..e122b3333e7 100644
--- a/chromium/content/browser/android/content_view_core.h
+++ b/chromium/content/browser/android/content_view_core.h
@@ -245,22 +245,11 @@ class ContentViewCore : public WebContentsObserver {
bool top_changed,
bool is_mobile_optimized_hint);
- bool HasFocus();
void RequestDisallowInterceptTouchEvent();
void OnGestureEventAck(const blink::WebGestureEvent& event,
InputEventAckState ack_result);
bool FilterInputEvent(const blink::WebInputEvent& event);
- // Shows the disambiguation popup
- // |rect_pixels| --> window coordinates which |zoomed_bitmap| represents
- // |zoomed_bitmap| --> magnified image of potential touch targets
- void ShowDisambiguationPopup(const gfx::Rect& rect_pixels,
- const SkBitmap& zoomed_bitmap);
-
- // Creates a java-side touch event, used for injecting motion events for
- // testing/benchmarking purposes.
- base::android::ScopedJavaLocalRef<jobject> CreateMotionEventSynthesizer();
-
void DidStopFlinging();
// Returns the context with which the ContentViewCore was created, typically
@@ -286,6 +275,7 @@ class ContentViewCore : public WebContentsObserver {
void SelectBetweenCoordinates(const gfx::PointF& base,
const gfx::PointF& extent);
+ void UpdateCursor(const content::CursorInfo& info);
void OnTouchDown(const base::android::ScopedJavaLocalRef<jobject>& event);
ui::ViewAndroid* GetViewAndroid() const;
@@ -356,8 +346,6 @@ class ContentViewCore : public WebContentsObserver {
DISALLOW_COPY_AND_ASSIGN(ContentViewCore);
};
-bool RegisterContentViewCore(JNIEnv* env);
-
} // namespace content
#endif // CONTENT_BROWSER_ANDROID_CONTENT_VIEW_CORE_H_
diff --git a/chromium/content/browser/android/content_view_core_observer.h b/chromium/content/browser/android/content_view_core_observer.h
index 396618aeaf3..aa444aca3ef 100644
--- a/chromium/content/browser/android/content_view_core_observer.h
+++ b/chromium/content/browser/android/content_view_core_observer.h
@@ -7,11 +7,10 @@
namespace content {
+// TODO(jinsukkim): Remove this interface.
class ContentViewCoreObserver {
public:
virtual void OnContentViewCoreDestroyed() = 0;
- virtual void OnAttachedToWindow() = 0;
- virtual void OnDetachedFromWindow() = 0;
protected:
virtual ~ContentViewCoreObserver() {}
diff --git a/chromium/content/browser/android/content_view_render_view.cc b/chromium/content/browser/android/content_view_render_view.cc
index 4a5e9aa7feb..8e72d811cc6 100644
--- a/chromium/content/browser/android/content_view_render_view.cc
+++ b/chromium/content/browser/android/content_view_render_view.cc
@@ -29,11 +29,6 @@ using base::android::ScopedJavaLocalRef;
namespace content {
-// static
-bool ContentViewRenderView::RegisterContentViewRenderView(JNIEnv* env) {
- return RegisterNativesImpl(env);
-}
-
ContentViewRenderView::ContentViewRenderView(JNIEnv* env,
jobject obj,
gfx::NativeWindow root_window)
diff --git a/chromium/content/browser/android/content_view_render_view.h b/chromium/content/browser/android/content_view_render_view.h
index 07927e1411d..3c1194d048c 100644
--- a/chromium/content/browser/android/content_view_render_view.h
+++ b/chromium/content/browser/android/content_view_render_view.h
@@ -19,9 +19,6 @@ class Compositor;
class ContentViewRenderView : public CompositorClient {
public:
- // Registers the JNI methods for ContentViewRender.
- static bool RegisterContentViewRenderView(JNIEnv* env);
-
ContentViewRenderView(JNIEnv* env,
jobject obj,
gfx::NativeWindow root_window);
diff --git a/chromium/content/browser/android/content_view_statics.cc b/chromium/content/browser/android/content_view_statics.cc
index 5ed75209868..222a5b81ba7 100644
--- a/chromium/content/browser/android/content_view_statics.cc
+++ b/chromium/content/browser/android/content_view_statics.cc
@@ -10,7 +10,6 @@
#include "base/android/scoped_java_ref.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
-#include "content/browser/android/content_view_statics.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/common/view_messages.h"
#include "content/public/browser/render_process_host.h"
@@ -100,11 +99,3 @@ static void SetWebKitSharedTimersSuspended(JNIEnv* env,
g_suspended_processes_watcher.Pointer()->ResumeWebkitSharedTimers();
}
}
-
-namespace content {
-
-bool RegisterWebViewStatics(JNIEnv* env) {
- return RegisterNativesImpl(env);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/android/content_view_statics.h b/chromium/content/browser/android/content_view_statics.h
deleted file mode 100644
index 00402531a3a..00000000000
--- a/chromium/content/browser/android/content_view_statics.h
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_ANDROID_CONTENT_VIEW_STATICS_H_
-#define CONTENT_BROWSER_ANDROID_CONTENT_VIEW_STATICS_H_
-
-namespace content {
-
-bool RegisterWebViewStatics(JNIEnv* env);
-
-}
-
-#endif // CONTENT_BROWSER_ANDROID_CONTENT_VIEW_STATICS_H_
diff --git a/chromium/content/browser/android/date_time_chooser_android.cc b/chromium/content/browser/android/date_time_chooser_android.cc
index 34557199101..5d0f0449f5a 100644
--- a/chromium/content/browser/android/date_time_chooser_android.cc
+++ b/chromium/content/browser/android/date_time_chooser_android.cc
@@ -103,11 +103,4 @@ void DateTimeChooserAndroid::ShowDialog(
ReplaceDateTime(env, j_date_time_chooser_, dialog_value);
}
-// ----------------------------------------------------------------------------
-// Native JNI methods
-// ----------------------------------------------------------------------------
-bool RegisterDateTimeChooserAndroid(JNIEnv* env) {
- return RegisterNativesImpl(env);
-}
-
} // namespace content
diff --git a/chromium/content/browser/android/date_time_chooser_android.h b/chromium/content/browser/android/date_time_chooser_android.h
index 0184ebc5e83..f5da0e6a473 100644
--- a/chromium/content/browser/android/date_time_chooser_android.h
+++ b/chromium/content/browser/android/date_time_chooser_android.h
@@ -53,9 +53,6 @@ class DateTimeChooserAndroid {
DISALLOW_COPY_AND_ASSIGN(DateTimeChooserAndroid);
};
-// Native JNI methods
-bool RegisterDateTimeChooserAndroid(JNIEnv* env);
-
} // namespace content
#endif // CONTENT_BROWSER_ANDROID_DATE_TIME_CHOOSER_ANDROID_H_
diff --git a/chromium/content/browser/android/dialog_overlay_impl.cc b/chromium/content/browser/android/dialog_overlay_impl.cc
index 5e3614051da..19dd5d6c03a 100644
--- a/chromium/content/browser/android/dialog_overlay_impl.cc
+++ b/chromium/content/browser/android/dialog_overlay_impl.cc
@@ -4,9 +4,13 @@
#include "content/browser/android/dialog_overlay_impl.h"
-#include "content/public/browser/web_contents.h"
+#include "content/browser/frame_host/render_frame_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/public/browser/web_contents_delegate.h"
#include "gpu/ipc/common/gpu_surface_tracker.h"
#include "jni/DialogOverlayImpl_jni.h"
+#include "ui/android/view_android_observer.h"
#include "ui/android/window_android.h"
using base::android::AttachCurrentThread;
@@ -15,11 +19,6 @@ using base::android::ScopedJavaLocalRef;
namespace content {
-// static
-bool DialogOverlayImpl::RegisterDialogOverlayImpl(JNIEnv* env) {
- return RegisterNativesImpl(env);
-}
-
static jlong Init(JNIEnv* env,
const JavaParamRef<jobject>& obj,
jlong high,
@@ -33,6 +32,13 @@ static jlong Init(JNIEnv* env,
if (!rfhi)
return 0;
+ // TODO(http://crbug.com/673886): Support overlay surfaces in VR using GVR
+ // reprojection video surface.
+ RenderWidgetHostViewBase* rwhvb =
+ static_cast<RenderWidgetHostViewBase*>(rfhi->GetView());
+ if (rwhvb->IsInVR())
+ return 0;
+
WebContentsImpl* web_contents_impl = static_cast<WebContentsImpl*>(
content::WebContents::FromRenderFrameHost(rfhi));
@@ -40,28 +46,25 @@ static jlong Init(JNIEnv* env,
if (!rfhi->IsCurrent() || web_contents_impl->IsHidden())
return 0;
- ContentViewCore* cvc = ContentViewCore::FromWebContents(web_contents_impl);
-
- if (!cvc)
+ // Dialog-based overlays are not supported for persistent video.
+ if (web_contents_impl->HasPersistentVideo())
return 0;
return reinterpret_cast<jlong>(
- new DialogOverlayImpl(obj, rfhi, web_contents_impl, cvc));
+ new DialogOverlayImpl(obj, rfhi, web_contents_impl));
}
DialogOverlayImpl::DialogOverlayImpl(const JavaParamRef<jobject>& obj,
RenderFrameHostImpl* rfhi,
- WebContents* web_contents,
- ContentViewCore* cvc)
- : WebContentsObserver(web_contents), rfhi_(rfhi), cvc_(cvc) {
+ WebContents* web_contents)
+ : WebContentsObserver(web_contents), rfhi_(rfhi) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(rfhi_);
- DCHECK(cvc_);
JNIEnv* env = AttachCurrentThread();
obj_ = JavaObjectWeakGlobalRef(env, obj);
- cvc_->AddObserver(this);
+ web_contents->GetNativeView()->AddObserver(this);
// Note that we're not allowed to call back into |obj| before it calls
// CompleteInit. However, the observer won't actually call us back until the
@@ -72,20 +75,31 @@ DialogOverlayImpl::DialogOverlayImpl(const JavaParamRef<jobject>& obj,
void DialogOverlayImpl::CompleteInit(JNIEnv* env,
const JavaParamRef<jobject>& obj) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ WebContentsDelegate* delegate = web_contents()->GetDelegate();
+
+ if (!delegate) {
+ Stop();
+ return;
+ }
+
+ // Note: It's ok to call SetOverlayMode() directly here, because there can be
+ // at most one overlay alive at the time. This logic needs to be updated if
+ // ever AndroidOverlayProviderImpl.MAX_OVERLAYS > 1.
+ delegate->SetOverlayMode(true);
+
// Send the initial token, if there is one. The observer will notify us about
// changes only.
- if (ui::WindowAndroid* window = cvc_->GetWindowAndroid()) {
+ if (auto* window = web_contents()->GetNativeView()->GetWindowAndroid()) {
ScopedJavaLocalRef<jobject> token = window->GetWindowToken();
if (!token.is_null())
- Java_DialogOverlayImpl_onWindowToken(env, obj.obj(), token);
- // else we will send one if we get a callback from |cvc_|.
+ Java_DialogOverlayImpl_onWindowToken(env, obj, token);
+ // else we will send one if we get a callback from ViewAndroid.
}
}
DialogOverlayImpl::~DialogOverlayImpl() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- // We should only be deleted after one unregisters for token callbacks.
- DCHECK(!cvc_);
}
void DialogOverlayImpl::Stop() {
@@ -94,7 +108,7 @@ void DialogOverlayImpl::Stop() {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj = obj_.get(env);
if (!obj.is_null())
- Java_DialogOverlayImpl_onDismissed(env, obj.obj());
+ Java_DialogOverlayImpl_onDismissed(env, obj);
obj_.reset();
}
@@ -110,28 +124,28 @@ void DialogOverlayImpl::GetCompositorOffset(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
const base::android::JavaParamRef<jobject>& rect) {
- gfx::Point point;
- if (cvc_) {
- if (ui::ViewAndroid* view = cvc_->GetViewAndroid())
- point = view->GetLocationOfContainerViewOnScreen();
- }
+ gfx::Point point =
+ web_contents()->GetNativeView()->GetLocationOfContainerViewInWindow();
- Java_DialogOverlayImpl_receiveCompositorOffset(env, rect.obj(), point.x(),
+ Java_DialogOverlayImpl_receiveCompositorOffset(env, rect, point.x(),
point.y());
}
void DialogOverlayImpl::UnregisterForTokensIfNeeded() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- if (!cvc_)
+
+ if (!rfhi_)
return;
- cvc_->RemoveObserver(this);
- cvc_ = nullptr;
- rfhi_ = nullptr;
-}
+ // We clear overlay mode here rather than in Destroy(), because we may have
+ // been called via a WebContentsDestroyed() event, and this might be the last
+ // opportunity we have to access web_contents().
+ WebContentsDelegate* delegate = web_contents()->GetDelegate();
+ if (delegate)
+ delegate->SetOverlayMode(false);
-void DialogOverlayImpl::OnContentViewCoreDestroyed() {
- // We will receive a destruction notification via WebContentsDestroyed().
+ web_contents()->GetNativeView()->RemoveObserver(this);
+ rfhi_ = nullptr;
}
void DialogOverlayImpl::RenderFrameDeleted(RenderFrameHost* render_frame_host) {
@@ -169,19 +183,19 @@ void DialogOverlayImpl::OnAttachedToWindow() {
ScopedJavaLocalRef<jobject> token;
- if (ui::WindowAndroid* window = cvc_->GetWindowAndroid())
+ if (auto* window = web_contents()->GetNativeView()->GetWindowAndroid())
token = window->GetWindowToken();
ScopedJavaLocalRef<jobject> obj = obj_.get(env);
if (!obj.is_null())
- Java_DialogOverlayImpl_onWindowToken(env, obj.obj(), token);
+ Java_DialogOverlayImpl_onWindowToken(env, obj, token);
}
void DialogOverlayImpl::OnDetachedFromWindow() {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj = obj_.get(env);
if (!obj.is_null())
- Java_DialogOverlayImpl_onWindowToken(env, obj.obj(), nullptr);
+ Java_DialogOverlayImpl_onWindowToken(env, obj, nullptr);
}
static jint RegisterSurface(JNIEnv* env,
diff --git a/chromium/content/browser/android/dialog_overlay_impl.h b/chromium/content/browser/android/dialog_overlay_impl.h
index c30707bed6f..ba8863afcf0 100644
--- a/chromium/content/browser/android/dialog_overlay_impl.h
+++ b/chromium/content/browser/android/dialog_overlay_impl.h
@@ -9,9 +9,9 @@
#include "base/android/jni_weak_ref.h"
#include "base/android/scoped_java_ref.h"
#include "base/unguessable_token.h"
-#include "content/browser/android/content_view_core.h"
-#include "content/browser/android/content_view_core_observer.h"
+#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"
namespace content {
@@ -19,18 +19,14 @@ namespace content {
// java side. When the ContentViewCore for the provided token is attached or
// detached from a WindowAndroid, we get the Android window token and notify the
// java side.
-class DialogOverlayImpl : public ContentViewCoreObserver,
+class DialogOverlayImpl : public ui::ViewAndroidObserver,
public WebContentsObserver {
public:
- // Registers the JNI methods for DialogOverlayImpl.
- static bool RegisterDialogOverlayImpl(JNIEnv* env);
-
// This may not call back into |obj| directly, but must post. This is because
// |obj| is still being initialized.
DialogOverlayImpl(const base::android::JavaParamRef<jobject>& obj,
RenderFrameHostImpl* rfhi,
- WebContents* web_contents,
- ContentViewCore* cvc);
+ WebContents* web_contents);
~DialogOverlayImpl() override;
// Called when the java side is ready for token / dismissed callbacks. May
@@ -48,8 +44,7 @@ class DialogOverlayImpl : public ContentViewCoreObserver,
const base::android::JavaParamRef<jobject>& obj,
const base::android::JavaParamRef<jobject>& rect);
- // ContentViewCoreObserver
- void OnContentViewCoreDestroyed() override;
+ // ui::ViewAndroidObserver
void OnAttachedToWindow() override;
void OnDetachedFromWindow() override;
@@ -61,7 +56,7 @@ class DialogOverlayImpl : public ContentViewCoreObserver,
void RenderFrameHostChanged(RenderFrameHost* old_host,
RenderFrameHost* new_host) override;
- // Unregister for tokens if we're registered, and clear |cvc_|.
+ // Unregister for tokens if we're registered.
void UnregisterForTokensIfNeeded();
private:
@@ -73,9 +68,6 @@ class DialogOverlayImpl : public ContentViewCoreObserver,
// RenderFrameHostImpl* associated with the given overlay routing token.
RenderFrameHostImpl* rfhi_;
-
- // ContentViewCore instance that we're registered with as an observer.
- ContentViewCore* cvc_;
};
} // namespace content
diff --git a/chromium/content/browser/android/gpu_process_callback.cc b/chromium/content/browser/android/gpu_process_callback.cc
index 23ca55a1fe3..0bcc4247dcd 100644
--- a/chromium/content/browser/android/gpu_process_callback.cc
+++ b/chromium/content/browser/android/gpu_process_callback.cc
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/browser/android/gpu_process_callback.h"
-
#include "base/android/scoped_java_ref.h"
#include "base/android/unguessable_token_android.h"
#include "content/browser/android/scoped_surface_request_manager.h"
@@ -44,8 +42,4 @@ base::android::ScopedJavaLocalRef<jobject> GetViewSurface(
return base::android::ScopedJavaLocalRef<jobject>(surface_view.j_surface());
}
-bool RegisterGpuProcessCallback(JNIEnv* env) {
- return RegisterNativesImpl(env);
-}
-
} // namespace content
diff --git a/chromium/content/browser/android/gpu_process_callback.h b/chromium/content/browser/android/gpu_process_callback.h
deleted file mode 100644
index e113a33a8fb..00000000000
--- a/chromium/content/browser/android/gpu_process_callback.h
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_ANDROID_GPU_PROCESS_CALLBACK_H_
-#define CONTENT_BROWSER_ANDROID_GPU_PROCESS_CALLBACK_H_
-
-#include <jni.h>
-
-namespace content {
-
-bool RegisterGpuProcessCallback(JNIEnv* env);
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_ANDROID_GPU_PROCESS_CALLBACK_H_
diff --git a/chromium/content/browser/android/ime_adapter_android.cc b/chromium/content/browser/android/ime_adapter_android.cc
index 5bd5f4bfe26..256b762e351 100644
--- a/chromium/content/browser/android/ime_adapter_android.cc
+++ b/chromium/content/browser/android/ime_adapter_android.cc
@@ -27,7 +27,7 @@
#include "jni/ImeAdapter_jni.h"
#include "third_party/WebKit/public/platform/WebInputEvent.h"
#include "third_party/WebKit/public/platform/WebTextInputType.h"
-#include "ui/base/ime/composition_underline.h"
+#include "ui/base/ime/ime_text_span.h"
using base::android::AttachCurrentThread;
using base::android::ConvertJavaStringToUTF16;
@@ -62,10 +62,6 @@ NativeWebKeyboardEvent NativeWebKeyboardEventFromKeyEvent(
} // anonymous namespace
-bool RegisterImeAdapter(JNIEnv* env) {
- return RegisterNativesImpl(env);
-}
-
jlong Init(JNIEnv* env,
const JavaParamRef<jobject>& obj,
const JavaParamRef<jobject>& jweb_contents) {
@@ -77,37 +73,38 @@ jlong Init(JNIEnv* env,
}
// Callback from Java to convert BackgroundColorSpan data to a
-// ui::CompositionUnderline instance, and append it to |underlines_ptr|.
+// ui::ImeTextSpan instance, and append it to |ime_text_spans_ptr|.
void AppendBackgroundColorSpan(JNIEnv*,
const JavaParamRef<jclass>&,
- jlong underlines_ptr,
+ jlong ime_text_spans_ptr,
jint start,
jint end,
jint background_color) {
DCHECK_GE(start, 0);
DCHECK_GE(end, 0);
// Do not check |background_color|.
- std::vector<ui::CompositionUnderline>* underlines =
- reinterpret_cast<std::vector<ui::CompositionUnderline>*>(underlines_ptr);
- underlines->push_back(ui::CompositionUnderline(
- static_cast<unsigned>(start), static_cast<unsigned>(end),
- SK_ColorTRANSPARENT, false, static_cast<unsigned>(background_color)));
+ std::vector<ui::ImeTextSpan>* ime_text_spans =
+ reinterpret_cast<std::vector<ui::ImeTextSpan>*>(ime_text_spans_ptr);
+ ime_text_spans->push_back(ui::ImeTextSpan(
+ ui::ImeTextSpan::Type::kComposition, static_cast<unsigned>(start),
+ static_cast<unsigned>(end), SK_ColorTRANSPARENT, false,
+ static_cast<unsigned>(background_color)));
}
// Callback from Java to convert UnderlineSpan data to a
-// ui::CompositionUnderline instance, and append it to |underlines_ptr|.
+// ui::ImeTextSpan instance, and append it to |ime_text_spans_ptr|.
void AppendUnderlineSpan(JNIEnv*,
const JavaParamRef<jclass>&,
- jlong underlines_ptr,
+ jlong ime_text_spans_ptr,
jint start,
jint end) {
DCHECK_GE(start, 0);
DCHECK_GE(end, 0);
- std::vector<ui::CompositionUnderline>* underlines =
- reinterpret_cast<std::vector<ui::CompositionUnderline>*>(underlines_ptr);
- underlines->push_back(ui::CompositionUnderline(
- static_cast<unsigned>(start), static_cast<unsigned>(end), SK_ColorBLACK,
- false, SK_ColorTRANSPARENT));
+ std::vector<ui::ImeTextSpan>* ime_text_spans =
+ reinterpret_cast<std::vector<ui::ImeTextSpan>*>(ime_text_spans_ptr);
+ ime_text_spans->push_back(ui::ImeTextSpan(
+ ui::ImeTextSpan::Type::kComposition, static_cast<unsigned>(start),
+ static_cast<unsigned>(end), SK_ColorBLACK, false, SK_ColorTRANSPARENT));
}
ImeAdapterAndroid::ImeAdapterAndroid(JNIEnv* env,
@@ -214,13 +211,14 @@ void ImeAdapterAndroid::SetComposingText(JNIEnv* env,
base::string16 text16 = ConvertJavaStringToUTF16(env, text_str);
- std::vector<ui::CompositionUnderline> underlines =
- GetUnderlinesFromSpans(env, obj, text, text16);
+ std::vector<ui::ImeTextSpan> ime_text_spans =
+ GetImeTextSpansFromJava(env, obj, text, text16);
// Default to plain underline if we didn't find any span that we care about.
- if (underlines.empty()) {
- underlines.push_back(ui::CompositionUnderline(
- 0, text16.length(), SK_ColorBLACK, false, SK_ColorTRANSPARENT));
+ if (ime_text_spans.empty()) {
+ ime_text_spans.push_back(
+ ui::ImeTextSpan(ui::ImeTextSpan::Type::kComposition, 0, text16.length(),
+ SK_ColorBLACK, false, SK_ColorTRANSPARENT));
}
// relative_cursor_pos is as described in the Android API for
@@ -229,7 +227,7 @@ void ImeAdapterAndroid::SetComposingText(JNIEnv* env,
if (relative_cursor_pos > 0)
relative_cursor_pos = text16.length() + relative_cursor_pos - 1;
- rwhi->ImeSetComposition(text16, underlines, gfx::Range::InvalidRange(),
+ rwhi->ImeSetComposition(text16, ime_text_spans, gfx::Range::InvalidRange(),
relative_cursor_pos, relative_cursor_pos);
}
@@ -244,8 +242,8 @@ void ImeAdapterAndroid::CommitText(JNIEnv* env,
base::string16 text16 = ConvertJavaStringToUTF16(env, text_str);
- std::vector<ui::CompositionUnderline> underlines =
- GetUnderlinesFromSpans(env, obj, text, text16);
+ std::vector<ui::ImeTextSpan> ime_text_spans =
+ GetImeTextSpansFromJava(env, obj, text, text16);
// relative_cursor_pos is as described in the Android API for
// InputConnection#commitText, whereas the parameters for
@@ -255,7 +253,7 @@ void ImeAdapterAndroid::CommitText(JNIEnv* env,
else
relative_cursor_pos -= text16.length();
- rwhi->ImeCommitText(text16, underlines, gfx::Range::InvalidRange(),
+ rwhi->ImeCommitText(text16, ime_text_spans, gfx::Range::InvalidRange(),
relative_cursor_pos);
}
@@ -340,12 +338,13 @@ void ImeAdapterAndroid::SetComposingRegion(JNIEnv*,
if (!rfh)
return;
- std::vector<ui::CompositionUnderline> underlines;
- underlines.push_back(ui::CompositionUnderline(0, end - start, SK_ColorBLACK,
- false, SK_ColorTRANSPARENT));
+ std::vector<ui::ImeTextSpan> ime_text_spans;
+ ime_text_spans.push_back(ui::ImeTextSpan(ui::ImeTextSpan::Type::kComposition,
+ 0, end - start, SK_ColorBLACK, false,
+ SK_ColorTRANSPARENT));
rfh->GetFrameInputHandler()->SetCompositionFromExistingText(start, end,
- underlines);
+ ime_text_spans);
}
void ImeAdapterAndroid::DeleteSurroundingText(JNIEnv*,
@@ -416,22 +415,24 @@ RenderFrameHost* ImeAdapterAndroid::GetFocusedFrame() {
return nullptr;
}
-std::vector<ui::CompositionUnderline> ImeAdapterAndroid::GetUnderlinesFromSpans(
+std::vector<ui::ImeTextSpan> ImeAdapterAndroid::GetImeTextSpansFromJava(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
const base::android::JavaParamRef<jobject>& text,
const base::string16& text16) {
- std::vector<ui::CompositionUnderline> underlines;
+ std::vector<ui::ImeTextSpan> ime_text_spans;
// Iterate over spans in |text|, dispatch those that we care about (e.g.,
// BackgroundColorSpan) to a matching callback (e.g.,
- // AppendBackgroundColorSpan()), and populate |underlines|.
- Java_ImeAdapter_populateUnderlinesFromSpans(
- env, obj, text, reinterpret_cast<jlong>(&underlines));
+ // AppendBackgroundColorSpan()), and populate |ime_text_spans|.
+ Java_ImeAdapter_populateImeTextSpansFromJava(
+ env, obj, text, reinterpret_cast<jlong>(&ime_text_spans));
- // Sort spans by |.startOffset|.
- std::sort(underlines.begin(), underlines.end());
+ std::sort(ime_text_spans.begin(), ime_text_spans.end(),
+ [](const ui::ImeTextSpan& span1, const ui::ImeTextSpan& span2) {
+ return span1.start_offset < span2.start_offset;
+ });
- return underlines;
+ return ime_text_spans;
}
} // namespace content
diff --git a/chromium/content/browser/android/ime_adapter_android.h b/chromium/content/browser/android/ime_adapter_android.h
index b0f775f99fa..9e591fe7c87 100644
--- a/chromium/content/browser/android/ime_adapter_android.h
+++ b/chromium/content/browser/android/ime_adapter_android.h
@@ -16,7 +16,7 @@
namespace ui {
-struct CompositionUnderline;
+struct ImeTextSpan;
} // namespace ui
@@ -113,7 +113,7 @@ class CONTENT_EXPORT ImeAdapterAndroid : public RenderWidgetHostConnector {
private:
RenderWidgetHostImpl* GetFocusedWidget();
RenderFrameHost* GetFocusedFrame();
- std::vector<ui::CompositionUnderline> GetUnderlinesFromSpans(
+ std::vector<ui::ImeTextSpan> GetImeTextSpansFromJava(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
const base::android::JavaParamRef<jobject>& text,
@@ -124,8 +124,6 @@ class CONTENT_EXPORT ImeAdapterAndroid : public RenderWidgetHostConnector {
JavaObjectWeakGlobalRef java_ime_adapter_;
};
-bool RegisterImeAdapter(JNIEnv* env);
-
} // namespace content
#endif // CONTENT_BROWSER_ANDROID_IME_ADAPTER_ANDROID_H_
diff --git a/chromium/content/browser/android/interstitial_page_delegate_android.cc b/chromium/content/browser/android/interstitial_page_delegate_android.cc
index 31e221895f6..9da5c8146b4 100644
--- a/chromium/content/browser/android/interstitial_page_delegate_android.cc
+++ b/chromium/content/browser/android/interstitial_page_delegate_android.cc
@@ -82,12 +82,6 @@ void InterstitialPageDelegateAndroid::CommandReceived(
}
}
-// static
-bool InterstitialPageDelegateAndroid
- ::RegisterInterstitialPageDelegateAndroid(JNIEnv* env) {
- return RegisterNativesImpl(env);
-}
-
static jlong Init(JNIEnv* env,
const JavaParamRef<jobject>& obj,
const JavaParamRef<jstring>& html_content) {
diff --git a/chromium/content/browser/android/interstitial_page_delegate_android.h b/chromium/content/browser/android/interstitial_page_delegate_android.h
index 3c136298934..b4900e2c461 100644
--- a/chromium/content/browser/android/interstitial_page_delegate_android.h
+++ b/chromium/content/browser/android/interstitial_page_delegate_android.h
@@ -40,8 +40,6 @@ class InterstitialPageDelegateAndroid : public InterstitialPageDelegate {
void OnDontProceed() override;
void CommandReceived(const std::string& command) override;
- static bool RegisterInterstitialPageDelegateAndroid(JNIEnv* env);
-
private:
JavaObjectWeakGlobalRef weak_java_obj_;
diff --git a/chromium/content/browser/android/java/gin_java_bridge_dispatcher_host.cc b/chromium/content/browser/android/java/gin_java_bridge_dispatcher_host.cc
index ed067a504f8..55a902efa34 100644
--- a/chromium/content/browser/android/java/gin_java_bridge_dispatcher_host.cc
+++ b/chromium/content/browser/android/java/gin_java_bridge_dispatcher_host.cc
@@ -159,24 +159,19 @@ JavaObjectWeakGlobalRef GinJavaBridgeDispatcherHost::GetObjectWeakRef(
}
JavaObjectWeakGlobalRef
-GinJavaBridgeDispatcherHost::RemoveHolderAndAdvanceLocked(
+GinJavaBridgeDispatcherHost::RemoveHolderLocked(
int32_t holder,
ObjectMap::iterator* iter_ptr) {
objects_lock_.AssertAcquired();
JavaObjectWeakGlobalRef result;
scoped_refptr<GinJavaBoundObject> object((*iter_ptr)->second);
- bool object_erased = false;
if (!object->IsNamed()) {
object->RemoveHolder(holder);
if (!object->HasHolders()) {
result = object->GetWeakRef();
- objects_.erase((*iter_ptr)++);
- object_erased = true;
+ objects_.erase(*iter_ptr);
}
}
- if (!object_erased) {
- ++(*iter_ptr);
- }
return result;
}
@@ -372,8 +367,7 @@ void GinJavaBridgeDispatcherHost::OnObjectWrapperDeleted(
auto iter = objects_.find(object_id);
if (iter == objects_.end())
return;
- JavaObjectWeakGlobalRef ref =
- RemoveHolderAndAdvanceLocked(routing_id, &iter);
+ JavaObjectWeakGlobalRef ref = RemoveHolderLocked(routing_id, &iter);
if (!ref.is_uninitialized()) {
RemoveFromRetainedObjectSetLocked(ref);
}
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 aeffec893fa..7e0b723342d 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
@@ -95,7 +95,7 @@ class GinJavaBridgeDispatcherHost
bool FindObjectId(const base::android::JavaRef<jobject>& object,
GinJavaBoundObject::ObjectID* object_id);
void RemoveFromRetainedObjectSetLocked(const JavaObjectWeakGlobalRef& ref);
- JavaObjectWeakGlobalRef RemoveHolderAndAdvanceLocked(
+ JavaObjectWeakGlobalRef RemoveHolderLocked(
int32_t holder,
ObjectMap::iterator* iter_ptr);
diff --git a/chromium/content/browser/android/java_interfaces_impl.cc b/chromium/content/browser/android/java_interfaces_impl.cc
index 8bfa589bad8..7e2b2e22494 100644
--- a/chromium/content/browser/android/java_interfaces_impl.cc
+++ b/chromium/content/browser/android/java_interfaces_impl.cc
@@ -56,7 +56,7 @@ void BindInterfaceRegistryForWebContents(
JNIEnv* env = base::android::AttachCurrentThread();
Java_InterfaceRegistrarImpl_createInterfaceRegistryForWebContents(
env, request.PassMessagePipe().release().value(),
- web_contents->GetJavaWebContents().obj());
+ web_contents->GetJavaWebContents());
}
void BindInterfaceRegistryForRenderFrameHost(
@@ -65,7 +65,7 @@ void BindInterfaceRegistryForRenderFrameHost(
JNIEnv* env = base::android::AttachCurrentThread();
Java_InterfaceRegistrarImpl_createInterfaceRegistryForRenderFrameHost(
env, request.PassMessagePipe().release().value(),
- render_frame_host->GetJavaRenderFrameHost().obj());
+ render_frame_host->GetJavaRenderFrameHost());
}
} // namespace content
diff --git a/chromium/content/browser/android/load_url_params.cc b/chromium/content/browser/android/load_url_params.cc
index 98c681968e9..bd9f814f66b 100644
--- a/chromium/content/browser/android/load_url_params.cc
+++ b/chromium/content/browser/android/load_url_params.cc
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/browser/android/load_url_params.h"
-
#include <jni.h>
#include "base/android/jni_string.h"
@@ -16,10 +14,6 @@ using base::android::JavaParamRef;
namespace content {
-bool RegisterLoadUrlParams(JNIEnv* env) {
- return RegisterNativesImpl(env);
-}
-
jboolean IsDataScheme(JNIEnv* env,
const JavaParamRef<jclass>& clazz,
const JavaParamRef<jstring>& jurl) {
diff --git a/chromium/content/browser/android/load_url_params.h b/chromium/content/browser/android/load_url_params.h
deleted file mode 100644
index 77a68f15637..00000000000
--- a/chromium/content/browser/android/load_url_params.h
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_ANDROID_LOAD_URL_PARAMS_H_
-#define CONTENT_BROWSER_ANDROID_LOAD_URL_PARAMS_H_
-
-#include <jni.h>
-
-namespace content {
-
-bool RegisterLoadUrlParams(JNIEnv* env);
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_ANDROID_LOAD_URL_PARAMS_H_
diff --git a/chromium/content/browser/android/nfc_host.cc b/chromium/content/browser/android/nfc_host.cc
index 2709c8b5e58..179a21e79b1 100644
--- a/chromium/content/browser/android/nfc_host.cc
+++ b/chromium/content/browser/android/nfc_host.cc
@@ -28,7 +28,7 @@ NFCHost::NFCHost(WebContents* web_contents)
JNIEnv* env = base::android::AttachCurrentThread();
java_nfc_host_.Reset(
- Java_NfcHost_create(env, web_contents_->GetJavaWebContents().obj(), id_));
+ Java_NfcHost_create(env, web_contents_->GetJavaWebContents(), id_));
if (ServiceManagerConnection::GetForProcess()) {
service_manager::Connector* connector =
diff --git a/chromium/content/browser/android/overscroll_controller_android.cc b/chromium/content/browser/android/overscroll_controller_android.cc
index 3be50dac488..2a3201dba32 100644
--- a/chromium/content/browser/android/overscroll_controller_android.cc
+++ b/chromium/content/browser/android/overscroll_controller_android.cc
@@ -9,6 +9,7 @@
#include "base/memory/ptr_util.h"
#include "cc/layers/layer.h"
#include "cc/output/compositor_frame_metadata.h"
+#include "content/common/content_switches_internal.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/common/content_switches.h"
#include "third_party/WebKit/public/platform/WebGestureEvent.h"
@@ -95,6 +96,30 @@ std::unique_ptr<OverscrollRefresh> CreateRefreshEffect(
} // namespace
+// static
+std::unique_ptr<OverscrollControllerAndroid>
+OverscrollControllerAndroid::CreateForTests(
+ ui::WindowAndroidCompositor* compositor,
+ float dpi_scale,
+ std::unique_ptr<ui::OverscrollGlow> glow_effect,
+ std::unique_ptr<ui::OverscrollRefresh> refresh_effect) {
+ return std::unique_ptr<OverscrollControllerAndroid>(
+ new OverscrollControllerAndroid(compositor, dpi_scale,
+ std::move(glow_effect),
+ std::move(refresh_effect)));
+}
+
+OverscrollControllerAndroid::OverscrollControllerAndroid(
+ ui::WindowAndroidCompositor* compositor,
+ float dpi_scale,
+ std::unique_ptr<ui::OverscrollGlow> glow_effect,
+ std::unique_ptr<ui::OverscrollRefresh> refresh_effect)
+ : compositor_(compositor),
+ dpi_scale_(dpi_scale),
+ enabled_(true),
+ glow_effect_(std::move(glow_effect)),
+ refresh_effect_(std::move(refresh_effect)) {}
+
OverscrollControllerAndroid::OverscrollControllerAndroid(
ui::OverscrollRefreshHandler* overscroll_refresh_handler,
ui::WindowAndroidCompositor* compositor,
@@ -189,10 +214,11 @@ void OverscrollControllerAndroid::OnGestureEventAck(
refresh_effect_) {
// The effect should only be allowed if both the causal touch events go
// unconsumed and the generated scroll events go unconsumed.
- bool consumed =
- ack_result == INPUT_EVENT_ACK_STATE_CONSUMED ||
- event.data.scroll_update.previous_update_in_sequence_prevented;
- refresh_effect_->OnScrollUpdateAck(consumed);
+ if (refresh_effect_->IsAwaitingScrollUpdateAck() &&
+ (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED ||
+ event.data.scroll_update.previous_update_in_sequence_prevented)) {
+ refresh_effect_->Reset();
+ }
}
}
@@ -201,22 +227,54 @@ void OverscrollControllerAndroid::OnOverscrolled(
if (!enabled_)
return;
- if (refresh_effect_ && (refresh_effect_->IsActive() ||
- refresh_effect_->IsAwaitingScrollUpdateAck())) {
- // An active (or potentially active) refresh effect should always pre-empt
- // the passive glow effect.
- return;
+ if (refresh_effect_) {
+ if (params.scroll_boundary_behavior.y !=
+ cc::ScrollBoundaryBehavior::ScrollBoundaryBehaviorType::
+ kScrollBoundaryBehaviorTypeAuto)
+ refresh_effect_->Reset();
+ else
+ refresh_effect_->OnOverscrolled();
+
+ if (refresh_effect_->IsActive() ||
+ refresh_effect_->IsAwaitingScrollUpdateAck()) {
+ // An active (or potentially active) refresh effect should always pre-empt
+ // the passive glow effect.
+ return;
+ }
}
- if (glow_effect_ &&
- glow_effect_->OnOverscrolled(
- base::TimeTicks::Now(),
- gfx::ScaleVector2d(params.accumulated_overscroll, dpi_scale_),
- gfx::ScaleVector2d(params.latest_overscroll_delta, dpi_scale_),
- gfx::ScaleVector2d(params.current_fling_velocity, dpi_scale_),
- gfx::ScaleVector2d(
- params.causal_event_viewport_point.OffsetFromOrigin(),
- dpi_scale_))) {
+ // When use-zoom-for-dsf is enabled, each value of params was already scaled
+ // by the device scale factor.
+ float scale_factor = IsUseZoomForDSFEnabled() ? 1.f : dpi_scale_;
+ gfx::Vector2dF accumulated_overscroll =
+ gfx::ScaleVector2d(params.accumulated_overscroll, scale_factor);
+ gfx::Vector2dF latest_overscroll_delta =
+ gfx::ScaleVector2d(params.latest_overscroll_delta, scale_factor);
+ gfx::Vector2dF current_fling_velocity =
+ gfx::ScaleVector2d(params.current_fling_velocity, scale_factor);
+ gfx::Vector2dF overscroll_location = gfx::ScaleVector2d(
+ params.causal_event_viewport_point.OffsetFromOrigin(), scale_factor);
+
+ if (params.scroll_boundary_behavior.x ==
+ cc::ScrollBoundaryBehavior::ScrollBoundaryBehaviorType::
+ kScrollBoundaryBehaviorTypeNone) {
+ accumulated_overscroll.set_x(0);
+ latest_overscroll_delta.set_x(0);
+ current_fling_velocity.set_x(0);
+ }
+
+ if (params.scroll_boundary_behavior.y ==
+ cc::ScrollBoundaryBehavior::ScrollBoundaryBehaviorType::
+ kScrollBoundaryBehaviorTypeNone) {
+ accumulated_overscroll.set_y(0);
+ latest_overscroll_delta.set_y(0);
+ current_fling_velocity.set_y(0);
+ }
+
+ if (glow_effect_ && glow_effect_->OnOverscrolled(
+ base::TimeTicks::Now(), accumulated_overscroll,
+ latest_overscroll_delta, current_fling_velocity,
+ overscroll_location)) {
SetNeedsAnimate();
}
}
@@ -235,8 +293,12 @@ void OverscrollControllerAndroid::OnFrameMetadataUpdated(
if (!refresh_effect_ && !glow_effect_)
return;
- const float scale_factor =
- frame_metadata.page_scale_factor * frame_metadata.device_scale_factor;
+ // When use-zoom-for-dsf is enabled, frame_metadata.page_scale_factor was
+ // already scaled by the device scale factor.
+ float scale_factor = frame_metadata.page_scale_factor;
+ if (!IsUseZoomForDSFEnabled()) {
+ scale_factor *= frame_metadata.device_scale_factor;
+ }
gfx::SizeF viewport_size =
gfx::ScaleSize(frame_metadata.scrollable_viewport_size, scale_factor);
gfx::SizeF content_size =
diff --git a/chromium/content/browser/android/overscroll_controller_android.h b/chromium/content/browser/android/overscroll_controller_android.h
index f049bdc2cd9..b9051561888 100644
--- a/chromium/content/browser/android/overscroll_controller_android.h
+++ b/chromium/content/browser/android/overscroll_controller_android.h
@@ -10,6 +10,7 @@
#include "base/android/scoped_java_ref.h"
#include "base/macros.h"
#include "base/time/time.h"
+#include "content/common/content_export.h"
#include "content/common/input/input_event_ack_state.h"
#include "ui/android/overscroll_glow.h"
#include "ui/android/overscroll_refresh.h"
@@ -34,12 +35,20 @@ namespace content {
// Glue class for handling all inputs into Android-specific overscroll effects,
// both the passive overscroll glow and the active overscroll pull-to-refresh.
// Note that all input coordinates (both for events and overscroll) are in DIPs.
-class OverscrollControllerAndroid : public ui::OverscrollGlowClient {
+class CONTENT_EXPORT OverscrollControllerAndroid
+ : public ui::OverscrollGlowClient {
public:
OverscrollControllerAndroid(
ui::OverscrollRefreshHandler* overscroll_refresh_handler,
ui::WindowAndroidCompositor* compositor,
float dpi_scale);
+
+ static std::unique_ptr<OverscrollControllerAndroid> CreateForTests(
+ ui::WindowAndroidCompositor* compositor,
+ float dpi_scale,
+ std::unique_ptr<ui::OverscrollGlow> glow_effect,
+ std::unique_ptr<ui::OverscrollRefresh> refresh_effect);
+
~OverscrollControllerAndroid() override;
// Returns true if |event| is consumed by an overscroll effect, in which
@@ -66,6 +75,13 @@ class OverscrollControllerAndroid : public ui::OverscrollGlowClient {
void Disable();
private:
+ // This method should only be called from CreateForTests.
+ OverscrollControllerAndroid(
+ ui::WindowAndroidCompositor* compositor,
+ float dpi_scale,
+ std::unique_ptr<ui::OverscrollGlow> glow_effect,
+ std::unique_ptr<ui::OverscrollRefresh> refresh_effect);
+
// OverscrollGlowClient implementation.
std::unique_ptr<ui::EdgeEffectBase> CreateEdgeEffect() override;
diff --git a/chromium/content/browser/android/overscroll_controller_android_unittest.cc b/chromium/content/browser/android/overscroll_controller_android_unittest.cc
new file mode 100644
index 00000000000..7db012376b3
--- /dev/null
+++ b/chromium/content/browser/android/overscroll_controller_android_unittest.cc
@@ -0,0 +1,210 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/android/overscroll_controller_android.h"
+#include <memory>
+#include "base/macros.h"
+#include "base/memory/ptr_util.h"
+#include "cc/layers/layer.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/public/platform/WebGestureEvent.h"
+#include "third_party/WebKit/public/platform/WebInputEvent.h"
+#include "ui/android/overscroll_glow.h"
+#include "ui/android/overscroll_refresh.h"
+#include "ui/android/resources/resource_manager_impl.h"
+#include "ui/android/window_android_compositor.h"
+#include "ui/events/base_event_utils.h"
+#include "ui/events/blink/did_overscroll_params.h"
+
+using ui::EdgeEffectBase;
+using ui::ResourceManager;
+using ui::OverscrollGlow;
+using ui::OverscrollGlowClient;
+using ui::OverscrollRefresh;
+using ui::WindowAndroidCompositor;
+using ::testing::_;
+using ::testing::Return;
+
+namespace content {
+
+namespace {
+
+class MockCompositor : public WindowAndroidCompositor {
+ public:
+ void AttachLayerForReadback(scoped_refptr<cc::Layer>) override {}
+ void RequestCopyOfOutputOnRootLayer(
+ std::unique_ptr<viz::CopyOutputRequest>) override {}
+ void SetNeedsAnimate() override {}
+ MOCK_METHOD0(GetResourceManager, ResourceManager&());
+ MOCK_METHOD0(GetFrameSinkId, viz::FrameSinkId());
+ void AddChildFrameSink(const viz::FrameSinkId& frame_sink_id) override {}
+ void RemoveChildFrameSink(const viz::FrameSinkId& frame_sink_id) override {}
+};
+
+class MockGlowClient : public OverscrollGlowClient {
+ public:
+ MOCK_METHOD0(CreateEdgeEffect, std::unique_ptr<EdgeEffectBase>());
+};
+
+class MockGlow : public OverscrollGlow {
+ public:
+ MockGlow() : OverscrollGlow(new MockGlowClient()) {}
+ MOCK_METHOD5(OnOverscrolled,
+ bool(base::TimeTicks,
+ gfx::Vector2dF,
+ gfx::Vector2dF,
+ gfx::Vector2dF,
+ gfx::Vector2dF));
+};
+
+class MockRefresh : public OverscrollRefresh {
+ public:
+ MockRefresh() : OverscrollRefresh() {}
+ MOCK_METHOD0(OnOverscrolled, void());
+ MOCK_METHOD0(Reset, void());
+ MOCK_CONST_METHOD0(IsActive, bool());
+ MOCK_CONST_METHOD0(IsAwaitingScrollUpdateAck, bool());
+};
+
+class OverscrollControllerAndroidUnitTest : public testing::Test {
+ public:
+ OverscrollControllerAndroidUnitTest() {
+ std::unique_ptr<MockGlow> glow_ptr = base::MakeUnique<MockGlow>();
+ std::unique_ptr<MockRefresh> refresh_ptr = base::MakeUnique<MockRefresh>();
+ compositor_ = base::MakeUnique<MockCompositor>();
+ glow_ = glow_ptr.get();
+ refresh_ = refresh_ptr.get();
+ controller_ = OverscrollControllerAndroid::CreateForTests(
+ compositor_.get(), 560, std::move(glow_ptr), std::move(refresh_ptr));
+ }
+
+ ui::DidOverscrollParams CreateVerticalOverscrollParams() {
+ ui::DidOverscrollParams params;
+ params.accumulated_overscroll = gfx::Vector2dF(0, 1);
+ params.latest_overscroll_delta = gfx::Vector2dF(0, 1);
+ params.current_fling_velocity = gfx::Vector2dF(0, 1);
+ params.causal_event_viewport_point = gfx::PointF(100, 100);
+ return params;
+ }
+
+ protected:
+ MockGlow* glow_;
+ MockRefresh* refresh_;
+ std::unique_ptr<MockCompositor> compositor_;
+ std::unique_ptr<OverscrollControllerAndroid> controller_;
+};
+
+TEST_F(OverscrollControllerAndroidUnitTest,
+ ScrollBoundaryBehaviorAutoAllowsGlowAndNavigation) {
+ ui::DidOverscrollParams params = CreateVerticalOverscrollParams();
+ params.scroll_boundary_behavior.y = cc::ScrollBoundaryBehavior::
+ ScrollBoundaryBehaviorType::kScrollBoundaryBehaviorTypeAuto;
+
+ EXPECT_CALL(*refresh_, OnOverscrolled());
+ EXPECT_CALL(*refresh_, IsActive()).WillOnce(Return(true));
+ EXPECT_CALL(*refresh_, IsAwaitingScrollUpdateAck()).Times(0);
+ EXPECT_CALL(*glow_, OnOverscrolled(_, _, _, _, _)).Times(0);
+
+ controller_->OnOverscrolled(params);
+ testing::Mock::VerifyAndClearExpectations(&refresh_);
+}
+
+TEST_F(OverscrollControllerAndroidUnitTest,
+ ScrollBoundaryBehaviorContainPreventsNavigation) {
+ ui::DidOverscrollParams params = CreateVerticalOverscrollParams();
+ params.scroll_boundary_behavior.y = cc::ScrollBoundaryBehavior::
+ ScrollBoundaryBehaviorType::kScrollBoundaryBehaviorTypeContain;
+
+ EXPECT_CALL(*refresh_, OnOverscrolled()).Times(0);
+ EXPECT_CALL(*refresh_, Reset());
+ EXPECT_CALL(*refresh_, IsActive()).WillOnce(Return(false));
+ EXPECT_CALL(*refresh_, IsAwaitingScrollUpdateAck()).WillOnce(Return(false));
+ EXPECT_CALL(*glow_,
+ OnOverscrolled(_, gfx::Vector2dF(0, 560), gfx::Vector2dF(0, 560),
+ gfx::Vector2dF(0, 560), _));
+
+ controller_->OnOverscrolled(params);
+ testing::Mock::VerifyAndClearExpectations(refresh_);
+ testing::Mock::VerifyAndClearExpectations(glow_);
+
+ // Test that the "contain" set on x-axis would not affect navigation.
+ params.scroll_boundary_behavior.y = cc::ScrollBoundaryBehavior::
+ ScrollBoundaryBehaviorType::kScrollBoundaryBehaviorTypeAuto;
+ params.scroll_boundary_behavior.x = cc::ScrollBoundaryBehavior::
+ ScrollBoundaryBehaviorType::kScrollBoundaryBehaviorTypeContain;
+
+ EXPECT_CALL(*refresh_, OnOverscrolled());
+ EXPECT_CALL(*refresh_, Reset()).Times(0);
+ EXPECT_CALL(*refresh_, IsActive()).WillOnce(Return(true));
+ EXPECT_CALL(*refresh_, IsAwaitingScrollUpdateAck()).Times(0);
+ EXPECT_CALL(*glow_, OnOverscrolled(_, _, _, _, _)).Times(0);
+
+ controller_->OnOverscrolled(params);
+ testing::Mock::VerifyAndClearExpectations(refresh_);
+ testing::Mock::VerifyAndClearExpectations(glow_);
+}
+
+TEST_F(OverscrollControllerAndroidUnitTest,
+ ScrollBoundaryBehaviorNonePreventsNavigationAndGlow) {
+ ui::DidOverscrollParams params = CreateVerticalOverscrollParams();
+ params.scroll_boundary_behavior.y = cc::ScrollBoundaryBehavior::
+ ScrollBoundaryBehaviorType::kScrollBoundaryBehaviorTypeNone;
+
+ EXPECT_CALL(*refresh_, OnOverscrolled()).Times(0);
+ EXPECT_CALL(*refresh_, Reset());
+ EXPECT_CALL(*refresh_, IsActive()).WillOnce(Return(false));
+ EXPECT_CALL(*refresh_, IsAwaitingScrollUpdateAck()).WillOnce(Return(false));
+ EXPECT_CALL(*glow_, OnOverscrolled(_, gfx::Vector2dF(), gfx::Vector2dF(),
+ gfx::Vector2dF(), _));
+
+ controller_->OnOverscrolled(params);
+ testing::Mock::VerifyAndClearExpectations(refresh_);
+ testing::Mock::VerifyAndClearExpectations(glow_);
+
+ // Test that the "none" set on y-axis would not affect glow on x-axis.
+ params.accumulated_overscroll = gfx::Vector2dF(1, 1);
+ params.latest_overscroll_delta = gfx::Vector2dF(1, 1);
+ params.current_fling_velocity = gfx::Vector2dF(1, 1);
+
+ EXPECT_CALL(*refresh_, OnOverscrolled()).Times(0);
+ EXPECT_CALL(*refresh_, Reset());
+ EXPECT_CALL(*refresh_, IsActive()).WillOnce(Return(false));
+ EXPECT_CALL(*refresh_, IsAwaitingScrollUpdateAck()).WillOnce(Return(false));
+ EXPECT_CALL(*glow_,
+ OnOverscrolled(_, gfx::Vector2dF(560, 0), gfx::Vector2dF(560, 0),
+ gfx::Vector2dF(560, 0), _));
+
+ controller_->OnOverscrolled(params);
+ testing::Mock::VerifyAndClearExpectations(refresh_);
+ testing::Mock::VerifyAndClearExpectations(glow_);
+}
+
+TEST_F(OverscrollControllerAndroidUnitTest,
+ ConsumedUpdateDoesNotResetEnabledRefresh) {
+ ui::DidOverscrollParams params = CreateVerticalOverscrollParams();
+ params.scroll_boundary_behavior.y = cc::ScrollBoundaryBehavior::
+ ScrollBoundaryBehaviorType::kScrollBoundaryBehaviorTypeAuto;
+
+ EXPECT_CALL(*refresh_, OnOverscrolled());
+ EXPECT_CALL(*refresh_, IsActive()).WillOnce(Return(true));
+ EXPECT_CALL(*refresh_, IsAwaitingScrollUpdateAck()).WillOnce(Return(false));
+ EXPECT_CALL(*refresh_, Reset()).Times(0);
+
+ // Enable the refresh effect.
+ controller_->OnOverscrolled(params);
+
+ // Generate a consumed scroll update.
+ blink::WebGestureEvent event(
+ blink::WebInputEvent::kGestureScrollUpdate,
+ blink::WebInputEvent::kNoModifiers,
+ ui::EventTimeStampToSeconds(ui::EventTimeForNow()));
+ controller_->OnGestureEventAck(event, INPUT_EVENT_ACK_STATE_CONSUMED);
+
+ testing::Mock::VerifyAndClearExpectations(&refresh_);
+}
+
+} // namespace
+
+} // namespace content \ No newline at end of file
diff --git a/chromium/content/browser/android/popup_zoomer.cc b/chromium/content/browser/android/popup_zoomer.cc
new file mode 100644
index 00000000000..8f1357e1e93
--- /dev/null
+++ b/chromium/content/browser/android/popup_zoomer.cc
@@ -0,0 +1,105 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/android/popup_zoomer.h"
+
+#include "base/android/jni_android.h"
+#include "base/android/jni_string.h"
+#include "base/android/scoped_java_ref.h"
+#include "content/browser/renderer_host/render_widget_host_view_android.h"
+#include "content/public/browser/web_contents.h"
+#include "jni/PopupZoomer_jni.h"
+#include "ui/gfx/android/java_bitmap.h"
+
+using base::android::AttachCurrentThread;
+using base::android::ConvertUTF8ToJavaString;
+using base::android::JavaParamRef;
+using base::android::ScopedJavaLocalRef;
+
+namespace content {
+
+namespace {
+
+ScopedJavaLocalRef<jobject> CreateJavaRect(JNIEnv* env, const gfx::Rect& rect) {
+ return ScopedJavaLocalRef<jobject>(Java_PopupZoomer_createRect(
+ env, rect.x(), rect.y(), rect.right(), rect.bottom()));
+}
+
+} // namespace
+
+jlong Init(JNIEnv* env,
+ const JavaParamRef<jobject>& obj,
+ const JavaParamRef<jobject>& jweb_contents) {
+ WebContents* web_contents = WebContents::FromJavaWebContents(jweb_contents);
+ DCHECK(web_contents);
+
+ // Owns itself and gets destroyed when |WebContentsDestroyed| is called.
+ auto* popup_zoomer = new PopupZoomer(env, obj, web_contents);
+ popup_zoomer->Initialize();
+ return reinterpret_cast<intptr_t>(popup_zoomer);
+}
+
+PopupZoomer::PopupZoomer(JNIEnv* env,
+ const JavaParamRef<jobject>& obj,
+ WebContents* web_contents)
+ : RenderWidgetHostConnector(web_contents), rwhva_(nullptr) {
+ java_obj_ = JavaObjectWeakGlobalRef(env, obj);
+}
+
+PopupZoomer::~PopupZoomer() {
+ JNIEnv* env = AttachCurrentThread();
+ ScopedJavaLocalRef<jobject> obj = java_obj_.get(env);
+ if (!obj.is_null())
+ Java_PopupZoomer_destroy(env, obj);
+}
+
+void PopupZoomer::UpdateRenderProcessConnection(
+ RenderWidgetHostViewAndroid* old_rwhva,
+ RenderWidgetHostViewAndroid* new_rwhva) {
+ if (old_rwhva)
+ old_rwhva->set_popup_zoomer(nullptr);
+ if (new_rwhva)
+ new_rwhva->set_popup_zoomer(this);
+ rwhva_ = new_rwhva;
+}
+
+void PopupZoomer::ShowPopup(const gfx::Rect& rect_pixels,
+ const SkBitmap& zoomed_bitmap) {
+ JNIEnv* env = AttachCurrentThread();
+ ScopedJavaLocalRef<jobject> obj = java_obj_.get(env);
+ if (obj.is_null())
+ return;
+
+ ScopedJavaLocalRef<jobject> rect_object(CreateJavaRect(env, rect_pixels));
+
+ ScopedJavaLocalRef<jobject> java_bitmap =
+ gfx::ConvertToJavaBitmap(&zoomed_bitmap);
+ DCHECK(!java_bitmap.is_null());
+
+ Java_PopupZoomer_showPopup(env, obj, rect_object, java_bitmap);
+}
+
+void PopupZoomer::HidePopup() {
+ JNIEnv* env = AttachCurrentThread();
+ ScopedJavaLocalRef<jobject> obj = java_obj_.get(env);
+ if (obj.is_null())
+ return;
+ Java_PopupZoomer_hidePopup(env, obj);
+}
+
+void PopupZoomer::ResolveTapDisambiguation(JNIEnv* env,
+ const JavaParamRef<jobject>& obj,
+ jlong time_ms,
+ jfloat x,
+ jfloat y,
+ jboolean is_long_press) {
+ if (!rwhva_)
+ return;
+
+ float dip_scale = rwhva_->GetNativeView()->GetDipScale();
+ rwhva_->ResolveTapDisambiguation(
+ time_ms / 1000, gfx::Point(x / dip_scale, y / dip_scale), is_long_press);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/android/popup_zoomer.h b/chromium/content/browser/android/popup_zoomer.h
new file mode 100644
index 00000000000..e3f33d545d8
--- /dev/null
+++ b/chromium/content/browser/android/popup_zoomer.h
@@ -0,0 +1,57 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_ANDROID_POPUP_ZOOMER_H_
+#define CONTENT_BROWSER_ANDROID_POPUP_ZOOMER_H_
+
+#include <jni.h>
+
+#include "base/android/jni_weak_ref.h"
+#include "content/browser/android/render_widget_host_connector.h"
+#include "ui/gfx/geometry/rect_f.h"
+
+namespace content {
+
+class RenderWidgetHostViewAndroid;
+
+class PopupZoomer : public RenderWidgetHostConnector {
+ public:
+ PopupZoomer(JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj,
+ WebContents* web_contents);
+
+ // RendetWidgetHostConnector implementation.
+ void UpdateRenderProcessConnection(
+ RenderWidgetHostViewAndroid* old_rwhva,
+ RenderWidgetHostViewAndroid* new_rhwva) override;
+
+ // Shows the disambiguation popup
+ // |rect_pixels| --> window coordinates which |zoomed_bitmap| represents
+ // |zoomed_bitmap| --> magnified image of potential touch targets
+ void ResolveTapDisambiguation(JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj,
+ jlong time_ms,
+ jfloat x,
+ jfloat y,
+ jboolean is_long_press);
+
+ // Called from native -> java
+
+ // Shows the disambiguation popup
+ // |rect_pixels| --> window coordinates which |zoomed_bitmap| represents
+ // |zoomed_bitmap| --> magnified image of potential touch targets
+ void ShowPopup(const gfx::Rect& rect_pixels, const SkBitmap& zoomed_bitmap);
+ void HidePopup();
+
+ private:
+ ~PopupZoomer() override;
+
+ // Current RenderWidgetHostView connected to this instance. Can be null.
+ RenderWidgetHostViewAndroid* rwhva_;
+ JavaObjectWeakGlobalRef java_obj_;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_ANDROID_POPUP_ZOOMER_H_
diff --git a/chromium/content/browser/android/selection_popup_controller.cc b/chromium/content/browser/android/selection_popup_controller.cc
index dddea6e7e7d..550dc3dc883 100644
--- a/chromium/content/browser/android/selection_popup_controller.cc
+++ b/chromium/content/browser/android/selection_popup_controller.cc
@@ -32,10 +32,6 @@ void Init(JNIEnv* env,
(new SelectionPopupController(env, obj, web_contents))->Initialize();
}
-bool RegisterSelectionPopupController(JNIEnv* env) {
- return RegisterNativesImpl(env);
-}
-
SelectionPopupController::SelectionPopupController(
JNIEnv* env,
const JavaParamRef<jobject>& obj,
diff --git a/chromium/content/browser/android/selection_popup_controller.h b/chromium/content/browser/android/selection_popup_controller.h
index b7684713c47..676b89a504e 100644
--- a/chromium/content/browser/android/selection_popup_controller.h
+++ b/chromium/content/browser/android/selection_popup_controller.h
@@ -43,8 +43,6 @@ class SelectionPopupController : public RenderWidgetHostConnector {
JavaObjectWeakGlobalRef java_obj_;
};
-bool RegisterSelectionPopupController(JNIEnv* env);
-
} // namespace content
#endif // CONTENT_BROWSER_ANDROID_SELECTION_POPUP_CONTROLLER_H_
diff --git a/chromium/content/browser/android/smart_selection_client.cc b/chromium/content/browser/android/smart_selection_client.cc
index fdf347cba40..95497ef141e 100644
--- a/chromium/content/browser/android/smart_selection_client.cc
+++ b/chromium/content/browser/android/smart_selection_client.cc
@@ -103,8 +103,4 @@ void SmartSelectionClient::OnSurroundingTextReceived(int callback_data,
}
}
-bool RegisterSmartSelectionClient(JNIEnv* env) {
- return RegisterNativesImpl(env);
-}
-
} // namespace content
diff --git a/chromium/content/browser/android/smart_selection_client.h b/chromium/content/browser/android/smart_selection_client.h
index ed35f18b154..ca1c32a48f4 100644
--- a/chromium/content/browser/android/smart_selection_client.h
+++ b/chromium/content/browser/android/smart_selection_client.h
@@ -55,8 +55,6 @@ class SmartSelectionClient {
DISALLOW_COPY_AND_ASSIGN(SmartSelectionClient);
};
-bool RegisterSmartSelectionClient(JNIEnv* env);
-
} // namespace content
#endif // CONTENT_BROWSER_ANDROID_SMART_SELECTION_CLIENT_H_
diff --git a/chromium/content/browser/android/string_message_codec.cc b/chromium/content/browser/android/string_message_codec.cc
index b2bae5ddcf9..5303ac43b73 100644
--- a/chromium/content/browser/android/string_message_codec.cc
+++ b/chromium/content/browser/android/string_message_codec.cc
@@ -81,7 +81,7 @@ bool ContainsOnlyLatin1(const base::string16& data) {
} // namespace
-base::string16 EncodeStringMessage(const base::string16& data) {
+std::vector<uint8_t> EncodeStringMessage(const base::string16& data) {
std::vector<uint8_t> buffer;
WriteUint8(kVersionTag, &buffer);
WriteUint32(kVersion, &buffer);
@@ -100,20 +100,13 @@ base::string16 EncodeStringMessage(const base::string16& data) {
WriteBytes(reinterpret_cast<const char*>(data.data()), num_bytes, &buffer);
}
- base::string16 result;
- size_t result_num_bytes = (buffer.size() + 1) & ~1;
- result.resize(result_num_bytes / 2);
- uint8_t* destination = reinterpret_cast<uint8_t*>(&result[0]);
- memcpy(destination, &buffer[0], buffer.size());
- return result;
+ return buffer;
}
-bool DecodeStringMessage(const base::string16& encoded_data,
+bool DecodeStringMessage(const std::vector<uint8_t>& encoded_data,
base::string16* result) {
- size_t num_bytes = encoded_data.size() * 2;
-
- const uint8_t* ptr = reinterpret_cast<const uint8_t*>(&encoded_data[0]);
- const uint8_t* end = ptr + num_bytes;
+ const uint8_t* ptr = encoded_data.data();
+ const uint8_t* end = ptr + encoded_data.size();
uint8_t tag;
// Discard any leading version and padding tags.
diff --git a/chromium/content/browser/android/string_message_codec.h b/chromium/content/browser/android/string_message_codec.h
index 94f18c2d596..a613f057609 100644
--- a/chromium/content/browser/android/string_message_codec.h
+++ b/chromium/content/browser/android/string_message_codec.h
@@ -5,6 +5,7 @@
#ifndef CONTENT_BROWSER_ANDROID_STRING_MESSAGE_CODEC_H_
#define CONTENT_BROWSER_ANDROID_STRING_MESSAGE_CODEC_H_
+#include <vector>
#include "base/strings/string16.h"
#include "content/common/content_export.h"
@@ -20,10 +21,12 @@ namespace content {
// handle string messages and this serialization format is static, as it is a
// format we currently persist to disk via IndexedDB.
-CONTENT_EXPORT base::string16 EncodeStringMessage(const base::string16& data);
+CONTENT_EXPORT std::vector<uint8_t> EncodeStringMessage(
+ const base::string16& data);
-CONTENT_EXPORT bool DecodeStringMessage(const base::string16& encoded_data,
- base::string16* result);
+CONTENT_EXPORT bool DecodeStringMessage(
+ const std::vector<uint8_t>& encoded_data,
+ base::string16* result);
} // namespace content
diff --git a/chromium/content/browser/android/string_message_codec_unittest.cc b/chromium/content/browser/android/string_message_codec_unittest.cc
index fc3e2c31c86..d32233e30ab 100644
--- a/chromium/content/browser/android/string_message_codec_unittest.cc
+++ b/chromium/content/browser/android/string_message_codec_unittest.cc
@@ -5,15 +5,15 @@
#include "content/browser/android/string_message_codec.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/test/scoped_async_task_scheduler.h"
+#include "base/test/scoped_task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "v8/include/v8.h"
namespace content {
namespace {
-base::string16 DecodeWithV8(const base::string16& encoded) {
- base::test::ScopedAsyncTaskScheduler task_scheduler;
+base::string16 DecodeWithV8(const std::vector<uint8_t>& encoded) {
+ base::test::ScopedTaskEnvironment scoped_task_environment;
base::string16 result;
v8::Isolate::CreateParams params;
@@ -26,10 +26,7 @@ base::string16 DecodeWithV8(const base::string16& encoded) {
v8::Local<v8::Context> context = v8::Context::New(isolate);
- v8::ValueDeserializer deserializer(
- isolate,
- reinterpret_cast<const uint8_t*>(encoded.data()),
- encoded.size() * sizeof(base::char16));
+ v8::ValueDeserializer deserializer(isolate, encoded.data(), encoded.size());
deserializer.SetSupportsLegacyWireFormat(true);
EXPECT_TRUE(deserializer.ReadHeader(context).ToChecked());
@@ -47,9 +44,9 @@ base::string16 DecodeWithV8(const base::string16& encoded) {
return result;
}
-base::string16 EncodeWithV8(const base::string16& message) {
- base::test::ScopedAsyncTaskScheduler task_scheduler;
- base::string16 result;
+std::vector<uint8_t> EncodeWithV8(const base::string16& message) {
+ base::test::ScopedTaskEnvironment scoped_task_environment;
+ std::vector<uint8_t> result;
v8::Isolate::CreateParams params;
params.array_buffer_allocator =
@@ -72,11 +69,7 @@ base::string16 EncodeWithV8(const base::string16& message) {
EXPECT_TRUE(serializer.WriteValue(context, message_as_value).ToChecked());
std::pair<uint8_t*, size_t> buffer = serializer.Release();
-
- size_t result_num_bytes = (buffer.second + 1) & ~1;
- result.resize(result_num_bytes / 2);
- memcpy(reinterpret_cast<uint8_t*>(&result[0]), buffer.first, buffer.second);
-
+ result = std::vector<uint8_t>(buffer.first, buffer.first + buffer.second);
free(buffer.first);
}
isolate->Dispose();
diff --git a/chromium/content/browser/android/synchronous_compositor_host.cc b/chromium/content/browser/android/synchronous_compositor_host.cc
index dd086115828..00ad2f486ab 100644
--- a/chromium/content/browser/android/synchronous_compositor_host.cc
+++ b/chromium/content/browser/android/synchronous_compositor_host.cc
@@ -314,7 +314,7 @@ void SynchronousCompositorHost::SendZeroMemory() {
void SynchronousCompositorHost::ReturnResources(
uint32_t layer_tree_frame_sink_id,
- const std::vector<cc::ReturnedResource>& resources) {
+ const std::vector<viz::ReturnedResource>& resources) {
DCHECK(!resources.empty());
sender_->Send(new SyncCompositorMsg_ReclaimResources(
routing_id_, layer_tree_frame_sink_id, resources));
diff --git a/chromium/content/browser/android/synchronous_compositor_host.h b/chromium/content/browser/android/synchronous_compositor_host.h
index 53d6a546c0f..12dfc9f6db4 100644
--- a/chromium/content/browser/android/synchronous_compositor_host.h
+++ b/chromium/content/browser/android/synchronous_compositor_host.h
@@ -56,7 +56,7 @@ class SynchronousCompositorHost : public SynchronousCompositor {
bool DemandDrawSw(SkCanvas* canvas) override;
void ReturnResources(
uint32_t layer_tree_frame_sink_id,
- const std::vector<cc::ReturnedResource>& resources) override;
+ const std::vector<viz::ReturnedResource>& resources) override;
void SetMemoryPolicy(size_t bytes_limit) override;
void DidChangeRootLayerScrollOffset(
const gfx::ScrollOffset& root_offset) override;
diff --git a/chromium/content/browser/android/text_suggestion_host_android.cc b/chromium/content/browser/android/text_suggestion_host_android.cc
new file mode 100644
index 00000000000..24c647ffa8f
--- /dev/null
+++ b/chromium/content/browser/android/text_suggestion_host_android.cc
@@ -0,0 +1,198 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/android/text_suggestion_host_android.h"
+
+#include "base/android/jni_android.h"
+#include "base/android/jni_array.h"
+#include "base/android/jni_string.h"
+#include "content/browser/android/text_suggestion_host_mojo_impl_android.h"
+#include "content/browser/renderer_host/render_widget_host_impl.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/web_contents.h"
+#include "jni/TextSuggestionHost_jni.h"
+#include "services/service_manager/public/cpp/interface_provider.h"
+#include "ui/gfx/android/view_configuration.h"
+
+using base::android::AttachCurrentThread;
+using base::android::ConvertUTF8ToJavaString;
+using base::android::JavaParamRef;
+using base::android::ScopedJavaLocalRef;
+using base::android::ToJavaArrayOfStrings;
+
+namespace content {
+
+jlong 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);
+ 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)),
+ spellcheck_menu_timeout_(
+ base::Bind(&TextSuggestionHostAndroid::OnSpellCheckMenuTimeout,
+ base::Unretained(this))) {
+ registry_.AddInterface(base::Bind(&TextSuggestionHostMojoImplAndroid::Create,
+ base::Unretained(this)));
+}
+
+TextSuggestionHostAndroid::~TextSuggestionHostAndroid() {
+ JNIEnv* env = AttachCurrentThread();
+ ScopedJavaLocalRef<jobject> obj = java_text_suggestion_host_.get(env);
+ if (!obj.is_null())
+ Java_TextSuggestionHost_destroy(env, obj);
+}
+
+void TextSuggestionHostAndroid::UpdateRenderProcessConnection(
+ RenderWidgetHostViewAndroid* old_rwhva,
+ RenderWidgetHostViewAndroid* new_rwhva) {
+ text_suggestion_backend_ = nullptr;
+ if (old_rwhva)
+ old_rwhva->set_text_suggestion_host(nullptr);
+ if (new_rwhva)
+ new_rwhva->set_text_suggestion_host(this);
+ rwhva_ = new_rwhva;
+}
+
+void TextSuggestionHostAndroid::ApplySpellCheckSuggestion(
+ JNIEnv* env,
+ const JavaParamRef<jobject>&,
+ const base::android::JavaParamRef<jstring>& replacement) {
+ const blink::mojom::TextSuggestionBackendPtr& text_suggestion_backend =
+ GetTextSuggestionBackend();
+ if (!text_suggestion_backend)
+ return;
+ text_suggestion_backend->ApplySpellCheckSuggestion(
+ ConvertJavaStringToUTF8(env, replacement));
+}
+
+void TextSuggestionHostAndroid::DeleteActiveSuggestionRange(
+ JNIEnv*,
+ const JavaParamRef<jobject>&) {
+ const blink::mojom::TextSuggestionBackendPtr& text_suggestion_backend =
+ GetTextSuggestionBackend();
+ if (!text_suggestion_backend)
+ return;
+ text_suggestion_backend->DeleteActiveSuggestionRange();
+}
+
+void TextSuggestionHostAndroid::NewWordAddedToDictionary(
+ JNIEnv* env,
+ const JavaParamRef<jobject>&,
+ const base::android::JavaParamRef<jstring>& word) {
+ const blink::mojom::TextSuggestionBackendPtr& text_suggestion_backend =
+ GetTextSuggestionBackend();
+ if (!text_suggestion_backend)
+ return;
+ text_suggestion_backend->NewWordAddedToDictionary(
+ ConvertJavaStringToUTF8(env, word));
+}
+
+void TextSuggestionHostAndroid::SuggestionMenuClosed(
+ JNIEnv*,
+ const JavaParamRef<jobject>&) {
+ const blink::mojom::TextSuggestionBackendPtr& text_suggestion_backend =
+ GetTextSuggestionBackend();
+ if (!text_suggestion_backend)
+ return;
+ text_suggestion_backend->SuggestionMenuClosed();
+}
+
+void TextSuggestionHostAndroid::ShowSpellCheckSuggestionMenu(
+ double caret_x,
+ double caret_y,
+ const std::string& marked_text,
+ const std::vector<blink::mojom::SpellCheckSuggestionPtr>& suggestions) {
+ std::vector<std::string> suggestion_strings;
+ for (const auto& suggestion_ptr : suggestions)
+ suggestion_strings.push_back(suggestion_ptr->suggestion);
+ JNIEnv* env = AttachCurrentThread();
+ ScopedJavaLocalRef<jobject> obj = java_text_suggestion_host_.get(env);
+ if (obj.is_null())
+ return;
+
+ Java_TextSuggestionHost_showSpellCheckSuggestionMenu(
+ env, obj, caret_x, caret_y, ConvertUTF8ToJavaString(env, marked_text),
+ ToJavaArrayOfStrings(env, suggestion_strings));
+}
+
+void TextSuggestionHostAndroid::StartSpellCheckMenuTimer() {
+ spellcheck_menu_timeout_.Stop();
+ spellcheck_menu_timeout_.Start(base::TimeDelta::FromMilliseconds(
+ gfx::ViewConfiguration::GetDoubleTapTimeoutInMs()));
+}
+
+void TextSuggestionHostAndroid::OnKeyEvent() {
+ spellcheck_menu_timeout_.Stop();
+
+ JNIEnv* env = AttachCurrentThread();
+ ScopedJavaLocalRef<jobject> obj = java_text_suggestion_host_.get(env);
+ if (obj.is_null())
+ return;
+
+ Java_TextSuggestionHost_hidePopups(env, obj);
+}
+
+void TextSuggestionHostAndroid::StopSpellCheckMenuTimer() {
+ spellcheck_menu_timeout_.Stop();
+}
+
+void TextSuggestionHostAndroid::OnInterfaceRequestFromFrame(
+ content::RenderFrameHost* render_frame_host,
+ const std::string& interface_name,
+ mojo::ScopedMessagePipeHandle* interface_pipe) {
+ registry_.TryBindInterface(interface_name, interface_pipe);
+}
+
+RenderFrameHost* TextSuggestionHostAndroid::GetFocusedFrame() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ // We get the focused frame from the WebContents of the page. Although
+ // |rwhva_->GetFocusedWidget()| does a similar thing, there is no direct way
+ // to get a RenderFrameHost from its RWH.
+ if (!rwhva_)
+ return nullptr;
+ RenderWidgetHostImpl* rwh =
+ RenderWidgetHostImpl::From(rwhva_->GetRenderWidgetHost());
+ if (!rwh || !rwh->delegate())
+ return nullptr;
+
+ if (auto* contents = rwh->delegate()->GetAsWebContents())
+ return contents->GetFocusedFrame();
+
+ return nullptr;
+}
+
+const blink::mojom::TextSuggestionBackendPtr&
+TextSuggestionHostAndroid::GetTextSuggestionBackend() {
+ if (!text_suggestion_backend_) {
+ if (RenderFrameHost* rfh = GetFocusedFrame()) {
+ rfh->GetRemoteInterfaces()->GetInterface(
+ mojo::MakeRequest(&text_suggestion_backend_));
+ }
+ }
+ return text_suggestion_backend_;
+}
+
+void TextSuggestionHostAndroid::OnSpellCheckMenuTimeout() {
+ const blink::mojom::TextSuggestionBackendPtr& text_suggestion_backend =
+ GetTextSuggestionBackend();
+ if (!text_suggestion_backend)
+ return;
+ text_suggestion_backend->SpellCheckMenuTimeoutCallback();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/android/text_suggestion_host_android.h b/chromium/content/browser/android/text_suggestion_host_android.h
new file mode 100644
index 00000000000..61435ef2726
--- /dev/null
+++ b/chromium/content/browser/android/text_suggestion_host_android.h
@@ -0,0 +1,100 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_ANDROID_TEXT_SUGGESTION_HOST_ANDROID_H_
+#define CONTENT_BROWSER_ANDROID_TEXT_SUGGESTION_HOST_ANDROID_H_
+
+#include "content/browser/android/render_widget_host_connector.h"
+#include "content/browser/renderer_host/input/timeout_monitor.h"
+#include "services/service_manager/public/cpp/binder_registry.h"
+#include "third_party/WebKit/public/platform/input_host.mojom.h"
+#include "third_party/WebKit/public/platform/input_messages.mojom.h"
+
+namespace content {
+
+// This class, along with its Java counterpart TextSuggestionHost, is used to
+// implement the Android text suggestion menu that appears when you tap a
+// 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).
+class TextSuggestionHostAndroid : public RenderWidgetHostConnector,
+ public WebContentsObserver {
+ public:
+ TextSuggestionHostAndroid(JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj,
+ WebContents* web_contents);
+ ~TextSuggestionHostAndroid() override;
+
+ // RenderWidgetHostConnector implementation.
+ void UpdateRenderProcessConnection(
+ RenderWidgetHostViewAndroid* old_rwhva,
+ RenderWidgetHostViewAndroid* new_rhwva) override;
+
+ // Called from the Java text suggestion menu to have Blink apply a spell
+ // check suggestion.
+ void ApplySpellCheckSuggestion(
+ JNIEnv*,
+ const base::android::JavaParamRef<jobject>&,
+ const base::android::JavaParamRef<jstring>& replacement);
+ // Called from the Java text suggestion menu to have Blink delete the
+ // currently highlighted region of text that the open suggestion menu pertains
+ // to.
+ void DeleteActiveSuggestionRange(JNIEnv*,
+ const base::android::JavaParamRef<jobject>&);
+ // Called from the Java text suggestion menu to tell Blink that a word is
+ // being added to the dictionary (so Blink can clear the spell check markers
+ // for that word).
+ void NewWordAddedToDictionary(
+ JNIEnv*,
+ const base::android::JavaParamRef<jobject>&,
+ const base::android::JavaParamRef<jstring>& word);
+ // Called from the Java text suggestion menu to tell Blink that the user
+ // closed the menu without performing one of the available actions, so Blink
+ // can re-show the insertion caret and remove the suggestion range highlight.
+ void SuggestionMenuClosed(JNIEnv*,
+ const base::android::JavaParamRef<jobject>&);
+ // Called from Blink to tell the Java TextSuggestionHost to open the text
+ // suggestion menu.
+ void ShowSpellCheckSuggestionMenu(
+ double caret_x,
+ double caret_y,
+ const std::string& marked_text,
+ const std::vector<blink::mojom::SpellCheckSuggestionPtr>& suggestions);
+
+ // Called by browser-side code in response to an input event to stop the
+ // spell check menu timer and close the suggestion menu (if open).
+ void OnKeyEvent();
+ // Called by Blink when the user taps on a spell check marker and we might
+ // want to show the text suggestion menu after the double-tap timer expires.
+ void StartSpellCheckMenuTimer();
+ // Called by browser-side code in response to an input event to stop the
+ // spell check menu timer.
+ void StopSpellCheckMenuTimer();
+
+ // WebContentsObserver overrides
+ void OnInterfaceRequestFromFrame(
+ content::RenderFrameHost* render_frame_host,
+ const std::string& interface_name,
+ mojo::ScopedMessagePipeHandle* interface_pipe) override;
+
+ private:
+ RenderFrameHost* GetFocusedFrame();
+ const blink::mojom::TextSuggestionBackendPtr& GetTextSuggestionBackend();
+ // Used by the spell check menu timer to notify Blink that the timer has
+ // expired.
+ void OnSpellCheckMenuTimeout();
+
+ service_manager::BinderRegistry registry_;
+ // Current RenderWidgetHostView connected to this instance. Can be null.
+ RenderWidgetHostViewAndroid* rwhva_;
+ JavaObjectWeakGlobalRef java_text_suggestion_host_;
+ blink::mojom::TextSuggestionBackendPtr text_suggestion_backend_;
+ TimeoutMonitor spellcheck_menu_timeout_;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_ANDROID_TEXT_SUGGESTION_HOST_ANDROID_H_
diff --git a/chromium/content/browser/android/text_suggestion_host_mojo_impl_android.cc b/chromium/content/browser/android/text_suggestion_host_mojo_impl_android.cc
new file mode 100644
index 00000000000..6510499ce28
--- /dev/null
+++ b/chromium/content/browser/android/text_suggestion_host_mojo_impl_android.cc
@@ -0,0 +1,38 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/android/text_suggestion_host_mojo_impl_android.h"
+
+#include "content/browser/android/text_suggestion_host_android.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
+
+namespace content {
+
+TextSuggestionHostMojoImplAndroid::TextSuggestionHostMojoImplAndroid(
+ TextSuggestionHostAndroid* text_suggestion_host)
+ : text_suggestion_host_(text_suggestion_host) {}
+
+// static
+void TextSuggestionHostMojoImplAndroid::Create(
+ TextSuggestionHostAndroid* text_suggestion_host,
+ blink::mojom::TextSuggestionHostRequest request) {
+ mojo::MakeStrongBinding(
+ base::MakeUnique<TextSuggestionHostMojoImplAndroid>(text_suggestion_host),
+ std::move(request));
+}
+
+void TextSuggestionHostMojoImplAndroid::StartSpellCheckMenuTimer() {
+ text_suggestion_host_->StartSpellCheckMenuTimer();
+}
+
+void TextSuggestionHostMojoImplAndroid::ShowSpellCheckSuggestionMenu(
+ double caret_x,
+ double caret_y,
+ const std::string& marked_text,
+ std::vector<blink::mojom::SpellCheckSuggestionPtr> suggestions) {
+ text_suggestion_host_->ShowSpellCheckSuggestionMenu(caret_x, caret_y,
+ marked_text, suggestions);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/android/text_suggestion_host_mojo_impl_android.h b/chromium/content/browser/android/text_suggestion_host_mojo_impl_android.h
new file mode 100644
index 00000000000..4281948ea72
--- /dev/null
+++ b/chromium/content/browser/android/text_suggestion_host_mojo_impl_android.h
@@ -0,0 +1,39 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_ANDROID_TEXT_SUGGESTION_HOST_MOJO_IMPL_ANDROID_H_
+#define CONTENT_BROWSER_ANDROID_TEXT_SUGGESTION_HOST_MOJO_IMPL_ANDROID_H_
+
+#include "third_party/WebKit/public/platform/input_host.mojom.h"
+
+namespace content {
+
+class TextSuggestionHostAndroid;
+
+// Android implementation of mojom::TextSuggestionHost.
+class TextSuggestionHostMojoImplAndroid final
+ : public blink::mojom::TextSuggestionHost {
+ public:
+ explicit TextSuggestionHostMojoImplAndroid(TextSuggestionHostAndroid*);
+
+ static void Create(TextSuggestionHostAndroid*,
+ blink::mojom::TextSuggestionHostRequest request);
+
+ void StartSpellCheckMenuTimer() final;
+
+ void ShowSpellCheckSuggestionMenu(
+ double caret_x,
+ double caret_y,
+ const std::string& marked_text,
+ std::vector<blink::mojom::SpellCheckSuggestionPtr> suggestions) final;
+
+ private:
+ TextSuggestionHostAndroid* const text_suggestion_host_;
+
+ DISALLOW_COPY_AND_ASSIGN(TextSuggestionHostMojoImplAndroid);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_ANDROID_TEXT_SUGGESTION_HOST_MOJO_IMPL_ANDROID_H_
diff --git a/chromium/content/browser/android/tracing_controller_android.cc b/chromium/content/browser/android/tracing_controller_android.cc
index 41df1ae3f0b..a6a3f6ae817 100644
--- a/chromium/content/browser/android/tracing_controller_android.cc
+++ b/chromium/content/browser/android/tracing_controller_android.cc
@@ -117,8 +117,4 @@ static ScopedJavaLocalRef<jstring> GetDefaultCategories(
env, trace_config.ToCategoryFilterString());
}
-bool RegisterTracingControllerAndroid(JNIEnv* env) {
- return RegisterNativesImpl(env);
-}
-
} // namespace content
diff --git a/chromium/content/browser/android/tracing_controller_android.h b/chromium/content/browser/android/tracing_controller_android.h
index 77f6144f2e0..98b7d3997c6 100644
--- a/chromium/content/browser/android/tracing_controller_android.h
+++ b/chromium/content/browser/android/tracing_controller_android.h
@@ -44,9 +44,6 @@ class TracingControllerAndroid {
DISALLOW_COPY_AND_ASSIGN(TracingControllerAndroid);
};
-// Register this class's native methods through jni.
-bool RegisterTracingControllerAndroid(JNIEnv* env);
-
} // namespace content
#endif // CONTENT_BROWSER_ANDROID_TRACING_CONTROLLER_ANDROID_H_
diff --git a/chromium/content/browser/android/web_contents_observer_proxy.cc b/chromium/content/browser/android/web_contents_observer_proxy.cc
index feaa3312573..4e584bb4a3c 100644
--- a/chromium/content/browser/android/web_contents_observer_proxy.cc
+++ b/chromium/content/browser/android/web_contents_observer_proxy.cc
@@ -108,8 +108,7 @@ void WebContentsObserverProxy::DidFailLoad(
RenderFrameHost* render_frame_host,
const GURL& validated_url,
int error_code,
- const base::string16& error_description,
- bool was_ignored_by_handler) {
+ const base::string16& error_description) {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj(java_observer_);
ScopedJavaLocalRef<jstring> jstring_error_description(
@@ -159,7 +158,8 @@ void WebContentsObserverProxy::DidFinishNavigation(
}
// TODO(shaktisahu): Provide appropriate error description (crbug/690784).
- ScopedJavaLocalRef<jstring> jerror_description;
+ ScopedJavaLocalRef<jstring> jerror_description =
+ ConvertUTF8ToJavaString(env, "");
Java_WebContentsObserverProxy_didFinishNavigation(
env, obj, jstring_url, navigation_handle->IsInMainFrame(),
@@ -269,7 +269,4 @@ void WebContentsObserverProxy::SetToBaseURLForDataURLIfNeeded(
}
}
-bool RegisterWebContentsObserverProxy(JNIEnv* env) {
- return RegisterNativesImpl(env);
-}
} // 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 6b07f60fe09..3cc7e304359 100644
--- a/chromium/content/browser/android/web_contents_observer_proxy.h
+++ b/chromium/content/browser/android/web_contents_observer_proxy.h
@@ -37,8 +37,7 @@ class WebContentsObserverProxy : public WebContentsObserver {
void DidFailLoad(RenderFrameHost* render_frame_host,
const GURL& validated_url,
int error_code,
- const base::string16& error_description,
- bool was_ignored_by_handler) override;
+ const base::string16& error_description) override;
void DocumentAvailableInMainFrame() override;
void DidFirstVisuallyNonEmptyPaint() override;
void WasShown() override;
@@ -65,7 +64,6 @@ class WebContentsObserverProxy : public WebContentsObserver {
DISALLOW_COPY_AND_ASSIGN(WebContentsObserverProxy);
};
-bool RegisterWebContentsObserverProxy(JNIEnv* env);
} // namespace content
#endif // CONTENT_BROWSER_ANDROID_WEB_CONTENTS_OBSERVER_PROXY_H_
diff --git a/chromium/content/browser/appcache/appcache_backend_impl.cc b/chromium/content/browser/appcache/appcache_backend_impl.cc
index c07951504d1..0c30e74dbaa 100644
--- a/chromium/content/browser/appcache/appcache_backend_impl.cc
+++ b/chromium/content/browser/appcache/appcache_backend_impl.cc
@@ -99,33 +99,36 @@ bool AppCacheBackendImpl::MarkAsForeignEntry(
return host->MarkAsForeignEntry(document_url, cache_document_was_loaded_from);
}
-bool AppCacheBackendImpl::GetStatusWithCallback(
- int host_id, const GetStatusCallback& callback, void* callback_param) {
+bool AppCacheBackendImpl::GetStatusWithCallback(int host_id,
+ GetStatusCallback callback,
+ void* callback_param) {
AppCacheHost* host = GetHost(host_id);
if (!host)
return false;
- host->GetStatusWithCallback(callback, callback_param);
+ host->GetStatusWithCallback(std::move(callback), callback_param);
return true;
}
-bool AppCacheBackendImpl::StartUpdateWithCallback(
- int host_id, const StartUpdateCallback& callback, void* callback_param) {
+bool AppCacheBackendImpl::StartUpdateWithCallback(int host_id,
+ StartUpdateCallback callback,
+ void* callback_param) {
AppCacheHost* host = GetHost(host_id);
if (!host)
return false;
- host->StartUpdateWithCallback(callback, callback_param);
+ host->StartUpdateWithCallback(std::move(callback), callback_param);
return true;
}
-bool AppCacheBackendImpl::SwapCacheWithCallback(
- int host_id, const SwapCacheCallback& callback, void* callback_param) {
+bool AppCacheBackendImpl::SwapCacheWithCallback(int host_id,
+ SwapCacheCallback callback,
+ void* callback_param) {
AppCacheHost* host = GetHost(host_id);
if (!host)
return false;
- host->SwapCacheWithCallback(callback, callback_param);
+ host->SwapCacheWithCallback(std::move(callback), callback_param);
return true;
}
diff --git a/chromium/content/browser/appcache/appcache_backend_impl.h b/chromium/content/browser/appcache/appcache_backend_impl.h
index 83e64632cc6..bb89020120e 100644
--- a/chromium/content/browser/appcache/appcache_backend_impl.h
+++ b/chromium/content/browser/appcache/appcache_backend_impl.h
@@ -44,11 +44,14 @@ class CONTENT_EXPORT AppCacheBackendImpl {
bool MarkAsForeignEntry(int host_id,
const GURL& document_url,
int64_t cache_document_was_loaded_from);
- bool GetStatusWithCallback(int host_id, const GetStatusCallback& callback,
+ bool GetStatusWithCallback(int host_id,
+ GetStatusCallback callback,
void* callback_param);
- bool StartUpdateWithCallback(int host_id, const StartUpdateCallback& callback,
+ bool StartUpdateWithCallback(int host_id,
+ StartUpdateCallback callback,
void* callback_param);
- bool SwapCacheWithCallback(int host_id, const SwapCacheCallback& callback,
+ bool SwapCacheWithCallback(int host_id,
+ SwapCacheCallback callback,
void* callback_param);
// Returns a pointer to a registered host. The backend retains ownership.
diff --git a/chromium/content/browser/appcache/appcache_browsertest.cc b/chromium/content/browser/appcache/appcache_browsertest.cc
new file mode 100644
index 00000000000..b1dd1f393d1
--- /dev/null
+++ b/chromium/content/browser/appcache/appcache_browsertest.cc
@@ -0,0 +1,107 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <stdint.h>
+
+#include "base/command_line.h"
+#include "base/strings/utf_string_conversions.h"
+#include "build/build_config.h"
+#include "content/browser/appcache/appcache_subresource_url_factory.h"
+#include "content/public/common/content_features.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
+#include "content/public/test/test_navigation_observer.h"
+#include "content/public/test/test_utils.h"
+#include "content/shell/browser/shell.h"
+#include "net/dns/mock_host_resolver.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "net/test/embedded_test_server/http_request.h"
+#include "net/test/embedded_test_server/http_response.h"
+namespace content {
+
+// This class currently enables the network service feature, which allows us to
+// test the AppCache code in that mode.
+class AppCacheNetworkServiceBrowserTest : public ContentBrowserTest {
+ public:
+ AppCacheNetworkServiceBrowserTest() {}
+
+ // Handler to count the number of requests.
+ std::unique_ptr<net::test_server::HttpResponse> HandleRequest(
+ const net::test_server::HttpRequest& request) {
+ request_count_++;
+ return std::unique_ptr<net::test_server::HttpResponse>();
+ }
+
+ // Call this to reset the request_count_.
+ void Clear() { request_count_ = 0; }
+
+ int request_count() const { return request_count_; }
+
+ protected:
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ command_line->AppendSwitchASCII(switches::kEnableFeatures,
+ features::kNetworkService.name);
+ }
+
+ private:
+ // Tracks the number of requests.
+ int request_count_ = 0;
+
+ DISALLOW_COPY_AND_ASSIGN(AppCacheNetworkServiceBrowserTest);
+};
+
+// The network service process launch DCHECK's on Android. The bug
+// here http://crbug.com/748764. It looks like unsandboxed utility
+// processes are not supported on Android.
+#if !defined(OS_ANDROID)
+// This test validates that navigating to a TLD which has an AppCache
+// associated with it and then navigating to another TLD within that
+// host clears the previously registered factory. We verify this by
+// validating that request count for the last navigation.
+IN_PROC_BROWSER_TEST_F(AppCacheNetworkServiceBrowserTest,
+ VerifySubresourceFactoryClearedOnNewNavigation) {
+ std::unique_ptr<net::EmbeddedTestServer> embedded_test_server(
+ new net::EmbeddedTestServer());
+
+ embedded_test_server->RegisterRequestHandler(
+ base::Bind(&AppCacheNetworkServiceBrowserTest::HandleRequest,
+ base::Unretained(this)));
+
+ base::FilePath content_test_data(FILE_PATH_LITERAL("content/test/data"));
+ embedded_test_server->AddDefaultHandlers(content_test_data);
+
+ ASSERT_TRUE(embedded_test_server->Start());
+
+ GURL main_url =
+ embedded_test_server->GetURL("/appcache/simple_page_with_manifest.html");
+
+ base::string16 expected_title = base::ASCIIToUTF16("AppCache updated");
+ TitleWatcher title_watcher(shell()->web_contents(), expected_title);
+
+ // Load the main page twice. The second navigation should have AppCache
+ // initialized for the page.
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+ EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
+
+ TestNavigationObserver observer(shell()->web_contents());
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+ EXPECT_EQ(main_url, observer.last_navigation_url());
+ EXPECT_TRUE(observer.last_navigation_succeeded());
+
+ Clear();
+ GURL page_no_manifest =
+ embedded_test_server->GetURL("/appcache/simple_page_no_manifest.html");
+
+ EXPECT_TRUE(NavigateToURL(shell(), page_no_manifest));
+ // We expect two requests for simple_page_no_manifest.html. The request
+ // for the main page and the logo.
+ EXPECT_GT(request_count(), 1);
+ EXPECT_EQ(page_no_manifest, observer.last_navigation_url());
+ EXPECT_TRUE(observer.last_navigation_succeeded());
+}
+#endif
+
+} // namespace content \ No newline at end of file
diff --git a/chromium/content/browser/appcache/appcache_disk_cache.cc b/chromium/content/browser/appcache/appcache_disk_cache.cc
index 16dbe751ef2..66dba6fc372 100644
--- a/chromium/content/browser/appcache/appcache_disk_cache.cc
+++ b/chromium/content/browser/appcache/appcache_disk_cache.cc
@@ -220,20 +220,16 @@ int AppCacheDiskCache::InitWithDiskBackend(
const base::FilePath& disk_cache_directory,
int disk_cache_size,
bool force,
- const scoped_refptr<base::SingleThreadTaskRunner>& cache_thread,
+ base::OnceClosure post_cleanup_callback,
const net::CompletionCallback& callback) {
- return Init(net::APP_CACHE,
- disk_cache_directory,
- disk_cache_size,
- force,
- cache_thread,
- callback);
+ return Init(net::APP_CACHE, disk_cache_directory, disk_cache_size, force,
+ std::move(post_cleanup_callback), callback);
}
int AppCacheDiskCache::InitWithMemBackend(
int mem_cache_size, const net::CompletionCallback& callback) {
- return Init(net::MEMORY_CACHE, base::FilePath(), mem_cache_size, false, NULL,
- callback);
+ return Init(net::MEMORY_CACHE, base::FilePath(), mem_cache_size, false,
+ base::OnceClosure(), callback);
}
void AppCacheDiskCache::Disable() {
@@ -340,13 +336,12 @@ AppCacheDiskCache::PendingCall::PendingCall(const PendingCall& other) = default;
AppCacheDiskCache::PendingCall::~PendingCall() {}
-int AppCacheDiskCache::Init(
- net::CacheType cache_type,
- const base::FilePath& cache_directory,
- int cache_size,
- bool force,
- const scoped_refptr<base::SingleThreadTaskRunner>& cache_thread,
- const net::CompletionCallback& callback) {
+int AppCacheDiskCache::Init(net::CacheType cache_type,
+ const base::FilePath& cache_directory,
+ int cache_size,
+ bool force,
+ base::OnceClosure post_cleanup_callback,
+ const net::CompletionCallback& callback) {
DCHECK(!is_initializing_or_waiting_to_initialize() && !disk_cache_.get());
is_disabled_ = false;
create_backend_callback_ = new CreateBackendCallbackShim(this);
@@ -355,12 +350,9 @@ int AppCacheDiskCache::Init(
cache_type,
use_simple_cache_ ? net::CACHE_BACKEND_SIMPLE
: net::CACHE_BACKEND_DEFAULT,
- cache_directory,
- cache_size,
- force,
- cache_thread,
- NULL,
+ cache_directory, cache_size, force, NULL,
&(create_backend_callback_->backend_ptr_),
+ std::move(post_cleanup_callback),
base::Bind(&CreateBackendCallbackShim::Callback,
create_backend_callback_));
if (rv == net::ERR_IO_PENDING)
diff --git a/chromium/content/browser/appcache/appcache_disk_cache.h b/chromium/content/browser/appcache/appcache_disk_cache.h
index b5d67eb8b13..876e8ec9db5 100644
--- a/chromium/content/browser/appcache/appcache_disk_cache.h
+++ b/chromium/content/browser/appcache/appcache_disk_cache.h
@@ -11,15 +11,12 @@
#include <set>
#include <vector>
+#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/disk_cache/disk_cache.h"
-namespace base {
-class SingleThreadTaskRunner;
-} // namespace base
-
namespace content {
// An implementation of AppCacheDiskCacheInterface that
@@ -31,12 +28,11 @@ class CONTENT_EXPORT AppCacheDiskCache
~AppCacheDiskCache() override;
// Initializes the object to use disk backed storage.
- int InitWithDiskBackend(
- const base::FilePath& disk_cache_directory,
- int disk_cache_size,
- bool force,
- const scoped_refptr<base::SingleThreadTaskRunner>& cache_thread,
- const net::CompletionCallback& callback);
+ int InitWithDiskBackend(const base::FilePath& disk_cache_directory,
+ int disk_cache_size,
+ bool force,
+ base::OnceClosure post_cleanup_callback,
+ const net::CompletionCallback& callback);
// Initializes the object to use memory only storage.
// This is used for Chrome's incognito browsing.
@@ -107,7 +103,7 @@ class CONTENT_EXPORT AppCacheDiskCache
const base::FilePath& directory,
int cache_size,
bool force,
- const scoped_refptr<base::SingleThreadTaskRunner>& cache_thread,
+ base::OnceClosure post_cleanup_callback,
const net::CompletionCallback& callback);
void OnCreateBackendComplete(int rv);
void AddOpenEntry(EntryImpl* entry) { open_entries_.insert(entry); }
diff --git a/chromium/content/browser/appcache/appcache_disk_cache_unittest.cc b/chromium/content/browser/appcache/appcache_disk_cache_unittest.cc
index 5241805330e..f8ef08c912c 100644
--- a/chromium/content/browser/appcache/appcache_disk_cache_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_disk_cache_unittest.cc
@@ -9,9 +9,12 @@
#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 "net/base/io_buffer.h"
#include "net/base/net_errors.h"
+#include "net/base/test_completion_callback.h"
+#include "net/disk_cache/disk_cache.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
@@ -21,31 +24,25 @@ class AppCacheDiskCacheTest : public testing::Test {
AppCacheDiskCacheTest() {}
void SetUp() override {
- // Use the current thread for the DiskCache's cache_thread.
- message_loop_.reset(new base::MessageLoopForIO());
- cache_thread_ = base::ThreadTaskRunnerHandle::Get();
ASSERT_TRUE(directory_.CreateUniqueTempDir());
completion_callback_ = base::Bind(
&AppCacheDiskCacheTest::OnComplete,
base::Unretained(this));
}
- void TearDown() override {
- base::RunLoop().RunUntilIdle();
- message_loop_.reset(NULL);
- }
+ void TearDown() override { scoped_task_environment_.RunUntilIdle(); }
void FlushCacheTasks() {
- base::RunLoop().RunUntilIdle();
+ disk_cache::FlushCacheThreadForTesting();
+ scoped_task_environment_.RunUntilIdle();
}
void OnComplete(int err) {
completion_results_.push_back(err);
}
+ base::test::ScopedTaskEnvironment scoped_task_environment_;
base::ScopedTempDir directory_;
- std::unique_ptr<base::MessageLoop> message_loop_;
- scoped_refptr<base::SingleThreadTaskRunner> cache_thread_;
net::CompletionCallback completion_callback_;
std::vector<int> completion_results_;
@@ -60,7 +57,7 @@ TEST_F(AppCacheDiskCacheTest, DisablePriorToInitCompletion) {
std::unique_ptr<AppCacheDiskCache> disk_cache(new AppCacheDiskCache);
EXPECT_FALSE(disk_cache->is_disabled());
disk_cache->InitWithDiskBackend(directory_.GetPath(), k10MBytes, false,
- cache_thread_, completion_callback_);
+ base::OnceClosure(), completion_callback_);
disk_cache->CreateEntry(1, &entry, completion_callback_);
disk_cache->OpenEntry(2, &entry, completion_callback_);
disk_cache->DoomEntry(3, completion_callback_);
@@ -91,7 +88,7 @@ TEST_F(AppCacheDiskCacheTest, DisableAfterInitted) {
std::unique_ptr<AppCacheDiskCache> disk_cache(new AppCacheDiskCache);
EXPECT_FALSE(disk_cache->is_disabled());
disk_cache->InitWithDiskBackend(directory_.GetPath(), k10MBytes, false,
- cache_thread_, completion_callback_);
+ base::OnceClosure(), completion_callback_);
FlushCacheTasks();
EXPECT_EQ(1u, completion_results_.size());
EXPECT_EQ(net::OK, completion_results_[0]);
@@ -126,7 +123,7 @@ TEST_F(AppCacheDiskCacheTest, DISABLED_DisableWithEntriesOpen) {
std::unique_ptr<AppCacheDiskCache> disk_cache(new AppCacheDiskCache);
EXPECT_FALSE(disk_cache->is_disabled());
disk_cache->InitWithDiskBackend(directory_.GetPath(), k10MBytes, false,
- cache_thread_, completion_callback_);
+ base::OnceClosure(), completion_callback_);
FlushCacheTasks();
EXPECT_EQ(1u, completion_results_.size());
EXPECT_EQ(net::OK, completion_results_[0]);
@@ -182,4 +179,26 @@ TEST_F(AppCacheDiskCacheTest, DISABLED_DisableWithEntriesOpen) {
FlushCacheTasks();
}
+TEST_F(AppCacheDiskCacheTest, CleanupCallback) {
+ // Test that things delete fine when we disable the cache and wait for
+ // the cleanup callback.
+
+ net::TestClosure cleanup_done;
+ net::TestCompletionCallback init_done;
+ std::unique_ptr<AppCacheDiskCache> disk_cache(new AppCacheDiskCache);
+ EXPECT_FALSE(disk_cache->is_disabled());
+ disk_cache->InitWithDiskBackend(directory_.GetPath(), k10MBytes, false,
+ cleanup_done.closure(), init_done.callback());
+ EXPECT_EQ(net::OK, init_done.WaitForResult());
+
+ disk_cache->Disable();
+ cleanup_done.WaitForResult();
+
+ // Ensure the directory can be deleted at this point.
+ EXPECT_TRUE(base::DirectoryExists(directory_.GetPath()));
+ EXPECT_FALSE(base::IsDirectoryEmpty(directory_.GetPath()));
+ EXPECT_TRUE(base::DeleteFile(directory_.GetPath(), true));
+ EXPECT_FALSE(base::DirectoryExists(directory_.GetPath()));
+}
+
} // namespace content
diff --git a/chromium/content/browser/appcache/appcache_dispatcher_host.cc b/chromium/content/browser/appcache/appcache_dispatcher_host.cc
index 37fee0794e6..2aa5137dd2b 100644
--- a/chromium/content/browser/appcache/appcache_dispatcher_host.cc
+++ b/chromium/content/browser/appcache/appcache_dispatcher_host.cc
@@ -31,12 +31,6 @@ void AppCacheDispatcherHost::OnChannelConnected(int32_t peer_pid) {
backend_impl_.Initialize(appcache_service_.get(), &frontend_proxy_,
process_id_);
- get_status_callback_ = base::Bind(&AppCacheDispatcherHost::GetStatusCallback,
- weak_factory_.GetWeakPtr());
- start_update_callback_ = base::Bind(
- &AppCacheDispatcherHost::StartUpdateCallback, weak_factory_.GetWeakPtr());
- swap_cache_callback_ = base::Bind(&AppCacheDispatcherHost::SwapCacheCallback,
- weak_factory_.GetWeakPtr());
}
bool AppCacheDispatcherHost::OnMessageReceived(const IPC::Message& message) {
@@ -169,8 +163,11 @@ void AppCacheDispatcherHost::OnGetStatus(int host_id, IPC::Message* reply_msg) {
pending_reply_msg_.reset(reply_msg);
if (appcache_service_.get()) {
- if (!backend_impl_.GetStatusWithCallback(host_id, get_status_callback_,
- reply_msg)) {
+ if (!backend_impl_.GetStatusWithCallback(
+ host_id,
+ base::BindOnce(&AppCacheDispatcherHost::GetStatusCallback,
+ weak_factory_.GetWeakPtr()),
+ reply_msg)) {
bad_message::ReceivedBadMessage(this, bad_message::ACDH_GET_STATUS);
}
return;
@@ -190,8 +187,11 @@ void AppCacheDispatcherHost::OnStartUpdate(int host_id,
pending_reply_msg_.reset(reply_msg);
if (appcache_service_.get()) {
- if (!backend_impl_.StartUpdateWithCallback(host_id, start_update_callback_,
- reply_msg)) {
+ if (!backend_impl_.StartUpdateWithCallback(
+ host_id,
+ base::BindOnce(&AppCacheDispatcherHost::StartUpdateCallback,
+ weak_factory_.GetWeakPtr()),
+ reply_msg)) {
bad_message::ReceivedBadMessage(this, bad_message::ACDH_START_UPDATE);
}
return;
@@ -210,8 +210,11 @@ void AppCacheDispatcherHost::OnSwapCache(int host_id, IPC::Message* reply_msg) {
pending_reply_msg_.reset(reply_msg);
if (appcache_service_.get()) {
- if (!backend_impl_.SwapCacheWithCallback(host_id, swap_cache_callback_,
- reply_msg)) {
+ if (!backend_impl_.SwapCacheWithCallback(
+ host_id,
+ base::BindOnce(&AppCacheDispatcherHost::SwapCacheCallback,
+ weak_factory_.GetWeakPtr()),
+ reply_msg)) {
bad_message::ReceivedBadMessage(this, bad_message::ACDH_SWAP_CACHE);
}
return;
diff --git a/chromium/content/browser/appcache/appcache_dispatcher_host.h b/chromium/content/browser/appcache/appcache_dispatcher_host.h
index 0b4b16e6bb0..d148276136f 100644
--- a/chromium/content/browser/appcache/appcache_dispatcher_host.h
+++ b/chromium/content/browser/appcache/appcache_dispatcher_host.h
@@ -66,9 +66,6 @@ class AppCacheDispatcherHost : public BrowserMessageFilter {
AppCacheFrontendProxy frontend_proxy_;
AppCacheBackendImpl backend_impl_;
- content::GetStatusCallback get_status_callback_;
- content::StartUpdateCallback start_update_callback_;
- content::SwapCacheCallback swap_cache_callback_;
std::unique_ptr<IPC::Message> pending_reply_msg_;
// The corresponding ChildProcessHost object's id().
diff --git a/chromium/content/browser/appcache/appcache_host.cc b/chromium/content/browser/appcache/appcache_host.cc
index ecfa39ca9a6..2d05e2dfea5 100644
--- a/chromium/content/browser/appcache/appcache_host.cc
+++ b/chromium/content/browser/appcache/appcache_host.cc
@@ -210,13 +210,13 @@ bool AppCacheHost::MarkAsForeignEntry(const GURL& document_url,
return true;
}
-void AppCacheHost::GetStatusWithCallback(const GetStatusCallback& callback,
+void AppCacheHost::GetStatusWithCallback(GetStatusCallback callback,
void* callback_param) {
DCHECK(pending_start_update_callback_.is_null() &&
pending_swap_cache_callback_.is_null() &&
pending_get_status_callback_.is_null());
- pending_get_status_callback_ = callback;
+ pending_get_status_callback_ = std::move(callback);
pending_callback_param_ = callback_param;
if (is_selection_pending())
return;
@@ -227,18 +227,18 @@ void AppCacheHost::GetStatusWithCallback(const GetStatusCallback& callback,
void AppCacheHost::DoPendingGetStatus() {
DCHECK_EQ(false, pending_get_status_callback_.is_null());
- pending_get_status_callback_.Run(GetStatus(), pending_callback_param_);
- pending_get_status_callback_.Reset();
+ std::move(pending_get_status_callback_)
+ .Run(GetStatus(), pending_callback_param_);
pending_callback_param_ = NULL;
}
-void AppCacheHost::StartUpdateWithCallback(const StartUpdateCallback& callback,
+void AppCacheHost::StartUpdateWithCallback(StartUpdateCallback callback,
void* callback_param) {
DCHECK(pending_start_update_callback_.is_null() &&
pending_swap_cache_callback_.is_null() &&
pending_get_status_callback_.is_null());
- pending_start_update_callback_ = callback;
+ pending_start_update_callback_ = std::move(callback);
pending_callback_param_ = callback_param;
if (is_selection_pending())
return;
@@ -259,18 +259,18 @@ void AppCacheHost::DoPendingStartUpdate() {
}
}
- pending_start_update_callback_.Run(success, pending_callback_param_);
- pending_start_update_callback_.Reset();
+ std::move(pending_start_update_callback_)
+ .Run(success, pending_callback_param_);
pending_callback_param_ = NULL;
}
-void AppCacheHost::SwapCacheWithCallback(const SwapCacheCallback& callback,
+void AppCacheHost::SwapCacheWithCallback(SwapCacheCallback callback,
void* callback_param) {
DCHECK(pending_start_update_callback_.is_null() &&
pending_swap_cache_callback_.is_null() &&
pending_get_status_callback_.is_null());
- pending_swap_cache_callback_ = callback;
+ pending_swap_cache_callback_ = std::move(callback);
pending_callback_param_ = callback_param;
if (is_selection_pending())
return;
@@ -295,8 +295,7 @@ void AppCacheHost::DoPendingSwapCache() {
}
}
- pending_swap_cache_callback_.Run(success, pending_callback_param_);
- pending_swap_cache_callback_.Reset();
+ std::move(pending_swap_cache_callback_).Run(success, pending_callback_param_);
pending_callback_param_ = NULL;
}
@@ -332,7 +331,7 @@ std::unique_ptr<AppCacheRequestHandler> AppCacheHost::CreateRequestHandler(
if (AppCacheRequestHandler::IsMainResourceType(resource_type)) {
// Store the first party origin so that it can be used later in SelectCache
// for checking whether the creation of the appcache is allowed.
- first_party_url_ = request->GetFirstPartyForCookies();
+ first_party_url_ = request->GetSiteForCookies();
return base::WrapUnique(new AppCacheRequestHandler(
this, resource_type, should_reset_appcache, std::move(request)));
}
diff --git a/chromium/content/browser/appcache/appcache_host.h b/chromium/content/browser/appcache/appcache_host.h
index 2cbf4353318..afb06ccc489 100644
--- a/chromium/content/browser/appcache/appcache_host.h
+++ b/chromium/content/browser/appcache/appcache_host.h
@@ -52,9 +52,9 @@ class AppCacheStorageImplTest;
class AppCacheTest;
class AppCacheUpdateJobTest;
-typedef base::Callback<void(AppCacheStatus, void*)> GetStatusCallback;
-typedef base::Callback<void(bool, void*)> StartUpdateCallback;
-typedef base::Callback<void(bool, void*)> SwapCacheCallback;
+typedef base::OnceCallback<void(AppCacheStatus, void*)> GetStatusCallback;
+typedef base::OnceCallback<void(bool, void*)> StartUpdateCallback;
+typedef base::OnceCallback<void(bool, void*)> SwapCacheCallback;
// Server-side representation of an application cache host.
class CONTENT_EXPORT AppCacheHost
@@ -92,12 +92,10 @@ class CONTENT_EXPORT AppCacheHost
bool SelectCacheForSharedWorker(int64_t appcache_id);
bool MarkAsForeignEntry(const GURL& document_url,
int64_t cache_document_was_loaded_from);
- void GetStatusWithCallback(const GetStatusCallback& callback,
- void* callback_param);
- void StartUpdateWithCallback(const StartUpdateCallback& callback,
+ void GetStatusWithCallback(GetStatusCallback callback, void* callback_param);
+ void StartUpdateWithCallback(StartUpdateCallback callback,
void* callback_param);
- void SwapCacheWithCallback(const SwapCacheCallback& callback,
- void* callback_param);
+ void SwapCacheWithCallback(SwapCacheCallback callback, void* callback_param);
// Called prior to the main resource load. When the system contains multiple
// candidates for a main resource load, the appcache preferred by the host
diff --git a/chromium/content/browser/appcache/appcache_host_unittest.cc b/chromium/content/browser/appcache/appcache_host_unittest.cc
index 16c3626eb9a..b4e7d2daef0 100644
--- a/chromium/content/browser/appcache/appcache_host_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_host_unittest.cc
@@ -25,15 +25,8 @@ namespace content {
class AppCacheHostTest : public testing::Test {
public:
AppCacheHostTest() {
- get_status_callback_ =
- base::Bind(&AppCacheHostTest::GetStatusCallback,
- base::Unretained(this));
- start_update_callback_ =
- base::Bind(&AppCacheHostTest::StartUpdateCallback,
- base::Unretained(this));
- swap_cache_callback_ =
- base::Bind(&AppCacheHostTest::SwapCacheCallback,
- base::Unretained(this));
+ get_status_callback_ = base::BindRepeating(
+ &AppCacheHostTest::GetStatusCallback, base::Unretained(this));
}
class MockFrontend : public AppCacheFrontend {
@@ -156,8 +149,6 @@ class AppCacheHostTest : public testing::Test {
// Mock callbacks we expect to receive from the 'host'
content::GetStatusCallback get_status_callback_;
- content::StartUpdateCallback start_update_callback_;
- content::SwapCacheCallback swap_cache_callback_;
AppCacheStatus last_status_result_;
bool last_swap_result_;
@@ -177,18 +168,24 @@ TEST_F(AppCacheHostTest, Basic) {
// See that the callbacks are delivered immediately
// and respond as if there is no cache selected.
last_status_result_ = APPCACHE_STATUS_OBSOLETE;
- host.GetStatusWithCallback(get_status_callback_, reinterpret_cast<void*>(1));
+ host.GetStatusWithCallback(std::move(get_status_callback_),
+ reinterpret_cast<void*>(1));
EXPECT_EQ(APPCACHE_STATUS_UNCACHED, last_status_result_);
EXPECT_EQ(reinterpret_cast<void*>(1), last_callback_param_);
last_start_result_ = true;
- host.StartUpdateWithCallback(start_update_callback_,
- reinterpret_cast<void*>(2));
+ host.StartUpdateWithCallback(
+ base::BindOnce(&AppCacheHostTest::StartUpdateCallback,
+ base::Unretained(this)),
+ reinterpret_cast<void*>(2));
EXPECT_FALSE(last_start_result_);
EXPECT_EQ(reinterpret_cast<void*>(2), last_callback_param_);
last_swap_result_ = true;
- host.SwapCacheWithCallback(swap_cache_callback_, reinterpret_cast<void*>(3));
+ host.SwapCacheWithCallback(
+ base::BindOnce(&AppCacheHostTest::SwapCacheCallback,
+ base::Unretained(this)),
+ reinterpret_cast<void*>(3));
EXPECT_FALSE(last_swap_result_);
EXPECT_EQ(reinterpret_cast<void*>(3), last_callback_param_);
}
@@ -301,7 +298,8 @@ TEST_F(AppCacheHostTest, FailedCacheLoad) {
// The callback should not occur until we finish cache selection.
last_status_result_ = APPCACHE_STATUS_OBSOLETE;
last_callback_param_ = reinterpret_cast<void*>(-1);
- host.GetStatusWithCallback(get_status_callback_, reinterpret_cast<void*>(1));
+ host.GetStatusWithCallback(std::move(get_status_callback_),
+ reinterpret_cast<void*>(1));
EXPECT_EQ(APPCACHE_STATUS_OBSOLETE, last_status_result_);
EXPECT_EQ(reinterpret_cast<void*>(-1), last_callback_param_);
@@ -332,7 +330,8 @@ TEST_F(AppCacheHostTest, FailedGroupLoad) {
// The callback should not occur until we finish cache selection.
last_status_result_ = APPCACHE_STATUS_OBSOLETE;
last_callback_param_ = reinterpret_cast<void*>(-1);
- host.GetStatusWithCallback(get_status_callback_, reinterpret_cast<void*>(1));
+ host.GetStatusWithCallback(std::move(get_status_callback_),
+ reinterpret_cast<void*>(1));
EXPECT_EQ(APPCACHE_STATUS_OBSOLETE, last_status_result_);
EXPECT_EQ(reinterpret_cast<void*>(-1), last_callback_param_);
diff --git a/chromium/content/browser/appcache/appcache_interceptor.cc b/chromium/content/browser/appcache/appcache_interceptor.cc
index ab2ace4ca21..95e24b01a87 100644
--- a/chromium/content/browser/appcache/appcache_interceptor.cc
+++ b/chromium/content/browser/appcache/appcache_interceptor.cc
@@ -104,8 +104,7 @@ void AppCacheInterceptor::CompleteCrossSiteTransfer(
if (!handler->SanityCheckIsSameService(requester_info->appcache_service())) {
// This can happen when V2 apps and web pages end up in the same storage
// partition.
- const GURL& first_party_url_for_cookies =
- request->first_party_for_cookies();
+ const GURL& first_party_url_for_cookies = request->site_for_cookies();
if (first_party_url_for_cookies.is_valid()) {
// TODO(lazyboy): Remove this once we know which extensions run into this
// issue. See https://crbug.com/612711#c25 for details.
diff --git a/chromium/content/browser/appcache/appcache_internals_ui.cc b/chromium/content/browser/appcache/appcache_internals_ui.cc
index e9ad038d9f8..f7c812a2c9b 100644
--- a/chromium/content/browser/appcache/appcache_internals_ui.cc
+++ b/chromium/content/browser/appcache/appcache_internals_ui.cc
@@ -146,7 +146,7 @@ void AppCacheInternalsUI::Proxy::Initialize(
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&Proxy::Initialize, this, chrome_appcache_service));
+ base::BindOnce(&Proxy::Initialize, this, chrome_appcache_service));
return;
}
appcache_service_ = chrome_appcache_service->AsWeakPtr();
@@ -161,7 +161,7 @@ AppCacheInternalsUI::Proxy::~Proxy() {
void AppCacheInternalsUI::Proxy::Shutdown() {
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::Bind(&Proxy::Shutdown, this));
+ base::BindOnce(&Proxy::Shutdown, this));
return;
}
shutdown_called_ = true;
@@ -174,8 +174,9 @@ void AppCacheInternalsUI::Proxy::Shutdown() {
void AppCacheInternalsUI::Proxy::RequestAllAppCacheInfo() {
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::Bind(&Proxy::RequestAllAppCacheInfo, this));
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&Proxy::RequestAllAppCacheInfo, this));
return;
}
if (appcache_service_) {
@@ -192,8 +193,8 @@ void AppCacheInternalsUI::Proxy::OnAllAppCacheInfoReady(
int net_result_code) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&AppCacheInternalsUI::OnAllAppCacheInfoReady,
- appcache_internals_ui_, collection, partition_path_));
+ base::BindOnce(&AppCacheInternalsUI::OnAllAppCacheInfoReady,
+ appcache_internals_ui_, collection, partition_path_));
}
void AppCacheInternalsUI::Proxy::DeleteAppCache(
@@ -201,7 +202,7 @@ void AppCacheInternalsUI::Proxy::DeleteAppCache(
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&Proxy::DeleteAppCache, this, manifest_url));
+ base::BindOnce(&Proxy::DeleteAppCache, this, manifest_url));
return;
}
if (appcache_service_) {
@@ -216,9 +217,9 @@ void AppCacheInternalsUI::Proxy::OnAppCacheInfoDeleted(
int net_result_code) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&AppCacheInternalsUI::OnAppCacheInfoDeleted,
- appcache_internals_ui_, partition_path_, manifest_url,
- net_result_code == net::OK));
+ base::BindOnce(&AppCacheInternalsUI::OnAppCacheInfoDeleted,
+ appcache_internals_ui_, partition_path_, manifest_url,
+ net_result_code == net::OK));
}
void AppCacheInternalsUI::Proxy::RequestAppCacheDetails(
@@ -226,7 +227,7 @@ void AppCacheInternalsUI::Proxy::RequestAppCacheDetails(
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&Proxy::RequestAppCacheDetails, this, manifest_url));
+ base::BindOnce(&Proxy::RequestAppCacheDetails, this, manifest_url));
return;
}
@@ -246,9 +247,10 @@ void AppCacheInternalsUI::Proxy::OnGroupLoaded(AppCacheGroup* appcache_group,
}
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&AppCacheInternalsUI::OnAppCacheDetailsReady,
- appcache_internals_ui_, partition_path_, manifest_gurl.spec(),
- base::Passed(&resource_info_vector)));
+ base::BindOnce(&AppCacheInternalsUI::OnAppCacheDetailsReady,
+ appcache_internals_ui_, partition_path_,
+ manifest_gurl.spec(),
+ base::Passed(&resource_info_vector)));
}
void AppCacheInternalsUI::Proxy::RequestFileDetails(
@@ -256,7 +258,7 @@ void AppCacheInternalsUI::Proxy::RequestFileDetails(
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&Proxy::RequestFileDetails, this, response_enquiry));
+ base::BindOnce(&Proxy::RequestFileDetails, this, response_enquiry));
return;
}
DCHECK(!shutdown_called_);
@@ -313,14 +315,15 @@ void AppCacheInternalsUI::Proxy::OnResponseDataReadComplete(
if (!response_info || net_result_code < 0) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&AppCacheInternalsUI::OnFileDetailsFailed,
- appcache_internals_ui_, response_enquiry, net_result_code));
+ base::BindOnce(&AppCacheInternalsUI::OnFileDetailsFailed,
+ appcache_internals_ui_, response_enquiry,
+ net_result_code));
} else {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&AppCacheInternalsUI::OnFileDetailsReady,
- appcache_internals_ui_, response_enquiry, response_info,
- response_data, net_result_code));
+ base::BindOnce(&AppCacheInternalsUI::OnFileDetailsReady,
+ appcache_internals_ui_, response_enquiry, response_info,
+ response_data, net_result_code));
}
preparing_response_ = false;
HandleFileDetailsRequest();
diff --git a/chromium/content/browser/appcache/appcache_job.cc b/chromium/content/browser/appcache/appcache_job.cc
index 3ef6fb868c3..e5258140d19 100644
--- a/chromium/content/browser/appcache/appcache_job.cc
+++ b/chromium/content/browser/appcache/appcache_job.cc
@@ -22,15 +22,18 @@ std::unique_ptr<AppCacheJob> AppCacheJob::Create(
AppCacheStorage* storage,
AppCacheRequest* request,
net::NetworkDelegate* network_delegate,
- const OnPrepareToRestartCallback& restart_callback) {
+ OnPrepareToRestartCallback restart_callback,
+ std::unique_ptr<SubresourceLoadInfo> subresource_load_info,
+ URLLoaderFactoryGetter* loader_factory_getter) {
std::unique_ptr<AppCacheJob> job;
if (base::FeatureList::IsEnabled(features::kNetworkService)) {
- job.reset(new AppCacheURLLoaderJob(*(request->GetResourceRequest()),
- request->AsURLLoaderRequest(), storage));
+ job.reset(new AppCacheURLLoaderJob(
+ *(request->GetResourceRequest()), request->AsURLLoaderRequest(),
+ storage, std::move(subresource_load_info), loader_factory_getter));
} else {
- job.reset(new AppCacheURLRequestJob(request->GetURLRequest(),
- network_delegate, storage, host,
- is_main_resource, restart_callback));
+ job.reset(new AppCacheURLRequestJob(
+ request->GetURLRequest(), network_delegate, storage, host,
+ is_main_resource, std::move(restart_callback)));
}
return job;
}
diff --git a/chromium/content/browser/appcache/appcache_job.h b/chromium/content/browser/appcache/appcache_job.h
index f1af703099f..88a06280e9b 100644
--- a/chromium/content/browser/appcache/appcache_job.h
+++ b/chromium/content/browser/appcache/appcache_job.h
@@ -31,7 +31,9 @@ class AppCacheResponseInfo;
class AppCacheResponseReader;
class AppCacheStorage;
class AppCacheURLLoaderJob;
+class URLLoaderFactoryGetter;
class URLRequestJob;
+struct SubresourceLoadInfo;
// Interface for an AppCache job. This is used to send data stored in the
// AppCache to networking consumers.
@@ -53,7 +55,7 @@ class CONTENT_EXPORT AppCacheJob : public base::SupportsWeakPtr<AppCacheJob> {
// TODO(ananta)
// This applies only to the URLRequestJob at the moment. Look into taking
// this knowledge out of this class.
- using OnPrepareToRestartCallback = base::Closure;
+ using OnPrepareToRestartCallback = base::OnceClosure;
// Factory function to create the AppCacheJob instance for the |request|
// passed in. The |job_type| parameter controls the type of job which is
@@ -64,7 +66,9 @@ class CONTENT_EXPORT AppCacheJob : public base::SupportsWeakPtr<AppCacheJob> {
AppCacheStorage* storage,
AppCacheRequest* request,
net::NetworkDelegate* network_delegate,
- const OnPrepareToRestartCallback& restart_callback);
+ OnPrepareToRestartCallback restart_callback,
+ std::unique_ptr<SubresourceLoadInfo> subresource_load_info,
+ URLLoaderFactoryGetter* loader_factory_getter);
virtual ~AppCacheJob();
@@ -118,6 +122,10 @@ class CONTENT_EXPORT AppCacheJob : public base::SupportsWeakPtr<AppCacheJob> {
// AppCaches loaded via the URLRequest mechanism.
virtual AppCacheURLLoaderJob* AsURLLoaderJob();
+ void set_delivery_type(DeliveryType delivery_type) {
+ delivery_type_ = delivery_type;
+ }
+
protected:
AppCacheJob();
diff --git a/chromium/content/browser/appcache/appcache_manifest_parser.cc b/chromium/content/browser/appcache/appcache_manifest_parser.cc
index ca4cb7a2033..a8b9321e5d8 100644
--- a/chromium/content/browser/appcache/appcache_manifest_parser.cc
+++ b/chromium/content/browser/appcache/appcache_manifest_parser.cc
@@ -60,7 +60,7 @@ bool HasPatternMatchingAnnotation(const wchar_t* line_p,
bool ScopeMatches(const GURL& manifest_url, const GURL& namespace_url) {
return base::StartsWith(namespace_url.spec(),
- manifest_url.Resolve(".").spec(),
+ manifest_url.GetWithoutFilename().spec(),
base::CompareCase::SENSITIVE);
}
diff --git a/chromium/content/browser/appcache/appcache_manifest_parser_unittest.cc b/chromium/content/browser/appcache/appcache_manifest_parser_unittest.cc
index bd34ef194e8..caa0264b770 100644
--- a/chromium/content/browser/appcache/appcache_manifest_parser_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_manifest_parser_unittest.cc
@@ -564,7 +564,8 @@ TEST(AppCacheManifestParserTest, IgnoreDangerousFallbacks) {
"http://foo.com/out_of_scope/ fallback_url\r");
// Scope matching depends on resolving "." as a relative url.
- EXPECT_EQ(kUrl.Resolve(".").spec(), std::string("http://foo.com/scope/"));
+ EXPECT_EQ(kUrl.GetWithoutFilename().spec(),
+ std::string("http://foo.com/scope/"));
AppCacheManifest manifest;
EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(),
diff --git a/chromium/content/browser/appcache/appcache_navigation_handle.cc b/chromium/content/browser/appcache/appcache_navigation_handle.cc
index a5de291e2be..6c47bf8a415 100644
--- a/chromium/content/browser/appcache/appcache_navigation_handle.cc
+++ b/chromium/content/browser/appcache/appcache_navigation_handle.cc
@@ -27,9 +27,10 @@ AppCacheNavigationHandle::AppCacheNavigationHandle(
appcache_host_id_ = g_next_appcache_host_id--;
core_.reset(new AppCacheNavigationHandleCore(
weak_factory_.GetWeakPtr(), appcache_service, appcache_host_id_));
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::Bind(&AppCacheNavigationHandleCore::Initialize,
- base::Unretained(core_.get())));
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&AppCacheNavigationHandleCore::Initialize,
+ base::Unretained(core_.get())));
}
AppCacheNavigationHandle::~AppCacheNavigationHandle() {
diff --git a/chromium/content/browser/appcache/appcache_quota_client.cc b/chromium/content/browser/appcache/appcache_quota_client.cc
index 6edfd887762..dbc9a1a492c 100644
--- a/chromium/content/browser/appcache/appcache_quota_client.cc
+++ b/chromium/content/browser/appcache/appcache_quota_client.cc
@@ -25,9 +25,9 @@ storage::QuotaStatusCode NetErrorCodeToQuotaStatus(int code) {
}
void RunFront(content::AppCacheQuotaClient::RequestQueue* queue) {
- base::Closure request = queue->front();
+ base::OnceClosure request = std::move(queue->front());
queue->pop_front();
- request.Run();
+ std::move(request).Run();
}
} // namespace
diff --git a/chromium/content/browser/appcache/appcache_quota_client.h b/chromium/content/browser/appcache/appcache_quota_client.h
index 73f2559cb7c..6366204c0db 100644
--- a/chromium/content/browser/appcache/appcache_quota_client.h
+++ b/chromium/content/browser/appcache/appcache_quota_client.h
@@ -31,7 +31,7 @@ class AppCacheStorageImpl;
// been destroyed.
class AppCacheQuotaClient : public storage::QuotaClient {
public:
- typedef std::deque<base::Closure> RequestQueue;
+ typedef std::deque<base::OnceClosure> RequestQueue;
~AppCacheQuotaClient() override;
diff --git a/chromium/content/browser/appcache/appcache_request.h b/chromium/content/browser/appcache/appcache_request.h
index 63dc5ec7384..b97a1e805b2 100644
--- a/chromium/content/browser/appcache/appcache_request.h
+++ b/chromium/content/browser/appcache/appcache_request.h
@@ -34,7 +34,7 @@ class CONTENT_EXPORT AppCacheRequest {
virtual const std::string& GetMethod() const = 0;
// Used for cookie policy.
- virtual const GURL& GetFirstPartyForCookies() const = 0;
+ virtual const GURL& GetSiteForCookies() const = 0;
// The referrer for this request.
virtual const GURL GetReferrer() const = 0;
diff --git a/chromium/content/browser/appcache/appcache_request_handler.cc b/chromium/content/browser/appcache/appcache_request_handler.cc
index 8db5e59d2af..10148ba8285 100644
--- a/chromium/content/browser/appcache/appcache_request_handler.cc
+++ b/chromium/content/browser/appcache/appcache_request_handler.cc
@@ -25,6 +25,12 @@
namespace content {
+namespace {
+
+bool g_running_in_tests = false;
+
+} // namespace
+
AppCacheRequestHandler::AppCacheRequestHandler(
AppCacheHost* host,
ResourceType resource_type,
@@ -168,7 +174,7 @@ AppCacheJob* AppCacheRequestHandler::MaybeLoadFallbackForResponse(
}
// We don't fallback for responses that we delivered.
- if (job_.get() && !base::FeatureList::IsEnabled(features::kNetworkService)) {
+ if (job_.get()) {
DCHECK(!job_->IsDeliveringNetworkResponse());
return NULL;
}
@@ -240,6 +246,26 @@ void AppCacheRequestHandler::MaybeCompleteCrossSiteTransferInOldProcess(
CompleteCrossSiteTransfer(old_process_id_, old_host_id_);
}
+AppCacheJob* AppCacheRequestHandler::MaybeCreateSubresourceLoader(
+ std::unique_ptr<SubresourceLoadInfo> subresource_load_info,
+ URLLoaderFactoryGetter* loader_factory_getter) {
+ DCHECK(!is_main_resource());
+ DCHECK(base::FeatureList::IsEnabled(features::kNetworkService));
+
+ subresource_load_info_ = std::move(subresource_load_info);
+ network_url_loader_factory_getter_ = loader_factory_getter;
+
+ AppCacheJob* job = MaybeLoadResource(nullptr);
+ if (!job)
+ return nullptr;
+
+ AppCacheURLLoaderJob* loader_job = job->AsURLLoaderJob();
+ // The job takes ownership of the handler.
+ loader_job->set_request_handler(
+ std::unique_ptr<AppCacheRequestHandler>(this));
+ return job;
+}
+
// static
std::unique_ptr<AppCacheRequestHandler>
AppCacheRequestHandler::InitializeForNavigationNetworkService(
@@ -255,11 +281,6 @@ AppCacheRequestHandler::InitializeForNavigationNetworkService(
return handler;
}
-void AppCacheRequestHandler::SetSubresourceRequestLoadInfo(
- std::unique_ptr<SubresourceLoadInfo> subresource_load_info) {
- subresource_load_info_ = std::move(subresource_load_info);
-}
-
void AppCacheRequestHandler::OnDestructionImminent(AppCacheHost* host) {
storage()->CancelDelegateCallbacks(this);
host_ = NULL; // no need to RemoveObserver, the host is being deleted
@@ -302,6 +323,10 @@ void AppCacheRequestHandler::DeliverAppCachedResponse(
host_->NotifyMainResourceIsNamespaceEntry(namespace_entry_url);
job_->DeliverAppCachedResponse(manifest_url, cache_id, entry, is_fallback);
+ // In the network service world, we need to release the AppCacheJob instance
+ // created for handling navigation requests. These instances will get
+ // destroyed when the client disconnects.
+ navigation_request_job_.release();
}
void AppCacheRequestHandler::DeliverErrorResponse() {
@@ -309,6 +334,10 @@ void AppCacheRequestHandler::DeliverErrorResponse() {
DCHECK_EQ(kAppCacheNoCacheId, cache_id_);
DCHECK(manifest_url_.is_empty());
job_->DeliverErrorResponse();
+ // In the network service world, we need to release the AppCacheJob instance
+ // created for handling navigation requests. These instances will get
+ // destroyed when the client disconnects.
+ navigation_request_job_.release();
}
void AppCacheRequestHandler::DeliverNetworkResponse() {
@@ -316,6 +345,9 @@ void AppCacheRequestHandler::DeliverNetworkResponse() {
DCHECK_EQ(kAppCacheNoCacheId, cache_id_);
DCHECK(manifest_url_.is_empty());
job_->DeliverNetworkResponse();
+ // In the network service world, we need to destroy the AppCacheJob instance
+ // created for handling navigation requests.
+ navigation_request_job_.reset(nullptr);
}
void AppCacheRequestHandler::OnPrepareToRestart() {
@@ -337,28 +369,24 @@ std::unique_ptr<AppCacheJob> AppCacheRequestHandler::CreateJob(
net::NetworkDelegate* network_delegate) {
std::unique_ptr<AppCacheJob> job = AppCacheJob::Create(
is_main_resource(), host_, storage(), request_.get(), network_delegate,
- base::Bind(&AppCacheRequestHandler::OnPrepareToRestart,
- base::Unretained(this)));
+ base::BindOnce(&AppCacheRequestHandler::OnPrepareToRestart,
+ base::Unretained(this)),
+ std::move(subresource_load_info_),
+ network_url_loader_factory_getter_.get());
job_ = job->GetWeakPtr();
- if (!is_main_resource() &&
- base::FeatureList::IsEnabled(features::kNetworkService)) {
- AppCacheURLLoaderJob* loader_job = job_->AsURLLoaderJob();
-
- loader_job->SetSubresourceLoadInfo(
- std::move(subresource_load_info_),
- network_url_loader_factory_getter_.get());
- }
-
return job;
}
std::unique_ptr<AppCacheJob> AppCacheRequestHandler::MaybeCreateJobForFallback(
net::NetworkDelegate* network_delegate) {
- if (!base::FeatureList::IsEnabled(features::kNetworkService))
+ if (!base::FeatureList::IsEnabled(features::kNetworkService) ||
+ IsMainResourceType(resource_type_)) {
return CreateJob(network_delegate);
+ }
// In network service land, the job initiates a fallback request. We reuse
// the existing job to deliver the fallback response.
DCHECK(job_.get());
+ job_->set_delivery_type(AppCacheJob::AWAITING_DELIVERY_ORDERS);
return std::unique_ptr<AppCacheJob>(job_.get());
}
@@ -595,4 +623,34 @@ AppCacheRequestHandler::MaybeCreateSubresourceFactory() {
return factory_ptr;
}
+bool AppCacheRequestHandler::MaybeCreateLoaderForResponse(
+ const ResourceResponseHead& response,
+ mojom::URLLoaderPtr* loader,
+ mojom::URLLoaderClientRequest* client_request) {
+ request_->AsURLLoaderRequest()->set_response(response);
+ // The AppCacheJob will get destroyed when the client connection is
+ // dropped.
+ AppCacheJob* job = MaybeLoadFallbackForResponse(nullptr);
+ if (job) {
+ mojom::URLLoaderClientPtr client;
+ *client_request = mojo::MakeRequest(&client);
+ mojom::URLLoaderRequest loader_request = mojo::MakeRequest(loader);
+
+ job->AsURLLoaderJob()->BindRequest(std::move(client),
+ std::move(loader_request));
+ return true;
+ }
+ return false;
+}
+
+// static
+void AppCacheRequestHandler::SetRunningInTests(bool in_tests) {
+ g_running_in_tests = in_tests;
+}
+
+// static
+bool AppCacheRequestHandler::IsRunningInTests() {
+ return g_running_in_tests;
+}
+
} // namespace content
diff --git a/chromium/content/browser/appcache/appcache_request_handler.h b/chromium/content/browser/appcache/appcache_request_handler.h
index 24ee0fcc745..081c0bb2f22 100644
--- a/chromium/content/browser/appcache/appcache_request_handler.h
+++ b/chromium/content/browser/appcache/appcache_request_handler.h
@@ -15,6 +15,7 @@
#include "base/supports_user_data.h"
#include "content/browser/appcache/appcache_entry.h"
#include "content/browser/appcache/appcache_host.h"
+#include "content/browser/appcache/appcache_request_handler.h"
#include "content/browser/appcache/appcache_service_impl.h"
#include "content/browser/loader/url_loader_request_handler.h"
#include "content/browser/url_loader_factory_getter.h"
@@ -70,6 +71,17 @@ class CONTENT_EXPORT AppCacheRequestHandler
return !host_ || (host_->service() == service);
}
+ // This method is called in the network service code path for creating a job
+ // for handling subresource load requests.
+ // The |subresource_load_info| parameter contains the information required to
+ // service the load request.
+ // The |loader_factory_getter| parameter points to the URLLoaderFactoryGetter
+ // instance which provides functionality to return the default network
+ // URLLoader interface.
+ AppCacheJob* MaybeCreateSubresourceLoader(
+ std::unique_ptr<SubresourceLoadInfo> subresource_load_info,
+ URLLoaderFactoryGetter* loader_factory_getter);
+
static bool IsMainResourceType(ResourceType type) {
return IsResourceTypeFrame(type) ||
type == RESOURCE_TYPE_SHARED_WORKER;
@@ -81,14 +93,11 @@ class CONTENT_EXPORT AppCacheRequestHandler
AppCacheNavigationHandleCore* appcache_handle_core,
URLLoaderFactoryGetter* url_loader_factory_getter);
- // The following setters only apply for the network service code.
- void set_network_url_loader_factory_getter(
- URLLoaderFactoryGetter* url_loader_factory_getter) {
- network_url_loader_factory_getter_ = url_loader_factory_getter;
- }
+ // Called by unittests to indicate that we are in test mode.
+ static void SetRunningInTests(bool in_tests);
- void SetSubresourceRequestLoadInfo(
- std::unique_ptr<SubresourceLoadInfo> subresource_load_info);
+ // Returns true if we are running in tests.
+ static bool IsRunningInTests();
private:
friend class AppCacheHost;
@@ -160,11 +169,19 @@ class CONTENT_EXPORT AppCacheRequestHandler
// AppCacheHost::Observer override
void OnCacheSelectionComplete(AppCacheHost* host) override;
- // URLLoaderRequestHandler override
+ // Network service loading
+
+ // URLLoaderRequestHandler overrides
+ // These functions are invoked for loading AppCache content for the frame and
+ // for subresources.
void MaybeCreateLoader(const ResourceRequest& resource_request,
ResourceContext* resource_context,
LoaderCallback callback) override;
mojom::URLLoaderFactoryPtr MaybeCreateSubresourceFactory() override;
+ bool MaybeCreateLoaderForResponse(
+ const ResourceResponseHead& response,
+ mojom::URLLoaderPtr* loader,
+ mojom::URLLoaderClientRequest* client_request) override;
// Data members -----------------------------------------------
@@ -235,8 +252,7 @@ class CONTENT_EXPORT AppCacheRequestHandler
// the AppCache, we delete the job.
std::unique_ptr<AppCacheJob> navigation_request_job_;
- // In the network service world, points to the getter for the network URL
- // loader.
+ // Points to the getter for the network URL loader.
scoped_refptr<URLLoaderFactoryGetter> network_url_loader_factory_getter_;
friend class content::AppCacheRequestHandlerTest;
diff --git a/chromium/content/browser/appcache/appcache_request_handler_unittest.cc b/chromium/content/browser/appcache/appcache_request_handler_unittest.cc
index 94ec32f294b..dc81c0b1c6e 100644
--- a/chromium/content/browser/appcache/appcache_request_handler_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_request_handler_unittest.cc
@@ -18,18 +18,24 @@
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/memory/weak_ptr.h"
+#include "base/message_loop/message_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/stringprintf.h"
#include "base/synchronization/waitable_event.h"
+#include "base/test/scoped_feature_list.h"
#include "base/test/scoped_task_environment.h"
#include "base/threading/thread.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/appcache/appcache.h"
#include "content/browser/appcache/appcache_backend_impl.h"
+#include "content/browser/appcache/appcache_job.h"
+#include "content/browser/appcache/appcache_url_loader_request.h"
#include "content/browser/appcache/appcache_url_request.h"
#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/common/content_features.h"
+#include "content/public/common/resource_request.h"
#include "net/base/net_errors.h"
#include "net/base/request_priority.h"
#include "net/http/http_response_headers.h"
@@ -45,7 +51,20 @@ namespace content {
static const int kMockProcessId = 1;
-class AppCacheRequestHandlerTest : public testing::Test {
+// Controls whether we instantiate the URLRequest based AppCache handler or
+// the URLLoader based one.
+enum RequestHandlerType {
+ URLREQUEST,
+ URLLOADER,
+};
+
+// TODO(michaeln/ananta)
+// Build on the abstractions provided by the request and the job classes to
+// provide mock request and job classes to the AppCacheRequestHandler class
+// which would make it testable. It would also allow us to avoid the URLRequest
+// and URLLoader semantics in the test cases here,
+class AppCacheRequestHandlerTest
+ : public testing::TestWithParam<RequestHandlerType> {
public:
class MockFrontend : public AppCacheFrontend {
public:
@@ -192,7 +211,16 @@ class AppCacheRequestHandlerTest : public testing::Test {
// Test harness --------------------------------------------------
- AppCacheRequestHandlerTest() : host_(NULL) {}
+ AppCacheRequestHandlerTest()
+ : host_(NULL), request_(nullptr), request_handler_type_(GetParam()) {
+ AppCacheRequestHandler::SetRunningInTests(true);
+ if (request_handler_type_ == URLLOADER)
+ feature_list_.InitAndEnableFeature(features::kNetworkService);
+ }
+
+ ~AppCacheRequestHandlerTest() {
+ AppCacheRequestHandler::SetRunningInTests(false);
+ }
template <class Method>
void RunTestOnIOThread(Method method) {
@@ -201,8 +229,8 @@ class AppCacheRequestHandlerTest : public testing::Test {
base::WaitableEvent::InitialState::NOT_SIGNALED));
io_thread_->task_runner()->PostTask(
FROM_HERE,
- base::Bind(&AppCacheRequestHandlerTest::MethodWrapper<Method>,
- base::Unretained(this), method));
+ base::BindOnce(&AppCacheRequestHandlerTest::MethodWrapper<Method>,
+ base::Unretained(this), method));
test_finished_event_->Wait();
}
@@ -229,7 +257,8 @@ class AppCacheRequestHandlerTest : public testing::Test {
DCHECK(io_thread_->task_runner()->BelongsToCurrentThread());
job_ = NULL;
handler_.reset();
- request_.reset();
+ request_ = nullptr;
+ url_request_.reset();
backend_impl_.reset();
mock_frontend_.reset();
mock_service_.reset();
@@ -244,8 +273,9 @@ class AppCacheRequestHandlerTest : public testing::Test {
// based objects get deleted.
DCHECK(io_thread_->task_runner()->BelongsToCurrentThread());
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&AppCacheRequestHandlerTest::TestFinishedUnwound,
- base::Unretained(this)));
+ FROM_HERE,
+ base::BindOnce(&AppCacheRequestHandlerTest::TestFinishedUnwound,
+ base::Unretained(this)));
}
void TestFinishedUnwound() {
@@ -253,8 +283,8 @@ class AppCacheRequestHandlerTest : public testing::Test {
test_finished_event_->Signal();
}
- void PushNextTask(const base::Closure& task) {
- task_stack_.push(task);
+ void PushNextTask(base::OnceClosure task) {
+ task_stack_.push(std::move(task));
}
void ScheduleNextTask() {
@@ -263,7 +293,8 @@ class AppCacheRequestHandlerTest : public testing::Test {
TestFinished();
return;
}
- base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, task_stack_.top());
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+ std::move(task_stack_.top()));
task_stack_.pop();
}
@@ -274,17 +305,11 @@ class AppCacheRequestHandlerTest : public testing::Test {
base::Bind(&AppCacheRequestHandlerTest::Verify_MainResource_Miss,
base::Unretained(this)));
- request_ = empty_context_->CreateRequest(GURL("http://blah/"),
- net::DEFAULT_PRIORITY, &delegate_,
- TRAFFIC_ANNOTATION_FOR_TESTS);
- handler_ =
- host_->CreateRequestHandler(AppCacheURLRequest::Create(request_.get()),
- RESOURCE_TYPE_MAIN_FRAME, false);
+ EXPECT_TRUE(CreateRequestAndHandler(GURL("http://blah"), host_,
+ RESOURCE_TYPE_MAIN_FRAME));
EXPECT_TRUE(handler_.get());
- job_.reset(static_cast<AppCacheURLRequestJob*>(
- handler_->MaybeLoadResource(request_->context()->network_delegate())
- ->AsURLRequestJob()));
+ job_.reset(handler_->MaybeLoadResource(nullptr));
EXPECT_TRUE(job_.get());
EXPECT_TRUE(job_->IsWaiting());
@@ -303,15 +328,11 @@ class AppCacheRequestHandlerTest : public testing::Test {
EXPECT_EQ(GURL(), manifest_url);
EXPECT_EQ(0, handler_->found_group_id_);
- std::unique_ptr<AppCacheURLRequestJob> fallback_job(
- static_cast<AppCacheURLRequestJob*>(
- handler_->MaybeLoadFallbackForRedirect(
- request_->context()->network_delegate(),
- GURL("http://blah/redirect"))));
+ std::unique_ptr<AppCacheJob> fallback_job(
+ handler_->MaybeLoadFallbackForRedirect(nullptr,
+ GURL("http://blah/redirect")));
EXPECT_FALSE(fallback_job);
- fallback_job.reset(static_cast<AppCacheURLRequestJob*>(
- handler_->MaybeLoadFallbackForResponse(
- request_->context()->network_delegate())));
+ fallback_job.reset(handler_->MaybeLoadFallbackForResponse(nullptr));
EXPECT_FALSE(fallback_job);
EXPECT_TRUE(host_->preferred_manifest_url().is_empty());
@@ -326,12 +347,8 @@ class AppCacheRequestHandlerTest : public testing::Test {
base::Bind(&AppCacheRequestHandlerTest::Verify_MainResource_Hit,
base::Unretained(this)));
- request_ = empty_context_->CreateRequest(GURL("http://blah/"),
- net::DEFAULT_PRIORITY, &delegate_,
- TRAFFIC_ANNOTATION_FOR_TESTS);
- handler_ =
- host_->CreateRequestHandler(AppCacheURLRequest::Create(request_.get()),
- RESOURCE_TYPE_MAIN_FRAME, false);
+ EXPECT_TRUE(CreateRequestAndHandler(GURL("http://blah"), host_,
+ RESOURCE_TYPE_MAIN_FRAME));
EXPECT_TRUE(handler_.get());
mock_storage()->SimulateFindMainResource(
@@ -339,8 +356,7 @@ class AppCacheRequestHandlerTest : public testing::Test {
GURL(), AppCacheEntry(),
1, 2, GURL("http://blah/manifest/"));
- job_.reset(static_cast<AppCacheURLRequestJob*>(
- handler_->MaybeLoadResource(request_->context()->network_delegate())));
+ job_.reset(handler_->MaybeLoadResource(nullptr));
EXPECT_TRUE(job_.get());
EXPECT_TRUE(job_->IsWaiting());
@@ -359,10 +375,8 @@ class AppCacheRequestHandlerTest : public testing::Test {
EXPECT_EQ(GURL("http://blah/manifest/"), manifest_url);
EXPECT_EQ(2, handler_->found_group_id_);
- std::unique_ptr<AppCacheURLRequestJob> fallback_job(
- static_cast<AppCacheURLRequestJob*>(
- handler_->MaybeLoadFallbackForResponse(
- request_->context()->network_delegate())));
+ std::unique_ptr<AppCacheJob> fallback_job(
+ handler_->MaybeLoadFallbackForResponse(nullptr));
EXPECT_FALSE(fallback_job);
EXPECT_EQ(GURL("http://blah/manifest/"),
@@ -378,12 +392,8 @@ class AppCacheRequestHandlerTest : public testing::Test {
base::Bind(&AppCacheRequestHandlerTest::Verify_MainResource_Fallback,
base::Unretained(this)));
- request_ = empty_context_->CreateRequest(GURL("http://blah/"),
- net::DEFAULT_PRIORITY, &delegate_,
- TRAFFIC_ANNOTATION_FOR_TESTS);
- handler_ =
- host_->CreateRequestHandler(AppCacheURLRequest::Create(request_.get()),
- RESOURCE_TYPE_MAIN_FRAME, false);
+ EXPECT_TRUE(CreateRequestAndHandler(GURL("http://blah"), host_,
+ RESOURCE_TYPE_MAIN_FRAME));
EXPECT_TRUE(handler_.get());
mock_storage()->SimulateFindMainResource(
@@ -392,8 +402,7 @@ class AppCacheRequestHandlerTest : public testing::Test {
AppCacheEntry(AppCacheEntry::EXPLICIT, 1),
1, 2, GURL("http://blah/manifest/"));
- job_.reset(static_cast<AppCacheURLRequestJob*>(
- handler_->MaybeLoadResource(request_->context()->network_delegate())));
+ job_.reset(handler_->MaybeLoadResource(nullptr));
EXPECT_TRUE(job_.get());
EXPECT_TRUE(job_->IsWaiting());
@@ -408,18 +417,31 @@ class AppCacheRequestHandlerTest : public testing::Test {
info.headers = new net::HttpResponseHeaders(
net::HttpUtil::AssembleRawHeaders(headers.c_str(), headers.length()));
- job_factory_->SetJob(base::MakeUnique<MockURLRequestJob>(
- request_.get(), request_->context()->network_delegate(), info));
- request_->Start();
- // All our simulation needs to satisfy are the following two DCHECKs.
- DCHECK_EQ(net::OK, delegate_.request_status());
+ if (request_handler_type_ == URLREQUEST) {
+ job_factory_->SetJob(base::MakeUnique<MockURLRequestJob>(
+ url_request_.get(), nullptr, info));
+ request_->AsURLRequest()->GetURLRequest()->Start();
+ // All our simulation needs to satisfy are the DCHECK's for the request
+ // status and the response code.
+ DCHECK_EQ(net::OK, delegate_.request_status());
+ } else {
+ ResourceResponseHead response;
+ response.headers = info.headers;
+ request_->AsURLLoaderRequest()->set_response(response);
+ }
DCHECK_EQ(response_code, request_->GetResponseCode());
}
void SimulateResponseInfo(const net::HttpResponseInfo& info) {
- job_factory_->SetJob(base::MakeUnique<MockURLRequestJob>(
- request_.get(), request_->context()->network_delegate(), info));
- request_->Start();
+ if (request_handler_type_ == URLREQUEST) {
+ job_factory_->SetJob(base::MakeUnique<MockURLRequestJob>(
+ url_request_.get(), nullptr, info));
+ request_->AsURLRequest()->GetURLRequest()->Start();
+ } else {
+ ResourceResponseHead response;
+ response.headers = info.headers;
+ request_->AsURLLoaderRequest()->set_response(response);
+ }
}
void Verify_MainResource_Fallback() {
@@ -433,16 +455,13 @@ class AppCacheRequestHandlerTest : public testing::Test {
// When the request is restarted, the existing job is dropped so a
// real network job gets created. We expect NULL here which will cause
// the net library to create a real job.
- job_.reset(static_cast<AppCacheURLRequestJob*>(
- handler_->MaybeLoadResource(request_->context()->network_delegate())));
+ job_.reset(handler_->MaybeLoadResource(nullptr));
EXPECT_FALSE(job_.get());
// Simulate an http error of the real network job.
SimulateResponseCode(500);
- job_.reset(static_cast<AppCacheURLRequestJob*>(
- handler_->MaybeLoadFallbackForResponse(
- request_->context()->network_delegate())));
+ job_.reset(handler_->MaybeLoadFallbackForResponse(nullptr));
EXPECT_TRUE(job_.get());
EXPECT_TRUE(job_->IsDeliveringAppCacheResponse());
@@ -467,12 +486,8 @@ class AppCacheRequestHandlerTest : public testing::Test {
&AppCacheRequestHandlerTest::Verify_MainResource_FallbackOverride,
base::Unretained(this)));
- request_ = empty_context_->CreateRequest(
- GURL("http://blah/fallback-override"), net::DEFAULT_PRIORITY,
- &delegate_, TRAFFIC_ANNOTATION_FOR_TESTS);
- handler_ =
- host_->CreateRequestHandler(AppCacheURLRequest::Create(request_.get()),
- RESOURCE_TYPE_MAIN_FRAME, false);
+ EXPECT_TRUE(CreateRequestAndHandler(GURL("http://blah/fallback-override"),
+ host_, RESOURCE_TYPE_MAIN_FRAME));
EXPECT_TRUE(handler_.get());
mock_storage()->SimulateFindMainResource(
@@ -481,8 +496,7 @@ class AppCacheRequestHandlerTest : public testing::Test {
AppCacheEntry(AppCacheEntry::EXPLICIT, 1),
1, 2, GURL("http://blah/manifest/"));
- job_.reset(static_cast<AppCacheURLRequestJob*>(
- handler_->MaybeLoadResource(request_->context()->network_delegate())));
+ job_.reset(handler_->MaybeLoadResource(nullptr));
EXPECT_TRUE(job_.get());
EXPECT_TRUE(job_->IsWaiting());
@@ -501,8 +515,7 @@ class AppCacheRequestHandlerTest : public testing::Test {
// When the request is restarted, the existing job is dropped so a
// real network job gets created. We expect NULL here which will cause
// the net library to create a real job.
- job_.reset(static_cast<AppCacheURLRequestJob*>(
- handler_->MaybeLoadResource(request_->context()->network_delegate())));
+ job_.reset(handler_->MaybeLoadResource(nullptr));
EXPECT_FALSE(job_.get());
// Simulate an http error of the real network job, but with custom
@@ -516,9 +529,7 @@ class AppCacheRequestHandlerTest : public testing::Test {
std::string(kOverrideHeaders, arraysize(kOverrideHeaders)));
SimulateResponseInfo(info);
- job_.reset(static_cast<AppCacheURLRequestJob*>(
- handler_->MaybeLoadFallbackForResponse(
- request_->context()->network_delegate())));
+ job_.reset(handler_->MaybeLoadFallbackForResponse(nullptr));
EXPECT_FALSE(job_.get());
// GetExtraResponseInfo should return no information.
@@ -534,13 +545,8 @@ class AppCacheRequestHandlerTest : public testing::Test {
// SubResource_Miss_WithNoCacheSelected ----------------------------------
void SubResource_Miss_WithNoCacheSelected() {
- request_ = empty_context_->CreateRequest(GURL("http://blah/"),
- net::DEFAULT_PRIORITY, &delegate_,
- TRAFFIC_ANNOTATION_FOR_TESTS);
- handler_ =
- host_->CreateRequestHandler(AppCacheURLRequest::Create(request_.get()),
- RESOURCE_TYPE_SUB_RESOURCE, false);
-
+ EXPECT_TRUE(CreateRequestAndHandler(GURL("http://blah/"), host_,
+ RESOURCE_TYPE_SUB_RESOURCE));
// We avoid creating handler when possible, sub-resource requests are not
// subject to retrieval from an appcache when there's no associated cache.
EXPECT_FALSE(handler_.get());
@@ -555,28 +561,19 @@ class AppCacheRequestHandlerTest : public testing::Test {
// in a network or fallback namespace, should result in a failed request.
host_->AssociateCompleteCache(MakeNewCache());
- request_ = empty_context_->CreateRequest(GURL("http://blah/"),
- net::DEFAULT_PRIORITY, &delegate_,
- TRAFFIC_ANNOTATION_FOR_TESTS);
- handler_ =
- host_->CreateRequestHandler(AppCacheURLRequest::Create(request_.get()),
- RESOURCE_TYPE_SUB_RESOURCE, false);
+ EXPECT_TRUE(CreateRequestAndHandler(GURL("http://blah/"), host_,
+ RESOURCE_TYPE_SUB_RESOURCE));
EXPECT_TRUE(handler_.get());
- job_.reset(static_cast<AppCacheURLRequestJob*>(
- handler_->MaybeLoadResource(request_->context()->network_delegate())));
+ job_.reset(handler_->MaybeLoadResource(nullptr));
EXPECT_TRUE(job_.get());
EXPECT_TRUE(job_->IsDeliveringErrorResponse());
- std::unique_ptr<AppCacheURLRequestJob> fallback_job(
- static_cast<AppCacheURLRequestJob*>(
- handler_->MaybeLoadFallbackForRedirect(
- request_->context()->network_delegate(),
- GURL("http://blah/redirect"))));
+ std::unique_ptr<AppCacheJob> fallback_job(
+ handler_->MaybeLoadFallbackForRedirect(nullptr,
+ GURL("http://blah/redirect")));
EXPECT_FALSE(fallback_job);
- fallback_job.reset(static_cast<AppCacheURLRequestJob*>(
- handler_->MaybeLoadFallbackForResponse(
- request_->context()->network_delegate())));
+ fallback_job.reset(handler_->MaybeLoadFallbackForResponse(nullptr));
EXPECT_FALSE(fallback_job);
TestFinished();
@@ -590,15 +587,10 @@ class AppCacheRequestHandlerTest : public testing::Test {
host_->pending_selected_cache_id_ = cache->cache_id();
host_->set_preferred_manifest_url(cache->owning_group()->manifest_url());
- request_ = empty_context_->CreateRequest(GURL("http://blah/"),
- net::DEFAULT_PRIORITY, &delegate_,
- TRAFFIC_ANNOTATION_FOR_TESTS);
- handler_ =
- host_->CreateRequestHandler(AppCacheURLRequest::Create(request_.get()),
- RESOURCE_TYPE_SUB_RESOURCE, false);
+ EXPECT_TRUE(CreateRequestAndHandler(GURL("http://blah/"), host_,
+ RESOURCE_TYPE_SUB_RESOURCE));
EXPECT_TRUE(handler_.get());
- job_.reset(static_cast<AppCacheURLRequestJob*>(
- handler_->MaybeLoadResource(request_->context()->network_delegate())));
+ job_.reset(handler_->MaybeLoadResource(nullptr));
EXPECT_TRUE(job_.get());
EXPECT_TRUE(job_->IsWaiting());
@@ -606,15 +598,11 @@ class AppCacheRequestHandlerTest : public testing::Test {
EXPECT_FALSE(job_->IsWaiting());
EXPECT_TRUE(job_->IsDeliveringErrorResponse());
- std::unique_ptr<AppCacheURLRequestJob> fallback_job(
- static_cast<AppCacheURLRequestJob*>(
- handler_->MaybeLoadFallbackForRedirect(
- request_->context()->network_delegate(),
- GURL("http://blah/redirect"))));
+ std::unique_ptr<AppCacheJob> fallback_job(
+ handler_->MaybeLoadFallbackForRedirect(nullptr,
+ GURL("http://blah/redirect")));
EXPECT_FALSE(fallback_job);
- fallback_job.reset(static_cast<AppCacheURLRequestJob*>(
- handler_->MaybeLoadFallbackForResponse(
- request_->context()->network_delegate())));
+ fallback_job.reset(handler_->MaybeLoadFallbackForResponse(nullptr));
EXPECT_FALSE(fallback_job);
TestFinished();
@@ -628,27 +616,18 @@ class AppCacheRequestHandlerTest : public testing::Test {
mock_storage()->SimulateFindSubResource(
AppCacheEntry(AppCacheEntry::EXPLICIT, 1), AppCacheEntry(), false);
- request_ = empty_context_->CreateRequest(GURL("http://blah/"),
- net::DEFAULT_PRIORITY, &delegate_,
- TRAFFIC_ANNOTATION_FOR_TESTS);
- handler_ =
- host_->CreateRequestHandler(AppCacheURLRequest::Create(request_.get()),
- RESOURCE_TYPE_SUB_RESOURCE, false);
+ EXPECT_TRUE(CreateRequestAndHandler(GURL("http://blah/"), host_,
+ RESOURCE_TYPE_SUB_RESOURCE));
EXPECT_TRUE(handler_.get());
- job_.reset(static_cast<AppCacheURLRequestJob*>(
- handler_->MaybeLoadResource(request_->context()->network_delegate())));
+ job_.reset(handler_->MaybeLoadResource(nullptr));
EXPECT_TRUE(job_.get());
EXPECT_TRUE(job_->IsDeliveringAppCacheResponse());
- std::unique_ptr<AppCacheURLRequestJob> fallback_job(
- static_cast<AppCacheURLRequestJob*>(
- handler_->MaybeLoadFallbackForRedirect(
- request_->context()->network_delegate(),
- GURL("http://blah/redirect"))));
+ std::unique_ptr<AppCacheJob> fallback_job(
+ handler_->MaybeLoadFallbackForRedirect(nullptr,
+ GURL("http://blah/redirect")));
EXPECT_FALSE(fallback_job);
- fallback_job.reset(static_cast<AppCacheURLRequestJob*>(
- handler_->MaybeLoadFallbackForResponse(
- request_->context()->network_delegate())));
+ fallback_job.reset(handler_->MaybeLoadFallbackForResponse(nullptr));
EXPECT_FALSE(fallback_job);
TestFinished();
@@ -664,28 +643,36 @@ class AppCacheRequestHandlerTest : public testing::Test {
mock_storage()->SimulateFindSubResource(
AppCacheEntry(), AppCacheEntry(AppCacheEntry::EXPLICIT, 1), false);
- request_ = empty_context_->CreateRequest(GURL("http://blah/"),
- net::DEFAULT_PRIORITY, &delegate_,
- TRAFFIC_ANNOTATION_FOR_TESTS);
- handler_ =
- host_->CreateRequestHandler(AppCacheURLRequest::Create(request_.get()),
- RESOURCE_TYPE_SUB_RESOURCE, false);
+ EXPECT_TRUE(CreateRequestAndHandler(GURL("http://blah/"), host_,
+ RESOURCE_TYPE_SUB_RESOURCE));
EXPECT_TRUE(handler_.get());
- job_.reset(static_cast<AppCacheURLRequestJob*>(
- handler_->MaybeLoadResource(request_->context()->network_delegate())));
- EXPECT_FALSE(job_.get());
+ job_.reset(handler_->MaybeLoadResource(nullptr));
+ // If the request goes to the network, the URLRequest job is destroyed. The
+ // URLLoader job is destroyed when the URLLoaderClient disconnects.
+ if (request_handler_type_ == URLREQUEST) {
+ EXPECT_FALSE(job_.get());
+ } else {
+ // In the URLLoader world, the same job instance is used to provide the
+ // fallback.
+ EXPECT_TRUE(job_.get());
+ EXPECT_TRUE(job_->IsDeliveringNetworkResponse());
+ }
- job_.reset(static_cast<AppCacheURLRequestJob*>(
- handler_->MaybeLoadFallbackForRedirect(
- request_->context()->network_delegate(),
- GURL("http://not_blah/redirect"))));
- EXPECT_TRUE(job_.get());
- EXPECT_TRUE(job_->IsDeliveringAppCacheResponse());
+ std::unique_ptr<AppCacheJob> redirect_fallback_job;
+ redirect_fallback_job.reset(handler_->MaybeLoadFallbackForRedirect(
+ nullptr, GURL("http://not_blah/redirect")));
+ EXPECT_TRUE(redirect_fallback_job.get());
+ EXPECT_TRUE(redirect_fallback_job->IsDeliveringAppCacheResponse());
+
+ if (request_handler_type_ == URLLOADER) {
+ // In the URLLoader world, the same job instance is used to provide the
+ // fallback.
+ EXPECT_EQ(job_.get(), redirect_fallback_job.get());
+ job_.release();
+ }
- std::unique_ptr<AppCacheURLRequestJob> fallback_job(
- static_cast<AppCacheURLRequestJob*>(
- handler_->MaybeLoadFallbackForResponse(
- request_->context()->network_delegate())));
+ std::unique_ptr<AppCacheJob> fallback_job(
+ handler_->MaybeLoadFallbackForResponse(nullptr));
EXPECT_FALSE(fallback_job);
TestFinished();
@@ -701,28 +688,30 @@ class AppCacheRequestHandlerTest : public testing::Test {
mock_storage()->SimulateFindSubResource(
AppCacheEntry(), AppCacheEntry(AppCacheEntry::EXPLICIT, 1), false);
- request_ = empty_context_->CreateRequest(GURL("http://blah/"),
- net::DEFAULT_PRIORITY, &delegate_,
- TRAFFIC_ANNOTATION_FOR_TESTS);
- handler_ =
- host_->CreateRequestHandler(AppCacheURLRequest::Create(request_.get()),
- RESOURCE_TYPE_SUB_RESOURCE, false);
+ EXPECT_TRUE(CreateRequestAndHandler(GURL("http://blah/"), host_,
+ RESOURCE_TYPE_SUB_RESOURCE));
EXPECT_TRUE(handler_.get());
- job_.reset(static_cast<AppCacheURLRequestJob*>(
- handler_->MaybeLoadResource(request_->context()->network_delegate())));
- EXPECT_FALSE(job_.get());
+ job_.reset(handler_->MaybeLoadResource(nullptr));
+ if (request_handler_type_ == URLREQUEST) {
+ EXPECT_FALSE(job_.get());
+ } else {
+ // In the URLLoader world, the same job instance is used to provide the
+ // fallback.
+ EXPECT_TRUE(job_.get());
+ EXPECT_TRUE(job_->IsDeliveringNetworkResponse());
+ }
- std::unique_ptr<AppCacheURLRequestJob> fallback_job(
- static_cast<AppCacheURLRequestJob*>(
- handler_->MaybeLoadFallbackForRedirect(
- request_->context()->network_delegate(),
- GURL("http://blah/redirect"))));
+ std::unique_ptr<AppCacheJob> fallback_job(
+ handler_->MaybeLoadFallbackForRedirect(nullptr,
+ GURL("http://blah/redirect")));
EXPECT_FALSE(fallback_job);
+ // Fallback responses are provided by a new job instance.
+ if (request_handler_type_ == URLLOADER)
+ job_.reset(nullptr);
+
SimulateResponseCode(200);
- fallback_job.reset(static_cast<AppCacheURLRequestJob*>(
- handler_->MaybeLoadFallbackForResponse(
- request_->context()->network_delegate())));
+ fallback_job.reset(handler_->MaybeLoadFallbackForResponse(nullptr));
EXPECT_FALSE(fallback_job);
TestFinished();
@@ -739,26 +728,24 @@ class AppCacheRequestHandlerTest : public testing::Test {
mock_storage()->SimulateFindSubResource(
AppCacheEntry(), AppCacheEntry(), true);
- request_ = empty_context_->CreateRequest(GURL("http://blah/"),
- net::DEFAULT_PRIORITY, &delegate_,
- TRAFFIC_ANNOTATION_FOR_TESTS);
- handler_ =
- host_->CreateRequestHandler(AppCacheURLRequest::Create(request_.get()),
- RESOURCE_TYPE_SUB_RESOURCE, false);
+ EXPECT_TRUE(CreateRequestAndHandler(GURL("http://blah/"), host_,
+ RESOURCE_TYPE_SUB_RESOURCE));
EXPECT_TRUE(handler_.get());
- job_.reset(static_cast<AppCacheURLRequestJob*>(
- handler_->MaybeLoadResource(request_->context()->network_delegate())));
- EXPECT_FALSE(job_.get());
+ job_.reset(handler_->MaybeLoadResource(nullptr));
+ // If the request goes to the network, the URLRequest job is destroyed. The
+ // URLLoader job is destroyed when the URLLoaderClient disconnects.
+ if (request_handler_type_ == URLREQUEST) {
+ EXPECT_FALSE(job_.get());
+ } else {
+ EXPECT_TRUE(job_.get());
+ EXPECT_TRUE(job_->IsDeliveringNetworkResponse());
+ }
- std::unique_ptr<AppCacheURLRequestJob> fallback_job(
- static_cast<AppCacheURLRequestJob*>(
- handler_->MaybeLoadFallbackForRedirect(
- request_->context()->network_delegate(),
- GURL("http://blah/redirect"))));
+ std::unique_ptr<AppCacheJob> fallback_job(
+ handler_->MaybeLoadFallbackForRedirect(nullptr,
+ GURL("http://blah/redirect")));
EXPECT_FALSE(fallback_job);
- fallback_job.reset(static_cast<AppCacheURLRequestJob*>(
- handler_->MaybeLoadFallbackForResponse(
- request_->context()->network_delegate())));
+ fallback_job.reset(handler_->MaybeLoadFallbackForResponse(nullptr));
EXPECT_FALSE(fallback_job);
TestFinished();
@@ -772,26 +759,17 @@ class AppCacheRequestHandlerTest : public testing::Test {
mock_storage()->SimulateFindSubResource(
AppCacheEntry(AppCacheEntry::EXPLICIT, 1), AppCacheEntry(), false);
- request_ = empty_context_->CreateRequest(GURL("http://blah/"),
- net::DEFAULT_PRIORITY, &delegate_,
- TRAFFIC_ANNOTATION_FOR_TESTS);
- handler_ =
- host_->CreateRequestHandler(AppCacheURLRequest::Create(request_.get()),
- RESOURCE_TYPE_SUB_RESOURCE, false);
+ EXPECT_TRUE(CreateRequestAndHandler(GURL("http://blah/"), host_,
+ RESOURCE_TYPE_SUB_RESOURCE));
EXPECT_TRUE(handler_.get());
backend_impl_->UnregisterHost(1);
host_ = NULL;
- EXPECT_FALSE(static_cast<AppCacheURLRequestJob*>(
- handler_->MaybeLoadResource(request_->context()->network_delegate())));
- EXPECT_FALSE(static_cast<AppCacheURLRequestJob*>(
- handler_->MaybeLoadFallbackForRedirect(
- request_->context()->network_delegate(),
- GURL("http://blah/redirect"))));
- EXPECT_FALSE(static_cast<AppCacheURLRequestJob*>(
- handler_->MaybeLoadFallbackForResponse(
- request_->context()->network_delegate())));
+ EXPECT_FALSE(handler_->MaybeLoadResource(nullptr));
+ EXPECT_FALSE(handler_->MaybeLoadFallbackForRedirect(
+ nullptr, GURL("http://blah/redirect")));
+ EXPECT_FALSE(handler_->MaybeLoadFallbackForResponse(nullptr));
TestFinished();
}
@@ -802,32 +780,25 @@ class AppCacheRequestHandlerTest : public testing::Test {
// Precondition, the host is waiting on cache selection.
host_->pending_selected_cache_id_ = 1;
- request_ = empty_context_->CreateRequest(GURL("http://blah/"),
- net::DEFAULT_PRIORITY, &delegate_,
- TRAFFIC_ANNOTATION_FOR_TESTS);
- handler_ =
- host_->CreateRequestHandler(AppCacheURLRequest::Create(request_.get()),
- RESOURCE_TYPE_SUB_RESOURCE, false);
+ EXPECT_TRUE(CreateRequestAndHandler(GURL("http://blah/"), host_,
+ RESOURCE_TYPE_SUB_RESOURCE));
EXPECT_TRUE(handler_.get());
- job_.reset(static_cast<AppCacheURLRequestJob*>(
- handler_->MaybeLoadResource(request_->context()->network_delegate())));
+ job_.reset(handler_->MaybeLoadResource(nullptr));
EXPECT_TRUE(job_.get());
EXPECT_TRUE(job_->IsWaiting());
backend_impl_->UnregisterHost(1);
host_ = NULL;
- EXPECT_TRUE(job_->has_been_killed());
-
- EXPECT_FALSE(static_cast<AppCacheURLRequestJob*>(
- handler_->MaybeLoadResource(request_->context()->network_delegate())));
- EXPECT_FALSE(static_cast<AppCacheURLRequestJob*>(
- handler_->MaybeLoadFallbackForRedirect(
- request_->context()->network_delegate(),
- GURL("http://blah/redirect"))));
- EXPECT_FALSE(static_cast<AppCacheURLRequestJob*>(
- handler_->MaybeLoadFallbackForResponse(
- request_->context()->network_delegate())));
+
+ if (request_handler_type_ == URLREQUEST) {
+ EXPECT_TRUE(
+ static_cast<AppCacheURLRequestJob*>(job_.get())->has_been_killed());
+ }
+ EXPECT_FALSE(handler_->MaybeLoadResource(nullptr));
+ EXPECT_FALSE(handler_->MaybeLoadFallbackForRedirect(
+ nullptr, GURL("http://blah/redirect")));
+ EXPECT_FALSE(handler_->MaybeLoadFallbackForResponse(nullptr));
TestFinished();
}
@@ -840,15 +811,10 @@ class AppCacheRequestHandlerTest : public testing::Test {
mock_storage()->SimulateFindSubResource(
AppCacheEntry(AppCacheEntry::EXPLICIT, 1), AppCacheEntry(), false);
- request_ = empty_context_->CreateRequest(GURL("http://blah/"),
- net::DEFAULT_PRIORITY, &delegate_,
- TRAFFIC_ANNOTATION_FOR_TESTS);
- handler_ =
- host_->CreateRequestHandler(AppCacheURLRequest::Create(request_.get()),
- RESOURCE_TYPE_SUB_RESOURCE, false);
+ EXPECT_TRUE(CreateRequestAndHandler(GURL("http://blah/"), host_,
+ RESOURCE_TYPE_SUB_RESOURCE));
EXPECT_TRUE(handler_.get());
- job_.reset(static_cast<AppCacheURLRequestJob*>(
- handler_->MaybeLoadResource(request_->context()->network_delegate())));
+ job_.reset(handler_->MaybeLoadResource(nullptr));
EXPECT_TRUE(job_.get());
backend_impl_.reset();
@@ -857,27 +823,21 @@ class AppCacheRequestHandlerTest : public testing::Test {
mock_policy_.reset();
host_ = NULL;
- EXPECT_TRUE(job_->has_been_killed());
- EXPECT_FALSE(static_cast<AppCacheURLRequestJob*>(
- handler_->MaybeLoadResource(request_->context()->network_delegate())));
- EXPECT_FALSE(static_cast<AppCacheURLRequestJob*>(
- handler_->MaybeLoadFallbackForRedirect(
- request_->context()->network_delegate(),
- GURL("http://blah/redirect"))));
- EXPECT_FALSE(static_cast<AppCacheURLRequestJob*>(
- handler_->MaybeLoadFallbackForResponse(
- request_->context()->network_delegate())));
+ if (request_handler_type_ == URLREQUEST) {
+ EXPECT_TRUE(
+ static_cast<AppCacheURLRequestJob*>(job_.get())->has_been_killed());
+ }
+ EXPECT_FALSE(handler_->MaybeLoadResource(nullptr));
+ EXPECT_FALSE(handler_->MaybeLoadFallbackForRedirect(
+ nullptr, GURL("http://blah/redirect")));
+ EXPECT_FALSE(handler_->MaybeLoadFallbackForResponse(nullptr));
TestFinished();
}
void DestroyedServiceWithCrossSiteNav() {
- request_ = empty_context_->CreateRequest(GURL("http://blah/"),
- net::DEFAULT_PRIORITY, &delegate_,
- TRAFFIC_ANNOTATION_FOR_TESTS);
- handler_ =
- host_->CreateRequestHandler(AppCacheURLRequest::Create(request_.get()),
- RESOURCE_TYPE_MAIN_FRAME, false);
+ EXPECT_TRUE(CreateRequestAndHandler(GURL("http://blah/"), host_,
+ RESOURCE_TYPE_MAIN_FRAME));
EXPECT_TRUE(handler_.get());
handler_->PrepareForCrossSiteTransfer(backend_impl_->process_id());
EXPECT_TRUE(handler_->host_for_cross_site_transfer_.get());
@@ -889,15 +849,10 @@ class AppCacheRequestHandlerTest : public testing::Test {
host_ = NULL;
EXPECT_FALSE(handler_->host_for_cross_site_transfer_.get());
- EXPECT_FALSE(static_cast<AppCacheURLRequestJob*>(
- handler_->MaybeLoadResource(request_->context()->network_delegate())));
- EXPECT_FALSE(static_cast<AppCacheURLRequestJob*>(
- handler_->MaybeLoadFallbackForRedirect(
- request_->context()->network_delegate(),
- GURL("http://blah/redirect"))));
- EXPECT_FALSE(static_cast<AppCacheURLRequestJob*>(
- handler_->MaybeLoadFallbackForResponse(
- request_->context()->network_delegate())));
+ EXPECT_FALSE(handler_->MaybeLoadResource(nullptr));
+ EXPECT_FALSE(handler_->MaybeLoadFallbackForRedirect(
+ nullptr, GURL("http://blah/redirect")));
+ EXPECT_FALSE(handler_->MaybeLoadFallbackForResponse(nullptr));
TestFinished();
}
@@ -908,23 +863,14 @@ class AppCacheRequestHandlerTest : public testing::Test {
// Precondition, the host is waiting on cache selection.
host_->pending_selected_cache_id_ = 1;
- request_ = empty_context_->CreateRequest(GURL("ftp://blah/"),
- net::DEFAULT_PRIORITY, &delegate_,
- TRAFFIC_ANNOTATION_FOR_TESTS);
- handler_ =
- host_->CreateRequestHandler(AppCacheURLRequest::Create(request_.get()),
- RESOURCE_TYPE_SUB_RESOURCE, false);
+ EXPECT_TRUE(CreateRequestAndHandler(GURL("ftp://blah/"), host_,
+ RESOURCE_TYPE_SUB_RESOURCE));
EXPECT_TRUE(handler_.get()); // we could redirect to http (conceivably)
- EXPECT_FALSE(static_cast<AppCacheURLRequestJob*>(
- handler_->MaybeLoadResource(request_->context()->network_delegate())));
- EXPECT_FALSE(static_cast<AppCacheURLRequestJob*>(
- handler_->MaybeLoadFallbackForRedirect(
- request_->context()->network_delegate(),
- GURL("ftp://blah/redirect"))));
- EXPECT_FALSE(static_cast<AppCacheURLRequestJob*>(
- handler_->MaybeLoadFallbackForResponse(
- request_->context()->network_delegate())));
+ EXPECT_FALSE(handler_->MaybeLoadResource(nullptr));
+ EXPECT_FALSE(handler_->MaybeLoadFallbackForRedirect(
+ nullptr, GURL("ftp://blah/redirect")));
+ EXPECT_FALSE(handler_->MaybeLoadFallbackForResponse(nullptr));
TestFinished();
}
@@ -932,33 +878,33 @@ class AppCacheRequestHandlerTest : public testing::Test {
// CanceledRequest -----------------------------
void CanceledRequest() {
- request_ = empty_context_->CreateRequest(GURL("http://blah/"),
- net::DEFAULT_PRIORITY, &delegate_,
- TRAFFIC_ANNOTATION_FOR_TESTS);
- handler_ =
- host_->CreateRequestHandler(AppCacheURLRequest::Create(request_.get()),
- RESOURCE_TYPE_MAIN_FRAME, false);
+ EXPECT_TRUE(CreateRequestAndHandler(GURL("http://blah/"), host_,
+ RESOURCE_TYPE_MAIN_FRAME));
EXPECT_TRUE(handler_.get());
- job_.reset(static_cast<AppCacheURLRequestJob*>(
- handler_->MaybeLoadResource(request_->context()->network_delegate())));
+ job_.reset(handler_->MaybeLoadResource(nullptr));
EXPECT_TRUE(job_.get());
EXPECT_TRUE(job_->IsWaiting());
EXPECT_FALSE(job_->IsStarted());
base::WeakPtr<AppCacheJob> weak_job = job_->GetWeakPtr();
- job_factory_->SetJob(std::move(job_));
- request_->Start();
- ASSERT_TRUE(weak_job);
- EXPECT_TRUE(weak_job->IsStarted());
+ // TODO(ananta/michaeln)
+ // Rewrite this test for URLLoader.
+ if (request_handler_type_ == URLREQUEST) {
+ std::unique_ptr<AppCacheURLRequestJob> job(
+ static_cast<AppCacheURLRequestJob*>(job_.release()));
+ job_factory_->SetJob(std::move(job));
- request_->Cancel();
- ASSERT_FALSE(weak_job);
+ request_->AsURLRequest()->GetURLRequest()->Start();
+ ASSERT_TRUE(weak_job);
+ EXPECT_TRUE(weak_job->IsStarted());
- EXPECT_FALSE(static_cast<AppCacheURLRequestJob*>(
- handler_->MaybeLoadFallbackForResponse(
- request_->context()->network_delegate())));
+ request_->AsURLRequest()->GetURLRequest()->Cancel();
+ ASSERT_FALSE(weak_job);
+ }
+
+ EXPECT_FALSE(handler_->MaybeLoadFallbackForResponse(nullptr));
TestFinished();
}
@@ -975,9 +921,6 @@ class AppCacheRequestHandlerTest : public testing::Test {
EXPECT_FALSE(AppCacheRequestHandler::IsMainResourceType(
RESOURCE_TYPE_WORKER));
- request_ = empty_context_->CreateRequest(GURL("http://blah/"),
- net::DEFAULT_PRIORITY, &delegate_,
- TRAFFIC_ANNOTATION_FOR_TESTS);
const int kParentHostId = host_->host_id();
const int kWorkerHostId = 2;
@@ -987,9 +930,8 @@ class AppCacheRequestHandlerTest : public testing::Test {
backend_impl_->RegisterHost(kWorkerHostId);
AppCacheHost* worker_host = backend_impl_->GetHost(kWorkerHostId);
worker_host->SelectCacheForWorker(kParentHostId, kMockProcessId);
- handler_ = worker_host->CreateRequestHandler(
- AppCacheURLRequest::Create(request_.get()), RESOURCE_TYPE_SHARED_WORKER,
- false);
+ EXPECT_TRUE(CreateRequestAndHandler(GURL("http://blah/"), worker_host,
+ RESOURCE_TYPE_SHARED_WORKER));
EXPECT_TRUE(handler_.get());
// Verify that the handler is associated with the parent host.
EXPECT_EQ(host_, handler_->host_);
@@ -1001,9 +943,8 @@ class AppCacheRequestHandlerTest : public testing::Test {
worker_host = backend_impl_->GetHost(kAbandonedWorkerHostId);
EXPECT_EQ(NULL, backend_impl_->GetHost(kNonExsitingHostId));
worker_host->SelectCacheForWorker(kNonExsitingHostId, kMockProcessId);
- handler_ = worker_host->CreateRequestHandler(
- AppCacheURLRequest::Create(request_.get()), RESOURCE_TYPE_SHARED_WORKER,
- false);
+ EXPECT_TRUE(CreateRequestAndHandler(GURL("http://blah/"), worker_host,
+ RESOURCE_TYPE_SHARED_WORKER));
EXPECT_FALSE(handler_.get());
TestFinished();
@@ -1016,12 +957,8 @@ class AppCacheRequestHandlerTest : public testing::Test {
base::Bind(&AppCacheRequestHandlerTest::Verify_MainResource_Blocked,
base::Unretained(this)));
- request_ = empty_context_->CreateRequest(GURL("http://blah/"),
- net::DEFAULT_PRIORITY, &delegate_,
- TRAFFIC_ANNOTATION_FOR_TESTS);
- handler_ =
- host_->CreateRequestHandler(AppCacheURLRequest::Create(request_.get()),
- RESOURCE_TYPE_MAIN_FRAME, false);
+ EXPECT_TRUE(CreateRequestAndHandler(GURL("http://blah/"), host_,
+ RESOURCE_TYPE_MAIN_FRAME));
EXPECT_TRUE(handler_.get());
mock_policy_->can_load_return_value_ = false;
@@ -1030,8 +967,7 @@ class AppCacheRequestHandlerTest : public testing::Test {
GURL(), AppCacheEntry(),
1, 2, GURL("http://blah/manifest/"));
- job_.reset(static_cast<AppCacheURLRequestJob*>(
- handler_->MaybeLoadResource(request_->context()->network_delegate())));
+ job_.reset(handler_->MaybeLoadResource(nullptr));
EXPECT_TRUE(job_.get());
EXPECT_TRUE(job_->IsWaiting());
@@ -1070,10 +1006,37 @@ class AppCacheRequestHandlerTest : public testing::Test {
return reinterpret_cast<MockAppCacheStorage*>(mock_service_->storage());
}
+ bool CreateRequestAndHandler(const GURL& url,
+ AppCacheHost* host,
+ ResourceType resource_type) {
+ if (request_handler_type_ == URLREQUEST) {
+ url_request_ = empty_context_->CreateRequest(
+ url, net::DEFAULT_PRIORITY, &delegate_, TRAFFIC_ANNOTATION_FOR_TESTS);
+
+ std::unique_ptr<AppCacheRequest> request =
+ AppCacheURLRequest::Create(url_request_.get());
+ request_ = request.get();
+ handler_ =
+ host->CreateRequestHandler(std::move(request), resource_type, false);
+ return true;
+ } else if (request_handler_type_ == URLLOADER) {
+ ResourceRequest resource_request;
+ resource_request.url = url;
+ resource_request.method = "GET";
+ std::unique_ptr<AppCacheRequest> request =
+ AppCacheURLLoaderRequest::Create(resource_request);
+ request_ = request.get();
+ handler_ =
+ host->CreateRequestHandler(std::move(request), resource_type, false);
+ return true;
+ }
+ return false;
+ }
+
// Data members --------------------------------------------------
std::unique_ptr<base::WaitableEvent> test_finished_event_;
- std::stack<base::Closure> task_stack_;
+ std::stack<base::OnceClosure> task_stack_;
std::unique_ptr<MockAppCacheService> mock_service_;
std::unique_ptr<AppCacheBackendImpl> backend_impl_;
std::unique_ptr<MockFrontend> mock_frontend_;
@@ -1082,13 +1045,17 @@ class AppCacheRequestHandlerTest : public testing::Test {
std::unique_ptr<net::URLRequestContext> empty_context_;
std::unique_ptr<MockURLRequestJobFactory> job_factory_;
MockURLRequestDelegate delegate_;
- std::unique_ptr<net::URLRequest> request_;
+ AppCacheRequest* request_;
+ std::unique_ptr<net::URLRequest> url_request_;
std::unique_ptr<AppCacheRequestHandler> handler_;
- std::unique_ptr<AppCacheURLRequestJob> job_;
+ std::unique_ptr<AppCacheJob> job_;
static std::unique_ptr<base::Thread> io_thread_;
static std::unique_ptr<base::test::ScopedTaskEnvironment>
scoped_task_environment_;
+
+ RequestHandlerType request_handler_type_;
+ base::test::ScopedFeatureList feature_list_;
};
// static
@@ -1096,87 +1063,90 @@ std::unique_ptr<base::Thread> AppCacheRequestHandlerTest::io_thread_;
std::unique_ptr<base::test::ScopedTaskEnvironment>
AppCacheRequestHandlerTest::scoped_task_environment_;
-TEST_F(AppCacheRequestHandlerTest, MainResource_Miss) {
+TEST_P(AppCacheRequestHandlerTest, MainResource_Miss) {
RunTestOnIOThread(&AppCacheRequestHandlerTest::MainResource_Miss);
}
-TEST_F(AppCacheRequestHandlerTest, MainResource_Hit) {
+TEST_P(AppCacheRequestHandlerTest, MainResource_Hit) {
RunTestOnIOThread(&AppCacheRequestHandlerTest::MainResource_Hit);
}
-TEST_F(AppCacheRequestHandlerTest, MainResource_Fallback) {
+TEST_P(AppCacheRequestHandlerTest, MainResource_Fallback) {
RunTestOnIOThread(&AppCacheRequestHandlerTest::MainResource_Fallback);
}
-TEST_F(AppCacheRequestHandlerTest, MainResource_FallbackOverride) {
+TEST_P(AppCacheRequestHandlerTest, MainResource_FallbackOverride) {
RunTestOnIOThread(
&AppCacheRequestHandlerTest::MainResource_FallbackOverride);
}
-TEST_F(AppCacheRequestHandlerTest, SubResource_Miss_WithNoCacheSelected) {
+TEST_P(AppCacheRequestHandlerTest, SubResource_Miss_WithNoCacheSelected) {
RunTestOnIOThread(
&AppCacheRequestHandlerTest::SubResource_Miss_WithNoCacheSelected);
}
-TEST_F(AppCacheRequestHandlerTest, SubResource_Miss_WithCacheSelected) {
+TEST_P(AppCacheRequestHandlerTest, SubResource_Miss_WithCacheSelected) {
RunTestOnIOThread(
&AppCacheRequestHandlerTest::SubResource_Miss_WithCacheSelected);
}
-TEST_F(AppCacheRequestHandlerTest,
- SubResource_Miss_WithWaitForCacheSelection) {
+TEST_P(AppCacheRequestHandlerTest, SubResource_Miss_WithWaitForCacheSelection) {
RunTestOnIOThread(
&AppCacheRequestHandlerTest::SubResource_Miss_WithWaitForCacheSelection);
}
-TEST_F(AppCacheRequestHandlerTest, SubResource_Hit) {
+TEST_P(AppCacheRequestHandlerTest, SubResource_Hit) {
RunTestOnIOThread(&AppCacheRequestHandlerTest::SubResource_Hit);
}
-TEST_F(AppCacheRequestHandlerTest, SubResource_RedirectFallback) {
+TEST_P(AppCacheRequestHandlerTest, SubResource_RedirectFallback) {
RunTestOnIOThread(&AppCacheRequestHandlerTest::SubResource_RedirectFallback);
}
-TEST_F(AppCacheRequestHandlerTest, SubResource_NoRedirectFallback) {
+TEST_P(AppCacheRequestHandlerTest, SubResource_NoRedirectFallback) {
RunTestOnIOThread(
&AppCacheRequestHandlerTest::SubResource_NoRedirectFallback);
}
-TEST_F(AppCacheRequestHandlerTest, SubResource_Network) {
+TEST_P(AppCacheRequestHandlerTest, SubResource_Network) {
RunTestOnIOThread(&AppCacheRequestHandlerTest::SubResource_Network);
}
-TEST_F(AppCacheRequestHandlerTest, DestroyedHost) {
+TEST_P(AppCacheRequestHandlerTest, DestroyedHost) {
RunTestOnIOThread(&AppCacheRequestHandlerTest::DestroyedHost);
}
-TEST_F(AppCacheRequestHandlerTest, DestroyedHostWithWaitingJob) {
+TEST_P(AppCacheRequestHandlerTest, DestroyedHostWithWaitingJob) {
RunTestOnIOThread(&AppCacheRequestHandlerTest::DestroyedHostWithWaitingJob);
}
-TEST_F(AppCacheRequestHandlerTest, DestroyedService) {
+TEST_P(AppCacheRequestHandlerTest, DestroyedService) {
RunTestOnIOThread(&AppCacheRequestHandlerTest::DestroyedService);
}
-TEST_F(AppCacheRequestHandlerTest, DestroyedServiceWithCrossSiteNav) {
+TEST_P(AppCacheRequestHandlerTest, DestroyedServiceWithCrossSiteNav) {
RunTestOnIOThread(
&AppCacheRequestHandlerTest::DestroyedServiceWithCrossSiteNav);
}
-TEST_F(AppCacheRequestHandlerTest, UnsupportedScheme) {
+TEST_P(AppCacheRequestHandlerTest, UnsupportedScheme) {
RunTestOnIOThread(&AppCacheRequestHandlerTest::UnsupportedScheme);
}
-TEST_F(AppCacheRequestHandlerTest, CanceledRequest) {
+TEST_P(AppCacheRequestHandlerTest, CanceledRequest) {
RunTestOnIOThread(&AppCacheRequestHandlerTest::CanceledRequest);
}
-TEST_F(AppCacheRequestHandlerTest, WorkerRequest) {
+TEST_P(AppCacheRequestHandlerTest, WorkerRequest) {
RunTestOnIOThread(&AppCacheRequestHandlerTest::WorkerRequest);
}
-TEST_F(AppCacheRequestHandlerTest, MainResource_Blocked) {
+TEST_P(AppCacheRequestHandlerTest, MainResource_Blocked) {
RunTestOnIOThread(&AppCacheRequestHandlerTest::MainResource_Blocked);
}
+INSTANTIATE_TEST_CASE_P(,
+ AppCacheRequestHandlerTest,
+ ::testing::Values(URLREQUEST, URLLOADER));
+
} // namespace content
diff --git a/chromium/content/browser/appcache/appcache_response.cc b/chromium/content/browser/appcache/appcache_response.cc
index 7a33785f283..13698f0e038 100644
--- a/chromium/content/browser/appcache/appcache_response.cc
+++ b/chromium/content/browser/appcache/appcache_response.cc
@@ -109,8 +109,8 @@ AppCacheResponseIO::~AppCacheResponseIO() {
void AppCacheResponseIO::ScheduleIOCompletionCallback(int result) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&AppCacheResponseIO::OnIOComplete,
- weak_factory_.GetWeakPtr(), result));
+ FROM_HERE, base::BindOnce(&AppCacheResponseIO::OnIOComplete,
+ weak_factory_.GetWeakPtr(), result));
}
void AppCacheResponseIO::InvokeUserCompletionCallback(int result) {
diff --git a/chromium/content/browser/appcache/appcache_response_unittest.cc b/chromium/content/browser/appcache/appcache_response_unittest.cc
index 34ed2c41f71..223b6c25218 100644
--- a/chromium/content/browser/appcache/appcache_response_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_response_unittest.cc
@@ -15,6 +15,7 @@
#include "base/compiler_specific.h"
#include "base/location.h"
#include "base/macros.h"
+#include "base/message_loop/message_loop.h"
#include "base/pickle.h"
#include "base/single_thread_task_runner.h"
#include "base/synchronization/waitable_event.h"
@@ -88,8 +89,8 @@ class AppCacheResponseTest : public testing::Test {
base::WaitableEvent::ResetPolicy::AUTOMATIC,
base::WaitableEvent::InitialState::NOT_SIGNALED));
io_thread_->task_runner()->PostTask(
- FROM_HERE, base::Bind(&AppCacheResponseTest::MethodWrapper<Method>,
- base::Unretained(this), method));
+ FROM_HERE, base::BindOnce(&AppCacheResponseTest::MethodWrapper<Method>,
+ base::Unretained(this), method));
test_finished_event_->Wait();
}
@@ -129,8 +130,8 @@ class AppCacheResponseTest : public testing::Test {
// based objects get deleted.
DCHECK(io_thread_->task_runner()->BelongsToCurrentThread());
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&AppCacheResponseTest::TestFinishedUnwound,
- base::Unretained(this)));
+ FROM_HERE, base::BindOnce(&AppCacheResponseTest::TestFinishedUnwound,
+ base::Unretained(this)));
}
void TestFinishedUnwound() {
@@ -138,12 +139,13 @@ class AppCacheResponseTest : public testing::Test {
test_finished_event_->Signal();
}
- void PushNextTask(const base::Closure& task) {
- task_stack_.push(std::pair<base::Closure, bool>(task, false));
+ void PushNextTask(base::OnceClosure task) {
+ task_stack_.push(
+ std::pair<base::OnceClosure, bool>(std::move(task), false));
}
- void PushNextTaskAsImmediate(const base::Closure& task) {
- task_stack_.push(std::pair<base::Closure, bool>(task, true));
+ void PushNextTaskAsImmediate(base::OnceClosure task) {
+ task_stack_.push(std::pair<base::OnceClosure, bool>(std::move(task), true));
}
void ScheduleNextTask() {
@@ -152,13 +154,13 @@ class AppCacheResponseTest : public testing::Test {
TestFinished();
return;
}
- base::Closure task = task_stack_.top().first;
+ base::OnceClosure task = std::move(task_stack_.top().first);
bool immediate = task_stack_.top().second;
task_stack_.pop();
if (immediate)
- task.Run();
+ std::move(task).Run();
else
- base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, task);
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, std::move(task));
}
// Wrappers to call AppCacheResponseReader/Writer Read and Write methods
@@ -179,8 +181,8 @@ class AppCacheResponseTest : public testing::Test {
IOBuffer* body, int body_len) {
DCHECK(body);
scoped_refptr<IOBuffer> body_ref(body);
- PushNextTask(base::Bind(&AppCacheResponseTest::WriteResponseBody,
- base::Unretained(this), body_ref, body_len));
+ PushNextTask(base::BindOnce(&AppCacheResponseTest::WriteResponseBody,
+ base::Unretained(this), body_ref, body_len));
WriteResponseHead(head);
}
@@ -327,10 +329,10 @@ class AppCacheResponseTest : public testing::Test {
service_->storage()->CreateResponseReader(GURL(), kNoSuchResponseId));
// Push tasks in reverse order
- PushNextTask(base::Bind(&AppCacheResponseTest::ReadNonExistentData,
- base::Unretained(this)));
- PushNextTask(base::Bind(&AppCacheResponseTest::ReadNonExistentInfo,
- base::Unretained(this)));
+ PushNextTask(base::BindOnce(&AppCacheResponseTest::ReadNonExistentData,
+ base::Unretained(this)));
+ PushNextTask(base::BindOnce(&AppCacheResponseTest::ReadNonExistentInfo,
+ base::Unretained(this)));
ScheduleNextTask();
}
@@ -357,8 +359,9 @@ class AppCacheResponseTest : public testing::Test {
// LoadResponseInfo_Miss ----------------------------------------------------
void LoadResponseInfo_Miss() {
- PushNextTask(base::Bind(&AppCacheResponseTest::LoadResponseInfo_Miss_Verify,
- base::Unretained(this)));
+ PushNextTask(
+ base::BindOnce(&AppCacheResponseTest::LoadResponseInfo_Miss_Verify,
+ base::Unretained(this)));
service_->storage()->LoadResponseInfo(GURL(), kNoSuchResponseId,
storage_delegate_.get());
}
@@ -376,8 +379,9 @@ class AppCacheResponseTest : public testing::Test {
// a. headers
// b. body
// 2. Use LoadResponseInfo to read the response headers back out
- PushNextTask(base::Bind(&AppCacheResponseTest::LoadResponseInfo_Hit_Step2,
- base::Unretained(this)));
+ PushNextTask(
+ base::BindOnce(&AppCacheResponseTest::LoadResponseInfo_Hit_Step2,
+ base::Unretained(this)));
writer_.reset(service_->storage()->CreateResponseWriter(GURL()));
written_response_id_ = writer_->response_id();
WriteBasicResponse();
@@ -385,8 +389,9 @@ class AppCacheResponseTest : public testing::Test {
void LoadResponseInfo_Hit_Step2() {
writer_.reset();
- PushNextTask(base::Bind(&AppCacheResponseTest::LoadResponseInfo_Hit_Verify,
- base::Unretained(this)));
+ PushNextTask(
+ base::BindOnce(&AppCacheResponseTest::LoadResponseInfo_Hit_Verify,
+ base::Unretained(this)));
service_->storage()->LoadResponseInfo(GURL(), written_response_id_,
storage_delegate_.get());
}
@@ -416,26 +421,29 @@ class AppCacheResponseTest : public testing::Test {
// 7. Check metadata was deleted.
// Push tasks in reverse order.
- PushNextTask(base::Bind(&AppCacheResponseTest::Metadata_VerifyMetadata,
- base::Unretained(this), ""));
- PushNextTask(base::Bind(&AppCacheResponseTest::Metadata_LoadResponseInfo,
- base::Unretained(this)));
- PushNextTask(base::Bind(&AppCacheResponseTest::Metadata_WriteMetadata,
- base::Unretained(this), ""));
- PushNextTask(base::Bind(&AppCacheResponseTest::Metadata_VerifyMetadata,
- base::Unretained(this), "Second"));
- PushNextTask(base::Bind(&AppCacheResponseTest::Metadata_LoadResponseInfo,
- base::Unretained(this)));
- PushNextTask(base::Bind(&AppCacheResponseTest::Metadata_WriteMetadata,
- base::Unretained(this), "Second"));
- PushNextTask(base::Bind(&AppCacheResponseTest::Metadata_VerifyMetadata,
- base::Unretained(this), "Metadata First"));
- PushNextTask(base::Bind(&AppCacheResponseTest::Metadata_LoadResponseInfo,
- base::Unretained(this)));
- PushNextTask(base::Bind(&AppCacheResponseTest::Metadata_WriteMetadata,
- base::Unretained(this), "Metadata First"));
- PushNextTask(base::Bind(&AppCacheResponseTest::Metadata_ResetWriter,
- base::Unretained(this)));
+ PushNextTask(base::BindOnce(&AppCacheResponseTest::Metadata_VerifyMetadata,
+ base::Unretained(this), ""));
+ PushNextTask(
+ base::BindOnce(&AppCacheResponseTest::Metadata_LoadResponseInfo,
+ base::Unretained(this)));
+ PushNextTask(base::BindOnce(&AppCacheResponseTest::Metadata_WriteMetadata,
+ base::Unretained(this), ""));
+ PushNextTask(base::BindOnce(&AppCacheResponseTest::Metadata_VerifyMetadata,
+ base::Unretained(this), "Second"));
+ PushNextTask(
+ base::BindOnce(&AppCacheResponseTest::Metadata_LoadResponseInfo,
+ base::Unretained(this)));
+ PushNextTask(base::BindOnce(&AppCacheResponseTest::Metadata_WriteMetadata,
+ base::Unretained(this), "Second"));
+ PushNextTask(base::BindOnce(&AppCacheResponseTest::Metadata_VerifyMetadata,
+ base::Unretained(this), "Metadata First"));
+ PushNextTask(
+ base::BindOnce(&AppCacheResponseTest::Metadata_LoadResponseInfo,
+ base::Unretained(this)));
+ PushNextTask(base::BindOnce(&AppCacheResponseTest::Metadata_WriteMetadata,
+ base::Unretained(this), "Metadata First"));
+ PushNextTask(base::BindOnce(&AppCacheResponseTest::Metadata_ResetWriter,
+ base::Unretained(this)));
writer_.reset(service_->storage()->CreateResponseWriter(GURL()));
written_response_id_ = writer_->response_id();
WriteBasicResponse();
@@ -493,14 +501,15 @@ class AppCacheResponseTest : public testing::Test {
GetHttpResponseInfoSize(head) + kNumBlocks * kBlockSize;
// Push tasks in reverse order.
- PushNextTask(base::Bind(&AppCacheResponseTest::Verify_AmountWritten,
- base::Unretained(this), expected_amount_written));
+ PushNextTask(base::BindOnce(&AppCacheResponseTest::Verify_AmountWritten,
+ base::Unretained(this),
+ expected_amount_written));
for (int i = 0; i < kNumBlocks; ++i) {
- PushNextTask(base::Bind(&AppCacheResponseTest::WriteOneBlock,
- base::Unretained(this), kNumBlocks - i));
+ PushNextTask(base::BindOnce(&AppCacheResponseTest::WriteOneBlock,
+ base::Unretained(this), kNumBlocks - i));
}
- PushNextTask(base::Bind(&AppCacheResponseTest::WriteResponseHead,
- base::Unretained(this), head));
+ PushNextTask(base::BindOnce(&AppCacheResponseTest::WriteResponseHead,
+ base::Unretained(this), head));
writer_.reset(service_->storage()->CreateResponseWriter(GURL()));
written_response_id_ = writer_->response_id();
@@ -526,22 +535,23 @@ class AppCacheResponseTest : public testing::Test {
// 6. Attempt to read beyond EOF of a range.
// Push tasks in reverse order
- PushNextTask(base::Bind(&AppCacheResponseTest::ReadRangeFullyBeyondEOF,
- base::Unretained(this)));
- PushNextTask(base::Bind(&AppCacheResponseTest::ReadRangePartiallyBeyondEOF,
- base::Unretained(this)));
- PushNextTask(base::Bind(&AppCacheResponseTest::ReadPastEOF,
- base::Unretained(this)));
- PushNextTask(base::Bind(&AppCacheResponseTest::ReadRange,
- base::Unretained(this)));
- PushNextTask(base::Bind(&AppCacheResponseTest::ReadPastEOF,
- base::Unretained(this)));
- PushNextTask(base::Bind(&AppCacheResponseTest::ReadAllAtOnce,
- base::Unretained(this)));
- PushNextTask(base::Bind(&AppCacheResponseTest::ReadInBlocks,
- base::Unretained(this)));
- PushNextTask(base::Bind(&AppCacheResponseTest::WriteOutBlocks,
- base::Unretained(this)));
+ PushNextTask(base::BindOnce(&AppCacheResponseTest::ReadRangeFullyBeyondEOF,
+ base::Unretained(this)));
+ PushNextTask(
+ base::BindOnce(&AppCacheResponseTest::ReadRangePartiallyBeyondEOF,
+ base::Unretained(this)));
+ PushNextTask(base::BindOnce(&AppCacheResponseTest::ReadPastEOF,
+ base::Unretained(this)));
+ PushNextTask(base::BindOnce(&AppCacheResponseTest::ReadRange,
+ base::Unretained(this)));
+ PushNextTask(base::BindOnce(&AppCacheResponseTest::ReadPastEOF,
+ base::Unretained(this)));
+ PushNextTask(base::BindOnce(&AppCacheResponseTest::ReadAllAtOnce,
+ base::Unretained(this)));
+ PushNextTask(base::BindOnce(&AppCacheResponseTest::ReadInBlocks,
+ base::Unretained(this)));
+ PushNextTask(base::BindOnce(&AppCacheResponseTest::WriteOutBlocks,
+ base::Unretained(this)));
// Get them going.
ScheduleNextTask();
@@ -551,8 +561,8 @@ class AppCacheResponseTest : public testing::Test {
writer_.reset(service_->storage()->CreateResponseWriter(GURL()));
written_response_id_ = writer_->response_id();
for (int i = 0; i < kNumBlocks; ++i) {
- PushNextTask(base::Bind(&AppCacheResponseTest::WriteOneBlock,
- base::Unretained(this), kNumBlocks - i));
+ PushNextTask(base::BindOnce(&AppCacheResponseTest::WriteOneBlock,
+ base::Unretained(this), kNumBlocks - i));
}
ScheduleNextTask();
}
@@ -569,15 +579,15 @@ class AppCacheResponseTest : public testing::Test {
reader_.reset(service_->storage()->CreateResponseReader(
GURL(), written_response_id_));
for (int i = 0; i < kNumBlocks; ++i) {
- PushNextTask(base::Bind(&AppCacheResponseTest::ReadOneBlock,
- base::Unretained(this), kNumBlocks - i));
+ PushNextTask(base::BindOnce(&AppCacheResponseTest::ReadOneBlock,
+ base::Unretained(this), kNumBlocks - i));
}
ScheduleNextTask();
}
void ReadOneBlock(int block_number) {
- PushNextTask(base::Bind(&AppCacheResponseTest::VerifyOneBlock,
- base::Unretained(this), block_number));
+ PushNextTask(base::BindOnce(&AppCacheResponseTest::VerifyOneBlock,
+ base::Unretained(this), block_number));
ReadResponseBody(new IOBuffer(kBlockSize), kBlockSize);
}
@@ -587,8 +597,8 @@ class AppCacheResponseTest : public testing::Test {
}
void ReadAllAtOnce() {
- PushNextTask(base::Bind(&AppCacheResponseTest::VerifyAllAtOnce,
- base::Unretained(this)));
+ PushNextTask(base::BindOnce(&AppCacheResponseTest::VerifyAllAtOnce,
+ base::Unretained(this)));
reader_.reset(service_->storage()->CreateResponseReader(
GURL(), written_response_id_));
int big_size = kNumBlocks * kBlockSize;
@@ -613,8 +623,8 @@ class AppCacheResponseTest : public testing::Test {
}
void ReadRange() {
- PushNextTask(base::Bind(&AppCacheResponseTest::VerifyRange,
- base::Unretained(this)));
+ PushNextTask(base::BindOnce(&AppCacheResponseTest::VerifyRange,
+ base::Unretained(this)));
reader_.reset(service_->storage()->CreateResponseReader(
GURL(), written_response_id_));
reader_->SetReadRange(kBlockSize, kBlockSize);
@@ -627,8 +637,8 @@ class AppCacheResponseTest : public testing::Test {
}
void ReadRangePartiallyBeyondEOF() {
- PushNextTask(base::Bind(&AppCacheResponseTest::VerifyRangeBeyondEOF,
- base::Unretained(this)));
+ PushNextTask(base::BindOnce(&AppCacheResponseTest::VerifyRangeBeyondEOF,
+ base::Unretained(this)));
reader_.reset(service_->storage()->CreateResponseReader(
GURL(), written_response_id_));
reader_->SetReadRange(kBlockSize, kNumBlocks * kBlockSize);
@@ -710,10 +720,10 @@ class AppCacheResponseTest : public testing::Test {
should_delete_writer_in_completion_callback_ = true;
writer_deletion_count_down_ = kNumBlocks;
- PushNextTask(base::Bind(&AppCacheResponseTest::ReadInBlocks,
- base::Unretained(this)));
- PushNextTask(base::Bind(&AppCacheResponseTest::WriteOutBlocks,
- base::Unretained(this)));
+ PushNextTask(base::BindOnce(&AppCacheResponseTest::ReadInBlocks,
+ base::Unretained(this)));
+ PushNextTask(base::BindOnce(&AppCacheResponseTest::WriteOutBlocks,
+ base::Unretained(this)));
ScheduleNextTask();
}
@@ -722,12 +732,12 @@ class AppCacheResponseTest : public testing::Test {
// 1. Write a few blocks normally.
// 2. Start a write, delete with it pending.
// 3. Start a read, delete with it pending.
- PushNextTask(base::Bind(&AppCacheResponseTest::ReadThenDelete,
- base::Unretained(this)));
- PushNextTask(base::Bind(&AppCacheResponseTest::WriteThenDelete,
- base::Unretained(this)));
- PushNextTask(base::Bind(&AppCacheResponseTest::WriteOutBlocks,
- base::Unretained(this)));
+ PushNextTask(base::BindOnce(&AppCacheResponseTest::ReadThenDelete,
+ base::Unretained(this)));
+ PushNextTask(base::BindOnce(&AppCacheResponseTest::WriteThenDelete,
+ base::Unretained(this)));
+ PushNextTask(base::BindOnce(&AppCacheResponseTest::WriteOutBlocks,
+ base::Unretained(this)));
ScheduleNextTask();
}
@@ -749,8 +759,9 @@ class AppCacheResponseTest : public testing::Test {
// Wait a moment to verify no callbacks.
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, base::Bind(&AppCacheResponseTest::VerifyNoCallbacks,
- base::Unretained(this)),
+ FROM_HERE,
+ base::BindOnce(&AppCacheResponseTest::VerifyNoCallbacks,
+ base::Unretained(this)),
base::TimeDelta::FromMilliseconds(10));
}
@@ -765,7 +776,7 @@ class AppCacheResponseTest : public testing::Test {
std::unique_ptr<base::WaitableEvent> test_finished_event_;
std::unique_ptr<MockStorageDelegate> storage_delegate_;
std::unique_ptr<MockAppCacheService> service_;
- std::stack<std::pair<base::Closure, bool> > task_stack_;
+ std::stack<std::pair<base::OnceClosure, bool>> task_stack_;
std::unique_ptr<AppCacheResponseReader> reader_;
scoped_refptr<HttpResponseInfoIOBuffer> read_info_buffer_;
diff --git a/chromium/content/browser/appcache/appcache_service_impl.cc b/chromium/content/browser/appcache/appcache_service_impl.cc
index 9af861bf7d7..cd29124a253 100644
--- a/chromium/content/browser/appcache/appcache_service_impl.cc
+++ b/chromium/content/browser/appcache/appcache_service_impl.cc
@@ -70,7 +70,7 @@ class AppCacheServiceImpl::AsyncHelper
if (!callback_.is_null()) {
// Defer to guarantee async completion.
base::SequencedTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&DeferredCallback, callback_, rv));
+ FROM_HERE, base::BindOnce(&DeferredCallback, callback_, rv));
}
callback_.Reset();
}
@@ -431,14 +431,11 @@ AppCacheServiceImpl::~AppCacheServiceImpl() {
storage_.reset();
}
-void AppCacheServiceImpl::Initialize(
- const base::FilePath& cache_directory,
- const scoped_refptr<base::SingleThreadTaskRunner>& cache_thread) {
+void AppCacheServiceImpl::Initialize(const base::FilePath& cache_directory) {
DCHECK(!storage_.get());
cache_directory_ = cache_directory;
- cache_thread_ = cache_thread;
AppCacheStorageImpl* storage = new AppCacheStorageImpl(this);
- storage->Initialize(cache_directory, db_task_runner_, cache_thread);
+ storage->Initialize(cache_directory, db_task_runner_);
storage_.reset(storage);
}
@@ -480,7 +477,7 @@ void AppCacheServiceImpl::Reinitialize() {
for (auto& observer : observers_)
observer.OnServiceReinitialized(old_storage_ref.get());
- Initialize(cache_directory_, cache_thread_);
+ Initialize(cache_directory_);
}
void AppCacheServiceImpl::GetAllAppCacheInfo(
diff --git a/chromium/content/browser/appcache/appcache_service_impl.h b/chromium/content/browser/appcache/appcache_service_impl.h
index 372e96e8488..e0ea217ab31 100644
--- a/chromium/content/browser/appcache/appcache_service_impl.h
+++ b/chromium/content/browser/appcache/appcache_service_impl.h
@@ -16,6 +16,7 @@
#include "base/observer_list.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
+#include "content/browser/url_loader_factory_getter.h"
#include "content/common/appcache_interfaces.h"
#include "content/common/content_export.h"
#include "content/public/browser/appcache_service.h"
@@ -25,7 +26,6 @@
namespace base {
class FilePath;
-class SingleThreadTaskRunner;
} // namespace base
namespace net {
@@ -87,9 +87,7 @@ class CONTENT_EXPORT AppCacheServiceImpl
explicit AppCacheServiceImpl(storage::QuotaManagerProxy* quota_manager_proxy);
~AppCacheServiceImpl() override;
- void Initialize(
- const base::FilePath& cache_directory,
- const scoped_refptr<base::SingleThreadTaskRunner>& cache_thread);
+ void Initialize(const base::FilePath& cache_directory);
void AddObserver(Observer* observer) {
observers_.AddObserver(observer);
@@ -182,6 +180,18 @@ class CONTENT_EXPORT AppCacheServiceImpl
void set_force_keep_session_state() { force_keep_session_state_ = true; }
bool force_keep_session_state() const { return force_keep_session_state_; }
+ // The following two functions are invoked in the network service world to
+ // set/get a pointer to the URLLoaderFactoryGetter instance which is used to
+ // get to the network URL loader factory.
+ void set_url_loader_factory_getter(
+ URLLoaderFactoryGetter* loader_factory_getter) {
+ url_loader_factory_getter_ = loader_factory_getter;
+ }
+
+ URLLoaderFactoryGetter* url_loader_factory_getter() const {
+ return url_loader_factory_getter_.get();
+ }
+
protected:
friend class content::AppCacheServiceImplTest;
friend class content::AppCacheStorageImplTest;
@@ -202,7 +212,6 @@ class CONTENT_EXPORT AppCacheServiceImpl
base::FilePath cache_directory_;
scoped_refptr<base::SequencedTaskRunner> db_task_runner_;
- scoped_refptr<base::SingleThreadTaskRunner> cache_thread_;
AppCachePolicy* appcache_policy_;
AppCacheQuotaClient* quota_client_;
AppCacheExecutableHandlerFactory* handler_factory_;
@@ -220,6 +229,11 @@ class CONTENT_EXPORT AppCacheServiceImpl
base::OneShotTimer reinit_timer_;
base::ObserverList<Observer> observers_;
+ // In the network service world contains the pointer to the
+ // URLLoaderFactoryGetter instance which is used to get to the network
+ // URL loader factory.
+ scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter_;
+
private:
base::WeakPtrFactory<AppCacheServiceImpl> weak_factory_;
diff --git a/chromium/content/browser/appcache/appcache_service_unittest.cc b/chromium/content/browser/appcache/appcache_service_unittest.cc
index 552244a0248..a3a58eb0e65 100644
--- a/chromium/content/browser/appcache/appcache_service_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_service_unittest.cc
@@ -79,8 +79,9 @@ class MockResponseReader : public AppCacheResponseReader {
private:
void ScheduleUserCallback(int result) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&MockResponseReader::InvokeUserCompletionCallback,
- weak_factory_.GetWeakPtr(), result));
+ FROM_HERE,
+ base::BindOnce(&MockResponseReader::InvokeUserCompletionCallback,
+ weak_factory_.GetWeakPtr(), result));
}
std::unique_ptr<net::HttpResponseInfo> info_;
diff --git a/chromium/content/browser/appcache/appcache_storage_impl.cc b/chromium/content/browser/appcache/appcache_storage_impl.cc
index 6e8dac792ef..6cac373d41a 100644
--- a/chromium/content/browser/appcache/appcache_storage_impl.cc
+++ b/chromium/content/browser/appcache/appcache_storage_impl.cc
@@ -195,8 +195,8 @@ void AppCacheStorageImpl::DatabaseTask::Schedule() {
return;
if (storage_->db_task_runner_->PostTask(
- FROM_HERE,
- base::Bind(&DatabaseTask::CallRun, this, base::TimeTicks::Now()))) {
+ FROM_HERE, base::BindOnce(&DatabaseTask::CallRun, this,
+ base::TimeTicks::Now()))) {
storage_->scheduled_database_tasks_.push_back(this);
} else {
NOTREACHED() << "Thread for database tasks is not running.";
@@ -224,15 +224,13 @@ void AppCacheStorageImpl::DatabaseTask::CallRun(
database_->Disable();
}
if (database_->is_disabled()) {
- io_thread_->PostTask(
- FROM_HERE,
- base::Bind(&DatabaseTask::OnFatalError, this));
+ io_thread_->PostTask(FROM_HERE,
+ base::BindOnce(&DatabaseTask::OnFatalError, this));
}
}
- io_thread_->PostTask(
- FROM_HERE,
- base::Bind(&DatabaseTask::CallRunCompleted, this,
- base::TimeTicks::Now()));
+ io_thread_->PostTask(FROM_HERE,
+ base::BindOnce(&DatabaseTask::CallRunCompleted, this,
+ base::TimeTicks::Now()));
}
void AppCacheStorageImpl::DatabaseTask::CallRunCompleted(
@@ -323,8 +321,9 @@ void AppCacheStorageImpl::InitTask::RunCompleted() {
const base::TimeDelta kDelay = base::TimeDelta::FromMinutes(5);
base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE,
- base::Bind(&AppCacheStorageImpl::DelayedStartDeletingUnusedResponses,
- storage_->weak_factory_.GetWeakPtr()),
+ base::BindOnce(
+ &AppCacheStorageImpl::DelayedStartDeletingUnusedResponses,
+ storage_->weak_factory_.GetWeakPtr()),
kDelay);
}
@@ -1415,8 +1414,9 @@ AppCacheStorageImpl::AppCacheStorageImpl(AppCacheServiceImpl* service)
last_deletable_response_rowid_(0),
database_(NULL),
is_disabled_(false),
- weak_factory_(this) {
-}
+ delete_and_start_over_pending_(false),
+ expecting_cleanup_complete_on_disable_(false),
+ weak_factory_(this) {}
AppCacheStorageImpl::~AppCacheStorageImpl() {
for (auto* task : pending_quota_queries_)
@@ -1427,9 +1427,9 @@ AppCacheStorageImpl::~AppCacheStorageImpl() {
if (database_ &&
!db_task_runner_->PostTask(
FROM_HERE,
- base::Bind(&ClearSessionOnlyOrigins, database_,
- make_scoped_refptr(service_->special_storage_policy()),
- service()->force_keep_session_state()))) {
+ base::BindOnce(&ClearSessionOnlyOrigins, database_,
+ make_scoped_refptr(service_->special_storage_policy()),
+ service()->force_keep_session_state()))) {
delete database_;
}
database_ = NULL; // So no further database tasks can be scheduled.
@@ -1437,8 +1437,7 @@ AppCacheStorageImpl::~AppCacheStorageImpl() {
void AppCacheStorageImpl::Initialize(
const base::FilePath& cache_directory,
- const scoped_refptr<base::SequencedTaskRunner>& db_task_runner,
- const scoped_refptr<base::SingleThreadTaskRunner>& cache_thread) {
+ const scoped_refptr<base::SequencedTaskRunner>& db_task_runner) {
cache_directory_ = cache_directory;
is_incognito_ = cache_directory_.empty();
@@ -1448,7 +1447,6 @@ void AppCacheStorageImpl::Initialize(
database_ = new AppCacheDatabase(db_file_path);
db_task_runner_ = db_task_runner;
- cache_thread_ = cache_thread;
scoped_refptr<InitTask> task(new InitTask(this));
task->Schedule();
@@ -1607,11 +1605,10 @@ void AppCacheStorageImpl::FindResponseForMainRequest(
// the DB thread.
scoped_refptr<AppCacheGroup> no_group;
scoped_refptr<AppCache> no_cache;
- ScheduleSimpleTask(
- base::Bind(&AppCacheStorageImpl::DeliverShortCircuitedFindMainResponse,
- weak_factory_.GetWeakPtr(), url, AppCacheEntry(), no_group,
- no_cache,
- make_scoped_refptr(GetOrCreateDelegateReference(delegate))));
+ ScheduleSimpleTask(base::BindOnce(
+ &AppCacheStorageImpl::DeliverShortCircuitedFindMainResponse,
+ weak_factory_.GetWeakPtr(), url, AppCacheEntry(), no_group, no_cache,
+ make_scoped_refptr(GetOrCreateDelegateReference(delegate))));
return;
}
@@ -1633,11 +1630,11 @@ bool AppCacheStorageImpl::FindResponseForMainRequestInGroup(
if (!entry || entry->IsForeign())
return false;
- ScheduleSimpleTask(
- base::Bind(&AppCacheStorageImpl::DeliverShortCircuitedFindMainResponse,
- weak_factory_.GetWeakPtr(), url, *entry,
- make_scoped_refptr(group), make_scoped_refptr(cache),
- make_scoped_refptr(GetOrCreateDelegateReference(delegate))));
+ ScheduleSimpleTask(base::BindOnce(
+ &AppCacheStorageImpl::DeliverShortCircuitedFindMainResponse,
+ weak_factory_.GetWeakPtr(), url, *entry, make_scoped_refptr(group),
+ make_scoped_refptr(cache),
+ make_scoped_refptr(GetOrCreateDelegateReference(delegate))));
return true;
}
@@ -1805,8 +1802,8 @@ void AppCacheStorageImpl::ScheduleDeleteOneResponse() {
const base::TimeDelta kBriefDelay = base::TimeDelta::FromMilliseconds(10);
base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE,
- base::Bind(&AppCacheStorageImpl::DeleteOneResponse,
- weak_factory_.GetWeakPtr()),
+ base::BindOnce(&AppCacheStorageImpl::DeleteOneResponse,
+ weak_factory_.GetWeakPtr()),
kBriefDelay);
is_response_deletion_scheduled_ = true;
}
@@ -1887,18 +1884,18 @@ void AppCacheStorageImpl::GetPendingForeignMarkingsForCache(
}
}
-void AppCacheStorageImpl::ScheduleSimpleTask(const base::Closure& task) {
- pending_simple_tasks_.push_back(task);
+void AppCacheStorageImpl::ScheduleSimpleTask(base::OnceClosure task) {
+ pending_simple_tasks_.push_back(std::move(task));
base::SequencedTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&AppCacheStorageImpl::RunOnePendingSimpleTask,
- weak_factory_.GetWeakPtr()));
+ FROM_HERE, base::BindOnce(&AppCacheStorageImpl::RunOnePendingSimpleTask,
+ weak_factory_.GetWeakPtr()));
}
void AppCacheStorageImpl::RunOnePendingSimpleTask() {
DCHECK(!pending_simple_tasks_.empty());
- base::Closure task = pending_simple_tasks_.front();
+ base::OnceClosure task = std::move(pending_simple_tasks_.front());
pending_simple_tasks_.pop_front();
- task.Run();
+ std::move(task).Run();
}
AppCacheDiskCache* AppCacheStorageImpl::disk_cache() {
@@ -1914,11 +1911,12 @@ AppCacheDiskCache* AppCacheStorageImpl::disk_cache() {
base::Bind(&AppCacheStorageImpl::OnDiskCacheInitialized,
base::Unretained(this)));
} else {
+ expecting_cleanup_complete_on_disable_ = true;
rv = disk_cache_->InitWithDiskBackend(
- cache_directory_.Append(kDiskCacheDirectoryName),
- kMaxDiskCacheSize,
+ cache_directory_.Append(kDiskCacheDirectoryName), kMaxDiskCacheSize,
false,
- cache_thread_.get(),
+ base::BindOnce(&AppCacheStorageImpl::OnDiskCacheCleanupComplete,
+ weak_factory_.GetWeakPtr()),
base::Bind(&AppCacheStorageImpl::OnDiskCacheInitialized,
base::Unretained(this)));
}
@@ -1947,23 +1945,31 @@ void AppCacheStorageImpl::DeleteAndStartOver() {
DCHECK(is_disabled_);
if (!is_incognito_) {
VLOG(1) << "Deleting existing appcache data and starting over.";
+
// We can have tasks in flight to close file handles on both the db
// and cache threads, we need to allow those tasks to cycle thru
- // prior to deleting the files and calling reinit.
- cache_thread_->PostTaskAndReply(
- FROM_HERE,
- base::Bind(&base::DoNothing),
- base::Bind(&AppCacheStorageImpl::DeleteAndStartOverPart2,
- weak_factory_.GetWeakPtr()));
+ // prior to deleting the files and calling reinit. We will know that the
+ // cache ones will be finished once we get into OnDiskCacheCleanupComplete,
+ // so let that known to synchronize with the DB thread.
+ delete_and_start_over_pending_ = true;
+
+ // Won't get a callback about cleanup being done, so call it ourselves.
+ if (!expecting_cleanup_complete_on_disable_)
+ OnDiskCacheCleanupComplete();
}
}
-void AppCacheStorageImpl::DeleteAndStartOverPart2() {
- db_task_runner_->PostTaskAndReply(
- FROM_HERE,
- base::Bind(base::IgnoreResult(&base::DeleteFile), cache_directory_, true),
- base::Bind(&AppCacheStorageImpl::CallScheduleReinitialize,
- weak_factory_.GetWeakPtr()));
+void AppCacheStorageImpl::OnDiskCacheCleanupComplete() {
+ expecting_cleanup_complete_on_disable_ = false;
+ if (delete_and_start_over_pending_) {
+ delete_and_start_over_pending_ = false;
+ db_task_runner_->PostTaskAndReply(
+ FROM_HERE,
+ base::BindOnce(base::IgnoreResult(&base::DeleteFile), cache_directory_,
+ true),
+ base::BindOnce(&AppCacheStorageImpl::CallScheduleReinitialize,
+ weak_factory_.GetWeakPtr()));
+ }
}
void AppCacheStorageImpl::CallScheduleReinitialize() {
diff --git a/chromium/content/browser/appcache/appcache_storage_impl.h b/chromium/content/browser/appcache/appcache_storage_impl.h
index cde701e1025..bc98e38a4c2 100644
--- a/chromium/content/browser/appcache/appcache_storage_impl.h
+++ b/chromium/content/browser/appcache/appcache_storage_impl.h
@@ -24,7 +24,7 @@
#include "content/common/content_export.h"
namespace base {
-class SingleThreadTaskRunner;
+class SequencedTaskRunner;
} // namespace base
namespace content {
@@ -38,8 +38,7 @@ class AppCacheStorageImpl : public AppCacheStorage {
void Initialize(
const base::FilePath& cache_directory,
- const scoped_refptr<base::SequencedTaskRunner>& db_task_runner,
- const scoped_refptr<base::SingleThreadTaskRunner>& cache_thread);
+ const scoped_refptr<base::SequencedTaskRunner>& db_task_runner);
void Disable();
bool is_disabled() const { return is_disabled_; }
@@ -112,7 +111,7 @@ class AppCacheStorageImpl : public AppCacheStorage {
void GetPendingForeignMarkingsForCache(int64_t cache_id,
std::vector<GURL>* urls);
- void ScheduleSimpleTask(const base::Closure& task);
+ void ScheduleSimpleTask(base::OnceClosure task);
void RunOnePendingSimpleTask();
void DelayedStartDeletingUnusedResponses();
@@ -121,8 +120,9 @@ class AppCacheStorageImpl : public AppCacheStorage {
void DeleteOneResponse();
void OnDeletedOneResponse(int rv);
void OnDiskCacheInitialized(int rv);
+ void OnDiskCacheCleanupComplete();
+
void DeleteAndStartOver();
- void DeleteAndStartOverPart2();
void CallScheduleReinitialize();
void LazilyCommitLastAccessTimes();
void OnLazyCommitTimer();
@@ -154,10 +154,8 @@ class AppCacheStorageImpl : public AppCacheStorage {
bool is_incognito_;
// This class operates primarily on the IO thread, but schedules
- // its DatabaseTasks on the db thread. Separately, the disk_cache uses
- // the cache thread.
+ // its DatabaseTasks on the db thread.
scoped_refptr<base::SequencedTaskRunner> db_task_runner_;
- scoped_refptr<base::SingleThreadTaskRunner> cache_thread_;
// Structures to keep track of DatabaseTasks that are in-flight.
DatabaseTaskQueue scheduled_database_tasks_;
@@ -180,12 +178,20 @@ class AppCacheStorageImpl : public AppCacheStorage {
// disk cache and cannot continue.
bool is_disabled_;
+ // This is set when we want to use the post-cleanup callback to initiate
+ // directory deletion.
+ bool delete_and_start_over_pending_;
+
+ // This is set when we know that a call to Disable() will result in
+ // OnDiskCacheCleanupComplete() eventually called.
+ bool expecting_cleanup_complete_on_disable_;
+
std::unique_ptr<AppCacheDiskCache> disk_cache_;
base::OneShotTimer lazy_commit_timer_;
// Used to short-circuit certain operations without having to schedule
// any tasks on the background database thread.
- std::deque<base::Closure> pending_simple_tasks_;
+ std::deque<base::OnceClosure> pending_simple_tasks_;
base::WeakPtrFactory<AppCacheStorageImpl> weak_factory_;
friend class content::AppCacheStorageImplTest;
diff --git a/chromium/content/browser/appcache/appcache_storage_impl_unittest.cc b/chromium/content/browser/appcache/appcache_storage_impl_unittest.cc
index 4752d8f9e89..dd59d62b817 100644
--- a/chromium/content/browser/appcache/appcache_storage_impl_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_storage_impl_unittest.cc
@@ -280,7 +280,6 @@ class AppCacheStorageImplTest : public testing::Test {
: QuotaManager(true /* is_incognito */,
base::FilePath(),
io_thread->task_runner().get(),
- background_thread->task_runner().get(),
nullptr,
storage::GetQuotaSettingsFunc()),
async_(false) {}
@@ -291,8 +290,8 @@ class AppCacheStorageImplTest : public testing::Test {
EXPECT_EQ(storage::kStorageTypeTemporary, type);
if (async_) {
base::SequencedTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&MockQuotaManager::CallCallback,
- base::Unretained(this), callback));
+ FROM_HERE, base::BindOnce(&MockQuotaManager::CallCallback,
+ base::Unretained(this), callback));
return;
}
CallCallback(callback);
@@ -380,8 +379,8 @@ class AppCacheStorageImplTest : public testing::Test {
// on the IO thread prior to running the test. Its guaranteed to be
// queued by this time.
base::SequencedTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&AppCacheStorageImplTest::RunMethod<Method>,
- base::Unretained(this), method));
+ FROM_HERE, base::BindOnce(&AppCacheStorageImplTest::RunMethod<Method>,
+ base::Unretained(this), method));
}
static void SetUpTestCase() {
@@ -412,15 +411,16 @@ class AppCacheStorageImplTest : public testing::Test {
base::WaitableEvent::ResetPolicy::AUTOMATIC,
base::WaitableEvent::InitialState::NOT_SIGNALED));
io_thread->task_runner()->PostTask(
- FROM_HERE, base::Bind(&AppCacheStorageImplTest::MethodWrapper<Method>,
- base::Unretained(this), method));
+ FROM_HERE,
+ base::BindOnce(&AppCacheStorageImplTest::MethodWrapper<Method>,
+ base::Unretained(this), method));
test_finished_event_->Wait();
}
void SetUpTest() {
DCHECK(io_thread->task_runner()->BelongsToCurrentThread());
service_.reset(new AppCacheServiceImpl(nullptr));
- service_->Initialize(base::FilePath(), background_thread->task_runner());
+ service_->Initialize(base::FilePath());
mock_quota_manager_proxy_ = new MockQuotaManagerProxy();
service_->quota_manager_proxy_ = mock_quota_manager_proxy_;
delegate_.reset(new MockStorageDelegate(this));
@@ -447,8 +447,8 @@ class AppCacheStorageImplTest : public testing::Test {
// based objects get deleted.
DCHECK(io_thread->task_runner()->BelongsToCurrentThread());
base::SequencedTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&AppCacheStorageImplTest::TestFinishedUnwound,
- base::Unretained(this)));
+ FROM_HERE, base::BindOnce(&AppCacheStorageImplTest::TestFinishedUnwound,
+ base::Unretained(this)));
}
void TestFinishedUnwound() {
@@ -456,8 +456,8 @@ class AppCacheStorageImplTest : public testing::Test {
test_finished_event_->Signal();
}
- void PushNextTask(const base::Closure& task) {
- task_stack_.push(task);
+ void PushNextTask(base::OnceClosure task) {
+ task_stack_.push(std::move(task));
}
void ScheduleNextTask() {
@@ -465,8 +465,8 @@ class AppCacheStorageImplTest : public testing::Test {
if (task_stack_.empty()) {
return;
}
- base::SequencedTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- task_stack_.top());
+ base::SequencedTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, std::move(task_stack_.top()));
task_stack_.pop();
}
@@ -485,8 +485,9 @@ class AppCacheStorageImplTest : public testing::Test {
// scheduled on that thread have been performed prior to return.
base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC,
base::WaitableEvent::InitialState::NOT_SIGNALED);
- runner->PostTask(FROM_HERE,
- base::Bind(&AppCacheStorageImplTest::SignalEvent, &event));
+ runner->PostTask(
+ FROM_HERE,
+ base::BindOnce(&AppCacheStorageImplTest::SignalEvent, &event));
event.Wait();
}
@@ -495,8 +496,8 @@ class AppCacheStorageImplTest : public testing::Test {
void LoadCache_Miss() {
// Attempt to load a cache that doesn't exist. Should
// complete asynchronously.
- PushNextTask(base::Bind(&AppCacheStorageImplTest::Verify_LoadCache_Miss,
- base::Unretained(this)));
+ PushNextTask(base::BindOnce(&AppCacheStorageImplTest::Verify_LoadCache_Miss,
+ base::Unretained(this)));
storage()->LoadCache(111, delegate());
EXPECT_NE(111, delegate()->loaded_cache_id_);
@@ -546,8 +547,8 @@ class AppCacheStorageImplTest : public testing::Test {
void CreateGroupInPopulatedOrigin() {
// Attempt to load a group that doesn't exist, one should
// be created for us, but not stored.
- PushNextTask(base::Bind(&AppCacheStorageImplTest::Verify_CreateGroup,
- base::Unretained(this)));
+ PushNextTask(base::BindOnce(&AppCacheStorageImplTest::Verify_CreateGroup,
+ base::Unretained(this)));
// Since the origin has groups, storage class will have to
// consult the database and completion will be async.
@@ -580,8 +581,9 @@ class AppCacheStorageImplTest : public testing::Test {
// Attempt to load a cache that is not currently in use
// and does require loading from disk. This
// load should complete asynchronously.
- PushNextTask(base::Bind(&AppCacheStorageImplTest::Verify_LoadCache_Far_Hit,
- base::Unretained(this)));
+ PushNextTask(
+ base::BindOnce(&AppCacheStorageImplTest::Verify_LoadCache_Far_Hit,
+ base::Unretained(this)));
// Setup some preconditions. Create a group and newest cache that
// appear to be "stored" and "not currently in use".
@@ -611,8 +613,9 @@ class AppCacheStorageImplTest : public testing::Test {
EXPECT_FALSE(delegate()->loaded_group_.get());
// Conduct the group load test, also complete asynchronously.
- PushNextTask(base::Bind(&AppCacheStorageImplTest::Verify_LoadGroup_Far_Hit,
- base::Unretained(this)));
+ PushNextTask(
+ base::BindOnce(&AppCacheStorageImplTest::Verify_LoadGroup_Far_Hit,
+ base::Unretained(this)));
storage()->LoadOrCreateGroup(kManifestUrl, delegate());
}
@@ -632,8 +635,8 @@ class AppCacheStorageImplTest : public testing::Test {
void StoreNewGroup() {
// Store a group and its newest cache. Should complete asynchronously.
- PushNextTask(base::Bind(&AppCacheStorageImplTest::Verify_StoreNewGroup,
- base::Unretained(this)));
+ PushNextTask(base::BindOnce(&AppCacheStorageImplTest::Verify_StoreNewGroup,
+ base::Unretained(this)));
// Setup some preconditions. Create a group and newest cache that
// appear to be "unstored".
@@ -678,8 +681,9 @@ class AppCacheStorageImplTest : public testing::Test {
void StoreExistingGroup() {
// Store a group and its newest cache. Should complete asynchronously.
- PushNextTask(base::Bind(&AppCacheStorageImplTest::Verify_StoreExistingGroup,
- base::Unretained(this)));
+ PushNextTask(
+ base::BindOnce(&AppCacheStorageImplTest::Verify_StoreExistingGroup,
+ base::Unretained(this)));
// Setup some preconditions. Create a group and old complete cache
// that appear to be "stored"
@@ -738,7 +742,7 @@ class AppCacheStorageImplTest : public testing::Test {
cache_->AddEntry(kEntryUrl, AppCacheEntry(AppCacheEntry::MASTER, 1, 100));
cache_->set_update_time(now);
- PushNextTask(base::Bind(
+ PushNextTask(base::BindOnce(
&AppCacheStorageImplTest::Verify_StoreExistingGroupExistingCache,
base::Unretained(this), now));
@@ -785,8 +789,8 @@ class AppCacheStorageImplTest : public testing::Test {
void FailStoreGroup() {
// Store a group and its newest cache. Should complete asynchronously.
- PushNextTask(base::Bind(&AppCacheStorageImplTest::Verify_FailStoreGroup,
- base::Unretained(this)));
+ PushNextTask(base::BindOnce(&AppCacheStorageImplTest::Verify_FailStoreGroup,
+ base::Unretained(this)));
// Setup some preconditions. Create a group and newest cache that
// appear to be "unstored" and big enough to exceed the 5M limit.
@@ -824,8 +828,9 @@ class AppCacheStorageImplTest : public testing::Test {
void MakeGroupObsolete() {
// Make a group obsolete, should complete asynchronously.
- PushNextTask(base::Bind(&AppCacheStorageImplTest::Verify_MakeGroupObsolete,
- base::Unretained(this)));
+ PushNextTask(
+ base::BindOnce(&AppCacheStorageImplTest::Verify_MakeGroupObsolete,
+ base::Unretained(this)));
// Setup some preconditions. Create a group and newest cache that
// appears to be "stored" and "currently in use".
@@ -926,9 +931,9 @@ class AppCacheStorageImplTest : public testing::Test {
// MarkEntryAsForeignWithLoadInProgress -------------------------------
void MarkEntryAsForeignWithLoadInProgress() {
- PushNextTask(base::Bind(
- &AppCacheStorageImplTest::Verify_MarkEntryAsForeignWithLoadInProgress,
- base::Unretained(this)));
+ PushNextTask(base::BindOnce(
+ &AppCacheStorageImplTest::Verify_MarkEntryAsForeignWithLoadInProgress,
+ base::Unretained(this)));
// Setup some preconditions. Create a cache with an entry
// in storage, but not in the working set.
@@ -971,8 +976,9 @@ class AppCacheStorageImplTest : public testing::Test {
// FindNoMainResponse -------------------------------
void FindNoMainResponse() {
- PushNextTask(base::Bind(&AppCacheStorageImplTest::Verify_FindNoMainResponse,
- base::Unretained(this)));
+ PushNextTask(
+ base::BindOnce(&AppCacheStorageImplTest::Verify_FindNoMainResponse,
+ base::Unretained(this)));
// Conduct the test.
storage()->FindResponseForMainRequest(kEntryUrl, GURL(), delegate());
@@ -1003,9 +1009,9 @@ class AppCacheStorageImplTest : public testing::Test {
}
void BasicFindMainResponse(bool drop_from_working_set) {
- PushNextTask(base::Bind(
- &AppCacheStorageImplTest::Verify_BasicFindMainResponse,
- base::Unretained(this)));
+ PushNextTask(
+ base::BindOnce(&AppCacheStorageImplTest::Verify_BasicFindMainResponse,
+ base::Unretained(this)));
// Setup some preconditions. Create a complete cache with an entry
// in storage.
@@ -1053,7 +1059,7 @@ class AppCacheStorageImplTest : public testing::Test {
}
void BasicFindMainFallbackResponse(bool drop_from_working_set) {
- PushNextTask(base::Bind(
+ PushNextTask(base::BindOnce(
&AppCacheStorageImplTest::Verify_BasicFindMainFallbackResponse,
base::Unretained(this)));
@@ -1131,7 +1137,7 @@ class AppCacheStorageImplTest : public testing::Test {
}
void BasicFindMainInterceptResponse(bool drop_from_working_set) {
- PushNextTask(base::Bind(
+ PushNextTask(base::BindOnce(
&AppCacheStorageImplTest::Verify_BasicFindMainInterceptResponse,
base::Unretained(this)));
@@ -1243,7 +1249,7 @@ class AppCacheStorageImplTest : public testing::Test {
}
// First test something that does not match the pattern.
- PushNextTask(base::Bind(
+ PushNextTask(base::BindOnce(
&AppCacheStorageImplTest::Verify_FindInterceptPatternMatchNegative,
base::Unretained(this)));
storage()->FindResponseForMainRequest(
@@ -1263,7 +1269,7 @@ class AppCacheStorageImplTest : public testing::Test {
EXPECT_EQ(0, delegate()->found_fallback_entry_.types());
// Then test something that matches.
- PushNextTask(base::Bind(
+ PushNextTask(base::BindOnce(
&AppCacheStorageImplTest::Verify_FindInterceptPatternMatchPositive,
base::Unretained(this)));
storage()->FindResponseForMainRequest(
@@ -1330,7 +1336,7 @@ class AppCacheStorageImplTest : public testing::Test {
}
// First test something that does not match the pattern.
- PushNextTask(base::Bind(
+ PushNextTask(base::BindOnce(
&AppCacheStorageImplTest::Verify_FindFallbackPatternMatchNegative,
base::Unretained(this)));
storage()->FindResponseForMainRequest(
@@ -1350,7 +1356,7 @@ class AppCacheStorageImplTest : public testing::Test {
EXPECT_EQ(0, delegate()->found_fallback_entry_.types());
// Then test something that matches.
- PushNextTask(base::Bind(
+ PushNextTask(base::BindOnce(
&AppCacheStorageImplTest::Verify_FindFallbackPatternMatchPositive,
base::Unretained(this)));
storage()->FindResponseForMainRequest(
@@ -1372,7 +1378,7 @@ class AppCacheStorageImplTest : public testing::Test {
// FindMainResponseWithMultipleHits -------------------------------
void FindMainResponseWithMultipleHits() {
- PushNextTask(base::Bind(
+ PushNextTask(base::BindOnce(
&AppCacheStorageImplTest::Verify_FindMainResponseWithMultipleHits,
base::Unretained(this)));
@@ -1446,7 +1452,7 @@ class AppCacheStorageImplTest : public testing::Test {
// Conduct another test preferring kManifestUrl
delegate_.reset(new MockStorageDelegate(this));
- PushNextTask(base::Bind(
+ PushNextTask(base::BindOnce(
&AppCacheStorageImplTest::Verify_FindMainResponseWithMultipleHits2,
base::Unretained(this)));
storage()->FindResponseForMainRequest(kEntryUrl, kManifestUrl, delegate());
@@ -1464,7 +1470,7 @@ class AppCacheStorageImplTest : public testing::Test {
// Conduct the another test preferring kManifestUrl2
delegate_.reset(new MockStorageDelegate(this));
- PushNextTask(base::Bind(
+ PushNextTask(base::BindOnce(
&AppCacheStorageImplTest::Verify_FindMainResponseWithMultipleHits3,
base::Unretained(this)));
storage()->FindResponseForMainRequest(kEntryUrl, kManifestUrl2, delegate());
@@ -1482,7 +1488,7 @@ class AppCacheStorageImplTest : public testing::Test {
// Conduct another test with no preferred manifest that hits the fallback.
delegate_.reset(new MockStorageDelegate(this));
- PushNextTask(base::Bind(
+ PushNextTask(base::BindOnce(
&AppCacheStorageImplTest::Verify_FindMainResponseWithMultipleHits4,
base::Unretained(this)));
storage()->FindResponseForMainRequest(
@@ -1503,7 +1509,7 @@ class AppCacheStorageImplTest : public testing::Test {
// Conduct another test preferring kManifestUrl2 that hits the fallback.
delegate_.reset(new MockStorageDelegate(this));
- PushNextTask(base::Bind(
+ PushNextTask(base::BindOnce(
&AppCacheStorageImplTest::Verify_FindMainResponseWithMultipleHits5,
base::Unretained(this)));
storage()->FindResponseForMainRequest(
@@ -1580,8 +1586,9 @@ class AppCacheStorageImplTest : public testing::Test {
}
// We should not find anything for the foreign entry.
- PushNextTask(base::Bind(&AppCacheStorageImplTest::Verify_ExclusionNotFound,
- base::Unretained(this), kEntryUrl, 1));
+ PushNextTask(
+ base::BindOnce(&AppCacheStorageImplTest::Verify_ExclusionNotFound,
+ base::Unretained(this), kEntryUrl, 1));
storage()->FindResponseForMainRequest(kEntryUrl, GURL(), delegate());
}
@@ -1609,7 +1616,7 @@ class AppCacheStorageImplTest : public testing::Test {
if (phase == 2) {
// We should not find anything for the online namespace nested within
// the fallback namespace.
- PushNextTask(base::Bind(
+ PushNextTask(base::BindOnce(
&AppCacheStorageImplTest::Verify_ExclusionNotFound,
base::Unretained(this), kOnlineNamespaceWithinFallback, 3));
storage()->FindResponseForMainRequest(
@@ -1740,8 +1747,7 @@ class AppCacheStorageImplTest : public testing::Test {
// Recreate the service to point at the db and corruption on disk.
service_.reset(new AppCacheServiceImpl(NULL));
service_->set_request_context(io_thread->request_context());
- service_->Initialize(temp_directory_.GetPath(),
- background_thread->task_runner());
+ service_->Initialize(temp_directory_.GetPath());
mock_quota_manager_proxy_ = new MockQuotaManagerProxy();
service_->quota_manager_proxy_ = mock_quota_manager_proxy_;
delegate_.reset(new MockStorageDelegate(this));
@@ -1754,8 +1760,9 @@ class AppCacheStorageImplTest : public testing::Test {
// on the current thread.
FlushAllTasks();
base::SequencedTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&AppCacheStorageImplTest::Continue_Reinitialize,
- base::Unretained(this), test_case));
+ FROM_HERE,
+ base::BindOnce(&AppCacheStorageImplTest::Continue_Reinitialize,
+ base::Unretained(this), test_case));
}
void Continue_Reinitialize(ReinitTestCase test_case) {
@@ -1798,10 +1805,8 @@ class AppCacheStorageImplTest : public testing::Test {
request_->Start();
}
- PushNextTask(base::Bind(
- &AppCacheStorageImplTest::Verify_Reinitialized,
- base::Unretained(this),
- test_case));
+ PushNextTask(base::BindOnce(&AppCacheStorageImplTest::Verify_Reinitialized,
+ base::Unretained(this), test_case));
}
void Verify_Reinitialized(ReinitTestCase test_case) {
@@ -1900,7 +1905,7 @@ class AppCacheStorageImplTest : public testing::Test {
// Data members --------------------------------------------------
std::unique_ptr<base::WaitableEvent> test_finished_event_;
- std::stack<base::Closure> task_stack_;
+ std::stack<base::OnceClosure> task_stack_;
std::unique_ptr<AppCacheServiceImpl> service_;
std::unique_ptr<MockStorageDelegate> delegate_;
scoped_refptr<MockQuotaManagerProxy> mock_quota_manager_proxy_;
diff --git a/chromium/content/browser/appcache/appcache_subresource_url_factory.cc b/chromium/content/browser/appcache/appcache_subresource_url_factory.cc
index 4b6f9fd36b5..65a0d5e1a07 100644
--- a/chromium/content/browser/appcache/appcache_subresource_url_factory.cc
+++ b/chromium/content/browser/appcache/appcache_subresource_url_factory.cc
@@ -23,13 +23,11 @@ namespace content {
// Implements the URLLoaderFactory mojom for AppCache requests.
AppCacheSubresourceURLFactory::AppCacheSubresourceURLFactory(
- mojom::URLLoaderFactoryRequest request,
URLLoaderFactoryGetter* default_url_loader_factory_getter,
base::WeakPtr<AppCacheHost> host)
- : binding_(this, std::move(request)),
- default_url_loader_factory_getter_(default_url_loader_factory_getter),
+ : default_url_loader_factory_getter_(default_url_loader_factory_getter),
appcache_host_(host) {
- binding_.set_connection_error_handler(
+ bindings_.set_connection_error_handler(
base::Bind(&AppCacheSubresourceURLFactory::OnConnectionError,
base::Unretained(this)));
}
@@ -37,21 +35,22 @@ AppCacheSubresourceURLFactory::AppCacheSubresourceURLFactory(
AppCacheSubresourceURLFactory::~AppCacheSubresourceURLFactory() {}
// static
-AppCacheSubresourceURLFactory*
-AppCacheSubresourceURLFactory::CreateURLLoaderFactory(
+void AppCacheSubresourceURLFactory::CreateURLLoaderFactory(
URLLoaderFactoryGetter* default_url_loader_factory_getter,
base::WeakPtr<AppCacheHost> host,
mojom::URLLoaderFactoryPtr* loader_factory) {
mojom::URLLoaderFactoryRequest request = mojo::MakeRequest(loader_factory);
- // This instance will get deleted when the client drops the connection.
+ // This instance is effectively reference counted by the number of pipes open
+ // to it and will get deleted when all clients drop their connections.
// Please see OnConnectionError() for details.
- return new AppCacheSubresourceURLFactory(
- std::move(request), default_url_loader_factory_getter, host);
+ auto* impl = new AppCacheSubresourceURLFactory(
+ default_url_loader_factory_getter, host);
+ impl->Clone(std::move(request));
}
void AppCacheSubresourceURLFactory::CreateLoaderAndStart(
- mojom::URLLoaderAssociatedRequest url_loader_request,
+ mojom::URLLoaderRequest url_loader_request,
int32_t routing_id,
int32_t request_id,
uint32_t options,
@@ -63,23 +62,20 @@ void AppCacheSubresourceURLFactory::CreateLoaderAndStart(
// If the host is invalid, it means that the renderer has probably died.
// (Frame has navigated elsewhere?)
- if (!appcache_host_.get())
+ if (!appcache_host_.get()) {
+ NotifyError(std::move(client), net::ERR_FAILED);
return;
+ }
std::unique_ptr<AppCacheRequestHandler> handler =
appcache_host_->CreateRequestHandler(
AppCacheURLLoaderRequest::Create(request), request.resource_type,
request.should_reset_appcache);
if (!handler) {
- ResourceRequestCompletionStatus request_result;
- request_result.error_code = net::ERR_FAILED;
- client->OnComplete(request_result);
+ NotifyError(std::move(client), net::ERR_FAILED);
return;
}
- handler->set_network_url_loader_factory_getter(
- default_url_loader_factory_getter_.get());
-
std::unique_ptr<SubresourceLoadInfo> load_info(new SubresourceLoadInfo());
load_info->url_loader_request = std::move(url_loader_request);
load_info->routing_id = routing_id;
@@ -89,24 +85,33 @@ void AppCacheSubresourceURLFactory::CreateLoaderAndStart(
load_info->client = std::move(client);
load_info->traffic_annotation = traffic_annotation;
- handler->SetSubresourceRequestLoadInfo(std::move(load_info));
-
- AppCacheJob* job = handler->MaybeLoadResource(nullptr);
- if (job) {
- // The handler is owned by the job.
- job->AsURLLoaderJob()->set_request_handler(std::move(handler));
+ // TODO(ananta/michaeln)
+ // We need to handle redirects correctly, i.e every subresource redirect
+ // could potentially be served out of the cache.
+ if (handler->MaybeCreateSubresourceLoader(
+ std::move(load_info), default_url_loader_factory_getter_.get())) {
+ // The handler is owned by the job and will be destoryed when the job is
+ // destroyed.
+ handler.release();
}
}
-void AppCacheSubresourceURLFactory::SyncLoad(int32_t routing_id,
- int32_t request_id,
- const ResourceRequest& request,
- SyncLoadCallback callback) {
- NOTREACHED();
+void AppCacheSubresourceURLFactory::Clone(
+ mojom::URLLoaderFactoryRequest request) {
+ bindings_.AddBinding(this, std::move(request));
}
void AppCacheSubresourceURLFactory::OnConnectionError() {
- base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this);
+ if (bindings_.empty())
+ delete this;
+}
+
+void AppCacheSubresourceURLFactory::NotifyError(
+ mojom::URLLoaderClientPtr client,
+ int error_code) {
+ ResourceRequestCompletionStatus request_result;
+ request_result.error_code = error_code;
+ client->OnComplete(request_result);
}
-} // namespace content \ No newline at end of file
+} // namespace content
diff --git a/chromium/content/browser/appcache/appcache_subresource_url_factory.h b/chromium/content/browser/appcache/appcache_subresource_url_factory.h
index ef4458e8a51..712cc375a57 100644
--- a/chromium/content/browser/appcache/appcache_subresource_url_factory.h
+++ b/chromium/content/browser/appcache/appcache_subresource_url_factory.h
@@ -7,8 +7,9 @@
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
+#include "content/common/content_export.h"
#include "content/public/common/url_loader_factory.mojom.h"
-#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/binding_set.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "url/gurl.h"
@@ -20,7 +21,8 @@ class AppCacheServiceImpl;
class URLLoaderFactoryGetter;
// Implements the URLLoaderFactory mojom for AppCache subresource requests.
-class AppCacheSubresourceURLFactory : public mojom::URLLoaderFactory {
+class CONTENT_EXPORT AppCacheSubresourceURLFactory
+ : public mojom::URLLoaderFactory {
public:
~AppCacheSubresourceURLFactory() override;
@@ -30,37 +32,36 @@ class AppCacheSubresourceURLFactory : public mojom::URLLoaderFactory {
// 2. The |host| parameter contains the appcache host instance. This is used
// to create the AppCacheRequestHandler instances for handling subresource
// requests.
- // Returns the AppCacheSubresourceURLFactory instance. The URLLoaderFactoryPtr
- // is returned in the |loader_factory| parameter.
- static AppCacheSubresourceURLFactory* CreateURLLoaderFactory(
+ static void CreateURLLoaderFactory(
URLLoaderFactoryGetter* factory_getter,
base::WeakPtr<AppCacheHost> host,
mojom::URLLoaderFactoryPtr* loader_factory);
// mojom::URLLoaderFactory implementation.
- void CreateLoaderAndStart(
- mojom::URLLoaderAssociatedRequest url_loader_request,
- int32_t routing_id,
- int32_t request_id,
- uint32_t options,
- const ResourceRequest& request,
- mojom::URLLoaderClientPtr client,
- const net::MutableNetworkTrafficAnnotationTag& traffic_annotation)
- override;
- void SyncLoad(int32_t routing_id,
- int32_t request_id,
- const ResourceRequest& request,
- SyncLoadCallback callback) override;
+ void CreateLoaderAndStart(mojom::URLLoaderRequest url_loader_request,
+ int32_t routing_id,
+ int32_t request_id,
+ uint32_t options,
+ const ResourceRequest& request,
+ mojom::URLLoaderClientPtr client,
+ const net::MutableNetworkTrafficAnnotationTag&
+ traffic_annotation) override;
+ void Clone(mojom::URLLoaderFactoryRequest request) override;
private:
- AppCacheSubresourceURLFactory(mojom::URLLoaderFactoryRequest request,
- URLLoaderFactoryGetter* factory_getter,
+ friend class AppCacheNetworkServiceBrowserTest;
+
+ AppCacheSubresourceURLFactory(URLLoaderFactoryGetter* factory_getter,
base::WeakPtr<AppCacheHost> host);
void OnConnectionError();
- // Mojo binding.
- mojo::Binding<mojom::URLLoaderFactory> binding_;
+ // Notifies the |client| if there is a failure. The |error_code| contains the
+ // actual error.
+ void NotifyError(mojom::URLLoaderClientPtr client, int error_code);
+
+ // Mojo bindings.
+ mojo::BindingSet<mojom::URLLoaderFactory> bindings_;
// Used to retrieve the network service factory to pass unhandled requests to
// the network service.
diff --git a/chromium/content/browser/appcache/appcache_update_job.cc b/chromium/content/browser/appcache/appcache_update_job.cc
index ec16a5a27f2..835f2b141f1 100644
--- a/chromium/content/browser/appcache/appcache_update_job.cc
+++ b/chromium/content/browser/appcache/appcache_update_job.cc
@@ -14,15 +14,13 @@
#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/appcache/appcache_group.h"
#include "content/browser/appcache/appcache_histograms.h"
+#include "content/browser/appcache/appcache_update_request_base.h"
+#include "content/browser/appcache/appcache_update_url_fetcher.h"
#include "content/public/browser/browser_thread.h"
#include "net/base/io_buffer.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
#include "net/base/request_priority.h"
-#include "net/http/http_request_headers.h"
-#include "net/http/http_response_headers.h"
-#include "net/traffic_annotation/network_traffic_annotation.h"
-#include "net/url_request/url_request_context.h"
#include "url/origin.h"
namespace content {
@@ -31,7 +29,6 @@ namespace {
const int kBufferSize = 32768;
const size_t kMaxConcurrentUrlFetches = 2;
-const int kMax503Retries = 3;
std::string FormatUrlErrorMessage(
const char* format, const GURL& url,
@@ -68,38 +65,32 @@ bool IsEvictableError(AppCacheUpdateJob::ResultType result,
}
}
+bool CanUseExistingResource(const net::HttpResponseInfo* http_info) {
+ // Check HTTP caching semantics based on max-age and expiration headers.
+ if (!http_info->headers || http_info->headers->RequiresValidation(
+ http_info->request_time,
+ http_info->response_time, base::Time::Now())) {
+ return false;
+ }
+
+ // Responses with a "vary" header generally get treated as expired,
+ // but we special case the "Origin" header since we know it's invariant.
+ // Also, content decoding is handled by the network library, the appcache
+ // stores decoded response bodies, so we can safely ignore varying on
+ // the "Accept-Encoding" header.
+ std::string value;
+ size_t iter = 0;
+ while (http_info->headers->EnumerateHeader(&iter, "vary", &value)) {
+ if (!base::EqualsCaseInsensitiveASCII(value, "Accept-Encoding") &&
+ !base::EqualsCaseInsensitiveASCII(value, "Origin")) {
+ return false;
+ }
+ }
+ return true;
+}
+
void EmptyCompletionCallback(int result) {}
-constexpr net::NetworkTrafficAnnotationTag kTrafficAnnotation =
- net::DefineNetworkTrafficAnnotation("appcache_update_job", R"(
- semantics {
- sender: "HTML5 AppCache System"
- description:
- "Web pages can include a link to a manifest file which lists "
- "resources to be cached for offline access. The AppCache system"
- "retrieves those resources in the background."
- trigger:
- "User visits a web page containing a <html manifest=manifestUrl> "
- "tag, or navigates to a document retrieved from an existing appcache "
- "and some resource should be updated."
- data: "None"
- destination: WEBSITE
- }
- policy {
- cookies_allowed: true
- 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, appcaches are disabled for the site only. If they are totally "
- "disabled, all appcache requests will be stopped."
- chrome_policy {
- DefaultCookiesSetting {
- policy_options {mode: MANDATORY}
- DefaultCookiesSetting: 2
- }
- }
- })");
} // namespace
// Helper class for collecting hosts per frontend when sending notifications
@@ -178,260 +169,6 @@ AppCacheUpdateJob::UrlToFetch::UrlToFetch(const UrlToFetch& other) = default;
AppCacheUpdateJob::UrlToFetch::~UrlToFetch() {
}
-// Helper class to fetch resources. Depending on the fetch type,
-// can either fetch to an in-memory string or write the response
-// data out to the disk cache.
-AppCacheUpdateJob::URLFetcher::URLFetcher(const GURL& url,
- FetchType fetch_type,
- AppCacheUpdateJob* job)
- : url_(url),
- job_(job),
- fetch_type_(fetch_type),
- retry_503_attempts_(0),
- buffer_(new net::IOBuffer(kBufferSize)),
- request_(
- job->service_->request_context()->CreateRequest(url,
- net::DEFAULT_PRIORITY,
- this,
- kTrafficAnnotation)),
- result_(UPDATE_OK),
- redirect_response_code_(-1) {}
-
-AppCacheUpdateJob::URLFetcher::~URLFetcher() {
- // To defend against URLRequest calling delegate methods during
- // destruction, we test for a !request_ in those methods.
- std::unique_ptr<net::URLRequest> temp = std::move(request_);
-}
-
-void AppCacheUpdateJob::URLFetcher::Start() {
- request_->set_first_party_for_cookies(job_->manifest_url_);
- request_->set_initiator(url::Origin(job_->manifest_url_));
- if (fetch_type_ == MANIFEST_FETCH && job_->doing_full_update_check_)
- request_->SetLoadFlags(request_->load_flags() | net::LOAD_BYPASS_CACHE);
- else if (existing_response_headers_.get())
- AddConditionalHeaders(existing_response_headers_.get());
- request_->Start();
-}
-
-void AppCacheUpdateJob::URLFetcher::OnReceivedRedirect(
- net::URLRequest* request,
- const net::RedirectInfo& redirect_info,
- bool* defer_redirect) {
- if (!request_)
- return;
- DCHECK_EQ(request_.get(), request);
- // Redirect is not allowed by the update process.
- job_->MadeProgress();
- redirect_response_code_ = request->GetResponseCode();
- request->Cancel();
- result_ = REDIRECT_ERROR;
- OnResponseCompleted(net::ERR_ABORTED);
-}
-
-void AppCacheUpdateJob::URLFetcher::OnResponseStarted(net::URLRequest* request,
- int net_error) {
- if (!request_)
- return;
- DCHECK_EQ(request_.get(), request);
- DCHECK_NE(net::ERR_IO_PENDING, net_error);
-
- int response_code = -1;
- if (net_error == net::OK) {
- response_code = request->GetResponseCode();
- job_->MadeProgress();
- }
-
- if ((response_code / 100) != 2) {
- if (response_code > 0)
- result_ = SERVER_ERROR;
- else
- result_ = NETWORK_ERROR;
- OnResponseCompleted(net_error);
- return;
- }
-
- if (url_.SchemeIsCryptographic()) {
- // Do not cache content with cert errors.
- // Also, we willfully violate the HTML5 spec at this point in order
- // to support the appcaching of cross-origin HTTPS resources.
- // We've opted for a milder constraint and allow caching unless
- // the resource has a "no-store" header. A spec change has been
- // requested on the whatwg list.
- // See http://code.google.com/p/chromium/issues/detail?id=69594
- // TODO(michaeln): Consider doing this for cross-origin HTTP too.
- const net::HttpNetworkSession::Params* session_params =
- request->context()->GetNetworkSessionParams();
- bool ignore_cert_errors = session_params &&
- session_params->ignore_certificate_errors;
- if ((net::IsCertStatusError(request->ssl_info().cert_status) &&
- !ignore_cert_errors) ||
- (url_.GetOrigin() != job_->manifest_url_.GetOrigin() &&
- request->response_headers()->
- HasHeaderValue("cache-control", "no-store"))) {
- DCHECK_EQ(-1, redirect_response_code_);
- request->Cancel();
- result_ = SECURITY_ERROR;
- OnResponseCompleted(net::ERR_ABORTED);
- return;
- }
- }
-
- // 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());
- scoped_refptr<HttpResponseInfoIOBuffer> io_buffer(
- new HttpResponseInfoIOBuffer(
- new net::HttpResponseInfo(request->response_info())));
- response_writer_->WriteInfo(
- io_buffer.get(),
- base::Bind(&URLFetcher::OnWriteComplete, base::Unretained(this)));
- } else {
- ReadResponseData();
- }
-}
-
-void AppCacheUpdateJob::URLFetcher::OnReadCompleted(
- net::URLRequest* request, int bytes_read) {
- if (!request_)
- return;
- DCHECK_NE(net::ERR_IO_PENDING, bytes_read);
- DCHECK_EQ(request_.get(), request);
- bool data_consumed = true;
- if (bytes_read > 0) {
- job_->MadeProgress();
- data_consumed = ConsumeResponseData(bytes_read);
- if (data_consumed) {
- while (true) {
- bytes_read = request->Read(buffer_.get(), kBufferSize);
- if (bytes_read <= 0)
- break;
- data_consumed = ConsumeResponseData(bytes_read);
- if (!data_consumed)
- break;
- }
- }
- }
-
- if (data_consumed && bytes_read != net::ERR_IO_PENDING) {
- DCHECK_EQ(UPDATE_OK, result_);
- OnResponseCompleted(bytes_read);
- }
-}
-
-void AppCacheUpdateJob::URLFetcher::AddConditionalHeaders(
- const net::HttpResponseHeaders* headers) {
- DCHECK(request_);
- DCHECK(headers);
- net::HttpRequestHeaders extra_headers;
-
- // Add If-Modified-Since header if response info has Last-Modified header.
- const std::string last_modified = "Last-Modified";
- std::string last_modified_value;
- headers->EnumerateHeader(nullptr, last_modified, &last_modified_value);
- if (!last_modified_value.empty()) {
- extra_headers.SetHeader(net::HttpRequestHeaders::kIfModifiedSince,
- last_modified_value);
- }
-
- // Add If-None-Match header if response info has ETag header.
- const std::string etag = "ETag";
- std::string etag_value;
- headers->EnumerateHeader(nullptr, etag, &etag_value);
- if (!etag_value.empty()) {
- extra_headers.SetHeader(net::HttpRequestHeaders::kIfNoneMatch,
- etag_value);
- }
- if (!extra_headers.IsEmpty())
- request_->SetExtraRequestHeaders(extra_headers);
-}
-
-void AppCacheUpdateJob::URLFetcher::OnWriteComplete(int result) {
- if (result < 0) {
- request_->Cancel();
- result_ = DISKCACHE_ERROR;
- OnResponseCompleted(net::ERR_ABORTED);
- return;
- }
- ReadResponseData();
-}
-
-void AppCacheUpdateJob::URLFetcher::ReadResponseData() {
- InternalUpdateState state = job_->internal_state_;
- if (state == CACHE_FAILURE || state == CANCELLED || state == COMPLETED)
- return;
- int bytes_read = request_->Read(buffer_.get(), kBufferSize);
- if (bytes_read != net::ERR_IO_PENDING)
- OnReadCompleted(request_.get(), bytes_read);
-}
-
-// Returns false if response data is processed asynchronously, in which
-// case ReadResponseData will be invoked when it is safe to continue
-// reading more response data from the request.
-bool AppCacheUpdateJob::URLFetcher::ConsumeResponseData(int bytes_read) {
- DCHECK_GT(bytes_read, 0);
- switch (fetch_type_) {
- case MANIFEST_FETCH:
- case MANIFEST_REFETCH:
- manifest_data_.append(buffer_->data(), bytes_read);
- break;
- case URL_FETCH:
- case MASTER_ENTRY_FETCH:
- DCHECK(response_writer_.get());
- response_writer_->WriteData(
- buffer_.get(),
- bytes_read,
- base::Bind(&URLFetcher::OnWriteComplete, base::Unretained(this)));
- return false; // wait for async write completion to continue reading
- default:
- NOTREACHED();
- }
- return true;
-}
-
-void AppCacheUpdateJob::URLFetcher::OnResponseCompleted(int net_error) {
- if (net_error == net::OK)
- job_->MadeProgress();
-
- // Retry for 503s where retry-after is 0.
- if (net_error == net::OK && request_->GetResponseCode() == 503 &&
- MaybeRetryRequest()) {
- return;
- }
-
- switch (fetch_type_) {
- case MANIFEST_FETCH:
- job_->HandleManifestFetchCompleted(this, net_error);
- break;
- case URL_FETCH:
- job_->HandleUrlFetchCompleted(this, net_error);
- break;
- case MASTER_ENTRY_FETCH:
- job_->HandleMasterEntryFetchCompleted(this, net_error);
- break;
- case MANIFEST_REFETCH:
- job_->HandleManifestRefetchCompleted(this, net_error);
- break;
- default:
- NOTREACHED();
- }
-
- delete this;
-}
-
-bool AppCacheUpdateJob::URLFetcher::MaybeRetryRequest() {
- if (retry_503_attempts_ >= kMax503Retries ||
- !request_->response_headers()->HasHeaderValue("retry-after", "0")) {
- return false;
- }
- ++retry_503_attempts_;
- result_ = UPDATE_OK;
- request_ = job_->service_->request_context()->CreateRequest(
- url_, net::DEFAULT_PRIORITY, this, kTrafficAnnotation);
- Start();
- return true;
-}
-
AppCacheUpdateJob::AppCacheUpdateJob(AppCacheServiceImpl* service,
AppCacheGroup* group)
: service_(service),
@@ -538,8 +275,8 @@ void AppCacheUpdateJob::StartUpdate(AppCacheHost* host,
BrowserThread::PostAfterStartupTask(
FROM_HERE, base::ThreadTaskRunnerHandle::Get(),
- base::Bind(&AppCacheUpdateJob::FetchManifest, weak_factory_.GetWeakPtr(),
- true));
+ base::BindOnce(&AppCacheUpdateJob::FetchManifest,
+ weak_factory_.GetWeakPtr(), true));
}
AppCacheResponseWriter* AppCacheUpdateJob::CreateResponseWriter() {
@@ -597,11 +334,11 @@ void AppCacheUpdateJob::HandleCacheFailure(
void AppCacheUpdateJob::FetchManifest(bool is_first_fetch) {
DCHECK(!manifest_fetcher_);
- manifest_fetcher_ = new URLFetcher(
- manifest_url_,
- is_first_fetch ? URLFetcher::MANIFEST_FETCH :
- URLFetcher::MANIFEST_REFETCH,
- this);
+ manifest_fetcher_ =
+ new URLFetcher(manifest_url_,
+ is_first_fetch ? URLFetcher::MANIFEST_FETCH
+ : URLFetcher::MANIFEST_REFETCH,
+ this, kBufferSize);
if (is_first_fetch) {
// Maybe load the cached headers to make a condiditional request.
@@ -630,22 +367,21 @@ void AppCacheUpdateJob::HandleManifestFetchCompleted(URLFetcher* fetcher,
manifest_fetcher_ = NULL;
- net::URLRequest* request = fetcher->request();
+ UpdateRequestBase* request = fetcher->request();
int response_code = -1;
bool is_valid_response_code = false;
if (net_error == net::OK) {
response_code = request->GetResponseCode();
is_valid_response_code = (response_code / 100 == 2);
- std::string mime_type;
- request->GetMimeType(&mime_type);
+ std::string mime_type = request->GetMimeType();
manifest_has_valid_mime_type_ = (mime_type == "text/cache-manifest");
}
if (is_valid_response_code) {
manifest_data_ = fetcher->manifest_data();
manifest_response_info_.reset(
- new net::HttpResponseInfo(request->response_info()));
+ new net::HttpResponseInfo(request->GetResponseInfo()));
if (update_type_ == UPGRADE_ATTEMPT)
CheckIfManifestChanged(); // continues asynchronously
else
@@ -772,8 +508,8 @@ void AppCacheUpdateJob::HandleUrlFetchCompleted(URLFetcher* fetcher,
int net_error) {
DCHECK(internal_state_ == DOWNLOADING);
- net::URLRequest* request = fetcher->request();
- const GURL& url = request->original_url();
+ UpdateRequestBase* request = fetcher->request();
+ const GURL& url = request->GetURL();
pending_url_fetches_.erase(url);
NotifyAllProgress(url);
++url_fetches_completed_;
@@ -873,8 +609,8 @@ void AppCacheUpdateJob::HandleMasterEntryFetchCompleted(URLFetcher* fetcher,
// master entry fetches when entering cache failure state so this will never
// be called in CACHE_FAILURE state.
- net::URLRequest* request = fetcher->request();
- const GURL& url = request->original_url();
+ UpdateRequestBase* request = fetcher->request();
+ const GURL& url = request->GetURL();
master_entry_fetches_.erase(url);
++master_entries_completed_;
@@ -926,13 +662,10 @@ void AppCacheUpdateJob::HandleMasterEntryFetchCompleted(URLFetcher* fetcher,
const char kFormatString[] = "Manifest fetch failed (%d) %s";
std::string message = FormatUrlErrorMessage(
- kFormatString, request->url(), fetcher->result(), response_code);
- host_notifier.SendErrorNotifications(
- AppCacheErrorDetails(message,
- APPCACHE_MANIFEST_ERROR,
- request->url(),
- response_code,
- false /*is_cross_origin*/));
+ kFormatString, request->GetURL(), fetcher->result(), response_code);
+ host_notifier.SendErrorNotifications(AppCacheErrorDetails(
+ message, APPCACHE_MANIFEST_ERROR, request->GetURL(), response_code,
+ false /*is_cross_origin*/));
// In downloading case, update result is different if all master entries
// failed vs. only some failing.
@@ -943,13 +676,11 @@ void AppCacheUpdateJob::HandleMasterEntryFetchCompleted(URLFetcher* fetcher,
// Section 6.9.4, step 22.3.
if (update_type_ == CACHE_ATTEMPT && pending_master_entries_.empty()) {
- HandleCacheFailure(AppCacheErrorDetails(message,
- APPCACHE_MANIFEST_ERROR,
- request->url(),
- response_code,
- false /*is_cross_origin*/),
- fetcher->result(),
- GURL());
+ HandleCacheFailure(
+ AppCacheErrorDetails(message, APPCACHE_MANIFEST_ERROR,
+ request->GetURL(), response_code,
+ false /*is_cross_origin*/),
+ fetcher->result(), GURL());
return;
}
}
@@ -1304,7 +1035,7 @@ void AppCacheUpdateJob::FetchUrls() {
// Continues asynchronously after data is loaded from newest cache.
} else {
URLFetcher* fetcher = new URLFetcher(
- url_to_fetch.url, URLFetcher::URL_FETCH, this);
+ url_to_fetch.url, URLFetcher::URL_FETCH, this, kBufferSize);
if (url_to_fetch.existing_response_info.get() &&
group_->newest_complete_cache()) {
AppCacheEntry* existing_entry =
@@ -1426,8 +1157,8 @@ void AppCacheUpdateJob::FetchMasterEntries() {
}
}
} else {
- URLFetcher* fetcher = new URLFetcher(
- url, URLFetcher::MASTER_ENTRY_FETCH, this);
+ URLFetcher* fetcher = new URLFetcher(url, URLFetcher::MASTER_ENTRY_FETCH,
+ this, kBufferSize);
fetcher->Start();
master_entry_fetches_.insert(PendingUrlFetches::value_type(url, fetcher));
}
@@ -1515,36 +1246,25 @@ void AppCacheUpdateJob::OnResponseInfoLoaded(
if (!http_info) {
LoadFromNewestCacheFailed(url, NULL); // no response found
+ } else if (!CanUseExistingResource(http_info)) {
+ LoadFromNewestCacheFailed(url, response_info);
} else {
- // Check if response can be re-used according to HTTP caching semantics.
- // Responses with a "vary" header get treated as expired.
- const std::string name = "vary";
- std::string value;
- size_t iter = 0;
- if (!http_info->headers.get() ||
- http_info->headers->RequiresValidation(http_info->request_time,
- http_info->response_time,
- base::Time::Now()) ||
- http_info->headers->EnumerateHeader(&iter, name, &value)) {
- LoadFromNewestCacheFailed(url, response_info);
- } else {
- DCHECK(group_->newest_complete_cache());
- AppCacheEntry* copy_me = group_->newest_complete_cache()->GetEntry(url);
- DCHECK(copy_me);
- DCHECK(copy_me->response_id() == response_id);
-
- AppCache::EntryMap::iterator it = url_file_list_.find(url);
- DCHECK(it != url_file_list_.end());
- AppCacheEntry& entry = it->second;
- entry.set_response_id(response_id);
- entry.set_response_size(copy_me->response_size());
- inprogress_cache_->AddOrModifyEntry(url, entry);
- NotifyAllProgress(url);
- ++url_fetches_completed_;
- }
+ DCHECK(group_->newest_complete_cache());
+ AppCacheEntry* copy_me = group_->newest_complete_cache()->GetEntry(url);
+ DCHECK(copy_me);
+ DCHECK_EQ(copy_me->response_id(), response_id);
+
+ AppCache::EntryMap::iterator it = url_file_list_.find(url);
+ DCHECK(it != url_file_list_.end());
+ AppCacheEntry& entry = it->second;
+ entry.set_response_id(response_id);
+ entry.set_response_size(copy_me->response_size());
+ inprogress_cache_->AddOrModifyEntry(url, entry);
+ NotifyAllProgress(url);
+ ++url_fetches_completed_;
}
- loading_responses_.erase(found);
+ loading_responses_.erase(found);
MaybeCompleteUpdate();
}
diff --git a/chromium/content/browser/appcache/appcache_update_job.h b/chromium/content/browser/appcache/appcache_update_job.h
index e11c78e5a5e..cce40a24c5b 100644
--- a/chromium/content/browser/appcache/appcache_update_job.h
+++ b/chromium/content/browser/appcache/appcache_update_job.h
@@ -36,6 +36,7 @@ FORWARD_DECLARE_TEST(AppCacheGroupTest, QueueUpdate);
class AppCacheGroupTest;
class AppCacheUpdateJobTest;
class HostNotifier;
+class URLFetcher;
// Application cache Update algorithm and state.
class CONTENT_EXPORT AppCacheUpdateJob
@@ -60,7 +61,11 @@ class CONTENT_EXPORT AppCacheUpdateJob
private:
friend class content::AppCacheGroupTest;
friend class content::AppCacheUpdateJobTest;
+
class URLFetcher;
+ class UpdateRequestBase;
+ class UpdateURLLoaderRequest;
+ class UpdateURLRequest;
// Master entries have multiple hosts, for example, the same page is opened
// in different tabs.
@@ -109,64 +114,6 @@ class CONTENT_EXPORT AppCacheUpdateJob
scoped_refptr<AppCacheResponseInfo> existing_response_info;
};
- class URLFetcher : public net::URLRequest::Delegate {
- public:
- enum FetchType {
- MANIFEST_FETCH,
- URL_FETCH,
- MASTER_ENTRY_FETCH,
- MANIFEST_REFETCH,
- };
- URLFetcher(const GURL& url,
- FetchType fetch_type,
- AppCacheUpdateJob* job);
- ~URLFetcher() override;
- void Start();
- FetchType fetch_type() const { return fetch_type_; }
- net::URLRequest* request() const { return request_.get(); }
- const AppCacheEntry& existing_entry() const { return existing_entry_; }
- const std::string& manifest_data() const { return manifest_data_; }
- AppCacheResponseWriter* response_writer() const {
- return response_writer_.get();
- }
- void set_existing_response_headers(net::HttpResponseHeaders* headers) {
- existing_response_headers_ = headers;
- }
- void set_existing_entry(const AppCacheEntry& entry) {
- existing_entry_ = entry;
- }
- ResultType result() const { return result_; }
- int redirect_response_code() const { return redirect_response_code_; }
-
- private:
- // URLRequest::Delegate overrides
- void OnReceivedRedirect(net::URLRequest* request,
- const net::RedirectInfo& redirect_info,
- bool* defer_redirect) override;
- void OnResponseStarted(net::URLRequest* request, int net_error) override;
- void OnReadCompleted(net::URLRequest* request, int bytes_read) override;
-
- void AddConditionalHeaders(const net::HttpResponseHeaders* headers);
- void OnWriteComplete(int result);
- void ReadResponseData();
- bool ConsumeResponseData(int bytes_read);
- void OnResponseCompleted(int net_error);
- bool MaybeRetryRequest();
-
- GURL url_;
- AppCacheUpdateJob* job_;
- FetchType fetch_type_;
- int retry_503_attempts_;
- scoped_refptr<net::IOBuffer> buffer_;
- std::unique_ptr<net::URLRequest> request_;
- AppCacheEntry existing_entry_;
- scoped_refptr<net::HttpResponseHeaders> existing_response_headers_;
- std::string manifest_data_;
- ResultType result_;
- int redirect_response_code_;
- std::unique_ptr<AppCacheResponseWriter> response_writer_;
- }; // class URLFetcher
-
AppCacheResponseWriter* CreateResponseWriter();
// Methods for AppCacheStorage::Delegate.
diff --git a/chromium/content/browser/appcache/appcache_update_job_unittest.cc b/chromium/content/browser/appcache/appcache_update_job_unittest.cc
index 078a640e9cb..0c9880505a6 100644
--- a/chromium/content/browser/appcache/appcache_update_job_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_update_job_unittest.cc
@@ -14,18 +14,28 @@
#include "base/location.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/stl_util.h"
#include "base/strings/stringprintf.h"
#include "base/synchronization/waitable_event.h"
+#include "base/test/scoped_feature_list.h"
#include "base/test/scoped_task_environment.h"
-#include "base/threading/thread.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/appcache/appcache_group.h"
#include "content/browser/appcache/appcache_host.h"
#include "content/browser/appcache/appcache_response.h"
+#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/common/content_features.h"
+#include "content/public/common/url_loader.mojom.h"
+#include "content/public/common/url_loader_factory.mojom.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"
#include "net/base/net_errors.h"
+#include "net/http/http_request_headers.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_util.h"
#include "net/url_request/url_request_error_job.h"
@@ -84,7 +94,6 @@ class MockHttpServer {
request, network_delegate, headers, body, true);
}
- private:
static void GetMockResponse(const std::string& path,
std::string* headers,
std::string* body) {
@@ -401,15 +410,23 @@ class RetryRequestTestJob : public net::URLRequestTestJob {
static net::URLRequestJob* RetryFactory(
net::URLRequest* request, net::NetworkDelegate* network_delegate) {
+ std::string headers;
+ GetResponseForURL(request->original_url(), &headers, nullptr);
+ return new RetryRequestTestJob(request, network_delegate, headers);
+ }
+
+ static void GetResponseForURL(const GURL& url,
+ std::string* headers,
+ std::string* data) {
++num_requests_;
- if (num_retries_ > 0 && request->original_url() == kRetryUrl) {
+ if (num_retries_ > 0 && url == kRetryUrl) {
--num_retries_;
- return new RetryRequestTestJob(request, network_delegate,
- RetryRequestTestJob::retry_headers());
+ *headers = RetryRequestTestJob::retry_headers();
} else {
- return new RetryRequestTestJob(request, network_delegate,
- RetryRequestTestJob::manifest_headers());
+ *headers = RetryRequestTestJob::manifest_headers();
}
+ if (data)
+ *data = RetryRequestTestJob::data();
}
private:
@@ -511,24 +528,29 @@ class HttpHeadersRequestTestJob : public net::URLRequestTestJob {
static net::URLRequestJob* IfModifiedSinceFactory(
net::URLRequest* request, net::NetworkDelegate* network_delegate) {
- if (!already_checked_) {
- already_checked_ = true; // only check once for a test
- const net::HttpRequestHeaders& extra_headers =
- request->extra_request_headers();
- std::string header_value;
- saw_if_modified_since_ =
- extra_headers.GetHeader(
- net::HttpRequestHeaders::kIfModifiedSince, &header_value) &&
- header_value == expect_if_modified_since_;
-
- saw_if_none_match_ =
- extra_headers.GetHeader(
- net::HttpRequestHeaders::kIfNoneMatch, &header_value) &&
- header_value == expect_if_none_match_;
- }
+ ValidateExtraHeaders(request->extra_request_headers());
return MockHttpServer::JobFactory(request, network_delegate);
}
+ static void ValidateExtraHeaders(
+ const net::HttpRequestHeaders& extra_headers) {
+ if (already_checked_)
+ return;
+
+ already_checked_ = true; // only check once for a test
+
+ std::string header_value;
+ saw_if_modified_since_ =
+ extra_headers.GetHeader(net::HttpRequestHeaders::kIfModifiedSince,
+ &header_value) &&
+ header_value == expect_if_modified_since_;
+
+ saw_if_none_match_ =
+ extra_headers.GetHeader(net::HttpRequestHeaders::kIfNoneMatch,
+ &header_value) &&
+ header_value == expect_if_none_match_;
+ }
+
protected:
~HttpHeadersRequestTestJob() override {}
@@ -558,13 +580,84 @@ class IfModifiedSinceJobFactory
}
};
-class IOThread : public base::Thread {
+// Provides a test URLLoaderFactory which serves content using the
+// MockHttpServer and RetryRequestTestJob classes.
+// TODO(ananta/michaeln). Remove dependencies on URLRequest based
+// classes by refactoring the response headers/data into a common class.
+class MockURLLoaderFactory : public mojom::URLLoaderFactory {
public:
- explicit IOThread(const char* name)
- : base::Thread(name) {
+ static void Create(mojom::URLLoaderFactoryPtr* loader_factory) {
+ mojom::URLLoaderFactoryRequest request = mojo::MakeRequest(loader_factory);
+ new MockURLLoaderFactory(std::move(request));
+ }
+
+ // mojom::URLLoaderFactory implementation.
+ void CreateLoaderAndStart(mojom::URLLoaderRequest request,
+ int32_t routing_id,
+ int32_t request_id,
+ uint32_t options,
+ const ResourceRequest& url_request,
+ mojom::URLLoaderClientPtr client,
+ const net::MutableNetworkTrafficAnnotationTag&
+ traffic_annotation) override {
+ if (url_request.url.host() == "failme" ||
+ url_request.url.host() == "testme") {
+ ResourceRequestCompletionStatus status;
+ status.error_code = -100;
+ client->OnComplete(status);
+ return;
+ }
+
+ net::HttpRequestHeaders request_headers;
+ request_headers.AddHeadersFromString(url_request.headers);
+ HttpHeadersRequestTestJob::ValidateExtraHeaders(request_headers);
+
+ std::string headers;
+ std::string body;
+ if (url_request.url == RetryRequestTestJob::kRetryUrl) {
+ RetryRequestTestJob::GetResponseForURL(url_request.url, &headers, &body);
+ } else {
+ MockHttpServer::GetMockResponse(url_request.url.path(), &headers, &body);
+ }
+
+ net::HttpResponseInfo info;
+ info.headers = new net::HttpResponseHeaders(
+ net::HttpUtil::AssembleRawHeaders(headers.c_str(), headers.length()));
+
+ ResourceResponseHead response;
+ response.headers = info.headers;
+ response.headers->GetMimeType(&response.mime_type);
+
+ client->OnReceiveResponse(response, base::nullopt, nullptr);
+
+ mojo::DataPipe data_pipe;
+
+ uint32_t bytes_written = body.size();
+ data_pipe.producer_handle->WriteData(body.data(), &bytes_written,
+ MOJO_WRITE_DATA_FLAG_ALL_OR_NONE);
+ client->OnStartLoadingResponseBody(std::move(data_pipe.consumer_handle));
+ }
+
+ void Clone(mojom::URLLoaderFactoryRequest factory) override { NOTREACHED(); }
+
+ private:
+ MockURLLoaderFactory(mojom::URLLoaderFactoryRequest request)
+ : binding_(this, std::move(request)) {
+ binding_.set_connection_error_handler(base::BindOnce(
+ &MockURLLoaderFactory::OnConnectionError, base::Unretained(this)));
}
- ~IOThread() override { Stop(); }
+ void OnConnectionError() { delete this; }
+
+ mojo::Binding<mojom::URLLoaderFactory> binding_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockURLLoaderFactory);
+};
+
+class IOThread {
+ public:
+ IOThread() {}
+ ~IOThread() {}
net::URLRequestContext* request_context() {
return request_context_.get();
@@ -576,7 +669,7 @@ class IOThread : public base::Thread {
request_context_->set_job_factory(job_factory_.get());
}
- void Init() override {
+ void Init() {
std::unique_ptr<net::URLRequestJobFactoryImpl> factory(
new net::URLRequestJobFactoryImpl());
factory->SetProtocolHandler("http",
@@ -588,7 +681,7 @@ class IOThread : public base::Thread {
request_context_->set_job_factory(job_factory_.get());
}
- void CleanUp() override {
+ void CleanUp() {
request_context_.reset();
job_factory_.reset();
}
@@ -598,11 +691,19 @@ class IOThread : public base::Thread {
std::unique_ptr<net::URLRequestContext> request_context_;
};
-class AppCacheUpdateJobTest : public testing::Test,
+// Controls whether we instantiate the URLRequest based AppCache handler or
+// the URLLoader based one.
+enum RequestHandlerType {
+ URLREQUEST,
+ URLLOADER,
+};
+
+class AppCacheUpdateJobTest : public testing::TestWithParam<RequestHandlerType>,
public AppCacheGroup::UpdateObserver {
public:
AppCacheUpdateJobTest()
- : do_checks_after_update_finished_(false),
+ : io_thread_(new IOThread),
+ do_checks_after_update_finished_(false),
expect_group_obsolete_(false),
expect_group_has_cache_(false),
expect_group_is_being_deleted_(false),
@@ -612,10 +713,31 @@ class AppCacheUpdateJobTest : public testing::Test,
expect_newest_cache_(NULL),
expect_non_null_update_time_(false),
tested_manifest_(NONE),
- tested_manifest_path_override_(NULL) {
- io_thread_.reset(new IOThread("AppCacheUpdateJob IO test thread"));
- base::Thread::Options options(base::MessageLoop::TYPE_IO, 0);
- io_thread_->StartWithOptions(options);
+ tested_manifest_path_override_(NULL),
+ request_handler_type_(GetParam()),
+ thread_bundle_(content::TestBrowserThreadBundle::REAL_IO_THREAD) {
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&IOThread::Init, base::Unretained(io_thread_.get())));
+
+ if (request_handler_type_ == URLLOADER) {
+ loader_factory_getter_ = new URLLoaderFactoryGetter();
+ feature_list_.InitAndEnableFeature(features::kNetworkService);
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&AppCacheUpdateJobTest::InitializeFactory,
+ base::Unretained(this)));
+ }
+ }
+
+ ~AppCacheUpdateJobTest() {
+ loader_factory_getter_ = nullptr;
+ // 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::BindOnce(&IOThread::CleanUp, base::Unretained(io_thread_.get())));
}
// Use a separate IO thread to run a test. Thread will be destroyed
@@ -625,13 +747,23 @@ class AppCacheUpdateJobTest : public testing::Test,
event_.reset(new base::WaitableEvent(
base::WaitableEvent::ResetPolicy::AUTOMATIC,
base::WaitableEvent::InitialState::NOT_SIGNALED));
- io_thread_->task_runner()->PostTask(
- FROM_HERE, base::Bind(method, base::Unretained(this)));
+
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+ base::BindOnce(method, base::Unretained(this)));
// Wait until task is done before exiting the test.
event_->Wait();
}
+ void InitializeFactory() {
+ if (!loader_factory_getter_.get())
+ return;
+ mojom::URLLoaderFactoryPtr test_loader_factory;
+ MockURLLoaderFactory::Create(&test_loader_factory);
+ loader_factory_getter_->SetNetworkFactoryForTesting(
+ std::move(test_loader_factory));
+ }
+
void StartCacheAttemptTest() {
ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
@@ -803,11 +935,13 @@ class AppCacheUpdateJobTest : public testing::Test,
void ManifestRedirectTest() {
ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
- net::URLRequestJobFactoryImpl* new_factory(
- new net::URLRequestJobFactoryImpl);
- new_factory->SetProtocolHandler("http",
- base::WrapUnique(new RedirectFactory));
- io_thread_->SetNewJobFactory(new_factory);
+ if (request_handler_type_ == URLREQUEST) {
+ net::URLRequestJobFactoryImpl* new_factory(
+ new net::URLRequestJobFactoryImpl);
+ new_factory->SetProtocolHandler("http",
+ base::WrapUnique(new RedirectFactory));
+ io_thread_->SetNewJobFactory(new_factory);
+ }
MakeService();
group_ = new AppCacheGroup(service_->storage(), GURL("http://testme"),
@@ -1388,6 +1522,70 @@ class AppCacheUpdateJobTest : public testing::Test,
// Start update after data write completes asynchronously.
}
+ void UpgradeLoadFromNewestCacheReuseVaryHeaderTest() {
+ ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
+
+ MakeService();
+ group_ = new AppCacheGroup(service_->storage(),
+ MockHttpServer::GetMockUrl("files/manifest1"),
+ service_->storage()->NewGroupId());
+ AppCacheUpdateJob* update =
+ new AppCacheUpdateJob(service_.get(), group_.get());
+ group_->update_job_ = update;
+
+ AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 42);
+ MockFrontend* frontend = MakeMockFrontend();
+ AppCacheHost* host = MakeHost(1, frontend);
+ host->AssociateCompleteCache(cache);
+
+ // Give the newest cache an entry that is in storage.
+ response_writer_.reset(
+ service_->storage()->CreateResponseWriter(group_->manifest_url()));
+ cache->AddEntry(MockHttpServer::GetMockUrl("files/explicit1"),
+ AppCacheEntry(AppCacheEntry::EXPLICIT,
+ response_writer_->response_id()));
+
+ // Set up checks for when update job finishes.
+ do_checks_after_update_finished_ = true;
+ expect_group_obsolete_ = false;
+ expect_group_has_cache_ = true;
+ expect_old_cache_ = cache;
+ expect_response_ids_.insert(std::map<GURL, int64_t>::value_type(
+ MockHttpServer::GetMockUrl("files/explicit1"),
+ response_writer_->response_id()));
+ tested_manifest_ = MANIFEST1;
+ MockFrontend::HostIds ids(1, host->host_id());
+ frontend->AddExpectedEvent(ids, APPCACHE_CHECKING_EVENT);
+ frontend->AddExpectedEvent(ids, APPCACHE_DOWNLOADING_EVENT);
+ frontend->AddExpectedEvent(ids, APPCACHE_PROGRESS_EVENT);
+ frontend->AddExpectedEvent(ids, APPCACHE_PROGRESS_EVENT);
+ frontend->AddExpectedEvent(ids, APPCACHE_PROGRESS_EVENT); // final
+ frontend->AddExpectedEvent(ids, APPCACHE_UPDATE_READY_EVENT);
+
+ // Seed storage with expected http response info for an entry
+ // with a vary header for which we allow reuse.
+ const char data[] =
+ "HTTP/1.1 200 OK\0"
+ "Cache-Control: max-age=8675309\0"
+ "Vary: origin, accept-encoding\0"
+ "\0";
+ net::HttpResponseHeaders* headers =
+ new net::HttpResponseHeaders(std::string(data, arraysize(data)));
+ net::HttpResponseInfo* response_info = new net::HttpResponseInfo();
+ response_info->request_time = base::Time::Now();
+ response_info->response_time = base::Time::Now();
+ response_info->headers = headers; // adds ref to headers
+ scoped_refptr<HttpResponseInfoIOBuffer> io_buffer(
+ new HttpResponseInfoIOBuffer(response_info)); // adds ref to info
+ response_writer_->WriteInfo(
+ io_buffer.get(),
+ base::Bind(
+ &AppCacheUpdateJobTest::StartUpdateAfterSeedingStorageData,
+ base::Unretained(this)));
+
+ // Start update after data write completes asynchronously.
+ }
+
void UpgradeSuccessMergedTypesTest() {
ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
@@ -1684,11 +1882,14 @@ class AppCacheUpdateJobTest : public testing::Test,
// Set some large number of times to return retry.
// Expect 1 manifest fetch and 3 retries.
RetryRequestTestJob::Initialize(5, RetryRequestTestJob::RETRY_AFTER_0, 4);
- net::URLRequestJobFactoryImpl* new_factory(
- new net::URLRequestJobFactoryImpl);
- new_factory->SetProtocolHandler(
- "http", base::WrapUnique(new RetryRequestTestJobFactory));
- io_thread_->SetNewJobFactory(new_factory);
+
+ if (request_handler_type_ == URLREQUEST) {
+ net::URLRequestJobFactoryImpl* new_factory(
+ new net::URLRequestJobFactoryImpl);
+ new_factory->SetProtocolHandler(
+ "http", base::WrapUnique(new RetryRequestTestJobFactory));
+ io_thread_->SetNewJobFactory(new_factory);
+ }
MakeService();
group_ = new AppCacheGroup(service_->storage(),
@@ -1718,11 +1919,14 @@ class AppCacheUpdateJobTest : public testing::Test,
// Set some large number of times to return retry.
// Expect 1 manifest fetch and 0 retries.
RetryRequestTestJob::Initialize(5, RetryRequestTestJob::NO_RETRY_AFTER, 1);
- net::URLRequestJobFactoryImpl* new_factory(
- new net::URLRequestJobFactoryImpl);
- new_factory->SetProtocolHandler(
- "http", base::WrapUnique(new RetryRequestTestJobFactory));
- io_thread_->SetNewJobFactory(new_factory);
+
+ if (request_handler_type_ == URLREQUEST) {
+ net::URLRequestJobFactoryImpl* new_factory(
+ new net::URLRequestJobFactoryImpl);
+ new_factory->SetProtocolHandler(
+ "http", base::WrapUnique(new RetryRequestTestJobFactory));
+ io_thread_->SetNewJobFactory(new_factory);
+ }
MakeService();
group_ = new AppCacheGroup(service_->storage(),
@@ -1753,11 +1957,14 @@ class AppCacheUpdateJobTest : public testing::Test,
// Expect 1 request and 0 retry attempts.
RetryRequestTestJob::Initialize(
5, RetryRequestTestJob::NONZERO_RETRY_AFTER, 1);
- net::URLRequestJobFactoryImpl* new_factory(
- new net::URLRequestJobFactoryImpl);
- new_factory->SetProtocolHandler(
- "http", base::WrapUnique(new RetryRequestTestJobFactory));
- io_thread_->SetNewJobFactory(new_factory);
+
+ if (request_handler_type_ == URLREQUEST) {
+ net::URLRequestJobFactoryImpl* new_factory(
+ new net::URLRequestJobFactoryImpl);
+ new_factory->SetProtocolHandler(
+ "http", base::WrapUnique(new RetryRequestTestJobFactory));
+ io_thread_->SetNewJobFactory(new_factory);
+ }
MakeService();
group_ = new AppCacheGroup(service_->storage(),
@@ -1787,11 +1994,14 @@ class AppCacheUpdateJobTest : public testing::Test,
// Set 2 as the retry limit (does not exceed the max).
// Expect 1 manifest fetch, 2 retries, 1 url fetch, 1 manifest refetch.
RetryRequestTestJob::Initialize(2, RetryRequestTestJob::RETRY_AFTER_0, 5);
- net::URLRequestJobFactoryImpl* new_factory(
- new net::URLRequestJobFactoryImpl);
- new_factory->SetProtocolHandler(
- "http", base::WrapUnique(new RetryRequestTestJobFactory));
- io_thread_->SetNewJobFactory(new_factory);
+
+ if (request_handler_type_ == URLREQUEST) {
+ net::URLRequestJobFactoryImpl* new_factory(
+ new net::URLRequestJobFactoryImpl);
+ new_factory->SetProtocolHandler(
+ "http", base::WrapUnique(new RetryRequestTestJobFactory));
+ io_thread_->SetNewJobFactory(new_factory);
+ }
MakeService();
group_ = new AppCacheGroup(service_->storage(),
@@ -1821,15 +2031,19 @@ class AppCacheUpdateJobTest : public testing::Test,
// Set 1 as the retry limit (does not exceed the max).
// Expect 1 manifest fetch, 1 url fetch, 1 url retry, 1 manifest refetch.
RetryRequestTestJob::Initialize(1, RetryRequestTestJob::RETRY_AFTER_0, 4);
- net::URLRequestJobFactoryImpl* new_factory(
- new net::URLRequestJobFactoryImpl);
- new_factory->SetProtocolHandler(
- "http", base::WrapUnique(new RetryRequestTestJobFactory));
- io_thread_->SetNewJobFactory(new_factory);
+
+ if (request_handler_type_ == URLREQUEST) {
+ net::URLRequestJobFactoryImpl* new_factory(
+ new net::URLRequestJobFactoryImpl);
+ new_factory->SetProtocolHandler(
+ "http", base::WrapUnique(new RetryRequestTestJobFactory));
+ io_thread_->SetNewJobFactory(new_factory);
+ }
MakeService();
- group_ = new AppCacheGroup(service_->storage(), GURL("http://retryurl"),
- service_->storage()->NewGroupId());
+ group_ =
+ new AppCacheGroup(service_->storage(), RetryRequestTestJob::kRetryUrl,
+ service_->storage()->NewGroupId());
AppCacheUpdateJob* update =
new AppCacheUpdateJob(service_.get(), group_.get());
group_->update_job_ = update;
@@ -2684,14 +2898,21 @@ class AppCacheUpdateJobTest : public testing::Test,
group_->AddUpdateObserver(this);
}
- void IfModifiedSinceTest() {
+ static void VerifyHeadersAndDeleteUpdate(AppCacheUpdateJob* update) {
+ HttpHeadersRequestTestJob::Verify();
+ delete update;
+ }
+
+ void IfModifiedSinceTestCache() {
ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
- net::URLRequestJobFactoryImpl* new_factory(
- new net::URLRequestJobFactoryImpl);
- new_factory->SetProtocolHandler(
- "http", base::WrapUnique(new IfModifiedSinceJobFactory));
- io_thread_->SetNewJobFactory(new_factory);
+ if (request_handler_type_ == URLREQUEST) {
+ net::URLRequestJobFactoryImpl* new_factory(
+ new net::URLRequestJobFactoryImpl);
+ new_factory->SetProtocolHandler(
+ "http", base::WrapUnique(new IfModifiedSinceJobFactory));
+ io_thread_->SetNewJobFactory(new_factory);
+ }
MakeService();
group_ = new AppCacheGroup(
@@ -2706,8 +2927,33 @@ class AppCacheUpdateJobTest : public testing::Test,
MockFrontend mock_frontend;
AppCacheHost host(1, &mock_frontend, service_.get());
update->StartUpdate(&host, GURL());
- HttpHeadersRequestTestJob::Verify();
- delete update;
+
+ // If URLLoader based tests are enabled, we need to wait for the URL
+ // load requests to make it to the MockURLLoaderFactory.
+ if (request_handler_type_ == URLLOADER) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&AppCacheUpdateJobTest::VerifyHeadersAndDeleteUpdate,
+ update));
+ } else {
+ VerifyHeadersAndDeleteUpdate(update);
+ }
+
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(&AppCacheUpdateJobTest::UpdateFinishedUnwound,
+ base::Unretained(this)));
+ }
+
+ void IfModifiedTestRefetch() {
+ ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
+
+ if (request_handler_type_ == URLREQUEST) {
+ net::URLRequestJobFactoryImpl* new_factory(
+ new net::URLRequestJobFactoryImpl);
+ new_factory->SetProtocolHandler(
+ "http", base::WrapUnique(new IfModifiedSinceJobFactory));
+ io_thread_->SetNewJobFactory(new_factory);
+ }
// Now simulate a refetch manifest request. Will start fetch request
// synchronously.
@@ -2719,15 +2965,46 @@ class AppCacheUpdateJobTest : public testing::Test,
net::HttpResponseInfo* response_info = new net::HttpResponseInfo();
response_info->headers = headers; // adds ref to headers
+ MakeService();
+ group_ =
+ new AppCacheGroup(service_->storage(), GURL("http://headertest"), 111);
+
HttpHeadersRequestTestJob::Initialize(std::string(), std::string());
- update = new AppCacheUpdateJob(service_.get(), group_.get());
+
+ AppCacheUpdateJob* update =
+ new AppCacheUpdateJob(service_.get(), group_.get());
group_->update_job_ = update;
group_->update_status_ = AppCacheGroup::DOWNLOADING;
update->manifest_response_info_.reset(response_info);
update->internal_state_ = AppCacheUpdateJob::REFETCH_MANIFEST;
update->FetchManifest(false); // not first request
- HttpHeadersRequestTestJob::Verify();
- delete update;
+
+ // If URLLoader based tests are enabled, we need to wait for the URL
+ // load requests to make it to the MockURLLoaderFactory.
+ if (request_handler_type_ == URLLOADER) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&AppCacheUpdateJobTest::VerifyHeadersAndDeleteUpdate,
+ update));
+ } else {
+ VerifyHeadersAndDeleteUpdate(update);
+ }
+
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(&AppCacheUpdateJobTest::UpdateFinishedUnwound,
+ base::Unretained(this)));
+ }
+
+ void IfModifiedTestLastModified() {
+ ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
+
+ if (request_handler_type_ == URLREQUEST) {
+ net::URLRequestJobFactoryImpl* new_factory(
+ new net::URLRequestJobFactoryImpl);
+ new_factory->SetProtocolHandler(
+ "http", base::WrapUnique(new IfModifiedSinceJobFactory));
+ io_thread_->SetNewJobFactory(new_factory);
+ }
// Change the headers to include a Last-Modified header. Manifest refetch
// should include If-Modified-Since header.
@@ -2737,21 +3014,37 @@ class AppCacheUpdateJobTest : public testing::Test,
"\0";
net::HttpResponseHeaders* headers2 =
new net::HttpResponseHeaders(std::string(data2, arraysize(data2)));
- response_info = new net::HttpResponseInfo();
+ net::HttpResponseInfo* response_info = new net::HttpResponseInfo();
response_info->headers = headers2;
+ MakeService();
+ group_ =
+ new AppCacheGroup(service_->storage(), GURL("http://headertest"), 111);
+
HttpHeadersRequestTestJob::Initialize("Sat, 29 Oct 1994 19:43:31 GMT",
std::string());
- update = new AppCacheUpdateJob(service_.get(), group_.get());
+ AppCacheUpdateJob* update =
+ new AppCacheUpdateJob(service_.get(), group_.get());
group_->update_job_ = update;
group_->update_status_ = AppCacheGroup::DOWNLOADING;
update->manifest_response_info_.reset(response_info);
update->internal_state_ = AppCacheUpdateJob::REFETCH_MANIFEST;
update->FetchManifest(false); // not first request
- HttpHeadersRequestTestJob::Verify();
- delete update;
- UpdateFinished();
+ // If URLLoader based tests are enabled, we need to wait for the URL
+ // load requests to make it to the MockURLLoaderFactory.
+ if (request_handler_type_ == URLLOADER) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&AppCacheUpdateJobTest::VerifyHeadersAndDeleteUpdate,
+ update));
+ } else {
+ VerifyHeadersAndDeleteUpdate(update);
+ }
+
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(&AppCacheUpdateJobTest::UpdateFinishedUnwound,
+ base::Unretained(this)));
}
void IfModifiedSinceUpgradeTest() {
@@ -2759,11 +3052,14 @@ class AppCacheUpdateJobTest : public testing::Test,
HttpHeadersRequestTestJob::Initialize("Sat, 29 Oct 1994 19:43:31 GMT",
std::string());
- net::URLRequestJobFactoryImpl* new_factory(
- new net::URLRequestJobFactoryImpl);
- new_factory->SetProtocolHandler(
- "http", base::WrapUnique(new IfModifiedSinceJobFactory));
- io_thread_->SetNewJobFactory(new_factory);
+
+ if (request_handler_type_ == URLREQUEST) {
+ net::URLRequestJobFactoryImpl* new_factory(
+ new net::URLRequestJobFactoryImpl);
+ new_factory->SetProtocolHandler(
+ "http", base::WrapUnique(new IfModifiedSinceJobFactory));
+ io_thread_->SetNewJobFactory(new_factory);
+ }
MakeService();
group_ = new AppCacheGroup(
@@ -2822,11 +3118,14 @@ class AppCacheUpdateJobTest : public testing::Test,
ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
HttpHeadersRequestTestJob::Initialize(std::string(), "\"LadeDade\"");
- net::URLRequestJobFactoryImpl* new_factory(
- new net::URLRequestJobFactoryImpl);
- new_factory->SetProtocolHandler(
- "http", base::WrapUnique(new IfModifiedSinceJobFactory));
- io_thread_->SetNewJobFactory(new_factory);
+
+ if (request_handler_type_ == URLREQUEST) {
+ net::URLRequestJobFactoryImpl* new_factory(
+ new net::URLRequestJobFactoryImpl);
+ new_factory->SetProtocolHandler(
+ "http", base::WrapUnique(new IfModifiedSinceJobFactory));
+ io_thread_->SetNewJobFactory(new_factory);
+ }
MakeService();
group_ = new AppCacheGroup(
@@ -2885,11 +3184,14 @@ class AppCacheUpdateJobTest : public testing::Test,
ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
HttpHeadersRequestTestJob::Initialize(std::string(), "\"LadeDade\"");
- net::URLRequestJobFactoryImpl* new_factory(
- new net::URLRequestJobFactoryImpl);
- new_factory->SetProtocolHandler(
- "http", base::WrapUnique(new IfModifiedSinceJobFactory));
- io_thread_->SetNewJobFactory(new_factory);
+
+ if (request_handler_type_ == URLREQUEST) {
+ net::URLRequestJobFactoryImpl* new_factory(
+ new net::URLRequestJobFactoryImpl);
+ new_factory->SetProtocolHandler(
+ "http", base::WrapUnique(new IfModifiedSinceJobFactory));
+ io_thread_->SetNewJobFactory(new_factory);
+ }
MakeService();
group_ = new AppCacheGroup(
@@ -2912,10 +3214,21 @@ class AppCacheUpdateJobTest : public testing::Test,
update->manifest_response_info_.reset(response_info);
update->internal_state_ = AppCacheUpdateJob::REFETCH_MANIFEST;
update->FetchManifest(false); // not first request
- HttpHeadersRequestTestJob::Verify();
- delete update;
- UpdateFinished();
+ // If URLLoader based tests are enabled, we need to wait for the URL
+ // load requests to make it to the MockURLLoaderFactory.
+ if (request_handler_type_ == URLLOADER) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&AppCacheUpdateJobTest::VerifyHeadersAndDeleteUpdate,
+ update));
+ } else {
+ VerifyHeadersAndDeleteUpdate(update);
+ }
+
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(&AppCacheUpdateJobTest::UpdateFinishedUnwound,
+ base::Unretained(this)));
}
void MultipleHeadersRefetchTest() {
@@ -2924,11 +3237,14 @@ class AppCacheUpdateJobTest : public testing::Test,
// Verify that code is correct when building multiple extra headers.
HttpHeadersRequestTestJob::Initialize(
"Sat, 29 Oct 1994 19:43:31 GMT", "\"LadeDade\"");
- net::URLRequestJobFactoryImpl* new_factory(
- new net::URLRequestJobFactoryImpl);
- new_factory->SetProtocolHandler(
- "http", base::WrapUnique(new IfModifiedSinceJobFactory));
- io_thread_->SetNewJobFactory(new_factory);
+
+ if (request_handler_type_ == URLREQUEST) {
+ net::URLRequestJobFactoryImpl* new_factory(
+ new net::URLRequestJobFactoryImpl);
+ new_factory->SetProtocolHandler(
+ "http", base::WrapUnique(new IfModifiedSinceJobFactory));
+ io_thread_->SetNewJobFactory(new_factory);
+ }
MakeService();
group_ = new AppCacheGroup(
@@ -2952,10 +3268,21 @@ class AppCacheUpdateJobTest : public testing::Test,
update->manifest_response_info_.reset(response_info);
update->internal_state_ = AppCacheUpdateJob::REFETCH_MANIFEST;
update->FetchManifest(false); // not first request
- HttpHeadersRequestTestJob::Verify();
- delete update;
- UpdateFinished();
+ // If URLLoader based tests are enabled, we need to wait for the URL
+ // load requests to make it to the MockURLLoaderFactory.
+ if (request_handler_type_ == URLLOADER) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&AppCacheUpdateJobTest::VerifyHeadersAndDeleteUpdate,
+ update));
+ } else {
+ VerifyHeadersAndDeleteUpdate(update);
+ }
+
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(&AppCacheUpdateJobTest::UpdateFinishedUnwound,
+ base::Unretained(this)));
}
void CrossOriginHttpsSuccessTest() {
@@ -3031,8 +3358,8 @@ class AppCacheUpdateJobTest : public testing::Test,
// We unwind the stack prior to finishing up to let stack-based objects
// get deleted.
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&AppCacheUpdateJobTest::UpdateFinishedUnwound,
- base::Unretained(this)));
+ FROM_HERE, base::BindOnce(&AppCacheUpdateJobTest::UpdateFinishedUnwound,
+ base::Unretained(this)));
}
void UpdateFinishedUnwound() {
@@ -3055,6 +3382,7 @@ class AppCacheUpdateJobTest : public testing::Test,
void MakeService() {
service_.reset(new MockAppCacheService());
service_->set_request_context(io_thread_->request_context());
+ service_->set_url_loader_factory_getter(loader_factory_getter_.get());
}
AppCache* MakeCacheForGroup(int64_t cache_id, int64_t manifest_response_id) {
@@ -3415,7 +3743,7 @@ class AppCacheUpdateJobTest : public testing::Test,
MANIFEST_WITH_INTERCEPT
};
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ // base::test::ScopedTaskEnvironment scoped_task_environment_;
std::unique_ptr<IOThread> io_thread_;
std::unique_ptr<MockAppCacheService> service_;
@@ -3451,9 +3779,14 @@ class AppCacheUpdateJobTest : public testing::Test,
const char* tested_manifest_path_override_;
AppCache::EntryMap expect_extra_entries_;
std::map<GURL, int64_t> expect_response_ids_;
+
+ RequestHandlerType request_handler_type_;
+ base::test::ScopedFeatureList feature_list_;
+ scoped_refptr<URLLoaderFactoryGetter> loader_factory_getter_;
+ content::TestBrowserThreadBundle thread_bundle_;
};
-TEST_F(AppCacheUpdateJobTest, AlreadyChecking) {
+TEST_P(AppCacheUpdateJobTest, AlreadyChecking) {
MockAppCacheService service;
scoped_refptr<AppCacheGroup> group(
new AppCacheGroup(service.storage(), GURL("http://manifesturl.com"),
@@ -3481,7 +3814,7 @@ TEST_F(AppCacheUpdateJobTest, AlreadyChecking) {
EXPECT_EQ(AppCacheGroup::CHECKING, group->update_status());
}
-TEST_F(AppCacheUpdateJobTest, AlreadyDownloading) {
+TEST_P(AppCacheUpdateJobTest, AlreadyDownloading) {
MockAppCacheService service;
scoped_refptr<AppCacheGroup> group(
new AppCacheGroup(service.storage(), GURL("http://manifesturl.com"),
@@ -3515,218 +3848,235 @@ TEST_F(AppCacheUpdateJobTest, AlreadyDownloading) {
EXPECT_EQ(AppCacheGroup::DOWNLOADING, group->update_status());
}
-TEST_F(AppCacheUpdateJobTest, StartCacheAttempt) {
+TEST_P(AppCacheUpdateJobTest, StartCacheAttempt) {
RunTestOnIOThread(&AppCacheUpdateJobTest::StartCacheAttemptTest);
}
-TEST_F(AppCacheUpdateJobTest, StartUpgradeAttempt) {
+TEST_P(AppCacheUpdateJobTest, StartUpgradeAttempt) {
RunTestOnIOThread(&AppCacheUpdateJobTest::StartUpgradeAttemptTest);
}
-TEST_F(AppCacheUpdateJobTest, CacheAttemptFetchManifestFail) {
+TEST_P(AppCacheUpdateJobTest, CacheAttemptFetchManifestFail) {
RunTestOnIOThread(&AppCacheUpdateJobTest::CacheAttemptFetchManifestFailTest);
}
-TEST_F(AppCacheUpdateJobTest, UpgradeFetchManifestFail) {
+TEST_P(AppCacheUpdateJobTest, UpgradeFetchManifestFail) {
RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeFetchManifestFailTest);
}
-TEST_F(AppCacheUpdateJobTest, ManifestRedirect) {
+TEST_P(AppCacheUpdateJobTest, ManifestRedirect) {
RunTestOnIOThread(&AppCacheUpdateJobTest::ManifestRedirectTest);
}
-TEST_F(AppCacheUpdateJobTest, ManifestMissingMimeTypeTest) {
+TEST_P(AppCacheUpdateJobTest, ManifestMissingMimeTypeTest) {
RunTestOnIOThread(&AppCacheUpdateJobTest::ManifestMissingMimeTypeTest);
}
-TEST_F(AppCacheUpdateJobTest, ManifestNotFound) {
+TEST_P(AppCacheUpdateJobTest, ManifestNotFound) {
RunTestOnIOThread(&AppCacheUpdateJobTest::ManifestNotFoundTest);
}
-TEST_F(AppCacheUpdateJobTest, ManifestGone) {
+TEST_P(AppCacheUpdateJobTest, ManifestGone) {
RunTestOnIOThread(&AppCacheUpdateJobTest::ManifestGoneTest);
}
-TEST_F(AppCacheUpdateJobTest, CacheAttemptNotModified) {
+TEST_P(AppCacheUpdateJobTest, CacheAttemptNotModified) {
RunTestOnIOThread(&AppCacheUpdateJobTest::CacheAttemptNotModifiedTest);
}
-TEST_F(AppCacheUpdateJobTest, UpgradeNotModified) {
+TEST_P(AppCacheUpdateJobTest, UpgradeNotModified) {
RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeNotModifiedTest);
}
-TEST_F(AppCacheUpdateJobTest, UpgradeManifestDataUnchanged) {
+TEST_P(AppCacheUpdateJobTest, UpgradeManifestDataUnchanged) {
RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeManifestDataUnchangedTest);
}
-TEST_F(AppCacheUpdateJobTest, Bug95101Test) {
+TEST_P(AppCacheUpdateJobTest, Bug95101Test) {
RunTestOnIOThread(&AppCacheUpdateJobTest::Bug95101Test);
}
-TEST_F(AppCacheUpdateJobTest, BasicCacheAttemptSuccess) {
+TEST_P(AppCacheUpdateJobTest, BasicCacheAttemptSuccess) {
RunTestOnIOThread(&AppCacheUpdateJobTest::BasicCacheAttemptSuccessTest);
}
-TEST_F(AppCacheUpdateJobTest, DownloadInterceptEntriesTest) {
+TEST_P(AppCacheUpdateJobTest, DownloadInterceptEntriesTest) {
RunTestOnIOThread(&AppCacheUpdateJobTest::DownloadInterceptEntriesTest);
}
-TEST_F(AppCacheUpdateJobTest, BasicUpgradeSuccess) {
+TEST_P(AppCacheUpdateJobTest, BasicUpgradeSuccess) {
RunTestOnIOThread(&AppCacheUpdateJobTest::BasicUpgradeSuccessTest);
}
-TEST_F(AppCacheUpdateJobTest, UpgradeLoadFromNewestCache) {
+TEST_P(AppCacheUpdateJobTest, UpgradeLoadFromNewestCache) {
RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeLoadFromNewestCacheTest);
}
-TEST_F(AppCacheUpdateJobTest, UpgradeNoLoadFromNewestCache) {
+TEST_P(AppCacheUpdateJobTest, UpgradeNoLoadFromNewestCache) {
RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeNoLoadFromNewestCacheTest);
}
-TEST_F(AppCacheUpdateJobTest, UpgradeLoadFromNewestCacheVaryHeader) {
+TEST_P(AppCacheUpdateJobTest, UpgradeLoadFromNewestCacheVaryHeader) {
RunTestOnIOThread(
&AppCacheUpdateJobTest::UpgradeLoadFromNewestCacheVaryHeaderTest);
}
-TEST_F(AppCacheUpdateJobTest, UpgradeSuccessMergedTypes) {
+TEST_P(AppCacheUpdateJobTest, UpgradeLoadFromNewestCacheReuseVaryHeader) {
+ RunTestOnIOThread(
+ &AppCacheUpdateJobTest::UpgradeLoadFromNewestCacheReuseVaryHeaderTest);
+}
+
+TEST_P(AppCacheUpdateJobTest, UpgradeSuccessMergedTypes) {
RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeSuccessMergedTypesTest);
}
-TEST_F(AppCacheUpdateJobTest, CacheAttemptFailUrlFetch) {
+TEST_P(AppCacheUpdateJobTest, CacheAttemptFailUrlFetch) {
RunTestOnIOThread(&AppCacheUpdateJobTest::CacheAttemptFailUrlFetchTest);
}
-TEST_F(AppCacheUpdateJobTest, UpgradeFailUrlFetch) {
+TEST_P(AppCacheUpdateJobTest, UpgradeFailUrlFetch) {
RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeFailUrlFetchTest);
}
-TEST_F(AppCacheUpdateJobTest, UpgradeFailMasterUrlFetch) {
+TEST_P(AppCacheUpdateJobTest, UpgradeFailMasterUrlFetch) {
RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeFailMasterUrlFetchTest);
}
-TEST_F(AppCacheUpdateJobTest, EmptyManifest) {
+TEST_P(AppCacheUpdateJobTest, EmptyManifest) {
RunTestOnIOThread(&AppCacheUpdateJobTest::EmptyManifestTest);
}
-TEST_F(AppCacheUpdateJobTest, EmptyFile) {
+TEST_P(AppCacheUpdateJobTest, EmptyFile) {
RunTestOnIOThread(&AppCacheUpdateJobTest::EmptyFileTest);
}
-TEST_F(AppCacheUpdateJobTest, RetryRequest) {
+TEST_P(AppCacheUpdateJobTest, RetryRequest) {
RunTestOnIOThread(&AppCacheUpdateJobTest::RetryRequestTest);
}
-TEST_F(AppCacheUpdateJobTest, RetryNoRetryAfter) {
+TEST_P(AppCacheUpdateJobTest, RetryNoRetryAfter) {
RunTestOnIOThread(&AppCacheUpdateJobTest::RetryNoRetryAfterTest);
}
-TEST_F(AppCacheUpdateJobTest, RetryNonzeroRetryAfter) {
+TEST_P(AppCacheUpdateJobTest, RetryNonzeroRetryAfter) {
RunTestOnIOThread(&AppCacheUpdateJobTest::RetryNonzeroRetryAfterTest);
}
-TEST_F(AppCacheUpdateJobTest, RetrySuccess) {
+TEST_P(AppCacheUpdateJobTest, RetrySuccess) {
RunTestOnIOThread(&AppCacheUpdateJobTest::RetrySuccessTest);
}
-TEST_F(AppCacheUpdateJobTest, RetryUrl) {
+TEST_P(AppCacheUpdateJobTest, RetryUrl) {
RunTestOnIOThread(&AppCacheUpdateJobTest::RetryUrlTest);
}
-TEST_F(AppCacheUpdateJobTest, FailStoreNewestCache) {
+TEST_P(AppCacheUpdateJobTest, FailStoreNewestCache) {
RunTestOnIOThread(&AppCacheUpdateJobTest::FailStoreNewestCacheTest);
}
-TEST_F(AppCacheUpdateJobTest, MasterEntryFailStoreNewestCacheTest) {
+TEST_P(AppCacheUpdateJobTest, MasterEntryFailStoreNewestCacheTest) {
RunTestOnIOThread(
&AppCacheUpdateJobTest::MasterEntryFailStoreNewestCacheTest);
}
-TEST_F(AppCacheUpdateJobTest, UpgradeFailStoreNewestCache) {
+TEST_P(AppCacheUpdateJobTest, UpgradeFailStoreNewestCache) {
RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeFailStoreNewestCacheTest);
}
-TEST_F(AppCacheUpdateJobTest, UpgradeFailMakeGroupObsolete) {
+TEST_P(AppCacheUpdateJobTest, UpgradeFailMakeGroupObsolete) {
RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeFailMakeGroupObsoleteTest);
}
-TEST_F(AppCacheUpdateJobTest, MasterEntryFetchManifestFail) {
+TEST_P(AppCacheUpdateJobTest, MasterEntryFetchManifestFail) {
RunTestOnIOThread(&AppCacheUpdateJobTest::MasterEntryFetchManifestFailTest);
}
-TEST_F(AppCacheUpdateJobTest, MasterEntryBadManifest) {
+TEST_P(AppCacheUpdateJobTest, MasterEntryBadManifest) {
RunTestOnIOThread(&AppCacheUpdateJobTest::MasterEntryBadManifestTest);
}
-TEST_F(AppCacheUpdateJobTest, MasterEntryManifestNotFound) {
+TEST_P(AppCacheUpdateJobTest, MasterEntryManifestNotFound) {
RunTestOnIOThread(&AppCacheUpdateJobTest::MasterEntryManifestNotFoundTest);
}
-TEST_F(AppCacheUpdateJobTest, MasterEntryFailUrlFetch) {
+TEST_P(AppCacheUpdateJobTest, MasterEntryFailUrlFetch) {
RunTestOnIOThread(&AppCacheUpdateJobTest::MasterEntryFailUrlFetchTest);
}
-TEST_F(AppCacheUpdateJobTest, MasterEntryAllFail) {
+TEST_P(AppCacheUpdateJobTest, MasterEntryAllFail) {
RunTestOnIOThread(&AppCacheUpdateJobTest::MasterEntryAllFailTest);
}
-TEST_F(AppCacheUpdateJobTest, UpgradeMasterEntryAllFail) {
+TEST_P(AppCacheUpdateJobTest, UpgradeMasterEntryAllFail) {
RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeMasterEntryAllFailTest);
}
-TEST_F(AppCacheUpdateJobTest, MasterEntrySomeFail) {
+TEST_P(AppCacheUpdateJobTest, MasterEntrySomeFail) {
RunTestOnIOThread(&AppCacheUpdateJobTest::MasterEntrySomeFailTest);
}
-TEST_F(AppCacheUpdateJobTest, UpgradeMasterEntrySomeFail) {
+TEST_P(AppCacheUpdateJobTest, UpgradeMasterEntrySomeFail) {
RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeMasterEntrySomeFailTest);
}
-TEST_F(AppCacheUpdateJobTest, MasterEntryNoUpdate) {
+TEST_P(AppCacheUpdateJobTest, MasterEntryNoUpdate) {
RunTestOnIOThread(&AppCacheUpdateJobTest::MasterEntryNoUpdateTest);
}
-TEST_F(AppCacheUpdateJobTest, StartUpdateMidCacheAttempt) {
+TEST_P(AppCacheUpdateJobTest, StartUpdateMidCacheAttempt) {
RunTestOnIOThread(&AppCacheUpdateJobTest::StartUpdateMidCacheAttemptTest);
}
-TEST_F(AppCacheUpdateJobTest, StartUpdateMidNoUpdate) {
+TEST_P(AppCacheUpdateJobTest, StartUpdateMidNoUpdate) {
RunTestOnIOThread(&AppCacheUpdateJobTest::StartUpdateMidNoUpdateTest);
}
-TEST_F(AppCacheUpdateJobTest, StartUpdateMidDownload) {
+TEST_P(AppCacheUpdateJobTest, StartUpdateMidDownload) {
RunTestOnIOThread(&AppCacheUpdateJobTest::StartUpdateMidDownloadTest);
}
-TEST_F(AppCacheUpdateJobTest, QueueMasterEntry) {
+TEST_P(AppCacheUpdateJobTest, QueueMasterEntry) {
RunTestOnIOThread(&AppCacheUpdateJobTest::QueueMasterEntryTest);
}
-TEST_F(AppCacheUpdateJobTest, IfModifiedSince) {
- RunTestOnIOThread(&AppCacheUpdateJobTest::IfModifiedSinceTest);
+TEST_P(AppCacheUpdateJobTest, IfModifiedSinceCache) {
+ RunTestOnIOThread(&AppCacheUpdateJobTest::IfModifiedSinceTestCache);
}
-TEST_F(AppCacheUpdateJobTest, IfModifiedSinceUpgrade) {
+TEST_P(AppCacheUpdateJobTest, IfModifiedRefetch) {
+ RunTestOnIOThread(&AppCacheUpdateJobTest::IfModifiedTestRefetch);
+}
+
+TEST_P(AppCacheUpdateJobTest, IfModifiedLastModified) {
+ RunTestOnIOThread(&AppCacheUpdateJobTest::IfModifiedTestLastModified);
+}
+
+TEST_P(AppCacheUpdateJobTest, IfModifiedSinceUpgrade) {
RunTestOnIOThread(&AppCacheUpdateJobTest::IfModifiedSinceUpgradeTest);
}
-TEST_F(AppCacheUpdateJobTest, IfNoneMatchUpgrade) {
+TEST_P(AppCacheUpdateJobTest, IfNoneMatchUpgrade) {
RunTestOnIOThread(&AppCacheUpdateJobTest::IfNoneMatchUpgradeTest);
}
-TEST_F(AppCacheUpdateJobTest, IfNoneMatchRefetch) {
+TEST_P(AppCacheUpdateJobTest, IfNoneMatchRefetch) {
RunTestOnIOThread(&AppCacheUpdateJobTest::IfNoneMatchRefetchTest);
}
-TEST_F(AppCacheUpdateJobTest, MultipleHeadersRefetch) {
+TEST_P(AppCacheUpdateJobTest, MultipleHeadersRefetch) {
RunTestOnIOThread(&AppCacheUpdateJobTest::MultipleHeadersRefetchTest);
}
-TEST_F(AppCacheUpdateJobTest, CrossOriginHttpsSuccess) {
+TEST_P(AppCacheUpdateJobTest, CrossOriginHttpsSuccess) {
RunTestOnIOThread(&AppCacheUpdateJobTest::CrossOriginHttpsSuccessTest);
}
-TEST_F(AppCacheUpdateJobTest, CrossOriginHttpsDenied) {
+TEST_P(AppCacheUpdateJobTest, CrossOriginHttpsDenied) {
RunTestOnIOThread(&AppCacheUpdateJobTest::CrossOriginHttpsDeniedTest);
}
+INSTANTIATE_TEST_CASE_P(,
+ AppCacheUpdateJobTest,
+ ::testing::Values(URLREQUEST, URLLOADER));
+
} // namespace content
diff --git a/chromium/content/browser/appcache/appcache_update_request_base.cc b/chromium/content/browser/appcache/appcache_update_request_base.cc
new file mode 100644
index 00000000000..30dcd0d9011
--- /dev/null
+++ b/chromium/content/browser/appcache/appcache_update_request_base.cc
@@ -0,0 +1,71 @@
+// Copyright (c) 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/appcache/appcache_update_request_base.h"
+#include "content/browser/appcache/appcache_update_url_loader_request.h"
+#include "content/browser/appcache/appcache_update_url_request.h"
+#include "content/public/common/content_features.h"
+#include "net/url_request/url_request_context.h"
+
+namespace content {
+
+namespace {
+constexpr net::NetworkTrafficAnnotationTag kTrafficAnnotation =
+ net::DefineNetworkTrafficAnnotation("appcache_update_job", R"(
+ semantics {
+ sender: "HTML5 AppCache System"
+ description:
+ "Web pages can include a link to a manifest file which lists "
+ "resources to be cached for offline access. The AppCache system"
+ "retrieves those resources in the background."
+ trigger:
+ "User visits a web page containing a <html manifest=manifestUrl> "
+ "tag, or navigates to a document retrieved from an existing appcache "
+ "and some resource should be updated."
+ data: "None"
+ 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, appcaches are disabled for the site only. If they are totally "
+ "disabled, all appcache requests will be stopped."
+ chrome_policy {
+ DefaultCookiesSetting {
+ DefaultCookiesSetting: 2
+ }
+ }
+ })");
+}
+
+AppCacheUpdateJob::UpdateRequestBase::~UpdateRequestBase() {}
+
+// static
+std::unique_ptr<AppCacheUpdateJob::UpdateRequestBase>
+AppCacheUpdateJob::UpdateRequestBase::Create(
+ AppCacheServiceImpl* appcache_service,
+ const GURL& url,
+ int buffer_size,
+ URLFetcher* fetcher) {
+ if (!base::FeatureList::IsEnabled(features::kNetworkService)) {
+ return std::unique_ptr<UpdateRequestBase>(new UpdateURLRequest(
+ appcache_service->request_context(), url, buffer_size, fetcher));
+ } else {
+ return std::unique_ptr<UpdateRequestBase>(new UpdateURLLoaderRequest(
+ appcache_service->url_loader_factory_getter(), url, buffer_size,
+ fetcher));
+ }
+}
+
+AppCacheUpdateJob::UpdateRequestBase::UpdateRequestBase() {}
+
+net::NetworkTrafficAnnotationTag
+AppCacheUpdateJob::UpdateRequestBase::GetTrafficAnnotation() const {
+ return kTrafficAnnotation;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/appcache/appcache_update_request_base.h b/chromium/content/browser/appcache/appcache_update_request_base.h
new file mode 100644
index 00000000000..9238d0b5898
--- /dev/null
+++ b/chromium/content/browser/appcache/appcache_update_request_base.h
@@ -0,0 +1,96 @@
+// Copyright (c) 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_APPCACHE_APPCACHE_UPDATE_REQUEST_BASE_H_
+#define CONTENT_BROWSER_APPCACHE_APPCACHE_UPDATE_REQUEST_BASE_H_
+
+#include <stddef.h>
+#include <stdint.h>
+#include <memory>
+#include <string>
+
+#include "base/macros.h"
+#include "base/optional.h"
+#include "content/browser/appcache/appcache_update_job.h"
+#include "net/base/io_buffer.h"
+#include "net/http/http_request_headers.h"
+#include "net/http/http_response_headers.h"
+#include "net/http/http_response_info.h"
+#include "url/gurl.h"
+#include "url/origin.h"
+
+namespace content {
+
+class AppCacheUpdateJob::UpdateRequestBase {
+ public:
+ virtual ~UpdateRequestBase();
+
+ // Creates an instance of the AppCacheUpdateRequestBase subclass.
+ static std::unique_ptr<UpdateRequestBase> Create(
+ AppCacheServiceImpl* appcache_service,
+ const GURL& url,
+ int buffer_size,
+ URLFetcher* fetcher);
+
+ // This method is called to start the request.
+ virtual void Start() = 0;
+
+ // Sets all extra request headers. Any extra request headers set by other
+ // methods are overwritten by this method. This method may only be called
+ // before Start() is called. It is an error to call it later.
+ virtual void SetExtraRequestHeaders(
+ const net::HttpRequestHeaders& headers) = 0;
+
+ // Returns the request URL.
+ virtual GURL GetURL() const = 0;
+
+ // Sets flags which control the request load. e.g. if it can be loaded
+ // from cache, etc.
+ virtual void SetLoadFlags(int flags) = 0;
+
+ // Gets the load flags on the request.
+ virtual int GetLoadFlags() const = 0;
+
+ // Get the mime type. This method may only be called after the response was
+ // started.
+ virtual std::string GetMimeType() const = 0;
+
+ // Cookie policy.
+ virtual void SetSiteForCookies(const GURL& site_for_cookies) = 0;
+
+ // Sets the origin of the context which initiated the request.
+ virtual void SetInitiator(const base::Optional<url::Origin>& initiator) = 0;
+
+ // Get all response headers, as a HttpResponseHeaders object. See comments
+ // in HttpResponseHeaders class as to the format of the data.
+ virtual net::HttpResponseHeaders* GetResponseHeaders() const = 0;
+
+ // Returns the HTTP response code (e.g., 200, 404, and so on). This method
+ // may only be called once the delegate's OnResponseStarted method has been
+ // called. For non-HTTP requests, this method returns -1.
+ virtual int GetResponseCode() const = 0;
+
+ // Get the HTTP response info in its entirety.
+ virtual const net::HttpResponseInfo& GetResponseInfo() const = 0;
+
+ // Initiates an asynchronous read. Multiple concurrent reads are not
+ // supported.
+ virtual void Read() = 0;
+
+ // This method may be called at any time after Start() has been called to
+ // cancel the request.
+ // Returns net::ERR_ABORTED or any applicable net error.
+ virtual int Cancel() = 0;
+
+ protected:
+ UpdateRequestBase();
+
+ // Returns the traffic annotation information to be used for the outgoing
+ // request.
+ net::NetworkTrafficAnnotationTag GetTrafficAnnotation() const;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_APPCACHE_APPCACHE_UPDATE_REQUEST_BASE_H_
diff --git a/chromium/content/browser/appcache/appcache_update_url_fetcher.cc b/chromium/content/browser/appcache/appcache_update_url_fetcher.cc
new file mode 100644
index 00000000000..d91d8e63a39
--- /dev/null
+++ b/chromium/content/browser/appcache/appcache_update_url_fetcher.cc
@@ -0,0 +1,252 @@
+// Copyright (c) 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/appcache/appcache_update_url_fetcher.h"
+
+#include "base/command_line.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "components/network_session_configurator/common/network_switches.h"
+#include "content/browser/appcache/appcache_update_request_base.h"
+#include "net/base/load_flags.h"
+#include "net/http/http_request_headers.h"
+#include "net/http/http_response_headers.h"
+
+namespace content {
+
+namespace {
+
+const int kMax503Retries = 3;
+
+} // namespace
+
+// Helper class to fetch resources. Depending on the fetch type,
+// can either fetch to an in-memory string or write the response
+// data out to the disk cache.
+AppCacheUpdateJob::URLFetcher::URLFetcher(const GURL& url,
+ FetchType fetch_type,
+ AppCacheUpdateJob* job,
+ int buffer_size)
+ : url_(url),
+ job_(job),
+ fetch_type_(fetch_type),
+ retry_503_attempts_(0),
+ request_(
+ UpdateRequestBase::Create(job->service_, url, buffer_size, this)),
+ result_(AppCacheUpdateJob::UPDATE_OK),
+ redirect_response_code_(-1),
+ buffer_size_(buffer_size) {}
+
+AppCacheUpdateJob::URLFetcher::~URLFetcher() {}
+
+void AppCacheUpdateJob::URLFetcher::Start() {
+ request_->SetSiteForCookies(job_->manifest_url_);
+ request_->SetInitiator(url::Origin(job_->manifest_url_));
+ if (fetch_type_ == MANIFEST_FETCH && job_->doing_full_update_check_)
+ request_->SetLoadFlags(request_->GetLoadFlags() | net::LOAD_BYPASS_CACHE);
+ else if (existing_response_headers_.get())
+ AddConditionalHeaders(existing_response_headers_.get());
+ request_->Start();
+}
+
+void AppCacheUpdateJob::URLFetcher::OnReceivedRedirect(
+ const net::RedirectInfo& redirect_info) {
+ DCHECK(request_);
+ // Redirect is not allowed by the update process.
+ job_->MadeProgress();
+ redirect_response_code_ = request_->GetResponseCode();
+ request_->Cancel();
+ result_ = AppCacheUpdateJob::REDIRECT_ERROR;
+ OnResponseCompleted(net::ERR_ABORTED);
+}
+
+void AppCacheUpdateJob::URLFetcher::OnResponseStarted(int net_error) {
+ DCHECK(request_);
+ DCHECK_NE(net::ERR_IO_PENDING, net_error);
+
+ int response_code = -1;
+ if (net_error == net::OK) {
+ response_code = request_->GetResponseCode();
+ job_->MadeProgress();
+ }
+
+ if ((response_code / 100) != 2) {
+ if (response_code > 0)
+ result_ = AppCacheUpdateJob::SERVER_ERROR;
+ else
+ result_ = AppCacheUpdateJob::NETWORK_ERROR;
+ OnResponseCompleted(net_error);
+ return;
+ }
+
+ if (url_.SchemeIsCryptographic()) {
+ // Do not cache content with cert errors.
+ // Also, we willfully violate the HTML5 spec at this point in order
+ // to support the appcaching of cross-origin HTTPS resources.
+ // We've opted for a milder constraint and allow caching unless
+ // the resource has a "no-store" header. A spec change has been
+ // requested on the whatwg list.
+ // See http://code.google.com/p/chromium/issues/detail?id=69594
+ // TODO(michaeln): Consider doing this for cross-origin HTTP too.
+ if ((net::IsCertStatusError(
+ request_->GetResponseInfo().ssl_info.cert_status) &&
+ !base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kIgnoreCertificateErrors)) ||
+ (url_.GetOrigin() != job_->manifest_url_.GetOrigin() &&
+ request_->GetResponseHeaders()->HasHeaderValue("cache-control",
+ "no-store"))) {
+ DCHECK_EQ(-1, redirect_response_code_);
+ request_->Cancel();
+ result_ = AppCacheUpdateJob::SECURITY_ERROR;
+ OnResponseCompleted(net::ERR_ABORTED);
+ return;
+ }
+ }
+
+ // 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());
+ scoped_refptr<HttpResponseInfoIOBuffer> io_buffer(
+ new HttpResponseInfoIOBuffer(
+ new net::HttpResponseInfo(request_->GetResponseInfo())));
+ response_writer_->WriteInfo(
+ io_buffer.get(),
+ base::Bind(&URLFetcher::OnWriteComplete, base::Unretained(this)));
+ } else {
+ ReadResponseData();
+ }
+}
+
+void AppCacheUpdateJob::URLFetcher::OnReadCompleted(net::IOBuffer* buffer,
+ int bytes_read) {
+ DCHECK(request_);
+ DCHECK_NE(net::ERR_IO_PENDING, bytes_read);
+
+ if (bytes_read <= 0) {
+ OnResponseCompleted(bytes_read);
+ return;
+ }
+
+ job_->MadeProgress();
+ if (ConsumeResponseData(buffer, bytes_read))
+ request_->Read();
+}
+
+void AppCacheUpdateJob::URLFetcher::AddConditionalHeaders(
+ const net::HttpResponseHeaders* headers) {
+ DCHECK(request_);
+ DCHECK(headers);
+ net::HttpRequestHeaders extra_headers;
+
+ // Add If-Modified-Since header if response info has Last-Modified header.
+ const std::string last_modified = "Last-Modified";
+ std::string last_modified_value;
+ headers->EnumerateHeader(nullptr, last_modified, &last_modified_value);
+ if (!last_modified_value.empty()) {
+ extra_headers.SetHeader(net::HttpRequestHeaders::kIfModifiedSince,
+ last_modified_value);
+ }
+
+ // Add If-None-Match header if response info has ETag header.
+ const std::string etag = "ETag";
+ std::string etag_value;
+ headers->EnumerateHeader(nullptr, etag, &etag_value);
+ if (!etag_value.empty()) {
+ extra_headers.SetHeader(net::HttpRequestHeaders::kIfNoneMatch, etag_value);
+ }
+ if (!extra_headers.IsEmpty())
+ request_->SetExtraRequestHeaders(extra_headers);
+}
+
+void AppCacheUpdateJob::URLFetcher::OnWriteComplete(int result) {
+ if (result < 0) {
+ request_->Cancel();
+ result_ = AppCacheUpdateJob::DISKCACHE_ERROR;
+ OnResponseCompleted(net::ERR_ABORTED);
+ return;
+ }
+ ReadResponseData();
+}
+
+void AppCacheUpdateJob::URLFetcher::ReadResponseData() {
+ AppCacheUpdateJob::InternalUpdateState state = job_->internal_state_;
+ if (state == AppCacheUpdateJob::CACHE_FAILURE ||
+ state == AppCacheUpdateJob::CANCELLED ||
+ state == AppCacheUpdateJob::COMPLETED) {
+ return;
+ }
+ request_->Read();
+}
+
+// Returns false if response data is processed asynchronously, in which
+// case ReadResponseData will be invoked when it is safe to continue
+// reading more response data from the request.
+bool AppCacheUpdateJob::URLFetcher::ConsumeResponseData(net::IOBuffer* buffer,
+ int bytes_read) {
+ DCHECK_GT(bytes_read, 0);
+ switch (fetch_type_) {
+ case MANIFEST_FETCH:
+ case MANIFEST_REFETCH:
+ manifest_data_.append(buffer->data(), bytes_read);
+ break;
+ case URL_FETCH:
+ case MASTER_ENTRY_FETCH:
+ DCHECK(response_writer_.get());
+ response_writer_->WriteData(
+ buffer, bytes_read,
+ base::Bind(&URLFetcher::OnWriteComplete, base::Unretained(this)));
+ return false; // wait for async write completion to continue reading
+ default:
+ NOTREACHED();
+ }
+ return true;
+}
+
+void AppCacheUpdateJob::URLFetcher::OnResponseCompleted(int net_error) {
+ if (net_error == net::OK) {
+ job_->MadeProgress();
+ } else if (result_ == AppCacheUpdateJob::UPDATE_OK) {
+ result_ = AppCacheUpdateJob::NETWORK_ERROR;
+ }
+
+ // Retry for 503s where retry-after is 0.
+ if (net_error == net::OK && request_->GetResponseCode() == 503 &&
+ MaybeRetryRequest()) {
+ return;
+ }
+
+ switch (fetch_type_) {
+ case MANIFEST_FETCH:
+ job_->HandleManifestFetchCompleted(this, net_error);
+ break;
+ case URL_FETCH:
+ job_->HandleUrlFetchCompleted(this, net_error);
+ break;
+ case MASTER_ENTRY_FETCH:
+ job_->HandleMasterEntryFetchCompleted(this, net_error);
+ break;
+ case MANIFEST_REFETCH:
+ job_->HandleManifestRefetchCompleted(this, net_error);
+ break;
+ default:
+ NOTREACHED();
+ }
+
+ delete this;
+}
+
+bool AppCacheUpdateJob::URLFetcher::MaybeRetryRequest() {
+ if (retry_503_attempts_ >= kMax503Retries ||
+ !request_->GetResponseHeaders()->HasHeaderValue("retry-after", "0")) {
+ return false;
+ }
+ ++retry_503_attempts_;
+ result_ = AppCacheUpdateJob::UPDATE_OK;
+ request_ =
+ UpdateRequestBase::Create(job_->service_, url_, buffer_size_, this);
+ Start();
+ return true;
+}
+
+} // namespace content. \ No newline at end of file
diff --git a/chromium/content/browser/appcache/appcache_update_url_fetcher.h b/chromium/content/browser/appcache/appcache_update_url_fetcher.h
new file mode 100644
index 00000000000..a3d3d939e94
--- /dev/null
+++ b/chromium/content/browser/appcache/appcache_update_url_fetcher.h
@@ -0,0 +1,82 @@
+// Copyright (c) 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_APPCACHE_APPCACHE_UPDATE_URL_FETCHER_H_
+#define CONTENT_BROWSER_APPCACHE_APPCACHE_UPDATE_URL_FETCHER_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "content/browser/appcache/appcache_response.h"
+#include "content/browser/appcache/appcache_update_job.h"
+#include "net/base/io_buffer.h"
+#include "url/gurl.h"
+
+namespace content {
+
+// Helper class to fetch resources. Depending on the fetch type,
+// can either fetch to an in-memory string or write the response
+// data out to the disk cache.
+class AppCacheUpdateJob::URLFetcher {
+ public:
+ enum FetchType {
+ MANIFEST_FETCH,
+ URL_FETCH,
+ MASTER_ENTRY_FETCH,
+ MANIFEST_REFETCH,
+ };
+ URLFetcher(const GURL& url,
+ FetchType fetch_type,
+ AppCacheUpdateJob* job,
+ int buffer_size);
+ ~URLFetcher();
+ void Start();
+ FetchType fetch_type() const { return fetch_type_; }
+ UpdateRequestBase* request() const { return request_.get(); }
+ const AppCacheEntry& existing_entry() const { return existing_entry_; }
+ const std::string& manifest_data() const { return manifest_data_; }
+ AppCacheResponseWriter* response_writer() const {
+ return response_writer_.get();
+ }
+ void set_existing_response_headers(net::HttpResponseHeaders* headers) {
+ existing_response_headers_ = headers;
+ }
+ void set_existing_entry(const AppCacheEntry& entry) {
+ existing_entry_ = entry;
+ }
+ AppCacheUpdateJob::ResultType result() const { return result_; }
+ int redirect_response_code() const { return redirect_response_code_; }
+
+ private:
+ void OnReceivedRedirect(const net::RedirectInfo& redirect_info);
+ void OnResponseStarted(int net_error);
+ void OnReadCompleted(net::IOBuffer* buffer, int bytes_read);
+
+ void AddConditionalHeaders(const net::HttpResponseHeaders* headers);
+ void OnWriteComplete(int result);
+ void ReadResponseData();
+ bool ConsumeResponseData(net::IOBuffer* buffer, int bytes_read);
+ void OnResponseCompleted(int net_error);
+ bool MaybeRetryRequest();
+
+ friend class UpdateURLRequest;
+ friend class UpdateURLLoaderRequest;
+
+ GURL url_;
+ AppCacheUpdateJob* job_;
+ FetchType fetch_type_;
+ int retry_503_attempts_;
+ std::unique_ptr<UpdateRequestBase> request_;
+ AppCacheEntry existing_entry_;
+ scoped_refptr<net::HttpResponseHeaders> existing_response_headers_;
+ std::string manifest_data_;
+ AppCacheUpdateJob::ResultType result_;
+ int redirect_response_code_;
+ std::unique_ptr<AppCacheResponseWriter> response_writer_;
+ int buffer_size_;
+}; // class URLFetcher
+
+} // namespace content.
+
+#endif // CONTENT_BROWSER_APPCACHE_APPCACHE_UPDATE_URL_FETCHER_H_ \ No newline at end of file
diff --git a/chromium/content/browser/appcache/appcache_update_url_loader_request.cc b/chromium/content/browser/appcache/appcache_update_url_loader_request.cc
new file mode 100644
index 00000000000..c6171c38a1f
--- /dev/null
+++ b/chromium/content/browser/appcache/appcache_update_url_loader_request.cc
@@ -0,0 +1,237 @@
+// Copyright (c) 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/appcache/appcache_update_url_loader_request.h"
+
+#include "content/browser/appcache/appcache_request_handler.h"
+#include "content/browser/appcache/appcache_update_url_fetcher.h"
+#include "net/http/http_response_info.h"
+#include "net/url_request/url_request_context.h"
+
+namespace content {
+
+AppCacheUpdateJob::UpdateURLLoaderRequest::~UpdateURLLoaderRequest() {}
+
+void AppCacheUpdateJob::UpdateURLLoaderRequest::Start() {
+ // If we are in tests mode, we don't need to issue network requests.
+ if (AppCacheRequestHandler::IsRunningInTests())
+ return;
+
+ mojom::URLLoaderClientPtr client;
+ client_binding_.Bind(mojo::MakeRequest(&client));
+
+ DCHECK(loader_factory_getter_->GetNetworkFactory()->get());
+ loader_factory_getter_->GetNetworkFactory()->get()->CreateLoaderAndStart(
+ mojo::MakeRequest(&url_loader_), -1, -1, mojom::kURLLoadOptionNone,
+ request_, std::move(client),
+ net::MutableNetworkTrafficAnnotationTag(GetTrafficAnnotation()));
+}
+
+void AppCacheUpdateJob::UpdateURLLoaderRequest::SetExtraRequestHeaders(
+ const net::HttpRequestHeaders& headers) {
+ request_.headers = headers.ToString();
+}
+
+GURL AppCacheUpdateJob::UpdateURLLoaderRequest::GetURL() const {
+ return request_.url;
+}
+
+void AppCacheUpdateJob::UpdateURLLoaderRequest::SetLoadFlags(int flags) {
+ request_.load_flags = flags;
+}
+
+int AppCacheUpdateJob::UpdateURLLoaderRequest::GetLoadFlags() const {
+ return request_.load_flags;
+}
+
+std::string AppCacheUpdateJob::UpdateURLLoaderRequest::GetMimeType() const {
+ return response_.mime_type;
+}
+
+void AppCacheUpdateJob::UpdateURLLoaderRequest::SetSiteForCookies(
+ const GURL& site_for_cookies) {
+ request_.site_for_cookies = site_for_cookies;
+}
+
+void AppCacheUpdateJob::UpdateURLLoaderRequest::SetInitiator(
+ const base::Optional<url::Origin>& initiator) {
+ request_.request_initiator = initiator;
+}
+
+net::HttpResponseHeaders*
+AppCacheUpdateJob::UpdateURLLoaderRequest::GetResponseHeaders() const {
+ return response_.headers.get();
+}
+
+int AppCacheUpdateJob::UpdateURLLoaderRequest::GetResponseCode() const {
+ if (response_.headers)
+ return response_.headers->response_code();
+ return 0;
+}
+
+const net::HttpResponseInfo&
+AppCacheUpdateJob::UpdateURLLoaderRequest::GetResponseInfo() const {
+ return *http_response_info_;
+}
+
+void AppCacheUpdateJob::UpdateURLLoaderRequest::Read() {
+ DCHECK(!read_requested_);
+
+ read_requested_ = true;
+ // Initiate a read from the pipe if we have not done so.
+ MaybeStartReading();
+}
+
+int AppCacheUpdateJob::UpdateURLLoaderRequest::Cancel() {
+ client_binding_.Close();
+ url_loader_ = nullptr;
+ handle_watcher_.Cancel();
+ handle_.reset();
+ response_ = ResourceResponseHead();
+ http_response_info_.reset(nullptr);
+ read_requested_ = false;
+ return 0;
+}
+
+void AppCacheUpdateJob::UpdateURLLoaderRequest::OnReceiveResponse(
+ const ResourceResponseHead& response_head,
+ const base::Optional<net::SSLInfo>& ssl_info,
+ mojom::DownloadedTempFilePtr downloaded_file) {
+ response_ = response_head;
+
+ // TODO(ananta/michaeln)
+ // Populate other fields in the HttpResponseInfo class. It would be good to
+ // have a helper function which populates the HttpResponseInfo structure from
+ // the ResourceResponseHead structure.
+ http_response_info_.reset(new net::HttpResponseInfo());
+ if (ssl_info.has_value())
+ http_response_info_->ssl_info = *ssl_info;
+ http_response_info_->headers = response_head.headers;
+ http_response_info_->was_fetched_via_spdy =
+ response_head.was_fetched_via_spdy;
+ http_response_info_->was_alpn_negotiated = response_head.was_alpn_negotiated;
+ http_response_info_->alpn_negotiated_protocol =
+ response_head.alpn_negotiated_protocol;
+ http_response_info_->connection_info = response_head.connection_info;
+ http_response_info_->socket_address = response_head.socket_address;
+ fetcher_->OnResponseStarted(net::OK);
+}
+
+void AppCacheUpdateJob::UpdateURLLoaderRequest::OnReceiveRedirect(
+ const net::RedirectInfo& redirect_info,
+ const ResourceResponseHead& response_head) {
+ response_ = response_head;
+ fetcher_->OnReceivedRedirect(redirect_info);
+}
+
+void AppCacheUpdateJob::UpdateURLLoaderRequest::OnDataDownloaded(
+ int64_t data_len,
+ int64_t encoded_data_len) {
+ NOTIMPLEMENTED();
+}
+
+void AppCacheUpdateJob::UpdateURLLoaderRequest::OnUploadProgress(
+ int64_t current_position,
+ int64_t total_size,
+ OnUploadProgressCallback ack_callback) {
+ NOTIMPLEMENTED();
+}
+
+void AppCacheUpdateJob::UpdateURLLoaderRequest::OnReceiveCachedMetadata(
+ const std::vector<uint8_t>& data) {
+}
+
+void AppCacheUpdateJob::UpdateURLLoaderRequest::OnTransferSizeUpdated(
+ int32_t transfer_size_diff) {
+ NOTIMPLEMENTED();
+}
+
+void AppCacheUpdateJob::UpdateURLLoaderRequest::OnStartLoadingResponseBody(
+ mojo::ScopedDataPipeConsumerHandle body) {
+ handle_ = std::move(body);
+
+ handle_watcher_.Watch(
+ handle_.get(), MOJO_HANDLE_SIGNAL_READABLE,
+ base::Bind(&AppCacheUpdateJob::UpdateURLLoaderRequest::StartReading,
+ base::Unretained(this)));
+
+ // Initiate a read from the pipe if we have a pending Read() request.
+ MaybeStartReading();
+}
+
+void AppCacheUpdateJob::UpdateURLLoaderRequest::OnComplete(
+ const ResourceRequestCompletionStatus& status) {
+ response_status_ = status;
+ // We inform the URLFetcher about a failure only here. For the success case
+ // OnResponseCompleted() is invoked by URLFetcher::OnReadCompleted().
+ if (status.error_code != net::OK)
+ fetcher_->OnResponseCompleted(status.error_code);
+}
+
+AppCacheUpdateJob::UpdateURLLoaderRequest::UpdateURLLoaderRequest(
+ URLLoaderFactoryGetter* loader_factory_getter,
+ const GURL& url,
+ int buffer_size,
+ URLFetcher* fetcher)
+ : fetcher_(fetcher),
+ loader_factory_getter_(loader_factory_getter),
+ client_binding_(this),
+ buffer_size_(buffer_size),
+ handle_watcher_(FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::MANUAL),
+ read_requested_(false) {
+ request_.url = url;
+ request_.method = "GET";
+}
+
+void AppCacheUpdateJob::UpdateURLLoaderRequest::StartReading(
+ MojoResult unused) {
+ DCHECK(read_requested_);
+
+ // Get the handle_ from a previous read operation if we have one.
+ if (pending_read_) {
+ DCHECK(pending_read_->IsComplete());
+ handle_ = pending_read_->ReleaseHandle();
+ pending_read_ = nullptr;
+ }
+
+ uint32_t available = 0;
+ MojoResult result = network::MojoToNetPendingBuffer::BeginRead(
+ &handle_, &pending_read_, &available);
+ DCHECK_NE(result, MOJO_RESULT_BUSY);
+
+ if (result == MOJO_RESULT_SHOULD_WAIT) {
+ handle_watcher_.ArmOrNotify();
+ return;
+ }
+
+ read_requested_ = false;
+
+ if (result == MOJO_RESULT_FAILED_PRECONDITION) {
+ DCHECK_EQ(response_status_.error_code, net::OK);
+ fetcher_->OnReadCompleted(nullptr, 0);
+ return;
+ }
+
+ if (result != MOJO_RESULT_OK) {
+ fetcher_->OnResponseCompleted(net::ERR_FAILED);
+ return;
+ }
+
+ int bytes_to_be_read = std::min<int>(buffer_size_, available);
+
+ auto buffer = base::MakeRefCounted<network::MojoToNetIOBuffer>(
+ pending_read_.get(), bytes_to_be_read);
+
+ fetcher_->OnReadCompleted(buffer.get(), bytes_to_be_read);
+}
+
+void AppCacheUpdateJob::UpdateURLLoaderRequest::MaybeStartReading() {
+ if (!read_requested_)
+ return;
+
+ if (handle_watcher_.IsWatching())
+ handle_watcher_.ArmOrNotify();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/appcache/appcache_update_url_loader_request.h b/chromium/content/browser/appcache/appcache_update_url_loader_request.h
new file mode 100644
index 00000000000..ebe478c7a30
--- /dev/null
+++ b/chromium/content/browser/appcache/appcache_update_url_loader_request.h
@@ -0,0 +1,124 @@
+// Copyright (c) 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_APPCACHE_APPCACHE_UPDATE_URL_LOADER_REQUEST_H_
+#define CONTENT_BROWSER_APPCACHE_APPCACHE_UPDATE_URL_LOADER_REQUEST_H_
+
+#include <stddef.h>
+#include <stdint.h>
+#include <memory>
+
+#include "base/macros.h"
+#include "content/browser/appcache/appcache_update_request_base.h"
+#include "content/public/common/resource_request.h"
+#include "content/public/common/resource_response.h"
+#include "content/public/common/url_loader.mojom.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/system/simple_watcher.h"
+#include "net/base/io_buffer.h"
+#include "services/network/public/cpp/net_adapters.h"
+
+namespace net {
+class HttpResponseInfo;
+}
+
+namespace content {
+
+class URLLoaderFactoryGetter;
+struct ResourceRequest;
+
+// URLLoaderClient subclass for the UpdateRequestBase class. Provides
+// functionality to update the AppCache using functionality provided by the
+// network URL loader.
+class AppCacheUpdateJob::UpdateURLLoaderRequest
+ : public AppCacheUpdateJob::UpdateRequestBase,
+ public mojom::URLLoaderClient {
+ public:
+ ~UpdateURLLoaderRequest() override;
+
+ // UpdateRequestBase overrides.
+ void Start() override;
+ void SetExtraRequestHeaders(const net::HttpRequestHeaders& headers) override;
+ GURL GetURL() const override;
+ void SetLoadFlags(int flags) override;
+ int GetLoadFlags() const override;
+ std::string GetMimeType() const override;
+ void SetSiteForCookies(const GURL& site_for_cookies) override;
+ void SetInitiator(const base::Optional<url::Origin>& initiator) override;
+ net::HttpResponseHeaders* GetResponseHeaders() const override;
+ int GetResponseCode() const override;
+ const net::HttpResponseInfo& GetResponseInfo() const override;
+ void Read() override;
+ int Cancel() override;
+
+ // mojom::URLLoaderClient implementation.
+ // These methods are called by the network loader.
+ void OnReceiveResponse(const ResourceResponseHead& response_head,
+ const base::Optional<net::SSLInfo>& ssl_info,
+ mojom::DownloadedTempFilePtr downloaded_file) override;
+ void OnReceiveRedirect(const net::RedirectInfo& redirect_info,
+ const ResourceResponseHead& response_head) override;
+ void OnDataDownloaded(int64_t data_len, int64_t encoded_data_len) 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 body) override;
+ void OnComplete(const ResourceRequestCompletionStatus& status) override;
+
+ private:
+ UpdateURLLoaderRequest(URLLoaderFactoryGetter* loader_factory_getter,
+ const GURL& url,
+ int buffer_size,
+ URLFetcher* fetcher);
+
+ // Helper function to initiate an asynchronous read on the data pipe.
+ void StartReading(MojoResult unused);
+
+ // Helper function to setup the data pipe watcher to start reading from
+ // the pipe. We need to do this when the data pipe is available and there is
+ // a pending read.
+ void MaybeStartReading();
+
+ friend class AppCacheUpdateJob::UpdateRequestBase;
+
+ URLFetcher* fetcher_;
+ // Used to retrieve the network URLLoader interface to issue network
+ // requests
+ scoped_refptr<URLLoaderFactoryGetter> loader_factory_getter_;
+
+ ResourceRequest request_;
+ ResourceResponseHead response_;
+ ResourceRequestCompletionStatus response_status_;
+ // Response details.
+ std::unique_ptr<net::HttpResponseInfo> http_response_info_;
+ // Binds the URLLoaderClient interface to the channel.
+ mojo::Binding<mojom::URLLoaderClient> client_binding_;
+ // The network URL loader.
+ mojom::URLLoaderPtr url_loader_;
+ // Caller buffer size.
+ int buffer_size_;
+ // The mojo data pipe.
+ mojo::ScopedDataPipeConsumerHandle handle_;
+ // Used to watch the data pipe to initiate reads.
+ mojo::SimpleWatcher handle_watcher_;
+ // Set to true when the caller issues a read request. We set it to false in
+ // the StartReading() function when the mojo BeginReadData API returns a
+ // value indicating one of the following:
+ // 1. Data is available.
+ // 2. End of data has been reached.
+ // 3. Error.
+ // Please look at the StartReading() function for details.
+ bool read_requested_;
+ // Adapter for transferring data from a mojo data pipe to net.
+ scoped_refptr<network::MojoToNetPendingBuffer> pending_read_;
+
+ DISALLOW_COPY_AND_ASSIGN(UpdateURLLoaderRequest);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_APPCACHE_APPCACHE_UPDATE_URL_LOADER_REQUEST_H_
diff --git a/chromium/content/browser/appcache/appcache_update_url_request.cc b/chromium/content/browser/appcache/appcache_update_url_request.cc
new file mode 100644
index 00000000000..d2c28d702af
--- /dev/null
+++ b/chromium/content/browser/appcache/appcache_update_url_request.cc
@@ -0,0 +1,126 @@
+// Copyright (c) 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/appcache/appcache_update_url_request.h"
+
+#include "base/threading/thread_task_runner_handle.h"
+#include "content/browser/appcache/appcache_update_url_fetcher.h"
+#include "net/url_request/url_request_context.h"
+
+namespace content {
+
+AppCacheUpdateJob::UpdateURLRequest::~UpdateURLRequest() {
+ // To defend against URLRequest calling delegate methods during
+ // destruction, we test for a !request_ in those methods.
+ std::unique_ptr<net::URLRequest> temp = std::move(request_);
+}
+
+void AppCacheUpdateJob::UpdateURLRequest::Start() {
+ request_->Start();
+}
+
+void AppCacheUpdateJob::UpdateURLRequest::SetExtraRequestHeaders(
+ const net::HttpRequestHeaders& headers) {
+ request_->SetExtraRequestHeaders(headers);
+}
+
+GURL AppCacheUpdateJob::UpdateURLRequest::GetURL() const {
+ return request_->url();
+}
+
+void AppCacheUpdateJob::UpdateURLRequest::SetLoadFlags(int flags) {
+ request_->SetLoadFlags(flags);
+}
+
+int AppCacheUpdateJob::UpdateURLRequest::GetLoadFlags() const {
+ return request_->load_flags();
+}
+
+std::string AppCacheUpdateJob::UpdateURLRequest::GetMimeType() const {
+ std::string mime_type;
+ request_->GetMimeType(&mime_type);
+ return mime_type;
+}
+
+void AppCacheUpdateJob::UpdateURLRequest::SetSiteForCookies(
+ const GURL& site_for_cookies) {
+ request_->set_site_for_cookies(site_for_cookies);
+}
+
+void AppCacheUpdateJob::UpdateURLRequest::SetInitiator(
+ const base::Optional<url::Origin>& initiator) {
+ request_->set_initiator(initiator);
+}
+
+net::HttpResponseHeaders*
+AppCacheUpdateJob::UpdateURLRequest::GetResponseHeaders() const {
+ return request_->response_headers();
+}
+
+int AppCacheUpdateJob::UpdateURLRequest::GetResponseCode() const {
+ return request_->GetResponseCode();
+}
+
+const net::HttpResponseInfo&
+AppCacheUpdateJob::UpdateURLRequest::GetResponseInfo() const {
+ return request_->response_info();
+}
+
+void AppCacheUpdateJob::UpdateURLRequest::Read() {
+ int bytes_read = request_->Read(buffer_.get(), buffer_size_);
+ if (bytes_read != net::ERR_IO_PENDING) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&AppCacheUpdateJob::UpdateURLRequest::OnReadCompleted,
+ weak_factory_.GetWeakPtr(), request_.get(), bytes_read));
+ }
+}
+
+int AppCacheUpdateJob::UpdateURLRequest::Cancel() {
+ return request_->Cancel();
+}
+
+void AppCacheUpdateJob::UpdateURLRequest::OnReceivedRedirect(
+ net::URLRequest* request,
+ const net::RedirectInfo& redirect_info,
+ bool* defer_redirect) {
+ if (!request_)
+ return;
+ DCHECK_EQ(request_.get(), request);
+ fetcher_->OnReceivedRedirect(redirect_info);
+}
+
+void AppCacheUpdateJob::UpdateURLRequest::OnResponseStarted(
+ net::URLRequest* request,
+ int net_error) {
+ if (!request_)
+ return;
+ DCHECK_EQ(request_.get(), request);
+ fetcher_->OnResponseStarted(net_error);
+}
+
+void AppCacheUpdateJob::UpdateURLRequest::OnReadCompleted(
+ net::URLRequest* request,
+ int bytes_read) {
+ if (!request_)
+ return;
+ DCHECK_EQ(request_.get(), request);
+ fetcher_->OnReadCompleted(buffer_.get(), bytes_read);
+}
+
+AppCacheUpdateJob::UpdateURLRequest::UpdateURLRequest(
+ net::URLRequestContext* request_context,
+ const GURL& url,
+ int buffer_size,
+ URLFetcher* fetcher)
+ : request_(request_context->CreateRequest(url,
+ net::DEFAULT_PRIORITY,
+ this,
+ GetTrafficAnnotation())),
+ fetcher_(fetcher),
+ buffer_(new net::IOBuffer(buffer_size)),
+ buffer_size_(buffer_size),
+ weak_factory_(this) {}
+
+} // namespace content
diff --git a/chromium/content/browser/appcache/appcache_update_url_request.h b/chromium/content/browser/appcache/appcache_update_url_request.h
new file mode 100644
index 00000000000..c2c55a0053b
--- /dev/null
+++ b/chromium/content/browser/appcache/appcache_update_url_request.h
@@ -0,0 +1,69 @@
+// Copyright (c) 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_APPCACHE_APPCACHE_UPDATE_URL_REQUEST_H_
+#define CONTENT_BROWSER_APPCACHE_APPCACHE_UPDATE_URL_REQUEST_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "content/browser/appcache/appcache_update_request_base.h"
+#include "net/base/io_buffer.h"
+#include "net/url_request/url_request.h"
+
+namespace content {
+
+// URLRequest subclass for the UpdateRequestBase class. Provides functionality
+// to update the AppCache using functionality provided by the URLRequest class.
+class AppCacheUpdateJob::UpdateURLRequest
+ : public AppCacheUpdateJob::UpdateRequestBase,
+ public net::URLRequest::Delegate {
+ public:
+ ~UpdateURLRequest() override;
+
+ // UpdateRequestBase overrides.
+ void Start() override;
+ void SetExtraRequestHeaders(const net::HttpRequestHeaders& headers) override;
+ GURL GetURL() const override;
+ void SetLoadFlags(int flags) override;
+ int GetLoadFlags() const override;
+ std::string GetMimeType() const override;
+ void SetSiteForCookies(const GURL& site_for_cookies) override;
+ void SetInitiator(const base::Optional<url::Origin>& initiator) override;
+ net::HttpResponseHeaders* GetResponseHeaders() const override;
+ int GetResponseCode() const override;
+ const net::HttpResponseInfo& GetResponseInfo() const override;
+ void Read() override;
+ int Cancel() override;
+
+ // URLRequest::Delegate overrides
+ void OnReceivedRedirect(net::URLRequest* request,
+ const net::RedirectInfo& redirect_info,
+ bool* defer_redirect) override;
+ void OnResponseStarted(net::URLRequest* request, int net_error) override;
+ void OnReadCompleted(net::URLRequest* request, int bytes_read) override;
+
+ private:
+ UpdateURLRequest(net::URLRequestContext* request_context,
+ const GURL& url,
+ int buffer_size,
+ URLFetcher* fetcher);
+
+ friend class AppCacheUpdateJob::UpdateRequestBase;
+
+ std::unique_ptr<net::URLRequest> request_;
+ URLFetcher* fetcher_;
+ scoped_refptr<net::IOBuffer> buffer_;
+ int buffer_size_;
+
+ base::WeakPtrFactory<AppCacheUpdateJob::UpdateURLRequest> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(UpdateURLRequest);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_APPCACHE_APPCACHE_UPDATE_URL_REQUEST_H_
diff --git a/chromium/content/browser/appcache/appcache_url_loader_job.cc b/chromium/content/browser/appcache/appcache_url_loader_job.cc
index 8ddd92a49de..74591da9b39 100644
--- a/chromium/content/browser/appcache/appcache_url_loader_job.cc
+++ b/chromium/content/browser/appcache/appcache_url_loader_job.cc
@@ -6,12 +6,13 @@
#include "base/strings/string_number_conversions.h"
#include "content/browser/appcache/appcache_histograms.h"
+#include "content/browser/appcache/appcache_request_handler.h"
#include "content/browser/appcache/appcache_subresource_url_factory.h"
#include "content/browser/appcache/appcache_url_loader_request.h"
#include "content/browser/url_loader_factory_getter.h"
-#include "content/common/net_adapters.h"
#include "content/public/common/resource_type.h"
#include "net/http/http_status_code.h"
+#include "services/network/public/cpp/net_adapters.h"
namespace content {
@@ -42,6 +43,10 @@ void AppCacheURLLoaderJob::DeliverAppCachedResponse(const GURL& manifest_url,
delivery_type_ = APPCACHED_DELIVERY;
+ // In tests we only care about the delivery_type_ state.
+ if (AppCacheRequestHandler::IsRunningInTests())
+ return;
+
load_timing_info_.request_start_time = base::Time::Now();
load_timing_info_.request_start = base::TimeTicks::Now();
@@ -67,6 +72,10 @@ void AppCacheURLLoaderJob::DeliverAppCachedResponse(const GURL& manifest_url,
void AppCacheURLLoaderJob::DeliverNetworkResponse() {
delivery_type_ = NETWORK_DELIVERY;
+ // In tests we only care about the delivery_type_ state.
+ if (AppCacheRequestHandler::IsRunningInTests())
+ return;
+
AppCacheHistograms::AddNetworkJobStartDelaySample(base::TimeTicks::Now() -
start_time_tick_);
@@ -94,8 +103,9 @@ void AppCacheURLLoaderJob::DeliverNetworkResponse() {
void AppCacheURLLoaderJob::DeliverErrorResponse() {
delivery_type_ = ERROR_DELIVERY;
- // We expect the URLLoaderClient pointer to be valid at this point.
- DCHECK(client_);
+ // In tests we only care about the delivery_type_ state.
+ if (AppCacheRequestHandler::IsRunningInTests())
+ return;
// AppCacheURLRequestJob uses ERR_FAILED as the error code here. That seems
// to map to HTTP_INTERNAL_SERVER_ERROR.
@@ -143,6 +153,9 @@ void AppCacheURLLoaderJob::OnReceiveResponse(
// response to us. Reset the delivery_type_ to ensure that we can
// receive it
delivery_type_ = AWAITING_DELIVERY_ORDERS;
+
+ received_response_ = true;
+
if (!sub_resource_handler_->MaybeLoadFallbackForResponse(nullptr)) {
client_->OnReceiveResponse(response_head, ssl_info,
std::move(downloaded_file));
@@ -201,39 +214,31 @@ void AppCacheURLLoaderJob::OnStartLoadingResponseBody(
void AppCacheURLLoaderJob::OnComplete(
const ResourceRequestCompletionStatus& status) {
delivery_type_ = AWAITING_DELIVERY_ORDERS;
- if (!sub_resource_handler_->MaybeLoadFallbackForResponse(nullptr)) {
- client_->OnComplete(status);
- } else {
- // Disconnect from the network loader as we are delivering a fallback
- // response to the client.
- DisconnectFromNetworkLoader();
+ if (status.error_code != net::OK && !received_response_) {
+ if (sub_resource_handler_->MaybeLoadFallbackForResponse(nullptr)) {
+ // Disconnect from the network loader as we are delivering a fallback
+ // response to the client.
+ DisconnectFromNetworkLoader();
+ return;
+ }
}
+ client_->OnComplete(status);
}
-void AppCacheURLLoaderJob::SetSubresourceLoadInfo(
- std::unique_ptr<SubresourceLoadInfo> subresource_load_info,
- URLLoaderFactoryGetter* default_url_loader) {
- subresource_load_info_ = std::move(subresource_load_info);
+void AppCacheURLLoaderJob::BindRequest(mojom::URLLoaderClientPtr client,
+ mojom::URLLoaderRequest request) {
+ DCHECK(!binding_.is_bound());
+ binding_.Bind(std::move(request));
- associated_binding_.reset(new mojo::AssociatedBinding<mojom::URLLoader>(
- this, std::move(subresource_load_info_->url_loader_request)));
- associated_binding_->set_connection_error_handler(base::Bind(
- &AppCacheURLLoaderJob::OnConnectionError, StaticAsWeakPtr(this)));
+ client_ = std::move(client);
- client_ = std::move(subresource_load_info_->client);
- default_url_loader_factory_getter_ = default_url_loader;
+ binding_.set_connection_error_handler(base::BindOnce(
+ &AppCacheURLLoaderJob::OnConnectionError, StaticAsWeakPtr(this)));
}
void AppCacheURLLoaderJob::Start(mojom::URLLoaderRequest request,
mojom::URLLoaderClientPtr client) {
- DCHECK(!binding_.is_bound());
- binding_.Bind(std::move(request));
-
- binding_.set_connection_error_handler(base::Bind(
- &AppCacheURLLoaderJob::OnConnectionError, StaticAsWeakPtr(this)));
-
- client_ = std::move(client);
-
+ BindRequest(std::move(client), std::move(request));
// Send the cached AppCacheResponse if any.
if (info_.get())
SendResponseInfo();
@@ -242,7 +247,9 @@ void AppCacheURLLoaderJob::Start(mojom::URLLoaderRequest request,
AppCacheURLLoaderJob::AppCacheURLLoaderJob(
const ResourceRequest& request,
AppCacheURLLoaderRequest* appcache_request,
- AppCacheStorage* storage)
+ AppCacheStorage* storage,
+ std::unique_ptr<SubresourceLoadInfo> subresource_load_info,
+ URLLoaderFactoryGetter* loader_factory_getter)
: request_(request),
storage_(storage->GetWeakPtr()),
start_time_tick_(base::TimeTicks::Now()),
@@ -252,7 +259,20 @@ AppCacheURLLoaderJob::AppCacheURLLoaderJob(
writable_handle_watcher_(FROM_HERE,
mojo::SimpleWatcher::ArmingPolicy::MANUAL),
network_loader_client_binding_(this),
- appcache_request_(appcache_request) {}
+ appcache_request_(appcache_request),
+ received_response_(false) {
+ if (subresource_load_info.get()) {
+ DCHECK(loader_factory_getter);
+ subresource_load_info_ = std::move(subresource_load_info);
+
+ binding_.Bind(std::move(subresource_load_info_->url_loader_request));
+ binding_.set_connection_error_handler(base::BindOnce(
+ &AppCacheURLLoaderJob::OnConnectionError, StaticAsWeakPtr(this)));
+
+ client_ = std::move(subresource_load_info_->client);
+ default_url_loader_factory_getter_ = loader_factory_getter;
+ }
+}
void AppCacheURLLoaderJob::OnResponseInfoLoaded(
AppCacheResponseInfo* response_info,
@@ -272,10 +292,11 @@ void AppCacheURLLoaderJob::OnResponseInfoLoaded(
if (is_range_request())
SetupRangeResponse();
- if (IsResourceTypeFrame(request_.resource_type)) {
- DCHECK(!main_resource_loader_callback_.is_null());
+ if (IsResourceTypeFrame(request_.resource_type) &&
+ main_resource_loader_callback_) {
std::move(main_resource_loader_callback_)
- .Run(base::Bind(&AppCacheURLLoaderJob::Start, StaticAsWeakPtr(this)));
+ .Run(base::BindOnce(&AppCacheURLLoaderJob::Start,
+ StaticAsWeakPtr(this)));
}
response_body_stream_ = std::move(data_pipe_.producer_handle);
@@ -390,7 +411,7 @@ void AppCacheURLLoaderJob::ReadMore() {
uint32_t num_bytes;
// TODO: we should use the abstractions in MojoAsyncResourceHandler.
- MojoResult result = NetToMojoPendingBuffer::BeginWrite(
+ MojoResult result = network::NetToMojoPendingBuffer::BeginWrite(
&response_body_stream_, &pending_write_, &num_bytes);
if (result == MOJO_RESULT_SHOULD_WAIT) {
// The pipe is full. We need to wait for it to have more space.
@@ -407,8 +428,8 @@ void AppCacheURLLoaderJob::ReadMore() {
}
CHECK_GT(static_cast<uint32_t>(std::numeric_limits<int>::max()), num_bytes);
- scoped_refptr<NetToMojoIOBuffer> buffer =
- new NetToMojoIOBuffer(pending_write_.get());
+ auto buffer =
+ base::MakeRefCounted<network::NetToMojoIOBuffer>(pending_write_.get());
reader_->ReadData(
buffer.get(), info_->response_data_size(),
@@ -429,9 +450,12 @@ void AppCacheURLLoaderJob::NotifyCompleted(int error_code) {
if (storage_.get())
storage_->CancelDelegateCallbacks(this);
- const net::HttpResponseInfo* http_info = is_range_request()
- ? range_response_info_.get()
- : info_->http_response_info();
+ if (AppCacheRequestHandler::IsRunningInTests())
+ return;
+
+ const net::HttpResponseInfo* http_info =
+ is_range_request() ? range_response_info_.get()
+ : (info_ ? info_->http_response_info() : nullptr);
ResourceRequestCompletionStatus request_complete_data;
request_complete_data.error_code = error_code;
@@ -444,7 +468,7 @@ void AppCacheURLLoaderJob::NotifyCompleted(int error_code) {
request_complete_data.completion_time = base::TimeTicks::Now();
request_complete_data.encoded_body_length =
is_range_request() ? range_response_info_->headers->GetContentLength()
- : info_->response_data_size();
+ : (info_ ? info_->response_data_size() : 0);
request_complete_data.decoded_body_length =
request_complete_data.encoded_body_length;
}
diff --git a/chromium/content/browser/appcache/appcache_url_loader_job.h b/chromium/content/browser/appcache/appcache_url_loader_job.h
index d7ea502709c..36c67fb5ae7 100644
--- a/chromium/content/browser/appcache/appcache_url_loader_job.h
+++ b/chromium/content/browser/appcache/appcache_url_loader_job.h
@@ -19,15 +19,17 @@
#include "content/common/content_export.h"
#include "content/public/common/resource_request.h"
#include "content/public/common/url_loader.mojom.h"
-#include "mojo/public/cpp/bindings/associated_binding.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/system/data_pipe.h"
+namespace network {
+class NetToMojoPendingBuffer;
+}
+
namespace content {
class AppCacheRequest;
class AppCacheURLLoaderRequest;
-class NetToMojoPendingBuffer;
class URLLoaderFactoryGetter;
// Holds information about the subresource load request like the routing id,
@@ -36,7 +38,7 @@ struct SubresourceLoadInfo {
SubresourceLoadInfo();
~SubresourceLoadInfo();
- mojom::URLLoaderAssociatedRequest url_loader_request;
+ mojom::URLLoaderRequest url_loader_request;
int32_t routing_id;
int32_t request_id;
uint32_t options;
@@ -97,28 +99,29 @@ class CONTENT_EXPORT AppCacheURLLoaderJob : public AppCacheJob,
main_resource_loader_callback_ = std::move(callback);
}
- // Subresource request load information is passed in the
- // |subresource_load_info| parameter. This includes the request id, the
- // client pointer, etc.
- // |default_url_loader| is used to retrieve the network loader for requests
- // intended to be sent to the network.
- void SetSubresourceLoadInfo(
- std::unique_ptr<SubresourceLoadInfo> subresource_load_info,
- URLLoaderFactoryGetter* default_url_loader);
-
// Ownership of the |handler| is transferred to us via this call. This is
// only for subresource requests.
void set_request_handler(std::unique_ptr<AppCacheRequestHandler> handler) {
sub_resource_handler_ = std::move(handler);
}
+ // Binds to the URLLoaderRequest instance passed in the |request| parameter.
+ // The URLLoaderClient instance is passed in the |client| parameter. This
+ // enables the client to receive notifications/data, etc for the ensuing
+ // URL load.
+ void BindRequest(mojom::URLLoaderClientPtr client,
+ mojom::URLLoaderRequest request);
+
protected:
// AppCacheJob::Create() creates this instance.
friend class AppCacheJob;
- AppCacheURLLoaderJob(const ResourceRequest& request,
- AppCacheURLLoaderRequest* appcache_request,
- AppCacheStorage* storage);
+ AppCacheURLLoaderJob(
+ const ResourceRequest& request,
+ AppCacheURLLoaderRequest* appcache_request,
+ AppCacheStorage* storage,
+ std::unique_ptr<SubresourceLoadInfo> subresource_load_info,
+ URLLoaderFactoryGetter* loader_factory_getter);
// AppCacheStorage::Delegate methods
void OnResponseInfoLoaded(AppCacheResponseInfo* response_info,
@@ -177,7 +180,7 @@ class CONTENT_EXPORT AppCacheURLLoaderJob : public AppCacheJob,
// mojo data pipe entities.
mojo::ScopedDataPipeProducerHandle response_body_stream_;
- scoped_refptr<NetToMojoPendingBuffer> pending_write_;
+ scoped_refptr<network::NetToMojoPendingBuffer> pending_write_;
mojo::SimpleWatcher writable_handle_watcher_;
@@ -198,13 +201,7 @@ class CONTENT_EXPORT AppCacheURLLoaderJob : public AppCacheJob,
net::LoadTimingInfo load_timing_info_;
// Used for subresource requests which go to the network.
- mojom::URLLoaderAssociatedPtr network_loader_;
-
- // Binds the subresource URLLoaderClient with us. We can use the regular
- // binding_ member above when we remove the need for the associated requests
- // issue with URLLoaderFactory.
- std::unique_ptr<mojo::AssociatedBinding<mojom::URLLoader>>
- associated_binding_;
+ mojom::URLLoaderPtr network_loader_;
// Network URLLoaderClient binding for subresource requests.
mojo::Binding<mojom::URLLoaderClient> network_loader_client_binding_;
@@ -213,6 +210,10 @@ class CONTENT_EXPORT AppCacheURLLoaderJob : public AppCacheJob,
// info when we receive it.
AppCacheURLLoaderRequest* appcache_request_;
+ // Set to true when we receive a response from the network URL loader.
+ // Please see OnReceiveResponse()
+ bool received_response_;
+
DISALLOW_COPY_AND_ASSIGN(AppCacheURLLoaderJob);
};
diff --git a/chromium/content/browser/appcache/appcache_url_loader_request.cc b/chromium/content/browser/appcache/appcache_url_loader_request.cc
index 4669be97d15..a0898eb3e92 100644
--- a/chromium/content/browser/appcache/appcache_url_loader_request.cc
+++ b/chromium/content/browser/appcache/appcache_url_loader_request.cc
@@ -25,8 +25,8 @@ const std::string& AppCacheURLLoaderRequest::GetMethod() const {
return request_.method;
}
-const GURL& AppCacheURLLoaderRequest::GetFirstPartyForCookies() const {
- return request_.first_party_for_cookies;
+const GURL& AppCacheURLLoaderRequest::GetSiteForCookies() const {
+ return request_.site_for_cookies;
}
const GURL AppCacheURLLoaderRequest::GetReferrer() const {
@@ -34,8 +34,9 @@ const GURL AppCacheURLLoaderRequest::GetReferrer() const {
}
bool AppCacheURLLoaderRequest::IsSuccess() const {
- int response_code = GetResponseCode();
- return (response_code >= 200 && response_code <= 226);
+ if (response_.headers)
+ return true;
+ return false;
}
bool AppCacheURLLoaderRequest::IsCancelled() const {
@@ -54,7 +55,10 @@ int AppCacheURLLoaderRequest::GetResponseCode() const {
std::string AppCacheURLLoaderRequest::GetResponseHeaderByName(
const std::string& name) const {
- return std::string();
+ std::string header;
+ if (response_.headers)
+ response_.headers->GetNormalizedHeader(name, &header);
+ return header;
}
ResourceRequest* AppCacheURLLoaderRequest::GetResourceRequest() {
diff --git a/chromium/content/browser/appcache/appcache_url_loader_request.h b/chromium/content/browser/appcache/appcache_url_loader_request.h
index d0435c72b47..19a893bb569 100644
--- a/chromium/content/browser/appcache/appcache_url_loader_request.h
+++ b/chromium/content/browser/appcache/appcache_url_loader_request.h
@@ -28,7 +28,7 @@ class CONTENT_EXPORT AppCacheURLLoaderRequest : public AppCacheRequest {
// a chain of redirects.
const GURL& GetURL() const override;
const std::string& GetMethod() const override;
- const GURL& GetFirstPartyForCookies() const override;
+ const GURL& GetSiteForCookies() const override;
const GURL GetReferrer() const override;
// TODO(ananta)
// ResourceRequest only identifies the request unlike URLRequest which
diff --git a/chromium/content/browser/appcache/appcache_url_request.cc b/chromium/content/browser/appcache/appcache_url_request.cc
index da320b4b21f..2234ff3a9c6 100644
--- a/chromium/content/browser/appcache/appcache_url_request.cc
+++ b/chromium/content/browser/appcache/appcache_url_request.cc
@@ -23,8 +23,8 @@ const std::string& AppCacheURLRequest::GetMethod() const {
return url_request_->method();
}
-const GURL& AppCacheURLRequest::GetFirstPartyForCookies() const {
- return url_request_->first_party_for_cookies();
+const GURL& AppCacheURLRequest::GetSiteForCookies() const {
+ return url_request_->site_for_cookies();
}
const GURL AppCacheURLRequest::GetReferrer() const {
diff --git a/chromium/content/browser/appcache/appcache_url_request.h b/chromium/content/browser/appcache/appcache_url_request.h
index 35291588b43..d67143f3bb7 100644
--- a/chromium/content/browser/appcache/appcache_url_request.h
+++ b/chromium/content/browser/appcache/appcache_url_request.h
@@ -26,7 +26,7 @@ class CONTENT_EXPORT AppCacheURLRequest : public AppCacheRequest {
// AppCacheRequest overrides.
const GURL& GetURL() const override;
const std::string& GetMethod() const override;
- const GURL& GetFirstPartyForCookies() const override;
+ const GURL& GetSiteForCookies() const override;
const GURL GetReferrer() const override;
bool IsSuccess() const override;
bool IsCancelled() const override;
diff --git a/chromium/content/browser/appcache/appcache_url_request_job.cc b/chromium/content/browser/appcache/appcache_url_request_job.cc
index 17438b87540..da5a584ccd0 100644
--- a/chromium/content/browser/appcache/appcache_url_request_job.cc
+++ b/chromium/content/browser/appcache/appcache_url_request_job.cc
@@ -101,7 +101,7 @@ AppCacheURLRequestJob::AppCacheURLRequestJob(
AppCacheStorage* storage,
AppCacheHost* host,
bool is_main_resource,
- const OnPrepareToRestartCallback& restart_callback)
+ OnPrepareToRestartCallback restart_callback)
: net::URLRequestJob(request, network_delegate),
host_(host),
storage_(storage),
@@ -110,7 +110,7 @@ AppCacheURLRequestJob::AppCacheURLRequestJob(
cache_id_(kAppCacheNoCacheId),
is_fallback_(false),
is_main_resource_(is_main_resource),
- on_prepare_to_restart_callback_(restart_callback) {
+ on_prepare_to_restart_callback_(std::move(restart_callback)) {
DCHECK(storage_);
}
@@ -119,8 +119,8 @@ void AppCacheURLRequestJob::MaybeBeginDelivery() {
// Start asynchronously so that all error reporting and data
// callbacks happen as they would for network requests.
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&AppCacheURLRequestJob::BeginDelivery,
- StaticAsWeakPtr(this)));
+ FROM_HERE, base::BindOnce(&AppCacheURLRequestJob::BeginDelivery,
+ StaticAsWeakPtr(this)));
}
}
@@ -417,7 +417,7 @@ void AppCacheURLRequestJob::SetExtraRequestHeaders(
}
void AppCacheURLRequestJob::NotifyRestartRequired() {
- on_prepare_to_restart_callback_.Run();
+ std::move(on_prepare_to_restart_callback_).Run();
URLRequestJob::NotifyRestartRequired();
}
diff --git a/chromium/content/browser/appcache/appcache_url_request_job.h b/chromium/content/browser/appcache/appcache_url_request_job.h
index 1e0d37adf32..25ea0604823 100644
--- a/chromium/content/browser/appcache/appcache_url_request_job.h
+++ b/chromium/content/browser/appcache/appcache_url_request_job.h
@@ -35,7 +35,7 @@ class CONTENT_EXPORT AppCacheURLRequestJob : public net::URLRequestJob,
// Callback that will be invoked before the request is restarted. The caller
// can use this opportunity to grab state from the AppCacheURLRequestJob to
// determine how it should behave when the request is restarted.
- using OnPrepareToRestartCallback = base::Closure;
+ using OnPrepareToRestartCallback = base::OnceClosure;
~AppCacheURLRequestJob() override;
@@ -74,7 +74,7 @@ class CONTENT_EXPORT AppCacheURLRequestJob : public net::URLRequestJob,
AppCacheStorage* storage,
AppCacheHost* host,
bool is_main_resource,
- const OnPrepareToRestartCallback& restart_callback_);
+ OnPrepareToRestartCallback restart_callback_);
// Returns true if one of the Deliver methods has been called.
bool has_delivery_orders() const { return !IsWaiting(); }
@@ -133,7 +133,7 @@ class CONTENT_EXPORT AppCacheURLRequestJob : public net::URLRequestJob,
std::unique_ptr<AppCacheResponseReader> handler_source_reader_;
scoped_refptr<AppCache> cache_;
scoped_refptr<AppCacheGroup> group_;
- const OnPrepareToRestartCallback on_prepare_to_restart_callback_;
+ OnPrepareToRestartCallback on_prepare_to_restart_callback_;
};
} // namespace content
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 ed8b6e91831..80cf2f15950 100644
--- a/chromium/content/browser/appcache/appcache_url_request_job_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_url_request_job_unittest.cc
@@ -19,6 +19,7 @@
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
+#include "base/message_loop/message_loop.h"
#include "base/pickle.h"
#include "base/single_thread_task_runner.h"
#include "base/synchronization/waitable_event.h"
@@ -249,8 +250,9 @@ class AppCacheURLRequestJobTest : public testing::Test {
base::WaitableEvent::ResetPolicy::AUTOMATIC,
base::WaitableEvent::InitialState::NOT_SIGNALED));
io_thread_->task_runner()->PostTask(
- FROM_HERE, base::Bind(&AppCacheURLRequestJobTest::MethodWrapper<Method>,
- base::Unretained(this), method));
+ FROM_HERE,
+ base::BindOnce(&AppCacheURLRequestJobTest::MethodWrapper<Method>,
+ base::Unretained(this), method));
test_finished_event_->Wait();
}
@@ -301,8 +303,9 @@ class AppCacheURLRequestJobTest : public testing::Test {
// based objects get deleted.
DCHECK(io_thread_->task_runner()->BelongsToCurrentThread());
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&AppCacheURLRequestJobTest::TestFinishedUnwound,
- base::Unretained(this)));
+ FROM_HERE,
+ base::BindOnce(&AppCacheURLRequestJobTest::TestFinishedUnwound,
+ base::Unretained(this)));
}
void TestFinishedUnwound() {
@@ -310,12 +313,13 @@ class AppCacheURLRequestJobTest : public testing::Test {
test_finished_event_->Signal();
}
- void PushNextTask(const base::Closure& task) {
- task_stack_.push(std::pair<base::Closure, bool>(task, false));
+ void PushNextTask(base::OnceClosure task) {
+ task_stack_.push(
+ std::pair<base::OnceClosure, bool>(std::move(task), false));
}
- void PushNextTaskAsImmediate(const base::Closure& task) {
- task_stack_.push(std::pair<base::Closure, bool>(task, true));
+ void PushNextTaskAsImmediate(base::Closure task) {
+ task_stack_.push(std::pair<base::OnceClosure, bool>(std::move(task), true));
}
void ScheduleNextTask() {
@@ -324,13 +328,13 @@ class AppCacheURLRequestJobTest : public testing::Test {
TestFinished();
return;
}
- base::Closure task =task_stack_.top().first;
+ base::OnceClosure task = std::move(task_stack_.top().first);
bool immediate = task_stack_.top().second;
task_stack_.pop();
if (immediate)
- task.Run();
+ std::move(task).Run();
else
- base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, task);
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, std::move(task));
}
// Wrappers to call AppCacheResponseReader/Writer Read and Write methods
@@ -470,7 +474,7 @@ class AppCacheURLRequestJobTest : public testing::Test {
std::unique_ptr<AppCacheURLRequestJob> job(
new AppCacheURLRequestJob(request_.get(), nullptr, storage, nullptr,
- false, base::Bind(&ExpectNotRestarted)));
+ false, base::BindOnce(&ExpectNotRestarted)));
EXPECT_TRUE(job->IsWaiting());
EXPECT_FALSE(job->IsDeliveringAppCacheResponse());
EXPECT_FALSE(job->IsDeliveringNetworkResponse());
@@ -496,21 +500,21 @@ class AppCacheURLRequestJobTest : public testing::Test {
std::unique_ptr<AppCacheURLRequestJob> job(
new AppCacheURLRequestJob(request.get(), nullptr, storage, nullptr,
- false, base::Bind(&ExpectNotRestarted)));
+ false, base::BindOnce(&ExpectNotRestarted)));
job->DeliverErrorResponse();
EXPECT_TRUE(job->IsDeliveringErrorResponse());
EXPECT_FALSE(job->IsStarted());
job.reset(new AppCacheURLRequestJob(request.get(), nullptr, storage,
nullptr, false,
- base::Bind(&ExpectNotRestarted)));
+ base::BindOnce(&ExpectNotRestarted)));
job->DeliverNetworkResponse();
EXPECT_TRUE(job->IsDeliveringNetworkResponse());
EXPECT_FALSE(job->IsStarted());
job.reset(new AppCacheURLRequestJob(request.get(), nullptr, storage,
nullptr, false,
- base::Bind(&ExpectNotRestarted)));
+ base::BindOnce(&ExpectNotRestarted)));
const GURL kManifestUrl("http://blah/");
const int64_t kCacheId(1);
const AppCacheEntry kEntry(AppCacheEntry::EXPLICIT, 1);
@@ -543,7 +547,7 @@ class AppCacheURLRequestJobTest : public testing::Test {
// a network response.
std::unique_ptr<AppCacheURLRequestJob> mock_job(new AppCacheURLRequestJob(
request_.get(), nullptr, storage, nullptr, false,
- base::Bind(&SetIfCalled, &restart_callback_invoked_)));
+ base::BindOnce(&SetIfCalled, &restart_callback_invoked_)));
mock_job->DeliverNetworkResponse();
EXPECT_TRUE(mock_job->IsDeliveringNetworkResponse());
EXPECT_FALSE(mock_job->IsStarted());
@@ -581,7 +585,7 @@ class AppCacheURLRequestJobTest : public testing::Test {
// a network response.
std::unique_ptr<AppCacheURLRequestJob> mock_job(
new AppCacheURLRequestJob(request_.get(), nullptr, storage, nullptr,
- false, base::Bind(&ExpectNotRestarted)));
+ false, base::BindOnce(&ExpectNotRestarted)));
mock_job->DeliverErrorResponse();
EXPECT_TRUE(mock_job->IsDeliveringErrorResponse());
EXPECT_FALSE(mock_job->IsStarted());
@@ -633,7 +637,7 @@ class AppCacheURLRequestJobTest : public testing::Test {
// a network response.
std::unique_ptr<AppCacheURLRequestJob> job(
new AppCacheURLRequestJob(request_.get(), NULL, storage, NULL, false,
- base::Bind(&ExpectNotRestarted)));
+ base::BindOnce(&ExpectNotRestarted)));
if (start_after_delivery_orders) {
job->DeliverAppCachedResponse(
@@ -753,7 +757,7 @@ class AppCacheURLRequestJobTest : public testing::Test {
// Create job with orders to deliver an appcached entry.
std::unique_ptr<AppCacheURLRequestJob> job(
new AppCacheURLRequestJob(request_.get(), NULL, storage, NULL, false,
- base::Bind(&ExpectNotRestarted)));
+ base::BindOnce(&ExpectNotRestarted)));
job->DeliverAppCachedResponse(
GURL(), 111,
AppCacheEntry(AppCacheEntry::EXPLICIT, written_response_id_), false);
@@ -843,7 +847,7 @@ class AppCacheURLRequestJobTest : public testing::Test {
std::unique_ptr<base::WaitableEvent> test_finished_event_;
std::unique_ptr<MockStorageDelegate> storage_delegate_;
std::unique_ptr<MockAppCacheService> service_;
- std::stack<std::pair<base::Closure, bool> > task_stack_;
+ std::stack<std::pair<base::OnceClosure, bool>> task_stack_;
std::unique_ptr<AppCacheResponseReader> reader_;
scoped_refptr<HttpResponseInfoIOBuffer> read_info_buffer_;
diff --git a/chromium/content/browser/appcache/chrome_appcache_service.cc b/chromium/content/browser/appcache/chrome_appcache_service.cc
index cdceb0a1b5e..7d2fab2a3af 100644
--- a/chromium/content/browser/appcache/chrome_appcache_service.cc
+++ b/chromium/content/browser/appcache/chrome_appcache_service.cc
@@ -44,8 +44,7 @@ void ChromeAppCacheService::InitializeOnIOThread(
set_request_context(request_context_getter->GetURLRequestContext());
// Init our base class.
- Initialize(cache_path_,
- BrowserThread::GetTaskRunnerForThread(BrowserThread::CACHE).get());
+ Initialize(cache_path_);
set_appcache_policy(this);
set_special_storage_policy(special_storage_policy.get());
}
diff --git a/chromium/content/browser/appcache/chrome_appcache_service.h b/chromium/content/browser/appcache/chrome_appcache_service.h
index a34cd084cf4..d4a2430c5ee 100644
--- a/chromium/content/browser/appcache/chrome_appcache_service.h
+++ b/chromium/content/browser/appcache/chrome_appcache_service.h
@@ -41,8 +41,8 @@ struct ChromeAppCacheServiceDeleter;
class CONTENT_EXPORT ChromeAppCacheService
: public base::RefCountedThreadSafe<ChromeAppCacheService,
ChromeAppCacheServiceDeleter>,
- NON_EXPORTED_BASE(public AppCacheServiceImpl),
- NON_EXPORTED_BASE(public AppCachePolicy) {
+ public AppCacheServiceImpl,
+ public AppCachePolicy {
public:
explicit ChromeAppCacheService(storage::QuotaManagerProxy* proxy);
diff --git a/chromium/content/browser/appcache/chrome_appcache_service_unittest.cc b/chromium/content/browser/appcache/chrome_appcache_service_unittest.cc
index c69ce704d55..9b98d31d2a2 100644
--- a/chromium/content/browser/appcache/chrome_appcache_service_unittest.cc
+++ b/chromium/content/browser/appcache/chrome_appcache_service_unittest.cc
@@ -105,10 +105,10 @@ ChromeAppCacheServiceTest::CreateAppCacheServiceImpl(
base::ThreadTaskRunnerHandle::Get());
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&ChromeAppCacheService::InitializeOnIOThread,
- appcache_service, appcache_path,
- browser_context_.GetResourceContext(),
- base::RetainedRef(mock_request_context_getter), mock_policy));
+ base::BindOnce(
+ &ChromeAppCacheService::InitializeOnIOThread, appcache_service,
+ appcache_path, browser_context_.GetResourceContext(),
+ base::RetainedRef(mock_request_context_getter), mock_policy));
// Steps needed to initialize the storage of AppCache data.
scoped_task_environment_.RunUntilIdle();
if (init_storage) {
diff --git a/chromium/content/browser/appcache/mock_appcache_service.cc b/chromium/content/browser/appcache/mock_appcache_service.cc
index 1ae1b8a12e0..20efcfe9261 100644
--- a/chromium/content/browser/appcache/mock_appcache_service.cc
+++ b/chromium/content/browser/appcache/mock_appcache_service.cc
@@ -20,8 +20,8 @@ void MockAppCacheService::DeleteAppCachesForOrigin(
const GURL& origin, const net::CompletionCallback& callback) {
++delete_called_count_;
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&DeferredCallCallback, callback,
- mock_delete_appcaches_for_origin_result_));
+ FROM_HERE, base::BindOnce(&DeferredCallCallback, callback,
+ mock_delete_appcaches_for_origin_result_));
}
} // namespace content
diff --git a/chromium/content/browser/appcache/mock_appcache_storage.cc b/chromium/content/browser/appcache/mock_appcache_storage.cc
index 1bd3bed59aa..afe84d27486 100644
--- a/chromium/content/browser/appcache/mock_appcache_storage.cc
+++ b/chromium/content/browser/appcache/mock_appcache_storage.cc
@@ -477,8 +477,8 @@ void MockAppCacheStorage::ProcessMakeGroupObsolete(
void MockAppCacheStorage::ScheduleTask(const base::Closure& task) {
pending_tasks_.push_back(task);
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&MockAppCacheStorage::RunOnePendingTask,
- weak_factory_.GetWeakPtr()));
+ FROM_HERE, base::BindOnce(&MockAppCacheStorage::RunOnePendingTask,
+ weak_factory_.GetWeakPtr()));
}
void MockAppCacheStorage::RunOnePendingTask() {
diff --git a/chromium/content/browser/background_fetch/background_fetch_context.cc b/chromium/content/browser/background_fetch/background_fetch_context.cc
index 90b1be1e3ec..646da31e069 100644
--- a/chromium/content/browser/background_fetch/background_fetch_context.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_context.cc
@@ -4,6 +4,8 @@
#include "content/browser/background_fetch/background_fetch_context.h"
+#include <utility>
+
#include "base/memory/ptr_util.h"
#include "content/browser/background_fetch/background_fetch_data_manager.h"
#include "content/browser/background_fetch/background_fetch_event_dispatcher.h"
@@ -35,12 +37,13 @@ void RecordRegistrationDeletedError(blink::mojom::BackgroundFetchError error) {
BackgroundFetchContext::BackgroundFetchContext(
BrowserContext* browser_context,
- scoped_refptr<ServiceWorkerContextWrapper> service_worker_context)
+ const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context)
: browser_context_(browser_context),
data_manager_(
- base::MakeUnique<BackgroundFetchDataManager>(browser_context)),
+ base::MakeUnique<BackgroundFetchDataManager>(browser_context,
+ service_worker_context)),
event_dispatcher_(base::MakeUnique<BackgroundFetchEventDispatcher>(
- std::move(service_worker_context))),
+ service_worker_context)),
weak_factory_(this) {
// Although this lives only on the IO thread, it is constructed on UI thread.
DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -55,6 +58,8 @@ void BackgroundFetchContext::InitializeOnIOThread(
DCHECK_CURRENTLY_ON(BrowserThread::IO);
request_context_getter_ = request_context_getter;
+ delegate_proxy_ = base::MakeUnique<BackgroundFetchDelegateProxy>(
+ browser_context_, request_context_getter);
}
void BackgroundFetchContext::StartFetch(
@@ -90,7 +95,7 @@ void BackgroundFetchContext::DidCreateRegistration(
// Create the BackgroundFetchRegistration the renderer process will receive,
// which enables it to resolve the promise telling the developer it worked.
BackgroundFetchRegistration registration;
- registration.tag = registration_id.tag();
+ registration.id = registration_id.id();
registration.icons = options.icons;
registration.title = options.title;
registration.total_download_size = options.total_download_size;
@@ -100,25 +105,25 @@ void BackgroundFetchContext::DidCreateRegistration(
}
std::vector<std::string>
-BackgroundFetchContext::GetActiveTagsForServiceWorkerRegistration(
+BackgroundFetchContext::GetActiveIdsForServiceWorkerRegistration(
int64_t service_worker_registration_id,
const url::Origin& origin) const {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- std::vector<std::string> tags;
+ std::vector<std::string> ids;
for (const auto& pair : active_fetches_) {
const BackgroundFetchRegistrationId& registration_id =
pair.second->registration_id();
- // Only return the tags when the origin and SW registration id match.
+ // Only return the ids when the origin and SW registration id match.
if (registration_id.origin() == origin &&
registration_id.service_worker_registration_id() ==
service_worker_registration_id) {
- tags.push_back(pair.second->registration_id().tag());
+ ids.push_back(pair.second->registration_id().id());
}
}
- return tags;
+ return ids;
}
BackgroundFetchJobController* BackgroundFetchContext::GetActiveFetch(
@@ -145,8 +150,7 @@ void BackgroundFetchContext::CreateController(
std::unique_ptr<BackgroundFetchJobController> controller =
base::MakeUnique<BackgroundFetchJobController>(
- registration_id, options, data_manager_.get(), browser_context_,
- request_context_getter_,
+ delegate_proxy_.get(), registration_id, options, data_manager_.get(),
base::BindOnce(&BackgroundFetchContext::DidCompleteJob,
weak_factory_.GetWeakPtr()));
diff --git a/chromium/content/browser/background_fetch/background_fetch_context.h b/chromium/content/browser/background_fetch/background_fetch_context.h
index d96e76b82d3..8a2059d8dd5 100644
--- a/chromium/content/browser/background_fetch/background_fetch_context.h
+++ b/chromium/content/browser/background_fetch/background_fetch_context.h
@@ -6,6 +6,7 @@
#define CONTENT_BROWSER_BACKGROUND_FETCH_BACKGROUND_FETCH_CONTEXT_H_
#include <map>
+#include <memory>
#include <string>
#include <vector>
@@ -27,6 +28,7 @@ class Origin;
namespace content {
class BackgroundFetchDataManager;
+class BackgroundFetchDelegateProxy;
class BackgroundFetchEventDispatcher;
class BackgroundFetchJobController;
struct BackgroundFetchOptions;
@@ -46,8 +48,9 @@ class CONTENT_EXPORT BackgroundFetchContext
public:
// The BackgroundFetchContext will watch the ServiceWorkerContextWrapper so
// that it can respond to service worker events such as unregister.
- BackgroundFetchContext(BrowserContext* browser_context,
- scoped_refptr<ServiceWorkerContextWrapper> context);
+ BackgroundFetchContext(
+ BrowserContext* browser_context,
+ const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context);
// Finishes initializing the Background Fetch context on the IO thread by
// setting the |request_context_getter|.
@@ -62,9 +65,9 @@ class CONTENT_EXPORT BackgroundFetchContext
const BackgroundFetchOptions& options,
blink::mojom::BackgroundFetchService::FetchCallback callback);
- // Returns a vector with the tags of the active fetches for the given |origin|
+ // Returns a vector with the ids of the active fetches for the given |origin|
// and |service_worker_registration_id|.
- std::vector<std::string> GetActiveTagsForServiceWorkerRegistration(
+ std::vector<std::string> GetActiveIdsForServiceWorkerRegistration(
int64_t service_worker_registration_id,
const url::Origin& origin) const;
@@ -118,6 +121,7 @@ class CONTENT_EXPORT BackgroundFetchContext
std::unique_ptr<BackgroundFetchDataManager> data_manager_;
std::unique_ptr<BackgroundFetchEventDispatcher> event_dispatcher_;
+ std::unique_ptr<BackgroundFetchDelegateProxy> delegate_proxy_;
// Map of the Background Fetch fetches that are currently in-progress.
std::map<BackgroundFetchRegistrationId,
diff --git a/chromium/content/browser/background_fetch/background_fetch_cross_origin_filter_unittest.cc b/chromium/content/browser/background_fetch/background_fetch_cross_origin_filter_unittest.cc
index b930f6b05bf..5677d67c898 100644
--- a/chromium/content/browser/background_fetch/background_fetch_cross_origin_filter_unittest.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_cross_origin_filter_unittest.cc
@@ -4,6 +4,9 @@
#include "content/browser/background_fetch/background_fetch_cross_origin_filter.h"
+#include <map>
+#include <string>
+
#include "base/macros.h"
#include "content/browser/background_fetch/background_fetch_request_info.h"
#include "content/common/service_worker/service_worker_types.h"
@@ -37,10 +40,7 @@ class BackgroundFetchCrossOriginFilterTest : public ::testing::Test {
make_scoped_refptr(new BackgroundFetchRequestInfo(
0 /* request_info */, ServiceWorkerFetchRequest()));
- request_info->download_state_populated_ = true;
request_info->response_headers_ = response_headers;
-
- request_info->response_data_populated_ = true;
request_info->url_chain_ = {GURL(response_url)};
return request_info;
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 408dc1dbb9d..28d89eb4854 100644
--- a/chromium/content/browser/background_fetch/background_fetch_data_manager.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_data_manager.cc
@@ -7,20 +7,63 @@
#include <algorithm>
#include <queue>
+#include "base/command_line.h"
#include "base/memory/ptr_util.h"
#include "content/browser/background_fetch/background_fetch_constants.h"
#include "content/browser/background_fetch/background_fetch_context.h"
#include "content/browser/background_fetch/background_fetch_cross_origin_filter.h"
#include "content/browser/background_fetch/background_fetch_request_info.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
+#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/public/browser/blob_handle.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/download_interrupt_reasons.h"
#include "content/public/browser/download_item.h"
-#include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerResponseType.h"
+#include "content/public/common/content_switches.h"
+#include "services/network/public/interfaces/fetch_api.mojom.h"
namespace content {
+namespace {
+
+enum class DatabaseStatus { kOk, kFailed, kNotFound };
+
+DatabaseStatus ToDatabaseStatus(ServiceWorkerStatusCode status) {
+ switch (status) {
+ case SERVICE_WORKER_OK:
+ return DatabaseStatus::kOk;
+ case SERVICE_WORKER_ERROR_FAILED:
+ case SERVICE_WORKER_ERROR_ABORT:
+ // FAILED is for invalid arguments (e.g. empty key) or database errors.
+ // ABORT is for unexpected failures, e.g. because shutdown is in progress.
+ // BackgroundFetchDataManager handles both of these the same way.
+ return DatabaseStatus::kFailed;
+ case SERVICE_WORKER_ERROR_NOT_FOUND:
+ // This can also happen for writes, if the ServiceWorkerRegistration has
+ // been deleted.
+ return DatabaseStatus::kNotFound;
+ case SERVICE_WORKER_ERROR_START_WORKER_FAILED:
+ case SERVICE_WORKER_ERROR_PROCESS_NOT_FOUND:
+ case SERVICE_WORKER_ERROR_EXISTS:
+ case SERVICE_WORKER_ERROR_INSTALL_WORKER_FAILED:
+ case SERVICE_WORKER_ERROR_ACTIVATE_WORKER_FAILED:
+ case SERVICE_WORKER_ERROR_IPC_FAILED:
+ case SERVICE_WORKER_ERROR_NETWORK:
+ case SERVICE_WORKER_ERROR_SECURITY:
+ case SERVICE_WORKER_ERROR_EVENT_WAITUNTIL_REJECTED:
+ case SERVICE_WORKER_ERROR_STATE:
+ case SERVICE_WORKER_ERROR_TIMEOUT:
+ case SERVICE_WORKER_ERROR_SCRIPT_EVALUATE_FAILED:
+ case SERVICE_WORKER_ERROR_DISK_CACHE:
+ case SERVICE_WORKER_ERROR_REDUNDANT:
+ case SERVICE_WORKER_ERROR_DISALLOWED:
+ case SERVICE_WORKER_ERROR_MAX_VALUE:
+ break;
+ }
+ NOTREACHED();
+ return DatabaseStatus::kFailed;
+}
+
// Returns whether the response contained in the Background Fetch |request| is
// considered OK. See https://fetch.spec.whatwg.org/#ok-status aka a successful
// 2xx status per https://tools.ietf.org/html/rfc7231#section-6.3.
@@ -29,6 +72,194 @@ bool IsOK(const BackgroundFetchRequestInfo& request) {
return status >= 200 && status < 300;
}
+const char kRegistrationKeyPrefix[] = "bgf_registration_";
+
+std::string RegistrationKey(
+ const BackgroundFetchRegistrationId& registration_id) {
+ return kRegistrationKeyPrefix + registration_id.id();
+}
+
+} // namespace
+
+// A DatabaseTask is an asynchronous "transaction" that needs to read/write the
+// Service Worker Database.
+//
+// Only one DatabaseTask can run at once per StoragePartition, and no other code
+// reads/writes Background Fetch keys, so each task effectively has an exclusive
+// lock, except that core Service Worker code may delete all keys for a
+// ServiceWorkerRegistration or the entire database at any time.
+class BackgroundFetchDataManager::DatabaseTask {
+ public:
+ virtual ~DatabaseTask() = default;
+
+ void Run() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(!data_manager_->database_tasks_.empty());
+ DCHECK_EQ(data_manager_->database_tasks_.front().get(), this);
+ Start();
+ }
+
+ protected:
+ explicit DatabaseTask(BackgroundFetchDataManager* data_manager)
+ : data_manager_(data_manager) {}
+
+ // The task should begin reading/writing when this is called.
+ virtual void Start() = 0;
+
+ // Each task MUST call this once finished, even if exceptions occur, to
+ // release their lock and allow the next task to execute.
+ void Finished() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(!data_manager_->database_tasks_.empty());
+ DCHECK_EQ(data_manager_->database_tasks_.front().get(), this);
+ // Keep a reference to |this| on the stack, so |this| lives until |self|
+ // goes out of scope instead of being destroyed when |pop| is called.
+ std::unique_ptr<DatabaseTask> self(
+ std::move(data_manager_->database_tasks_.front()));
+ data_manager_->database_tasks_.pop();
+ if (!data_manager_->database_tasks_.empty())
+ data_manager_->database_tasks_.front()->Run();
+ }
+
+ ServiceWorkerContextWrapper* service_worker_context() {
+ DCHECK(data_manager_->service_worker_context_);
+ return data_manager_->service_worker_context_.get();
+ }
+
+ private:
+ BackgroundFetchDataManager* data_manager_; // Owns this.
+
+ DISALLOW_COPY_AND_ASSIGN(DatabaseTask);
+};
+
+namespace {
+
+class CreateRegistrationTask : public BackgroundFetchDataManager::DatabaseTask {
+ public:
+ CreateRegistrationTask(
+ BackgroundFetchDataManager* data_manager,
+ const BackgroundFetchRegistrationId& registration_id,
+ const std::vector<ServiceWorkerFetchRequest>& requests,
+ const BackgroundFetchOptions& options,
+ BackgroundFetchDataManager::CreateRegistrationCallback callback)
+ : DatabaseTask(data_manager),
+ registration_id_(registration_id),
+ requests_(requests),
+ options_(options),
+ callback_(std::move(callback)),
+ weak_factory_(this) {}
+
+ ~CreateRegistrationTask() override = default;
+
+ void Start() override {
+ service_worker_context()->GetRegistrationUserData(
+ registration_id_.service_worker_registration_id(),
+ {RegistrationKey(registration_id_)},
+ base::Bind(&CreateRegistrationTask::DidGetRegistration,
+ weak_factory_.GetWeakPtr()));
+ }
+
+ private:
+ void DidGetRegistration(const std::vector<std::string>& data,
+ ServiceWorkerStatusCode status) {
+ switch (ToDatabaseStatus(status)) {
+ case DatabaseStatus::kNotFound:
+ service_worker_context()->StoreRegistrationUserData(
+ registration_id_.service_worker_registration_id(),
+ registration_id_.origin().GetURL(),
+ {
+ {RegistrationKey(registration_id_), "TODO VALUE"}
+ // TODO(crbug.com/757760): Store requests as well.
+ },
+ base::Bind(&CreateRegistrationTask::DidStoreRegistration,
+ weak_factory_.GetWeakPtr()));
+ return;
+ case DatabaseStatus::kOk:
+ std::move(callback_).Run(
+ blink::mojom::BackgroundFetchError::DUPLICATED_ID);
+ Finished(); // Destroys |this|.
+ return;
+ case DatabaseStatus::kFailed:
+ std::move(callback_).Run(
+ blink::mojom::BackgroundFetchError::STORAGE_ERROR);
+ Finished(); // Destroys |this|.
+ return;
+ }
+ }
+
+ void DidStoreRegistration(ServiceWorkerStatusCode status) {
+ switch (ToDatabaseStatus(status)) {
+ case DatabaseStatus::kOk:
+ std::move(callback_).Run(blink::mojom::BackgroundFetchError::NONE);
+ Finished(); // Destroys |this|.
+ return;
+ case DatabaseStatus::kFailed:
+ case DatabaseStatus::kNotFound:
+ std::move(callback_).Run(
+ blink::mojom::BackgroundFetchError::STORAGE_ERROR);
+ Finished(); // Destroys |this|.
+ return;
+ }
+ }
+
+ BackgroundFetchRegistrationId registration_id_;
+ std::vector<ServiceWorkerFetchRequest> requests_;
+ BackgroundFetchOptions options_;
+ BackgroundFetchDataManager::CreateRegistrationCallback callback_;
+
+ base::WeakPtrFactory<CreateRegistrationTask> weak_factory_; // Keep as last.
+
+ DISALLOW_COPY_AND_ASSIGN(CreateRegistrationTask);
+};
+
+class DeleteRegistrationTask : public BackgroundFetchDataManager::DatabaseTask {
+ public:
+ DeleteRegistrationTask(
+ BackgroundFetchDataManager* data_manager,
+ const BackgroundFetchRegistrationId& registration_id,
+ BackgroundFetchDataManager::DeleteRegistrationCallback callback)
+ : DatabaseTask(data_manager),
+ registration_id_(registration_id),
+ callback_(std::move(callback)),
+ weak_factory_(this) {}
+
+ void Start() override {
+ service_worker_context()->ClearRegistrationUserData(
+ registration_id_.service_worker_registration_id(),
+ {
+ RegistrationKey(registration_id_)
+ // TODO(crbug.com/757760): Delete requests as well.
+ },
+ base::Bind(&DeleteRegistrationTask::DidDeleteRegistration,
+ weak_factory_.GetWeakPtr()));
+ }
+
+ private:
+ void DidDeleteRegistration(ServiceWorkerStatusCode status) {
+ switch (ToDatabaseStatus(status)) {
+ case DatabaseStatus::kOk:
+ case DatabaseStatus::kNotFound:
+ std::move(callback_).Run(blink::mojom::BackgroundFetchError::NONE);
+ Finished(); // Destroys |this|.
+ return;
+ case DatabaseStatus::kFailed:
+ std::move(callback_).Run(
+ blink::mojom::BackgroundFetchError::STORAGE_ERROR);
+ Finished(); // Destroys |this|.
+ return;
+ }
+ }
+
+ BackgroundFetchRegistrationId registration_id_;
+ BackgroundFetchDataManager::DeleteRegistrationCallback callback_;
+
+ base::WeakPtrFactory<DeleteRegistrationTask> weak_factory_; // Keep as last.
+
+ DISALLOW_COPY_AND_ASSIGN(DeleteRegistrationTask);
+};
+
+} // namespace
+
// The Registration Data class encapsulates the data stored for a particular
// Background Fetch registration. This roughly matches the on-disk format that
// will be adhered to in the future.
@@ -124,12 +355,12 @@ class BackgroundFetchDataManager::RegistrationData {
};
BackgroundFetchDataManager::BackgroundFetchDataManager(
- BrowserContext* browser_context)
- : weak_ptr_factory_(this) {
- // Constructed on the UI thread, then used on a different thread.
+ BrowserContext* browser_context,
+ scoped_refptr<ServiceWorkerContextWrapper> service_worker_context)
+ : service_worker_context_(std::move(service_worker_context)),
+ weak_ptr_factory_(this) {
+ // Constructed on the UI thread, then used on the IO thread.
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- DETACH_FROM_SEQUENCE(sequence_checker_);
-
DCHECK(browser_context);
// Store the blob storage context for the given |browser_context|.
@@ -139,7 +370,7 @@ BackgroundFetchDataManager::BackgroundFetchDataManager(
}
BackgroundFetchDataManager::~BackgroundFetchDataManager() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
}
void BackgroundFetchDataManager::CreateRegistration(
@@ -147,10 +378,17 @@ void BackgroundFetchDataManager::CreateRegistration(
const std::vector<ServiceWorkerFetchRequest>& requests,
const BackgroundFetchOptions& options,
CreateRegistrationCallback callback) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableBackgroundFetchPersistence)) {
+ AddDatabaseTask(std::make_unique<CreateRegistrationTask>(
+ this, registration_id, requests, options, std::move(callback)));
+ return;
+ }
if (registrations_.find(registration_id) != registrations_.end()) {
- std::move(callback).Run(blink::mojom::BackgroundFetchError::DUPLICATED_TAG);
+ std::move(callback).Run(blink::mojom::BackgroundFetchError::DUPLICATED_ID);
return;
}
@@ -165,7 +403,7 @@ void BackgroundFetchDataManager::CreateRegistration(
void BackgroundFetchDataManager::PopNextRequest(
const BackgroundFetchRegistrationId& registration_id,
NextRequestCallback callback) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
auto iter = registrations_.find(registration_id);
DCHECK(iter != registrations_.end());
@@ -183,7 +421,7 @@ void BackgroundFetchDataManager::MarkRequestAsStarted(
const BackgroundFetchRegistrationId& registration_id,
BackgroundFetchRequestInfo* request,
const std::string& download_guid) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
auto iter = registrations_.find(registration_id);
DCHECK(iter != registrations_.end());
@@ -196,7 +434,7 @@ void BackgroundFetchDataManager::MarkRequestAsComplete(
const BackgroundFetchRegistrationId& registration_id,
BackgroundFetchRequestInfo* request,
MarkedCompleteCallback callback) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
auto iter = registrations_.find(registration_id);
DCHECK(iter != registrations_.end());
@@ -211,7 +449,7 @@ void BackgroundFetchDataManager::MarkRequestAsComplete(
void BackgroundFetchDataManager::GetSettledFetchesForRegistration(
const BackgroundFetchRegistrationId& registration_id,
SettledFetchesCallback callback) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
auto iter = registrations_.find(registration_id);
DCHECK(iter != registrations_.end());
@@ -238,7 +476,7 @@ void BackgroundFetchDataManager::GetSettledFetchesForRegistration(
settled_fetch.response.url_list = request->GetURLChain();
settled_fetch.response.response_type =
- blink::kWebServiceWorkerResponseTypeDefault;
+ network::mojom::FetchResponseType::kDefault;
// Include the status code, status text and the response's body as a blob
// when this is allowed by the CORS protocol.
@@ -251,8 +489,6 @@ void BackgroundFetchDataManager::GetSettledFetchesForRegistration(
if (request->GetFileSize() > 0) {
DCHECK(!request->GetFilePath().empty());
- // CreateFileBackedBlob DCHECKs that it is called on the IO thread. This
- // imposes a more specific requirement than our sequence_checker_.
std::unique_ptr<BlobHandle> blob_handle =
blob_storage_context_->CreateFileBackedBlob(
request->GetFilePath(), 0 /* offset */, request->GetFileSize(),
@@ -289,11 +525,18 @@ void BackgroundFetchDataManager::GetSettledFetchesForRegistration(
void BackgroundFetchDataManager::DeleteRegistration(
const BackgroundFetchRegistrationId& registration_id,
DeleteRegistrationCallback callback) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableBackgroundFetchPersistence)) {
+ AddDatabaseTask(std::make_unique<DeleteRegistrationTask>(
+ this, registration_id, std::move(callback)));
+ return;
+ }
auto iter = registrations_.find(registration_id);
if (iter == registrations_.end()) {
- std::move(callback).Run(blink::mojom::BackgroundFetchError::INVALID_TAG);
+ std::move(callback).Run(blink::mojom::BackgroundFetchError::INVALID_ID);
return;
}
@@ -302,4 +545,11 @@ void BackgroundFetchDataManager::DeleteRegistration(
std::move(callback).Run(blink::mojom::BackgroundFetchError::NONE);
}
+void BackgroundFetchDataManager::AddDatabaseTask(
+ std::unique_ptr<DatabaseTask> task) {
+ database_tasks_.push(std::move(task));
+ if (database_tasks_.size() == 1)
+ database_tasks_.front()->Run();
+}
+
} // namespace content
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 424d5be11c9..8e9892c72f8 100644
--- a/chromium/content/browser/background_fetch/background_fetch_data_manager.h
+++ b/chromium/content/browser/background_fetch/background_fetch_data_manager.h
@@ -11,9 +11,9 @@
#include <unordered_map>
#include "base/callback_forward.h"
+#include "base/containers/queue.h"
#include "base/macros.h"
#include "base/optional.h"
-#include "base/sequence_checker.h"
#include "content/browser/background_fetch/background_fetch_registration_id.h"
#include "content/common/content_export.h"
#include "third_party/WebKit/public/platform/modules/background_fetch/background_fetch.mojom.h"
@@ -26,11 +26,20 @@ struct BackgroundFetchSettledFetch;
class BlobHandle;
class BrowserContext;
class ChromeBlobStorageContext;
-
-// The BackgroundFetchDataManager keeps track of all of the outstanding requests
-// which are in process in the DownloadManager. When Chromium restarts, it is
-// responsibile for reconnecting all the in progress downloads with an observer
-// which will keep the metadata up to date.
+class ServiceWorkerContextWrapper;
+
+// The BackgroundFetchDataManager is a wrapper around persistent storage (the
+// Service Worker database), exposing APIs for the read and write queries needed
+// for Background Fetch.
+//
+// There must only be a single instance of this class per StoragePartition, and
+// it must only be used on the IO thread, since it relies on there being no
+// other code concurrently reading/writing the Background Fetch keys of the same
+// Service Worker database (except for deletions, e.g. it's safe for the Service
+// Worker code to remove a ServiceWorkerRegistration and all its keys).
+//
+// Schema design doc:
+// https://docs.google.com/document/d/1-WPPTP909Gb5PnaBOKP58tPVLw2Fq0Ln-u1EBviIBns/edit
class CONTENT_EXPORT BackgroundFetchDataManager {
public:
using CreateRegistrationCallback =
@@ -47,7 +56,11 @@ class CONTENT_EXPORT BackgroundFetchDataManager {
std::vector<BackgroundFetchSettledFetch>,
std::vector<std::unique_ptr<BlobHandle>>)>;
- explicit BackgroundFetchDataManager(BrowserContext* browser_context);
+ class DatabaseTask;
+
+ BackgroundFetchDataManager(
+ BrowserContext* browser_context,
+ scoped_refptr<ServiceWorkerContextWrapper> service_worker_context);
~BackgroundFetchDataManager();
// Creates and stores a new registration with the given properties. Will
@@ -95,6 +108,10 @@ class CONTENT_EXPORT BackgroundFetchDataManager {
class RegistrationData;
+ void AddDatabaseTask(std::unique_ptr<DatabaseTask> task);
+
+ scoped_refptr<ServiceWorkerContextWrapper> service_worker_context_;
+
// The blob storage request with which response information will be stored.
scoped_refptr<ChromeBlobStorageContext> blob_storage_context_;
@@ -102,7 +119,9 @@ class CONTENT_EXPORT BackgroundFetchDataManager {
std::map<BackgroundFetchRegistrationId, std::unique_ptr<RegistrationData>>
registrations_;
- SEQUENCE_CHECKER(sequence_checker_);
+ // Pending database operations, serialized to ensure consistency.
+ // Invariant: the frontmost task, if any, has already been started.
+ base::queue<std::unique_ptr<DatabaseTask>> database_tasks_;
base::WeakPtrFactory<BackgroundFetchDataManager> weak_ptr_factory_;
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 9a9e71a83a2..d0c465f3155 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
@@ -7,29 +7,40 @@
#include <memory>
#include <string>
+#include "base/barrier_closure.h"
#include "base/bind_helpers.h"
#include "base/callback_helpers.h"
+#include "base/command_line.h"
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
#include "content/browser/background_fetch/background_fetch_request_info.h"
#include "content/browser/background_fetch/background_fetch_test_base.h"
+#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/common/content_switches.h"
namespace content {
namespace {
-const char kExampleTag[] = "my-example-tag";
+const char kExampleId[] = "my-example-id";
} // namespace
class BackgroundFetchDataManagerTest : public BackgroundFetchTestBase {
public:
- BackgroundFetchDataManagerTest()
- : background_fetch_data_manager_(
- base::MakeUnique<BackgroundFetchDataManager>(browser_context())) {}
+ BackgroundFetchDataManagerTest() {
+ RestartDataManagerFromPersistentStorage();
+ }
~BackgroundFetchDataManagerTest() override = default;
- protected:
+ // Re-creates the data manager. Useful for testing that data was persisted.
+ void RestartDataManagerFromPersistentStorage() {
+ background_fetch_data_manager_ =
+ base::MakeUnique<BackgroundFetchDataManager>(
+ browser_context(),
+ embedded_worker_test_helper()->context_wrapper());
+ }
+
// Synchronous version of BackgroundFetchDataManager::CreateRegistration().
void CreateRegistration(
const BackgroundFetchRegistrationId& registration_id,
@@ -61,7 +72,6 @@ class BackgroundFetchDataManagerTest : public BackgroundFetchTestBase {
run_loop.Run();
}
- private:
void DidCreateRegistration(base::Closure quit_closure,
blink::mojom::BackgroundFetchError* out_error,
blink::mojom::BackgroundFetchError error) {
@@ -78,7 +88,6 @@ class BackgroundFetchDataManagerTest : public BackgroundFetchTestBase {
quit_closure.Run();
}
- std::string job_guid_;
std::unique_ptr<BackgroundFetchDataManager> background_fetch_data_manager_;
};
@@ -87,7 +96,7 @@ TEST_F(BackgroundFetchDataManagerTest, NoDuplicateRegistrations) {
// registration that's already known to the system.
BackgroundFetchRegistrationId registration_id;
- ASSERT_TRUE(CreateRegistrationId(kExampleTag, &registration_id));
+ ASSERT_TRUE(CreateRegistrationId(kExampleId, &registration_id));
std::vector<ServiceWorkerFetchRequest> requests;
BackgroundFetchOptions options;
@@ -95,27 +104,111 @@ TEST_F(BackgroundFetchDataManagerTest, NoDuplicateRegistrations) {
blink::mojom::BackgroundFetchError error;
// Deleting the not-yet-created registration should fail.
- ASSERT_NO_FATAL_FAILURE(DeleteRegistration(registration_id, &error));
- EXPECT_EQ(error, blink::mojom::BackgroundFetchError::INVALID_TAG);
+ DeleteRegistration(registration_id, &error);
+ EXPECT_EQ(error, blink::mojom::BackgroundFetchError::INVALID_ID);
// Creating the initial registration should succeed.
- ASSERT_NO_FATAL_FAILURE(
- CreateRegistration(registration_id, requests, options, &error));
+ CreateRegistration(registration_id, requests, options, &error);
EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
// Attempting to create it again should yield an error.
- ASSERT_NO_FATAL_FAILURE(
- CreateRegistration(registration_id, requests, options, &error));
- EXPECT_EQ(error, blink::mojom::BackgroundFetchError::DUPLICATED_TAG);
+ CreateRegistration(registration_id, requests, options, &error);
+ EXPECT_EQ(error, blink::mojom::BackgroundFetchError::DUPLICATED_ID);
// Deleting the registration should succeed.
- ASSERT_NO_FATAL_FAILURE(DeleteRegistration(registration_id, &error));
+ DeleteRegistration(registration_id, &error);
EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
// And then recreating the registration again should work fine.
- ASSERT_NO_FATAL_FAILURE(
- CreateRegistration(registration_id, requests, options, &error));
+ CreateRegistration(registration_id, requests, options, &error);
+ EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+}
+
+TEST_F(BackgroundFetchDataManagerTest, CreateAndDeleteRegistrationPersisted) {
+ // Tests that the BackgroundFetchDataManager persists created registrations to
+ // the Service Worker DB.
+
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kEnableBackgroundFetchPersistence);
+
+ BackgroundFetchRegistrationId registration_id;
+ ASSERT_TRUE(CreateRegistrationId(kExampleId, &registration_id));
+
+ std::vector<ServiceWorkerFetchRequest> requests;
+ BackgroundFetchOptions options;
+
+ blink::mojom::BackgroundFetchError error;
+
+ // Creating the initial registration should succeed.
+ CreateRegistration(registration_id, requests, options, &error);
+ EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+
+ RestartDataManagerFromPersistentStorage();
+
+ // Attempting to create it again should yield an error, even after restarting.
+ CreateRegistration(registration_id, requests, options, &error);
+ EXPECT_EQ(error, blink::mojom::BackgroundFetchError::DUPLICATED_ID);
+
+ // Deleting the registration should succeed.
+ DeleteRegistration(registration_id, &error);
EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+
+ RestartDataManagerFromPersistentStorage();
+
+ // And then recreating the registration again should work fine, even after
+ // restarting.
+ CreateRegistration(registration_id, requests, options, &error);
+ EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+}
+
+TEST_F(BackgroundFetchDataManagerTest, CreateInParallel) {
+ // Tests that multiple parallel calls to the BackgroundFetchDataManager are
+ // linearized and handled one at a time, rather than producing inconsistent
+ // results due to interleaving.
+
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kEnableBackgroundFetchPersistence);
+
+ BackgroundFetchRegistrationId registration_id;
+ ASSERT_TRUE(CreateRegistrationId(kExampleId, &registration_id));
+
+ std::vector<ServiceWorkerFetchRequest> requests;
+ BackgroundFetchOptions options;
+
+ std::vector<blink::mojom::BackgroundFetchError> errors(5);
+
+ const int num_parallel_creates = 5;
+
+ base::RunLoop run_loop;
+ base::RepeatingClosure quit_once_all_finished_closure =
+ base::BarrierClosure(num_parallel_creates, run_loop.QuitClosure());
+ for (int i = 0; i < num_parallel_creates; i++) {
+ background_fetch_data_manager_->CreateRegistration(
+ registration_id, requests, options,
+ base::BindOnce(&BackgroundFetchDataManagerTest::DidCreateRegistration,
+ base::Unretained(this), quit_once_all_finished_closure,
+ &errors[i]));
+ }
+ run_loop.Run();
+
+ int success_count = 0;
+ int duplicated_id_count = 0;
+ for (auto error : errors) {
+ switch (error) {
+ case blink::mojom::BackgroundFetchError::NONE:
+ success_count++;
+ break;
+ case blink::mojom::BackgroundFetchError::DUPLICATED_ID:
+ duplicated_id_count++;
+ break;
+ default:
+ break;
+ }
+ }
+ // Exactly one of the calls should have succeeded in creating a registration,
+ // and all the others should have failed with DUPLICATED_ID.
+ EXPECT_EQ(1, success_count);
+ EXPECT_EQ(num_parallel_creates - 1, duplicated_id_count);
}
} // namespace content
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 4963425a41c..2ca7beb0f1f 100644
--- a/chromium/content/browser/background_fetch/background_fetch_delegate_proxy.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_delegate_proxy.cc
@@ -4,9 +4,13 @@
#include "content/browser/background_fetch/background_fetch_delegate_proxy.h"
+#include <utility>
+
+#include "base/guid.h"
#include "base/memory/ptr_util.h"
#include "build/build_config.h"
#include "content/browser/background_fetch/background_fetch_job_controller.h"
+#include "content/browser/background_fetch/background_fetch_response.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/download_item.h"
#include "content/public/browser/download_manager.h"
@@ -15,7 +19,6 @@
#if defined(OS_ANDROID)
#include "base/android/path_utils.h"
#include "base/files/file_path.h"
-#include "base/guid.h"
#endif
namespace content {
@@ -24,7 +27,7 @@ namespace content {
namespace {
// Prefix for files stored in the Chromium-internal download directory to
-// indicate files thta were fetched through Background Fetch.
+// indicate files that were fetched through Background Fetch.
const char kBackgroundFetchFilePrefix[] = "BGFetch-";
} // namespace
@@ -32,14 +35,12 @@ const char kBackgroundFetchFilePrefix[] = "BGFetch-";
// Internal functionality of the BackgroundFetchDelegateProxy that lives on the
// UI thread, where all interaction with the download manager must happen.
-class BackgroundFetchDelegateProxy::Core : public DownloadItem::Observer {
+class BackgroundFetchDelegateProxy::Core {
public:
Core(const base::WeakPtr<BackgroundFetchDelegateProxy>& io_parent,
- const BackgroundFetchRegistrationId& registration_id,
BrowserContext* browser_context,
scoped_refptr<net::URLRequestContextGetter> request_context)
: io_parent_(io_parent),
- registration_id_(registration_id),
browser_context_(browser_context),
request_context_(std::move(request_context)),
weak_ptr_factory_(this) {
@@ -47,19 +48,15 @@ class BackgroundFetchDelegateProxy::Core : public DownloadItem::Observer {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
}
- ~Core() final {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- for (const auto& pair : downloads_)
- pair.first->RemoveObserver(this);
- }
+ ~Core() { DCHECK_CURRENTLY_ON(BrowserThread::UI); }
base::WeakPtr<Core> GetWeakPtrOnUI() {
return weak_ptr_factory_.GetWeakPtr();
}
- void StartRequest(
- scoped_refptr<BackgroundFetchRequestInfo> request,
- const net::NetworkTrafficAnnotationTag& traffic_annotation) {
+ void StartRequest(const std::string& guid,
+ const url::Origin& origin,
+ scoped_refptr<BackgroundFetchRequestInfo> request) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(request_context_);
DCHECK(request);
@@ -70,6 +67,35 @@ class BackgroundFetchDelegateProxy::Core : public DownloadItem::Observer {
const ServiceWorkerFetchRequest& fetch_request = request->fetch_request();
+ const net::NetworkTrafficAnnotationTag traffic_annotation(
+ net::DefineNetworkTrafficAnnotation("background_fetch_context",
+ R"(
+ semantics {
+ sender: "Background Fetch API"
+ description:
+ "The Background Fetch API enables developers to upload or "
+ "download files on behalf of the user. Such fetches will yield "
+ "a user visible notification to inform the user of the "
+ "operation, through which it can be suspended, resumed and/or "
+ "cancelled. The developer retains control of the file once the "
+ "fetch is completed, similar to XMLHttpRequest and other "
+ "mechanisms for fetching resources using JavaScript."
+ trigger:
+ "When the website uses the Background Fetch API to request "
+ "fetching a file and/or a list of files. This is a Web "
+ "Platform API for which no express user permission is required."
+ data:
+ "The request headers and data as set by the website's "
+ "developer."
+ destination: WEBSITE
+ }
+ policy {
+ cookies_allowed: YES
+ cookies_store: "user"
+ setting: "This feature cannot be disabled in settings."
+ policy_exception_justification: "Not implemented."
+ })"));
+
std::unique_ptr<DownloadUrlParameters> download_parameters(
base::MakeUnique<DownloadUrlParameters>(
fetch_request.url, request_context_.get(), traffic_annotation));
@@ -86,8 +112,7 @@ class BackgroundFetchDelegateProxy::Core : public DownloadItem::Observer {
if (fetch_request.mode == FETCH_REQUEST_MODE_CORS ||
fetch_request.mode == FETCH_REQUEST_MODE_CORS_WITH_FORCED_PREFLIGHT ||
(fetch_request.method != "GET" && fetch_request.method != "POST")) {
- download_parameters->add_request_header(
- "Origin", registration_id_.origin().Serialize());
+ download_parameters->add_request_header("Origin", origin.Serialize());
}
// TODO(peter): Background Fetch responses should not end up in the user's
@@ -104,158 +129,127 @@ class BackgroundFetchDelegateProxy::Core : public DownloadItem::Observer {
}
#endif // defined(OS_ANDROID)
- download_parameters->set_callback(base::Bind(&Core::DidStartRequest,
- weak_ptr_factory_.GetWeakPtr(),
- std::move(request)));
+ download_parameters->set_callback(
+ base::Bind(&Core::DidStartRequest, weak_ptr_factory_.GetWeakPtr()));
+ download_parameters->set_guid(guid);
download_manager->DownloadUrl(std::move(download_parameters));
}
- // DownloadItem::Observer overrides:
- void OnDownloadUpdated(DownloadItem* download_item) override {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
- auto iter = downloads_.find(download_item);
- DCHECK(iter != downloads_.end());
-
- scoped_refptr<BackgroundFetchRequestInfo> request = iter->second;
-
- switch (download_item->GetState()) {
- case DownloadItem::DownloadState::COMPLETE:
- request->PopulateResponseFromDownloadItemOnUI(download_item);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::Bind(&BackgroundFetchRequestInfo::SetResponseDataPopulated,
- request));
- download_item->RemoveObserver(this);
-
- // Inform the host about |host| having completed.
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::Bind(&BackgroundFetchDelegateProxy::DidCompleteRequest,
- io_parent_, std::move(request)));
-
- // Clear the local state for the |request|, it no longer is our concern.
- downloads_.erase(iter);
- break;
- case DownloadItem::DownloadState::CANCELLED:
- // TODO(harkness): Consider how we want to handle cancelled downloads.
- break;
- case DownloadItem::DownloadState::INTERRUPTED:
- // TODO(harkness): Just update the notification that it is paused.
- break;
- case DownloadItem::DownloadState::IN_PROGRESS:
- // TODO(harkness): If the download was previously paused, this should
- // now unpause the notification.
- break;
- case DownloadItem::DownloadState::MAX_DOWNLOAD_STATE:
- NOTREACHED();
- break;
+ private:
+ class DownloadItemObserver : public DownloadItem::Observer {
+ public:
+ explicit DownloadItemObserver(base::WeakPtr<Core> core) : core_(core) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
}
- }
- void OnDownloadDestroyed(DownloadItem* download_item) override {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- DCHECK_EQ(downloads_.count(download_item), 1u);
- downloads_.erase(download_item);
+ void OnDownloadUpdated(DownloadItem* download_item) override;
+ void OnDownloadDestroyed(DownloadItem* download_item) override;
- download_item->RemoveObserver(this);
- }
+ private:
+ base::WeakPtr<Core> core_;
+ };
- private:
- // Called when the download manager has started the given |request|. The
- // |download_item| continues to be owned by the download system. The
- // |interrupt_reason| will indicate when a request could not be started.
- void DidStartRequest(scoped_refptr<BackgroundFetchRequestInfo> request,
- DownloadItem* download_item,
+ // Called when the download manager has started a request. The |download_item|
+ // continues to be owned by the download system. The |interrupt_reason| will
+ // indicate when a request could not be started.
+ void DidStartRequest(DownloadItem* download_item,
DownloadInterruptReason interrupt_reason) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- DCHECK_EQ(interrupt_reason, DOWNLOAD_INTERRUPT_REASON_NONE);
- DCHECK(download_item);
- request->PopulateDownloadStateOnUI(download_item, interrupt_reason);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::Bind(&BackgroundFetchRequestInfo::SetDownloadStatePopulated,
- request));
-
- // TODO(peter): The above two DCHECKs are assumptions our implementation
+ // TODO(peter): These two DCHECKs are assumptions our implementation
// currently makes, but are not fit for production. We need to handle such
// failures gracefully.
+ DCHECK_EQ(interrupt_reason, DOWNLOAD_INTERRUPT_REASON_NONE);
+ DCHECK(download_item);
// Register for updates on the download's progress.
- download_item->AddObserver(this);
+ download_item->AddObserver(
+ new DownloadItemObserver(weak_ptr_factory_.GetWeakPtr()));
+
+ const std::string& guid = download_item->GetGuid();
- // Inform the host about the |request| having started.
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&BackgroundFetchDelegateProxy::DidStartRequest, io_parent_,
- request, download_item->GetGuid()));
-
- // Associate the |download_item| with the |request| so that we can retrieve
- // it's information when further updates happen.
- downloads_.insert(std::make_pair(download_item, std::move(request)));
+ base::BindOnce(&BackgroundFetchDelegateProxy::DidStartRequest,
+ io_parent_, guid,
+ base::MakeUnique<BackgroundFetchResponse>(
+ download_item->GetUrlChain(),
+ download_item->GetResponseHeaders())));
}
// Weak reference to the BackgroundFetchJobController instance that owns us.
base::WeakPtr<BackgroundFetchDelegateProxy> io_parent_;
- // The Background Fetch registration Id for which this request is being made.
- BackgroundFetchRegistrationId registration_id_;
-
// The BrowserContext that owns the JobController, and thereby us.
BrowserContext* browser_context_;
// The URL request context to use when issuing the requests.
scoped_refptr<net::URLRequestContextGetter> request_context_;
- // Map from DownloadItem* to the request info for the in-progress downloads.
- std::unordered_map<DownloadItem*, scoped_refptr<BackgroundFetchRequestInfo>>
- downloads_;
-
base::WeakPtrFactory<Core> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(Core);
};
+void BackgroundFetchDelegateProxy::Core::DownloadItemObserver::
+ OnDownloadUpdated(DownloadItem* download_item) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ if (!core_.get()) {
+ download_item->RemoveObserver(this);
+ delete this;
+ return;
+ }
+
+ switch (download_item->GetState()) {
+ case DownloadItem::DownloadState::COMPLETE:
+ // Inform the host about |host| having completed.
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&BackgroundFetchDelegateProxy::OnDownloadComplete,
+ core_->io_parent_, download_item->GetGuid(),
+ base::MakeUnique<BackgroundFetchResult>(
+ download_item->GetEndTime(),
+ download_item->GetTargetFilePath(),
+ download_item->GetReceivedBytes())));
+
+ download_item->RemoveObserver(this);
+ delete this;
+ // Cannot access this after deleting itself so return immediately.
+ return;
+ case DownloadItem::DownloadState::CANCELLED:
+ // TODO(harkness): Consider how we want to handle cancelled downloads.
+ break;
+ case DownloadItem::DownloadState::INTERRUPTED:
+ // TODO(harkness): Just update the notification that it is paused.
+ break;
+ case DownloadItem::DownloadState::IN_PROGRESS:
+ // TODO(harkness): If the download was previously paused, this should
+ // now unpause the notification.
+ break;
+ case DownloadItem::DownloadState::MAX_DOWNLOAD_STATE:
+ NOTREACHED();
+ break;
+ }
+}
+
+void BackgroundFetchDelegateProxy::Core::DownloadItemObserver::
+ OnDownloadDestroyed(DownloadItem* download_item) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ download_item->RemoveObserver(this);
+ delete this;
+}
+
BackgroundFetchDelegateProxy::BackgroundFetchDelegateProxy(
- BackgroundFetchJobController* job_controller,
- const BackgroundFetchRegistrationId& registration_id,
BrowserContext* browser_context,
scoped_refptr<net::URLRequestContextGetter> request_context)
- : job_controller_(job_controller),
- traffic_annotation_(
- net::DefineNetworkTrafficAnnotation("background_fetch_context", R"(
- semantics {
- sender: "Background Fetch API"
- description:
- "The Background Fetch API enables developers to upload or "
- "download files on behalf of the user. Such fetches will yield "
- "a user visible notification to inform the user of the "
- "operation, through which it can be suspended, resumed and/or "
- "cancelled. The developer retains control of the file once the "
- "fetch is completed, similar to XMLHttpRequest and other "
- "mechanisms for fetching resources using JavaScript."
- trigger:
- "When the website uses the Background Fetch API to request "
- "fetching a file and/or a list of files. This is a Web "
- "Platform API for which no express user permission is required."
- data:
- "The request headers and data as set by the website's "
- "developer."
- destination: WEBSITE
- }
- policy {
- cookies_allowed: true
- cookies_store: "user"
- setting: "This feature cannot be disabled in settings."
- policy_exception_justification: "Not implemented."
- })")),
- weak_ptr_factory_(this) {
+ : weak_ptr_factory_(this) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- ui_core_.reset(new Core(weak_ptr_factory_.GetWeakPtr(), registration_id,
- browser_context, request_context));
+ ui_core_.reset(new Core(weak_ptr_factory_.GetWeakPtr(), browser_context,
+ request_context));
// Get a WeakPtr over which we can talk to the |ui_core_|. Normally it
// would be unsafe to obtain a weak pointer on the IO thread from a
@@ -269,12 +263,18 @@ BackgroundFetchDelegateProxy::~BackgroundFetchDelegateProxy() {
}
void BackgroundFetchDelegateProxy::StartRequest(
+ BackgroundFetchJobController* job_controller,
scoped_refptr<BackgroundFetchRequestInfo> request) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(&Core::StartRequest, ui_core_ptr_,
- std::move(request), traffic_annotation_));
+ std::string guid(base::GenerateGUID());
+
+ controller_map_[guid] = std::make_pair(request, job_controller->GetWeakPtr());
+
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&Core::StartRequest, ui_core_ptr_, guid,
+ job_controller->registration_id().origin(), request));
}
void BackgroundFetchDelegateProxy::UpdateUI(const std::string& title) {
@@ -290,18 +290,33 @@ void BackgroundFetchDelegateProxy::Abort() {
}
void BackgroundFetchDelegateProxy::DidStartRequest(
- scoped_refptr<BackgroundFetchRequestInfo> request,
- const std::string& download_guid) {
+ const std::string& guid,
+ std::unique_ptr<BackgroundFetchResponse> response) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- job_controller_->DidStartRequest(request, download_guid);
+ scoped_refptr<BackgroundFetchRequestInfo> request_info;
+ base::WeakPtr<BackgroundFetchJobController> job_controller;
+ std::tie(request_info, job_controller) = controller_map_[guid];
+
+ request_info->PopulateWithResponse(std::move(response));
+
+ if (job_controller)
+ job_controller->DidStartRequest(request_info, guid);
}
-void BackgroundFetchDelegateProxy::DidCompleteRequest(
- scoped_refptr<BackgroundFetchRequestInfo> request) {
+void BackgroundFetchDelegateProxy::OnDownloadComplete(
+ const std::string& guid,
+ std::unique_ptr<BackgroundFetchResult> result) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- job_controller_->DidCompleteRequest(request);
+ scoped_refptr<BackgroundFetchRequestInfo> request_info;
+ base::WeakPtr<BackgroundFetchJobController> job_controller;
+ std::tie(request_info, job_controller) = controller_map_[guid];
+
+ request_info->SetResult(std::move(result));
+
+ if (job_controller)
+ job_controller->DidCompleteRequest(request_info);
}
} // namespace content
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 b0aebfa8717..9e2dd4e68d3 100644
--- a/chromium/content/browser/background_fetch/background_fetch_delegate_proxy.h
+++ b/chromium/content/browser/background_fetch/background_fetch_delegate_proxy.h
@@ -5,12 +5,15 @@
#ifndef CONTENT_BROWSER_BACKGROUND_FETCH_BACKGROUND_FETCH_DELEGATE_PROXY_H_
#define CONTENT_BROWSER_BACKGROUND_FETCH_BACKGROUND_FETCH_DELEGATE_PROXY_H_
+#include <map>
+#include <memory>
+#include <string>
+#include <utility>
+
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "content/browser/background_fetch/background_fetch_registration_id.h"
#include "content/browser/background_fetch/background_fetch_request_info.h"
#include "content/public/browser/browser_thread.h"
-#include "net/traffic_annotation/network_traffic_annotation.h"
namespace net {
class URLRequestContextGetter;
@@ -19,16 +22,15 @@ class URLRequestContextGetter;
namespace content {
class BackgroundFetchJobController;
+struct BackgroundFetchResponse;
class BrowserContext;
-// Proxy class for passing messages between BackgroundFetchJobController on the
-// IO thread to and BackgroundFetchDelegate on the UI thread.
+// Proxy class for passing messages between BackgroundFetchJobControllers on the
+// IO thread and BackgroundFetchDelegate on the UI thread.
// TODO(delphick): Create BackgroundFetchDelegate.
-class BackgroundFetchDelegateProxy {
+class CONTENT_EXPORT BackgroundFetchDelegateProxy {
public:
BackgroundFetchDelegateProxy(
- BackgroundFetchJobController* job_controller,
- const BackgroundFetchRegistrationId& registration_id,
BrowserContext* browser_context,
scoped_refptr<net::URLRequestContextGetter> request_context);
@@ -37,7 +39,8 @@ class BackgroundFetchDelegateProxy {
// Requests that the download manager start fetching |request|.
// Should only be called from the BackgroundFetchJobController (on the IO
// thread).
- void StartRequest(scoped_refptr<BackgroundFetchRequestInfo> request);
+ void StartRequest(BackgroundFetchJobController* job_controller,
+ scoped_refptr<BackgroundFetchRequestInfo> request);
// Updates the representation of this Background Fetch in the user interface
// to match the given |title|.
@@ -53,25 +56,24 @@ class BackgroundFetchDelegateProxy {
private:
class Core;
- // Called when the download manager has started the given |request|. The
- // |download_item| continues to be owned by the download system. The
- // |interrupt_reason| will indicate when a request could not be started.
- // Should only be called from the BackgroundFetchDelegate (on the IO thread).
- void DidStartRequest(scoped_refptr<BackgroundFetchRequestInfo> request,
- const std::string& download_guid);
+ // Called when the given download identified by |guid| has been completed.
+ // Should only be called on the IO thread.
+ void OnDownloadComplete(const std::string& guid,
+ std::unique_ptr<BackgroundFetchResult> result);
- // Called when the given |request| has been completed.
// Should only be called from the BackgroundFetchDelegate (on the IO thread).
- void DidCompleteRequest(scoped_refptr<BackgroundFetchRequestInfo> request);
-
- // Parent job controller that owns |this|.
- BackgroundFetchJobController* const job_controller_;
+ void DidStartRequest(const std::string& guid,
+ std::unique_ptr<BackgroundFetchResponse> response);
std::unique_ptr<Core, BrowserThread::DeleteOnUIThread> ui_core_;
base::WeakPtr<Core> ui_core_ptr_;
- // Traffic annotation for network request.
- const net::NetworkTrafficAnnotationTag traffic_annotation_;
+ // Map from DownloadService GUIDs to the RequestInfo and the JobController
+ // that started the download.
+ std::map<std::string,
+ std::pair<scoped_refptr<BackgroundFetchRequestInfo>,
+ base::WeakPtr<BackgroundFetchJobController>>>
+ controller_map_;
base::WeakPtrFactory<BackgroundFetchDelegateProxy> weak_ptr_factory_;
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 e5d4b165cd0..7542a7544a1 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
@@ -20,10 +20,10 @@ BackgroundFetchEmbeddedWorkerTestHelper::
~BackgroundFetchEmbeddedWorkerTestHelper() = default;
void BackgroundFetchEmbeddedWorkerTestHelper::OnBackgroundFetchAbortEvent(
- const std::string& tag,
+ const std::string& id,
mojom::ServiceWorkerEventDispatcher::
DispatchBackgroundFetchAbortEventCallback callback) {
- last_tag_ = tag;
+ last_id_ = id;
if (fail_abort_event_) {
std::move(callback).Run(SERVICE_WORKER_ERROR_EVENT_WAITUNTIL_REJECTED,
@@ -37,11 +37,11 @@ void BackgroundFetchEmbeddedWorkerTestHelper::OnBackgroundFetchAbortEvent(
}
void BackgroundFetchEmbeddedWorkerTestHelper::OnBackgroundFetchClickEvent(
- const std::string& tag,
+ const std::string& id,
mojom::BackgroundFetchState state,
mojom::ServiceWorkerEventDispatcher::
DispatchBackgroundFetchClickEventCallback callback) {
- last_tag_ = tag;
+ last_id_ = id;
last_state_ = state;
if (fail_click_event_) {
@@ -56,11 +56,11 @@ void BackgroundFetchEmbeddedWorkerTestHelper::OnBackgroundFetchClickEvent(
}
void BackgroundFetchEmbeddedWorkerTestHelper::OnBackgroundFetchFailEvent(
- const std::string& tag,
+ const std::string& id,
const std::vector<BackgroundFetchSettledFetch>& fetches,
mojom::ServiceWorkerEventDispatcher::
DispatchBackgroundFetchFailEventCallback callback) {
- last_tag_ = tag;
+ last_id_ = id;
last_fetches_ = fetches;
if (fail_fetch_fail_event_) {
@@ -75,11 +75,11 @@ void BackgroundFetchEmbeddedWorkerTestHelper::OnBackgroundFetchFailEvent(
}
void BackgroundFetchEmbeddedWorkerTestHelper::OnBackgroundFetchedEvent(
- const std::string& tag,
+ const std::string& id,
const std::vector<BackgroundFetchSettledFetch>& fetches,
mojom::ServiceWorkerEventDispatcher::DispatchBackgroundFetchedEventCallback
callback) {
- last_tag_ = tag;
+ last_id_ = id;
last_fetches_ = fetches;
if (fail_fetched_event_) {
diff --git a/chromium/content/browser/background_fetch/background_fetch_embedded_worker_test_helper.h b/chromium/content/browser/background_fetch/background_fetch_embedded_worker_test_helper.h
index 07abed7164c..4192f4b4cdb 100644
--- a/chromium/content/browser/background_fetch/background_fetch_embedded_worker_test_helper.h
+++ b/chromium/content/browser/background_fetch/background_fetch_embedded_worker_test_helper.h
@@ -50,7 +50,7 @@ class BackgroundFetchEmbeddedWorkerTestHelper
fetched_event_closure_ = closure;
}
- const base::Optional<std::string>& last_tag() const { return last_tag_; }
+ const base::Optional<std::string>& last_id() const { return last_id_; }
const base::Optional<mojom::BackgroundFetchState>& last_state() const {
return last_state_;
}
@@ -62,21 +62,21 @@ class BackgroundFetchEmbeddedWorkerTestHelper
protected:
// EmbeddedWorkerTestHelper overrides:
void OnBackgroundFetchAbortEvent(
- const std::string& tag,
+ const std::string& id,
mojom::ServiceWorkerEventDispatcher::
DispatchBackgroundFetchAbortEventCallback callback) override;
void OnBackgroundFetchClickEvent(
- const std::string& tag,
+ const std::string& id,
mojom::BackgroundFetchState state,
mojom::ServiceWorkerEventDispatcher::
DispatchBackgroundFetchClickEventCallback callback) override;
void OnBackgroundFetchFailEvent(
- const std::string& tag,
+ const std::string& id,
const std::vector<BackgroundFetchSettledFetch>& fetches,
mojom::ServiceWorkerEventDispatcher::
DispatchBackgroundFetchFailEventCallback callback) override;
void OnBackgroundFetchedEvent(
- const std::string& tag,
+ const std::string& id,
const std::vector<BackgroundFetchSettledFetch>& fetches,
mojom::ServiceWorkerEventDispatcher::
DispatchBackgroundFetchedEventCallback callback) override;
@@ -92,7 +92,7 @@ class BackgroundFetchEmbeddedWorkerTestHelper
base::Closure fetch_fail_event_closure_;
base::Closure fetched_event_closure_;
- base::Optional<std::string> last_tag_;
+ base::Optional<std::string> last_id_;
base::Optional<mojom::BackgroundFetchState> last_state_;
base::Optional<std::vector<BackgroundFetchSettledFetch>> last_fetches_;
diff --git a/chromium/content/browser/background_fetch/background_fetch_event_dispatcher.cc b/chromium/content/browser/background_fetch/background_fetch_event_dispatcher.cc
index 1de7fef1b8f..d694845718e 100644
--- a/chromium/content/browser/background_fetch/background_fetch_event_dispatcher.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_event_dispatcher.cc
@@ -64,8 +64,8 @@ void RecordFailureResult(ServiceWorkerMetrics::EventType event,
} // namespace
BackgroundFetchEventDispatcher::BackgroundFetchEventDispatcher(
- const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context)
- : service_worker_context_(service_worker_context) {
+ scoped_refptr<ServiceWorkerContextWrapper> service_worker_context)
+ : service_worker_context_(std::move(service_worker_context)) {
// Constructed on the UI thread, then lives on the IO thread.
DCHECK_CURRENTLY_ON(BrowserThread::UI);
}
@@ -83,16 +83,16 @@ void BackgroundFetchEventDispatcher::DispatchBackgroundFetchAbortEvent(
std::move(finished_closure),
base::Bind(
&BackgroundFetchEventDispatcher::DoDispatchBackgroundFetchAbortEvent,
- registration_id.tag()));
+ registration_id.id()));
}
void BackgroundFetchEventDispatcher::DoDispatchBackgroundFetchAbortEvent(
- const std::string& tag,
+ const std::string& id,
scoped_refptr<ServiceWorkerVersion> service_worker_version,
int request_id) {
DCHECK(service_worker_version);
service_worker_version->event_dispatcher()->DispatchBackgroundFetchAbortEvent(
- tag, service_worker_version->CreateSimpleEventCallback(request_id));
+ id, service_worker_version->CreateSimpleEventCallback(request_id));
}
void BackgroundFetchEventDispatcher::DispatchBackgroundFetchClickEvent(
@@ -105,18 +105,17 @@ void BackgroundFetchEventDispatcher::DispatchBackgroundFetchClickEvent(
std::move(finished_closure),
base::Bind(
&BackgroundFetchEventDispatcher::DoDispatchBackgroundFetchClickEvent,
- registration_id.tag(), state));
+ registration_id.id(), state));
}
void BackgroundFetchEventDispatcher::DoDispatchBackgroundFetchClickEvent(
- const std::string& tag,
+ const std::string& id,
mojom::BackgroundFetchState state,
scoped_refptr<ServiceWorkerVersion> service_worker_version,
int request_id) {
DCHECK(service_worker_version);
service_worker_version->event_dispatcher()->DispatchBackgroundFetchClickEvent(
- tag, state,
- service_worker_version->CreateSimpleEventCallback(request_id));
+ id, state, service_worker_version->CreateSimpleEventCallback(request_id));
}
void BackgroundFetchEventDispatcher::DispatchBackgroundFetchFailEvent(
@@ -129,17 +128,17 @@ void BackgroundFetchEventDispatcher::DispatchBackgroundFetchFailEvent(
std::move(finished_closure),
base::Bind(
&BackgroundFetchEventDispatcher::DoDispatchBackgroundFetchFailEvent,
- registration_id.tag(), fetches));
+ registration_id.id(), fetches));
}
void BackgroundFetchEventDispatcher::DoDispatchBackgroundFetchFailEvent(
- const std::string& tag,
+ const std::string& id,
const std::vector<BackgroundFetchSettledFetch>& fetches,
scoped_refptr<ServiceWorkerVersion> service_worker_version,
int request_id) {
DCHECK(service_worker_version);
service_worker_version->event_dispatcher()->DispatchBackgroundFetchFailEvent(
- tag, fetches,
+ id, fetches,
service_worker_version->CreateSimpleEventCallback(request_id));
}
@@ -153,17 +152,17 @@ void BackgroundFetchEventDispatcher::DispatchBackgroundFetchedEvent(
std::move(finished_closure),
base::Bind(
&BackgroundFetchEventDispatcher::DoDispatchBackgroundFetchedEvent,
- registration_id.tag(), fetches));
+ registration_id.id(), fetches));
}
void BackgroundFetchEventDispatcher::DoDispatchBackgroundFetchedEvent(
- const std::string& tag,
+ const std::string& id,
const std::vector<BackgroundFetchSettledFetch>& fetches,
scoped_refptr<ServiceWorkerVersion> service_worker_version,
int request_id) {
DCHECK(service_worker_version);
service_worker_version->event_dispatcher()->DispatchBackgroundFetchedEvent(
- tag, fetches,
+ id, fetches,
service_worker_version->CreateSimpleEventCallback(request_id));
}
@@ -197,9 +196,9 @@ void BackgroundFetchEventDispatcher::StartActiveWorkerForDispatch(
service_worker_version->RunAfterStartWorker(
event,
- base::Bind(&BackgroundFetchEventDispatcher::DispatchEvent, event,
- finished_closure, loaded_callback,
- make_scoped_refptr(service_worker_version)),
+ base::BindOnce(&BackgroundFetchEventDispatcher::DispatchEvent, event,
+ finished_closure, loaded_callback,
+ make_scoped_refptr(service_worker_version)),
base::Bind(&BackgroundFetchEventDispatcher::DidDispatchEvent, event,
finished_closure, DispatchPhase::STARTING));
}
diff --git a/chromium/content/browser/background_fetch/background_fetch_event_dispatcher.h b/chromium/content/browser/background_fetch/background_fetch_event_dispatcher.h
index 9d781ef7568..ab3d5c45b89 100644
--- a/chromium/content/browser/background_fetch/background_fetch_event_dispatcher.h
+++ b/chromium/content/browser/background_fetch/background_fetch_event_dispatcher.h
@@ -38,7 +38,7 @@ class CONTENT_EXPORT BackgroundFetchEventDispatcher {
};
explicit BackgroundFetchEventDispatcher(
- const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context);
+ scoped_refptr<ServiceWorkerContextWrapper> service_worker_context);
~BackgroundFetchEventDispatcher();
// Dispatches the `backgroundfetchabort` event, which indicates that an active
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 222dd93a1fd..b7c2128c7a8 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
@@ -19,8 +19,8 @@
namespace content {
namespace {
-const char kExampleTag[] = "my-tag";
-const char kExampleTag2[] = "my-second-tag";
+const char kExampleId[] = "my-id";
+const char kExampleId2[] = "my-second-id";
class BackgroundFetchEventDispatcherTest : public BackgroundFetchTestBase {
public:
@@ -37,7 +37,7 @@ class BackgroundFetchEventDispatcherTest : public BackgroundFetchTestBase {
TEST_F(BackgroundFetchEventDispatcherTest, DispatchInvalidRegistration) {
BackgroundFetchRegistrationId invalid_registration_id(
- 9042 /* random invalid id */, origin(), kExampleTag);
+ 9042 /* random invalid id */, origin(), kExampleId);
base::RunLoop run_loop;
event_dispatcher_.DispatchBackgroundFetchAbortEvent(invalid_registration_id,
@@ -55,7 +55,7 @@ TEST_F(BackgroundFetchEventDispatcherTest, DispatchInvalidRegistration) {
TEST_F(BackgroundFetchEventDispatcherTest, DispatchAbortEvent) {
BackgroundFetchRegistrationId registration_id;
- ASSERT_TRUE(CreateRegistrationId(kExampleTag, &registration_id));
+ ASSERT_TRUE(CreateRegistrationId(kExampleId, &registration_id));
{
base::RunLoop run_loop;
@@ -65,8 +65,8 @@ TEST_F(BackgroundFetchEventDispatcherTest, DispatchAbortEvent) {
run_loop.Run();
}
- ASSERT_TRUE(embedded_worker_test_helper()->last_tag().has_value());
- EXPECT_EQ(kExampleTag, embedded_worker_test_helper()->last_tag().value());
+ ASSERT_TRUE(embedded_worker_test_helper()->last_id().has_value());
+ EXPECT_EQ(kExampleId, embedded_worker_test_helper()->last_id().value());
histogram_tester_.ExpectUniqueSample(
"BackgroundFetch.EventDispatchResult.AbortEvent",
@@ -76,7 +76,7 @@ TEST_F(BackgroundFetchEventDispatcherTest, DispatchAbortEvent) {
BackgroundFetchRegistrationId second_registration_id(
registration_id.service_worker_registration_id(),
- registration_id.origin(), kExampleTag2);
+ registration_id.origin(), kExampleId2);
{
base::RunLoop run_loop;
@@ -86,8 +86,8 @@ TEST_F(BackgroundFetchEventDispatcherTest, DispatchAbortEvent) {
run_loop.Run();
}
- ASSERT_TRUE(embedded_worker_test_helper()->last_tag().has_value());
- EXPECT_EQ(kExampleTag2, embedded_worker_test_helper()->last_tag().value());
+ ASSERT_TRUE(embedded_worker_test_helper()->last_id().has_value());
+ EXPECT_EQ(kExampleId2, embedded_worker_test_helper()->last_id().value());
histogram_tester_.ExpectBucketCount(
"BackgroundFetch.EventDispatchResult.AbortEvent",
@@ -102,7 +102,7 @@ TEST_F(BackgroundFetchEventDispatcherTest, DispatchAbortEvent) {
TEST_F(BackgroundFetchEventDispatcherTest, DispatchClickEvent) {
BackgroundFetchRegistrationId registration_id;
- ASSERT_TRUE(CreateRegistrationId(kExampleTag, &registration_id));
+ ASSERT_TRUE(CreateRegistrationId(kExampleId, &registration_id));
{
base::RunLoop run_loop;
@@ -113,8 +113,8 @@ TEST_F(BackgroundFetchEventDispatcherTest, DispatchClickEvent) {
run_loop.Run();
}
- ASSERT_TRUE(embedded_worker_test_helper()->last_tag().has_value());
- EXPECT_EQ(kExampleTag, embedded_worker_test_helper()->last_tag().value());
+ ASSERT_TRUE(embedded_worker_test_helper()->last_id().has_value());
+ EXPECT_EQ(kExampleId, embedded_worker_test_helper()->last_id().value());
ASSERT_TRUE(embedded_worker_test_helper()->last_state().has_value());
EXPECT_EQ(mojom::BackgroundFetchState::PENDING,
@@ -128,7 +128,7 @@ TEST_F(BackgroundFetchEventDispatcherTest, DispatchClickEvent) {
BackgroundFetchRegistrationId second_registration_id(
registration_id.service_worker_registration_id(),
- registration_id.origin(), kExampleTag2);
+ registration_id.origin(), kExampleId2);
{
base::RunLoop run_loop;
@@ -139,8 +139,8 @@ TEST_F(BackgroundFetchEventDispatcherTest, DispatchClickEvent) {
run_loop.Run();
}
- ASSERT_TRUE(embedded_worker_test_helper()->last_tag().has_value());
- EXPECT_EQ(kExampleTag2, embedded_worker_test_helper()->last_tag().value());
+ ASSERT_TRUE(embedded_worker_test_helper()->last_id().has_value());
+ EXPECT_EQ(kExampleId2, embedded_worker_test_helper()->last_id().value());
ASSERT_TRUE(embedded_worker_test_helper()->last_state().has_value());
EXPECT_EQ(mojom::BackgroundFetchState::SUCCEEDED,
@@ -159,7 +159,7 @@ TEST_F(BackgroundFetchEventDispatcherTest, DispatchClickEvent) {
TEST_F(BackgroundFetchEventDispatcherTest, DispatchFailEvent) {
BackgroundFetchRegistrationId registration_id;
- ASSERT_TRUE(CreateRegistrationId(kExampleTag, &registration_id));
+ ASSERT_TRUE(CreateRegistrationId(kExampleId, &registration_id));
std::vector<BackgroundFetchSettledFetch> fetches;
fetches.push_back(BackgroundFetchSettledFetch());
@@ -172,8 +172,8 @@ TEST_F(BackgroundFetchEventDispatcherTest, DispatchFailEvent) {
run_loop.Run();
}
- ASSERT_TRUE(embedded_worker_test_helper()->last_tag().has_value());
- EXPECT_EQ(kExampleTag, embedded_worker_test_helper()->last_tag().value());
+ ASSERT_TRUE(embedded_worker_test_helper()->last_id().has_value());
+ EXPECT_EQ(kExampleId, embedded_worker_test_helper()->last_id().value());
ASSERT_TRUE(embedded_worker_test_helper()->last_fetches().has_value());
EXPECT_EQ(fetches.size(),
@@ -189,7 +189,7 @@ TEST_F(BackgroundFetchEventDispatcherTest, DispatchFailEvent) {
BackgroundFetchRegistrationId second_registration_id(
registration_id.service_worker_registration_id(),
- registration_id.origin(), kExampleTag2);
+ registration_id.origin(), kExampleId2);
{
base::RunLoop run_loop;
@@ -199,8 +199,8 @@ TEST_F(BackgroundFetchEventDispatcherTest, DispatchFailEvent) {
run_loop.Run();
}
- ASSERT_TRUE(embedded_worker_test_helper()->last_tag().has_value());
- EXPECT_EQ(kExampleTag2, embedded_worker_test_helper()->last_tag().value());
+ ASSERT_TRUE(embedded_worker_test_helper()->last_id().has_value());
+ EXPECT_EQ(kExampleId2, embedded_worker_test_helper()->last_id().value());
ASSERT_TRUE(embedded_worker_test_helper()->last_fetches().has_value());
EXPECT_EQ(fetches.size(),
@@ -219,7 +219,7 @@ TEST_F(BackgroundFetchEventDispatcherTest, DispatchFailEvent) {
TEST_F(BackgroundFetchEventDispatcherTest, DispatchFetchedEvent) {
BackgroundFetchRegistrationId registration_id;
- ASSERT_TRUE(CreateRegistrationId(kExampleTag, &registration_id));
+ ASSERT_TRUE(CreateRegistrationId(kExampleId, &registration_id));
std::vector<BackgroundFetchSettledFetch> fetches;
fetches.push_back(BackgroundFetchSettledFetch());
@@ -232,8 +232,8 @@ TEST_F(BackgroundFetchEventDispatcherTest, DispatchFetchedEvent) {
run_loop.Run();
}
- ASSERT_TRUE(embedded_worker_test_helper()->last_tag().has_value());
- EXPECT_EQ(kExampleTag, embedded_worker_test_helper()->last_tag().value());
+ ASSERT_TRUE(embedded_worker_test_helper()->last_id().has_value());
+ EXPECT_EQ(kExampleId, embedded_worker_test_helper()->last_id().value());
ASSERT_TRUE(embedded_worker_test_helper()->last_fetches().has_value());
EXPECT_EQ(fetches.size(),
@@ -249,7 +249,7 @@ TEST_F(BackgroundFetchEventDispatcherTest, DispatchFetchedEvent) {
BackgroundFetchRegistrationId second_registration_id(
registration_id.service_worker_registration_id(),
- registration_id.origin(), kExampleTag2);
+ registration_id.origin(), kExampleId2);
{
base::RunLoop run_loop;
@@ -259,8 +259,8 @@ TEST_F(BackgroundFetchEventDispatcherTest, DispatchFetchedEvent) {
run_loop.Run();
}
- ASSERT_TRUE(embedded_worker_test_helper()->last_tag().has_value());
- EXPECT_EQ(kExampleTag2, embedded_worker_test_helper()->last_tag().value());
+ ASSERT_TRUE(embedded_worker_test_helper()->last_id().has_value());
+ EXPECT_EQ(kExampleId2, embedded_worker_test_helper()->last_id().value());
ASSERT_TRUE(embedded_worker_test_helper()->last_fetches().has_value());
EXPECT_EQ(fetches.size(),
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 9165857ec4e..eb0523dddc9 100644
--- a/chromium/content/browser/background_fetch/background_fetch_job_controller.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_job_controller.cc
@@ -4,24 +4,24 @@
#include "content/browser/background_fetch/background_fetch_job_controller.h"
+#include <utility>
+
#include "base/memory/ptr_util.h"
#include "content/browser/background_fetch/background_fetch_data_manager.h"
#include "content/public/browser/browser_thread.h"
-#include "net/url_request/url_request_context_getter.h"
namespace content {
BackgroundFetchJobController::BackgroundFetchJobController(
+ BackgroundFetchDelegateProxy* delegate_proxy,
const BackgroundFetchRegistrationId& registration_id,
const BackgroundFetchOptions& options,
BackgroundFetchDataManager* data_manager,
- BrowserContext* browser_context,
- scoped_refptr<net::URLRequestContextGetter> request_context,
CompletedCallback completed_callback)
: registration_id_(registration_id),
options_(options),
data_manager_(data_manager),
- delegate_proxy_(this, registration_id, browser_context, request_context),
+ delegate_proxy_(delegate_proxy),
completed_callback_(std::move(completed_callback)),
weak_ptr_factory_(this) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -29,7 +29,7 @@ BackgroundFetchJobController::BackgroundFetchJobController(
BackgroundFetchJobController::~BackgroundFetchJobController() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
-};
+}
void BackgroundFetchJobController::Start() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -59,7 +59,7 @@ void BackgroundFetchJobController::StartRequest(
return;
}
- delegate_proxy_.StartRequest(request);
+ delegate_proxy_->StartRequest(this, request);
}
void BackgroundFetchJobController::DidStartRequest(
@@ -105,7 +105,7 @@ void BackgroundFetchJobController::DidMarkRequestCompleted(
void BackgroundFetchJobController::UpdateUI(const std::string& title) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- delegate_proxy_.UpdateUI(title);
+ delegate_proxy_->UpdateUI(title);
}
void BackgroundFetchJobController::Abort() {
@@ -120,7 +120,7 @@ void BackgroundFetchJobController::Abort() {
return; // Ignore attempt to abort after completion/abort.
}
- delegate_proxy_.Abort();
+ delegate_proxy_->Abort();
state_ = State::ABORTED;
// Inform the owner of the controller about the job having aborted.
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 f9867e7b68a..7c39aad9c6e 100644
--- a/chromium/content/browser/background_fetch/background_fetch_job_controller.h
+++ b/chromium/content/browser/background_fetch/background_fetch_job_controller.h
@@ -19,14 +19,9 @@
#include "content/common/content_export.h"
#include "content/public/browser/browser_thread.h"
-namespace net {
-class URLRequestContextGetter;
-}
-
namespace content {
class BackgroundFetchDataManager;
-class BrowserContext;
// The JobController will be responsible for coordinating communication with the
// DownloadManager. It will get requests from the DataManager and dispatch them
@@ -39,11 +34,10 @@ class CONTENT_EXPORT BackgroundFetchJobController {
base::OnceCallback<void(BackgroundFetchJobController*)>;
BackgroundFetchJobController(
+ BackgroundFetchDelegateProxy* delegate_proxy,
const BackgroundFetchRegistrationId& registration_id,
const BackgroundFetchOptions& options,
BackgroundFetchDataManager* data_manager,
- BrowserContext* browser_context,
- scoped_refptr<net::URLRequestContextGetter> request_context,
CompletedCallback completed_callback);
~BackgroundFetchJobController();
@@ -69,6 +63,10 @@ class CONTENT_EXPORT BackgroundFetchJobController {
// Returns the options with which this job is fetching data.
const BackgroundFetchOptions& options() const { return options_; }
+ base::WeakPtr<BackgroundFetchJobController> GetWeakPtr() {
+ return weak_ptr_factory_.GetWeakPtr();
+ }
+
// Called when the given |request| has started fetching, after having been
// assigned the |download_guid| by the download system.
void DidStartRequest(scoped_refptr<BackgroundFetchRequestInfo> request,
@@ -98,8 +96,8 @@ class CONTENT_EXPORT BackgroundFetchJobController {
BackgroundFetchDataManager* data_manager_;
// Proxy for interacting with the BackgroundFetchDelegate across thread
- // boundaries.
- BackgroundFetchDelegateProxy delegate_proxy_;
+ // boundaries. It is owned by the BackgroundFetchContext.
+ BackgroundFetchDelegateProxy* delegate_proxy_;
// Callback for when all fetches have been completed.
CompletedCallback completed_callback_;
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 c73cae1aac5..9ac670cf488 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
@@ -4,9 +4,12 @@
#include "content/browser/background_fetch/background_fetch_job_controller.h"
+#include <map>
#include <memory>
#include <string>
#include <unordered_map>
+#include <utility>
+#include <vector>
#include "base/guid.h"
#include "base/macros.h"
@@ -15,6 +18,7 @@
#include "content/browser/background_fetch/background_fetch_data_manager.h"
#include "content/browser/background_fetch/background_fetch_registration_id.h"
#include "content/browser/background_fetch/background_fetch_test_base.h"
+#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/download_item.h"
#include "content/public/browser/storage_partition.h"
@@ -32,7 +36,9 @@ const char kExampleTag[] = "my-example-tag";
class BackgroundFetchJobControllerTest : public BackgroundFetchTestBase {
public:
- BackgroundFetchJobControllerTest() : data_manager_(browser_context()) {}
+ BackgroundFetchJobControllerTest()
+ : data_manager_(browser_context(),
+ embedded_worker_test_helper()->context_wrapper()) {}
~BackgroundFetchJobControllerTest() override = default;
// Creates a new Background Fetch registration, whose id will be stored in
@@ -81,10 +87,13 @@ class BackgroundFetchJobControllerTest : public BackgroundFetchTestBase {
StoragePartition* storage_partition =
BrowserContext::GetDefaultStoragePartition(browser_context());
- return base::MakeUnique<BackgroundFetchJobController>(
- registration_id, BackgroundFetchOptions(), &data_manager_,
+ delegate_proxy_.reset(new BackgroundFetchDelegateProxy(
browser_context(),
- make_scoped_refptr(storage_partition->GetURLRequestContext()),
+ make_scoped_refptr(storage_partition->GetURLRequestContext())));
+
+ return base::MakeUnique<BackgroundFetchJobController>(
+ delegate_proxy_.get(), registration_id, BackgroundFetchOptions(),
+ &data_manager_,
base::BindOnce(&BackgroundFetchJobControllerTest::DidCompleteJob,
base::Unretained(this)));
}
@@ -97,6 +106,8 @@ class BackgroundFetchJobControllerTest : public BackgroundFetchTestBase {
// available jobs. Enables use of a run loop for deterministic waits.
base::OnceClosure job_completed_closure_;
+ std::unique_ptr<BackgroundFetchDelegateProxy> delegate_proxy_;
+
private:
void DidCreateRegistration(blink::mojom::BackgroundFetchError* out_error,
const base::Closure& quit_closure,
diff --git a/chromium/content/browser/background_fetch/background_fetch_registration_id.cc b/chromium/content/browser/background_fetch/background_fetch_registration_id.cc
index db7653bbb1b..02d5a6ea054 100644
--- a/chromium/content/browser/background_fetch/background_fetch_registration_id.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_registration_id.cc
@@ -16,10 +16,10 @@ BackgroundFetchRegistrationId::BackgroundFetchRegistrationId()
BackgroundFetchRegistrationId::BackgroundFetchRegistrationId(
int64_t service_worker_registration_id,
const url::Origin& origin,
- const std::string& tag)
+ const std::string& id)
: service_worker_registration_id_(service_worker_registration_id),
origin_(origin),
- tag_(tag) {}
+ id_(id) {}
BackgroundFetchRegistrationId::BackgroundFetchRegistrationId(
const BackgroundFetchRegistrationId& other) = default;
@@ -36,7 +36,7 @@ bool BackgroundFetchRegistrationId::operator==(
const BackgroundFetchRegistrationId& other) const {
return other.service_worker_registration_id_ ==
service_worker_registration_id_ &&
- other.origin_ == origin_ && other.tag_ == tag_;
+ other.origin_ == origin_ && other.id_ == id_;
}
bool BackgroundFetchRegistrationId::operator!=(
@@ -46,9 +46,9 @@ bool BackgroundFetchRegistrationId::operator!=(
bool BackgroundFetchRegistrationId::operator<(
const BackgroundFetchRegistrationId& other) const {
- return std::tie(service_worker_registration_id_, origin_, tag_) <
+ return std::tie(service_worker_registration_id_, origin_, id_) <
std::tie(other.service_worker_registration_id_, other.origin_,
- other.tag_);
+ other.id_);
}
bool BackgroundFetchRegistrationId::is_null() const {
diff --git a/chromium/content/browser/background_fetch/background_fetch_registration_id.h b/chromium/content/browser/background_fetch/background_fetch_registration_id.h
index 32fb5da8145..7552f204b97 100644
--- a/chromium/content/browser/background_fetch/background_fetch_registration_id.h
+++ b/chromium/content/browser/background_fetch/background_fetch_registration_id.h
@@ -20,7 +20,7 @@ class CONTENT_EXPORT BackgroundFetchRegistrationId {
BackgroundFetchRegistrationId();
BackgroundFetchRegistrationId(int64_t service_worker_registration_id,
const url::Origin& origin,
- const std::string& tag);
+ const std::string& id);
BackgroundFetchRegistrationId(const BackgroundFetchRegistrationId& other);
BackgroundFetchRegistrationId(BackgroundFetchRegistrationId&& other);
~BackgroundFetchRegistrationId();
@@ -43,12 +43,12 @@ class CONTENT_EXPORT BackgroundFetchRegistrationId {
return service_worker_registration_id_;
}
const url::Origin& origin() const { return origin_; }
- const std::string& tag() const { return tag_; }
+ const std::string& id() const { return id_; }
private:
int64_t service_worker_registration_id_;
url::Origin origin_;
- std::string tag_;
+ std::string id_;
};
} // namespace content
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 0f23af18e1a..bf5cfdc39df 100644
--- a/chromium/content/browser/background_fetch/background_fetch_request_info.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_request_info.cc
@@ -4,10 +4,9 @@
#include "content/browser/background_fetch/background_fetch_request_info.h"
-#include <string>
-
#include "base/strings/string_util.h"
#include "base/threading/sequenced_task_runner_handle.h"
+#include "content/browser/background_fetch/background_fetch_response.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/download_item.h"
#include "net/http/http_response_headers.h"
@@ -26,93 +25,68 @@ BackgroundFetchRequestInfo::~BackgroundFetchRequestInfo() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
}
-void BackgroundFetchRequestInfo::PopulateDownloadStateOnUI(
- DownloadItem* download_item,
- DownloadInterruptReason download_interrupt_reason) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- DCHECK(!download_state_populated_);
+void BackgroundFetchRequestInfo::PopulateWithResponse(
+ std::unique_ptr<const BackgroundFetchResponse> response) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
- download_guid_ = download_item->GetGuid();
- download_state_ = download_item->GetState();
+ url_chain_ = response->url_chain;
// The response code, text and headers all are stored in the
// net::HttpResponseHeaders object, shared by the |download_item|.
- if (download_item->GetResponseHeaders()) {
- const auto& headers = download_item->GetResponseHeaders();
-
- response_code_ = headers->response_code();
- response_text_ = headers->GetStatusText();
+ response_code_ = response->headers->response_code();
+ response_text_ = response->headers->GetStatusText();
- size_t iter = 0;
- std::string name, value;
+ size_t iter = 0;
+ std::string name, value;
- while (headers->EnumerateHeaderLines(&iter, &name, &value))
- response_headers_[base::ToLowerASCII(name)] = value;
- }
+ while (response->headers->EnumerateHeaderLines(&iter, &name, &value))
+ response_headers_[base::ToLowerASCII(name)] = value;
}
-void BackgroundFetchRequestInfo::SetDownloadStatePopulated() {
+void BackgroundFetchRequestInfo::SetResult(
+ std::unique_ptr<const BackgroundFetchResult> result) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- download_state_populated_ = true;
-}
-
-void BackgroundFetchRequestInfo::PopulateResponseFromDownloadItemOnUI(
- DownloadItem* download_item) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- DCHECK(!response_data_populated_);
- url_chain_ = download_item->GetUrlChain();
- file_path_ = download_item->GetTargetFilePath();
- file_size_ = download_item->GetReceivedBytes();
- response_time_ = download_item->GetEndTime();
-}
-
-void BackgroundFetchRequestInfo::SetResponseDataPopulated() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- response_data_populated_ = true;
+ result_ = std::move(result);
}
int BackgroundFetchRequestInfo::GetResponseCode() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DCHECK(download_state_populated_);
return response_code_;
}
const std::string& BackgroundFetchRequestInfo::GetResponseText() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DCHECK(download_state_populated_);
return response_text_;
}
const std::map<std::string, std::string>&
BackgroundFetchRequestInfo::GetResponseHeaders() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DCHECK(download_state_populated_);
return response_headers_;
}
const std::vector<GURL>& BackgroundFetchRequestInfo::GetURLChain() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DCHECK(response_data_populated_);
return url_chain_;
}
const base::FilePath& BackgroundFetchRequestInfo::GetFilePath() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DCHECK(response_data_populated_);
- return file_path_;
+ DCHECK(result_);
+ return result_->file_path;
}
int64_t BackgroundFetchRequestInfo::GetFileSize() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DCHECK(response_data_populated_);
- return file_size_;
+ DCHECK(result_);
+ return result_->file_size;
}
const base::Time& BackgroundFetchRequestInfo::GetResponseTime() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DCHECK(response_data_populated_);
- return response_time_;
+ DCHECK(result_);
+ return result_->response_time;
}
} // namespace content
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 f0b95fe289c..a76a400d8fb 100644
--- a/chromium/content/browser/background_fetch/background_fetch_request_info.h
+++ b/chromium/content/browser/background_fetch/background_fetch_request_info.h
@@ -2,10 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_BROWSER_BACKGROUND_FETCH_REQUEST_INFO_H_
-#define CONTENT_BROWSER_BACKGROUND_FETCH_REQUEST_INFO_H_
+#ifndef CONTENT_BROWSER_BACKGROUND_FETCH_BACKGROUND_FETCH_REQUEST_INFO_H_
+#define CONTENT_BROWSER_BACKGROUND_FETCH_BACKGROUND_FETCH_REQUEST_INFO_H_
+#include <map>
#include <memory>
+#include <string>
#include <vector>
#include "base/files/file_path.h"
@@ -14,16 +16,14 @@
#include "base/sequence_checker.h"
#include "base/time/time.h"
#include "content/browser/background_fetch/background_fetch_constants.h"
+#include "content/browser/background_fetch/background_fetch_response.h"
#include "content/common/content_export.h"
#include "content/common/service_worker/service_worker_types.h"
-#include "content/public/browser/download_interrupt_reasons.h"
#include "content/public/browser/download_item.h"
#include "url/gurl.h"
namespace content {
-class DownloadItem;
-
// Simple class to encapsulate the components of a fetch request.
// TODO(peter): This can likely change to have a single owner, and thus become
// an std::unique_ptr<>, when persistent storage has been implemented.
@@ -33,18 +33,11 @@ class CONTENT_EXPORT BackgroundFetchRequestInfo
BackgroundFetchRequestInfo(int request_index,
const ServiceWorkerFetchRequest& fetch_request);
- // Populates the cached state for the in-progress |download_item|.
- void PopulateDownloadStateOnUI(
- DownloadItem* download_item,
- DownloadInterruptReason download_interrupt_reason);
-
- void SetDownloadStatePopulated();
-
- // Populates the response portion of this object from the information made
- // available in the |download_item|.
- void PopulateResponseFromDownloadItemOnUI(DownloadItem* download_item);
+ // Populates the cached state for the in-progress download.
+ void PopulateWithResponse(
+ std::unique_ptr<const BackgroundFetchResponse> response);
- void SetResponseDataPopulated();
+ void SetResult(std::unique_ptr<const BackgroundFetchResult> result);
// Returns the index of this request within a Background Fetch registration.
int request_index() const { return request_index_; }
@@ -91,26 +84,16 @@ class CONTENT_EXPORT BackgroundFetchRequestInfo
ServiceWorkerFetchRequest fetch_request_;
// ---- Data associated with the in-progress download ------------------------
-
- // Indicates whether download progress data has been populated.
- bool download_state_populated_ = false;
-
std::string download_guid_;
DownloadItem::DownloadState download_state_ = DownloadItem::IN_PROGRESS;
int response_code_ = 0;
std::string response_text_;
std::map<std::string, std::string> response_headers_;
+ std::vector<GURL> url_chain_;
// ---- Data associated with the response ------------------------------------
-
- // Indicates whether response data has been populated.
- bool response_data_populated_ = false;
-
- std::vector<GURL> url_chain_;
- base::FilePath file_path_;
- int64_t file_size_ = 0;
- base::Time response_time_;
+ std::unique_ptr<const BackgroundFetchResult> result_;
SEQUENCE_CHECKER(sequence_checker_);
@@ -119,4 +102,4 @@ class CONTENT_EXPORT BackgroundFetchRequestInfo
} // namespace content
-#endif // CONTENT_BROWSER_BACKGROUND_FETCH_REQUEST_INFO_H_
+#endif // CONTENT_BROWSER_BACKGROUND_FETCH_BACKGROUND_FETCH_REQUEST_INFO_H_
diff --git a/chromium/content/browser/background_fetch/background_fetch_response.cc b/chromium/content/browser/background_fetch/background_fetch_response.cc
new file mode 100644
index 00000000000..73c7a7f228e
--- /dev/null
+++ b/chromium/content/browser/background_fetch/background_fetch_response.cc
@@ -0,0 +1,23 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/background_fetch/background_fetch_response.h"
+
+namespace content {
+
+BackgroundFetchResponse::BackgroundFetchResponse(
+ const std::vector<GURL>& url_chain,
+ const scoped_refptr<const net::HttpResponseHeaders>& headers)
+ : url_chain(url_chain), headers(headers) {}
+
+BackgroundFetchResponse::~BackgroundFetchResponse() {}
+
+BackgroundFetchResult::BackgroundFetchResult(base::Time response_time,
+ const base::FilePath& path,
+ uint64_t size)
+ : response_time(response_time), file_path(path), file_size(size) {}
+
+BackgroundFetchResult::~BackgroundFetchResult() {}
+
+} // namespace content
diff --git a/chromium/content/browser/background_fetch/background_fetch_response.h b/chromium/content/browser/background_fetch/background_fetch_response.h
new file mode 100644
index 00000000000..a15c786ecce
--- /dev/null
+++ b/chromium/content/browser/background_fetch/background_fetch_response.h
@@ -0,0 +1,50 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_BACKGROUND_FETCH_BACKGROUND_FETCH_RESPONSE_H_
+#define CONTENT_BROWSER_BACKGROUND_FETCH_BACKGROUND_FETCH_RESPONSE_H_
+
+#include <vector>
+
+#include "base/files/file_path.h"
+#include "base/time/time.h"
+#include "content/common/content_export.h"
+#include "net/http/http_response_headers.h"
+#include "url/gurl.h"
+
+namespace content {
+
+// Contains the response after a background fetch has started.
+struct CONTENT_EXPORT BackgroundFetchResponse {
+ BackgroundFetchResponse(
+ const std::vector<GURL>& url_chain,
+ const scoped_refptr<const net::HttpResponseHeaders>& headers);
+
+ ~BackgroundFetchResponse();
+
+ const std::vector<GURL> url_chain;
+ const scoped_refptr<const net::HttpResponseHeaders> headers;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(BackgroundFetchResponse);
+};
+
+struct CONTENT_EXPORT BackgroundFetchResult {
+ BackgroundFetchResult(base::Time response_time,
+ const base::FilePath& path,
+ uint64_t size);
+
+ ~BackgroundFetchResult();
+
+ const base::Time response_time;
+ const base::FilePath file_path;
+ const uint64_t file_size;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(BackgroundFetchResult);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_BACKGROUND_FETCH_BACKGROUND_FETCH_RESPONSE_H_
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 e3c53375424..a65b82d9e44 100644
--- a/chromium/content/browser/background_fetch/background_fetch_service_impl.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_service_impl.cc
@@ -22,8 +22,8 @@ namespace content {
namespace {
-// Maximum length of a developer-provided tag for a Background Fetch.
-constexpr size_t kMaxTagLength = 1024 * 1024;
+// Maximum length of a developer-provided id for a Background Fetch.
+constexpr size_t kMaxIdLength = 1024 * 1024;
// Maximum length of a developer-provided title for a Background Fetch.
constexpr size_t kMaxTitleLength = 1024 * 1024;
@@ -57,12 +57,12 @@ BackgroundFetchServiceImpl::~BackgroundFetchServiceImpl() {
void BackgroundFetchServiceImpl::Fetch(
int64_t service_worker_registration_id,
const url::Origin& origin,
- const std::string& tag,
+ const std::string& id,
const std::vector<ServiceWorkerFetchRequest>& requests,
const BackgroundFetchOptions& options,
FetchCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (!ValidateTag(tag)) {
+ if (!ValidateId(id)) {
std::move(callback).Run(
blink::mojom::BackgroundFetchError::INVALID_ARGUMENT,
base::nullopt /* registration */);
@@ -77,7 +77,7 @@ void BackgroundFetchServiceImpl::Fetch(
}
BackgroundFetchRegistrationId registration_id(service_worker_registration_id,
- origin, tag);
+ origin, id);
background_fetch_context_->StartFetch(registration_id, requests, options,
std::move(callback));
@@ -86,11 +86,11 @@ void BackgroundFetchServiceImpl::Fetch(
void BackgroundFetchServiceImpl::UpdateUI(
int64_t service_worker_registration_id,
const url::Origin& origin,
- const std::string& tag,
+ const std::string& id,
const std::string& title,
UpdateUICallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (!ValidateTag(tag) || !ValidateTitle(title)) {
+ if (!ValidateId(id) || !ValidateTitle(title)) {
std::move(callback).Run(
blink::mojom::BackgroundFetchError::INVALID_ARGUMENT);
return;
@@ -98,22 +98,22 @@ void BackgroundFetchServiceImpl::UpdateUI(
BackgroundFetchJobController* controller =
background_fetch_context_->GetActiveFetch(BackgroundFetchRegistrationId(
- service_worker_registration_id, origin, tag));
+ service_worker_registration_id, origin, id));
if (controller)
controller->UpdateUI(title);
- std::move(callback).Run(
- controller ? blink::mojom::BackgroundFetchError::NONE
- : blink::mojom::BackgroundFetchError::INVALID_TAG);
+ std::move(callback).Run(controller
+ ? blink::mojom::BackgroundFetchError::NONE
+ : blink::mojom::BackgroundFetchError::INVALID_ID);
}
void BackgroundFetchServiceImpl::Abort(int64_t service_worker_registration_id,
const url::Origin& origin,
- const std::string& tag,
+ const std::string& id,
AbortCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (!ValidateTag(tag)) {
+ if (!ValidateId(id)) {
std::move(callback).Run(
blink::mojom::BackgroundFetchError::INVALID_ARGUMENT);
return;
@@ -121,23 +121,23 @@ void BackgroundFetchServiceImpl::Abort(int64_t service_worker_registration_id,
BackgroundFetchJobController* controller =
background_fetch_context_->GetActiveFetch(BackgroundFetchRegistrationId(
- service_worker_registration_id, origin, tag));
+ service_worker_registration_id, origin, id));
if (controller)
controller->Abort();
- std::move(callback).Run(
- controller ? blink::mojom::BackgroundFetchError::NONE
- : blink::mojom::BackgroundFetchError::INVALID_TAG);
+ std::move(callback).Run(controller
+ ? blink::mojom::BackgroundFetchError::NONE
+ : blink::mojom::BackgroundFetchError::INVALID_ID);
}
void BackgroundFetchServiceImpl::GetRegistration(
int64_t service_worker_registration_id,
const url::Origin& origin,
- const std::string& tag,
+ const std::string& id,
GetRegistrationCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (!ValidateTag(tag)) {
+ if (!ValidateId(id)) {
std::move(callback).Run(
blink::mojom::BackgroundFetchError::INVALID_ARGUMENT,
base::nullopt /* registration */);
@@ -146,10 +146,10 @@ void BackgroundFetchServiceImpl::GetRegistration(
BackgroundFetchJobController* controller =
background_fetch_context_->GetActiveFetch(BackgroundFetchRegistrationId(
- service_worker_registration_id, origin, tag));
+ service_worker_registration_id, origin, id));
if (!controller) {
- std::move(callback).Run(blink::mojom::BackgroundFetchError::INVALID_TAG,
+ std::move(callback).Run(blink::mojom::BackgroundFetchError::INVALID_ID,
base::nullopt /* registration */);
return;
}
@@ -157,7 +157,7 @@ void BackgroundFetchServiceImpl::GetRegistration(
// Compile the BackgroundFetchRegistration object that will be given to the
// developer, representing the data associated with the |controller|.
BackgroundFetchRegistration registration;
- registration.tag = controller->registration_id().tag();
+ registration.id = controller->registration_id().id();
registration.icons = controller->options().icons;
registration.title = controller->options().title;
registration.total_download_size = controller->options().total_download_size;
@@ -166,20 +166,20 @@ void BackgroundFetchServiceImpl::GetRegistration(
registration);
}
-void BackgroundFetchServiceImpl::GetTags(int64_t service_worker_registration_id,
- const url::Origin& origin,
- GetTagsCallback callback) {
+void BackgroundFetchServiceImpl::GetIds(int64_t service_worker_registration_id,
+ const url::Origin& origin,
+ GetIdsCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
std::move(callback).Run(
blink::mojom::BackgroundFetchError::NONE,
- background_fetch_context_->GetActiveTagsForServiceWorkerRegistration(
+ background_fetch_context_->GetActiveIdsForServiceWorkerRegistration(
service_worker_registration_id, origin));
}
-bool BackgroundFetchServiceImpl::ValidateTag(const std::string& tag) {
- if (tag.empty() || tag.size() > kMaxTagLength) {
+bool BackgroundFetchServiceImpl::ValidateId(const std::string& id) {
+ if (id.empty() || id.size() > kMaxIdLength) {
bad_message::ReceivedBadMessage(render_process_id_,
- bad_message::BFSI_INVALID_TAG);
+ bad_message::BFSI_INVALID_ID);
return false;
}
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 2fcf66a2672..b675c504a08 100644
--- a/chromium/content/browser/background_fetch/background_fetch_service_impl.h
+++ b/chromium/content/browser/background_fetch/background_fetch_service_impl.h
@@ -41,31 +41,31 @@ class CONTENT_EXPORT BackgroundFetchServiceImpl
// blink::mojom::BackgroundFetchService implementation.
void Fetch(int64_t service_worker_registration_id,
const url::Origin& origin,
- const std::string& tag,
+ const std::string& id,
const std::vector<ServiceWorkerFetchRequest>& requests,
const BackgroundFetchOptions& options,
FetchCallback callback) override;
void UpdateUI(int64_t service_worker_registration_id,
const url::Origin& origin,
- const std::string& tag,
+ const std::string& id,
const std::string& title,
UpdateUICallback callback) override;
void Abort(int64_t service_worker_registration_id,
const url::Origin& origin,
- const std::string& tag,
+ const std::string& id,
AbortCallback callback) override;
void GetRegistration(int64_t service_worker_registration_id,
const url::Origin& origin,
- const std::string& tag,
+ const std::string& id,
GetRegistrationCallback callback) override;
- void GetTags(int64_t service_worker_registration_id,
- const url::Origin& origin,
- GetTagsCallback callback) override;
+ void GetIds(int64_t service_worker_registration_id,
+ const url::Origin& origin,
+ GetIdsCallback callback) override;
private:
- // Validates and returns whether the |tag| contains a valid value. The
+ // Validates and returns whether the |id| contains a valid value. The
// renderer will be flagged for having send a bad message if it isn't.
- bool ValidateTag(const std::string& tag) WARN_UNUSED_RESULT;
+ bool ValidateId(const std::string& id) WARN_UNUSED_RESULT;
// Validates and returns whether |requests| contains at least a valid request.
// The renderer will be flagged for having send a bad message if it isn't.
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 4f405523182..64ba83163f8 100644
--- a/chromium/content/browser/background_fetch/background_fetch_service_unittest.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_service_unittest.cc
@@ -18,12 +18,13 @@
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/storage_partition_impl.h"
#include "content/common/service_worker/service_worker_types.h"
+#include "services/network/public/interfaces/fetch_api.mojom.h"
namespace content {
namespace {
-const char kExampleTag[] = "my-background-fetch";
-const char kAlternativeTag[] = "my-alternative-fetch";
+const char kExampleId[] = "my-background-fetch";
+const char kAlternativeId[] = "my-alternative-fetch";
IconDefinition CreateIcon(std::string src,
std::string sizes,
@@ -52,12 +53,12 @@ class BackgroundFetchServiceTest : public BackgroundFetchTestBase {
DCHECK(out_registration);
base::RunLoop run_loop;
- service_->Fetch(registration_id.service_worker_registration_id(),
- registration_id.origin(), registration_id.tag(), requests,
- options,
- base::Bind(&BackgroundFetchServiceTest::DidGetRegistration,
- base::Unretained(this), run_loop.QuitClosure(),
- out_error, out_registration));
+ service_->Fetch(
+ registration_id.service_worker_registration_id(),
+ registration_id.origin(), registration_id.id(), requests, options,
+ base::BindOnce(&BackgroundFetchServiceTest::DidGetRegistration,
+ base::Unretained(this), run_loop.QuitClosure(),
+ out_error, out_registration));
run_loop.Run();
}
@@ -72,11 +73,11 @@ class BackgroundFetchServiceTest : public BackgroundFetchTestBase {
DCHECK(out_error);
base::RunLoop run_loop;
- service_->Abort(
- registration_id.service_worker_registration_id(),
- registration_id.origin(), registration_id.tag(),
- base::Bind(&BackgroundFetchServiceTest::DidAbort,
- base::Unretained(this), run_loop.QuitClosure(), out_error));
+ service_->Abort(registration_id.service_worker_registration_id(),
+ registration_id.origin(), registration_id.id(),
+ base::BindOnce(&BackgroundFetchServiceTest::DidAbort,
+ base::Unretained(this),
+ run_loop.QuitClosure(), out_error));
run_loop.Run();
}
@@ -92,27 +93,28 @@ class BackgroundFetchServiceTest : public BackgroundFetchTestBase {
base::RunLoop run_loop;
service_->GetRegistration(
registration_id.service_worker_registration_id(),
- registration_id.origin(), registration_id.tag(),
- base::Bind(&BackgroundFetchServiceTest::DidGetRegistration,
- base::Unretained(this), run_loop.QuitClosure(), out_error,
- out_registration));
+ registration_id.origin(), registration_id.id(),
+ base::BindOnce(&BackgroundFetchServiceTest::DidGetRegistration,
+ base::Unretained(this), run_loop.QuitClosure(),
+ out_error, out_registration));
run_loop.Run();
}
- // Synchronous wrapper for BackgroundFetchServiceImpl::GetTags().
- void GetTags(const BackgroundFetchRegistrationId& registration_id,
- blink::mojom::BackgroundFetchError* out_error,
- std::vector<std::string>* out_tags) {
+ // Synchronous wrapper for BackgroundFetchServiceImpl::GetIds().
+ void GetIds(const BackgroundFetchRegistrationId& registration_id,
+ blink::mojom::BackgroundFetchError* out_error,
+ std::vector<std::string>* out_ids) {
DCHECK(out_error);
- DCHECK(out_tags);
+ DCHECK(out_ids);
base::RunLoop run_loop;
- service_->GetTags(registration_id.service_worker_registration_id(),
- registration_id.origin(),
- base::Bind(&BackgroundFetchServiceTest::DidGetTags,
- base::Unretained(this), run_loop.QuitClosure(),
- out_error, out_tags));
+ service_->GetIds(
+ registration_id.service_worker_registration_id(),
+ registration_id.origin(),
+ base::BindOnce(&BackgroundFetchServiceTest::DidGetIds,
+ base::Unretained(this), run_loop.QuitClosure(),
+ out_error, out_ids));
run_loop.Run();
}
@@ -171,13 +173,13 @@ class BackgroundFetchServiceTest : public BackgroundFetchTestBase {
quit_closure.Run();
}
- void DidGetTags(base::Closure quit_closure,
- blink::mojom::BackgroundFetchError* out_error,
- std::vector<std::string>* out_tags,
- blink::mojom::BackgroundFetchError error,
- const std::vector<std::string>& tags) {
+ void DidGetIds(base::Closure quit_closure,
+ blink::mojom::BackgroundFetchError* out_error,
+ std::vector<std::string>* out_ids,
+ blink::mojom::BackgroundFetchError error,
+ const std::vector<std::string>& ids) {
*out_error = error;
- *out_tags = tags;
+ *out_ids = ids;
quit_closure.Run();
}
@@ -194,10 +196,10 @@ TEST_F(BackgroundFetchServiceTest, FetchInvalidArguments) {
BackgroundFetchOptions options;
- // The `tag` must be a non-empty string.
+ // The `id` must be a non-empty string.
{
BackgroundFetchRegistrationId registration_id(
- 42 /* service_worker_registration_id */, origin(), "" /* tag */);
+ 42 /* service_worker_registration_id */, origin(), "" /* id */);
std::vector<ServiceWorkerFetchRequest> requests;
requests.emplace_back(); // empty, but valid
@@ -213,7 +215,7 @@ TEST_F(BackgroundFetchServiceTest, FetchInvalidArguments) {
// At least a single ServiceWorkerFetchRequest must be given.
{
BackgroundFetchRegistrationId registration_id(
- 42 /* service_worker_registration_id */, origin(), kExampleTag);
+ 42 /* service_worker_registration_id */, origin(), kExampleId);
std::vector<ServiceWorkerFetchRequest> requests;
// |requests| has deliberately been left empty.
@@ -230,10 +232,10 @@ TEST_F(BackgroundFetchServiceTest, FetchInvalidArguments) {
TEST_F(BackgroundFetchServiceTest, FetchRegistrationProperties) {
// This test starts a new Background Fetch and verifies that the returned
// BackgroundFetchRegistration object matches the given options. Then gets
- // the active Background Fetch with the same tag, and verifies it again.
+ // the active Background Fetch with the same id, and verifies it again.
BackgroundFetchRegistrationId registration_id;
- ASSERT_TRUE(CreateRegistrationId(kExampleTag, &registration_id));
+ ASSERT_TRUE(CreateRegistrationId(kExampleId, &registration_id));
std::vector<ServiceWorkerFetchRequest> requests;
requests.emplace_back(); // empty, but valid
@@ -252,7 +254,7 @@ TEST_F(BackgroundFetchServiceTest, FetchRegistrationProperties) {
ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
// The |registration| should reflect the options given in |options|.
- EXPECT_EQ(registration.tag, kExampleTag);
+ EXPECT_EQ(registration.id, kExampleId);
ASSERT_EQ(registration.icons.size(), options.icons.size());
for (size_t i = 0; i < registration.icons.size(); ++i) {
@@ -272,7 +274,7 @@ TEST_F(BackgroundFetchServiceTest, FetchRegistrationProperties) {
ASSERT_EQ(second_error, blink::mojom::BackgroundFetchError::NONE);
// The |second_registration| should reflect the options given in |options|.
- EXPECT_EQ(second_registration.tag, kExampleTag);
+ EXPECT_EQ(second_registration.id, kExampleId);
ASSERT_EQ(second_registration.icons.size(), options.icons.size());
for (size_t i = 0; i < second_registration.icons.size(); ++i) {
@@ -289,10 +291,10 @@ TEST_F(BackgroundFetchServiceTest, FetchRegistrationProperties) {
TEST_F(BackgroundFetchServiceTest, FetchDuplicatedRegistrationFailure) {
// This tests starts a new Background Fetch, verifies that a registration was
// successfully created, and then tries to start a second fetch for the same
- // registration. This should fail with a DUPLICATED_TAG error.
+ // registration. This should fail with a DUPLICATED_ID error.
BackgroundFetchRegistrationId registration_id;
- ASSERT_TRUE(CreateRegistrationId(kExampleTag, &registration_id));
+ ASSERT_TRUE(CreateRegistrationId(kExampleId, &registration_id));
std::vector<ServiceWorkerFetchRequest> requests;
requests.emplace_back(); // empty, but valid
@@ -313,7 +315,7 @@ TEST_F(BackgroundFetchServiceTest, FetchDuplicatedRegistrationFailure) {
// Create the second registration with the same data. This must fail.
ASSERT_NO_FATAL_FAILURE(Fetch(registration_id, requests, options,
&second_error, &second_registration));
- ASSERT_EQ(second_error, blink::mojom::BackgroundFetchError::DUPLICATED_TAG);
+ ASSERT_EQ(second_error, blink::mojom::BackgroundFetchError::DUPLICATED_ID);
}
TEST_F(BackgroundFetchServiceTest, FetchSuccessEventDispatch) {
@@ -322,7 +324,7 @@ TEST_F(BackgroundFetchServiceTest, FetchSuccessEventDispatch) {
// `backgroundfetched` event will be dispatched with the expected contents.
BackgroundFetchRegistrationId registration_id;
- ASSERT_TRUE(CreateRegistrationId(kExampleTag, &registration_id));
+ ASSERT_TRUE(CreateRegistrationId(kExampleId, &registration_id));
// base::RunLoop that we'll run until the event has been dispatched. If this
// test times out, it means that the event could not be dispatched.
@@ -377,8 +379,8 @@ TEST_F(BackgroundFetchServiceTest, FetchSuccessEventDispatch) {
// Spin the |event_dispatched_loop| to wait for the dispatched event.
event_dispatched_loop.Run();
- ASSERT_TRUE(embedded_worker_test_helper()->last_tag().has_value());
- EXPECT_EQ(kExampleTag, embedded_worker_test_helper()->last_tag().value());
+ ASSERT_TRUE(embedded_worker_test_helper()->last_id().has_value());
+ EXPECT_EQ(kExampleId, embedded_worker_test_helper()->last_id().value());
ASSERT_TRUE(embedded_worker_test_helper()->last_fetches().has_value());
@@ -392,7 +394,7 @@ TEST_F(BackgroundFetchServiceTest, FetchSuccessEventDispatch) {
EXPECT_EQ(fetches[i].response.url_list[0], fetches[i].request.url);
EXPECT_EQ(fetches[i].response.response_type,
- blink::kWebServiceWorkerResponseTypeDefault);
+ network::mojom::FetchResponseType::kDefault);
switch (i) {
case 0:
@@ -433,7 +435,7 @@ TEST_F(BackgroundFetchServiceTest, FetchFailEventDispatch) {
// has a non-OK status code, or the response cannot be accessed due to CORS.
BackgroundFetchRegistrationId registration_id;
- ASSERT_TRUE(CreateRegistrationId(kExampleTag, &registration_id));
+ ASSERT_TRUE(CreateRegistrationId(kExampleId, &registration_id));
// base::RunLoop that we'll run until the event has been dispatched. If this
// test times out, it means that the event could not be dispatched.
@@ -474,8 +476,8 @@ TEST_F(BackgroundFetchServiceTest, FetchFailEventDispatch) {
// Spin the |event_dispatched_loop| to wait for the dispatched event.
event_dispatched_loop.Run();
- ASSERT_TRUE(embedded_worker_test_helper()->last_tag().has_value());
- EXPECT_EQ(kExampleTag, embedded_worker_test_helper()->last_tag().value());
+ ASSERT_TRUE(embedded_worker_test_helper()->last_id().has_value());
+ EXPECT_EQ(kExampleId, embedded_worker_test_helper()->last_id().value());
ASSERT_TRUE(embedded_worker_test_helper()->last_fetches().has_value());
@@ -489,7 +491,7 @@ TEST_F(BackgroundFetchServiceTest, FetchFailEventDispatch) {
EXPECT_EQ(fetches[i].response.url_list[0], fetches[i].request.url);
EXPECT_EQ(fetches[i].response.response_type,
- blink::kWebServiceWorkerResponseTypeDefault);
+ network::mojom::FetchResponseType::kDefault);
switch (i) {
case 0:
@@ -517,10 +519,10 @@ TEST_F(BackgroundFetchServiceTest, FetchFailEventDispatch) {
TEST_F(BackgroundFetchServiceTest, Abort) {
// This test starts a new Background Fetch, completes the registration, and
// then aborts the Background Fetch mid-process. Tests all of StartFetch(),
- // GetActiveFetches() and GetActiveTagsForServiceWorkerRegistration().
+ // GetActiveFetches() and GetActiveIdsForServiceWorkerRegistration().
BackgroundFetchRegistrationId registration_id;
- ASSERT_TRUE(CreateRegistrationId(kExampleTag, &registration_id));
+ ASSERT_TRUE(CreateRegistrationId(kExampleId, &registration_id));
std::vector<ServiceWorkerFetchRequest> requests;
requests.emplace_back(); // empty, but valid
@@ -550,7 +552,7 @@ TEST_F(BackgroundFetchServiceTest, Abort) {
// Now try to get the created registration, which is expected to fail.
ASSERT_NO_FATAL_FAILURE(
GetRegistration(registration_id, &second_error, &second_registration));
- ASSERT_EQ(second_error, blink::mojom::BackgroundFetchError::INVALID_TAG);
+ ASSERT_EQ(second_error, blink::mojom::BackgroundFetchError::INVALID_ID);
}
TEST_F(BackgroundFetchServiceTest, AbortInvalidArguments) {
@@ -558,7 +560,7 @@ TEST_F(BackgroundFetchServiceTest, AbortInvalidArguments) {
// return INVALID_ARGUMENT when invalid data is send over the Mojo channel.
BackgroundFetchRegistrationId registration_id(
- 42 /* service_worker_registration_id */, origin(), "" /* tag */);
+ 42 /* service_worker_registration_id */, origin(), "" /* id */);
blink::mojom::BackgroundFetchError error;
@@ -566,19 +568,19 @@ TEST_F(BackgroundFetchServiceTest, AbortInvalidArguments) {
ASSERT_EQ(error, blink::mojom::BackgroundFetchError::INVALID_ARGUMENT);
}
-TEST_F(BackgroundFetchServiceTest, AbortInvalidTag) {
+TEST_F(BackgroundFetchServiceTest, AbortInvalidId) {
// This test verifies that aborting a Background Fetch registration with a
- // tag that does not correspond to an active fetch kindly tells us so.
+ // id that does not correspond to an active fetch kindly tells us so.
BackgroundFetchRegistrationId registration_id;
- ASSERT_TRUE(CreateRegistrationId(kExampleTag, &registration_id));
+ ASSERT_TRUE(CreateRegistrationId(kExampleId, &registration_id));
// Deliberate do *not* create a fetch for the |registration_id|.
blink::mojom::BackgroundFetchError error;
ASSERT_NO_FATAL_FAILURE(Abort(registration_id, &error));
- ASSERT_EQ(error, blink::mojom::BackgroundFetchError::INVALID_TAG);
+ ASSERT_EQ(error, blink::mojom::BackgroundFetchError::INVALID_ID);
}
TEST_F(BackgroundFetchServiceTest, AbortEventDispatch) {
@@ -586,7 +588,7 @@ TEST_F(BackgroundFetchServiceTest, AbortEventDispatch) {
// Fetch registration has been aborted by either the user or developer.
BackgroundFetchRegistrationId registration_id;
- ASSERT_TRUE(CreateRegistrationId(kExampleTag, &registration_id));
+ ASSERT_TRUE(CreateRegistrationId(kExampleId, &registration_id));
// base::RunLoop that we'll run until the event has been dispatched. If this
// test times out, it means that the event could not be dispatched.
@@ -627,34 +629,34 @@ TEST_F(BackgroundFetchServiceTest, AbortEventDispatch) {
event_dispatched_loop.Run();
- ASSERT_TRUE(embedded_worker_test_helper()->last_tag().has_value());
- EXPECT_EQ(kExampleTag, embedded_worker_test_helper()->last_tag().value());
+ ASSERT_TRUE(embedded_worker_test_helper()->last_id().has_value());
+ EXPECT_EQ(kExampleId, embedded_worker_test_helper()->last_id().value());
}
-TEST_F(BackgroundFetchServiceTest, GetTags) {
- // This test verifies that the list of active tags can be retrieved from the
+TEST_F(BackgroundFetchServiceTest, GetIds) {
+ // This test verifies that the list of active ids can be retrieved from the
// service for a given Service Worker, as extracted from a registration.
BackgroundFetchRegistrationId registration_id;
- ASSERT_TRUE(CreateRegistrationId(kExampleTag, &registration_id));
+ ASSERT_TRUE(CreateRegistrationId(kExampleId, &registration_id));
BackgroundFetchRegistrationId second_registration_id;
- ASSERT_TRUE(CreateRegistrationId(kAlternativeTag, &second_registration_id));
+ ASSERT_TRUE(CreateRegistrationId(kAlternativeId, &second_registration_id));
std::vector<ServiceWorkerFetchRequest> requests;
requests.emplace_back(); // empty, but valid
BackgroundFetchOptions options;
- // Verify that there are no active tags yet.
+ // Verify that there are no active ids yet.
{
blink::mojom::BackgroundFetchError error;
- std::vector<std::string> tags;
+ std::vector<std::string> ids;
- ASSERT_NO_FATAL_FAILURE(GetTags(registration_id, &error, &tags));
+ ASSERT_NO_FATAL_FAILURE(GetIds(registration_id, &error, &ids));
ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
- ASSERT_EQ(tags.size(), 0u);
+ ASSERT_EQ(ids.size(), 0u);
}
// Start the Background Fetch for the |registration_id|.
@@ -670,13 +672,13 @@ TEST_F(BackgroundFetchServiceTest, GetTags) {
// Verify that there is a single active fetch (the one we just started).
{
blink::mojom::BackgroundFetchError error;
- std::vector<std::string> tags;
+ std::vector<std::string> ids;
- ASSERT_NO_FATAL_FAILURE(GetTags(registration_id, &error, &tags));
+ ASSERT_NO_FATAL_FAILURE(GetIds(registration_id, &error, &ids));
ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
- ASSERT_EQ(tags.size(), 1u);
- EXPECT_EQ(tags[0], kExampleTag);
+ ASSERT_EQ(ids.size(), 1u);
+ EXPECT_EQ(ids[0], kExampleId);
}
// Start the Background Fetch for the |second_registration_id|.
@@ -692,21 +694,20 @@ TEST_F(BackgroundFetchServiceTest, GetTags) {
// Verify that there are two active fetches.
{
blink::mojom::BackgroundFetchError error;
- std::vector<std::string> tags;
+ std::vector<std::string> ids;
- ASSERT_NO_FATAL_FAILURE(GetTags(registration_id, &error, &tags));
+ ASSERT_NO_FATAL_FAILURE(GetIds(registration_id, &error, &ids));
ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
- ASSERT_EQ(tags.size(), 2u);
+ ASSERT_EQ(ids.size(), 2u);
- // We make no guarantees about ordering of the tags.
- const bool has_example_tag =
- tags[0] == kExampleTag || tags[1] == kExampleTag;
- const bool has_alternative_tag =
- tags[0] == kAlternativeTag || tags[1] == kAlternativeTag;
+ // We make no guarantees about ordering of the ids.
+ const bool has_example_id = ids[0] == kExampleId || ids[1] == kExampleId;
+ const bool has_alternative_id =
+ ids[0] == kAlternativeId || ids[1] == kAlternativeId;
- EXPECT_TRUE(has_example_tag);
- EXPECT_TRUE(has_alternative_tag);
+ EXPECT_TRUE(has_example_id);
+ EXPECT_TRUE(has_alternative_id);
}
}
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 fb538f4601f..dc637b26e77 100644
--- a/chromium/content/browser/background_fetch/background_fetch_test_base.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_test_base.cc
@@ -5,6 +5,7 @@
#include "content/browser/background_fetch/background_fetch_test_base.h"
#include <stdint.h>
+#include <map>
#include <memory>
#include <utility>
@@ -139,7 +140,8 @@ class BackgroundFetchTestBase::RespondingDownloadManager
download_item->SetURL(params->url());
download_item->SetUrlChain({params->url()});
download_item->SetState(DownloadItem::DownloadState::IN_PROGRESS);
- download_item->SetGuid(base::GenerateGUID());
+ download_item->SetGuid(params->guid().empty() ? base::GenerateGUID()
+ : params->guid());
download_item->SetStartTime(base::Time::Now());
download_item->SetResponseHeaders(response->headers);
@@ -147,10 +149,10 @@ class BackgroundFetchTestBase::RespondingDownloadManager
// dealing with the response in this class.
BrowserThread::PostTaskAndReply(
BrowserThread::UI, FROM_HERE,
- base::Bind(params->callback(), download_item.get(),
- DOWNLOAD_INTERRUPT_REASON_NONE),
- base::Bind(&RespondingDownloadManager::DidStartDownload,
- weak_ptr_factory_.GetWeakPtr(), download_item.get()));
+ base::BindOnce(params->callback(), download_item.get(),
+ DOWNLOAD_INTERRUPT_REASON_NONE),
+ base::BindOnce(&RespondingDownloadManager::DidStartDownload,
+ weak_ptr_factory_.GetWeakPtr(), download_item.get()));
download_items_.push_back(std::move(download_item));
}
diff --git a/chromium/content/browser/background_sync/background_sync_browsertest.cc b/chromium/content/browser/background_sync/background_sync_browsertest.cc
index 2b522c4de35..c45610f981f 100644
--- a/chromium/content/browser/background_sync/background_sync_browsertest.cc
+++ b/chromium/content/browser/background_sync/background_sync_browsertest.cc
@@ -11,6 +11,7 @@
#include "base/command_line.h"
#include "base/macros.h"
+#include "base/run_loop.h"
#include "base/strings/string_split.h"
#include "base/strings/stringprintf.h"
#include "base/task_runner_util.h"
diff --git a/chromium/content/browser/background_sync/background_sync_manager.cc b/chromium/content/browser/background_sync/background_sync_manager.cc
index 14a07320d43..72fbea09219 100644
--- a/chromium/content/browser/background_sync/background_sync_manager.cc
+++ b/chromium/content/browser/background_sync/background_sync_manager.cc
@@ -763,10 +763,9 @@ void BackgroundSyncManager::DispatchSyncEvent(
if (active_version->running_status() != EmbeddedWorkerStatus::RUNNING) {
active_version->RunAfterStartWorker(
ServiceWorkerMetrics::EventType::SYNC,
- base::AdaptCallbackForRepeating(
- base::BindOnce(&BackgroundSyncManager::DispatchSyncEvent,
- weak_ptr_factory_.GetWeakPtr(), tag, active_version,
- last_chance, callback)),
+ base::BindOnce(&BackgroundSyncManager::DispatchSyncEvent,
+ weak_ptr_factory_.GetWeakPtr(), tag, active_version,
+ last_chance, callback),
callback);
return;
}
diff --git a/chromium/content/browser/background_sync/background_sync_manager.h b/chromium/content/browser/background_sync/background_sync_manager.h
index 92ebc2102ac..0ab44cea698 100644
--- a/chromium/content/browser/background_sync/background_sync_manager.h
+++ b/chromium/content/browser/background_sync/background_sync_manager.h
@@ -51,7 +51,7 @@ class ServiceWorkerContextWrapper;
// the sync registrations are removed. This class must be run on the IO
// thread. The asynchronous methods are executed sequentially.
class CONTENT_EXPORT BackgroundSyncManager
- : NON_EXPORTED_BASE(public ServiceWorkerContextCoreObserver) {
+ : public ServiceWorkerContextCoreObserver {
public:
using BoolCallback = base::OnceCallback<void(bool)>;
using StatusAndRegistrationCallback =
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 f65652b57e5..b74b824acb0 100644
--- a/chromium/content/browser/background_sync/background_sync_manager_unittest.cc
+++ b/chromium/content/browser/background_sync/background_sync_manager_unittest.cc
@@ -27,6 +27,8 @@
#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"
+#include "content/browser/service_worker/service_worker_dispatcher_host.h"
+#include "content/browser/service_worker/service_worker_registration_handle.h"
#include "content/browser/service_worker/service_worker_storage.h"
#include "content/browser/storage_partition_impl.h"
#include "content/public/browser/background_sync_parameters.h"
@@ -34,6 +36,7 @@
#include "content/public/test/background_sync_test_util.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_background_sync_controller.h"
#include "content/test/mock_permission_manager.h"
#include "content/test/test_background_sync_manager.h"
@@ -404,7 +407,7 @@ class BackgroundSyncManagerTest : public testing::Test {
void DeleteServiceWorkerAndStartOver() {
helper_->context()->ScheduleDeleteAndStartOver();
- base::RunLoop().RunUntilIdle();
+ content::RunAllBlockingPoolTasksUntilIdle();
}
int MaxTagLength() const { return BackgroundSyncManager::kMaxTagLength; }
@@ -456,7 +459,28 @@ TEST_F(BackgroundSyncManagerTest, RegistrationIntact) {
}
TEST_F(BackgroundSyncManagerTest, RegisterWithoutLiveSWRegistration) {
+ // Get a provider host which is used to install the service worker.
+ ASSERT_TRUE(sw_registration_1_->active_version());
+ ASSERT_FALSE(sw_registration_1_->waiting_version());
+ ASSERT_FALSE(sw_registration_1_->installing_version());
+ ServiceWorkerProviderHost* provider_host =
+ sw_registration_1_->active_version()->provider_host();
+ ASSERT_TRUE(provider_host);
+ int process_id = provider_host->process_id();
+ int provider_id = provider_host->provider_id();
+
+ // Remove the registration handle registered on the dispatcher host.
+ ServiceWorkerDispatcherHost* dispatcher_host =
+ helper_->context()->GetDispatcherHost(process_id);
+ ServiceWorkerRegistrationHandle* handle =
+ dispatcher_host->FindRegistrationHandle(provider_id,
+ sw_registration_1_->id());
+ dispatcher_host->OnDecrementRegistrationRefCount(handle->handle_id());
+
+ // Ensure |sw_registration_1_| is the last reference to the registration.
+ ASSERT_TRUE(sw_registration_1_->HasOneRef());
sw_registration_1_ = nullptr;
+
EXPECT_FALSE(Register(sync_options_1_));
EXPECT_EQ(BACKGROUND_SYNC_STATUS_NO_SERVICE_WORKER, callback_status_);
}
diff --git a/chromium/content/browser/background_sync/background_sync_service_impl.h b/chromium/content/browser/background_sync/background_sync_service_impl.h
index cf846da1631..115d92f78f5 100644
--- a/chromium/content/browser/background_sync/background_sync_service_impl.h
+++ b/chromium/content/browser/background_sync/background_sync_service_impl.h
@@ -10,7 +10,7 @@
#include <memory>
#include <vector>
-#include "base/id_map.h"
+#include "base/containers/id_map.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "content/browser/background_sync/background_sync_manager.h"
@@ -22,7 +22,7 @@ namespace content {
class BackgroundSyncContext;
class CONTENT_EXPORT BackgroundSyncServiceImpl
- : public NON_EXPORTED_BASE(blink::mojom::BackgroundSyncService) {
+ : public blink::mojom::BackgroundSyncService {
public:
BackgroundSyncServiceImpl(
BackgroundSyncContext* background_sync_context,
diff --git a/chromium/content/browser/bad_message.cc b/chromium/content/browser/bad_message.cc
index ee8fba472bf..34007f1e2df 100644
--- a/chromium/content/browser/bad_message.cc
+++ b/chromium/content/browser/bad_message.cc
@@ -53,10 +53,9 @@ void ReceivedBadMessage(int render_process_id, BadMessageReason reason) {
base::debug::DumpWithoutCrashing();
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- BrowserThread::PostTask(
- BrowserThread::UI,
- FROM_HERE,
- base::Bind(&ReceivedBadMessageOnUIThread, render_process_id, reason));
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&ReceivedBadMessageOnUIThread,
+ render_process_id, reason));
return;
}
ReceivedBadMessageOnUIThread(render_process_id, reason);
diff --git a/chromium/content/browser/bad_message.h b/chromium/content/browser/bad_message.h
index 7b5e1d2e19d..45c16febc44 100644
--- a/chromium/content/browser/bad_message.h
+++ b/chromium/content/browser/bad_message.h
@@ -5,6 +5,8 @@
#ifndef CONTENT_BROWSER_BAD_MESSAGE_H_
#define CONTENT_BROWSER_BAD_MESSAGE_H_
+#include "content/common/content_export.h"
+
namespace content {
class BrowserMessageFilter;
class RenderProcessHost;
@@ -185,7 +187,7 @@ enum BadMessageReason {
BDH_INVALID_DESCRIPTOR_ID = 161,
RWH_INVALID_BEGIN_FRAME_ACK_DID_NOT_SWAP = 162,
RWH_INVALID_BEGIN_FRAME_ACK_COMPOSITOR_FRAME = 163,
- BFSI_INVALID_TAG = 164,
+ BFSI_INVALID_ID = 164,
BFSI_INVALID_REQUESTS = 165,
BFSI_INVALID_TITLE = 166,
RWH_INVALID_FRAME_TOKEN = 167,
@@ -213,7 +215,8 @@ enum BadMessageReason {
void ReceivedBadMessage(RenderProcessHost* host, BadMessageReason reason);
// Equivalent to the above, but callable from any thread.
-void ReceivedBadMessage(int render_process_id, BadMessageReason reason);
+CONTENT_EXPORT void ReceivedBadMessage(int render_process_id,
+ BadMessageReason reason);
// Called when a browser message filter receives a bad IPC message from a
// renderer or other child process. Logs the event, records a histogram metric
diff --git a/chromium/content/browser/blob_storage/blob_dispatcher_host.cc b/chromium/content/browser/blob_storage/blob_dispatcher_host.cc
index dd7209c7b1d..3030bf95763 100644
--- a/chromium/content/browser/blob_storage/blob_dispatcher_host.cc
+++ b/chromium/content/browser/blob_storage/blob_dispatcher_host.cc
@@ -121,6 +121,9 @@ void BlobDispatcherHost::OnRegisterBlob(
if (!FileSystemURLIsValid(file_system_context_.get(), filesystem_url) ||
!security_policy->CanReadFileSystemFile(process_id_,
filesystem_url)) {
+ DVLOG(1) << "BlobDispatcherHost::OnRegisterBlob(" << uuid
+ << "): Invalid or prohibited FileSystem URL: "
+ << filesystem_url.DebugString();
HostedBlobState hosted_state(
context->AddBrokenBlob(uuid, content_type, content_disposition,
BlobStatus::ERR_FILE_WRITE_FAILED));
@@ -133,6 +136,9 @@ void BlobDispatcherHost::OnRegisterBlob(
}
case storage::DataElement::TYPE_FILE: {
if (!security_policy->CanReadFile(process_id_, item.path())) {
+ DVLOG(1) << "BlobDispatcherHost::OnRegisterBlob(" << uuid
+ << "): Invalid or prohibited FilePath: "
+ << item.path().value();
HostedBlobState hosted_state(
context->AddBrokenBlob(uuid, content_type, content_disposition,
BlobStatus::ERR_FILE_WRITE_FAILED));
@@ -243,6 +249,8 @@ void BlobDispatcherHost::OnIncrementBlobRefCount(const std::string& uuid) {
return;
}
if (!context->registry().HasEntry(uuid)) {
+ DVLOG(1) << "BlobDispatcherHost::OnIncrementBlobRefCount(" << uuid
+ << "): Unknown UUID.";
UMA_HISTOGRAM_ENUMERATION("Storage.Blob.InvalidReference", BDH_INCREMENT,
BDH_TRACING_ENUM_LAST);
return;
@@ -265,6 +273,8 @@ void BlobDispatcherHost::OnDecrementBlobRefCount(const std::string& uuid) {
}
auto state_it = blobs_inuse_map_.find(uuid);
if (state_it == blobs_inuse_map_.end()) {
+ DVLOG(1) << "BlobDispatcherHost::OnDecrementBlobRefCount(" << uuid
+ << "): Unknown UUID.";
UMA_HISTOGRAM_ENUMERATION("Storage.Blob.InvalidReference", BDH_DECREMENT,
BDH_TRACING_ENUM_LAST);
return;
@@ -295,6 +305,9 @@ void BlobDispatcherHost::OnRegisterPublicBlobURL(const GURL& public_url,
// on the URL is allowed to be rendered in this process.
if (!public_url.SchemeIsBlob() ||
!security_policy->CanCommitURL(process_id_, public_url)) {
+ DVLOG(1) << "BlobDispatcherHost::OnRegisterPublicBlobURL("
+ << public_url.spec() << ", " << uuid
+ << "): Invalid or prohibited URL.";
bad_message::ReceivedBadMessage(this, bad_message::BDH_DISALLOWED_ORIGIN);
return;
}
@@ -305,6 +318,8 @@ void BlobDispatcherHost::OnRegisterPublicBlobURL(const GURL& public_url,
}
BlobStorageContext* context = this->context();
if (!IsInUseInHost(uuid) || context->registry().IsURLMapped(public_url)) {
+ DVLOG(1) << "BlobDispatcherHost::OnRegisterPublicBlobURL("
+ << public_url.spec() << ", " << uuid << "): Invalid url or uuid.";
UMA_HISTOGRAM_ENUMERATION("Storage.Blob.InvalidURLRegister", BDH_INCREMENT,
BDH_TRACING_ENUM_LAST);
return;
@@ -321,6 +336,8 @@ void BlobDispatcherHost::OnRevokePublicBlobURL(const GURL& public_url) {
return;
}
if (!IsUrlRegisteredInHost(public_url)) {
+ DVLOG(1) << "BlobDispatcherHost::OnRevokePublicBlobURL("
+ << public_url.spec() << "): Unknown URL.";
UMA_HISTOGRAM_ENUMERATION("Storage.Blob.InvalidURLRegister", BDH_DECREMENT,
BDH_TRACING_ENUM_LAST);
return;
diff --git a/chromium/content/browser/blob_storage/blob_internals_url_loader.cc b/chromium/content/browser/blob_storage/blob_internals_url_loader.cc
index 84906c806d8..910b356b185 100644
--- a/chromium/content/browser/blob_storage/blob_internals_url_loader.cc
+++ b/chromium/content/browser/blob_storage/blob_internals_url_loader.cc
@@ -30,14 +30,13 @@ void StartBlobInternalsURLLoader(
void* buffer = nullptr;
uint32_t num_bytes = output.size();
- MojoResult result =
- BeginWriteDataRaw(data_pipe.producer_handle.get(), &buffer, &num_bytes,
- MOJO_WRITE_DATA_FLAG_NONE);
+ MojoResult result = data_pipe.producer_handle->BeginWriteData(
+ &buffer, &num_bytes, MOJO_WRITE_DATA_FLAG_NONE);
CHECK_EQ(result, MOJO_RESULT_OK);
CHECK_EQ(num_bytes, output.size());
memcpy(buffer, output.c_str(), output.size());
- result = EndWriteDataRaw(data_pipe.producer_handle.get(), num_bytes);
+ result = data_pipe.producer_handle->EndWriteData(num_bytes);
CHECK_EQ(result, MOJO_RESULT_OK);
client->OnStartLoadingResponseBody(std::move(data_pipe.consumer_handle));
diff --git a/chromium/content/browser/blob_storage/blob_registry_wrapper.cc b/chromium/content/browser/blob_storage/blob_registry_wrapper.cc
index 154aebf53f5..a339b24cce6 100644
--- a/chromium/content/browser/blob_storage/blob_registry_wrapper.cc
+++ b/chromium/content/browser/blob_storage/blob_registry_wrapper.cc
@@ -29,6 +29,11 @@ class BindingDelegate : public storage::BlobRegistryImpl::Delegate {
ChildProcessSecurityPolicyImpl::GetInstance();
return security_policy->CanReadFileSystemFile(process_id_, url);
}
+ bool CanCommitURL(const GURL& url) override {
+ ChildProcessSecurityPolicyImpl* security_policy =
+ ChildProcessSecurityPolicyImpl::GetInstance();
+ return security_policy->CanCommitURL(process_id_, url);
+ }
private:
const int process_id_;
diff --git a/chromium/content/browser/blob_storage/blob_url_loader_factory.cc b/chromium/content/browser/blob_storage/blob_url_loader_factory.cc
index 37d29f70b53..e4d165545c3 100644
--- a/chromium/content/browser/blob_storage/blob_url_loader_factory.cc
+++ b/chromium/content/browser/blob_storage/blob_url_loader_factory.cc
@@ -5,14 +5,15 @@
#include "content/browser/blob_storage/blob_url_loader_factory.h"
#include <stddef.h>
+#include <utility>
#include "base/bind.h"
#include "base/logging.h"
#include "base/macros.h"
+#include "base/memory/ptr_util.h"
#include "base/memory/weak_ptr.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
#include "content/browser/storage_partition_impl.h"
-#include "content/common/net_adapters.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/url_loader.mojom.h"
#include "mojo/public/cpp/system/simple_watcher.h"
@@ -26,6 +27,7 @@
#include "storage/browser/blob/blob_reader.h"
#include "storage/browser/blob/blob_storage_context.h"
#include "storage/browser/blob/blob_url_request_job.h"
+#include "storage/browser/blob/mojo_blob_reader.h"
#include "storage/browser/fileapi/file_system_context.h"
namespace content {
@@ -33,12 +35,14 @@ namespace content {
namespace {
constexpr size_t kDefaultAllocationSize = 512 * 1024;
-// This class handles a request for a blob:// url. It self-destructs (see
-// DeleteIfNeeded) when it has finished responding.
+// This class handles a request for a blob:// url. It self-destructs (directly,
+// or after passing ownership to storage::MojoBlobReader at the end of the Start
+// method) when it has finished responding.
// Note: some of this code is duplicated from storage::BlobURLRequestJob.
-class BlobURLLoader : public mojom::URLLoader {
+class BlobURLLoader : public storage::MojoBlobReader::Delegate,
+ public mojom::URLLoader {
public:
- BlobURLLoader(mojom::URLLoaderAssociatedRequest url_loader_request,
+ BlobURLLoader(mojom::URLLoaderRequest url_loader_request,
const ResourceRequest& request,
mojom::URLLoaderClientPtr client,
std::unique_ptr<storage::BlobDataHandle> blob_handle,
@@ -46,37 +50,29 @@ class BlobURLLoader : public mojom::URLLoader {
: binding_(this, std::move(url_loader_request)),
client_(std::move(client)),
blob_handle_(std::move(blob_handle)),
- writable_handle_watcher_(FROM_HERE,
- mojo::SimpleWatcher::ArmingPolicy::MANUAL),
- peer_closed_handle_watcher_(FROM_HERE,
- mojo::SimpleWatcher::ArmingPolicy::MANUAL),
weak_factory_(this) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
// PostTask since it might destruct.
- base::ThreadTaskRunnerHandle::Get()->PostTask(
+ base::SequencedTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
- base::Bind(&BlobURLLoader::Start, weak_factory_.GetWeakPtr(), request,
- make_scoped_refptr(file_system_context)));
+ base::BindOnce(&BlobURLLoader::Start, weak_factory_.GetWeakPtr(),
+ request, make_scoped_refptr(file_system_context)));
}
+ private:
void Start(const ResourceRequest& request,
scoped_refptr<storage::FileSystemContext> file_system_context) {
if (!blob_handle_) {
- NotifyCompleted(net::ERR_FILE_NOT_FOUND);
+ OnComplete(net::ERR_FILE_NOT_FOUND, 0);
+ delete this;
return;
}
- blob_reader_ = blob_handle_->CreateReader(file_system_context.get());
-
// We only support GET request per the spec.
if (request.method != "GET") {
- NotifyCompleted(net::ERR_METHOD_NOT_SUPPORTED);
- return;
- }
-
- if (blob_reader_->net_error()) {
- NotifyCompleted(blob_reader_->net_error());
+ OnComplete(net::ERR_METHOD_NOT_SUPPORTED, 0);
+ delete this;
return;
}
@@ -95,112 +91,65 @@ class BlobURLLoader : public mojom::URLLoader {
// We don't support multiple range requests in one single URL request,
// because we need to do multipart encoding here.
// TODO(jianli): Support multipart byte range requests.
- NotifyCompleted(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE);
+ OnComplete(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE, 0);
+ delete this;
+ return;
}
}
}
- storage::BlobReader::Status size_status =
- blob_reader_->CalculateSize(base::Bind(&BlobURLLoader::DidCalculateSize,
- weak_factory_.GetWeakPtr()));
- switch (size_status) {
- case storage::BlobReader::Status::NET_ERROR:
- NotifyCompleted(blob_reader_->net_error());
- return;
- case storage::BlobReader::Status::IO_PENDING:
- return;
- case storage::BlobReader::Status::DONE:
- DidCalculateSize(net::OK);
- return;
- }
-
- NOTREACHED();
+ storage::MojoBlobReader::Create(file_system_context.get(),
+ blob_handle_.get(), byte_range_,
+ base::WrapUnique(this));
}
- ~BlobURLLoader() override {}
-
- private:
// mojom::URLLoader implementation:
void FollowRedirect() override { NOTREACHED(); }
void SetPriority(net::RequestPriority priority,
int32_t intra_priority_value) override {}
- // Notifies the client that the request completed. Takes care of deleting this
- // object now if possible (i.e. no outstanding data pipe), otherwise this
- // object will be deleted when the data pipe is closed.
- void NotifyCompleted(int error_code) {
- if (error_code != net::OK && !sent_headers_) {
- net::HttpStatusCode status_code =
- storage::BlobURLRequestJob::NetErrorToHttpStatusCode(error_code);
- ResourceResponseHead response;
- response.headers = storage::BlobURLRequestJob::GenerateHeaders(
- status_code, nullptr, nullptr, nullptr, nullptr);
- client_->OnReceiveResponse(response, base::nullopt, nullptr);
- }
- ResourceRequestCompletionStatus request_complete_data;
- // TODO(kinuko): We should probably set the error_code here,
- // while it makes existing tests fail. crbug.com/732750
- request_complete_data.completion_time = base::TimeTicks::Now();
- request_complete_data.encoded_body_length = total_written_bytes_;
- request_complete_data.decoded_body_length = total_written_bytes_;
- client_->OnComplete(request_complete_data);
-
- DeleteIfNeeded();
+ // storage::MojoBlobReader::Delegate implementation:
+ mojo::ScopedDataPipeProducerHandle PassDataPipe() override {
+ mojo::DataPipe data_pipe(kDefaultAllocationSize);
+ response_body_consumer_handle_ = std::move(data_pipe.consumer_handle);
+ return std::move(data_pipe.producer_handle);
}
- void DidCalculateSize(int result) {
- if (result != net::OK) {
- NotifyCompleted(result);
- return;
- }
-
- // Apply the range requirement.
- if (!byte_range_.ComputeBounds(blob_reader_->total_size())) {
- NotifyCompleted(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE);
- return;
- }
-
- DCHECK_LE(byte_range_.first_byte_position(),
- byte_range_.last_byte_position() + 1);
- uint64_t length =
- base::checked_cast<uint64_t>(byte_range_.last_byte_position() -
- byte_range_.first_byte_position() + 1);
-
- if (byte_range_set_)
- blob_reader_->SetReadRange(byte_range_.first_byte_position(), length);
+ RequestSideData DidCalculateSize(uint64_t total_size,
+ uint64_t content_size) override {
+ total_size_ = total_size;
+ bool result = byte_range_.ComputeBounds(total_size);
+ DCHECK(result);
net::HttpStatusCode status_code = net::HTTP_OK;
if (byte_range_set_ && byte_range_.IsValid()) {
status_code = net::HTTP_PARTIAL_CONTENT;
} else {
+ DCHECK_EQ(total_size, content_size);
// TODO(horo): When the requester doesn't need the side data
// (ex:FileReader) we should skip reading the side data.
- if (blob_reader_->has_side_data() &&
- blob_reader_->ReadSideData(base::Bind(&BlobURLLoader::DidReadMetadata,
- weak_factory_.GetWeakPtr())) ==
- storage::BlobReader::Status::IO_PENDING) {
- return;
- }
+ return REQUEST_SIDE_DATA;
}
- HeadersCompleted(status_code);
+ HeadersCompleted(status_code, content_size, nullptr);
+ return DONT_REQUEST_SIDE_DATA;
}
- void DidReadMetadata(storage::BlobReader::Status result) {
- if (result != storage::BlobReader::Status::DONE) {
- NotifyCompleted(blob_reader_->net_error());
- return;
- }
- HeadersCompleted(net::HTTP_OK);
+ void DidReadSideData(net::IOBufferWithSize* data) override {
+ HeadersCompleted(net::HTTP_OK, total_size_, data);
}
- void HeadersCompleted(net::HttpStatusCode status_code) {
+ void HeadersCompleted(net::HttpStatusCode status_code,
+ uint64_t content_size,
+ net::IOBufferWithSize* metadata) {
ResourceResponseHead response;
response.content_length = 0;
+ if (status_code == net::HTTP_OK || status_code == net::HTTP_PARTIAL_CONTENT)
+ response.content_length = content_size;
response.headers = storage::BlobURLRequestJob::GenerateHeaders(
- status_code, blob_handle_.get(), blob_reader_.get(), &byte_range_,
- &response.content_length);
+ status_code, blob_handle_.get(), &byte_range_, total_size_,
+ content_size);
std::string mime_type;
response.headers->GetMimeType(&mime_type);
@@ -214,132 +163,51 @@ class BlobURLLoader : public mojom::URLLoader {
client_->OnReceiveResponse(response, base::nullopt, nullptr);
sent_headers_ = true;
- net::IOBufferWithSize* metadata = blob_reader_->side_data();
if (metadata) {
const uint8_t* data = reinterpret_cast<const uint8_t*>(metadata->data());
client_->OnReceiveCachedMetadata(
std::vector<uint8_t>(data, data + metadata->size()));
}
-
- mojo::DataPipe data_pipe(kDefaultAllocationSize);
- response_body_stream_ = std::move(data_pipe.producer_handle);
- response_body_consumer_handle_ = std::move(data_pipe.consumer_handle);
- peer_closed_handle_watcher_.Watch(
- response_body_stream_.get(), MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- base::Bind(&BlobURLLoader::OnResponseBodyStreamClosed,
- base::Unretained(this)));
- peer_closed_handle_watcher_.ArmOrNotify();
-
- writable_handle_watcher_.Watch(
- response_body_stream_.get(), MOJO_HANDLE_SIGNAL_WRITABLE,
- base::Bind(&BlobURLLoader::OnResponseBodyStreamReady,
- base::Unretained(this)));
-
- // Start reading...
- ReadMore();
- }
-
- void ReadMore() {
- DCHECK(!pending_write_.get());
-
- uint32_t num_bytes;
- // TODO: we should use the abstractions in MojoAsyncResourceHandler.
- MojoResult result = NetToMojoPendingBuffer::BeginWrite(
- &response_body_stream_, &pending_write_, &num_bytes);
- if (result == MOJO_RESULT_SHOULD_WAIT) {
- // The pipe is full. We need to wait for it to have more space.
- writable_handle_watcher_.ArmOrNotify();
- return;
- } else if (result != MOJO_RESULT_OK) {
- // The response body stream is in a bad state. Bail.
- writable_handle_watcher_.Cancel();
- response_body_stream_.reset();
- NotifyCompleted(net::ERR_UNEXPECTED);
- return;
- }
-
- CHECK_GT(static_cast<uint32_t>(std::numeric_limits<int>::max()), num_bytes);
- scoped_refptr<net::IOBuffer> buf(
- new NetToMojoIOBuffer(pending_write_.get()));
- int bytes_read;
- storage::BlobReader::Status read_status = blob_reader_->Read(
- buf.get(), static_cast<int>(num_bytes), &bytes_read,
- base::Bind(&BlobURLLoader::DidRead, weak_factory_.GetWeakPtr(), false));
- switch (read_status) {
- case storage::BlobReader::Status::NET_ERROR:
- NotifyCompleted(blob_reader_->net_error());
- return;
- case storage::BlobReader::Status::IO_PENDING:
- // Wait for DidRead.
- return;
- case storage::BlobReader::Status::DONE:
- if (bytes_read > 0) {
- DidRead(true, bytes_read);
- } else {
- writable_handle_watcher_.Cancel();
- pending_write_->Complete(0);
- pending_write_ = nullptr; // This closes the data pipe.
- NotifyCompleted(net::OK);
- return;
- }
- }
}
- void DidRead(bool completed_synchronously, int num_bytes) {
+ void DidRead(int num_bytes) override {
if (response_body_consumer_handle_.is_valid()) {
// Send the data pipe on the first OnReadCompleted call.
client_->OnStartLoadingResponseBody(
std::move(response_body_consumer_handle_));
}
- response_body_stream_ = pending_write_->Complete(num_bytes);
- total_written_bytes_ += num_bytes;
- pending_write_ = nullptr;
- if (completed_synchronously) {
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::Bind(&BlobURLLoader::ReadMore, weak_factory_.GetWeakPtr()));
- } else {
- ReadMore();
- }
- }
-
- void OnResponseBodyStreamClosed(MojoResult result) {
- response_body_stream_.reset();
- pending_write_ = nullptr;
- DeleteIfNeeded();
- }
-
- void OnResponseBodyStreamReady(MojoResult result) {
- // TODO: Handle a bad |result| value.
- DCHECK_EQ(result, MOJO_RESULT_OK);
- ReadMore();
}
- void DeleteIfNeeded() {
- bool has_data_pipe =
- pending_write_.get() || response_body_stream_.is_valid();
- if (!has_data_pipe)
- delete this;
+ void OnComplete(net::Error error_code,
+ uint64_t total_written_bytes) override {
+ if (error_code != net::OK && !sent_headers_) {
+ net::HttpStatusCode status_code =
+ storage::BlobURLRequestJob::NetErrorToHttpStatusCode(error_code);
+ ResourceResponseHead response;
+ response.headers = storage::BlobURLRequestJob::GenerateHeaders(
+ status_code, nullptr, nullptr, 0, 0);
+ client_->OnReceiveResponse(response, base::nullopt, nullptr);
+ }
+ ResourceRequestCompletionStatus request_complete_data;
+ // TODO(kinuko): We should probably set the error_code here,
+ // while it makes existing tests fail. crbug.com/732750
+ request_complete_data.completion_time = base::TimeTicks::Now();
+ request_complete_data.encoded_body_length = total_written_bytes;
+ request_complete_data.decoded_body_length = total_written_bytes;
+ client_->OnComplete(request_complete_data);
}
- mojo::AssociatedBinding<mojom::URLLoader> binding_;
+ mojo::Binding<mojom::URLLoader> binding_;
mojom::URLLoaderClientPtr client_;
bool byte_range_set_ = false;
net::HttpByteRange byte_range_;
+ uint64_t total_size_ = 0;
bool sent_headers_ = false;
std::unique_ptr<storage::BlobDataHandle> blob_handle_;
- std::unique_ptr<storage::BlobReader> blob_reader_;
-
- // TODO(jam): share with URLLoaderImpl
- mojo::ScopedDataPipeProducerHandle response_body_stream_;
mojo::ScopedDataPipeConsumerHandle response_body_consumer_handle_;
- scoped_refptr<NetToMojoPendingBuffer> pending_write_;
- mojo::SimpleWatcher writable_handle_watcher_;
- mojo::SimpleWatcher peer_closed_handle_watcher_;
- int64_t total_written_bytes_ = 0;
base::WeakPtrFactory<BlobURLLoader> weak_factory_;
@@ -389,7 +257,7 @@ void BlobURLLoaderFactory::BindOnIO(mojom::URLLoaderFactoryRequest request) {
// static
void BlobURLLoaderFactory::CreateLoaderAndStart(
- mojom::URLLoaderAssociatedRequest loader,
+ mojom::URLLoaderRequest loader,
const ResourceRequest& request,
mojom::URLLoaderClientPtr client,
std::unique_ptr<storage::BlobDataHandle> blob_handle,
@@ -399,7 +267,7 @@ void BlobURLLoaderFactory::CreateLoaderAndStart(
}
void BlobURLLoaderFactory::CreateLoaderAndStart(
- mojom::URLLoaderAssociatedRequest loader,
+ mojom::URLLoaderRequest loader,
int32_t routing_id,
int32_t request_id,
uint32_t options,
@@ -415,11 +283,8 @@ void BlobURLLoaderFactory::CreateLoaderAndStart(
std::move(blob_handle), file_system_context_.get());
}
-void BlobURLLoaderFactory::SyncLoad(int32_t routing_id,
- int32_t request_id,
- const ResourceRequest& request,
- SyncLoadCallback callback) {
- NOTREACHED();
+void BlobURLLoaderFactory::Clone(mojom::URLLoaderFactoryRequest request) {
+ loader_factory_bindings_.AddBinding(this, std::move(request));
}
} // namespace content
diff --git a/chromium/content/browser/blob_storage/blob_url_loader_factory.h b/chromium/content/browser/blob_storage/blob_url_loader_factory.h
index a58effb31f7..11a2af8ff65 100644
--- a/chromium/content/browser/blob_storage/blob_url_loader_factory.h
+++ b/chromium/content/browser/blob_storage/blob_url_loader_factory.h
@@ -44,14 +44,14 @@ class BlobURLLoaderFactory
// Note that given |request|'s URL is not referenced, but only method and
// range headers are used.
static void CreateLoaderAndStart(
- mojom::URLLoaderAssociatedRequest url_loader_request,
+ mojom::URLLoaderRequest url_loader_request,
const ResourceRequest& request,
mojom::URLLoaderClientPtr client,
std::unique_ptr<storage::BlobDataHandle> blob_handle,
storage::FileSystemContext* file_system_context);
// mojom::URLLoaderFactory implementation:
- void CreateLoaderAndStart(mojom::URLLoaderAssociatedRequest loader,
+ void CreateLoaderAndStart(mojom::URLLoaderRequest loader,
int32_t routing_id,
int32_t request_id,
uint32_t options,
@@ -59,10 +59,7 @@ class BlobURLLoaderFactory
mojom::URLLoaderClientPtr client,
const net::MutableNetworkTrafficAnnotationTag&
traffic_annotation) override;
- void SyncLoad(int32_t routing_id,
- int32_t request_id,
- const ResourceRequest& request,
- SyncLoadCallback callback) override;
+ void Clone(mojom::URLLoaderFactoryRequest request) override;
private:
friend class base::DeleteHelper<BlobURLLoaderFactory>;
diff --git a/chromium/content/browser/blob_storage/blob_url_unittest.cc b/chromium/content/browser/blob_storage/blob_url_unittest.cc
index bfe3ce2f0b4..da49844e97d 100644
--- a/chromium/content/browser/blob_storage/blob_url_unittest.cc
+++ b/chromium/content/browser/blob_storage/blob_url_unittest.cc
@@ -90,7 +90,7 @@ std::unique_ptr<disk_cache::Backend> CreateInMemoryDiskCache() {
net::TestCompletionCallback callback;
int rv = disk_cache::CreateCacheBackend(
net::MEMORY_CACHE, net::CACHE_BACKEND_DEFAULT, base::FilePath(), 0, false,
- nullptr, nullptr, &cache, callback.callback());
+ nullptr, &cache, callback.callback());
EXPECT_EQ(net::OK, callback.GetResult(rv));
return cache;
@@ -200,8 +200,8 @@ class BlobURLRequestJobTest : public testing::TestWithParam<bool> {
file_system_context_->OpenFileSystem(
GURL(kFileSystemURLOrigin), kFileSystemType,
storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
- base::Bind(&BlobURLRequestJobTest::OnValidateFileSystem,
- base::Unretained(this)));
+ base::BindOnce(&BlobURLRequestJobTest::OnValidateFileSystem,
+ base::Unretained(this)));
base::RunLoop().RunUntilIdle();
ASSERT_TRUE(file_system_root_url_.is_valid());
@@ -280,12 +280,12 @@ class BlobURLRequestJobTest : public testing::TestWithParam<bool> {
if (!extra_headers.IsEmpty())
request.headers = extra_headers.ToString();
- mojom::URLLoaderAssociatedPtr url_loader;
+ mojom::URLLoaderPtr url_loader;
TestURLLoaderClient url_loader_client;
scoped_refptr<BlobURLLoaderFactory> factory =
BlobURLLoaderFactory::Create(
- base::Bind(&BlobURLRequestJobTest::GetStorageContext,
- base::Unretained(this)),
+ base::BindOnce(&BlobURLRequestJobTest::GetStorageContext,
+ base::Unretained(this)),
file_system_context_);
base::RunLoop().RunUntilIdle();
factory->CreateLoaderAndStart(mojo::MakeRequest(&url_loader), 0, 0,
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 d814ea2e04c..325736ab142 100644
--- a/chromium/content/browser/blob_storage/chrome_blob_storage_context.cc
+++ b/chromium/content/browser/blob_storage/chrome_blob_storage_context.cc
@@ -112,16 +112,16 @@ ChromeBlobStorageContext* ChromeBlobStorageContext::GetFor(
// Removes our old blob directories if they exist.
BrowserThread::PostAfterStartupTask(
FROM_HERE, file_task_runner,
- base::Bind(&RemoveOldBlobStorageDirectories,
- base::Passed(&blob_storage_parent), blob_storage_dir));
+ base::BindOnce(&RemoveOldBlobStorageDirectories,
+ base::Passed(&blob_storage_parent), blob_storage_dir));
}
if (io_thread_valid) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&ChromeBlobStorageContext::InitializeOnIOThread, blob,
- base::Passed(&blob_storage_dir),
- base::Passed(&file_task_runner)));
+ base::BindOnce(&ChromeBlobStorageContext::InitializeOnIOThread, blob,
+ base::Passed(&blob_storage_dir),
+ base::Passed(&file_task_runner)));
}
}
@@ -139,8 +139,8 @@ void ChromeBlobStorageContext::InitializeOnIOThread(
// storage limits.
BrowserThread::PostAfterStartupTask(
FROM_HERE, BrowserThread::GetTaskRunnerForThread(BrowserThread::IO),
- base::Bind(&storage::BlobMemoryController::CalculateBlobStorageLimits,
- context_->mutable_memory_controller()->GetWeakPtr()));
+ base::BindOnce(&storage::BlobMemoryController::CalculateBlobStorageLimits,
+ context_->mutable_memory_controller()->GetWeakPtr()));
}
std::unique_ptr<BlobHandle> ChromeBlobStorageContext::CreateMemoryBackedBlob(
diff --git a/chromium/content/browser/bluetooth/bluetooth_device_chooser_controller.cc b/chromium/content/browser/bluetooth/bluetooth_device_chooser_controller.cc
index ed7de745066..3beb85b93e9 100644
--- a/chromium/content/browser/bluetooth/bluetooth_device_chooser_controller.cc
+++ b/chromium/content/browser/bluetooth/bluetooth_device_chooser_controller.cc
@@ -610,8 +610,8 @@ void BluetoothDeviceChooserController::PostSuccessCallback(
const std::string& device_address) {
if (!base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
- base::Bind(success_callback_, base::Passed(std::move(options_)),
- device_address))) {
+ base::BindOnce(success_callback_, base::Passed(std::move(options_)),
+ device_address))) {
LOG(WARNING) << "No TaskRunner.";
}
}
@@ -619,7 +619,7 @@ void BluetoothDeviceChooserController::PostSuccessCallback(
void BluetoothDeviceChooserController::PostErrorCallback(
blink::mojom::WebBluetoothResult error) {
if (!base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(error_callback_, error))) {
+ FROM_HERE, base::BindOnce(error_callback_, error))) {
LOG(WARNING) << "No TaskRunner.";
}
}
diff --git a/chromium/content/browser/bluetooth/web_bluetooth_service_impl.cc b/chromium/content/browser/bluetooth/web_bluetooth_service_impl.cc
index 4edb4da4d37..13d802fa72c 100644
--- a/chromium/content/browser/bluetooth/web_bluetooth_service_impl.cc
+++ b/chromium/content/browser/bluetooth/web_bluetooth_service_impl.cc
@@ -261,9 +261,10 @@ void WebBluetoothServiceImpl::GattCharacteristicValueChanged(
// in an event being fired before the readValue promise is resolved.
if (!base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
- base::Bind(&WebBluetoothServiceImpl::NotifyCharacteristicValueChanged,
- weak_ptr_factory_.GetWeakPtr(),
- characteristic->GetIdentifier(), value))) {
+ base::BindOnce(
+ &WebBluetoothServiceImpl::NotifyCharacteristicValueChanged,
+ weak_ptr_factory_.GetWeakPtr(), characteristic->GetIdentifier(),
+ value))) {
LOG(WARNING) << "No TaskRunner.";
}
}
diff --git a/chromium/content/browser/bluetooth/web_bluetooth_service_impl.h b/chromium/content/browser/bluetooth/web_bluetooth_service_impl.h
index c28200ebf10..5ecd3e0b7e9 100644
--- a/chromium/content/browser/bluetooth/web_bluetooth_service_impl.h
+++ b/chromium/content/browser/bluetooth/web_bluetooth_service_impl.h
@@ -47,7 +47,7 @@ class RenderProcessHost;
// RenderFrameHostImpl will create an instance of this class and keep
// ownership of it.
class CONTENT_EXPORT WebBluetoothServiceImpl
- : public NON_EXPORTED_BASE(blink::mojom::WebBluetoothService),
+ : public blink::mojom::WebBluetoothService,
public WebContentsObserver,
public device::BluetoothAdapter::Observer {
public:
diff --git a/chromium/content/browser/browser_associated_interface_unittest.cc b/chromium/content/browser/browser_associated_interface_unittest.cc
index 491f9dd0d8f..bf814f2aa97 100644
--- a/chromium/content/browser/browser_associated_interface_unittest.cc
+++ b/chromium/content/browser/browser_associated_interface_unittest.cc
@@ -106,7 +106,7 @@ class TestDriverMessageFilter
void RequestQuit(RequestQuitCallback callback) override {
EXPECT_EQ(kNumTestMessages, message_count_);
std::move(callback).Run();
- base::MessageLoop::current()->QuitWhenIdle();
+ base::RunLoop::QuitCurrentWhenIdleDeprecated();
}
std::string next_expected_string_;
@@ -119,7 +119,7 @@ class TestClientRunner {
: client_thread_("Test client") {
client_thread_.Start();
client_thread_.task_runner()->PostTask(
- FROM_HERE, base::Bind(&RunTestClient, base::Passed(&pipe)));
+ FROM_HERE, base::BindOnce(&RunTestClient, base::Passed(&pipe)));
}
~TestClientRunner() {
diff --git a/chromium/content/browser/browser_child_process_host_impl.cc b/chromium/content/browser/browser_child_process_host_impl.cc
index 15f619a089d..bf3331eef96 100644
--- a/chromium/content/browser/browser_child_process_host_impl.cc
+++ b/chromium/content/browser/browser_child_process_host_impl.cc
@@ -181,8 +181,9 @@ BrowserChildProcessHostImpl::~BrowserChildProcessHostImpl() {
g_child_process_list.Get().remove(this);
if (notify_child_disconnected_) {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(&NotifyProcessHostDisconnected, data_));
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&NotifyProcessHostDisconnected, data_));
}
}
@@ -312,7 +313,7 @@ void BrowserChildProcessHostImpl::BindInterface(
}
void BrowserChildProcessHostImpl::HistogramBadMessageTerminated(
- int process_type) {
+ ProcessType process_type) {
UMA_HISTOGRAM_ENUMERATION("ChildProcess.BadMessgeTerminated", process_type,
PROCESS_TYPE_MAX);
}
@@ -344,15 +345,15 @@ void BrowserChildProcessHostImpl::OnChannelConnected(int32_t peer_pid) {
#endif
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(&NotifyProcessHostConnected, data_));
+ base::BindOnce(&NotifyProcessHostConnected, data_));
delegate_->OnChannelConnected(peer_pid);
if (IsProcessLaunched()) {
ShareMetricsAllocatorToProcess();
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(&NotifyProcessLaunchedAndConnected,
- data_));
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&NotifyProcessLaunchedAndConnected, data_));
}
}
@@ -369,7 +370,7 @@ void BrowserChildProcessHostImpl::OnBadMessageReceived(
void BrowserChildProcessHostImpl::TerminateOnBadMessageReceived(
const std::string& error) {
- HistogramBadMessageTerminated(data_.process_type);
+ HistogramBadMessageTerminated(static_cast<ProcessType>(data_.process_type));
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableKillAfterBadIPC)) {
return;
@@ -407,9 +408,9 @@ void BrowserChildProcessHostImpl::OnChildDisconnected() {
delegate_->OnProcessCrashed(exit_code);
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&NotifyProcessCrashed, data_, exit_code));
+ base::BindOnce(&NotifyProcessCrashed, data_, exit_code));
UMA_HISTOGRAM_ENUMERATION("ChildProcess.Crashed2",
- data_.process_type,
+ static_cast<ProcessType>(data_.process_type),
PROCESS_TYPE_MAX);
break;
}
@@ -423,28 +424,28 @@ void BrowserChildProcessHostImpl::OnChildDisconnected() {
delegate_->OnProcessCrashed(exit_code);
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&NotifyProcessKilled, data_, exit_code));
+ base::BindOnce(&NotifyProcessKilled, data_, exit_code));
// Report that this child process was killed.
UMA_HISTOGRAM_ENUMERATION("ChildProcess.Killed2",
- data_.process_type,
+ static_cast<ProcessType>(data_.process_type),
PROCESS_TYPE_MAX);
break;
}
case base::TERMINATION_STATUS_STILL_RUNNING: {
UMA_HISTOGRAM_ENUMERATION("ChildProcess.DisconnectedAlive2",
- data_.process_type,
+ static_cast<ProcessType>(data_.process_type),
PROCESS_TYPE_MAX);
}
default:
break;
}
UMA_HISTOGRAM_ENUMERATION("ChildProcess.Disconnected2",
- data_.process_type,
+ static_cast<ProcessType>(data_.process_type),
PROCESS_TYPE_MAX);
#if defined(OS_CHROMEOS)
if (status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED_BY_OOM) {
UMA_HISTOGRAM_ENUMERATION("ChildProcess.Killed2.OOM",
- data_.process_type,
+ static_cast<ProcessType>(data_.process_type),
PROCESS_TYPE_MAX);
}
#endif
@@ -469,7 +470,8 @@ void BrowserChildProcessHostImpl::CreateMetricsAllocator() {
base::StringPiece metrics_name;
switch (data_.process_type) {
case PROCESS_TYPE_UTILITY:
- memory_size = 64 << 10; // 64 KiB
+ // This needs to be larger for the network service.
+ memory_size = 256 << 10; // 256 KiB
metrics_name = "UtilityMetrics";
break;
@@ -559,9 +561,9 @@ void BrowserChildProcessHostImpl::OnProcessLaunched() {
if (is_channel_connected_) {
ShareMetricsAllocatorToProcess();
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(&NotifyProcessLaunchedAndConnected,
- data_));
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&NotifyProcessLaunchedAndConnected, data_));
}
}
@@ -578,13 +580,14 @@ void BrowserChildProcessHostImpl::OnMojoError(
const std::string& error) {
if (!task_runner->BelongsToCurrentThread()) {
task_runner->PostTask(
- FROM_HERE, base::Bind(&BrowserChildProcessHostImpl::OnMojoError,
- process, task_runner, error));
+ FROM_HERE, base::BindOnce(&BrowserChildProcessHostImpl::OnMojoError,
+ process, task_runner, error));
return;
}
if (!process)
return;
- HistogramBadMessageTerminated(process->data_.process_type);
+ HistogramBadMessageTerminated(
+ static_cast<ProcessType>(process->data_.process_type));
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableKillAfterBadIPC)) {
return;
diff --git a/chromium/content/browser/browser_child_process_host_impl.h b/chromium/content/browser/browser_child_process_host_impl.h
index d91d1adce3a..7d23f161b6f 100644
--- a/chromium/content/browser/browser_child_process_host_impl.h
+++ b/chromium/content/browser/browser_child_process_host_impl.h
@@ -44,7 +44,7 @@ class ChildConnection;
/// class because it lives on the UI thread.
class CONTENT_EXPORT BrowserChildProcessHostImpl
: public BrowserChildProcessHost,
- public NON_EXPORTED_BASE(ChildProcessHostDelegate),
+ public ChildProcessHostDelegate,
#if defined(OS_WIN)
public base::win::ObjectWatcher::Delegate,
#endif
@@ -101,7 +101,7 @@ class CONTENT_EXPORT BrowserChildProcessHostImpl
// Adds an IPC message filter.
void AddFilter(BrowserMessageFilter* filter);
- static void HistogramBadMessageTerminated(int process_type);
+ static void HistogramBadMessageTerminated(ProcessType process_type);
BrowserChildProcessHostDelegate* delegate() const { return delegate_; }
diff --git a/chromium/content/browser/browser_context.cc b/chromium/content/browser/browser_context.cc
index 1dddb591f0e..42b002908c3 100644
--- a/chromium/content/browser/browser_context.cc
+++ b/chromium/content/browser/browser_context.cc
@@ -370,7 +370,7 @@ void BrowserContext::NotifyWillBeDestroyed(BrowserContext* browser_context) {
RenderProcessHost* host = host_iterator.GetCurrentValue();
if (host->GetBrowserContext() == browser_context) {
// This will also clean up spare RPH references.
- host->ForceReleaseWorkerRefCounts();
+ host->DisableKeepAliveRefCount();
}
}
}
@@ -388,18 +388,24 @@ void BrowserContext::EnsureResourceContextInitialized(BrowserContext* context) {
}
void BrowserContext::SaveSessionState(BrowserContext* browser_context) {
- GetDefaultStoragePartition(browser_context)->GetDatabaseTracker()->
- SetForceKeepSessionState();
StoragePartition* storage_partition =
BrowserContext::GetDefaultStoragePartition(browser_context);
+ storage::DatabaseTracker* database_tracker =
+ storage_partition->GetDatabaseTracker();
+ database_tracker->task_runner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&storage::DatabaseTracker::SetForceKeepSessionState,
+ make_scoped_refptr(database_tracker)));
+
if (BrowserThread::IsMessageLoopValid(BrowserThread::IO)) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(
+ base::BindOnce(
&SaveSessionStateOnIOThread,
- make_scoped_refptr(BrowserContext::GetDefaultStoragePartition(
- browser_context)->GetURLRequestContext()),
+ make_scoped_refptr(
+ BrowserContext::GetDefaultStoragePartition(browser_context)
+ ->GetURLRequestContext()),
static_cast<AppCacheServiceImpl*>(
storage_partition->GetAppCacheService())));
}
@@ -415,9 +421,8 @@ void BrowserContext::SaveSessionState(BrowserContext* browser_context) {
// No task runner in unit tests.
if (indexed_db_context_impl->TaskRunner()) {
indexed_db_context_impl->TaskRunner()->PostTask(
- FROM_HERE,
- base::Bind(&SaveSessionStateOnIndexedDBThread,
- make_scoped_refptr(indexed_db_context_impl)));
+ FROM_HERE, base::BindOnce(&SaveSessionStateOnIndexedDBThread,
+ make_scoped_refptr(indexed_db_context_impl)));
}
}
diff --git a/chromium/content/browser/browser_main_loop.cc b/chromium/content/browser/browser_main_loop.cc
index 18a8cd05606..e1eabbfcd42 100644
--- a/chromium/content/browser/browser_main_loop.cc
+++ b/chromium/content/browser/browser_main_loop.cc
@@ -49,10 +49,10 @@
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "components/discardable_memory/service/discardable_shared_memory_manager.h"
-#include "components/tracing/common/process_metrics_memory_dump_provider.h"
#include "components/tracing/common/trace_config_file.h"
#include "components/tracing/common/trace_to_console.h"
#include "components/tracing/common/tracing_switches.h"
+#include "components/viz/common/switches.h"
#include "components/viz/host/host_frame_sink_manager.h"
#include "components/viz/service/display_embedder/server_shared_bitmap_manager.h"
#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
@@ -74,7 +74,7 @@
#include "content/browser/loader_delegate_impl.h"
#include "content/browser/media/media_internals.h"
#include "content/browser/memory/memory_coordinator_impl.h"
-#include "content/browser/memory/swap_metrics_observer.h"
+#include "content/browser/memory/swap_metrics_delegate_uma.h"
#include "content/browser/net/browser_online_state_observer.h"
#include "content/browser/renderer_host/media/media_stream_manager.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
@@ -91,6 +91,7 @@
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/gpu_data_manager_observer.h"
#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/swap_metrics_driver.h"
#include "content/public/browser/tracing_controller.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_features.h"
@@ -105,6 +106,7 @@
#include "media/audio/audio_thread_impl.h"
#include "media/base/media.h"
#include "media/base/user_input_monitor.h"
+#include "media/media_features.h"
#include "media/midi/midi_service.h"
#include "media/mojo/features.h"
#include "mojo/edk/embedder/embedder.h"
@@ -186,6 +188,13 @@
#include "media/device_monitors/device_monitor_mac.h"
#endif
+#if defined(OS_FUCHSIA)
+#include <magenta/process.h>
+#include <magenta/syscalls.h>
+
+#include "base/fuchsia/default_job.h"
+#endif // defined(OS_FUCHSIA)
+
#if defined(OS_POSIX) && !defined(OS_MACOSX)
#include "content/browser/renderer_host/render_sandbox_host_linux.h"
#include "content/browser/zygote_host/zygote_host_impl_linux.h"
@@ -201,7 +210,7 @@
#include "content/browser/plugin_service_impl.h"
#endif
-#if BUILDFLAG(ENABLE_MOJO_CDM) && BUILDFLAG(ENABLE_PEPPER_CDMS)
+#if BUILDFLAG(ENABLE_MOJO_CDM) && BUILDFLAG(ENABLE_LIBRARY_CDMS)
#include "content/browser/media/cdm_registry_impl.h"
#endif
@@ -228,7 +237,16 @@
namespace content {
namespace {
-#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
+bool IsUsingMus() {
+#if defined(USE_AURA)
+ return aura::Env::GetInstance()->mode() == aura::Env::Mode::MUS;
+#else
+ return false;
+#endif
+}
+
+#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) && \
+ !defined(OS_FUCHSIA)
void SetupSandbox(const base::CommandLine& parsed_command_line) {
TRACE_EVENT0("startup", "SetupSandbox");
// RenderSandboxHostLinux needs to be initialized even if the sandbox and
@@ -250,7 +268,8 @@ void SetupSandbox(const base::CommandLine& parsed_command_line) {
ZygoteHostImpl::GetInstance()->SetRendererSandboxStatus(
generic_zygote->GetSandboxStatus());
}
-#endif
+#endif // defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) && \
+ // !defined(OS_FUCHSIA)
#if defined(USE_GLIB)
static void GLibLogHandler(const gchar* log_domain,
@@ -403,56 +422,64 @@ enum WorkerPoolType : size_t {
std::unique_ptr<base::TaskScheduler::InitParams>
GetDefaultTaskSchedulerInitParams() {
- using StandbyThreadPolicy =
- base::SchedulerWorkerPoolParams::StandbyThreadPolicy;
#if defined(OS_ANDROID)
// Mobile config, for iOS see ios/web/app/web_main_loop.cc.
return base::MakeUnique<base::TaskScheduler::InitParams>(
base::SchedulerWorkerPoolParams(
- StandbyThreadPolicy::ONE,
base::RecommendedMaxNumberOfThreadsInPool(2, 8, 0.1, 0),
base::TimeDelta::FromSeconds(30)),
base::SchedulerWorkerPoolParams(
- StandbyThreadPolicy::ONE,
base::RecommendedMaxNumberOfThreadsInPool(2, 8, 0.1, 0),
base::TimeDelta::FromSeconds(30)),
base::SchedulerWorkerPoolParams(
- StandbyThreadPolicy::ONE,
base::RecommendedMaxNumberOfThreadsInPool(3, 8, 0.3, 0),
base::TimeDelta::FromSeconds(30)),
base::SchedulerWorkerPoolParams(
- StandbyThreadPolicy::ONE,
base::RecommendedMaxNumberOfThreadsInPool(3, 8, 0.3, 0),
base::TimeDelta::FromSeconds(60)));
#else
// Desktop config.
return base::MakeUnique<base::TaskScheduler::InitParams>(
base::SchedulerWorkerPoolParams(
- StandbyThreadPolicy::ONE,
base::RecommendedMaxNumberOfThreadsInPool(3, 8, 0.1, 0),
base::TimeDelta::FromSeconds(30)),
base::SchedulerWorkerPoolParams(
- StandbyThreadPolicy::ONE,
base::RecommendedMaxNumberOfThreadsInPool(3, 8, 0.1, 0),
base::TimeDelta::FromSeconds(40)),
base::SchedulerWorkerPoolParams(
- StandbyThreadPolicy::ONE,
base::RecommendedMaxNumberOfThreadsInPool(8, 32, 0.3, 0),
base::TimeDelta::FromSeconds(30)),
// Tasks posted to SequencedWorkerPool or BrowserThreadImpl may be
// redirected to this pool. Since COM STA is initialized in these
// environments, it must also be initialized in this pool.
base::SchedulerWorkerPoolParams(
- StandbyThreadPolicy::ONE,
base::RecommendedMaxNumberOfThreadsInPool(8, 32, 0.3, 0),
base::TimeDelta::FromSeconds(60),
base::SchedulerBackwardCompatibility::INIT_COM_STA));
#endif
}
+#if !defined(OS_FUCHSIA)
+// Time between updating and recording swap rates.
+constexpr base::TimeDelta kSwapMetricsInterval =
+ base::TimeDelta::FromSeconds(60);
+#endif // !defined(OS_FUCHSIA)
+
+#if defined(OS_FUCHSIA)
+// Create and register the job which will contain all child processes
+// of the browser process as well as their descendents.
+void InitDefaultJob() {
+ base::ScopedMxHandle handle;
+ mx_status_t result = mx_job_create(mx_job_default(), 0, handle.receive());
+ CHECK_EQ(MX_OK, result) << "mx_job_create(job): "
+ << mx_status_get_string(result);
+ base::SetDefaultJob(std::move(handle));
+}
+#endif // defined(OS_FUCHSIA)
+
} // namespace
-#if defined(USE_X11) && !defined(OS_CHROMEOS)
+#if defined(USE_X11)
namespace internal {
// Forwards GPUInfo updates to ui::XVisualManager
@@ -543,7 +570,8 @@ void BrowserMainLoop::Init() {
void BrowserMainLoop::EarlyInitialization() {
TRACE_EVENT0("startup", "BrowserMainLoop::EarlyInitialization");
-#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
+#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) && \
+ !defined(OS_FUCHSIA)
// No thread should be created before this call, as SetupSandbox()
// will end-up using fork().
SetupSandbox(parsed_command_line_);
@@ -599,6 +627,10 @@ void BrowserMainLoop::EarlyInitialization() {
crypto::EnsureNSPRInit();
#endif
+#if defined(OS_FUCHSIA)
+ InitDefaultJob();
+#endif
+
if (parsed_command_line_.HasSwitch(switches::kRendererProcessLimit)) {
std::string limit_string = parsed_command_line_.GetSwitchValueASCII(
switches::kRendererProcessLimit);
@@ -689,9 +721,7 @@ void BrowserMainLoop::PostMainMessageLoopStart() {
BrowserThread::GetTaskRunnerForThread(BrowserThread::UI));
}
- // Only use discardable_memory::DiscardableSharedMemoryManager when Chrome is
- // not running in mus+ash.
- if (!service_manager::ServiceManagerIsRemote()) {
+ if (parameters_.create_discardable_memory) {
discardable_shared_memory_manager_ =
base::MakeUnique<discardable_memory::DiscardableSharedMemoryManager>();
// TODO(boliu): kSingleProcess check is a temporary workaround for
@@ -778,8 +808,6 @@ void BrowserMainLoop::PostMainMessageLoopStart() {
// Enable memory-infra dump providers.
InitSkiaEventTracer();
- tracing::ProcessMetricsMemoryDumpProvider::RegisterForProcess(
- base::kNullProcessId);
base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
viz::ServerSharedBitmapManager::current(),
"viz::ServerSharedBitmapManager", nullptr);
@@ -839,7 +867,7 @@ int BrowserMainLoop::PreCreateThreads() {
}
#endif
-#if BUILDFLAG(ENABLE_MOJO_CDM) && BUILDFLAG(ENABLE_PEPPER_CDMS)
+#if BUILDFLAG(ENABLE_MOJO_CDM) && BUILDFLAG(ENABLE_LIBRARY_CDMS)
// Prior to any processing happening on the IO thread, we create the
// CDM service as it is predominantly used from the IO thread. This must
// be called on the main thread since it involves file path checks.
@@ -855,7 +883,7 @@ int BrowserMainLoop::PreCreateThreads() {
GpuDataManagerImpl* gpu_data_manager = GpuDataManagerImpl::GetInstance();
-#if defined(USE_X11) && !defined(OS_CHROMEOS)
+#if defined(USE_X11)
// GpuDataManagerVisualProxy() just adds itself as an observer of
// |gpu_data_manager|, which is safe to do before Initialize().
gpu_data_manager_visual_proxy_.reset(
@@ -978,7 +1006,6 @@ int BrowserMainLoop::CreateThreads() {
task_scheduler_init_params->foreground_worker_pool_params);
task_scheduler_init_params->foreground_worker_pool_params =
base::SchedulerWorkerPoolParams(
- current_foreground_worker_pool_params.standby_thread_policy(),
std::max(GetMinThreadsInRendererTaskSchedulerForegroundPool(),
current_foreground_worker_pool_params.max_threads()),
current_foreground_worker_pool_params.suggested_reclaim_time(),
@@ -1186,8 +1213,8 @@ void BrowserMainLoop::ShutdownThreadsAndCleanUp() {
base::ThreadRestrictions::SetIOAllowed(true);
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(base::IgnoreResult(&base::ThreadRestrictions::SetIOAllowed),
- true));
+ base::BindOnce(
+ base::IgnoreResult(&base::ThreadRestrictions::SetIOAllowed), true));
#if defined(OS_ANDROID)
g_browser_main_loop_shutting_down = true;
@@ -1429,7 +1456,7 @@ int BrowserMainLoop::BrowserThreadsStarted() {
memory_instrumentation::ClientProcessImpl::CreateInstance(config);
#if defined(USE_AURA)
- if (service_manager::ServiceManagerIsRemote()) {
+ if (IsUsingMus()) {
base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kIsRunningInMash);
}
@@ -1452,8 +1479,7 @@ int BrowserMainLoop::BrowserThreadsStarted() {
// BrowserGpuChannelHostFactory below, since that depends on an initialized
// ShaderCacheFactory.
InitShaderCacheFactorySingleton(
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO),
- BrowserThread::GetTaskRunnerForThread(BrowserThread::CACHE));
+ BrowserThread::GetTaskRunnerForThread(BrowserThread::IO));
bool always_uses_gpu = true;
bool established_gpu_channel = false;
@@ -1466,7 +1492,7 @@ int BrowserMainLoop::BrowserThreadsStarted() {
established_gpu_channel = true;
if (!GpuDataManagerImpl::GetInstance()->CanUseGpuBrowserCompositor() ||
parsed_command_line_.HasSwitch(switches::kDisableGpuEarlyInit) ||
- service_manager::ServiceManagerIsRemote()) {
+ IsUsingMus()) {
established_gpu_channel = always_uses_gpu = false;
}
gpu::GpuChannelEstablishFactory* factory =
@@ -1476,8 +1502,16 @@ int BrowserMainLoop::BrowserThreadsStarted() {
factory = BrowserGpuChannelHostFactory::instance();
}
#if !defined(OS_ANDROID)
- if (!service_manager::ServiceManagerIsRemote()) {
- frame_sink_manager_impl_ = base::MakeUnique<viz::FrameSinkManagerImpl>();
+ if (!IsUsingMus()) {
+ // TODO(kylechar): Remove flag along with surface sequences.
+ // See https://crbug.com/676384.
+ auto surface_lifetime_type =
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableSurfaceReferences)
+ ? viz::SurfaceManager::LifetimeType::SEQUENCES
+ : viz::SurfaceManager::LifetimeType::REFERENCES;
+ frame_sink_manager_impl_ =
+ std::make_unique<viz::FrameSinkManagerImpl>(surface_lifetime_type);
host_frame_sink_manager_ = base::MakeUnique<viz::HostFrameSinkManager>();
@@ -1521,7 +1555,8 @@ int BrowserMainLoop::BrowserThreadsStarted() {
device_monitor_linux_.reset(
new media::DeviceMonitorLinux(io_thread_->task_runner()));
#elif defined(OS_MACOSX)
- device_monitor_mac_.reset(new media::DeviceMonitorMac());
+ device_monitor_mac_.reset(
+ new media::DeviceMonitorMac(audio_manager_->GetTaskRunner()));
#endif
// RDH needs the IO thread to be created
@@ -1549,7 +1584,8 @@ int BrowserMainLoop::BrowserThreadsStarted() {
{
TRACE_EVENT0("startup",
"BrowserMainLoop::BrowserThreadsStarted:InitMediaStreamManager");
- media_stream_manager_.reset(new MediaStreamManager(audio_system_.get()));
+ media_stream_manager_.reset(new MediaStreamManager(
+ audio_system_.get(), audio_manager_->GetTaskRunner()));
}
{
@@ -1590,14 +1626,14 @@ int BrowserMainLoop::BrowserThreadsStarted() {
// ChildProcess instance which is created by the renderer thread.
if (GpuDataManagerImpl::GetInstance()->GpuAccessAllowed(NULL) &&
!established_gpu_channel && always_uses_gpu && !UsingInProcessGpu() &&
- !service_manager::ServiceManagerIsRemote()) {
+ !IsUsingMus()) {
TRACE_EVENT_INSTANT0("gpu", "Post task to launch GPU process",
TRACE_EVENT_SCOPE_THREAD);
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(base::IgnoreResult(&GpuProcessHost::Get),
- GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
- true /* force_create */));
+ base::BindOnce(base::IgnoreResult(&GpuProcessHost::Get),
+ GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
+ true /* force_create */));
}
#if defined(OS_MACOSX)
@@ -1637,9 +1673,16 @@ void BrowserMainLoop::InitializeMemoryManagementComponent() {
if (base::FeatureList::IsEnabled(features::kMemoryCoordinator))
MemoryCoordinatorImpl::GetInstance()->Start();
- auto* swap_metrics_observer = SwapMetricsObserver::GetInstance();
- if (swap_metrics_observer)
- swap_metrics_observer->Start();
+ std::unique_ptr<SwapMetricsDriver::Delegate> delegate(
+ base::WrapUnique<SwapMetricsDriver::Delegate>(
+ new SwapMetricsDelegateUma()));
+
+#if !defined(OS_FUCHSIA)
+ swap_metrics_driver_ =
+ SwapMetricsDriver::Create(std::move(delegate), kSwapMetricsInterval);
+ if (swap_metrics_driver_)
+ swap_metrics_driver_->Start();
+#endif // !defined(OS_FUCHSIA)
}
bool BrowserMainLoop::InitializeToolkit() {
@@ -1716,6 +1759,8 @@ void BrowserMainLoop::InitializeMojo() {
#if defined(OS_MACOSX)
mojo::edk::SetMachPortProvider(MachBroker::GetInstance());
#endif // defined(OS_MACOSX)
+ GetContentClient()->OnServiceManagerConnected(
+ ServiceManagerConnection::GetForProcess());
if (parts_) {
parts_->ServiceManagerConnectionStarted(
ServiceManagerConnection::GetForProcess());
diff --git a/chromium/content/browser/browser_main_loop.h b/chromium/content/browser/browser_main_loop.h
index e0e55998c68..d341e72d29f 100644
--- a/chromium/content/browser/browser_main_loop.h
+++ b/chromium/content/browser/browser_main_loop.h
@@ -98,13 +98,14 @@ class SaveFileManager;
class ServiceManagerContext;
class SpeechRecognitionManagerImpl;
class StartupTaskRunner;
+class SwapMetricsDriver;
struct MainFunctionParams;
#if defined(OS_ANDROID)
class ScreenOrientationDelegate;
#endif
-#if defined(USE_X11) && !defined(OS_CHROMEOS)
+#if defined(USE_X11)
namespace internal {
class GpuDataManagerVisualProxy;
}
@@ -301,7 +302,8 @@ class CONTENT_EXPORT BrowserMainLoop {
// Members initialized in |PreCreateThreads()| -------------------------------
// Torn down in ShutdownThreadsAndCleanUp.
std::unique_ptr<base::MemoryPressureMonitor> memory_pressure_monitor_;
-#if defined(USE_X11) && !(OS_CHROMEOS)
+ std::unique_ptr<SwapMetricsDriver> swap_metrics_driver_;
+#if defined(USE_X11)
std::unique_ptr<internal::GpuDataManagerVisualProxy>
gpu_data_manager_visual_proxy_;
#endif
diff --git a/chromium/content/browser/browser_main_loop_unittest.cc b/chromium/content/browser/browser_main_loop_unittest.cc
index 3e2f04f04ec..76fab428647 100644
--- a/chromium/content/browser/browser_main_loop_unittest.cc
+++ b/chromium/content/browser/browser_main_loop_unittest.cc
@@ -29,11 +29,15 @@ TEST(BrowserMainLoopTest, CreateThreadsInSingleProcess) {
browser_main_loop.MainMessageLoopStart();
browser_main_loop.CreateThreads();
EXPECT_GE(base::TaskScheduler::GetInstance()
- ->GetMaxConcurrentTasksWithTraitsDeprecated(
+ ->GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated(
{base::TaskPriority::USER_VISIBLE}),
base::SysInfo::NumberOfProcessors());
browser_main_loop.ShutdownThreadsAndCleanUp();
}
+ for (int id = BrowserThread::UI; id < BrowserThread::ID_COUNT; ++id) {
+ BrowserThreadImpl::ResetGlobalsForTesting(
+ static_cast<BrowserThread::ID>(id));
+ }
base::TaskScheduler::GetInstance()->JoinForTesting();
base::TaskScheduler::SetInstance(nullptr);
}
diff --git a/chromium/content/browser/browser_main_runner.cc b/chromium/content/browser/browser_main_runner.cc
index d770c3d6297..d55dd0299f2 100644
--- a/chromium/content/browser/browser_main_runner.cc
+++ b/chromium/content/browser/browser_main_runner.cc
@@ -26,6 +26,7 @@
#include "content/browser/browser_main_loop.h"
#include "content/browser/browser_shutdown_profile_dumper.h"
#include "content/browser/notification_service_impl.h"
+#include "content/common/content_switches_internal.h"
#include "content/public/browser/tracing_controller.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/main_function_params.h"
@@ -88,6 +89,9 @@ class BrowserMainRunnerImpl : public BrowserMainRunner {
if (parameters.command_line.HasSwitch(switches::kWaitForDebugger))
base::debug::WaitForDebugger(60, true);
+ if (parameters.command_line.HasSwitch(switches::kBrowserStartupDialog))
+ WaitForDebugger("Browser");
+
base::StatisticsRecorder::Initialize();
notification_service_.reset(new NotificationServiceImpl);
@@ -136,6 +140,12 @@ class BrowserMainRunnerImpl : public BrowserMainRunner {
return -1;
}
+#if defined(OS_ANDROID)
+ void SynchronouslyFlushStartupTasks() override {
+ main_loop_->SynchronouslyFlushStartupTasks();
+ }
+#endif
+
int Run() override {
DCHECK(initialization_started_);
DCHECK(!is_shutdown_);
@@ -210,7 +220,7 @@ class BrowserMainRunnerImpl : public BrowserMainRunner {
// proper shutdown for content_browsertests. Shutdown() is not used by
// the actual browser.
if (base::RunLoop::IsRunningOnCurrentThread())
- base::MessageLoop::current()->QuitNow();
+ base::RunLoop::QuitCurrentDeprecated();
#endif
main_loop_.reset(NULL);
diff --git a/chromium/content/browser/browser_plugin/browser_plugin_guest.cc b/chromium/content/browser/browser_plugin/browser_plugin_guest.cc
index 964c9a093a3..abeb583eae5 100644
--- a/chromium/content/browser/browser_plugin/browser_plugin_guest.cc
+++ b/chromium/content/browser/browser_plugin/browser_plugin_guest.cc
@@ -15,21 +15,21 @@
#include "base/pickle.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
-#include "cc/surfaces/surface.h"
#include "components/viz/common/surfaces/surface_info.h"
#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
+#include "components/viz/service/surfaces/surface.h"
#include "content/browser/browser_plugin/browser_plugin_embedder.h"
#include "content/browser/browser_thread_impl.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/compositor/surface_utils.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/frame_host/render_frame_proxy_host.h"
-#include "content/browser/frame_host/render_widget_host_view_child_frame.h"
#include "content/browser/frame_host/render_widget_host_view_guest.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
+#include "content/browser/renderer_host/render_widget_host_view_child_frame.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/browser/web_contents/web_contents_view_guest.h"
#include "content/common/browser_plugin/browser_plugin_constants.h"
@@ -62,16 +62,31 @@ namespace content {
namespace {
-std::vector<ui::CompositionUnderline> ConvertToUiUnderline(
- const std::vector<blink::WebCompositionUnderline>& underlines) {
- std::vector<ui::CompositionUnderline> ui_underlines;
- for (const auto& underline : underlines) {
- ui_underlines.emplace_back(ui::CompositionUnderline(
- underline.start_offset, underline.end_offset, underline.color,
- underline.thick, underline.background_color));
+ui::ImeTextSpan::Type ConvertWebTypeToUiType(blink::WebImeTextSpan::Type type) {
+ switch (type) {
+ case blink::WebImeTextSpan::Type::kComposition:
+ return ui::ImeTextSpan::Type::kComposition;
+ case blink::WebImeTextSpan::Type::kSuggestion:
+ return ui::ImeTextSpan::Type::kSuggestion;
}
- return ui_underlines;
+
+ NOTREACHED();
+ return ui::ImeTextSpan::Type::kComposition;
}
+
+std::vector<ui::ImeTextSpan> ConvertToUiImeTextSpan(
+ const std::vector<blink::WebImeTextSpan>& ime_text_spans) {
+ std::vector<ui::ImeTextSpan> ui_ime_text_spans;
+ for (const auto& ime_text_span : ime_text_spans) {
+ ui_ime_text_spans.emplace_back(ui::ImeTextSpan(
+ ConvertWebTypeToUiType(ime_text_span.type), ime_text_span.start_offset,
+ ime_text_span.end_offset, ime_text_span.underline_color,
+ ime_text_span.thick, ime_text_span.background_color,
+ ime_text_span.suggestion_highlight_color, ime_text_span.suggestions));
+ }
+ return ui_ime_text_spans;
+}
+
}; // namespace
class BrowserPluginGuest::EmbedderVisibilityObserver
@@ -735,7 +750,7 @@ void BrowserPluginGuest::RenderProcessGone(base::TerminationStatus status) {
bool BrowserPluginGuest::ShouldForwardToBrowserPluginGuest(
const IPC::Message& message) {
return (message.type() != BrowserPluginHostMsg_Attach::ID) &&
- (IPC_MESSAGE_CLASS(message) == BrowserPluginMsgStart);
+ (IPC_MESSAGE_CLASS(message) == BrowserPluginMsgStart);
}
bool BrowserPluginGuest::OnMessageReceived(const IPC::Message& message) {
@@ -782,12 +797,10 @@ bool BrowserPluginGuest::OnMessageReceived(const IPC::Message& message,
bool handled = true;
IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(BrowserPluginGuest, message,
render_frame_host)
-#if defined(OS_MACOSX)
// MacOS X creates and populates platform-specific select drop-down menus
// whereas other platforms merely create a popup window that the guest
// renderer process paints inside.
IPC_MESSAGE_HANDLER(FrameHostMsg_ShowPopup, OnShowPopup)
-#endif
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
@@ -929,29 +942,30 @@ void BrowserPluginGuest::OnExecuteEditCommand(int browser_plugin_instance_id,
void BrowserPluginGuest::OnImeSetComposition(
int browser_plugin_instance_id,
const BrowserPluginHostMsg_SetComposition_Params& params) {
- std::vector<ui::CompositionUnderline> ui_underlines =
- ConvertToUiUnderline(params.underlines);
+ std::vector<ui::ImeTextSpan> ui_ime_text_spans =
+ ConvertToUiImeTextSpan(params.ime_text_spans);
GetWebContents()
->GetRenderViewHost()
->GetWidget()
->GetWidgetInputHandler()
- ->ImeSetComposition(params.text, ui_underlines, params.replacement_range,
- params.selection_start, params.selection_end);
+ ->ImeSetComposition(params.text, ui_ime_text_spans,
+ params.replacement_range, params.selection_start,
+ params.selection_end);
}
void BrowserPluginGuest::OnImeCommitText(
int browser_plugin_instance_id,
const base::string16& text,
- const std::vector<blink::WebCompositionUnderline>& underlines,
+ const std::vector<blink::WebImeTextSpan>& ime_text_spans,
const gfx::Range& replacement_range,
int relative_cursor_pos) {
- std::vector<ui::CompositionUnderline> ui_underlines =
- ConvertToUiUnderline(underlines);
+ std::vector<ui::ImeTextSpan> ui_ime_text_spans =
+ ConvertToUiImeTextSpan(ime_text_spans);
GetWebContents()
->GetRenderViewHost()
->GetWidget()
->GetWidgetInputHandler()
- ->ImeCommitText(text, ui_underlines, replacement_range,
+ ->ImeCommitText(text, ui_ime_text_spans, replacement_range,
relative_cursor_pos);
}
@@ -1069,7 +1083,14 @@ void BrowserPluginGuest::OnShowPopup(
RenderFrameHost* render_frame_host,
const FrameHostMsg_ShowPopup_Params& params) {
gfx::Rect translated_bounds(params.bounds);
- translated_bounds.Offset(guest_window_rect_.OffsetFromOrigin());
+ WebContents* guest = web_contents();
+ if (GuestMode::IsCrossProcessFrameGuest(guest)) {
+ translated_bounds.set_origin(
+ guest->GetRenderWidgetHostView()->TransformPointToRootCoordSpace(
+ translated_bounds.origin()));
+ } else {
+ translated_bounds.Offset(guest_window_rect_.OffsetFromOrigin());
+ }
BrowserPluginPopupMenuHelper popup_menu_helper(
owner_web_contents_->GetMainFrame(), render_frame_host);
popup_menu_helper.ShowPopupMenu(translated_bounds,
diff --git a/chromium/content/browser/browser_plugin/browser_plugin_guest.h b/chromium/content/browser/browser_plugin/browser_plugin_guest.h
index 725b77d36dc..ac97e2290d5 100644
--- a/chromium/content/browser/browser_plugin/browser_plugin_guest.h
+++ b/chromium/content/browser/browser_plugin/browser_plugin_guest.h
@@ -38,8 +38,8 @@
#include "third_party/WebKit/public/platform/WebDragOperation.h"
#include "third_party/WebKit/public/platform/WebFocusType.h"
#include "third_party/WebKit/public/platform/WebInputEvent.h"
-#include "third_party/WebKit/public/web/WebCompositionUnderline.h"
#include "third_party/WebKit/public/web/WebDragStatus.h"
+#include "third_party/WebKit/public/web/WebImeTextSpan.h"
#include "ui/base/ime/text_input_mode.h"
#include "ui/base/ime/text_input_type.h"
#include "ui/gfx/geometry/rect.h"
@@ -336,12 +336,11 @@ class CONTENT_EXPORT BrowserPluginGuest : public GuestHost,
void OnImeSetComposition(
int instance_id,
const BrowserPluginHostMsg_SetComposition_Params& params);
- void OnImeCommitText(
- int instance_id,
- const base::string16& text,
- const std::vector<blink::WebCompositionUnderline>& underlines,
- const gfx::Range& replacement_range,
- int relative_cursor_pos);
+ void OnImeCommitText(int instance_id,
+ const base::string16& text,
+ const std::vector<blink::WebImeTextSpan>& ime_text_spans,
+ const gfx::Range& replacement_range,
+ int relative_cursor_pos);
void OnImeFinishComposingText(int instance_id, bool keep_selection);
void OnExtendSelectionAndDelete(int instance_id, int before, int after);
void OnImeCancelComposition();
diff --git a/chromium/content/browser/browser_shutdown_profile_dumper.cc b/chromium/content/browser/browser_shutdown_profile_dumper.cc
index 5310782802b..6840acd1edb 100644
--- a/chromium/content/browser/browser_shutdown_profile_dumper.cc
+++ b/chromium/content/browser/browser_shutdown_profile_dumper.cc
@@ -63,9 +63,9 @@ void BrowserShutdownProfileDumper::WriteTracesToDisc() {
base::Thread flush_thread("browser_shutdown_trace_event_flush");
flush_thread.Start();
flush_thread.task_runner()->PostTask(
- FROM_HERE, base::Bind(&BrowserShutdownProfileDumper::EndTraceAndFlush,
- base::Unretained(this),
- base::Unretained(&flush_complete_event)));
+ FROM_HERE, base::BindOnce(&BrowserShutdownProfileDumper::EndTraceAndFlush,
+ base::Unretained(this),
+ base::Unretained(&flush_complete_event)));
bool original_wait_allowed = base::ThreadRestrictions::SetWaitAllowed(true);
flush_complete_event.Wait();
diff --git a/chromium/content/browser/browser_side_navigation_browsertest.cc b/chromium/content/browser/browser_side_navigation_browsertest.cc
index a33b095a604..4296e29d4ea 100644
--- a/chromium/content/browser/browser_side_navigation_browsertest.cc
+++ b/chromium/content/browser/browser_side_navigation_browsertest.cc
@@ -206,7 +206,7 @@ IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBrowserTest, FailedNavigation) {
net::URLRequestFailedJob::GetMockHttpUrl(net::ERR_CONNECTION_RESET));
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&net::URLRequestFailedJob::AddUrlHandler));
+ base::BindOnce(&net::URLRequestFailedJob::AddUrlHandler));
NavigateToURL(shell(), error_url);
EXPECT_EQ(error_url, observer.last_navigation_url());
NavigationEntry* entry =
diff --git a/chromium/content/browser/browser_thread_impl.cc b/chromium/content/browser/browser_thread_impl.cc
index 205340ed301..8756c06cb8f 100644
--- a/chromium/content/browser/browser_thread_impl.cc
+++ b/chromium/content/browser/browser_thread_impl.cc
@@ -464,7 +464,7 @@ void BrowserThreadImpl::StopRedirectionOfThreadID(
base::WaitableEvent::InitialState::NOT_SIGNALED);
globals.task_runners[identifier]->PostTask(
FROM_HERE,
- base::Bind(&base::WaitableEvent::Signal, base::Unretained(&flushed)));
+ base::BindOnce(&base::WaitableEvent::Signal, base::Unretained(&flushed)));
{
base::AutoUnlock auto_lock(globals.lock);
flushed.Wait();
diff --git a/chromium/content/browser/browser_thread_unittest.cc b/chromium/content/browser/browser_thread_unittest.cc
index 68f6a96425e..866b51db09c 100644
--- a/chromium/content/browser/browser_thread_unittest.cc
+++ b/chromium/content/browser/browser_thread_unittest.cc
@@ -91,7 +91,7 @@ class UIThreadDestructionObserver
BrowserThread::GetTaskRunnerForThread(BrowserThread::UI)),
did_shutdown_(did_shutdown) {
BrowserThread::GetTaskRunnerForThread(BrowserThread::UI)
- ->PostTask(FROM_HERE, base::Bind(&Watch, this));
+ ->PostTask(FROM_HERE, base::BindOnce(&Watch, this));
}
private:
@@ -120,9 +120,8 @@ class UIThreadDestructionObserver
TEST_F(BrowserThreadTest, PostTask) {
BrowserThread::PostTask(
- BrowserThread::FILE,
- FROM_HERE,
- base::Bind(&BasicFunction, base::MessageLoop::current()));
+ BrowserThread::FILE, FROM_HERE,
+ base::BindOnce(&BasicFunction, base::MessageLoop::current()));
base::RunLoop().Run();
}
@@ -143,7 +142,7 @@ TEST_F(BrowserThreadTest, PostTaskViaTaskRunner) {
scoped_refptr<base::SingleThreadTaskRunner> task_runner =
BrowserThread::GetTaskRunnerForThread(BrowserThread::FILE);
task_runner->PostTask(
- FROM_HERE, base::Bind(&BasicFunction, base::MessageLoop::current()));
+ FROM_HERE, base::BindOnce(&BasicFunction, base::MessageLoop::current()));
base::RunLoop().Run();
}
@@ -158,19 +157,18 @@ TEST_F(BrowserThreadTest, PostTaskAndReply) {
// Most of the heavy testing for PostTaskAndReply() is done inside the
// task runner test. This just makes sure we get piped through at all.
ASSERT_TRUE(BrowserThread::PostTaskAndReply(
- BrowserThread::FILE, FROM_HERE, base::Bind(&base::DoNothing),
- base::Bind(&base::MessageLoop::QuitWhenIdle,
- base::Unretained(base::MessageLoop::current()->current()))));
+ BrowserThread::FILE, FROM_HERE, base::BindOnce(&base::DoNothing),
+ base::BindOnce(&base::RunLoop::QuitCurrentWhenIdleDeprecated)));
base::RunLoop().Run();
}
-TEST_F(BrowserThreadTest, RunsTasksOnCurrentThreadDuringShutdown) {
+TEST_F(BrowserThreadTest, RunsTasksInCurrentSequencedDuringShutdown) {
bool did_shutdown = false;
base::RunLoop loop;
UIThreadDestructionObserver observer(&did_shutdown, loop.QuitClosure());
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
- base::Bind(&BrowserThreadTest::StopUIThread, base::Unretained(this)));
+ base::BindOnce(&BrowserThreadTest::StopUIThread, base::Unretained(this)));
loop.Run();
EXPECT_TRUE(did_shutdown);
diff --git a/chromium/content/browser/browser_url_handler_impl.cc b/chromium/content/browser/browser_url_handler_impl.cc
index 31cbaabfb4a..feef0ca919a 100644
--- a/chromium/content/browser/browser_url_handler_impl.cc
+++ b/chromium/content/browser/browser_url_handler_impl.cc
@@ -28,7 +28,6 @@ static bool HandleViewSource(GURL* url, BrowserContext* browser_context) {
url::kHttpScheme,
url::kHttpsScheme,
url::kFtpScheme,
- kChromeDevToolsScheme,
kChromeUIScheme,
url::kFileScheme,
url::kFileSystemScheme
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 db9e312cd8f..c3c257cf1b9 100644
--- a/chromium/content/browser/browsing_data/browsing_data_remover_impl.cc
+++ b/chromium/content/browser/browsing_data/browsing_data_remover_impl.cc
@@ -188,6 +188,9 @@ BrowsingDataRemoverImpl::~BrowsingDataRemoverImpl() {
<< " pending tasks";
}
+ UMA_HISTOGRAM_EXACT_LINEAR("History.ClearBrowsingData.TaskQueueAtShutdown",
+ task_queue_.size(), 10);
+
// If we are still removing data, notify observers that their task has been
// (albeit unsucessfuly) processed, so they can unregister themselves.
// TODO(bauerb): If it becomes a problem that browsing data might not actually
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 960c1eb7f4e..02ad505f9bc 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
@@ -27,7 +27,6 @@
#include "base/task/cancelable_task_tracker.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
-#include "build/build_config.h"
#include "content/browser/browsing_data/browsing_data_remover_impl.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browsing_data_filter_builder.h"
@@ -41,6 +40,7 @@
#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_storage_partition.h"
#include "content/public/test/test_utils.h"
#include "net/cookies/cookie_store.h"
#include "net/http/http_network_session.h"
@@ -126,37 +126,11 @@ net::CanonicalCookie CreateCookieWithHost(const GURL& source) {
return *cookie;
}
-class TestStoragePartition : public StoragePartition {
+class StoragePartitionRemovalTestStoragePartition
+ : public TestStoragePartition {
public:
- TestStoragePartition() {}
- ~TestStoragePartition() override {}
-
- // StoragePartition implementation.
- base::FilePath GetPath() override { return base::FilePath(); }
- net::URLRequestContextGetter* GetURLRequestContext() override {
- return nullptr;
- }
- net::URLRequestContextGetter* GetMediaURLRequestContext() override {
- return nullptr;
- }
- storage::QuotaManager* GetQuotaManager() override { return nullptr; }
- AppCacheService* GetAppCacheService() override { return nullptr; }
- storage::FileSystemContext* GetFileSystemContext() override {
- return nullptr;
- }
- storage::DatabaseTracker* GetDatabaseTracker() override { return nullptr; }
- DOMStorageContext* GetDOMStorageContext() override { return nullptr; }
- IndexedDBContext* GetIndexedDBContext() override { return nullptr; }
- ServiceWorkerContext* GetServiceWorkerContext() override { return nullptr; }
- CacheStorageContext* GetCacheStorageContext() override { return nullptr; }
- PlatformNotificationContext* GetPlatformNotificationContext() override {
- return nullptr;
- }
-#if !defined(OS_ANDROID)
- HostZoomMap* GetHostZoomMap() override { return nullptr; }
- HostZoomLevelContext* GetHostZoomLevelContext() override { return nullptr; }
- ZoomLevelDelegate* GetZoomLevelDelegate() override { return nullptr; }
-#endif // !defined(OS_ANDROID)
+ StoragePartitionRemovalTestStoragePartition() {}
+ ~StoragePartitionRemovalTestStoragePartition() override {}
void ClearDataForOrigin(uint32_t remove_mask,
uint32_t quota_storage_remove_mask,
@@ -165,8 +139,9 @@ class TestStoragePartition : public StoragePartition {
const base::Closure& callback) override {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::BindOnce(&TestStoragePartition::AsyncRunCallback,
- base::Unretained(this), callback));
+ base::BindOnce(
+ &StoragePartitionRemovalTestStoragePartition::AsyncRunCallback,
+ base::Unretained(this), callback));
}
void ClearData(uint32_t remove_mask,
@@ -186,8 +161,9 @@ class TestStoragePartition : public StoragePartition {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::BindOnce(&TestStoragePartition::AsyncRunCallback,
- base::Unretained(this), callback));
+ base::BindOnce(
+ &StoragePartitionRemovalTestStoragePartition::AsyncRunCallback,
+ base::Unretained(this), callback));
}
void ClearData(uint32_t remove_mask,
@@ -208,22 +184,11 @@ class TestStoragePartition : public StoragePartition {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::BindOnce(&TestStoragePartition::AsyncRunCallback,
- base::Unretained(this), callback));
- }
-
- void ClearHttpAndMediaCaches(
- const base::Time begin,
- const base::Time end,
- const base::Callback<bool(const GURL&)>& url_matcher,
- const base::Closure& callback) override {
- // Not needed in this test.
+ base::BindOnce(
+ &StoragePartitionRemovalTestStoragePartition::AsyncRunCallback,
+ base::Unretained(this), callback));
}
- void Flush() override {}
-
- void ClearBluetoothAllowedDevicesMapForTesting() override {}
-
StoragePartitionRemovalData GetStoragePartitionRemovalData() {
return storage_partition_removal_data_;
}
@@ -233,7 +198,7 @@ class TestStoragePartition : public StoragePartition {
StoragePartitionRemovalData storage_partition_removal_data_;
- DISALLOW_COPY_AND_ASSIGN(TestStoragePartition);
+ DISALLOW_COPY_AND_ASSIGN(StoragePartitionRemovalTestStoragePartition);
};
// Custom matcher to test the equivalence of two URL filters. Since those are
@@ -310,8 +275,8 @@ class RemoveCookieTester {
get_cookie_success_ = false;
cookie_store_->GetCookiesWithOptionsAsync(
kOrigin1, net::CookieOptions(),
- base::Bind(&RemoveCookieTester::GetCookieCallback,
- base::Unretained(this)));
+ base::BindOnce(&RemoveCookieTester::GetCookieCallback,
+ base::Unretained(this)));
message_loop_runner->Run();
return get_cookie_success_;
}
@@ -322,8 +287,8 @@ class RemoveCookieTester {
quit_closure_ = message_loop_runner->QuitClosure();
cookie_store_->SetCookieWithOptionsAsync(
kOrigin1, "A=1", net::CookieOptions(),
- base::Bind(&RemoveCookieTester::SetCookieCallback,
- base::Unretained(this)));
+ base::BindOnce(&RemoveCookieTester::SetCookieCallback,
+ base::Unretained(this)));
message_loop_runner->Run();
}
@@ -532,14 +497,14 @@ class BrowsingDataRemoverImplTest : public testing::Test {
// destroyed, and that the message loop is cleared out, before destroying
// the threads and loop. Otherwise we leak memory.
browser_context_.reset();
- base::RunLoop().RunUntilIdle();
+ RunAllBlockingPoolTasksUntilIdle();
}
void BlockUntilBrowsingDataRemoved(const base::Time& delete_begin,
const base::Time& delete_end,
int remove_mask,
bool include_protected_origins) {
- TestStoragePartition storage_partition;
+ StoragePartitionRemovalTestStoragePartition storage_partition;
remover_->OverrideStoragePartitionForTesting(&storage_partition);
int origin_type_mask = BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB;
@@ -561,7 +526,7 @@ class BrowsingDataRemoverImplTest : public testing::Test {
const base::Time& delete_end,
int remove_mask,
std::unique_ptr<BrowsingDataFilterBuilder> filter_builder) {
- TestStoragePartition storage_partition;
+ StoragePartitionRemovalTestStoragePartition storage_partition;
remover_->OverrideStoragePartitionForTesting(&storage_partition);
BrowsingDataRemoverCompletionObserver completion_observer(remover_);
@@ -1403,7 +1368,7 @@ TEST_F(BrowsingDataRemoverImplTest, CompletionInhibition) {
// sure we do not complete asynchronously before ContinueToCompletion() is
// called.
completion_inhibitor.BlockUntilNearCompletion();
- base::RunLoop().RunUntilIdle();
+ RunAllBlockingPoolTasksUntilIdle();
// Verify that the removal has not yet been completed and the observer has
// not been called.
@@ -1610,6 +1575,9 @@ TEST_F(BrowsingDataRemoverImplTest, MultipleTasks) {
}
EXPECT_FALSE(remover->is_removing());
+
+ // Run clean up tasks.
+ RunAllBlockingPoolTasksUntilIdle();
}
// The previous test, BrowsingDataRemoverTest.MultipleTasks, tests that the
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 4666c04cf47..dcc9b914aa3 100644
--- a/chromium/content/browser/browsing_data/clear_site_data_throttle.cc
+++ b/chromium/content/browser/browsing_data/clear_site_data_throttle.cc
@@ -457,7 +457,10 @@ bool ClearSiteDataThrottle::ParseHeader(const std::string& header,
} else if (type == kDatatypeStorage) {
data_type = clear_storage;
} else if (type == kDatatypeCache) {
- data_type = clear_cache;
+ delegate->AddMessage(
+ current_url, "The \"cache\" datatype is temporarily not supported.",
+ CONSOLE_MESSAGE_LEVEL_ERROR);
+ continue;
} else {
delegate->AddMessage(current_url,
base::StringPrintf("Unrecognized type: %s.",
diff --git a/chromium/content/browser/browsing_data/clear_site_data_throttle_browsertest.cc b/chromium/content/browser/browsing_data/clear_site_data_throttle_browsertest.cc
index 3aae2ad7562..c8824b59894 100644
--- a/chromium/content/browser/browsing_data/clear_site_data_throttle_browsertest.cc
+++ b/chromium/content/browser/browsing_data/clear_site_data_throttle_browsertest.cc
@@ -9,6 +9,7 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/command_line.h"
+#include "base/run_loop.h"
#include "base/scoped_observer.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
@@ -263,9 +264,9 @@ class ClearSiteDataThrottleBrowserTest : public ContentBrowserTest {
base::RunLoop run_loop;
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&ServiceWorkerActivationObserver::SignalActivation,
- base::Unretained(service_worker_context),
- run_loop.QuitClosure()));
+ base::BindOnce(&ServiceWorkerActivationObserver::SignalActivation,
+ base::Unretained(service_worker_context),
+ run_loop.QuitClosure()));
run_loop.Run();
}
@@ -755,11 +756,15 @@ IN_PROC_BROWSER_TEST_F(ClearSiteDataThrottleBrowserTest, Types) {
} test_cases[] = {
{"\"cookies\"", true, false, false},
{"\"storage\"", false, true, false},
- {"\"cache\"", false, false, true},
+
+ // TODO(crbug.com/762417): The "cache" parameter is temporarily disabled.
+ {"\"cache\"", false, false, false},
{"\"cookies\", \"storage\"", true, true, false},
- {"\"cookies\", \"cache\"", true, false, true},
- {"\"storage\", \"cache\"", false, true, true},
- {"\"cookies\", \"storage\", \"cache\"", true, true, true},
+
+ // TODO(crbug.com/762417): The "cache" parameter is temporarily disabled.
+ {"\"cookies\", \"cache\"", true, false, false},
+ {"\"storage\", \"cache\"", false, true, false},
+ {"\"cookies\", \"storage\", \"cache\"", true, true, false},
};
for (const TestCase& test_case : test_cases) {
@@ -846,7 +851,9 @@ IN_PROC_BROWSER_TEST_F(ClearSiteDataThrottleBrowserTest,
// entries are actually written to the disk. Other tests using CacheTestUtil
// show that a timeout of around 1s between cache operations is necessary to
// avoid flakiness.
-IN_PROC_BROWSER_TEST_F(ClearSiteDataThrottleBrowserTest, CacheIntegrationTest) {
+// TODO(crbug.com/762417): The "cache" parameter is temporarily disabled.
+IN_PROC_BROWSER_TEST_F(ClearSiteDataThrottleBrowserTest,
+ DISABLED_CacheIntegrationTest) {
const int kTimeoutMs = 1000;
CacheTestUtil util(
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 c605b3c12b5..204508f1fd6 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
@@ -17,6 +17,7 @@
#include "content/public/test/test_browser_thread_bundle.h"
#include "net/base/load_flags.h"
#include "net/http/http_util.h"
+#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "net/url_request/redirect_info.h"
#include "net/url_request/url_request_job.h"
#include "net/url_request/url_request_test_util.h"
@@ -150,8 +151,8 @@ TEST_F(ClearSiteDataThrottleTest, MaybeCreateThrottleForRequest) {
// Create a URL request.
GURL url("https://www.example.com");
net::TestURLRequestContext context;
- std::unique_ptr<net::URLRequest> request(
- context.CreateRequest(url, net::DEFAULT_PRIORITY, nullptr));
+ std::unique_ptr<net::URLRequest> request(context.CreateRequest(
+ url, net::DEFAULT_PRIORITY, nullptr, TRAFFIC_ANNOTATION_FOR_TESTS));
// We will not create the throttle for an empty ResourceRequestInfo.
EXPECT_FALSE(
@@ -175,17 +176,24 @@ TEST_F(ClearSiteDataThrottleTest, ParseHeaderAndExecuteClearingTask) {
// One data type.
{"\"cookies\"", true, false, false},
{"\"storage\"", false, true, false},
- {"\"cache\"", false, false, true},
+
+ // TODO(crbug.com/762417): The "cache" parameter is temporarily disabled.
+ // Therefore, a header consisting solely of the "cache" parameter is
+ // invalid. As this test verifies the behavior of Clear-Site-Data with
+ // valid headers, we will omit such test case.
// Two data types.
{"\"cookies\", \"storage\"", true, true, false},
- {"\"cookies\", \"cache\"", true, false, true},
- {"\"storage\", \"cache\"", false, true, true},
+
+ // TODO(crbug.com/762417): The "cache" parameter is temporarily disabled.
+ {"\"cookies\", \"cache\"", true, false, false},
+ {"\"storage\", \"cache\"", false, true, false},
// Three data types.
- {"\"storage\", \"cache\", \"cookies\"", true, true, true},
- {"\"cache\", \"cookies\", \"storage\"", true, true, true},
- {"\"cookies\", \"storage\", \"cache\"", true, true, true},
+ // TODO(crbug.com/762417): The "cache" parameter is temporarily disabled.
+ {"\"storage\", \"cache\", \"cookies\"", true, true, false},
+ {"\"cache\", \"cookies\", \"storage\"", true, true, false},
+ {"\"cookies\", \"storage\", \"cache\"", true, true, false},
// Different formatting.
{"\"cookies\"", true, false, false},
@@ -198,7 +206,7 @@ TEST_F(ClearSiteDataThrottleTest, ParseHeaderAndExecuteClearingTask) {
// Unknown types are ignored, but we still proceed with the deletion for
// those that we recognize.
- {"\"cache\", \"foo\"", false, false, true},
+ {"\"storage\", \"foo\"", false, true, false},
};
for (const TestCase& test_case : test_cases) {
@@ -223,8 +231,8 @@ TEST_F(ClearSiteDataThrottleTest, ParseHeaderAndExecuteClearingTask) {
// Test that a call with the above parameters actually reaches
// ExecuteClearingTask().
net::TestURLRequestContext context;
- std::unique_ptr<net::URLRequest> request(
- context.CreateRequest(url, net::DEFAULT_PRIORITY, nullptr));
+ std::unique_ptr<net::URLRequest> request(context.CreateRequest(
+ url, net::DEFAULT_PRIORITY, nullptr, TRAFFIC_ANNOTATION_FOR_TESTS));
TestThrottle throttle(request.get(),
base::MakeUnique<ConsoleMessagesDelegate>());
MockResourceThrottleDelegate delegate;
@@ -253,6 +261,9 @@ TEST_F(ClearSiteDataThrottleTest, InvalidHeader) {
{"\"passwords\"",
"Unrecognized type: \"passwords\".\n"
"No recognized types specified.\n"},
+ {"\"cache\"",
+ "The \"cache\" datatype is temporarily not supported.\n"
+ "No recognized types specified.\n"},
{"[ \"list\" ]",
"Unrecognized type: [ \"list\" ].\n"
"No recognized types specified.\n"},
@@ -291,7 +302,8 @@ TEST_F(ClearSiteDataThrottleTest, InvalidHeader) {
TEST_F(ClearSiteDataThrottleTest, LoadDoNotSaveCookies) {
net::TestURLRequestContext context;
std::unique_ptr<net::URLRequest> request(context.CreateRequest(
- GURL("https://www.example.com"), net::DEFAULT_PRIORITY, nullptr));
+ GURL("https://www.example.com"), net::DEFAULT_PRIORITY, nullptr,
+ TRAFFIC_ANNOTATION_FOR_TESTS));
std::unique_ptr<ConsoleMessagesDelegate> scoped_console_delegate(
new ConsoleMessagesDelegate());
const ConsoleMessagesDelegate* console_delegate =
@@ -352,8 +364,9 @@ TEST_F(ClearSiteDataThrottleTest, InvalidOrigin) {
net::TestURLRequestContext context;
for (const TestCase& test_case : kTestCases) {
- std::unique_ptr<net::URLRequest> request(context.CreateRequest(
- GURL(test_case.origin), net::DEFAULT_PRIORITY, nullptr));
+ std::unique_ptr<net::URLRequest> request(
+ context.CreateRequest(GURL(test_case.origin), net::DEFAULT_PRIORITY,
+ nullptr, TRAFFIC_ANNOTATION_FOR_TESTS));
std::unique_ptr<ConsoleMessagesDelegate> scoped_console_delegate(
new ConsoleMessagesDelegate());
const ConsoleMessagesDelegate* console_delegate =
@@ -455,8 +468,9 @@ TEST_F(ClearSiteDataThrottleTest, DeferAndResume) {
test_origin.origin, test_case.stage,
test_case.response_headers.c_str()));
- std::unique_ptr<net::URLRequest> request(context.CreateRequest(
- GURL(test_origin.origin), net::DEFAULT_PRIORITY, nullptr));
+ std::unique_ptr<net::URLRequest> request(
+ context.CreateRequest(GURL(test_origin.origin), net::DEFAULT_PRIORITY,
+ nullptr, TRAFFIC_ANNOTATION_FOR_TESTS));
TestThrottle throttle(request.get(),
base::MakeUnique<ConsoleMessagesDelegate>());
throttle.SetResponseHeaders(test_case.response_headers);
@@ -544,9 +558,9 @@ TEST_F(ClearSiteDataThrottleTest, FormattedConsoleOutput) {
"No recognized types specified.\n"},
// Successful deletion on the same URL.
- {"\"cache\"", "https://origin3.com/bar",
+ {"\"cookies\"", "https://origin3.com/bar",
"Clear-Site-Data header on 'https://origin3.com/bar': "
- "Cleared data types: \"cache\".\n"},
+ "Cleared data types: \"cookies\".\n"},
// Redirect to the original URL.
// Successful deletion outputs one line.
@@ -560,8 +574,9 @@ TEST_F(ClearSiteDataThrottleTest, FormattedConsoleOutput) {
SCOPED_TRACE(navigation ? "Navigation test." : "Subresource test.");
net::TestURLRequestContext context;
- std::unique_ptr<net::URLRequest> request(context.CreateRequest(
- GURL(kTestCases[0].url), net::DEFAULT_PRIORITY, nullptr));
+ std::unique_ptr<net::URLRequest> request(
+ context.CreateRequest(GURL(kTestCases[0].url), net::DEFAULT_PRIORITY,
+ nullptr, TRAFFIC_ANNOTATION_FOR_TESTS));
ResourceRequestInfo::AllocateForTesting(
request.get(),
navigation ? RESOURCE_TYPE_SUB_FRAME : RESOURCE_TYPE_IMAGE, nullptr, 0,
diff --git a/chromium/content/browser/browsing_data/conditional_cache_deletion_helper.cc b/chromium/content/browser/browsing_data/conditional_cache_deletion_helper.cc
index de0e59ec850..fcaa95d6025 100644
--- a/chromium/content/browser/browsing_data/conditional_cache_deletion_helper.cc
+++ b/chromium/content/browser/browsing_data/conditional_cache_deletion_helper.cc
@@ -77,7 +77,7 @@ void ConditionalCacheDeletionHelper::IterateOverEntries(int error) {
// (e.g. the cache was destroyed). We cannot distinguish between the two,
// but we know that there is nothing more that we can do, so we return OK.
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(completion_callback_, net::OK));
+ FROM_HERE, base::BindOnce(completion_callback_, net::OK));
base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this);
return;
}
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 a4ccb08bf64..57a8b12d4fd 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
@@ -106,8 +106,8 @@ IN_PROC_BROWSER_TEST_F(ConditionalCacheDeletionHelperBrowserTest, Condition) {
// Delete the entries whose keys are even numbers.
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&ConditionalCacheDeletionHelperBrowserTest::DeleteEntries,
- base::Unretained(this), base::Bind(&KeyIsEven)));
+ base::BindOnce(&ConditionalCacheDeletionHelperBrowserTest::DeleteEntries,
+ base::Unretained(this), base::Bind(&KeyIsEven)));
WaitForTasksOnIOThread();
// Expect that the keys with values 56 and 42 were deleted.
@@ -166,8 +166,8 @@ IN_PROC_BROWSER_TEST_F(ConditionalCacheDeletionHelperBrowserTest,
// Delete the entries.
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&ConditionalCacheDeletionHelperBrowserTest::DeleteEntries,
- base::Unretained(this), base::ConstRef(condition)));
+ base::BindOnce(&ConditionalCacheDeletionHelperBrowserTest::DeleteEntries,
+ base::Unretained(this), base::ConstRef(condition)));
WaitForTasksOnIOThread();
// Expect that only "icon2.png" and "icon3.png" were deleted.
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 cce81dbbc0a..0b71b09429c 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
@@ -72,7 +72,7 @@ void StoragePartitionHttpCacheDataRemover::Remove(
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(
+ base::BindOnce(
&StoragePartitionHttpCacheDataRemover::ClearHttpCacheOnIOThread,
base::Unretained(this)));
}
@@ -181,8 +181,9 @@ void StoragePartitionHttpCacheDataRemover::DoClearCache(int rv) {
// Notify the UI thread that we are done.
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&StoragePartitionHttpCacheDataRemover::ClearedHttpCache,
- base::Unretained(this)));
+ base::BindOnce(
+ &StoragePartitionHttpCacheDataRemover::ClearedHttpCache,
+ base::Unretained(this)));
return;
}
case CacheState::NONE: {
diff --git a/chromium/content/browser/byte_stream.cc b/chromium/content/browser/byte_stream.cc
index 0209bb85d5b..eb07e14ea55 100644
--- a/chromium/content/browser/byte_stream.cc
+++ b/chromium/content/browser/byte_stream.cc
@@ -297,14 +297,10 @@ void ByteStreamWriterImpl::PostToPeer(bool complete, int status) {
input_contents_size_ = 0;
}
peer_task_runner_->PostTask(
- FROM_HERE, base::Bind(
- &ByteStreamReaderImpl::TransferData,
- peer_lifetime_flag_,
- peer_,
- base::Passed(&transfer_buffer),
- buffer_size,
- complete,
- status));
+ FROM_HERE,
+ base::BindOnce(&ByteStreamReaderImpl::TransferData, peer_lifetime_flag_,
+ peer_, base::Passed(&transfer_buffer), buffer_size,
+ complete, status));
}
ByteStreamReaderImpl::ByteStreamReaderImpl(
@@ -425,11 +421,9 @@ void ByteStreamReaderImpl::MaybeUpdateInput() {
return;
peer_task_runner_->PostTask(
- FROM_HERE, base::Bind(
- &ByteStreamWriterImpl::UpdateWindow,
- peer_lifetime_flag_,
- peer_,
- unreported_consumed_bytes_));
+ FROM_HERE,
+ base::BindOnce(&ByteStreamWriterImpl::UpdateWindow, peer_lifetime_flag_,
+ peer_, unreported_consumed_bytes_));
unreported_consumed_bytes_ = 0;
}
diff --git a/chromium/content/browser/byte_stream.h b/chromium/content/browser/byte_stream.h
index 91152df3106..375eeb5c16b 100644
--- a/chromium/content/browser/byte_stream.h
+++ b/chromium/content/browser/byte_stream.h
@@ -67,7 +67,7 @@ namespace content {
// std::unique_ptr<ByteStreamReader> reader;
// CreateByteStream(
// BrowserThread::GetTaskRunnerForThread(BrowserThread::IO),
-// BrowserThread::GetTaskRunnerForThread(BrowserThread::FILE),
+// base::CreateSequencedTaskRunnerWithTraits({base::MayBlock, ...}),
// kStreamBufferSize /* e.g. 10240. */,
// &writer,
// &reader); // Presumed passed to FILE thread for reading.
diff --git a/chromium/content/browser/cache_storage/cache_storage.cc b/chromium/content/browser/cache_storage/cache_storage.cc
index f6466e61279..881502d425f 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_cache.h"
#include "content/browser/cache_storage/cache_storage_cache_handle.h"
#include "content/browser/cache_storage/cache_storage_index.h"
+#include "content/browser/cache_storage/cache_storage_manager.h"
#include "content/browser/cache_storage/cache_storage_scheduler.h"
#include "content/public/browser/browser_thread.h"
#include "net/base/directory_lister.h"
@@ -503,6 +504,7 @@ CacheStorage::CacheStorage(
scoped_refptr<net::URLRequestContextGetter> request_context,
scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy,
base::WeakPtr<storage::BlobStorageContext> blob_context,
+ CacheStorageManager* cache_storage_manager,
const GURL& origin)
: initialized_(false),
initializing_(false),
@@ -513,6 +515,7 @@ CacheStorage::CacheStorage(
cache_task_runner_(cache_task_runner),
quota_manager_proxy_(quota_manager_proxy),
origin_(origin),
+ cache_storage_manager_(cache_storage_manager),
weak_factory_(this) {
if (memory_only)
cache_loader_.reset(new MemoryLoader(
@@ -651,6 +654,15 @@ void CacheStorage::Size(CacheStorage::SizeCallback callback) {
scheduler_->WrapCallbackToRunNext(std::move(callback))));
}
+void CacheStorage::ResetManager() {
+ cache_storage_manager_ = nullptr;
+}
+
+void CacheStorage::NotifyCacheContentChanged(const std::string& cache_name) {
+ if (cache_storage_manager_)
+ cache_storage_manager_->NotifyCacheContentChanged(origin_, cache_name);
+}
+
void CacheStorage::ScheduleWriteIndex() {
static const int64_t kWriteIndexDelaySecs = 5;
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -794,6 +806,8 @@ void CacheStorage::CreateCacheDidCreateCache(
base::Passed(CreateCacheHandle(cache_ptr))));
cache_loader_->NotifyCacheCreated(cache_name, CreateCacheHandle(cache_ptr));
+ if (cache_storage_manager_)
+ cache_storage_manager_->NotifyCacheListChanged(origin_);
}
void CacheStorage::CreateCacheDidWriteIndex(
@@ -859,6 +873,8 @@ void CacheStorage::DeleteCacheDidWriteIndex(
cache_map_.erase(map_iter);
cache_loader_->NotifyCacheDoomed(std::move(cache_handle));
+ if (cache_storage_manager_)
+ cache_storage_manager_->NotifyCacheListChanged(origin_);
std::move(callback).Run(true, CACHE_STORAGE_OK);
}
diff --git a/chromium/content/browser/cache_storage/cache_storage.h b/chromium/content/browser/cache_storage/cache_storage.h
index fe0f2116f37..6a1f976f39e 100644
--- a/chromium/content/browser/cache_storage/cache_storage.h
+++ b/chromium/content/browser/cache_storage/cache_storage.h
@@ -35,6 +35,7 @@ class BlobStorageContext;
namespace content {
class CacheStorageCacheHandle;
class CacheStorageIndex;
+class CacheStorageManager;
class CacheStorageScheduler;
// TODO(jkarlin): Constrain the total bytes used per origin.
@@ -63,6 +64,7 @@ class CONTENT_EXPORT CacheStorage : public CacheStorageCacheObserver {
scoped_refptr<net::URLRequestContextGetter> request_context_getter,
scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy,
base::WeakPtr<storage::BlobStorageContext> blob_context,
+ CacheStorageManager* cache_storage_manager,
const GURL& origin);
// Any unfinished asynchronous operations may not complete or call their
@@ -118,6 +120,10 @@ class CONTENT_EXPORT CacheStorage : public CacheStorageCacheObserver {
void StartAsyncOperationForTesting();
void CompleteAsyncOperationForTesting();
+ // Removes the manager reference. Called before this storage is deleted by the
+ // manager, since it is removed from manager's storage map before deleting.
+ void ResetManager();
+
// CacheStorageCacheObserver:
void CacheSizeUpdated(const CacheStorageCache* cache, int64_t size) override;
@@ -213,6 +219,8 @@ class CONTENT_EXPORT CacheStorage : public CacheStorageCacheObserver {
int64_t* accumulator,
int64_t size);
+ void NotifyCacheContentChanged(const std::string& cache_name);
+
void ScheduleWriteIndex();
void WriteIndex(base::OnceCallback<void(bool)> callback);
void WriteIndexImpl(base::OnceCallback<void(bool)> callback);
@@ -261,6 +269,10 @@ class CONTENT_EXPORT CacheStorage : public CacheStorageCacheObserver {
// The origin that this CacheStorage is associated with.
GURL origin_;
+ // The manager that owns this cache storage. Only set to null by
+ // RemoveManager() when this cache storage is being deleted.
+ CacheStorageManager* cache_storage_manager_;
+
base::CancelableClosure index_write_task_;
base::WeakPtrFactory<CacheStorage> weak_factory_;
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 9b60c731593..a650aaa6b7b 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
@@ -141,8 +141,7 @@ class CacheStorageBlobToDiskCacheTest : public testing::Test {
int rv = CreateCacheBackend(
net::MEMORY_CACHE, net::CACHE_BACKEND_DEFAULT, base::FilePath(),
(CacheStorageBlobToDiskCache::kBufferSize * 100) /* max bytes */,
- false /* force */, base::ThreadTaskRunnerHandle::Get(),
- nullptr /* net log */, &cache_backend_,
+ false /* force */, nullptr /* net log */, &cache_backend_,
base::Bind(&DoNothingCompletion));
// The memory cache runs synchronously.
EXPECT_EQ(net::OK, rv);
diff --git a/chromium/content/browser/cache_storage/cache_storage_cache.cc b/chromium/content/browser/cache_storage/cache_storage_cache.cc
index c06ef710ece..2f1e0202508 100644
--- a/chromium/content/browser/cache_storage/cache_storage_cache.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_cache.cc
@@ -27,19 +27,22 @@
#include "content/browser/cache_storage/cache_storage_cache_observer.h"
#include "content/browser/cache_storage/cache_storage_scheduler.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/common/content_features.h"
#include "content/public/common/referrer.h"
#include "net/base/completion_callback.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/disk_cache/disk_cache.h"
#include "net/url_request/url_request_context_getter.h"
+#include "services/network/public/interfaces/fetch_api.mojom.h"
#include "storage/browser/blob/blob_data_builder.h"
#include "storage/browser/blob/blob_data_handle.h"
+#include "storage/browser/blob/blob_impl.h"
#include "storage/browser/blob/blob_storage_context.h"
#include "storage/browser/blob/blob_url_request_job_factory.h"
#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/WebKit/public/platform/modules/serviceworker/WebServiceWorkerResponseType.h"
namespace content {
@@ -76,40 +79,40 @@ using MetadataCallback =
// is controlled per-origin by the QuotaManager.
const int kMaxCacheBytes = std::numeric_limits<int>::max();
-blink::WebServiceWorkerResponseType ProtoResponseTypeToWebResponseType(
+network::mojom::FetchResponseType ProtoResponseTypeToFetchResponseType(
proto::CacheResponse::ResponseType response_type) {
switch (response_type) {
case proto::CacheResponse::BASIC_TYPE:
- return blink::kWebServiceWorkerResponseTypeBasic;
+ return network::mojom::FetchResponseType::kBasic;
case proto::CacheResponse::CORS_TYPE:
- return blink::kWebServiceWorkerResponseTypeCORS;
+ return network::mojom::FetchResponseType::kCORS;
case proto::CacheResponse::DEFAULT_TYPE:
- return blink::kWebServiceWorkerResponseTypeDefault;
+ return network::mojom::FetchResponseType::kDefault;
case proto::CacheResponse::ERROR_TYPE:
- return blink::kWebServiceWorkerResponseTypeError;
+ return network::mojom::FetchResponseType::kError;
case proto::CacheResponse::OPAQUE_TYPE:
- return blink::kWebServiceWorkerResponseTypeOpaque;
+ return network::mojom::FetchResponseType::kOpaque;
case proto::CacheResponse::OPAQUE_REDIRECT_TYPE:
- return blink::kWebServiceWorkerResponseTypeOpaqueRedirect;
+ return network::mojom::FetchResponseType::kOpaqueRedirect;
}
NOTREACHED();
- return blink::kWebServiceWorkerResponseTypeOpaque;
+ return network::mojom::FetchResponseType::kOpaque;
}
-proto::CacheResponse::ResponseType WebResponseTypeToProtoResponseType(
- blink::WebServiceWorkerResponseType response_type) {
+proto::CacheResponse::ResponseType FetchResponseTypeToProtoResponseType(
+ network::mojom::FetchResponseType response_type) {
switch (response_type) {
- case blink::kWebServiceWorkerResponseTypeBasic:
+ case network::mojom::FetchResponseType::kBasic:
return proto::CacheResponse::BASIC_TYPE;
- case blink::kWebServiceWorkerResponseTypeCORS:
+ case network::mojom::FetchResponseType::kCORS:
return proto::CacheResponse::CORS_TYPE;
- case blink::kWebServiceWorkerResponseTypeDefault:
+ case network::mojom::FetchResponseType::kDefault:
return proto::CacheResponse::DEFAULT_TYPE;
- case blink::kWebServiceWorkerResponseTypeError:
+ case network::mojom::FetchResponseType::kError:
return proto::CacheResponse::ERROR_TYPE;
- case blink::kWebServiceWorkerResponseTypeOpaque:
+ case network::mojom::FetchResponseType::kOpaque:
return proto::CacheResponse::OPAQUE_TYPE;
- case blink::kWebServiceWorkerResponseTypeOpaqueRedirect:
+ case network::mojom::FetchResponseType::kOpaqueRedirect:
return proto::CacheResponse::OPAQUE_REDIRECT_TYPE;
}
NOTREACHED();
@@ -246,8 +249,9 @@ std::unique_ptr<ServiceWorkerResponse> CreateResponse(
return base::MakeUnique<ServiceWorkerResponse>(
std::move(url_list), metadata.response().status_code(),
metadata.response().status_text(),
- ProtoResponseTypeToWebResponseType(metadata.response().response_type()),
- std::move(headers), "", 0, blink::kWebServiceWorkerResponseErrorUnknown,
+ ProtoResponseTypeToFetchResponseType(metadata.response().response_type()),
+ std::move(headers), "", 0, nullptr /* blob */,
+ blink::kWebServiceWorkerResponseErrorUnknown,
base::Time::FromInternalValue(metadata.response().response_time()),
true /* is_in_cache_storage */, cache_name,
base::MakeUnique<ServiceWorkerHeaderList>(
@@ -1059,6 +1063,8 @@ void CacheStorageCache::Put(const CacheStorageBatchOperation& operation,
std::unique_ptr<storage::BlobDataHandle> blob_data_handle;
if (!response->blob_uuid.empty()) {
+ DCHECK_EQ(response->blob != nullptr,
+ base::FeatureList::IsEnabled(features::kMojoBlobs));
if (!blob_storage_context_) {
std::move(callback).Run(CACHE_STORAGE_ERROR_STORAGE);
return;
@@ -1074,8 +1080,7 @@ void CacheStorageCache::Put(const CacheStorageBatchOperation& operation,
UMA_HISTOGRAM_ENUMERATION(
"ServiceWorkerCache.Cache.AllWritesResponseType",
operation.response.response_type,
- blink::WebServiceWorkerResponseType::kWebServiceWorkerResponseTypeLast +
- 1);
+ static_cast<int>(network::mojom::FetchResponseType::kLast) + 1);
std::unique_ptr<PutContext> put_context(new PutContext(
std::move(request), std::move(response), std::move(blob_data_handle),
@@ -1161,8 +1166,8 @@ void CacheStorageCache::PutDidCreateEntry(
proto::CacheResponse* response_metadata = metadata.mutable_response();
response_metadata->set_status_code(put_context->response->status_code);
response_metadata->set_status_text(put_context->response->status_text);
- response_metadata->set_response_type(
- WebResponseTypeToProtoResponseType(put_context->response->response_type));
+ response_metadata->set_response_type(FetchResponseTypeToProtoResponseType(
+ put_context->response->response_type));
for (const auto& url : put_context->response->url_list)
response_metadata->add_url_list(url.spec());
response_metadata->set_response_time(
@@ -1299,6 +1304,9 @@ void CacheStorageCache::UpdateCacheSizeGotSize(
storage::QuotaClient::kServiceWorkerCache, origin_,
storage::kStorageTypeTemporary, size_delta);
+ if (cache_storage_)
+ cache_storage_->NotifyCacheContentChanged(cache_name_);
+
if (cache_observer_)
cache_observer_->CacheSizeUpdated(this, current_cache_size);
@@ -1396,11 +1404,18 @@ void CacheStorageCache::KeysDidQueryCache(
}
void CacheStorageCache::CloseImpl(base::OnceClosure callback) {
- DCHECK_NE(BACKEND_CLOSED, backend_state_);
+ DCHECK_EQ(BACKEND_OPEN, backend_state_);
- backend_state_ = BACKEND_CLOSED;
backend_.reset();
- std::move(callback).Run();
+ post_backend_closed_callback_ = std::move(callback);
+}
+
+void CacheStorageCache::DeleteBackendCompletedIO() {
+ if (!post_backend_closed_callback_.is_null()) {
+ DCHECK_NE(BACKEND_CLOSED, backend_state_);
+ backend_state_ = BACKEND_CLOSED;
+ std::move(post_backend_closed_callback_).Run();
+ }
}
void CacheStorageCache::SizeImpl(SizeCallback callback) {
@@ -1433,13 +1448,13 @@ void CacheStorageCache::CreateBackend(ErrorCallback callback) {
weak_ptr_factory_.GetWeakPtr(), std::move(callback),
base::Passed(std::move(backend_ptr))));
- // TODO(jkarlin): Use the cache task runner that ServiceWorkerCacheCore
- // has for disk caches.
int rv = disk_cache::CreateCacheBackend(
cache_type, net::CACHE_BACKEND_SIMPLE, path_, kMaxCacheBytes,
false, /* force */
- BrowserThread::GetTaskRunnerForThread(BrowserThread::CACHE).get(), NULL,
- backend, create_cache_callback);
+ NULL, backend,
+ base::BindOnce(&CacheStorageCache::DeleteBackendCompletedIO,
+ weak_ptr_factory_.GetWeakPtr()),
+ create_cache_callback);
if (rv != net::ERR_IO_PENDING)
create_cache_callback.Run(rv);
}
@@ -1535,7 +1550,18 @@ CacheStorageCache::PopulateResponseBody(disk_cache::ScopedEntryPtr entry,
blob_data.AppendDiskCacheEntryWithSideData(
new CacheStorageCacheDataHandle(CreateCacheHandle(), std::move(entry)),
temp_entry, INDEX_RESPONSE_BODY, INDEX_SIDE_DATA);
- return blob_storage_context_->AddFinishedBlob(&blob_data);
+ auto result = blob_storage_context_->AddFinishedBlob(&blob_data);
+
+ if (base::FeatureList::IsEnabled(features::kMojoBlobs)) {
+ storage::mojom::BlobPtr blob_ptr;
+ storage::BlobImpl::Create(
+ base::MakeUnique<storage::BlobDataHandle>(*result),
+ MakeRequest(&blob_ptr));
+ response->blob =
+ base::MakeRefCounted<storage::BlobHandle>(std::move(blob_ptr));
+ }
+
+ return result;
}
std::unique_ptr<CacheStorageCacheHandle>
diff --git a/chromium/content/browser/cache_storage/cache_storage_cache.h b/chromium/content/browser/cache_storage/cache_storage_cache.h
index 3a737bd7a91..38a622c30f1 100644
--- a/chromium/content/browser/cache_storage/cache_storage_cache.h
+++ b/chromium/content/browser/cache_storage/cache_storage_cache.h
@@ -12,8 +12,8 @@
#include <vector>
#include "base/callback.h"
+#include "base/containers/id_map.h"
#include "base/files/file_path.h"
-#include "base/id_map.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "content/common/cache_storage/cache_storage_types.h"
@@ -198,7 +198,7 @@ class CONTENT_EXPORT CacheStorageCache {
using Entries = std::vector<disk_cache::Entry*>;
using ScopedBackendPtr = std::unique_ptr<disk_cache::Backend>;
using BlobToDiskCacheIDMap =
- IDMap<std::unique_ptr<CacheStorageBlobToDiskCache>>;
+ base::IDMap<std::unique_ptr<CacheStorageBlobToDiskCache>>;
CacheStorageCache(
const GURL& origin,
@@ -362,6 +362,7 @@ class CONTENT_EXPORT CacheStorageCache {
void InitGotCacheSize(base::OnceClosure callback,
CacheStorageError cache_create_error,
int cache_size);
+ void DeleteBackendCompletedIO();
std::unique_ptr<storage::BlobDataHandle> PopulateResponseBody(
disk_cache::ScopedEntryPtr entry,
@@ -396,6 +397,10 @@ class CONTENT_EXPORT CacheStorageCache {
// Whether or not to store data in disk or memory.
bool memory_only_;
+ // Active while waiting for the backend to finish its closing up, and contains
+ // the callback passed to CloseImpl.
+ base::OnceClosure post_backend_closed_callback_;
+
base::WeakPtrFactory<CacheStorageCache> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(CacheStorageCache);
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 30dfe7754cf..ca22403d12e 100644
--- a/chromium/content/browser/cache_storage/cache_storage_cache_unittest.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_cache_unittest.cc
@@ -29,7 +29,9 @@
#include "content/public/common/referrer.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 "net/base/test_completion_callback.h"
+#include "net/disk_cache/disk_cache.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
#include "net/url_request/url_request_job_factory_impl.h"
@@ -41,6 +43,7 @@
#include "storage/browser/quota/quota_manager_proxy.h"
#include "storage/browser/test/mock_quota_manager_proxy.h"
#include "storage/browser/test/mock_special_storage_policy.h"
+#include "storage/common/blob_storage/blob_handle.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
@@ -354,7 +357,7 @@ class CacheStorageCacheTest : public testing::Test {
quota_policy_ = new MockSpecialStoragePolicy;
mock_quota_manager_ = new MockQuotaManager(
is_incognito, temp_dir_path, base::ThreadTaskRunnerHandle::Get().get(),
- base::ThreadTaskRunnerHandle::Get().get(), quota_policy_.get());
+ quota_policy_.get());
mock_quota_manager_->SetQuota(GURL(kOrigin), storage::kStorageTypeTemporary,
1024 * 1024 * 100);
@@ -383,7 +386,8 @@ class CacheStorageCacheTest : public testing::Test {
void TearDown() override {
quota_manager_proxy_->SimulateQuotaManagerDestroyed();
- base::RunLoop().RunUntilIdle();
+ disk_cache::FlushCacheThreadForTesting();
+ content::RunAllBlockingPoolTasksUntilIdle();
}
void CreateRequests(ChromeBlobStorageContext* blob_storage_context) {
@@ -443,9 +447,10 @@ class CacheStorageCacheTest : public testing::Test {
std::unique_ptr<ServiceWorkerHeaderList> cors_exposed_header_names) {
return ServiceWorkerResponse(
base::MakeUnique<std::vector<GURL>>(1, GURL(url)), 200, "OK",
- blink::kWebServiceWorkerResponseTypeDefault, std::move(headers),
- blob_uuid, blob_size, blink::kWebServiceWorkerResponseErrorUnknown,
- base::Time::Now(), false /* is_in_cache_storage */,
+ network::mojom::FetchResponseType::kDefault, std::move(headers),
+ blob_uuid, blob_size, nullptr /* blob */,
+ blink::kWebServiceWorkerResponseErrorUnknown, base::Time::Now(),
+ false /* is_in_cache_storage */,
std::string() /* cache_storage_cache_name */,
std::move(cors_exposed_header_names));
}
@@ -671,7 +676,7 @@ class CacheStorageCacheTest : public testing::Test {
run_loop->Quit();
}
- bool TestResponseType(blink::WebServiceWorkerResponseType response_type) {
+ bool TestResponseType(network::mojom::FetchResponseType response_type) {
body_response_.response_type = response_type;
EXPECT_TRUE(Put(body_request_, body_response_));
EXPECT_TRUE(Match(body_request_));
@@ -1408,11 +1413,13 @@ TEST_P(CacheStorageCacheTestP, QuickStressBody) {
}
TEST_P(CacheStorageCacheTestP, PutResponseType) {
- EXPECT_TRUE(TestResponseType(blink::kWebServiceWorkerResponseTypeBasic));
- EXPECT_TRUE(TestResponseType(blink::kWebServiceWorkerResponseTypeCORS));
- EXPECT_TRUE(TestResponseType(blink::kWebServiceWorkerResponseTypeDefault));
- EXPECT_TRUE(TestResponseType(blink::kWebServiceWorkerResponseTypeError));
- EXPECT_TRUE(TestResponseType(blink::kWebServiceWorkerResponseTypeOpaque));
+ EXPECT_TRUE(TestResponseType(network::mojom::FetchResponseType::kBasic));
+ EXPECT_TRUE(TestResponseType(network::mojom::FetchResponseType::kCORS));
+ EXPECT_TRUE(TestResponseType(network::mojom::FetchResponseType::kDefault));
+ EXPECT_TRUE(TestResponseType(network::mojom::FetchResponseType::kError));
+ EXPECT_TRUE(TestResponseType(network::mojom::FetchResponseType::kOpaque));
+ EXPECT_TRUE(
+ TestResponseType(network::mojom::FetchResponseType::kOpaqueRedirect));
}
TEST_P(CacheStorageCacheTestP, WriteSideData) {
@@ -1517,8 +1524,8 @@ TEST_F(CacheStorageCacheTest, CaselessServiceWorkerResponseHeaders) {
// headers so that it can quickly lookup vary headers.
ServiceWorkerResponse response(
base::MakeUnique<std::vector<GURL>>(), 200, "OK",
- blink::kWebServiceWorkerResponseTypeDefault,
- base::MakeUnique<ServiceWorkerHeaderMap>(), "", 0,
+ network::mojom::FetchResponseType::kDefault,
+ base::MakeUnique<ServiceWorkerHeaderMap>(), "", 0, nullptr /* blob */,
blink::kWebServiceWorkerResponseErrorUnknown, base::Time(),
false /* is_in_cache_storage */,
std::string() /* cache_storage_cache_name */,
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 b34e08c9e8f..448c7e3b760 100644
--- a/chromium/content/browser/cache_storage/cache_storage_context_impl.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_context_impl.cc
@@ -16,6 +16,7 @@
#include "storage/browser/blob/blob_storage_context.h"
#include "storage/browser/quota/quota_manager_proxy.h"
#include "storage/browser/quota/special_storage_policy.h"
+#include "url/origin.h"
namespace content {
@@ -99,6 +100,20 @@ void CacheStorageContextImpl::DeleteForOrigin(const GURL& origin) {
cache_manager_->DeleteOriginData(origin);
}
+void CacheStorageContextImpl::AddObserver(
+ CacheStorageContextImpl::Observer* observer) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ if (cache_manager_)
+ cache_manager_->AddObserver(observer);
+}
+
+void CacheStorageContextImpl::RemoveObserver(
+ CacheStorageContextImpl::Observer* observer) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ if (cache_manager_)
+ cache_manager_->RemoveObserver(observer);
+}
+
void CacheStorageContextImpl::CreateCacheStorageManager(
const base::FilePath& user_data_directory,
scoped_refptr<base::SequencedTaskRunner> cache_task_runner,
diff --git a/chromium/content/browser/cache_storage/cache_storage_context_impl.h b/chromium/content/browser/cache_storage/cache_storage_context_impl.h
index bd0a3207393..47c28f06ce8 100644
--- a/chromium/content/browser/cache_storage/cache_storage_context_impl.h
+++ b/chromium/content/browser/cache_storage/cache_storage_context_impl.h
@@ -26,6 +26,10 @@ namespace storage {
class QuotaManagerProxy;
}
+namespace url {
+class Origin;
+}
+
namespace content {
class BrowserContext;
@@ -36,11 +40,20 @@ class CacheStorageManager;
// child processes/origins. Most logic is delegated to the owned
// CacheStorageManager instance, which is only accessed on the IO
// thread.
-class CONTENT_EXPORT CacheStorageContextImpl
- : NON_EXPORTED_BASE(public CacheStorageContext) {
+class CONTENT_EXPORT CacheStorageContextImpl : public CacheStorageContext {
public:
explicit CacheStorageContextImpl(BrowserContext* browser_context);
+ class Observer {
+ public:
+ virtual void OnCacheListChanged(const url::Origin& origin) = 0;
+ virtual void OnCacheContentChanged(const url::Origin& origin,
+ const std::string& cache_name) = 0;
+
+ protected:
+ virtual ~Observer() {};
+ };
+
// Init and Shutdown are for use on the UI thread when the profile,
// storagepartition is being setup and torn down.
void Init(const base::FilePath& user_data_directory,
@@ -66,6 +79,10 @@ class CONTENT_EXPORT CacheStorageContextImpl
void GetAllOriginsInfo(const GetUsageInfoCallback& callback) override;
void DeleteForOrigin(const GURL& origin) override;
+ // Only callable on the IO thread.
+ void AddObserver(CacheStorageContextImpl::Observer* observer);
+ void RemoveObserver(CacheStorageContextImpl::Observer* observer);
+
protected:
~CacheStorageContextImpl() override;
diff --git a/chromium/content/browser/cache_storage/cache_storage_manager.cc b/chromium/content/browser/cache_storage/cache_storage_manager.cc
index 180377f3665..8457a2f9c83 100644
--- a/chromium/content/browser/cache_storage/cache_storage_manager.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_manager.cc
@@ -12,9 +12,9 @@
#include "base/barrier_closure.h"
#include "base/bind.h"
+#include "base/containers/id_map.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_util.h"
-#include "base/id_map.h"
#include "base/memory/ptr_util.h"
#include "base/sequenced_task_runner.h"
#include "base/sha1.h"
@@ -33,6 +33,7 @@
#include "storage/common/database/database_identifier.h"
#include "storage/common/quota/quota_status_code.h"
#include "url/gurl.h"
+#include "url/origin.h"
namespace content {
@@ -251,6 +252,28 @@ void CacheStorageManager::SetBlobParametersForCache(
blob_context_ = blob_storage_context;
}
+void CacheStorageManager::AddObserver(
+ CacheStorageContextImpl::Observer* observer) {
+ DCHECK(!observers_.HasObserver(observer));
+ observers_.AddObserver(observer);
+}
+
+void CacheStorageManager::RemoveObserver(
+ CacheStorageContextImpl::Observer* observer) {
+ observers_.RemoveObserver(observer);
+}
+
+void CacheStorageManager::NotifyCacheListChanged(const GURL& origin) {
+ for (auto& observer : observers_)
+ observer.OnCacheListChanged(url::Origin(origin));
+}
+
+void CacheStorageManager::NotifyCacheContentChanged(const GURL& origin,
+ const std::string& name) {
+ for (auto& observer : observers_)
+ observer.OnCacheContentChanged(url::Origin(origin), name);
+}
+
void CacheStorageManager::GetAllOriginsUsage(
const CacheStorageContext::GetUsageInfoCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -373,6 +396,7 @@ void CacheStorageManager::DeleteOriginData(
DCHECK(it != cache_storage_map_.end());
CacheStorage* cache_storage = it->second.release();
+ cache_storage->ResetManager();
cache_storage_map_.erase(origin);
cache_storage->GetSizeThenCloseAllCaches(
base::BindOnce(&CacheStorageManager::DeleteOriginDidClose,
@@ -398,6 +422,7 @@ void CacheStorageManager::DeleteOriginDidClose(
quota_manager_proxy_->NotifyStorageModified(
storage::QuotaClient::kServiceWorkerCache, origin,
storage::kStorageTypeTemporary, -1 * origin_size);
+ NotifyCacheListChanged(origin);
if (IsMemoryBacked()) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
@@ -434,7 +459,7 @@ CacheStorage* CacheStorageManager::FindOrCreateCacheStorage(
CacheStorage* cache_storage = new CacheStorage(
ConstructOriginPath(root_path_, origin), IsMemoryBacked(),
cache_task_runner_.get(), request_context_getter_, quota_manager_proxy_,
- blob_context_, origin);
+ blob_context_, this, origin);
cache_storage_map_.insert(
std::make_pair(origin, base::WrapUnique(cache_storage)));
return cache_storage;
diff --git a/chromium/content/browser/cache_storage/cache_storage_manager.h b/chromium/content/browser/cache_storage/cache_storage_manager.h
index e5bbff33712..d3d126ba87b 100644
--- a/chromium/content/browser/cache_storage/cache_storage_manager.h
+++ b/chromium/content/browser/cache_storage/cache_storage_manager.h
@@ -14,6 +14,7 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "content/browser/cache_storage/cache_storage.h"
+#include "content/browser/cache_storage/cache_storage_context_impl.h"
#include "content/common/content_export.h"
#include "content/public/browser/cache_storage_context.h"
#include "content/public/browser/cache_storage_usage_info.h"
@@ -83,6 +84,12 @@ class CONTENT_EXPORT CacheStorageManager {
scoped_refptr<net::URLRequestContextGetter> request_context_getter,
base::WeakPtr<storage::BlobStorageContext> blob_storage_context);
+ void AddObserver(CacheStorageContextImpl::Observer* observer);
+ void RemoveObserver(CacheStorageContextImpl::Observer* observer);
+
+ void NotifyCacheListChanged(const GURL& origin);
+ void NotifyCacheContentChanged(const GURL& origin, const std::string& name);
+
base::WeakPtr<CacheStorageManager> AsWeakPtr() {
return weak_ptr_factory_.GetWeakPtr();
}
@@ -150,6 +157,8 @@ class CONTENT_EXPORT CacheStorageManager {
// |cache_task_runner_|.
CacheStorageMap cache_storage_map_;
+ base::ObserverList<CacheStorageContextImpl::Observer> observers_;
+
scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
base::WeakPtr<storage::BlobStorageContext> blob_context_;
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 c03bc50aa84..c2c6edfeedd 100644
--- a/chromium/content/browser/cache_storage/cache_storage_manager_unittest.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_manager_unittest.cc
@@ -27,6 +27,7 @@
#include "content/browser/cache_storage/cache_storage.h"
#include "content/browser/cache_storage/cache_storage.pb.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_index.h"
#include "content/browser/cache_storage/cache_storage_quota_client.h"
#include "content/public/browser/browser_thread.h"
@@ -34,9 +35,12 @@
#include "content/public/browser/storage_partition.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 "net/disk_cache/disk_cache.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
#include "net/url_request/url_request_job_factory_impl.h"
+#include "services/network/public/interfaces/fetch_api.mojom.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"
@@ -44,6 +48,7 @@
#include "storage/browser/quota/quota_manager_proxy.h"
#include "storage/browser/test/mock_quota_manager_proxy.h"
#include "storage/browser/test/mock_special_storage_policy.h"
+#include "storage/common/blob_storage/blob_handle.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
@@ -78,6 +83,21 @@ void CopyCacheStorageIndex(CacheStorageIndex* dest,
dest->Insert(cache_metadata);
}
+class TestCacheStorageObserver : public CacheStorageContextImpl::Observer {
+ public:
+ void OnCacheListChanged(const url::Origin& origin) override {
+ ++notify_list_changed_count;
+ }
+
+ void OnCacheContentChanged(const url::Origin& origin,
+ const std::string& cache_name) override {
+ ++notify_content_changed_count;
+ }
+
+ int notify_list_changed_count = 0;
+ int notify_content_changed_count = 0;
+};
+
} // anonymous namespace
// Returns a BlobProtocolHandler that uses |blob_storage_context|. Caller owns
@@ -106,7 +126,11 @@ class CacheStorageManagerTest : public testing::Test {
CreateStorageManager();
}
- void TearDown() override { DestroyStorageManager(); }
+ void TearDown() override {
+ DestroyStorageManager();
+ disk_cache::FlushCacheThreadForTesting();
+ content::RunAllBlockingPoolTasksUntilIdle();
+ }
virtual bool MemoryOnly() { return false; }
@@ -155,6 +179,11 @@ class CacheStorageManagerTest : public testing::Test {
run_loop->Quit();
}
+ void CacheDeleteCallback(base::RunLoop* run_loop, CacheStorageError error) {
+ callback_error_ = error;
+ run_loop->Quit();
+ }
+
void CacheMatchCallback(
base::RunLoop* run_loop,
CacheStorageError error,
@@ -191,7 +220,7 @@ class CacheStorageManagerTest : public testing::Test {
quota_policy_ = new MockSpecialStoragePolicy;
mock_quota_manager_ = new MockQuotaManager(
MemoryOnly(), temp_dir_path, base::ThreadTaskRunnerHandle::Get().get(),
- base::ThreadTaskRunnerHandle::Get().get(), quota_policy_.get());
+ quota_policy_.get());
mock_quota_manager_->SetQuota(
GURL(origin1_), storage::kStorageTypeTemporary, 1024 * 1024 * 100);
mock_quota_manager_->SetQuota(
@@ -377,9 +406,9 @@ class CacheStorageManagerTest : public testing::Test {
url_list->push_back(request.url);
ServiceWorkerResponse response(
std::move(url_list), status_code, "OK",
- blink::kWebServiceWorkerResponseTypeDefault,
+ network::mojom::FetchResponseType::kDefault,
base::MakeUnique<ServiceWorkerHeaderMap>(response_headers),
- blob_handle->uuid(), request.url.spec().size(),
+ blob_handle->uuid(), request.url.spec().size(), nullptr /* blob */,
blink::kWebServiceWorkerResponseErrorUnknown, base::Time(),
false /* is_in_cache_storage */,
std::string() /* cache_storage_cache_name */,
@@ -401,6 +430,26 @@ class CacheStorageManagerTest : public testing::Test {
return callback_error_ == CACHE_STORAGE_OK;
}
+ bool CacheDelete(CacheStorageCache* cache, const GURL& url) {
+ ServiceWorkerFetchRequest request;
+ request.url = url;
+ ServiceWorkerResponse response;
+
+ CacheStorageBatchOperation operation;
+ operation.operation_type = CACHE_STORAGE_CACHE_OPERATION_TYPE_DELETE;
+ operation.request = request;
+ operation.response = response;
+
+ base::RunLoop loop;
+ cache->BatchOperation(
+ std::vector<CacheStorageBatchOperation>(1, operation),
+ base::BindOnce(&CacheStorageManagerTest::CacheDeleteCallback,
+ base::Unretained(this), base::Unretained(&loop)));
+ loop.Run();
+
+ return callback_error_ == CACHE_STORAGE_OK;
+ }
+
bool CacheMatch(CacheStorageCache* cache, const GURL& url) {
std::unique_ptr<ServiceWorkerFetchRequest> request(
new ServiceWorkerFetchRequest());
@@ -1220,6 +1269,102 @@ TEST_P(CacheStorageManagerTestP, SizeThenCloseStorageAccessed) {
EXPECT_EQ(0, quota_manager_proxy_->notify_storage_accessed_count());
}
+TEST_P(CacheStorageManagerTestP, NotifyCacheListChanged_Created) {
+ TestCacheStorageObserver observer;
+ cache_manager_->AddObserver(&observer);
+
+ EXPECT_EQ(0, observer.notify_list_changed_count);
+ EXPECT_TRUE(Open(origin1_, "foo"));
+ EXPECT_EQ(1, observer.notify_list_changed_count);
+ EXPECT_TRUE(CachePut(callback_cache_handle_->value(),
+ GURL("http://example.com/foo")));
+ EXPECT_EQ(1, observer.notify_list_changed_count);
+}
+
+TEST_P(CacheStorageManagerTestP, NotifyCacheListChanged_Deleted) {
+ TestCacheStorageObserver observer;
+ cache_manager_->AddObserver(&observer);
+
+ EXPECT_EQ(0, observer.notify_list_changed_count);
+ EXPECT_FALSE(Delete(origin1_, "foo"));
+ EXPECT_EQ(0, observer.notify_list_changed_count);
+ EXPECT_TRUE(Open(origin1_, "foo"));
+ EXPECT_EQ(1, observer.notify_list_changed_count);
+ EXPECT_TRUE(Delete(origin1_, "foo"));
+ EXPECT_EQ(2, observer.notify_list_changed_count);
+}
+
+TEST_P(CacheStorageManagerTestP, NotifyCacheListChanged_DeletedThenCreated) {
+ TestCacheStorageObserver observer;
+ cache_manager_->AddObserver(&observer);
+
+ EXPECT_EQ(0, observer.notify_list_changed_count);
+ EXPECT_TRUE(Open(origin1_, "foo"));
+ EXPECT_EQ(1, observer.notify_list_changed_count);
+ EXPECT_TRUE(Delete(origin1_, "foo"));
+ EXPECT_EQ(2, observer.notify_list_changed_count);
+ EXPECT_TRUE(Open(origin2_, "foo2"));
+ EXPECT_EQ(3, observer.notify_list_changed_count);
+}
+
+TEST_P(CacheStorageManagerTestP, NotifyCacheContentChanged_PutEntry) {
+ TestCacheStorageObserver observer;
+ cache_manager_->AddObserver(&observer);
+
+ EXPECT_EQ(0, observer.notify_content_changed_count);
+ EXPECT_TRUE(Open(origin1_, "foo"));
+ EXPECT_EQ(0, observer.notify_content_changed_count);
+ EXPECT_TRUE(CachePut(callback_cache_handle_->value(),
+ GURL("http://example.com/foo")));
+ EXPECT_EQ(1, observer.notify_content_changed_count);
+ EXPECT_TRUE(CachePut(callback_cache_handle_->value(),
+ GURL("http://example.com/foo1")));
+ EXPECT_TRUE(CachePut(callback_cache_handle_->value(),
+ GURL("http://example.com/foo2")));
+ EXPECT_EQ(3, observer.notify_content_changed_count);
+}
+
+TEST_P(CacheStorageManagerTestP, NotifyCacheContentChanged_DeleteEntry) {
+ TestCacheStorageObserver observer;
+ cache_manager_->AddObserver(&observer);
+
+ EXPECT_EQ(0, observer.notify_content_changed_count);
+ EXPECT_FALSE(Delete(origin1_, "foo"));
+ EXPECT_EQ(0, observer.notify_content_changed_count);
+ EXPECT_TRUE(Open(origin1_, "foo"));
+ EXPECT_EQ(0, observer.notify_content_changed_count);
+ EXPECT_TRUE(CachePut(callback_cache_handle_->value(),
+ GURL("http://example.com/foo")));
+ EXPECT_EQ(1, observer.notify_content_changed_count);
+ EXPECT_TRUE(CacheDelete(callback_cache_handle_->value(),
+ GURL("http://example.com/foo")));
+ EXPECT_EQ(2, observer.notify_content_changed_count);
+ EXPECT_FALSE(CacheDelete(callback_cache_handle_->value(),
+ GURL("http://example.com/foo")));
+ EXPECT_EQ(2, observer.notify_content_changed_count);
+}
+
+TEST_P(CacheStorageManagerTestP, NotifyCacheContentChanged_DeleteThenPutEntry) {
+ TestCacheStorageObserver observer;
+ cache_manager_->AddObserver(&observer);
+
+ EXPECT_EQ(0, observer.notify_content_changed_count);
+ EXPECT_TRUE(Open(origin1_, "foo"));
+ EXPECT_EQ(0, observer.notify_content_changed_count);
+ EXPECT_TRUE(CachePut(callback_cache_handle_->value(),
+ GURL("http://example.com/foo")));
+ EXPECT_EQ(1, observer.notify_content_changed_count);
+ EXPECT_TRUE(CacheDelete(callback_cache_handle_->value(),
+ GURL("http://example.com/foo")));
+ EXPECT_EQ(2, observer.notify_content_changed_count);
+ EXPECT_TRUE(CachePut(callback_cache_handle_->value(),
+ GURL("http://example.com/foo")));
+ EXPECT_EQ(3, observer.notify_content_changed_count);
+ EXPECT_TRUE(CacheDelete(callback_cache_handle_->value(),
+ GURL("http://example.com/foo")));
+ EXPECT_EQ(4, observer.notify_content_changed_count);
+}
+
TEST_P(CacheStorageManagerTestP, StorageMatch_IgnoreSearch) {
EXPECT_TRUE(Open(origin1_, "foo"));
EXPECT_TRUE(CachePut(callback_cache_handle_->value(),
diff --git a/chromium/content/browser/child_process_launcher.cc b/chromium/content/browser/child_process_launcher.cc
index 0d87a7d9413..f6d984071cd 100644
--- a/chromium/content/browser/child_process_launcher.cc
+++ b/chromium/content/browser/child_process_launcher.cc
@@ -60,16 +60,15 @@ ChildProcessLauncher::~ChildProcessLauncher() {
}
}
-void ChildProcessLauncher::SetProcessPriority(bool background,
- bool boost_for_pending_views) {
+void ChildProcessLauncher::SetProcessPriority(
+ const ChildProcessLauncherPriority& priority) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
base::Process to_pass = process_.process.Duplicate();
BrowserThread::PostTask(
BrowserThread::PROCESS_LAUNCHER, FROM_HERE,
- base::Bind(
+ base::BindOnce(
&ChildProcessLauncherHelper::SetProcessPriorityOnLauncherThread,
- helper_, base::Passed(&to_pass), background,
- boost_for_pending_views));
+ helper_, base::Passed(&to_pass), priority));
}
void ChildProcessLauncher::Notify(
@@ -181,4 +180,14 @@ ChildProcessLauncher::Client* ChildProcessLauncher::ReplaceClientForTest(
return ret;
}
+bool ChildProcessLauncherPriority::operator==(
+ const ChildProcessLauncherPriority& other) const {
+ return background == other.background &&
+ boost_for_pending_views == other.boost_for_pending_views
+#if defined(OS_ANDROID)
+ && importance == other.importance
+#endif
+ ;
+}
+
} // namespace content
diff --git a/chromium/content/browser/child_process_launcher.h b/chromium/content/browser/child_process_launcher.h
index 074f2cf6b25..75e57e16f04 100644
--- a/chromium/content/browser/child_process_launcher.h
+++ b/chromium/content/browser/child_process_launcher.h
@@ -22,6 +22,10 @@
#include "mojo/edk/embedder/outgoing_broker_client_invitation.h"
#include "mojo/edk/embedder/scoped_platform_handle.h"
+#if defined(OS_ANDROID)
+#include "content/public/browser/android/child_process_importance.h"
+#endif
+
namespace base {
class CommandLine;
}
@@ -49,6 +53,19 @@ static_assert(static_cast<int>(LAUNCH_RESULT_START) >
"LaunchResultCode must not overlap with sandbox::ResultCode");
#endif
+struct ChildProcessLauncherPriority {
+ bool background;
+ bool boost_for_pending_views;
+#if defined(OS_ANDROID)
+ ChildProcessImportance importance;
+#endif
+
+ bool operator==(const ChildProcessLauncherPriority& other) const;
+ bool operator!=(const ChildProcessLauncherPriority& other) const {
+ return !(*this == other);
+ }
+};
+
// Launches a process asynchronously and notifies the client of the process
// handle when it's available. It's used to avoid blocking the calling thread
// on the OS since often it can take > 100 ms to create the process.
@@ -108,7 +125,7 @@ class CONTENT_EXPORT ChildProcessLauncher {
// Changes whether the process runs in the background or not. Only call
// this after the process has started.
- void SetProcessPriority(bool background, bool boost_for_pending_views);
+ void SetProcessPriority(const ChildProcessLauncherPriority& priority);
// Terminates the process associated with this ChildProcessLauncher.
// Returns true if the process was stopped, false if the process had not been
diff --git a/chromium/content/browser/child_process_launcher_helper.cc b/chromium/content/browser/child_process_launcher_helper.cc
index 86533fe7ac4..7b5ce4eae65 100644
--- a/chromium/content/browser/child_process_launcher_helper.cc
+++ b/chromium/content/browser/child_process_launcher_helper.cc
@@ -82,7 +82,8 @@ void ChildProcessLauncherHelper::StartLaunchOnClientThread() {
BrowserThread::PostTask(
BrowserThread::PROCESS_LAUNCHER, FROM_HERE,
- base::Bind(&ChildProcessLauncherHelper::LaunchOnLauncherThread, this));
+ base::BindOnce(&ChildProcessLauncherHelper::LaunchOnLauncherThread,
+ this));
}
void ChildProcessLauncherHelper::LaunchOnLauncherThread() {
@@ -124,8 +125,8 @@ void ChildProcessLauncherHelper::PostLaunchOnLauncherThread(
BrowserThread::PostTask(
client_thread_id_, FROM_HERE,
- base::Bind(&ChildProcessLauncherHelper::PostLaunchOnClientThread, this,
- base::Passed(&process), launch_result));
+ base::BindOnce(&ChildProcessLauncherHelper::PostLaunchOnClientThread,
+ this, base::Passed(&process), launch_result));
}
void ChildProcessLauncherHelper::PostLaunchOnClientThread(
@@ -155,8 +156,9 @@ void ChildProcessLauncherHelper::ForceNormalProcessTerminationAsync(
// So don't do this on the UI/IO threads.
BrowserThread::PostTask(
BrowserThread::PROCESS_LAUNCHER, FROM_HERE,
- base::Bind(&ChildProcessLauncherHelper::ForceNormalProcessTerminationSync,
- base::Passed(&process)));
+ base::BindOnce(
+ &ChildProcessLauncherHelper::ForceNormalProcessTerminationSync,
+ base::Passed(&process)));
}
} // namespace internal
diff --git a/chromium/content/browser/child_process_launcher_helper.h b/chromium/content/browser/child_process_launcher_helper.h
index c68e0a52f8b..4a684026c89 100644
--- a/chromium/content/browser/child_process_launcher_helper.h
+++ b/chromium/content/browser/child_process_launcher_helper.h
@@ -25,7 +25,7 @@
#if defined(OS_WIN)
#include "sandbox/win/src/sandbox_types.h"
#else
-#include "content/public/browser/file_descriptor_info.h"
+#include "content/public/browser/posix_file_descriptor_info.h"
#endif
#if defined(OS_LINUX)
@@ -43,16 +43,19 @@ class CommandLine;
namespace content {
class ChildProcessLauncher;
-class FileDescriptorInfo;
class SandboxedProcessLauncherDelegate;
+struct ChildProcessLauncherPriority;
-namespace internal {
+#if defined(OS_POSIX)
+class PosixFileDescriptorInfo;
+#endif
+namespace internal {
-#if defined(OS_WIN)
-using FileMappedForLaunch = base::HandlesToInheritVector;
+#if defined(OS_POSIX)
+using FileMappedForLaunch = PosixFileDescriptorInfo;
#else
-using FileMappedForLaunch = FileDescriptorInfo;
+using FileMappedForLaunch = base::HandlesToInheritVector;
#endif
// ChildProcessLauncherHelper is used by ChildProcessLauncher to start a
@@ -157,9 +160,9 @@ class ChildProcessLauncherHelper :
static void ForceNormalProcessTerminationAsync(
ChildProcessLauncherHelper::Process process);
- void SetProcessPriorityOnLauncherThread(base::Process process,
- bool background,
- bool boost_for_pending_views);
+ void SetProcessPriorityOnLauncherThread(
+ base::Process process,
+ const ChildProcessLauncherPriority& priority);
static void SetRegisteredFilesForService(
const std::string& service_name,
diff --git a/chromium/content/browser/child_process_launcher_helper_android.cc b/chromium/content/browser/child_process_launcher_helper_android.cc
index 22437ad8594..0496ad309d4 100644
--- a/chromium/content/browser/child_process_launcher_helper_android.cc
+++ b/chromium/content/browser/child_process_launcher_helper_android.cc
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/browser/child_process_launcher_helper_android.h"
-
#include <memory>
#include "base/android/apk_assets.h"
@@ -11,9 +9,10 @@
#include "base/i18n/icu_util.h"
#include "base/logging.h"
#include "base/metrics/field_trial.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/file_descriptor_info_impl.h"
+#include "content/browser/posix_file_descriptor_info_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
@@ -63,7 +62,7 @@ ChildProcessLauncherHelper::PrepareMojoPipeHandlesOnClientThread() {
return mojo::edk::ScopedPlatformHandle();
}
-std::unique_ptr<FileDescriptorInfo>
+std::unique_ptr<PosixFileDescriptorInfo>
ChildProcessLauncherHelper::GetFilesToMap() {
DCHECK_CURRENTLY_ON(BrowserThread::PROCESS_LAUNCHER);
@@ -71,7 +70,7 @@ ChildProcessLauncherHelper::GetFilesToMap() {
// running in single process mode.
CHECK(!command_line()->HasSwitch(switches::kSingleProcess));
- std::unique_ptr<FileDescriptorInfo> files_to_register =
+ std::unique_ptr<PosixFileDescriptorInfo> files_to_register =
CreateDefaultPosixFilesToMap(child_process_id(), mojo_client_handle(),
true /* include_service_required_files */,
GetProcessType(), command_line());
@@ -86,14 +85,13 @@ ChildProcessLauncherHelper::GetFilesToMap() {
}
void ChildProcessLauncherHelper::BeforeLaunchOnLauncherThread(
- const FileDescriptorInfo& files_to_register,
- base::LaunchOptions* options) {
-}
+ const PosixFileDescriptorInfo& files_to_register,
+ base::LaunchOptions* options) {}
ChildProcessLauncherHelper::Process
ChildProcessLauncherHelper::LaunchProcessOnLauncherThread(
const base::LaunchOptions& options,
- std::unique_ptr<FileDescriptorInfo> files_to_register,
+ std::unique_ptr<PosixFileDescriptorInfo> files_to_register,
bool* is_synchronous_launch,
int* launch_result) {
*is_synchronous_launch = false;
@@ -173,12 +171,12 @@ void ChildProcessLauncherHelper::ForceNormalProcessTerminationSync(
void ChildProcessLauncherHelper::SetProcessPriorityOnLauncherThread(
base::Process process,
- bool background,
- bool boost_for_pending_views) {
+ const ChildProcessLauncherPriority& priority) {
JNIEnv* env = AttachCurrentThread();
DCHECK(env);
- return Java_ChildProcessLauncherHelper_setInForeground(
- env, java_peer_, process.Handle(), !background, boost_for_pending_views);
+ return Java_ChildProcessLauncherHelper_setPriority(
+ env, java_peer_, process.Handle(), !priority.background,
+ priority.boost_for_pending_views, static_cast<jint>(priority.importance));
}
// static
@@ -228,8 +226,4 @@ size_t ChildProcessLauncherHelper::GetNumberOfRendererSlots() {
} // namespace internal
-bool RegisterChildProcessLauncher(JNIEnv* env) {
- return internal::RegisterNativesImpl(env);
-}
-
} // namespace content
diff --git a/chromium/content/browser/child_process_launcher_helper_android.h b/chromium/content/browser/child_process_launcher_helper_android.h
deleted file mode 100644
index 50c083872e0..00000000000
--- a/chromium/content/browser/child_process_launcher_helper_android.h
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_CHILD_PROCESS_LAUNCHER_HELPER_ANDROID_H_
-#define CONTENT_BROWSER_CHILD_PROCESS_LAUNCHER_HELPER_ANDROID_H_
-
-#include <jni.h>
-
-namespace content {
-
-bool RegisterChildProcessLauncher(JNIEnv* env);
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_CHILD_PROCESS_LAUNCHER_HELPER_ANDROID_H_
diff --git a/chromium/content/browser/child_process_launcher_helper_fuchsia.cc b/chromium/content/browser/child_process_launcher_helper_fuchsia.cc
new file mode 100644
index 00000000000..e714128b401
--- /dev/null
+++ b/chromium/content/browser/child_process_launcher_helper_fuchsia.cc
@@ -0,0 +1,115 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/child_process_launcher_helper.h"
+
+#include "base/command_line.h"
+#include "base/process/launch.h"
+#include "content/browser/child_process_launcher.h"
+#include "mojo/edk/embedder/platform_channel_pair.h"
+
+namespace content {
+namespace internal {
+
+void ChildProcessLauncherHelper::SetProcessPriorityOnLauncherThread(
+ base::Process process,
+ const ChildProcessLauncherPriority& priority) {
+ DCHECK_CURRENTLY_ON(BrowserThread::PROCESS_LAUNCHER);
+ // TODO(fuchsia): Implement this. (crbug.com/707031)
+ NOTIMPLEMENTED();
+}
+
+base::TerminationStatus ChildProcessLauncherHelper::GetTerminationStatus(
+ const ChildProcessLauncherHelper::Process& process,
+ bool known_dead,
+ int* exit_code) {
+ return base::GetTerminationStatus(process.process.Handle(), exit_code);
+}
+
+// static
+bool ChildProcessLauncherHelper::TerminateProcess(const base::Process& process,
+ int exit_code,
+ bool wait) {
+ return process.Terminate(exit_code, wait);
+}
+
+// static
+void ChildProcessLauncherHelper::SetRegisteredFilesForService(
+ const std::string& service_name,
+ catalog::RequiredFileMap required_files) {
+ // TODO(fuchsia): Implement this. (crbug.com/707031)
+ NOTIMPLEMENTED();
+}
+
+// static
+void ChildProcessLauncherHelper::ResetRegisteredFilesForTesting() {
+ // TODO(fuchsia): Implement this. (crbug.com/707031)
+ NOTIMPLEMENTED();
+}
+
+void ChildProcessLauncherHelper::BeforeLaunchOnClientThread() {
+ DCHECK_CURRENTLY_ON(client_thread_id_);
+}
+
+mojo::edk::ScopedPlatformHandle
+ChildProcessLauncherHelper::PrepareMojoPipeHandlesOnClientThread() {
+ DCHECK_CURRENTLY_ON(client_thread_id_);
+
+ // By doing nothing here, StartLaunchOnClientThread() will construct a channel
+ // pair instead.
+ return mojo::edk::ScopedPlatformHandle();
+}
+
+std::unique_ptr<FileMappedForLaunch>
+ChildProcessLauncherHelper::GetFilesToMap() {
+ DCHECK_CURRENTLY_ON(BrowserThread::PROCESS_LAUNCHER);
+ return std::unique_ptr<FileMappedForLaunch>();
+}
+
+void ChildProcessLauncherHelper::BeforeLaunchOnLauncherThread(
+ const PosixFileDescriptorInfo& files_to_register,
+ base::LaunchOptions* options) {
+ DCHECK_CURRENTLY_ON(BrowserThread::PROCESS_LAUNCHER);
+
+ mojo::edk::PlatformChannelPair::PrepareToPassHandleToChildProcess(
+ mojo_client_handle(), command_line(), &options->handles_to_transfer);
+}
+
+ChildProcessLauncherHelper::Process
+ChildProcessLauncherHelper::LaunchProcessOnLauncherThread(
+ const base::LaunchOptions& options,
+ std::unique_ptr<FileMappedForLaunch> files_to_register,
+ bool* is_synchronous_launch,
+ int* launch_result) {
+ DCHECK_CURRENTLY_ON(BrowserThread::PROCESS_LAUNCHER);
+ DCHECK(mojo_client_handle().is_valid());
+
+ // TODO(750938): Implement sandboxed/isolated subprocess launching.
+ Process child_process;
+ child_process.process = base::LaunchProcess(*command_line(), options);
+ return child_process;
+}
+
+void ChildProcessLauncherHelper::AfterLaunchOnLauncherThread(
+ const ChildProcessLauncherHelper::Process& process,
+ const base::LaunchOptions& options) {
+ DCHECK_CURRENTLY_ON(BrowserThread::PROCESS_LAUNCHER);
+
+ if (process.process.IsValid()) {
+ // |mojo_client_handle_| has already been transferred to the child process
+ // by this point. Remove it from the scoped container so that we don't
+ // erroneously delete it.
+ ignore_result(mojo_client_handle_.release());
+ }
+}
+
+// static
+void ChildProcessLauncherHelper::ForceNormalProcessTerminationSync(
+ ChildProcessLauncherHelper::Process process) {
+ DCHECK_CURRENTLY_ON(BrowserThread::PROCESS_LAUNCHER);
+ process.process.Terminate(RESULT_CODE_NORMAL_EXIT, true);
+}
+
+} // namespace internal
+} // namespace content
diff --git a/chromium/content/browser/child_process_launcher_helper_linux.cc b/chromium/content/browser/child_process_launcher_helper_linux.cc
index 0b2387d7a69..e720b93f2d2 100644
--- a/chromium/content/browser/child_process_launcher_helper_linux.cc
+++ b/chromium/content/browser/child_process_launcher_helper_linux.cc
@@ -40,22 +40,19 @@ ChildProcessLauncherHelper::GetFilesToMap() {
}
void ChildProcessLauncherHelper::BeforeLaunchOnLauncherThread(
- const FileDescriptorInfo& files_to_register,
+ const PosixFileDescriptorInfo& files_to_register,
base::LaunchOptions* options) {
// Convert FD mapping to FileHandleMappingVector
- std::unique_ptr<base::FileHandleMappingVector> fds_to_map =
- files_to_register.GetMappingWithIDAdjustment(
- base::GlobalDescriptors::kBaseDescriptor);
+ options->fds_to_remap = files_to_register.GetMappingWithIDAdjustment(
+ base::GlobalDescriptors::kBaseDescriptor);
if (GetProcessType() == switches::kRendererProcess) {
const int sandbox_fd =
RenderSandboxHostLinux::GetInstance()->GetRendererSocket();
- fds_to_map->push_back(std::make_pair(sandbox_fd, GetSandboxFD()));
+ options->fds_to_remap.push_back(std::make_pair(sandbox_fd, GetSandboxFD()));
}
options->environ = delegate_->GetEnvironment();
- // fds_to_remap will de deleted in AfterLaunchOnLauncherThread() below.
- options->fds_to_remap = fds_to_map.release();
}
ChildProcessLauncherHelper::Process
@@ -93,7 +90,6 @@ ChildProcessLauncherHelper::LaunchProcessOnLauncherThread(
void ChildProcessLauncherHelper::AfterLaunchOnLauncherThread(
const ChildProcessLauncherHelper::Process& process,
const base::LaunchOptions& options) {
- delete options.fds_to_remap;
}
base::TerminationStatus ChildProcessLauncherHelper::GetTerminationStatus(
@@ -133,11 +129,10 @@ void ChildProcessLauncherHelper::ForceNormalProcessTerminationSync(
void ChildProcessLauncherHelper::SetProcessPriorityOnLauncherThread(
base::Process process,
- bool background,
- bool boost_for_pending_views) {
+ const ChildProcessLauncherPriority& priority) {
DCHECK_CURRENTLY_ON(BrowserThread::PROCESS_LAUNCHER);
if (process.CanBackgroundProcesses())
- process.SetProcessBackgrounded(background);
+ process.SetProcessBackgrounded(priority.background);
}
// static
diff --git a/chromium/content/browser/child_process_launcher_helper_mac.cc b/chromium/content/browser/child_process_launcher_helper_mac.cc
index c90a377d647..8da7dfb11a8 100644
--- a/chromium/content/browser/child_process_launcher_helper_mac.cc
+++ b/chromium/content/browser/child_process_launcher_helper_mac.cc
@@ -38,7 +38,7 @@ void ChildProcessLauncherHelper::BeforeLaunchOnClientThread() {
DCHECK_CURRENTLY_ON(client_thread_id_);
}
-std::unique_ptr<FileDescriptorInfo>
+std::unique_ptr<PosixFileDescriptorInfo>
ChildProcessLauncherHelper::GetFilesToMap() {
DCHECK_CURRENTLY_ON(BrowserThread::PROCESS_LAUNCHER);
return CreateDefaultPosixFilesToMap(
@@ -51,14 +51,15 @@ void ChildProcessLauncherHelper::BeforeLaunchOnLauncherThread(
const FileMappedForLaunch& files_to_register,
base::LaunchOptions* options) {
// Convert FD mapping to FileHandleMappingVector.
- std::unique_ptr<base::FileHandleMappingVector> fds_to_map =
- files_to_register.GetMappingWithIDAdjustment(
- base::GlobalDescriptors::kBaseDescriptor);
+ options->fds_to_remap = files_to_register.GetMappingWithIDAdjustment(
+ base::GlobalDescriptors::kBaseDescriptor);
options->environ = delegate_->GetEnvironment();
+ bool no_sandbox = command_line_->HasSwitch(switches::kNoSandbox);
+
if (base::FeatureList::IsEnabled(features::kMacV2Sandbox) &&
- GetProcessType() == switches::kRendererProcess) {
+ GetProcessType() == switches::kRendererProcess && !no_sandbox) {
seatbelt_exec_client_ = base::MakeUnique<sandbox::SeatbeltExecClient>();
base::StringPiece renderer_sb = GetContentClient()->GetDataResource(
IDR_RENDERER_SANDBOX_V2_PROFILE, ui::SCALE_FACTOR_NONE);
@@ -73,7 +74,7 @@ void ChildProcessLauncherHelper::BeforeLaunchOnLauncherThread(
base::FilePath helper_executable;
CHECK(PathService::Get(content::CHILD_PROCESS_EXE, &helper_executable));
- fds_to_map->push_back(std::make_pair(pipe, pipe));
+ options->fds_to_remap.push_back(std::make_pair(pipe, pipe));
// Update the command line to enable the V2 sandbox and pass the
// communication FD to the helper executable.
@@ -81,9 +82,6 @@ void ChildProcessLauncherHelper::BeforeLaunchOnLauncherThread(
command_line_->AppendArg("--fd_mapping=" + std::to_string(pipe));
}
- // fds_to_remap will de deleted in AfterLaunchOnLauncherThread() below.
- options->fds_to_remap = fds_to_map.release();
-
// Hold the MachBroker lock for the duration of LaunchProcess. The child will
// send its task port to the parent almost immediately after startup. The Mach
// message will be delivered to the parent, but updating the record of the
@@ -115,7 +113,7 @@ void ChildProcessLauncherHelper::BeforeLaunchOnLauncherThread(
ChildProcessLauncherHelper::Process
ChildProcessLauncherHelper::LaunchProcessOnLauncherThread(
const base::LaunchOptions& options,
- std::unique_ptr<FileDescriptorInfo> files_to_register,
+ std::unique_ptr<PosixFileDescriptorInfo> files_to_register,
bool* is_synchronous_launch,
int* launch_result) {
*is_synchronous_launch = true;
@@ -129,8 +127,6 @@ ChildProcessLauncherHelper::LaunchProcessOnLauncherThread(
void ChildProcessLauncherHelper::AfterLaunchOnLauncherThread(
const ChildProcessLauncherHelper::Process& process,
const base::LaunchOptions& options) {
- delete options.fds_to_remap;
-
std::unique_ptr<sandbox::PreExecDelegate> pre_exec_delegate =
base::WrapUnique(static_cast<sandbox::PreExecDelegate*>(
options.pre_exec_delegate));
@@ -177,10 +173,11 @@ void ChildProcessLauncherHelper::ForceNormalProcessTerminationSync(
void ChildProcessLauncherHelper::SetProcessPriorityOnLauncherThread(
base::Process process,
- bool background,
- bool boost_for_pending_views) {
- if (process.CanBackgroundProcesses())
- process.SetProcessBackgrounded(MachBroker::GetInstance(), background);
+ const ChildProcessLauncherPriority& priority) {
+ if (process.CanBackgroundProcesses()) {
+ process.SetProcessBackgrounded(MachBroker::GetInstance(),
+ priority.background);
+ }
}
// static
diff --git a/chromium/content/browser/child_process_launcher_helper_posix.cc b/chromium/content/browser/child_process_launcher_helper_posix.cc
index 38b818dea83..42e1c9e4cf1 100644
--- a/chromium/content/browser/child_process_launcher_helper_posix.cc
+++ b/chromium/content/browser/child_process_launcher_helper_posix.cc
@@ -9,7 +9,7 @@
#include "base/posix/global_descriptors.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
-#include "content/browser/file_descriptor_info_impl.h"
+#include "content/browser/posix_file_descriptor_info_impl.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_descriptors.h"
@@ -71,14 +71,14 @@ base::PlatformFile OpenFileIfNecessary(const base::FilePath& path,
} // namespace
-std::unique_ptr<FileDescriptorInfo> CreateDefaultPosixFilesToMap(
+std::unique_ptr<PosixFileDescriptorInfo> CreateDefaultPosixFilesToMap(
int child_process_id,
const mojo::edk::PlatformHandle& mojo_client_handle,
bool include_service_required_files,
const std::string& process_type,
base::CommandLine* command_line) {
- std::unique_ptr<FileDescriptorInfo> files_to_register(
- FileDescriptorInfoImpl::Create());
+ std::unique_ptr<PosixFileDescriptorInfo> files_to_register(
+ PosixFileDescriptorInfoImpl::Create());
base::SharedMemoryHandle shm = base::FieldTrialList::GetFieldTrialHandle();
if (shm.IsValid()) {
diff --git a/chromium/content/browser/child_process_launcher_helper_posix.h b/chromium/content/browser/child_process_launcher_helper_posix.h
index 059e567cd79..7f08758cae4 100644
--- a/chromium/content/browser/child_process_launcher_helper_posix.h
+++ b/chromium/content/browser/child_process_launcher_helper_posix.h
@@ -27,11 +27,11 @@ struct PlatformHandle;
namespace content {
-class FileDescriptorInfo;
+class PosixFileDescriptorInfo;
namespace internal {
-std::unique_ptr<FileDescriptorInfo> CreateDefaultPosixFilesToMap(
+std::unique_ptr<PosixFileDescriptorInfo> CreateDefaultPosixFilesToMap(
int child_process_id,
const mojo::edk::PlatformHandle& mojo_client_handle,
bool include_service_required_files,
diff --git a/chromium/content/browser/child_process_launcher_helper_win.cc b/chromium/content/browser/child_process_launcher_helper_win.cc
index d839c7b8604..59289019991 100644
--- a/chromium/content/browser/child_process_launcher_helper_win.cc
+++ b/chromium/content/browser/child_process_launcher_helper_win.cc
@@ -8,6 +8,7 @@
#include "base/strings/string_number_conversions.h"
#include "base/win/scoped_handle.h"
#include "base/win/win_util.h"
+#include "content/browser/child_process_launcher.h"
#include "content/browser/child_process_launcher_helper.h"
#include "content/common/sandbox_win.h"
#include "content/public/common/result_codes.h"
@@ -109,11 +110,10 @@ void ChildProcessLauncherHelper::ForceNormalProcessTerminationSync(
void ChildProcessLauncherHelper::SetProcessPriorityOnLauncherThread(
base::Process process,
- bool background,
- bool boost_for_pending_views) {
+ const ChildProcessLauncherPriority& priority) {
DCHECK_CURRENTLY_ON(BrowserThread::PROCESS_LAUNCHER);
if (process.CanBackgroundProcesses())
- process.SetProcessBackgrounded(background);
+ process.SetProcessBackgrounded(priority.background);
}
// static
diff --git a/chromium/content/browser/child_process_security_policy_impl.cc b/chromium/content/browser/child_process_security_policy_impl.cc
index c285ff22ac5..53dbb689cb9 100644
--- a/chromium/content/browser/child_process_security_policy_impl.cc
+++ b/chromium/content/browser/child_process_security_policy_impl.cc
@@ -677,6 +677,10 @@ bool ChildProcessSecurityPolicyImpl::CanRedirectToURL(const GURL& url) {
const std::string& scheme = url.scheme();
+ // Can't redirect to error pages.
+ if (scheme == kChromeErrorScheme)
+ return false;
+
if (IsPseudoScheme(scheme)) {
// Redirects to a pseudo scheme (about, javascript, view-source, ...) are
// not allowed. An exception is made for <about:blank> and its variations.
diff --git a/chromium/content/browser/child_process_security_policy_impl.h b/chromium/content/browser/child_process_security_policy_impl.h
index 60dc521045f..b1211d024f3 100644
--- a/chromium/content/browser/child_process_security_policy_impl.h
+++ b/chromium/content/browser/child_process_security_policy_impl.h
@@ -39,7 +39,7 @@ class SiteInstance;
class ResourceRequestBody;
class CONTENT_EXPORT ChildProcessSecurityPolicyImpl
- : NON_EXPORTED_BASE(public ChildProcessSecurityPolicy) {
+ : public ChildProcessSecurityPolicy {
public:
// Object can only be created through GetInstance() so the constructor is
// private.
diff --git a/chromium/content/browser/child_process_security_policy_unittest.cc b/chromium/content/browser/child_process_security_policy_unittest.cc
index c45919d0c86..6b69dd7fe38 100644
--- a/chromium/content/browser/child_process_security_policy_unittest.cc
+++ b/chromium/content/browser/child_process_security_policy_unittest.cc
@@ -207,6 +207,8 @@ TEST_F(ChildProcessSecurityPolicyTest, StandardSchemesTest) {
EXPECT_FALSE(p->CanSetAsOriginHeader(kRendererID, GURL("chrome://foo/bar")));
EXPECT_FALSE(p->CanSetAsOriginHeader(
kRendererID, GURL("view-source:http://www.google.com/")));
+ EXPECT_FALSE(p->CanRedirectToURL(GURL(kUnreachableWebDataURL)));
+ EXPECT_FALSE(p->CanCommitURL(kRendererID, GURL(kUnreachableWebDataURL)));
p->Remove(kRendererID);
}
diff --git a/chromium/content/browser/compositor/DEPS b/chromium/content/browser/compositor/DEPS
index 30b67d53dbd..1b482fbe5b9 100644
--- a/chromium/content/browser/compositor/DEPS
+++ b/chromium/content/browser/compositor/DEPS
@@ -5,3 +5,17 @@ include_rules = [
"+services/ui/public/cpp",
"+ui/platform_window",
]
+
+# TODO(crbug.com/734668): Dependencies on ozone should be removed, as content
+# embedded in mus won't be able to talk to the native ozone.
+specific_include_rules = {
+ ".*ozone.*cc": [
+ "+ui/ozone/public",
+ ],
+ "gpu_process_transport_factory\.cc": [
+ "+ui/ozone/public",
+ ],
+ "reflector_impl_unittest\.cc": [
+ "+ui/ozone/public",
+ ]
+}
diff --git a/chromium/content/browser/compositor/browser_compositor_output_surface.cc b/chromium/content/browser/compositor/browser_compositor_output_surface.cc
index 888ceb44036..0d5b7dbb87d 100644
--- a/chromium/content/browser/compositor/browser_compositor_output_surface.cc
+++ b/chromium/content/browser/compositor/browser_compositor_output_surface.cc
@@ -12,7 +12,7 @@
#include "base/memory/ptr_util.h"
#include "base/strings/string_number_conversions.h"
#include "cc/output/output_surface_client.h"
-#include "cc/scheduler/begin_frame_source.h"
+#include "components/viz/common/frame_sinks/begin_frame_source.h"
#include "components/viz/service/display_embedder/compositor_overlay_candidate_validator.h"
#include "content/browser/compositor/reflector_impl.h"
#include "services/ui/public/cpp/gpu/context_provider_command_buffer.h"
@@ -38,7 +38,7 @@ BrowserCompositorOutputSurface::BrowserCompositorOutputSurface(
reflector_(nullptr) {}
BrowserCompositorOutputSurface::BrowserCompositorOutputSurface(
- const scoped_refptr<cc::VulkanContextProvider>& vulkan_context_provider,
+ const scoped_refptr<viz::VulkanContextProvider>& vulkan_context_provider,
const UpdateVSyncParametersCallback& update_vsync_parameters_callback)
: OutputSurface(std::move(vulkan_context_provider)),
update_vsync_parameters_callback_(update_vsync_parameters_callback),
diff --git a/chromium/content/browser/compositor/browser_compositor_output_surface.h b/chromium/content/browser/compositor/browser_compositor_output_surface.h
index fabf34892e0..66b73c66d18 100644
--- a/chromium/content/browser/compositor/browser_compositor_output_surface.h
+++ b/chromium/content/browser/compositor/browser_compositor_output_surface.h
@@ -62,7 +62,7 @@ class CONTENT_EXPORT BrowserCompositorOutputSurface
// Constructor used by the Vulkan implementation.
BrowserCompositorOutputSurface(
- const scoped_refptr<cc::VulkanContextProvider>& vulkan_context_provider,
+ const scoped_refptr<viz::VulkanContextProvider>& vulkan_context_provider,
const UpdateVSyncParametersCallback& update_vsync_parameters_callback);
const UpdateVSyncParametersCallback update_vsync_parameters_callback_;
diff --git a/chromium/content/browser/compositor/gpu_browser_compositor_output_surface.cc b/chromium/content/browser/compositor/gpu_browser_compositor_output_surface.cc
index 8464f621836..5ac88528b14 100644
--- a/chromium/content/browser/compositor/gpu_browser_compositor_output_surface.cc
+++ b/chromium/content/browser/compositor/gpu_browser_compositor_output_surface.cc
@@ -17,6 +17,7 @@
#include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu/ipc/client/command_buffer_proxy_impl.h"
#include "services/ui/public/cpp/gpu/context_provider_command_buffer.h"
+#include "ui/gl/gl_utils.h"
namespace content {
@@ -100,7 +101,8 @@ void GpuBrowserCompositorOutputSurface::Reshape(
size_ = size;
has_set_draw_rectangle_since_last_resize_ = false;
context_provider()->ContextGL()->ResizeCHROMIUM(
- size.width(), size.height(), device_scale_factor, has_alpha);
+ size.width(), size.height(), device_scale_factor,
+ gl::GetGLColorSpace(color_space), has_alpha);
}
void GpuBrowserCompositorOutputSurface::SwapBuffers(
diff --git a/chromium/content/browser/compositor/gpu_process_transport_factory.cc b/chromium/content/browser/compositor/gpu_process_transport_factory.cc
index 0e405efc281..8313f13f335 100644
--- a/chromium/content/browser/compositor/gpu_process_transport_factory.cc
+++ b/chromium/content/browser/compositor/gpu_process_transport_factory.cc
@@ -21,13 +21,15 @@
#include "cc/base/histograms.h"
#include "cc/base/switches.h"
#include "cc/output/texture_mailbox_deleter.h"
-#include "cc/output/vulkan_in_process_context_provider.h"
#include "cc/raster/single_thread_task_graph_runner.h"
#include "cc/raster/task_graph_runner.h"
-#include "cc/scheduler/begin_frame_source.h"
-#include "cc/scheduler/delay_based_time_source.h"
+#include "components/viz/common/frame_sinks/begin_frame_args.h"
+#include "components/viz/common/frame_sinks/begin_frame_source.h"
+#include "components/viz/common/frame_sinks/delay_based_time_source.h"
#include "components/viz/common/gl_helper.h"
+#include "components/viz/common/gpu/vulkan_in_process_context_provider.h"
#include "components/viz/host/host_frame_sink_manager.h"
+#include "components/viz/host/renderer_settings_creation.h"
#include "components/viz/service/display/display.h"
#include "components/viz/service/display/display_scheduler.h"
#include "components/viz/service/display_embedder/compositor_overlay_candidate_validator.h"
@@ -57,9 +59,7 @@
#include "services/ui/public/cpp/gpu/context_provider_command_buffer.h"
#include "third_party/khronos/GLES2/gl2.h"
#include "ui/compositor/compositor.h"
-#include "ui/compositor/compositor_constants.h"
#include "ui/compositor/compositor_switches.h"
-#include "ui/compositor/compositor_util.h"
#include "ui/compositor/layer.h"
#include "ui/display/display_switches.h"
#include "ui/display/types/display_snapshot.h"
@@ -69,6 +69,7 @@
#if defined(USE_AURA)
#include "content/public/common/service_manager_connection.h"
+#include "ui/aura/env.h"
#include "ui/aura/window_tree_host.h"
#endif
@@ -186,13 +187,44 @@ bool IsCALayersDisabledFromCommandLine() {
namespace content {
+class ExternalBeginFrameController : public viz::ExternalBeginFrameSourceClient,
+ public viz::DisplayObserver {
+ public:
+ explicit ExternalBeginFrameController(ui::Compositor* compositor)
+ : begin_frame_source_(this), compositor_(compositor) {}
+ ~ExternalBeginFrameController() override {}
+
+ // Issue a BeginFrame with the given |args|.
+ void IssueExternalBeginFrame(const viz::BeginFrameArgs& args) {
+ begin_frame_source_.OnBeginFrame(args);
+ }
+
+ viz::BeginFrameSource* begin_frame_source() { return &begin_frame_source_; }
+
+ private:
+ // viz::ExternalBeginFrameSourceClient implementation.
+ void OnNeedsBeginFrames(bool needs_begin_frames) override {
+ compositor_->OnNeedsExternalBeginFrames(needs_begin_frames);
+ }
+
+ // viz::DisplayObserver implementation.
+ void OnDisplayDidFinishFrame(const viz::BeginFrameAck& ack) override {
+ compositor_->OnDisplayDidFinishFrame(ack);
+ }
+
+ viz::ExternalBeginFrameSource begin_frame_source_;
+ ui::Compositor* compositor_ = nullptr;
+};
+
struct GpuProcessTransportFactory::PerCompositorData {
gpu::SurfaceHandle surface_handle = gpu::kNullSurfaceHandle;
BrowserCompositorOutputSurface* display_output_surface = nullptr;
- // Either |synthetic_begin_frame_source| or |gpu_vsync_begin_frame_source| is
- // valid but not both at the same time.
- std::unique_ptr<cc::SyntheticBeginFrameSource> synthetic_begin_frame_source;
+ // Exactly one of |synthetic_begin_frame_source|,
+ // |gpu_vsync_begin_frame_source|, and |external_begin_frame_source| is valid
+ // at the same time.
+ std::unique_ptr<viz::SyntheticBeginFrameSource> synthetic_begin_frame_source;
std::unique_ptr<GpuVSyncBeginFrameSource> gpu_vsync_begin_frame_source;
+ std::unique_ptr<ExternalBeginFrameController> external_begin_frame_controller;
ReflectorImpl* reflector = nullptr;
std::unique_ptr<viz::Display> display;
bool output_is_secure = false;
@@ -202,7 +234,7 @@ GpuProcessTransportFactory::GpuProcessTransportFactory(
scoped_refptr<base::SingleThreadTaskRunner> resize_task_runner)
: frame_sink_id_allocator_(kDefaultClientId),
renderer_settings_(
- ui::CreateRendererSettings(CreateBufferToTextureTargetMap())),
+ viz::CreateRendererSettings(CreateBufferToTextureTargetMap())),
resize_task_runner_(std::move(resize_task_runner)),
task_graph_runner_(new cc::SingleThreadTaskGraphRunner),
callback_factory_(this) {
@@ -220,6 +252,9 @@ GpuProcessTransportFactory::GpuProcessTransportFactory(
}
}
+ if (command_line->HasSwitch(cc::switches::kRunAllCompositorStagesBeforeDraw))
+ wait_for_all_pipeline_stages_before_draw_ = true;
+
task_graph_runner_->Start("CompositorTileWorker1",
base::SimpleThread::Options());
#if defined(OS_WIN)
@@ -244,7 +279,7 @@ GpuProcessTransportFactory::CreateSoftwareOutputDevice(
return base::WrapUnique(new cc::SoftwareOutputDevice);
#if defined(USE_AURA)
- if (service_manager::ServiceManagerIsRemote()) {
+ if (aura::Env::GetInstance()->mode() == aura::Env::Mode::MUS) {
NOTREACHED();
return nullptr;
}
@@ -308,11 +343,9 @@ static bool ShouldCreateGpuLayerTreeFrameSink(ui::Compositor* compositor) {
// Software fallback does not happen on Chrome OS.
return true;
#endif
-#if defined(OS_WIN)
- if (::GetProp(compositor->widget(), kForceSoftwareCompositor) &&
- ::RemoveProp(compositor->widget(), kForceSoftwareCompositor))
+
+ if (compositor->force_software_compositor())
return false;
-#endif
return GpuDataManagerImpl::GetInstance()->CanUseGpuBrowserCompositor();
}
@@ -392,7 +425,7 @@ void GpuProcessTransportFactory::EstablishedGpuChannel(
compositor->widget());
#endif
- scoped_refptr<cc::VulkanInProcessContextProvider> vulkan_context_provider =
+ scoped_refptr<viz::VulkanInProcessContextProvider> vulkan_context_provider =
SharedVulkanContextProvider();
scoped_refptr<ui::ContextProviderCommandBuffer> context_provider;
if (create_gpu_output_surface && !vulkan_context_provider) {
@@ -486,7 +519,6 @@ void GpuProcessTransportFactory::EstablishedGpuChannel(
BrowserCompositorOutputSurface::UpdateVSyncParametersCallback vsync_callback =
base::Bind(&ui::Compositor::SetDisplayVSyncParameters, compositor);
- cc::BeginFrameSource* begin_frame_source = nullptr;
GpuVSyncControl* gpu_vsync_control = nullptr;
std::unique_ptr<BrowserCompositorOutputSurface> display_output_surface;
@@ -539,7 +571,7 @@ void GpuProcessTransportFactory::EstablishedGpuChannel(
} else {
std::unique_ptr<viz::CompositorOverlayCandidateValidator> validator;
#if defined(OS_WIN)
- if (capabilities.dc_layers)
+ if (capabilities.dc_layers && capabilities.use_dc_overlays_for_video)
validator = CreateOverlayCandidateValidator(compositor->widget());
#elif !defined(OS_MACOSX)
// Overlays are only supported on surfaceless output surfaces on Mac.
@@ -558,29 +590,33 @@ void GpuProcessTransportFactory::EstablishedGpuChannel(
if (data->reflector)
data->reflector->OnSourceSurfaceReady(data->display_output_surface);
- std::unique_ptr<cc::SyntheticBeginFrameSource> synthetic_begin_frame_source;
+ std::unique_ptr<viz::SyntheticBeginFrameSource> synthetic_begin_frame_source;
std::unique_ptr<GpuVSyncBeginFrameSource> gpu_vsync_begin_frame_source;
-
- if (!begin_frame_source) {
- if (!disable_display_vsync_) {
- if (gpu_vsync_control && IsGpuVSyncSignalSupported()) {
- gpu_vsync_begin_frame_source =
- base::MakeUnique<GpuVSyncBeginFrameSource>(gpu_vsync_control);
- begin_frame_source = gpu_vsync_begin_frame_source.get();
- } else {
- synthetic_begin_frame_source =
- base::MakeUnique<cc::DelayBasedBeginFrameSource>(
- base::MakeUnique<cc::DelayBasedTimeSource>(
- compositor->task_runner().get()));
- begin_frame_source = synthetic_begin_frame_source.get();
- }
+ std::unique_ptr<ExternalBeginFrameController> external_begin_frame_controller;
+
+ viz::BeginFrameSource* begin_frame_source = nullptr;
+ if (compositor->external_begin_frames_enabled()) {
+ external_begin_frame_controller =
+ base::MakeUnique<ExternalBeginFrameController>(compositor.get());
+ begin_frame_source = external_begin_frame_controller->begin_frame_source();
+ } else if (!disable_display_vsync_) {
+ if (gpu_vsync_control && IsGpuVSyncSignalSupported()) {
+ gpu_vsync_begin_frame_source =
+ base::MakeUnique<GpuVSyncBeginFrameSource>(gpu_vsync_control);
+ begin_frame_source = gpu_vsync_begin_frame_source.get();
} else {
synthetic_begin_frame_source =
- base::MakeUnique<cc::BackToBackBeginFrameSource>(
- base::MakeUnique<cc::DelayBasedTimeSource>(
+ base::MakeUnique<viz::DelayBasedBeginFrameSource>(
+ base::MakeUnique<viz::DelayBasedTimeSource>(
compositor->task_runner().get()));
begin_frame_source = synthetic_begin_frame_source.get();
}
+ } else {
+ synthetic_begin_frame_source =
+ base::MakeUnique<viz::BackToBackBeginFrameSource>(
+ base::MakeUnique<viz::DelayBasedTimeSource>(
+ compositor->task_runner().get()));
+ begin_frame_source = synthetic_begin_frame_source.get();
}
#if defined(OS_WIN)
@@ -593,11 +629,16 @@ void GpuProcessTransportFactory::EstablishedGpuChannel(
} else if (data->gpu_vsync_begin_frame_source) {
GetFrameSinkManager()->UnregisterBeginFrameSource(
data->gpu_vsync_begin_frame_source.get());
+ } else if (data->external_begin_frame_controller) {
+ GetFrameSinkManager()->UnregisterBeginFrameSource(
+ data->external_begin_frame_controller->begin_frame_source());
+ data->display->RemoveObserver(data->external_begin_frame_controller.get());
}
auto scheduler = base::MakeUnique<viz::DisplayScheduler>(
begin_frame_source, compositor->task_runner().get(),
- display_output_surface->capabilities().max_frames_pending);
+ display_output_surface->capabilities().max_frames_pending,
+ wait_for_all_pipeline_stages_before_draw_);
// The Display owns and uses the |display_output_surface| created above.
data->display = base::MakeUnique<viz::Display>(
@@ -612,6 +653,11 @@ void GpuProcessTransportFactory::EstablishedGpuChannel(
// until we have reset |data->display|.
data->synthetic_begin_frame_source = std::move(synthetic_begin_frame_source);
data->gpu_vsync_begin_frame_source = std::move(gpu_vsync_begin_frame_source);
+ data->external_begin_frame_controller =
+ std::move(external_begin_frame_controller);
+
+ if (data->external_begin_frame_controller)
+ data->display->AddObserver(data->external_begin_frame_controller.get());
// The |delegated_output_surface| is given back to the compositor, it
// delegates to the Display as its root surface. Importantly, it shares the
@@ -621,7 +667,7 @@ void GpuProcessTransportFactory::EstablishedGpuChannel(
? base::MakeUnique<viz::DirectLayerTreeFrameSink>(
compositor->frame_sink_id(), GetHostFrameSinkManager(),
GetFrameSinkManager(), data->display.get(),
- static_cast<scoped_refptr<cc::VulkanContextProvider>>(
+ static_cast<scoped_refptr<viz::VulkanContextProvider>>(
vulkan_context_provider))
: base::MakeUnique<viz::DirectLayerTreeFrameSink>(
compositor->frame_sink_id(), GetHostFrameSinkManager(),
@@ -673,6 +719,10 @@ void GpuProcessTransportFactory::RemoveCompositor(ui::Compositor* compositor) {
} else if (data->gpu_vsync_begin_frame_source) {
GetFrameSinkManager()->UnregisterBeginFrameSource(
data->gpu_vsync_begin_frame_source.get());
+ } else if (data->external_begin_frame_controller) {
+ GetFrameSinkManager()->UnregisterBeginFrameSource(
+ data->external_begin_frame_controller->begin_frame_source());
+ data->display->RemoveObserver(data->external_begin_frame_controller.get());
}
per_compositor_data_.erase(it);
if (per_compositor_data_.empty()) {
@@ -797,6 +847,18 @@ void GpuProcessTransportFactory::SetDisplayVSyncParameters(
}
}
+void GpuProcessTransportFactory::IssueExternalBeginFrame(
+ ui::Compositor* compositor,
+ const viz::BeginFrameArgs& args) {
+ PerCompositorDataMap::iterator it = per_compositor_data_.find(compositor);
+ if (it == per_compositor_data_.end())
+ return;
+ PerCompositorData* data = it->second.get();
+ DCHECK(data);
+ if (data->external_begin_frame_controller)
+ data->external_begin_frame_controller->IssueExternalBeginFrame(args);
+}
+
void GpuProcessTransportFactory::SetOutputIsSecure(ui::Compositor* compositor,
bool secure) {
PerCompositorDataMap::iterator it = per_compositor_data_.find(compositor);
@@ -922,8 +984,8 @@ GpuProcessTransportFactory::CreatePerCompositorData(
void GpuProcessTransportFactory::OnLostMainThreadSharedContextInsideCallback() {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
- base::Bind(&GpuProcessTransportFactory::OnLostMainThreadSharedContext,
- callback_factory_.GetWeakPtr()));
+ base::BindOnce(&GpuProcessTransportFactory::OnLostMainThreadSharedContext,
+ callback_factory_.GetWeakPtr()));
}
void GpuProcessTransportFactory::OnLostMainThreadSharedContext() {
@@ -947,13 +1009,13 @@ void GpuProcessTransportFactory::OnLostMainThreadSharedContext() {
lost_shared_main_thread_contexts = NULL;
}
-scoped_refptr<cc::VulkanInProcessContextProvider>
+scoped_refptr<viz::VulkanInProcessContextProvider>
GpuProcessTransportFactory::SharedVulkanContextProvider() {
if (!shared_vulkan_context_provider_initialized_) {
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableVulkan)) {
shared_vulkan_context_provider_ =
- cc::VulkanInProcessContextProvider::Create();
+ viz::VulkanInProcessContextProvider::Create();
}
shared_vulkan_context_provider_initialized_ = true;
diff --git a/chromium/content/browser/compositor/gpu_process_transport_factory.h b/chromium/content/browser/compositor/gpu_process_transport_factory.h
index e31e910b1db..65c32b634ea 100644
--- a/chromium/content/browser/compositor/gpu_process_transport_factory.h
+++ b/chromium/content/browser/compositor/gpu_process_transport_factory.h
@@ -10,7 +10,7 @@
#include <map>
#include <memory>
-#include "base/id_map.h"
+#include "base/containers/id_map.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
@@ -32,13 +32,16 @@ class ResourceSettings;
class SingleThreadTaskGraphRunner;
class SoftwareOutputDevice;
class SurfaceManager;
-class VulkanInProcessContextProvider;
}
namespace ui {
class ContextProviderCommandBuffer;
}
+namespace viz {
+class VulkanInProcessContextProvider;
+}
+
namespace content {
class OutputDeviceBacking;
@@ -81,6 +84,8 @@ class GpuProcessTransportFactory : public ui::ContextFactory,
void SetDisplayVSyncParameters(ui::Compositor* compositor,
base::TimeTicks timebase,
base::TimeDelta interval) override;
+ void IssueExternalBeginFrame(ui::Compositor* compositor,
+ const viz::BeginFrameArgs& args) override;
void SetOutputIsSecure(ui::Compositor* compositor, bool secure) override;
// ImageTransportFactory implementation.
@@ -110,7 +115,7 @@ class GpuProcessTransportFactory : public ui::ContextFactory,
void OnLostMainThreadSharedContextInsideCallback();
void OnLostMainThreadSharedContext();
- scoped_refptr<cc::VulkanInProcessContextProvider>
+ scoped_refptr<viz::VulkanInProcessContextProvider>
SharedVulkanContextProvider();
viz::FrameSinkIdAllocator frame_sink_id_allocator_;
@@ -135,8 +140,9 @@ class GpuProcessTransportFactory : public ui::ContextFactory,
shared_worker_context_provider_;
bool disable_display_vsync_ = false;
+ bool wait_for_all_pipeline_stages_before_draw_ = false;
bool shared_vulkan_context_provider_initialized_ = false;
- scoped_refptr<cc::VulkanInProcessContextProvider>
+ scoped_refptr<viz::VulkanInProcessContextProvider>
shared_vulkan_context_provider_;
gpu::GpuChannelEstablishFactory* gpu_channel_factory_ = nullptr;
diff --git a/chromium/content/browser/compositor/gpu_vsync_begin_frame_source.cc b/chromium/content/browser/compositor/gpu_vsync_begin_frame_source.cc
index 7e43be479ad..d46b8337f35 100644
--- a/chromium/content/browser/compositor/gpu_vsync_begin_frame_source.cc
+++ b/chromium/content/browser/compositor/gpu_vsync_begin_frame_source.cc
@@ -8,10 +8,10 @@ namespace content {
GpuVSyncBeginFrameSource::GpuVSyncBeginFrameSource(
GpuVSyncControl* vsync_control)
- : cc::ExternalBeginFrameSource(this),
+ : viz::ExternalBeginFrameSource(this),
vsync_control_(vsync_control),
needs_begin_frames_(false),
- next_sequence_number_(cc::BeginFrameArgs::kStartingFrameNumber) {
+ next_sequence_number_(viz::BeginFrameArgs::kStartingFrameNumber) {
DCHECK(vsync_control);
}
@@ -22,16 +22,23 @@ void GpuVSyncBeginFrameSource::OnVSync(base::TimeTicks timestamp,
if (!needs_begin_frames_)
return;
- base::TimeTicks now = base::TimeTicks::Now();
+ base::TimeTicks now = Now();
base::TimeTicks deadline = now.SnappedToNextTick(timestamp, interval);
TRACE_EVENT1("cc", "GpuVSyncBeginFrameSource::OnVSync", "latency",
(now - timestamp).ToInternalValue());
+ // Fast forward timestamp to avoid generating BeginFrame with a timestamp
+ // that is too far behind. Most of the time it would remain the same.
+ timestamp = deadline - interval;
+
next_sequence_number_++;
- OnBeginFrame(cc::BeginFrameArgs::Create(
+
+ // OnBeginFrame can still skip this notification if it is behind
+ // last_begin_frame_args_.
+ OnBeginFrame(viz::BeginFrameArgs::Create(
BEGINFRAME_FROM_HERE, source_id(), next_sequence_number_, timestamp,
- deadline, interval, cc::BeginFrameArgs::NORMAL));
+ deadline, interval, viz::BeginFrameArgs::NORMAL));
}
void GpuVSyncBeginFrameSource::OnNeedsBeginFrames(bool needs_begin_frames) {
@@ -39,4 +46,42 @@ void GpuVSyncBeginFrameSource::OnNeedsBeginFrames(bool needs_begin_frames) {
vsync_control_->SetNeedsVSync(needs_begin_frames);
}
+base::TimeTicks GpuVSyncBeginFrameSource::Now() const {
+ return base::TimeTicks::Now();
+}
+
+viz::BeginFrameArgs GpuVSyncBeginFrameSource::GetMissedBeginFrameArgs(
+ viz::BeginFrameObserver* obs) {
+ if (!last_begin_frame_args_.IsValid())
+ return viz::BeginFrameArgs();
+
+ base::TimeTicks now = Now();
+ base::TimeTicks estimated_next_timestamp = now.SnappedToNextTick(
+ last_begin_frame_args_.frame_time, last_begin_frame_args_.interval);
+ base::TimeTicks missed_timestamp =
+ estimated_next_timestamp - last_begin_frame_args_.interval;
+
+ if (missed_timestamp > last_begin_frame_args_.frame_time) {
+ // The projected missed timestamp is newer than the last known timestamp.
+ // In this case create BeginFrameArgs with a new sequence number.
+ next_sequence_number_++;
+ last_begin_frame_args_ = viz::BeginFrameArgs::Create(
+ BEGINFRAME_FROM_HERE, source_id(), next_sequence_number_,
+ missed_timestamp, estimated_next_timestamp,
+ last_begin_frame_args_.interval, viz::BeginFrameArgs::NORMAL);
+ }
+
+ // The last known args object is up-to-date. Skip sending notification
+ // if the observer has already seen it.
+ const viz::BeginFrameArgs& last_observer_args = obs->LastUsedBeginFrameArgs();
+ if (last_observer_args.IsValid() &&
+ last_begin_frame_args_.frame_time <= last_observer_args.frame_time) {
+ return viz::BeginFrameArgs();
+ }
+
+ viz::BeginFrameArgs missed_args = last_begin_frame_args_;
+ missed_args.type = viz::BeginFrameArgs::MISSED;
+ return missed_args;
+}
+
} // namespace content
diff --git a/chromium/content/browser/compositor/gpu_vsync_begin_frame_source.h b/chromium/content/browser/compositor/gpu_vsync_begin_frame_source.h
index a3ddd6b0786..251b69263a6 100644
--- a/chromium/content/browser/compositor/gpu_vsync_begin_frame_source.h
+++ b/chromium/content/browser/compositor/gpu_vsync_begin_frame_source.h
@@ -7,30 +7,39 @@
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
-#include "cc/scheduler/begin_frame_source.h"
+#include "components/viz/common/frame_sinks/begin_frame_source.h"
+#include "content/common/content_export.h"
namespace content {
// This class is used to control VSync production on GPU side.
-class GpuVSyncControl {
+class CONTENT_EXPORT GpuVSyncControl {
public:
virtual void SetNeedsVSync(bool needs_vsync) = 0;
};
// This is a type of ExternalBeginFrameSource where VSync signals are
// generated externally on GPU side.
-class GpuVSyncBeginFrameSource : public cc::ExternalBeginFrameSource,
- cc::ExternalBeginFrameSourceClient {
+class CONTENT_EXPORT GpuVSyncBeginFrameSource
+ : public viz::ExternalBeginFrameSource,
+ public viz::ExternalBeginFrameSourceClient {
public:
explicit GpuVSyncBeginFrameSource(GpuVSyncControl* vsync_control);
~GpuVSyncBeginFrameSource() override;
- // cc::ExternalBeginFrameSourceClient implementation.
+ // viz::ExternalBeginFrameSourceClient implementation.
void OnNeedsBeginFrames(bool needs_begin_frames) override;
void OnVSync(base::TimeTicks timestamp, base::TimeDelta interval);
+ protected:
+ // Virtual for testing.
+ virtual base::TimeTicks Now() const;
+
private:
+ viz::BeginFrameArgs GetMissedBeginFrameArgs(
+ viz::BeginFrameObserver* obs) override;
+
GpuVSyncControl* const vsync_control_;
bool needs_begin_frames_;
uint64_t next_sequence_number_;
diff --git a/chromium/content/browser/compositor/gpu_vsync_begin_frame_source_unittest.cc b/chromium/content/browser/compositor/gpu_vsync_begin_frame_source_unittest.cc
new file mode 100644
index 00000000000..7b091fe0b98
--- /dev/null
+++ b/chromium/content/browser/compositor/gpu_vsync_begin_frame_source_unittest.cc
@@ -0,0 +1,190 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/compositor/gpu_vsync_begin_frame_source.h"
+
+#include "base/macros.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+namespace {
+
+class TestBeginFrameObserver : public viz::BeginFrameObserverBase {
+ public:
+ TestBeginFrameObserver() = default;
+
+ int begin_frame_count() { return begin_frame_count_; }
+
+ private:
+ bool OnBeginFrameDerivedImpl(const viz::BeginFrameArgs& args) override {
+ begin_frame_count_++;
+ return true;
+ }
+
+ void OnBeginFrameSourcePausedChanged(bool paused) override {}
+
+ int begin_frame_count_ = 0;
+
+ DISALLOW_COPY_AND_ASSIGN(TestBeginFrameObserver);
+};
+
+class TestGpuVSyncBeginFrameSource : public GpuVSyncBeginFrameSource {
+ public:
+ explicit TestGpuVSyncBeginFrameSource(GpuVSyncControl* vsync_control)
+ : GpuVSyncBeginFrameSource(vsync_control) {}
+
+ void SetNow(base::TimeTicks now) { now_ = now; }
+
+ private:
+ base::TimeTicks Now() const override { return now_; }
+
+ base::TimeTicks now_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestGpuVSyncBeginFrameSource);
+};
+
+class GpuVSyncBeginFrameSourceTest : public testing::Test,
+ public GpuVSyncControl {
+ public:
+ GpuVSyncBeginFrameSourceTest() = default;
+ ~GpuVSyncBeginFrameSourceTest() override = default;
+
+ protected:
+ void SetNeedsVSync(bool needs_vsync) override { needs_vsync_ = needs_vsync; }
+
+ bool needs_vsync_ = false;
+
+ DISALLOW_COPY_AND_ASSIGN(GpuVSyncBeginFrameSourceTest);
+};
+
+// Test that an observer can be added to BFS and that it receives OnBeginFrame
+// notification.
+TEST_F(GpuVSyncBeginFrameSourceTest, BasicTest) {
+ TestBeginFrameObserver observer;
+ TestGpuVSyncBeginFrameSource begin_frame_source(this);
+
+ base::TimeTicks now = base::TimeTicks() + base::TimeDelta::FromHours(2);
+ begin_frame_source.SetNow(now);
+
+ EXPECT_FALSE(needs_vsync_);
+
+ begin_frame_source.AddObserver(&observer);
+
+ EXPECT_TRUE(needs_vsync_);
+ EXPECT_FALSE(observer.LastUsedBeginFrameArgs().IsValid());
+
+ base::TimeTicks timestamp = now - base::TimeDelta::FromSeconds(1);
+ base::TimeDelta interval = base::TimeDelta::FromSeconds(2);
+
+ begin_frame_source.OnVSync(timestamp, interval);
+
+ EXPECT_EQ(1, observer.begin_frame_count());
+
+ viz::BeginFrameArgs args = observer.LastUsedBeginFrameArgs();
+ EXPECT_TRUE(args.IsValid());
+ EXPECT_EQ(timestamp, args.frame_time);
+ EXPECT_EQ(interval, args.interval);
+ EXPECT_EQ(timestamp + interval, args.deadline);
+ EXPECT_EQ(viz::BeginFrameArgs::kStartingFrameNumber + 1,
+ args.sequence_number);
+ EXPECT_EQ(viz::BeginFrameArgs::NORMAL, args.type);
+ EXPECT_EQ(begin_frame_source.source_id(), args.source_id);
+
+ // Make sure that the deadline time is correctly advanced forward to be after
+ // 'now' when frame time is way behind.
+ now += base::TimeDelta::FromSeconds(10);
+ begin_frame_source.SetNow(now);
+ // v-sync timestamp is 5 seconds behind but frame time should be projected
+ // forward to be 1 second before 'now' and the the deadline should be 1 second
+ // after 'now' considering the 2 second interval.
+ timestamp = now - base::TimeDelta::FromSeconds(5);
+
+ begin_frame_source.OnVSync(timestamp, interval);
+
+ EXPECT_EQ(2, observer.begin_frame_count());
+
+ args = observer.LastUsedBeginFrameArgs();
+ EXPECT_TRUE(args.IsValid());
+ EXPECT_EQ(now - base::TimeDelta::FromSeconds(1), args.frame_time);
+ EXPECT_EQ(interval, args.interval);
+ EXPECT_EQ(now + base::TimeDelta::FromSeconds(1), args.deadline);
+ EXPECT_EQ(viz::BeginFrameArgs::kStartingFrameNumber + 2,
+ args.sequence_number);
+ EXPECT_EQ(viz::BeginFrameArgs::NORMAL, args.type);
+ EXPECT_EQ(begin_frame_source.source_id(), args.source_id);
+
+ begin_frame_source.RemoveObserver(&observer);
+
+ EXPECT_EQ(2, observer.begin_frame_count());
+ EXPECT_FALSE(needs_vsync_);
+}
+
+// Test that MISSED OnBeginFrame is produced as expected.
+TEST_F(GpuVSyncBeginFrameSourceTest, MissedBeginFrameArgs) {
+ TestBeginFrameObserver observer1;
+ TestBeginFrameObserver observer2;
+ TestGpuVSyncBeginFrameSource begin_frame_source(this);
+
+ base::TimeTicks now = base::TimeTicks() + base::TimeDelta::FromHours(2);
+ begin_frame_source.SetNow(now);
+
+ begin_frame_source.AddObserver(&observer1);
+
+ // The observer shouldn't be getting any BeginFrame at this point.
+ EXPECT_EQ(0, observer1.begin_frame_count());
+
+ base::TimeDelta interval = base::TimeDelta::FromSeconds(2);
+
+ // Trigger first OnBeginFrame.
+ begin_frame_source.OnVSync(now, interval);
+
+ // The observer should get a NORMAL BeginFrame notification which is covered
+ // by BasicTest above.
+ EXPECT_EQ(1, observer1.begin_frame_count());
+ EXPECT_EQ(viz::BeginFrameArgs::NORMAL,
+ observer1.LastUsedBeginFrameArgs().type);
+
+ // Remove the first observer and add it back after advancing the 'now' time.
+ // It should get a more recent missed notification calculated from the
+ // projection of the previous notification.
+ begin_frame_source.RemoveObserver(&observer1);
+ now = now + base::TimeDelta::FromSeconds(5);
+ begin_frame_source.SetNow(now);
+ begin_frame_source.AddObserver(&observer1);
+
+ EXPECT_EQ(2, observer1.begin_frame_count());
+
+ // The projected MISSED frame_time should be 1 second behind 'now'.
+ base::TimeTicks timestamp1 = now - base::TimeDelta::FromSeconds(1);
+ viz::BeginFrameArgs args1 = observer1.LastUsedBeginFrameArgs();
+ EXPECT_TRUE(args1.IsValid());
+ EXPECT_EQ(timestamp1, args1.frame_time);
+ EXPECT_EQ(timestamp1 + interval, args1.deadline);
+ EXPECT_EQ(viz::BeginFrameArgs::kStartingFrameNumber + 2,
+ args1.sequence_number);
+ EXPECT_EQ(viz::BeginFrameArgs::MISSED, args1.type);
+
+ // Add second observer which should receive the same notification.
+ begin_frame_source.AddObserver(&observer2);
+
+ EXPECT_EQ(1, observer2.begin_frame_count());
+
+ viz::BeginFrameArgs args2 = observer2.LastUsedBeginFrameArgs();
+ EXPECT_TRUE(args2.IsValid());
+ EXPECT_EQ(timestamp1, args2.frame_time);
+ EXPECT_EQ(timestamp1 + interval, args2.deadline);
+ EXPECT_EQ(viz::BeginFrameArgs::kStartingFrameNumber + 2,
+ args2.sequence_number);
+ EXPECT_EQ(viz::BeginFrameArgs::MISSED, args2.type);
+
+ // Adding and removing the second observer shouldn't produce any
+ // new notifications.
+ begin_frame_source.RemoveObserver(&observer2);
+ begin_frame_source.AddObserver(&observer2);
+
+ EXPECT_EQ(1, observer2.begin_frame_count());
+}
+
+} // namespace
+} // namespace content
diff --git a/chromium/content/browser/compositor/reflector_impl.cc b/chromium/content/browser/compositor/reflector_impl.cc
index 08292d61887..69b3639827d 100644
--- a/chromium/content/browser/compositor/reflector_impl.cc
+++ b/chromium/content/browser/compositor/reflector_impl.cc
@@ -159,7 +159,8 @@ void ReflectorImpl::UpdateTexture(ReflectorImpl::LayerData* layer_data,
if (layer_data->needs_set_mailbox) {
layer_data->layer->SetTextureMailbox(
viz::TextureMailbox(mailbox_->holder()),
- cc::SingleReleaseCallback::Create(base::Bind(ReleaseMailbox, mailbox_)),
+ viz::SingleReleaseCallback::Create(
+ base::Bind(ReleaseMailbox, mailbox_)),
source_size);
layer_data->needs_set_mailbox = false;
} else {
diff --git a/chromium/content/browser/compositor/reflector_impl_unittest.cc b/chromium/content/browser/compositor/reflector_impl_unittest.cc
index 45520eb35fb..16267dccd79 100644
--- a/chromium/content/browser/compositor/reflector_impl_unittest.cc
+++ b/chromium/content/browser/compositor/reflector_impl_unittest.cc
@@ -11,10 +11,10 @@
#include "base/single_thread_task_runner.h"
#include "build/build_config.h"
#include "cc/output/output_surface_frame.h"
-#include "cc/scheduler/begin_frame_source.h"
-#include "cc/scheduler/delay_based_time_source.h"
#include "cc/test/test_context_provider.h"
#include "cc/test/test_web_graphics_context_3d.h"
+#include "components/viz/common/frame_sinks/begin_frame_source.h"
+#include "components/viz/common/frame_sinks/delay_based_time_source.h"
#include "components/viz/service/display_embedder/compositor_overlay_candidate_validator.h"
#include "content/browser/compositor/browser_compositor_output_surface.h"
#include "content/browser/compositor/reflector_texture.h"
@@ -140,13 +140,14 @@ class ReflectorImplTest : public testing::Test {
base::MakeUnique<NoTransportImageTransportFactory>());
task_runner_ = message_loop_->task_runner();
compositor_task_runner_ = new FakeTaskRunner();
- begin_frame_source_.reset(new cc::DelayBasedBeginFrameSource(
- base::MakeUnique<cc::DelayBasedTimeSource>(
+ begin_frame_source_.reset(new viz::DelayBasedBeginFrameSource(
+ base::MakeUnique<viz::DelayBasedTimeSource>(
compositor_task_runner_.get())));
compositor_.reset(new ui::Compositor(
context_factory_private->AllocateFrameSinkId(), context_factory,
context_factory_private, compositor_task_runner_.get(),
- false /* enable_surface_synchronization */));
+ false /* enable_surface_synchronization */,
+ false /* enable_pixel_canvas */));
compositor_->SetAcceleratedWidget(gfx::kNullAcceleratedWidget);
auto context_provider = cc::TestContextProvider::Create();
@@ -173,7 +174,7 @@ class ReflectorImplTest : public testing::Test {
if (reflector_)
reflector_->RemoveMirroringLayer(mirroring_layer_.get());
viz::TextureMailbox mailbox;
- std::unique_ptr<cc::SingleReleaseCallback> release;
+ std::unique_ptr<viz::SingleReleaseCallback> release;
if (mirroring_layer_->PrepareTextureMailbox(&mailbox, &release)) {
release->Run(gpu::SyncToken(), false);
}
@@ -188,7 +189,7 @@ class ReflectorImplTest : public testing::Test {
protected:
scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner_;
- std::unique_ptr<cc::SyntheticBeginFrameSource> begin_frame_source_;
+ std::unique_ptr<viz::SyntheticBeginFrameSource> begin_frame_source_;
std::unique_ptr<base::MessageLoop> message_loop_;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
std::unique_ptr<ui::Compositor> compositor_;
diff --git a/chromium/content/browser/compositor/software_browser_compositor_output_surface.cc b/chromium/content/browser/compositor/software_browser_compositor_output_surface.cc
index 4de9cb070c9..ee51f27d551 100644
--- a/chromium/content/browser/compositor/software_browser_compositor_output_surface.cc
+++ b/chromium/content/browser/compositor/software_browser_compositor_output_surface.cc
@@ -80,8 +80,9 @@ void SoftwareBrowserCompositorOutputSurface::SwapBuffers(
swap_time, 1);
}
task_runner_->PostTask(
- FROM_HERE, base::Bind(&RenderWidgetHostImpl::OnGpuSwapBuffersCompleted,
- frame.latency_info));
+ FROM_HERE,
+ base::BindOnce(&RenderWidgetHostImpl::OnGpuSwapBuffersCompleted,
+ frame.latency_info));
gfx::VSyncProvider* vsync_provider = software_device()->GetVSyncProvider();
if (vsync_provider)
@@ -89,8 +90,9 @@ void SoftwareBrowserCompositorOutputSurface::SwapBuffers(
task_runner_->PostTask(
FROM_HERE,
- base::Bind(&SoftwareBrowserCompositorOutputSurface::SwapBuffersCallback,
- weak_factory_.GetWeakPtr()));
+ base::BindOnce(
+ &SoftwareBrowserCompositorOutputSurface::SwapBuffersCallback,
+ weak_factory_.GetWeakPtr()));
}
void SoftwareBrowserCompositorOutputSurface::SwapBuffersCallback() {
diff --git a/chromium/content/browser/compositor/software_browser_compositor_output_surface_unittest.cc b/chromium/content/browser/compositor/software_browser_compositor_output_surface_unittest.cc
index a65d61f4ff0..9cf29d5fdc3 100644
--- a/chromium/content/browser/compositor/software_browser_compositor_output_surface_unittest.cc
+++ b/chromium/content/browser/compositor/software_browser_compositor_output_surface_unittest.cc
@@ -11,9 +11,9 @@
#include "base/test/test_message_loop.h"
#include "base/threading/thread_task_runner_handle.h"
#include "cc/output/output_surface_frame.h"
-#include "cc/scheduler/begin_frame_source.h"
-#include "cc/scheduler/delay_based_time_source.h"
#include "cc/test/fake_output_surface_client.h"
+#include "components/viz/common/frame_sinks/begin_frame_source.h"
+#include "components/viz/common/frame_sinks/delay_based_time_source.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/compositor/compositor.h"
#include "ui/compositor/test/context_factories_for_test.h"
@@ -65,7 +65,7 @@ class FakeSoftwareOutputDevice : public cc::SoftwareOutputDevice {
class SoftwareBrowserCompositorOutputSurfaceTest : public testing::Test {
public:
SoftwareBrowserCompositorOutputSurfaceTest()
- : begin_frame_source_(base::MakeUnique<cc::DelayBasedTimeSource>(
+ : begin_frame_source_(base::MakeUnique<viz::DelayBasedTimeSource>(
message_loop_.task_runner().get())) {}
~SoftwareBrowserCompositorOutputSurfaceTest() override = default;
@@ -85,7 +85,7 @@ class SoftwareBrowserCompositorOutputSurfaceTest : public testing::Test {
// inside the OutputSurface, so we shouldn't need a MessageLoop. The
// OutputSurface should be using the TaskRunner given to the compositor.
base::TestMessageLoop message_loop_;
- cc::DelayBasedBeginFrameSource begin_frame_source_;
+ viz::DelayBasedBeginFrameSource begin_frame_source_;
std::unique_ptr<ui::Compositor> compositor_;
int update_vsync_parameters_call_count_ = 0;
@@ -104,7 +104,8 @@ void SoftwareBrowserCompositorOutputSurfaceTest::SetUp() {
compositor_.reset(new ui::Compositor(
context_factory_private->AllocateFrameSinkId(), context_factory,
context_factory_private, message_loop_.task_runner().get(),
- false /* enable_surface_synchronization */));
+ false /* enable_surface_synchronization */,
+ false /* enable_pixel_canvas */));
compositor_->SetAcceleratedWidget(gfx::kNullAcceleratedWidget);
}
diff --git a/chromium/content/browser/compositor/software_output_device_ozone_unittest.cc b/chromium/content/browser/compositor/software_output_device_ozone_unittest.cc
index af3e1574e17..2b34384e78e 100644
--- a/chromium/content/browser/compositor/software_output_device_ozone_unittest.cc
+++ b/chromium/content/browser/compositor/software_output_device_ozone_unittest.cc
@@ -96,7 +96,8 @@ void SoftwareOutputDeviceOzoneTest::SetUp() {
compositor_.reset(
new ui::Compositor(viz::FrameSinkId(1, 1), context_factory, nullptr,
base::ThreadTaskRunnerHandle::Get(),
- false /* enable_surface_synchronization */));
+ false /* enable_surface_synchronization */,
+ false /* enable_pixel_canvas */));
compositor_->SetAcceleratedWidget(window_delegate_.GetAcceleratedWidget());
compositor_->SetScaleAndSize(1.0f, size);
diff --git a/chromium/content/browser/compositor/surface_utils.cc b/chromium/content/browser/compositor/surface_utils.cc
index 1d6b7ff4607..ace5a1818d2 100644
--- a/chromium/content/browser/compositor/surface_utils.cc
+++ b/chromium/content/browser/compositor/surface_utils.cc
@@ -8,9 +8,9 @@
#include "base/callback_helpers.h"
#include "base/sequenced_task_runner.h"
#include "build/build_config.h"
-#include "cc/output/copy_output_result.h"
-#include "cc/resources/single_release_callback.h"
#include "components/viz/common/gl_helper.h"
+#include "components/viz/common/quads/copy_output_result.h"
+#include "components/viz/common/quads/single_release_callback.h"
#include "components/viz/host/host_frame_sink_manager.h"
#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
#include "content/browser/browser_main_loop.h"
@@ -33,7 +33,7 @@ namespace {
#if !defined(OS_ANDROID) || defined(USE_AURA)
void CopyFromCompositingSurfaceFinished(
const content::ReadbackRequestCallback& callback,
- std::unique_ptr<cc::SingleReleaseCallback> release_callback,
+ std::unique_ptr<viz::SingleReleaseCallback> release_callback,
std::unique_ptr<SkBitmap> bitmap,
bool result) {
gpu::SyncToken sync_token;
@@ -59,7 +59,7 @@ void PrepareTextureCopyOutputResult(
const gfx::Size& dst_size_in_pixel,
const SkColorType color_type,
const content::ReadbackRequestCallback& callback,
- std::unique_ptr<cc::CopyOutputResult> result) {
+ std::unique_ptr<viz::CopyOutputResult> result) {
#if defined(OS_ANDROID) && !defined(USE_AURA)
// TODO(wjmaclean): See if there's an equivalent pathway for Android and
// implement it here.
@@ -67,7 +67,7 @@ void PrepareTextureCopyOutputResult(
#else
DCHECK(result->HasTexture());
base::ScopedClosureRunner scoped_callback_runner(
- base::Bind(callback, SkBitmap(), content::READBACK_FAILED));
+ base::BindOnce(callback, SkBitmap(), content::READBACK_FAILED));
// TODO(siva.gunturi): We should be able to validate the format here using
// GLHelper::IsReadbackConfigSupported before we processs the result.
@@ -76,7 +76,7 @@ void PrepareTextureCopyOutputResult(
if (!bitmap->tryAllocPixels(SkImageInfo::Make(
dst_size_in_pixel.width(), dst_size_in_pixel.height(), color_type,
kOpaque_SkAlphaType))) {
- scoped_callback_runner.ReplaceClosure(base::Bind(
+ scoped_callback_runner.ReplaceClosure(base::BindOnce(
callback, SkBitmap(), content::READBACK_BITMAP_ALLOCATION_FAILURE));
return;
}
@@ -90,7 +90,7 @@ void PrepareTextureCopyOutputResult(
uint8_t* pixels = static_cast<uint8_t*>(bitmap->getPixels());
viz::TextureMailbox texture_mailbox;
- std::unique_ptr<cc::SingleReleaseCallback> release_callback;
+ std::unique_ptr<viz::SingleReleaseCallback> release_callback;
result->TakeTexture(&texture_mailbox, &release_callback);
DCHECK(texture_mailbox.IsTexture());
@@ -109,7 +109,7 @@ void PrepareBitmapCopyOutputResult(
const gfx::Size& dst_size_in_pixel,
const SkColorType preferred_color_type,
const content::ReadbackRequestCallback& callback,
- std::unique_ptr<cc::CopyOutputResult> result) {
+ std::unique_ptr<viz::CopyOutputResult> result) {
SkColorType color_type = preferred_color_type;
if (color_type != kN32_SkColorType && color_type != kAlpha_8_SkColorType) {
// Switch back to default colortype if format not supported.
@@ -190,7 +190,7 @@ void CopyFromCompositingSurfaceHasResult(
const gfx::Size& dst_size_in_pixel,
const SkColorType color_type,
const ReadbackRequestCallback& callback,
- std::unique_ptr<cc::CopyOutputResult> result) {
+ std::unique_ptr<viz::CopyOutputResult> result) {
if (result->IsEmpty() || result->size().IsEmpty()) {
callback.Run(SkBitmap(), READBACK_FAILED);
return;
@@ -222,14 +222,14 @@ void ConnectWithInProcessFrameSinkManager(
viz::FrameSinkManagerImpl* manager,
scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
// A mojo pointer to |host| which is the FrameSinkManagerImpl's client.
- cc::mojom::FrameSinkManagerClientPtr host_mojo;
+ viz::mojom::FrameSinkManagerClientPtr host_mojo;
// A mojo pointer to |manager|.
- cc::mojom::FrameSinkManagerPtr manager_mojo;
+ viz::mojom::FrameSinkManagerPtr manager_mojo;
// A request to bind to each of the above interfaces.
- cc::mojom::FrameSinkManagerClientRequest host_mojo_request =
+ viz::mojom::FrameSinkManagerClientRequest host_mojo_request =
mojo::MakeRequest(&host_mojo);
- cc::mojom::FrameSinkManagerRequest manager_mojo_request =
+ viz::mojom::FrameSinkManagerRequest manager_mojo_request =
mojo::MakeRequest(&manager_mojo);
// Sets |manager_mojo| which is given to the |host|.
diff --git a/chromium/content/browser/compositor/surface_utils.h b/chromium/content/browser/compositor/surface_utils.h
index 84fea8110fb..3e1bd890a6a 100644
--- a/chromium/content/browser/compositor/surface_utils.h
+++ b/chromium/content/browser/compositor/surface_utils.h
@@ -18,11 +18,8 @@ namespace base {
class SingleThreadTaskRunner;
}
-namespace cc {
-class CopyOutputResult;
-} // namespace cc
-
namespace viz {
+class CopyOutputResult;
class FrameSinkManagerImpl;
class HostFrameSinkManager;
class FrameSinkManagerImpl;
@@ -40,7 +37,7 @@ void CopyFromCompositingSurfaceHasResult(
const gfx::Size& dst_size_in_pixel,
const SkColorType color_type,
const ReadbackRequestCallback& callback,
- std::unique_ptr<cc::CopyOutputResult> result);
+ std::unique_ptr<viz::CopyOutputResult> result);
namespace surface_utils {
diff --git a/chromium/content/browser/cross_site_transfer_browsertest.cc b/chromium/content/browser/cross_site_transfer_browsertest.cc
index f0c8e1fb22f..29d7514b5b8 100644
--- a/chromium/content/browser/cross_site_transfer_browsertest.cc
+++ b/chromium/content/browser/cross_site_transfer_browsertest.cc
@@ -10,6 +10,7 @@
#include "base/files/scoped_temp_dir.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
+#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
@@ -78,7 +79,7 @@ class TrackingResourceDispatcherHostDelegate
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(
+ base::BindOnce(
&TrackingResourceDispatcherHostDelegate::SetTrackedURLOnIOThread,
base::Unretained(this), tracked_url, run_loop_->QuitClosure()));
}
@@ -186,8 +187,9 @@ class CrossSiteTransferTest
void SetUpOnMainThread() override {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&CrossSiteTransferTest::InjectResourceDispatcherHostDelegate,
- base::Unretained(this)));
+ base::BindOnce(
+ &CrossSiteTransferTest::InjectResourceDispatcherHostDelegate,
+ base::Unretained(this)));
host_resolver()->AddRule("*", "127.0.0.1");
content::SetupCrossSiteRedirector(embedded_test_server());
ASSERT_TRUE(embedded_test_server()->Start());
@@ -196,7 +198,7 @@ class CrossSiteTransferTest
void TearDownOnMainThread() override {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(
+ base::BindOnce(
&CrossSiteTransferTest::RestoreResourceDisptcherHostDelegate,
base::Unretained(this)));
}
diff --git a/chromium/content/browser/device_sensors/device_sensor_browsertest.cc b/chromium/content/browser/device_sensors/device_sensor_browsertest.cc
index ef16d3810c3..06f0d2c5234 100644
--- a/chromium/content/browser/device_sensors/device_sensor_browsertest.cc
+++ b/chromium/content/browser/device_sensors/device_sensor_browsertest.cc
@@ -2,9 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <memory>
+#include <string>
+#include <utility>
+
#include "base/command_line.h"
#include "base/macros.h"
+#include "base/memory/ptr_util.h"
#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/platform_thread.h"
#include "build/build_config.h"
@@ -21,6 +27,15 @@
#include "device/sensors/device_sensor_service.h"
#include "device/sensors/public/cpp/device_motion_hardware_buffer.h"
#include "device/sensors/public/cpp/device_orientation_hardware_buffer.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "mojo/public/cpp/system/buffer.h"
+#include "services/device/public/cpp/generic_sensor/platform_sensor_configuration.h"
+#include "services/device/public/cpp/generic_sensor/sensor_reading.h"
+#include "services/device/public/interfaces/constants.mojom.h"
+#include "services/device/public/interfaces/sensor.mojom.h"
+#include "services/device/public/interfaces/sensor_provider.mojom.h"
+#include "services/service_manager/public/cpp/service_context.h"
namespace content {
@@ -31,14 +46,6 @@ class FakeDataFetcher : public device::DataFetcherSharedMemory {
FakeDataFetcher() : sensor_data_available_(true) {}
~FakeDataFetcher() override {}
- void SetMotionStartedCallback(base::Closure motion_started_callback) {
- motion_started_callback_ = motion_started_callback;
- }
-
- void SetMotionStoppedCallback(base::Closure motion_stopped_callback) {
- motion_stopped_callback_ = motion_stopped_callback;
- }
-
void SetOrientationStartedCallback(
base::Closure orientation_started_callback) {
orientation_started_callback_ = orientation_started_callback;
@@ -65,15 +72,6 @@ class FakeDataFetcher : public device::DataFetcherSharedMemory {
EXPECT_TRUE(buffer);
switch (consumer_type) {
- case device::CONSUMER_TYPE_MOTION: {
- device::DeviceMotionHardwareBuffer* motion_buffer =
- static_cast<device::DeviceMotionHardwareBuffer*>(buffer);
- if (sensor_data_available_)
- UpdateMotion(motion_buffer);
- SetMotionBufferReady(motion_buffer);
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- motion_started_callback_);
- } break;
case device::CONSUMER_TYPE_ORIENTATION: {
device::DeviceOrientationHardwareBuffer* orientation_buffer =
static_cast<device::DeviceOrientationHardwareBuffer*>(buffer);
@@ -100,10 +98,6 @@ class FakeDataFetcher : public device::DataFetcherSharedMemory {
bool Stop(device::ConsumerType consumer_type) override {
switch (consumer_type) {
- case device::CONSUMER_TYPE_MOTION:
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- motion_stopped_callback_);
- break;
case device::CONSUMER_TYPE_ORIENTATION:
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
orientation_stopped_callback_);
@@ -128,12 +122,6 @@ class FakeDataFetcher : public device::DataFetcherSharedMemory {
sensor_data_available_ = available;
}
- void SetMotionBufferReady(device::DeviceMotionHardwareBuffer* buffer) {
- buffer->seqlock.WriteBegin();
- buffer->data.all_available_sensors_are_active = true;
- buffer->seqlock.WriteEnd();
- }
-
void SetOrientationBufferReady(
device::DeviceOrientationHardwareBuffer* buffer) {
buffer->seqlock.WriteBegin();
@@ -141,34 +129,6 @@ class FakeDataFetcher : public device::DataFetcherSharedMemory {
buffer->seqlock.WriteEnd();
}
- void UpdateMotion(device::DeviceMotionHardwareBuffer* buffer) {
- buffer->seqlock.WriteBegin();
- buffer->data.acceleration_x = 1;
- buffer->data.has_acceleration_x = true;
- buffer->data.acceleration_y = 2;
- buffer->data.has_acceleration_y = true;
- buffer->data.acceleration_z = 3;
- buffer->data.has_acceleration_z = true;
-
- buffer->data.acceleration_including_gravity_x = 4;
- buffer->data.has_acceleration_including_gravity_x = true;
- buffer->data.acceleration_including_gravity_y = 5;
- buffer->data.has_acceleration_including_gravity_y = true;
- buffer->data.acceleration_including_gravity_z = 6;
- buffer->data.has_acceleration_including_gravity_z = true;
-
- buffer->data.rotation_rate_alpha = 7;
- buffer->data.has_rotation_rate_alpha = true;
- buffer->data.rotation_rate_beta = 8;
- buffer->data.has_rotation_rate_beta = true;
- buffer->data.rotation_rate_gamma = 9;
- buffer->data.has_rotation_rate_gamma = true;
-
- buffer->data.interval = 100;
- buffer->data.all_available_sensors_are_active = true;
- buffer->seqlock.WriteEnd();
- }
-
void UpdateOrientation(device::DeviceOrientationHardwareBuffer* buffer) {
buffer->seqlock.WriteBegin();
buffer->data.alpha = 1;
@@ -196,10 +156,8 @@ class FakeDataFetcher : public device::DataFetcherSharedMemory {
}
// The below callbacks should be run on the UI thread.
- base::Closure motion_started_callback_;
base::Closure orientation_started_callback_;
base::Closure orientation_absolute_started_callback_;
- base::Closure motion_stopped_callback_;
base::Closure orientation_stopped_callback_;
base::Closure orientation_absolute_stopped_callback_;
bool sensor_data_available_;
@@ -208,6 +166,190 @@ class FakeDataFetcher : public device::DataFetcherSharedMemory {
DISALLOW_COPY_AND_ASSIGN(FakeDataFetcher);
};
+class FakeSensor : public device::mojom::Sensor {
+ public:
+ FakeSensor(device::mojom::SensorType sensor_type)
+ : sensor_type_(sensor_type) {
+ shared_buffer_handle_ = mojo::SharedBufferHandle::Create(
+ sizeof(device::SensorReadingSharedBuffer) *
+ static_cast<uint64_t>(device::mojom::SensorType::LAST));
+ }
+
+ ~FakeSensor() override = default;
+
+ // device::mojom::Sensor:
+ void AddConfiguration(
+ const device::PlatformSensorConfiguration& configuration,
+ AddConfigurationCallback callback) override {
+ std::move(callback).Run(true);
+ SensorReadingChanged();
+ }
+
+ // device::mojom::Sensor:
+ void GetDefaultConfiguration(
+ GetDefaultConfigurationCallback callback) override {
+ std::move(callback).Run(GetDefaultConfiguration());
+ }
+
+ // device::mojom::Sensor:
+ void RemoveConfiguration(
+ const device::PlatformSensorConfiguration& configuration) override {}
+
+ // device::mojom::Sensor:
+ void Suspend() override {}
+ void Resume() override {}
+ void ConfigureReadingChangeNotifications(bool enabled) override {
+ reading_notification_enabled_ = enabled;
+ }
+
+ device::PlatformSensorConfiguration GetDefaultConfiguration() {
+ return device::PlatformSensorConfiguration(60 /* frequency */);
+ }
+
+ device::mojom::ReportingMode GetReportingMode() {
+ return device::mojom::ReportingMode::ON_CHANGE;
+ }
+
+ double GetMaximumSupportedFrequency() { return 60.0; }
+ double GetMinimumSupportedFrequency() { return 1.0; }
+
+ device::mojom::SensorClientRequest GetClient() {
+ return mojo::MakeRequest(&client_);
+ }
+
+ mojo::ScopedSharedBufferHandle GetSharedBufferHandle() {
+ return shared_buffer_handle_->Clone(
+ mojo::SharedBufferHandle::AccessMode::READ_ONLY);
+ }
+
+ uint64_t GetBufferOffset() {
+ return device::SensorReadingSharedBuffer::GetOffset(sensor_type_);
+ }
+
+ void set_reading(device::SensorReading reading) { reading_ = reading; }
+
+ void SensorReadingChanged() {
+ if (!shared_buffer_handle_.is_valid())
+ return;
+
+ mojo::ScopedSharedBufferMapping shared_buffer =
+ shared_buffer_handle_->MapAtOffset(
+ device::mojom::SensorInitParams::kReadBufferSizeForTests,
+ GetBufferOffset());
+
+ device::SensorReadingSharedBuffer* buffer =
+ static_cast<device::SensorReadingSharedBuffer*>(shared_buffer.get());
+ auto& seqlock = buffer->seqlock.value();
+ seqlock.WriteBegin();
+ buffer->reading = reading_;
+ seqlock.WriteEnd();
+
+ if (client_ && reading_notification_enabled_)
+ client_->SensorReadingChanged();
+ }
+
+ private:
+ device::mojom::SensorType sensor_type_;
+ bool reading_notification_enabled_ = true;
+ mojo::ScopedSharedBufferHandle shared_buffer_handle_;
+ device::mojom::SensorClientPtr client_;
+ device::SensorReading reading_;
+
+ DISALLOW_COPY_AND_ASSIGN(FakeSensor);
+};
+
+class FakeSensorProvider : public device::mojom::SensorProvider {
+ public:
+ FakeSensorProvider() : binding_(this) {}
+ ~FakeSensorProvider() override = default;
+
+ void Bind(const std::string& interface_name,
+ mojo::ScopedMessagePipeHandle handle,
+ const service_manager::BindSourceInfo& source_info) {
+ DCHECK(!binding_.is_bound());
+ binding_.Bind(device::mojom::SensorProviderRequest(std::move(handle)));
+ }
+
+ void set_accelerometer_is_available(bool accelerometer_is_available) {
+ accelerometer_is_available_ = accelerometer_is_available;
+ }
+
+ void set_linear_acceleration_sensor_is_available(
+ bool linear_acceleration_sensor_is_available) {
+ linear_acceleration_sensor_is_available_ =
+ linear_acceleration_sensor_is_available;
+ }
+
+ void set_gyroscope_is_available(bool gyroscope_is_available) {
+ gyroscope_is_available_ = gyroscope_is_available;
+ }
+
+ // device::mojom::sensorProvider:
+ void GetSensor(device::mojom::SensorType type,
+ device::mojom::SensorRequest sensor_request,
+ GetSensorCallback callback) override {
+ std::unique_ptr<FakeSensor> sensor;
+ device::SensorReading reading;
+ reading.raw.timestamp =
+ (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF();
+
+ switch (type) {
+ case device::mojom::SensorType::ACCELEROMETER:
+ if (accelerometer_is_available_) {
+ sensor = base::MakeUnique<FakeSensor>(
+ device::mojom::SensorType::ACCELEROMETER);
+ reading.accel.x = 4;
+ reading.accel.y = 5;
+ reading.accel.z = 6;
+ }
+ break;
+ case device::mojom::SensorType::LINEAR_ACCELERATION:
+ if (linear_acceleration_sensor_is_available_) {
+ sensor = base::MakeUnique<FakeSensor>(
+ device::mojom::SensorType::LINEAR_ACCELERATION);
+ reading.accel.x = 1;
+ reading.accel.y = 2;
+ reading.accel.z = 3;
+ }
+ break;
+ case device::mojom::SensorType::GYROSCOPE:
+ if (gyroscope_is_available_) {
+ sensor = base::MakeUnique<FakeSensor>(
+ device::mojom::SensorType::GYROSCOPE);
+ reading.gyro.x = 7;
+ reading.gyro.y = 8;
+ reading.gyro.z = 9;
+ }
+ break;
+ default:
+ NOTIMPLEMENTED();
+ }
+
+ if (sensor) {
+ sensor->set_reading(reading);
+ auto init_params = device::mojom::SensorInitParams::New();
+ init_params->memory = sensor->GetSharedBufferHandle();
+ init_params->buffer_offset = sensor->GetBufferOffset();
+ init_params->default_configuration = sensor->GetDefaultConfiguration();
+ init_params->maximum_frequency = sensor->GetMaximumSupportedFrequency();
+ init_params->minimum_frequency = sensor->GetMinimumSupportedFrequency();
+
+ std::move(callback).Run(std::move(init_params), sensor->GetClient());
+ mojo::MakeStrongBinding(std::move(sensor), std::move(sensor_request));
+ } else {
+ std::move(callback).Run(nullptr, nullptr);
+ }
+ }
+
+ private:
+ mojo::Binding<device::mojom::SensorProvider> binding_;
+ bool accelerometer_is_available_ = true;
+ bool linear_acceleration_sensor_is_available_ = true;
+ bool gyroscope_is_available_ = true;
+
+ DISALLOW_COPY_AND_ASSIGN(FakeSensorProvider);
+};
+
class DeviceSensorBrowserTest : public ContentBrowserTest {
public:
DeviceSensorBrowserTest()
@@ -218,8 +360,6 @@ class DeviceSensorBrowserTest : public ContentBrowserTest {
void SetUpOnMainThread() override {
// Initialize the RunLoops now that the main thread has been created.
- motion_started_runloop_.reset(new base::RunLoop());
- motion_stopped_runloop_.reset(new base::RunLoop());
orientation_started_runloop_.reset(new base::RunLoop());
orientation_stopped_runloop_.reset(new base::RunLoop());
orientation_absolute_started_runloop_.reset(new base::RunLoop());
@@ -227,20 +367,17 @@ class DeviceSensorBrowserTest : public ContentBrowserTest {
#if defined(OS_ANDROID)
// On Android, the DeviceSensorService lives on the UI thread.
SetUpFetcher();
-#else
- // On all other platforms, the DeviceSensorService lives on the IO thread.
+#endif // defined(OS_ANDROID)
+ sensor_provider_ = base::MakeUnique<FakeSensorProvider>();
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&DeviceSensorBrowserTest::SetUpOnIOThread,
- base::Unretained(this)));
+ base::BindOnce(&DeviceSensorBrowserTest::SetUpOnIOThread,
+ base::Unretained(this)));
io_loop_finished_event_.Wait();
-#endif
}
void SetUpFetcher() {
fetcher_ = new FakeDataFetcher();
- fetcher_->SetMotionStartedCallback(motion_started_runloop_->QuitClosure());
- fetcher_->SetMotionStoppedCallback(motion_stopped_runloop_->QuitClosure());
fetcher_->SetOrientationStartedCallback(
orientation_started_runloop_->QuitClosure());
fetcher_->SetOrientationStoppedCallback(
@@ -254,13 +391,24 @@ class DeviceSensorBrowserTest : public ContentBrowserTest {
}
void SetUpOnIOThread() {
+#if !defined(OS_ANDROID)
+ // On non-Android platforms, the DeviceSensorService lives on the IO thread.
SetUpFetcher();
+#endif // !defined(OS_ANDROID)
+ // Because Device Service also runs in this process(browser process), here
+ // we can directly set our binder to intercept interface requests against
+ // it.
+ service_manager::ServiceContext::SetGlobalBinderForTesting(
+ device::mojom::kServiceName, device::mojom::SensorProvider::Name_,
+ base::Bind(&FakeSensorProvider::Bind,
+ base::Unretained(sensor_provider_.get())));
+
io_loop_finished_event_.Signal();
}
void DelayAndQuit(base::TimeDelta delay) {
base::PlatformThread::Sleep(delay);
- base::MessageLoop::current()->QuitWhenIdle();
+ base::RunLoop::QuitCurrentWhenIdleDeprecated();
}
void WaitForAlertDialogAndQuitAfterDelay(base::TimeDelta delay) {
@@ -276,11 +424,10 @@ class DeviceSensorBrowserTest : public ContentBrowserTest {
}
FakeDataFetcher* fetcher_;
+ std::unique_ptr<FakeSensorProvider> sensor_provider_;
// NOTE: These can only be initialized once the main thread has been created
// and so must be pointers instead of plain objects.
- std::unique_ptr<base::RunLoop> motion_started_runloop_;
- std::unique_ptr<base::RunLoop> motion_stopped_runloop_;
std::unique_ptr<base::RunLoop> orientation_started_runloop_;
std::unique_ptr<base::RunLoop> orientation_stopped_runloop_;
std::unique_ptr<base::RunLoop> orientation_absolute_started_runloop_;
@@ -323,8 +470,6 @@ IN_PROC_BROWSER_TEST_F(DeviceSensorBrowserTest, MotionTest) {
NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 2);
EXPECT_EQ("pass", shell()->web_contents()->GetLastCommittedURL().ref());
- motion_started_runloop_->Run();
- motion_stopped_runloop_->Run();
}
IN_PROC_BROWSER_TEST_F(DeviceSensorBrowserTest, OrientationNullTest) {
@@ -359,13 +504,27 @@ IN_PROC_BROWSER_TEST_F(DeviceSensorBrowserTest, MotionNullTest) {
// The test page registers an event handler for motion events and
// expects to get an event with null values, because no sensor data can be
// provided.
- fetcher_->SetSensorDataAvailable(false);
+ sensor_provider_->set_accelerometer_is_available(false);
+ sensor_provider_->set_linear_acceleration_sensor_is_available(false);
+ sensor_provider_->set_gyroscope_is_available(false);
GURL test_url = GetTestUrl("device_sensors", "device_motion_null_test.html");
NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 2);
EXPECT_EQ("pass", shell()->web_contents()->GetLastCommittedURL().ref());
- motion_started_runloop_->Run();
- motion_stopped_runloop_->Run();
+}
+
+IN_PROC_BROWSER_TEST_F(DeviceSensorBrowserTest,
+ MotionOnlySomeSensorsAreAvailableTest) {
+ // The test page registers an event handler for motion events and
+ // expects to get an event with only the gyroscope and linear acceleration
+ // sensor values, because no accelerometer values can be provided.
+ sensor_provider_->set_accelerometer_is_available(false);
+ GURL test_url =
+ GetTestUrl("device_sensors",
+ "device_motion_only_some_sensors_are_available_test.html");
+ NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 2);
+
+ EXPECT_EQ("pass", shell()->web_contents()->GetLastCommittedURL().ref());
}
IN_PROC_BROWSER_TEST_F(DeviceSensorBrowserTest, NullTestWithAlert) {
@@ -375,6 +534,9 @@ IN_PROC_BROWSER_TEST_F(DeviceSensorBrowserTest, NullTestWithAlert) {
// window after the alert is dismissed and the callbacks are invoked which
// eventually navigate to #pass.
fetcher_->SetSensorDataAvailable(false);
+ sensor_provider_->set_accelerometer_is_available(false);
+ sensor_provider_->set_linear_acceleration_sensor_is_available(false);
+ sensor_provider_->set_gyroscope_is_available(false);
TestNavigationObserver same_tab_observer(shell()->web_contents(), 2);
GURL test_url =
@@ -385,8 +547,6 @@ IN_PROC_BROWSER_TEST_F(DeviceSensorBrowserTest, NullTestWithAlert) {
// delay, crbug.com/360044.
WaitForAlertDialogAndQuitAfterDelay(base::TimeDelta::FromMilliseconds(500));
- motion_started_runloop_->Run();
- motion_stopped_runloop_->Run();
orientation_started_runloop_->Run();
orientation_stopped_runloop_->Run();
same_tab_observer.Wait();
diff --git a/chromium/content/browser/devtools/BUILD.gn b/chromium/content/browser/devtools/BUILD.gn
index 1f3a739e474..611d0281158 100644
--- a/chromium/content/browser/devtools/BUILD.gn
+++ b/chromium/content/browser/devtools/BUILD.gn
@@ -74,6 +74,8 @@ inspector_protocol_generate("protocol_sources") {
# These are relative to $target_gen_dir.
outputs = [
+ "protocol/browser.cc",
+ "protocol/browser.h",
"protocol/dom.cc",
"protocol/dom.h",
"protocol/emulation.cc",
diff --git a/chromium/content/browser/devtools/browser_devtools_agent_host.cc b/chromium/content/browser/devtools/browser_devtools_agent_host.cc
index 7b233826743..74d572018d8 100644
--- a/chromium/content/browser/devtools/browser_devtools_agent_host.cc
+++ b/chromium/content/browser/devtools/browser_devtools_agent_host.cc
@@ -9,6 +9,7 @@
#include "base/memory/ptr_util.h"
#include "base/single_thread_task_runner.h"
#include "content/browser/devtools/devtools_session.h"
+#include "content/browser/devtools/protocol/browser_handler.h"
#include "content/browser/devtools/protocol/io_handler.h"
#include "content/browser/devtools/protocol/memory_handler.h"
#include "content/browser/devtools/protocol/protocol.h"
@@ -47,11 +48,11 @@ BrowserDevToolsAgentHost::~BrowserDevToolsAgentHost() {
}
void BrowserDevToolsAgentHost::AttachSession(DevToolsSession* session) {
- if (only_discovery_) {
- session->AddHandler(base::WrapUnique(new protocol::TargetHandler()));
+ session->AddHandler(base::WrapUnique(new protocol::TargetHandler()));
+ if (only_discovery_)
return;
- }
+ session->AddHandler(base::WrapUnique(new protocol::BrowserHandler()));
session->AddHandler(base::WrapUnique(new protocol::IOHandler(
GetIOContext())));
session->AddHandler(base::WrapUnique(new protocol::MemoryHandler()));
diff --git a/chromium/content/browser/devtools/devtools_agent_host_impl.cc b/chromium/content/browser/devtools/devtools_agent_host_impl.cc
index 184becccee2..11cbc87d150 100644
--- a/chromium/content/browser/devtools/devtools_agent_host_impl.cc
+++ b/chromium/content/browser/devtools/devtools_agent_host_impl.cc
@@ -22,7 +22,6 @@
#include "content/browser/devtools/shared_worker_devtools_agent_host.h"
#include "content/browser/devtools/shared_worker_devtools_manager.h"
#include "content/browser/frame_host/frame_tree_node.h"
-#include "content/browser/loader/netlog_observer.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
@@ -37,14 +36,13 @@ base::LazyInstance<base::ObserverList<DevToolsAgentHostObserver>>::Leaky
g_observers = LAZY_INSTANCE_INITIALIZER;
} // namespace
-char DevToolsAgentHost::kTypePage[] = "page";
-char DevToolsAgentHost::kTypeFrame[] = "iframe";
-char DevToolsAgentHost::kTypeSharedWorker[] = "shared_worker";
-char DevToolsAgentHost::kTypeServiceWorker[] = "service_worker";
-char DevToolsAgentHost::kTypeBrowser[] = "browser";
-char DevToolsAgentHost::kTypeGuest[] = "webview";
-char DevToolsAgentHost::kTypeOther[] = "other";
-int DevToolsAgentHostImpl::s_attached_count_ = 0;
+const char DevToolsAgentHost::kTypePage[] = "page";
+const char DevToolsAgentHost::kTypeFrame[] = "iframe";
+const char DevToolsAgentHost::kTypeSharedWorker[] = "shared_worker";
+const char DevToolsAgentHost::kTypeServiceWorker[] = "service_worker";
+const char DevToolsAgentHost::kTypeBrowser[] = "browser";
+const char DevToolsAgentHost::kTypeGuest[] = "webview";
+const char DevToolsAgentHost::kTypeOther[] = "other";
int DevToolsAgentHostImpl::s_force_creation_count_ = 0;
// static
@@ -171,11 +169,8 @@ void DevToolsAgentHostImpl::InnerAttachClient(DevToolsAgentHostClient* client) {
NotifyAttached();
}
-bool DevToolsAgentHostImpl::AttachClient(DevToolsAgentHostClient* client) {
- if (!sessions_.empty())
- return false;
+void DevToolsAgentHostImpl::AttachClient(DevToolsAgentHostClient* client) {
InnerAttachClient(client);
- return true;
}
void DevToolsAgentHostImpl::ForceAttachClient(DevToolsAgentHostClient* client) {
@@ -186,10 +181,6 @@ void DevToolsAgentHostImpl::ForceAttachClient(DevToolsAgentHostClient* client) {
InnerAttachClient(client);
}
-void DevToolsAgentHostImpl::AttachMultiClient(DevToolsAgentHostClient* client) {
- InnerAttachClient(client);
-}
-
bool DevToolsAgentHostImpl::DetachClient(DevToolsAgentHostClient* client) {
if (!SessionByClient(client))
return false;
@@ -345,28 +336,11 @@ void DevToolsAgentHostImpl::NotifyCreated() {
}
void DevToolsAgentHostImpl::NotifyAttached() {
- if (!s_attached_count_) {
- BrowserThread::PostTask(
- BrowserThread::IO,
- FROM_HERE,
- base::Bind(&NetLogObserver::Attach,
- GetContentClient()->browser()->GetNetLog()));
- }
- ++s_attached_count_;
-
for (auto& observer : g_observers.Get())
observer.DevToolsAgentHostAttached(this);
}
void DevToolsAgentHostImpl::NotifyDetached() {
- --s_attached_count_;
- if (!s_attached_count_) {
- BrowserThread::PostTask(
- BrowserThread::IO,
- FROM_HERE,
- base::Bind(&NetLogObserver::Detach));
- }
-
for (auto& observer : g_observers.Get())
observer.DevToolsAgentHostDetached(this);
}
diff --git a/chromium/content/browser/devtools/devtools_agent_host_impl.h b/chromium/content/browser/devtools/devtools_agent_host_impl.h
index 0d27827fb1e..36b28522b9c 100644
--- a/chromium/content/browser/devtools/devtools_agent_host_impl.h
+++ b/chromium/content/browser/devtools/devtools_agent_host_impl.h
@@ -26,7 +26,7 @@ class DevToolsSession;
class CONTENT_EXPORT DevToolsAgentHostImpl : public DevToolsAgentHost {
public:
// DevToolsAgentHost implementation.
- bool AttachClient(DevToolsAgentHostClient* client) override;
+ void AttachClient(DevToolsAgentHostClient* client) override;
void ForceAttachClient(DevToolsAgentHostClient* client) override;
bool DetachClient(DevToolsAgentHostClient* client) override;
bool DispatchProtocolMessage(DevToolsAgentHostClient* client,
@@ -44,7 +44,6 @@ class CONTENT_EXPORT DevToolsAgentHostImpl : public DevToolsAgentHost {
void DisconnectWebContents() override;
void ConnectWebContents(WebContents* wc) override;
- void AttachMultiClient(DevToolsAgentHostClient* client);
bool Inspect();
protected:
@@ -84,7 +83,6 @@ class CONTENT_EXPORT DevToolsAgentHostImpl : public DevToolsAgentHost {
base::flat_map<DevToolsAgentHostClient*, std::unique_ptr<DevToolsSession>>
session_by_client_;
DevToolsIOContext io_context_;
- static int s_attached_count_;
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 498f0c40160..4468bc4be35 100644
--- a/chromium/content/browser/devtools/devtools_http_handler.cc
+++ b/chromium/content/browser/devtools/devtools_http_handler.cc
@@ -11,6 +11,7 @@
#include "base/bind.h"
#include "base/compiler_specific.h"
#include "base/files/file_util.h"
+#include "base/guid.h"
#include "base/json/json_writer.h"
#include "base/location.h"
#include "base/logging.h"
@@ -59,6 +60,7 @@ const base::FilePath::CharType kDevToolsActivePortFileName[] =
const char kDevToolsHandlerThreadName[] = "Chrome_DevToolsHandlerThread";
const char kPageUrlPrefix[] = "/devtools/page/";
+const char kBrowserUrlPrefix[] = "/devtools/browser";
const char kTargetIdField[] = "id";
const char kTargetParentIdField[] = "parentId";
@@ -98,8 +100,6 @@ class ServerWrapper : net::HttpServer::Delegate {
void Send500(int connection_id, const std::string& message);
void Close(int connection_id);
- void WriteActivePortToUserProfile(const base::FilePath& output_directory);
-
~ServerWrapper() override {}
private:
@@ -210,6 +210,7 @@ void StartServerOnHandlerThread(
std::unique_ptr<DevToolsSocketFactory> socket_factory,
const base::FilePath& output_directory,
const base::FilePath& frontend_dir,
+ const std::string& browser_guid,
bool bundles_resources) {
DCHECK(thread->task_runner()->BelongsToCurrentThread());
std::unique_ptr<ServerWrapper> server_wrapper;
@@ -219,15 +220,35 @@ void StartServerOnHandlerThread(
if (server_socket) {
server_wrapper.reset(new ServerWrapper(handler, std::move(server_socket),
frontend_dir, bundles_resources));
- if (!output_directory.empty())
- server_wrapper->WriteActivePortToUserProfile(output_directory);
-
if (server_wrapper->GetLocalAddress(ip_address.get()) != net::OK)
ip_address.reset();
} else {
ip_address.reset();
+ }
+
+ if (ip_address) {
+ std::string message = base::StringPrintf(
+ "\nDevTools listening on ws://%s%s\n", ip_address->ToString().c_str(),
+ browser_guid.c_str());
+ fprintf(stderr, "%s", message.c_str());
+ fflush(stderr);
+
+ // Write this port to a well-known file in the profile directory
+ // so Telemetry can pick it up.
+ if (!output_directory.empty()) {
+ base::FilePath path =
+ output_directory.Append(kDevToolsActivePortFileName);
+ std::string port_target_string = base::StringPrintf(
+ "%d\n%s", ip_address->port(), browser_guid.c_str());
+ if (base::WriteFile(path, port_target_string.c_str(),
+ static_cast<int>(port_target_string.length())) < 0) {
+ LOG(ERROR) << "Error writing DevTools active port to file";
+ }
+ }
+ } else {
LOG(ERROR) << "Cannot start http server for devtools. Stop devtools.";
}
+
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::BindOnce(&ServerStartedOnUI, std::move(handler), thread.release(),
@@ -273,8 +294,8 @@ class DevToolsAgentHostClientImpl : public DevToolsAgentHostClient {
agent_host_ = nullptr;
message_loop_->task_runner()->PostTask(
FROM_HERE,
- base::Bind(&ServerWrapper::Close, base::Unretained(server_wrapper_),
- connection_id_));
+ base::BindOnce(&ServerWrapper::Close, base::Unretained(server_wrapper_),
+ connection_id_));
}
void DispatchProtocolMessage(DevToolsAgentHost* agent_host,
@@ -282,9 +303,9 @@ class DevToolsAgentHostClientImpl : public DevToolsAgentHostClient {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(agent_host == agent_host_.get());
message_loop_->task_runner()->PostTask(
- FROM_HERE,
- base::Bind(&ServerWrapper::SendOverWebSocket,
- base::Unretained(server_wrapper_), connection_id_, message));
+ FROM_HERE, base::BindOnce(&ServerWrapper::SendOverWebSocket,
+ base::Unretained(server_wrapper_),
+ connection_id_, message));
}
void OnMessage(const std::string& message) {
@@ -353,24 +374,18 @@ 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::Bind(&DevToolsHttpHandler::OnJsonRequest,
- handler_,
- connection_id,
- info));
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ 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::Bind(&DevToolsHttpHandler::OnDiscoveryPageRequest,
- handler_,
- connection_id));
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&DevToolsHttpHandler::OnDiscoveryPageRequest, handler_,
+ connection_id));
return;
}
@@ -393,12 +408,9 @@ void ServerWrapper::OnHttpRequest(int connection_id,
if (bundles_resources_) {
BrowserThread::PostTask(
- BrowserThread::UI,
- FROM_HERE,
- base::Bind(&DevToolsHttpHandler::OnFrontendResourceRequest,
- handler_,
- connection_id,
- filename));
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&DevToolsHttpHandler::OnFrontendResourceRequest,
+ handler_, connection_id, filename));
return;
}
server_->Send404(connection_id);
@@ -408,35 +420,23 @@ void ServerWrapper::OnWebSocketRequest(
int connection_id,
const net::HttpServerRequestInfo& request) {
BrowserThread::PostTask(
- BrowserThread::UI,
- FROM_HERE,
- base::Bind(
- &DevToolsHttpHandler::OnWebSocketRequest,
- handler_,
- connection_id,
- request));
+ BrowserThread::UI, FROM_HERE,
+ 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::Bind(
- &DevToolsHttpHandler::OnWebSocketMessage,
- handler_,
- connection_id,
- data));
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&DevToolsHttpHandler::OnWebSocketMessage, handler_,
+ connection_id, data));
}
void ServerWrapper::OnClose(int connection_id) {
BrowserThread::PostTask(
- BrowserThread::UI,
- FROM_HERE,
- base::Bind(
- &DevToolsHttpHandler::OnClose,
- handler_,
- connection_id));
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&DevToolsHttpHandler::OnClose, handler_, connection_id));
}
std::string DevToolsHttpHandler::GetFrontendURLInternal(
@@ -509,9 +509,13 @@ void DevToolsHttpHandler::OnJsonRequest(
version.SetString("Protocol-Version",
DevToolsAgentHost::GetProtocolVersion());
version.SetString("WebKit-Version", GetWebKitVersion());
- version.SetString("Browser", product_name_);
- version.SetString("User-Agent", user_agent_);
+ version.SetString("Browser", GetContentClient()->GetProduct());
+ version.SetString("User-Agent", GetContentClient()->GetUserAgent());
version.SetString("V8-Version", V8_VERSION_STRING);
+ std::string host = info.headers["host"];
+ version.SetString(
+ kTargetWebSocketDebuggerUrlField,
+ base::StringPrintf("ws://%s%s", host.c_str(), browser_guid_.c_str()));
#if defined(OS_ANDROID)
version.SetString("Android-Package",
base::android::BuildInfo::GetInstance()->package_name());
@@ -543,9 +547,7 @@ void DevToolsHttpHandler::OnJsonRequest(
scoped_refptr<DevToolsAgentHost> agent_host = nullptr;
agent_host = delegate_->CreateNewTarget(url);
if (!agent_host) {
- SendJson(connection_id,
- net::HTTP_INTERNAL_SERVER_ERROR,
- NULL,
+ SendJson(connection_id, net::HTTP_INTERNAL_SERVER_ERROR, NULL,
"Could not create new page");
return;
}
@@ -669,8 +671,7 @@ void DevToolsHttpHandler::OnWebSocketRequest(
if (!thread_)
return;
- std::string browser_prefix = "/devtools/browser";
- if (base::StartsWith(request.path, browser_prefix,
+ if (base::StartsWith(request.path, browser_guid_,
base::CompareCase::SENSITIVE)) {
scoped_refptr<DevToolsAgentHost> browser_agent =
DevToolsAgentHost::CreateForBrowser(
@@ -698,12 +699,6 @@ void DevToolsHttpHandler::OnWebSocketRequest(
return;
}
- if (agent->IsAttached()) {
- Send500(connection_id,
- "Target with given id is being inspected: " + target_id);
- return;
- }
-
connection_to_client_[connection_id].reset(new DevToolsAgentHostClientImpl(
thread_->message_loop(), server_wrapper_.get(), connection_id, agent));
@@ -728,14 +723,12 @@ DevToolsHttpHandler::DevToolsHttpHandler(
std::unique_ptr<DevToolsSocketFactory> socket_factory,
const std::string& frontend_url,
const base::FilePath& output_directory,
- const base::FilePath& debug_frontend_dir,
- const std::string& product_name,
- const std::string& user_agent)
- : frontend_url_(frontend_url),
- product_name_(product_name),
- user_agent_(user_agent),
- delegate_(delegate),
- weak_factory_(this) {
+ const base::FilePath& debug_frontend_dir)
+ : frontend_url_(frontend_url), delegate_(delegate), weak_factory_(this) {
+ browser_guid_ = delegate_->IsBrowserTargetDiscoverable()
+ ? kBrowserUrlPrefix
+ : base::StringPrintf("%s/%s", kBrowserUrlPrefix,
+ base::GenerateGUID().c_str());
bool bundles_resources = frontend_url_.empty();
if (frontend_url_.empty())
frontend_url_ = "/devtools/inspector.html";
@@ -747,10 +740,11 @@ DevToolsHttpHandler::DevToolsHttpHandler(
if (thread->StartWithOptions(options)) {
base::TaskRunner* task_runner = thread->task_runner().get();
task_runner->PostTask(
- FROM_HERE, base::BindOnce(&StartServerOnHandlerThread,
- weak_factory_.GetWeakPtr(), std::move(thread),
- std::move(socket_factory), output_directory,
- debug_frontend_dir, bundles_resources));
+ FROM_HERE,
+ base::BindOnce(&StartServerOnHandlerThread, weak_factory_.GetWeakPtr(),
+ std::move(thread), std::move(socket_factory),
+ output_directory, debug_frontend_dir, browser_guid_,
+ bundles_resources));
}
}
@@ -765,27 +759,6 @@ void DevToolsHttpHandler::ServerStarted(
server_ip_address_ = std::move(ip_address);
}
-void ServerWrapper::WriteActivePortToUserProfile(
- const base::FilePath& output_directory) {
- DCHECK(!output_directory.empty());
- net::IPEndPoint endpoint;
- int err;
- if ((err = server_->GetLocalAddress(&endpoint)) != net::OK) {
- LOG(ERROR) << "Error " << err << " getting local address";
- return;
- }
-
- // Write this port to a well-known file in the profile directory
- // so Telemetry can pick it up.
- base::FilePath path = output_directory.Append(kDevToolsActivePortFileName);
- std::string port_string = base::UintToString(endpoint.port());
- if (base::WriteFile(path, port_string.c_str(),
- static_cast<int>(port_string.length())) < 0) {
- LOG(ERROR) << "Error writing DevTools active port to file";
- }
- LOG(ERROR) << "\nDevTools listening on " << endpoint.ToString() << "\n";
-}
-
void DevToolsHttpHandler::SendJson(int connection_id,
net::HttpStatusCode status_code,
base::Value* value,
@@ -806,9 +779,9 @@ void DevToolsHttpHandler::SendJson(int connection_id,
response.SetBody(json_value + message, "application/json; charset=UTF-8");
thread_->task_runner()->PostTask(
- FROM_HERE, base::Bind(&ServerWrapper::SendResponse,
- base::Unretained(server_wrapper_.get()),
- connection_id, response));
+ FROM_HERE, base::BindOnce(&ServerWrapper::SendResponse,
+ base::Unretained(server_wrapper_.get()),
+ connection_id, response));
}
void DevToolsHttpHandler::Send200(int connection_id,
@@ -873,16 +846,11 @@ std::unique_ptr<base::DictionaryValue> DevToolsHttpHandler::SerializeDescriptor(
if (favicon_url.is_valid())
dictionary->SetString(kTargetFaviconUrlField, favicon_url.spec());
- if (!agent_host->IsAttached()) {
- dictionary->SetString(kTargetWebSocketDebuggerUrlField,
- base::StringPrintf("ws://%s%s%s",
- host.c_str(),
- kPageUrlPrefix,
- id.c_str()));
- std::string devtools_frontend_url = GetFrontendURLInternal(id, host);
- dictionary->SetString(
- kTargetDevtoolsFrontendUrlField, devtools_frontend_url);
- }
+ dictionary->SetString(kTargetWebSocketDebuggerUrlField,
+ base::StringPrintf("ws://%s%s%s", host.c_str(),
+ kPageUrlPrefix, id.c_str()));
+ std::string devtools_frontend_url = GetFrontendURLInternal(id, host);
+ dictionary->SetString(kTargetDevtoolsFrontendUrlField, devtools_frontend_url);
return dictionary;
}
diff --git a/chromium/content/browser/devtools/devtools_http_handler.h b/chromium/content/browser/devtools/devtools_http_handler.h
index 4ef441367a9..83e1f8cf389 100644
--- a/chromium/content/browser/devtools/devtools_http_handler.h
+++ b/chromium/content/browser/devtools/devtools_http_handler.h
@@ -54,9 +54,7 @@ class DevToolsHttpHandler {
std::unique_ptr<DevToolsSocketFactory> server_socket_factory,
const std::string& frontend_url,
const base::FilePath& active_port_output_directory,
- const base::FilePath& debug_frontend_dir,
- const std::string& product_name,
- const std::string& user_agent);
+ const base::FilePath& debug_frontend_dir);
~DevToolsHttpHandler();
private:
@@ -111,8 +109,7 @@ class DevToolsHttpHandler {
// The thread used by the devtools handler to run server socket.
std::unique_ptr<base::Thread> thread_;
std::string frontend_url_;
- std::string product_name_;
- std::string user_agent_;
+ std::string browser_guid_;
std::unique_ptr<ServerWrapper> server_wrapper_;
std::unique_ptr<net::IPEndPoint> server_ip_address_;
using ConnectionToClientMap =
diff --git a/chromium/content/browser/devtools/devtools_http_handler_unittest.cc b/chromium/content/browser/devtools/devtools_http_handler_unittest.cc
index 7232833cc25..c116cce0b73 100644
--- a/chromium/content/browser/devtools/devtools_http_handler_unittest.cc
+++ b/chromium/content/browser/devtools/devtools_http_handler_unittest.cc
@@ -16,6 +16,7 @@
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_split.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/values.h"
#include "content/public/browser/content_browser_client.h"
@@ -75,7 +76,7 @@ class DummyServerSocketFactory : public DevToolsSocketFactory {
protected:
std::unique_ptr<net::ServerSocket> CreateForHttpServer() override {
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&QuitFromHandlerThread, quit_closure_1_));
+ FROM_HERE, base::BindOnce(&QuitFromHandlerThread, quit_closure_1_));
return base::WrapUnique(new DummyServerSocket());
}
@@ -98,7 +99,7 @@ class FailingServerSocketFactory : public DummyServerSocketFactory {
private:
std::unique_ptr<net::ServerSocket> CreateForHttpServer() override {
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&QuitFromHandlerThread, quit_closure_1_));
+ FROM_HERE, base::BindOnce(&QuitFromHandlerThread, quit_closure_1_));
return nullptr;
}
};
@@ -136,8 +137,7 @@ TEST_F(DevToolsHttpHandlerTest, TestStartStop) {
new DummyServerSocketFactory(run_loop.QuitClosure(),
run_loop_2.QuitClosure()));
DevToolsAgentHost::StartRemoteDebuggingServer(
- std::move(factory), std::string(), base::FilePath(), base::FilePath(),
- std::string(), std::string());
+ std::move(factory), std::string(), base::FilePath(), base::FilePath());
// Our dummy socket factory will post a quit message once the server will
// become ready.
run_loop.Run();
@@ -153,8 +153,7 @@ TEST_F(DevToolsHttpHandlerTest, TestServerSocketFailed) {
run_loop_2.QuitClosure()));
LOG(INFO) << "Following error message is expected:";
DevToolsAgentHost::StartRemoteDebuggingServer(
- std::move(factory), std::string(), base::FilePath(), base::FilePath(),
- std::string(), std::string());
+ std::move(factory), std::string(), base::FilePath(), base::FilePath());
// Our dummy socket factory will post a quit message once the server will
// become ready.
run_loop.Run();
@@ -175,8 +174,7 @@ TEST_F(DevToolsHttpHandlerTest, TestDevToolsActivePort) {
run_loop_2.QuitClosure()));
DevToolsAgentHost::StartRemoteDebuggingServer(
- std::move(factory), std::string(), temp_dir.GetPath(), base::FilePath(),
- std::string(), std::string());
+ std::move(factory), std::string(), temp_dir.GetPath(), base::FilePath());
// Our dummy socket factory will post a quit message once the server will
// become ready.
run_loop.Run();
@@ -191,8 +189,10 @@ TEST_F(DevToolsHttpHandlerTest, TestDevToolsActivePort) {
EXPECT_TRUE(base::PathExists(active_port_file));
std::string file_contents;
EXPECT_TRUE(base::ReadFileToString(active_port_file, &file_contents));
+ std::vector<std::string> tokens = base::SplitString(
+ file_contents, "\n", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
int port = 0;
- EXPECT_TRUE(base::StringToInt(file_contents, &port));
+ EXPECT_TRUE(base::StringToInt(tokens[0], &port));
EXPECT_EQ(static_cast<int>(kDummyPort), port);
}
diff --git a/chromium/content/browser/devtools/devtools_io_context.cc b/chromium/content/browser/devtools/devtools_io_context.cc
index 719ef4263e6..2e8bb8761ac 100644
--- a/chromium/content/browser/devtools/devtools_io_context.cc
+++ b/chromium/content/browser/devtools/devtools_io_context.cc
@@ -4,36 +4,84 @@
#include "content/browser/devtools/devtools_io_context.h"
+#include "base/base64.h"
#include "base/files/file.h"
#include "base/files/file_util.h"
+#include "base/memory/ptr_util.h"
#include "base/sequenced_task_runner.h"
#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
+#include "base/task_scheduler/lazy_task_runner.h"
#include "base/task_scheduler/post_task.h"
#include "base/third_party/icu/icu_utf.h"
#include "base/threading/thread_restrictions.h"
+#include "content/browser/blob_storage/chrome_blob_storage_context.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/storage_partition.h"
+#include "net/base/io_buffer.h"
+#include "net/base/net_errors.h"
+#include "storage/browser/blob/blob_data_handle.h"
+#include "storage/browser/blob/blob_reader.h"
+#include "storage/browser/blob/blob_storage_context.h"
+#include "storage/browser/fileapi/file_system_context.h"
+#include "storage/common/blob_storage/blob_storage_constants.h"
+
+#include <queue>
namespace content {
namespace {
-unsigned s_last_stream_handle = 0;
+
+base::SequencedTaskRunner* impl_task_runner() {
+ constexpr base::TaskTraits kBlockingTraits = {base::MayBlock(),
+ base::TaskPriority::BACKGROUND};
+ static base::LazySequencedTaskRunner s_sequenced_task_unner =
+ LAZY_SEQUENCED_TASK_RUNNER_INITIALIZER(kBlockingTraits);
+ return s_sequenced_task_unner.Get().get();
}
-using Stream = DevToolsIOContext::Stream;
+using storage::BlobReader;
+
+unsigned s_last_stream_handle = 0;
+
+class TempFileStream : public DevToolsIOContext::RWStream {
+ public:
+ TempFileStream();
+
+ void Read(off_t position, size_t max_size, ReadCallback callback) override;
+ void Close(bool invoke_pending_callbacks) override {}
+ void Append(std::unique_ptr<std::string> data) override;
+ const std::string& handle() override { return handle_; }
-Stream::Stream(base::SequencedTaskRunner* task_runner)
- : base::RefCountedDeleteOnSequence<Stream>(task_runner),
+ private:
+ ~TempFileStream() override;
+
+ void ReadOnFileSequence(off_t pos, size_t max_size, ReadCallback callback);
+ void AppendOnFileSequence(std::unique_ptr<std::string> data);
+ bool InitOnFileSequenceIfNeeded();
+
+ const std::string handle_;
+ base::File file_;
+ scoped_refptr<base::SequencedTaskRunner> task_runner_;
+ bool had_errors_;
+ off_t last_read_pos_;
+
+ DISALLOW_COPY_AND_ASSIGN(TempFileStream);
+};
+
+TempFileStream::TempFileStream()
+ : DevToolsIOContext::RWStream(impl_task_runner()),
handle_(base::UintToString(++s_last_stream_handle)),
- task_runner_(task_runner),
+ task_runner_(impl_task_runner()),
had_errors_(false),
last_read_pos_(0) {}
-Stream::~Stream() {
+TempFileStream::~TempFileStream() {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
}
-bool Stream::InitOnFileSequenceIfNeeded() {
+bool TempFileStream::InitOnFileSequenceIfNeeded() {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
base::ThreadRestrictions::AssertIOAllowed();
if (had_errors_)
@@ -60,21 +108,23 @@ bool Stream::InitOnFileSequenceIfNeeded() {
return true;
}
-void Stream::Read(off_t position, size_t max_size, ReadCallback callback) {
+void TempFileStream::Read(off_t position,
+ size_t max_size,
+ ReadCallback callback) {
task_runner_->PostTask(
- FROM_HERE, base::BindOnce(&Stream::ReadOnFileSequence, this, position,
- max_size, std::move(callback)));
+ FROM_HERE, base::BindOnce(&TempFileStream::ReadOnFileSequence, this,
+ position, max_size, std::move(callback)));
}
-void Stream::Append(std::unique_ptr<std::string> data) {
+void TempFileStream::Append(std::unique_ptr<std::string> data) {
task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&Stream::AppendOnFileSequence, this, std::move(data)));
+ FROM_HERE, base::BindOnce(&TempFileStream::AppendOnFileSequence, this,
+ std::move(data)));
}
-void Stream::ReadOnFileSequence(off_t position,
- size_t max_size,
- ReadCallback callback) {
+void TempFileStream::ReadOnFileSequence(off_t position,
+ size_t max_size,
+ ReadCallback callback) {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
Status status = StatusFailure;
std::unique_ptr<std::string> data;
@@ -105,10 +155,10 @@ void Stream::ReadOnFileSequence(off_t position,
}
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::BindOnce(std::move(callback), std::move(data), status));
+ base::BindOnce(std::move(callback), std::move(data), false, status));
}
-void Stream::AppendOnFileSequence(std::unique_ptr<std::string> data) {
+void TempFileStream::AppendOnFileSequence(std::unique_ptr<std::string> data) {
if (!InitOnFileSequenceIfNeeded())
return;
int size_written = file_.WriteAtCurrentPos(&*data->begin(), data->length());
@@ -119,33 +169,362 @@ void Stream::AppendOnFileSequence(std::unique_ptr<std::string> data) {
}
}
-DevToolsIOContext::DevToolsIOContext() = default;
+class BlobStream : public DevToolsIOContext::ROStream {
+ public:
+ using OpenCallback = base::OnceCallback<void(bool)>;
+
+ BlobStream()
+ : DevToolsIOContext::ROStream(
+ BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)),
+ last_read_pos_(0),
+ failed_(false),
+ is_binary_(false) {}
+
+ void Open(scoped_refptr<ChromeBlobStorageContext> context,
+ StoragePartition* partition,
+ const std::string& handle,
+ OpenCallback callback);
+
+ void Read(off_t position, size_t max_size, ReadCallback callback) override;
+ void Close(bool invoke_pending_callbacks) override;
+
+ private:
+ struct ReadRequest {
+ off_t position;
+ size_t max_size;
+ ReadCallback callback;
+
+ void Fail();
+
+ ReadRequest(off_t position, size_t max_size, ReadCallback callback)
+ : position(position),
+ max_size(max_size),
+ callback(std::move(callback)) {}
+ };
+
+ ~BlobStream() override = default;
+
+ void OpenOnIO(scoped_refptr<ChromeBlobStorageContext> blob_context,
+ scoped_refptr<storage::FileSystemContext> fs_context,
+ const std::string& uuid,
+ OpenCallback callback);
+ void ReadOnIO(std::unique_ptr<ReadRequest> request);
+ void CloseOnIO(bool invoke_pending_callbacks);
+
+ void FailOnIO();
+ void FailOnIO(OpenCallback callback) {
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::BindOnce(std::move(callback), false));
+ FailOnIO();
+ }
+
+ void StartReadRequest();
+ void CreateReader();
+ void BeginRead();
+
+ void OnReadComplete(int bytes_read);
+ void OnBlobConstructionComplete(storage::BlobStatus status);
+ void OnCalculateSizeComplete(int net_error);
+
+ static bool IsTextMimeType(const std::string& mime_type);
+
+ std::unique_ptr<storage::BlobDataHandle> blob_handle_;
+ OpenCallback open_callback_;
+ scoped_refptr<storage::FileSystemContext> fs_context_;
+ std::unique_ptr<BlobReader> blob_reader_;
+ std::queue<std::unique_ptr<ReadRequest>> pending_reads_;
+ scoped_refptr<net::IOBufferWithSize> io_buf_;
+ off_t last_read_pos_;
+ bool failed_;
+ bool is_binary_;
+
+ DISALLOW_COPY_AND_ASSIGN(BlobStream);
+};
+
+void BlobStream::ReadRequest::Fail() {
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::BindOnce(std::move(callback), nullptr, false,
+ ROStream::StatusFailure));
+}
+
+// static
+bool BlobStream::IsTextMimeType(const std::string& mime_type) {
+ static const char* kTextMIMETypePrefixes[] = {
+ "text/", "application/x-javascript", "application/json",
+ "application/xml"};
+ for (size_t i = 0; i < arraysize(kTextMIMETypePrefixes); ++i) {
+ if (base::StartsWith(mime_type, kTextMIMETypePrefixes[i],
+ base::CompareCase::INSENSITIVE_ASCII))
+ return true;
+ }
+ return false;
+}
+
+void BlobStream::Open(scoped_refptr<ChromeBlobStorageContext> context,
+ StoragePartition* partition,
+ const std::string& handle,
+ OpenCallback callback) {
+ scoped_refptr<storage::FileSystemContext> fs_context =
+ partition->GetFileSystemContext();
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&BlobStream::OpenOnIO, this, context, fs_context, handle,
+ std::move(callback)));
+}
+
+void BlobStream::Read(off_t position, size_t max_size, ReadCallback callback) {
+ std::unique_ptr<ReadRequest> request(
+ new ReadRequest(position, max_size, std::move(callback)));
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&BlobStream::ReadOnIO, this, std::move(request)));
+}
+
+void BlobStream::Close(bool invoke_pending_callbacks) {
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&BlobStream::CloseOnIO, this, invoke_pending_callbacks));
+}
+
+void BlobStream::OpenOnIO(scoped_refptr<ChromeBlobStorageContext> blob_context,
+ scoped_refptr<storage::FileSystemContext> fs_context,
+ const std::string& uuid,
+ OpenCallback callback) {
+ DCHECK(!blob_handle_);
+
+ storage::BlobStorageContext* bsc = blob_context->context();
+ blob_handle_ = bsc->GetBlobDataFromUUID(uuid);
+ if (!blob_handle_) {
+ LOG(ERROR) << "No blob with uuid: " << uuid;
+ FailOnIO(std::move(callback));
+ return;
+ }
+ is_binary_ = !IsTextMimeType(blob_handle_->content_type());
+ open_callback_ = std::move(callback);
+ fs_context_ = std::move(fs_context);
+ blob_handle_->RunOnConstructionComplete(
+ base::Bind(&BlobStream::OnBlobConstructionComplete, this));
+}
+
+void BlobStream::OnBlobConstructionComplete(storage::BlobStatus status) {
+ DCHECK(!BlobStatusIsPending(status));
+ if (BlobStatusIsError(status)) {
+ LOG(ERROR) << "Blob building failed: " << static_cast<int>(status);
+ FailOnIO(std::move(open_callback_));
+ return;
+ }
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::BindOnce(std::move(open_callback_), true));
+ if (!pending_reads_.empty())
+ StartReadRequest();
+}
+
+void BlobStream::ReadOnIO(std::unique_ptr<ReadRequest> request) {
+ if (failed_) {
+ request->Fail();
+ return;
+ }
+ pending_reads_.push(std::move(request));
+ if (pending_reads_.size() > 1 || open_callback_)
+ return;
+ StartReadRequest();
+}
+
+void BlobStream::FailOnIO() {
+ failed_ = true;
+ while (!pending_reads_.empty()) {
+ pending_reads_.front()->Fail();
+ pending_reads_.pop();
+ }
+}
+
+void BlobStream::CloseOnIO(bool invoke_pending_callbacks) {
+ if (blob_reader_) {
+ blob_reader_->Kill();
+ blob_reader_.reset();
+ }
+ if (blob_handle_)
+ blob_handle_.reset();
+ if (invoke_pending_callbacks) {
+ FailOnIO();
+ return;
+ }
+ failed_ = true;
+ pending_reads_ = std::queue<std::unique_ptr<ReadRequest>>();
+ open_callback_ = OpenCallback();
+}
+
+void BlobStream::StartReadRequest() {
+ DCHECK_GE(pending_reads_.size(), 1UL);
+ DCHECK(blob_handle_);
+ DCHECK(!failed_);
+
+ ReadRequest& request = *pending_reads_.front();
+ if (request.position < 0)
+ request.position = last_read_pos_;
+ if (request.position != last_read_pos_)
+ blob_reader_.reset();
+ if (!blob_reader_)
+ CreateReader();
+ else
+ BeginRead();
+}
+
+void BlobStream::BeginRead() {
+ DCHECK_GE(pending_reads_.size(), 1UL);
+ ReadRequest& request = *pending_reads_.front();
+ if (!io_buf_ || static_cast<size_t>(io_buf_->size()) < request.max_size)
+ io_buf_ = new net::IOBufferWithSize(request.max_size);
+ int bytes_read;
+ BlobReader::Status status =
+ blob_reader_->Read(io_buf_.get(), request.max_size, &bytes_read,
+ base::Bind(&BlobStream::OnReadComplete, this));
+ if (status == BlobReader::Status::IO_PENDING)
+ return;
+ // This is for uniformity with the asynchronous case.
+ if (status == BlobReader::Status::NET_ERROR) {
+ bytes_read = blob_reader_->net_error();
+ DCHECK_LT(0, bytes_read);
+ }
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&BlobStream::OnReadComplete, this, bytes_read));
+}
+
+void BlobStream::OnReadComplete(int bytes_read) {
+ std::unique_ptr<ReadRequest> request = std::move(pending_reads_.front());
+ pending_reads_.pop();
-DevToolsIOContext::~DevToolsIOContext() = default;
+ Status status;
+ std::unique_ptr<std::string> data(new std::string());
+ bool base64_encoded = false;
+
+ if (bytes_read < 0) {
+ status = StatusFailure;
+ LOG(ERROR) << "Error reading blob: " << net::ErrorToString(bytes_read);
+ } else if (!bytes_read) {
+ status = StatusEOF;
+ } else {
+ last_read_pos_ += bytes_read;
+ status = blob_reader_->remaining_bytes() ? StatusSuccess : StatusEOF;
+ if (is_binary_) {
+ base64_encoded = true;
+ Base64Encode(base::StringPiece(io_buf_->data(), bytes_read), data.get());
+ } else {
+ // TODO(caseq): truncate at UTF8 boundary.
+ *data = std::string(io_buf_->data(), bytes_read);
+ }
+ }
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(std::move(request->callback), std::move(data),
+ base64_encoded, status));
+ if (!pending_reads_.empty())
+ StartReadRequest();
+}
-scoped_refptr<Stream> DevToolsIOContext::CreateTempFileBackedStream() {
- if (!task_runner_) {
- task_runner_ = base::CreateSequencedTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::BACKGROUND});
+void BlobStream::CreateReader() {
+ DCHECK(!blob_reader_);
+ blob_reader_ = blob_handle_->CreateReader(fs_context_.get());
+ BlobReader::Status status = blob_reader_->CalculateSize(
+ base::Bind(&BlobStream::OnCalculateSizeComplete, this));
+ if (status != BlobReader::Status::IO_PENDING) {
+ OnCalculateSizeComplete(status == BlobReader::Status::NET_ERROR
+ ? blob_reader_->net_error()
+ : net::OK);
}
- scoped_refptr<Stream> result = new Stream(task_runner_.get());
+}
+
+void BlobStream::OnCalculateSizeComplete(int net_error) {
+ if (net_error != net::OK) {
+ FailOnIO();
+ return;
+ }
+ off_t seek_to = pending_reads_.front()->position;
+ if (seek_to != 0UL) {
+ if (seek_to >= static_cast<off_t>(blob_reader_->total_size())) {
+ OnReadComplete(0);
+ return;
+ }
+ BlobReader::Status status = blob_reader_->SetReadRange(
+ seek_to, blob_reader_->total_size() - seek_to);
+ if (status != BlobReader::Status::DONE) {
+ FailOnIO();
+ return;
+ }
+ }
+ BeginRead();
+}
+
+} // namespace
+
+DevToolsIOContext::ROStream::ROStream(
+ scoped_refptr<base::SequencedTaskRunner> task_runner)
+ : RefCountedDeleteOnSequence<DevToolsIOContext::ROStream>(
+ std::move(task_runner)) {}
+
+DevToolsIOContext::ROStream::~ROStream() = default;
+
+DevToolsIOContext::RWStream::RWStream(
+ scoped_refptr<base::SequencedTaskRunner> task_runner)
+ : DevToolsIOContext::ROStream(std::move(task_runner)) {}
+
+DevToolsIOContext::RWStream::~RWStream() = default;
+
+DevToolsIOContext::DevToolsIOContext() : weak_factory_(this) {}
+
+DevToolsIOContext::~DevToolsIOContext() {
+ DiscardAllStreams();
+}
+
+scoped_refptr<DevToolsIOContext::RWStream>
+DevToolsIOContext::CreateTempFileBackedStream() {
+ scoped_refptr<TempFileStream> result = new TempFileStream();
bool inserted =
streams_.insert(std::make_pair(result->handle(), result)).second;
DCHECK(inserted);
return result;
}
-scoped_refptr<Stream>
- DevToolsIOContext::GetByHandle(const std::string& handle) {
+scoped_refptr<DevToolsIOContext::ROStream> DevToolsIOContext::GetByHandle(
+ const std::string& handle) {
StreamsMap::const_iterator it = streams_.find(handle);
- return it == streams_.end() ? scoped_refptr<Stream>() : it->second;
+ return it == streams_.end() ? scoped_refptr<ROStream>() : it->second;
+}
+
+scoped_refptr<DevToolsIOContext::ROStream> DevToolsIOContext::OpenBlob(
+ ChromeBlobStorageContext* context,
+ StoragePartition* partition,
+ const std::string& handle,
+ const std::string& uuid) {
+ scoped_refptr<BlobStream> result = new BlobStream();
+ bool inserted = streams_.insert(std::make_pair(handle, result)).second;
+
+ result->Open(context, partition, uuid,
+ base::BindOnce(&DevToolsIOContext::OnBlobOpenComplete,
+ weak_factory_.GetWeakPtr(), handle));
+ DCHECK(inserted);
+ return std::move(result);
+}
+
+void DevToolsIOContext::OnBlobOpenComplete(const std::string& handle,
+ bool success) {
+ if (!success)
+ Close(handle);
}
bool DevToolsIOContext::Close(const std::string& handle) {
- return streams_.erase(handle) == 1;
+ StreamsMap::iterator it = streams_.find(handle);
+ if (it == streams_.end())
+ return false;
+ it->second->Close(false);
+ streams_.erase(it);
+ return true;
}
void DevToolsIOContext::DiscardAllStreams() {
+ for (auto& entry : streams_)
+ entry.second->Close(true);
return streams_.clear();
}
diff --git a/chromium/content/browser/devtools/devtools_io_context.h b/chromium/content/browser/devtools/devtools_io_context.h
index 67f91134205..11665be988a 100644
--- a/chromium/content/browser/devtools/devtools_io_context.h
+++ b/chromium/content/browser/devtools/devtools_io_context.h
@@ -13,15 +13,19 @@
#include "base/files/file.h"
#include "base/memory/ref_counted_delete_on_sequence.h"
#include "base/memory/ref_counted_memory.h"
+#include "base/memory/weak_ptr.h"
namespace base {
class SequencedTaskRunner;
}
+
namespace content {
+class ChromeBlobStorageContext;
+class StoragePartition;
class DevToolsIOContext {
public:
- class Stream : public base::RefCountedDeleteOnSequence<Stream> {
+ class ROStream : public base::RefCountedDeleteOnSequence<ROStream> {
public:
enum Status {
StatusSuccess,
@@ -30,42 +34,54 @@ class DevToolsIOContext {
};
using ReadCallback =
- base::OnceCallback<void(std::unique_ptr<std::string> data, int status)>;
-
- void Read(off_t position, size_t max_size, ReadCallback callback);
- void Append(std::unique_ptr<std::string> data);
- const std::string& handle() const { return handle_; }
-
- private:
- explicit Stream(base::SequencedTaskRunner* task_runner);
- ~Stream();
- friend class DevToolsIOContext;
- friend class base::RefCountedDeleteOnSequence<Stream>;
- friend class base::DeleteHelper<Stream>;
-
- void ReadOnFileSequence(off_t pos, size_t max_size, ReadCallback callback);
- void AppendOnFileSequence(std::unique_ptr<std::string> data);
- bool InitOnFileSequenceIfNeeded();
-
- const std::string handle_;
- base::File file_;
- scoped_refptr<base::SequencedTaskRunner> task_runner_;
- bool had_errors_;
- off_t last_read_pos_;
+ base::OnceCallback<void(std::unique_ptr<std::string> data,
+ bool base64_encoded,
+ int status)>;
+
+ virtual void Read(off_t position,
+ size_t max_size,
+ ReadCallback callback) = 0;
+ virtual void Close(bool invoke_pending_callbacks) = 0;
+
+ protected:
+ friend class base::DeleteHelper<content::DevToolsIOContext::ROStream>;
+ friend class base::RefCountedDeleteOnSequence<ROStream>;
+
+ explicit ROStream(scoped_refptr<base::SequencedTaskRunner> task_runner);
+ virtual ~ROStream() = 0;
+
+ DISALLOW_COPY_AND_ASSIGN(ROStream);
+ };
+
+ class RWStream : public ROStream {
+ public:
+ virtual void Append(std::unique_ptr<std::string> data) = 0;
+ virtual const std::string& handle() = 0;
+
+ protected:
+ explicit RWStream(scoped_refptr<base::SequencedTaskRunner> task_runner);
+ ~RWStream() override = 0;
+ DISALLOW_COPY_AND_ASSIGN(RWStream);
};
DevToolsIOContext();
~DevToolsIOContext();
- scoped_refptr<Stream> CreateTempFileBackedStream();
- scoped_refptr<Stream> GetByHandle(const std::string& handle);
+ scoped_refptr<RWStream> CreateTempFileBackedStream();
+ scoped_refptr<ROStream> GetByHandle(const std::string& handle);
+ scoped_refptr<ROStream> OpenBlob(ChromeBlobStorageContext*,
+ StoragePartition*,
+ const std::string& handle,
+ const std::string& uuid);
+
bool Close(const std::string& handle);
void DiscardAllStreams();
+ void OnBlobOpenComplete(const std::string& handle, bool success);
private:
- using StreamsMap = std::map<std::string, scoped_refptr<Stream>>;
+ using StreamsMap = std::map<std::string, scoped_refptr<ROStream>>;
StreamsMap streams_;
- scoped_refptr<base::SequencedTaskRunner> task_runner_;
+ base::WeakPtrFactory<DevToolsIOContext> weak_factory_;
};
} // namespace content
diff --git a/chromium/content/browser/devtools/devtools_manager.cc b/chromium/content/browser/devtools/devtools_manager.cc
index efd7bd71af2..886e59e10ab 100644
--- a/chromium/content/browser/devtools/devtools_manager.cc
+++ b/chromium/content/browser/devtools/devtools_manager.cc
@@ -9,7 +9,6 @@
#include "base/message_loop/message_loop.h"
#include "content/browser/devtools/devtools_agent_host_impl.h"
#include "content/browser/devtools/devtools_http_handler.h"
-#include "content/browser/loader/netlog_observer.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/devtools_socket_factory.h"
@@ -18,19 +17,16 @@ namespace content {
// static
void DevToolsAgentHost::StartRemoteDebuggingServer(
- std::unique_ptr<DevToolsSocketFactory> server_socket_factory,
- const std::string& frontend_url,
- const base::FilePath& active_port_output_directory,
- const base::FilePath& debug_frontend_dir,
- const std::string& product_name,
- const std::string& user_agent) {
+ std::unique_ptr<DevToolsSocketFactory> server_socket_factory,
+ const std::string& frontend_url,
+ const base::FilePath& active_port_output_directory,
+ const base::FilePath& debug_frontend_dir) {
DevToolsManager* manager = DevToolsManager::GetInstance();
if (!manager->delegate())
return;
manager->SetHttpHandler(base::WrapUnique(new DevToolsHttpHandler(
manager->delegate(), std::move(server_socket_factory), frontend_url,
- active_port_output_directory, debug_frontend_dir, product_name,
- user_agent)));
+ active_port_output_directory, debug_frontend_dir)));
}
// static
diff --git a/chromium/content/browser/devtools/devtools_manager_unittest.cc b/chromium/content/browser/devtools/devtools_manager_unittest.cc
index 22329b1207b..f243e4ec092 100644
--- a/chromium/content/browser/devtools/devtools_manager_unittest.cc
+++ b/chromium/content/browser/devtools/devtools_manager_unittest.cc
@@ -25,6 +25,7 @@
#include "content/public/browser/devtools_external_agent_proxy_delegate.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/common/browser_side_navigation_policy.h"
+#include "content/public/test/navigation_simulator.h"
#include "content/public/test/test_utils.h"
#include "content/test/test_content_browser_client.h"
#include "content/test/test_render_view_host.h"
@@ -179,13 +180,7 @@ TEST_F(DevToolsManagerTest, ReattachOnCancelPendingNavigation) {
return;
// Navigate to URL. First URL should use first RenderViewHost.
const GURL url("http://www.google.com");
- controller().LoadURL(
- url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
- int pending_id = controller().GetPendingEntry()->GetUniqueID();
- contents()->GetMainFrame()->PrepareForCommit();
- contents()->TestDidNavigate(contents()->GetMainFrame(), pending_id, true,
- url, ui::PAGE_TRANSITION_TYPED);
- contents()->GetMainFrame()->SimulateNavigationStop();
+ NavigationSimulator::NavigateAndCommitFromBrowser(web_contents(), url);
EXPECT_FALSE(contents()->CrossProcessNavigationPending());
TestDevToolsClientHost client_host;
@@ -194,20 +189,15 @@ TEST_F(DevToolsManagerTest, ReattachOnCancelPendingNavigation) {
// Navigate to new site which should get a new RenderViewHost.
const GURL url2("http://www.yahoo.com");
- controller().LoadURL(
- url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
- contents()->GetMainFrame()->PrepareForCommit();
+ auto navigation =
+ NavigationSimulator::CreateBrowserInitiated(url2, web_contents());
+ navigation->ReadyToCommit();
EXPECT_TRUE(contents()->CrossProcessNavigationPending());
EXPECT_EQ(client_host.agent_host(),
DevToolsAgentHost::GetOrCreateFor(web_contents()).get());
// Interrupt pending navigation and navigate back to the original site.
- controller().LoadURL(
- url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
- pending_id = controller().GetPendingEntry()->GetUniqueID();
- contents()->GetMainFrame()->PrepareForCommit();
- contents()->TestDidNavigate(contents()->GetMainFrame(), pending_id, false,
- url, ui::PAGE_TRANSITION_TYPED);
+ NavigationSimulator::NavigateAndCommitFromBrowser(web_contents(), url);
EXPECT_FALSE(contents()->CrossProcessNavigationPending());
EXPECT_EQ(client_host.agent_host(),
DevToolsAgentHost::GetOrCreateFor(web_contents()).get());
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 8db9c6923aa..85801e666ac 100644
--- a/chromium/content/browser/devtools/devtools_url_interceptor_request_job.cc
+++ b/chromium/content/browser/devtools/devtools_url_interceptor_request_job.cc
@@ -17,6 +17,7 @@
#include "net/cert/cert_status_flags.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_util.h"
+#include "net/traffic_annotation/network_traffic_annotation.h"
#include "net/url_request/url_request_context.h"
namespace content {
@@ -65,31 +66,51 @@ const char* ResourceTypeToString(ResourceType resource_type) {
}
}
+void UnregisterNavigationRequestOnUI(
+ base::WeakPtr<protocol::NetworkHandler> network_handler,
+ std::string interception_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ if (!network_handler)
+ return;
+ network_handler->InterceptedNavigationRequestFinished(interception_id);
+}
+
void SendRequestInterceptedEventOnUiThread(
base::WeakPtr<protocol::NetworkHandler> network_handler,
std::string interception_id,
+ GlobalRequestID global_request_id,
std::unique_ptr<protocol::Network::Request> network_request,
- std::string resource_type) {
+ ResourceType resource_type) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (!network_handler)
return;
+ bool is_navigation_request = resource_type == RESOURCE_TYPE_MAIN_FRAME ||
+ resource_type == RESOURCE_TYPE_SUB_FRAME;
+ if (is_navigation_request) {
+ network_handler->InterceptedNavigationRequest(global_request_id,
+ interception_id);
+ }
network_handler->frontend()->RequestIntercepted(
- interception_id, std::move(network_request), resource_type);
+ interception_id, std::move(network_request),
+ ResourceTypeToString(resource_type), is_navigation_request);
}
void SendRedirectInterceptedEventOnUiThread(
base::WeakPtr<protocol::NetworkHandler> network_handler,
std::string interception_id,
std::unique_ptr<protocol::Network::Request> network_request,
- std::string resource_type,
+ ResourceType resource_type,
std::unique_ptr<protocol::Object> headers_object,
int http_status_code,
std::string redirect_url) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (!network_handler)
return;
- return network_handler->frontend()->RequestIntercepted(
- interception_id, std::move(network_request), resource_type,
+ bool is_navigation_request = resource_type == RESOURCE_TYPE_MAIN_FRAME ||
+ resource_type == RESOURCE_TYPE_SUB_FRAME;
+ network_handler->frontend()->RequestIntercepted(
+ interception_id, std::move(network_request),
+ ResourceTypeToString(resource_type), is_navigation_request,
std::move(headers_object), http_status_code, redirect_url);
}
@@ -97,13 +118,16 @@ void SendAuthRequiredEventOnUiThread(
base::WeakPtr<protocol::NetworkHandler> network_handler,
std::string interception_id,
std::unique_ptr<protocol::Network::Request> network_request,
- std::string resource_type,
+ ResourceType resource_type,
std::unique_ptr<protocol::Network::AuthChallenge> auth_challenge) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (!network_handler)
return;
+ bool is_navigation_request = resource_type == RESOURCE_TYPE_MAIN_FRAME ||
+ resource_type == RESOURCE_TYPE_SUB_FRAME;
network_handler->frontend()->RequestIntercepted(
- interception_id, std::move(network_request), resource_type,
+ interception_id, std::move(network_request),
+ ResourceTypeToString(resource_type), is_navigation_request,
protocol::Maybe<protocol::Network::Headers>(), protocol::Maybe<int>(),
protocol::Maybe<protocol::String>(), std::move(auth_challenge));
}
@@ -190,10 +214,21 @@ DevToolsURLInterceptorRequestJob::DevToolsURLInterceptorRequestJob(
resource_type_(resource_type),
weak_ptr_factory_(this) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ if (const ResourceRequestInfo* info =
+ ResourceRequestInfo::ForRequest(original_request)) {
+ global_request_id_ = info->GetGlobalRequestID();
+ }
}
DevToolsURLInterceptorRequestJob::~DevToolsURLInterceptorRequestJob() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ bool is_navigation_request = resource_type_ == RESOURCE_TYPE_MAIN_FRAME ||
+ resource_type_ == RESOURCE_TYPE_SUB_FRAME;
+ if (is_navigation_request) {
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::BindOnce(UnregisterNavigationRequestOnUI,
+ network_handler_, interception_id_));
+ }
devtools_url_request_interceptor_state_->JobFinished(interception_id_);
}
@@ -219,9 +254,9 @@ void DevToolsURLInterceptorRequestJob::Start() {
protocol::NetworkHandler::CreateRequestFromURLRequest(request());
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(SendRequestInterceptedEventOnUiThread, network_handler_,
- interception_id_, base::Passed(&network_request),
- ResourceTypeToString(resource_type_)));
+ base::BindOnce(SendRequestInterceptedEventOnUiThread, network_handler_,
+ interception_id_, global_request_id_,
+ base::Passed(&network_request), resource_type_));
}
}
@@ -328,6 +363,13 @@ void DevToolsURLInterceptorRequestJob::OnAuthRequired(
DCHECK_EQ(request, sub_request_->request());
auth_info_ = auth_info;
+ if (!intercepting_requests_) {
+ // This should trigger default auth behavior.
+ // See comment in ProcessAuthRespose.
+ NotifyHeadersComplete();
+ return;
+ }
+
// This notification came from the sub requests URLRequest::Delegate and
// depending on what the protocol user wants us to do we must either cancel
// the auth, provide the credentials or proxy it the original
@@ -350,10 +392,9 @@ void DevToolsURLInterceptorRequestJob::OnAuthRequired(
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(SendAuthRequiredEventOnUiThread, network_handler_,
- interception_id_, base::Passed(&network_request),
- ResourceTypeToString(resource_type_),
- base::Passed(&auth_challenge)));
+ base::BindOnce(SendAuthRequiredEventOnUiThread, network_handler_,
+ interception_id_, base::Passed(&network_request),
+ resource_type_, base::Passed(&auth_challenge)));
}
void DevToolsURLInterceptorRequestJob::OnCertificateRequested(
@@ -443,11 +484,10 @@ void DevToolsURLInterceptorRequestJob::OnReceivedRedirect(
protocol::Object::fromValue(headers_dict.get(), nullptr);
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(SendRedirectInterceptedEventOnUiThread, network_handler_,
- interception_id_, base::Passed(&network_request),
- ResourceTypeToString(resource_type_),
- base::Passed(&headers_object), redirectinfo.status_code,
- redirectinfo.new_url.spec()));
+ base::BindOnce(SendRedirectInterceptedEventOnUiThread, network_handler_,
+ interception_id_, base::Passed(&network_request),
+ resource_type_, base::Passed(&headers_object),
+ redirectinfo.status_code, redirectinfo.new_url.spec()));
}
void DevToolsURLInterceptorRequestJob::StopIntercepting() {
@@ -455,12 +495,38 @@ void DevToolsURLInterceptorRequestJob::StopIntercepting() {
intercepting_requests_ = false;
// Allow the request to continue if we're waiting for user input.
- ProcessInterceptionRespose(
- base::MakeUnique<DevToolsURLRequestInterceptor::Modifications>(
- 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>()));
+ switch (waiting_for_user_response_) {
+ case WaitingForUserResponse::NOT_WAITING:
+ return;
+
+ case WaitingForUserResponse::WAITING_FOR_INTERCEPTION_RESPONSE:
+ ProcessInterceptionRespose(
+ base::MakeUnique<DevToolsURLRequestInterceptor::Modifications>(
+ 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>()));
+ return;
+
+ case WaitingForUserResponse::WAITING_FOR_AUTH_RESPONSE: {
+ std::unique_ptr<protocol::Network::AuthChallengeResponse> auth_response =
+ protocol::Network::AuthChallengeResponse::Create()
+ .SetResponse(protocol::Network::AuthChallengeResponse::
+ ResponseEnum::Default)
+ .Build();
+ ProcessAuthRespose(
+ base::MakeUnique<DevToolsURLRequestInterceptor::Modifications>(
+ 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)));
+ return;
+ }
+
+ default:
+ NOTREACHED();
+ return;
+ }
}
void DevToolsURLInterceptorRequestJob::ContinueInterceptedRequest(
@@ -669,9 +735,35 @@ DevToolsURLInterceptorRequestJob::SubRequest::SubRequest(
devtools_url_request_interceptor_state),
fetch_in_progress_(true) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ net::NetworkTrafficAnnotationTag traffic_annotation =
+ net::DefineNetworkTrafficAnnotation("devtools_interceptor", R"(
+ semantics {
+ sender: "Developer Tools"
+ description:
+ "When user is debugging a page, all actions resulting in a network "
+ "request are intercepted to enrich the debugging experience."
+ trigger:
+ "User triggers an action that requires network request (like "
+ "navigation, download, etc.) while debugging the page."
+ data:
+ "Any data that user action sends."
+ destination: WEBSITE
+ }
+ policy {
+ cookies_allowed: YES
+ cookies_store: "user"
+ setting:
+ "This feature cannot be disabled in settings, however it happens "
+ "only when user is debugging a page."
+ chrome_policy {
+ DeveloperToolsDisabled {
+ DeveloperToolsDisabled: true
+ }
+ }
+ })");
request_ = request_details.url_request_context->CreateRequest(
request_details.url, request_details.priority,
- devtools_interceptor_request_job_),
+ devtools_interceptor_request_job_, traffic_annotation),
request_->set_method(request_details.method);
request_->SetExtraRequestHeaders(request_details.extra_request_headers);
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 8ec210cdc3d..33d1a442737 100644
--- a/chromium/content/browser/devtools/devtools_url_interceptor_request_job.h
+++ b/chromium/content/browser/devtools/devtools_url_interceptor_request_job.h
@@ -10,6 +10,7 @@
#include "content/browser/devtools/devtools_url_request_interceptor.h"
#include "content/browser/devtools/protocol/network.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/global_request_id.h"
#include "content/public/common/resource_type.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_job.h"
@@ -199,6 +200,7 @@ class DevToolsURLInterceptorRequestJob : public net::URLRequestJob,
const base::WeakPtr<protocol::NetworkHandler> network_handler_;
const bool is_redirect_;
const ResourceType resource_type_;
+ GlobalRequestID global_request_id_;
base::WeakPtrFactory<DevToolsURLInterceptorRequestJob> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(DevToolsURLInterceptorRequestJob);
diff --git a/chromium/content/browser/devtools/devtools_url_request_interceptor.cc b/chromium/content/browser/devtools/devtools_url_request_interceptor.cc
index de4f70f1536..cdd117597e3 100644
--- a/chromium/content/browser/devtools/devtools_url_request_interceptor.cc
+++ b/chromium/content/browser/devtools/devtools_url_request_interceptor.cc
@@ -5,6 +5,7 @@
#include "content/browser/devtools/devtools_url_request_interceptor.h"
#include "base/memory/ptr_util.h"
+#include "base/strings/pattern.h"
#include "base/strings/stringprintf.h"
#include "base/supports_user_data.h"
#include "content/browser/devtools/devtools_agent_host_impl.h"
@@ -85,6 +86,12 @@ DevToolsURLRequestInterceptor::State::State() : next_id_(0) {}
DevToolsURLRequestInterceptor::State::~State() {}
+DevToolsURLRequestInterceptor::State::RenderFrameHostInfo::RenderFrameHostInfo(
+ RenderFrameHost* host)
+ : routing_id(host->GetRoutingID()),
+ frame_tree_node_id(host->GetFrameTreeNodeId()),
+ process_id(host->GetProcess()->GetID()) {}
+
void DevToolsURLRequestInterceptor::State::ContinueInterceptedRequest(
std::string interception_id,
std::unique_ptr<Modifications> modifications,
@@ -93,13 +100,13 @@ void DevToolsURLRequestInterceptor::State::ContinueInterceptedRequest(
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&DevToolsURLRequestInterceptor::State::
- ContinueInterceptedRequestOnIoThread,
- this, interception_id, base::Passed(std::move(modifications)),
- base::Passed(std::move(callback))));
+ base::BindOnce(
+ &DevToolsURLRequestInterceptor::State::ContinueInterceptedRequestOnIO,
+ this, interception_id, base::Passed(std::move(modifications)),
+ base::Passed(std::move(callback))));
}
-void DevToolsURLRequestInterceptor::State::ContinueInterceptedRequestOnIoThread(
+void DevToolsURLRequestInterceptor::State::ContinueInterceptedRequestOnIO(
std::string interception_id,
std::unique_ptr<Modifications> modifications,
std::unique_ptr<ContinueInterceptedRequestCallback> callback) {
@@ -123,6 +130,7 @@ DevToolsURLInterceptorRequestJob* DevToolsURLRequestInterceptor::State::
MaybeCreateDevToolsURLInterceptorRequestJob(
net::URLRequest* request,
net::NetworkDelegate* network_delegate) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
// Bail out if we're not intercepting anything.
if (intercepted_render_frames_.empty()) {
DCHECK(intercepted_frame_tree_nodes_.empty());
@@ -139,7 +147,7 @@ DevToolsURLInterceptorRequestJob* DevToolsURLRequestInterceptor::State::
return nullptr;
int child_id = resource_request_info->GetChildID();
int frame_tree_node_id = resource_request_info->GetFrameTreeNodeId();
- const InterceptedPage* intercepted_page;
+ WebContents* web_contents = nullptr;
if (frame_tree_node_id == -1) {
// |frame_tree_node_id| is not set for renderer side requests, fall back to
// the RenderFrameID.
@@ -148,26 +156,41 @@ DevToolsURLInterceptorRequestJob* DevToolsURLRequestInterceptor::State::
std::make_pair(render_frame_id, child_id));
if (find_it == intercepted_render_frames_.end())
return nullptr;
- intercepted_page = &find_it->second;
+ web_contents = find_it->second;
} else {
// |frame_tree_node_id| is set for browser side navigations, so use that
// because the RenderFrameID isn't known (neither is the ChildID).
const auto find_it = intercepted_frame_tree_nodes_.find(frame_tree_node_id);
if (find_it == intercepted_frame_tree_nodes_.end())
return nullptr;
- intercepted_page = &find_it->second;
+ web_contents = find_it->second;
}
+ DCHECK(intercepted_page_for_web_contents_.count(web_contents));
+
+ const InterceptedPage& intercepted_page =
+ *intercepted_page_for_web_contents_.find(web_contents)->second;
+
// We don't want to intercept our own sub requests.
if (sub_requests_.find(request) != sub_requests_.end())
return nullptr;
+ bool matchFound = false;
+ for (const std::string& pattern : intercepted_page.patterns) {
+ if (base::MatchPattern(request->url().spec(), pattern)) {
+ matchFound = true;
+ break;
+ }
+ }
+ if (!matchFound)
+ return nullptr;
+
bool is_redirect;
- std::string interception_id = GetIdForRequest(request, &is_redirect);
+ std::string interception_id = GetIdForRequestOnIO(request, &is_redirect);
DevToolsURLInterceptorRequestJob* job = new DevToolsURLInterceptorRequestJob(
- this, interception_id, request, network_delegate,
- intercepted_page->web_contents, intercepted_page->network_handler,
- is_redirect, resource_request_info->GetResourceType());
+ this, interception_id, request, network_delegate, web_contents,
+ intercepted_page.network_handler, is_redirect,
+ resource_request_info->GetResourceType());
interception_id_to_job_map_[interception_id] = job;
return job;
}
@@ -179,80 +202,108 @@ class DevToolsURLRequestInterceptor::State::InterceptedWebContentsObserver
WebContents* web_contents,
scoped_refptr<DevToolsURLRequestInterceptor::State> state,
base::WeakPtr<protocol::NetworkHandler> network_handler)
- : WebContentsObserver(web_contents),
- state_(state),
- network_handler_(network_handler) {
+ : WebContentsObserver(web_contents), state_(state) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
}
- void RenderFrameCreated(RenderFrameHost* render_frame_host) override {
+ void RenderFrameHostChanged(RenderFrameHost* old_host,
+ RenderFrameHost* new_host) override {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ base::Optional<DevToolsURLRequestInterceptor::State::RenderFrameHostInfo>
+ old_host_info;
+ DevToolsURLRequestInterceptor::State::RenderFrameHostInfo new_host_info(
+ new_host);
+ if (old_host) {
+ old_host_info.emplace(
+ DevToolsURLRequestInterceptor::State::RenderFrameHostInfo(old_host));
+ }
+
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::BindOnce(&DevToolsURLRequestInterceptor::State::
- StartInterceptingRequestsInternal,
- state_, render_frame_host->GetRoutingID(),
- render_frame_host->GetFrameTreeNodeId(),
- render_frame_host->GetProcess()->GetID(), web_contents(),
- network_handler_));
+ base::BindOnce(
+ &DevToolsURLRequestInterceptor::State::RenderFrameHostChangedOnIO,
+ state_, old_host_info, new_host_info, web_contents()));
}
- void RenderFrameDeleted(RenderFrameHost* render_frame_host) override {
+ void FrameDeleted(RenderFrameHost* render_frame_host) override {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::BindOnce(&DevToolsURLRequestInterceptor::State::
- StopInterceptingRequestsInternal,
- state_, render_frame_host->GetRoutingID(),
- render_frame_host->GetFrameTreeNodeId(),
- render_frame_host->GetProcess()->GetID()));
+ base::BindOnce(
+ &DevToolsURLRequestInterceptor::State::
+ StopInterceptingRequestsForHostInfoOnIO,
+ state_,
+ DevToolsURLRequestInterceptor::State::RenderFrameHostInfo(
+ render_frame_host)));
}
private:
scoped_refptr<DevToolsURLRequestInterceptor::State> state_;
- base::WeakPtr<protocol::NetworkHandler> network_handler_;
};
-void DevToolsURLRequestInterceptor::State::StartInterceptingRequestsInternal(
- int render_frame_id,
- int frame_tree_node_id,
- int process_id,
+void DevToolsURLRequestInterceptor::State::RenderFrameHostChangedOnIO(
+ base::Optional<RenderFrameHostInfo> old_host_info,
+ RenderFrameHostInfo new_host_info,
+ WebContents* web_contents) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ if (old_host_info)
+ StopInterceptingRequestsForHostInfoOnIO(old_host_info.value());
+ StartInterceptingRequestsForHostInfoOnIOInternal(new_host_info, web_contents);
+}
+
+void DevToolsURLRequestInterceptor::State::
+ StartInterceptingRequestsForHostInfoOnIOInternal(
+ RenderFrameHostInfo host_info,
+ WebContents* web_contents) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(intercepted_page_for_web_contents_.count(web_contents));
+
+ // We can assume that if there are frames already in the map they are in the
+ // same web_contents as before.
+ intercepted_render_frames_[std::make_pair(
+ host_info.routing_id, host_info.process_id)] = web_contents;
+ intercepted_frame_tree_nodes_[host_info.frame_tree_node_id] = web_contents;
+}
+
+void DevToolsURLRequestInterceptor::State::StartInterceptingRequestsOnIO(
+ std::vector<RenderFrameHostInfo> host_info_list,
WebContents* web_contents,
- base::WeakPtr<protocol::NetworkHandler> network_handler) {
+ std::unique_ptr<InterceptedPage> interceptedPage) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- intercepted_render_frames_.emplace(
- std::piecewise_construct,
- std::forward_as_tuple(render_frame_id, process_id),
- std::forward_as_tuple(web_contents, network_handler));
- intercepted_frame_tree_nodes_.emplace(
- std::piecewise_construct, std::forward_as_tuple(frame_tree_node_id),
- std::forward_as_tuple(web_contents, network_handler));
+
+ intercepted_page_for_web_contents_[web_contents] = std::move(interceptedPage);
+ for (const auto host_info : host_info_list)
+ StartInterceptingRequestsForHostInfoOnIOInternal(host_info, web_contents);
}
-void DevToolsURLRequestInterceptor::State::StopInterceptingRequestsInternal(
- int render_frame_id,
- int frame_tree_node_id,
- int process_id) {
+void DevToolsURLRequestInterceptor::State::
+ StopInterceptingRequestsForHostInfoOnIO(RenderFrameHostInfo host_info) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- intercepted_render_frames_.erase(std::make_pair(render_frame_id, process_id));
- intercepted_frame_tree_nodes_.erase(frame_tree_node_id);
+ // Since Devtools has not unregistered to the web_contents, we do not remove
+ // it from the map.
+ intercepted_render_frames_.erase(
+ std::make_pair(host_info.routing_id, host_info.process_id));
+ intercepted_frame_tree_nodes_.erase(host_info.frame_tree_node_id);
}
void DevToolsURLRequestInterceptor::State::StartInterceptingRequests(
WebContents* web_contents,
- base::WeakPtr<protocol::NetworkHandler> network_handler) {
+ base::WeakPtr<protocol::NetworkHandler> network_handler,
+ std::vector<std::string> patterns) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- // WebContents methods are UI thread only.
- for (RenderFrameHost* render_frame_host : web_contents->GetAllFrames()) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&DevToolsURLRequestInterceptor::State::
- StartInterceptingRequestsInternal,
- this, render_frame_host->GetRoutingID(),
- render_frame_host->GetFrameTreeNodeId(),
- render_frame_host->GetProcess()->GetID(), web_contents,
- network_handler));
- }
+
+ std::vector<RenderFrameHostInfo> host_info_list;
+ for (RenderFrameHost* render_frame_host : web_contents->GetAllFrames())
+ host_info_list.push_back(RenderFrameHostInfo(render_frame_host));
+
+ std::unique_ptr<InterceptedPage> intercepted_page(
+ new InterceptedPage(network_handler, std::move(patterns)));
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(
+ &DevToolsURLRequestInterceptor::State::StartInterceptingRequestsOnIO,
+ this, std::move(host_info_list), web_contents,
+ std::move(intercepted_page)));
// Listen for future updates.
observers_.emplace(web_contents,
@@ -264,35 +315,41 @@ void DevToolsURLRequestInterceptor::State::StopInterceptingRequests(
WebContents* web_contents) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
observers_.erase(web_contents);
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::BindOnce(&DevToolsURLRequestInterceptor::State::
- StopInterceptingRequestsOnIoThread,
- this, web_contents));
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(
+ &DevToolsURLRequestInterceptor::State::StopInterceptingRequestsOnIO,
+ this, web_contents));
}
-void DevToolsURLRequestInterceptor::State::StopInterceptingRequestsOnIoThread(
+void DevToolsURLRequestInterceptor::State::StopInterceptingRequestsOnIO(
WebContents* web_contents) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
// Remove any intercepted render frames associated with |web_contents|.
- base::flat_map<std::pair<int, int>, InterceptedPage>
+ base::flat_map<std::pair<int, int>, WebContents*>
remaining_intercepted_render_frames;
- for (const auto pair : intercepted_render_frames_) {
- if (pair.second.web_contents == web_contents)
+ for (const auto& pair : intercepted_render_frames_) {
+ DCHECK(intercepted_page_for_web_contents_.count(pair.second));
+ if (pair.second == web_contents)
continue;
remaining_intercepted_render_frames.insert(pair);
}
std::swap(remaining_intercepted_render_frames, intercepted_render_frames_);
// Remove any intercepted frame tree nodes associated with |web_contents|.
- base::flat_map<int, InterceptedPage> remaining_intercepted_frame_tree_nodes;
- for (const auto pair : intercepted_frame_tree_nodes_) {
- if (pair.second.web_contents == web_contents)
+ base::flat_map<FrameTreeNodeId, WebContents*>
+ remaining_intercepted_frame_tree_nodes;
+ for (const auto& pair : intercepted_frame_tree_nodes_) {
+ DCHECK(intercepted_page_for_web_contents_.count(pair.second));
+ if (pair.second == web_contents)
continue;
remaining_intercepted_frame_tree_nodes.insert(pair);
}
std::swap(remaining_intercepted_frame_tree_nodes,
intercepted_frame_tree_nodes_);
+ intercepted_page_for_web_contents_.erase(web_contents);
+
// Tell any jobs associated with |web_contents| to stop intercepting.
for (const auto pair : interception_id_to_job_map_) {
if (pair.second->web_contents() == web_contents)
@@ -321,7 +378,7 @@ void DevToolsURLRequestInterceptor::State::ExpectRequestAfterRedirect(
expected_redirects_[request] = id;
}
-std::string DevToolsURLRequestInterceptor::State::GetIdForRequest(
+std::string DevToolsURLRequestInterceptor::State::GetIdForRequestOnIO(
const net::URLRequest* request,
bool* is_redirect) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -355,9 +412,12 @@ void DevToolsURLRequestInterceptor::State::JobFinished(
DevToolsURLRequestInterceptor*
DevToolsURLRequestInterceptor::FromBrowserContext(BrowserContext* context) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- return static_cast<DevToolsURLRequestInterceptorUserData*>(
- context->GetUserData(kDevToolsURLRequestInterceptorKeyName))
- ->devtools_url_request_interceptor();
+ auto* interceptor_user_data =
+ static_cast<DevToolsURLRequestInterceptorUserData*>(
+ context->GetUserData(kDevToolsURLRequestInterceptorKeyName));
+ if (!interceptor_user_data)
+ return nullptr;
+ return interceptor_user_data->devtools_url_request_interceptor();
}
DevToolsURLRequestInterceptor::Modifications::Modifications(
@@ -379,16 +439,10 @@ DevToolsURLRequestInterceptor::Modifications::Modifications(
DevToolsURLRequestInterceptor::Modifications::~Modifications() {}
-DevToolsURLRequestInterceptor::State::InterceptedPage::InterceptedPage()
- : web_contents(nullptr) {}
-
-DevToolsURLRequestInterceptor::State::InterceptedPage::InterceptedPage(
- const InterceptedPage& other) = default;
-
DevToolsURLRequestInterceptor::State::InterceptedPage::InterceptedPage(
- WebContents* web_contents,
- base::WeakPtr<protocol::NetworkHandler> network_handler)
- : web_contents(web_contents), network_handler(network_handler) {}
+ base::WeakPtr<protocol::NetworkHandler> network_handler,
+ std::vector<std::string> patterns)
+ : network_handler(network_handler), patterns(std::move(patterns)) {}
DevToolsURLRequestInterceptor::State::InterceptedPage::~InterceptedPage() =
default;
diff --git a/chromium/content/browser/devtools/devtools_url_request_interceptor.h b/chromium/content/browser/devtools/devtools_url_request_interceptor.h
index e209149ee2e..6aff05affb1 100644
--- a/chromium/content/browser/devtools/devtools_url_request_interceptor.h
+++ b/chromium/content/browser/devtools/devtools_url_request_interceptor.h
@@ -24,6 +24,7 @@ class NetworkHandler;
class BrowserContext;
class DevToolsURLInterceptorRequestJob;
class WebContents;
+class RenderFrameHost;
// An interceptor that creates DevToolsURLInterceptorRequestJobs for requests
// from pages where interception has been enabled via
@@ -85,6 +86,7 @@ class DevToolsURLRequestInterceptor : public net::URLRequestInterceptor {
public:
State();
+ using FrameTreeNodeId = int;
using ContinueInterceptedRequestCallback =
protocol::Network::Backend::ContinueInterceptedRequestCallback;
@@ -104,7 +106,8 @@ class DevToolsURLRequestInterceptor : public net::URLRequestInterceptor {
// Must be called on the UI thread.
void StartInterceptingRequests(
WebContents* web_contents,
- base::WeakPtr<protocol::NetworkHandler> network_handler);
+ base::WeakPtr<protocol::NetworkHandler> network_handler,
+ std::vector<std::string> patterns);
// Must be called on the UI thread.
void StopInterceptingRequests(WebContents* web_contents);
@@ -126,47 +129,63 @@ class DevToolsURLRequestInterceptor : public net::URLRequestInterceptor {
private:
class InterceptedWebContentsObserver;
+ struct RenderFrameHostInfo {
+ explicit RenderFrameHostInfo(RenderFrameHost* host);
+ const int routing_id;
+ const FrameTreeNodeId frame_tree_node_id;
+ const int process_id;
+ };
+
struct InterceptedPage {
- InterceptedPage();
- InterceptedPage(const InterceptedPage& other);
- InterceptedPage(WebContents* web_contents,
- base::WeakPtr<protocol::NetworkHandler> network_handler);
+ InterceptedPage(base::WeakPtr<protocol::NetworkHandler> network_handler,
+ std::vector<std::string> patterns);
~InterceptedPage();
- WebContents* web_contents;
- base::WeakPtr<protocol::NetworkHandler> network_handler;
+ const base::WeakPtr<protocol::NetworkHandler> network_handler;
+ const std::vector<std::string> patterns;
};
- void ContinueInterceptedRequestOnIoThread(
+ void ContinueInterceptedRequestOnIO(
std::string interception_id,
std::unique_ptr<DevToolsURLRequestInterceptor::Modifications>
modifications,
std::unique_ptr<ContinueInterceptedRequestCallback> callback);
- void StartInterceptingRequestsInternal(
- int render_frame_id,
- int frame_tree_node_id,
- int process_id,
+ void RenderFrameHostChangedOnIO(
+ base::Optional<RenderFrameHostInfo> old_host_info,
+ RenderFrameHostInfo new_host_info,
+ WebContents* web_contents);
+
+ void StartInterceptingRequestsForHostInfoOnIOInternal(
+ RenderFrameHostInfo host_info,
+ WebContents* web_contents);
+
+ void StartInterceptingRequestsOnIO(
+ std::vector<RenderFrameHostInfo> host_info_list,
WebContents* web_contents,
- base::WeakPtr<protocol::NetworkHandler> network_handler);
+ std::unique_ptr<InterceptedPage> interceptedPage);
- void StopInterceptingRequestsInternal(int render_frame_id,
- int frame_tree_node_id,
- int process_id);
- void StopInterceptingRequestsOnIoThread(WebContents* web_contents);
+ void StopInterceptingRequestsForHostInfoOnIO(RenderFrameHostInfo host_info);
+ void StopInterceptingRequestsOnIO(WebContents* web_contents);
- std::string GetIdForRequest(const net::URLRequest* request,
- bool* is_redirect);
+ std::string GetIdForRequestOnIO(const net::URLRequest* request,
+ bool* is_redirect);
// Returns a WeakPtr to the DevToolsURLInterceptorRequestJob corresponding
// to |interception_id|. Must be called on the IO thread.
DevToolsURLInterceptorRequestJob* GetJob(
const std::string& interception_id) const;
- base::flat_map<std::pair<int, int>, InterceptedPage>
+ // |intercepted_page_for_web_contents_| should always have an entry if
+ // |intercepted_render_frames_| or |intercepted_frame_tree_nodes_| have
+ // values. Entries in |intercepted_page_for_web_contents_| only get removed
+ // if WebContents goes away.
+ base::flat_map<WebContents*, std::unique_ptr<InterceptedPage>>
+ intercepted_page_for_web_contents_;
+ // First item is routing_id second is process_id.
+ base::flat_map<std::pair<int, int>, WebContents*>
intercepted_render_frames_;
-
- base::flat_map<int, InterceptedPage> intercepted_frame_tree_nodes_;
+ base::flat_map<FrameTreeNodeId, WebContents*> intercepted_frame_tree_nodes_;
// UI thread only.
base::flat_map<WebContents*,
diff --git a/chromium/content/browser/devtools/page_navigation_throttle.cc b/chromium/content/browser/devtools/page_navigation_throttle.cc
deleted file mode 100644
index bd73a5c63d3..00000000000
--- a/chromium/content/browser/devtools/page_navigation_throttle.cc
+++ /dev/null
@@ -1,83 +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/devtools/page_navigation_throttle.h"
-
-#include "base/strings/stringprintf.h"
-#include "content/browser/devtools/protocol/page_handler.h"
-#include "content/public/browser/navigation_handle.h"
-#include "content/public/browser/render_process_host.h"
-#include "content/public/browser/web_contents.h"
-
-namespace content {
-
-PageNavigationThrottle::PageNavigationThrottle(
- base::WeakPtr<protocol::PageHandler> page_handler,
- int navigation_id,
- content::NavigationHandle* navigation_handle)
- : content::NavigationThrottle(navigation_handle),
- navigation_id_(navigation_id),
- page_handler_(page_handler),
- navigation_deferred_(false) {}
-
-PageNavigationThrottle::~PageNavigationThrottle() {
- if (page_handler_)
- page_handler_->OnPageNavigationThrottleDisposed(navigation_id_);
-}
-
-NavigationThrottle::ThrottleCheckResult
-PageNavigationThrottle::WillStartRequest() {
- if (!page_handler_)
- return ThrottleCheckResult::PROCEED;
- navigation_deferred_ = true;
- page_handler_->NavigationRequested(this);
- return ThrottleCheckResult::DEFER;
-}
-
-NavigationThrottle::ThrottleCheckResult
-PageNavigationThrottle::WillRedirectRequest() {
- if (!page_handler_)
- return ThrottleCheckResult::PROCEED;
- navigation_deferred_ = true;
- page_handler_->NavigationRequested(this);
- return ThrottleCheckResult::DEFER;
-}
-
-const char* PageNavigationThrottle::GetNameForLogging() {
- return "PageNavigationThrottle";
-}
-
-void PageNavigationThrottle::AlwaysProceed() {
- // Makes WillStartRequest and WillRedirectRequest always return
- // ThrottleCheckResult::PROCEED.
- page_handler_.reset();
- Resume();
-}
-
-// Resumes a deferred navigation request. Does nothing if a response isn't
-// expected.
-void PageNavigationThrottle::Resume() {
- if (!navigation_deferred_)
- return;
- navigation_deferred_ = false;
- content::NavigationThrottle::Resume();
-
- // Do not add code after this as the PageNavigationThrottle may be deleted by
- // the line above.
-}
-
-// Cancels a deferred navigation request. Does nothing if a response isn't
-// expected.
-void PageNavigationThrottle::CancelDeferredNavigation(
- NavigationThrottle::ThrottleCheckResult result) {
- if (!navigation_deferred_)
- return;
- navigation_deferred_ = false;
- content::NavigationThrottle::CancelDeferredNavigation(result);
-
- // Do not add code after this as the PageNavigationThrottle may be deleted by
- // the line above.
-}
-
-} // namespace content
diff --git a/chromium/content/browser/devtools/page_navigation_throttle.h b/chromium/content/browser/devtools/page_navigation_throttle.h
deleted file mode 100644
index 6fd23f0ae98..00000000000
--- a/chromium/content/browser/devtools/page_navigation_throttle.h
+++ /dev/null
@@ -1,56 +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_DEVTOOLS_PAGE_NAVIGATION_THROTTLE_H_
-#define CONTENT_BROWSER_DEVTOOLS_PAGE_NAVIGATION_THROTTLE_H_
-
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "content/public/browser/navigation_throttle.h"
-
-namespace content {
-namespace protocol {
-class PageHandler;
-} // namespace protocol
-
-// Used to allow the DevTools client to optionally cancel navigations via the
-// Page.setControlNavigations and Page.processNavigation commands.
-class PageNavigationThrottle : public content::NavigationThrottle {
- public:
- PageNavigationThrottle(base::WeakPtr<protocol::PageHandler> page_handler,
- int navigation_id,
- content::NavigationHandle* navigation_handle);
- ~PageNavigationThrottle() override;
-
- // content::NavigationThrottle implementation:
- NavigationThrottle::ThrottleCheckResult WillStartRequest() override;
- NavigationThrottle::ThrottleCheckResult WillRedirectRequest() override;
- const char* GetNameForLogging() override;
- void Resume() override;
- void CancelDeferredNavigation(
- NavigationThrottle::ThrottleCheckResult result) override;
-
- int navigation_id() const { return navigation_id_; }
-
- // Tells the PageNavigationThrottle to not throttle anything!
- void AlwaysProceed();
-
- private:
- // An opaque ID assigned by the PageHandler, used to allow the protocol client
- // to refer to this navigation throttle.
- const int navigation_id_;
-
- // The PageHandler that this navigation throttle is associated with.
- base::WeakPtr<protocol::PageHandler> page_handler_;
-
- // Whether or not a navigation was deferred. If deferred we expect a
- // subsequent call to AlwaysProceed, Resume or CancelNavigationIfDeferred.
- bool navigation_deferred_;
-
- DISALLOW_COPY_AND_ASSIGN(PageNavigationThrottle);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_DEVTOOLS_PAGE_NAVIGATION_THROTTLE_H_
diff --git a/chromium/content/browser/devtools/protocol/browser_handler.cc b/chromium/content/browser/devtools/protocol/browser_handler.cc
new file mode 100644
index 00000000000..b5fd5f4b692
--- /dev/null
+++ b/chromium/content/browser/devtools/protocol/browser_handler.cc
@@ -0,0 +1,38 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/devtools/protocol/browser_handler.h"
+
+#include "content/public/browser/devtools_agent_host.h"
+#include "content/public/common/content_client.h"
+#include "content/public/common/user_agent.h"
+#include "v8/include/v8-version-string.h"
+
+namespace content {
+namespace protocol {
+
+BrowserHandler::BrowserHandler()
+ : DevToolsDomainHandler(Browser::Metainfo::domainName) {}
+
+BrowserHandler::~BrowserHandler() {}
+
+void BrowserHandler::Wire(UberDispatcher* dispatcher) {
+ Browser::Dispatcher::wire(dispatcher, this);
+}
+
+Response BrowserHandler::GetVersion(std::string* protocol_version,
+ std::string* product,
+ std::string* revision,
+ std::string* user_agent,
+ std::string* js_version) {
+ *protocol_version = DevToolsAgentHost::GetProtocolVersion();
+ *revision = GetWebKitRevision();
+ *product = GetContentClient()->GetProduct();
+ *user_agent = GetContentClient()->GetUserAgent();
+ *js_version = V8_VERSION_STRING;
+ 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
new file mode 100644
index 00000000000..fe109fe1248
--- /dev/null
+++ b/chromium/content/browser/devtools/protocol/browser_handler.h
@@ -0,0 +1,37 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_DEVTOOLS_PROTOCOL_BROWSER_HANDLER_H_
+#define CONTENT_BROWSER_DEVTOOLS_PROTOCOL_BROWSER_HANDLER_H_
+
+#include "base/macros.h"
+#include "content/browser/devtools/protocol/browser.h"
+#include "content/browser/devtools/protocol/devtools_domain_handler.h"
+
+namespace content {
+
+namespace protocol {
+
+class BrowserHandler : public DevToolsDomainHandler, public Browser::Backend {
+ public:
+ BrowserHandler();
+ ~BrowserHandler() override;
+
+ void Wire(UberDispatcher* dispatcher) override;
+
+ // Protocol methods.
+ Response GetVersion(std::string* protocol_version,
+ std::string* product,
+ std::string* revision,
+ std::string* user_agent,
+ std::string* js_version) override;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(BrowserHandler);
+};
+
+} // namespace protocol
+} // namespace content
+
+#endif // CONTENT_BROWSER_DEVTOOLS_PROTOCOL_BROWSER_HANDLER_H_
diff --git a/chromium/content/browser/devtools/protocol/devtools_download_manager_delegate.cc b/chromium/content/browser/devtools/protocol/devtools_download_manager_delegate.cc
new file mode 100644
index 00000000000..cb057ac0474
--- /dev/null
+++ b/chromium/content/browser/devtools/protocol/devtools_download_manager_delegate.cc
@@ -0,0 +1,186 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/devtools/protocol/devtools_download_manager_delegate.h"
+
+#include "base/bind.h"
+#include "base/files/file_util.h"
+#include "base/task_scheduler/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_thread.h"
+#include "content/public/browser/download_manager.h"
+#include "net/base/filename_util.h"
+
+namespace content {
+
+class WebContents;
+
+namespace protocol {
+
+namespace {
+
+DevToolsDownloadManagerDelegate* g_devtools_manager_delegate = nullptr;
+
+} // namespace
+
+DevToolsDownloadManagerDelegate::DevToolsDownloadManagerDelegate()
+ : download_manager_(nullptr), proxy_download_delegate_(nullptr) {
+ g_devtools_manager_delegate = this;
+}
+
+// static
+DevToolsDownloadManagerDelegate*
+DevToolsDownloadManagerDelegate::GetInstance() {
+ if (!g_devtools_manager_delegate)
+ new DevToolsDownloadManagerDelegate();
+
+ return g_devtools_manager_delegate;
+}
+
+DevToolsDownloadManagerDelegate::~DevToolsDownloadManagerDelegate() {
+ // Reset the proxy delegate.
+ DevToolsDownloadManagerDelegate* download_delegate = GetInstance();
+ download_delegate->download_manager_->SetDelegate(
+ download_delegate->proxy_download_delegate_);
+ download_delegate->download_manager_ = nullptr;
+
+ if (download_manager_) {
+ download_manager_->SetDelegate(proxy_download_delegate_);
+ download_manager_ = nullptr;
+ }
+ g_devtools_manager_delegate = nullptr;
+}
+
+scoped_refptr<DevToolsDownloadManagerDelegate>
+DevToolsDownloadManagerDelegate::TakeOver(
+ content::DownloadManager* download_manager) {
+ CHECK(download_manager);
+ DevToolsDownloadManagerDelegate* download_delegate = GetInstance();
+ if (download_manager == download_delegate->download_manager_)
+ return download_delegate;
+ // Recover state of previously owned download manager.
+ if (download_delegate->download_manager_)
+ download_delegate->download_manager_->SetDelegate(
+ download_delegate->proxy_download_delegate_);
+ download_delegate->proxy_download_delegate_ = download_manager->GetDelegate();
+ // Take over delegate in download_manager.
+ download_delegate->download_manager_ = download_manager;
+ download_manager->SetDelegate(download_delegate);
+ return download_delegate;
+}
+
+void DevToolsDownloadManagerDelegate::Shutdown() {
+ if (proxy_download_delegate_)
+ proxy_download_delegate_->Shutdown();
+ // Revoke any pending callbacks. download_manager_ et. al. are no longer safe
+ // to access after this point.
+ download_manager_ = nullptr;
+}
+
+bool DevToolsDownloadManagerDelegate::DetermineDownloadTarget(
+ content::DownloadItem* item,
+ const content::DownloadTargetCallback& callback) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+ DevToolsDownloadManagerHelper* download_helper =
+ DevToolsDownloadManagerHelper::FromWebContents(item->GetWebContents());
+
+ // Check if we should failback to delegate.
+ if (proxy_download_delegate_ && !download_helper)
+ return proxy_download_delegate_->DetermineDownloadTarget(item, callback);
+
+ // In headless mode there's no no proxy delegate set, so if there's no
+ // information associated to the download, we deny it by default.
+ if (!download_helper ||
+ download_helper->GetDownloadBehavior() !=
+ DevToolsDownloadManagerHelper::DownloadBehavior::ALLOW) {
+ base::FilePath empty_path = base::FilePath();
+ callback.Run(empty_path,
+ content::DownloadItem::TARGET_DISPOSITION_OVERWRITE,
+ content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, empty_path,
+ content::DOWNLOAD_INTERRUPT_REASON_FILE_BLOCKED);
+ return true;
+ }
+
+ base::FilePath download_path =
+ base::FilePath::FromUTF8Unsafe(download_helper->GetDownloadPath());
+
+ FilenameDeterminedCallback filename_determined_callback =
+ base::Bind(&DevToolsDownloadManagerDelegate::OnDownloadPathGenerated,
+ base::Unretained(this), item->GetId(), callback);
+
+ PostTaskWithTraits(
+ FROM_HERE,
+ {base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN,
+ base::TaskPriority::USER_VISIBLE},
+ base::BindOnce(&DevToolsDownloadManagerDelegate::GenerateFilename,
+ item->GetURL(), item->GetContentDisposition(),
+ item->GetSuggestedFilename(), item->GetMimeType(),
+ download_path, filename_determined_callback));
+ return true;
+}
+
+bool DevToolsDownloadManagerDelegate::ShouldOpenDownload(
+ content::DownloadItem* item,
+ const content::DownloadOpenDelayedCallback& callback) {
+ DevToolsDownloadManagerHelper* download_helper =
+ DevToolsDownloadManagerHelper::FromWebContents(item->GetWebContents());
+
+ if (download_helper)
+ return true;
+ if (proxy_download_delegate_)
+ return proxy_download_delegate_->ShouldOpenDownload(item, callback);
+ return false;
+}
+
+void DevToolsDownloadManagerDelegate::GetNextId(
+ const content::DownloadIdCallback& callback) {
+ static uint32_t next_id = content::DownloadItem::kInvalidId + 1;
+ // Be sure to follow the proxy delegate Ids to avoid compatibility problems
+ // with the download manager.
+ if (proxy_download_delegate_) {
+ proxy_download_delegate_->GetNextId(callback);
+ return;
+ }
+ callback.Run(next_id++);
+}
+
+// static
+void DevToolsDownloadManagerDelegate::GenerateFilename(
+ const GURL& url,
+ const std::string& content_disposition,
+ const std::string& suggested_filename,
+ const std::string& mime_type,
+ const base::FilePath& suggested_directory,
+ const FilenameDeterminedCallback& callback) {
+ base::ThreadRestrictions::AssertIOAllowed();
+ base::FilePath generated_name =
+ net::GenerateFileName(url, content_disposition, std::string(),
+ suggested_filename, mime_type, "download");
+
+ if (!base::PathExists(suggested_directory))
+ 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));
+}
+
+void DevToolsDownloadManagerDelegate::OnDownloadPathGenerated(
+ uint32_t download_id,
+ const content::DownloadTargetCallback& callback,
+ const base::FilePath& suggested_path) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+ callback.Run(suggested_path,
+ content::DownloadItem::TARGET_DISPOSITION_OVERWRITE,
+ content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
+ suggested_path.AddExtension(FILE_PATH_LITERAL(".crdownload")),
+ content::DOWNLOAD_INTERRUPT_REASON_NONE);
+}
+
+} // namespace protocol
+} // namespace content
diff --git a/chromium/content/browser/devtools/protocol/devtools_download_manager_delegate.h b/chromium/content/browser/devtools/protocol/devtools_download_manager_delegate.h
new file mode 100644
index 00000000000..bea863a14ae
--- /dev/null
+++ b/chromium/content/browser/devtools/protocol/devtools_download_manager_delegate.h
@@ -0,0 +1,80 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_DEVTOOLS_PROTOCOL_DEVTOOLS_DOWNLOAD_MANAGER_DELEGATE_H_
+#define CONTENT_BROWSER_DEVTOOLS_PROTOCOL_DEVTOOLS_DOWNLOAD_MANAGER_DELEGATE_H_
+
+#include <stdint.h>
+#include <string>
+
+#include "base/callback_forward.h"
+#include "base/compiler_specific.h"
+#include "base/files/file_util.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/singleton.h"
+#include "base/memory/weak_ptr.h"
+#include "content/common/content_export.h"
+#include "content/public/browser/download_manager_delegate.h"
+
+namespace content {
+
+class DownloadManager;
+
+namespace protocol {
+
+class CONTENT_EXPORT DevToolsDownloadManagerDelegate
+ : public content::DownloadManagerDelegate,
+ public base::RefCounted<DevToolsDownloadManagerDelegate> {
+ public:
+ // Takes over a |download_manager|. If the |download_manager| owns a
+ // |DownloadManagerDelegate| it will be stored as a proxy delegate.
+ // When the proxy is set, this delegate will use the proxy's |GetNextId|
+ // function to ensure compatibility. It will also call its |Shutdown| method
+ // when sutting down and it will fallback to the proxy if it cannot find any
+ // DevToolsDownloadManagerHelper associated with the download.
+ static scoped_refptr<DevToolsDownloadManagerDelegate> TakeOver(
+ content::DownloadManager* download_manager);
+
+ // DownloadManagerDelegate overrides.
+ void Shutdown() override;
+ bool DetermineDownloadTarget(
+ content::DownloadItem* download,
+ const content::DownloadTargetCallback& callback) override;
+ bool ShouldOpenDownload(
+ content::DownloadItem* item,
+ const content::DownloadOpenDelayedCallback& callback) override;
+ void GetNextId(const content::DownloadIdCallback& callback) override;
+
+ private:
+ friend class base::RefCounted<DevToolsDownloadManagerDelegate>;
+
+ DevToolsDownloadManagerDelegate();
+ static DevToolsDownloadManagerDelegate* GetInstance();
+ ~DevToolsDownloadManagerDelegate() override;
+
+ typedef base::Callback<void(const base::FilePath&)>
+ FilenameDeterminedCallback;
+
+ static void GenerateFilename(const GURL& url,
+ const std::string& content_disposition,
+ const std::string& suggested_filename,
+ const std::string& mime_type,
+ const base::FilePath& suggested_directory,
+ const FilenameDeterminedCallback& callback);
+
+ void OnDownloadPathGenerated(uint32_t download_id,
+ const content::DownloadTargetCallback& callback,
+ const base::FilePath& suggested_path);
+
+ content::DownloadManager* download_manager_;
+ content::DownloadManagerDelegate* proxy_download_delegate_;
+
+ DISALLOW_COPY_AND_ASSIGN(DevToolsDownloadManagerDelegate);
+};
+
+} // namespace protocol
+} // namespace content
+
+#endif // CONTENT_BROWSER_DEVTOOLS_PROTOCOL_DEVTOOLS_DOWNLOAD_MANAGER_DELEGATE_H_
diff --git a/chromium/content/browser/devtools/protocol/devtools_download_manager_helper.cc b/chromium/content/browser/devtools/protocol/devtools_download_manager_helper.cc
new file mode 100644
index 00000000000..d1b63f6f571
--- /dev/null
+++ b/chromium/content/browser/devtools/protocol/devtools_download_manager_helper.cc
@@ -0,0 +1,47 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/devtools/protocol/devtools_download_manager_helper.h"
+
+#include "base/bind.h"
+
+DEFINE_WEB_CONTENTS_USER_DATA_KEY(
+ content::protocol::DevToolsDownloadManagerHelper);
+
+namespace content {
+namespace protocol {
+
+DevToolsDownloadManagerHelper::DevToolsDownloadManagerHelper(
+ content::WebContents* contents)
+ : download_behavior_(
+ DevToolsDownloadManagerHelper::DownloadBehavior::DENY) {}
+
+DevToolsDownloadManagerHelper::~DevToolsDownloadManagerHelper() {}
+
+// static
+void DevToolsDownloadManagerHelper::RemoveFromWebContents(
+ content::WebContents* web_contents) {
+ web_contents->RemoveUserData(UserDataKey());
+}
+
+DevToolsDownloadManagerHelper::DownloadBehavior
+DevToolsDownloadManagerHelper::GetDownloadBehavior() {
+ return download_behavior_;
+}
+
+void DevToolsDownloadManagerHelper::SetDownloadBehavior(
+ DevToolsDownloadManagerHelper::DownloadBehavior behavior) {
+ download_behavior_ = behavior;
+}
+
+std::string DevToolsDownloadManagerHelper::GetDownloadPath() {
+ return download_path_;
+}
+
+void DevToolsDownloadManagerHelper::SetDownloadPath(const std::string& path) {
+ download_path_ = path;
+}
+
+} // namespace protocol
+} // namespace content
diff --git a/chromium/content/browser/devtools/protocol/devtools_download_manager_helper.h b/chromium/content/browser/devtools/protocol/devtools_download_manager_helper.h
new file mode 100644
index 00000000000..2b07614f7a5
--- /dev/null
+++ b/chromium/content/browser/devtools/protocol/devtools_download_manager_helper.h
@@ -0,0 +1,53 @@
+// Copyright (c) 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_DEVTOOLS_PROTOCOL_DEVTOOLS_DOWNLOAD_MANAGER_HELPER_H_
+#define CONTENT_BROWSER_DEVTOOLS_PROTOCOL_DEVTOOLS_DOWNLOAD_MANAGER_HELPER_H_
+
+#include <string>
+
+#include "content/public/browser/web_contents_user_data.h"
+
+namespace content {
+
+class WebContents;
+
+namespace protocol {
+
+// Per-WebContents class to handle DevTools download requests.
+class DevToolsDownloadManagerHelper
+ : public content::WebContentsUserData<DevToolsDownloadManagerHelper> {
+ public:
+ enum class DownloadBehavior {
+ // All downloads are denied.
+ DENY,
+
+ // All downloads are accepted.
+ ALLOW,
+
+ // Use default download behavior if available, otherwise deny.
+ DEFAULT
+ };
+
+ ~DevToolsDownloadManagerHelper() override;
+ // Remove from WebContents user data.
+ static void RemoveFromWebContents(content::WebContents* web_contents);
+
+ DownloadBehavior GetDownloadBehavior();
+ void SetDownloadBehavior(DownloadBehavior behavior);
+ std::string GetDownloadPath();
+ void SetDownloadPath(const std::string& path);
+
+ private:
+ explicit DevToolsDownloadManagerHelper(content::WebContents* web_contents);
+ friend class content::WebContentsUserData<DevToolsDownloadManagerHelper>;
+
+ DownloadBehavior download_behavior_;
+ std::string download_path_;
+};
+
+} // namespace protocol
+} // namespace content
+
+#endif // CONTENT_BROWSER_DEVTOOLS_PROTOCOL_DEVTOOLS_DOWNLOAD_MANAGER_HELPER_H_
diff --git a/chromium/content/browser/devtools/protocol/devtools_protocol_browsertest.cc b/chromium/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
index d2f53445a55..7b46319703a 100644
--- a/chromium/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
+++ b/chromium/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
@@ -21,10 +21,16 @@
#include "base/sys_info.h"
#include "base/values.h"
#include "build/build_config.h"
+#include "content/browser/devtools/protocol/devtools_download_manager_delegate.h"
+#include "content/browser/download/download_file_factory.h"
+#include "content/browser/download/download_file_impl.h"
+#include "content/browser/download/download_manager_impl.h"
+#include "content/browser/download/download_task_runner.h"
#include "content/browser/frame_host/interstitial_page_impl.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/devtools_agent_host.h"
+#include "content/public/browser/download_manager.h"
#include "content/public/browser/interstitial_page_delegate.h"
#include "content/public/browser/javascript_dialog_manager.h"
#include "content/public/browser/navigation_controller.h"
@@ -33,19 +39,26 @@
#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/security_style_explanations.h"
#include "content/public/browser/ssl_status.h"
#include "content/public/browser/web_contents.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"
#include "content/public/test/content_browser_test_utils.h"
+#include "content/public/test/download_test_observer.h"
#include "content/public/test/test_navigation_observer.h"
#include "content/shell/browser/shell.h"
+#include "content/shell/browser/shell_browser_context.h"
+#include "content/shell/browser/shell_download_manager_delegate.h"
#include "content/test/content_browser_test_utils_internal.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/test_data_directory.h"
+#include "net/test/url_request/url_request_mock_http_job.h"
+#include "net/test/url_request/url_request_slow_download_job.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkColor.h"
@@ -74,14 +87,41 @@ const char kIdParam[] = "id";
const char kMethodParam[] = "method";
const char kParamsParam[] = "params";
+// If |params| contains an explanation with a non-empty certificate list,
+// returns true and points |certificate| to the certificate list of the first
+// explanation that contains a nonempty certificate list. Otherwise returns
+// false. |params| is expected to be the parameters of a securityStateChanged
+// notification.
+bool GetCertificateFromNotificationParams(base::DictionaryValue* params,
+ const base::ListValue** certificate) {
+ const base::ListValue* explanations;
+ if (!params->GetList("explanations", &explanations)) {
+ return false;
+ }
+ for (const auto& explanation : *explanations) {
+ const base::DictionaryValue* explanation_dict;
+ if (explanation.GetAsDictionary(&explanation_dict) &&
+ explanation_dict->GetList("certificate", certificate) &&
+ (*certificate)->GetSize() > 0u) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool SecurityStateChangedHasCertificateExplanation(
+ base::DictionaryValue* params) {
+ const base::ListValue* unused;
+ return GetCertificateFromNotificationParams(params, &unused);
+}
+
class TestJavaScriptDialogManager : public JavaScriptDialogManager,
public WebContentsDelegate {
public:
- TestJavaScriptDialogManager() : handle_(false) {}
+ TestJavaScriptDialogManager() {}
~TestJavaScriptDialogManager() override {}
- void Handle()
- {
+ void Handle() {
if (!callback_.is_null()) {
callback_.Run(true, base::string16());
callback_.Reset();
@@ -98,7 +138,7 @@ class TestJavaScriptDialogManager : public JavaScriptDialogManager,
// JavaScriptDialogManager
void RunJavaScriptDialog(WebContents* web_contents,
- const GURL& origin_url,
+ const GURL& alerting_frame_url,
JavaScriptDialogType dialog_type,
const base::string16& message_text,
const base::string16& default_prompt_text,
@@ -119,24 +159,30 @@ class TestJavaScriptDialogManager : public JavaScriptDialogManager,
bool HandleJavaScriptDialog(WebContents* web_contents,
bool accept,
const base::string16* prompt_override) override {
+ is_handled_ = true;
return true;
}
void CancelDialogs(WebContents* web_contents,
bool reset_state) override {}
+ bool is_handled() { return is_handled_; }
+
private:
DialogClosedCallback callback_;
- bool handle_;
+ bool handle_ = false;
+ bool is_handled_ = false;
DISALLOW_COPY_AND_ASSIGN(TestJavaScriptDialogManager);
};
-}
+} // namespace
class DevToolsProtocolTest : public ContentBrowserTest,
public DevToolsAgentHostClient,
public WebContentsDelegate {
public:
+ typedef base::Callback<bool(base::DictionaryValue*)> NotificationMatcher;
+
DevToolsProtocolTest()
: last_sent_id_(0),
waiting_for_command_result_id_(0),
@@ -144,15 +190,11 @@ class DevToolsProtocolTest : public ContentBrowserTest,
agent_host_can_close_(false) {}
void SetUpOnMainThread() override {
- ok_cert_ =
- net::ImportCertFromFile(net::GetTestCertsDirectory(), "ok_cert.pem");
- expired_cert_ = net::ImportCertFromFile(net::GetTestCertsDirectory(),
- "expired_cert.pem");
host_resolver()->AddRule("*", "127.0.0.1");
}
protected:
- // WebContentsDelegate method:
+ // WebContentsDelegate methods:
bool DidAddMessageToConsole(WebContents* source,
int32_t level,
const base::string16& message,
@@ -162,10 +204,15 @@ class DevToolsProtocolTest : public ContentBrowserTest,
return true;
}
- void ShowCertificateViewerInDevTools(
- WebContents* web_contents,
- scoped_refptr<net::X509Certificate> certificate) override {
- last_shown_certificate_ = certificate;
+ blink::WebSecurityStyle GetSecurityStyle(
+ content::WebContents* web_contents,
+ content::SecurityStyleExplanations* security_style_explanations)
+ override {
+ security_style_explanations->secure_explanations.push_back(
+ SecurityStyleExplanation(
+ "an explanation", "an explanation description", cert_,
+ blink::WebMixedContentContextType::kNotMixedContent));
+ return blink::kWebSecurityStyleNeutral;
}
base::DictionaryValue* SendCommand(
@@ -267,6 +314,28 @@ class DevToolsProtocolTest : public ContentBrowserTest,
return std::move(waiting_for_notification_params_);
}
+ // Waits for a notification whose params, when passed to |matcher|, returns
+ // true. Existing notifications are allowed.
+ std::unique_ptr<base::DictionaryValue> WaitForMatchingNotification(
+ const std::string& notification,
+ const NotificationMatcher& matcher) {
+ for (size_t i = 0; i < notifications_.size(); i++) {
+ if (notifications_[i] == notification &&
+ matcher.Run(notification_params_[i].get())) {
+ std::unique_ptr<base::DictionaryValue> result =
+ std::move(notification_params_[i]);
+ notifications_.erase(notifications_.begin() + i);
+ notification_params_.erase(notification_params_.begin() + i);
+ return result;
+ }
+ }
+
+ waiting_for_notification_ = notification;
+ waiting_for_notification_matcher_ = matcher;
+ RunMessageLoop();
+ return std::move(waiting_for_notification_params_);
+ }
+
void ClearNotifications() {
notifications_.clear();
notification_params_.clear();
@@ -274,9 +343,8 @@ class DevToolsProtocolTest : public ContentBrowserTest,
struct ExpectedNavigation {
std::string url;
- bool is_in_main_frame;
bool is_redirect;
- std::string navigation_response;
+ bool abort;
};
std::string RemovePort(const GURL& url) {
@@ -286,48 +354,57 @@ class DevToolsProtocolTest : public ContentBrowserTest,
}
// Waits for the expected navigations to occur in any order. If an expected
- // navigation occurs, Page.processNavigation is called with the specified
- // navigation_response to either allow it to proceed or to cancel it.
+ // navigation occurs, Network.continueInterceptedRequest is called with the
+ // specified navigation_response to either allow it to proceed or to cancel
+ // it.
void ProcessNavigationsAnyOrder(
std::vector<ExpectedNavigation> expected_navigations) {
+ std::unique_ptr<base::DictionaryValue> params;
while (!expected_navigations.empty()) {
std::unique_ptr<base::DictionaryValue> params =
- WaitForNotification("Page.navigationRequested");
-
+ WaitForNotification("Network.requestIntercepted");
+
+ std::string interception_id;
+ ASSERT_TRUE(params->GetString("interceptionId", &interception_id));
+ bool is_redirect = params->HasKey("redirectUrl");
+ bool is_navigation;
+ ASSERT_TRUE(params->GetBoolean("isNavigationRequest", &is_navigation));
+ std::string resource_type;
+ ASSERT_TRUE(params->GetString("resourceType", &resource_type));
std::string url;
- ASSERT_TRUE(params->GetString("url", &url));
-
+ ASSERT_TRUE(params->GetString("request.url", &url));
+ if (is_redirect)
+ ASSERT_TRUE(params->GetString("redirectUrl", &url));
// The url will typically have a random port which we want to remove.
url = RemovePort(GURL(url));
- int navigation_id;
- ASSERT_TRUE(params->GetInteger("navigationId", &navigation_id));
- bool is_in_main_frame;
- ASSERT_TRUE(params->GetBoolean( "isInMainFrame", &is_in_main_frame));
- bool is_redirect;
- ASSERT_TRUE(params->GetBoolean("isRedirect", &is_redirect));
+ if (!is_navigation) {
+ params.reset(new base::DictionaryValue());
+ params->SetString("interceptionId", interception_id);
+ SendCommand("Network.continueInterceptedRequest", std::move(params),
+ false);
+ continue;
+ }
- bool navigation_was_expected;
+ bool navigation_was_expected = false;
for (auto it = expected_navigations.begin();
it != expected_navigations.end(); it++) {
- if (url != it->url || is_in_main_frame != it->is_in_main_frame ||
- is_redirect != it->is_redirect) {
+ if (url != it->url || is_redirect != it->is_redirect)
continue;
- }
- std::unique_ptr<base::DictionaryValue> process_params(
- new base::DictionaryValue());
- process_params->SetString("response", it->navigation_response);
- process_params->SetInteger("navigationId", navigation_id);
- SendCommand("Page.processNavigation", std::move(process_params), false);
+ params.reset(new base::DictionaryValue());
+ params->SetString("interceptionId", interception_id);
+ if (it->abort)
+ params->SetString("errorReason", "Aborted");
+ SendCommand("Network.continueInterceptedRequest", std::move(params),
+ false);
navigation_was_expected = true;
expected_navigations.erase(it);
break;
}
EXPECT_TRUE(navigation_was_expected)
- << "url = " << url << "is_in_main_frame = " << is_in_main_frame
- << "is_redirect = " << is_redirect;
+ << "url = " << url << "is_redirect = " << is_redirect;
}
}
@@ -340,18 +417,13 @@ class DevToolsProtocolTest : public ContentBrowserTest,
return urls;
}
- const scoped_refptr<net::X509Certificate>& last_shown_certificate() {
- return last_shown_certificate_;
- }
-
- const scoped_refptr<net::X509Certificate>& ok_cert() { return ok_cert_; }
+ void set_agent_host_can_close() { agent_host_can_close_ = true; }
- const scoped_refptr<net::X509Certificate>& expired_cert() {
- return expired_cert_;
+ void SetSecurityExplanationCert(
+ const scoped_refptr<net::X509Certificate>& cert) {
+ cert_ = cert;
}
- void set_agent_host_can_close() { agent_host_can_close_ = true; }
-
std::unique_ptr<base::DictionaryValue> result_;
scoped_refptr<DevToolsAgentHost> agent_host_;
int last_sent_id_;
@@ -375,7 +447,7 @@ class DevToolsProtocolTest : public ContentBrowserTest,
in_dispatch_ = false;
if (id && id == waiting_for_command_result_id_) {
waiting_for_command_result_id_ = 0;
- base::MessageLoop::current()->QuitNow();
+ base::RunLoop::QuitCurrentDeprecated();
}
} else {
std::string notification;
@@ -388,11 +460,15 @@ class DevToolsProtocolTest : public ContentBrowserTest,
notification_params_.push_back(
base::WrapUnique(new base::DictionaryValue()));
}
- if (waiting_for_notification_ == notification) {
+ if (waiting_for_notification_ == notification &&
+ (waiting_for_notification_matcher_.is_null() ||
+ waiting_for_notification_matcher_.Run(
+ notification_params_[notification_params_.size() - 1].get()))) {
waiting_for_notification_ = std::string();
+ waiting_for_notification_matcher_ = NotificationMatcher();
waiting_for_notification_params_ = base::WrapUnique(
notification_params_[notification_params_.size() - 1]->DeepCopy());
- base::MessageLoop::current()->QuitNow();
+ base::RunLoop::QuitCurrentDeprecated();
}
}
}
@@ -403,13 +479,12 @@ class DevToolsProtocolTest : public ContentBrowserTest,
}
std::string waiting_for_notification_;
+ NotificationMatcher waiting_for_notification_matcher_;
std::unique_ptr<base::DictionaryValue> waiting_for_notification_params_;
int waiting_for_command_result_id_;
bool in_dispatch_;
- scoped_refptr<net::X509Certificate> last_shown_certificate_;
- scoped_refptr<net::X509Certificate> ok_cert_;
- scoped_refptr<net::X509Certificate> expired_cert_;
bool agent_host_can_close_;
+ scoped_refptr<net::X509Certificate> cert_;
};
class TestInterstitialDelegate : public InterstitialPageDelegate {
@@ -573,17 +648,21 @@ bool ColorsMatchWithinLimit(SkColor color1,
bool MatchesBitmap(const SkBitmap& expected_bmp,
const SkBitmap& actual_bmp,
const gfx::Rect& matching_mask,
+ float device_scale_factor,
int error_limit) {
// Number of pixels with an error
int error_pixels_count = 0;
gfx::Rect error_bounding_rect = gfx::Rect();
+ // Scale expectations along with the mask.
+ device_scale_factor = device_scale_factor ? device_scale_factor : 1;
+
// Check that bitmaps have identical dimensions.
- EXPECT_EQ(expected_bmp.width(), actual_bmp.width());
- EXPECT_EQ(expected_bmp.height(), actual_bmp.height());
- if (expected_bmp.width() != actual_bmp.width() ||
- expected_bmp.height() != actual_bmp.height()) {
+ EXPECT_EQ(expected_bmp.width() * device_scale_factor, actual_bmp.width());
+ EXPECT_EQ(expected_bmp.height() * device_scale_factor, actual_bmp.height());
+ if (expected_bmp.width() * device_scale_factor != actual_bmp.width() ||
+ expected_bmp.height() * device_scale_factor != actual_bmp.height()) {
return false;
}
@@ -591,7 +670,8 @@ bool MatchesBitmap(const SkBitmap& expected_bmp,
for (int x = matching_mask.x(); x < matching_mask.right(); ++x) {
for (int y = matching_mask.y(); y < matching_mask.bottom(); ++y) {
- SkColor actual_color = actual_bmp.getColor(x, y);
+ SkColor actual_color =
+ actual_bmp.getColor(x * device_scale_factor, y * device_scale_factor);
SkColor expected_color = expected_bmp.getColor(x, y);
if (!ColorsMatchWithinLimit(actual_color, expected_color, error_limit)) {
if (error_pixels_count < 10) {
@@ -619,11 +699,24 @@ class CaptureScreenshotTest : public DevToolsProtocolTest {
enum ScreenshotEncoding { ENCODING_PNG, ENCODING_JPEG };
void CaptureScreenshotAndCompareTo(const SkBitmap& expected_bitmap,
ScreenshotEncoding encoding,
- bool fromSurface) {
+ bool from_surface,
+ float device_scale_factor = 0,
+ const gfx::RectF& clip = gfx::RectF(),
+ float clip_scale = 0) {
std::unique_ptr<base::DictionaryValue> params(new base::DictionaryValue());
params->SetString("format", encoding == ENCODING_PNG ? "png" : "jpeg");
params->SetInteger("quality", 100);
- params->SetBoolean("fromSurface", fromSurface);
+ params->SetBoolean("fromSurface", from_surface);
+ if (clip_scale) {
+ std::unique_ptr<base::DictionaryValue> clip_value(
+ new base::DictionaryValue());
+ clip_value->SetDouble("x", clip.x());
+ clip_value->SetDouble("y", clip.y());
+ clip_value->SetDouble("width", clip.width());
+ clip_value->SetDouble("height", clip.height());
+ clip_value->SetDouble("scale", clip_scale);
+ params->Set("clip", std::move(clip_value));
+ }
SendCommand("Page.captureScreenshot", std::move(params));
std::string base64;
@@ -649,13 +742,14 @@ class CaptureScreenshotTest : public DevToolsProtocolTest {
matching_mask.Inset(4, 4, 4, 4);
#endif
EXPECT_TRUE(MatchesBitmap(expected_bitmap, *result_bitmap, matching_mask,
- error_limit));
+ device_scale_factor, error_limit));
}
// Takes a screenshot of a colored box that is positioned inside the frame.
void PlaceAndCaptureBox(const gfx::Size& frame_size,
const gfx::Size& box_size,
- float screenshot_scale) {
+ float screenshot_scale,
+ float device_scale_factor) {
static const int kBoxOffsetHeight = 100;
const gfx::Size scaled_box_size =
ScaleToFlooredSize(box_size, screenshot_scale);
@@ -682,36 +776,30 @@ class CaptureScreenshotTest : public DevToolsProtocolTest {
// Force frame size: The offset of the blue box within the frame shouldn't
// change during screenshotting. This verifies that the page doesn't observe
// a change in frame size as a side effect of screenshotting.
+
params.reset(new base::DictionaryValue());
params->SetInteger("width", frame_size.width());
params->SetInteger("height", frame_size.height());
- params->SetDouble("deviceScaleFactor", 0);
+ params->SetDouble("deviceScaleFactor", device_scale_factor);
params->SetBoolean("mobile", false);
- params->SetBoolean("fitWindow", false);
SendCommand("Emulation.setDeviceMetricsOverride", std::move(params));
// Resize frame to scaled blue box size.
- params.reset(new base::DictionaryValue());
- params->SetInteger("width", scaled_box_size.width());
- params->SetInteger("height", scaled_box_size.height());
- SendCommand("Emulation.setVisibleSize", std::move(params));
-
- // Force viewport to match scaled blue box.
- params.reset(new base::DictionaryValue());
- params->SetDouble("x", (frame_size.width() - box_size.width()) / 2.);
- params->SetDouble("y", kBoxOffsetHeight);
- params->SetDouble("scale", screenshot_scale);
- SendCommand("Emulation.forceViewport", std::move(params));
+ gfx::RectF clip;
+ clip.set_width(box_size.width());
+ clip.set_height(box_size.height());
+ clip.set_x((frame_size.width() - box_size.width()) / 2.);
+ clip.set_y(kBoxOffsetHeight);
// Capture screenshot and verify that it is indeed blue.
SkBitmap expected_bitmap;
expected_bitmap.allocN32Pixels(scaled_box_size.width(),
scaled_box_size.height());
expected_bitmap.eraseColor(SkColorSetRGB(0x00, 0x00, 0xff));
- CaptureScreenshotAndCompareTo(expected_bitmap, ENCODING_PNG, true);
+ CaptureScreenshotAndCompareTo(expected_bitmap, ENCODING_PNG, true,
+ device_scale_factor, clip, screenshot_scale);
// Reset for next screenshot.
- SendCommand("Emulation.resetViewport", nullptr);
SendCommand("Emulation.clearDeviceMetricsOverride", nullptr);
}
@@ -772,8 +860,7 @@ IN_PROC_BROWSER_TEST_F(CaptureScreenshotTest, CaptureScreenshotJpeg) {
#if defined(OS_ANDROID)
#define MAYBE_CaptureScreenshotArea DISABLED_CaptureScreenshotArea
#else
-// Temporarily disabled while protocol methods are being refactored.
-#define MAYBE_CaptureScreenshotArea DISABLED_CaptureScreenshotArea
+#define MAYBE_CaptureScreenshotArea CaptureScreenshotArea
#endif
IN_PROC_BROWSER_TEST_F(CaptureScreenshotTest,
MAYBE_CaptureScreenshotArea) {
@@ -783,12 +870,17 @@ IN_PROC_BROWSER_TEST_F(CaptureScreenshotTest,
Attach();
// Test capturing a subarea inside the emulated frame at different scales.
- PlaceAndCaptureBox(kFrameSize, gfx::Size(100, 200), 1.0);
- PlaceAndCaptureBox(kFrameSize, gfx::Size(100, 200), 2.0);
- PlaceAndCaptureBox(kFrameSize, gfx::Size(100, 200), 0.5);
+ PlaceAndCaptureBox(kFrameSize, gfx::Size(100, 200), 1.0, 1.);
+ PlaceAndCaptureBox(kFrameSize, gfx::Size(100, 200), 2.0, 1.);
+ PlaceAndCaptureBox(kFrameSize, gfx::Size(100, 200), 0.5, 1.);
// Ensure that content outside the emulated frame is painted, too.
- PlaceAndCaptureBox(kFrameSize, gfx::Size(10, 8192), 1.0);
+ PlaceAndCaptureBox(kFrameSize, gfx::Size(10, 8192), 1.0, 1.);
+
+ // Check non-1 device scale factor.
+ PlaceAndCaptureBox(kFrameSize, gfx::Size(100, 200), 1.0, 2.);
+ // Ensure not emulating device scale factor works.
+ PlaceAndCaptureBox(kFrameSize, gfx::Size(100, 200), 1.0, 0.);
}
// Verifies that setDefaultBackgroundColor and captureScreenshot support a
@@ -1157,13 +1249,101 @@ IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, JavaScriptDialogNotifications) {
NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
Attach();
TestJavaScriptDialogManager dialog_manager;
- shell()->web_contents()->SetDelegate(&dialog_manager);
+ WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell()->web_contents());
+ wc->SetDelegate(&dialog_manager);
SendCommand("Page.enable", nullptr, true);
+
std::unique_ptr<base::DictionaryValue> params(new base::DictionaryValue());
- params->SetString("expression", "alert('alert')");
+ params->SetString("expression", "prompt('hello?', 'default')");
+ SendCommand("Runtime.evaluate", std::move(params), false);
+
+ params = WaitForNotification("Page.javascriptDialogOpening");
+ std::string url;
+ EXPECT_TRUE(params->GetString("url", &url));
+ EXPECT_EQ("about:blank", url);
+ std::string message;
+ EXPECT_TRUE(params->GetString("message", &message));
+ EXPECT_EQ("hello?", message);
+ std::string type;
+ EXPECT_TRUE(params->GetString("type", &type));
+ EXPECT_EQ("prompt", type);
+ std::string default_prompt;
+ EXPECT_TRUE(params->GetString("defaultPrompt", &default_prompt));
+ EXPECT_EQ("default", default_prompt);
+
+ params.reset(new base::DictionaryValue());
+ params->SetBoolean("accept", true);
+ params->SetString("promptText", "hi!");
+ SendCommand("Page.handleJavaScriptDialog", std::move(params), false);
+
+ params = WaitForNotification("Page.javascriptDialogClosed", true);
+ bool result = false;
+ EXPECT_TRUE(params->GetBoolean("result", &result));
+ EXPECT_TRUE(result);
+
+ EXPECT_TRUE(dialog_manager.is_handled());
+
+ std::string input;
+ EXPECT_TRUE(params->GetString("userInput", &input));
+ EXPECT_EQ("hi!", input);
+ wc->SetDelegate(nullptr);
+ wc->SetJavaScriptDialogManagerForTesting(nullptr);
+}
+
+IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, JavaScriptDialogInterop) {
+ NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
+ Attach();
+ TestJavaScriptDialogManager dialog_manager;
+ WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell()->web_contents());
+ wc->SetDelegate(&dialog_manager);
+ SendCommand("Page.enable", nullptr, true);
+
+ std::unique_ptr<base::DictionaryValue> params(new base::DictionaryValue());
+ params->SetString("expression", "alert('42')");
SendCommand("Runtime.evaluate", std::move(params), false);
WaitForNotification("Page.javascriptDialogOpening");
+
dialog_manager.Handle();
+ WaitForNotification("Page.javascriptDialogClosed", true);
+ wc->SetDelegate(nullptr);
+ wc->SetJavaScriptDialogManagerForTesting(nullptr);
+}
+
+IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, BeforeUnloadDialog) {
+ NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
+ Attach();
+ TestJavaScriptDialogManager dialog_manager;
+
+ WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell()->web_contents());
+ wc->SetDelegate(&dialog_manager);
+ SendCommand("Runtime.enable", nullptr, true);
+
+ std::unique_ptr<base::DictionaryValue> params(new base::DictionaryValue());
+
+ params.reset(new base::DictionaryValue());
+ params->SetString("expression",
+ "window.onbeforeunload=()=>{return 'prompt';}");
+ params->SetBoolean("userGesture", true);
+ SendCommand("Runtime.evaluate", std::move(params), true);
+
+ SendCommand("Page.enable", nullptr, true);
+ SendCommand("Page.reload", nullptr, false);
+
+ params = WaitForNotification("Page.javascriptDialogOpening", true);
+
+ std::string url;
+ EXPECT_TRUE(params->GetString("url", &url));
+ EXPECT_EQ("about:blank", url);
+ std::string type;
+ EXPECT_TRUE(params->GetString("type", &type));
+ EXPECT_EQ("beforeunload", type);
+
+ params.reset(new base::DictionaryValue());
+ params->SetBoolean("accept", true);
+ SendCommand("Page.handleJavaScriptDialog", std::move(params), false);
+ WaitForNotification("Page.javascriptDialogClosed", true);
+ wc->SetDelegate(nullptr);
+ wc->SetJavaScriptDialogManagerForTesting(nullptr);
}
IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, BrowserCreateAndCloseTarget) {
@@ -1223,7 +1403,7 @@ class NavigationFinishedObserver : public content::WebContentsObserver {
num_finished_++;
if (num_finished_ >= num_to_wait_for_ && num_to_wait_for_ != 0) {
- base::MessageLoop::current()->QuitNow();
+ base::RunLoop::QuitCurrentDeprecated();
}
}
@@ -1269,20 +1449,20 @@ IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, PageStopLoading) {
ASSERT_TRUE(embedded_test_server()->Start());
// Navigate to about:blank first so we can make sure there is a target page we
- // can attach to, and have Page.setControlNavigations complete before we start
- // the navigations we're interested in.
+ // can attach to, and have Network.setRequestInterceptionEnabled complete
+ // before we start the navigations we're interested in.
NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
Attach();
std::unique_ptr<base::DictionaryValue> params(new base::DictionaryValue());
params->SetBoolean("enabled", true);
- SendCommand("Page.setControlNavigations", std::move(params), true);
+ SendCommand("Network.setRequestInterceptionEnabled", std::move(params), true);
LoadFinishedObserver load_finished_observer(shell()->web_contents());
// The page will try to navigate twice, however since
- // Page.setControlNavigations is true, it'll wait for confirmation before
- // committing to the navigation.
+ // Network.setRequestInterceptionEnabled is true,
+ // it'll wait for confirmation before committing to the navigation.
GURL test_url = embedded_test_server()->GetURL(
"/devtools/control_navigations/meta_tag.html");
shell()->LoadURL(test_url);
@@ -1298,14 +1478,14 @@ IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, ControlNavigationsMainFrame) {
ASSERT_TRUE(embedded_test_server()->Start());
// Navigate to about:blank first so we can make sure there is a target page we
- // can attach to, and have Page.setControlNavigations complete before we start
- // the navigations we're interested in.
+ // can attach to, and have Network.setRequestInterceptionEnabled complete
+ // before we start the navigations we're interested in.
NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
Attach();
std::unique_ptr<base::DictionaryValue> params(new base::DictionaryValue());
params->SetBoolean("enabled", true);
- SendCommand("Page.setControlNavigations", std::move(params), true);
+ SendCommand("Network.setRequestInterceptionEnabled", std::move(params), true);
NavigationFinishedObserver navigation_finished_observer(
shell()->web_contents());
@@ -1316,11 +1496,9 @@ IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, ControlNavigationsMainFrame) {
std::vector<ExpectedNavigation> expected_navigations = {
{"http://127.0.0.1/devtools/control_navigations/meta_tag.html",
- true /* expected_is_in_main_frame */, false /* expected_is_redirect */,
- "Proceed"},
+ false /* expected_is_redirect */, false /* abort */},
{"http://127.0.0.1/devtools/navigation.html",
- true /* expected_is_in_main_frame */, false /* expected_is_redirect */,
- "Cancel"}};
+ false /* expected_is_redirect */, true /* abort */}};
ProcessNavigationsAnyOrder(std::move(expected_navigations));
@@ -1350,14 +1528,14 @@ IN_PROC_BROWSER_TEST_F(IsolatedDevToolsProtocolTest,
ASSERT_TRUE(embedded_test_server()->Start());
// Navigate to about:blank first so we can make sure there is a target page we
- // can attach to, and have Page.setControlNavigations complete before we start
- // the navigations we're interested in.
+ // can attach to, and have Network.setRequestInterceptionEnabled complete
+ // before we start the navigations we're interested in.
NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
Attach();
std::unique_ptr<base::DictionaryValue> params(new base::DictionaryValue());
params->SetBoolean("enabled", true);
- SendCommand("Page.setControlNavigations", std::move(params), true);
+ SendCommand("Network.setRequestInterceptionEnabled", std::move(params), true);
NavigationFinishedObserver navigation_finished_observer(
shell()->web_contents());
@@ -1372,28 +1550,21 @@ IN_PROC_BROWSER_TEST_F(IsolatedDevToolsProtocolTest,
std::vector<ExpectedNavigation> expected_navigations = {
{"http://127.0.0.1/devtools/control_navigations/"
"iframe_navigation.html",
- /* expected_is_in_main_frame */ true,
- /* expected_is_redirect */ false, "Proceed"},
+ false /* expected_is_redirect */, false /* abort */},
{"http://127.0.0.1/cross-site/a.com/devtools/control_navigations/"
"meta_tag.html",
- /* expected_is_in_main_frame */ false,
- /* expected_is_redirect */ false, "Proceed"},
+ false /* expected_is_redirect */, false /* abort */},
{"http://127.0.0.1/cross-site/b.com/devtools/control_navigations/"
"meta_tag.html",
- /* expected_is_in_main_frame */ false,
- /* expected_is_redirect */ false, "Proceed"},
+ false /* expected_is_redirect */, false /* abort */},
{"http://a.com/devtools/control_navigations/meta_tag.html",
- /* expected_is_in_main_frame */ false,
- /* expected_is_redirect */ true, "Proceed"},
+ true /* expected_is_redirect */, false /* abort */},
{"http://b.com/devtools/control_navigations/meta_tag.html",
- /* expected_is_in_main_frame */ false,
- /* expected_is_redirect */ true, "Proceed"},
+ true /* expected_is_redirect */, false /* abort */},
{"http://a.com/devtools/navigation.html",
- /* expected_is_in_main_frame */ false,
- /* expected_is_redirect */ false, "Proceed"},
+ false /* expected_is_redirect */, false /* abort */},
{"http://b.com/devtools/navigation.html",
- /* expected_is_in_main_frame */ false,
- /* expected_is_redirect */ false, "Cancel"}};
+ false /* expected_is_redirect */, true /* abort */}};
ProcessNavigationsAnyOrder(std::move(expected_navigations));
@@ -1451,59 +1622,6 @@ IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, VirtualTimeTest) {
EXPECT_THAT(console_messages_, ElementsAre("before", "at", "done", "after"));
}
-// Tests that the Security.showCertificateViewer command shows the
-// certificate corresponding to the visible navigation entry, even when
-// an interstitial is showing. Regression test for
-// https://crbug.com/647759.
-IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, ShowCertificateViewer) {
- // First test that the correct certificate is shown for a normal
- // (non-interstitial) page.
- NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
- Attach();
-
- // Set a dummy certificate on the NavigationEntry.
- shell()
- ->web_contents()
- ->GetController()
- .GetVisibleEntry()
- ->GetSSL()
- .certificate = ok_cert();
-
- std::unique_ptr<base::DictionaryValue> params1(new base::DictionaryValue());
- SendCommand("Security.showCertificateViewer", std::move(params1), true);
-
- scoped_refptr<net::X509Certificate> normal_page_cert = shell()
- ->web_contents()
- ->GetController()
- .GetVisibleEntry()
- ->GetSSL()
- .certificate;
- ASSERT_TRUE(normal_page_cert);
- EXPECT_EQ(normal_page_cert, last_shown_certificate());
-
- // Now test that the correct certificate is shown on an interstitial.
- TestInterstitialDelegate* delegate = new TestInterstitialDelegate;
- WebContentsImpl* web_contents =
- static_cast<WebContentsImpl*>(shell()->web_contents());
- GURL interstitial_url("https://example.test");
- InterstitialPageImpl* interstitial = new InterstitialPageImpl(
- web_contents, static_cast<RenderWidgetHostDelegate*>(web_contents), true,
- interstitial_url, delegate);
- interstitial->Show();
- WaitForInterstitialAttach(web_contents);
-
- // Set the transient navigation entry certificate.
- NavigationEntry* transient_entry =
- web_contents->GetController().GetTransientEntry();
- ASSERT_TRUE(transient_entry);
- transient_entry->GetSSL().certificate = expired_cert();
- ASSERT_TRUE(transient_entry->GetSSL().certificate);
-
- std::unique_ptr<base::DictionaryValue> params2(new base::DictionaryValue());
- SendCommand("Security.showCertificateViewer", std::move(params2), true);
- EXPECT_EQ(transient_entry->GetSSL().certificate, last_shown_certificate());
-}
-
IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, CertificateError) {
net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
https_server.SetSSLConfig(net::EmbeddedTestServer::CERT_EXPIRED);
@@ -1874,4 +1992,596 @@ IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, SetAndGetCookies) {
EXPECT_EQ(2u, found);
}
+class DevToolsProtocolTouchTest : public DevToolsProtocolTest {
+ public:
+ ~DevToolsProtocolTouchTest() override {}
+
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ command_line->AppendSwitchASCII(
+ switches::kTouchEventFeatureDetection,
+ switches::kTouchEventFeatureDetectionDisabled);
+ }
+};
+
+IN_PROC_BROWSER_TEST_F(DevToolsProtocolTouchTest, EnableTouch) {
+ std::unique_ptr<base::DictionaryValue> params;
+ bool result;
+
+ ASSERT_TRUE(embedded_test_server()->Start());
+ GURL test_url = embedded_test_server()->GetURL("/devtools/enable_touch.html");
+ NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 1);
+ Attach();
+
+ params.reset(new base::DictionaryValue());
+ SendCommand("Page.enable", std::move(params), true);
+
+ ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
+ shell()->web_contents(),
+ "domAutomationController.send(checkProtos(false))", &result));
+ EXPECT_TRUE(result);
+
+ params.reset(new base::DictionaryValue());
+ params->SetBoolean("enabled", true);
+ SendCommand("Emulation.setTouchEmulationEnabled", std::move(params), true);
+ ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
+ shell()->web_contents(),
+ "domAutomationController.send(checkProtos(false))", &result));
+ EXPECT_TRUE(result);
+
+ params.reset(new base::DictionaryValue());
+ SendCommand("Page.reload", std::move(params), false);
+ WaitForNotification("Page.frameStoppedLoading");
+ ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
+ shell()->web_contents(),
+ "domAutomationController.send(checkProtos(true))", &result));
+ EXPECT_TRUE(result);
+
+ params.reset(new base::DictionaryValue());
+ params->SetBoolean("enabled", false);
+ SendCommand("Emulation.setTouchEmulationEnabled", std::move(params), true);
+ ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
+ shell()->web_contents(),
+ "domAutomationController.send(checkProtos(true))", &result));
+ EXPECT_TRUE(result);
+
+ params.reset(new base::DictionaryValue());
+ SendCommand("Page.reload", std::move(params), false);
+ WaitForNotification("Page.frameStoppedLoading");
+ ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
+ shell()->web_contents(),
+ "domAutomationController.send(checkProtos(false))", &result));
+ EXPECT_TRUE(result);
+}
+
+// Tests that when a security explanation contains a certificate, it is properly
+// serialized into the protocol message.
+IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, CertificateExplanations) {
+ net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
+ https_server.AddDefaultHandlers(
+ base::FilePath(FILE_PATH_LITERAL("content/test/data")));
+ ASSERT_TRUE(https_server.Start());
+
+ shell()->LoadURL(GURL("about:blank"));
+ WaitForLoadStop(shell()->web_contents());
+
+ // Navigate to a page on the server in order to retrieve its certificate
+ // chain.
+ NavigateToURLBlockUntilNavigationsComplete(
+ shell(), https_server.GetURL("/title1.html"), 1);
+ WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell()->web_contents());
+ NavigationEntry* entry = wc->GetController().GetLastCommittedEntry();
+ ASSERT_TRUE(entry);
+ scoped_refptr<net::X509Certificate> cert = entry->GetSSL().certificate;
+
+ // Provide |cert| as the certificate on the security style explanations. When
+ // the security handler is enabled, DidChangeVisibleSecurityState() is called
+ // and the explanations with |cert| are sent to DevTools.
+ SetSecurityExplanationCert(cert);
+ Attach();
+ SendCommand("Security.enable", nullptr, false);
+ std::unique_ptr<base::DictionaryValue> params(new base::DictionaryValue());
+ params = WaitForMatchingNotification(
+ "Security.securityStateChanged",
+ base::Bind(&SecurityStateChangedHasCertificateExplanation));
+
+ // There should be one explanation containing the server's certificate chain.
+ net::SHA256HashValue cert_chain_fingerprint =
+ net::X509Certificate::CalculateChainFingerprint256(
+ cert->os_cert_handle(), cert->GetIntermediateCertificates());
+
+ // Read the certificate out of the first explanation.
+ const base::ListValue* certificate;
+ ASSERT_TRUE(GetCertificateFromNotificationParams(params.get(), &certificate));
+ std::vector<std::string> der_certs;
+ for (const auto& cert : *certificate) {
+ std::string decoded;
+ ASSERT_TRUE(base::Base64Decode(cert.GetString(), &decoded));
+ der_certs.push_back(decoded);
+ }
+ std::vector<base::StringPiece> cert_string_piece;
+ for (const auto& str : der_certs)
+ cert_string_piece.push_back(str);
+
+ // Check that the explanation certificate is correct.
+ scoped_refptr<net::X509Certificate> explanation_cert =
+ net::X509Certificate::CreateFromDERCertChain(cert_string_piece);
+ ASSERT_TRUE(explanation_cert);
+ EXPECT_EQ(cert_chain_fingerprint,
+ net::X509Certificate::CalculateChainFingerprint256(
+ explanation_cert->os_cert_handle(),
+ explanation_cert->GetIntermediateCertificates()));
+}
+
+// Download tests are flaky on Android: https://crbug.com/7546
+#if !defined(OS_ANDROID)
+namespace {
+
+static DownloadManagerImpl* DownloadManagerForShell(Shell* shell) {
+ // We're in a content_browsertest; we know that the DownloadManager
+ // is a DownloadManagerImpl.
+ return static_cast<DownloadManagerImpl*>(
+ content::BrowserContext::GetDownloadManager(
+ shell->web_contents()->GetBrowserContext()));
+}
+
+static void RemoveShellDelegate(Shell* shell) {
+ content::ShellDownloadManagerDelegate* shell_delegate =
+ static_cast<content::ShellDownloadManagerDelegate*>(
+ DownloadManagerForShell(shell)->GetDelegate());
+ shell_delegate->SetDownloadManager(nullptr);
+ DownloadManagerForShell(shell)->SetDelegate(nullptr);
+}
+
+class CountingDownloadFile : public DownloadFileImpl {
+ public:
+ CountingDownloadFile(std::unique_ptr<DownloadSaveInfo> save_info,
+ const base::FilePath& default_downloads_directory,
+ std::unique_ptr<ByteStreamReader> stream,
+ const net::NetLogWithSource& net_log,
+ base::WeakPtr<DownloadDestinationObserver> observer)
+ : DownloadFileImpl(std::move(save_info),
+ default_downloads_directory,
+ std::move(stream),
+ net_log,
+ observer) {}
+
+ ~CountingDownloadFile() override {
+ DCHECK(GetDownloadTaskRunner()->RunsTasksInCurrentSequence());
+ active_files_--;
+ }
+
+ void Initialize(const InitializeCallback& callback,
+ const CancelRequestCallback& cancel_request_callback,
+ const DownloadItem::ReceivedSlices& received_slices,
+ bool is_parallelizable) override {
+ DCHECK(GetDownloadTaskRunner()->RunsTasksInCurrentSequence());
+ active_files_++;
+ DownloadFileImpl::Initialize(callback, cancel_request_callback,
+ received_slices, is_parallelizable);
+ }
+
+ static void GetNumberActiveFiles(int* result) {
+ DCHECK(GetDownloadTaskRunner()->RunsTasksInCurrentSequence());
+ *result = active_files_;
+ }
+
+ // Can be called on any thread, and will block (running message loop)
+ // until data is returned.
+ static int GetNumberActiveFilesFromFileThread() {
+ int result = -1;
+ GetDownloadTaskRunner()->PostTaskAndReply(
+ FROM_HERE,
+ base::BindOnce(&CountingDownloadFile::GetNumberActiveFiles, &result),
+ base::MessageLoop::current()->QuitWhenIdleClosure());
+ base::RunLoop().Run();
+ DCHECK_NE(-1, result);
+ return result;
+ }
+
+ private:
+ static int active_files_;
+};
+
+int CountingDownloadFile::active_files_ = 0;
+
+class CountingDownloadFileFactory : public DownloadFileFactory {
+ public:
+ CountingDownloadFileFactory() {}
+ ~CountingDownloadFileFactory() override {}
+
+ // DownloadFileFactory interface.
+ DownloadFile* CreateFile(
+ std::unique_ptr<DownloadSaveInfo> save_info,
+ const base::FilePath& default_downloads_directory,
+ std::unique_ptr<ByteStreamReader> stream,
+ const net::NetLogWithSource& net_log,
+ base::WeakPtr<DownloadDestinationObserver> observer) override {
+ return new CountingDownloadFile(std::move(save_info),
+ default_downloads_directory,
+ std::move(stream), net_log, observer);
+ }
+};
+
+class TestShellDownloadManagerDelegate : public ShellDownloadManagerDelegate {
+ public:
+ TestShellDownloadManagerDelegate() : delay_download_open_(false) {}
+ ~TestShellDownloadManagerDelegate() override {}
+
+ bool ShouldOpenDownload(
+ DownloadItem* item,
+ const DownloadOpenDelayedCallback& callback) override {
+ if (delay_download_open_) {
+ delayed_callbacks_.push_back(callback);
+ return false;
+ }
+ return true;
+ }
+
+ bool GenerateFileHash() override { return true; }
+
+ void SetDelayedOpen(bool delay) { delay_download_open_ = delay; }
+
+ void GetDelayedCallbacks(
+ std::vector<DownloadOpenDelayedCallback>* callbacks) {
+ callbacks->swap(delayed_callbacks_);
+ }
+
+ private:
+ bool delay_download_open_;
+ std::vector<DownloadOpenDelayedCallback> delayed_callbacks_;
+};
+
+// Get the next created download.
+class DownloadCreateObserver : DownloadManager::Observer {
+ public:
+ explicit DownloadCreateObserver(DownloadManager* manager)
+ : manager_(manager), item_(nullptr) {
+ manager_->AddObserver(this);
+ }
+
+ ~DownloadCreateObserver() override {
+ if (manager_)
+ manager_->RemoveObserver(this);
+ manager_ = nullptr;
+ }
+
+ void ManagerGoingDown(DownloadManager* manager) override {
+ DCHECK_EQ(manager_, manager);
+ manager_->RemoveObserver(this);
+ manager_ = nullptr;
+ }
+
+ void OnDownloadCreated(DownloadManager* manager,
+ DownloadItem* download) override {
+ if (!item_)
+ item_ = download;
+
+ if (!completion_closure_.is_null())
+ base::ResetAndReturn(&completion_closure_).Run();
+ }
+
+ DownloadItem* WaitForFinished() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ if (!item_) {
+ base::RunLoop run_loop;
+ completion_closure_ = run_loop.QuitClosure();
+ run_loop.Run();
+ }
+ return item_;
+ }
+
+ private:
+ DownloadManager* manager_;
+ DownloadItem* item_;
+ base::Closure completion_closure_;
+};
+
+bool IsDownloadInState(DownloadItem::DownloadState state, DownloadItem* item) {
+ return item->GetState() == state;
+}
+
+class DevToolsDownloadContentTest : public DevToolsProtocolTest {
+ protected:
+ void SetUpOnMainThread() override {
+ base::ThreadRestrictions::SetIOAllowed(true);
+ ASSERT_TRUE(downloads_directory_.CreateUniqueTempDir());
+
+ // Set shell default download manager to test proxy reset behavior.
+ test_delegate_.reset(new TestShellDownloadManagerDelegate());
+ test_delegate_->SetDownloadBehaviorForTesting(
+ downloads_directory_.GetPath());
+ DownloadManager* manager = DownloadManagerForShell(shell());
+ manager->GetDelegate()->Shutdown();
+ manager->SetDelegate(test_delegate_.get());
+ test_delegate_->SetDownloadManager(manager);
+
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&net::URLRequestSlowDownloadJob::AddUrlHandler));
+ base::FilePath mock_base(GetTestFilePath("download", ""));
+
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&net::URLRequestMockHTTPJob::AddUrlHandlers, mock_base));
+ ASSERT_TRUE(embedded_test_server()->Start());
+ }
+
+ void SetDownloadBehavior(const std::string& behavior) {
+ std::unique_ptr<base::DictionaryValue> params(new base::DictionaryValue());
+ params->SetString("behavior", behavior);
+ SendCommand("Page.setDownloadBehavior", std::move(params));
+
+ EXPECT_GE(result_ids_.size(), 1u);
+ }
+
+ void SetDownloadBehavior(const std::string& behavior,
+ const std::string& download_path) {
+ std::unique_ptr<base::DictionaryValue> params(new base::DictionaryValue());
+ params->SetString("behavior", behavior);
+ params->SetString("downloadPath", download_path);
+ SendCommand("Page.setDownloadBehavior", std::move(params));
+
+ EXPECT_GE(result_ids_.size(), 1u);
+ }
+
+ // Create a DownloadTestObserverTerminal that will wait for the
+ // specified number of downloads to finish.
+ DownloadTestObserver* CreateWaiter(Shell* shell, int num_downloads) {
+ DownloadManager* download_manager = DownloadManagerForShell(shell);
+ return new DownloadTestObserverTerminal(
+ download_manager, num_downloads,
+ DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL);
+ }
+
+ // Note: Cannot be used with other alternative DownloadFileFactorys
+ void SetupEnsureNoPendingDownloads() {
+ DownloadManagerForShell(shell())->SetDownloadFileFactoryForTesting(
+ std::unique_ptr<DownloadFileFactory>(
+ new CountingDownloadFileFactory()));
+ }
+
+ void WaitForCompletion(DownloadItem* download) {
+ DownloadUpdatedObserver(
+ download, base::Bind(&IsDownloadInState, DownloadItem::COMPLETE))
+ .WaitForEvent();
+ }
+
+ bool EnsureNoPendingDownloads() {
+ bool result = true;
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&EnsureNoPendingDownloadJobsOnIO, &result));
+ base::RunLoop().Run();
+ return result &&
+ (CountingDownloadFile::GetNumberActiveFilesFromFileThread() == 0);
+ }
+
+ // Checks that |path| is has |file_size| bytes, and matches the |value|
+ // string.
+ bool VerifyFile(const base::FilePath& path,
+ const std::string& value,
+ const int64_t file_size) {
+ std::string file_contents;
+
+ {
+ base::ThreadRestrictions::ScopedAllowIO allow_io_during_test_verification;
+ bool read = base::ReadFileToString(path, &file_contents);
+ EXPECT_TRUE(read) << "Failed reading file: " << path.value() << std::endl;
+ if (!read)
+ return false; // Couldn't read the file.
+ }
+
+ // Note: we don't handle really large files (more than size_t can hold)
+ // so we will fail in that case.
+ size_t expected_size = static_cast<size_t>(file_size);
+
+ // Check the size.
+ EXPECT_EQ(expected_size, file_contents.size());
+ if (expected_size != file_contents.size())
+ return false;
+
+ // Check the contents.
+ EXPECT_EQ(value, file_contents);
+ if (memcmp(file_contents.c_str(), value.c_str(), expected_size) != 0)
+ return false;
+
+ return true;
+ }
+
+ // Start a download and return the item.
+ DownloadItem* StartDownloadAndReturnItem(Shell* shell, GURL url) {
+ std::unique_ptr<DownloadCreateObserver> observer(
+ new DownloadCreateObserver(DownloadManagerForShell(shell)));
+ shell->LoadURL(url);
+ return observer->WaitForFinished();
+ }
+
+ private:
+ static void EnsureNoPendingDownloadJobsOnIO(bool* result) {
+ if (net::URLRequestSlowDownloadJob::NumberOutstandingRequests())
+ *result = false;
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::MessageLoop::current()->QuitWhenIdleClosure());
+ }
+
+ // Location of the downloads directory for these tests
+ base::ScopedTempDir downloads_directory_;
+ std::unique_ptr<TestShellDownloadManagerDelegate> test_delegate_;
+};
+
+} // namespace
+
+// Check that downloading a single file works.
+IN_PROC_BROWSER_TEST_F(DevToolsDownloadContentTest, SingleDownload) {
+ base::ThreadRestrictions::SetIOAllowed(true);
+ SetupEnsureNoPendingDownloads();
+ NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
+ Attach();
+
+ SetDownloadBehavior("allow", "download");
+ // Create a download, wait until it's started, and confirm
+ // we're in the expected state.
+ DownloadItem* download = StartDownloadAndReturnItem(
+ shell(),
+ GURL(net::URLRequestMockHTTPJob::GetMockUrl("download-test.lib")));
+ ASSERT_EQ(DownloadItem::IN_PROGRESS, download->GetState());
+
+ WaitForCompletion(download);
+ ASSERT_EQ(DownloadItem::COMPLETE, download->GetState());
+}
+
+// Check that downloads can be cancelled gracefully.
+IN_PROC_BROWSER_TEST_F(DevToolsDownloadContentTest, DownloadCancelled) {
+ base::ThreadRestrictions::SetIOAllowed(true);
+ SetupEnsureNoPendingDownloads();
+ NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
+ Attach();
+
+ SetDownloadBehavior("allow", "download");
+ // Create a download, wait until it's started, and confirm
+ // we're in the expected state.
+ DownloadItem* download = StartDownloadAndReturnItem(
+ shell(), GURL(net::URLRequestSlowDownloadJob::kUnknownSizeUrl));
+ ASSERT_EQ(DownloadItem::IN_PROGRESS, download->GetState());
+
+ // Cancel the download and wait for download system quiesce.
+ download->Cancel(true);
+ scoped_refptr<DownloadTestFlushObserver> flush_observer(
+ new DownloadTestFlushObserver(DownloadManagerForShell(shell())));
+ flush_observer->WaitForFlush();
+
+ // Get the important info from other threads and check it.
+ EXPECT_TRUE(EnsureNoPendingDownloads());
+}
+
+// Check that denying downloads works.
+IN_PROC_BROWSER_TEST_F(DevToolsDownloadContentTest, DeniedDownload) {
+ base::ThreadRestrictions::SetIOAllowed(true);
+ SetupEnsureNoPendingDownloads();
+ NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
+ Attach();
+
+ SetDownloadBehavior("deny");
+ // Create a download, wait and confirm it was cancelled.
+ DownloadItem* download = StartDownloadAndReturnItem(
+ shell(),
+ GURL(net::URLRequestMockHTTPJob::GetMockUrl("download-test.lib")));
+ EnsureNoPendingDownloads();
+ ASSERT_EQ(DownloadItem::CANCELLED, download->GetState());
+}
+
+// Check that defaulting downloads works as expected.
+IN_PROC_BROWSER_TEST_F(DevToolsDownloadContentTest, DefaultDownload) {
+ base::ThreadRestrictions::SetIOAllowed(true);
+ SetupEnsureNoPendingDownloads();
+ NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
+ Attach();
+
+ SetDownloadBehavior("default");
+ // Create a download, wait until it's started, and confirm
+ // we're in the expected state.
+ DownloadItem* download = StartDownloadAndReturnItem(
+ shell(), GURL(net::URLRequestSlowDownloadJob::kUnknownSizeUrl));
+ ASSERT_EQ(DownloadItem::IN_PROGRESS, download->GetState());
+
+ // Cancel the download and wait for download system quiesce.
+ download->Cancel(true);
+ scoped_refptr<DownloadTestFlushObserver> flush_observer(
+ new DownloadTestFlushObserver(DownloadManagerForShell(shell())));
+ flush_observer->WaitForFlush();
+
+ // Get the important info from other threads and check it.
+ EXPECT_TRUE(EnsureNoPendingDownloads());
+}
+
+// Check that defaulting downloads works as expected when there's no proxy
+// download delegate.
+IN_PROC_BROWSER_TEST_F(DevToolsDownloadContentTest, DefaultDownloadHeadless) {
+ base::ThreadRestrictions::SetIOAllowed(true);
+ SetupEnsureNoPendingDownloads();
+ NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
+ Attach();
+ RemoveShellDelegate(shell());
+
+ SetDownloadBehavior("default");
+ // Create a download, wait and confirm it was cancelled.
+ DownloadItem* download = StartDownloadAndReturnItem(
+ shell(),
+ GURL(net::URLRequestMockHTTPJob::GetMockUrl("download-test.lib")));
+ EnsureNoPendingDownloads();
+ ASSERT_EQ(DownloadItem::CANCELLED, download->GetState());
+}
+
+// Check that download logic is reset when creating a new target.
+IN_PROC_BROWSER_TEST_F(DevToolsDownloadContentTest, ResetDownloadState) {
+ base::ThreadRestrictions::SetIOAllowed(true);
+ SetupEnsureNoPendingDownloads();
+ NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
+ Attach();
+
+ SetDownloadBehavior("deny");
+
+ Shell* new_window = CreateBrowser();
+ NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
+ // Create a download, wait and confirm it wasn't cancelled.
+ DownloadItem* download = StartDownloadAndReturnItem(
+ new_window,
+ GURL(net::URLRequestMockHTTPJob::GetMockUrl("download-test.lib")));
+ WaitForCompletion(download);
+ ASSERT_EQ(DownloadItem::COMPLETE, download->GetState());
+}
+
+// Check that downloading multiple (in this case, 2) files does not result in
+// corrupted files.
+IN_PROC_BROWSER_TEST_F(DevToolsDownloadContentTest, MultiDownload) {
+ base::ThreadRestrictions::SetIOAllowed(true);
+ SetupEnsureNoPendingDownloads();
+ NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
+ Attach();
+
+ SetDownloadBehavior("allow", "download1");
+ // Create a download, wait until it's started, and confirm
+ // we're in the expected state.
+ DownloadItem* download1 = StartDownloadAndReturnItem(
+ shell(), GURL(net::URLRequestSlowDownloadJob::kUnknownSizeUrl));
+ ASSERT_EQ(DownloadItem::IN_PROGRESS, download1->GetState());
+
+ NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
+ SetDownloadBehavior("allow", "download2");
+ // Start the second download and wait until it's done.
+ GURL url(net::URLRequestMockHTTPJob::GetMockUrl("download-test.lib"));
+ DownloadItem* download2 = StartDownloadAndReturnItem(shell(), url);
+ WaitForCompletion(download2);
+
+ ASSERT_EQ(DownloadItem::IN_PROGRESS, download1->GetState());
+ ASSERT_EQ(DownloadItem::COMPLETE, download2->GetState());
+
+ // Allow the first request to finish.
+ std::unique_ptr<DownloadTestObserver> observer2(CreateWaiter(shell(), 1));
+ NavigateToURL(shell(),
+ GURL(net::URLRequestSlowDownloadJob::kFinishDownloadUrl));
+ observer2->WaitForFinished(); // Wait for the third request.
+ EXPECT_EQ(1u, observer2->NumDownloadsSeenInState(DownloadItem::COMPLETE));
+
+ // Get the important info from other threads and check it.
+ EXPECT_TRUE(EnsureNoPendingDownloads());
+
+ // The |DownloadItem|s should now be done and have the final file names.
+ // Verify that the files have the expected data and size.
+ // |file1| should be full of '*'s, and |file2| should be the same as the
+ // source file.
+ base::FilePath file1(download1->GetTargetFilePath());
+ ASSERT_EQ(file1.DirName().MaybeAsASCII(), "download1");
+ size_t file_size1 = net::URLRequestSlowDownloadJob::kFirstDownloadSize +
+ net::URLRequestSlowDownloadJob::kSecondDownloadSize;
+ std::string expected_contents(file_size1, '*');
+ ASSERT_TRUE(VerifyFile(file1, expected_contents, file_size1));
+
+ base::FilePath file2(download2->GetTargetFilePath());
+ ASSERT_EQ(file2.DirName().MaybeAsASCII(), "download2");
+ ASSERT_TRUE(base::ContentsEqual(
+ file2, GetTestFilePath("download", "download-test.lib")));
+}
+#endif // !defined(ANDROID)
} // namespace content
diff --git a/chromium/content/browser/devtools/protocol/emulation_handler.cc b/chromium/content/browser/devtools/protocol/emulation_handler.cc
index e9d47092e23..db96d1baae2 100644
--- a/chromium/content/browser/devtools/protocol/emulation_handler.cc
+++ b/chromium/content/browser/devtools/protocol/emulation_handler.cc
@@ -9,12 +9,14 @@
#include "base/strings/string_number_conversions.h"
#include "build/build_config.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/public/common/url_constants.h"
#include "device/geolocation/geolocation_context.h"
#include "device/geolocation/geoposition.h"
+#include "ui/events/gesture_detection/gesture_provider_config_helper.h"
namespace content {
namespace protocol {
@@ -42,11 +44,11 @@ ui::GestureProviderConfigType TouchEmulationConfigurationToType(
ui::GestureProviderConfigType result =
ui::GestureProviderConfigType::CURRENT_PLATFORM;
if (protocol_value ==
- Emulation::SetTouchEmulationEnabled::ConfigurationEnum::Mobile) {
+ Emulation::SetEmitTouchEventsForMouse::ConfigurationEnum::Mobile) {
result = ui::GestureProviderConfigType::GENERIC_MOBILE;
}
if (protocol_value ==
- Emulation::SetTouchEmulationEnabled::ConfigurationEnum::Desktop) {
+ Emulation::SetEmitTouchEventsForMouse::ConfigurationEnum::Desktop) {
result = ui::GestureProviderConfigType::GENERIC_DESKTOP;
}
return result;
@@ -69,7 +71,8 @@ void EmulationHandler::SetRenderFrameHost(RenderFrameHostImpl* host) {
return;
host_ = host;
- UpdateTouchEventEmulationState();
+ if (touch_emulation_enabled_)
+ UpdateTouchEventEmulationState();
UpdateDeviceEmulationState();
}
@@ -78,9 +81,11 @@ void EmulationHandler::Wire(UberDispatcher* dispatcher) {
}
Response EmulationHandler::Disable() {
- touch_emulation_enabled_ = false;
+ if (touch_emulation_enabled_) {
+ touch_emulation_enabled_ = false;
+ UpdateTouchEventEmulationState();
+ }
device_emulation_enabled_ = false;
- UpdateTouchEventEmulationState();
UpdateDeviceEmulationState();
return Response::OK();
}
@@ -117,12 +122,13 @@ Response EmulationHandler::ClearGeolocationOverride() {
return Response::OK();
}
-Response EmulationHandler::SetTouchEmulationEnabled(
- bool enabled, Maybe<std::string> configuration) {
+Response EmulationHandler::SetEmitTouchEventsForMouse(
+ bool enabled,
+ Maybe<std::string> configuration) {
touch_emulation_enabled_ = enabled;
touch_emulation_configuration_ = configuration.fromMaybe("");
UpdateTouchEventEmulationState();
- return Response::FallThrough();
+ return Response::OK();
}
Response EmulationHandler::CanEmulate(bool* result) {
@@ -242,6 +248,7 @@ Response EmulationHandler::ClearDeviceMetricsOverride() {
return Response::OK();
device_emulation_enabled_ = false;
+ device_emulation_params_ = blink::WebDeviceEmulationParams();
if (original_view_size_.width())
widget_host->GetView()->SetSize(original_view_size_);
original_view_size_ = gfx::Size();
@@ -269,6 +276,8 @@ blink::WebDeviceEmulationParams EmulationHandler::GetDeviceEmulationParams() {
void EmulationHandler::SetDeviceEmulationParams(
const blink::WebDeviceEmulationParams& params) {
+ bool enabled = params != blink::WebDeviceEmulationParams();
+ device_emulation_enabled_ = enabled;
device_emulation_params_ = params;
UpdateDeviceEmulationState();
}
@@ -284,12 +293,17 @@ void EmulationHandler::UpdateTouchEventEmulationState() {
host_ ? host_->GetRenderWidgetHost() : nullptr;
if (!widget_host)
return;
- bool enabled = touch_emulation_enabled_;
- ui::GestureProviderConfigType config_type =
- TouchEmulationConfigurationToType(touch_emulation_configuration_);
- widget_host->SetTouchEventEmulationEnabled(enabled, config_type);
- if (GetWebContents())
- GetWebContents()->SetForceDisableOverscrollContent(enabled);
+ if (touch_emulation_enabled_) {
+ widget_host->GetTouchEmulator()->Enable(
+ TouchEmulator::Mode::kEmulatingTouchFromMouse,
+ TouchEmulationConfigurationToType(touch_emulation_configuration_));
+ } else {
+ widget_host->GetTouchEmulator()->Disable();
+ }
+ if (GetWebContents()) {
+ GetWebContents()->SetForceDisableOverscrollContent(
+ touch_emulation_enabled_);
+ }
}
void EmulationHandler::UpdateDeviceEmulationState() {
diff --git a/chromium/content/browser/devtools/protocol/emulation_handler.h b/chromium/content/browser/devtools/protocol/emulation_handler.h
index 671724b6b2a..582debc47e4 100644
--- a/chromium/content/browser/devtools/protocol/emulation_handler.h
+++ b/chromium/content/browser/devtools/protocol/emulation_handler.h
@@ -32,8 +32,9 @@ class EmulationHandler : public DevToolsDomainHandler,
Maybe<double> accuracy) override;
Response ClearGeolocationOverride() override;
- Response SetTouchEmulationEnabled(bool enabled,
- Maybe<std::string> configuration) override;
+ Response SetEmitTouchEventsForMouse(
+ bool enabled,
+ Maybe<std::string> configuration) override;
Response CanEmulate(bool* result) override;
Response SetDeviceMetricsOverride(
diff --git a/chromium/content/browser/devtools/protocol/input_handler.cc b/chromium/content/browser/devtools/protocol/input_handler.cc
index 0e517ca0d47..dfdd4b9e73d 100644
--- a/chromium/content/browser/devtools/protocol/input_handler.cc
+++ b/chromium/content/browser/devtools/protocol/input_handler.cc
@@ -12,13 +12,17 @@
#include "base/trace_event/trace_event.h"
#include "cc/output/compositor_frame_metadata.h"
#include "content/browser/devtools/devtools_session.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"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/common/input/synthetic_pinch_gesture_params.h"
#include "content/common/input/synthetic_smooth_scroll_gesture_params.h"
#include "content/common/input/synthetic_tap_gesture_params.h"
-#include "third_party/WebKit/public/platform/WebInputEvent.h"
+#include "content/public/common/content_features.h"
+#include "ui/events/base_event_utils.h"
#include "ui/events/blink/web_input_event_traits.h"
+#include "ui/events/gesture_detection/gesture_provider_config_helper.h"
#include "ui/events/keycodes/dom/keycode_converter.h"
#include "ui/gfx/geometry/point.h"
@@ -133,9 +137,55 @@ blink::WebInputEvent::Type GetMouseEventType(const std::string& type) {
return blink::WebInputEvent::kMouseUp;
if (type == Input::DispatchMouseEvent::TypeEnum::MouseMoved)
return blink::WebInputEvent::kMouseMove;
+ if (type == Input::DispatchMouseEvent::TypeEnum::MouseWheel)
+ return blink::WebInputEvent::kMouseWheel;
return blink::WebInputEvent::kUndefined;
}
+blink::WebInputEvent::Type GetTouchEventType(const std::string& type) {
+ if (type == Input::DispatchTouchEvent::TypeEnum::TouchStart)
+ return blink::WebInputEvent::kTouchStart;
+ if (type == Input::DispatchTouchEvent::TypeEnum::TouchEnd)
+ return blink::WebInputEvent::kTouchEnd;
+ if (type == Input::DispatchTouchEvent::TypeEnum::TouchMove)
+ return blink::WebInputEvent::kTouchMove;
+ if (type == Input::DispatchTouchEvent::TypeEnum::TouchCancel)
+ return blink::WebInputEvent::kTouchCancel;
+ return blink::WebInputEvent::kUndefined;
+}
+
+bool GenerateTouchPoints(
+ blink::WebTouchEvent* event,
+ blink::WebInputEvent::Type type,
+ const base::flat_map<int, blink::WebTouchPoint>& points,
+ const blink::WebTouchPoint& changing) {
+ event->touches_length = 1;
+ event->touches[0] = changing;
+ for (auto& it : points) {
+ if (it.first == changing.id)
+ continue;
+ if (event->touches_length == blink::WebTouchEvent::kTouchesLengthCap)
+ return false;
+ event->touches[event->touches_length] = it.second;
+ event->touches[event->touches_length].state =
+ blink::WebTouchPoint::kStateStationary;
+ event->touches_length++;
+ }
+ if (type != blink::WebInputEvent::kUndefined) {
+ event->touches[0].state = type == blink::WebInputEvent::kTouchCancel
+ ? blink::WebTouchPoint::kStateCancelled
+ : blink::WebTouchPoint::kStateReleased;
+ event->SetType(type);
+ } else if (points.find(changing.id) == points.end()) {
+ event->touches[0].state = blink::WebTouchPoint::kStatePressed;
+ event->SetType(blink::WebInputEvent::kTouchStart);
+ } else {
+ event->touches[0].state = blink::WebTouchPoint::kStateMoved;
+ event->SetType(blink::WebInputEvent::kTouchMove);
+ }
+ return true;
+}
+
void SendSynthesizePinchGestureResponse(
std::unique_ptr<Input::Backend::SynthesizePinchGestureCallback> callback,
SyntheticGesture::Result result) {
@@ -198,8 +248,7 @@ InputHandler::InputHandler()
input_queued_(false),
page_scale_factor_(1.0),
last_id_(0),
- weak_factory_(this) {
-}
+ weak_factory_(this) {}
InputHandler::~InputHandler() {
}
@@ -212,7 +261,9 @@ std::vector<InputHandler*> InputHandler::ForAgentHost(
}
void InputHandler::SetRenderFrameHost(RenderFrameHostImpl* host) {
- ClearPendingKeyAndMouseCallbacks();
+ if (host == host_)
+ return;
+ ClearInputState();
if (host_) {
host_->GetRenderWidgetHost()->RemoveInputEventObserver(this);
if (ignore_input_events_)
@@ -235,10 +286,14 @@ void InputHandler::OnInputEventAck(const blink::WebInputEvent& event) {
!pending_key_callbacks_.empty()) {
pending_key_callbacks_.front()->sendSuccess();
pending_key_callbacks_.pop_front();
- } else if (blink::WebInputEvent::IsMouseEventType(event.GetType()) &&
- !pending_mouse_callbacks_.empty()) {
+ return;
+ }
+ if ((blink::WebInputEvent::IsMouseEventType(event.GetType()) ||
+ event.GetType() == blink::WebInputEvent::kMouseWheel) &&
+ !pending_mouse_callbacks_.empty()) {
pending_mouse_callbacks_.front()->sendSuccess();
pending_mouse_callbacks_.pop_front();
+ return;
}
}
@@ -253,13 +308,14 @@ void InputHandler::OnSwapCompositorFrame(
}
Response InputHandler::Disable() {
- ClearPendingKeyAndMouseCallbacks();
+ ClearInputState();
if (host_) {
host_->GetRenderWidgetHost()->RemoveInputEventObserver(this);
if (ignore_input_events_)
host_->GetRenderWidgetHost()->SetIgnoreInputEvents(false);
}
ignore_input_events_ = false;
+ touch_points_.clear();
return Response::OK();
}
@@ -300,7 +356,7 @@ void InputHandler::DispatchKeyEvent(
auto_repeat.fromMaybe(false),
is_keypad.fromMaybe(false)),
GetEventTimeTicks(std::move(timestamp)));
- event.skip_in_browser = true;
+
if (!SetKeyboardEventText(event.text, std::move(text))) {
callback->sendFailure(Response::InvalidParams("Invalid 'text' parameter"));
return;
@@ -334,6 +390,13 @@ void InputHandler::DispatchKeyEvent(
return;
}
+ // We do not pass events to browser if there is no native key event
+ // due to Mac needing the actual os_event.
+ if (event.native_key_code)
+ event.os_event = NativeInputEventBuilder::CreateEvent(event);
+ else
+ event.skip_in_browser = true;
+
host_->GetRenderWidgetHost()->Focus();
input_queued_ = false;
pending_key_callbacks_.push_back(std::move(callback));
@@ -345,56 +408,226 @@ void InputHandler::DispatchKeyEvent(
}
void InputHandler::DispatchMouseEvent(
- const std::string& type,
+ const std::string& event_type,
double x,
double y,
- Maybe<int> modifiers,
- Maybe<double> timestamp,
- Maybe<std::string> button,
+ Maybe<int> maybe_modifiers,
+ Maybe<double> maybe_timestamp,
+ Maybe<std::string> maybe_button,
Maybe<int> click_count,
+ Maybe<double> delta_x,
+ Maybe<double> delta_y,
std::unique_ptr<DispatchMouseEventCallback> callback) {
- blink::WebInputEvent::Type event_type = GetMouseEventType(type);
- if (event_type == blink::WebInputEvent::kUndefined) {
+ blink::WebInputEvent::Type type = GetMouseEventType(event_type);
+ if (type == blink::WebInputEvent::kUndefined) {
callback->sendFailure(Response::InvalidParams(
- base::StringPrintf("Unexpected event type '%s'", type.c_str())));
+ base::StringPrintf("Unexpected event type '%s'", event_type.c_str())));
return;
}
- blink::WebPointerProperties::Button event_button =
+
+ blink::WebPointerProperties::Button button =
blink::WebPointerProperties::Button::kNoButton;
int button_modifiers = 0;
- if (!GetMouseEventButton(button.fromMaybe(""), &event_button,
+ if (!GetMouseEventButton(maybe_button.fromMaybe(""), &button,
&button_modifiers)) {
callback->sendFailure(Response::InvalidParams("Invalid mouse button"));
return;
}
- blink::WebMouseEvent event(
- event_type,
- GetEventModifiers(modifiers.fromMaybe(blink::WebInputEvent::kNoModifiers),
- false, false) |
- button_modifiers,
- GetEventTimestamp(std::move(timestamp)));
+ int modifiers = GetEventModifiers(
+ maybe_modifiers.fromMaybe(blink::WebInputEvent::kNoModifiers), false,
+ false);
+ modifiers |= button_modifiers;
+ double timestamp = GetEventTimestamp(std::move(maybe_timestamp));
- event.button = event_button;
- event.SetPositionInWidget(x * page_scale_factor_, y * page_scale_factor_);
- event.SetPositionInScreen(x * page_scale_factor_, y * page_scale_factor_);
- event.click_count = click_count.fromMaybe(0);
- event.pointer_type = blink::WebPointerProperties::PointerType::kMouse;
+ std::unique_ptr<blink::WebMouseEvent, ui::WebInputEventDeleter> mouse_event;
+ blink::WebMouseWheelEvent* wheel_event = nullptr;
- if (!host_ || !host_->GetRenderWidgetHost())
+ if (type == blink::WebInputEvent::kMouseWheel) {
+ wheel_event = new blink::WebMouseWheelEvent(type, modifiers, timestamp);
+ mouse_event.reset(wheel_event);
+ if (!delta_x.isJust() || !delta_y.isJust()) {
+ callback->sendFailure(Response::InvalidParams(
+ "'deltaX' and 'deltaY' are expected for mouseWheel event"));
+ return;
+ }
+ wheel_event->delta_x = static_cast<float>(-delta_x.fromJust());
+ wheel_event->delta_y = static_cast<float>(-delta_y.fromJust());
+ if (base::FeatureList::IsEnabled(
+ features::kTouchpadAndWheelScrollLatching)) {
+ wheel_event->phase = blink::WebMouseWheelEvent::kPhaseBegan;
+ wheel_event->dispatch_type = blink::WebInputEvent::kBlocking;
+ }
+ } else {
+ mouse_event.reset(new blink::WebMouseEvent(type, modifiers, timestamp));
+ }
+
+ mouse_event->button = button;
+ mouse_event->SetPositionInWidget(x * page_scale_factor_,
+ y * page_scale_factor_);
+ mouse_event->SetPositionInScreen(x * page_scale_factor_,
+ y * page_scale_factor_);
+ mouse_event->click_count = click_count.fromMaybe(0);
+ mouse_event->pointer_type = blink::WebPointerProperties::PointerType::kMouse;
+
+ if (!host_ || !host_->GetRenderWidgetHost()) {
callback->sendFailure(Response::InternalError());
+ return;
+ }
host_->GetRenderWidgetHost()->Focus();
input_queued_ = false;
pending_mouse_callbacks_.push_back(std::move(callback));
- host_->GetRenderWidgetHost()->ForwardMouseEvent(event);
- // MouseUp/Down events don't create a round-trip to the renderer, so there's
- // no point in blocking the response until an ack is received. Only wait for
- // an ack if we're synthesizing a MouseMove event, which does make a
- // round-trip to the renderer.
- if (event_type != blink::WebInputEvent::kMouseMove || !input_queued_) {
+ if (wheel_event)
+ host_->GetRenderWidgetHost()->ForwardWheelEvent(*wheel_event);
+ else
+ host_->GetRenderWidgetHost()->ForwardMouseEvent(*mouse_event);
+ if (!input_queued_) {
pending_mouse_callbacks_.back()->sendSuccess();
pending_mouse_callbacks_.pop_back();
+ } else if (wheel_event && base::FeatureList::IsEnabled(
+ features::kTouchpadAndWheelScrollLatching)) {
+ // Send a synthetic wheel event with phaseEnded to finish scrolling.
+ wheel_event->delta_x = 0;
+ wheel_event->delta_y = 0;
+ wheel_event->phase = blink::WebMouseWheelEvent::kPhaseEnded;
+ wheel_event->dispatch_type = blink::WebInputEvent::kEventNonBlocking;
+ host_->GetRenderWidgetHost()->ForwardWheelEvent(*wheel_event);
+ }
+}
+
+void InputHandler::DispatchTouchEvent(
+ const std::string& event_type,
+ std::unique_ptr<Array<Input::TouchPoint>> touch_points,
+ protocol::Maybe<int> maybe_modifiers,
+ protocol::Maybe<double> maybe_timestamp,
+ std::unique_ptr<DispatchTouchEventCallback> callback) {
+ blink::WebInputEvent::Type type = GetTouchEventType(event_type);
+ if (type == blink::WebInputEvent::kUndefined) {
+ callback->sendFailure(Response::InvalidParams(
+ base::StringPrintf("Unexpected event type '%s'", event_type.c_str())));
+ return;
+ }
+
+ int modifiers = GetEventModifiers(
+ maybe_modifiers.fromMaybe(blink::WebInputEvent::kNoModifiers), false,
+ false);
+ double timestamp = GetEventTimestamp(std::move(maybe_timestamp));
+
+ if ((type == blink::WebInputEvent::kTouchStart ||
+ type == blink::WebInputEvent::kTouchMove) &&
+ touch_points->length() == 0) {
+ callback->sendFailure(Response::InvalidParams(
+ "TouchStart and TouchMove must have at least one touch point."));
+ return;
+ }
+ if ((type == blink::WebInputEvent::kTouchEnd ||
+ type == blink::WebInputEvent::kTouchCancel) &&
+ touch_points->length() > 0) {
+ callback->sendFailure(Response::InvalidParams(
+ "TouchEnd and TouchCancel must not have any touch points."));
+ return;
+ }
+ if (type == blink::WebInputEvent::kTouchStart && !touch_points_.empty()) {
+ callback->sendFailure(Response::InvalidParams(
+ "Must have no prior active touch points to start a new touch."));
+ return;
+ }
+ if (type != blink::WebInputEvent::kTouchStart && touch_points_.empty()) {
+ callback->sendFailure(Response::InvalidParams(
+ "Must send a TouchStart first to start a new touch."));
+ return;
+ }
+
+ base::flat_map<int, blink::WebTouchPoint> points;
+ size_t with_id = 0;
+ for (size_t i = 0; i < touch_points->length(); ++i) {
+ Input::TouchPoint* point = touch_points->get(i);
+ int id = point->GetId(i);
+ if (point->HasId())
+ with_id++;
+ points[id].id = id;
+ points[id].radius_x = point->GetRadiusX(1);
+ points[id].radius_y = point->GetRadiusY(1);
+ points[id].rotation_angle = point->GetRotationAngle(0.0);
+ points[id].force = point->GetForce(1.0);
+ points[id].pointer_type = blink::WebPointerProperties::PointerType::kTouch;
+ points[id].SetPositionInWidget(point->GetX() * page_scale_factor_,
+ point->GetY() * page_scale_factor_);
+ points[id].SetPositionInScreen(point->GetX() * page_scale_factor_,
+ point->GetY() * page_scale_factor_);
+ }
+ if (with_id > 0 && with_id < touch_points->length()) {
+ callback->sendFailure(Response::InvalidParams(
+ "All or none of the provided TouchPoints must supply ids."));
+ return;
+ }
+
+ if (!host_ || !host_->GetRenderWidgetHost()) {
+ callback->sendFailure(Response::InternalError());
+ return;
+ }
+
+ std::vector<blink::WebTouchEvent> events;
+ bool ok = true;
+ for (auto& id_point : points) {
+ if (touch_points_.find(id_point.first) != touch_points_.end())
+ continue;
+ events.emplace_back(type, modifiers, timestamp);
+ ok &= GenerateTouchPoints(&events.back(), blink::WebInputEvent::kUndefined,
+ touch_points_, id_point.second);
+ touch_points_.insert(id_point);
+ }
+ for (auto& id_point : points) {
+ DCHECK(touch_points_.find(id_point.first) != touch_points_.end());
+ if (touch_points_[id_point.first].PositionInWidget() ==
+ id_point.second.PositionInWidget()) {
+ continue;
+ }
+ events.emplace_back(type, modifiers, timestamp);
+ ok &= GenerateTouchPoints(&events.back(), blink::WebInputEvent::kUndefined,
+ touch_points_, id_point.second);
+ touch_points_[id_point.first] = id_point.second;
+ }
+ if (type != blink::WebInputEvent::kTouchCancel)
+ type = blink::WebInputEvent::kTouchEnd;
+ for (auto it = touch_points_.begin(); it != touch_points_.end();) {
+ if (points.find(it->first) != points.end()) {
+ it++;
+ continue;
+ }
+ events.emplace_back(type, modifiers, timestamp);
+ ok &= GenerateTouchPoints(&events.back(), type, touch_points_, it->second);
+ it = touch_points_.erase(it);
+ }
+ if (!ok) {
+ callback->sendFailure(Response::Error(
+ base::StringPrintf("Exceeded maximum touch points limit of %d",
+ blink::WebTouchEvent::kTouchesLengthCap)));
+ return;
+ }
+
+ if (events.empty()) {
+ callback->sendSuccess();
+ return;
+ }
+
+ host_->GetRenderWidgetHost()->Focus();
+ host_->GetRenderWidgetHost()->GetTouchEmulator()->Enable(
+ TouchEmulator::Mode::kInjectingTouchEvents,
+ ui::GestureProviderConfigType::CURRENT_PLATFORM);
+ base::OnceClosure closure = base::BindOnce(
+ &DispatchTouchEventCallback::sendSuccess, std::move(callback));
+ for (size_t i = 0; i < events.size(); i++) {
+ events[i].dispatch_type =
+ events[i].GetType() == blink::WebInputEvent::kTouchCancel
+ ? blink::WebInputEvent::kEventNonBlocking
+ : blink::WebInputEvent::kBlocking;
+ events[i].moved_beyond_slop_region = true;
+ events[i].unique_touch_event_id = ui::GetNextTouchEventId();
+ host_->GetRenderWidgetHost()->GetTouchEmulator()->InjectTouchEvent(
+ events[i],
+ i == events.size() - 1 ? std::move(closure) : base::OnceClosure());
}
}
@@ -612,10 +845,10 @@ void InputHandler::OnScrollFinished(
if (repeat_count > 0) {
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE,
- base::Bind(&InputHandler::SynthesizeRepeatingScroll,
- weak_factory_.GetWeakPtr(), gesture_params, repeat_count - 1,
- repeat_delay, interaction_marker_name, id,
- base::Passed(std::move(callback))),
+ base::BindOnce(&InputHandler::SynthesizeRepeatingScroll,
+ weak_factory_.GetWeakPtr(), gesture_params,
+ repeat_count - 1, repeat_delay, interaction_marker_name,
+ id, base::Passed(std::move(callback))),
repeat_delay);
} else {
SendSynthesizeScrollGestureResponse(std::move(callback), result);
@@ -670,13 +903,15 @@ void InputHandler::SynthesizeTapGesture(
}
}
-void InputHandler::ClearPendingKeyAndMouseCallbacks() {
+void InputHandler::ClearInputState() {
for (auto& callback : pending_key_callbacks_)
callback->sendSuccess();
pending_key_callbacks_.clear();
for (auto& callback : pending_mouse_callbacks_)
callback->sendSuccess();
pending_mouse_callbacks_.clear();
+ // TODO(dgozman): cleanup touch callbacks as well?
+ touch_points_.clear();
}
bool InputHandler::PointIsWithinContents(gfx::PointF point) const {
diff --git a/chromium/content/browser/devtools/protocol/input_handler.h b/chromium/content/browser/devtools/protocol/input_handler.h
index ec1e10d84e1..e14d78f89d1 100644
--- a/chromium/content/browser/devtools/protocol/input_handler.h
+++ b/chromium/content/browser/devtools/protocol/input_handler.h
@@ -5,6 +5,7 @@
#ifndef CONTENT_BROWSER_DEVTOOLS_PROTOCOL_INPUT_HANDLER_H_
#define CONTENT_BROWSER_DEVTOOLS_PROTOCOL_INPUT_HANDLER_H_
+#include "base/containers/flat_map.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "content/browser/devtools/protocol/devtools_domain_handler.h"
@@ -12,6 +13,7 @@
#include "content/browser/renderer_host/input/synthetic_gesture.h"
#include "content/common/input/synthetic_smooth_scroll_gesture_params.h"
#include "content/public/browser/render_widget_host.h"
+#include "third_party/WebKit/public/platform/WebInputEvent.h"
#include "ui/gfx/geometry/size_f.h"
namespace cc {
@@ -63,8 +65,17 @@ class InputHandler : public DevToolsDomainHandler,
Maybe<double> timestamp,
Maybe<std::string> button,
Maybe<int> click_count,
+ Maybe<double> delta_x,
+ Maybe<double> delta_y,
std::unique_ptr<DispatchMouseEventCallback> callback) override;
+ void DispatchTouchEvent(
+ const std::string& type,
+ std::unique_ptr<Array<Input::TouchPoint>> touch_points,
+ protocol::Maybe<int> modifiers,
+ protocol::Maybe<double> timestamp,
+ std::unique_ptr<DispatchTouchEventCallback> callback) override;
+
Response EmulateTouchFromMouseEvent(const std::string& type,
int x,
int y,
@@ -130,7 +141,7 @@ class InputHandler : public DevToolsDomainHandler,
std::unique_ptr<SynthesizeScrollGestureCallback> callback,
SyntheticGesture::Result result);
- void ClearPendingKeyAndMouseCallbacks();
+ void ClearInputState();
bool PointIsWithinContents(gfx::PointF point) const;
RenderFrameHostImpl* host_;
@@ -144,6 +155,7 @@ class InputHandler : public DevToolsDomainHandler,
gfx::SizeF scrollable_viewport_size_;
int last_id_;
bool ignore_input_events_ = false;
+ base::flat_map<int, blink::WebTouchPoint> touch_points_;
base::WeakPtrFactory<InputHandler> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(InputHandler);
diff --git a/chromium/content/browser/devtools/protocol/io_handler.cc b/chromium/content/browser/devtools/protocol/io_handler.cc
index ec0d49c503d..4caa0965d9d 100644
--- a/chromium/content/browser/devtools/protocol/io_handler.cc
+++ b/chromium/content/browser/devtools/protocol/io_handler.cc
@@ -12,7 +12,11 @@
#include "base/files/file_util.h"
#include "base/memory/ref_counted_memory.h"
#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "content/browser/blob_storage/chrome_blob_storage_context.h"
#include "content/browser/devtools/devtools_io_context.h"
+#include "content/browser/frame_host/render_frame_host_impl.h"
+#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
namespace content {
@@ -20,8 +24,9 @@ namespace protocol {
IOHandler::IOHandler(DevToolsIOContext* io_context)
: DevToolsDomainHandler(IO::Metainfo::domainName),
- io_context_(io_context)
- , weak_factory_(this) {}
+ io_context_(io_context),
+ host_(nullptr),
+ weak_factory_(this) {}
IOHandler::~IOHandler() {}
@@ -30,15 +35,37 @@ void IOHandler::Wire(UberDispatcher* dispatcher) {
IO::Dispatcher::wire(dispatcher, this);
}
+void IOHandler::SetRenderFrameHost(RenderFrameHostImpl* host) {
+ host_ = host;
+}
+
void IOHandler::Read(
const std::string& handle,
Maybe<int> offset,
Maybe<int> max_size,
std::unique_ptr<ReadCallback> callback) {
static const size_t kDefaultChunkSize = 10 * 1024 * 1024;
+ static const char kBlobPrefix[] = "blob:";
- scoped_refptr<DevToolsIOContext::Stream> stream =
+ scoped_refptr<DevToolsIOContext::ROStream> stream =
io_context_->GetByHandle(handle);
+ if (!stream &&
+ StartsWith(handle, kBlobPrefix, base::CompareCase::SENSITIVE)) {
+ std::string uuid = handle.substr(strlen(kBlobPrefix));
+ BrowserContext* browser_context =
+ host_ ? host_->GetSiteInstance()->GetBrowserContext() : nullptr;
+ if (browser_context) {
+ ChromeBlobStorageContext* blob_context =
+ ChromeBlobStorageContext::GetFor(browser_context);
+ StoragePartition* storage_partition = BrowserContext::GetStoragePartition(
+ browser_context, host_->GetSiteInstance());
+ if (storage_partition) {
+ stream = io_context_->OpenBlob(blob_context, storage_partition, handle,
+ uuid);
+ }
+ }
+ }
+
if (!stream) {
callback->sendFailure(Response::InvalidParams("Invalid stream handle"));
return;
@@ -51,13 +78,14 @@ void IOHandler::Read(
void IOHandler::ReadComplete(std::unique_ptr<ReadCallback> callback,
std::unique_ptr<std::string> data,
+ bool base64_encoded,
int status) {
- if (status == DevToolsIOContext::Stream::StatusFailure) {
+ if (status == DevToolsIOContext::ROStream::StatusFailure) {
callback->sendFailure(Response::Error("Read failed"));
return;
}
- bool eof = status == DevToolsIOContext::Stream::StatusEOF;
- callback->sendSuccess(std::move(*data), eof);
+ bool eof = status == DevToolsIOContext::ROStream::StatusEOF;
+ callback->sendSuccess(base64_encoded, std::move(*data), eof);
}
Response IOHandler::Close(const std::string& handle) {
diff --git a/chromium/content/browser/devtools/protocol/io_handler.h b/chromium/content/browser/devtools/protocol/io_handler.h
index 04297698f5d..066541cebf6 100644
--- a/chromium/content/browser/devtools/protocol/io_handler.h
+++ b/chromium/content/browser/devtools/protocol/io_handler.h
@@ -22,6 +22,7 @@ class IOHandler : public DevToolsDomainHandler,
~IOHandler() override;
void Wire(UberDispatcher* dispatcher) override;
+ void SetRenderFrameHost(RenderFrameHostImpl* host) override;
// Protocol methods.
void Read(
@@ -34,10 +35,12 @@ class IOHandler : public DevToolsDomainHandler,
private:
void ReadComplete(std::unique_ptr<ReadCallback> callback,
std::unique_ptr<std::string> data,
+ bool base64_encoded,
int status);
std::unique_ptr<IO::Frontend> frontend_;
DevToolsIOContext* io_context_;
+ RenderFrameHostImpl* host_;
base::WeakPtrFactory<IOHandler> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(IOHandler);
@@ -46,4 +49,4 @@ class IOHandler : public DevToolsDomainHandler,
} // namespace protocol
} // namespace content
-#endif // CONTENT_BROWSER_DEVTOOLS_PROTOCOL_TRACING_HANDLER_H_
+#endif // CONTENT_BROWSER_DEVTOOLS_PROTOCOL_IO_HANDLER_H_
diff --git a/chromium/content/browser/devtools/protocol/native_input_event_builder.h b/chromium/content/browser/devtools/protocol/native_input_event_builder.h
new file mode 100644
index 00000000000..e766e03756d
--- /dev/null
+++ b/chromium/content/browser/devtools/protocol/native_input_event_builder.h
@@ -0,0 +1,30 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_DEVTOOLS_PROTOCOL_NATIVE_INPUT_EVENT_BUILDER_H_
+#define CONTENT_BROWSER_DEVTOOLS_PROTOCOL_NATIVE_INPUT_EVENT_BUILDER_H_
+
+#include "content/public/browser/native_web_keyboard_event.h"
+
+namespace content {
+namespace protocol {
+
+class NativeInputEventBuilder {
+ public:
+#if defined(OS_MACOSX)
+ // This returned object has a retain count of 1.
+ static gfx::NativeEvent CreateEvent(const NativeWebKeyboardEvent& event);
+#else
+ // We only need this for Macs because they require an OS event to process
+ // some keyboard events in browser (see: crbug.com/667387).
+ static gfx::NativeEvent CreateEvent(const NativeWebKeyboardEvent& event) {
+ return nullptr;
+ }
+#endif
+};
+
+} // namespace protocol
+} // namespace content
+
+#endif // CONTENT_BROWSER_DEVTOOLS_PROTOCOL_NATIVE_INPUT_EVENT_BUILDER_H_
diff --git a/chromium/content/browser/devtools/protocol/native_input_event_builder_mac.mm b/chromium/content/browser/devtools/protocol/native_input_event_builder_mac.mm
new file mode 100644
index 00000000000..601ec197b5b
--- /dev/null
+++ b/chromium/content/browser/devtools/protocol/native_input_event_builder_mac.mm
@@ -0,0 +1,49 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <Cocoa/Cocoa.h>
+#include "base/strings/sys_string_conversions.h"
+#include "content/browser/devtools/protocol/native_input_event_builder.h"
+#include "third_party/WebKit/public/platform/WebInputEvent.h"
+
+namespace content {
+namespace protocol {
+
+// Mac requires a native event to emulate key events. This method gives
+// only crude capabilities (see: crbug.com/667387).
+// The returned object has a retain count of 1.
+gfx::NativeEvent NativeInputEventBuilder::CreateEvent(
+ const NativeWebKeyboardEvent& event) {
+ NSEventType type = NSKeyUp;
+ if (event.GetType() == blink::WebInputEvent::kRawKeyDown ||
+ event.GetType() == blink::WebInputEvent::kKeyDown)
+ type = NSKeyDown;
+ const blink::WebUChar* textStartAddr = &event.text[0];
+ const int textLength =
+ std::find(textStartAddr,
+ textStartAddr + NativeWebKeyboardEvent::kTextLengthCap, '\0') -
+ textStartAddr;
+ NSString* character =
+ base::SysUTF16ToNSString(base::string16(textStartAddr, textLength));
+ int modifiers = event.GetModifiers();
+ NSUInteger flags =
+ (modifiers & blink::WebInputEvent::kShiftKey ? NSShiftKeyMask : 0) |
+ (modifiers & blink::WebInputEvent::kControlKey ? NSControlKeyMask : 0) |
+ (modifiers & blink::WebInputEvent::kAltKey ? NSAlternateKeyMask : 0) |
+ (modifiers & blink::WebInputEvent::kMetaKey ? NSCommandKeyMask : 0);
+
+ return [[NSEvent keyEventWithType:type
+ location:NSZeroPoint
+ modifierFlags:flags
+ timestamp:0
+ windowNumber:0
+ context:nil
+ characters:character
+ charactersIgnoringModifiers:character
+ isARepeat:NO
+ keyCode:event.native_key_code] retain];
+};
+
+} // namespace protocol
+} // namespace content
diff --git a/chromium/content/browser/devtools/protocol/network_handler.cc b/chromium/content/browser/devtools/protocol/network_handler.cc
index bff4f04c84a..8b406dc568d 100644
--- a/chromium/content/browser/devtools/protocol/network_handler.cc
+++ b/chromium/content/browser/devtools/protocol/network_handler.cc
@@ -26,6 +26,8 @@
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/browsing_data_remover.h"
#include "content/public/browser/content_browser_client.h"
+#include "content/public/browser/global_request_id.h"
+#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/resource_context.h"
#include "content/public/browser/site_instance.h"
@@ -52,23 +54,11 @@ using ProtocolCookieArray = Array<Network::Cookie>;
using GetCookiesCallback = Network::Backend::GetCookiesCallback;
using GetAllCookiesCallback = Network::Backend::GetAllCookiesCallback;
using SetCookieCallback = Network::Backend::SetCookieCallback;
-using DeleteCookieCallback = Network::Backend::DeleteCookieCallback;
+using SetCookiesCallback = Network::Backend::SetCookiesCallback;
+using DeleteCookiesCallback = Network::Backend::DeleteCookiesCallback;
using ClearBrowserCookiesCallback =
Network::Backend::ClearBrowserCookiesCallback;
-net::URLRequestContext* GetRequestContextOnIO(
- ResourceContext* resource_context,
- net::URLRequestContextGetter* context_getter,
- const GURL& url) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- net::URLRequestContext* context =
- GetContentClient()->browser()->OverrideRequestContextForURL(
- url, resource_context);
- if (!context)
- context = context_getter->GetURLRequestContext();
- return context;
-}
-
class CookieRetriever : public base::RefCountedThreadSafe<CookieRetriever> {
public:
CookieRetriever(std::unique_ptr<GetCookiesCallback> callback)
@@ -80,7 +70,6 @@ class CookieRetriever : public base::RefCountedThreadSafe<CookieRetriever> {
all_callback_(std::move(callback)) {}
void RetrieveCookiesOnIO(
- ResourceContext* resource_context,
net::URLRequestContextGetter* context_getter,
const std::vector<GURL>& urls) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -93,14 +82,13 @@ class CookieRetriever : public base::RefCountedThreadSafe<CookieRetriever> {
for (const GURL& url : urls) {
net::URLRequestContext* request_context =
- GetRequestContextOnIO(resource_context, context_getter, url);
- request_context->cookie_store()->GetAllCookiesForURLAsync(url,
- base::Bind(&CookieRetriever::GotCookies, this));
+ context_getter->GetURLRequestContext();
+ request_context->cookie_store()->GetAllCookiesForURLAsync(
+ url, base::BindOnce(&CookieRetriever::GotCookies, this));
}
}
void RetrieveAllCookiesOnIO(
- ResourceContext* resource_context,
net::URLRequestContextGetter* context_getter) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
callback_count_ = 1;
@@ -108,7 +96,7 @@ class CookieRetriever : public base::RefCountedThreadSafe<CookieRetriever> {
net::URLRequestContext* request_context =
context_getter->GetURLRequestContext();
request_context->cookie_store()->GetAllCookiesAsync(
- base::Bind(&CookieRetriever::GotCookies, this));
+ base::BindOnce(&CookieRetriever::GotCookies, this));
}
protected:
virtual ~CookieRetriever() {}
@@ -133,11 +121,9 @@ class CookieRetriever : public base::RefCountedThreadSafe<CookieRetriever> {
master_cookie_list.push_back(pair.second);
BrowserThread::PostTask(
- BrowserThread::UI,
- FROM_HERE,
- base::Bind(&CookieRetriever::SendCookiesResponseOnUI,
- this,
- master_cookie_list));
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&CookieRetriever::SendCookiesResponseOnUI, this,
+ master_cookie_list));
}
void SendCookiesResponseOnUI(const net::CookieList& cookie_list) {
@@ -146,28 +132,28 @@ class CookieRetriever : public base::RefCountedThreadSafe<CookieRetriever> {
ProtocolCookieArray::create();
for (const net::CanonicalCookie& cookie : cookie_list) {
- std::unique_ptr<Network::Cookie> devtools_cookie =
+ std::unique_ptr<Network::Cookie> devtools_cookie =
Network::Cookie::Create()
- .SetName(cookie.Name())
- .SetValue(cookie.Value())
- .SetDomain(cookie.Domain())
- .SetPath(cookie.Path())
- .SetExpires(cookie.ExpiryDate().ToDoubleT() * 1000)
- .SetSize(cookie.Name().length() + cookie.Value().length())
- .SetHttpOnly(cookie.IsHttpOnly())
- .SetSecure(cookie.IsSecure())
- .SetSession(!cookie.IsPersistent())
- .Build();
-
- switch (cookie.SameSite()) {
- case net::CookieSameSite::STRICT_MODE:
- devtools_cookie->SetSameSite(Network::CookieSameSiteEnum::Strict);
- break;
- case net::CookieSameSite::LAX_MODE:
- devtools_cookie->SetSameSite(Network::CookieSameSiteEnum::Lax);
- break;
- case net::CookieSameSite::NO_RESTRICTION:
- break;
+ .SetName(cookie.Name())
+ .SetValue(cookie.Value())
+ .SetDomain(cookie.Domain())
+ .SetPath(cookie.Path())
+ .SetExpires(cookie.ExpiryDate().ToDoubleT())
+ .SetSize(cookie.Name().length() + cookie.Value().length())
+ .SetHttpOnly(cookie.IsHttpOnly())
+ .SetSecure(cookie.IsSecure())
+ .SetSession(!cookie.IsPersistent())
+ .Build();
+
+ switch (cookie.SameSite()) {
+ case net::CookieSameSite::STRICT_MODE:
+ devtools_cookie->SetSameSite(Network::CookieSameSiteEnum::Strict);
+ break;
+ case net::CookieSameSite::LAX_MODE:
+ devtools_cookie->SetSameSite(Network::CookieSameSiteEnum::Lax);
+ break;
+ case net::CookieSameSite::NO_RESTRICTION:
+ break;
}
cookies->addItem(std::move(devtools_cookie));
@@ -193,81 +179,172 @@ class CookieRetriever : public base::RefCountedThreadSafe<CookieRetriever> {
void ClearedCookiesOnIO(std::unique_ptr<ClearBrowserCookiesCallback> callback,
uint32_t num_deleted) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(&ClearBrowserCookiesCallback::sendSuccess,
- base::Passed(std::move(callback))));
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&ClearBrowserCookiesCallback::sendSuccess,
+ std::move(callback)));
}
-void ClearCookiesOnIO(ResourceContext* resource_context,
- net::URLRequestContextGetter* context_getter,
+void ClearCookiesOnIO(net::URLRequestContextGetter* context_getter,
std::unique_ptr<ClearBrowserCookiesCallback> callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
net::URLRequestContext* request_context =
context_getter->GetURLRequestContext();
request_context->cookie_store()->DeleteAllAsync(
- base::Bind(&ClearedCookiesOnIO, base::Passed(std::move(callback))));
+ base::BindOnce(&ClearedCookiesOnIO, base::Passed(std::move(callback))));
}
-void DeletedCookieOnIO(std::unique_ptr<DeleteCookieCallback> callback) {
+void DeletedCookiesOnIO(base::OnceClosure callback, uint32_t num_deleted) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- BrowserThread::PostTask(
- BrowserThread::UI,
- FROM_HERE,
- base::Bind(&DeleteCookieCallback::sendSuccess,
- base::Passed(std::move(callback))));
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, std::move(callback));
}
-void DeleteCookieOnIO(
- ResourceContext* resource_context,
- net::URLRequestContextGetter* context_getter,
- const GURL& url,
- const std::string& cookie_name,
- std::unique_ptr<DeleteCookieCallback> callback) {
+void DeleteSelectedCookiesOnIO(net::URLRequestContextGetter* context_getter,
+ const std::string& name,
+ const std::string& url_spec,
+ const std::string& domain,
+ const std::string& path,
+ base::OnceClosure callback,
+ const net::CookieList& cookie_list) {
+ net::URLRequestContext* request_context =
+ context_getter->GetURLRequestContext();
+ std::string normalized_domain = domain;
+ if (normalized_domain.empty()) {
+ GURL url(url_spec);
+ if (!url.SchemeIsHTTPOrHTTPS()) {
+ std::move(callback).Run();
+ return;
+ }
+ normalized_domain = url.host();
+ }
+
+ net::CookieList filtered_list;
+ for (const auto& cookie : cookie_list) {
+ if (cookie.Name() != name)
+ continue;
+ if (cookie.Domain() != normalized_domain)
+ continue;
+ if (!path.empty() && cookie.Path() != path)
+ continue;
+ filtered_list.push_back(cookie);
+ }
+
+ for (size_t i = 0; i < filtered_list.size(); ++i) {
+ const auto& cookie = filtered_list[i];
+ base::OnceCallback<void(uint32_t)> once_callback;
+ if (i == filtered_list.size() - 1)
+ once_callback = base::BindOnce(&DeletedCookiesOnIO, std::move(callback));
+ request_context->cookie_store()->DeleteCanonicalCookieAsync(
+ cookie, std::move(once_callback));
+ }
+ if (!filtered_list.size())
+ std::move(callback).Run();
+}
+
+void DeleteCookiesOnIO(net::URLRequestContextGetter* context_getter,
+ const std::string& name,
+ const std::string& url,
+ const std::string& domain,
+ const std::string& path,
+ base::OnceClosure callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
net::URLRequestContext* request_context =
- GetRequestContextOnIO(resource_context, context_getter, url);
- request_context->cookie_store()->DeleteCookieAsync(
- url, cookie_name, base::Bind(&DeletedCookieOnIO,
- base::Passed(std::move(callback))));
+ context_getter->GetURLRequestContext();
+
+ request_context->cookie_store()->GetAllCookiesAsync(base::BindOnce(
+ &DeleteSelectedCookiesOnIO, base::Unretained(context_getter), name, url,
+ domain, path, std::move(callback)));
}
void CookieSetOnIO(std::unique_ptr<SetCookieCallback> callback, bool success) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- BrowserThread::PostTask(
- BrowserThread::UI,
- FROM_HERE,
- base::Bind(&SetCookieCallback::sendSuccess,
- base::Passed(std::move(callback)),
- success));
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&SetCookieCallback::sendSuccess,
+ std::move(callback), success));
}
-void SetCookieOnIO(
- ResourceContext* resource_context,
- net::URLRequestContextGetter* context_getter,
- const GURL& url,
- const std::string& name,
- const std::string& value,
- const std::string& domain,
- const std::string& path,
- bool secure,
- bool http_only,
- net::CookieSameSite same_site,
- base::Time expires,
- std::unique_ptr<SetCookieCallback> callback) {
+void SetCookieOnIO(net::URLRequestContextGetter* context_getter,
+ const std::string& name,
+ const std::string& value,
+ const std::string& url_spec,
+ const std::string& domain,
+ const std::string& path,
+ bool secure,
+ bool http_only,
+ const std::string& same_site,
+ double expires,
+ base::OnceCallback<void(bool)> callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
net::URLRequestContext* request_context =
- GetRequestContextOnIO(resource_context, context_getter, url);
+ context_getter->GetURLRequestContext();
+
+ if (url_spec.empty() && domain.empty()) {
+ std::move(callback).Run(false);
+ return;
+ }
+
+ std::string normalized_domain = domain;
+ if (!url_spec.empty()) {
+ GURL source_url = GURL(url_spec);
+ if (!source_url.SchemeIsHTTPOrHTTPS()) {
+ std::move(callback).Run(false);
+ return;
+ }
+
+ secure = secure || source_url.SchemeIsCryptographic();
+ if (normalized_domain.empty())
+ normalized_domain = source_url.host();
+ }
+
+ GURL url = GURL((secure ? "https://" : "http://") + normalized_domain);
+ if (!normalized_domain.empty() && normalized_domain[0] != '.')
+ normalized_domain = "";
+
+ base::Time expiration_date;
+ if (expires >= 0) {
+ expiration_date =
+ expires ? base::Time::FromDoubleT(expires) : base::Time::UnixEpoch();
+ }
+
+ net::CookieSameSite css = net::CookieSameSite::NO_RESTRICTION;
+ if (same_site == Network::CookieSameSiteEnum::Lax)
+ css = net::CookieSameSite::LAX_MODE;
+ if (same_site == Network::CookieSameSiteEnum::Strict)
+ css = net::CookieSameSite::STRICT_MODE;
request_context->cookie_store()->SetCookieWithDetailsAsync(
- url, name, value, domain, path,
- base::Time(),
- expires,
- base::Time(),
- secure,
- http_only,
- same_site,
- net::COOKIE_PRIORITY_DEFAULT,
- base::Bind(&CookieSetOnIO, base::Passed(std::move(callback))));
+ url, name, value, normalized_domain, path, base::Time(), expiration_date,
+ base::Time(), secure, http_only, css, net::COOKIE_PRIORITY_DEFAULT,
+ std::move(callback));
+}
+
+void CookiesSetOnIO(std::unique_ptr<SetCookiesCallback> callback,
+ bool success) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&SetCookiesCallback::sendSuccess, std::move(callback)));
+}
+
+void SetCookiesOnIO(
+ net::URLRequestContextGetter* context_getter,
+ std::unique_ptr<protocol::Array<Network::CookieParam>> cookies,
+ base::OnceCallback<void(bool)> callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ for (size_t i = 0; i < cookies->length(); i++) {
+ Network::CookieParam* cookie = cookies->get(i);
+
+ base::OnceCallback<void(bool)> once_callback;
+ if (i == cookies->length() - 1)
+ once_callback = std::move(callback);
+
+ SetCookieOnIO(context_getter, cookie->GetName(), cookie->GetValue(),
+ cookie->GetUrl(""), cookie->GetDomain(""),
+ cookie->GetPath(""), cookie->GetSecure(false),
+ cookie->GetHttpOnly(false), cookie->GetSameSite(""),
+ cookie->GetExpires(-1), std::move(once_callback));
+ }
}
std::vector<GURL> ComputeCookieURLs(RenderFrameHostImpl* frame_host,
@@ -376,7 +453,8 @@ String securityState(const GURL& url, const net::CertStatus& cert_status) {
return Security::SecurityStateEnum::Secure;
}
-net::Error NetErrorFromString(const std::string& error) {
+net::Error NetErrorFromString(const std::string& error, bool* ok) {
+ *ok = true;
if (error == Network::ErrorReasonEnum::Failed)
return net::ERR_FAILED;
if (error == Network::ErrorReasonEnum::Aborted)
@@ -401,6 +479,7 @@ net::Error NetErrorFromString(const std::string& error) {
return net::ERR_INTERNET_DISCONNECTED;
if (error == Network::ErrorReasonEnum::AddressUnreachable)
return net::ERR_ADDRESS_UNREACHABLE;
+ *ok = false;
return net::ERR_FAILED;
}
@@ -472,6 +551,34 @@ String getProtocol(const GURL& url, const ResourceResponseHead& head) {
return protocol;
}
+class NetworkNavigationThrottle : public content::NavigationThrottle {
+ public:
+ NetworkNavigationThrottle(
+ base::WeakPtr<protocol::NetworkHandler> network_handler,
+ content::NavigationHandle* navigation_handle)
+ : content::NavigationThrottle(navigation_handle),
+ network_handler_(network_handler) {}
+
+ ~NetworkNavigationThrottle() override {}
+
+ // content::NavigationThrottle implementation:
+ NavigationThrottle::ThrottleCheckResult WillProcessResponse() override {
+ if (network_handler_ && network_handler_->ShouldCancelNavigation(
+ navigation_handle()->GetGlobalRequestID())) {
+ return ThrottleCheckResult::CANCEL_AND_IGNORE;
+ }
+ return ThrottleCheckResult::PROCEED;
+ }
+
+ const char* GetNameForLogging() override {
+ return "DevToolsNetworkNavigationThrottle";
+ }
+
+ private:
+ base::WeakPtr<protocol::NetworkHandler> network_handler_;
+ DISALLOW_COPY_AND_ASSIGN(NetworkNavigationThrottle);
+};
+
} // namespace
NetworkHandler::NetworkHandler()
@@ -509,7 +616,7 @@ Response NetworkHandler::Enable(Maybe<int> max_total_size,
Response NetworkHandler::Disable() {
enabled_ = false;
user_agent_ = std::string();
- SetRequestInterceptionEnabled(false);
+ SetRequestInterceptionEnabled(false, Maybe<protocol::Array<String>>());
return Response::FallThrough();
}
@@ -535,14 +642,11 @@ void NetworkHandler::ClearBrowserCookies(
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&ClearCookiesOnIO,
- base::Unretained(host_->GetSiteInstance()
- ->GetBrowserContext()
- ->GetResourceContext()),
- base::Unretained(host_->GetProcess()
- ->GetStoragePartition()
- ->GetURLRequestContext()),
- base::Passed(std::move(callback))));
+ base::BindOnce(&ClearCookiesOnIO,
+ base::Unretained(host_->GetProcess()
+ ->GetStoragePartition()
+ ->GetURLRequestContext()),
+ std::move(callback)));
}
void NetworkHandler::GetCookies(Maybe<Array<String>> protocol_urls,
@@ -558,15 +662,11 @@ void NetworkHandler::GetCookies(Maybe<Array<String>> protocol_urls,
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&CookieRetriever::RetrieveCookiesOnIO,
- retriever,
- base::Unretained(host_->GetSiteInstance()
- ->GetBrowserContext()
- ->GetResourceContext()),
- base::Unretained(host_->GetProcess()
- ->GetStoragePartition()
- ->GetURLRequestContext()),
- urls));
+ base::BindOnce(&CookieRetriever::RetrieveCookiesOnIO, retriever,
+ base::Unretained(host_->GetProcess()
+ ->GetStoragePartition()
+ ->GetURLRequestContext()),
+ urls));
}
void NetworkHandler::GetAllCookies(
@@ -581,75 +681,88 @@ void NetworkHandler::GetAllCookies(
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&CookieRetriever::RetrieveAllCookiesOnIO,
- retriever,
- base::Unretained(host_->GetSiteInstance()
- ->GetBrowserContext()
- ->GetResourceContext()),
- base::Unretained(host_->GetProcess()
- ->GetStoragePartition()
- ->GetURLRequestContext())));
-}
-
-void NetworkHandler::SetCookie(
- const std::string& url,
- const std::string& name,
- const std::string& value,
- Maybe<std::string> domain,
- Maybe<std::string> path,
- Maybe<bool> secure,
- Maybe<bool> http_only,
- Maybe<std::string> same_site,
- Maybe<double> expires,
- std::unique_ptr<SetCookieCallback> callback) {
+ base::BindOnce(&CookieRetriever::RetrieveAllCookiesOnIO, retriever,
+ base::Unretained(host_->GetProcess()
+ ->GetStoragePartition()
+ ->GetURLRequestContext())));
+}
+
+void NetworkHandler::SetCookie(const std::string& name,
+ const std::string& value,
+ Maybe<std::string> url,
+ Maybe<std::string> domain,
+ Maybe<std::string> path,
+ Maybe<bool> secure,
+ Maybe<bool> http_only,
+ Maybe<std::string> same_site,
+ Maybe<double> expires,
+ std::unique_ptr<SetCookieCallback> callback) {
if (!host_) {
callback->sendFailure(Response::InternalError());
return;
}
- net::CookieSameSite same_site_enum = net::CookieSameSite::DEFAULT_MODE;
- if (same_site.isJust()) {
- if (same_site.fromJust() == Network::CookieSameSiteEnum::Lax)
- same_site_enum = net::CookieSameSite::LAX_MODE;
- else if (same_site.fromJust() == Network::CookieSameSiteEnum::Strict)
- same_site_enum = net::CookieSameSite::STRICT_MODE;
+ if (!url.isJust() && !domain.isJust()) {
+ callback->sendFailure(Response::InvalidParams(
+ "At least one of the url and domain needs to be specified"));
}
- base::Time expiration_date;
- if (expires.isJust()) {
- expiration_date = expires.fromJust() == 0
- ? base::Time::UnixEpoch()
- : base::Time::FromDoubleT(expires.fromJust());
- }
-
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
- &SetCookieOnIO,
- base::Unretained(host_->GetSiteInstance()->GetBrowserContext()->
- GetResourceContext()),
- base::Unretained(host_->GetProcess()->GetStoragePartition()->
- GetURLRequestContext()),
- GURL(url), name, value, domain.fromMaybe(""), path.fromMaybe(""),
- secure.fromMaybe(false), http_only.fromMaybe(false), same_site_enum,
- expiration_date, base::Passed(std::move(callback))));
-}
-
-void NetworkHandler::DeleteCookie(
- const std::string& cookie_name,
- const std::string& url,
- std::unique_ptr<DeleteCookieCallback> callback) {
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&SetCookieOnIO,
+ base::Unretained(host_->GetProcess()
+ ->GetStoragePartition()
+ ->GetURLRequestContext()),
+ name, value, url.fromMaybe(""), domain.fromMaybe(""),
+ path.fromMaybe(""), secure.fromMaybe(false),
+ http_only.fromMaybe(false), same_site.fromMaybe(""),
+ expires.fromMaybe(-1),
+ base::BindOnce(&CookieSetOnIO, std::move(callback))));
+}
+
+void NetworkHandler::SetCookies(
+ std::unique_ptr<protocol::Array<Network::CookieParam>> cookies,
+ std::unique_ptr<SetCookiesCallback> callback) {
if (!host_) {
callback->sendFailure(Response::InternalError());
return;
}
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
- &DeleteCookieOnIO,
- base::Unretained(host_->GetSiteInstance()->GetBrowserContext()->
- GetResourceContext()),
- base::Unretained(host_->GetProcess()->GetStoragePartition()->
- GetURLRequestContext()),
- GURL(url),
- cookie_name,
- base::Passed(std::move(callback))));
+
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&SetCookiesOnIO,
+ base::Unretained(host_->GetProcess()
+ ->GetStoragePartition()
+ ->GetURLRequestContext()),
+ std::move(cookies),
+ base::BindOnce(&CookiesSetOnIO, std::move(callback))));
+}
+
+void NetworkHandler::DeleteCookies(
+ const std::string& name,
+ Maybe<std::string> url,
+ Maybe<std::string> domain,
+ Maybe<std::string> path,
+ std::unique_ptr<DeleteCookiesCallback> callback) {
+ if (!host_) {
+ callback->sendFailure(Response::InternalError());
+ return;
+ }
+
+ if (!url.isJust() && !domain.isJust()) {
+ callback->sendFailure(Response::InvalidParams(
+ "At least one of the url and domain needs to be specified"));
+ }
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&DeleteCookiesOnIO,
+ base::Unretained(host_->GetProcess()
+ ->GetStoragePartition()
+ ->GetURLRequestContext()),
+ name, url.fromMaybe(""), domain.fromMaybe(""),
+ path.fromMaybe(""),
+ base::BindOnce(&DeleteCookiesCallback::sendSuccess,
+ std::move(callback))));
}
Response NetworkHandler::SetUserAgentOverride(const std::string& user_agent) {
@@ -827,28 +940,39 @@ std::string NetworkHandler::UserAgentOverride() const {
return enabled_ ? user_agent_ : std::string();
}
-DispatchResponse NetworkHandler::SetRequestInterceptionEnabled(bool enabled) {
- if (interception_enabled_ == enabled)
- return Response::OK(); // Nothing to do.
-
+DispatchResponse NetworkHandler::SetRequestInterceptionEnabled(
+ bool enabled,
+ Maybe<protocol::Array<std::string>> patterns) {
WebContents* web_contents = WebContents::FromRenderFrameHost(host_);
if (!web_contents)
- return Response::OK();
+ return Response::InternalError();
DevToolsURLRequestInterceptor* devtools_url_request_interceptor =
DevToolsURLRequestInterceptor::FromBrowserContext(
web_contents->GetBrowserContext());
if (!devtools_url_request_interceptor)
- return Response::OK();
+ return Response::Error("Interception not supported");
+ std::vector<std::string> new_patterns;
if (enabled) {
+ if (patterns.isJust()) {
+ for (size_t i = 0; i < patterns.fromJust()->length(); i++)
+ new_patterns.push_back(patterns.fromJust()->get(i));
+ } else {
+ new_patterns.push_back("*");
+ }
+ }
+ interception_enabled_ = new_patterns.size();
+
+ if (interception_enabled_) {
devtools_url_request_interceptor->state()->StartInterceptingRequests(
- web_contents, weak_factory_.GetWeakPtr());
+ web_contents, weak_factory_.GetWeakPtr(), new_patterns);
} else {
devtools_url_request_interceptor->state()->StopInterceptingRequests(
web_contents);
+ navigation_requests_.clear();
+ canceled_navigation_requests_.clear();
}
- interception_enabled_ = enabled;
return Response::OK();
}
@@ -895,10 +1019,6 @@ void NetworkHandler::ContinueInterceptedRequest(
return;
}
- base::Optional<net::Error> error;
- if (error_reason.isJust())
- error = NetErrorFromString(error_reason.fromJust());
-
base::Optional<std::string> raw_response;
if (base64_raw_response.isJust()) {
std::string decoded;
@@ -909,6 +1029,27 @@ void NetworkHandler::ContinueInterceptedRequest(
raw_response = decoded;
}
+ base::Optional<net::Error> error;
+ if (error_reason.isJust()) {
+ bool ok;
+ error = NetErrorFromString(error_reason.fromJust(), &ok);
+ if (!ok) {
+ callback->sendFailure(Response::InvalidParams("Invalid errorReason."));
+ return;
+ }
+
+ if (error_reason.fromJust() == Network::ErrorReasonEnum::Aborted) {
+ auto it = navigation_requests_.find(interception_id);
+ if (it != navigation_requests_.end()) {
+ canceled_navigation_requests_.insert(it->second);
+ // To successfully cancel navigation the request must succeed. We
+ // provide simple mock response to avoid pointless network fetch.
+ error.reset();
+ raw_response = std::string("HTTP/1.1 200 OK\r\n\r\n");
+ }
+ }
+ }
+
devtools_url_request_interceptor->state()->ContinueInterceptedRequest(
interception_id,
base::MakeUnique<DevToolsURLRequestInterceptor::Modifications>(
@@ -940,5 +1081,34 @@ std::unique_ptr<Network::Request> NetworkHandler::CreateRequestFromURLRequest(
return request_object;
}
+std::unique_ptr<NavigationThrottle> NetworkHandler::CreateThrottleForNavigation(
+ NavigationHandle* navigation_handle) {
+ if (!interception_enabled_)
+ return nullptr;
+ std::unique_ptr<NavigationThrottle> throttle(new NetworkNavigationThrottle(
+ weak_factory_.GetWeakPtr(), navigation_handle));
+ return throttle;
+}
+
+void NetworkHandler::InterceptedNavigationRequest(
+ const GlobalRequestID& global_request_id,
+ const std::string& interception_id) {
+ navigation_requests_[interception_id] = global_request_id;
+}
+
+void NetworkHandler::InterceptedNavigationRequestFinished(
+ const std::string& interception_id) {
+ navigation_requests_.erase(interception_id);
+}
+
+bool NetworkHandler::ShouldCancelNavigation(
+ const GlobalRequestID& global_request_id) {
+ auto it = canceled_navigation_requests_.find(global_request_id);
+ if (it == canceled_navigation_requests_.end())
+ return false;
+ canceled_navigation_requests_.erase(it);
+ return true;
+}
+
} // namespace protocol
} // namespace content
diff --git a/chromium/content/browser/devtools/protocol/network_handler.h b/chromium/content/browser/devtools/protocol/network_handler.h
index f0d64c9322c..9b80a3f0ee1 100644
--- a/chromium/content/browser/devtools/protocol/network_handler.h
+++ b/chromium/content/browser/devtools/protocol/network_handler.h
@@ -7,6 +7,8 @@
#include <memory>
+#include "base/containers/flat_map.h"
+#include "base/containers/flat_set.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "content/browser/devtools/protocol/devtools_domain_handler.h"
@@ -24,6 +26,9 @@ class DevToolsAgentHostImpl;
class RenderFrameHostImpl;
struct BeginNavigationParams;
struct CommonNavigationParams;
+struct GlobalRequestID;
+class NavigationHandle;
+class NavigationThrottle;
struct ResourceRequest;
struct ResourceRequestCompletionStatus;
struct ResourceResponseHead;
@@ -52,25 +57,31 @@ class NetworkHandler : public DevToolsDomainHandler,
void GetCookies(Maybe<protocol::Array<String>> urls,
std::unique_ptr<GetCookiesCallback> callback) override;
void GetAllCookies(std::unique_ptr<GetAllCookiesCallback> callback) override;
- void DeleteCookie(const std::string& cookie_name,
- const std::string& url,
- std::unique_ptr<DeleteCookieCallback> callback) override;
- void SetCookie(
- const std::string& url,
- const std::string& name,
- const std::string& value,
- Maybe<std::string> domain,
- Maybe<std::string> path,
- Maybe<bool> secure,
- Maybe<bool> http_only,
- Maybe<std::string> same_site,
- Maybe<double> expires,
- std::unique_ptr<SetCookieCallback> callback) override;
+ void DeleteCookies(const std::string& name,
+ Maybe<std::string> url,
+ Maybe<std::string> domain,
+ Maybe<std::string> path,
+ std::unique_ptr<DeleteCookiesCallback> callback) override;
+ void SetCookie(const std::string& name,
+ const std::string& value,
+ Maybe<std::string> url,
+ Maybe<std::string> domain,
+ Maybe<std::string> path,
+ Maybe<bool> secure,
+ Maybe<bool> http_only,
+ Maybe<std::string> same_site,
+ Maybe<double> expires,
+ std::unique_ptr<SetCookieCallback> callback) override;
+ void SetCookies(
+ std::unique_ptr<protocol::Array<Network::CookieParam>> cookies,
+ std::unique_ptr<SetCookiesCallback> callback) override;
Response SetUserAgentOverride(const std::string& user_agent) override;
Response CanEmulateNetworkConditions(bool* result) override;
- DispatchResponse SetRequestInterceptionEnabled(bool enabled) override;
+ DispatchResponse SetRequestInterceptionEnabled(
+ bool enabled,
+ Maybe<protocol::Array<std::string>> patterns) override;
void ContinueInterceptedRequest(
const std::string& request_id,
Maybe<std::string> error_reason,
@@ -104,12 +115,21 @@ class NetworkHandler : public DevToolsDomainHandler,
static std::unique_ptr<Network::Request> CreateRequestFromURLRequest(
const net::URLRequest* request);
+ std::unique_ptr<NavigationThrottle> CreateThrottleForNavigation(
+ NavigationHandle* navigation_handle);
+ void InterceptedNavigationRequest(const GlobalRequestID& global_request_id,
+ const std::string& interception_id);
+ void InterceptedNavigationRequestFinished(const std::string& interception_id);
+ bool ShouldCancelNavigation(const GlobalRequestID& global_request_id);
+
private:
std::unique_ptr<Network::Frontend> frontend_;
RenderFrameHostImpl* host_;
bool enabled_;
bool interception_enabled_;
std::string user_agent_;
+ base::flat_map<std::string, GlobalRequestID> navigation_requests_;
+ base::flat_set<GlobalRequestID> canceled_navigation_requests_;
base::WeakPtrFactory<NetworkHandler> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(NetworkHandler);
diff --git a/chromium/content/browser/devtools/protocol/page_handler.cc b/chromium/content/browser/devtools/protocol/page_handler.cc
index 6518cd24aeb..5875a86132c 100644
--- a/chromium/content/browser/devtools/protocol/page_handler.cc
+++ b/chromium/content/browser/devtools/protocol/page_handler.cc
@@ -17,18 +17,22 @@
#include "base/memory/ref_counted_memory.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string16.h"
+#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task_scheduler/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/devtools/devtools_session.h"
-#include "content/browser/devtools/page_navigation_throttle.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"
#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/browser/web_contents/web_contents_view.h"
#include "content/common/view_messages.h"
+#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/download_manager.h"
#include "content/public/browser/javascript_dialog_manager.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_entry.h"
@@ -46,19 +50,18 @@
#include "ui/gfx/image/image.h"
#include "ui/gfx/image/image_util.h"
#include "ui/snapshot/snapshot.h"
-#include "url/gurl.h"
namespace content {
namespace protocol {
namespace {
-static const char kPng[] = "png";
-static const char kJpeg[] = "jpeg";
-static int kDefaultScreenshotQuality = 80;
-static int kFrameRetryDelayMs = 100;
-static int kCaptureRetryLimit = 2;
-static int kMaxScreencastFramesInFlight = 2;
+constexpr const char* kPng = "png";
+constexpr const char* kJpeg = "jpeg";
+constexpr int kDefaultScreenshotQuality = 80;
+constexpr int kFrameRetryDelayMs = 100;
+constexpr int kCaptureRetryLimit = 2;
+constexpr int kMaxScreencastFramesInFlight = 2;
std::string EncodeImage(const gfx::Image& image,
const std::string& format,
@@ -107,8 +110,6 @@ PageHandler::PageHandler(EmulationHandler* emulation_handler)
session_id_(0),
frame_counter_(0),
frames_in_flight_(0),
- navigation_throttle_enabled_(false),
- next_navigation_id_(0),
host_(nullptr),
emulation_handler_(emulation_handler),
weak_factory_(this) {
@@ -119,6 +120,21 @@ PageHandler::~PageHandler() {
}
// static
+std::vector<PageHandler*> PageHandler::EnabledForWebContents(
+ WebContentsImpl* contents) {
+ if (!DevToolsAgentHost::HasFor(contents))
+ return std::vector<PageHandler*>();
+ std::vector<PageHandler*> result;
+ for (auto* handler :
+ PageHandler::ForAgentHost(static_cast<DevToolsAgentHostImpl*>(
+ DevToolsAgentHost::GetOrCreateFor(contents).get()))) {
+ if (handler->enabled_)
+ result.push_back(handler);
+ }
+ return result;
+}
+
+// static
std::vector<PageHandler*> PageHandler::ForAgentHost(
DevToolsAgentHostImpl* host) {
return DevToolsSession::HandlersForAgentHost<PageHandler>(
@@ -201,6 +217,45 @@ void PageHandler::DidDetachInterstitialPage() {
frontend_->InterstitialHidden();
}
+void PageHandler::DidRunJavaScriptDialog(
+ const GURL& url,
+ const base::string16& message,
+ const base::string16& default_prompt,
+ JavaScriptDialogType dialog_type,
+ const JavaScriptDialogCallback& callback) {
+ if (!enabled_)
+ return;
+ DCHECK(pending_dialog_.is_null());
+ pending_dialog_ = callback;
+ std::string type = Page::DialogTypeEnum::Alert;
+ if (dialog_type == JAVASCRIPT_DIALOG_TYPE_CONFIRM)
+ type = Page::DialogTypeEnum::Confirm;
+ if (dialog_type == JAVASCRIPT_DIALOG_TYPE_PROMPT)
+ type = Page::DialogTypeEnum::Prompt;
+ frontend_->JavascriptDialogOpening(url.spec(), base::UTF16ToUTF8(message),
+ type, base::UTF16ToUTF8(default_prompt));
+}
+
+void PageHandler::DidRunBeforeUnloadConfirm(
+ const GURL& url,
+ const JavaScriptDialogCallback& callback) {
+ if (!enabled_)
+ return;
+ DCHECK(pending_dialog_.is_null());
+ pending_dialog_ = callback;
+ frontend_->JavascriptDialogOpening(url.spec(), std::string(),
+ Page::DialogTypeEnum::Beforeunload,
+ std::string());
+}
+
+void PageHandler::DidCloseJavaScriptDialog(bool success,
+ const base::string16& user_input) {
+ if (!enabled_)
+ return;
+ pending_dialog_.Reset();
+ frontend_->JavascriptDialogClosed(success, base::UTF16ToUTF8(user_input));
+}
+
Response PageHandler::Enable() {
enabled_ = true;
if (GetWebContents() && GetWebContents()->ShowingInterstitialPage())
@@ -211,7 +266,10 @@ Response PageHandler::Enable() {
Response PageHandler::Disable() {
enabled_ = false;
screencast_enabled_ = false;
- SetControlNavigations(false);
+ if (!pending_dialog_.is_null())
+ pending_dialog_.Run(false, base::string16());
+ pending_dialog_.Reset();
+ download_manager_delegate_ = nullptr;
return Response::FallThrough();
}
@@ -364,56 +422,98 @@ void PageHandler::CaptureScreenshot(
}
RenderWidgetHostImpl* widget_host = host_->GetRenderWidgetHost();
+ std::string screenshot_format = format.fromMaybe(kPng);
+ int screenshot_quality = quality.fromMaybe(kDefaultScreenshotQuality);
+
+ // We don't support clip/emulation when capturing from window, bail out.
+ if (!from_surface.fromMaybe(true)) {
+ widget_host->GetSnapshotFromBrowser(
+ base::Bind(&PageHandler::ScreenshotCaptured, weak_factory_.GetWeakPtr(),
+ base::Passed(std::move(callback)), screenshot_format,
+ screenshot_quality, gfx::Size(),
+ blink::WebDeviceEmulationParams()),
+ false);
+ return;
+ }
+
+ // Welcome to the neural net of capturing screenshot while emulating device
+ // metrics!
bool emulation_enabled = emulation_handler_->device_emulation_enabled();
- gfx::Size original_view_size =
- emulation_enabled ? widget_host->GetView()->GetViewBounds().size()
- : gfx::Size();
blink::WebDeviceEmulationParams original_params =
emulation_handler_->GetDeviceEmulationParams();
+ blink::WebDeviceEmulationParams modified_params = original_params;
- if (emulation_enabled && from_surface.fromMaybe(true)) {
- blink::WebDeviceEmulationParams modified_params = original_params;
- gfx::Size emulated_view_size = modified_params.view_size;
- if (!modified_params.view_size.width)
- emulated_view_size = original_view_size;
+ // Capture original view size if we know we are going to destroy it. We use
+ // it in ScreenshotCaptured to restore.
+ gfx::Size original_view_size =
+ emulation_enabled || clip.isJust()
+ ? widget_host->GetView()->GetViewBounds().size()
+ : gfx::Size();
+ gfx::Size emulated_view_size = modified_params.view_size;
+ double dpfactor = 1;
+ if (emulation_enabled) {
ScreenInfo screen_info;
widget_host->GetScreenInfo(&screen_info);
- double dpfactor =
- modified_params.device_scale_factor / screen_info.device_scale_factor;
- modified_params.scale = dpfactor;
- modified_params.view_size.width = emulated_view_size.width();
- modified_params.view_size.height = emulated_view_size.height();
- if (clip.isJust()) {
- // TODO(pfeldman): Modifying here to save on the extra
- // RenderWidgetScreenMetricsEmulator / DevToolsEmulator delegate back
- // and forth.
- modified_params.viewport_offset.x = clip.fromJust()->GetX() * dpfactor;
- modified_params.viewport_offset.y = clip.fromJust()->GetY() * dpfactor;
- modified_params.viewport_scale = clip.fromJust()->GetScale();
+ // When emulating, emulate again and scale to make resulting image match
+ // physical DP resolution. If view_size is not overriden, use actual view
+ // size.
+ float original_scale =
+ original_params.scale > 0 ? original_params.scale : 1;
+ if (!modified_params.view_size.width) {
+ emulated_view_size.set_width(
+ ceil(original_view_size.width() / original_scale));
+ }
+ if (!modified_params.view_size.height) {
+ emulated_view_size.set_height(
+ ceil(original_view_size.height() / original_scale));
}
- emulation_handler_->SetDeviceEmulationParams(modified_params);
+ dpfactor = modified_params.device_scale_factor
+ ? modified_params.device_scale_factor /
+ screen_info.device_scale_factor
+ : 1;
+ // When clip is specified, we scale viewport via clip, otherwise we use
+ // scale.
+ modified_params.scale = clip.isJust() ? 1 : dpfactor;
+ modified_params.view_size.width = emulated_view_size.width();
+ modified_params.view_size.height = emulated_view_size.height();
+ } else if (clip.isJust()) {
+ // When not emulating, still need to emulate the page size.
+ modified_params.view_size.width = original_view_size.width();
+ modified_params.view_size.height = original_view_size.height();
+ modified_params.screen_size.width = 0;
+ modified_params.screen_size.height = 0;
+ modified_params.device_scale_factor = 0;
+ modified_params.scale = 1;
+ }
- if (clip.isJust()) {
- double scale = dpfactor * clip.fromJust()->GetScale();
- widget_host->GetView()->SetSize(
- gfx::Size(gfx::ToRoundedInt(clip.fromJust()->GetWidth() * scale),
- gfx::ToRoundedInt(clip.fromJust()->GetHeight() * scale)));
- } else {
- widget_host->GetView()->SetSize(
- gfx::ScaleToFlooredSize(emulated_view_size, dpfactor));
- }
+ // Set up viewport in renderer.
+ if (clip.isJust()) {
+ modified_params.viewport_offset.x = clip.fromJust()->GetX();
+ modified_params.viewport_offset.y = clip.fromJust()->GetY();
+ modified_params.viewport_scale = clip.fromJust()->GetScale() * dpfactor;
}
- std::string screenshot_format = format.fromMaybe(kPng);
- int screenshot_quality = quality.fromMaybe(kDefaultScreenshotQuality);
+ // We use WebDeviceEmulationParams to either emulate, set viewport or both.
+ emulation_handler_->SetDeviceEmulationParams(modified_params);
+
+ // Set view size for the screenshot right after emulating.
+ if (clip.isJust()) {
+ double scale = dpfactor * clip.fromJust()->GetScale();
+ widget_host->GetView()->SetSize(
+ gfx::Size(gfx::ToRoundedInt(clip.fromJust()->GetWidth() * scale),
+ gfx::ToRoundedInt(clip.fromJust()->GetHeight() * scale)));
+ } else if (emulation_enabled) {
+ widget_host->GetView()->SetSize(
+ gfx::ScaleToFlooredSize(emulated_view_size, dpfactor));
+ }
widget_host->GetSnapshotFromBrowser(
base::Bind(&PageHandler::ScreenshotCaptured, weak_factory_.GetWeakPtr(),
base::Passed(std::move(callback)), screenshot_format,
screenshot_quality, original_view_size, original_params),
- from_surface.fromMaybe(true));
+ true);
}
void PageHandler::PrintToPDF(Maybe<bool> landscape,
@@ -481,23 +581,28 @@ Response PageHandler::ScreencastFrameAck(int session_id) {
Response PageHandler::HandleJavaScriptDialog(bool accept,
Maybe<std::string> prompt_text) {
- base::string16 prompt_override;
- if (prompt_text.isJust())
- prompt_override = base::UTF8ToUTF16(prompt_text.fromJust());
-
WebContentsImpl* web_contents = GetWebContents();
if (!web_contents)
return Response::InternalError();
+ if (pending_dialog_.is_null())
+ return Response::InvalidParams("No dialog is showing");
+
+ base::string16 prompt_override;
+ if (prompt_text.isJust())
+ prompt_override = base::UTF8ToUTF16(prompt_text.fromJust());
+ pending_dialog_.Run(accept, prompt_override);
+
+ // Clean up the dialog UI if any.
JavaScriptDialogManager* manager =
web_contents->GetDelegate()->GetJavaScriptDialogManager(web_contents);
- if (manager && manager->HandleJavaScriptDialog(
- web_contents, accept,
- prompt_text.isJust() ? &prompt_override : nullptr)) {
- return Response::OK();
+ if (manager) {
+ manager->HandleJavaScriptDialog(
+ web_contents, accept,
+ prompt_text.isJust() ? &prompt_override : nullptr);
}
- return Response::Error("Could not handle JavaScript dialog");
+ return Response::OK();
}
Response PageHandler::RequestAppBanner() {
@@ -508,62 +613,54 @@ Response PageHandler::RequestAppBanner() {
return Response::OK();
}
-Response PageHandler::SetControlNavigations(bool enabled) {
- navigation_throttle_enabled_ = enabled;
- // We don't own the page PageNavigationThrottles so we can't delete them, but
- // we can turn them into NOPs.
- for (auto& pair : navigation_throttles_) {
- pair.second->AlwaysProceed();
+Response PageHandler::BringToFront() {
+ WebContentsImpl* wc = GetWebContents();
+ if (wc) {
+ wc->Activate();
+ return Response::OK();
}
- navigation_throttles_.clear();
- return Response::OK();
+ return Response::InternalError();
}
-Response PageHandler::ProcessNavigation(const std::string& response,
- int navigation_id) {
- auto it = navigation_throttles_.find(navigation_id);
- if (it == navigation_throttles_.end())
- return Response::InvalidParams("Unknown navigation id");
+Response PageHandler::SetDownloadBehavior(const std::string& behavior,
+ Maybe<std::string> download_path) {
+ WebContentsImpl* web_contents = GetWebContents();
+ if (!web_contents)
+ return Response::InternalError();
+
+ if (behavior == Page::SetDownloadBehavior::BehaviorEnum::Allow &&
+ !download_path.isJust())
+ return Response::Error("downloadPath not provided");
- if (response == Page::NavigationResponseEnum::Proceed) {
- it->second->Resume();
- return Response::OK();
- } else if (response == Page::NavigationResponseEnum::Cancel) {
- it->second->CancelDeferredNavigation(content::NavigationThrottle::CANCEL);
- return Response::OK();
- } else if (response == Page::NavigationResponseEnum::CancelAndIgnore) {
- it->second->CancelDeferredNavigation(
- content::NavigationThrottle::CANCEL_AND_IGNORE);
+ if (behavior == Page::SetDownloadBehavior::BehaviorEnum::Default) {
+ DevToolsDownloadManagerHelper::RemoveFromWebContents(web_contents);
+ download_manager_delegate_ = nullptr;
return Response::OK();
}
- return Response::InvalidParams("Unrecognized response");
-}
-
-std::unique_ptr<PageNavigationThrottle>
-PageHandler::CreateThrottleForNavigation(NavigationHandle* navigation_handle) {
- if (!navigation_throttle_enabled_)
- return nullptr;
-
- std::unique_ptr<PageNavigationThrottle> throttle(new PageNavigationThrottle(
- weak_factory_.GetWeakPtr(), next_navigation_id_, navigation_handle));
- navigation_throttles_[next_navigation_id_++] = throttle.get();
- return throttle;
-}
-
-void PageHandler::OnPageNavigationThrottleDisposed(int navigation_id) {
- DCHECK(navigation_throttles_.find(navigation_id) !=
- navigation_throttles_.end());
- navigation_throttles_.erase(navigation_id);
-}
+ // Override download manager delegate.
+ content::BrowserContext* browser_context = web_contents->GetBrowserContext();
+ DCHECK(browser_context);
+ content::DownloadManager* download_manager =
+ content::BrowserContext::GetDownloadManager(browser_context);
+ download_manager_delegate_ =
+ DevToolsDownloadManagerDelegate::TakeOver(download_manager);
+
+ // Ensure that there is one helper attached. If there's already one, we reuse
+ // it.
+ DevToolsDownloadManagerHelper::CreateForWebContents(web_contents);
+ DevToolsDownloadManagerHelper* download_helper =
+ DevToolsDownloadManagerHelper::FromWebContents(web_contents);
+
+ download_helper->SetDownloadBehavior(
+ DevToolsDownloadManagerHelper::DownloadBehavior::DENY);
+ if (behavior == Page::SetDownloadBehavior::BehaviorEnum::Allow) {
+ download_helper->SetDownloadBehavior(
+ DevToolsDownloadManagerHelper::DownloadBehavior::ALLOW);
+ download_helper->SetDownloadPath(download_path.fromJust());
+ }
-void PageHandler::NavigationRequested(const PageNavigationThrottle* throttle) {
- NavigationHandle* navigation_handle = throttle->navigation_handle();
- frontend_->NavigationRequested(
- navigation_handle->IsInMainFrame(),
- navigation_handle->WasServerRedirect(),
- throttle->navigation_id(),
- navigation_handle->GetURL().spec());
+ return Response::OK();
}
WebContentsImpl* PageHandler::GetWebContents() {
@@ -639,8 +736,9 @@ void PageHandler::ScreencastFrameCaptured(cc::CompositorFrameMetadata metadata,
if (capture_retry_count_) {
--capture_retry_count_;
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, base::Bind(&PageHandler::InnerSwapCompositorFrame,
- weak_factory_.GetWeakPtr()),
+ FROM_HERE,
+ base::BindOnce(&PageHandler::InnerSwapCompositorFrame,
+ weak_factory_.GetWeakPtr()),
base::TimeDelta::FromMilliseconds(kFrameRetryDelayMs));
}
--frames_in_flight_;
diff --git a/chromium/content/browser/devtools/protocol/page_handler.h b/chromium/content/browser/devtools/protocol/page_handler.h
index c03d5bcd764..b3602785b61 100644
--- a/chromium/content/browser/devtools/protocol/page_handler.h
+++ b/chromium/content/browser/devtools/protocol/page_handler.h
@@ -10,6 +10,7 @@
#include <map>
#include <memory>
#include <string>
+#include <vector>
#include "base/compiler_specific.h"
#include "base/macros.h"
@@ -17,10 +18,13 @@
#include "base/time/time.h"
#include "cc/output/compositor_frame_metadata.h"
#include "content/browser/devtools/protocol/devtools_domain_handler.h"
+#include "content/browser/devtools/protocol/devtools_download_manager_delegate.h"
#include "content/browser/devtools/protocol/page.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/readback_types.h"
+#include "content/public/common/javascript_dialog_type.h"
+#include "url/gurl.h"
class SkBitmap;
@@ -35,8 +39,6 @@ struct WebDeviceEmulationParams;
namespace content {
class DevToolsAgentHostImpl;
-class NavigationHandle;
-class PageNavigationThrottle;
class RenderFrameHostImpl;
class WebContentsImpl;
@@ -51,6 +53,8 @@ class PageHandler : public DevToolsDomainHandler,
explicit PageHandler(EmulationHandler* handler);
~PageHandler() override;
+ static std::vector<PageHandler*> EnabledForWebContents(
+ WebContentsImpl* contents);
static std::vector<PageHandler*> ForAgentHost(DevToolsAgentHostImpl* host);
void Wire(UberDispatcher* dispatcher) override;
@@ -61,6 +65,16 @@ class PageHandler : public DevToolsDomainHandler,
void DidAttachInterstitialPage();
void DidDetachInterstitialPage();
bool screencast_enabled() const { return enabled_ && screencast_enabled_; }
+ using JavaScriptDialogCallback =
+ base::Callback<void(bool, const base::string16&)>;
+ void DidRunJavaScriptDialog(const GURL& url,
+ const base::string16& message,
+ const base::string16& default_prompt,
+ JavaScriptDialogType dialog_type,
+ const JavaScriptDialogCallback& callback);
+ void DidRunBeforeUnloadConfirm(const GURL& url,
+ const JavaScriptDialogCallback& callback);
+ void DidCloseJavaScriptDialog(bool success, const base::string16& user_input);
Response Enable() override;
Response Disable() override;
@@ -111,15 +125,10 @@ class PageHandler : public DevToolsDomainHandler,
Response RequestAppBanner() override;
- Response SetControlNavigations(bool enabled) override;
- Response ProcessNavigation(const std::string& response,
- int navigation_id) override;
+ Response BringToFront() override;
- std::unique_ptr<PageNavigationThrottle> CreateThrottleForNavigation(
- NavigationHandle* navigation_handle);
-
- void OnPageNavigationThrottleDisposed(int navigation_id);
- void NavigationRequested(const PageNavigationThrottle* throttle);
+ Response SetDownloadBehavior(const std::string& behavior,
+ Maybe<std::string> download_path) override;
private:
enum EncodingFormat { PNG, JPEG };
@@ -163,14 +172,12 @@ class PageHandler : public DevToolsDomainHandler,
int frame_counter_;
int frames_in_flight_;
- bool navigation_throttle_enabled_;
- int next_navigation_id_;
- std::map<int, PageNavigationThrottle*> navigation_throttles_;
-
RenderFrameHostImpl* host_;
EmulationHandler* emulation_handler_;
std::unique_ptr<Page::Frontend> frontend_;
NotificationRegistrar registrar_;
+ JavaScriptDialogCallback pending_dialog_;
+ scoped_refptr<DevToolsDownloadManagerDelegate> download_manager_delegate_;
base::WeakPtrFactory<PageHandler> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(PageHandler);
diff --git a/chromium/content/browser/devtools/protocol/schema_handler.cc b/chromium/content/browser/devtools/protocol/schema_handler.cc
index 30b45e3324c..b0d00c99d80 100644
--- a/chromium/content/browser/devtools/protocol/schema_handler.cc
+++ b/chromium/content/browser/devtools/protocol/schema_handler.cc
@@ -30,7 +30,8 @@ Response SchemaHandler::GetDomains(
"ServiceWorker", "Input", "LayerTree", "DeviceOrientation",
"Tracing", "Animation", "Accessibility", "Storage",
"Log", "Runtime", "Debugger", "Profiler",
- "HeapProfiler", "Schema", "Target", "Overlay"};
+ "HeapProfiler", "Schema", "Target", "Overlay",
+ "Performance", "Audits"};
*domains = protocol::Array<Schema::Domain>::create();
for (size_t i = 0; i < arraysize(kDomains); ++i) {
(*domains)->addItem(Schema::Domain::Create()
diff --git a/chromium/content/browser/devtools/protocol/security_handler.cc b/chromium/content/browser/devtools/protocol/security_handler.cc
index 0ba37a9d39b..4632562c7e2 100644
--- a/chromium/content/browser/devtools/protocol/security_handler.cc
+++ b/chromium/content/browser/devtools/protocol/security_handler.cc
@@ -4,8 +4,12 @@
#include "content/browser/devtools/protocol/security_handler.h"
+#include <memory>
#include <string>
+#include <utility>
+#include <vector>
+#include "base/base64.h"
#include "content/browser/devtools/devtools_session.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/public/browser/navigation_controller.h"
@@ -14,6 +18,7 @@
#include "content/public/browser/ssl_status.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_delegate.h"
+#include "net/cert/x509_certificate.h"
#include "third_party/WebKit/public/platform/WebMixedContentContextType.h"
namespace content {
@@ -32,8 +37,6 @@ std::string SecurityStyleToProtocolSecurityState(
return Security::SecurityStateEnum::Neutral;
case blink::kWebSecurityStyleInsecure:
return Security::SecurityStateEnum::Insecure;
- case blink::kWebSecurityStyleWarning:
- return Security::SecurityStateEnum::Warning;
case blink::kWebSecurityStyleSecure:
return Security::SecurityStateEnum::Secure;
default:
@@ -66,12 +69,32 @@ void AddExplanations(
const std::vector<SecurityStyleExplanation>& explanations_to_add,
Explanations* explanations) {
for (const auto& it : explanations_to_add) {
+ std::unique_ptr<protocol::Array<String>> certificate =
+ protocol::Array<String>::create();
+ if (it.certificate) {
+ std::string der;
+ std::string encoded;
+ bool rv = net::X509Certificate::GetDEREncoded(
+ it.certificate->os_cert_handle(), &der);
+ DCHECK(rv);
+ base::Base64Encode(der, &encoded);
+
+ certificate->addItem(encoded);
+
+ for (auto* cert : it.certificate->GetIntermediateCertificates()) {
+ rv = net::X509Certificate::GetDEREncoded(cert, &der);
+ DCHECK(rv);
+ base::Base64Encode(der, &encoded);
+ certificate->addItem(encoded);
+ }
+ }
+
explanations->addItem(
Security::SecurityStateExplanation::Create()
.SetSecurityState(security_style)
.SetSummary(it.summary)
.SetDescription(it.description)
- .SetHasCertificate(it.has_certificate)
+ .SetCertificate(std::move(certificate))
.SetMixedContentType(MixedContentTypeToProtocolMixedContentType(
it.mixed_content_type))
.Build());
@@ -210,19 +233,6 @@ Response SecurityHandler::Disable() {
return Response::OK();
}
-Response SecurityHandler::ShowCertificateViewer() {
- if (!host_)
- return Response::InternalError();
- WebContents* web_contents = WebContents::FromRenderFrameHost(host_);
- scoped_refptr<net::X509Certificate> certificate =
- web_contents->GetController().GetVisibleEntry()->GetSSL().certificate;
- if (!certificate)
- return Response::Error("Could not find certificate");
- web_contents->GetDelegate()->ShowCertificateViewerInDevTools(
- web_contents, certificate);
- return Response::OK();
-}
-
Response SecurityHandler::HandleCertificateError(int event_id,
const String& action) {
if (cert_error_callbacks_.find(event_id) == cert_error_callbacks_.end()) {
diff --git a/chromium/content/browser/devtools/protocol/security_handler.h b/chromium/content/browser/devtools/protocol/security_handler.h
index 96c24ff3473..c70fdef0050 100644
--- a/chromium/content/browser/devtools/protocol/security_handler.h
+++ b/chromium/content/browser/devtools/protocol/security_handler.h
@@ -40,7 +40,6 @@ class SecurityHandler : public DevToolsDomainHandler,
// Security::Backend overrides.
Response Enable() override;
Response Disable() override;
- Response ShowCertificateViewer() override;
Response HandleCertificateError(int event_id, const String& action) override;
Response SetOverrideCertificateErrors(bool override) override;
diff --git a/chromium/content/browser/devtools/protocol/service_worker_handler.cc b/chromium/content/browser/devtools/protocol/service_worker_handler.cc
index 9cfabe31171..c2fbb6a68dd 100644
--- a/chromium/content/browser/devtools/protocol/service_worker_handler.cc
+++ b/chromium/content/browser/devtools/protocol/service_worker_handler.cc
@@ -104,7 +104,7 @@ void GetDevToolsRouteInfoOnIO(
context->GetLiveVersion(version_id)) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(
+ base::BindOnce(
callback, version->embedded_worker()->process_id(),
version->embedded_worker()->worker_devtools_agent_route_id()));
}
@@ -249,7 +249,7 @@ Response ServiceWorkerHandler::StopWorker(const std::string& version_id) {
if (!base::StringToInt64(version_id, &id))
return CreateInvalidVersionIdErrorResponse();
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::Bind(&StopServiceWorkerOnIO, context_, id));
+ base::BindOnce(&StopServiceWorkerOnIO, context_, id));
return Response::OK();
}
@@ -274,9 +274,9 @@ Response ServiceWorkerHandler::InspectWorker(const std::string& version_id) {
return CreateInvalidVersionIdErrorResponse();
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&GetDevToolsRouteInfoOnIO, context_, id,
- base::Bind(&ServiceWorkerHandler::OpenNewDevToolsWindow,
- weak_factory_.GetWeakPtr())));
+ base::BindOnce(&GetDevToolsRouteInfoOnIO, context_, id,
+ base::Bind(&ServiceWorkerHandler::OpenNewDevToolsWindow,
+ weak_factory_.GetWeakPtr())));
return Response::OK();
}
@@ -328,9 +328,9 @@ Response ServiceWorkerHandler::DispatchSyncEvent(
BackgroundSyncContext* sync_context = partition->GetBackgroundSyncContext();
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::Bind(&DispatchSyncEventOnIO, context_,
- make_scoped_refptr(sync_context),
- GURL(origin), id, tag, last_chance));
+ base::BindOnce(&DispatchSyncEventOnIO, context_,
+ make_scoped_refptr(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 a0202bd3377..e0b373aa07e 100644
--- a/chromium/content/browser/devtools/protocol/storage_handler.cc
+++ b/chromium/content/browser/devtools/protocol/storage_handler.cc
@@ -4,17 +4,21 @@
#include "content/browser/devtools/protocol/storage_handler.h"
+#include <memory>
#include <unordered_set>
#include <utility>
#include <vector>
#include "base/strings/string_split.h"
+#include "content/browser/cache_storage/cache_storage_context_impl.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/storage_partition.h"
#include "storage/browser/quota/quota_client.h"
#include "storage/browser/quota/quota_manager.h"
#include "storage/common/quota/quota_status_code.h"
+#include "url/gurl.h"
+#include "url/origin.h"
namespace content {
namespace protocol {
@@ -71,10 +75,11 @@ 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::Bind(ReportUsageAndQuotaDataOnUIThread,
- base::Passed(std::move(callback)), code,
- usage, quota, std::move(usage_breakdown)));
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(ReportUsageAndQuotaDataOnUIThread,
+ base::Passed(std::move(callback)), code, usage, quota,
+ std::move(usage_breakdown)));
}
void GetUsageAndQuotaOnIOThread(
@@ -91,12 +96,18 @@ void GetUsageAndQuotaOnIOThread(
StorageHandler::StorageHandler()
: DevToolsDomainHandler(Storage::Metainfo::domainName),
- host_(nullptr) {
-}
+ host_(nullptr),
+ weak_ptr_factory_(this) {}
-StorageHandler::~StorageHandler() = default;
+StorageHandler::~StorageHandler() {
+ if (cache_storage_observer_) {
+ BrowserThread::DeleteSoon(BrowserThread::IO, FROM_HERE,
+ cache_storage_observer_.release());
+ }
+}
void StorageHandler::Wire(UberDispatcher* dispatcher) {
+ frontend_ = base::MakeUnique<Storage::Frontend>(dispatcher->channel());
Storage::Dispatcher::wire(dispatcher, this);
}
@@ -164,8 +175,133 @@ void StorageHandler::GetUsageAndQuota(
host_->GetProcess()->GetStoragePartition()->GetQuotaManager();
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&GetUsageAndQuotaOnIOThread, base::RetainedRef(manager),
- origin_url, base::Passed(std::move(callback))));
+ base::BindOnce(&GetUsageAndQuotaOnIOThread, base::RetainedRef(manager),
+ origin_url, base::Passed(std::move(callback))));
+}
+
+// Observer that listens on the IO thread for cache storage notifications and
+// informs the StorageHandler on the UI for origins of interest.
+// Created on the UI thread but predominantly used and deleted on the IO thread.
+// Registered on creation as an observer in CacheStorageContext, unregistered on
+// destruction
+class StorageHandler::CacheStorageObserver : CacheStorageContextImpl::Observer {
+ public:
+ 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::BindOnce(&CacheStorageObserver::AddObserverOnIOThread,
+ base::Unretained(this)));
+ }
+
+ ~CacheStorageObserver() override {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ context_->RemoveObserver(this);
+ }
+
+ void TrackOriginOnIOThread(const url::Origin& origin) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ if (origins_.find(origin) != origins_.end())
+ return;
+ origins_.insert(origin);
+ }
+
+ void UntrackOriginOnIOThread(const url::Origin& origin) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ origins_.erase(origin);
+ }
+
+ private:
+ void AddObserverOnIOThread() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ context_->AddObserver(this);
+ }
+
+ void OnCacheListChanged(const url::Origin& origin) override {
+ auto found = origins_.find(origin);
+ if (found == origins_.end())
+ return;
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&StorageHandler::NotifyCacheStorageListChanged, owner_,
+ origin.Serialize()));
+ }
+
+ void OnCacheContentChanged(const url::Origin& origin,
+ const std::string& cache_name) override {
+ auto found = origins_.find(origin);
+ if (found == origins_.end())
+ return;
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&StorageHandler::NotifyCacheStorageContentChanged,
+ owner_, origin.Serialize(), cache_name));
+ }
+
+ // Maintained on the IO thread to avoid mutex contention.
+ base::flat_set<url::Origin> origins_;
+
+ base::WeakPtr<StorageHandler> owner_;
+ scoped_refptr<CacheStorageContextImpl> context_;
+
+ DISALLOW_COPY_AND_ASSIGN(CacheStorageObserver);
+};
+
+Response StorageHandler::TrackCacheStorageForOrigin(const std::string& origin) {
+ if (!host_)
+ return Response::InternalError();
+
+ GURL origin_url(origin);
+ if (!origin_url.is_valid())
+ return Response::InvalidParams(origin + " is not a valid URL");
+
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&CacheStorageObserver::TrackOriginOnIOThread,
+ base::Unretained(GetCacheStorageObserver()),
+ url::Origin(origin_url)));
+ return Response::OK();
+}
+
+Response StorageHandler::UntrackCacheStorageForOrigin(
+ const std::string& origin) {
+ if (!host_)
+ return Response::InternalError();
+
+ GURL origin_url(origin);
+ if (!origin_url.is_valid())
+ return Response::InvalidParams(origin + " is not a valid URL");
+
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&CacheStorageObserver::UntrackOriginOnIOThread,
+ base::Unretained(GetCacheStorageObserver()),
+ url::Origin(origin_url)));
+ return Response::OK();
+}
+
+StorageHandler::CacheStorageObserver*
+StorageHandler::GetCacheStorageObserver() {
+ if (cache_storage_observer_ == nullptr) {
+ cache_storage_observer_ = base::MakeUnique<CacheStorageObserver>(
+ weak_ptr_factory_.GetWeakPtr(),
+ static_cast<CacheStorageContextImpl*>(host_->GetProcess()
+ ->GetStoragePartition()
+ ->GetCacheStorageContext()));
+ }
+ return cache_storage_observer_.get();
+}
+
+void StorageHandler::NotifyCacheStorageListChanged(const std::string& origin) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ frontend_->CacheStorageListUpdated(origin);
+}
+
+void StorageHandler::NotifyCacheStorageContentChanged(const std::string& origin,
+ const std::string& name) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ frontend_->CacheStorageContentUpdated(origin, name);
}
} // namespace protocol
diff --git a/chromium/content/browser/devtools/protocol/storage_handler.h b/chromium/content/browser/devtools/protocol/storage_handler.h
index 23731d21815..0845ff527f2 100644
--- a/chromium/content/browser/devtools/protocol/storage_handler.h
+++ b/chromium/content/browser/devtools/protocol/storage_handler.h
@@ -8,7 +8,10 @@
#include <memory>
#include <string>
+#include "base/containers/flat_set.h"
#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "content/browser/cache_storage/cache_storage_context_impl.h"
#include "content/browser/devtools/protocol/devtools_domain_handler.h"
#include "content/browser/devtools/protocol/storage.h"
@@ -33,9 +36,24 @@ class StorageHandler : public DevToolsDomainHandler,
void GetUsageAndQuota(
const String& origin,
std::unique_ptr<GetUsageAndQuotaCallback> callback) override;
+ // Ignores all double calls to track an origin.
+ Response TrackCacheStorageForOrigin(const std::string& origin) override;
+ Response UntrackCacheStorageForOrigin(const std::string& origin) override;
private:
+ // See definition for lifetime information.
+ class CacheStorageObserver;
+
+ CacheStorageObserver* GetCacheStorageObserver();
+ void NotifyCacheStorageListChanged(const std::string& origin);
+ void NotifyCacheStorageContentChanged(const std::string& origin,
+ const std::string& name);
+
+ std::unique_ptr<Storage::Frontend> frontend_;
RenderFrameHostImpl* host_;
+ std::unique_ptr<CacheStorageObserver> cache_storage_observer_;
+
+ base::WeakPtrFactory<StorageHandler> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(StorageHandler);
};
diff --git a/chromium/content/browser/devtools/protocol/system_info_handler.cc b/chromium/content/browser/devtools/protocol/system_info_handler.cc
index ac0c8be5900..26068389a45 100644
--- a/chromium/content/browser/devtools/protocol/system_info_handler.cc
+++ b/chromium/content/browser/devtools/protocol/system_info_handler.cc
@@ -148,10 +148,9 @@ class SystemInfoHandlerGpuObserver : public content::GpuDataManagerObserver {
: callback_(std::move(callback)),
weak_factory_(this) {
BrowserThread::PostDelayedTask(
- BrowserThread::UI,
- FROM_HERE,
- base::Bind(&SystemInfoHandlerGpuObserver::ObserverWatchdogCallback,
- weak_factory_.GetWeakPtr()),
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&SystemInfoHandlerGpuObserver::ObserverWatchdogCallback,
+ weak_factory_.GetWeakPtr()),
base::TimeDelta::FromMilliseconds(kGPUInfoWatchdogTimeoutMs));
GpuDataManager::GetInstance()->AddObserver(this);
@@ -208,10 +207,9 @@ void SystemInfoHandler::GetInfo(
// Waiting for complete GPU info in the if-test above seems to
// frequently hit internal timeouts in the launching of the unsandboxed
// GPU process in debug builds on Windows.
- BrowserThread::PostTask(
- BrowserThread::UI,
- FROM_HERE,
- base::Bind(&SendGetInfoResponse, base::Passed(std::move(callback))));
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&SendGetInfoResponse,
+ base::Passed(std::move(callback))));
} else {
// We will be able to get more information from the GpuDataManager.
// Register a transient observer with it to call us back when the
diff --git a/chromium/content/browser/devtools/protocol/target_auto_attacher.cc b/chromium/content/browser/devtools/protocol/target_auto_attacher.cc
index 06064c02e4e..90e566decb5 100644
--- a/chromium/content/browser/devtools/protocol/target_auto_attacher.cc
+++ b/chromium/content/browser/devtools/protocol/target_auto_attacher.cc
@@ -134,7 +134,7 @@ void TargetAutoAttacher::UpdateFrames() {
}
void TargetAutoAttacher::AgentHostClosed(DevToolsAgentHost* host) {
- auto_attached_hosts_.erase(host);
+ auto_attached_hosts_.erase(make_scoped_refptr(host));
}
void TargetAutoAttacher::ReattachServiceWorkers(bool waiting_for_debugger) {
@@ -166,17 +166,15 @@ void TargetAutoAttacher::ReattachTargetsOfType(const Hosts& new_hosts,
const std::string& type,
bool waiting_for_debugger) {
Hosts old_hosts = auto_attached_hosts_;
- for (auto& it : old_hosts) {
- DevToolsAgentHost* host = it.get();
+ for (auto& host : old_hosts) {
if (host->GetType() == type && new_hosts.find(host) == new_hosts.end()) {
auto_attached_hosts_.erase(host);
- detach_callback_.Run(host);
+ detach_callback_.Run(host.get());
}
}
- for (auto& it : new_hosts) {
- DevToolsAgentHost* host = it.get();
+ for (auto& host : new_hosts) {
if (old_hosts.find(host) == old_hosts.end()) {
- attach_callback_.Run(host, waiting_for_debugger);
+ attach_callback_.Run(host.get(), waiting_for_debugger);
auto_attached_hosts_.insert(host);
}
}
diff --git a/chromium/content/browser/devtools/protocol/target_handler.cc b/chromium/content/browser/devtools/protocol/target_handler.cc
index 19255cfddb5..54d754b10b3 100644
--- a/chromium/content/browser/devtools/protocol/target_handler.cc
+++ b/chromium/content/browser/devtools/protocol/target_handler.cc
@@ -35,7 +35,7 @@ class TargetHandler::Session : public DevToolsAgentHostClient {
++handler->last_session_id_);
Session* session = new Session(handler, agent_host, id);
handler->attached_sessions_[id].reset(session);
- static_cast<DevToolsAgentHostImpl*>(agent_host)->AttachMultiClient(session);
+ agent_host->AttachClient(session);
handler->frontend_->AttachedToTarget(id, CreateInfo(agent_host),
waiting_for_debugger);
return id;
diff --git a/chromium/content/browser/devtools/protocol/tethering_handler.cc b/chromium/content/browser/devtools/protocol/tethering_handler.cc
index d20b325ca12..36a9d39091d 100644
--- a/chromium/content/browser/devtools/protocol/tethering_handler.cc
+++ b/chromium/content/browser/devtools/protocol/tethering_handler.cc
@@ -261,10 +261,11 @@ 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::Bind(
- &BindCallback::sendFailure,
- base::Passed(std::move(callback)),
- Response::Error("Port already bound")));
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&BindCallback::sendFailure,
+ base::Passed(std::move(callback)),
+ Response::Error("Port already bound")));
return;
}
@@ -273,42 +274,43 @@ void TetheringHandler::TetheringImpl::Bind(
std::unique_ptr<BoundSocket> bound_socket =
base::MakeUnique<BoundSocket>(accepted, socket_callback_);
if (!bound_socket->Listen(port)) {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
- &BindCallback::sendFailure,
- base::Passed(std::move(callback)),
- Response::Error("Could not bind port")));
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&BindCallback::sendFailure,
+ base::Passed(std::move(callback)),
+ Response::Error("Could not bind port")));
return;
}
bound_sockets_[port] = std::move(bound_socket);
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
- &BindCallback::sendSuccess,
- base::Passed(std::move(callback))));
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&BindCallback::sendSuccess,
+ base::Passed(std::move(callback))));
}
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::Bind(
- &UnbindCallback::sendFailure,
- base::Passed(std::move(callback)),
- Response::InvalidParams("Port is not bound")));
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&UnbindCallback::sendFailure,
+ base::Passed(std::move(callback)),
+ Response::InvalidParams("Port is not bound")));
return;
}
bound_sockets_.erase(it);
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
- &UnbindCallback::sendSuccess,
- base::Passed(std::move(callback))));
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&UnbindCallback::sendSuccess,
+ base::Passed(std::move(callback))));
}
void TetheringHandler::TetheringImpl::Accepted(uint16_t port,
const std::string& name) {
BrowserThread::PostTask(
- BrowserThread::UI,
- FROM_HERE,
- base::Bind(&TetheringHandler::Accepted, handler_, port, name));
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&TetheringHandler::Accepted, handler_, port, name));
}
@@ -368,8 +370,8 @@ void TetheringHandler::Bind(
DCHECK(impl_);
task_runner_->PostTask(
- FROM_HERE, base::Bind(&TetheringImpl::Bind, base::Unretained(impl_),
- port, base::Passed(std::move(callback))));
+ FROM_HERE, base::BindOnce(&TetheringImpl::Bind, base::Unretained(impl_),
+ port, base::Passed(std::move(callback))));
}
void TetheringHandler::Unbind(
@@ -382,8 +384,8 @@ void TetheringHandler::Unbind(
DCHECK(impl_);
task_runner_->PostTask(
- FROM_HERE, base::Bind(&TetheringImpl::Unbind, base::Unretained(impl_),
- port, base::Passed(std::move(callback))));
+ FROM_HERE, base::BindOnce(&TetheringImpl::Unbind, base::Unretained(impl_),
+ port, base::Passed(std::move(callback))));
}
} // namespace protocol
diff --git a/chromium/content/browser/devtools/protocol/tracing_handler.cc b/chromium/content/browser/devtools/protocol/tracing_handler.cc
index 63286a591f7..cff02198f79 100644
--- a/chromium/content/browser/devtools/protocol/tracing_handler.cc
+++ b/chromium/content/browser/devtools/protocol/tracing_handler.cc
@@ -95,7 +95,7 @@ class DevToolsStreamEndpoint : public TraceDataEndpoint {
public:
explicit DevToolsStreamEndpoint(
base::WeakPtr<TracingHandler> handler,
- const scoped_refptr<DevToolsIOContext::Stream>& stream)
+ const scoped_refptr<DevToolsIOContext::RWStream>& stream)
: stream_(stream), tracing_handler_(handler) {}
void ReceiveTraceChunk(std::unique_ptr<std::string> chunk) override {
@@ -111,7 +111,7 @@ class DevToolsStreamEndpoint : public TraceDataEndpoint {
private:
~DevToolsStreamEndpoint() override {}
- scoped_refptr<DevToolsIOContext::Stream> stream_;
+ scoped_refptr<DevToolsIOContext::RWStream> stream_;
base::WeakPtr<TracingHandler> tracing_handler_;
};
@@ -150,21 +150,87 @@ Response TracingHandler::Disable() {
}
void TracingHandler::OnTraceDataCollected(const std::string& trace_fragment) {
+ const std::string valid_trace_fragment =
+ UpdateTraceDataBuffer(trace_fragment);
+ if (valid_trace_fragment.empty())
+ return;
+
// Hand-craft protocol notification message so we can substitute JSON
// that we already got as string as a bare object, not a quoted string.
std::string message(
"{ \"method\": \"Tracing.dataCollected\", \"params\": { \"value\": [");
const size_t messageSuffixSize = 10;
- message.reserve(message.size() + trace_fragment.size() + messageSuffixSize);
- message += trace_fragment;
+ message.reserve(message.size() + valid_trace_fragment.size() +
+ messageSuffixSize);
+ message += valid_trace_fragment;
message += "] } }";
frontend_->sendRawNotification(message);
}
void TracingHandler::OnTraceComplete() {
+ if (!trace_data_buffer_state_.data.empty())
+ OnTraceDataCollected("");
+
+ DCHECK(trace_data_buffer_state_.data.empty());
+ DCHECK_EQ(0u, trace_data_buffer_state_.pos);
+ DCHECK_EQ(0, trace_data_buffer_state_.open_braces);
+ DCHECK(!trace_data_buffer_state_.in_string);
+ DCHECK(!trace_data_buffer_state_.slashed);
+
frontend_->TracingComplete();
}
+std::string TracingHandler::UpdateTraceDataBuffer(
+ const std::string& trace_fragment) {
+ size_t end = 0;
+ TraceDataBufferState& state = trace_data_buffer_state_;
+ for (; state.pos < trace_fragment.size(); ++state.pos) {
+ char c = trace_fragment[state.pos];
+ switch (c) {
+ case '{':
+ if (!state.in_string && !state.slashed)
+ state.open_braces++;
+ break;
+ case '}':
+ if (!state.in_string && !state.slashed) {
+ DCHECK_GT(state.open_braces, 0);
+ state.open_braces--;
+ if (state.open_braces == 0)
+ end = state.data.size() + state.pos + 1;
+ }
+ break;
+ case '"':
+ if (!state.slashed)
+ state.in_string = !state.in_string;
+ break;
+ case 'u':
+ if (state.slashed)
+ state.pos += 4;
+ break;
+ }
+
+ if (state.in_string && c == '\\') {
+ state.slashed = !state.slashed;
+ } else {
+ state.slashed = false;
+ }
+ }
+
+ // Next starting position is usually 0 except when we are in the middle of
+ // processing a unicode character, i.e. \uxxxx.
+ state.pos -= trace_fragment.size();
+ std::string complete_str = state.data + trace_fragment;
+
+ // Skip over commas between objects so that the next valid prefix does not
+ // start with a comma.
+ size_t next_start = complete_str.find('{', end);
+ state.data =
+ next_start == std::string::npos ? "" : complete_str.substr(next_start);
+
+ complete_str.resize(end);
+ return complete_str;
+}
+
void TracingHandler::OnTraceToStreamComplete(const std::string& stream_handle) {
frontend_->TracingComplete(stream_handle);
}
@@ -239,6 +305,8 @@ void TracingHandler::End(std::unique_ptr<EndCallback> callback) {
sink = TracingControllerImpl::CreateJSONSink(new DevToolsStreamEndpoint(
weak_factory_.GetWeakPtr(), io_context_->CreateTempFileBackedStream()));
} else {
+ // Reset the trace data buffer state.
+ trace_data_buffer_state_ = TracingHandler::TraceDataBufferState();
sink = new DevToolsTraceSinkProxy(weak_factory_.GetWeakPtr());
}
StopTracing(sink);
diff --git a/chromium/content/browser/devtools/protocol/tracing_handler.h b/chromium/content/browser/devtools/protocol/tracing_handler.h
index 5a2c63cc7b8..cb7c8a64a57 100644
--- a/chromium/content/browser/devtools/protocol/tracing_handler.h
+++ b/chromium/content/browser/devtools/protocol/tracing_handler.h
@@ -31,14 +31,13 @@ class DevToolsIOContext;
namespace protocol {
-class TracingHandler : public DevToolsDomainHandler,
- public Tracing::Backend {
+class TracingHandler : public DevToolsDomainHandler, public Tracing::Backend {
public:
enum Target { Browser, Renderer };
- TracingHandler(Target target,
- int frame_tree_node_id,
- DevToolsIOContext* io_context);
- ~TracingHandler() override;
+ CONTENT_EXPORT TracingHandler(Target target,
+ int frame_tree_node_id,
+ DevToolsIOContext* io_context);
+ CONTENT_EXPORT ~TracingHandler() override;
static std::vector<TracingHandler*> ForAgentHost(DevToolsAgentHostImpl* host);
@@ -65,6 +64,17 @@ class TracingHandler : public DevToolsDomainHandler,
bool did_initiate_recording() { return did_initiate_recording_; }
private:
+ friend class TracingHandlerTest;
+
+ struct TraceDataBufferState {
+ public:
+ std::string data;
+ size_t pos = 0;
+ int open_braces = 0;
+ bool in_string = false;
+ bool slashed = false;
+ };
+
void OnRecordingEnabled(std::unique_ptr<StartCallback> callback);
void OnBufferUsage(float percent_full, size_t approximate_event_count);
void OnCategoriesReceived(std::unique_ptr<GetCategoriesCallback> callback,
@@ -73,6 +83,12 @@ class TracingHandler : public DevToolsDomainHandler,
bool success,
uint64_t dump_id);
+ // Assuming that the input is a potentially incomplete string representation
+ // of a comma separated list of JSON objects, return the longest prefix that
+ // is a valid list and store the rest to be used in subsequent calls.
+ CONTENT_EXPORT std::string UpdateTraceDataBuffer(
+ const std::string& trace_fragment);
+
void SetupTimer(double usage_reporting_interval);
void StopTracing(
const scoped_refptr<TracingController::TraceDataSink>& trace_data_sink);
@@ -90,6 +106,7 @@ class TracingHandler : public DevToolsDomainHandler,
int frame_tree_node_id_;
bool did_initiate_recording_;
bool return_as_stream_;
+ TraceDataBufferState trace_data_buffer_state_;
base::WeakPtrFactory<TracingHandler> weak_factory_;
FRIEND_TEST_ALL_PREFIXES(TracingHandlerTest,
diff --git a/chromium/content/browser/devtools/protocol/tracing_handler_unittest.cc b/chromium/content/browser/devtools/protocol/tracing_handler_unittest.cc
index 0b1d7bc480d..352c7cab9ef 100644
--- a/chromium/content/browser/devtools/protocol/tracing_handler_unittest.cc
+++ b/chromium/content/browser/devtools/protocol/tracing_handler_unittest.cc
@@ -69,7 +69,24 @@ const char kCustomTraceConfigStringDevToolsStyle[] =
} // namespace
-TEST(TracingHandlerTest, GetTraceConfigFromDevToolsConfig) {
+class TracingHandlerTest : public testing::Test {
+ public:
+ void SetUp() override {
+ tracing_handler_.reset(
+ new TracingHandler(TracingHandler::Browser, 0, nullptr));
+ }
+
+ void TearDown() override { tracing_handler_.reset(); }
+
+ std::string UpdateTraceDataBuffer(const std::string& trace_fragment) {
+ return tracing_handler_->UpdateTraceDataBuffer(trace_fragment);
+ }
+
+ private:
+ std::unique_ptr<TracingHandler> tracing_handler_;
+};
+
+TEST_F(TracingHandlerTest, GetTraceConfigFromDevToolsConfig) {
std::unique_ptr<base::Value> value =
base::JSONReader::Read(kCustomTraceConfigStringDevToolsStyle);
std::unique_ptr<base::DictionaryValue> devtools_style_dict(
@@ -81,5 +98,30 @@ TEST(TracingHandlerTest, GetTraceConfigFromDevToolsConfig) {
EXPECT_STREQ(kCustomTraceConfigString, trace_config.ToString().c_str());
}
+TEST_F(TracingHandlerTest, SimpleUpdateTraceDataBuffer) {
+ // No prefix is valid.
+ EXPECT_EQ("", UpdateTraceDataBuffer("{pid: 1, "));
+
+ // The longest valid prefix of "{pid: 1, args: {}}, {pid: 2" is
+ // "{pid: 1, args: {}}".
+ EXPECT_EQ("{pid: 1, args: {}}", UpdateTraceDataBuffer("args: {}}, {pid: 2"));
+
+ EXPECT_EQ("{pid: 2}, {pid: 3}", UpdateTraceDataBuffer("}, {pid: 3}"));
+}
+
+TEST_F(TracingHandlerTest, ComplexUpdateTraceDataBuffer) {
+ const std::string chunk1 = "{\"pid\":1,\"args\":{\"key\":\"}\"},\"tid\":1}";
+ const std::string chunk2 =
+ "{\"pid\":2,\"args\":{\"key\":{\"key\":\"\\\"t}\"},\"key2\":2},\"tid\":"
+ "2}";
+ const std::string trace_data = chunk1 + "," + chunk2;
+
+ EXPECT_EQ("", UpdateTraceDataBuffer(trace_data.substr(0, chunk1.size() - 1)));
+ EXPECT_EQ(chunk1, UpdateTraceDataBuffer(trace_data.substr(
+ chunk1.size() - 1, trace_data.size() - chunk1.size())));
+ EXPECT_EQ(chunk2,
+ UpdateTraceDataBuffer(trace_data.substr(trace_data.size() - 1, 1)));
+}
+
} // namespace protocol
} // namespace content
diff --git a/chromium/content/browser/devtools/protocol_config.json b/chromium/content/browser/devtools/protocol_config.json
index afb7fd2d6d9..ed640ef3c57 100644
--- a/chromium/content/browser/devtools/protocol_config.json
+++ b/chromium/content/browser/devtools/protocol_config.json
@@ -10,6 +10,10 @@
"export_header": "content/common/content_export.h",
"options": [
{
+ "domain": "Browser",
+ "include": ["getVersion"]
+ },
+ {
"domain": "DOM",
"include": ["setFileInputFiles"],
"include_events": [],
@@ -17,19 +21,19 @@
},
{
"domain": "Emulation",
- "include": ["setGeolocationOverride", "clearGeolocationOverride", "setTouchEmulationEnabled", "canEmulate", "setDeviceMetricsOverride", "clearDeviceMetricsOverride", "setVisibleSize"]
+ "include": ["setGeolocationOverride", "clearGeolocationOverride", "setEmitTouchEventsForMouse", "canEmulate", "setDeviceMetricsOverride", "clearDeviceMetricsOverride", "setVisibleSize"]
},
{
"domain": "Input",
- "exclude": ["dispatchTouchEvent"],
- "async": ["dispatchKeyEvent", "dispatchMouseEvent", "synthesizePinchGesture", "synthesizeScrollGesture", "synthesizeTapGesture"]
+ "async": ["dispatchKeyEvent", "dispatchMouseEvent", "dispatchTouchEvent", "synthesizePinchGesture", "synthesizeScrollGesture", "synthesizeTapGesture"]
},
{
"domain": "Inspector"
},
{
"domain": "IO",
- "async": ["read"]
+ "async": ["read"],
+ "exclude": ["resolveBlob"]
},
{
"domain": "Memory",
@@ -37,18 +41,18 @@
},
{
"domain": "Network",
- "include": ["enable", "disable", "clearBrowserCache", "clearBrowserCookies", "getCookies", "getAllCookies", "deleteCookie", "setCookie", "setUserAgentOverride", "canEmulateNetworkConditions", "setRequestInterceptionEnabled", "continueInterceptedRequest"],
- "include_types": ["CookieSameSite", "Cookie", "Response", "Headers", "Request", "ResourceTiming", "SecurityDetails", "SignedCertificateTimestamp", "Initiator", "ResourcePriority", "RequestWillBeSentNotification", "ResponseReceivedNotification", "LoadingFinishedNotification", "LoadingFailedNotification", "RequestWillBeSentNotification",
+ "include": ["enable", "disable", "clearBrowserCache", "clearBrowserCookies", "getCookies", "getAllCookies", "deleteCookies", "setCookie", "setCookies", "setUserAgentOverride", "canEmulateNetworkConditions", "setRequestInterceptionEnabled", "continueInterceptedRequest"],
+ "include_types": ["CookieSameSite", "Cookie", "CookieParam", "Response", "Headers", "Request", "ResourceTiming", "SecurityDetails", "SignedCertificateTimestamp", "Initiator", "ResourcePriority", "RequestWillBeSentNotification", "ResponseReceivedNotification", "LoadingFinishedNotification", "LoadingFailedNotification", "RequestWillBeSentNotification",
"ErrorReason", "RequestInterceptedNotification", "AuthChallenge", "AuthChallengeResponse"],
"include_events": ["requestWillBeSent", "responseReceived", "loadingFinished", "loadingFailed", "requestIntercepted"],
- "async": ["clearBrowserCookies", "getCookies", "getAllCookies", "deleteCookie", "setCookie", "continueInterceptedRequest"]
+ "async": ["clearBrowserCookies", "getCookies", "getAllCookies", "deleteCookies", "setCookie", "setCookies", "continueInterceptedRequest"]
},
{
"domain": "Page",
"include": ["enable", "disable", "reload", "navigate", "stopLoading", "getNavigationHistory", "navigateToHistoryEntry", "captureScreenshot",
"startScreencast", "stopScreencast", "screencastFrameAck", "handleJavaScriptDialog", "setColorPickerEnabled", "requestAppBanner",
- "setControlNavigations", "processNavigation", "printToPDF"],
- "include_events": ["interstitialShown", "interstitialHidden", "navigationRequested", "screencastVisibilityChanged", "screencastFrame", "colorPicked"],
+ "printToPDF", "bringToFront", "setDownloadBehavior"],
+ "include_events": ["colorPicked", "interstitialShown", "interstitialHidden", "javascriptDialogOpening", "javascriptDialogClosed", "screencastVisibilityChanged", "screencastFrame"],
"async": ["captureScreenshot", "printToPDF"]
},
{
diff --git a/chromium/content/browser/devtools/protocol_string.cc b/chromium/content/browser/devtools/protocol_string.cc
index 3d24afddddf..891e59c6795 100644
--- a/chromium/content/browser/devtools/protocol_string.cc
+++ b/chromium/content/browser/devtools/protocol_string.cc
@@ -6,6 +6,8 @@
#include "base/json/json_reader.h"
#include "base/memory/ptr_util.h"
+#include "base/strings/string16.h"
+#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "content/browser/devtools/protocol/protocol.h"
@@ -144,6 +146,16 @@ void StringBuilder::append(const char* characters, size_t length) {
string_.append(characters, length);
}
+// static
+void StringUtil::builderAppendQuotedString(StringBuilder& builder,
+ const String& str) {
+ builder.append('"');
+ base::string16 str16 = base::UTF8ToUTF16(str);
+ escapeWideStringForJSON(reinterpret_cast<const uint16_t*>(&str16[0]),
+ str16.length(), &builder);
+ builder.append('"');
+}
+
std::string StringBuilder::toString() {
return string_;
}
diff --git a/chromium/content/browser/devtools/protocol_string.h b/chromium/content/browser/devtools/protocol_string.h
index 38dd03e41c3..71f4e2a4c01 100644
--- a/chromium/content/browser/devtools/protocol_string.h
+++ b/chromium/content/browser/devtools/protocol_string.h
@@ -28,10 +28,10 @@ class CONTENT_EXPORT StringBuilder {
public:
StringBuilder();
~StringBuilder();
- void append(const std::string&);
+ void append(const String&);
void append(char);
void append(const char*, size_t);
- std::string toString();
+ String toString();
void reserveCapacity(size_t);
private:
@@ -73,12 +73,15 @@ class CONTENT_EXPORT StringUtil {
static void builderAppend(StringBuilder& builder, const char* s, size_t len) {
builder.append(s, len);
}
+ static void builderAppendQuotedString(StringBuilder& builder,
+ const String& str);
static void builderReserve(StringBuilder& builder, unsigned capacity) {
builder.reserveCapacity(capacity);
}
static String builderToString(StringBuilder& builder) {
return builder.toString();
}
+
static std::unique_ptr<protocol::Value> parseJSON(const String&);
};
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 6de1f99bf4b..beb58e39cd8 100644
--- a/chromium/content/browser/devtools/render_frame_devtools_agent_host.cc
+++ b/chromium/content/browser/devtools/render_frame_devtools_agent_host.cc
@@ -18,7 +18,7 @@
#include "content/browser/devtools/devtools_frame_trace_recorder.h"
#include "content/browser/devtools/devtools_manager.h"
#include "content/browser/devtools/devtools_session.h"
-#include "content/browser/devtools/page_navigation_throttle.h"
+#include "content/browser/devtools/protocol/browser_handler.h"
#include "content/browser/devtools/protocol/dom_handler.h"
#include "content/browser/devtools/protocol/emulation_handler.h"
#include "content/browser/devtools/protocol/input_handler.h"
@@ -110,45 +110,41 @@ class RenderFrameDevToolsAgentHost::FrameHostHolder {
bool ProcessChunkedMessageFromAgent(const DevToolsMessageChunk& chunk);
void Suspend();
void Resume();
- std::string StateCookie() const { return chunk_processor_.state_cookie(); }
- void ReattachWithCookie(std::string cookie);
+ std::string StateCookie(int session_id) const;
+ void ReattachWithCookie(DevToolsSession* session, std::string cookie);
private:
- void SendMessageToClient(int session_id, const std::string& message);
+ struct Message {
+ std::string method;
+ std::string message;
+ };
+ struct SessionInfo {
+ std::unique_ptr<DevToolsMessageChunkProcessor> chunk_processor;
+ std::vector<std::string> pending_messages;
+ using CallId = int;
+ std::map<CallId, Message> sent_messages;
+ };
+
+ void SendChunkedMessage(int session_id, const std::string& message);
+ SessionInfo& InitInfo(int session_id);
RenderFrameDevToolsAgentHost* agent_;
RenderFrameHostImpl* host_;
- bool attached_;
bool suspended_;
- DevToolsMessageChunkProcessor chunk_processor_;
- struct PendingMessage {
- int session_id;
- std::string method;
- std::string message;
- };
- // <session_id, message>
- std::vector<std::pair<int, std::string>> pending_messages_;
- // <call_id> -> PendingMessage
- std::map<int, PendingMessage> sent_messages_;
- // These are sent messages for which we got a reply while suspended.
- std::map<int, PendingMessage> sent_messages_whose_reply_came_while_suspended_;
+ base::flat_map<int, SessionInfo> infos_;
};
RenderFrameDevToolsAgentHost::FrameHostHolder::FrameHostHolder(
- RenderFrameDevToolsAgentHost* agent, RenderFrameHostImpl* host)
- : agent_(agent),
- host_(host),
- attached_(false),
- suspended_(false),
- chunk_processor_(base::Bind(
- &RenderFrameDevToolsAgentHost::FrameHostHolder::SendMessageToClient,
- base::Unretained(this))) {
+ RenderFrameDevToolsAgentHost* agent,
+ RenderFrameHostImpl* host)
+ : agent_(agent), host_(host), suspended_(false) {
+ DCHECK(!IsBrowserSideNavigationEnabled());
DCHECK(agent_);
DCHECK(host_);
}
RenderFrameDevToolsAgentHost::FrameHostHolder::~FrameHostHolder() {
- if (attached_)
+ if (!infos_.empty())
agent_->RevokePolicy(host_);
}
@@ -157,42 +153,48 @@ void RenderFrameDevToolsAgentHost::FrameHostHolder::Attach(
host_->Send(new DevToolsAgentMsg_Attach(
host_->GetRoutingID(), agent_->GetId(), session->session_id()));
agent_->GrantPolicy(host_);
- attached_ = true;
+ InitInfo(session->session_id());
}
void RenderFrameDevToolsAgentHost::FrameHostHolder::Reattach(
FrameHostHolder* old) {
- std::string cookie = old ? old->chunk_processor_.state_cookie() : "";
- ReattachWithCookie(std::move(cookie));
- if (!old)
- return;
- if (IsBrowserSideNavigationEnabled()) {
- for (const auto& pair :
- old->sent_messages_whose_reply_came_while_suspended_) {
- DispatchProtocolMessage(pair.second.session_id, pair.first,
- pair.second.method, pair.second.message);
+ for (DevToolsSession* session : agent_->sessions()) {
+ int session_id = session->session_id();
+ std::string cookie = old ? old->StateCookie(session_id) : std::string();
+ ReattachWithCookie(session, std::move(cookie));
+ if (!old)
+ continue;
+ auto it = old->infos_.find(session_id);
+ if (it == old->infos_.end())
+ continue;
+ for (const auto& pair : it->second.sent_messages) {
+ DispatchProtocolMessage(session_id, pair.first, pair.second.method,
+ pair.second.message);
}
}
- for (const auto& pair : old->sent_messages_) {
- DispatchProtocolMessage(pair.second.session_id, pair.first,
- pair.second.method, pair.second.message);
- }
+}
+
+std::string RenderFrameDevToolsAgentHost::FrameHostHolder::StateCookie(
+ int session_id) const {
+ auto it = infos_.find(session_id);
+ if (it == infos_.end())
+ return std::string();
+ return it->second.chunk_processor->state_cookie();
}
void RenderFrameDevToolsAgentHost::FrameHostHolder::ReattachWithCookie(
+ DevToolsSession* session,
std::string cookie) {
- chunk_processor_.set_state_cookie(cookie);
+ InitInfo(session->session_id()).chunk_processor->set_state_cookie(cookie);
host_->Send(new DevToolsAgentMsg_Reattach(
- host_->GetRoutingID(), agent_->GetId(),
- agent_->SingleSession()->session_id(), cookie));
+ host_->GetRoutingID(), agent_->GetId(), session->session_id(), cookie));
agent_->GrantPolicy(host_);
- attached_ = true;
}
void RenderFrameDevToolsAgentHost::FrameHostHolder::Detach(int session_id) {
host_->Send(new DevToolsAgentMsg_Detach(host_->GetRoutingID(), session_id));
agent_->RevokePolicy(host_);
- attached_ = false;
+ infos_.erase(session_id);
}
void RenderFrameDevToolsAgentHost::FrameHostHolder::DispatchProtocolMessage(
@@ -202,12 +204,11 @@ void RenderFrameDevToolsAgentHost::FrameHostHolder::DispatchProtocolMessage(
const std::string& message) {
host_->Send(new DevToolsAgentMsg_DispatchOnInspectorBackend(
host_->GetRoutingID(), session_id, call_id, method, message));
- sent_messages_[call_id] = {session_id, method, message};
+ infos_[session_id].sent_messages[call_id] = {method, message};
}
void RenderFrameDevToolsAgentHost::FrameHostHolder::InspectElement(
int session_id, int x, int y) {
- DCHECK(attached_);
host_->Send(new DevToolsAgentMsg_InspectElement(
host_->GetRoutingID(), session_id, x, y));
}
@@ -215,21 +216,27 @@ void RenderFrameDevToolsAgentHost::FrameHostHolder::InspectElement(
bool
RenderFrameDevToolsAgentHost::FrameHostHolder::ProcessChunkedMessageFromAgent(
const DevToolsMessageChunk& chunk) {
- return chunk_processor_.ProcessChunkedMessageFromAgent(chunk);
+ auto it = infos_.find(chunk.session_id);
+ if (it != infos_.end())
+ return it->second.chunk_processor->ProcessChunkedMessageFromAgent(chunk);
+ return true;
}
-void RenderFrameDevToolsAgentHost::FrameHostHolder::SendMessageToClient(
+void RenderFrameDevToolsAgentHost::FrameHostHolder::SendChunkedMessage(
int session_id,
const std::string& message) {
- int id = chunk_processor_.last_call_id();
- PendingMessage sent_message = sent_messages_[id];
- sent_messages_.erase(id);
+ auto it = infos_.find(session_id);
+ if (it == infos_.end())
+ return;
+ SessionInfo& info = it->second;
+ int id = info.chunk_processor->last_call_id();
+ Message sent_message = std::move(info.sent_messages[id]);
+ info.sent_messages.erase(id);
if (suspended_) {
- sent_messages_whose_reply_came_while_suspended_[id] = sent_message;
- pending_messages_.push_back(std::make_pair(session_id, message));
+ info.pending_messages.push_back(message);
} else {
- DevToolsSession* session = agent_->SingleSession();
- if (session && session->session_id() == session_id)
+ DevToolsSession* session = agent_->SessionById(session_id);
+ if (session)
session->SendMessageToClient(message);
// |this| may be deleted at this point.
}
@@ -241,14 +248,24 @@ void RenderFrameDevToolsAgentHost::FrameHostHolder::Suspend() {
void RenderFrameDevToolsAgentHost::FrameHostHolder::Resume() {
suspended_ = false;
- for (const auto& pair : pending_messages_) {
- DevToolsSession* session = agent_->SingleSession();
- if (session && session->session_id() == pair.first)
- session->SendMessageToClient(pair.second);
+ for (DevToolsSession* session : agent_->sessions()) {
+ auto it = infos_.find(session->session_id());
+ if (it == infos_.end())
+ return;
+ SessionInfo& info = it->second;
+ std::vector<std::string> messages = std::move(info.pending_messages);
+ for (std::string& message : messages)
+ session->SendMessageToClient(message);
}
- std::vector<std::pair<int, std::string>> empty;
- pending_messages_.swap(empty);
- sent_messages_whose_reply_came_while_suspended_.clear();
+}
+
+RenderFrameDevToolsAgentHost::FrameHostHolder::SessionInfo&
+RenderFrameDevToolsAgentHost::FrameHostHolder::InitInfo(int session_id) {
+ SessionInfo& info = infos_[session_id];
+ info.chunk_processor.reset(new DevToolsMessageChunkProcessor(base::Bind(
+ &RenderFrameDevToolsAgentHost::FrameHostHolder::SendChunkedMessage,
+ base::Unretained(this))));
+ return info;
}
// RenderFrameDevToolsAgentHost ------------------------------------------------
@@ -355,14 +372,14 @@ RenderFrameDevToolsAgentHost::CreateThrottleForNavigation(
frame_tree_node = frame_tree_node->parent();
}
RenderFrameDevToolsAgentHost* agent_host = FindAgentHost(frame_tree_node);
- // Note Page.setControlNavigations is intended to control navigations in the
- // main frame and all child frames and |page_handler_| only exists for the
- // main frame.
+ // Note Network.setRequestInterceptionEnabled is intended to control
+ // navigations in the main frame and all child frames.
if (!agent_host)
return nullptr;
- for (auto* page_handler : protocol::PageHandler::ForAgentHost(agent_host)) {
+ for (auto* network_handler :
+ protocol::NetworkHandler::ForAgentHost(agent_host)) {
std::unique_ptr<NavigationThrottle> throttle =
- page_handler->CreateThrottleForNavigation(navigation_handle);
+ network_handler->CreateThrottleForNavigation(navigation_handle);
if (throttle)
return throttle;
}
@@ -384,18 +401,30 @@ bool RenderFrameDevToolsAgentHost::IsNetworkHandlerEnabled(
}
// static
-std::string RenderFrameDevToolsAgentHost::UserAgentOverride(
- FrameTreeNode* frame_tree_node) {
+void RenderFrameDevToolsAgentHost::AppendDevToolsHeaders(
+ FrameTreeNode* frame_tree_node,
+ net::HttpRequestHeaders* headers) {
+ static const char kDevToolsEmulateNetworkConditionsClientId[] =
+ "X-DevTools-Emulate-Network-Conditions-Client-Id";
+
frame_tree_node = GetFrameTreeNodeAncestor(frame_tree_node);
RenderFrameDevToolsAgentHost* agent_host = FindAgentHost(frame_tree_node);
if (!agent_host)
- return std::string();
+ return;
+ std::string ua_override;
+ bool enabled = false;
for (auto* network : protocol::NetworkHandler::ForAgentHost(agent_host)) {
- std::string override = network->UserAgentOverride();
- if (!override.empty())
- return override;
+ enabled = enabled || network->enabled();
+ ua_override = network->UserAgentOverride();
+ if (!ua_override.empty())
+ break;
}
- return std::string();
+ if (!enabled)
+ return;
+ headers->SetHeader(kDevToolsEmulateNetworkConditionsClientId,
+ agent_host->GetId());
+ if (!ua_override.empty())
+ headers->SetHeader(net::HttpRequestHeaders::kUserAgent, ua_override);
}
// static
@@ -495,6 +524,7 @@ void RenderFrameDevToolsAgentHost::AttachSession(DevToolsSession* session) {
protocol::EmulationHandler* emulation_handler =
new protocol::EmulationHandler();
+ session->AddHandler(base::WrapUnique(new protocol::BrowserHandler()));
session->AddHandler(base::WrapUnique(new protocol::DOMHandler()));
session->AddHandler(base::WrapUnique(emulation_handler));
session->AddHandler(base::WrapUnique(new protocol::InputHandler()));
@@ -666,9 +696,9 @@ void RenderFrameDevToolsAgentHost::DidFinishNavigation(
// UpdateFrameHost may destruct |this|.
scoped_refptr<RenderFrameDevToolsAgentHost> protect(this);
- if (handle->HasCommitted() && !handle->IsErrorPage())
- UpdateFrameHost(handle->GetRenderFrameHost());
+ UpdateFrameHost(frame_tree_node_->current_frame_host());
DCHECK(CheckConsistency());
+
if (navigation_handles_.empty()) {
for (auto& pair : suspended_messages_by_session_id_) {
int session_id = pair.first;
@@ -1061,7 +1091,7 @@ void RenderFrameDevToolsAgentHost::UpdateProtocolHandlers(
handlers_frame_host_->GetRenderWidgetHost()->GetRoutingID();
#endif
handlers_frame_host_ = host;
- if (DevToolsSession* session = SingleSession())
+ for (DevToolsSession* session : sessions())
session->SetRenderFrameHost(host);
}
@@ -1076,9 +1106,11 @@ void RenderFrameDevToolsAgentHost::DisconnectWebContents() {
if (pending_)
DiscardPending();
UpdateProtocolHandlers(nullptr);
- if (DevToolsSession* session = SingleSession()) {
- disconnected_cookie_ = current_->StateCookie();
- current_->Detach(session->session_id());
+ for (DevToolsSession* session : sessions()) {
+ int session_id = session->session_id();
+ disconnected_cookie_for_session_[session_id] =
+ current_->StateCookie(session_id);
+ current_->Detach(session_id);
}
current_.reset();
frame_tree_node_ = nullptr;
@@ -1106,9 +1138,12 @@ void RenderFrameDevToolsAgentHost::ConnectWebContents(WebContents* wc) {
DCHECK(host);
current_frame_crashed_ = false;
current_.reset(new FrameHostHolder(this, host));
- std::string cookie = std::move(disconnected_cookie_);
- if (IsAttached())
- current_->ReattachWithCookie(std::move(cookie));
+ for (DevToolsSession* session : sessions()) {
+ current_->ReattachWithCookie(
+ session,
+ std::move(disconnected_cookie_for_session_[session->session_id()]));
+ }
+ disconnected_cookie_for_session_.clear();
UpdateProtocolHandlers(host);
frame_tree_node_ = host->frame_tree_node();
@@ -1239,10 +1274,9 @@ void RenderFrameDevToolsAgentHost::SignalSynchronousSwapCompositorFrame(
// Unblock the compositor.
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(
+ base::BindOnce(
&RenderFrameDevToolsAgentHost::SynchronousSwapCompositorFrame,
- dtah.get(),
- base::Passed(std::move(frame_metadata))));
+ dtah.get(), base::Passed(std::move(frame_metadata))));
}
}
@@ -1314,9 +1348,4 @@ bool RenderFrameDevToolsAgentHost::IsChildFrame() {
return frame_tree_node_ && frame_tree_node_->parent();
}
-DevToolsSession* RenderFrameDevToolsAgentHost::SingleSession() {
- DCHECK(!IsBrowserSideNavigationEnabled());
- return sessions().empty() ? nullptr : *sessions().begin();
-}
-
} // namespace content
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 f0a499c2955..eb785bee16e 100644
--- a/chromium/content/browser/devtools/render_frame_devtools_agent_host.h
+++ b/chromium/content/browser/devtools/render_frame_devtools_agent_host.h
@@ -9,6 +9,7 @@
#include <memory>
#include "base/compiler_specific.h"
+#include "base/containers/flat_map.h"
#include "base/containers/flat_set.h"
#include "base/macros.h"
#include "build/build_config.h"
@@ -25,6 +26,10 @@ namespace cc {
class CompositorFrameMetadata;
}
+namespace net {
+class HttpRequestHeaders;
+}
+
#if defined(OS_ANDROID)
#include "services/device/public/interfaces/wake_lock.mojom.h"
#endif
@@ -60,8 +65,8 @@ class CONTENT_EXPORT RenderFrameDevToolsAgentHost
static std::unique_ptr<NavigationThrottle> CreateThrottleForNavigation(
NavigationHandle* navigation_handle);
static bool IsNetworkHandlerEnabled(FrameTreeNode* frame_tree_node);
- static std::string UserAgentOverride(FrameTreeNode* frame_tree_node);
-
+ static void AppendDevToolsHeaders(FrameTreeNode* frame_tree_node,
+ net::HttpRequestHeaders* headers);
static void WebContentsCreated(WebContents* web_contents);
static void SignalSynchronousSwapCompositorFrame(
@@ -144,9 +149,6 @@ class CONTENT_EXPORT RenderFrameDevToolsAgentHost
void GrantPolicy(RenderFrameHostImpl* host);
void RevokePolicy(RenderFrameHostImpl* host);
- // TODO(dgozman): remove together with old navigation code.
- DevToolsSession* SingleSession();
-
#if defined(OS_ANDROID)
device::mojom::WakeLock* GetWakeLock();
#endif
@@ -160,7 +162,7 @@ class CONTENT_EXPORT RenderFrameDevToolsAgentHost
std::unique_ptr<FrameHostHolder> pending_;
// Stores per-host state between DisconnectWebContents and ConnectWebContents.
- std::string disconnected_cookie_;
+ base::flat_map<int, std::string> disconnected_cookie_for_session_;
std::unique_ptr<DevToolsFrameTraceRecorder> frame_trace_recorder_;
#if defined(OS_ANDROID)
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 5b8aef57212..d72f8b94934 100644
--- a/chromium/content/browser/devtools/service_worker_devtools_agent_host.cc
+++ b/chromium/content/browser/devtools/service_worker_devtools_agent_host.cc
@@ -68,7 +68,7 @@ std::string ServiceWorkerDevToolsAgentHost::GetType() {
std::string ServiceWorkerDevToolsAgentHost::GetTitle() {
if (RenderProcessHost* host = RenderProcessHost::FromID(worker_id().first)) {
- return base::StringPrintf("Worker pid:%d",
+ return base::StringPrintf("Worker pid:%" CrPRIdPid,
base::GetProcId(host->GetHandle()));
}
return "";
@@ -87,25 +87,24 @@ void ServiceWorkerDevToolsAgentHost::Reload() {
bool ServiceWorkerDevToolsAgentHost::Close() {
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::Bind(&TerminateServiceWorkerOnIO,
- service_worker_->context_weak(),
- service_worker_->version_id()));
+ base::BindOnce(&TerminateServiceWorkerOnIO,
+ service_worker_->context_weak(),
+ service_worker_->version_id()));
return true;
}
void ServiceWorkerDevToolsAgentHost::UnregisterWorker() {
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::Bind(&UnregisterServiceWorkerOnIO,
- service_worker_->context_weak(),
- service_worker_->version_id()));
+ base::BindOnce(&UnregisterServiceWorkerOnIO,
+ service_worker_->context_weak(),
+ service_worker_->version_id()));
}
void ServiceWorkerDevToolsAgentHost::OnAttachedStateChanged(bool attached) {
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::Bind(&SetDevToolsAttachedOnIO,
- service_worker_->context_weak(),
- service_worker_->version_id(),
- attached));
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&SetDevToolsAttachedOnIO, service_worker_->context_weak(),
+ service_worker_->version_id(), attached));
}
void ServiceWorkerDevToolsAgentHost::WorkerVersionInstalled() {
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 921123022c4..6f876df1cb1 100644
--- a/chromium/content/browser/devtools/shared_worker_devtools_agent_host.cc
+++ b/chromium/content/browser/devtools/shared_worker_devtools_agent_host.cc
@@ -50,8 +50,9 @@ void SharedWorkerDevToolsAgentHost::Reload() {
}
bool SharedWorkerDevToolsAgentHost::Close() {
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::Bind(&TerminateSharedWorkerOnIO, worker_id()));
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&TerminateSharedWorkerOnIO, worker_id()));
return true;
}
diff --git a/chromium/content/browser/devtools/site_per_process_devtools_browsertest.cc b/chromium/content/browser/devtools/site_per_process_devtools_browsertest.cc
index 2d9ad30e67f..8b976de043f 100644
--- a/chromium/content/browser/devtools/site_per_process_devtools_browsertest.cc
+++ b/chromium/content/browser/devtools/site_per_process_devtools_browsertest.cc
@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "build/build_config.h"
#include "content/browser/devtools/render_frame_devtools_agent_host.h"
@@ -42,7 +41,7 @@ class TestClient: public DevToolsAgentHostClient {
const std::string& message) override {
if (waiting_for_reply_) {
waiting_for_reply_ = false;
- base::MessageLoop::current()->QuitNow();
+ base::RunLoop::QuitCurrentDeprecated();
}
}
@@ -239,7 +238,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessDownloadDevToolsBrowserTest,
scoped_refptr<DevToolsAgentHost> agent =
DevToolsAgentHost::GetOrCreateFor(shell()->web_contents());
TestClient client;
- ASSERT_TRUE(agent->AttachClient(&client));
+ agent->AttachClient(&client);
char message[] = "{\"id\": 0, \"method\": \"incorrect.method\"}";
// Check that client is responsive.
agent->DispatchProtocolMessage(&client, message);
diff --git a/chromium/content/browser/discardable_shared_memory_manager.cc b/chromium/content/browser/discardable_shared_memory_manager.cc
new file mode 100644
index 00000000000..54c05e9f758
--- /dev/null
+++ b/chromium/content/browser/discardable_shared_memory_manager.cc
@@ -0,0 +1,17 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/public/browser/discardable_shared_memory_manager.h"
+
+#include "content/browser/browser_main_loop.h"
+
+namespace content {
+
+discardable_memory::DiscardableSharedMemoryManager*
+GetDiscardableSharedMemoryManager() {
+ return content::BrowserMainLoop::GetInstance()
+ ->discardable_shared_memory_manager();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/dom_storage/dom_storage_area.cc b/chromium/content/browser/dom_storage/dom_storage_area.cc
index 87b55701d64..9dcc3d0f7e1 100644
--- a/chromium/content/browser/dom_storage/dom_storage_area.cc
+++ b/chromium/content/browser/dom_storage/dom_storage_area.cc
@@ -341,9 +341,8 @@ void DOMStorageArea::Shutdown() {
return;
bool success = task_runner_->PostShutdownBlockingTask(
- FROM_HERE,
- DOMStorageTaskRunner::COMMIT_SEQUENCE,
- base::Bind(&DOMStorageArea::ShutdownInCommitSequence, this));
+ FROM_HERE, DOMStorageTaskRunner::COMMIT_SEQUENCE,
+ base::BindOnce(&DOMStorageArea::ShutdownInCommitSequence, this));
DCHECK(success);
}
@@ -381,13 +380,13 @@ void DOMStorageArea::OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd) {
backing_->ReportMemoryUsage(pmd, name + "/local_storage");
// Do not add storage map usage if less than 1KB.
- if (map_->bytes_used() < 1024)
+ if (map_->memory_usage() < 1024)
return;
auto* map_mad = pmd->CreateAllocatorDump(name + "/storage_map");
map_mad->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
base::trace_event::MemoryAllocatorDump::kUnitsBytes,
- map_->bytes_used());
+ map_->memory_usage());
if (system_allocator_name)
pmd->AddSuballocation(map_mad->guid(), system_allocator_name);
}
@@ -435,7 +434,7 @@ DOMStorageArea::CommitBatch* DOMStorageArea::CreateCommitBatchIfNeeded() {
commit_batch_.reset(new CommitBatch());
BrowserThread::PostAfterStartupTask(
FROM_HERE, task_runner_,
- base::Bind(&DOMStorageArea::StartCommitTimer, this));
+ base::BindOnce(&DOMStorageArea::StartCommitTimer, this));
}
return commit_batch_.get();
}
@@ -457,7 +456,7 @@ void DOMStorageArea::StartCommitTimer() {
return;
task_runner_->PostDelayedTask(
- FROM_HERE, base::Bind(&DOMStorageArea::OnCommitTimer, this),
+ FROM_HERE, base::BindOnce(&DOMStorageArea::OnCommitTimer, this),
ComputeCommitDelay());
}
@@ -500,10 +499,9 @@ void DOMStorageArea::PostCommitTask() {
// a task for immediate execution on the commit sequence.
task_runner_->AssertIsRunningOnPrimarySequence();
bool success = task_runner_->PostShutdownBlockingTask(
- FROM_HERE,
- DOMStorageTaskRunner::COMMIT_SEQUENCE,
- base::Bind(&DOMStorageArea::CommitChanges, this,
- base::Owned(commit_batch_.release())));
+ FROM_HERE, DOMStorageTaskRunner::COMMIT_SEQUENCE,
+ base::BindOnce(&DOMStorageArea::CommitChanges, this,
+ base::Owned(commit_batch_.release())));
++commit_batches_in_flight_;
DCHECK(success);
}
@@ -516,8 +514,7 @@ void DOMStorageArea::CommitChanges(const CommitBatch* commit_batch) {
// TODO(michaeln): what if CommitChanges returns false (e.g., we're trying to
// commit to a DB which is in an inconsistent state?)
task_runner_->PostTask(
- FROM_HERE,
- base::Bind(&DOMStorageArea::OnCommitComplete, this));
+ FROM_HERE, base::BindOnce(&DOMStorageArea::OnCommitComplete, this));
}
void DOMStorageArea::OnCommitComplete() {
@@ -529,7 +526,7 @@ void DOMStorageArea::OnCommitComplete() {
if (commit_batch_.get() && !commit_batches_in_flight_) {
// More changes have accrued, restart the timer.
task_runner_->PostDelayedTask(
- FROM_HERE, base::Bind(&DOMStorageArea::OnCommitTimer, this),
+ FROM_HERE, base::BindOnce(&DOMStorageArea::OnCommitTimer, this),
ComputeCommitDelay());
}
}
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 8ec3f313f0e..7ed06ea1a4c 100644
--- a/chromium/content/browser/dom_storage/dom_storage_area_unittest.cc
+++ b/chromium/content/browser/dom_storage/dom_storage_area_unittest.cc
@@ -54,8 +54,8 @@ class DOMStorageAreaTest : public testing::Test {
// that.
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
- base::Bind(&DOMStorageAreaTest::InjectedCommitSequencingTask2,
- base::Unretained(this), area));
+ base::BindOnce(&DOMStorageAreaTest::InjectedCommitSequencingTask2,
+ base::Unretained(this), area));
}
void InjectedCommitSequencingTask2(
@@ -287,9 +287,8 @@ TEST_F(DOMStorageAreaTest, CommitTasks) {
// that a new commit batch is created for that additional change.
BrowserThread::PostAfterStartupTask(
FROM_HERE, base::ThreadTaskRunnerHandle::Get(),
- base::Bind(&DOMStorageAreaTest::InjectedCommitSequencingTask1,
- base::Unretained(this),
- area));
+ base::BindOnce(&DOMStorageAreaTest::InjectedCommitSequencingTask1,
+ base::Unretained(this), area));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(area->HasOneRef());
EXPECT_FALSE(area->HasUncommittedChanges());
diff --git a/chromium/content/browser/dom_storage/dom_storage_browsertest.cc b/chromium/content/browser/dom_storage/dom_storage_browsertest.cc
index c9efa248e17..2e5e1265f68 100644
--- a/chromium/content/browser/dom_storage/dom_storage_browsertest.cc
+++ b/chromium/content/browser/dom_storage/dom_storage_browsertest.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "base/command_line.h"
+#include "base/run_loop.h"
#include "build/build_config.h"
#include "content/browser/dom_storage/dom_storage_context_wrapper.h"
#include "content/browser/dom_storage/local_storage_context_mojo.h"
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 2b945dea40f..2519425d119 100644
--- a/chromium/content/browser/dom_storage/dom_storage_context_impl.cc
+++ b/chromium/content/browser/dom_storage/dom_storage_context_impl.cc
@@ -109,10 +109,9 @@ DOMStorageContextImpl::~DOMStorageContextImpl() {
to_release->AddRef();
session_storage_database_ = NULL;
task_runner_->PostShutdownBlockingTask(
- FROM_HERE,
- DOMStorageTaskRunner::COMMIT_SEQUENCE,
- base::Bind(&SessionStorageDatabase::Release,
- base::Unretained(to_release)));
+ FROM_HERE, DOMStorageTaskRunner::COMMIT_SEQUENCE,
+ base::BindOnce(&SessionStorageDatabase::Release,
+ base::Unretained(to_release)));
}
}
@@ -297,9 +296,8 @@ void DOMStorageContextImpl::Shutdown() {
// commit sequence after area shutdown tasks have cycled
// thru that sequence (and closed their database files).
bool success = task_runner_->PostShutdownBlockingTask(
- FROM_HERE,
- DOMStorageTaskRunner::COMMIT_SEQUENCE,
- base::Bind(&DOMStorageContextImpl::ClearSessionOnlyOrigins, this));
+ FROM_HERE, DOMStorageTaskRunner::COMMIT_SEQUENCE,
+ base::BindOnce(&DOMStorageContextImpl::ClearSessionOnlyOrigins, this));
DCHECK(success);
}
}
@@ -390,12 +388,10 @@ void DOMStorageContextImpl::DeleteSessionNamespace(int64_t namespace_id,
if (session_storage_database_.get()) {
if (!should_persist_data) {
task_runner_->PostShutdownBlockingTask(
- FROM_HERE,
- DOMStorageTaskRunner::COMMIT_SEQUENCE,
- base::Bind(
+ FROM_HERE, DOMStorageTaskRunner::COMMIT_SEQUENCE,
+ base::BindOnce(
base::IgnoreResult(&SessionStorageDatabase::DeleteNamespace),
- session_storage_database_,
- persistent_namespace_id));
+ session_storage_database_, persistent_namespace_id));
} else {
// Ensure that the data gets committed before we shut down.
it->second->Shutdown();
@@ -472,8 +468,8 @@ void DOMStorageContextImpl::SetSaveSessionStorageOnDisk() {
void DOMStorageContextImpl::StartScavengingUnusedSessionStorage() {
if (session_storage_database_.get()) {
task_runner_->PostDelayedTask(
- FROM_HERE, base::Bind(&DOMStorageContextImpl::FindUnusedNamespaces,
- this),
+ FROM_HERE,
+ base::BindOnce(&DOMStorageContextImpl::FindUnusedNamespaces, this),
base::TimeDelta::FromSeconds(kSessionStoraceScavengingSeconds));
}
}
@@ -581,9 +577,9 @@ void DOMStorageContextImpl::FindUnusedNamespaces() {
protected_persistent_session_ids.swap(protected_persistent_session_ids_);
task_runner_->PostShutdownBlockingTask(
FROM_HERE, DOMStorageTaskRunner::COMMIT_SEQUENCE,
- base::Bind(
- &DOMStorageContextImpl::FindUnusedNamespacesInCommitSequence,
- this, namespace_ids_in_use, protected_persistent_session_ids));
+ base::BindOnce(
+ &DOMStorageContextImpl::FindUnusedNamespacesInCommitSequence, this,
+ namespace_ids_in_use, protected_persistent_session_ids));
}
void DOMStorageContextImpl::FindUnusedNamespacesInCommitSequence(
@@ -605,9 +601,8 @@ void DOMStorageContextImpl::FindUnusedNamespacesInCommitSequence(
}
if (!deletable_persistent_namespace_ids_.empty()) {
task_runner_->PostDelayedTask(
- FROM_HERE, base::Bind(
- &DOMStorageContextImpl::DeleteNextUnusedNamespace,
- this),
+ FROM_HERE,
+ base::BindOnce(&DOMStorageContextImpl::DeleteNextUnusedNamespace, this),
base::TimeDelta::FromSeconds(kSessionStoraceScavengingSeconds));
}
}
@@ -616,10 +611,10 @@ void DOMStorageContextImpl::DeleteNextUnusedNamespace() {
if (is_shutdown_)
return;
task_runner_->PostShutdownBlockingTask(
- FROM_HERE, DOMStorageTaskRunner::COMMIT_SEQUENCE,
- base::Bind(
- &DOMStorageContextImpl::DeleteNextUnusedNamespaceInCommitSequence,
- this));
+ FROM_HERE, DOMStorageTaskRunner::COMMIT_SEQUENCE,
+ base::BindOnce(
+ &DOMStorageContextImpl::DeleteNextUnusedNamespaceInCommitSequence,
+ this));
}
void DOMStorageContextImpl::DeleteNextUnusedNamespaceInCommitSequence() {
@@ -630,9 +625,8 @@ void DOMStorageContextImpl::DeleteNextUnusedNamespaceInCommitSequence() {
deletable_persistent_namespace_ids_.pop_back();
if (!deletable_persistent_namespace_ids_.empty()) {
task_runner_->PostDelayedTask(
- FROM_HERE, base::Bind(
- &DOMStorageContextImpl::DeleteNextUnusedNamespace,
- this),
+ FROM_HERE,
+ base::BindOnce(&DOMStorageContextImpl::DeleteNextUnusedNamespace, this),
base::TimeDelta::FromSeconds(kSessionStoraceScavengingSeconds));
}
}
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 47b7c9b2548..520158f3672 100644
--- a/chromium/content/browser/dom_storage/dom_storage_context_wrapper.cc
+++ b/chromium/content/browser/dom_storage/dom_storage_context_wrapper.cc
@@ -86,8 +86,8 @@ void GetSessionStorageUsageHelper(
new std::vector<SessionStorageUsageInfo>;
context->GetSessionStorageUsage(infos);
reply_task_runner->PostTask(
- FROM_HERE, base::Bind(&InvokeSessionStorageUsageCallbackHelper, callback,
- base::Owned(infos)));
+ FROM_HERE, base::BindOnce(&InvokeSessionStorageUsageCallbackHelper,
+ callback, base::Owned(infos)));
}
} // namespace
@@ -172,18 +172,18 @@ void DOMStorageContextWrapper::GetLocalStorageUsage(
got_local_storage_usage))));
context_->task_runner()->PostShutdownBlockingTask(
FROM_HERE, DOMStorageTaskRunner::PRIMARY_SEQUENCE,
- base::Bind(&GetLocalStorageUsageHelper,
- base::RetainedRef(base::ThreadTaskRunnerHandle::Get()),
- base::RetainedRef(context_),
- base::Bind(&CollectLocalStorageUsage, infos_ptr,
- got_local_storage_usage)));
+ base::BindOnce(&GetLocalStorageUsageHelper,
+ base::RetainedRef(base::ThreadTaskRunnerHandle::Get()),
+ base::RetainedRef(context_),
+ base::Bind(&CollectLocalStorageUsage, infos_ptr,
+ got_local_storage_usage)));
return;
}
context_->task_runner()->PostShutdownBlockingTask(
FROM_HERE, DOMStorageTaskRunner::PRIMARY_SEQUENCE,
- base::Bind(&GetLocalStorageUsageHelper,
- base::RetainedRef(base::ThreadTaskRunnerHandle::Get()),
- base::RetainedRef(context_), callback));
+ base::BindOnce(&GetLocalStorageUsageHelper,
+ base::RetainedRef(base::ThreadTaskRunnerHandle::Get()),
+ base::RetainedRef(context_), callback));
}
void DOMStorageContextWrapper::GetSessionStorageUsage(
@@ -191,9 +191,9 @@ void DOMStorageContextWrapper::GetSessionStorageUsage(
DCHECK(context_.get());
context_->task_runner()->PostShutdownBlockingTask(
FROM_HERE, DOMStorageTaskRunner::PRIMARY_SEQUENCE,
- base::Bind(&GetSessionStorageUsageHelper,
- base::RetainedRef(base::ThreadTaskRunnerHandle::Get()),
- base::RetainedRef(context_), callback));
+ base::BindOnce(&GetSessionStorageUsageHelper,
+ base::RetainedRef(base::ThreadTaskRunnerHandle::Get()),
+ base::RetainedRef(context_), callback));
}
void DOMStorageContextWrapper::DeleteLocalStorageForPhysicalOrigin(
@@ -201,8 +201,9 @@ void DOMStorageContextWrapper::DeleteLocalStorageForPhysicalOrigin(
DCHECK(context_.get());
context_->task_runner()->PostShutdownBlockingTask(
FROM_HERE, DOMStorageTaskRunner::PRIMARY_SEQUENCE,
- base::Bind(&DOMStorageContextImpl::DeleteLocalStorageForPhysicalOrigin,
- context_, origin));
+ base::BindOnce(
+ &DOMStorageContextImpl::DeleteLocalStorageForPhysicalOrigin, context_,
+ origin));
if (mojo_state_) {
// base::Unretained is safe here, because the mojo_state_ won't be deleted
// until a ShutdownAndDelete task has been ran on the mojo_task_runner_, and
@@ -218,9 +219,9 @@ void DOMStorageContextWrapper::DeleteLocalStorageForPhysicalOrigin(
void DOMStorageContextWrapper::DeleteLocalStorage(const GURL& origin) {
DCHECK(context_.get());
context_->task_runner()->PostShutdownBlockingTask(
- FROM_HERE,
- DOMStorageTaskRunner::PRIMARY_SEQUENCE,
- base::Bind(&DOMStorageContextImpl::DeleteLocalStorage, context_, origin));
+ FROM_HERE, DOMStorageTaskRunner::PRIMARY_SEQUENCE,
+ base::BindOnce(&DOMStorageContextImpl::DeleteLocalStorage, context_,
+ origin));
if (mojo_state_) {
// base::Unretained is safe here, because the mojo_state_ won't be deleted
// until a ShutdownAndDelete task has been ran on the mojo_task_runner_, and
@@ -237,10 +238,9 @@ void DOMStorageContextWrapper::DeleteSessionStorage(
const SessionStorageUsageInfo& usage_info) {
DCHECK(context_.get());
context_->task_runner()->PostShutdownBlockingTask(
- FROM_HERE,
- DOMStorageTaskRunner::PRIMARY_SEQUENCE,
- base::Bind(&DOMStorageContextImpl::DeleteSessionStorage,
- context_, usage_info));
+ FROM_HERE, DOMStorageTaskRunner::PRIMARY_SEQUENCE,
+ base::BindOnce(&DOMStorageContextImpl::DeleteSessionStorage, context_,
+ usage_info));
}
void DOMStorageContextWrapper::SetSaveSessionStorageOnDisk() {
@@ -258,18 +258,18 @@ DOMStorageContextWrapper::RecreateSessionStorage(
void DOMStorageContextWrapper::StartScavengingUnusedSessionStorage() {
DCHECK(context_.get());
context_->task_runner()->PostShutdownBlockingTask(
- FROM_HERE,
- DOMStorageTaskRunner::PRIMARY_SEQUENCE,
- base::Bind(&DOMStorageContextImpl::StartScavengingUnusedSessionStorage,
- context_));
+ FROM_HERE, DOMStorageTaskRunner::PRIMARY_SEQUENCE,
+ base::BindOnce(
+ &DOMStorageContextImpl::StartScavengingUnusedSessionStorage,
+ context_));
}
void DOMStorageContextWrapper::SetForceKeepSessionState() {
DCHECK(context_.get());
context_->task_runner()->PostShutdownBlockingTask(
- FROM_HERE,
- DOMStorageTaskRunner::PRIMARY_SEQUENCE,
- base::Bind(&DOMStorageContextImpl::SetForceKeepSessionState, context_));
+ FROM_HERE, DOMStorageTaskRunner::PRIMARY_SEQUENCE,
+ base::BindOnce(&DOMStorageContextImpl::SetForceKeepSessionState,
+ context_));
if (mojo_state_) {
// base::Unretained is safe here, because the mojo_state_ won't be deleted
// until a ShutdownAndDelete task has been ran on the mojo_task_runner_, and
@@ -292,9 +292,8 @@ void DOMStorageContextWrapper::Shutdown() {
}
memory_pressure_listener_.reset();
context_->task_runner()->PostShutdownBlockingTask(
- FROM_HERE,
- DOMStorageTaskRunner::PRIMARY_SEQUENCE,
- base::Bind(&DOMStorageContextImpl::Shutdown, context_));
+ FROM_HERE, DOMStorageTaskRunner::PRIMARY_SEQUENCE,
+ base::BindOnce(&DOMStorageContextImpl::Shutdown, context_));
if (base::FeatureList::IsEnabled(features::kMemoryCoordinator)) {
base::MemoryCoordinatorClientRegistry::GetInstance()->Unregister(this);
}
@@ -305,7 +304,7 @@ void DOMStorageContextWrapper::Flush() {
context_->task_runner()->PostShutdownBlockingTask(
FROM_HERE, DOMStorageTaskRunner::PRIMARY_SEQUENCE,
- base::Bind(&DOMStorageContextImpl::Flush, context_));
+ base::BindOnce(&DOMStorageContextImpl::Flush, context_));
if (mojo_state_) {
// base::Unretained is safe here, because the mojo_state_ won't be deleted
// until a ShutdownAndDelete task has been ran on the mojo_task_runner_, and
@@ -364,8 +363,8 @@ void DOMStorageContextWrapper::OnPurgeMemory() {
void DOMStorageContextWrapper::PurgeMemory(DOMStorageContextImpl::PurgeOption
purge_option) {
context_->task_runner()->PostTask(
- FROM_HERE,
- base::Bind(&DOMStorageContextImpl::PurgeMemory, context_, purge_option));
+ FROM_HERE, base::BindOnce(&DOMStorageContextImpl::PurgeMemory, context_,
+ purge_option));
if (mojo_state_ && purge_option == DOMStorageContextImpl::PURGE_AGGRESSIVE) {
// base::Unretained is safe here, because the mojo_state_ won't be deleted
// until a ShutdownAndDelete task has been ran on the mojo_task_runner_, and
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 bab7dbe0ce0..ef74dc3066b 100644
--- a/chromium/content/browser/dom_storage/dom_storage_context_wrapper.h
+++ b/chromium/content/browser/dom_storage/dom_storage_context_wrapper.h
@@ -37,10 +37,10 @@ class LocalStorageContextMojo;
// This is owned by Storage Partition and encapsulates all its dom storage
// state.
-class CONTENT_EXPORT DOMStorageContextWrapper :
- NON_EXPORTED_BASE(public DOMStorageContext),
- public base::RefCountedThreadSafe<DOMStorageContextWrapper>,
- public base::MemoryCoordinatorClient {
+class CONTENT_EXPORT DOMStorageContextWrapper
+ : public DOMStorageContext,
+ public base::RefCountedThreadSafe<DOMStorageContextWrapper>,
+ public base::MemoryCoordinatorClient {
public:
// If |data_path| is empty, nothing will be saved to disk.
DOMStorageContextWrapper(
diff --git a/chromium/content/browser/dom_storage/dom_storage_host.cc b/chromium/content/browser/dom_storage/dom_storage_host.cc
index 162cdc736e7..f085668e3bc 100644
--- a/chromium/content/browser/dom_storage/dom_storage_host.cc
+++ b/chromium/content/browser/dom_storage/dom_storage_host.cc
@@ -16,9 +16,9 @@ DOMStorageHost::DOMStorageHost(DOMStorageContextImpl* context)
}
DOMStorageHost::~DOMStorageHost() {
- for (const auto& it : connections_)
- it.second.namespace_->CloseStorageArea(it.second.area_.get());
- connections_.clear(); // Clear prior to releasing the context_
+ // Clear connections prior to releasing the context_.
+ while (!connections_.empty())
+ CloseStorageArea(connections_.begin()->first);
}
base::Optional<bad_message::BadMessageReason>
@@ -32,8 +32,16 @@ DOMStorageHost::OpenStorageArea(
references.namespace_ = context_->GetStorageNamespace(namespace_id);
if (!references.namespace_.get())
return context_->DiagnoseSessionNamespaceId(namespace_id);
- references.area_ = references.namespace_->OpenStorageArea(origin);
- DCHECK(references.area_.get());
+
+ // namespace->OpenStorageArea() is called only once per process
+ // (areas_open_count[area] is 0).
+ references.area_ = references.namespace_->GetOpenStorageArea(origin);
+ if (!references.area_ || !areas_open_count_[references.area_.get()]) {
+ references.area_ = references.namespace_->OpenStorageArea(origin);
+ DCHECK(references.area_.get());
+ DCHECK_EQ(0, areas_open_count_[references.area_.get()]);
+ }
+ ++areas_open_count_[references.area_.get()];
connections_[connection_id] = references;
return base::nullopt;
}
@@ -42,7 +50,15 @@ void DOMStorageHost::CloseStorageArea(int connection_id) {
const auto found = connections_.find(connection_id);
if (found == connections_.end())
return;
- found->second.namespace_->CloseStorageArea(found->second.area_.get());
+ DOMStorageArea* area = found->second.area_.get();
+ DCHECK(areas_open_count_[area]);
+
+ // namespace->CloseStorageArea() is called only once per process
+ // (areas_open_count[area] becomes 0).
+ if (--areas_open_count_[area] == 0) {
+ found->second.namespace_->CloseStorageArea(area);
+ areas_open_count_.erase(area);
+ }
connections_.erase(found);
}
@@ -84,29 +100,34 @@ base::NullableString16 DOMStorageHost::GetAreaItem(int connection_id,
return area->GetItem(key);
}
-bool DOMStorageHost::SetAreaItem(
- int connection_id, const base::string16& key,
- const base::string16& value, const GURL& page_url,
- base::NullableString16* old_value) {
+bool DOMStorageHost::SetAreaItem(int connection_id,
+ const base::string16& key,
+ const base::string16& value,
+ const base::NullableString16& client_old_value,
+ const GURL& page_url) {
DOMStorageArea* area = GetOpenArea(connection_id);
if (!area)
return false;
- if (!area->SetItem(key, value, old_value))
+ base::NullableString16 old_value;
+ if (!area->SetItem(key, value, &old_value))
return false;
- if (old_value->is_null() || old_value->string() != value)
- context_->NotifyItemSet(area, key, value, *old_value, page_url);
+ if (old_value.is_null() || old_value.string() != value)
+ context_->NotifyItemSet(area, key, value, old_value, page_url);
return true;
}
bool DOMStorageHost::RemoveAreaItem(
- int connection_id, const base::string16& key, const GURL& page_url,
- base::string16* old_value) {
+ int connection_id,
+ const base::string16& key,
+ const base::NullableString16& client_old_value,
+ const GURL& page_url) {
DOMStorageArea* area = GetOpenArea(connection_id);
if (!area)
return false;
- if (!area->RemoveItem(key, old_value))
+ base::string16 old_value;
+ if (!area->RemoveItem(key, &old_value))
return false;
- context_->NotifyItemRemoved(area, key, *old_value, page_url);
+ context_->NotifyItemRemoved(area, key, old_value, page_url);
return true;
}
diff --git a/chromium/content/browser/dom_storage/dom_storage_host.h b/chromium/content/browser/dom_storage/dom_storage_host.h
index 6b931d19314..58048064440 100644
--- a/chromium/content/browser/dom_storage/dom_storage_host.h
+++ b/chromium/content/browser/dom_storage/dom_storage_host.h
@@ -45,13 +45,15 @@ class CONTENT_EXPORT DOMStorageHost {
base::NullableString16 GetAreaKey(int connection_id, unsigned index);
base::NullableString16 GetAreaItem(int connection_id,
const base::string16& key);
- bool SetAreaItem(int connection_id, const base::string16& key,
- const base::string16& value, const GURL& page_url,
- base::NullableString16* old_value);
+ bool SetAreaItem(int connection_id,
+ const base::string16& key,
+ const base::string16& value,
+ const base::NullableString16& client_old_value,
+ const GURL& page_url);
bool RemoveAreaItem(int connection_id,
const base::string16& key,
- const GURL& page_url,
- base::string16* old_value);
+ const base::NullableString16& client_old_value,
+ const GURL& page_url);
bool ClearArea(int connection_id, const GURL& page_url);
bool HasAreaOpen(int namespace_id, const GURL& origin) const;
bool HasConnection(int connection_id) const {
@@ -75,6 +77,7 @@ class CONTENT_EXPORT DOMStorageHost {
scoped_refptr<DOMStorageContextImpl> context_;
AreaMap connections_;
+ std::map<DOMStorageArea*, int> areas_open_count_;
DISALLOW_COPY_AND_ASSIGN(DOMStorageHost);
};
diff --git a/chromium/content/browser/dom_storage/dom_storage_message_filter.cc b/chromium/content/browser/dom_storage/dom_storage_message_filter.cc
index ec5622fa082..70315b7efaa 100644
--- a/chromium/content/browser/dom_storage/dom_storage_message_filter.cc
+++ b/chromium/content/browser/dom_storage/dom_storage_message_filter.cc
@@ -47,16 +47,14 @@ void DOMStorageMessageFilter::UninitializeInSequence() {
void DOMStorageMessageFilter::OnFilterAdded(IPC::Channel* channel) {
context_->task_runner()->PostShutdownBlockingTask(
- FROM_HERE,
- DOMStorageTaskRunner::PRIMARY_SEQUENCE,
- base::Bind(&DOMStorageMessageFilter::InitializeInSequence, this));
+ FROM_HERE, DOMStorageTaskRunner::PRIMARY_SEQUENCE,
+ base::BindOnce(&DOMStorageMessageFilter::InitializeInSequence, this));
}
void DOMStorageMessageFilter::OnFilterRemoved() {
context_->task_runner()->PostShutdownBlockingTask(
- FROM_HERE,
- DOMStorageTaskRunner::PRIMARY_SEQUENCE,
- base::Bind(&DOMStorageMessageFilter::UninitializeInSequence, this));
+ FROM_HERE, DOMStorageTaskRunner::PRIMARY_SEQUENCE,
+ base::BindOnce(&DOMStorageMessageFilter::UninitializeInSequence, this));
}
base::TaskRunner* DOMStorageMessageFilter::OverrideTaskRunnerForMessage(
@@ -112,27 +110,30 @@ void DOMStorageMessageFilter::OnLoadStorageArea(int connection_id,
}
void DOMStorageMessageFilter::OnSetItem(
- int connection_id, const base::string16& key,
- const base::string16& value, const GURL& page_url) {
+ int connection_id,
+ const base::string16& key,
+ const base::string16& value,
+ const base::NullableString16& client_old_value,
+ const GURL& page_url) {
DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
DCHECK_EQ(0, connection_dispatching_message_for_);
base::AutoReset<int> auto_reset(&connection_dispatching_message_for_,
connection_id);
- base::NullableString16 not_used;
- bool success = host_->SetAreaItem(connection_id, key, value,
- page_url, &not_used);
+ bool success =
+ host_->SetAreaItem(connection_id, key, value, client_old_value, page_url);
Send(new DOMStorageMsg_AsyncOperationComplete(success));
}
void DOMStorageMessageFilter::OnRemoveItem(
- int connection_id, const base::string16& key,
+ int connection_id,
+ const base::string16& key,
+ const base::NullableString16& client_old_value,
const GURL& page_url) {
DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
DCHECK_EQ(0, connection_dispatching_message_for_);
base::AutoReset<int> auto_reset(&connection_dispatching_message_for_,
connection_id);
- base::string16 not_used;
- host_->RemoveAreaItem(connection_id, key, page_url, &not_used);
+ host_->RemoveAreaItem(connection_id, key, client_old_value, page_url);
Send(new DOMStorageMsg_AsyncOperationComplete(true));
}
diff --git a/chromium/content/browser/dom_storage/dom_storage_message_filter.h b/chromium/content/browser/dom_storage/dom_storage_message_filter.h
index c3394e7ed8a..ff199f825c2 100644
--- a/chromium/content/browser/dom_storage/dom_storage_message_filter.h
+++ b/chromium/content/browser/dom_storage/dom_storage_message_filter.h
@@ -55,9 +55,14 @@ class DOMStorageMessageFilter
const GURL& origin);
void OnCloseStorageArea(int connection_id);
void OnLoadStorageArea(int connection_id, DOMStorageValuesMap* map);
- void OnSetItem(int connection_id, const base::string16& key,
- const base::string16& value, const GURL& page_url);
- void OnRemoveItem(int connection_id, const base::string16& key,
+ void OnSetItem(int connection_id,
+ const base::string16& key,
+ const base::string16& value,
+ const base::NullableString16& client_old_value,
+ const GURL& page_url);
+ void OnRemoveItem(int connection_id,
+ const base::string16& key,
+ const base::NullableString16& client_old_value,
const GURL& page_url);
void OnClear(int connection_id, const GURL& page_url);
void OnFlushMessages();
diff --git a/chromium/content/browser/dom_storage/dom_storage_namespace.cc b/chromium/content/browser/dom_storage/dom_storage_namespace.cc
index 847b1930d70..a448665f97f 100644
--- a/chromium/content/browser/dom_storage/dom_storage_namespace.cc
+++ b/chromium/content/browser/dom_storage/dom_storage_namespace.cc
@@ -88,11 +88,11 @@ DOMStorageNamespace* DOMStorageNamespace::Clone(
// And clone the on-disk structures, too.
if (session_storage_database_.get()) {
task_runner_->PostShutdownBlockingTask(
- FROM_HERE,
- DOMStorageTaskRunner::COMMIT_SEQUENCE,
- base::Bind(base::IgnoreResult(&SessionStorageDatabase::CloneNamespace),
- session_storage_database_.get(), persistent_namespace_id_,
- clone_persistent_namespace_id));
+ FROM_HERE, DOMStorageTaskRunner::COMMIT_SEQUENCE,
+ base::BindOnce(
+ base::IgnoreResult(&SessionStorageDatabase::CloneNamespace),
+ session_storage_database_.get(), persistent_namespace_id_,
+ clone_persistent_namespace_id));
}
return clone;
}
@@ -196,6 +196,13 @@ void DOMStorageNamespace::GetOriginsWithAreas(
origins->push_back(entry.first);
}
+int DOMStorageNamespace::GetAreaOpenCount(const GURL& origin) const {
+ const auto& found = areas_.find(origin);
+ if (found == areas_.end())
+ return 0;
+ return found->second.open_count_;
+}
+
DOMStorageNamespace::AreaHolder*
DOMStorageNamespace::GetAreaHolder(const GURL& origin) {
AreaMap::iterator found = areas_.find(origin);
diff --git a/chromium/content/browser/dom_storage/dom_storage_namespace.h b/chromium/content/browser/dom_storage/dom_storage_namespace.h
index 8f75f2ab825..2fdab5a13c2 100644
--- a/chromium/content/browser/dom_storage/dom_storage_namespace.h
+++ b/chromium/content/browser/dom_storage/dom_storage_namespace.h
@@ -85,6 +85,8 @@ class CONTENT_EXPORT DOMStorageNamespace
void GetOriginsWithAreas(std::vector<GURL>* origins) const;
+ int GetAreaOpenCount(const GURL& origin) const;
+
private:
friend class base::RefCountedThreadSafe<DOMStorageNamespace>;
diff --git a/chromium/content/browser/dom_storage/dom_storage_session.cc b/chromium/content/browser/dom_storage/dom_storage_session.cc
index 338b6cc25c6..a217f156e79 100644
--- a/chromium/content/browser/dom_storage/dom_storage_session.cc
+++ b/chromium/content/browser/dom_storage/dom_storage_session.cc
@@ -20,8 +20,8 @@ DOMStorageSession::DOMStorageSession(DOMStorageContextImpl* context)
should_persist_(false) {
context->task_runner()->PostTask(
FROM_HERE,
- base::Bind(&DOMStorageContextImpl::CreateSessionNamespace,
- context_, namespace_id_, persistent_namespace_id_));
+ base::BindOnce(&DOMStorageContextImpl::CreateSessionNamespace, context_,
+ namespace_id_, persistent_namespace_id_));
}
DOMStorageSession::DOMStorageSession(DOMStorageContextImpl* context,
@@ -32,8 +32,8 @@ DOMStorageSession::DOMStorageSession(DOMStorageContextImpl* context,
should_persist_(false) {
context->task_runner()->PostTask(
FROM_HERE,
- base::Bind(&DOMStorageContextImpl::CreateSessionNamespace,
- context_, namespace_id_, persistent_namespace_id_));
+ base::BindOnce(&DOMStorageContextImpl::CreateSessionNamespace, context_,
+ namespace_id_, persistent_namespace_id_));
}
void DOMStorageSession::SetShouldPersist(bool should_persist) {
@@ -59,8 +59,8 @@ DOMStorageSession* DOMStorageSession::CloneFrom(DOMStorageContextImpl* context,
std::string persistent_clone_id = context->AllocatePersistentSessionId();
context->task_runner()->PostTask(
FROM_HERE,
- base::Bind(&DOMStorageContextImpl::CloneSessionNamespace,
- context, namepace_id_to_clone, clone_id, persistent_clone_id));
+ base::BindOnce(&DOMStorageContextImpl::CloneSessionNamespace, context,
+ namepace_id_to_clone, clone_id, persistent_clone_id));
return new DOMStorageSession(context, clone_id, persistent_clone_id);
}
@@ -76,9 +76,8 @@ DOMStorageSession::DOMStorageSession(DOMStorageContextImpl* context,
DOMStorageSession::~DOMStorageSession() {
context_->task_runner()->PostTask(
- FROM_HERE,
- base::Bind(&DOMStorageContextImpl::DeleteSessionNamespace,
- context_, namespace_id_, should_persist_));
+ FROM_HERE, base::BindOnce(&DOMStorageContextImpl::DeleteSessionNamespace,
+ context_, namespace_id_, should_persist_));
}
} // namespace content
diff --git a/chromium/content/browser/dom_storage/local_storage_context_mojo.cc b/chromium/content/browser/dom_storage/local_storage_context_mojo.cc
index ad15ed2c728..a1f8dad0601 100644
--- a/chromium/content/browser/dom_storage/local_storage_context_mojo.cc
+++ b/chromium/content/browser/dom_storage/local_storage_context_mojo.cc
@@ -57,16 +57,6 @@ const int64_t kCurrentSchemaVersion = 1;
// database.
const int kCommitErrorThreshold = 8;
-// Use a smaller block cache on android. Because of the extra caching done in
-// LevelDBWrapperImpl the block cache isn't particularly useful, but it still
-// provides some benefit with speeding up compaction. And since this is a once
-// per profile overhead, the overhead should be fairly minimal on desktop.
-#if defined(OS_ANDROID)
-const size_t kMaxBlockCacheSize = 100 * 1024;
-#else
-const size_t kMaxBlockCacheSize = 2 * 1024 * 1024;
-#endif
-
// Limits on the cache size and number of areas in memory, over which the areas
// are purged.
#if defined(OS_ANDROID)
@@ -77,6 +67,9 @@ const unsigned kMaxStorageAreaCount = 50;
const size_t kMaxCacheSize = 20 * 1024 * 1024;
#endif
+static const uint8_t kUTF16Format = 0;
+static const uint8_t kLatin1Format = 1;
+
std::vector<uint8_t> CreateMetaDataKey(const url::Origin& origin) {
auto serialized_origin = leveldb::StdStringToUint8Vector(origin.Serialize());
std::vector<uint8_t> key;
@@ -103,7 +96,7 @@ void MigrateStorageHelper(
LocalStorageContextMojo::MigrateString(it.second.string());
}
reply_task_runner->PostTask(FROM_HERE,
- base::Bind(callback, base::Passed(&values)));
+ base::BindOnce(callback, base::Passed(&values)));
}
// Helper to convert from OnceCallback to Callback.
@@ -169,7 +162,7 @@ void RecordCachePurgedHistogram(CachePurgeReason reason,
} // namespace
-class LocalStorageContextMojo::LevelDBWrapperHolder
+class LocalStorageContextMojo::LevelDBWrapperHolder final
: public LevelDBWrapperImpl::Delegate {
public:
LevelDBWrapperHolder(LocalStorageContextMojo* context,
@@ -249,8 +242,8 @@ class LocalStorageContextMojo::LevelDBWrapperHolder
deleted_old_data_ = true;
context_->task_runner_->PostShutdownBlockingTask(
FROM_HERE, DOMStorageTaskRunner::PRIMARY_SEQUENCE,
- base::Bind(base::IgnoreResult(&sql::Connection::Delete),
- sql_db_path()));
+ base::BindOnce(base::IgnoreResult(&sql::Connection::Delete),
+ sql_db_path()));
}
context_->OnCommitResult(error);
@@ -260,7 +253,7 @@ class LocalStorageContextMojo::LevelDBWrapperHolder
if (context_->task_runner_ && !context_->old_localstorage_path_.empty()) {
context_->task_runner_->PostShutdownBlockingTask(
FROM_HERE, DOMStorageTaskRunner::PRIMARY_SEQUENCE,
- base::Bind(
+ base::BindOnce(
&MigrateStorageHelper, sql_db_path(),
base::ThreadTaskRunnerHandle::Get(),
base::Bind(&CallMigrationCalback, base::Passed(&callback))));
@@ -269,6 +262,58 @@ class LocalStorageContextMojo::LevelDBWrapperHolder
std::move(callback).Run(nullptr);
}
+ std::vector<LevelDBWrapperImpl::Change> FixUpData(
+ const LevelDBWrapperImpl::ValueMap& data) override {
+ std::vector<LevelDBWrapperImpl::Change> changes;
+ // Chrome M61/M62 had a bug where keys that should have been encoded as
+ // Latin1 were instead encoded as UTF16. Fix this by finding any 8-bit only
+ // keys, and re-encode those. If two encodings of the key exist, the Latin1
+ // encoded value should take precedence.
+ size_t fix_count = 0;
+ for (const auto& it : data) {
+ // Skip over any Latin1 encoded keys, or unknown encodings/corrupted data.
+ if (it.first.empty() || it.first[0] != kUTF16Format)
+ continue;
+ // Check if key is actually 8-bit safe.
+ bool is_8bit = true;
+ for (size_t i = 1; i < it.first.size(); i += sizeof(base::char16)) {
+ // Don't just cast to char16* as that could be undefined behavior.
+ // Instead use memcpy for the conversion, which compilers will generally
+ // optimize away anyway.
+ base::char16 char_val;
+ memcpy(&char_val, it.first.data() + i, sizeof(base::char16));
+ if (char_val & 0xff00) {
+ is_8bit = false;
+ break;
+ }
+ }
+ if (!is_8bit)
+ continue;
+ // Found a key that should have been encoded differently. Decode and
+ // re-encode.
+ std::vector<uint8_t> key(1 + (it.first.size() - 1) / 2);
+ key[0] = kLatin1Format;
+ for (size_t in = 1, out = 1; in < it.first.size();
+ in += sizeof(base::char16), out++) {
+ base::char16 char_val;
+ memcpy(&char_val, it.first.data() + in, sizeof(base::char16));
+ key[out] = char_val;
+ }
+ // Delete incorrect key.
+ changes.push_back(std::make_pair(it.first, base::nullopt));
+ fix_count++;
+ // Check if correct key already exists in data.
+ auto new_it = data.find(key);
+ if (new_it != data.end())
+ continue;
+ // Update value for correct key.
+ changes.push_back(std::make_pair(key, it.second));
+ }
+ UMA_HISTOGRAM_BOOLEAN("LocalStorageContext.MigrationFixUpNeeded",
+ fix_count != 0);
+ return changes;
+ }
+
void OnMapLoaded(leveldb::mojom::DatabaseError error) override {
if (error != leveldb::mojom::DatabaseError::OK)
UMA_HISTOGRAM_ENUMERATION("LocalStorageContext.MapLoadError",
@@ -350,12 +395,12 @@ void LocalStorageContextMojo::DeleteStorage(const url::Origin& origin) {
// Renderer process expects |source| to always be two newline separated
// strings.
found->second->level_db_wrapper()->DeleteAll("\n",
- base::Bind(&NoOpSuccess));
+ base::BindOnce(&NoOpSuccess));
found->second->level_db_wrapper()->ScheduleImmediateCommit();
} else if (database_) {
std::vector<leveldb::mojom::BatchedOperationPtr> operations;
AddDeleteOriginOperations(&operations, origin);
- database_->Write(std::move(operations), base::Bind(&NoOpDatabaseError));
+ database_->Write(std::move(operations), base::BindOnce(&NoOpDatabaseError));
}
}
@@ -533,8 +578,21 @@ bool LocalStorageContextMojo::OnMemoryDump(
// static
std::vector<uint8_t> LocalStorageContextMojo::MigrateString(
const base::string16& input) {
- static const uint8_t kUTF16Format = 0;
-
+ // TODO(mek): Deduplicate this somehow with the code in
+ // LocalStorageCachedArea::String16ToUint8Vector.
+ bool is_8bit = true;
+ for (const auto& c : input) {
+ if (c & 0xff00) {
+ is_8bit = false;
+ break;
+ }
+ }
+ if (is_8bit) {
+ std::vector<uint8_t> result(input.size() + 1);
+ result[0] = kLatin1Format;
+ std::copy(input.begin(), input.end(), result.begin() + 1);
+ return result;
+ }
const uint8_t* data = reinterpret_cast<const uint8_t*>(input.data());
std::vector<uint8_t> result;
result.reserve(input.size() * sizeof(base::char16) + 1);
@@ -582,15 +640,15 @@ void LocalStorageContextMojo::InitiateConnection(bool in_memory_only) {
connector_->BindInterface(file::mojom::kServiceName, &file_system_);
file_system_->GetSubDirectory(
subdirectory_.AsUTF8Unsafe(), MakeRequest(&directory_),
- base::Bind(&LocalStorageContextMojo::OnDirectoryOpened,
- weak_ptr_factory_.GetWeakPtr()));
+ base::BindOnce(&LocalStorageContextMojo::OnDirectoryOpened,
+ weak_ptr_factory_.GetWeakPtr()));
} else {
// We were not given a subdirectory. Use a memory backed database.
connector_->BindInterface(file::mojom::kServiceName, &leveldb_service_);
leveldb_service_->OpenInMemory(
memory_dump_id_, MakeRequest(&database_),
- base::Bind(&LocalStorageContextMojo::OnDatabaseOpened,
- weak_ptr_factory_.GetWeakPtr(), true));
+ base::BindOnce(&LocalStorageContextMojo::OnDatabaseOpened,
+ weak_ptr_factory_.GetWeakPtr(), true));
}
}
@@ -621,15 +679,12 @@ void LocalStorageContextMojo::OnDirectoryOpened(
// Default write_buffer_size is 4 MB but that might leave a 3.999
// memory allocation in RAM from a log file recovery.
options->write_buffer_size = 64 * 1024;
- // Default block_cache_size is 8 MB, but we don't really want to cache that
- // much data, so instead set it to a lower value. LevelDBWrapperImpl takes
- // care of almost all the actual block caching we care about.
- options->block_cache_size = kMaxBlockCacheSize;
+ options->shared_block_read_cache = leveldb::mojom::SharedReadCache::Web;
leveldb_service_->OpenWithOptions(
std::move(options), std::move(directory_clone), "leveldb",
memory_dump_id_, MakeRequest(&database_),
- base::Bind(&LocalStorageContextMojo::OnDatabaseOpened,
- weak_ptr_factory_.GetWeakPtr(), false));
+ base::BindOnce(&LocalStorageContextMojo::OnDatabaseOpened,
+ weak_ptr_factory_.GetWeakPtr(), false));
}
void LocalStorageContextMojo::OnDatabaseOpened(
@@ -657,9 +712,10 @@ void LocalStorageContextMojo::OnDatabaseOpened(
// Verify DB schema version.
if (database_) {
- database_->Get(leveldb::StdStringToUint8Vector(kVersionKey),
- base::Bind(&LocalStorageContextMojo::OnGotDatabaseVersion,
- weak_ptr_factory_.GetWeakPtr()));
+ database_->Get(
+ leveldb::StdStringToUint8Vector(kVersionKey),
+ base::BindOnce(&LocalStorageContextMojo::OnGotDatabaseVersion,
+ weak_ptr_factory_.GetWeakPtr()));
return;
}
@@ -761,8 +817,8 @@ void LocalStorageContextMojo::DeleteAndRecreateDatabase(
if (directory_.is_bound()) {
leveldb_service_->Destroy(
std::move(directory_), "leveldb",
- base::Bind(&LocalStorageContextMojo::OnDBDestroyed,
- weak_ptr_factory_.GetWeakPtr(), recreate_in_memory));
+ base::BindOnce(&LocalStorageContextMojo::OnDBDestroyed,
+ weak_ptr_factory_.GetWeakPtr(), recreate_in_memory));
} else {
// No directory, so nothing to destroy. Retrying to recreate will probably
// fail, but try anyway.
@@ -831,8 +887,8 @@ void LocalStorageContextMojo::RetrieveStorageUsage(
database_->GetPrefixed(
std::vector<uint8_t>(kMetaPrefix, kMetaPrefix + arraysize(kMetaPrefix)),
- base::Bind(&LocalStorageContextMojo::OnGotMetaData,
- weak_ptr_factory_.GetWeakPtr(), base::Passed(&callback)));
+ base::BindOnce(&LocalStorageContextMojo::OnGotMetaData,
+ weak_ptr_factory_.GetWeakPtr(), base::Passed(&callback)));
}
void LocalStorageContextMojo::OnGotMetaData(
@@ -900,9 +956,10 @@ void LocalStorageContextMojo::OnGotStorageUsageForShutdown(
}
if (!operations.empty()) {
- database_->Write(std::move(operations),
- base::Bind(&LocalStorageContextMojo::OnShutdownComplete,
- base::Unretained(this)));
+ database_->Write(
+ std::move(operations),
+ base::BindOnce(&LocalStorageContextMojo::OnShutdownComplete,
+ base::Unretained(this)));
} else {
OnShutdownComplete(leveldb::mojom::DatabaseError::OK);
}
diff --git a/chromium/content/browser/dom_storage/local_storage_context_mojo_unittest.cc b/chromium/content/browser/dom_storage/local_storage_context_mojo_unittest.cc
index 9bd47a33355..1e0b3c675b5 100644
--- a/chromium/content/browser/dom_storage/local_storage_context_mojo_unittest.cc
+++ b/chromium/content/browser/dom_storage/local_storage_context_mojo_unittest.cc
@@ -9,6 +9,7 @@
#include "base/files/scoped_temp_dir.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
+#include "build/build_config.h"
#include "components/filesystem/public/interfaces/file_system.mojom.h"
#include "components/leveldb/public/cpp/util.h"
#include "content/browser/dom_storage/dom_storage_area.h"
@@ -113,6 +114,21 @@ class TestLevelDBObserver : public mojom::LevelDBObserver {
mojo::AssociatedBinding<mojom::LevelDBObserver> binding_;
};
+class GetAllCallback : public mojom::LevelDBWrapperGetAllCallback {
+ public:
+ static mojom::LevelDBWrapperGetAllCallbackAssociatedPtrInfo CreateAndBind() {
+ mojom::LevelDBWrapperGetAllCallbackAssociatedPtrInfo ptr_info;
+ auto request = mojo::MakeRequest(&ptr_info);
+ mojo::MakeStrongAssociatedBinding(base::WrapUnique(new GetAllCallback),
+ std::move(request));
+ return ptr_info;
+ }
+
+ private:
+ GetAllCallback() {}
+ void Complete(bool success) override {}
+};
+
} // namespace
class LocalStorageContextMojoTest : public testing::Test {
@@ -213,7 +229,7 @@ TEST_F(LocalStorageContextMojoTest, Basic) {
mojom::LevelDBWrapperPtr wrapper;
context()->OpenLocalStorage(url::Origin(GURL("http://foobar.com")),
MakeRequest(&wrapper));
- wrapper->Put(key, value, "source", base::Bind(&NoOpSuccess));
+ wrapper->Put(key, value, "source", base::BindOnce(&NoOpSuccess));
wrapper.reset();
base::RunLoop().RunUntilIdle();
@@ -232,11 +248,11 @@ TEST_F(LocalStorageContextMojoTest, OriginsAreIndependent) {
mojom::LevelDBWrapperPtr wrapper;
context()->OpenLocalStorage(origin1, MakeRequest(&wrapper));
- wrapper->Put(key1, value, "source", base::Bind(&NoOpSuccess));
+ wrapper->Put(key1, value, "source", base::BindOnce(&NoOpSuccess));
wrapper.reset();
context()->OpenLocalStorage(origin2, MakeRequest(&wrapper));
- wrapper->Put(key2, value, "source", base::Bind(&NoOpSuccess));
+ wrapper->Put(key2, value, "source", base::BindOnce(&NoOpSuccess));
wrapper.reset();
base::RunLoop().RunUntilIdle();
@@ -251,7 +267,7 @@ TEST_F(LocalStorageContextMojoTest, WrapperOutlivesMojoConnection) {
mojom::LevelDBWrapperPtr wrapper;
context()->OpenLocalStorage(url::Origin(GURL("http://foobar.com")),
MakeRequest(&wrapper));
- wrapper->Put(key, value, "source", base::Bind(&NoOpSuccess));
+ wrapper->Put(key, value, "source", base::BindOnce(&NoOpSuccess));
wrapper.reset();
base::RunLoop().RunUntilIdle();
@@ -267,8 +283,8 @@ TEST_F(LocalStorageContextMojoTest, WrapperOutlivesMojoConnection) {
std::vector<uint8_t> result;
context()->OpenLocalStorage(url::Origin(GURL("http://foobar.com")),
MakeRequest(&wrapper));
- wrapper->Get(key, base::Bind(&GetCallback, run_loop.QuitClosure(), &success,
- &result));
+ wrapper->Get(key, base::BindOnce(&GetCallback, run_loop.QuitClosure(),
+ &success, &result));
run_loop.Run();
EXPECT_TRUE(success);
EXPECT_EQ(value, result);
@@ -285,8 +301,8 @@ TEST_F(LocalStorageContextMojoTest, WrapperOutlivesMojoConnection) {
std::vector<uint8_t> result;
context()->OpenLocalStorage(url::Origin(GURL("http://foobar.com")),
MakeRequest(&wrapper));
- wrapper->Get(key, base::Bind(&GetCallback, run_loop.QuitClosure(), &success,
- &result));
+ wrapper->Get(key, base::BindOnce(&GetCallback, run_loop.QuitClosure(),
+ &success, &result));
run_loop.Run();
EXPECT_FALSE(success);
wrapper.reset();
@@ -301,7 +317,7 @@ TEST_F(LocalStorageContextMojoTest, OpeningWrappersPurgesInactiveWrappers) {
mojom::LevelDBWrapperPtr wrapper;
context()->OpenLocalStorage(url::Origin(GURL("http://foobar.com")),
MakeRequest(&wrapper));
- wrapper->Put(key, value, "source", base::Bind(&NoOpSuccess));
+ wrapper->Put(key, value, "source", base::BindOnce(&NoOpSuccess));
wrapper.reset();
base::RunLoop().RunUntilIdle();
@@ -324,8 +340,8 @@ TEST_F(LocalStorageContextMojoTest, OpeningWrappersPurgesInactiveWrappers) {
std::vector<uint8_t> result;
context()->OpenLocalStorage(url::Origin(GURL("http://foobar.com")),
MakeRequest(&wrapper));
- wrapper->Get(
- key, base::Bind(&GetCallback, run_loop.QuitClosure(), &success, &result));
+ wrapper->Get(key, base::BindOnce(&GetCallback, run_loop.QuitClosure(),
+ &success, &result));
run_loop.Run();
EXPECT_FALSE(success);
wrapper.reset();
@@ -344,7 +360,7 @@ TEST_F(LocalStorageContextMojoTest, ValidVersion) {
std::vector<uint8_t> result;
wrapper->Get(
StdStringToUint8Vector("key"),
- base::Bind(&GetCallback, run_loop.QuitClosure(), &success, &result));
+ base::BindOnce(&GetCallback, run_loop.QuitClosure(), &success, &result));
run_loop.Run();
EXPECT_TRUE(success);
EXPECT_EQ(StdStringToUint8Vector("value"), result);
@@ -363,7 +379,7 @@ TEST_F(LocalStorageContextMojoTest, InvalidVersion) {
std::vector<uint8_t> result;
wrapper->Get(
StdStringToUint8Vector("key"),
- base::Bind(&GetCallback, run_loop.QuitClosure(), &success, &result));
+ base::BindOnce(&GetCallback, run_loop.QuitClosure(), &success, &result));
run_loop.Run();
EXPECT_FALSE(success);
}
@@ -378,7 +394,7 @@ TEST_F(LocalStorageContextMojoTest, VersionOnlyWrittenOnCommit) {
std::vector<uint8_t> result;
wrapper->Get(
StdStringToUint8Vector("key"),
- base::Bind(&GetCallback, run_loop.QuitClosure(), &success, &result));
+ base::BindOnce(&GetCallback, run_loop.QuitClosure(), &success, &result));
run_loop.Run();
EXPECT_FALSE(success);
wrapper.reset();
@@ -403,12 +419,12 @@ TEST_F(LocalStorageContextMojoTest, GetStorageUsage_Data) {
mojom::LevelDBWrapperPtr wrapper;
context()->OpenLocalStorage(origin1, MakeRequest(&wrapper));
- wrapper->Put(key1, value, "source", base::Bind(&NoOpSuccess));
- wrapper->Put(key2, value, "source", base::Bind(&NoOpSuccess));
+ wrapper->Put(key1, value, "source", base::BindOnce(&NoOpSuccess));
+ wrapper->Put(key2, value, "source", base::BindOnce(&NoOpSuccess));
wrapper.reset();
context()->OpenLocalStorage(origin2, MakeRequest(&wrapper));
- wrapper->Put(key2, value, "source", base::Bind(&NoOpSuccess));
+ wrapper->Put(key2, value, "source", base::BindOnce(&NoOpSuccess));
wrapper.reset();
// GetStorageUsage only includes committed data, but still returns all origins
@@ -450,13 +466,13 @@ TEST_F(LocalStorageContextMojoTest, MetaDataClearedOnDelete) {
mojom::LevelDBWrapperPtr wrapper;
context()->OpenLocalStorage(origin1, MakeRequest(&wrapper));
- wrapper->Put(key, value, "source", base::Bind(&NoOpSuccess));
+ wrapper->Put(key, value, "source", base::BindOnce(&NoOpSuccess));
wrapper.reset();
context()->OpenLocalStorage(origin2, MakeRequest(&wrapper));
- wrapper->Put(key, value, "source", base::Bind(&NoOpSuccess));
+ wrapper->Put(key, value, "source", base::BindOnce(&NoOpSuccess));
wrapper.reset();
context()->OpenLocalStorage(origin1, MakeRequest(&wrapper));
- wrapper->Delete(key, "source", base::Bind(&NoOpSuccess));
+ wrapper->Delete(key, "source", base::BindOnce(&NoOpSuccess));
wrapper.reset();
// Make sure all data gets committed to disk.
@@ -483,14 +499,14 @@ TEST_F(LocalStorageContextMojoTest, MetaDataClearedOnDeleteAll) {
mojom::LevelDBWrapperPtr wrapper;
context()->OpenLocalStorage(origin1, MakeRequest(&wrapper));
- wrapper->Put(key, value, "source", base::Bind(&NoOpSuccess));
+ wrapper->Put(key, value, "source", base::BindOnce(&NoOpSuccess));
wrapper.reset();
context()->OpenLocalStorage(origin2, MakeRequest(&wrapper));
- wrapper->Put(key, value, "source", base::Bind(&NoOpSuccess));
+ wrapper->Put(key, value, "source", base::BindOnce(&NoOpSuccess));
wrapper.reset();
context()->OpenLocalStorage(origin1, MakeRequest(&wrapper));
- wrapper->DeleteAll("source", base::Bind(&NoOpSuccess));
+ wrapper->DeleteAll("source", base::BindOnce(&NoOpSuccess));
wrapper.reset();
// Make sure all data gets committed to disk.
@@ -526,11 +542,11 @@ TEST_F(LocalStorageContextMojoTest, DeleteStorageWithoutConnection) {
mojom::LevelDBWrapperPtr wrapper;
context()->OpenLocalStorage(origin1, MakeRequest(&wrapper));
- wrapper->Put(key, value, "source", base::Bind(&NoOpSuccess));
+ wrapper->Put(key, value, "source", base::BindOnce(&NoOpSuccess));
wrapper.reset();
context()->OpenLocalStorage(origin2, MakeRequest(&wrapper));
- wrapper->Put(key, value, "source", base::Bind(&NoOpSuccess));
+ wrapper->Put(key, value, "source", base::BindOnce(&NoOpSuccess));
wrapper.reset();
// Make sure all data gets committed to disk.
@@ -561,11 +577,11 @@ TEST_F(LocalStorageContextMojoTest, DeleteStorageNotifiesWrapper) {
mojom::LevelDBWrapperPtr wrapper;
context()->OpenLocalStorage(origin1, MakeRequest(&wrapper));
- wrapper->Put(key, value, "source", base::Bind(&NoOpSuccess));
+ wrapper->Put(key, value, "source", base::BindOnce(&NoOpSuccess));
wrapper.reset();
context()->OpenLocalStorage(origin2, MakeRequest(&wrapper));
- wrapper->Put(key, value, "source", base::Bind(&NoOpSuccess));
+ wrapper->Put(key, value, "source", base::BindOnce(&NoOpSuccess));
wrapper.reset();
// Make sure all data gets committed to disk.
@@ -605,11 +621,11 @@ TEST_F(LocalStorageContextMojoTest, DeleteStorageWithPendingWrites) {
mojom::LevelDBWrapperPtr wrapper;
context()->OpenLocalStorage(origin1, MakeRequest(&wrapper));
- wrapper->Put(key, value, "source", base::Bind(&NoOpSuccess));
+ wrapper->Put(key, value, "source", base::BindOnce(&NoOpSuccess));
wrapper.reset();
context()->OpenLocalStorage(origin2, MakeRequest(&wrapper));
- wrapper->Put(key, value, "source", base::Bind(&NoOpSuccess));
+ wrapper->Put(key, value, "source", base::BindOnce(&NoOpSuccess));
wrapper.reset();
// Make sure all data gets committed to disk.
@@ -620,7 +636,7 @@ TEST_F(LocalStorageContextMojoTest, DeleteStorageWithPendingWrites) {
context()->OpenLocalStorage(origin1, MakeRequest(&wrapper));
wrapper->AddObserver(observer.Bind());
wrapper->Put(StdStringToUint8Vector("key2"), value, "source",
- base::Bind(&NoOpSuccess));
+ base::BindOnce(&NoOpSuccess));
base::RunLoop().RunUntilIdle();
context()->DeleteStorage(origin1);
@@ -654,14 +670,14 @@ TEST_F(LocalStorageContextMojoTest, DeleteStorageForPhysicalOrigin) {
mojom::LevelDBWrapperPtr wrapper;
context()->OpenLocalStorage(origin1a, MakeRequest(&wrapper));
- wrapper->Put(key, value, "source", base::Bind(&NoOpSuccess));
+ wrapper->Put(key, value, "source", base::BindOnce(&NoOpSuccess));
wrapper.reset();
context()->OpenLocalStorage(origin1b, MakeRequest(&wrapper));
- wrapper->Put(key, value, "source", base::Bind(&NoOpSuccess));
+ wrapper->Put(key, value, "source", base::BindOnce(&NoOpSuccess));
wrapper.reset();
context()->OpenLocalStorage(origin2, MakeRequest(&wrapper));
- wrapper->Put(key, value, "source", base::Bind(&NoOpSuccess));
+ wrapper->Put(key, value, "source", base::BindOnce(&NoOpSuccess));
wrapper.reset();
// Make sure all data gets committed to disk.
@@ -691,37 +707,55 @@ TEST_F(LocalStorageContextMojoTest, Migration) {
url::Origin origin2(GURL("http://example.com"));
base::string16 key = base::ASCIIToUTF16("key");
base::string16 value = base::ASCIIToUTF16("value");
+ base::string16 key2 = base::ASCIIToUTF16("key2");
+ key2.push_back(0xd83d);
+ key2.push_back(0xde00);
DOMStorageNamespace* local = local_storage_namespace();
DOMStorageArea* area = local->OpenStorageArea(origin1.GetURL());
base::NullableString16 dummy;
area->SetItem(key, value, &dummy);
+ area->SetItem(key2, value, &dummy);
local->CloseStorageArea(area);
FlushAndPurgeDOMStorageMemory();
// Opening origin2 and accessing its data should not migrate anything.
mojom::LevelDBWrapperPtr wrapper;
context()->OpenLocalStorage(origin2, MakeRequest(&wrapper));
- wrapper->Get(std::vector<uint8_t>(), base::Bind(&NoOpGet));
+ wrapper->Get(std::vector<uint8_t>(), base::BindOnce(&NoOpGet));
wrapper.reset();
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(mock_data().empty());
// Opening origin1 and accessing its data should migrate its storage.
context()->OpenLocalStorage(origin1, MakeRequest(&wrapper));
- wrapper->Get(std::vector<uint8_t>(), base::Bind(&NoOpGet));
+ wrapper->Get(std::vector<uint8_t>(), base::BindOnce(&NoOpGet));
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(mock_data().empty());
- base::RunLoop run_loop;
- bool success = false;
- std::vector<uint8_t> result;
- wrapper->Get(
- LocalStorageContextMojo::MigrateString(key),
- base::Bind(&GetCallback, run_loop.QuitClosure(), &success, &result));
- run_loop.Run();
- EXPECT_TRUE(success);
- EXPECT_EQ(LocalStorageContextMojo::MigrateString(value), result);
+ {
+ base::RunLoop run_loop;
+ bool success = false;
+ std::vector<uint8_t> result;
+ wrapper->Get(LocalStorageContextMojo::MigrateString(key),
+ base::BindOnce(&GetCallback, run_loop.QuitClosure(), &success,
+ &result));
+ run_loop.Run();
+ EXPECT_TRUE(success);
+ EXPECT_EQ(LocalStorageContextMojo::MigrateString(value), result);
+ }
+
+ {
+ base::RunLoop run_loop;
+ bool success = false;
+ std::vector<uint8_t> result;
+ wrapper->Get(LocalStorageContextMojo::MigrateString(key2),
+ base::BindOnce(&GetCallback, run_loop.QuitClosure(), &success,
+ &result));
+ run_loop.Run();
+ EXPECT_TRUE(success);
+ EXPECT_EQ(LocalStorageContextMojo::MigrateString(value), result);
+ }
// Origin1 should no longer exist in old storage.
area = local->OpenStorageArea(origin1.GetURL());
@@ -729,6 +763,70 @@ TEST_F(LocalStorageContextMojoTest, Migration) {
local->CloseStorageArea(area);
}
+static std::string EncodeKeyAsUTF16(const std::string& origin,
+ const base::string16& key) {
+ std::string result = '_' + origin + '\x00' + '\x00';
+ std::copy(reinterpret_cast<const char*>(key.data()),
+ reinterpret_cast<const char*>(key.data()) +
+ key.size() * sizeof(base::char16),
+ std::back_inserter(result));
+ return result;
+}
+
+TEST_F(LocalStorageContextMojoTest, FixUp) {
+ set_mock_data("VERSION", "1");
+ // Add mock data for the "key" key, with both possible encodings for key.
+ // We expect the value of the correctly encoded key to take precedence over
+ // the incorrectly encoded key (and expect the incorrectly encoded key to be
+ // deleted.
+ set_mock_data(std::string("_http://foobar.com") + '\x00' + "\x01key",
+ "value1");
+ set_mock_data(
+ EncodeKeyAsUTF16("http://foobar.com", base::ASCIIToUTF16("key")),
+ "value2");
+ // Also add mock data for the "foo" key, this time only with the incorrec
+ // encoding. This should be updated to the correct encoding.
+ set_mock_data(
+ EncodeKeyAsUTF16("http://foobar.com", base::ASCIIToUTF16("foo")),
+ "value3");
+
+ mojom::LevelDBWrapperPtr wrapper;
+ context()->OpenLocalStorage(url::Origin(GURL("http://foobar.com")),
+ MakeRequest(&wrapper));
+
+ {
+ base::RunLoop run_loop;
+ bool success = false;
+ std::vector<uint8_t> result;
+ wrapper->Get(leveldb::StdStringToUint8Vector("\x01key"),
+ base::BindOnce(&GetCallback, run_loop.QuitClosure(), &success,
+ &result));
+ run_loop.Run();
+ EXPECT_TRUE(success);
+ EXPECT_EQ(leveldb::StdStringToUint8Vector("value1"), result);
+ }
+ {
+ base::RunLoop run_loop;
+ bool success = false;
+ std::vector<uint8_t> result;
+ wrapper->Get(leveldb::StdStringToUint8Vector("\x01"
+ "foo"),
+ base::BindOnce(&GetCallback, run_loop.QuitClosure(), &success,
+ &result));
+ run_loop.Run();
+ EXPECT_TRUE(success);
+ EXPECT_EQ(leveldb::StdStringToUint8Vector("value3"), result);
+ }
+
+ // Expect 4 rows in the database: VERSION, meta-data for the origin, and two
+ // rows of actual data.
+ EXPECT_EQ(4u, mock_data().size());
+ EXPECT_EQ(leveldb::StdStringToUint8Vector("value1"),
+ mock_data().rbegin()->second);
+ EXPECT_EQ(leveldb::StdStringToUint8Vector("value3"),
+ std::next(mock_data().rbegin())->second);
+}
+
TEST_F(LocalStorageContextMojoTest, ShutdownClearsData) {
url::Origin origin1(GURL("http://foobar.com"));
url::Origin origin2(GURL("http://example.com"));
@@ -738,12 +836,12 @@ TEST_F(LocalStorageContextMojoTest, ShutdownClearsData) {
mojom::LevelDBWrapperPtr wrapper;
context()->OpenLocalStorage(origin1, MakeRequest(&wrapper));
- wrapper->Put(key1, value, "source", base::Bind(&NoOpSuccess));
- wrapper->Put(key2, value, "source", base::Bind(&NoOpSuccess));
+ wrapper->Put(key1, value, "source", base::BindOnce(&NoOpSuccess));
+ wrapper->Put(key2, value, "source", base::BindOnce(&NoOpSuccess));
wrapper.reset();
context()->OpenLocalStorage(origin2, MakeRequest(&wrapper));
- wrapper->Put(key2, value, "source", base::Bind(&NoOpSuccess));
+ wrapper->Put(key2, value, "source", base::BindOnce(&NoOpSuccess));
wrapper.reset();
// Make sure all data gets committed to the DB.
@@ -846,7 +944,7 @@ class LocalStorageContextMojoTestWithService
mojom::LevelDBWrapperPtr wrapper;
context->OpenLocalStorage(url::Origin(GURL("http://foobar.com")),
MakeRequest(&wrapper));
- wrapper->Put(key, value, "source", base::Bind(&NoOpSuccess));
+ wrapper->Put(key, value, "source", base::BindOnce(&NoOpSuccess));
wrapper.reset();
base::RunLoop().RunUntilIdle();
}
@@ -859,8 +957,8 @@ class LocalStorageContextMojoTestWithService
MakeRequest(&wrapper));
base::RunLoop run_loop;
bool success = false;
- wrapper->Get(key, base::Bind(&GetCallback, run_loop.QuitClosure(), &success,
- result));
+ wrapper->Get(key, base::BindOnce(&GetCallback, run_loop.QuitClosure(),
+ &success, result));
run_loop.Run();
return success;
}
@@ -954,7 +1052,13 @@ TEST_F(LocalStorageContextMojoTestWithService, OnDisk) {
context->ShutdownAndDelete();
}
-TEST_F(LocalStorageContextMojoTestWithService, InvalidVersionOnDisk) {
+// Flaky on Android. https://crbug.com/756550
+#if defined(OS_ANDROID)
+#define MAYBE_InvalidVersionOnDisk DISABLED_InvalidVersionOnDisk
+#else
+#define MAYBE_InvalidVersionOnDisk InvalidVersionOnDisk
+#endif
+TEST_F(LocalStorageContextMojoTestWithService, MAYBE_InvalidVersionOnDisk) {
base::FilePath test_path(FILE_PATH_LITERAL("test_path"));
// Create context and add some data to it.
@@ -977,7 +1081,7 @@ TEST_F(LocalStorageContextMojoTestWithService, InvalidVersionOnDisk) {
// Mess up version number in database.
leveldb_env::ChromiumEnv env;
std::unique_ptr<leveldb::DB> db;
- leveldb::Options options;
+ leveldb_env::Options options;
options.env = &env;
base::FilePath db_path =
temp_path().Append(test_path).Append(FILE_PATH_LITERAL("leveldb"));
@@ -1208,7 +1312,7 @@ TEST_F(LocalStorageContextMojoTestWithService, RecreateOnCommitFailure) {
// pending commit that will get cancelled when the database connection is
// closed.
wrapper3->Put(key, value, "source",
- base::Bind([](bool success) { EXPECT_TRUE(success); }));
+ base::BindOnce([](bool success) { EXPECT_TRUE(success); }));
// Repeatedly write data to the database, to trigger enough commit errors.
size_t values_written = 0;
@@ -1219,7 +1323,7 @@ TEST_F(LocalStorageContextMojoTestWithService, RecreateOnCommitFailure) {
value[0]++;
wrapper1.set_connection_error_handler(put_loop.QuitClosure());
wrapper1->Put(key, value, "source",
- base::Bind(
+ base::BindOnce(
[](base::Closure quit_closure, bool success) {
EXPECT_TRUE(success);
quit_closure.Run();
@@ -1252,8 +1356,8 @@ TEST_F(LocalStorageContextMojoTestWithService, RecreateOnCommitFailure) {
base::RunLoop get_loop;
std::vector<uint8_t> result;
bool success = true;
- wrapper1->Get(
- key, base::Bind(&GetCallback, get_loop.QuitClosure(), &success, &result));
+ wrapper1->Get(key, base::BindOnce(&GetCallback, get_loop.QuitClosure(),
+ &success, &result));
// Wait for LocalStorageContextMojo to try to reconnect to the database, and
// connect that new request to a properly functioning database.
@@ -1344,7 +1448,7 @@ TEST_F(LocalStorageContextMojoTestWithService,
value[0]++;
wrapper.set_connection_error_handler(put_loop.QuitClosure());
wrapper->Put(key, value, "source",
- base::Bind(
+ base::BindOnce(
[](base::Closure quit_closure, bool success) {
EXPECT_TRUE(success);
quit_closure.Run();
@@ -1391,7 +1495,7 @@ TEST_F(LocalStorageContextMojoTestWithService,
value[0]++;
wrapper.set_connection_error_handler(put_loop.QuitClosure());
wrapper->Put(key, value, "source",
- base::Bind(
+ base::BindOnce(
[](base::Closure quit_closure, bool success) {
EXPECT_TRUE(success);
quit_closure.Run();
diff --git a/chromium/content/browser/dom_storage/session_storage_database.cc b/chromium/content/browser/dom_storage/session_storage_database.cc
index 2e3d8f7b7a8..7fed2c63392 100644
--- a/chromium/content/browser/dom_storage/session_storage_database.cc
+++ b/chromium/content/browser/dom_storage/session_storage_database.cc
@@ -89,7 +89,7 @@ class SessionStorageDatabase::DBOperation {
// No other operations are ongoing and the data is bad -> delete it now.
session_storage_database_->db_.reset();
leveldb::DestroyDB(session_storage_database_->file_path_.AsUTF8Unsafe(),
- leveldb::Options());
+ leveldb_env::Options());
session_storage_database_->invalid_db_deleted_ = true;
}
}
@@ -432,16 +432,16 @@ bool SessionStorageDatabase::LazyOpen(bool create_if_needed) {
leveldb::Status SessionStorageDatabase::TryToOpen(
std::unique_ptr<leveldb::DB>* db) {
- leveldb::Options options;
+ leveldb_env::Options options;
// The directory exists but a valid leveldb database might not exist inside it
// (e.g., a subset of the needed files might be missing). Handle this
// situation gracefully by creating the database now.
options.max_open_files = 0; // Use minimum.
options.create_if_missing = true;
- options.reuse_logs = leveldb_env::kDefaultLogReuseOptionValue;
// Default write_buffer_size is 4 MB but that might leave a 3.999
// memory allocation in RAM from a log file recovery.
options.write_buffer_size = 64 * 1024;
+ options.block_cache = leveldb_env::SharedWebBlockCache();
return leveldb_env::OpenDB(options, file_path_.AsUTF8Unsafe(), db);
}
diff --git a/chromium/content/browser/dom_storage/session_storage_namespace_impl.h b/chromium/content/browser/dom_storage/session_storage_namespace_impl.h
index 4823efb6c06..f9afadb2e2a 100644
--- a/chromium/content/browser/dom_storage/session_storage_namespace_impl.h
+++ b/chromium/content/browser/dom_storage/session_storage_namespace_impl.h
@@ -17,8 +17,7 @@ namespace content {
class DOMStorageContextWrapper;
class DOMStorageSession;
-class SessionStorageNamespaceImpl
- : NON_EXPORTED_BASE(public SessionStorageNamespace) {
+class SessionStorageNamespaceImpl : public SessionStorageNamespace {
public:
// Constructs a |SessionStorageNamespaceImpl| and allocates new IDs for it.
//
diff --git a/chromium/content/browser/download/base_file.cc b/chromium/content/browser/download/base_file.cc
index 7c05f8deac3..0da99a1bd1a 100644
--- a/chromium/content/browser/download/base_file.cc
+++ b/chromium/content/browser/download/base_file.cc
@@ -18,7 +18,6 @@
#include "content/browser/download/download_interrupt_reasons_impl.h"
#include "content/browser/download/download_net_log_parameters.h"
#include "content/browser/download/download_stats.h"
-#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/common/quarantine.h"
#include "crypto/secure_hash.h"
@@ -28,10 +27,12 @@
namespace content {
-BaseFile::BaseFile(const net::NetLogWithSource& net_log) : net_log_(net_log) {}
+BaseFile::BaseFile(const net::NetLogWithSource& net_log) : net_log_(net_log) {
+ DETACH_FROM_SEQUENCE(sequence_checker_);
+}
BaseFile::~BaseFile() {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (detached_)
Close();
else
@@ -46,7 +47,7 @@ DownloadInterruptReason BaseFile::Initialize(
const std::string& hash_so_far,
std::unique_ptr<crypto::SecureHash> hash_state,
bool is_sparse_file) {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!detached_);
if (full_path.empty()) {
@@ -72,7 +73,9 @@ DownloadInterruptReason BaseFile::Initialize(
bytes_so_far_ = bytes_so_far;
secure_hash_ = std::move(hash_state);
is_sparse_file_ = is_sparse_file;
- DCHECK(!is_sparse_file_ || !secure_hash_);
+ // Sparse file doesn't validate hash.
+ if (is_sparse_file_)
+ secure_hash_.reset();
file_ = std::move(file);
return Open(hash_so_far);
@@ -127,7 +130,7 @@ DownloadInterruptReason BaseFile::WriteDataToFile(int64_t offset,
}
DownloadInterruptReason BaseFile::Rename(const base::FilePath& new_path) {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DownloadInterruptReason rename_result = DOWNLOAD_INTERRUPT_REASON_NONE;
// If the new path is same as the old one, there is no need to perform the
@@ -172,7 +175,7 @@ void BaseFile::Detach() {
}
void BaseFile::Cancel() {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!detached_);
net_log_.AddEvent(net::NetLogEventType::CANCELLED);
@@ -188,7 +191,7 @@ void BaseFile::Cancel() {
}
std::unique_ptr<crypto::SecureHash> BaseFile::Finish() {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// TODO(qinmin): verify that all the holes have been filled.
if (is_sparse_file_)
@@ -276,7 +279,7 @@ DownloadInterruptReason BaseFile::CalculatePartialHash(
}
DownloadInterruptReason BaseFile::Open(const std::string& hash_so_far) {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!detached_);
DCHECK(!full_path_.empty());
@@ -339,7 +342,7 @@ DownloadInterruptReason BaseFile::Open(const std::string& hash_so_far) {
}
void BaseFile::Close() {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (file_.IsValid()) {
// Currently we don't really care about the return value, since if it fails
@@ -426,7 +429,7 @@ DownloadInterruptReason BaseFile::AnnotateWithSourceInformation(
const std::string& client_guid,
const GURL& source_url,
const GURL& referrer_url) {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!detached_);
DCHECK(!full_path_.empty());
diff --git a/chromium/content/browser/download/base_file.h b/chromium/content/browser/download/base_file.h
index e630d778cfd..8b548777051 100644
--- a/chromium/content/browser/download/base_file.h
+++ b/chromium/content/browser/download/base_file.h
@@ -16,6 +16,7 @@
#include "base/gtest_prod_util.h"
#include "base/logging.h"
#include "base/macros.h"
+#include "base/sequence_checker.h"
#include "base/time/time.h"
#include "content/common/content_export.h"
#include "content/public/browser/download_interrupt_reasons.h"
@@ -34,7 +35,7 @@ namespace content {
class CONTENT_EXPORT BaseFile {
public:
// May be constructed on any thread. All other routines (including
- // destruction) must occur on the FILE thread.
+ // destruction) must occur on the same sequence.
BaseFile(const net::NetLogWithSource& net_log);
~BaseFile();
@@ -253,6 +254,8 @@ class CONTENT_EXPORT BaseFile {
net::NetLogWithSource net_log_;
+ SEQUENCE_CHECKER(sequence_checker_);
+
DISALLOW_COPY_AND_ASSIGN(BaseFile);
};
diff --git a/chromium/content/browser/download/docs/save-page-as.md b/chromium/content/browser/download/docs/save-page-as.md
index 8b170ef6462..cb6f38a5cee 100644
--- a/chromium/content/browser/download/docs/save-page-as.md
+++ b/chromium/content/browser/download/docs/save-page-as.md
@@ -26,11 +26,11 @@ are described by their code comments or by their code structure).
* UI-thread object
* SaveFileManager class
- * coordinates between FILE and UI threads
+ * coordinates between the download sequence and the UI thread
* Gets requests from `SavePackage` and communicates results back to
`SavePackage` on the UI thread.
* Shephards data (received from the network OR from DOM) into
- FILE thread - via `SaveFileManager::UpdateSaveProgress`
+ the download sequence - via `SaveFileManager::UpdateSaveProgress`
* created and owned by `BrowserMainLoop`
(ref-counted today, but it is unnecessary - see https://crbug.com/596953)
* The global instance can be retrieved by the Get method.
@@ -38,11 +38,11 @@ are described by their code comments or by their code structure).
* SaveFile class
* tracks saving a single file
* created and owned by `SaveFileManager`
- * FILE-thread object
+ * download sequence object
* SaveFileResourceHandler class
* tracks network downloads + forwards their status into `SaveFileManager`
- (onto FILE-thread)
+ (onto download sequence)
* created by `ResourceDispatcherHostImpl::BeginSaveFile`
* IO-thread object
diff --git a/chromium/content/browser/download/download_browsertest.cc b/chromium/content/browser/download/download_browsertest.cc
index 06db334784c..0879a3f0f17 100644
--- a/chromium/content/browser/download/download_browsertest.cc
+++ b/chromium/content/browser/download/download_browsertest.cc
@@ -37,6 +37,7 @@
#include "content/browser/download/download_item_impl.h"
#include "content/browser/download/download_manager_impl.h"
#include "content/browser/download/download_resource_handler.h"
+#include "content/browser/download/download_task_runner.h"
#include "content/browser/download/parallel_download_utils.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
@@ -172,7 +173,7 @@ class DownloadFileWithDelay : public DownloadFileImpl {
DownloadInterruptReason reason,
const base::FilePath& path);
- // This variable may only be read on the FILE thread, and may only be
+ // This variable may only be read on the download sequence, and may only be
// indirected through (e.g. methods on DownloadFileWithDelayFactory called)
// on the UI thread. This is because after construction,
// DownloadFileWithDelay lives on the file thread, but
@@ -229,7 +230,7 @@ DownloadFileWithDelay::~DownloadFileWithDelay() {}
void DownloadFileWithDelay::RenameAndUniquify(
const base::FilePath& full_path,
const RenameCompletionCallback& callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ DCHECK(GetDownloadTaskRunner()->RunsTasksInCurrentSequence());
DownloadFileImpl::RenameAndUniquify(
full_path, base::Bind(DownloadFileWithDelay::RenameCallbackWrapper,
owner_, callback));
@@ -241,7 +242,7 @@ void DownloadFileWithDelay::RenameAndAnnotate(
const GURL& source_url,
const GURL& referrer_url,
const RenameCompletionCallback& callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ DCHECK(GetDownloadTaskRunner()->RunsTasksInCurrentSequence());
DownloadFileImpl::RenameAndAnnotate(
full_path,
client_guid,
@@ -287,7 +288,7 @@ void DownloadFileWithDelayFactory::AddRenameCallback(base::Closure callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
rename_callbacks_.push_back(callback);
if (waiting_)
- base::MessageLoopForUI::current()->QuitWhenIdle();
+ base::RunLoop::QuitCurrentWhenIdleDeprecated();
}
void DownloadFileWithDelayFactory::GetAllRenameCallbacks(
@@ -321,7 +322,7 @@ class CountingDownloadFile : public DownloadFileImpl {
observer) {}
~CountingDownloadFile() override {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ DCHECK(GetDownloadTaskRunner()->RunsTasksInCurrentSequence());
active_files_--;
}
@@ -330,14 +331,14 @@ class CountingDownloadFile : public DownloadFileImpl {
const CancelRequestCallback& cancel_request_callback,
const DownloadItem::ReceivedSlices& received_slices,
bool is_parallelizable) override {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ DCHECK(GetDownloadTaskRunner()->RunsTasksInCurrentSequence());
active_files_++;
DownloadFileImpl::Initialize(callback, cancel_request_callback,
received_slices, is_parallelizable);
}
static void GetNumberActiveFiles(int* result) {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ DCHECK(GetDownloadTaskRunner()->RunsTasksInCurrentSequence());
*result = active_files_;
}
@@ -345,9 +346,9 @@ class CountingDownloadFile : public DownloadFileImpl {
// until data is returned.
static int GetNumberActiveFilesFromFileThread() {
int result = -1;
- BrowserThread::PostTaskAndReply(
- BrowserThread::FILE, FROM_HERE,
- base::Bind(&CountingDownloadFile::GetNumberActiveFiles, &result),
+ GetDownloadTaskRunner()->PostTaskAndReply(
+ FROM_HERE,
+ base::BindOnce(&CountingDownloadFile::GetNumberActiveFiles, &result),
base::MessageLoop::current()->QuitWhenIdleClosure());
base::RunLoop().Run();
DCHECK_NE(-1, result);
@@ -578,11 +579,11 @@ class DownloadContentTest : public ContentBrowserTest {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&net::URLRequestSlowDownloadJob::AddUrlHandler));
+ base::BindOnce(&net::URLRequestSlowDownloadJob::AddUrlHandler));
base::FilePath mock_base(GetTestFilePath("download", ""));
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&net::URLRequestMockHTTPJob::AddUrlHandlers, mock_base));
+ base::BindOnce(&net::URLRequestMockHTTPJob::AddUrlHandlers, mock_base));
ASSERT_TRUE(embedded_test_server()->Start());
const std::string real_host =
embedded_test_server()->host_port_pair().host();
@@ -646,7 +647,7 @@ class DownloadContentTest : public ContentBrowserTest {
bool result = true;
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&EnsureNoPendingDownloadJobsOnIO, &result));
+ base::BindOnce(&EnsureNoPendingDownloadJobsOnIO, &result));
base::RunLoop().Run();
return result &&
(CountingDownloadFile::GetNumberActiveFilesFromFileThread() == 0);
@@ -789,7 +790,13 @@ class ParallelDownloadTest : public DownloadContentTest {
} // namespace
-IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadCancelled) {
+#if defined(OS_ANDROID)
+// Failing/Flaky on Android: https://crbug.com/754679
+#define MAYBE_DownloadCancelled DISABLED_DownloadCancelled
+#else
+#define MAYBE_DownloadCancelled DownloadCancelled
+#endif
+IN_PROC_BROWSER_TEST_F(DownloadContentTest, MAYBE_DownloadCancelled) {
SetupEnsureNoPendingDownloads();
// Create a download, wait until it's started, and confirm
@@ -906,7 +913,7 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, CancelAtFinalRename) {
download_manager->GetAllDownloads(&items);
ASSERT_EQ(1u, items.size());
items[0]->Cancel(true);
- RunAllPendingInMessageLoop();
+ RunAllBlockingPoolTasksUntilIdle();
// Check state.
EXPECT_EQ(DownloadItem::CANCELLED, items[0]->GetState());
@@ -1021,13 +1028,15 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, MAYBE_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::Bind(&base::PlatformThread::Sleep,
- base::TimeDelta::FromMilliseconds(25)));
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&base::PlatformThread::Sleep,
+ base::TimeDelta::FromMilliseconds(25)));
DownloadManagerForShell(shell())->Shutdown();
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::Bind(&base::PlatformThread::Sleep,
- base::TimeDelta::FromMilliseconds(25)));
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&base::PlatformThread::Sleep,
+ base::TimeDelta::FromMilliseconds(25)));
}
// Try to shutdown just after we release the download file, by delaying
@@ -1074,7 +1083,7 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, ShutdownAtRelease) {
ASSERT_EQ(1u, items.size());
items[0]->Cancel(true);
EXPECT_EQ(DownloadItem::IN_PROGRESS, items[0]->GetState());
- RunAllPendingInMessageLoop();
+ RunAllBlockingPoolTasksUntilIdle();
EXPECT_EQ(DownloadItem::IN_PROGRESS, items[0]->GetState());
MockDownloadItemObserver observer;
@@ -1494,9 +1503,8 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, RecoverFromInitFileError) {
// We need to make sure that any cross-thread downloads communication has
// quiesced before clearing and injecting the new errors, as the
// InjectErrors() routine alters the currently in use download file
- // factory, which is a file thread object.
- RunAllPendingInMessageLoop(BrowserThread::FILE);
- RunAllPendingInMessageLoop();
+ // factory.
+ RunAllBlockingPoolTasksUntilIdle();
// Clear the old errors list.
injector->ClearError();
@@ -1537,9 +1545,8 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest,
// We need to make sure that any cross-thread downloads communication has
// quiesced before clearing and injecting the new errors, as the
// InjectErrors() routine alters the currently in use download file
- // factory, which is a file thread object.
- RunAllPendingInMessageLoop(BrowserThread::FILE);
- RunAllPendingInMessageLoop();
+ // factory.
+ RunAllBlockingPoolTasksUntilIdle();
// Clear the old errors list.
injector->ClearError();
@@ -1575,9 +1582,8 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, RecoverFromFinalRenameError) {
// We need to make sure that any cross-thread downloads communication has
// quiesced before clearing and injecting the new errors, as the
// InjectErrors() routine alters the currently in use download file
- // factory, which is a file thread object.
- RunAllPendingInMessageLoop(BrowserThread::FILE);
- RunAllPendingInMessageLoop();
+ // factory, which is a download sequence object.
+ RunAllBlockingPoolTasksUntilIdle();
// Clear the old errors list.
injector->ClearError();
@@ -1655,8 +1661,7 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, CancelInterruptedDownload) {
ASSERT_TRUE(PathExists(intermediate_path));
download->Cancel(true /* user_cancel */);
- RunAllPendingInMessageLoop(BrowserThread::FILE);
- RunAllPendingInMessageLoop();
+ RunAllBlockingPoolTasksUntilIdle();
// The intermediate file should now be gone.
EXPECT_FALSE(PathExists(intermediate_path));
@@ -1677,8 +1682,7 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, RemoveInterruptedDownload) {
ASSERT_TRUE(PathExists(intermediate_path));
download->Remove();
- RunAllPendingInMessageLoop(BrowserThread::FILE);
- RunAllPendingInMessageLoop();
+ RunAllBlockingPoolTasksUntilIdle();
// The intermediate file should now be gone.
EXPECT_FALSE(PathExists(intermediate_path));
@@ -1699,8 +1703,7 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, RemoveCompletedDownload) {
base::FilePath target_path(download->GetTargetFilePath());
EXPECT_TRUE(PathExists(target_path));
download->Remove();
- RunAllPendingInMessageLoop(BrowserThread::FILE);
- RunAllPendingInMessageLoop();
+ RunAllBlockingPoolTasksUntilIdle();
// The file should still exist.
EXPECT_TRUE(PathExists(target_path));
@@ -1739,8 +1742,7 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, RemoveResumingDownload) {
request_start_handler.RespondWith(std::string(), net::OK);
// The intermediate file should now be gone.
- RunAllPendingInMessageLoop(BrowserThread::FILE);
- RunAllPendingInMessageLoop();
+ RunAllBlockingPoolTasksUntilIdle();
EXPECT_FALSE(PathExists(intermediate_path));
parameters.ClearInjectedErrors();
@@ -1790,8 +1792,7 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, CancelResumingDownload) {
// The intermediate file should now be gone.
RunAllPendingInMessageLoop(BrowserThread::IO);
- RunAllPendingInMessageLoop(BrowserThread::FILE);
- RunAllPendingInMessageLoop();
+ RunAllBlockingPoolTasksUntilIdle();
EXPECT_FALSE(PathExists(intermediate_path));
parameters.ClearInjectedErrors();
@@ -1833,8 +1834,7 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, RemoveResumedDownload) {
download->Remove();
// The intermediate file should now be gone.
- RunAllPendingInMessageLoop(BrowserThread::FILE);
- RunAllPendingInMessageLoop();
+ RunAllBlockingPoolTasksUntilIdle();
EXPECT_FALSE(PathExists(intermediate_path));
EXPECT_FALSE(PathExists(target_path));
EXPECT_TRUE(EnsureNoPendingDownloads());
@@ -1866,8 +1866,7 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, CancelResumedDownload) {
download->Cancel(true);
// The intermediate file should now be gone.
- RunAllPendingInMessageLoop(BrowserThread::FILE);
- RunAllPendingInMessageLoop();
+ RunAllBlockingPoolTasksUntilIdle();
EXPECT_FALSE(PathExists(intermediate_path));
EXPECT_FALSE(PathExists(target_path));
EXPECT_TRUE(EnsureNoPendingDownloads());
@@ -2724,6 +2723,7 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest,
download->GetTargetFilePath().BaseName().value().c_str());
}
+// Verify parallel download in normal case.
IN_PROC_BROWSER_TEST_F(ParallelDownloadTest, ParallelDownloadComplete) {
EXPECT_TRUE(base::FeatureList::IsEnabled(features::kParallelDownloading));
@@ -2750,6 +2750,77 @@ IN_PROC_BROWSER_TEST_F(ParallelDownloadTest, ParallelDownloadComplete) {
download->GetTargetFilePath());
}
+// Verify parallel download resumption.
+IN_PROC_BROWSER_TEST_F(ParallelDownloadTest,
+ DISABLED_ParallelDownloadResumption) {
+ EXPECT_TRUE(base::FeatureList::IsEnabled(features::kParallelDownloading));
+
+ TestDownloadRequestHandler request_handler;
+ TestDownloadRequestHandler::Parameters parameters;
+ parameters.etag = "ABC";
+ parameters.size = 3000000;
+ parameters.last_modified = std::string();
+ parameters.connection_type = net::HttpResponseInfo::CONNECTION_INFO_HTTP1_1;
+ request_handler.StartServing(parameters);
+
+ base::FilePath intermediate_file_path =
+ GetDownloadDirectory().AppendASCII("intermediate");
+ std::vector<GURL> url_chain;
+ url_chain.push_back(request_handler.url());
+
+ // Create an intermediate file that contains 3 chunks of data.
+ const int kIntermediateSize = 1000;
+ std::vector<char> buffer(kIntermediateSize);
+ request_handler.GetPatternBytes(parameters.pattern_generator_seed, 0,
+ buffer.size(), buffer.data());
+ {
+ base::ThreadRestrictions::ScopedAllowIO allow_io_for_test_setup;
+ base::File file(intermediate_file_path,
+ base::File::FLAG_CREATE | base::File::FLAG_WRITE);
+ ASSERT_TRUE(file.IsValid());
+ request_handler.GetPatternBytes(parameters.pattern_generator_seed, 0,
+ buffer.size(), buffer.data());
+ EXPECT_EQ(kIntermediateSize,
+ file.Write(0, buffer.data(), kIntermediateSize));
+ request_handler.GetPatternBytes(parameters.pattern_generator_seed, 1000000,
+ buffer.size(), buffer.data());
+ EXPECT_EQ(kIntermediateSize,
+ file.Write(1000000, buffer.data(), kIntermediateSize));
+ request_handler.GetPatternBytes(parameters.pattern_generator_seed, 2000000,
+ buffer.size(), buffer.data());
+ EXPECT_EQ(kIntermediateSize,
+ file.Write(2000000, buffer.data(), kIntermediateSize));
+ file.Close();
+ }
+
+ // Create the received slices data that reflects the data in the file.
+ std::vector<DownloadItem::ReceivedSlice> received_slices = {
+ DownloadItem::ReceivedSlice(0, 1000),
+ DownloadItem::ReceivedSlice(1000000, 1000),
+ DownloadItem::ReceivedSlice(2000000, 1000)};
+
+ DownloadItem* download = DownloadManagerForShell(shell())->CreateDownloadItem(
+ "F7FB1F59-7DE1-4845-AFDB-8A688F70F583", 1, intermediate_file_path,
+ base::FilePath(), url_chain, GURL(), GURL(), GURL(), GURL(),
+ "application/octet-stream", "application/octet-stream", base::Time::Now(),
+ base::Time(), parameters.etag, parameters.last_modified,
+ kIntermediateSize * 3, parameters.size, std::string(),
+ DownloadItem::INTERRUPTED, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
+ DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED, false, base::Time(), false,
+ received_slices);
+
+ // Resume the parallel download with sparse file and received slices data.
+ download->Resume();
+ WaitForCompletion(download);
+
+ TestDownloadRequestHandler::CompletedRequests completed_requests;
+ request_handler.GetCompletedRequestInfo(&completed_requests);
+ EXPECT_EQ(kTestRequestCount, static_cast<int>(completed_requests.size()));
+
+ ReadAndVerifyFileContents(parameters.pattern_generator_seed, parameters.size,
+ download->GetTargetFilePath());
+}
+
// Test to verify that the browser-side enforcement of X-Frame-Options does
// not impact downloads. Since XFO is only checked for subframes, this test
// initiates a download in an iframe and expects it to succeed.
diff --git a/chromium/content/browser/download/download_create_info.h b/chromium/content/browser/download/download_create_info.h
index dbb599785c9..d2c85027bc1 100644
--- a/chromium/content/browser/download/download_create_info.h
+++ b/chromium/content/browser/download/download_create_info.h
@@ -133,7 +133,9 @@ struct CONTENT_EXPORT DownloadCreateInfo {
// For continuing a download, the ETag of the file.
std::string etag;
- // If "Accept-Ranges:bytes" header presents in the response header.
+ // If the download response can be partial content.
+ // Either "Accept-Ranges" or "Content-Range" header presents in the
+ // response header.
bool accept_range;
// The HTTP connection type.
diff --git a/chromium/content/browser/download/download_file.h b/chromium/content/browser/download/download_file.h
index 4b1aac72b45..8f6ae967563 100644
--- a/chromium/content/browser/download/download_file.h
+++ b/chromium/content/browser/download/download_file.h
@@ -15,6 +15,7 @@
#include "content/common/content_export.h"
#include "content/public/browser/download_interrupt_reasons.h"
#include "content/public/browser/download_item.h"
+#include "mojo/public/cpp/system/data_pipe.h"
class GURL;
@@ -22,9 +23,9 @@ namespace content {
class ByteStreamReader;
-// These objects live exclusively on the file thread and handle the writing
-// operations for one download. These objects live only for the duration that
-// the download is 'in progress': once the download has been completed or
+// These objects live exclusively on the download sequence and handle the
+// writing operations for one download. These objects live only for the duration
+// that the download is 'in progress': once the download has been completed or
// cancelled, the DownloadFile is destroyed.
class CONTENT_EXPORT DownloadFile {
public:
@@ -43,7 +44,7 @@ class CONTENT_EXPORT DownloadFile {
RenameCompletionCallback;
// Used to drop the request, when the byte stream reader should be closed on
- // FILE thread.
+ // download sequence.
typedef base::Callback<void(int64_t offset)> CancelRequestCallback;
virtual ~DownloadFile() {}
@@ -62,6 +63,16 @@ class CONTENT_EXPORT DownloadFile {
int64_t offset,
int64_t length) = 0;
+ // Add the consumer handle of a DataPipe to write into a slice of the file.
+ virtual void AddDataPipeConsumerHandle(
+ mojo::ScopedDataPipeConsumerHandle handle,
+ int64_t offset,
+ int64_t length) = 0;
+
+ // Called when the response for the stream starting at |offset| is completed,
+ virtual void OnResponseCompleted(int64_t offset,
+ DownloadInterruptReason status) = 0;
+
// Rename the download file to |full_path|. If that file exists
// |full_path| will be uniquified by suffixing " (<number>)" to the
// file name before the extension.
diff --git a/chromium/content/browser/download/download_file_impl.cc b/chromium/content/browser/download/download_file_impl.cc
index edde01e1bc0..0d5c0065c5a 100644
--- a/chromium/content/browser/download/download_file_impl.cc
+++ b/chromium/content/browser/download/download_file_impl.cc
@@ -11,6 +11,7 @@
#include "base/files/file_util.h"
#include "base/memory/ptr_util.h"
#include "base/strings/stringprintf.h"
+#include "base/threading/sequenced_task_runner_handle.h"
#include "base/time/time.h"
#include "base/values.h"
#include "content/browser/byte_stream.h"
@@ -23,6 +24,7 @@
#include "content/public/browser/browser_thread.h"
#include "crypto/secure_hash.h"
#include "crypto/sha2.h"
+#include "mojo/public/c/system/types.h"
#include "net/base/io_buffer.h"
#include "net/log/net_log.h"
#include "net/log/net_log_event_type.h"
@@ -51,6 +53,9 @@ const int kNoBytesToWrite = -1;
// Default content length when the potential file size is not yet determined.
const int kUnknownContentLength = -1;
+// Data length to read from data pipe.
+const int kBytesToRead = 4096;
+
} // namespace
DownloadFileImpl::SourceStream::SourceStream(
@@ -62,10 +67,39 @@ DownloadFileImpl::SourceStream::SourceStream(
bytes_written_(0),
finished_(false),
index_(0u),
- stream_reader_(std::move(stream_reader)) {}
+ stream_reader_(std::move(stream_reader)),
+ completion_status_(DOWNLOAD_INTERRUPT_REASON_NONE),
+ is_response_completed_(false) {}
+
+DownloadFileImpl::SourceStream::SourceStream(
+ int64_t offset,
+ int64_t length,
+ mojo::ScopedDataPipeConsumerHandle consumer_handle)
+ : offset_(offset),
+ length_(length),
+ bytes_written_(0),
+ finished_(false),
+ index_(0u),
+ completion_status_(DOWNLOAD_INTERRUPT_REASON_NONE),
+ is_response_completed_(false),
+ consumer_handle_(std::move(consumer_handle)),
+ handle_watcher_(base::MakeUnique<mojo::SimpleWatcher>(
+ FROM_HERE,
+ mojo::SimpleWatcher::ArmingPolicy::AUTOMATIC)) {}
DownloadFileImpl::SourceStream::~SourceStream() = default;
+void DownloadFileImpl::SourceStream::OnResponseCompleted(
+ DownloadInterruptReason status) {
+ // This can be called before or after data pipe is completely drained. So we
+ // need to pass the |completion_status_| to DownloadFileImpl if the data pipe
+ // is already drained.
+ is_response_completed_ = true;
+ completion_status_ = status;
+ if (completion_callback_)
+ std::move(completion_callback_).Run(this);
+}
+
void DownloadFileImpl::SourceStream::OnWriteBytesToDisk(int64_t bytes_write) {
bytes_written_ += bytes_write;
}
@@ -91,12 +125,107 @@ void DownloadFileImpl::SourceStream::TruncateLengthWithWrittenDataBlock(
}
}
+void DownloadFileImpl::SourceStream::RegisterDataReadyCallback(
+ const mojo::SimpleWatcher::ReadyCallback& callback) {
+ if (handle_watcher_) {
+ handle_watcher_->Watch(consumer_handle_.get(), MOJO_HANDLE_SIGNAL_READABLE,
+ callback);
+ } else if (stream_reader_) {
+ stream_reader_->RegisterCallback(base::Bind(callback, MOJO_RESULT_OK));
+ }
+}
+
+void DownloadFileImpl::SourceStream::ClearDataReadyCallback() {
+ if (handle_watcher_)
+ handle_watcher_->Cancel();
+ else if (stream_reader_)
+ stream_reader_->RegisterCallback(base::Closure());
+}
+
+DownloadInterruptReason DownloadFileImpl::SourceStream::GetCompletionStatus() {
+ if (stream_reader_)
+ return static_cast<DownloadInterruptReason>(stream_reader_->GetStatus());
+ return completion_status_;
+}
+
+void DownloadFileImpl::SourceStream::RegisterCompletionCallback(
+ DownloadFileImpl::SourceStream::CompletionCallback callback) {
+ completion_callback_ = std::move(callback);
+}
+
+DownloadFileImpl::SourceStream::StreamState
+DownloadFileImpl::SourceStream::Read(scoped_refptr<net::IOBuffer>* data,
+ size_t* length) {
+ if (handle_watcher_) {
+ *length = kBytesToRead;
+ *data = new net::IOBuffer(kBytesToRead);
+ MojoResult mojo_result = consumer_handle_->ReadData(
+ (*data)->data(), (uint32_t*)length, MOJO_READ_DATA_FLAG_NONE);
+ // TODO(qinmin): figure out when COMPLETE should be returned.
+ switch (mojo_result) {
+ case MOJO_RESULT_OK:
+ return HAS_DATA;
+ case MOJO_RESULT_SHOULD_WAIT:
+ return EMPTY;
+ case MOJO_RESULT_FAILED_PRECONDITION:
+ if (is_response_completed_)
+ return COMPLETE;
+ consumer_handle_.reset();
+ ClearDataReadyCallback();
+ return WAIT_FOR_COMPLETION;
+ case MOJO_RESULT_INVALID_ARGUMENT:
+ case MOJO_RESULT_OUT_OF_RANGE:
+ case MOJO_RESULT_BUSY:
+ NOTREACHED();
+ return COMPLETE;
+ }
+ } else if (stream_reader_) {
+ ByteStreamReader::StreamState state = stream_reader_->Read(data, length);
+ switch (state) {
+ case ByteStreamReader::STREAM_EMPTY:
+ return EMPTY;
+ case ByteStreamReader::STREAM_HAS_DATA:
+ return HAS_DATA;
+ case ByteStreamReader::STREAM_COMPLETE:
+ return COMPLETE;
+ }
+ }
+ return COMPLETE;
+}
+
DownloadFileImpl::DownloadFileImpl(
std::unique_ptr<DownloadSaveInfo> save_info,
const base::FilePath& default_download_directory,
std::unique_ptr<ByteStreamReader> stream_reader,
const net::NetLogWithSource& download_item_net_log,
base::WeakPtr<DownloadDestinationObserver> observer)
+ : DownloadFileImpl(std::move(save_info),
+ default_download_directory,
+ download_item_net_log,
+ observer) {
+ source_streams_[save_info_->offset] = base::MakeUnique<SourceStream>(
+ save_info_->offset, save_info_->length, std::move(stream_reader));
+}
+
+DownloadFileImpl::DownloadFileImpl(
+ std::unique_ptr<DownloadSaveInfo> save_info,
+ const base::FilePath& default_download_directory,
+ mojo::ScopedDataPipeConsumerHandle consumer_handle,
+ const net::NetLogWithSource& download_item_net_log,
+ base::WeakPtr<DownloadDestinationObserver> observer)
+ : DownloadFileImpl(std::move(save_info),
+ default_download_directory,
+ download_item_net_log,
+ observer) {
+ source_streams_[save_info_->offset] = base::MakeUnique<SourceStream>(
+ save_info_->offset, save_info_->length, std::move(consumer_handle));
+}
+
+DownloadFileImpl::DownloadFileImpl(
+ std::unique_ptr<DownloadSaveInfo> save_info,
+ const base::FilePath& default_download_directory,
+ const net::NetLogWithSource& download_item_net_log,
+ base::WeakPtr<DownloadDestinationObserver> observer)
: net_log_(
net::NetLogWithSource::Make(download_item_net_log.net_log(),
net::NetLogSourceType::DOWNLOAD_FILE)),
@@ -111,19 +240,19 @@ DownloadFileImpl::DownloadFileImpl(
bytes_seen_without_parallel_streams_(0),
observer_(observer),
weak_factory_(this) {
- source_streams_[save_info_->offset] = base::MakeUnique<SourceStream>(
- save_info_->offset, save_info_->length, std::move(stream_reader));
-
download_item_net_log.AddEvent(
net::NetLogEventType::DOWNLOAD_FILE_CREATED,
net_log_.source().ToEventParametersCallback());
net_log_.BeginEvent(
net::NetLogEventType::DOWNLOAD_FILE_ACTIVE,
download_item_net_log.source().ToEventParametersCallback());
+
+ DETACH_FROM_SEQUENCE(sequence_checker_);
}
DownloadFileImpl::~DownloadFileImpl() {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
net_log_.EndEvent(net::NetLogEventType::DOWNLOAD_FILE_ACTIVE);
}
@@ -132,7 +261,7 @@ void DownloadFileImpl::Initialize(
const CancelRequestCallback& cancel_request_callback,
const DownloadItem::ReceivedSlices& received_slices,
bool is_parallelizable) {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
update_timer_.reset(new base::RepeatingTimer());
int64_t bytes_so_far = 0;
@@ -152,7 +281,7 @@ void DownloadFileImpl::Initialize(
IsSparseFile());
if (result != DOWNLOAD_INTERRUPT_REASON_NONE) {
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(initialize_callback, result));
+ base::BindOnce(initialize_callback, result));
return;
}
@@ -165,7 +294,7 @@ void DownloadFileImpl::Initialize(
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(initialize_callback, DOWNLOAD_INTERRUPT_REASON_NONE));
+ base::BindOnce(initialize_callback, DOWNLOAD_INTERRUPT_REASON_NONE));
// Initial pull from the straw from all source streams.
for (auto& source_stream : source_streams_)
@@ -176,11 +305,32 @@ void DownloadFileImpl::AddByteStream(
std::unique_ptr<ByteStreamReader> stream_reader,
int64_t offset,
int64_t length) {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
source_streams_[offset] =
base::MakeUnique<SourceStream>(offset, length, std::move(stream_reader));
+ OnSourceStreamAdded(source_streams_[offset].get());
+}
+void DownloadFileImpl::AddDataPipeConsumerHandle(
+ mojo::ScopedDataPipeConsumerHandle consumer_handle,
+ int64_t offset,
+ int64_t length) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ source_streams_[offset] = base::MakeUnique<SourceStream>(
+ offset, length, std::move(consumer_handle));
+ OnSourceStreamAdded(source_streams_[offset].get());
+}
+
+void DownloadFileImpl::OnResponseCompleted(int64_t offset,
+ DownloadInterruptReason status) {
+ auto iter = source_streams_.find(offset);
+ if (iter != source_streams_.end())
+ iter->second->OnResponseCompleted(status);
+}
+
+void DownloadFileImpl::OnSourceStreamAdded(SourceStream* source_stream) {
// There are writers at different offsets now, create the received slices
// vector if necessary.
if (received_slices_.empty() && TotalBytesReceived() > 0) {
@@ -190,13 +340,14 @@ void DownloadFileImpl::AddByteStream(
}
// If the file is initialized, start to write data, or wait until file opened.
if (file_.in_progress())
- RegisterAndActivateStream(source_streams_[offset].get());
+ RegisterAndActivateStream(source_stream);
}
DownloadInterruptReason DownloadFileImpl::WriteDataToFile(int64_t offset,
const char* data,
size_t data_len) {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
WillWriteToDisk(data_len);
return file_.WriteDataToFile(offset, data, data_len);
}
@@ -274,7 +425,7 @@ bool DownloadFileImpl::ShouldRetryFailedRename(DownloadInterruptReason reason) {
void DownloadFileImpl::RenameWithRetryInternal(
std::unique_ptr<RenameParameters> parameters) {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
base::FilePath new_path = parameters->new_path;
@@ -299,12 +450,11 @@ void DownloadFileImpl::RenameWithRetryInternal(
--parameters->retries_left;
if (parameters->time_of_first_failure.is_null())
parameters->time_of_first_failure = base::TimeTicks::Now();
- BrowserThread::PostDelayedTask(
- BrowserThread::FILE,
+ base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE,
- base::Bind(&DownloadFileImpl::RenameWithRetryInternal,
- weak_factory_.GetWeakPtr(),
- base::Passed(std::move(parameters))),
+ base::BindOnce(&DownloadFileImpl::RenameWithRetryInternal,
+ weak_factory_.GetWeakPtr(),
+ base::Passed(std::move(parameters))),
GetRetryDelayForFailedRename(attempt_number));
return;
}
@@ -334,19 +484,15 @@ void DownloadFileImpl::RenameWithRetryInternal(
// Null out callback so that we don't do any more stream processing.
// The request that writes to the pipe should be canceled after
// the download being interrupted.
- for (auto& stream : source_streams_) {
- ByteStreamReader* stream_reader = stream.second->stream_reader();
- if (stream_reader)
- stream_reader->RegisterCallback(base::Closure());
- }
+ for (auto& stream : source_streams_)
+ stream.second->ClearDataReadyCallback();
new_path.clear();
}
BrowserThread::PostTask(
- BrowserThread::UI,
- FROM_HERE,
- base::Bind(parameters->completion_callback, reason, new_path));
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(parameters->completion_callback, reason, new_path));
}
void DownloadFileImpl::Detach() {
@@ -385,8 +531,11 @@ void DownloadFileImpl::WasPaused() {
record_stream_bandwidth_ = false;
}
-void DownloadFileImpl::StreamActive(SourceStream* source_stream) {
- DCHECK(source_stream->stream_reader());
+// TODO(qinmin): This only works with byte stream now, need to handle callback
+// from data pipe.
+void DownloadFileImpl::StreamActive(SourceStream* source_stream,
+ MojoResult result) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
base::TimeTicks start(base::TimeTicks::Now());
base::TimeTicks now;
scoped_refptr<net::IOBuffer> incoming_data;
@@ -395,83 +544,69 @@ void DownloadFileImpl::StreamActive(SourceStream* source_stream) {
size_t num_buffers = 0;
size_t bytes_to_write = 0;
bool should_terminate = false;
- ByteStreamReader::StreamState state(ByteStreamReader::STREAM_EMPTY);
+ SourceStream::StreamState state(SourceStream::EMPTY);
DownloadInterruptReason reason = DOWNLOAD_INTERRUPT_REASON_NONE;
base::TimeDelta delta(
base::TimeDelta::FromMilliseconds(kMaxTimeBlockingFileThreadMs));
// Take care of any file local activity required.
do {
- state = source_stream->stream_reader()->Read(&incoming_data,
- &incoming_data_size);
+ state = source_stream->Read(&incoming_data, &incoming_data_size);
switch (state) {
- case ByteStreamReader::STREAM_EMPTY:
+ case SourceStream::EMPTY:
should_terminate = (source_stream->length() == kNoBytesToWrite);
break;
- case ByteStreamReader::STREAM_HAS_DATA:
- {
- ++num_buffers;
- base::TimeTicks write_start(base::TimeTicks::Now());
- should_terminate = CalculateBytesToWrite(
- source_stream, incoming_data_size, &bytes_to_write);
- DCHECK_GE(incoming_data_size, bytes_to_write);
- reason = WriteDataToFile(
- source_stream->offset() + source_stream->bytes_written(),
- incoming_data.get()->data(), bytes_to_write);
- disk_writes_time_ += (base::TimeTicks::Now() - write_start);
- bytes_seen_ += bytes_to_write;
- total_incoming_data_size += bytes_to_write;
- if (reason == DOWNLOAD_INTERRUPT_REASON_NONE) {
- int64_t prev_bytes_written = source_stream->bytes_written();
- source_stream->OnWriteBytesToDisk(bytes_to_write);
- if (!IsSparseFile())
- break;
- // If the write operation creates a new slice, add it to the
- // |received_slices_| and update all the entries in
- // |source_streams_|.
- if (bytes_to_write > 0 && prev_bytes_written == 0) {
- AddNewSlice(source_stream->offset(), bytes_to_write);
- } else {
- received_slices_[source_stream->index()].received_bytes +=
- bytes_to_write;
- }
+ case SourceStream::HAS_DATA: {
+ ++num_buffers;
+ base::TimeTicks write_start(base::TimeTicks::Now());
+ should_terminate = CalculateBytesToWrite(
+ source_stream, incoming_data_size, &bytes_to_write);
+ DCHECK_GE(incoming_data_size, bytes_to_write);
+ reason = WriteDataToFile(
+ source_stream->offset() + source_stream->bytes_written(),
+ incoming_data.get()->data(), bytes_to_write);
+ disk_writes_time_ += (base::TimeTicks::Now() - write_start);
+ bytes_seen_ += bytes_to_write;
+ total_incoming_data_size += bytes_to_write;
+ if (reason == DOWNLOAD_INTERRUPT_REASON_NONE) {
+ int64_t prev_bytes_written = source_stream->bytes_written();
+ source_stream->OnWriteBytesToDisk(bytes_to_write);
+ if (!IsSparseFile())
+ break;
+ // If the write operation creates a new slice, add it to the
+ // |received_slices_| and update all the entries in
+ // |source_streams_|.
+ if (bytes_to_write > 0 && prev_bytes_written == 0) {
+ AddNewSlice(source_stream->offset(), bytes_to_write);
+ } else {
+ received_slices_[source_stream->index()].received_bytes +=
+ bytes_to_write;
}
}
+ } break;
+ case SourceStream::WAIT_FOR_COMPLETION:
+ source_stream->RegisterCompletionCallback(base::BindOnce(
+ &DownloadFileImpl::OnStreamCompleted, weak_factory_.GetWeakPtr()));
break;
- case ByteStreamReader::STREAM_COMPLETE:
- {
- reason = static_cast<DownloadInterruptReason>(
- source_stream->stream_reader()->GetStatus());
- if (source_stream->length() == DownloadSaveInfo::kLengthFullContent &&
- !received_slices_.empty() &&
- (source_stream->offset() == received_slices_.back().offset +
- received_slices_.back().received_bytes) &&
- reason == DownloadInterruptReason::
- DOWNLOAD_INTERRUPT_REASON_SERVER_NO_RANGE) {
- // We are probably reaching the end of the stream, don't treat this
- // as an error.
- reason = DOWNLOAD_INTERRUPT_REASON_NONE;
- }
- SendUpdate();
- }
+ case SourceStream::COMPLETE:
break;
default:
NOTREACHED();
break;
}
now = base::TimeTicks::Now();
- } while (state == ByteStreamReader::STREAM_HAS_DATA &&
+ } while (state == SourceStream::HAS_DATA &&
reason == DOWNLOAD_INTERRUPT_REASON_NONE && now - start <= delta &&
!should_terminate);
// If we're stopping to yield the thread, post a task so we come back.
- if (state == ByteStreamReader::STREAM_HAS_DATA && now - start > delta &&
+ if (state == SourceStream::HAS_DATA && now - start > delta &&
!should_terminate) {
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- base::Bind(&DownloadFileImpl::StreamActive, weak_factory_.GetWeakPtr(),
- source_stream));
+ base::SequencedTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(&DownloadFileImpl::StreamActive,
+ weak_factory_.GetWeakPtr(), source_stream,
+ MOJO_RESULT_OK));
}
if (total_incoming_data_size)
@@ -479,12 +614,44 @@ void DownloadFileImpl::StreamActive(SourceStream* source_stream) {
RecordContiguousWriteTime(now - start);
- // Take care of communication with our observer.
+ if (state == SourceStream::COMPLETE)
+ OnStreamCompleted(source_stream);
+ else
+ NotifyObserver(source_stream, reason, state, should_terminate);
+
+ if (net_log_.IsCapturing()) {
+ net_log_.AddEvent(net::NetLogEventType::DOWNLOAD_STREAM_DRAINED,
+ base::Bind(&FileStreamDrainedNetLogCallback,
+ total_incoming_data_size, num_buffers));
+ }
+}
+
+void DownloadFileImpl::OnStreamCompleted(SourceStream* source_stream) {
+ DownloadInterruptReason reason = source_stream->GetCompletionStatus();
+ if (source_stream->length() == DownloadSaveInfo::kLengthFullContent &&
+ !received_slices_.empty() &&
+ (source_stream->offset() == received_slices_.back().offset +
+ received_slices_.back().received_bytes) &&
+ reason ==
+ DownloadInterruptReason::DOWNLOAD_INTERRUPT_REASON_SERVER_NO_RANGE) {
+ // We are probably reaching the end of the stream, don't treat this
+ // as an error.
+ reason = DOWNLOAD_INTERRUPT_REASON_NONE;
+ }
+ SendUpdate();
+
+ NotifyObserver(source_stream, reason, SourceStream::COMPLETE, false);
+}
+
+void DownloadFileImpl::NotifyObserver(SourceStream* source_stream,
+ DownloadInterruptReason reason,
+ SourceStream::StreamState stream_state,
+ bool should_terminate) {
if (reason != DOWNLOAD_INTERRUPT_REASON_NONE) {
HandleStreamError(source_stream, reason);
- } else if (state == ByteStreamReader::STREAM_COMPLETE || should_terminate) {
+ } else if (stream_state == SourceStream::COMPLETE || should_terminate) {
// Signal successful completion or termination of the current stream.
- source_stream->stream_reader()->RegisterCallback(base::Closure());
+ source_stream->ClearDataReadyCallback();
source_stream->set_finished(true);
if (should_terminate)
CancelRequest(source_stream->offset());
@@ -513,33 +680,26 @@ void DownloadFileImpl::StreamActive(SourceStream* source_stream) {
update_timer_.reset();
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&DownloadDestinationObserver::DestinationCompleted,
- observer_, TotalBytesReceived(),
- base::Passed(&hash_state)));
+ base::BindOnce(&DownloadDestinationObserver::DestinationCompleted,
+ observer_, TotalBytesReceived(),
+ base::Passed(&hash_state)));
}
}
- if (net_log_.IsCapturing()) {
- net_log_.AddEvent(net::NetLogEventType::DOWNLOAD_STREAM_DRAINED,
- base::Bind(&FileStreamDrainedNetLogCallback,
- total_incoming_data_size, num_buffers));
- }
}
void DownloadFileImpl::RegisterAndActivateStream(SourceStream* source_stream) {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
- ByteStreamReader* stream_reader = source_stream->stream_reader();
- if (stream_reader) {
- stream_reader->RegisterCallback(base::Bind(&DownloadFileImpl::StreamActive,
- weak_factory_.GetWeakPtr(),
- source_stream));
- // Truncate |source_stream|'s length if necessary.
- for (const auto& received_slice : received_slices_) {
- source_stream->TruncateLengthWithWrittenDataBlock(
- received_slice.offset, received_slice.received_bytes);
- }
- num_active_streams_++;
- StreamActive(source_stream);
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ source_stream->RegisterDataReadyCallback(
+ base::Bind(&DownloadFileImpl::StreamActive, weak_factory_.GetWeakPtr(),
+ source_stream));
+ // Truncate |source_stream|'s length if necessary.
+ for (const auto& received_slice : received_slices_) {
+ source_stream->TruncateLengthWithWrittenDataBlock(
+ received_slice.offset, received_slice.received_bytes);
}
+ num_active_streams_++;
+ StreamActive(source_stream, MOJO_RESULT_OK);
}
int64_t DownloadFileImpl::TotalBytesReceived() const {
@@ -551,9 +711,9 @@ void DownloadFileImpl::SendUpdate() {
// far along with received_slices_.
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&DownloadDestinationObserver::DestinationUpdate, observer_,
- TotalBytesReceived(), rate_estimator_.GetCountPerSecond(),
- received_slices_));
+ base::BindOnce(&DownloadDestinationObserver::DestinationUpdate, observer_,
+ TotalBytesReceived(), rate_estimator_.GetCountPerSecond(),
+ received_slices_));
}
void DownloadFileImpl::WillWriteToDisk(size_t data_len) {
@@ -616,8 +776,8 @@ bool DownloadFileImpl::IsDownloadCompleted() {
void DownloadFileImpl::HandleStreamError(SourceStream* source_stream,
DownloadInterruptReason reason) {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
- source_stream->stream_reader()->RegisterCallback(base::Closure());
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ source_stream->ClearDataReadyCallback();
source_stream->set_finished(true);
num_active_streams_--;
@@ -659,7 +819,7 @@ void DownloadFileImpl::HandleStreamError(SourceStream* source_stream,
if (stream.second->offset() < source_stream->offset() &&
stream.second->offset() > preceding_neighbor->offset()) {
DCHECK_EQ(stream.second->bytes_written(), 0);
- stream.second->stream_reader()->RegisterCallback(base::Closure());
+ stream.second->ClearDataReadyCallback();
stream.second->set_finished(true);
CancelRequest(stream.second->offset());
num_active_streams_--;
@@ -678,8 +838,9 @@ void DownloadFileImpl::HandleStreamError(SourceStream* source_stream,
std::unique_ptr<crypto::SecureHash> hash_state = file_.Finish();
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&DownloadDestinationObserver::DestinationError, observer_,
- reason, TotalBytesReceived(), base::Passed(&hash_state)));
+ base::BindOnce(&DownloadDestinationObserver::DestinationError,
+ observer_, reason, TotalBytesReceived(),
+ base::Passed(&hash_state)));
}
}
@@ -704,7 +865,7 @@ DownloadFileImpl::SourceStream* DownloadFileImpl::FindPrecedingNeighbor(
void DownloadFileImpl::CancelRequest(int64_t offset) {
if (!cancel_request_callback_.is_null()) {
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(cancel_request_callback_, offset));
+ base::BindOnce(cancel_request_callback_, offset));
}
}
diff --git a/chromium/content/browser/download/download_file_impl.h b/chromium/content/browser/download/download_file_impl.h
index 23d6ce58d2e..bfd51744b7e 100644
--- a/chromium/content/browser/download/download_file_impl.h
+++ b/chromium/content/browser/download/download_file_impl.h
@@ -19,7 +19,7 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
-#include "base/threading/thread_checker.h"
+#include "base/sequence_checker.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "content/browser/byte_stream.h"
@@ -27,6 +27,7 @@
#include "content/browser/download/rate_estimator.h"
#include "content/public/browser/download_item.h"
#include "content/public/browser/download_save_info.h"
+#include "mojo/public/cpp/system/simple_watcher.h"
#include "net/log/net_log_with_source.h"
namespace content {
@@ -35,20 +36,24 @@ class DownloadDestinationObserver;
class CONTENT_EXPORT DownloadFileImpl : public DownloadFile {
public:
- // Takes ownership of the object pointed to by |request_handle|.
+ // Takes ownership of the object pointed to by |save_info|.
// |net_log| will be used for logging the download file's events.
// May be constructed on any thread. All methods besides the constructor
- // (including destruction) must occur on the FILE thread.
+ // (including destruction) must occur in the same sequence.
//
// Note that the DownloadFileImpl automatically reads from the passed in
- // stream, and sends updates and status of those reads to the
- // DownloadDestinationObserver.
- DownloadFileImpl(
- std::unique_ptr<DownloadSaveInfo> save_info,
- const base::FilePath& default_downloads_directory,
- std::unique_ptr<ByteStreamReader> stream_reader,
- const net::NetLogWithSource& net_log,
- base::WeakPtr<DownloadDestinationObserver> observer);
+ // |stream_reader| or |consumer_handle|, and sends updates and status of
+ // those reads to the DownloadDestinationObserver.
+ DownloadFileImpl(std::unique_ptr<DownloadSaveInfo> save_info,
+ const base::FilePath& default_downloads_directory,
+ std::unique_ptr<ByteStreamReader> stream_reader,
+ const net::NetLogWithSource& net_log,
+ base::WeakPtr<DownloadDestinationObserver> observer);
+ DownloadFileImpl(std::unique_ptr<DownloadSaveInfo> save_info,
+ const base::FilePath& default_downloads_directory,
+ mojo::ScopedDataPipeConsumerHandle consumer_handle,
+ const net::NetLogWithSource& net_log,
+ base::WeakPtr<DownloadDestinationObserver> observer);
~DownloadFileImpl() override;
@@ -57,11 +62,14 @@ class CONTENT_EXPORT DownloadFileImpl : public DownloadFile {
const CancelRequestCallback& cancel_request_callback,
const DownloadItem::ReceivedSlices& received_slices,
bool is_parallelizable) override;
-
void AddByteStream(std::unique_ptr<ByteStreamReader> stream_reader,
int64_t offset,
int64_t length) override;
-
+ void AddDataPipeConsumerHandle(mojo::ScopedDataPipeConsumerHandle handle,
+ int64_t offset,
+ int64_t length) override;
+ void OnResponseCompleted(int64_t offset,
+ DownloadInterruptReason status) override;
void RenameAndUniquify(const base::FilePath& full_path,
const RenameCompletionCallback& callback) override;
void RenameAndAnnotate(const base::FilePath& full_path,
@@ -91,11 +99,17 @@ class CONTENT_EXPORT DownloadFileImpl : public DownloadFile {
private:
friend class DownloadFileTest;
- // Wrapper of a ByteStreamReader, and the meta data needed to write to a
- // slice of the target file.
+ DownloadFileImpl(std::unique_ptr<DownloadSaveInfo> save_info,
+ const base::FilePath& default_downloads_directory,
+ const net::NetLogWithSource& net_log,
+ base::WeakPtr<DownloadDestinationObserver> observer);
+
+ // Wrapper of a ByteStreamReader or ScopedDataPipeConsumerHandle, and the meta
+ // data needed to write to a slice of the target file.
//
- // Does not require the stream reader ready when constructor is called.
- // |stream_reader_| can be set later when the network response is handled.
+ // Does not require the stream reader or the consumer handle to be ready when
+ // constructor is called. |stream_reader_| can be set later when the network
+ // response is handled.
//
// Multiple SourceStreams can concurrently write to the same file sink.
class CONTENT_EXPORT SourceStream {
@@ -103,8 +117,13 @@ class CONTENT_EXPORT DownloadFileImpl : public DownloadFile {
SourceStream(int64_t offset,
int64_t length,
std::unique_ptr<ByteStreamReader> stream_reader);
+ SourceStream(int64_t offset,
+ int64_t length,
+ mojo::ScopedDataPipeConsumerHandle consumer_handle);
~SourceStream();
+ void OnResponseCompleted(DownloadInterruptReason status);
+
// Called after successfully writing a buffer to disk.
void OnWriteBytesToDisk(int64_t bytes_write);
@@ -113,7 +132,35 @@ class CONTENT_EXPORT DownloadFileImpl : public DownloadFile {
void TruncateLengthWithWrittenDataBlock(int64_t offset,
int64_t bytes_written);
- ByteStreamReader* stream_reader() const { return stream_reader_.get(); }
+ // Registers the callback that will be called when data is ready.
+ void RegisterDataReadyCallback(
+ const mojo::SimpleWatcher::ReadyCallback& callback);
+ // Clears the callback that is registed when data is ready.
+ void ClearDataReadyCallback();
+
+ // Gets the status of the input stream when the stream completes.
+ // TODO(qinmin): for data pipe, it currently doesn't support sending an
+ // abort status at the end. The best way to do this is to add a separate
+ // mojo interface for control messages when creating this object. See
+ // http://crbug.com/748240. An alternative strategy is to let the
+ // DownloadManager pass the status code to DownloadItem or DownloadFile.
+ // However, a DownloadFile can have multiple SourceStreams, so we have to
+ // maintain a map between data pipe and DownloadItem/DownloadFile somewhere.
+ DownloadInterruptReason GetCompletionStatus();
+
+ using CompletionCallback = base::OnceCallback<void(SourceStream*)>;
+ // Register an callback to be called when download completes.
+ void RegisterCompletionCallback(CompletionCallback callback);
+
+ // Results for reading the SourceStream.
+ enum StreamState {
+ EMPTY = 0,
+ HAS_DATA,
+ WAIT_FOR_COMPLETION,
+ COMPLETE,
+ };
+ StreamState Read(scoped_refptr<net::IOBuffer>* data, size_t* length);
+
int64_t offset() const { return offset_; }
int64_t length() const { return length_; }
int64_t bytes_written() const { return bytes_written_; }
@@ -145,6 +192,17 @@ class CONTENT_EXPORT DownloadFileImpl : public DownloadFile {
// The stream through which data comes.
std::unique_ptr<ByteStreamReader> stream_reader_;
+ // Status when the response completes, used by data pipe.
+ DownloadInterruptReason completion_status_;
+
+ // Whether the producer has completed handling the response.
+ bool is_response_completed_;
+
+ CompletionCallback completion_callback_;
+
+ mojo::ScopedDataPipeConsumerHandle consumer_handle_;
+ std::unique_ptr<mojo::SimpleWatcher> handle_watcher_;
+
DISALLOW_COPY_AND_ASSIGN(SourceStream);
};
@@ -199,13 +257,25 @@ class CONTENT_EXPORT DownloadFileImpl : public DownloadFile {
size_t bytes_available_to_write,
size_t* bytes_to_write);
- // Called when there's some activity on the byte stream that needs to be
+ // Called when a new SourceStream object is added.
+ void OnSourceStreamAdded(SourceStream* source_stream);
+
+ // Called when there's some activity on the input data that needs to be
// handled.
- void StreamActive(SourceStream* source_stream);
+ void StreamActive(SourceStream* source_stream, MojoResult result);
// Register callback and start to read data from the stream.
void RegisterAndActivateStream(SourceStream* source_stream);
+ // Called when a stream completes.
+ void OnStreamCompleted(SourceStream* source_stream);
+
+ // Notify |observer_| about the download status.
+ void NotifyObserver(SourceStream* source_stream,
+ DownloadInterruptReason reason,
+ SourceStream::StreamState stream_state,
+ bool should_terminate);
+
// Adds a new slice to |received_slices_| and update the existing entries in
// |source_streams_| as their lengths will change.
// TODO(qinmin): add a test for this function.
@@ -243,7 +313,7 @@ class CONTENT_EXPORT DownloadFileImpl : public DownloadFile {
// DownloadSaveInfo provided during construction. Since the DownloadFileImpl
// can be created on any thread, this holds the save_info_ until it can be
- // used to initialize file_ on the FILE thread.
+ // used to initialize file_ on the download sequence.
std::unique_ptr<DownloadSaveInfo> save_info_;
// The default directory for creating the download file.
@@ -279,6 +349,8 @@ class CONTENT_EXPORT DownloadFileImpl : public DownloadFile {
std::vector<DownloadItem::ReceivedSlice> received_slices_;
+ SEQUENCE_CHECKER(sequence_checker_);
+
base::WeakPtr<DownloadDestinationObserver> observer_;
base::WeakPtrFactory<DownloadFileImpl> weak_factory_;
diff --git a/chromium/content/browser/download/download_file_unittest.cc b/chromium/content/browser/download/download_file_unittest.cc
index a51777d66b5..e191b6292bc 100644
--- a/chromium/content/browser/download/download_file_unittest.cc
+++ b/chromium/content/browser/download/download_file_unittest.cc
@@ -727,7 +727,7 @@ void TestRenameCompletionCallback(const base::Closure& closure,
} // namespace
// Test that the retry logic works. This test assumes that DownloadFileImpl will
-// post tasks to the current message loop (acting as the FILE thread)
+// post tasks to the current message loop (acting as the download sequence)
// asynchronously to retry the renames. We will stuff RunLoop::QuitClosures()
// in between the retry tasks to stagger them and then allow the rename to
// succeed.
diff --git a/chromium/content/browser/download/download_item_impl.cc b/chromium/content/browser/download/download_item_impl.cc
index a5d7db8cef5..ce19b3a69df 100644
--- a/chromium/content/browser/download/download_item_impl.cc
+++ b/chromium/content/browser/download/download_item_impl.cc
@@ -36,6 +36,7 @@
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/task_runner_util.h"
#include "content/browser/download/download_create_info.h"
#include "content/browser/download/download_file.h"
#include "content/browser/download/download_interrupt_reasons_impl.h"
@@ -45,6 +46,7 @@
#include "content/browser/download/download_net_log_parameters.h"
#include "content/browser/download/download_request_handle.h"
#include "content/browser/download/download_stats.h"
+#include "content/browser/download/download_task_runner.h"
#include "content/browser/download/parallel_download_utils.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
@@ -58,6 +60,7 @@
#include "content/public/common/content_features.h"
#include "content/public/common/referrer.h"
#include "net/http/http_response_headers.h"
+#include "net/http/http_status_code.h"
#include "net/log/net_log.h"
#include "net/log/net_log_event_type.h"
#include "net/log/net_log_parameters_callback.h"
@@ -69,7 +72,7 @@ namespace content {
namespace {
bool DeleteDownloadedFile(const base::FilePath& path) {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ DCHECK(GetDownloadTaskRunner()->RunsTasksInCurrentSequence());
// Make sure we only delete files.
if (base::DirectoryExists(path))
@@ -92,14 +95,14 @@ void DeleteDownloadedFileDone(
// at the end of the function.
static base::FilePath DownloadFileDetach(
std::unique_ptr<DownloadFile> download_file) {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ DCHECK(GetDownloadTaskRunner()->RunsTasksInCurrentSequence());
base::FilePath full_path = download_file->FullPath();
download_file->Detach();
return full_path;
}
static base::FilePath MakeCopyOfDownloadFile(DownloadFile* download_file) {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ DCHECK(GetDownloadTaskRunner()->RunsTasksInCurrentSequence());
base::FilePath temp_file_path;
if (base::CreateTemporaryFile(&temp_file_path) &&
base::CopyFile(download_file->FullPath(), temp_file_path)) {
@@ -114,7 +117,7 @@ static base::FilePath MakeCopyOfDownloadFile(DownloadFile* download_file) {
}
static void DownloadFileCancel(std::unique_ptr<DownloadFile> download_file) {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ DCHECK(GetDownloadTaskRunner()->RunsTasksInCurrentSequence());
download_file->Cancel();
}
@@ -232,7 +235,7 @@ DownloadItemImpl::DownloadItemImpl(
false,
std::string(),
start_time),
- guid_(base::ToUpperASCII(guid)),
+ guid_(guid),
download_id_(download_id),
mime_type_(mime_type),
original_mime_type_(original_mime_type),
@@ -255,6 +258,7 @@ DownloadItemImpl::DownloadItemImpl(
etag_(etag),
received_slices_(received_slices),
net_log_(net_log),
+ is_updating_observers_(false),
weak_ptr_factory_(this) {
delegate_->Attach();
DCHECK(state_ == COMPLETE_INTERNAL || state_ == INTERRUPTED_INTERNAL ||
@@ -280,8 +284,7 @@ DownloadItemImpl::DownloadItemImpl(DownloadItemImplDelegate* delegate,
info.has_user_gesture,
info.remote_address,
info.start_time),
- guid_(info.guid.empty() ? base::ToUpperASCII(base::GenerateGUID())
- : info.guid),
+ guid_(info.guid.empty() ? base::GenerateGUID() : info.guid),
download_id_(download_id),
response_headers_(info.response_headers),
content_disposition_(info.content_disposition),
@@ -300,6 +303,7 @@ DownloadItemImpl::DownloadItemImpl(DownloadItemImplDelegate* delegate,
last_modified_time_(info.last_modified),
etag_(info.etag),
net_log_(net_log),
+ is_updating_observers_(false),
weak_ptr_factory_(this) {
delegate_->Attach();
Init(true /* actively downloading */, SRC_ACTIVE_DOWNLOAD);
@@ -324,7 +328,7 @@ DownloadItemImpl::DownloadItemImpl(
std::unique_ptr<DownloadRequestHandleInterface> request_handle,
const net::NetLogWithSource& net_log)
: request_info_(url),
- guid_(base::ToUpperASCII(base::GenerateGUID())),
+ guid_(base::GenerateGUID()),
download_id_(download_id),
mime_type_(mime_type),
original_mime_type_(mime_type),
@@ -333,6 +337,7 @@ DownloadItemImpl::DownloadItemImpl(
delegate_(delegate),
destination_info_(path, path, 0, false, std::string(), base::Time()),
net_log_(net_log),
+ is_updating_observers_(false),
weak_ptr_factory_(this) {
job_ = DownloadJobFactory::CreateJob(this, std::move(request_handle),
DownloadCreateInfo(), true);
@@ -346,6 +351,7 @@ DownloadItemImpl::~DownloadItemImpl() {
// Should always have been nuked before now, at worst in
// DownloadManager shutdown.
DCHECK(!download_file_.get());
+ CHECK(!is_updating_observers_);
for (auto& observer : observers_)
observer.OnDownloadDestroyed(this);
@@ -369,8 +375,13 @@ void DownloadItemImpl::UpdateObservers() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DVLOG(20) << __func__ << "()";
+ // Nested updates should not be allowed.
+ DCHECK(!is_updating_observers_);
+
+ is_updating_observers_ = true;
for (auto& observer : observers_)
observer.OnDownloadUpdated(this);
+ is_updating_observers_ = false;
}
void DownloadItemImpl::ValidateDangerousDownload() {
@@ -409,8 +420,8 @@ void DownloadItemImpl::StealDangerousDownload(
if (delete_file_afterward) {
if (download_file_) {
- BrowserThread::PostTaskAndReplyWithResult(
- BrowserThread::FILE, FROM_HERE,
+ base::PostTaskAndReplyWithResult(
+ GetDownloadTaskRunner().get(), FROM_HERE,
base::Bind(&DownloadFileDetach, base::Passed(&download_file_)),
callback);
} else {
@@ -420,8 +431,8 @@ void DownloadItemImpl::StealDangerousDownload(
Remove();
// Download item has now been deleted.
} else if (download_file_) {
- BrowserThread::PostTaskAndReplyWithResult(
- BrowserThread::FILE, FROM_HERE,
+ base::PostTaskAndReplyWithResult(
+ GetDownloadTaskRunner().get(), FROM_HERE,
base::Bind(&MakeCopyOfDownloadFile, download_file_.get()), callback);
} else {
callback.Run(GetFullPath());
@@ -456,11 +467,11 @@ void DownloadItemImpl::Pause() {
job_->Pause();
UpdateObservers();
if (download_file_) {
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- base::Bind(&DownloadFile::WasPaused,
- // Safe because we control download file lifetime.
- base::Unretained(download_file_.get())));
+ GetDownloadTaskRunner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&DownloadFile::WasPaused,
+ // Safe because we control download file lifetime.
+ base::Unretained(download_file_.get())));
}
return;
@@ -752,20 +763,20 @@ void DownloadItemImpl::DeleteFile(const base::Callback<void(bool)>& callback) {
// Pass a null WeakPtr so it doesn't call OnDownloadedFileRemoved.
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&DeleteDownloadedFileDone,
- base::WeakPtr<DownloadItemImpl>(), callback, false));
+ base::BindOnce(&DeleteDownloadedFileDone,
+ base::WeakPtr<DownloadItemImpl>(), callback, false));
return;
}
if (GetFullPath().empty() || file_externally_removed_) {
// Pass a null WeakPtr so it doesn't call OnDownloadedFileRemoved.
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&DeleteDownloadedFileDone,
- base::WeakPtr<DownloadItemImpl>(), callback, true));
+ base::BindOnce(&DeleteDownloadedFileDone,
+ base::WeakPtr<DownloadItemImpl>(), callback, true));
return;
}
- BrowserThread::PostTaskAndReplyWithResult(
- BrowserThread::FILE, FROM_HERE,
+ base::PostTaskAndReplyWithResult(
+ GetDownloadTaskRunner().get(), FROM_HERE,
base::Bind(&DeleteDownloadedFile, GetFullPath()),
base::Bind(&DeleteDownloadedFileDone, weak_ptr_factory_.GetWeakPtr(),
callback));
@@ -1116,7 +1127,8 @@ void DownloadItemImpl::UpdateValidatorsOnResumption(
}
if (content_disposition_ != new_create_info.content_disposition)
origin_state |= ORIGIN_STATE_ON_RESUMPTION_CONTENT_DISPOSITION_CHANGED;
- RecordOriginStateOnResumption(is_partial, origin_state);
+ RecordOriginStateOnResumption(
+ is_partial, static_cast<OriginStateOnResumption>(origin_state));
request_info_.url_chain.insert(request_info_.url_chain.end(), chain_iter,
new_create_info.url_chain.end());
@@ -1377,9 +1389,9 @@ void DownloadItemImpl::Start(
if (state_ == RESUMING_INTERNAL)
UpdateValidatorsOnResumption(new_create_info);
- // If the download uses parallel requests, and choose not to create parallel
- // request during resumption, clear the received_slices_ vector.
- if (!IsParallelDownloadEnabled() && !received_slices_.empty()) {
+ // If the download is not parallel download during resumption, clear the
+ // |received_slices_|.
+ if (!job_->IsParallelizable() && !received_slices_.empty()) {
destination_info_.received_bytes =
GetMaxContiguousDataBlockSizeFromBeginning(received_slices_);
received_slices_.clear();
@@ -1494,12 +1506,12 @@ void DownloadItemImpl::OnDownloadTargetDetermined(
DownloadFile::RenameCompletionCallback callback =
base::Bind(&DownloadItemImpl::OnDownloadRenamedToIntermediateName,
weak_ptr_factory_.GetWeakPtr());
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- base::Bind(&DownloadFile::RenameAndUniquify,
- // Safe because we control download file lifetime.
- base::Unretained(download_file_.get()),
- intermediate_path, callback));
+ GetDownloadTaskRunner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&DownloadFile::RenameAndUniquify,
+ // Safe because we control download file lifetime.
+ base::Unretained(download_file_.get()), intermediate_path,
+ callback));
}
void DownloadItemImpl::OnDownloadRenamedToIntermediateName(
@@ -1605,16 +1617,13 @@ void DownloadItemImpl::OnDownloadCompleting() {
DownloadFile::RenameCompletionCallback callback =
base::Bind(&DownloadItemImpl::OnDownloadRenamedToFinalName,
weak_ptr_factory_.GetWeakPtr());
- BrowserThread::PostTask(
- BrowserThread::FILE,
+ GetDownloadTaskRunner()->PostTask(
FROM_HERE,
- base::Bind(&DownloadFile::RenameAndAnnotate,
- base::Unretained(download_file_.get()),
- GetTargetFilePath(),
- delegate_->GetApplicationClientIdForFileScanning(),
- GetURL(),
- GetReferrerUrl(),
- callback));
+ base::BindOnce(&DownloadFile::RenameAndAnnotate,
+ base::Unretained(download_file_.get()),
+ GetTargetFilePath(),
+ delegate_->GetApplicationClientIdForFileScanning(),
+ GetURL(), GetReferrerUrl(), callback));
}
void DownloadItemImpl::OnDownloadRenamedToFinalName(
@@ -1691,6 +1700,17 @@ void DownloadItemImpl::Completed() {
if (job_ && job_->IsParallelizable()) {
RecordParallelizableDownloadCount(COMPLETED_COUNT,
IsParallelDownloadEnabled());
+ int64_t content_length = -1;
+ if (response_headers_->response_code() != net::HTTP_PARTIAL_CONTENT) {
+ content_length = response_headers_->GetContentLength();
+ } else {
+ int64_t first_byte = -1;
+ int64_t last_byte = -1;
+ response_headers_->GetContentRangeFor206(&first_byte, &last_byte,
+ &content_length);
+ }
+ if (content_length > 0)
+ RecordParallelizableContentLength(content_length);
}
if (auto_opened_) {
@@ -1796,10 +1816,9 @@ void DownloadItemImpl::InterruptWithPartialState(
// There is no download file and this is transitioning from INTERRUPTED
// to CANCELLED. The intermediate file is no longer usable, and should
// be deleted.
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- base::Bind(base::IgnoreResult(&DeleteDownloadedFile),
- GetFullPath()));
+ GetDownloadTaskRunner()->PostTask(
+ FROM_HERE, base::BindOnce(base::IgnoreResult(&DeleteDownloadedFile),
+ GetFullPath()));
destination_info_.current_path.clear();
}
break;
@@ -1896,21 +1915,19 @@ void DownloadItemImpl::ReleaseDownloadFile(bool destroy_file) {
DVLOG(20) << __func__ << "() destroy_file:" << destroy_file;
if (destroy_file) {
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
+ GetDownloadTaskRunner()->PostTask(
+ FROM_HERE,
// Will be deleted at end of task execution.
- base::Bind(&DownloadFileCancel, base::Passed(&download_file_)));
+ base::BindOnce(&DownloadFileCancel, base::Passed(&download_file_)));
// Avoid attempting to reuse the intermediate file by clearing out
// current_path_ and received slices.
destination_info_.current_path.clear();
received_slices_.clear();
} else {
- BrowserThread::PostTask(
- BrowserThread::FILE,
- FROM_HERE,
- base::Bind(base::IgnoreResult(&DownloadFileDetach),
- // Will be deleted at end of task execution.
- base::Passed(&download_file_)));
+ GetDownloadTaskRunner()->PostTask(
+ FROM_HERE, base::BindOnce(base::IgnoreResult(&DownloadFileDetach),
+ // Will be deleted at end of task execution.
+ base::Passed(&download_file_)));
}
// Don't accept any more messages from the DownloadFile, and null
// out any previous "all data received". This also breaks links to
@@ -2152,7 +2169,7 @@ void DownloadItemImpl::ResumeInterruptedDownload(
destination: WEBSITE
}
policy {
- cookies_allowed: true
+ cookies_allowed: YES
cookies_store: "user"
setting:
"This feature cannot be disabled in settings, but it is activated "
diff --git a/chromium/content/browser/download/download_item_impl.h b/chromium/content/browser/download/download_item_impl.h
index 6d91f344d12..88b917912e2 100644
--- a/chromium/content/browser/download/download_item_impl.h
+++ b/chromium/content/browser/download/download_item_impl.h
@@ -628,6 +628,12 @@ class CONTENT_EXPORT DownloadItemImpl
RequestInfo request_info_;
+ // GUID to identify the download, generated by |base::GenerateGUID| in
+ // download item, or provided by |DownloadUrlParameters|.
+ // The format should follow UUID version 4 in RFC 4122.
+ // The string representation is case sensitive. Legacy download GUID hex
+ // digits may be upper case ASCII characters, and new GUID will be in lower
+ // case.
std::string guid_;
uint32_t download_id_ = kInvalidId;
@@ -712,7 +718,7 @@ class CONTENT_EXPORT DownloadItemImpl
// The following fields describe the current state of the download file.
// DownloadFile associated with this download. Note that this
- // pointer may only be used or destroyed on the FILE thread.
+ // pointer may only be used or destroyed on the download sequence.
// This pointer will be non-null only while the DownloadItem is in
// the IN_PROGRESS state.
std::unique_ptr<DownloadFile> download_file_;
@@ -750,6 +756,9 @@ class CONTENT_EXPORT DownloadItemImpl
// CONTENT_LENGTH_MISMATCH.
int64_t received_bytes_at_length_mismatch_ = -1;
+ // Check whether the download item is updating its observers.
+ bool is_updating_observers_;
+
base::WeakPtrFactory<DownloadItemImpl> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(DownloadItemImpl);
diff --git a/chromium/content/browser/download/download_item_impl_unittest.cc b/chromium/content/browser/download/download_item_impl_unittest.cc
index 4431bdd4c00..37d44531628 100644
--- a/chromium/content/browser/download/download_item_impl_unittest.cc
+++ b/chromium/content/browser/download/download_item_impl_unittest.cc
@@ -19,8 +19,7 @@
#include "base/feature_list.h"
#include "base/files/file_util.h"
#include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop.h"
-#include "base/run_loop.h"
+#include "base/test/scoped_task_environment.h"
#include "base/threading/thread.h"
#include "content/browser/byte_stream.h"
#include "content/browser/download/download_create_info.h"
@@ -36,6 +35,7 @@
#include "content/public/test/mock_download_item.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/public/test/web_contents_tester.h"
#include "crypto/secure_hash.h"
#include "net/http/http_response_headers.h"
@@ -206,7 +206,7 @@ class TestDownloadItemObserver : public DownloadItem::Observer {
// DOWNLOAD_INTERRUPT_REASON_NONE, new_path));
ACTION_P2(ScheduleRenameAndUniquifyCallback, interrupt_reason, new_path) {
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(arg1, interrupt_reason, new_path));
+ base::BindOnce(arg1, interrupt_reason, new_path));
}
// Schedules a task to invoke the RenameCompletionCallback with |new_path| on
@@ -216,9 +216,8 @@ ACTION_P2(ScheduleRenameAndUniquifyCallback, interrupt_reason, new_path) {
// .WillOnce(ScheduleRenameAndAnnotateCallback(
// DOWNLOAD_INTERRUPT_REASON_NONE, new_path));
ACTION_P2(ScheduleRenameAndAnnotateCallback, interrupt_reason, new_path) {
- BrowserThread::PostTask(BrowserThread::UI,
- FROM_HERE,
- base::Bind(arg4, interrupt_reason, new_path));
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::BindOnce(arg4, interrupt_reason, new_path));
}
// Schedules a task to invoke a callback that's bound to the specified
@@ -231,7 +230,7 @@ ACTION_P2(ScheduleRenameAndAnnotateCallback, interrupt_reason, new_path) {
// .. will invoke the second argument to Bar with 0 as the parameter.
ACTION_P(ScheduleCallbackWithParam, param) {
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(arg0, param));
+ base::BindOnce(arg0, param));
}
// Schedules a task to invoke a closure.
@@ -258,7 +257,10 @@ const uint8_t kHashOfTestData1[] = {
class DownloadItemTest : public testing::Test {
public:
DownloadItemTest()
- : delegate_(), next_download_id_(DownloadItem::kInvalidId + 1) {
+ : task_environment_(
+ base::test::ScopedTaskEnvironment::MainThreadType::UI,
+ base::test::ScopedTaskEnvironment::ExecutionMode::QUEUED),
+ next_download_id_(DownloadItem::kInvalidId + 1) {
create_info_.reset(new DownloadCreateInfo());
create_info_->save_info =
std::unique_ptr<DownloadSaveInfo>(new DownloadSaveInfo());
@@ -267,15 +269,11 @@ class DownloadItemTest : public testing::Test {
create_info_->etag = "SomethingToSatisfyResumption";
}
- ~DownloadItemTest() {
- RunAllPendingInMessageLoops();
- }
-
DownloadItemImpl* CreateDownloadItemWithCreateInfo(
std::unique_ptr<DownloadCreateInfo> info) {
DownloadItemImpl* download =
- new DownloadItemImpl(&delegate_, next_download_id_++, *(info.get()),
- net::NetLogWithSource());
+ new DownloadItemImpl(mock_delegate(), next_download_id_++,
+ *(info.get()), net::NetLogWithSource());
allocated_downloads_[download] = base::WrapUnique(download);
return download;
}
@@ -293,7 +291,7 @@ class DownloadItemTest : public testing::Test {
DownloadItemImpl* CreateDownloadItem() {
create_info_->download_id = ++next_download_id_;
DownloadItemImpl* download =
- new DownloadItemImpl(&delegate_, create_info_->download_id,
+ new DownloadItemImpl(mock_delegate(), create_info_->download_id,
*create_info_, net::NetLogWithSource());
allocated_downloads_[download] = base::WrapUnique(download);
return download;
@@ -321,7 +319,7 @@ class DownloadItemTest : public testing::Test {
base::MakeUnique<NiceMock<MockRequestHandle>>();
item->Start(std::move(download_file), std::move(request_handle),
*create_info_);
- RunAllPendingInMessageLoops();
+ task_environment_.RunUntilIdle();
// So that we don't have a function writing to a stack variable
// lying around if the above failed.
@@ -353,7 +351,7 @@ class DownloadItemTest : public testing::Test {
callback.Run(target_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE,
danger_type, intermediate_path,
DOWNLOAD_INTERRUPT_REASON_NONE);
- RunAllPendingInMessageLoops();
+ task_environment_.RunUntilIdle();
return download_file;
}
@@ -371,7 +369,7 @@ class DownloadItemTest : public testing::Test {
item->DestinationObserverAsWeakPtr()->DestinationCompleted(
0, std::unique_ptr<crypto::SecureHash>());
- RunAllPendingInMessageLoops();
+ task_environment_.RunUntilIdle();
}
// Cleanup a download item (specifically get rid of the DownloadFile on it).
@@ -385,7 +383,7 @@ class DownloadItemTest : public testing::Test {
if (download_file)
EXPECT_CALL(*download_file, Cancel());
item->Cancel(true);
- RunAllPendingInMessageLoops();
+ task_environment_.RunUntilIdle();
}
}
@@ -394,11 +392,7 @@ class DownloadItemTest : public testing::Test {
allocated_downloads_.erase(item);
}
- void RunAllPendingInMessageLoops() { base::RunLoop().RunUntilIdle(); }
-
- MockDelegate* mock_delegate() {
- return &delegate_;
- }
+ MockDelegate* mock_delegate() { return &mock_delegate_; }
void OnDownloadFileAcquired(base::FilePath* return_path,
const base::FilePath& path) {
@@ -409,9 +403,11 @@ class DownloadItemTest : public testing::Test {
BrowserContext* browser_context() { return &browser_context_; }
+ base::test::ScopedTaskEnvironment task_environment_;
+
private:
TestBrowserThreadBundle thread_bundle_;
- StrictMock<MockDelegate> delegate_;
+ StrictMock<MockDelegate> mock_delegate_;
std::map<DownloadItem*, std::unique_ptr<DownloadItem>> allocated_downloads_;
std::unique_ptr<DownloadCreateInfo> create_info_;
uint32_t next_download_id_ = DownloadItem::kInvalidId + 1;
@@ -591,7 +587,7 @@ TEST_F(DownloadItemTest, NotificationAfterOnDownloadTargetDetermined) {
DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, intermediate_path,
DOWNLOAD_INTERRUPT_REASON_NONE);
EXPECT_FALSE(observer.CheckAndResetDownloadUpdated());
- RunAllPendingInMessageLoops();
+ task_environment_.RunUntilIdle();
EXPECT_TRUE(observer.CheckAndResetDownloadUpdated());
EXPECT_EQ(new_intermediate_path, item->GetFullPath());
@@ -619,7 +615,7 @@ TEST_F(DownloadItemTest, NotificationAfterTogglePause) {
item->Resume();
ASSERT_TRUE(observer.CheckAndResetDownloadUpdated());
- RunAllPendingInMessageLoops();
+ task_environment_.RunUntilIdle();
CleanupItem(item, mock_download_file, DownloadItem::IN_PROGRESS);
}
@@ -662,7 +658,7 @@ TEST_F(DownloadItemTest, AutomaticResumption_Continue) {
// the mock doesn't follow through with the resumption.
// ResumeInterruptedDownload() being called is sufficient for verifying that
// the automatic resumption was triggered.
- RunAllPendingInMessageLoops();
+ task_environment_.RunUntilIdle();
// The download item is currently in RESUMING_INTERNAL state, which maps to
// IN_PROGRESS.
@@ -696,7 +692,7 @@ TEST_F(DownloadItemTest, AutomaticResumption_Restart) {
// Since the download is resumed automatically, the interrupt count doesn't
// increase.
ASSERT_EQ(0, observer.interrupt_count());
- RunAllPendingInMessageLoops();
+ task_environment_.RunUntilIdle();
CleanupItem(item, nullptr, DownloadItem::IN_PROGRESS);
}
@@ -718,7 +714,7 @@ TEST_F(DownloadItemTest, AutomaticResumption_NeedsUserAction) {
// Should not try to auto-resume.
ASSERT_EQ(1, observer.interrupt_count());
ASSERT_EQ(0, observer.resume_count());
- RunAllPendingInMessageLoops();
+ task_environment_.RunUntilIdle();
CleanupItem(item, nullptr, DownloadItem::INTERRUPTED);
}
@@ -757,7 +753,7 @@ TEST_F(DownloadItemTest, AutomaticResumption_ContentLengthMismatch) {
ASSERT_EQ(0, observer.interrupt_count());
ASSERT_EQ(0, observer.resume_count());
- RunAllPendingInMessageLoops();
+ task_environment_.RunUntilIdle();
CleanupItem(item, nullptr, DownloadItem::IN_PROGRESS);
}
@@ -780,7 +776,7 @@ TEST_F(DownloadItemTest, UnresumableInterrupt) {
// Complete download to trigger final rename.
item->DestinationObserverAsWeakPtr()->DestinationCompleted(
0, std::unique_ptr<crypto::SecureHash>());
- RunAllPendingInMessageLoops();
+ task_environment_.RunUntilIdle();
ASSERT_TRUE(observer.CheckAndResetDownloadUpdated());
// Should not try to auto-resume.
@@ -826,7 +822,7 @@ TEST_F(DownloadItemTest, AutomaticResumption_AttemptLimit) {
// to allow for holding onto the request handle.
item->Start(std::move(mock_download_file), std::move(mock_request_handle),
*create_info());
- RunAllPendingInMessageLoops();
+ task_environment_.RunUntilIdle();
base::FilePath target_path(kDummyTargetPath);
base::FilePath intermediate_path(kDummyIntermediatePath);
@@ -846,7 +842,7 @@ TEST_F(DownloadItemTest, AutomaticResumption_AttemptLimit) {
target_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE,
DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, intermediate_path,
DOWNLOAD_INTERRUPT_REASON_NONE);
- RunAllPendingInMessageLoops();
+ task_environment_.RunUntilIdle();
// Use a continuable interrupt.
EXPECT_CALL(*mock_download_file_ref, Cancel()).Times(0);
@@ -854,7 +850,7 @@ TEST_F(DownloadItemTest, AutomaticResumption_AttemptLimit) {
DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR, 1,
std::unique_ptr<crypto::SecureHash>());
- RunAllPendingInMessageLoops();
+ task_environment_.RunUntilIdle();
::testing::Mock::VerifyAndClearExpectations(mock_download_file_ref);
}
@@ -902,7 +898,7 @@ TEST_F(DownloadItemTest, FailedResumptionDoesntUpdateOriginState) {
item->DestinationObserverAsWeakPtr()->DestinationError(
DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR, 1,
std::unique_ptr<crypto::SecureHash>());
- RunAllPendingInMessageLoops();
+ task_environment_.RunUntilIdle();
EXPECT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
// Now change the create info. The changes should not cause the DownloadItem
@@ -934,7 +930,7 @@ TEST_F(DownloadItemTest, FailedResumptionDoesntUpdateOriginState) {
DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
base::FilePath(kDummyIntermediatePath),
DOWNLOAD_INTERRUPT_REASON_NONE);
- RunAllPendingInMessageLoops();
+ task_environment_.RunUntilIdle();
ASSERT_TRUE(item->GetResponseHeaders());
EXPECT_EQ(kFirstResponseCode, item->GetResponseHeaders()->response_code());
@@ -973,7 +969,7 @@ TEST_F(DownloadItemTest, SucceededResumptionUpdatesOriginState) {
item->DestinationObserverAsWeakPtr()->DestinationError(
DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR, 0,
std::unique_ptr<crypto::SecureHash>());
- RunAllPendingInMessageLoops();
+ task_environment_.RunUntilIdle();
EXPECT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
// Now change the create info. The changes should not cause the DownloadItem
@@ -1032,7 +1028,7 @@ TEST_F(DownloadItemTest, ClearReceivedSliceIfEtagChanged) {
std::unique_ptr<crypto::SecureHash>());
EXPECT_EQ(kReceivedSlice, item->GetReceivedSlices());
- RunAllPendingInMessageLoops();
+ task_environment_.RunUntilIdle();
// Change the strong validator and resume the download, the received slices
// should be cleared.
@@ -1076,7 +1072,7 @@ TEST_F(DownloadItemTest, ResumeUsesFinalURL) {
// the mock doesn't follow through with the resumption.
// ResumeInterruptedDownload() being called is sufficient for verifying that
// the resumption was triggered.
- RunAllPendingInMessageLoops();
+ task_environment_.RunUntilIdle();
// The download is currently in RESUMING_INTERNAL, which maps to IN_PROGRESS.
CleanupItem(item, nullptr, DownloadItem::IN_PROGRESS);
@@ -1097,7 +1093,7 @@ TEST_F(DownloadItemTest, DisplayName) {
callback.Run(target_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE,
DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, intermediate_path,
DOWNLOAD_INTERRUPT_REASON_NONE);
- RunAllPendingInMessageLoops();
+ task_environment_.RunUntilIdle();
EXPECT_EQ(FILE_PATH_LITERAL("foo.bar"),
item->GetFileNameToReportUser().value());
item->SetDisplayName(base::FilePath(FILE_PATH_LITERAL("new.name")));
@@ -1117,7 +1113,7 @@ TEST_F(DownloadItemTest, Start) {
EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(item, _));
item->Start(std::move(download_file), std::move(request_handle),
*create_info());
- RunAllPendingInMessageLoops();
+ task_environment_.RunUntilIdle();
CleanupItem(item, mock_download_file, DownloadItem::IN_PROGRESS);
}
@@ -1136,21 +1132,19 @@ TEST_F(DownloadItemTest, InitDownloadFileFails) {
.WillOnce(ScheduleCallbackWithParam(
DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED));
- base::RunLoop start_download_loop;
DownloadTargetCallback download_target_callback;
EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(item, _))
- .WillOnce(DoAll(SaveArg<1>(&download_target_callback),
- ScheduleClosure(start_download_loop.QuitClosure())));
+ .WillOnce(SaveArg<1>(&download_target_callback));
item->Start(std::move(file), std::move(request_handle), *create_info());
- start_download_loop.Run();
+ task_environment_.RunUntilIdle();
download_target_callback.Run(base::FilePath(kDummyTargetPath),
DownloadItem::TARGET_DISPOSITION_OVERWRITE,
DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
base::FilePath(kDummyIntermediatePath),
DOWNLOAD_INTERRUPT_REASON_NONE);
- RunAllPendingInMessageLoops();
+ task_environment_.RunUntilIdle();
EXPECT_EQ(DownloadItem::INTERRUPTED, item->GetState());
EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED,
@@ -1175,7 +1169,7 @@ TEST_F(DownloadItemTest, StartFailedDownload) {
item->Start(std::move(null_download_file), std::move(null_request_handle),
*create_info());
EXPECT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
- RunAllPendingInMessageLoops();
+ task_environment_.RunUntilIdle();
// The DownloadItemImpl should attempt to determine a target path even if the
// download was interrupted.
@@ -1186,7 +1180,7 @@ TEST_F(DownloadItemTest, StartFailedDownload) {
DownloadItem::TARGET_DISPOSITION_OVERWRITE,
DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, target_path,
DOWNLOAD_INTERRUPT_REASON_NONE);
- RunAllPendingInMessageLoops();
+ task_environment_.RunUntilIdle();
EXPECT_EQ(target_path, item->GetTargetFilePath());
CleanupItem(item, NULL, DownloadItem::INTERRUPTED);
@@ -1209,7 +1203,7 @@ TEST_F(DownloadItemTest, CallbackAfterRename) {
callback.Run(final_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE,
DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, intermediate_path,
DOWNLOAD_INTERRUPT_REASON_NONE);
- RunAllPendingInMessageLoops();
+ task_environment_.RunUntilIdle();
// All the callbacks should have happened by now.
::testing::Mock::VerifyAndClearExpectations(download_file);
mock_delegate()->VerifyAndClearExpectations();
@@ -1224,7 +1218,7 @@ TEST_F(DownloadItemTest, CallbackAfterRename) {
EXPECT_CALL(*download_file, Detach());
item->DestinationObserverAsWeakPtr()->DestinationCompleted(
0, std::unique_ptr<crypto::SecureHash>());
- RunAllPendingInMessageLoops();
+ task_environment_.RunUntilIdle();
::testing::Mock::VerifyAndClearExpectations(download_file);
mock_delegate()->VerifyAndClearExpectations();
}
@@ -1249,7 +1243,7 @@ TEST_F(DownloadItemTest, CallbackAfterInterruptedRename) {
callback.Run(final_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE,
DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, intermediate_path,
DOWNLOAD_INTERRUPT_REASON_NONE);
- RunAllPendingInMessageLoops();
+ task_environment_.RunUntilIdle();
// All the callbacks should have happened by now.
::testing::Mock::VerifyAndClearExpectations(download_file);
mock_delegate()->VerifyAndClearExpectations();
@@ -1267,7 +1261,7 @@ TEST_F(DownloadItemTest, Interrupted) {
EXPECT_CALL(*download_file, Cancel());
item->DestinationObserverAsWeakPtr()->DestinationError(
reason, 0, std::unique_ptr<crypto::SecureHash>());
- RunAllPendingInMessageLoops();
+ task_environment_.RunUntilIdle();
EXPECT_EQ(DownloadItem::INTERRUPTED, item->GetState());
EXPECT_EQ(reason, item->GetLastReason());
@@ -1302,7 +1296,7 @@ TEST_F(DownloadItemTest, InterruptedBeforeIntermediateRename_Restart) {
callback.Run(final_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE,
DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, intermediate_path,
DOWNLOAD_INTERRUPT_REASON_NONE);
- RunAllPendingInMessageLoops();
+ task_environment_.RunUntilIdle();
// All the callbacks should have happened by now.
::testing::Mock::VerifyAndClearExpectations(download_file);
mock_delegate()->VerifyAndClearExpectations();
@@ -1341,7 +1335,7 @@ TEST_F(DownloadItemTest, InterruptedBeforeIntermediateRename_Continue) {
callback.Run(final_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE,
DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, intermediate_path,
DOWNLOAD_INTERRUPT_REASON_NONE);
- RunAllPendingInMessageLoops();
+ task_environment_.RunUntilIdle();
// All the callbacks should have happened by now.
::testing::Mock::VerifyAndClearExpectations(download_file);
mock_delegate()->VerifyAndClearExpectations();
@@ -1375,7 +1369,7 @@ TEST_F(DownloadItemTest, InterruptedBeforeIntermediateRename_Failed) {
callback.Run(final_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE,
DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, intermediate_path,
DOWNLOAD_INTERRUPT_REASON_NONE);
- RunAllPendingInMessageLoops();
+ task_environment_.RunUntilIdle();
// All the callbacks should have happened by now.
::testing::Mock::VerifyAndClearExpectations(download_file);
mock_delegate()->VerifyAndClearExpectations();
@@ -1598,7 +1592,7 @@ TEST_F(DownloadItemTest, EnabledActionsForNormalDownload) {
EXPECT_CALL(*download_file, Detach());
item->DestinationObserverAsWeakPtr()->DestinationCompleted(
0, std::unique_ptr<crypto::SecureHash>());
- RunAllPendingInMessageLoops();
+ task_environment_.RunUntilIdle();
ASSERT_EQ(DownloadItem::COMPLETE, item->GetState());
EXPECT_TRUE(item->CanShowInFolder());
@@ -1631,7 +1625,7 @@ TEST_F(DownloadItemTest, EnabledActionsForTemporaryDownload) {
EXPECT_CALL(*download_file, Detach());
item->DestinationObserverAsWeakPtr()->DestinationCompleted(
0, std::unique_ptr<crypto::SecureHash>());
- RunAllPendingInMessageLoops();
+ task_environment_.RunUntilIdle();
ASSERT_EQ(DownloadItem::COMPLETE, item->GetState());
EXPECT_FALSE(item->CanShowInFolder());
@@ -1647,7 +1641,7 @@ TEST_F(DownloadItemTest, EnabledActionsForInterruptedDownload) {
item->DestinationObserverAsWeakPtr()->DestinationError(
DOWNLOAD_INTERRUPT_REASON_FILE_FAILED, 0,
std::unique_ptr<crypto::SecureHash>());
- RunAllPendingInMessageLoops();
+ task_environment_.RunUntilIdle();
ASSERT_EQ(DownloadItem::INTERRUPTED, item->GetState());
ASSERT_FALSE(item->GetTargetFilePath().empty());
@@ -1662,7 +1656,7 @@ TEST_F(DownloadItemTest, EnabledActionsForCancelledDownload) {
EXPECT_CALL(*download_file, Cancel());
item->Cancel(true);
- RunAllPendingInMessageLoops();
+ task_environment_.RunUntilIdle();
ASSERT_EQ(DownloadItem::CANCELLED, item->GetState());
EXPECT_FALSE(item->CanShowInFolder());
@@ -1697,7 +1691,7 @@ TEST_F(DownloadItemTest, CompleteDelegate_ReturnTrue) {
EXPECT_CALL(*download_file, FullPath())
.WillOnce(ReturnRefOfCopy(base::FilePath()));
EXPECT_CALL(*download_file, Detach());
- RunAllPendingInMessageLoops();
+ task_environment_.RunUntilIdle();
EXPECT_EQ(DownloadItem::COMPLETE, item->GetState());
}
@@ -1705,11 +1699,11 @@ TEST_F(DownloadItemTest, CompleteDelegate_ReturnTrue) {
TEST_F(DownloadItemTest, CompleteDelegate_BlockOnce) {
// Test to confirm that if we have a callback that returns true,
// we complete immediately.
+
DownloadItemImpl* item = CreateDownloadItem();
MockDownloadFile* download_file =
DoIntermediateRename(item, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
- // Drive the delegate interaction.
base::Closure delegate_callback;
base::Closure copy_delegate_callback;
EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(item, _))
@@ -1737,7 +1731,7 @@ TEST_F(DownloadItemTest, CompleteDelegate_BlockOnce) {
EXPECT_CALL(*download_file, FullPath())
.WillOnce(ReturnRefOfCopy(base::FilePath()));
EXPECT_CALL(*download_file, Detach());
- RunAllPendingInMessageLoops();
+ task_environment_.RunUntilIdle();
EXPECT_EQ(DownloadItem::COMPLETE, item->GetState());
}
@@ -1780,13 +1774,13 @@ TEST_F(DownloadItemTest, CompleteDelegate_SetDanger) {
EXPECT_CALL(*download_file, FullPath())
.WillOnce(ReturnRefOfCopy(base::FilePath()));
EXPECT_CALL(*download_file, Detach());
- RunAllPendingInMessageLoops();
+ task_environment_.RunUntilIdle();
EXPECT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
EXPECT_TRUE(item->IsDangerous());
item->ValidateDangerousDownload();
EXPECT_EQ(DOWNLOAD_DANGER_TYPE_USER_VALIDATED, item->GetDangerType());
- RunAllPendingInMessageLoops();
+ task_environment_.RunUntilIdle();
EXPECT_EQ(DownloadItem::COMPLETE, item->GetState());
}
@@ -1833,7 +1827,7 @@ TEST_F(DownloadItemTest, CompleteDelegate_BlockTwice) {
EXPECT_CALL(*download_file, FullPath())
.WillOnce(ReturnRefOfCopy(base::FilePath()));
EXPECT_CALL(*download_file, Detach());
- RunAllPendingInMessageLoops();
+ task_environment_.RunUntilIdle();
EXPECT_EQ(DownloadItem::COMPLETE, item->GetState());
}
@@ -1855,7 +1849,7 @@ TEST_F(DownloadItemTest, StealDangerousDownloadAndDiscard) {
base::Bind(&DownloadItemTest::OnDownloadFileAcquired,
weak_ptr_factory.GetWeakPtr(),
base::Unretained(&returned_path)));
- RunAllPendingInMessageLoops();
+ task_environment_.RunUntilIdle();
EXPECT_EQ(full_path, returned_path);
}
@@ -1874,7 +1868,7 @@ TEST_F(DownloadItemTest, StealDangerousDownloadAndKeep) {
base::Bind(&DownloadItemTest::OnDownloadFileAcquired,
weak_ptr_factory.GetWeakPtr(),
base::Unretained(&returned_path)));
- RunAllPendingInMessageLoops();
+ task_environment_.RunUntilIdle();
EXPECT_NE(full_path, returned_path);
CleanupItem(item, download_file, DownloadItem::IN_PROGRESS);
}
@@ -1900,7 +1894,7 @@ TEST_F(DownloadItemTest, StealInterruptedContinuableDangerousDownload) {
true, base::Bind(&DownloadItemTest::OnDownloadFileAcquired,
weak_ptr_factory.GetWeakPtr(),
base::Unretained(&returned_path)));
- RunAllPendingInMessageLoops();
+ task_environment_.RunUntilIdle();
EXPECT_EQ(full_path, returned_path);
}
@@ -1922,7 +1916,7 @@ TEST_F(DownloadItemTest, StealInterruptedNonContinuableDangerousDownload) {
true, base::Bind(&DownloadItemTest::OnDownloadFileAcquired,
weak_ptr_factory.GetWeakPtr(),
base::Unretained(&returned_path)));
- RunAllPendingInMessageLoops();
+ task_environment_.RunUntilIdle();
EXPECT_TRUE(returned_path.empty());
}
@@ -2138,7 +2132,7 @@ class DownloadItemDestinationUpdateRaceTest
base::WeakPtr<DownloadDestinationObserver> observer) {
for (const auto action : observations)
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(action, observer));
+ base::BindOnce(action, observer));
}
DownloadItemImpl* item_;
@@ -2167,31 +2161,25 @@ TEST_P(DownloadItemDestinationUpdateRaceTest, DownloadCancelledByUser) {
EXPECT_CALL(*file_, Cancel());
EXPECT_CALL(*request_handle_, CancelRequest(_));
- base::RunLoop download_start_loop;
DownloadFile::InitializeCallback initialize_callback;
EXPECT_CALL(*file_, Initialize(_, _, _, _))
- .WillOnce(DoAll(SaveArg<0>(&initialize_callback),
- ScheduleClosure(download_start_loop.QuitClosure())));
+ .WillOnce(SaveArg<0>(&initialize_callback));
item_->Start(std::move(file_), std::move(request_handle_), *create_info());
- download_start_loop.Run();
+ task_environment_.RunUntilIdle();
base::WeakPtr<DownloadDestinationObserver> destination_observer =
item_->DestinationObserverAsWeakPtr();
ScheduleObservations(PreInitializeFileObservations(), destination_observer);
- RunAllPendingInMessageLoops();
+ task_environment_.RunUntilIdle();
- base::RunLoop initialize_completion_loop;
DownloadTargetCallback target_callback;
EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(_, _))
- .WillOnce(
- DoAll(SaveArg<1>(&target_callback),
- ScheduleClosure(initialize_completion_loop.QuitClosure())));
+ .WillOnce(SaveArg<1>(&target_callback));
ScheduleObservations(PostInitializeFileObservations(), destination_observer);
initialize_callback.Run(DOWNLOAD_INTERRUPT_REASON_NONE);
- initialize_completion_loop.Run();
- RunAllPendingInMessageLoops();
+ task_environment_.RunUntilIdle();
ASSERT_FALSE(target_callback.is_null());
ScheduleObservations(PostTargetDeterminationObservations(),
@@ -2201,7 +2189,7 @@ TEST_P(DownloadItemDestinationUpdateRaceTest, DownloadCancelledByUser) {
DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, base::FilePath(),
DOWNLOAD_INTERRUPT_REASON_NONE);
EXPECT_EQ(DownloadItem::CANCELLED, item_->GetState());
- RunAllPendingInMessageLoops();
+ task_environment_.RunUntilIdle();
}
// Run through the DII workflow, but the intermediate rename fails.
@@ -2214,37 +2202,30 @@ TEST_P(DownloadItemDestinationUpdateRaceTest, IntermediateRenameFails) {
// Intermediate rename loop is not used immediately, but let's set up the
// DownloadFile expectations since we are about to transfer its ownership to
// the DownloadItem.
- base::RunLoop intermediate_rename_loop;
DownloadFile::RenameCompletionCallback intermediate_rename_callback;
EXPECT_CALL(*file_, RenameAndUniquify(_, _))
- .WillOnce(DoAll(SaveArg<1>(&intermediate_rename_callback),
- ScheduleClosure(intermediate_rename_loop.QuitClosure())));
+ .WillOnce(SaveArg<1>(&intermediate_rename_callback));
- base::RunLoop download_start_loop;
DownloadFile::InitializeCallback initialize_callback;
EXPECT_CALL(*file_, Initialize(_, _, _, _))
- .WillOnce(DoAll(SaveArg<0>(&initialize_callback),
- ScheduleClosure(download_start_loop.QuitClosure())));
+ .WillOnce(SaveArg<0>(&initialize_callback));
item_->Start(std::move(file_), std::move(request_handle_), *create_info());
- download_start_loop.Run();
+ task_environment_.RunUntilIdle();
+
base::WeakPtr<DownloadDestinationObserver> destination_observer =
item_->DestinationObserverAsWeakPtr();
ScheduleObservations(PreInitializeFileObservations(), destination_observer);
- RunAllPendingInMessageLoops();
+ task_environment_.RunUntilIdle();
- base::RunLoop initialize_completion_loop;
DownloadTargetCallback target_callback;
EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(_, _))
- .WillOnce(
- DoAll(SaveArg<1>(&target_callback),
- ScheduleClosure(initialize_completion_loop.QuitClosure())));
+ .WillOnce(SaveArg<1>(&target_callback));
ScheduleObservations(PostInitializeFileObservations(), destination_observer);
initialize_callback.Run(DOWNLOAD_INTERRUPT_REASON_NONE);
- initialize_completion_loop.Run();
- RunAllPendingInMessageLoops();
+ task_environment_.RunUntilIdle();
ASSERT_FALSE(target_callback.is_null());
ScheduleObservations(PostTargetDeterminationObservations(),
@@ -2255,14 +2236,14 @@ TEST_P(DownloadItemDestinationUpdateRaceTest, IntermediateRenameFails) {
base::FilePath(kDummyIntermediatePath),
DOWNLOAD_INTERRUPT_REASON_NONE);
- intermediate_rename_loop.Run();
+ task_environment_.RunUntilIdle();
ASSERT_FALSE(intermediate_rename_callback.is_null());
ScheduleObservations(PostIntermediateRenameObservations(),
destination_observer);
intermediate_rename_callback.Run(DOWNLOAD_INTERRUPT_REASON_FILE_FAILED,
base::FilePath());
- RunAllPendingInMessageLoops();
+ task_environment_.RunUntilIdle();
EXPECT_EQ(DownloadItem::INTERRUPTED, item_->GetState());
}
@@ -2284,37 +2265,30 @@ TEST_P(DownloadItemDestinationUpdateRaceTest, IntermediateRenameSucceeds) {
// Intermediate rename loop is not used immediately, but let's set up the
// DownloadFile expectations since we are about to transfer its ownership to
// the DownloadItem.
- base::RunLoop intermediate_rename_loop;
DownloadFile::RenameCompletionCallback intermediate_rename_callback;
EXPECT_CALL(*file_, RenameAndUniquify(_, _))
- .WillOnce(DoAll(SaveArg<1>(&intermediate_rename_callback),
- ScheduleClosure(intermediate_rename_loop.QuitClosure())));
+ .WillOnce(SaveArg<1>(&intermediate_rename_callback));
- base::RunLoop download_start_loop;
DownloadFile::InitializeCallback initialize_callback;
EXPECT_CALL(*file_, Initialize(_, _, _, _))
- .WillOnce(DoAll(SaveArg<0>(&initialize_callback),
- ScheduleClosure(download_start_loop.QuitClosure())));
+ .WillOnce(SaveArg<0>(&initialize_callback));
item_->Start(std::move(file_), std::move(request_handle_), *create_info());
- download_start_loop.Run();
+ task_environment_.RunUntilIdle();
+
base::WeakPtr<DownloadDestinationObserver> destination_observer =
item_->DestinationObserverAsWeakPtr();
ScheduleObservations(PreInitializeFileObservations(), destination_observer);
- RunAllPendingInMessageLoops();
+ task_environment_.RunUntilIdle();
- base::RunLoop initialize_completion_loop;
DownloadTargetCallback target_callback;
EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(_, _))
- .WillOnce(
- DoAll(SaveArg<1>(&target_callback),
- ScheduleClosure(initialize_completion_loop.QuitClosure())));
+ .WillOnce(SaveArg<1>(&target_callback));
ScheduleObservations(PostInitializeFileObservations(), destination_observer);
initialize_callback.Run(DOWNLOAD_INTERRUPT_REASON_NONE);
- initialize_completion_loop.Run();
- RunAllPendingInMessageLoops();
+ task_environment_.RunUntilIdle();
ASSERT_FALSE(target_callback.is_null());
ScheduleObservations(PostTargetDeterminationObservations(),
@@ -2325,7 +2299,7 @@ TEST_P(DownloadItemDestinationUpdateRaceTest, IntermediateRenameSucceeds) {
base::FilePath(kDummyIntermediatePath),
DOWNLOAD_INTERRUPT_REASON_NONE);
- intermediate_rename_loop.Run();
+ task_environment_.RunUntilIdle();
ASSERT_FALSE(intermediate_rename_callback.is_null());
// This may or may not be called, depending on whether there are any errors in
@@ -2337,7 +2311,7 @@ TEST_P(DownloadItemDestinationUpdateRaceTest, IntermediateRenameSucceeds) {
destination_observer);
intermediate_rename_callback.Run(DOWNLOAD_INTERRUPT_REASON_NONE,
base::FilePath(kDummyIntermediatePath));
- RunAllPendingInMessageLoops();
+ task_environment_.RunUntilIdle();
// The state of the download depends on the observer events that were played
// back to the DownloadItemImpl. Hence we can't establish a single expectation
@@ -2350,7 +2324,7 @@ TEST_P(DownloadItemDestinationUpdateRaceTest, IntermediateRenameSucceeds) {
EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED, item_->GetLastReason());
item_->Cancel(true);
- RunAllPendingInMessageLoops();
+ task_environment_.RunUntilIdle();
}
TEST(MockDownloadItem, Compiles) {
diff --git a/chromium/content/browser/download/download_job.cc b/chromium/content/browser/download/download_job.cc
index 5bd23a4291b..412084829ad 100644
--- a/chromium/content/browser/download/download_job.cc
+++ b/chromium/content/browser/download/download_job.cc
@@ -6,6 +6,7 @@
#include "base/bind_helpers.h"
#include "content/browser/download/download_item_impl.h"
+#include "content/browser/download/download_task_runner.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/web_contents.h"
@@ -48,16 +49,16 @@ WebContents* DownloadJob::GetWebContents() const {
void DownloadJob::Start(DownloadFile* download_file_,
const DownloadFile::InitializeCallback& callback,
const DownloadItem::ReceivedSlices& received_slices) {
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- base::Bind(&DownloadFile::Initialize,
- // Safe because we control download file lifetime.
- base::Unretained(download_file_),
- base::Bind(&DownloadJob::OnDownloadFileInitialized,
- weak_ptr_factory_.GetWeakPtr(), callback),
- base::Bind(&DownloadJob::CancelRequestWithOffset,
- weak_ptr_factory_.GetWeakPtr()),
- received_slices, IsParallelizable()));
+ GetDownloadTaskRunner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&DownloadFile::Initialize,
+ // Safe because we control download file lifetime.
+ base::Unretained(download_file_),
+ base::Bind(&DownloadJob::OnDownloadFileInitialized,
+ weak_ptr_factory_.GetWeakPtr(), callback),
+ base::Bind(&DownloadJob::CancelRequestWithOffset,
+ weak_ptr_factory_.GetWeakPtr()),
+ received_slices, IsParallelizable()));
}
void DownloadJob::OnDownloadFileInitialized(
@@ -75,12 +76,12 @@ bool DownloadJob::AddByteStream(std::unique_ptr<ByteStreamReader> stream_reader,
return false;
// download_file_ is owned by download_item_ on the UI thread and is always
- // deleted on the FILE thread after download_file_ is nulled out.
+ // deleted on the download task runner after download_file_ is nulled out.
// So it's safe to use base::Unretained here.
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- base::Bind(&DownloadFile::AddByteStream, base::Unretained(download_file),
- base::Passed(&stream_reader), offset, length));
+ GetDownloadTaskRunner()->PostTask(
+ FROM_HERE, base::BindOnce(&DownloadFile::AddByteStream,
+ base::Unretained(download_file),
+ base::Passed(&stream_reader), offset, length));
return true;
}
diff --git a/chromium/content/browser/download/download_job_factory.cc b/chromium/content/browser/download/download_job_factory.cc
index a530ccf4254..79a9376eb96 100644
--- a/chromium/content/browser/download/download_job_factory.cc
+++ b/chromium/content/browser/download/download_job_factory.cc
@@ -21,13 +21,15 @@ namespace content {
namespace {
// Returns if the download can be parallelized.
-bool IsParallelizableDownload(const DownloadCreateInfo& create_info) {
+bool IsParallelizableDownload(const DownloadCreateInfo& create_info,
+ DownloadItemImpl* download_item) {
// To enable parallel download, following conditions need to be satisfied.
// 1. Feature |kParallelDownloading| enabled.
// 2. Strong validators response headers. i.e. ETag and Last-Modified.
- // 3. Accept-Ranges header.
+ // 3. Accept-Ranges or Content-Range header.
// 4. Content-Length header.
- // 5. Content-Length is no less than the minimum slice size configuration.
+ // 5. Content-Length is no less than the minimum slice size configuration, or
+ // persisted slices alreay exist.
// 6. HTTP/1.1 protocol, not QUIC nor HTTP/1.0.
// 7. HTTP or HTTPS scheme with GET method in the initial request.
@@ -38,6 +40,7 @@ bool IsParallelizableDownload(const DownloadCreateInfo& create_info) {
!create_info.etag.empty() || !create_info.last_modified.empty();
bool has_content_length = create_info.total_bytes > 0;
bool satisfy_min_file_size =
+ !download_item->GetReceivedSlices().empty() ||
create_info.total_bytes >= GetMinSliceSizeConfig();
bool satisfy_connection_type = create_info.connection_info ==
net::HttpResponseInfo::CONNECTION_INFO_HTTP1_1;
@@ -97,7 +100,7 @@ std::unique_ptr<DownloadJob> DownloadJobFactory::CreateJob(
std::move(req_handle));
}
- bool is_parallelizable = IsParallelizableDownload(create_info);
+ bool is_parallelizable = IsParallelizableDownload(create_info, download_item);
// Build parallel download job.
if (IsParallelDownloadEnabled() && is_parallelizable) {
return base::MakeUnique<ParallelDownloadJob>(download_item,
diff --git a/chromium/content/browser/download/download_manager_impl.cc b/chromium/content/browser/download/download_manager_impl.cc
index d69a4312464..4722f367c32 100644
--- a/chromium/content/browser/download/download_manager_impl.cc
+++ b/chromium/content/browser/download/download_manager_impl.cc
@@ -29,9 +29,14 @@
#include "content/browser/download/download_item_factory.h"
#include "content/browser/download/download_item_impl.h"
#include "content/browser/download/download_stats.h"
+#include "content/browser/download/download_task_runner.h"
+#include "content/browser/download/download_utils.h"
+#include "content/browser/download/resource_downloader.h"
+#include "content/browser/download/url_downloader.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/loader/resource_request_info_impl.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
+#include "content/browser/storage_partition_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/content_browser_client.h"
@@ -43,6 +48,7 @@
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/resource_context.h"
#include "content/public/browser/web_contents_delegate.h"
+#include "content/public/common/content_features.h"
#include "content/public/common/previews_state.h"
#include "content/public/common/referrer.h"
#include "net/base/elements_upload_data_stream.h"
@@ -55,13 +61,31 @@
#include "storage/browser/blob/blob_url_request_job_factory.h"
#include "url/origin.h"
-#if defined(USE_X11) && !defined(OS_CHROMEOS)
+#if defined(USE_X11)
#include "base/nix/xdg_util.h"
#endif
namespace content {
namespace {
+scoped_refptr<URLLoaderFactoryGetter> GetURLLoaderFactoryGetter(
+ BrowserContext* context,
+ int render_process_id,
+ int render_frame_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ SiteInstance* site_instance = nullptr;
+ if (render_process_id >= 0) {
+ RenderFrameHost* render_frame_host_ =
+ RenderFrameHost::FromID(render_process_id, render_frame_id);
+ if (render_frame_host_)
+ site_instance = render_frame_host_->GetSiteInstance();
+ }
+ StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
+ BrowserContext::GetStoragePartition(context, site_instance));
+ return partition->url_loader_factory_getter();
+}
+
std::unique_ptr<UrlDownloader, BrowserThread::DeleteOnIOThread> BeginDownload(
std::unique_ptr<DownloadUrlParameters> params,
content::ResourceContext* resource_context,
@@ -104,9 +128,9 @@ std::unique_ptr<UrlDownloader, BrowserThread::DeleteOnIOThread> BeginDownload(
std::unique_ptr<ByteStreamReader> empty_byte_stream;
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&DownloadManager::StartDownload, download_manager,
- base::Passed(&failed_created_info),
- base::Passed(&empty_byte_stream), params->callback()));
+ base::BindOnce(&DownloadManager::StartDownload, download_manager,
+ base::Passed(&failed_created_info),
+ base::Passed(&empty_byte_stream), params->callback()));
return nullptr;
}
@@ -116,6 +140,23 @@ std::unique_ptr<UrlDownloader, BrowserThread::DeleteOnIOThread> BeginDownload(
.release());
}
+std::unique_ptr<ResourceDownloader, BrowserThread::DeleteOnIOThread>
+BeginResourceDownload(
+ std::unique_ptr<DownloadUrlParameters> params,
+ std::unique_ptr<ResourceRequest> request,
+ scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter,
+ uint32_t download_id,
+ base::WeakPtr<DownloadManagerImpl> download_manager) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ return std::unique_ptr<ResourceDownloader, BrowserThread::DeleteOnIOThread>(
+ ResourceDownloader::BeginDownload(download_manager, std::move(params),
+ std::move(request),
+ url_loader_factory_getter, download_id,
+ false)
+ .release());
+}
+
class DownloadItemFactoryImpl : public DownloadItemFactory {
public:
DownloadItemFactoryImpl() {}
@@ -178,7 +219,7 @@ class DownloadItemFactoryImpl : public DownloadItemFactory {
}
};
-#if defined(USE_X11) && !defined(OS_CHROMEOS)
+#if defined(USE_X11)
base::FilePath GetTemporaryDownloadDirectory() {
std::unique_ptr<base::Environment> env(base::Environment::Create());
return base::nix::GetXDGDirectory(env.get(), "XDG_DATA_HOME", ".local/share");
@@ -303,7 +344,7 @@ void DownloadManagerImpl::Shutdown() {
}
downloads_.clear();
downloads_by_guid_.clear();
- url_downloaders_.clear();
+ url_download_handlers_.clear();
// We'll have nothing more to report to the observers after this point.
observers_.Clear();
@@ -360,17 +401,16 @@ void DownloadManagerImpl::StartDownloadWithId(
info->request_handle->CancelRequest(true);
if (!on_started.is_null())
on_started.Run(nullptr, DOWNLOAD_INTERRUPT_REASON_USER_CANCELED);
- // The ByteStreamReader lives and dies on the FILE thread.
+ // The ByteStreamReader lives and dies on the download sequence.
if (info->result == DOWNLOAD_INTERRUPT_REASON_NONE)
- BrowserThread::DeleteSoon(BrowserThread::FILE, FROM_HERE,
- stream.release());
+ GetDownloadTaskRunner()->DeleteSoon(FROM_HERE, stream.release());
return;
}
download = item_iterator->second.get();
}
base::FilePath default_download_directory;
-#if defined(USE_X11) && !defined(OS_CHROMEOS)
+#if defined(USE_X11)
// TODO(thomasanderson): Remove this when all Linux distros with
// versions of GTK lower than 3.14.7 are no longer supported. This
// should happen when support for Ubuntu Trusty and Debian Jessie
@@ -430,8 +470,8 @@ void DownloadManagerImpl::CheckForFileRemoval(DownloadItemImpl* download_item) {
delegate_) {
delegate_->CheckForFileExistence(
download_item,
- base::Bind(&DownloadManagerImpl::OnFileExistenceChecked,
- weak_factory_.GetWeakPtr(), download_item->GetId()));
+ base::BindOnce(&DownloadManagerImpl::OnFileExistenceChecked,
+ weak_factory_.GetWeakPtr(), download_item->GetId()));
}
}
@@ -502,7 +542,7 @@ void DownloadManagerImpl::ResumeInterruptedDownload(
base::Bind(&BeginDownload, base::Passed(&params),
browser_context_->GetResourceContext(), id,
weak_factory_.GetWeakPtr()),
- base::Bind(&DownloadManagerImpl::AddUrlDownloader,
+ base::Bind(&DownloadManagerImpl::AddUrlDownloadHandler,
weak_factory_.GetWeakPtr()));
}
@@ -528,11 +568,11 @@ void DownloadManagerImpl::DownloadRemoved(DownloadItemImpl* download) {
downloads_.erase(download->GetId());
}
-void DownloadManagerImpl::AddUrlDownloader(
- std::unique_ptr<UrlDownloader, BrowserThread::DeleteOnIOThread>
+void DownloadManagerImpl::AddUrlDownloadHandler(
+ std::unique_ptr<UrlDownloadHandler, BrowserThread::DeleteOnIOThread>
downloader) {
if (downloader)
- url_downloaders_.push_back(std::move(downloader));
+ url_download_handlers_.push_back(std::move(downloader));
}
// static
@@ -625,13 +665,34 @@ void DownloadManagerImpl::DownloadUrl(
DCHECK(params->prefer_cache());
DCHECK_EQ("POST", params->method());
}
- BrowserThread::PostTaskAndReplyWithResult(
- BrowserThread::IO, FROM_HERE,
- base::Bind(&BeginDownload, base::Passed(&params),
- browser_context_->GetResourceContext(),
- content::DownloadItem::kInvalidId, weak_factory_.GetWeakPtr()),
- base::Bind(&DownloadManagerImpl::AddUrlDownloader,
- weak_factory_.GetWeakPtr()));
+
+ // TODO(qinmin): remove false from the if statement once download works when
+ // network service is enabled, or once we disable the tests that are currently
+ // passing with the URLRequest code path.
+ if (base::FeatureList::IsEnabled(features::kNetworkService) && false) {
+ std::unique_ptr<ResourceRequest> request = CreateResourceRequest(
+ params.get());
+ BrowserThread::PostTaskAndReplyWithResult(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&BeginResourceDownload, std::move(params),
+ std::move(request),
+ GetURLLoaderFactoryGetter(
+ browser_context_, params->render_process_host_id(),
+ params->render_frame_host_routing_id()),
+ content::DownloadItem::kInvalidId,
+ weak_factory_.GetWeakPtr()),
+ base::BindOnce(&DownloadManagerImpl::AddUrlDownloadHandler,
+ weak_factory_.GetWeakPtr()));
+ } else {
+ BrowserThread::PostTaskAndReplyWithResult(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&BeginDownload, std::move(params),
+ browser_context_->GetResourceContext(),
+ content::DownloadItem::kInvalidId,
+ weak_factory_.GetWeakPtr()),
+ base::BindOnce(&DownloadManagerImpl::AddUrlDownloadHandler,
+ weak_factory_.GetWeakPtr()));
+ }
}
void DownloadManagerImpl::AddObserver(Observer* observer) {
@@ -730,24 +791,25 @@ DownloadItem* DownloadManagerImpl::GetDownload(uint32_t download_id) {
}
DownloadItem* DownloadManagerImpl::GetDownloadByGuid(const std::string& guid) {
- DCHECK(guid == base::ToUpperASCII(guid));
return base::ContainsKey(downloads_by_guid_, guid) ? downloads_by_guid_[guid]
: nullptr;
}
-void DownloadManagerImpl::OnUrlDownloaderStarted(
+void DownloadManagerImpl::OnUrlDownloadStarted(
std::unique_ptr<DownloadCreateInfo> download_create_info,
- std::unique_ptr<ByteStreamReader> stream_reader,
+ std::unique_ptr<UrlDownloadHandler::InputStream> input_stream,
const DownloadUrlParameters::OnStartedCallback& callback) {
- StartDownload(std::move(download_create_info), std::move(stream_reader),
- callback);
+ if (!base::FeatureList::IsEnabled(features::kNetworkService)) {
+ StartDownload(std::move(download_create_info),
+ std::move(input_stream->stream_reader_), callback);
+ }
}
-void DownloadManagerImpl::OnUrlDownloaderStopped(UrlDownloader* downloader) {
- for (auto ptr = url_downloaders_.begin(); ptr != url_downloaders_.end();
- ++ptr) {
+void DownloadManagerImpl::OnUrlDownloadStopped(UrlDownloadHandler* downloader) {
+ for (auto ptr = url_download_handlers_.begin();
+ ptr != url_download_handlers_.end(); ++ptr) {
if (ptr->get() == downloader) {
- url_downloaders_.erase(ptr);
+ url_download_handlers_.erase(ptr);
return;
}
}
diff --git a/chromium/content/browser/download/download_manager_impl.h b/chromium/content/browser/download/download_manager_impl.h
index 67c48e31692..6e3b37e8ce9 100644
--- a/chromium/content/browser/download/download_manager_impl.h
+++ b/chromium/content/browser/download/download_manager_impl.h
@@ -21,7 +21,7 @@
#include "base/sequenced_task_runner_helpers.h"
#include "base/synchronization/lock.h"
#include "content/browser/download/download_item_impl_delegate.h"
-#include "content/browser/download/url_downloader.h"
+#include "content/browser/download/url_download_handler.h"
#include "content/common/content_export.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/download_manager.h"
@@ -40,7 +40,7 @@ class DownloadRequestHandleInterface;
class ResourceContext;
class CONTENT_EXPORT DownloadManagerImpl : public DownloadManager,
- public UrlDownloader::Delegate,
+ public UrlDownloadHandler::Delegate,
private DownloadItemImplDelegate {
public:
using DownloadItemImplCreated = base::Callback<void(DownloadItemImpl*)>;
@@ -114,12 +114,12 @@ class CONTENT_EXPORT DownloadManagerImpl : public DownloadManager,
DownloadItem* GetDownload(uint32_t id) override;
DownloadItem* GetDownloadByGuid(const std::string& guid) override;
- // UrlDownloader::Delegate implementation.
- void OnUrlDownloaderStarted(
+ // UrlDownloadHandler::Delegate implementation.
+ void OnUrlDownloadStarted(
std::unique_ptr<DownloadCreateInfo> download_create_info,
- std::unique_ptr<ByteStreamReader> stream_reader,
+ std::unique_ptr<UrlDownloadHandler::InputStream> input_stream,
const DownloadUrlParameters::OnStartedCallback& callback) override;
- void OnUrlDownloaderStopped(UrlDownloader* downloader) override;
+ void OnUrlDownloadStopped(UrlDownloadHandler* downloader) override;
// For testing; specifically, accessed from TestFileErrorInjector.
void SetDownloadItemFactoryForTesting(
@@ -199,8 +199,8 @@ class CONTENT_EXPORT DownloadManagerImpl : public DownloadManager,
void ShowDownloadInShell(DownloadItemImpl* download) override;
void DownloadRemoved(DownloadItemImpl* download) override;
- void AddUrlDownloader(
- std::unique_ptr<UrlDownloader, BrowserThread::DeleteOnIOThread>
+ void AddUrlDownloadHandler(
+ std::unique_ptr<UrlDownloadHandler, BrowserThread::DeleteOnIOThread>
downloader);
// Factory for creation of downloads items.
@@ -240,8 +240,9 @@ class CONTENT_EXPORT DownloadManagerImpl : public DownloadManager,
net::NetLog* net_log_;
- std::vector<std::unique_ptr<UrlDownloader, BrowserThread::DeleteOnIOThread>>
- url_downloaders_;
+ std::vector<
+ std::unique_ptr<UrlDownloadHandler, BrowserThread::DeleteOnIOThread>>
+ url_download_handlers_;
base::WeakPtrFactory<DownloadManagerImpl> weak_factory_;
diff --git a/chromium/content/browser/download/download_manager_impl_unittest.cc b/chromium/content/browser/download/download_manager_impl_unittest.cc
index ad9dd844c80..0aedd186874 100644
--- a/chromium/content/browser/download/download_manager_impl_unittest.cc
+++ b/chromium/content/browser/download/download_manager_impl_unittest.cc
@@ -18,7 +18,6 @@
#include "base/guid.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/stl_util.h"
#include "base/strings/string16.h"
@@ -40,7 +39,7 @@
#include "content/public/browser/download_manager_delegate.h"
#include "content/public/test/mock_download_item.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 "net/log/net_log_with_source.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gmock_mutant.h"
@@ -254,8 +253,7 @@ DownloadItemImpl* MockDownloadItemFactory::CreateActiveItem(
EXPECT_CALL(*result, GetId())
.WillRepeatedly(Return(download_id));
EXPECT_CALL(*result, GetGuid())
- .WillRepeatedly(
- ReturnRefOfCopy(base::ToUpperASCII(base::GenerateGUID())));
+ .WillRepeatedly(ReturnRefOfCopy(base::GenerateGUID()));
items_[download_id] = result;
// Active items are created and then immediately are called to start
@@ -389,8 +387,6 @@ class DownloadManagerTest : public testing::Test {
target_disposition_(DownloadItem::TARGET_DISPOSITION_OVERWRITE),
danger_type_(DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS),
interrupt_reason_(DOWNLOAD_INTERRUPT_REASON_NONE),
- ui_thread_(BrowserThread::UI, &message_loop_),
- file_thread_(BrowserThread::FILE, &message_loop_),
next_download_id_(0) {}
// We tear down everything in TearDown().
@@ -527,9 +523,7 @@ class DownloadManagerTest : public testing::Test {
std::vector<GURL> download_urls_;
private:
- base::MessageLoopForUI message_loop_;
- TestBrowserThread ui_thread_;
- TestBrowserThread file_thread_;
+ TestBrowserThreadBundle thread_bundle_;
base::WeakPtr<MockDownloadItemFactory> mock_download_item_factory_;
std::unique_ptr<MockDownloadManagerDelegate> mock_download_manager_delegate_;
std::unique_ptr<MockBrowserContext> mock_browser_context_;
@@ -553,7 +547,7 @@ TEST_F(DownloadManagerTest, StartDownload) {
EXPECT_CALL(GetMockDownloadManagerDelegate(), GetNextId(_))
.WillOnce(RunCallback<0>(local_id));
-#if !defined(USE_X11) || defined(OS_CHROMEOS)
+#if !defined(USE_X11)
// Doing nothing will set the default download directory to null.
EXPECT_CALL(GetMockDownloadManagerDelegate(), GetSaveDir(_, _, _, _));
#endif
diff --git a/chromium/content/browser/download/download_request_core.cc b/chromium/content/browser/download/download_request_core.cc
index ded98502547..8eb85dc0a41 100644
--- a/chromium/content/browser/download/download_request_core.cc
+++ b/chromium/content/browser/download/download_request_core.cc
@@ -23,6 +23,8 @@
#include "content/browser/download/download_manager_impl.h"
#include "content/browser/download/download_request_handle.h"
#include "content/browser/download/download_stats.h"
+#include "content/browser/download/download_task_runner.h"
+#include "content/browser/download/download_utils.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/service_manager/service_manager_context.h"
#include "content/public/browser/browser_thread.h"
@@ -32,15 +34,11 @@
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/resource_context.h"
#include "content/public/browser/web_contents.h"
-#include "net/base/elements_upload_data_stream.h"
#include "net/base/io_buffer.h"
-#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
-#include "net/base/upload_bytes_element_reader.h"
#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.h"
#include "services/device/public/interfaces/constants.mojom.h"
#include "services/device/public/interfaces/wake_lock_provider.mojom.h"
#include "services/service_manager/public/cpp/connector.h"
@@ -113,74 +111,15 @@ void DownloadRequestData::Detach(net::URLRequest* request) {
const int DownloadRequestCore::kDownloadByteStreamSize = 100 * 1024;
// static
-std::unique_ptr<net::URLRequest> DownloadRequestCore::CreateRequestOnIOThread(
- uint32_t download_id,
- DownloadUrlParameters* params) {
+std::unique_ptr<net::URLRequest>
+DownloadRequestCore::CreateRequestOnIOThread(uint32_t download_id,
+ DownloadUrlParameters* params) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(download_id == DownloadItem::kInvalidId ||
!params->content_initiated())
<< "Content initiated downloads shouldn't specify a download ID";
- DCHECK(params->offset() >= 0);
-
- // ResourceDispatcherHost{Base} is-not-a URLRequest::Delegate, and
- // DownloadUrlParameters can-not include 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()));
- request->set_method(params->method());
-
- if (!params->post_body().empty()) {
- const std::string& body = params->post_body();
- std::unique_ptr<net::UploadElementReader> reader(
- net::UploadOwnedBytesElementReader::CreateWithString(body));
- request->set_upload(
- net::ElementsUploadDataStream::CreateWithReader(std::move(reader), 0));
- }
-
- if (params->post_id() >= 0) {
- // The POST in this case does not have an actual body, and only works
- // when retrieving data from cache. This is done because we don't want
- // to do a re-POST without user consent, and currently don't have a good
- // plan on how to display the UI for that.
- DCHECK(params->prefer_cache());
- DCHECK_EQ("POST", params->method());
- std::vector<std::unique_ptr<net::UploadElementReader>> element_readers;
- request->set_upload(base::MakeUnique<net::ElementsUploadDataStream>(
- std::move(element_readers), params->post_id()));
- }
-
- int load_flags = request->load_flags();
- if (params->prefer_cache()) {
- // If there is upload data attached, only retrieve from cache because there
- // is no current mechanism to prompt the user for their consent for a
- // re-post. For GETs, try to retrieve data from the cache and skip
- // validating the entry if present.
- if (request->get_upload())
- load_flags |= net::LOAD_ONLY_FROM_CACHE | net::LOAD_SKIP_CACHE_VALIDATION;
- else
- load_flags |= net::LOAD_SKIP_CACHE_VALIDATION;
- } else {
- load_flags |= net::LOAD_DISABLE_CACHE;
- }
- request->SetLoadFlags(load_flags);
-
- // Add partial requests headers.
- AddPartialRequestHeaders(request.get(), params);
- // Downloads are treated as top level navigations. Hence the first-party
- // origin for cookies is always based on the target URL and is updated on
- // redirects.
- request->set_first_party_for_cookies(params->url());
- request->set_first_party_url_policy(
- net::URLRequest::UPDATE_FIRST_PARTY_URL_ON_REDIRECT);
- request->set_initiator(params->initiator());
-
- for (const auto& header : params->request_headers())
- request->SetExtraRequestHeaderByName(header.first, header.second,
- false /*overwrite*/);
+ std::unique_ptr<net::URLRequest> request = CreateURLRequestOnIOThread(params);
DownloadRequestData::Attach(request.get(), params, download_id);
return request;
@@ -307,8 +246,7 @@ bool DownloadRequestCore::OnResponseStarted(
// Create the ByteStream for sending data to the download sink.
std::unique_ptr<ByteStreamReader> stream_reader;
- CreateByteStream(base::ThreadTaskRunnerHandle::Get(),
- BrowserThread::GetTaskRunnerForThread(BrowserThread::FILE),
+ CreateByteStream(base::ThreadTaskRunnerHandle::Get(), GetDownloadTaskRunner(),
kDownloadByteStreamSize, &stream_writer_, &stream_reader);
stream_writer_->RegisterCallback(
base::Bind(&DownloadRequestCore::ResumeRequest, AsWeakPtr()));
@@ -340,8 +278,14 @@ bool DownloadRequestCore::OnResponseStarted(
if (!headers->GetMimeType(&create_info->original_mime_type))
create_info->original_mime_type.clear();
+ // Content-Range is validated in HandleSuccessfulServerResponse.
+ // In RFC 7233, a single part 206 partial response must generate
+ // Content-Range. Accept-Range may be sent in 200 response to indicate the
+ // server can handle range request, but optional in 206 response.
create_info->accept_range =
- headers->HasHeaderValue("Accept-Ranges", "bytes");
+ headers->HasHeaderValue("Accept-Ranges", "bytes") ||
+ (headers->HasHeader("Content-Range") &&
+ headers->response_code() == net::HTTP_PARTIAL_CONTENT);
}
// GURL::GetOrigin() doesn't support getting the inner origin of a blob URL.
@@ -437,29 +381,17 @@ void DownloadRequestCore::OnResponseCompleted(
has_strong_validators =
request()->response_headers()->HasStrongValidators();
}
- DownloadInterruptReason reason = HandleRequestStatus(
- status, has_strong_validators);
-
- if (status.error() == net::ERR_ABORTED) {
- // ERR_ABORTED == something outside of the network
- // stack cancelled the request. There aren't that many things that
- // could do this to a download request (whose lifetime is separated from
- // the tab from which it came). We map this to USER_CANCELLED as the
- // case we know about (system suspend because of laptop close) corresponds
- // to a user action.
- // TODO(asanka): A lid close or other power event should result in an
- // interruption that doesn't discard the partial state, unlike
- // USER_CANCELLED. (https://crbug.com/166179)
- if (net::IsCertStatusError(request()->ssl_info().cert_status)) {
- reason = DOWNLOAD_INTERRUPT_REASON_SERVER_CERT_PROBLEM;
- } else {
- reason = DOWNLOAD_INTERRUPT_REASON_USER_CANCELED;
- }
- } else if (abort_reason_ != DOWNLOAD_INTERRUPT_REASON_NONE) {
- // If a more specific interrupt reason was specified before the request
- // was explicitly cancelled, then use it.
- reason = abort_reason_;
+
+ net::Error error_code = net::OK;
+ if (!status.is_success()) {
+ error_code = static_cast<net::Error>(status.error()); // Normal case.
+ // Make sure that at least the fact of failure comes through.
+ if (error_code == net::OK)
+ error_code = net::ERR_FAILED;
}
+ DownloadInterruptReason reason = HandleRequestCompletionStatus(
+ error_code, has_strong_validators, request()->ssl_info().cert_status,
+ abort_reason_);
std::string accept_ranges;
if (request()->response_headers()) {
@@ -535,199 +467,4 @@ std::string DownloadRequestCore::DebugString() const {
request() ? request()->url().spec().c_str() : "<NULL request>");
}
-// static
-DownloadInterruptReason DownloadRequestCore::HandleRequestStatus(
- const net::URLRequestStatus& status, bool has_strong_validators) {
- net::Error error_code = net::OK;
- if (!status.is_success()) {
- error_code = static_cast<net::Error>(status.error()); // Normal case.
- // Make sure that at least the fact of failure comes through.
- if (error_code == net::OK)
- error_code = net::ERR_FAILED;
- }
-
- // ERR_CONTENT_LENGTH_MISMATCH can be caused by 1 of the following reasons:
- // 1. Server or proxy closes the connection too early.
- // 2. The content-length header is wrong.
- // If the download has strong validators, we can interrupt the download
- // and let it resume automatically. Otherwise, resuming the download will
- // cause it to restart and the download may never complete if the error was
- // caused by reason 2. As a result, downloads without strong validators are
- // treated as completed here.
- // TODO(qinmin): check the metrics from downloads with strong validators,
- // and decide whether we should interrupt downloads without strong validators
- // rather than complete them.
- if (error_code == net::ERR_CONTENT_LENGTH_MISMATCH &&
- !has_strong_validators) {
- error_code = net::OK;
- RecordDownloadCount(COMPLETED_WITH_CONTENT_LENGTH_MISMATCH_COUNT);
- }
-
- DownloadInterruptReason reason = ConvertNetErrorToInterruptReason(
- error_code, DOWNLOAD_INTERRUPT_FROM_NETWORK);
-
- return reason;
-}
-
-// static
-DownloadInterruptReason DownloadRequestCore::HandleSuccessfulServerResponse(
- const net::HttpResponseHeaders& http_headers,
- DownloadSaveInfo* save_info) {
- switch (http_headers.response_code()) {
- case -1: // Non-HTTP request.
- case net::HTTP_OK:
- case net::HTTP_NON_AUTHORITATIVE_INFORMATION:
- case net::HTTP_PARTIAL_CONTENT:
- // Expected successful codes.
- break;
-
- case net::HTTP_CREATED:
- case net::HTTP_ACCEPTED:
- // Per RFC 7231 the entity being transferred is metadata about the
- // resource at the target URL and not the resource at that URL (or the
- // resource that would be at the URL once processing is completed in the
- // case of HTTP_ACCEPTED). However, we currently don't have special
- // handling for these response and they are downloaded the same as a
- // regular response.
- break;
-
- case net::HTTP_NO_CONTENT:
- case net::HTTP_RESET_CONTENT:
- // These two status codes don't have an entity (or rather RFC 7231
- // requires that there be no entity). They are treated the same as the
- // resource not being found since there is no entity to download.
-
- case net::HTTP_NOT_FOUND:
- return DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT;
- break;
-
- case net::HTTP_REQUESTED_RANGE_NOT_SATISFIABLE:
- // Retry by downloading from the start automatically:
- // If we haven't received data when we get this error, we won't.
- return DOWNLOAD_INTERRUPT_REASON_SERVER_NO_RANGE;
- break;
- case net::HTTP_UNAUTHORIZED:
- case net::HTTP_PROXY_AUTHENTICATION_REQUIRED:
- // Server didn't authorize this request.
- return DOWNLOAD_INTERRUPT_REASON_SERVER_UNAUTHORIZED;
- break;
- case net::HTTP_FORBIDDEN:
- // Server forbids access to this resource.
- return DOWNLOAD_INTERRUPT_REASON_SERVER_FORBIDDEN;
- break;
- default: // All other errors.
- // Redirection and informational codes should have been handled earlier
- // in the stack.
- // TODO(xingliu): Handle HTTP_PRECONDITION_FAILED and resurrect
- // DOWNLOAD_INTERRUPT_REASON_SERVER_PRECONDITION for range requests.
- // This will change extensions::api::download::InterruptReason.
- DCHECK_NE(3, http_headers.response_code() / 100);
- DCHECK_NE(1, http_headers.response_code() / 100);
- return DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED;
- }
-
- // The caller is expecting a partial response.
- if (save_info && (save_info->offset > 0 || save_info->length > 0)) {
- if (http_headers.response_code() != net::HTTP_PARTIAL_CONTENT) {
- // Server should send partial content when "If-Match" or
- // "If-Unmodified-Since" check passes, and the range request header has
- // last byte position. e.g. "Range:bytes=50-99".
- if (save_info->length != DownloadSaveInfo::kLengthFullContent)
- return DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT;
-
- // Requested a partial range, but received the entire response, when
- // the range request header is "Range:bytes={offset}-".
- save_info->offset = 0;
- save_info->hash_of_partial_file.clear();
- save_info->hash_state.reset();
- return DOWNLOAD_INTERRUPT_REASON_NONE;
- }
-
- int64_t first_byte = -1;
- int64_t last_byte = -1;
- int64_t length = -1;
- if (!http_headers.GetContentRangeFor206(&first_byte, &last_byte, &length))
- return DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT;
- DCHECK_GE(first_byte, 0);
-
- if (first_byte != save_info->offset ||
- (save_info->length > 0 &&
- last_byte != save_info->offset + save_info->length - 1)) {
- // The server returned a different range than the one we requested. Assume
- // the response is bad.
- //
- // In the future we should consider allowing offsets that are less than
- // the offset we've requested, since in theory we can truncate the partial
- // file at the offset and continue.
- return DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT;
- }
-
- return DOWNLOAD_INTERRUPT_REASON_NONE;
- }
-
- if (http_headers.response_code() == net::HTTP_PARTIAL_CONTENT)
- return DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT;
-
- return DOWNLOAD_INTERRUPT_REASON_NONE;
-}
-
-// static
-void DownloadRequestCore::AddPartialRequestHeaders(
- net::URLRequest* request,
- DownloadUrlParameters* params) {
- if (params->offset() == 0 &&
- params->length() == DownloadSaveInfo::kLengthFullContent)
- return;
-
- bool has_last_modified = !params->last_modified().empty();
- bool has_etag = !params->etag().empty();
-
- // Strong validator(i.e. etag or last modified) is required in range requests
- // for download resumption and parallel download.
- DCHECK(has_etag || has_last_modified);
- if (!has_etag && !has_last_modified) {
- DVLOG(1) << "Creating partial request without strong validators.";
- return;
- }
-
- // Add "Range" header.
- std::string range_header =
- (params->length() == DownloadSaveInfo::kLengthFullContent)
- ? base::StringPrintf("bytes=%" PRId64 "-", params->offset())
- : base::StringPrintf("bytes=%" PRId64 "-%" PRId64, params->offset(),
- params->offset() + params->length() - 1);
- request->SetExtraRequestHeaderByName(net::HttpRequestHeaders::kRange,
- range_header, true);
-
- // Add "If-Range" headers.
- if (params->use_if_range()) {
- // In accordance with RFC 7233 Section 3.2, use If-Range to specify that
- // the server return the entire entity if the validator doesn't match.
- // Last-Modified can be used in the absence of ETag as a validator if the
- // response headers satisfied the HttpUtil::HasStrongValidators()
- // predicate.
- //
- // This function assumes that HasStrongValidators() was true and that the
- // ETag and Last-Modified header values supplied are valid.
- request->SetExtraRequestHeaderByName(
- net::HttpRequestHeaders::kIfRange,
- has_etag ? params->etag() : params->last_modified(), true);
- return;
- }
-
- // Add "If-Match"/"If-Unmodified-Since" headers.
- if (has_etag) {
- request->SetExtraRequestHeaderByName(net::HttpRequestHeaders::kIfMatch,
- params->etag(), true);
- }
- // According to RFC 7232 section 3.4, "If-Unmodified-Since" is mainly for
- // old servers that didn't implement "If-Match" and must be ignored when
- // "If-Match" presents.
- if (has_last_modified) {
- request->SetExtraRequestHeaderByName(
- net::HttpRequestHeaders::kIfUnmodifiedSince, params->last_modified(),
- true);
- }
-}
-
} // namespace content
diff --git a/chromium/content/browser/download/download_request_core.h b/chromium/content/browser/download/download_request_core.h
index 95d31672d72..52fd227f9cb 100644
--- a/chromium/content/browser/download/download_request_core.h
+++ b/chromium/content/browser/download/download_request_core.h
@@ -115,16 +115,6 @@ class CONTENT_EXPORT DownloadRequestCore
net::URLRequest* request() const { return request_; }
private:
- static DownloadInterruptReason HandleRequestStatus(
- const net::URLRequestStatus& status, bool has_strong_validators);
-
- static DownloadInterruptReason HandleSuccessfulServerResponse(
- const net::HttpResponseHeaders& http_headers,
- DownloadSaveInfo* save_info);
-
- static void AddPartialRequestHeaders(net::URLRequest* request,
- DownloadUrlParameters* params);
-
std::unique_ptr<DownloadCreateInfo> CreateDownloadCreateInfo(
DownloadInterruptReason result);
diff --git a/chromium/content/browser/download/download_request_handle.cc b/chromium/content/browser/download/download_request_handle.cc
index 0cde1f84e97..7be96910b20 100644
--- a/chromium/content/browser/download/download_request_handle.cc
+++ b/chromium/content/browser/download/download_request_handle.cc
@@ -45,19 +45,19 @@ DownloadManager* DownloadRequestHandle::GetDownloadManager() const {
void DownloadRequestHandle::PauseRequest() const {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&DownloadResourceHandler::PauseRequest, handler_));
+ base::BindOnce(&DownloadResourceHandler::PauseRequest, handler_));
}
void DownloadRequestHandle::ResumeRequest() const {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&DownloadResourceHandler::ResumeRequest, handler_));
+ base::BindOnce(&DownloadResourceHandler::ResumeRequest, handler_));
}
void DownloadRequestHandle::CancelRequest(bool user_cancel) const {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&DownloadResourceHandler::CancelRequest, handler_));
+ base::BindOnce(&DownloadResourceHandler::CancelRequest, handler_));
}
} // namespace content
diff --git a/chromium/content/browser/download/download_resource_handler.cc b/chromium/content/browser/download/download_resource_handler.cc
index 0babf278e79..ff55776a45e 100644
--- a/chromium/content/browser/download/download_resource_handler.cc
+++ b/chromium/content/browser/download/download_resource_handler.cc
@@ -16,6 +16,7 @@
#include "content/browser/download/download_interrupt_reasons_impl.h"
#include "content/browser/download/download_manager_impl.h"
#include "content/browser/download/download_request_handle.h"
+#include "content/browser/download/download_task_runner.h"
#include "content/browser/frame_host/frame_tree_node.h"
#include "content/browser/loader/resource_controller.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
@@ -70,8 +71,7 @@ static void StartOnUIThread(
started_cb.Run(nullptr, DOWNLOAD_INTERRUPT_REASON_USER_CANCELED);
if (stream)
- BrowserThread::DeleteSoon(BrowserThread::FILE, FROM_HERE,
- stream.release());
+ GetDownloadTaskRunner()->DeleteSoon(FROM_HERE, stream.release());
return;
}
@@ -115,7 +115,7 @@ DownloadResourceHandler::DownloadResourceHandler(net::URLRequest* request)
const ResourceRequestInfoImpl* request_info = GetRequestInfo();
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(
+ base::BindOnce(
&InitializeDownloadTabInfoOnUIThread,
DownloadRequestHandle(AsWeakPtr(),
request_info->GetWebContentsGetterForRequest()),
@@ -126,7 +126,7 @@ DownloadResourceHandler::~DownloadResourceHandler() {
if (tab_info_) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&DeleteOnUIThread, base::Passed(&tab_info_)));
+ base::BindOnce(&DeleteOnUIThread, base::Passed(&tab_info_)));
}
}
@@ -232,7 +232,7 @@ void DownloadResourceHandler::OnStart(
if (!callback.is_null())
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(callback, nullptr, create_info->result));
+ base::BindOnce(callback, nullptr, create_info->result));
return;
}
@@ -249,10 +249,10 @@ void DownloadResourceHandler::OnStart(
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&StartOnUIThread, base::Passed(&create_info),
- base::Passed(&tab_info_), base::Passed(&stream_reader),
- render_process_id, render_frame_id,
- request_info->frame_tree_node_id(), callback));
+ base::BindOnce(&StartOnUIThread, base::Passed(&create_info),
+ base::Passed(&tab_info_), base::Passed(&stream_reader),
+ render_process_id, render_frame_id,
+ request_info->frame_tree_node_id(), callback));
}
void DownloadResourceHandler::OnReadyToRead() {
diff --git a/chromium/content/browser/download/download_response_handler.cc b/chromium/content/browser/download/download_response_handler.cc
new file mode 100644
index 00000000000..ab85646bd7a
--- /dev/null
+++ b/chromium/content/browser/download/download_response_handler.cc
@@ -0,0 +1,71 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/download/download_response_handler.h"
+
+#include "content/browser/download/download_stats.h"
+#include "content/browser/download/download_utils.h"
+#include "content/public/browser/download_url_parameters.h"
+
+namespace content {
+
+DownloadResponseHandler::DownloadResponseHandler(DownloadUrlParameters* params,
+ Delegate* delegate,
+ bool is_parallel_request)
+ : delegate_(delegate) {
+ if (!is_parallel_request)
+ RecordDownloadCount(UNTHROTTLED_COUNT);
+
+ // TODO(qinmin): create the DownloadSaveInfo from |params|
+}
+
+DownloadResponseHandler::~DownloadResponseHandler() = default;
+
+void DownloadResponseHandler::OnReceiveResponse(
+ const content::ResourceResponseHead& head,
+ const base::Optional<net::SSLInfo>& ssl_info,
+ mojom::DownloadedTempFilePtr downloaded_file) {
+ // TODO(qinmin): create the DownloadCreateInfo from |head|.
+
+ // TODO(qinmin): pass DownloadSaveInfo here.
+ DownloadInterruptReason result =
+ head.headers
+ ? HandleSuccessfulServerResponse(*(head.headers.get()), nullptr)
+ : DOWNLOAD_INTERRUPT_REASON_NONE;
+ if (result != DOWNLOAD_INTERRUPT_REASON_NONE) {
+ delegate_->OnResponseStarted(base::MakeUnique<DownloadCreateInfo>(),
+ mojo::ScopedDataPipeConsumerHandle());
+ }
+}
+
+void DownloadResponseHandler::OnReceiveRedirect(
+ const net::RedirectInfo& redirect_info,
+ const content::ResourceResponseHead& head) {}
+
+void DownloadResponseHandler::OnDataDownloaded(int64_t data_length,
+ int64_t encoded_length) {}
+
+void DownloadResponseHandler::OnUploadProgress(
+ int64_t current_position,
+ int64_t total_size,
+ OnUploadProgressCallback callback) {}
+
+void DownloadResponseHandler::OnReceiveCachedMetadata(
+ const std::vector<uint8_t>& data) {}
+
+void DownloadResponseHandler::OnTransferSizeUpdated(
+ int32_t transfer_size_diff) {};
+
+void DownloadResponseHandler::OnStartLoadingResponseBody(
+ mojo::ScopedDataPipeConsumerHandle body) {
+ delegate_->OnResponseStarted(base::MakeUnique<DownloadCreateInfo>(),
+ std::move(body));
+}
+
+void DownloadResponseHandler::OnComplete(
+ const content::ResourceRequestCompletionStatus& completion_status) {
+ // TODO(qinmin): passing the |completion_status| to DownloadFile.
+}
+
+} // namespace content
diff --git a/chromium/content/browser/download/download_response_handler.h b/chromium/content/browser/download/download_response_handler.h
new file mode 100644
index 00000000000..d3a658cc4cd
--- /dev/null
+++ b/chromium/content/browser/download/download_response_handler.h
@@ -0,0 +1,58 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_DOWNLOAD_RESPONSE_HANDLER_
+#define CONTENT_BROWSER_DOWNLOAD_RESPONSE_HANDLER_
+
+#include "content/browser/download/download_create_info.h"
+#include "content/public/common/url_loader.mojom.h"
+
+namespace content {
+
+class DownloadUrlParameters;
+
+// This class is responsible for handling the server response for a download.
+// It passes the DataPipeConsumerHandle and completion status to the download
+// sink. The class is common to both navigation triggered downloads and
+// context menu downloads
+class DownloadResponseHandler : public mojom::URLLoaderClient {
+ public:
+ class Delegate {
+ public:
+ virtual void OnResponseStarted(
+ std::unique_ptr<DownloadCreateInfo> download_create_info,
+ mojo::ScopedDataPipeConsumerHandle body) = 0;
+ };
+
+ DownloadResponseHandler(DownloadUrlParameters* params,
+ Delegate* delegate,
+ bool is_parallel_request);
+ ~DownloadResponseHandler() override;
+
+ // mojom::URLLoaderClient
+ void OnReceiveResponse(const content::ResourceResponseHead& head,
+ const base::Optional<net::SSLInfo>& ssl_info,
+ mojom::DownloadedTempFilePtr downloaded_file) override;
+ void OnReceiveRedirect(const net::RedirectInfo& redirect_info,
+ const content::ResourceResponseHead& head) override;
+ void OnDataDownloaded(int64_t data_length, int64_t encoded_length) override;
+ void OnUploadProgress(int64_t current_position,
+ int64_t total_size,
+ OnUploadProgressCallback callback) override;
+ void OnReceiveCachedMetadata(const std::vector<uint8_t>& data) override;
+ void OnTransferSizeUpdated(int32_t transfer_size_diff) override;
+ void OnStartLoadingResponseBody(
+ mojo::ScopedDataPipeConsumerHandle body) override;
+ void OnComplete(const content::ResourceRequestCompletionStatus&
+ completion_status) override;
+
+ private:
+ Delegate* const delegate_;
+
+ DISALLOW_COPY_AND_ASSIGN(DownloadResponseHandler);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_DOWNLOAD_RESPONSE_HANDLER
diff --git a/chromium/content/browser/download/download_stats.cc b/chromium/content/browser/download/download_stats.cc
index 1289d61ad30..2e6952ab3fb 100644
--- a/chromium/content/browser/download/download_stats.cc
+++ b/chromium/content/browser/download/download_stats.cc
@@ -798,6 +798,11 @@ void RecordParallelDownloadAddStreamSuccess(bool success) {
UMA_HISTOGRAM_BOOLEAN("Download.ParallelDownloadAddStreamSuccess", success);
}
+void RecordParallelizableContentLength(int64_t content_length) {
+ UMA_HISTOGRAM_CUSTOM_COUNTS("Download.ContentLength.Parallelizable",
+ content_length / 1024, 1, kMaxFileSizeKb, 50);
+}
+
void RecordParallelizableDownloadStats(
size_t bytes_downloaded_with_parallel_streams,
base::TimeDelta time_with_parallel_streams,
@@ -924,7 +929,7 @@ void RecordSavePackageEvent(SavePackageEvent event) {
}
void RecordOriginStateOnResumption(bool is_partial,
- int state) {
+ OriginStateOnResumption state) {
if (is_partial)
UMA_HISTOGRAM_ENUMERATION("Download.OriginStateOnPartialResumption", state,
ORIGIN_STATE_ON_RESUMPTION_MAX);
diff --git a/chromium/content/browser/download/download_stats.h b/chromium/content/browser/download/download_stats.h
index f7e7e196c31..7ad51f66fd2 100644
--- a/chromium/content/browser/download/download_stats.h
+++ b/chromium/content/browser/download/download_stats.h
@@ -269,6 +269,9 @@ void RecordFileBandwidth(size_t length,
base::TimeDelta disk_write_time,
base::TimeDelta elapsed_time);
+// Records the size of the download from content-length header.
+void RecordParallelizableContentLength(int64_t content_length);
+
// Increment one of the count for parallelizable download.
void RecordParallelizableDownloadCount(DownloadCountTypes type,
bool is_parallel_download_enabled);
@@ -337,7 +340,7 @@ enum OriginStateOnResumption {
// request. |state| is a combination of values from OriginStateOnResumption
// enum.
void RecordOriginStateOnResumption(bool is_partial,
- int state);
+ OriginStateOnResumption state);
void RecordDownloadConnectionSecurity(const GURL& download_url,
const std::vector<GURL>& url_chain);
diff --git a/chromium/content/browser/download/download_task_runner.cc b/chromium/content/browser/download/download_task_runner.cc
new file mode 100644
index 00000000000..a4cef99c2dd
--- /dev/null
+++ b/chromium/content/browser/download/download_task_runner.cc
@@ -0,0 +1,33 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/download/download_task_runner.h"
+
+#include "base/task_scheduler/lazy_task_runner.h"
+#include "build/build_config.h"
+
+namespace content {
+
+namespace {
+
+#if defined(OS_WIN)
+// On Windows, the download code dips into COM and the shell here and there,
+// necessitating the use of a COM single-threaded apartment sequence.
+base::LazyCOMSTATaskRunner g_download_task_runner =
+ LAZY_COM_STA_TASK_RUNNER_INITIALIZER(
+ base::TaskTraits(base::MayBlock(), base::TaskPriority::USER_VISIBLE),
+ base::SingleThreadTaskRunnerThreadMode::SHARED);
+#else
+base::LazySequencedTaskRunner g_download_task_runner =
+ LAZY_SEQUENCED_TASK_RUNNER_INITIALIZER(
+ base::TaskTraits(base::MayBlock(), base::TaskPriority::USER_VISIBLE));
+#endif
+
+} // namespace
+
+scoped_refptr<base::SequencedTaskRunner> GetDownloadTaskRunner() {
+ return g_download_task_runner.Get();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/download/download_task_runner.h b/chromium/content/browser/download/download_task_runner.h
new file mode 100644
index 00000000000..b8bb5a4bec6
--- /dev/null
+++ b/chromium/content/browser/download/download_task_runner.h
@@ -0,0 +1,18 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_DOWNLOAD_DOWNLOAD_TASK_RUNNER_H_
+#define CONTENT_BROWSER_DOWNLOAD_DOWNLOAD_TASK_RUNNER_H_
+
+#include "base/sequenced_task_runner.h"
+#include "content/common/content_export.h"
+
+namespace content {
+
+// Returns the task runner used to save files and do other blocking operations.
+CONTENT_EXPORT scoped_refptr<base::SequencedTaskRunner> GetDownloadTaskRunner();
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_DOWNLOAD_DOWNLOAD_TASK_RUNNER_H_
diff --git a/chromium/content/browser/download/download_utils.cc b/chromium/content/browser/download/download_utils.cc
new file mode 100644
index 00000000000..319a3fa09f4
--- /dev/null
+++ b/chromium/content/browser/download/download_utils.cc
@@ -0,0 +1,376 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/download/download_utils.h"
+
+#include "base/format_macros.h"
+#include "base/memory/ptr_util.h"
+#include "base/process/process_handle.h"
+#include "base/strings/stringprintf.h"
+#include "content/browser/download/download_interrupt_reasons_impl.h"
+#include "content/browser/download/download_stats.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/download_save_info.h"
+#include "content/public/browser/download_url_parameters.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/common/resource_request.h"
+#include "net/base/elements_upload_data_stream.h"
+#include "net/base/load_flags.h"
+#include "net/base/upload_bytes_element_reader.h"
+#include "net/http/http_request_headers.h"
+#include "net/http/http_status_code.h"
+#include "net/url_request/url_request_context.h"
+
+namespace content {
+
+namespace {
+
+void AppendExtraHeaders(net::HttpRequestHeaders* headers,
+ DownloadUrlParameters* params) {
+ for (const auto& header : params->request_headers())
+ headers->SetHeaderIfMissing(header.first, header.second);
+}
+
+int GetLoadFlags(DownloadUrlParameters* params, bool has_upload_data) {
+ int load_flags = 0;
+ if (params->prefer_cache()) {
+ // If there is upload data attached, only retrieve from cache because there
+ // is no current mechanism to prompt the user for their consent for a
+ // re-post. For GETs, try to retrieve data from the cache and skip
+ // validating the entry if present.
+ if (has_upload_data)
+ load_flags |= net::LOAD_ONLY_FROM_CACHE | net::LOAD_SKIP_CACHE_VALIDATION;
+ else
+ load_flags |= net::LOAD_SKIP_CACHE_VALIDATION;
+ } else {
+ load_flags |= net::LOAD_DISABLE_CACHE;
+ }
+ return load_flags;
+}
+
+std::unique_ptr<net::HttpRequestHeaders> GetAdditionalRequestHeaders(
+ DownloadUrlParameters* params) {
+ auto headers = base::MakeUnique<net::HttpRequestHeaders>();
+ if (params->offset() == 0 &&
+ params->length() == DownloadSaveInfo::kLengthFullContent) {
+ AppendExtraHeaders(headers.get(), params);
+ return headers;
+ }
+
+ bool has_last_modified = !params->last_modified().empty();
+ bool has_etag = !params->etag().empty();
+
+ // Strong validator(i.e. etag or last modified) is required in range requests
+ // for download resumption and parallel download.
+ DCHECK(has_etag || has_last_modified);
+ if (!has_etag && !has_last_modified) {
+ DVLOG(1) << "Creating partial request without strong validators.";
+ AppendExtraHeaders(headers.get(), params);
+ return headers;
+ }
+
+ // Add "Range" header.
+ std::string range_header =
+ (params->length() == DownloadSaveInfo::kLengthFullContent)
+ ? base::StringPrintf("bytes=%" PRId64 "-", params->offset())
+ : base::StringPrintf("bytes=%" PRId64 "-%" PRId64, params->offset(),
+ params->offset() + params->length() - 1);
+ headers->SetHeader(net::HttpRequestHeaders::kRange, range_header);
+
+ // Add "If-Range" headers.
+ if (params->use_if_range()) {
+ // In accordance with RFC 7233 Section 3.2, use If-Range to specify that
+ // the server return the entire entity if the validator doesn't match.
+ // Last-Modified can be used in the absence of ETag as a validator if the
+ // response headers satisfied the HttpUtil::HasStrongValidators()
+ // predicate.
+ //
+ // This function assumes that HasStrongValidators() was true and that the
+ // ETag and Last-Modified header values supplied are valid.
+ headers->SetHeader(net::HttpRequestHeaders::kIfRange,
+ has_etag ? params->etag() : params->last_modified());
+ AppendExtraHeaders(headers.get(), params);
+ return headers;
+ }
+
+ // Add "If-Match"/"If-Unmodified-Since" headers.
+ if (has_etag)
+ headers->SetHeader(net::HttpRequestHeaders::kIfMatch, params->etag());
+
+ // According to RFC 7232 section 3.4, "If-Unmodified-Since" is mainly for
+ // old servers that didn't implement "If-Match" and must be ignored when
+ // "If-Match" presents.
+ if (has_last_modified) {
+ headers->SetHeader(net::HttpRequestHeaders::kIfUnmodifiedSince,
+ params->last_modified());
+ }
+
+ AppendExtraHeaders(headers.get(), params);
+ return headers;
+}
+
+} // namespace
+
+DownloadInterruptReason HandleRequestCompletionStatus(
+ net::Error error_code, bool has_strong_validators,
+ net::CertStatus cert_status, DownloadInterruptReason abort_reason) {
+ // ERR_CONTENT_LENGTH_MISMATCH can be caused by 1 of the following reasons:
+ // 1. Server or proxy closes the connection too early.
+ // 2. The content-length header is wrong.
+ // If the download has strong validators, we can interrupt the download
+ // and let it resume automatically. Otherwise, resuming the download will
+ // cause it to restart and the download may never complete if the error was
+ // caused by reason 2. As a result, downloads without strong validators are
+ // treated as completed here.
+ // TODO(qinmin): check the metrics from downloads with strong validators,
+ // and decide whether we should interrupt downloads without strong validators
+ // rather than complete them.
+ if (error_code == net::ERR_CONTENT_LENGTH_MISMATCH &&
+ !has_strong_validators) {
+ error_code = net::OK;
+ RecordDownloadCount(COMPLETED_WITH_CONTENT_LENGTH_MISMATCH_COUNT);
+ }
+
+ if (error_code == net::ERR_ABORTED) {
+ // ERR_ABORTED == something outside of the network
+ // stack cancelled the request. There aren't that many things that
+ // could do this to a download request (whose lifetime is separated from
+ // the tab from which it came). We map this to USER_CANCELLED as the
+ // case we know about (system suspend because of laptop close) corresponds
+ // to a user action.
+ // TODO(asanka): A lid close or other power event should result in an
+ // interruption that doesn't discard the partial state, unlike
+ // USER_CANCELLED. (https://crbug.com/166179)
+ if (net::IsCertStatusError(cert_status))
+ return DOWNLOAD_INTERRUPT_REASON_SERVER_CERT_PROBLEM;
+ else
+ return DOWNLOAD_INTERRUPT_REASON_USER_CANCELED;
+ } else if (abort_reason != DOWNLOAD_INTERRUPT_REASON_NONE) {
+ // If a more specific interrupt reason was specified before the request
+ // was explicitly cancelled, then use it.
+ return abort_reason;
+ }
+
+ return ConvertNetErrorToInterruptReason(
+ error_code, DOWNLOAD_INTERRUPT_FROM_NETWORK);
+}
+
+std::unique_ptr<ResourceRequest> CreateResourceRequest(
+ DownloadUrlParameters* params) {
+ DCHECK(params->offset() >= 0);
+
+ std::unique_ptr<ResourceRequest> request(new ResourceRequest);
+ request->method = params->method();
+ request->url = params->url();
+ request->request_initiator = params->initiator();
+ request->do_not_prompt_for_login = params->do_not_prompt_for_login();
+ request->site_for_cookies = params->url();
+ request->referrer = params->referrer().url;
+ request->referrer_policy = params->referrer().policy;
+ request->download_to_file = true;
+ request->allow_download = true;
+
+ if (params->render_process_host_id()) {
+ request->origin_pid = params->render_process_host_id();
+ RenderFrameHost* render_frame_host =
+ RenderFrameHost::FromID(params->render_process_host_id(),
+ params->render_frame_host_routing_id());
+ RenderFrameHost* parent_frame = render_frame_host->GetParent();
+ if (parent_frame) {
+ request->parent_render_frame_id = parent_frame->GetRoutingID();
+ request->parent_is_main_frame = (parent_frame->GetParent() == nullptr);
+ } else {
+ request->is_main_frame = true;
+ }
+
+ request->render_frame_id = params->render_frame_host_routing_id();
+ }
+
+ bool has_upload_data = false;
+ if (!params->post_body().empty()) {
+ request->request_body = ResourceRequestBody::CreateFromBytes(
+ params->post_body().data(), params->post_body().size());
+ has_upload_data = true;
+ }
+
+ if (params->post_id() >= 0) {
+ // The POST in this case does not have an actual body, and only works
+ // when retrieving data from cache. This is done because we don't want
+ // to do a re-POST without user consent, and currently don't have a good
+ // plan on how to display the UI for that.
+ DCHECK(params->prefer_cache());
+ DCHECK_EQ("POST", params->method());
+ request->request_body = new ResourceRequestBody();
+ request->request_body->set_identifier(params->post_id());
+ has_upload_data = true;
+ }
+
+ request->load_flags = GetLoadFlags(params, has_upload_data);
+
+ // Add additional request headers.
+ std::unique_ptr<net::HttpRequestHeaders> headers =
+ GetAdditionalRequestHeaders(params);
+ if (!headers->IsEmpty())
+ request->headers = headers->ToString();
+
+ return request;
+}
+
+std::unique_ptr<net::URLRequest>
+CreateURLRequestOnIOThread(DownloadUrlParameters* params) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(params->offset() >= 0);
+
+ // ResourceDispatcherHost{Base} is-not-a URLRequest::Delegate, and
+ // DownloadUrlParameters can-not include 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()));
+ request->set_method(params->method());
+
+ if (!params->post_body().empty()) {
+ const std::string& body = params->post_body();
+ std::unique_ptr<net::UploadElementReader> reader(
+ net::UploadOwnedBytesElementReader::CreateWithString(body));
+ request->set_upload(
+ net::ElementsUploadDataStream::CreateWithReader(std::move(reader), 0));
+ }
+
+ if (params->post_id() >= 0) {
+ // The POST in this case does not have an actual body, and only works
+ // when retrieving data from cache. This is done because we don't want
+ // to do a re-POST without user consent, and currently don't have a good
+ // plan on how to display the UI for that.
+ DCHECK(params->prefer_cache());
+ DCHECK_EQ("POST", params->method());
+ std::vector<std::unique_ptr<net::UploadElementReader>> element_readers;
+ request->set_upload(base::MakeUnique<net::ElementsUploadDataStream>(
+ std::move(element_readers), params->post_id()));
+ }
+
+ request->SetLoadFlags(GetLoadFlags(params, request->get_upload()));
+
+ // Add additional request headers.
+ std::unique_ptr<net::HttpRequestHeaders> headers =
+ GetAdditionalRequestHeaders(params);
+ if (!headers->IsEmpty())
+ request->SetExtraRequestHeaders(*headers);
+
+ // Downloads are treated as top level navigations. Hence the first-party
+ // origin for cookies is always based on the target URL and is updated on
+ // redirects.
+ request->set_site_for_cookies(params->url());
+ request->set_first_party_url_policy(
+ net::URLRequest::UPDATE_FIRST_PARTY_URL_ON_REDIRECT);
+ request->set_initiator(params->initiator());
+
+ return request;
+}
+
+DownloadInterruptReason HandleSuccessfulServerResponse(
+ const net::HttpResponseHeaders& http_headers,
+ DownloadSaveInfo* save_info) {
+ switch (http_headers.response_code()) {
+ case -1: // Non-HTTP request.
+ case net::HTTP_OK:
+ case net::HTTP_NON_AUTHORITATIVE_INFORMATION:
+ case net::HTTP_PARTIAL_CONTENT:
+ // Expected successful codes.
+ break;
+
+ case net::HTTP_CREATED:
+ case net::HTTP_ACCEPTED:
+ // Per RFC 7231 the entity being transferred is metadata about the
+ // resource at the target URL and not the resource at that URL (or the
+ // resource that would be at the URL once processing is completed in the
+ // case of HTTP_ACCEPTED). However, we currently don't have special
+ // handling for these response and they are downloaded the same as a
+ // regular response.
+ break;
+
+ case net::HTTP_NO_CONTENT:
+ case net::HTTP_RESET_CONTENT:
+ // These two status codes don't have an entity (or rather RFC 7231
+ // requires that there be no entity). They are treated the same as the
+ // resource not being found since there is no entity to download.
+
+ case net::HTTP_NOT_FOUND:
+ return DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT;
+ break;
+
+ case net::HTTP_REQUESTED_RANGE_NOT_SATISFIABLE:
+ // Retry by downloading from the start automatically:
+ // If we haven't received data when we get this error, we won't.
+ return DOWNLOAD_INTERRUPT_REASON_SERVER_NO_RANGE;
+ break;
+ case net::HTTP_UNAUTHORIZED:
+ case net::HTTP_PROXY_AUTHENTICATION_REQUIRED:
+ // Server didn't authorize this request.
+ return DOWNLOAD_INTERRUPT_REASON_SERVER_UNAUTHORIZED;
+ break;
+ case net::HTTP_FORBIDDEN:
+ // Server forbids access to this resource.
+ return DOWNLOAD_INTERRUPT_REASON_SERVER_FORBIDDEN;
+ break;
+ default: // All other errors.
+ // Redirection and informational codes should have been handled earlier
+ // in the stack.
+ // TODO(xingliu): Handle HTTP_PRECONDITION_FAILED and resurrect
+ // DOWNLOAD_INTERRUPT_REASON_SERVER_PRECONDITION for range requests.
+ // This will change extensions::api::download::InterruptReason.
+ DCHECK_NE(3, http_headers.response_code() / 100);
+ DCHECK_NE(1, http_headers.response_code() / 100);
+ return DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED;
+ }
+
+ // The caller is expecting a partial response.
+ if (save_info && (save_info->offset > 0 || save_info->length > 0)) {
+ if (http_headers.response_code() != net::HTTP_PARTIAL_CONTENT) {
+ // Server should send partial content when "If-Match" or
+ // "If-Unmodified-Since" check passes, and the range request header has
+ // last byte position. e.g. "Range:bytes=50-99".
+ if (save_info->length != DownloadSaveInfo::kLengthFullContent)
+ return DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT;
+
+ // Requested a partial range, but received the entire response, when
+ // the range request header is "Range:bytes={offset}-".
+ save_info->offset = 0;
+ save_info->hash_of_partial_file.clear();
+ save_info->hash_state.reset();
+ return DOWNLOAD_INTERRUPT_REASON_NONE;
+ }
+
+ int64_t first_byte = -1;
+ int64_t last_byte = -1;
+ int64_t length = -1;
+ if (!http_headers.GetContentRangeFor206(&first_byte, &last_byte, &length))
+ return DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT;
+ DCHECK_GE(first_byte, 0);
+
+ if (first_byte != save_info->offset ||
+ (save_info->length > 0 &&
+ last_byte != save_info->offset + save_info->length - 1)) {
+ // The server returned a different range than the one we requested. Assume
+ // the response is bad.
+ //
+ // In the future we should consider allowing offsets that are less than
+ // the offset we've requested, since in theory we can truncate the partial
+ // file at the offset and continue.
+ return DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT;
+ }
+
+ return DOWNLOAD_INTERRUPT_REASON_NONE;
+ }
+
+ if (http_headers.response_code() == net::HTTP_PARTIAL_CONTENT)
+ return DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT;
+
+ return DOWNLOAD_INTERRUPT_REASON_NONE;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/download/download_utils.h b/chromium/content/browser/download/download_utils.h
new file mode 100644
index 00000000000..4b8c2ef1394
--- /dev/null
+++ b/chromium/content/browser/download/download_utils.h
@@ -0,0 +1,43 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_DOWNLOAD_DOWNLOAD_UTILS_H_
+#define CONTENT_BROWSER_DOWNLOAD_DOWNLOAD_UTILS_H_
+
+#include "content/public/browser/download_interrupt_reasons.h"
+#include "net/base/net_errors.h"
+#include "net/cert/cert_status_flags.h"
+#include "net/http/http_response_headers.h"
+
+namespace net {
+class URLRequest;
+}
+
+namespace content {
+
+class DownloadUrlParameters;
+struct ResourceRequest;
+struct DownloadSaveInfo;
+
+// Handle the url request completion status and return the interrupt reasons.
+// |cert_status| is ignored if error_code is not net::ERR_ABORTED.
+DownloadInterruptReason CONTENT_EXPORT HandleRequestCompletionStatus(
+ net::Error error_code, bool has_strong_validators,
+ net::CertStatus cert_status, DownloadInterruptReason abort_reason);
+
+// Create a ResourceRequest from |params|.
+std::unique_ptr<ResourceRequest> CONTENT_EXPORT CreateResourceRequest(
+ DownloadUrlParameters* params);
+
+// Create a URLRequest from |params|.
+std::unique_ptr<net::URLRequest> CONTENT_EXPORT CreateURLRequestOnIOThread(
+ DownloadUrlParameters* params);
+
+DownloadInterruptReason CONTENT_EXPORT
+HandleSuccessfulServerResponse(const net::HttpResponseHeaders& http_headers,
+ DownloadSaveInfo* save_info);
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_DOWNLOAD_DOWNLOAD_UTILS_H_
diff --git a/chromium/content/browser/download/download_worker.cc b/chromium/content/browser/download/download_worker.cc
index 2f564e5f42e..b79f3f6129c 100644
--- a/chromium/content/browser/download/download_worker.cc
+++ b/chromium/content/browser/download/download_worker.cc
@@ -30,13 +30,14 @@ class CompletedByteStreamReader : public ByteStreamReader {
int status_;
};
-std::unique_ptr<UrlDownloader, BrowserThread::DeleteOnIOThread>
-CreateUrlDownloader(std::unique_ptr<DownloadUrlParameters> params,
- base::WeakPtr<UrlDownloader::Delegate> delegate) {
+std::unique_ptr<UrlDownloadHandler, BrowserThread::DeleteOnIOThread>
+CreateUrlDownloadHandler(std::unique_ptr<DownloadUrlParameters> params,
+ base::WeakPtr<UrlDownloadHandler::Delegate> delegate) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
// Build the URLRequest, BlobDataHandle is hold in original request for image
// download.
+ // TODO(qinmin): Handle the case when network service is enabled.
std::unique_ptr<net::URLRequest> url_request =
DownloadRequestCore::CreateRequestOnIOThread(DownloadItem::kInvalidId,
params.get());
@@ -69,10 +70,10 @@ void DownloadWorker::SendRequest(
DCHECK_CURRENTLY_ON(BrowserThread::UI);
BrowserThread::PostTaskAndReplyWithResult(
BrowserThread::IO, FROM_HERE,
- base::Bind(&CreateUrlDownloader, base::Passed(&params),
- weak_factory_.GetWeakPtr()),
- base::Bind(&DownloadWorker::AddUrlDownloader,
- weak_factory_.GetWeakPtr()));
+ base::BindOnce(&CreateUrlDownloadHandler, std::move(params),
+ weak_factory_.GetWeakPtr()),
+ base::BindOnce(&DownloadWorker::AddUrlDownloadHandler,
+ weak_factory_.GetWeakPtr()));
}
void DownloadWorker::Pause() {
@@ -94,9 +95,9 @@ void DownloadWorker::Cancel(bool user_cancel) {
request_handle_->CancelRequest(user_cancel);
}
-void DownloadWorker::OnUrlDownloaderStarted(
+void DownloadWorker::OnUrlDownloadStarted(
std::unique_ptr<DownloadCreateInfo> create_info,
- std::unique_ptr<ByteStreamReader> stream_reader,
+ std::unique_ptr<UrlDownloadHandler::InputStream> input_stream,
const DownloadUrlParameters::OnStartedCallback& callback) {
// |callback| is not used in subsequent requests.
DCHECK(callback.is_null());
@@ -113,7 +114,8 @@ void DownloadWorker::OnUrlDownloaderStarted(
DownloadInterruptReason::DOWNLOAD_INTERRUPT_REASON_NONE) {
VLOG(kVerboseLevel) << "Parallel download sub-request failed. reason = "
<< create_info->result;
- stream_reader.reset(new CompletedByteStreamReader(create_info->result));
+ input_stream->stream_reader_.reset(
+ new CompletedByteStreamReader(create_info->result));
}
request_handle_ = std::move(create_info->request_handle);
@@ -124,18 +126,19 @@ void DownloadWorker::OnUrlDownloaderStarted(
Pause();
}
- delegate_->OnByteStreamReady(this, std::move(stream_reader));
+ delegate_->OnByteStreamReady(this, std::move(input_stream->stream_reader_));
}
-void DownloadWorker::OnUrlDownloaderStopped(UrlDownloader* downloader) {
- // Release the |url_downloader_|, the object will be deleted on IO thread.
- url_downloader_.reset();
+void DownloadWorker::OnUrlDownloadStopped(UrlDownloadHandler* downloader) {
+ // Release the |url_download_handler_|, the object will be deleted on IO
+ // thread.
+ url_download_handler_.reset();
}
-void DownloadWorker::AddUrlDownloader(
- std::unique_ptr<UrlDownloader, BrowserThread::DeleteOnIOThread>
+void DownloadWorker::AddUrlDownloadHandler(
+ std::unique_ptr<UrlDownloadHandler, BrowserThread::DeleteOnIOThread>
downloader) {
- url_downloader_ = std::move(downloader);
+ url_download_handler_ = std::move(downloader);
}
} // namespace content
diff --git a/chromium/content/browser/download/download_worker.h b/chromium/content/browser/download/download_worker.h
index 4fd3a951058..81b49089db7 100644
--- a/chromium/content/browser/download/download_worker.h
+++ b/chromium/content/browser/download/download_worker.h
@@ -22,7 +22,7 @@ namespace content {
// file after handling response of the original non-range request.
// TODO(xingliu): we should consider to reuse this class for single connection
// download.
-class CONTENT_EXPORT DownloadWorker : public UrlDownloader::Delegate {
+class CONTENT_EXPORT DownloadWorker : public UrlDownloadHandler::Delegate {
public:
class Delegate {
public:
@@ -52,14 +52,14 @@ class CONTENT_EXPORT DownloadWorker : public UrlDownloader::Delegate {
private:
// UrlDownloader::Delegate implementation.
- void OnUrlDownloaderStarted(
+ void OnUrlDownloadStarted(
std::unique_ptr<DownloadCreateInfo> create_info,
- std::unique_ptr<ByteStreamReader> stream_reader,
+ std::unique_ptr<UrlDownloadHandler::InputStream> input_stream,
const DownloadUrlParameters::OnStartedCallback& callback) override;
- void OnUrlDownloaderStopped(UrlDownloader* downloader) override;
+ void OnUrlDownloadStopped(UrlDownloadHandler* downloader) override;
- void AddUrlDownloader(
- std::unique_ptr<UrlDownloader, BrowserThread::DeleteOnIOThread>
+ void AddUrlDownloadHandler(
+ std::unique_ptr<UrlDownloadHandler, BrowserThread::DeleteOnIOThread>
downloader);
DownloadWorker::Delegate* const delegate_;
@@ -79,8 +79,8 @@ class CONTENT_EXPORT DownloadWorker : public UrlDownloader::Delegate {
std::unique_ptr<DownloadRequestHandleInterface> request_handle_;
// Used to handle the url request. Live and die on IO thread.
- std::unique_ptr<UrlDownloader, BrowserThread::DeleteOnIOThread>
- url_downloader_;
+ std::unique_ptr<UrlDownloadHandler, BrowserThread::DeleteOnIOThread>
+ url_download_handler_;
base::WeakPtrFactory<DownloadWorker> weak_factory_;
diff --git a/chromium/content/browser/download/drag_download_file.cc b/chromium/content/browser/download/drag_download_file.cc
index 78611a1b0cd..da0ab7b1392 100644
--- a/chromium/content/browser/download/drag_download_file.cc
+++ b/chromium/content/browser/download/drag_download_file.cc
@@ -80,7 +80,7 @@ class DragDownloadFile::DragDownloadFileUI : public DownloadItem::Observer {
destination: WEBSITE
}
policy {
- cookies_allowed: true
+ cookies_allowed: YES
cookies_store: "user"
setting:
"This feature cannot be disabled in settings, but it is only "
@@ -128,7 +128,7 @@ class DragDownloadFile::DragDownloadFileUI : public DownloadItem::Observer {
if (!item || item->GetState() != DownloadItem::IN_PROGRESS) {
DCHECK(!item || item->GetLastReason() != DOWNLOAD_INTERRUPT_REASON_NONE);
on_completed_task_runner_->PostTask(FROM_HERE,
- base::Bind(on_completed_, false));
+ base::BindOnce(on_completed_, false));
return;
}
DCHECK_EQ(DOWNLOAD_INTERRUPT_REASON_NONE, interrupt_reason);
@@ -147,7 +147,7 @@ class DragDownloadFile::DragDownloadFileUI : public DownloadItem::Observer {
if (!on_completed_.is_null()) {
on_completed_task_runner_->PostTask(
FROM_HERE,
- base::Bind(on_completed_, state == DownloadItem::COMPLETE));
+ base::BindOnce(on_completed_, state == DownloadItem::COMPLETE));
on_completed_.Reset();
}
download_item_->RemoveObserver(this);
@@ -163,7 +163,7 @@ class DragDownloadFile::DragDownloadFileUI : public DownloadItem::Observer {
const bool is_complete =
download_item_->GetState() == DownloadItem::COMPLETE;
on_completed_task_runner_->PostTask(
- FROM_HERE, base::Bind(on_completed_, is_complete));
+ FROM_HERE, base::BindOnce(on_completed_, is_complete));
on_completed_.Reset();
}
download_item_->RemoveObserver(this);
@@ -210,8 +210,9 @@ 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::Bind(
- &DragDownloadFileUI::Delete, base::Unretained(drag_ui_)));
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&DragDownloadFileUI::Delete, base::Unretained(drag_ui_)));
drag_ui_ = NULL;
}
@@ -226,9 +227,10 @@ void DragDownloadFile::Start(ui::DownloadFileObserver* observer) {
observer_ = observer;
DCHECK(observer_.get());
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
- &DragDownloadFileUI::InitiateDownload, base::Unretained(drag_ui_),
- base::Passed(&file_), file_path_));
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&DragDownloadFileUI::InitiateDownload,
+ base::Unretained(drag_ui_),
+ base::Passed(&file_), file_path_));
}
bool DragDownloadFile::Wait() {
@@ -241,8 +243,9 @@ bool DragDownloadFile::Wait() {
void DragDownloadFile::Stop() {
CheckThread();
if (drag_ui_) {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
- &DragDownloadFileUI::Cancel, base::Unretained(drag_ui_)));
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ 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 93e2a58d24e..a023cdf41a1 100644
--- a/chromium/content/browser/download/drag_download_file_browsertest.cc
+++ b/chromium/content/browser/download/drag_download_file_browsertest.cc
@@ -75,7 +75,7 @@ class DragDownloadFileTest : public ContentBrowserTest {
base::FilePath mock_base(GetTestFilePath("download", ""));
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&net::URLRequestMockHTTPJob::AddUrlHandlers, mock_base));
+ base::BindOnce(&net::URLRequestMockHTTPJob::AddUrlHandlers, mock_base));
}
const base::FilePath& downloads_directory() const {
diff --git a/chromium/content/browser/download/drag_download_util.cc b/chromium/content/browser/download/drag_download_util.cc
index fb5a2b9441b..5e376100382 100644
--- a/chromium/content/browser/download/drag_download_util.cc
+++ b/chromium/content/browser/download/drag_download_util.cc
@@ -96,15 +96,13 @@ PromiseFileFinalizer::PromiseFileFinalizer(
void PromiseFileFinalizer::OnDownloadCompleted(
const base::FilePath& file_path) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&PromiseFileFinalizer::Cleanup, this));
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&PromiseFileFinalizer::Cleanup, this));
}
void PromiseFileFinalizer::OnDownloadAborted() {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&PromiseFileFinalizer::Cleanup, this));
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ 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 e13a93d2d6e..55be7702251 100644
--- a/chromium/content/browser/download/mhtml_generation_browsertest.cc
+++ b/chromium/content/browser/download/mhtml_generation_browsertest.cc
@@ -15,6 +15,7 @@
#include "base/strings/utf_string_conversions.h"
#include "base/test/histogram_tester.h"
#include "base/threading/thread_restrictions.h"
+#include "content/browser/download/download_task_runner.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/common/frame_messages.h"
#include "content/public/browser/mhtml_extra_parts.h"
@@ -276,12 +277,12 @@ class GenerateMHTMLAndExitRendererMessageFilter : public BrowserMessageFilter {
if (message.type() == FrameHostMsg_SerializeAsMHTMLResponse::ID) {
// After |return false| below, this IPC message will be handled by the
// product code as illustrated below. (1), (2), (3) depict points in time
- // when product code runs on UI and FILE threads. (X), (Y), (Z) depict
- // when we want test-injected tasks to run - for the repro, (Z) has to
- // happen between (1) and (3). (Y?) and (Z?) depict when test tasks can
- // theoretically happen and ruin the repro.
+ // when product code runs on UI thread and download sequence. (X), (Y),
+ // (Z) depict when we want test-injected tasks to run - for the repro, (Z)
+ // has to happen between (1) and (3). (Y?) and (Z?) depict when test
+ // tasks can theoretically happen and ruin the repro.
//
- // IO thread UI thread FILE thread
+ // IO thread UI thread download sequence
// --------- --------- -----------
// | | |
// WE ARE HERE | |
@@ -319,34 +320,35 @@ class GenerateMHTMLAndExitRendererMessageFilter : public BrowserMessageFilter {
// - From here post TaskX to UI thread. (X) is guaranteed to happen
// before timepoint (1) (because posting of (1) happens after
// |return false| / before we post TaskX below).
- // - From (X) post TaskY to FILE thread. Because this posting is done
- // before (1), we can guarantee that (Y) will happen before (2).
+ // - From (X) post TaskY to download sequence. Because this posting is
+ // done before (1), we can guarantee that (Y) will happen before (2).
// - From (Y) post TaskZ to UI thread. Because this posting is done
// before (2), we can guarantee that (Z) will happen before (3).
// - We cannot really guarantee that (Y) and (Z) happen *after* (1) - i.e.
// execution at (Y?) and (Z?) instead is possible. In practice,
- // bouncing off of UI and FILE thread does mean (Z) happens after (1).
+ // bouncing off of UI and download sequence does mean (Z) happens
+ // after (1).
BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE, base::Bind(
- &GenerateMHTMLAndExitRendererMessageFilter::TaskX,
- base::Unretained(this)));
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&GenerateMHTMLAndExitRendererMessageFilter::TaskX,
+ base::Unretained(this)));
}
return false;
};
void TaskX() {
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE, base::Bind(
- &GenerateMHTMLAndExitRendererMessageFilter::TaskY,
- base::Unretained(this)));
+ GetDownloadTaskRunner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&GenerateMHTMLAndExitRendererMessageFilter::TaskY,
+ base::Unretained(this)));
}
void TaskY() {
BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE, base::Bind(
- &GenerateMHTMLAndExitRendererMessageFilter::TaskZ,
- base::Unretained(this)));
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&GenerateMHTMLAndExitRendererMessageFilter::TaskZ,
+ base::Unretained(this)));
}
void TaskZ() {
diff --git a/chromium/content/browser/download/mhtml_generation_manager.cc b/chromium/content/browser/download/mhtml_generation_manager.cc
index df825ba7cac..910a3de1896 100644
--- a/chromium/content/browser/download/mhtml_generation_manager.cc
+++ b/chromium/content/browser/download/mhtml_generation_manager.cc
@@ -18,9 +18,11 @@
#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
+#include "base/task_runner_util.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
#include "content/browser/bad_message.h"
+#include "content/browser/download/download_task_runner.h"
#include "content/browser/download/mhtml_extra_parts_impl.h"
#include "content/browser/frame_host/frame_tree_node.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
@@ -380,8 +382,8 @@ void MHTMLGenerationManager::Job::CloseFile(
}
// If no previous error occurred the boundary should be sent.
- BrowserThread::PostTaskAndReplyWithResult(
- BrowserThread::FILE, FROM_HERE,
+ base::PostTaskAndReplyWithResult(
+ GetDownloadTaskRunner().get(), FROM_HERE,
base::Bind(
&MHTMLGenerationManager::Job::FinalizeAndCloseFileOnFileThread,
save_status,
@@ -438,7 +440,7 @@ MHTMLGenerationManager::Job::FinalizeAndCloseFileOnFileThread(
const std::string& boundary,
base::File file,
const MHTMLExtraPartsImpl* extra_parts) {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ DCHECK(GetDownloadTaskRunner()->RunsTasksInCurrentSequence());
// If no previous error occurred the boundary should have been provided.
if (save_status == MhtmlSaveStatus::SUCCESS) {
@@ -474,7 +476,7 @@ bool MHTMLGenerationManager::Job::WriteExtraDataParts(
const std::string& boundary,
base::File& file,
const MHTMLExtraPartsImpl* extra_parts) {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ DCHECK(GetDownloadTaskRunner()->RunsTasksInCurrentSequence());
// Don't write an extra data part if there is none.
if (extra_parts == nullptr)
return true;
@@ -509,7 +511,7 @@ bool MHTMLGenerationManager::Job::WriteExtraDataParts(
// static
bool MHTMLGenerationManager::Job::WriteFooter(const std::string& boundary,
base::File& file) {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ DCHECK(GetDownloadTaskRunner()->RunsTasksInCurrentSequence());
std::string footer = base::StringPrintf("--%s--\r\n", boundary.c_str());
DCHECK(base::IsStringASCII(footer));
return (file.WriteAtCurrentPos(footer.data(), footer.size()) >= 0);
@@ -518,7 +520,7 @@ bool MHTMLGenerationManager::Job::WriteFooter(const std::string& boundary,
// static
bool MHTMLGenerationManager::Job::CloseFileIfValid(base::File& file,
int64_t* file_size) {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ DCHECK(GetDownloadTaskRunner()->RunsTasksInCurrentSequence());
DCHECK(file_size);
if (file.IsValid()) {
*file_size = file.GetLength();
@@ -549,8 +551,8 @@ void MHTMLGenerationManager::SaveMHTML(WebContents* web_contents,
web_contents->GetLastCommittedURL().possibly_invalid_spec(),
"file", params.file_path.AsUTF8Unsafe());
- BrowserThread::PostTaskAndReplyWithResult(
- BrowserThread::FILE, FROM_HERE,
+ base::PostTaskAndReplyWithResult(
+ GetDownloadTaskRunner().get(), FROM_HERE,
base::Bind(&MHTMLGenerationManager::CreateFile, params.file_path),
base::Bind(&MHTMLGenerationManager::OnFileAvailable,
base::Unretained(this), // Safe b/c |this| is a singleton.
@@ -597,7 +599,7 @@ void MHTMLGenerationManager::OnSerializeAsMHTMLResponse(
// static
base::File MHTMLGenerationManager::CreateFile(const base::FilePath& file_path) {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ DCHECK(GetDownloadTaskRunner()->RunsTasksInCurrentSequence());
// SECURITY NOTE: A file descriptor to the file created below will be passed
// to multiple renderer processes which (in out-of-process iframes mode) can
diff --git a/chromium/content/browser/download/mock_download_file.cc b/chromium/content/browser/download/mock_download_file.cc
index 58edddd8651..aca43d0e7c3 100644
--- a/chromium/content/browser/download/mock_download_file.cc
+++ b/chromium/content/browser/download/mock_download_file.cc
@@ -3,6 +3,9 @@
// found in the LICENSE file.
#include "content/browser/download/mock_download_file.h"
+
+#include "base/bind.h"
+#include "content/public/browser/browser_thread.h"
#include "testing/gmock/include/gmock/gmock.h"
using ::testing::_;
@@ -11,12 +14,17 @@ using ::testing::Return;
namespace content {
namespace {
-void SuccessRun(
+void SuccessRun(const DownloadFile::InitializeCallback& initialize_callback) {
+ initialize_callback.Run(DOWNLOAD_INTERRUPT_REASON_NONE);
+}
+
+void PostSuccessRun(
const DownloadFile::InitializeCallback& initialize_callback,
const DownloadFile::CancelRequestCallback& cancel_request_callback,
const DownloadItem::ReceivedSlices& received_slices,
bool is_parallelizable) {
- initialize_callback.Run(DOWNLOAD_INTERRUPT_REASON_NONE);
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&SuccessRun, initialize_callback));
}
} // namespace
@@ -25,7 +33,7 @@ MockDownloadFile::MockDownloadFile() {
// This is here because |Initialize()| is normally called right after
// construction.
ON_CALL(*this, Initialize(_, _, _, _))
- .WillByDefault(::testing::Invoke(SuccessRun));
+ .WillByDefault(::testing::Invoke(PostSuccessRun));
}
MockDownloadFile::~MockDownloadFile() {
@@ -40,4 +48,11 @@ void MockDownloadFile::AddByteStream(
DoAddByteStream(stream_reader.get(), offset, length);
}
+void MockDownloadFile::AddDataPipeConsumerHandle(
+ mojo::ScopedDataPipeConsumerHandle handle,
+ int64_t offset,
+ int64_t length) {
+ DoAddDataPipeConsumerHandle(handle.get(), offset, length);
+}
+
} // namespace content
diff --git a/chromium/content/browser/download/mock_download_file.h b/chromium/content/browser/download/mock_download_file.h
index e95b1bb21d4..152a9322f24 100644
--- a/chromium/content/browser/download/mock_download_file.h
+++ b/chromium/content/browser/download/mock_download_file.h
@@ -36,10 +36,19 @@ class MockDownloadFile : public DownloadFile {
void AddByteStream(std::unique_ptr<ByteStreamReader> stream_reader,
int64_t offset,
int64_t length) override;
+ void AddDataPipeConsumerHandle(mojo::ScopedDataPipeConsumerHandle handle,
+ int64_t offset,
+ int64_t length) override;
+ MOCK_METHOD3(DoAddDataPipeConsumerHandle,
+ void(const mojo::DataPipeConsumerHandle& handle,
+ int64_t offset,
+ int64_t length));
MOCK_METHOD3(DoAddByteStream,
void(ByteStreamReader* stream_reader,
int64_t offset,
int64_t length));
+ MOCK_METHOD2(OnResponseCompleted, void(int64_t offset,
+ DownloadInterruptReason status));
MOCK_METHOD2(AppendDataToFile, DownloadInterruptReason(
const char* data, size_t data_len));
MOCK_METHOD1(Rename, DownloadInterruptReason(
diff --git a/chromium/content/browser/download/parallel_download_job.cc b/chromium/content/browser/download/parallel_download_job.cc
index 4ce373f3bf8..30e6258f2af 100644
--- a/chromium/content/browser/download/parallel_download_job.cc
+++ b/chromium/content/browser/download/parallel_download_job.cc
@@ -134,8 +134,10 @@ void ParallelDownloadJob::OnByteStreamReady(
void ParallelDownloadJob::BuildParallelRequests() {
DCHECK(!requests_sent_);
DCHECK(!is_paused());
- if (is_canceled_)
+ if (is_canceled_ ||
+ download_item_->GetState() != DownloadItem::DownloadState::IN_PROGRESS) {
return;
+ }
// TODO(qinmin): The size of |slices_to_download| should be no larger than
// |kParallelRequestCount| unless |kParallelRequestCount| is changed after
@@ -149,7 +151,15 @@ void ParallelDownloadJob::BuildParallelRequests() {
DCHECK(!slices_to_download.empty());
int64_t first_slice_offset = slices_to_download[0].offset;
- DCHECK_LE(initial_request_offset_, first_slice_offset);
+
+ // We may build parallel job without slices. The slices can be cleared or
+ // previous session only has one stream writing to disk. In these cases, fall
+ // back to non parallel download.
+ if (initial_request_offset_ > first_slice_offset) {
+ VLOG(kVerboseLevel)
+ << "Received slices data mismatch initial request offset.";
+ return;
+ }
// Create more slices for a new download. The initial request may generate
// a received slice.
@@ -225,7 +235,7 @@ void ParallelDownloadJob::CreateRequest(int64_t offset, int64_t length) {
destination: WEBSITE
}
policy {
- cookies_allowed: true
+ cookies_allowed: YES
cookies_store: "user"
setting: "This feature cannot be disabled in settings."
chrome_policy {
diff --git a/chromium/content/browser/download/parallel_download_job_unittest.cc b/chromium/content/browser/download/parallel_download_job_unittest.cc
index 2690ea4739b..96f8a6e883f 100644
--- a/chromium/content/browser/download/parallel_download_job_unittest.cc
+++ b/chromium/content/browser/download/parallel_download_job_unittest.cc
@@ -9,9 +9,12 @@
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
+#include "base/test/mock_callback.h"
+#include "base/test/scoped_task_environment.h"
#include "content/browser/download/download_destination_observer.h"
#include "content/browser/download/download_file_impl.h"
#include "content/browser/download/download_item_impl_delegate.h"
+#include "content/browser/download/download_task_runner.h"
#include "content/browser/download/mock_download_item_impl.h"
#include "content/browser/download/parallel_download_utils.h"
#include "content/public/test/test_browser_thread_bundle.h"
@@ -20,6 +23,7 @@
using ::testing::_;
using ::testing::NiceMock;
+using ::testing::Return;
using ::testing::StrictMock;
namespace content {
@@ -89,6 +93,11 @@ class ParallelDownloadJobForTest : public ParallelDownloadJob {
ParallelDownloadJob::WorkerMap& workers() { return workers_; }
+ void MakeFileInitialized(const DownloadFile::InitializeCallback& callback,
+ DownloadInterruptReason result) {
+ ParallelDownloadJob::OnDownloadFileInitialized(callback, result);
+ }
+
int GetParallelRequestCount() const override { return request_count_; }
int64_t GetMinSliceSize() const override { return min_slice_size_; }
int GetMinRemainingTimeInSeconds() const override {
@@ -112,6 +121,11 @@ class ParallelDownloadJobForTest : public ParallelDownloadJob {
class ParallelDownloadJobTest : public testing::Test {
public:
+ ParallelDownloadJobTest()
+ : task_environment_(
+ base::test::ScopedTaskEnvironment::MainThreadType::UI,
+ base::test::ScopedTaskEnvironment::ExecutionMode::QUEUED) {}
+
void CreateParallelJob(int64_t initial_request_offset,
int64_t content_length,
const DownloadItem::ReceivedSlices& slices,
@@ -153,13 +167,15 @@ class ParallelDownloadJobTest : public testing::Test {
void MakeWorkerReady(
DownloadWorker* worker,
std::unique_ptr<MockDownloadRequestHandle> request_handle) {
- UrlDownloader::Delegate* delegate =
- static_cast<UrlDownloader::Delegate*>(worker);
+ UrlDownloadHandler::Delegate* delegate =
+ static_cast<UrlDownloadHandler::Delegate*>(worker);
std::unique_ptr<DownloadCreateInfo> create_info =
base::MakeUnique<DownloadCreateInfo>();
create_info->request_handle = std::move(request_handle);
- delegate->OnUrlDownloaderStarted(
- std::move(create_info), std::unique_ptr<ByteStreamReader>(),
+ delegate->OnUrlDownloadStarted(
+ std::move(create_info),
+ base::MakeUnique<UrlDownloadHandler::InputStream>(
+ base::MakeUnique<MockByteStreamReader>()),
DownloadUrlParameters::OnStartedCallback());
}
@@ -173,6 +189,7 @@ class ParallelDownloadJobTest : public testing::Test {
file_initialized_ = true;
}
+ base::test::ScopedTaskEnvironment task_environment_;
content::TestBrowserThreadBundle browser_threads_;
std::unique_ptr<DownloadItemImplDelegate> item_delegate_;
std::unique_ptr<MockDownloadItemImpl> download_item_;
@@ -190,7 +207,7 @@ TEST_F(ParallelDownloadJobTest, CreateNewDownloadRequestsWithoutSlices) {
// Task 1: Range:50-, for 50 bytes.
CreateParallelJob(0, 100, DownloadItem::ReceivedSlices(), 2, 1, 10);
BuildParallelRequests();
- EXPECT_EQ(1, static_cast<int>(job_->workers().size()));
+ EXPECT_EQ(1u, job_->workers().size());
VerifyWorker(50, 0);
DestroyParallelJob();
@@ -200,7 +217,7 @@ TEST_F(ParallelDownloadJobTest, CreateNewDownloadRequestsWithoutSlices) {
// Task 2: Range:66-, for 34 bytes.
CreateParallelJob(0, 100, DownloadItem::ReceivedSlices(), 3, 1, 10);
BuildParallelRequests();
- EXPECT_EQ(2, static_cast<int>(job_->workers().size()));
+ EXPECT_EQ(2u, job_->workers().size());
VerifyWorker(33, 33);
VerifyWorker(66, 0);
DestroyParallelJob();
@@ -234,7 +251,7 @@ TEST_F(ParallelDownloadJobTest, CreateNewDownloadRequestsWithSlices) {
DownloadItem::ReceivedSlices slices = {DownloadItem::ReceivedSlice(0, 17)};
CreateParallelJob(12, 88, slices, 3, 1, 10);
BuildParallelRequests();
- EXPECT_EQ(2, static_cast<int>(job_->workers().size()));
+ EXPECT_EQ(2u, job_->workers().size());
VerifyWorker(44, 27);
VerifyWorker(71, 0);
DestroyParallelJob();
@@ -248,7 +265,7 @@ TEST_F(ParallelDownloadJobTest, CreateNewDownloadRequestsWithSlices) {
slices = {DownloadItem::ReceivedSlice(0, 60)};
CreateParallelJob(60, 40, slices, 4, 20, 10);
BuildParallelRequests();
- EXPECT_EQ(1, static_cast<int>(job_->workers().size()));
+ EXPECT_EQ(1u, job_->workers().size());
VerifyWorker(80, 0);
DestroyParallelJob();
@@ -269,7 +286,7 @@ TEST_F(ParallelDownloadJobTest, CreateNewDownloadRequestsWithSlices) {
DownloadItem::ReceivedSlice(40, 10), DownloadItem::ReceivedSlice(90, 10)};
CreateParallelJob(0, 12, slices, 2, 1, 10);
BuildParallelRequests();
- EXPECT_EQ(3, static_cast<int>(job_->workers().size()));
+ EXPECT_EQ(3u, job_->workers().size());
VerifyWorker(30, 10);
VerifyWorker(50, 40);
VerifyWorker(100, 0);
@@ -351,7 +368,7 @@ TEST_F(ParallelDownloadJobTest, RemainingContentWillFinishSoon) {
DownloadItem::ReceivedSlices slices = {DownloadItem::ReceivedSlice(0, 99)};
CreateParallelJob(99, 1, slices, 3, 1, 10);
BuildParallelRequests();
- EXPECT_EQ(0, static_cast<int>(job_->workers().size()));
+ EXPECT_EQ(0u, job_->workers().size());
DestroyParallelJob();
}
@@ -379,10 +396,37 @@ TEST_F(ParallelDownloadJobTest, ParallelRequestNotCreatedUntilFileInitialized) {
EXPECT_CALL(*input_stream, RegisterCallback(_));
EXPECT_CALL(*input_stream, Read(_, _));
EXPECT_CALL(*(observer.get()), DestinationUpdate(_, _, _));
- base::RunLoop().RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_TRUE(file_initialized_);
EXPECT_EQ(1u, job_->workers().size());
DestroyParallelJob();
+
+ // The download file lives on the download sequence, and must
+ // be deleted there.
+ GetDownloadTaskRunner()->DeleteSoon(FROM_HERE, std::move(download_file));
+ task_environment_.RunUntilIdle();
+}
+
+// Interruption from IO thread after the file initialized and before building
+// the parallel requests, should correctly stop the download.
+TEST_F(ParallelDownloadJobTest, InterruptOnStartup) {
+ DownloadItem::ReceivedSlices slices = {DownloadItem::ReceivedSlice(0, 99)};
+ CreateParallelJob(99, 1, slices, 3, 1, 10);
+
+ // Start to build the requests without any error.
+ base::MockCallback<DownloadFile::InitializeCallback> callback;
+ EXPECT_CALL(callback, Run(_)).Times(1);
+ job_->MakeFileInitialized(callback.Get(), DOWNLOAD_INTERRUPT_REASON_NONE);
+
+ // Simulate and inject an error from IO thread after file initialized.
+ EXPECT_CALL(*download_item_.get(), GetState())
+ .WillRepeatedly(Return(DownloadItem::DownloadState::INTERRUPTED));
+
+ // Because of the error, no parallel requests are built.
+ task_environment_.RunUntilIdle();
+ EXPECT_EQ(0u, job_->workers().size());
+
+ DestroyParallelJob();
}
} // namespace content
diff --git a/chromium/content/browser/download/resource_downloader.cc b/chromium/content/browser/download/resource_downloader.cc
new file mode 100644
index 00000000000..bef3f56b883
--- /dev/null
+++ b/chromium/content/browser/download/resource_downloader.cc
@@ -0,0 +1,73 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/download/resource_downloader.h"
+
+#include "content/browser/download/download_utils.h"
+#include "content/browser/url_loader_factory_getter.h"
+#include "content/common/throttling_url_loader.h"
+
+namespace content {
+
+// static
+std::unique_ptr<ResourceDownloader> ResourceDownloader::BeginDownload(
+ base::WeakPtr<UrlDownloadHandler::Delegate> delegate,
+ std::unique_ptr<DownloadUrlParameters> download_url_parameters,
+ std::unique_ptr<ResourceRequest> request,
+ scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter,
+ uint32_t download_id,
+ bool is_parallel_request) {
+ if (download_url_parameters->url().SchemeIs(url::kBlobScheme))
+ return nullptr;
+
+ auto downloader = base::MakeUnique<ResourceDownloader>(
+ delegate, std::move(download_url_parameters), url_loader_factory_getter,
+ download_id, is_parallel_request);
+ downloader->Start(std::move(request));
+
+ return downloader;
+}
+
+ResourceDownloader::ResourceDownloader(
+ base::WeakPtr<UrlDownloadHandler::Delegate> delegate,
+ std::unique_ptr<DownloadUrlParameters> download_url_parameters,
+ scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter,
+ uint32_t download_id,
+ bool is_parallel_request)
+ : delegate_(delegate),
+ download_url_parameters_(std::move(download_url_parameters)),
+ url_loader_factory_getter_(url_loader_factory_getter),
+ response_handler_(download_url_parameters_.get(),
+ this,
+ is_parallel_request),
+ download_id_(download_id),
+ weak_ptr_factory_(this) {}
+
+ResourceDownloader::~ResourceDownloader() = default;
+
+void ResourceDownloader::Start(std::unique_ptr<ResourceRequest> request) {
+ url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
+ url_loader_factory_getter_->GetNetworkFactory()->get(),
+ std::vector<std::unique_ptr<URLLoaderThrottle>>(),
+ 0, // routing_id
+ 0, // request_id
+ mojom::kURLLoadOptionSendSSLInfo | mojom::kURLLoadOptionSniffMimeType,
+ *(request.get()), &response_handler_,
+ download_url_parameters_->GetNetworkTrafficAnnotation());
+}
+
+void ResourceDownloader::OnResponseStarted(
+ std::unique_ptr<DownloadCreateInfo> download_create_info,
+ mojo::ScopedDataPipeConsumerHandle body) {
+ download_create_info->download_id = download_id_;
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(
+ &UrlDownloadHandler::Delegate::OnUrlDownloadStarted, delegate_,
+ std::move(download_create_info),
+ base::MakeUnique<UrlDownloadHandler::InputStream>(std::move(body)),
+ download_url_parameters_->callback()));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/download/resource_downloader.h b/chromium/content/browser/download/resource_downloader.h
new file mode 100644
index 00000000000..a5925efa3da
--- /dev/null
+++ b/chromium/content/browser/download/resource_downloader.h
@@ -0,0 +1,73 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_DOWNLOAD_RESOURCE_DOWNLOADER_
+#define CONTENT_BROWSER_DOWNLOAD_RESOURCE_DOWNLOADER_
+
+#include "content/browser/download/download_response_handler.h"
+#include "content/browser/download/url_download_handler.h"
+#include "content/public/common/resource_request.h"
+#include "content/public/common/url_loader.mojom.h"
+
+namespace content {
+
+class ThrottlingURLLoader;
+class URLLoaderFactoryGetter;
+
+// Class for handing the download of a url.
+class ResourceDownloader : public UrlDownloadHandler,
+ public DownloadResponseHandler::Delegate {
+ public:
+ // Called to start a download, must be called on IO thread.
+ static std::unique_ptr<ResourceDownloader> BeginDownload(
+ base::WeakPtr<UrlDownloadHandler::Delegate> delegate,
+ std::unique_ptr<DownloadUrlParameters> download_url_parameters,
+ std::unique_ptr<ResourceRequest> request,
+ scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter,
+ uint32_t download_id,
+ bool is_parallel_request);
+
+ ResourceDownloader(
+ base::WeakPtr<UrlDownloadHandler::Delegate> delegate,
+ std::unique_ptr<DownloadUrlParameters> download_url_parameters,
+ scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter,
+ uint32_t download_id,
+ bool is_parallel_request);
+ ~ResourceDownloader() override;
+
+ // DownloadResponseHandler::Delegate
+ void OnResponseStarted(
+ std::unique_ptr<DownloadCreateInfo> download_create_info,
+ mojo::ScopedDataPipeConsumerHandle body) override;
+
+ private:
+ // Helper method to start the network request.
+ void Start(std::unique_ptr<ResourceRequest> request);
+
+ base::WeakPtr<UrlDownloadHandler::Delegate> delegate_;
+
+ // URLLoader for sending out the request.
+ std::unique_ptr<ThrottlingURLLoader> url_loader_;
+
+ // Parameters for constructing the ResourceRequest.
+ std::unique_ptr<DownloadUrlParameters> download_url_parameters_;
+
+ // Object for retrieving the URLLoaderFactory.
+ scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter_;
+
+ // Object for handing the server response.
+ DownloadResponseHandler response_handler_;
+
+ // ID of the download, or DownloadItem::kInvalidId if this is a new
+ // download.
+ uint32_t download_id_;
+
+ base::WeakPtrFactory<ResourceDownloader> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(ResourceDownloader);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_DOWNLOAD_RESOURCE_DOWNLOADER_
diff --git a/chromium/content/browser/download/save_file.cc b/chromium/content/browser/download/save_file.cc
index 56f968a2ed7..a9b0aaee08c 100644
--- a/chromium/content/browser/download/save_file.cc
+++ b/chromium/content/browser/download/save_file.cc
@@ -5,7 +5,7 @@
#include "content/browser/download/save_file.h"
#include "base/logging.h"
-#include "content/public/browser/browser_thread.h"
+#include "content/browser/download/download_task_runner.h"
#include "net/log/net_log_with_source.h"
namespace content {
@@ -16,14 +16,14 @@ namespace content {
// have access to the SavePackage at this point.
SaveFile::SaveFile(const SaveFileCreateInfo* info, bool calculate_hash)
: file_(net::NetLogWithSource()), info_(info) {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ DCHECK(GetDownloadTaskRunner()->RunsTasksInCurrentSequence());
DCHECK(info);
DCHECK(info->path.empty());
}
SaveFile::~SaveFile() {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ DCHECK(GetDownloadTaskRunner()->RunsTasksInCurrentSequence());
}
DownloadInterruptReason SaveFile::Initialize() {
diff --git a/chromium/content/browser/download/save_file.h b/chromium/content/browser/download/save_file.h
index 580b833c23b..e5d3bc6867a 100644
--- a/chromium/content/browser/download/save_file.h
+++ b/chromium/content/browser/download/save_file.h
@@ -19,11 +19,11 @@
namespace content {
// SaveFile ----------------------------------------------------------------
-// These objects live exclusively on the file thread and handle the writing
-// operations for one save item. These objects live only for the duration that
-// the saving job is 'in progress': once the saving job has been completed or
-// canceled, the SaveFile is destroyed. One SaveFile object represents one item
-// in a save session.
+// These objects live exclusively on the download task runner and handle the
+// writing operations for one save item. These objects live only for the
+// duration that the saving job is 'in progress': once the saving job has been
+// completed or canceled, the SaveFile is destroyed. One SaveFile object
+// represents one item in a save session.
class SaveFile {
public:
explicit SaveFile(const SaveFileCreateInfo* info, bool calculate_hash);
diff --git a/chromium/content/browser/download/save_file_manager.cc b/chromium/content/browser/download/save_file_manager.cc
index 982eeac812a..b2458d298c5 100644
--- a/chromium/content/browser/download/save_file_manager.cc
+++ b/chromium/content/browser/download/save_file_manager.cc
@@ -13,6 +13,7 @@
#include "base/strings/string_util.h"
#include "base/threading/thread.h"
#include "content/browser/child_process_security_policy_impl.h"
+#include "content/browser/download/download_task_runner.h"
#include "content/browser/download/save_file.h"
#include "content/browser/download/save_file_resource_handler.h"
#include "content/browser/download/save_package.h"
@@ -60,19 +61,18 @@ SaveFileManager* SaveFileManager::Get() {
// Called during the browser shutdown process to clean up any state (open files,
// timers) that live on the saving thread (file thread).
void SaveFileManager::Shutdown() {
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- base::Bind(&SaveFileManager::OnShutdown, this));
+ GetDownloadTaskRunner()->PostTask(
+ FROM_HERE, base::BindOnce(&SaveFileManager::OnShutdown, this));
}
// Stop file thread operations.
void SaveFileManager::OnShutdown() {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ DCHECK(GetDownloadTaskRunner()->RunsTasksInCurrentSequence());
save_file_map_.clear();
}
SaveFile* SaveFileManager::LookupSaveFile(SaveItemId save_item_id) {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ DCHECK(GetDownloadTaskRunner()->RunsTasksInCurrentSequence());
auto it = save_file_map_.find(save_item_id);
return it == save_file_map_.end() ? nullptr : it->second.get();
}
@@ -109,9 +109,10 @@ void SaveFileManager::SaveURL(SaveItemId save_item_id,
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&SaveFileManager::OnSaveURL, this, url, referrer,
- save_item_id, save_package->id(), render_process_host_id,
- render_view_routing_id, render_frame_routing_id, context));
+ base::BindOnce(&SaveFileManager::OnSaveURL, this, url, referrer,
+ save_item_id, save_package->id(), render_process_host_id,
+ render_view_routing_id, render_frame_routing_id,
+ context));
} else {
// We manually start the save job.
SaveFileCreateInfo* info = new SaveFileCreateInfo(
@@ -120,9 +121,8 @@ void SaveFileManager::SaveURL(SaveItemId save_item_id,
// Since the data will come from render process, so we need to start
// this kind of save job by ourself.
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- base::Bind(&SaveFileManager::StartSave, this, info));
+ GetDownloadTaskRunner()->PostTask(
+ FROM_HERE, base::BindOnce(&SaveFileManager::StartSave, this, info));
}
}
@@ -161,18 +161,17 @@ SavePackage* SaveFileManager::GetSavePackageFromRenderIds(
void SaveFileManager::DeleteDirectoryOrFile(const base::FilePath& full_path,
bool is_dir) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- base::Bind(&SaveFileManager::OnDeleteDirectoryOrFile,
- this, full_path, is_dir));
+ GetDownloadTaskRunner()->PostTask(
+ FROM_HERE, base::BindOnce(&SaveFileManager::OnDeleteDirectoryOrFile, this,
+ full_path, is_dir));
}
void SaveFileManager::SendCancelRequest(SaveItemId save_item_id) {
// Cancel the request which has specific save id.
DCHECK(!save_item_id.is_null());
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- base::Bind(&SaveFileManager::CancelSave, this, save_item_id));
+ GetDownloadTaskRunner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&SaveFileManager::CancelSave, this, save_item_id));
}
// Notifications sent from the IO thread and run on the file thread:
@@ -181,7 +180,7 @@ void SaveFileManager::SendCancelRequest(SaveItemId save_item_id) {
// to create a SaveFile which will hold and finally destroy |info|. It will
// then passes |info| to the UI thread for reporting saving status.
void SaveFileManager::StartSave(SaveFileCreateInfo* info) {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ DCHECK(GetDownloadTaskRunner()->RunsTasksInCurrentSequence());
DCHECK(info);
// No need to calculate hash.
std::unique_ptr<SaveFile> save_file = base::MakeUnique<SaveFile>(info, false);
@@ -195,7 +194,7 @@ void SaveFileManager::StartSave(SaveFileCreateInfo* info) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&SaveFileManager::OnStartSave, this, *info));
+ base::BindOnce(&SaveFileManager::OnStartSave, this, *info));
}
// We do forward an update to the UI thread here, since we do not use timer to
@@ -205,7 +204,7 @@ void SaveFileManager::StartSave(SaveFileCreateInfo* info) {
void SaveFileManager::UpdateSaveProgress(SaveItemId save_item_id,
net::IOBuffer* data,
int data_len) {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ DCHECK(GetDownloadTaskRunner()->RunsTasksInCurrentSequence());
SaveFile* save_file = LookupSaveFile(save_item_id);
if (save_file) {
DCHECK(save_file->InProgress());
@@ -214,9 +213,9 @@ void SaveFileManager::UpdateSaveProgress(SaveItemId save_item_id,
save_file->AppendDataToFile(data->data(), data_len);
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&SaveFileManager::OnUpdateSaveProgress, this,
- save_file->save_item_id(), save_file->BytesSoFar(),
- reason == DOWNLOAD_INTERRUPT_REASON_NONE));
+ base::BindOnce(&SaveFileManager::OnUpdateSaveProgress, this,
+ save_file->save_item_id(), save_file->BytesSoFar(),
+ reason == DOWNLOAD_INTERRUPT_REASON_NONE));
}
}
@@ -228,7 +227,7 @@ void SaveFileManager::SaveFinished(SaveItemId save_item_id,
DVLOG(20) << __func__ << "() save_item_id = " << save_item_id
<< " save_package_id = " << save_package_id
<< " is_success = " << is_success;
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ DCHECK(GetDownloadTaskRunner()->RunsTasksInCurrentSequence());
int64_t bytes_so_far = 0;
SaveFile* save_file = LookupSaveFile(save_item_id);
@@ -247,8 +246,8 @@ void SaveFileManager::SaveFinished(SaveItemId save_item_id,
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&SaveFileManager::OnSaveFinished, this, save_item_id,
- bytes_so_far, is_success));
+ base::BindOnce(&SaveFileManager::OnSaveFinished, this, save_item_id,
+ bytes_so_far, is_success));
}
// Notifications sent from the file thread and run on the UI thread.
@@ -320,7 +319,7 @@ void SaveFileManager::OnSaveURL(const GURL& url,
destination: WEBSITE
}
policy {
- cookies_allowed: true
+ cookies_allowed: YES
cookies_store: "user"
setting:
"This feature cannot be disable by settings. The request is made "
@@ -382,7 +381,7 @@ void SaveFileManager::ExecuteCancelSaveRequest(int render_process_id,
// sent from the UI thread, the saving job may have already completed and
// won't exist in our map.
void SaveFileManager::CancelSave(SaveItemId save_item_id) {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ DCHECK(GetDownloadTaskRunner()->RunsTasksInCurrentSequence());
auto it = save_file_map_.find(save_item_id);
if (it != save_file_map_.end()) {
std::unique_ptr<SaveFile> save_file = std::move(it->second);
@@ -400,8 +399,9 @@ void SaveFileManager::CancelSave(SaveItemId save_item_id) {
// we can ignore the message.
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&SaveFileManager::ExecuteCancelSaveRequest, this,
- save_file->render_process_id(), save_file->request_id()));
+ base::BindOnce(&SaveFileManager::ExecuteCancelSaveRequest, this,
+ save_file->render_process_id(),
+ save_file->request_id()));
}
// Whatever the save file is complete or not, just delete it. This
@@ -412,7 +412,7 @@ void SaveFileManager::CancelSave(SaveItemId save_item_id) {
void SaveFileManager::OnDeleteDirectoryOrFile(const base::FilePath& full_path,
bool is_dir) {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ DCHECK(GetDownloadTaskRunner()->RunsTasksInCurrentSequence());
DCHECK(!full_path.empty());
base::DeleteFile(full_path, is_dir);
@@ -423,7 +423,7 @@ void SaveFileManager::RenameAllFiles(const FinalNamesMap& final_names,
int render_process_id,
int render_frame_routing_id,
SavePackageId save_package_id) {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ DCHECK(GetDownloadTaskRunner()->RunsTasksInCurrentSequence());
if (!resource_dir.empty() && !base::PathExists(resource_dir))
base::CreateDirectory(resource_dir);
@@ -443,8 +443,9 @@ void SaveFileManager::RenameAllFiles(const FinalNamesMap& final_names,
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&SaveFileManager::OnFinishSavePageJob, this, render_process_id,
- render_frame_routing_id, save_package_id));
+ base::BindOnce(&SaveFileManager::OnFinishSavePageJob, this,
+ render_process_id, render_frame_routing_id,
+ save_package_id));
}
void SaveFileManager::OnFinishSavePageJob(int render_process_id,
@@ -461,7 +462,7 @@ void SaveFileManager::OnFinishSavePageJob(int render_process_id,
void SaveFileManager::RemoveSavedFileFromFileMap(
const std::vector<SaveItemId>& save_item_ids) {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ DCHECK(GetDownloadTaskRunner()->RunsTasksInCurrentSequence());
for (const SaveItemId save_item_id : save_item_ids) {
auto it = save_file_map_.find(save_item_id);
diff --git a/chromium/content/browser/download/save_file_manager.h b/chromium/content/browser/download/save_file_manager.h
index d6fd762b689..c6066f26686 100644
--- a/chromium/content/browser/download/save_file_manager.h
+++ b/chromium/content/browser/download/save_file_manager.h
@@ -22,7 +22,7 @@
// SaveFileManager on the file thread. SaveFileManager will directly
// call SaveFile's method to persist data.
//
-// A typical saving job operation involves multiple threads:
+// A typical saving job operation involves multiple threads and sequences:
//
// Updating an in progress save file
// io_thread
@@ -32,15 +32,15 @@
// |----> data from ---->| |
// | render process | |
// ui_thread | |
-// file_thread (writes to disk)
-// |----> stats ---->|
+// download_task_runner (writes to disk)
+// |----> stats ---->|
// ui_thread (feedback for user)
//
//
// Cancel operations perform the inverse order when triggered by a user action:
// ui_thread (user click)
// |----> cancel command ---->|
-// | | file_thread (close file)
+// | | download_task_runner (close file)
// | |---------------------> cancel command ---->|
// | io_thread (stops net IO
// ui_thread (user close contents) for saving)
diff --git a/chromium/content/browser/download/save_file_resource_handler.cc b/chromium/content/browser/download/save_file_resource_handler.cc
index 98b332de01c..017cc507063 100644
--- a/chromium/content/browser/download/save_file_resource_handler.cc
+++ b/chromium/content/browser/download/save_file_resource_handler.cc
@@ -8,9 +8,9 @@
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/string_number_conversions.h"
+#include "content/browser/download/download_task_runner.h"
#include "content/browser/download/save_file_manager.h"
#include "content/browser/loader/resource_controller.h"
-#include "content/public/browser/browser_thread.h"
#include "net/base/io_buffer.h"
#include "net/url_request/redirect_info.h"
#include "net/url_request/url_request_status.h"
@@ -54,9 +54,9 @@ void SaveFileResourceHandler::OnResponseStarted(
url_, final_url_, save_item_id_, save_package_id_, render_process_id_,
render_frame_routing_id_, GetRequestID(), content_disposition_,
content_length_);
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- base::Bind(&SaveFileManager::StartSave, save_manager_, info));
+ GetDownloadTaskRunner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&SaveFileManager::StartSave, save_manager_, info));
controller->Resume();
}
@@ -92,10 +92,10 @@ void SaveFileResourceHandler::OnReadCompleted(
// We are passing ownership of this buffer to the save file manager.
scoped_refptr<net::IOBuffer> buffer;
read_buffer_.swap(buffer);
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- base::Bind(&SaveFileManager::UpdateSaveProgress, save_manager_,
- save_item_id_, base::RetainedRef(buffer), bytes_read));
+ GetDownloadTaskRunner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&SaveFileManager::UpdateSaveProgress, save_manager_,
+ save_item_id_, base::RetainedRef(buffer), bytes_read));
controller->Resume();
}
@@ -105,11 +105,11 @@ void SaveFileResourceHandler::OnResponseCompleted(
if (authorization_state_ != AuthorizationState::AUTHORIZED)
DCHECK(!status.is_success());
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- base::Bind(&SaveFileManager::SaveFinished, save_manager_, save_item_id_,
- save_package_id_,
- status.is_success() && !status.is_io_pending()));
+ GetDownloadTaskRunner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&SaveFileManager::SaveFinished, save_manager_,
+ save_item_id_, save_package_id_,
+ status.is_success() && !status.is_io_pending()));
read_buffer_ = nullptr;
controller->Resume();
}
diff --git a/chromium/content/browser/download/save_package.cc b/chromium/content/browser/download/save_package.cc
index b6b6bd454ff..9bf08234ad6 100644
--- a/chromium/content/browser/download/save_package.cc
+++ b/chromium/content/browser/download/save_package.cc
@@ -20,13 +20,16 @@
#include "base/strings/string_split.h"
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/task_runner_util.h"
#include "base/threading/thread.h"
+#include "base/threading/thread_restrictions.h"
#include "build/build_config.h"
#include "components/url_formatter/url_formatter.h"
#include "content/browser/bad_message.h"
#include "content/browser/download/download_item_impl.h"
#include "content/browser/download/download_manager_impl.h"
#include "content/browser/download/download_stats.h"
+#include "content/browser/download/download_task_runner.h"
#include "content/browser/download/save_file.h"
#include "content/browser/download/save_file_manager.h"
#include "content/browser/download/save_item.h"
@@ -600,8 +603,8 @@ bool SavePackage::UpdateSaveProgress(SaveItemId save_item_id,
return true;
}
-// Stop all page saving jobs that are in progress and instruct the FILE thread
-// to delete all saved files.
+// Stop all page saving jobs that are in progress and instruct the download
+// sequence to delete all saved files.
void SavePackage::Stop(bool cancel_download_item) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
// If we haven't moved out of the initial state, there's nothing to cancel and
@@ -632,10 +635,9 @@ void SavePackage::Stop(bool cancel_download_item) {
for (const auto& it : saved_failed_items_)
save_item_ids.push_back(it.first);
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- base::Bind(&SaveFileManager::RemoveSavedFileFromFileMap, file_manager_,
- save_item_ids));
+ GetDownloadTaskRunner()->PostTask(
+ FROM_HERE, base::BindOnce(&SaveFileManager::RemoveSavedFileFromFileMap,
+ file_manager_, save_item_ids));
finished_ = true;
wait_state_ = FAILED;
@@ -661,15 +663,12 @@ void SavePackage::CheckFinish() {
for (const auto& it : saved_success_items_)
final_names.insert(std::make_pair(it.first, it.second->full_path()));
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- base::Bind(&SaveFileManager::RenameAllFiles,
- file_manager_,
- final_names,
- dir,
- web_contents()->GetRenderProcessHost()->GetID(),
- web_contents()->GetMainFrame()->GetRoutingID(),
- id()));
+ GetDownloadTaskRunner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&SaveFileManager::RenameAllFiles, file_manager_,
+ final_names, dir,
+ web_contents()->GetRenderProcessHost()->GetID(),
+ web_contents()->GetMainFrame()->GetRoutingID(), id()));
}
// Successfully finished all items of this SavePackage.
@@ -701,10 +700,9 @@ void SavePackage::Finish() {
list_of_failed_save_item_ids.push_back(save_item->id());
}
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- base::Bind(&SaveFileManager::RemoveSavedFileFromFileMap, file_manager_,
- list_of_failed_save_item_ids));
+ GetDownloadTaskRunner()->PostTask(
+ FROM_HERE, base::BindOnce(&SaveFileManager::RemoveSavedFileFromFileMap,
+ file_manager_, list_of_failed_save_item_ids));
if (download_) {
if (save_type_ != SAVE_PAGE_TYPE_AS_MHTML) {
@@ -768,9 +766,9 @@ void SavePackage::SaveFinished(SaveItemId save_item_id,
void SavePackage::SaveCanceled(const SaveItem* save_item) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
file_manager_->RemoveSaveFile(save_item->id(), this);
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- base::Bind(&SaveFileManager::CancelSave, file_manager_, save_item->id()));
+ GetDownloadTaskRunner()->PostTask(
+ FROM_HERE, base::BindOnce(&SaveFileManager::CancelSave, file_manager_,
+ save_item->id()));
}
void SavePackage::SaveNextFile(bool process_all_remaining_items) {
@@ -929,10 +927,10 @@ void SavePackage::GetSerializedHtmlWithLocalLinks() {
number_of_frames_pending_response_++;
} else {
// Notify SaveFileManager about the failure to save this SaveItem.
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- base::Bind(&SaveFileManager::SaveFinished, file_manager_,
- save_item->id(), id(), false));
+ GetDownloadTaskRunner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&SaveFileManager::SaveFinished, file_manager_,
+ save_item->id(), id(), false));
}
}
if (number_of_frames_pending_response_ == 0) {
@@ -1042,22 +1040,21 @@ void SavePackage::OnSerializedHtmlWithLocalLinksResponse(
scoped_refptr<net::IOBuffer> new_data(new net::IOBuffer(data.size()));
memcpy(new_data->data(), data.data(), data.size());
- // Call write file functionality in FILE thread.
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- base::Bind(&SaveFileManager::UpdateSaveProgress, file_manager_,
- save_item->id(), base::RetainedRef(new_data),
- static_cast<int>(data.size())));
+ // Call write file functionality in download sequence.
+ GetDownloadTaskRunner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&SaveFileManager::UpdateSaveProgress, file_manager_,
+ save_item->id(), base::RetainedRef(new_data),
+ static_cast<int>(data.size())));
}
- // Current frame is completed saving, call finish in FILE thread.
+ // Current frame is completed saving, call finish in download sequence.
if (end_of_data) {
DVLOG(20) << __func__ << "() save_item_id = " << save_item->id()
<< " url = \"" << save_item->url().spec() << "\"";
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- base::Bind(&SaveFileManager::SaveFinished, file_manager_,
- save_item->id(), id(), true));
+ GetDownloadTaskRunner()->PostTask(
+ FROM_HERE, base::BindOnce(&SaveFileManager::SaveFinished, file_manager_,
+ save_item->id(), id(), true));
number_of_frames_pending_response_--;
DCHECK_LE(0, number_of_frames_pending_response_);
}
@@ -1289,7 +1286,7 @@ base::FilePath SavePackage::GetSuggestedNameForSaveAs(
// static
base::FilePath SavePackage::EnsureHtmlExtension(const base::FilePath& name) {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ base::ThreadRestrictions::AssertIOAllowed();
base::FilePath::StringType ext = name.Extension();
if (!ext.empty())
@@ -1306,7 +1303,7 @@ base::FilePath SavePackage::EnsureHtmlExtension(const base::FilePath& name) {
// static
base::FilePath SavePackage::EnsureMimeExtension(const base::FilePath& name,
const std::string& contents_mime_type) {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ base::ThreadRestrictions::AssertIOAllowed();
// Start extension at 1 to skip over period if non-empty.
base::FilePath::StringType ext = name.Extension();
@@ -1346,8 +1343,8 @@ const base::FilePath::CharType* SavePackage::ExtensionForMimeType(
void SavePackage::GetSaveInfo() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- // Can't use |web_contents_| in the FILE thread, so get the data that we need
- // before calling to it.
+ // Can't use |web_contents_| in the download sequence, so get the data that we
+ // need before calling to it.
base::FilePath website_save_dir;
base::FilePath download_save_dir;
bool skip_dir_check = false;
@@ -1359,8 +1356,8 @@ void SavePackage::GetSaveInfo() {
}
std::string mime_type = web_contents()->GetContentsMimeType();
bool can_save_as_complete = CanSaveAsComplete(mime_type);
- BrowserThread::PostTaskAndReplyWithResult(
- BrowserThread::FILE, FROM_HERE,
+ base::PostTaskAndReplyWithResult(
+ GetDownloadTaskRunner().get(), FROM_HERE,
base::Bind(&SavePackage::CreateDirectoryOnFileThread, title_, page_url_,
can_save_as_complete, mime_type, website_save_dir,
download_save_dir, skip_dir_check),
@@ -1377,7 +1374,7 @@ base::FilePath SavePackage::CreateDirectoryOnFileThread(
const base::FilePath& website_save_dir,
const base::FilePath& download_save_dir,
bool skip_dir_check) {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ DCHECK(GetDownloadTaskRunner()->RunsTasksInCurrentSequence());
base::FilePath suggested_filename = GetSuggestedNameForSaveAs(
title, page_url, can_save_as_complete, mime_type);
@@ -1420,7 +1417,7 @@ void SavePackage::ContinueGetSaveInfo(bool can_save_as_complete,
DCHECK_CURRENTLY_ON(BrowserThread::UI);
// The WebContents which owns this SavePackage may have disappeared during
- // the UI->FILE->UI thread hop of
+ // the UI->download sequence->UI thread hop of
// GetSaveInfo->CreateDirectoryOnFileThread->ContinueGetSaveInfo.
if (!web_contents() || !download_manager_->GetDelegate())
return;
diff --git a/chromium/content/browser/download/save_package.h b/chromium/content/browser/download/save_package.h
index 7a4fb8ce2fa..b7a8ab93b8e 100644
--- a/chromium/content/browser/download/save_package.h
+++ b/chromium/content/browser/download/save_package.h
@@ -100,7 +100,7 @@ class CONTENT_EXPORT SavePackage
void Finish();
- // Notifications sent from the FILE thread to the UI thread.
+ // Notifications sent from the download sequence to the UI thread.
void StartSave(const SaveFileCreateInfo* info);
bool UpdateSaveProgress(SaveItemId save_item_id,
int64_t size,
@@ -386,7 +386,7 @@ class CONTENT_EXPORT SavePackage
// Map of all saving job which are successfully saved.
SaveItemIdMap saved_success_items_;
- // Non-owning pointer for handling file writing on the FILE thread.
+ // Non-owning pointer for handling file writing on the download sequence.
SaveFileManager* file_manager_ = nullptr;
// DownloadManager owns the DownloadItem and handles history and UI.
diff --git a/chromium/content/browser/download/save_package_browsertest.cc b/chromium/content/browser/download/save_package_browsertest.cc
index c8ad8b418e7..6d4eb46c736 100644
--- a/chromium/content/browser/download/save_package_browsertest.cc
+++ b/chromium/content/browser/download/save_package_browsertest.cc
@@ -61,7 +61,7 @@ class DownloadicidalObserver : public DownloadManager::Observer {
void OnDownloadCreated(DownloadManager* manager,
DownloadItem* item) override {
base::SequencedTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(
+ FROM_HERE, base::BindOnce(
[](bool remove_download, const base::Closure& closure,
DownloadItem* item) {
remove_download ? item->Remove() : item->Cancel(true);
diff --git a/chromium/content/browser/download/url_download_handler.cc b/chromium/content/browser/download/url_download_handler.cc
new file mode 100644
index 00000000000..0a2f5fc506c
--- /dev/null
+++ b/chromium/content/browser/download/url_download_handler.cc
@@ -0,0 +1,19 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/download/url_download_handler.h"
+
+namespace content {
+
+UrlDownloadHandler::InputStream::InputStream(
+ std::unique_ptr<ByteStreamReader> stream_reader)
+ : stream_reader_(std::move(stream_reader)) {}
+
+UrlDownloadHandler::InputStream::InputStream(
+ mojo::ScopedDataPipeConsumerHandle body)
+ : body_(std::move(body)) {}
+
+UrlDownloadHandler::InputStream::~InputStream() = default;
+
+} // namespace content
diff --git a/chromium/content/browser/download/url_download_handler.h b/chromium/content/browser/download/url_download_handler.h
new file mode 100644
index 00000000000..7a7ac1b1cf2
--- /dev/null
+++ b/chromium/content/browser/download/url_download_handler.h
@@ -0,0 +1,49 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_DOWNLOAD_URL_DOWNLOAD_HANDLER
+#define CONTENT_BROWSER_DOWNLOAD_URL_DOWNLOAD_HANDLER
+
+#include "content/browser/byte_stream.h"
+#include "content/public/browser/download_url_parameters.h"
+#include "content/public/common/url_loader.mojom.h"
+
+namespace content {
+
+struct DownloadCreateInfo;
+
+// Class for handling the download of a url. Implemented by child classes.
+class CONTENT_EXPORT UrlDownloadHandler {
+ public:
+ // InputStream to read after the download starts. Only one of them could be
+ // available at the same time.
+ struct CONTENT_EXPORT InputStream {
+ explicit InputStream(std::unique_ptr<ByteStreamReader> stream_reader);
+ explicit InputStream(mojo::ScopedDataPipeConsumerHandle body);
+ ~InputStream();
+
+ std::unique_ptr<ByteStreamReader> stream_reader_;
+ mojo::ScopedDataPipeConsumerHandle body_;
+ };
+
+ // Class to be notified when download starts/stops.
+ class CONTENT_EXPORT Delegate {
+ public:
+ virtual void OnUrlDownloadStarted(
+ std::unique_ptr<DownloadCreateInfo> download_create_info,
+ std::unique_ptr<InputStream> input_stream,
+ const DownloadUrlParameters::OnStartedCallback& callback) = 0;
+ // Called after the connection is cancelled or finished.
+ virtual void OnUrlDownloadStopped(UrlDownloadHandler* downloader) = 0;
+ };
+
+ UrlDownloadHandler() = default;
+ virtual ~UrlDownloadHandler() = default;
+
+ DISALLOW_COPY_AND_ASSIGN(UrlDownloadHandler);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_DOWNLOAD_URL_DOWNLOAD_HANDLER
diff --git a/chromium/content/browser/download/url_downloader.cc b/chromium/content/browser/download/url_downloader.cc
index be20bb891de..f240cb63469 100644
--- a/chromium/content/browser/download/url_downloader.cc
+++ b/chromium/content/browser/download/url_downloader.cc
@@ -44,15 +44,15 @@ class UrlDownloader::RequestHandle : public DownloadRequestHandleInterface {
DownloadManager* GetDownloadManager() const override { return nullptr; }
void PauseRequest() const override {
downloader_task_runner_->PostTask(
- FROM_HERE, base::Bind(&UrlDownloader::PauseRequest, downloader_));
+ FROM_HERE, base::BindOnce(&UrlDownloader::PauseRequest, downloader_));
}
void ResumeRequest() const override {
downloader_task_runner_->PostTask(
- FROM_HERE, base::Bind(&UrlDownloader::ResumeRequest, downloader_));
+ FROM_HERE, base::BindOnce(&UrlDownloader::ResumeRequest, downloader_));
}
void CancelRequest(bool user_cancel) const override {
downloader_task_runner_->PostTask(
- FROM_HERE, base::Bind(&UrlDownloader::CancelRequest, downloader_));
+ FROM_HERE, base::BindOnce(&UrlDownloader::CancelRequest, downloader_));
}
private:
@@ -64,7 +64,7 @@ class UrlDownloader::RequestHandle : public DownloadRequestHandleInterface {
// static
std::unique_ptr<UrlDownloader> UrlDownloader::BeginDownload(
- base::WeakPtr<UrlDownloader::Delegate> delegate,
+ base::WeakPtr<UrlDownloadHandler::Delegate> delegate,
std::unique_ptr<net::URLRequest> request,
const Referrer& referrer,
bool is_parallel_request) {
@@ -84,9 +84,10 @@ std::unique_ptr<UrlDownloader> UrlDownloader::BeginDownload(
return downloader;
}
-UrlDownloader::UrlDownloader(std::unique_ptr<net::URLRequest> request,
- base::WeakPtr<Delegate> delegate,
- bool is_parallel_request)
+UrlDownloader::UrlDownloader(
+ std::unique_ptr<net::URLRequest> request,
+ base::WeakPtr<UrlDownloadHandler::Delegate> delegate,
+ bool is_parallel_request)
: request_(std::move(request)),
delegate_(delegate),
core_(request_.get(), this, is_parallel_request),
@@ -143,8 +144,8 @@ void UrlDownloader::StartReading(bool is_continuation) {
if (!core_.OnWillRead(&buf, &buf_size)) {
int result = request_->CancelWithError(net::ERR_ABORTED);
base::SequencedTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&UrlDownloader::ResponseCompleted,
- weak_ptr_factory_.GetWeakPtr(), result));
+ FROM_HERE, base::BindOnce(&UrlDownloader::ResponseCompleted,
+ weak_ptr_factory_.GetWeakPtr(), result));
return;
}
@@ -163,9 +164,9 @@ void UrlDownloader::StartReading(bool is_continuation) {
// Else, trigger OnReadCompleted asynchronously to avoid starving the IO
// thread in case the URLRequest can provide data synchronously.
base::SequencedTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::Bind(&UrlDownloader::OnReadCompleted,
- weak_ptr_factory_.GetWeakPtr(), request_.get(), bytes_read));
+ FROM_HERE, base::BindOnce(&UrlDownloader::OnReadCompleted,
+ weak_ptr_factory_.GetWeakPtr(),
+ request_.get(), bytes_read));
}
}
@@ -215,9 +216,11 @@ void UrlDownloader::OnStart(
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&UrlDownloader::Delegate::OnUrlDownloaderStarted, delegate_,
- base::Passed(&create_info), base::Passed(&stream_reader),
- callback));
+ base::BindOnce(&UrlDownloadHandler::Delegate::OnUrlDownloadStarted,
+ delegate_, std::move(create_info),
+ base::MakeUnique<UrlDownloadHandler::InputStream>(
+ std::move(stream_reader)),
+ callback));
}
void UrlDownloader::OnReadyToRead() {
@@ -239,8 +242,8 @@ void UrlDownloader::CancelRequest() {
void UrlDownloader::Destroy() {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&UrlDownloader::Delegate::OnUrlDownloaderStopped, delegate_,
- this));
+ base::BindOnce(&UrlDownloadHandler::Delegate::OnUrlDownloadStopped,
+ delegate_, this));
}
} // namespace content
diff --git a/chromium/content/browser/download/url_downloader.h b/chromium/content/browser/download/url_downloader.h
index e5c5b90a51a..5f16838fb5d 100644
--- a/chromium/content/browser/download/url_downloader.h
+++ b/chromium/content/browser/download/url_downloader.h
@@ -11,6 +11,7 @@
#include "base/memory/weak_ptr.h"
#include "content/browser/download/download_request_core.h"
+#include "content/browser/download/url_download_handler.h"
#include "content/public/browser/download_interrupt_reasons.h"
#include "content/public/browser/download_save_info.h"
#include "content/public/browser/download_url_parameters.h"
@@ -23,29 +24,16 @@ class ByteStreamReader;
struct DownloadCreateInfo;
class UrlDownloader : public net::URLRequest::Delegate,
- public DownloadRequestCore::Delegate {
+ public DownloadRequestCore::Delegate,
+ public UrlDownloadHandler {
public:
- // Implemented by the owner of UrlDownloader, functions need to be called on
- // UI thread.
- class Delegate {
- public:
- // Called after response is handled and the byte stream is established.
- virtual void OnUrlDownloaderStarted(
- std::unique_ptr<DownloadCreateInfo> download_create_info,
- std::unique_ptr<ByteStreamReader> stream_reader,
- const DownloadUrlParameters::OnStartedCallback& callback) = 0;
-
- // Called after the connection is cannceled or finished.
- virtual void OnUrlDownloaderStopped(UrlDownloader* downloader) = 0;
- };
-
UrlDownloader(std::unique_ptr<net::URLRequest> request,
- base::WeakPtr<Delegate> delegate,
+ base::WeakPtr<UrlDownloadHandler::Delegate> delegate,
bool is_parallel_request);
~UrlDownloader() override;
static std::unique_ptr<UrlDownloader> BeginDownload(
- base::WeakPtr<UrlDownloader::Delegate> delegate,
+ base::WeakPtr<UrlDownloadHandler::Delegate> delegate,
std::unique_ptr<net::URLRequest> request,
const Referrer& referrer,
bool is_parallel_request);
@@ -84,7 +72,7 @@ class UrlDownloader : public net::URLRequest::Delegate,
std::unique_ptr<net::URLRequest> request_;
// Live on UI thread, post task to call |delegate_| functions.
- base::WeakPtr<Delegate> delegate_;
+ base::WeakPtr<UrlDownloadHandler::Delegate> delegate_;
DownloadRequestCore core_;
base::WeakPtrFactory<UrlDownloader> weak_ptr_factory_;
diff --git a/chromium/content/browser/file_descriptor_info_impl.cc b/chromium/content/browser/file_descriptor_info_impl.cc
deleted file mode 100644
index 1343e7c3141..00000000000
--- a/chromium/content/browser/file_descriptor_info_impl.cc
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/file_descriptor_info_impl.h"
-
-#include <utility>
-
-#include "base/memory/ptr_util.h"
-#include "base/stl_util.h"
-
-namespace content {
-
-// static
-std::unique_ptr<FileDescriptorInfo> FileDescriptorInfoImpl::Create() {
- return std::unique_ptr<FileDescriptorInfo>(new FileDescriptorInfoImpl());
-}
-
-FileDescriptorInfoImpl::FileDescriptorInfoImpl() {
-}
-
-FileDescriptorInfoImpl::~FileDescriptorInfoImpl() {
-}
-
-void FileDescriptorInfoImpl::Share(int id, base::PlatformFile fd) {
- ShareWithRegion(id, fd, base::MemoryMappedFile::Region::kWholeFile);
-}
-
-void FileDescriptorInfoImpl::ShareWithRegion(int id, base::PlatformFile fd,
- const base::MemoryMappedFile::Region& region) {
- AddToMapping(id, fd, region);
-}
-
-void FileDescriptorInfoImpl::Transfer(int id, base::ScopedFD fd) {
- AddToMapping(id, fd.get(), base::MemoryMappedFile::Region::kWholeFile);
- owned_descriptors_.push_back(std::move(fd));
-}
-
-base::PlatformFile FileDescriptorInfoImpl::GetFDAt(size_t i) const {
- return mapping_[i].first;
-}
-
-int FileDescriptorInfoImpl::GetIDAt(size_t i) const {
- return mapping_[i].second;
-}
-
-const base::MemoryMappedFile::Region& FileDescriptorInfoImpl::GetRegionAt(
- size_t i) const {
- auto iter = ids_to_regions_.find(GetIDAt(i));
- return (iter != ids_to_regions_.end()) ?
- iter->second : base::MemoryMappedFile::Region::kWholeFile;
-}
-
-size_t FileDescriptorInfoImpl::GetMappingSize() const {
- return mapping_.size();
-}
-
-bool FileDescriptorInfoImpl::HasID(int id) const {
- for (unsigned i = 0; i < mapping_.size(); ++i) {
- if (mapping_[i].second == id)
- return true;
- }
-
- return false;
-}
-
-bool FileDescriptorInfoImpl::OwnsFD(base::PlatformFile file) const {
- return base::ContainsValue(owned_descriptors_, file);
-}
-
-base::ScopedFD FileDescriptorInfoImpl::ReleaseFD(base::PlatformFile file) {
- DCHECK(OwnsFD(file));
-
- base::ScopedFD fd;
- auto found =
- std::find(owned_descriptors_.begin(), owned_descriptors_.end(), file);
-
- std::swap(*found, fd);
- owned_descriptors_.erase(found);
-
- return fd;
-}
-
-void FileDescriptorInfoImpl::AddToMapping(int id, base::PlatformFile fd,
- const base::MemoryMappedFile::Region& region) {
- DCHECK(!HasID(id));
- mapping_.push_back(std::make_pair(fd, id));
- if (region != base::MemoryMappedFile::Region::kWholeFile)
- ids_to_regions_[id] = region;
-}
-
-const base::FileHandleMappingVector& FileDescriptorInfoImpl::GetMapping()
- const {
- return mapping_;
-}
-
-std::unique_ptr<base::FileHandleMappingVector>
-FileDescriptorInfoImpl::GetMappingWithIDAdjustment(int delta) const {
- std::unique_ptr<base::FileHandleMappingVector> result =
- base::MakeUnique<base::FileHandleMappingVector>(mapping_);
- // Adding delta to each ID.
- for (unsigned i = 0; i < mapping_.size(); ++i)
- (*result)[i].second += delta;
- return result;
-}
-
-} // namespace content
diff --git a/chromium/content/browser/fileapi/browser_file_system_helper.cc b/chromium/content/browser/fileapi/browser_file_system_helper.cc
index f8da5a6ad26..23f303a4ff4 100644
--- a/chromium/content/browser/fileapi/browser_file_system_helper.cc
+++ b/chromium/content/browser/fileapi/browser_file_system_helper.cc
@@ -13,7 +13,7 @@
#include "base/files/file_path.h"
#include "base/sequenced_task_runner.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/threading/sequenced_worker_pool.h"
+#include "base/task_scheduler/lazy_task_runner.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
@@ -36,11 +36,19 @@
#include "url/gurl.h"
#include "url/url_constants.h"
+using storage::FileSystemOptions;
+
namespace content {
namespace {
-using storage::FileSystemOptions;
+// All FileSystemContexts currently need to share the same sequence per sharing
+// global objects: https://codereview.chromium.org/2883403002#msg14.
+base::LazySequencedTaskRunner g_fileapi_task_runner =
+ LAZY_SEQUENCED_TASK_RUNNER_INITIALIZER(
+ base::TaskTraits(base::MayBlock(),
+ base::TaskPriority::USER_VISIBLE,
+ base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN));
FileSystemOptions CreateBrowserFileSystemOptions(bool is_incognito) {
FileSystemOptions::ProfileMode profile_mode =
@@ -63,12 +71,6 @@ scoped_refptr<storage::FileSystemContext> CreateFileSystemContext(
const base::FilePath& profile_path,
bool is_incognito,
storage::QuotaManagerProxy* quota_manager_proxy) {
- base::SequencedWorkerPool* pool = BrowserThread::GetBlockingPool();
- scoped_refptr<base::SequencedTaskRunner> file_task_runner =
- pool->GetSequencedTaskRunnerWithShutdownBehavior(
- pool->GetNamedSequenceToken("FileAPI"),
- base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
-
// Setting up additional filesystem backends.
std::vector<std::unique_ptr<storage::FileSystemBackend>> additional_backends;
GetContentClient()->browser()->GetAdditionalFileSystemBackends(
@@ -85,7 +87,7 @@ scoped_refptr<storage::FileSystemContext> CreateFileSystemContext(
scoped_refptr<storage::FileSystemContext> file_system_context =
new storage::FileSystemContext(
BrowserThread::GetTaskRunnerForThread(BrowserThread::IO).get(),
- file_task_runner.get(),
+ g_fileapi_task_runner.Get().get(),
BrowserContext::GetMountPoints(browser_context),
browser_context->GetSpecialStoragePolicy(), quota_manager_proxy,
std::move(additional_backends), url_request_auto_mount_handlers,
diff --git a/chromium/content/browser/fileapi/file_system_browsertest.cc b/chromium/content/browser/fileapi/file_system_browsertest.cc
index ed7fa379666..cce4e1155d0 100644
--- a/chromium/content/browser/fileapi/file_system_browsertest.cc
+++ b/chromium/content/browser/fileapi/file_system_browsertest.cc
@@ -64,7 +64,7 @@ class FileSystemBrowserTestWithLowQuota : public FileSystemBrowserTest {
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&FileSystemBrowserTestWithLowQuota::SetLowQuota, qm));
+ base::BindOnce(&FileSystemBrowserTestWithLowQuota::SetLowQuota, qm));
return;
}
DCHECK_CURRENTLY_ON(BrowserThread::IO);
diff --git a/chromium/content/browser/fileapi/file_system_operation_runner_unittest.cc b/chromium/content/browser/fileapi/file_system_operation_runner_unittest.cc
index 168d52eddf2..e20a4e859fc 100644
--- a/chromium/content/browser/fileapi/file_system_operation_runner_unittest.cc
+++ b/chromium/content/browser/fileapi/file_system_operation_runner_unittest.cc
@@ -9,6 +9,7 @@
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/task_scheduler/post_task.h"
+#include "base/task_scheduler/task_scheduler.h"
#include "base/task_scheduler/task_traits.h"
#include "base/test/scoped_task_environment.h"
#include "base/threading/thread_restrictions.h"
@@ -238,13 +239,8 @@ TEST_F(MultiThreadFileSystemOperationRunnerTest, OpenAndShutdown) {
base::Bind(&DidOpenFile));
operation_runner()->Shutdown();
- // Wait until the task posted on FILE thread is done.
- base::RunLoop run_loop;
- BrowserThread::PostTaskAndReply(
- BrowserThread::FILE, FROM_HERE,
- base::Bind(&base::DoNothing),
- run_loop.QuitClosure());
- run_loop.Run();
+ // Wait until the task posted on the blocking thread is done.
+ base::TaskScheduler::GetInstance()->FlushForTesting();
// This should finish without thread assertion failure on debug build.
}
diff --git a/chromium/content/browser/fileapi/fileapi_message_filter.cc b/chromium/content/browser/fileapi/fileapi_message_filter.cc
index 543f16cf8d0..9df198709dd 100644
--- a/chromium/content/browser/fileapi/fileapi_message_filter.cc
+++ b/chromium/content/browser/fileapi/fileapi_message_filter.cc
@@ -167,8 +167,10 @@ void FileAPIMessageFilter::OnOpenFileSystem(int request_id,
}
storage::OpenFileSystemMode mode =
storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT;
- context_->OpenFileSystem(origin_url, type, mode, base::Bind(
- &FileAPIMessageFilter::DidOpenFileSystem, this, request_id));
+ context_->OpenFileSystem(
+ origin_url, type, mode,
+ base::BindOnce(&FileAPIMessageFilter::DidOpenFileSystem, this,
+ request_id));
}
void FileAPIMessageFilter::OnResolveURL(
@@ -331,8 +333,8 @@ void FileAPIMessageFilter::OnReadDirectory(
}
operations_[request_id] = operation_runner()->ReadDirectory(
- url, base::Bind(&FileAPIMessageFilter::DidReadDirectory,
- this, request_id));
+ url, base::BindRepeating(&FileAPIMessageFilter::DidReadDirectory, this,
+ request_id));
}
void FileAPIMessageFilter::OnWrite(int request_id,
@@ -499,11 +501,12 @@ void FileAPIMessageFilter::DidGetMetadataForStreaming(
void FileAPIMessageFilter::DidReadDirectory(
int request_id,
base::File::Error result,
- const std::vector<storage::DirectoryEntry>& entries,
+ std::vector<storage::DirectoryEntry> entries,
bool has_more) {
if (result == base::File::FILE_OK) {
if (!entries.empty() || !has_more)
- Send(new FileSystemMsg_DidReadDirectory(request_id, entries, has_more));
+ Send(new FileSystemMsg_DidReadDirectory(request_id, std::move(entries),
+ has_more));
} else {
DCHECK(!has_more);
Send(new FileSystemMsg_DidFail(request_id, result));
@@ -571,7 +574,7 @@ void FileAPIMessageFilter::DidCreateSnapshot(
base::File::Error result,
const base::File::Info& info,
const base::FilePath& platform_path,
- const scoped_refptr<storage::ShareableFileReference>& /* unused */) {
+ scoped_refptr<storage::ShareableFileReference> /* unused */) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
operations_.erase(request_id);
diff --git a/chromium/content/browser/fileapi/fileapi_message_filter.h b/chromium/content/browser/fileapi/fileapi_message_filter.h
index e1a86e1afce..a4766ee8763 100644
--- a/chromium/content/browser/fileapi/fileapi_message_filter.h
+++ b/chromium/content/browser/fileapi/fileapi_message_filter.h
@@ -128,7 +128,7 @@ class CONTENT_EXPORT FileAPIMessageFilter : public BrowserMessageFilter {
const base::File::Info& info);
void DidReadDirectory(int request_id,
base::File::Error result,
- const std::vector<storage::DirectoryEntry>& entries,
+ std::vector<storage::DirectoryEntry> entries,
bool has_more);
void DidWrite(int request_id,
base::File::Error result,
@@ -149,7 +149,7 @@ class CONTENT_EXPORT FileAPIMessageFilter : public BrowserMessageFilter {
base::File::Error result,
const base::File::Info& info,
const base::FilePath& platform_path,
- const scoped_refptr<storage::ShareableFileReference>& file_ref);
+ scoped_refptr<storage::ShareableFileReference> file_ref);
// Sends a FileSystemMsg_DidFail and returns false if |url| is invalid.
bool ValidateFileSystemURL(int request_id, const storage::FileSystemURL& url);
diff --git a/chromium/content/browser/fileapi/upload_file_system_file_element_reader.h b/chromium/content/browser/fileapi/upload_file_system_file_element_reader.h
index 3a9ab9c8dab..be6e313da3f 100644
--- a/chromium/content/browser/fileapi/upload_file_system_file_element_reader.h
+++ b/chromium/content/browser/fileapi/upload_file_system_file_element_reader.h
@@ -27,8 +27,8 @@ class FileSystemContext;
namespace content {
// An UploadElementReader implementation for filesystem file.
-class CONTENT_EXPORT UploadFileSystemFileElementReader :
- NON_EXPORTED_BASE(public net::UploadElementReader) {
+class CONTENT_EXPORT UploadFileSystemFileElementReader
+ : public net::UploadElementReader {
public:
UploadFileSystemFileElementReader(
storage::FileSystemContext* file_system_context,
diff --git a/chromium/content/browser/fileapi/upload_file_system_file_element_reader_unittest.cc b/chromium/content/browser/fileapi/upload_file_system_file_element_reader_unittest.cc
index 64c7b500d29..d248c036bfe 100644
--- a/chromium/content/browser/fileapi/upload_file_system_file_element_reader_unittest.cc
+++ b/chromium/content/browser/fileapi/upload_file_system_file_element_reader_unittest.cc
@@ -49,11 +49,10 @@ class UploadFileSystemFileElementReaderTest : public testing::Test {
CreateFileSystemContextForTesting(NULL, temp_dir_.GetPath());
file_system_context_->OpenFileSystem(
- GURL(kFileSystemURLOrigin),
- kFileSystemType,
+ GURL(kFileSystemURLOrigin), kFileSystemType,
storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
- base::Bind(&UploadFileSystemFileElementReaderTest::OnOpenFileSystem,
- base::Unretained(this)));
+ base::BindOnce(&UploadFileSystemFileElementReaderTest::OnOpenFileSystem,
+ base::Unretained(this)));
base::RunLoop().RunUntilIdle();
ASSERT_TRUE(file_system_root_url_.is_valid());
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 576b7447019..173f3378316 100644
--- a/chromium/content/browser/frame_host/cross_process_frame_connector.cc
+++ b/chromium/content/browser/frame_host/cross_process_frame_connector.cc
@@ -4,21 +4,21 @@
#include "content/browser/frame_host/cross_process_frame_connector.h"
-#include "cc/surfaces/surface.h"
-#include "cc/surfaces/surface_hittest.h"
#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
+#include "components/viz/service/surfaces/surface.h"
+#include "components/viz/service/surfaces/surface_hittest.h"
#include "content/browser/compositor/surface_utils.h"
#include "content/browser/frame_host/frame_tree.h"
#include "content/browser/frame_host/frame_tree_node.h"
#include "content/browser/frame_host/render_frame_host_manager.h"
#include "content/browser/frame_host/render_frame_proxy_host.h"
-#include "content/browser/frame_host/render_widget_host_view_child_frame.h"
#include "content/browser/renderer_host/cursor_manager.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_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/renderer_host/render_widget_host_view_child_frame.h"
#include "content/common/frame_messages.h"
#include "gpu/ipc/common/gpu_messages.h"
#include "third_party/WebKit/public/platform/WebInputEvent.h"
@@ -34,7 +34,7 @@ CrossProcessFrameConnector::CrossProcessFrameConnector(
CrossProcessFrameConnector::~CrossProcessFrameConnector() {
// Notify the view of this object being destroyed, if the view still exists.
- set_view(nullptr);
+ SetView(nullptr);
}
bool CrossProcessFrameConnector::OnMessageReceived(const IPC::Message& msg) {
@@ -54,15 +54,14 @@ bool CrossProcessFrameConnector::OnMessageReceived(const IPC::Message& msg) {
return handled;
}
-void CrossProcessFrameConnector::set_view(
- RenderWidgetHostViewChildFrame* view) {
+void CrossProcessFrameConnector::SetView(RenderWidgetHostViewChildFrame* view) {
// Detach ourselves from the previous |view_|.
if (view_) {
RenderWidgetHostViewBase* root_view = GetRootRenderWidgetHostView();
if (root_view && root_view->GetCursorManager())
root_view->GetCursorManager()->ViewBeingDestroyed(view_);
- // The RenderWidgetHostDelegate needs to be checked because set_view() can
+ // The RenderWidgetHostDelegate needs to be checked because SetView() can
// be called during nested WebContents destruction. See
// https://crbug.com/644306.
if (is_scroll_bubbling_ && GetParentRenderWidgetHostView() &&
@@ -76,15 +75,23 @@ void CrossProcessFrameConnector::set_view(
->CancelScrollBubbling(view_);
is_scroll_bubbling_ = false;
}
- view_->SetCrossProcessFrameConnector(nullptr);
+ view_->SetFrameConnectorDelegate(nullptr);
}
+ ResetFrameRect();
view_ = view;
- // Attach ourselves to the new view and size it appropriately.
+ // Attach ourselves to the new view and size it appropriately. Also update
+ // visibility in case the frame owner is hidden in parent process. We should
+ // try to move these updates to a single IPC (see https://crbug.com/750179).
if (view_) {
- view_->SetCrossProcessFrameConnector(this);
+ view_->SetFrameConnectorDelegate(this);
SetRect(child_frame_rect_);
+ if (is_hidden_)
+ OnVisibilityChanged(false);
+ frame_proxy_in_parent_renderer_->Send(new FrameMsg_ViewChanged(
+ frame_proxy_in_parent_renderer_->GetRoutingID(),
+ view_->GetFrameSinkId()));
}
}
@@ -146,7 +153,8 @@ bool CrossProcessFrameConnector::TransformPointToLocalCoordSpace(
// is necessary.
*transformed_point =
gfx::ConvertPointToPixel(view_->current_surface_scale_factor(), point);
- cc::SurfaceHittest hittest(nullptr, GetFrameSinkManager()->surface_manager());
+ viz::SurfaceHittest hittest(nullptr,
+ GetFrameSinkManager()->surface_manager());
if (!hittest.TransformPointToTargetSurface(original_surface, local_surface_id,
transformed_point))
return false;
@@ -263,7 +271,9 @@ void CrossProcessFrameConnector::UnlockMouse() {
}
void CrossProcessFrameConnector::OnFrameRectChanged(
- const gfx::Rect& frame_rect) {
+ const gfx::Rect& frame_rect,
+ const viz::LocalSurfaceId& local_surface_id) {
+ local_surface_id_ = local_surface_id;
if (!frame_rect.size().IsEmpty())
SetRect(frame_rect);
}
@@ -276,6 +286,7 @@ void CrossProcessFrameConnector::OnUpdateViewportIntersection(
}
void CrossProcessFrameConnector::OnVisibilityChanged(bool visible) {
+ is_hidden_ = !visible;
if (!view_)
return;
@@ -372,4 +383,24 @@ CrossProcessFrameConnector::GetParentRenderWidgetHostView() {
return nullptr;
}
+bool CrossProcessFrameConnector::IsInert() const {
+ return is_inert_;
+}
+
+bool CrossProcessFrameConnector::IsHidden() const {
+ return is_hidden_;
+}
+
+void CrossProcessFrameConnector::SetVisibilityForChildViews(
+ bool visible) const {
+ frame_proxy_in_parent_renderer_->frame_tree_node()
+ ->current_frame_host()
+ ->SetVisibilityForChildViews(visible);
+}
+
+void CrossProcessFrameConnector::ResetFrameRect() {
+ local_surface_id_ = viz::LocalSurfaceId();
+ child_frame_rect_ = gfx::Rect();
+}
+
} // namespace content
diff --git a/chromium/content/browser/frame_host/cross_process_frame_connector.h b/chromium/content/browser/frame_host/cross_process_frame_connector.h
index 46d6f9edd8d..43468081406 100644
--- a/chromium/content/browser/frame_host/cross_process_frame_connector.h
+++ b/chromium/content/browser/frame_host/cross_process_frame_connector.h
@@ -8,30 +8,16 @@
#include <stdint.h>
#include "cc/output/compositor_frame.h"
-#include "content/browser/renderer_host/event_with_latency_info.h"
+#include "components/viz/common/surfaces/local_surface_id.h"
+#include "content/browser/renderer_host/frame_connector_delegate.h"
#include "content/common/content_export.h"
-#include "content/common/input/input_event_ack_state.h"
-#include "ui/gfx/geometry/rect.h"
-
-namespace blink {
-class WebGestureEvent;
-}
namespace IPC {
class Message;
}
-namespace viz {
-class SurfaceId;
-class SurfaceInfo;
-struct SurfaceSequence;
-} // namespace viz
-
namespace content {
class RenderFrameProxyHost;
-class RenderWidgetHostViewBase;
-class RenderWidgetHostViewChildFrame;
-class WebCursor;
// CrossProcessFrameConnector provides the platform view abstraction for
// RenderWidgetHostViewChildFrame allowing RWHVChildFrame to remain ignorant
@@ -48,7 +34,7 @@ class WebCursor;
// | ----------- |
// -----------------
//
-// If frames 1 and 2 are in process A and B, there are 4 RenderFrameHosts:
+// If frames 1 and 2 are in process A and B, there are 4 hosts:
// A1 - RFH for frame 1 in process A
// B1 - RFPH for frame 1 in process B
// A2 - RFPH for frame 2 in process A
@@ -56,10 +42,10 @@ class WebCursor;
//
// B2, having a parent frame in a different process, will have a
// RenderWidgetHostViewChildFrame. This RenderWidgetHostViewChildFrame needs
-// to communicate with A2 because the embedding process is an abstract
-// for the child frame -- it needs information necessary for compositing child
-// frame textures, and also can pass platform messages such as view resizing.
-// CrossProcessFrameConnector bridges between B2's
+// to communicate with A2 because the embedding frame represents the platform
+// that the child frame is rendering into -- it needs information necessary for
+// compositing child frame textures, and also can pass platform messages such as
+// view resizing. CrossProcessFrameConnector bridges between B2's
// RenderWidgetHostViewChildFrame and A2 to allow for this communication.
// (Note: B1 is only mentioned for completeness. It is not needed in this
// example.)
@@ -67,77 +53,56 @@ class WebCursor;
// CrossProcessFrameConnector objects are owned by the RenderFrameProxyHost
// in the child frame's RenderFrameHostManager corresponding to the parent's
// SiteInstance, A2 in the picture above. When a child frame navigates in a new
-// process, set_view() is called to update to the new view.
+// process, SetView() is called to update to the new view.
//
-class CONTENT_EXPORT CrossProcessFrameConnector {
+class CONTENT_EXPORT CrossProcessFrameConnector
+ : public FrameConnectorDelegate {
public:
// |frame_proxy_in_parent_renderer| corresponds to A2 in the example above.
explicit CrossProcessFrameConnector(
RenderFrameProxyHost* frame_proxy_in_parent_renderer);
- virtual ~CrossProcessFrameConnector();
+ ~CrossProcessFrameConnector() override;
bool OnMessageReceived(const IPC::Message &msg);
// |view| corresponds to B2's RenderWidgetHostViewChildFrame in the example
// above.
- void set_view(RenderWidgetHostViewChildFrame* view);
RenderWidgetHostViewChildFrame* get_view_for_testing() { return view_; }
- void RenderProcessGone();
-
- virtual void SetChildFrameSurface(const viz::SurfaceInfo& surface_info,
- const viz::SurfaceSequence& sequence);
-
- gfx::Rect ChildFrameRect();
- void UpdateCursor(const WebCursor& cursor);
- gfx::Point TransformPointToRootCoordSpace(const gfx::Point& point,
- const viz::SurfaceId& surface_id);
- // TransformPointToLocalCoordSpace() can only transform points between
- // surfaces where one is embedded (not necessarily directly) within the
- // other, and will return false if this is not the case. For points that can
- // be in sibling surfaces, they must first be converted to the root
- // surface's coordinate space.
+ // FrameConnectorDelegate implementation.
+ void SetView(RenderWidgetHostViewChildFrame* view) override;
+ RenderWidgetHostViewBase* GetParentRenderWidgetHostView() override;
+ RenderWidgetHostViewBase* GetRootRenderWidgetHostView() override;
+ void RenderProcessGone() override;
+ void SetChildFrameSurface(const viz::SurfaceInfo& surface_info,
+ const viz::SurfaceSequence& sequence) override;
+ gfx::Rect ChildFrameRect() override;
+ void UpdateCursor(const WebCursor& cursor) override;
+ gfx::Point TransformPointToRootCoordSpace(
+ const gfx::Point& point,
+ const viz::SurfaceId& surface_id) override;
bool TransformPointToLocalCoordSpace(const gfx::Point& point,
const viz::SurfaceId& original_surface,
const viz::SurfaceId& local_surface_id,
- gfx::Point* transformed_point);
- // Returns false if |target_view| and |view_| do not have the same root
- // RenderWidgetHostView.
- bool TransformPointToCoordSpaceForView(const gfx::Point& point,
- RenderWidgetHostViewBase* target_view,
- const viz::SurfaceId& local_surface_id,
- gfx::Point* transformed_point);
-
- // Pass acked touch events to the root view for gesture processing.
+ gfx::Point* transformed_point) override;
+ bool TransformPointToCoordSpaceForView(
+ const gfx::Point& point,
+ RenderWidgetHostViewBase* target_view,
+ const viz::SurfaceId& local_surface_id,
+ gfx::Point* transformed_point) override;
void ForwardProcessAckedTouchEvent(const TouchEventWithLatencyInfo& touch,
- InputEventAckState ack_result);
- // Gesture events with unused scroll deltas must be bubbled to ancestors
- // who may consume the delta.
- void BubbleScrollEvent(const blink::WebGestureEvent& event);
-
- // Determines whether the root RenderWidgetHostView (and thus the current
- // page) has focus.
- bool HasFocus();
- // Focuses the root RenderWidgetHostView.
- void FocusRootView();
-
- // Locks the mouse. Returns true if mouse is locked.
- bool LockMouse();
-
- // Unlocks the mouse if the mouse is locked.
- void UnlockMouse();
-
- // Returns the parent RenderWidgetHostView or nullptr it it doesn't have one.
- virtual RenderWidgetHostViewBase* GetParentRenderWidgetHostView();
-
- // Returns the view for the top-level frame under the same WebContents.
- RenderWidgetHostViewBase* GetRootRenderWidgetHostView();
-
- const gfx::Rect& viewport_intersection() const {
- return viewport_intersection_rect_;
- }
-
- bool is_inert() const { return is_inert_; }
+ InputEventAckState ack_result) override;
+ void BubbleScrollEvent(const blink::WebGestureEvent& event) override;
+ bool HasFocus() override;
+ void FocusRootView() override;
+ bool LockMouse() override;
+ void UnlockMouse() override;
+ bool IsInert() const override;
+ bool IsHidden() const override;
+
+ // Set the visibility of immediate child views, i.e. views whose parent view
+ // is |view_|.
+ void SetVisibilityForChildViews(bool visible) const override;
// Exposed for tests.
RenderWidgetHostViewBase* GetRootRenderWidgetHostViewForTesting() {
@@ -147,8 +112,13 @@ class CONTENT_EXPORT CrossProcessFrameConnector {
private:
friend class MockCrossProcessFrameConnector;
+ // Resets the rect and the viz::LocalSurfaceId of the connector to ensure the
+ // unguessable surface ID is not reused after a cross-process navigation.
+ void ResetFrameRect();
+
// Handlers for messages received from the parent frame.
- void OnFrameRectChanged(const gfx::Rect& frame_rect);
+ void OnFrameRectChanged(const gfx::Rect& frame_rect,
+ const viz::LocalSurfaceId& local_surface_id);
void OnUpdateViewportIntersection(const gfx::Rect& viewport_intersection);
void OnVisibilityChanged(bool visible);
void OnSetIsInert(bool);
@@ -166,9 +136,12 @@ class CONTENT_EXPORT CrossProcessFrameConnector {
RenderWidgetHostViewChildFrame* view_;
gfx::Rect child_frame_rect_;
- gfx::Rect viewport_intersection_rect_;
bool is_inert_ = false;
+ // Visibility state of the corresponding frame owner element in parent process
+ // which is set through CSS.
+ bool is_hidden_ = false;
+
bool is_scroll_bubbling_;
};
diff --git a/chromium/content/browser/frame_host/debug_urls.cc b/chromium/content/browser/frame_host/debug_urls.cc
index bcf53d5960e..c1764c51128 100644
--- a/chromium/content/browser/frame_host/debug_urls.cc
+++ b/chromium/content/browser/frame_host/debug_urls.cc
@@ -161,7 +161,7 @@ bool HandleDebugURL(const GURL& url, ui::PageTransition transition) {
// 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::Bind(&HangCurrentThread),
+ base::BindOnce(&HangCurrentThread),
base::TimeDelta::FromSeconds(2));
return true;
}
@@ -210,7 +210,7 @@ bool HandleDebugURL(const GURL& url, ui::PageTransition transition) {
if (url == kChromeUIPpapiFlashCrashURL || url == kChromeUIPpapiFlashHangURL) {
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::Bind(&HandlePpapiFlashDebugURL, url));
+ base::BindOnce(&HandlePpapiFlashDebugURL, url));
return true;
}
diff --git a/chromium/content/browser/frame_host/frame_tree.cc b/chromium/content/browser/frame_host/frame_tree.cc
index ed6b885f8a2..837907acd72 100644
--- a/chromium/content/browser/frame_host/frame_tree.cc
+++ b/chromium/content/browser/frame_host/frame_tree.cc
@@ -289,7 +289,6 @@ void FrameTree::SetFocusedFrame(FrameTreeNode* node, SiteInstance* source) {
// below.
for (auto* instance : frame_tree_site_instances) {
if (instance != source && instance != current_instance) {
- DCHECK(SiteIsolationPolicy::AreCrossProcessFramesPossible());
RenderFrameProxyHost* proxy =
node->render_manager()->GetRenderFrameProxyHost(instance);
proxy->SetFocusedFrame();
diff --git a/chromium/content/browser/frame_host/frame_tree_node.cc b/chromium/content/browser/frame_host/frame_tree_node.cc
index 27e700e674d..933c86b9950 100644
--- a/chromium/content/browser/frame_host/frame_tree_node.cc
+++ b/chromium/content/browser/frame_host/frame_tree_node.cc
@@ -97,11 +97,17 @@ class FrameTreeNode::OpenerDestroyedObserver : public FrameTreeNode::Observer {
// FrameTreeNode::Observer
void OnFrameTreeNodeDestroyed(FrameTreeNode* node) override {
if (observing_original_opener_) {
+ // The "original owner" is special. It's used for attribution, and clients
+ // walk down the original owner chain. Therefore, if a link in the chain
+ // is being destroyed, reconnect the observation to the parent of the link
+ // being destroyed.
CHECK_EQ(owner_->original_opener(), node);
- owner_->SetOriginalOpener(nullptr);
+ owner_->SetOriginalOpener(node->original_opener());
+ // |this| is deleted at this point.
} else {
CHECK_EQ(owner_->opener(), node);
owner_->SetOpener(nullptr);
+ // |this| is deleted at this point.
}
}
@@ -141,9 +147,7 @@ FrameTreeNode::FrameTreeNode(FrameTree* frame_tree,
frame_tree_node_id_(next_frame_tree_node_id_++),
parent_(parent),
opener_(nullptr),
- opener_observer_(nullptr),
original_opener_(nullptr),
- original_opener_observer_(nullptr),
has_committed_real_load_(false),
is_collapsed_(false),
replication_state_(
@@ -220,9 +224,7 @@ FrameTreeNode* FrameTreeNode::AddChild(std::unique_ptr<FrameTreeNode> child,
// 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.
- // TODO(alexmos, nick): We ought to do this for non-oopif too, for openers.
- if (SiteIsolationPolicy::AreCrossProcessFramesPossible())
- render_manager_.CreateProxiesForChildFrame(child.get());
+ render_manager_.CreateProxiesForChildFrame(child.get());
children_.push_back(std::move(child));
return children_.back().get();
@@ -242,7 +244,7 @@ void FrameTreeNode::RemoveChild(FrameTreeNode* child) {
}
void FrameTreeNode::ResetForNewProcess() {
- current_frame_host()->set_last_committed_url(GURL());
+ current_frame_host()->SetLastCommittedUrl(GURL());
blame_context_.TakeSnapshot();
// Remove child nodes from the tree, then delete them. This destruction
@@ -259,20 +261,23 @@ void FrameTreeNode::SetOpener(FrameTreeNode* opener) {
opener_ = opener;
if (opener_) {
- if (!opener_observer_)
- opener_observer_ = base::MakeUnique<OpenerDestroyedObserver>(this, false);
+ opener_observer_ = base::MakeUnique<OpenerDestroyedObserver>(this, false);
opener_->AddObserver(opener_observer_.get());
}
}
void FrameTreeNode::SetOriginalOpener(FrameTreeNode* opener) {
- DCHECK(!original_opener_ || !opener);
+ // The original opener tracks main frames only.
DCHECK(opener == nullptr || !opener->parent());
+ if (original_opener_) {
+ original_opener_->RemoveObserver(original_opener_observer_.get());
+ original_opener_observer_.reset();
+ }
+
original_opener_ = opener;
if (original_opener_) {
- DCHECK(!original_opener_observer_);
original_opener_observer_ =
base::MakeUnique<OpenerDestroyedObserver>(this, true);
original_opener_->AddObserver(original_opener_observer_.get());
@@ -282,7 +287,7 @@ void FrameTreeNode::SetOriginalOpener(FrameTreeNode* opener) {
void FrameTreeNode::SetCurrentURL(const GURL& url) {
if (!has_committed_real_load_ && url != url::kAboutBlankURL)
has_committed_real_load_ = true;
- current_frame_host()->set_last_committed_url(url);
+ current_frame_host()->SetLastCommittedUrl(url);
blame_context_.TakeSnapshot();
}
diff --git a/chromium/content/browser/frame_host/input/input_injector_impl.cc b/chromium/content/browser/frame_host/input/input_injector_impl.cc
new file mode 100644
index 00000000000..cf14431c5ac
--- /dev/null
+++ b/chromium/content/browser/frame_host/input/input_injector_impl.cc
@@ -0,0 +1,82 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/frame_host/input/input_injector_impl.h"
+
+#include "content/browser/renderer_host/render_widget_host_impl.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
+
+namespace content {
+
+namespace {
+
+void SyntheticGestureCallback(base::OnceClosure callback,
+ SyntheticGesture::Result result) {
+ std::move(callback).Run();
+}
+
+} // namespace
+
+InputInjectorImpl::InputInjectorImpl(
+ base::WeakPtr<RenderFrameHostImpl> frame_host)
+ : frame_host_(std::move(frame_host)) {}
+
+InputInjectorImpl::~InputInjectorImpl() {}
+
+void InputInjectorImpl::Create(base::WeakPtr<RenderFrameHostImpl> frame_host,
+ mojom::InputInjectorRequest request) {
+ mojo::MakeStrongBinding(base::MakeUnique<InputInjectorImpl>(frame_host),
+ std::move(request));
+}
+
+void InputInjectorImpl::QueueSyntheticSmoothDrag(
+ const SyntheticSmoothDragGestureParams& drag,
+ QueueSyntheticSmoothDragCallback callback) {
+ if (!frame_host_)
+ return;
+ frame_host_->GetRenderWidgetHost()->QueueSyntheticGesture(
+ SyntheticGesture::Create(drag),
+ base::BindOnce(SyntheticGestureCallback, std::move(callback)));
+}
+
+void InputInjectorImpl::QueueSyntheticSmoothScroll(
+ const SyntheticSmoothScrollGestureParams& scroll,
+ QueueSyntheticSmoothScrollCallback callback) {
+ if (!frame_host_)
+ return;
+ frame_host_->GetRenderWidgetHost()->QueueSyntheticGesture(
+ SyntheticGesture::Create(scroll),
+ base::BindOnce(SyntheticGestureCallback, std::move(callback)));
+}
+
+void InputInjectorImpl::QueueSyntheticPinch(
+ const SyntheticPinchGestureParams& pinch,
+ QueueSyntheticPinchCallback callback) {
+ if (!frame_host_)
+ return;
+ frame_host_->GetRenderWidgetHost()->QueueSyntheticGesture(
+ SyntheticGesture::Create(pinch),
+ base::BindOnce(SyntheticGestureCallback, std::move(callback)));
+}
+
+void InputInjectorImpl::QueueSyntheticTap(const SyntheticTapGestureParams& tap,
+ QueueSyntheticTapCallback callback) {
+ if (!frame_host_)
+ return;
+ frame_host_->GetRenderWidgetHost()->QueueSyntheticGesture(
+ SyntheticGesture::Create(tap),
+ base::BindOnce(SyntheticGestureCallback, std::move(callback)));
+}
+
+void InputInjectorImpl::QueueSyntheticPointerAction(
+ const SyntheticPointerActionListParams& pointer_action,
+ QueueSyntheticPointerActionCallback callback) {
+ if (!frame_host_)
+ return;
+ frame_host_->GetRenderWidgetHost()->QueueSyntheticGesture(
+ SyntheticGesture::Create(pointer_action),
+ base::BindOnce(SyntheticGestureCallback, std::move(callback)));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/frame_host/input/input_injector_impl.h b/chromium/content/browser/frame_host/input/input_injector_impl.h
new file mode 100644
index 00000000000..492885484a2
--- /dev/null
+++ b/chromium/content/browser/frame_host/input/input_injector_impl.h
@@ -0,0 +1,45 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_FRAME_HOST_INPUT_INPUT_INJECTOR_IMPL_H_
+#define CONTENT_BROWSER_FRAME_HOST_INPUT_INPUT_INJECTOR_IMPL_H_
+
+#include "content/browser/frame_host/render_frame_host_impl.h"
+#include "content/common/input/input_injector.mojom.h"
+
+namespace content {
+
+// An implementation of InputInjector.
+class CONTENT_EXPORT InputInjectorImpl : public mojom::InputInjector {
+ public:
+ explicit InputInjectorImpl(base::WeakPtr<RenderFrameHostImpl> frame_host);
+ ~InputInjectorImpl() override;
+
+ static void Create(base::WeakPtr<RenderFrameHostImpl> frame_host,
+ mojom::InputInjectorRequest request);
+
+ // mojom::InputInjector overrides.
+ void QueueSyntheticSmoothDrag(
+ const SyntheticSmoothDragGestureParams& drag,
+ QueueSyntheticSmoothDragCallback callback) override;
+ void QueueSyntheticSmoothScroll(
+ const SyntheticSmoothScrollGestureParams& scroll,
+ QueueSyntheticSmoothScrollCallback callback) override;
+ void QueueSyntheticPinch(const SyntheticPinchGestureParams& pinch,
+ QueueSyntheticPinchCallback callback) override;
+ void QueueSyntheticTap(const SyntheticTapGestureParams& tap,
+ QueueSyntheticTapCallback callback) override;
+ void QueueSyntheticPointerAction(
+ const SyntheticPointerActionListParams& pointer_action,
+ QueueSyntheticPointerActionCallback callback) override;
+
+ private:
+ base::WeakPtr<RenderFrameHostImpl> frame_host_;
+
+ DISALLOW_COPY_AND_ASSIGN(InputInjectorImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_FRAME_HOST_INPUT_INPUT_INJECTOR_IMPL_H_
diff --git a/chromium/content/browser/frame_host/input/legacy_ipc_frame_input_handler.cc b/chromium/content/browser/frame_host/input/legacy_ipc_frame_input_handler.cc
index 849d9c1b633..f6325a92b89 100644
--- a/chromium/content/browser/frame_host/input/legacy_ipc_frame_input_handler.cc
+++ b/chromium/content/browser/frame_host/input/legacy_ipc_frame_input_handler.cc
@@ -11,6 +11,23 @@
namespace content {
+namespace {
+
+blink::WebImeTextSpan::Type ConvertUiImeTextSpanTypeToBlinkType(
+ ui::ImeTextSpan::Type type) {
+ switch (type) {
+ case ui::ImeTextSpan::Type::kComposition:
+ return blink::WebImeTextSpan::Type::kComposition;
+ case ui::ImeTextSpan::Type::kSuggestion:
+ return blink::WebImeTextSpan::Type::kSuggestion;
+ }
+
+ NOTREACHED();
+ return blink::WebImeTextSpan::Type::kComposition;
+}
+
+} // namespace
+
LegacyIPCFrameInputHandler::LegacyIPCFrameInputHandler(
RenderFrameHostImpl* frame_host)
: frame_host_(frame_host), routing_id_(frame_host->GetRoutingID()) {}
@@ -20,17 +37,20 @@ LegacyIPCFrameInputHandler::~LegacyIPCFrameInputHandler() {}
void LegacyIPCFrameInputHandler::SetCompositionFromExistingText(
int32_t start,
int32_t end,
- const std::vector<ui::CompositionUnderline>& ui_underlines) {
- std::vector<blink::WebCompositionUnderline> underlines;
- for (const auto& underline : ui_underlines) {
- blink::WebCompositionUnderline blink_underline(
- underline.start_offset, underline.end_offset, underline.color,
- underline.thick, underline.background_color);
- underlines.push_back(blink_underline);
+ const std::vector<ui::ImeTextSpan>& ui_ime_text_spans) {
+ std::vector<blink::WebImeTextSpan> ime_text_spans;
+ for (const auto& ime_text_span : ui_ime_text_spans) {
+ blink::WebImeTextSpan blink_ime_text_span(
+ ConvertUiImeTextSpanTypeToBlinkType(ime_text_span.type),
+ ime_text_span.start_offset, ime_text_span.end_offset,
+ ime_text_span.underline_color, ime_text_span.thick,
+ ime_text_span.background_color,
+ ime_text_span.suggestion_highlight_color, ime_text_span.suggestions);
+ ime_text_spans.push_back(blink_ime_text_span);
}
SendInput(base::MakeUnique<InputMsg_SetCompositionFromExistingText>(
- routing_id_, start, end, underlines));
+ routing_id_, start, end, ime_text_spans));
}
void LegacyIPCFrameInputHandler::ExtendSelectionAndDelete(int32_t before,
@@ -145,6 +165,11 @@ void LegacyIPCFrameInputHandler::MoveCaret(const gfx::Point& point) {
SendInput(base::MakeUnique<InputMsg_MoveCaret>(routing_id_, point));
}
+void LegacyIPCFrameInputHandler::GetWidgetInputHandler(
+ mojom::WidgetInputHandlerAssociatedRequest interface_request) {
+ NOTREACHED();
+}
+
void LegacyIPCFrameInputHandler::SendInput(
std::unique_ptr<IPC::Message> message) {
static_cast<LegacyInputRouterImpl*>(
diff --git a/chromium/content/browser/frame_host/input/legacy_ipc_frame_input_handler.h b/chromium/content/browser/frame_host/input/legacy_ipc_frame_input_handler.h
index 7a10e51429b..7db84105b93 100644
--- a/chromium/content/browser/frame_host/input/legacy_ipc_frame_input_handler.h
+++ b/chromium/content/browser/frame_host/input/legacy_ipc_frame_input_handler.h
@@ -24,7 +24,7 @@ class CONTENT_EXPORT LegacyIPCFrameInputHandler
void SetCompositionFromExistingText(
int32_t start,
int32_t end,
- const std::vector<ui::CompositionUnderline>& underlines) override;
+ const std::vector<ui::ImeTextSpan>& ime_text_spans) override;
void ExtendSelectionAndDelete(int32_t before, int32_t after) override;
void DeleteSurroundingText(int32_t before, int32_t after) override;
void DeleteSurroundingTextInCodePoints(int32_t before,
@@ -49,6 +49,8 @@ class CONTENT_EXPORT LegacyIPCFrameInputHandler
void MoveRangeSelectionExtent(const gfx::Point& extent) override;
void ScrollFocusedEditableNodeIntoRect(const gfx::Rect& rect) override;
void MoveCaret(const gfx::Point& point) override;
+ void GetWidgetInputHandler(
+ mojom::WidgetInputHandlerAssociatedRequest interface_request) override;
private:
void SendInput(std::unique_ptr<IPC::Message> message);
diff --git a/chromium/content/browser/frame_host/interstitial_page_impl.cc b/chromium/content/browser/frame_host/interstitial_page_impl.cc
index de0043f4638..28a7ddfc40a 100644
--- a/chromium/content/browser/frame_host/interstitial_page_impl.cc
+++ b/chromium/content/browser/frame_host/interstitial_page_impl.cc
@@ -289,8 +289,8 @@ void InterstitialPageImpl::Hide() {
// been called from a RVH delegate method, and we can't delete the RVH out
// from under itself.
base::ThreadTaskRunnerHandle::Get()->PostNonNestableTask(
- FROM_HERE, base::Bind(&InterstitialPageImpl::Shutdown,
- weak_ptr_factory_.GetWeakPtr()));
+ FROM_HERE, base::BindOnce(&InterstitialPageImpl::Shutdown,
+ weak_ptr_factory_.GetWeakPtr()));
bool has_focus = render_view_host_->GetWidget()->GetView() &&
render_view_host_->GetWidget()->GetView()->HasFocus();
render_view_host_ = NULL;
@@ -417,11 +417,11 @@ InterstitialPage* InterstitialPageImpl::GetAsInterstitialPage() {
return this;
}
-AccessibilityMode InterstitialPageImpl::GetAccessibilityMode() const {
+ui::AXMode InterstitialPageImpl::GetAccessibilityMode() const {
if (web_contents_)
return static_cast<WebContentsImpl*>(web_contents_)->GetAccessibilityMode();
else
- return AccessibilityMode();
+ return ui::AXMode();
}
void InterstitialPageImpl::Cut() {
diff --git a/chromium/content/browser/frame_host/interstitial_page_impl.h b/chromium/content/browser/frame_host/interstitial_page_impl.h
index 2550b95bcb5..4af4ea8353b 100644
--- a/chromium/content/browser/frame_host/interstitial_page_impl.h
+++ b/chromium/content/browser/frame_host/interstitial_page_impl.h
@@ -42,13 +42,12 @@ enum ResourceRequestAction {
CANCEL
};
-class CONTENT_EXPORT InterstitialPageImpl
- : public NON_EXPORTED_BASE(InterstitialPage),
- public NotificationObserver,
- public NON_EXPORTED_BASE(RenderFrameHostDelegate),
- public RenderViewHostDelegate,
- public RenderWidgetHostDelegate,
- public NON_EXPORTED_BASE(NavigatorDelegate) {
+class CONTENT_EXPORT InterstitialPageImpl : public InterstitialPage,
+ public NotificationObserver,
+ public RenderFrameHostDelegate,
+ public RenderViewHostDelegate,
+ public RenderWidgetHostDelegate,
+ public NavigatorDelegate {
public:
// The different state of actions the user can take in an interstitial.
enum ActionState {
@@ -114,7 +113,7 @@ class CONTENT_EXPORT InterstitialPageImpl
const base::string16& title,
base::i18n::TextDirection title_direction) override;
InterstitialPage* GetAsInterstitialPage() override;
- AccessibilityMode GetAccessibilityMode() const override;
+ ui::AXMode GetAccessibilityMode() const override;
void ExecuteEditCommand(const std::string& command,
const base::Optional<base::string16>& value) override;
void Cut() override;
diff --git a/chromium/content/browser/frame_host/interstitial_page_impl_browsertest.cc b/chromium/content/browser/frame_host/interstitial_page_impl_browsertest.cc
index 6439a0d6aed..7ec70faf0b3 100644
--- a/chromium/content/browser/frame_host/interstitial_page_impl_browsertest.cc
+++ b/chromium/content/browser/frame_host/interstitial_page_impl_browsertest.cc
@@ -7,6 +7,7 @@
#include <tuple>
#include "base/macros.h"
+#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/clipboard_messages.h"
@@ -105,15 +106,15 @@ class ClipboardMessageWatcher : public IPC::MessageFilter {
if (ClipboardHostMsg_WriteText::Read(&message, &params)) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&ClipboardMessageWatcher::OnWriteText, this,
- base::UTF16ToUTF8(std::get<1>(params))));
+ base::BindOnce(&ClipboardMessageWatcher::OnWriteText, this,
+ base::UTF16ToUTF8(std::get<1>(params))));
}
return true;
}
if (message.type() == ClipboardHostMsg_CommitWrite::ID) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&ClipboardMessageWatcher::OnCommitWrite, this));
+ base::BindOnce(&ClipboardMessageWatcher::OnCommitWrite, this));
return true;
}
return false;
diff --git a/chromium/content/browser/frame_host/navigation_controller_android.cc b/chromium/content/browser/frame_host/navigation_controller_android.cc
index 9b3b1d9b4ca..d770cf5e26b 100644
--- a/chromium/content/browser/frame_host/navigation_controller_android.cc
+++ b/chromium/content/browser/frame_host/navigation_controller_android.cc
@@ -68,11 +68,6 @@ static void AddNavigationEntryToHistory(JNIEnv* env,
namespace content {
-// static
-bool NavigationControllerAndroid::Register(JNIEnv* env) {
- return RegisterNativesImpl(env);
-}
-
NavigationControllerAndroid::NavigationControllerAndroid(
NavigationControllerImpl* navigation_controller)
: navigation_controller_(navigation_controller) {
diff --git a/chromium/content/browser/frame_host/navigation_controller_android.h b/chromium/content/browser/frame_host/navigation_controller_android.h
index 09c2dd1603a..b87821cd542 100644
--- a/chromium/content/browser/frame_host/navigation_controller_android.h
+++ b/chromium/content/browser/frame_host/navigation_controller_android.h
@@ -21,8 +21,6 @@ class NavigationControllerImpl;
// with its native counterpart.
class CONTENT_EXPORT NavigationControllerAndroid {
public:
- static bool Register(JNIEnv* env);
-
explicit NavigationControllerAndroid(
NavigationControllerImpl* navigation_controller);
~NavigationControllerAndroid();
diff --git a/chromium/content/browser/frame_host/navigation_controller_delegate.h b/chromium/content/browser/frame_host/navigation_controller_delegate.h
index c57ac461f58..dd3c8efe5ff 100644
--- a/chromium/content/browser/frame_host/navigation_controller_delegate.h
+++ b/chromium/content/browser/frame_host/navigation_controller_delegate.h
@@ -45,6 +45,10 @@ class NavigationControllerDelegate {
virtual void NotifyBeforeFormRepostWarningShow() = 0;
virtual void NotifyNavigationEntryCommitted(
const LoadCommittedDetails& load_details) = 0;
+ virtual void NotifyNavigationEntryChanged(
+ const EntryChangedDetails& change_details) = 0;
+ virtual void NotifyNavigationListPruned(
+ const PrunedDetails& pruned_details) = 0;
virtual void SetHistoryOffsetAndLength(int history_offset,
int history_length) = 0;
virtual void ActivateAndShowRepostFormWarningDialog() = 0;
diff --git a/chromium/content/browser/frame_host/navigation_controller_impl.cc b/chromium/content/browser/frame_host/navigation_controller_impl.cc
index 4eb65b14dd4..7c5ed54e605 100644
--- a/chromium/content/browser/frame_host/navigation_controller_impl.cc
+++ b/chromium/content/browser/frame_host/navigation_controller_impl.cc
@@ -49,7 +49,6 @@
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "cc/base/switches.h"
-#include "components/mime_util/mime_util.h"
#include "content/browser/bad_message.h"
#include "content/browser/browser_url_handler_impl.h"
#include "content/browser/dom_storage/dom_storage_context_wrapper.h"
@@ -80,6 +79,7 @@
#include "media/base/mime_util.h"
#include "net/base/escape.h"
#include "skia/ext/platform_canvas.h"
+#include "third_party/WebKit/common/mime_util/mime_util.h"
#include "url/url_constants.h"
namespace content {
@@ -94,10 +94,7 @@ void NotifyPrunedEntries(NavigationControllerImpl* nav_controller,
PrunedDetails details;
details.from_front = from_front;
details.count = count;
- NotificationService::current()->Notify(
- NOTIFICATION_NAV_LIST_PRUNED,
- Source<NavigationController>(nav_controller),
- Details<PrunedDetails>(&details));
+ nav_controller->delegate()->NotifyNavigationListPruned(details);
}
// Ensure the given NavigationEntry has a valid state, so that WebKit does not
@@ -420,12 +417,6 @@ void NavigationControllerImpl::Reload(ReloadType reload_type,
pending_entry_ = entry;
pending_entry_index_ = current_index;
- // The title of the page being reloaded might have been removed in the
- // meanwhile, so we need to revert to the default title upon reload and
- // invalidate the previously cached title (SetTitle will do both).
- // See Chromium issue 96041.
- pending_entry_->SetTitle(base::string16());
-
pending_entry_->SetTransitionType(ui::PAGE_TRANSITION_RELOAD);
}
@@ -551,9 +542,8 @@ NavigationEntryImpl* NavigationControllerImpl::GetLastCommittedEntry() const {
bool NavigationControllerImpl::CanViewSource() const {
const std::string& mime_type = delegate_->GetContentsMimeType();
- bool is_viewable_mime_type =
- mime_util::IsSupportedNonImageMimeType(mime_type) &&
- !media::IsSupportedMediaMimeType(mime_type);
+ bool is_viewable_mime_type = blink::IsSupportedNonImageMimeType(mime_type) &&
+ !media::IsSupportedMediaMimeType(mime_type);
NavigationEntry* visible_entry = GetVisibleEntry();
return visible_entry && !visible_entry->IsViewSourceMode() &&
is_viewable_mime_type && !delegate_->GetInterstitialPage();
@@ -943,8 +933,14 @@ bool NavigationControllerImpl::RendererDidNavigate(
active_entry->SetTimestamp(timestamp);
active_entry->SetHttpStatusCode(params.http_status_code);
+ // Grab the corresponding FrameNavigationEntry for a few updates, but only if
+ // the SiteInstance matches (to avoid updating the wrong entry by mistake).
+ // A mismatch can occur if the renderer lies or due to a unique name collision
+ // after a race with an OOPIF (see https://crbug.com/616820).
FrameNavigationEntry* frame_entry =
active_entry->GetFrameEntry(rfh->frame_tree_node());
+ if (frame_entry && frame_entry->site_instance() != rfh->GetSiteInstance())
+ frame_entry = nullptr;
// Update the frame-specific PageState and RedirectChain
// We may not find a frame_entry in some cases; ignore the PageState if so.
// TODO(creis): Remove the "if" once https://crbug.com/522193 is fixed.
@@ -2230,10 +2226,7 @@ void NavigationControllerImpl::NotifyEntryChanged(
det.changed_entry = entry;
det.index = GetIndexOfEntry(
NavigationEntryImpl::FromNavigationEntry(entry));
- NotificationService::current()->Notify(
- NOTIFICATION_NAV_ENTRY_CHANGED,
- Source<NavigationController>(this),
- Details<EntryChangedDetails>(&det));
+ delegate_->NotifyNavigationEntryChanged(det);
}
void NavigationControllerImpl::FinishRestore(int selected_index,
diff --git a/chromium/content/browser/frame_host/navigation_controller_impl.h b/chromium/content/browser/frame_host/navigation_controller_impl.h
index a86ca169327..967691069b2 100644
--- a/chromium/content/browser/frame_host/navigation_controller_impl.h
+++ b/chromium/content/browser/frame_host/navigation_controller_impl.h
@@ -32,8 +32,7 @@ class NavigationEntryScreenshotManager;
class SiteInstance;
struct LoadCommittedDetails;
-class CONTENT_EXPORT NavigationControllerImpl
- : public NON_EXPORTED_BASE(NavigationController) {
+class CONTENT_EXPORT NavigationControllerImpl : public NavigationController {
public:
NavigationControllerImpl(
NavigationControllerDelegate* delegate,
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 292bb226b76..ee827529332 100644
--- a/chromium/content/browser/frame_host/navigation_controller_impl_browsertest.cc
+++ b/chromium/content/browser/frame_host/navigation_controller_impl_browsertest.cc
@@ -52,7 +52,7 @@
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/embedded_test_server/http_request.h"
#include "net/test/url_request/url_request_failed_job.h"
-#include "testing/gmock/include/gmock/gmock-matchers.h"
+#include "testing/gmock/include/gmock/gmock.h"
namespace {
@@ -680,6 +680,57 @@ class FrameNavigateParamsCapturer : public WebContentsObserver {
scoped_refptr<MessageLoopRunner> message_loop_runner_;
};
+// Test that going back in a subframe on a loadDataWithBaseURL page doesn't
+// crash. See https://crbug.com/768575.
+IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
+ NavigateBackInChildOfLoadDataWithBaseURL) {
+ GURL iframe_url(embedded_test_server()->GetURL(
+ "/navigation_controller/page_with_links.html"));
+
+ const GURL base_url("http://baseurl");
+ const GURL history_url("http://historyurl");
+ std::string data =
+ "<html><body>"
+ " <p>"
+ " <iframe src=\"";
+ data += iframe_url.spec();
+ data +=
+ "\" />"
+ " </p>"
+ "</body></html>";
+
+ // Load data and commit.
+ TestNavigationObserver same_tab_observer(shell()->web_contents(), 1);
+#if defined(OS_ANDROID)
+ shell()->LoadDataAsStringWithBaseURL(history_url, data, base_url);
+#else
+ shell()->LoadDataWithBaseURL(history_url, data, base_url);
+#endif
+ same_tab_observer.Wait();
+
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+ ASSERT_EQ(1u, root->child_count());
+ FrameTreeNode* child = root->child_at(0u);
+
+ {
+ TestNavigationObserver observer(shell()->web_contents(), 1);
+ std::string script = "document.getElementById('thelink').click()";
+ EXPECT_TRUE(ExecuteScript(child, script));
+ observer.Wait();
+ }
+
+ {
+ TestNavigationObserver observer(shell()->web_contents(), 1);
+ shell()->web_contents()->GetController().GoBack();
+ observer.Wait();
+ }
+
+ // Passes if renderer is still alive.
+ EXPECT_TRUE(ExecuteScript(shell(), "console.log('Success');"));
+}
+
class LoadCommittedCapturer : public WebContentsObserver {
public:
// Observes the load commit for the specified |node|.
@@ -709,11 +760,11 @@ class LoadCommittedCapturer : public WebContentsObserver {
RenderFrameHostImpl* rfh =
static_cast<RenderFrameHostImpl*>(render_frame_host);
- // Don't pay attention to swapped out RenderFrameHosts in the main frame.
- // TODO(nasko): Remove once swappedout:// is gone.
- // See https://crbug.com/357747.
+ // Don't pay attention to pending delete RenderFrameHosts in the main frame,
+ // which might happen in a race if a cross-process navigation happens
+ // quickly.
if (!rfh->is_active()) {
- DLOG(INFO) << "Skipping swapped out RFH: "
+ DLOG(INFO) << "Skipping pending delete RFH: "
<< rfh->GetSiteInstance()->GetSiteURL();
return;
}
@@ -913,8 +964,9 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
NavigationController& controller = shell()->web_contents()->GetController();
GURL error_url(
net::URLRequestFailedJob::GetMockHttpUrl(net::ERR_CONNECTION_RESET));
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::Bind(&net::URLRequestFailedJob::AddUrlHandler));
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&net::URLRequestFailedJob::AddUrlHandler));
EXPECT_TRUE(NavigateToURL(shell(), GURL(url::kAboutBlankURL)));
EXPECT_EQ(1, controller.GetEntryCount());
@@ -4308,9 +4360,6 @@ class NavigationControllerOopifBrowserTest
// create out-of-process iframes unless the current SiteIsolationPolicy says to.
IN_PROC_BROWSER_TEST_F(NavigationControllerOopifBrowserTest,
RestoreWithoutExtraOopifs) {
- // This test requires OOPIFs to be possible.
- EXPECT_TRUE(SiteIsolationPolicy::AreCrossProcessFramesPossible());
-
// 1. Start on a page with a data URL iframe.
GURL main_url_a(embedded_test_server()->GetURL(
"a.com", "/navigation_controller/page_with_data_iframe.html"));
@@ -4739,8 +4788,7 @@ class FailureWatcher : public WebContentsObserver {
void DidFailLoad(RenderFrameHost* render_frame_host,
const GURL& validated_url,
int error_code,
- const base::string16& error_description,
- bool was_ignored_by_handler) override {
+ const base::string16& error_description) override {
RenderFrameHostImpl* rfh =
static_cast<RenderFrameHostImpl*>(render_frame_host);
if (rfh->frame_tree_node()->frame_tree_node_id() != frame_tree_node_id_)
@@ -6144,7 +6192,7 @@ class GoBackAndCommitFilter : public BrowserMessageFilter {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&NavigateBackAndCommit, message, web_contents_));
+ base::BindOnce(&NavigateBackAndCommit, message, web_contents_));
return true;
}
@@ -6585,7 +6633,7 @@ class RequestMonitoringNavigationBrowserTest : public ContentBrowserTest {
const net::test_server::HttpRequest& request) {
postback_task_runner->PostTask(
FROM_HERE,
- base::Bind(
+ base::BindOnce(
&RequestMonitoringNavigationBrowserTest::MonitorRequestOnMainThread,
weak_this, request));
}
@@ -6869,6 +6917,59 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
controller.GetLastCommittedEntry()->GetURL().spec());
}
+// Same-document navigations can sometimes succeed but then later be blocked by
+// policy (e.g., X-Frame-Options) after a page is restored or reloaded. Ensure
+// that navigating back from a newly blocked URL in a subframe is not treated as
+// same-document, even if it had been same-document originally.
+// See https://crbug.com/765291.
+IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
+ BackSameDocumentAfterBlockedSubframe) {
+ NavigationControllerImpl& controller = static_cast<NavigationControllerImpl&>(
+ shell()->web_contents()->GetController());
+
+ GURL start_url(embedded_test_server()->GetURL(
+ "/navigation_controller/page_with_iframe_simple.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), start_url));
+
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+
+ // pushState to a URL that will be blocked by XFO if loaded from scratch.
+ {
+ FrameNavigateParamsCapturer capturer(root->child_at(0));
+ std::string pushStateToXfo =
+ "history.pushState({}, '', '/x-frame-options-deny.html')";
+ EXPECT_TRUE(ExecuteScript(root->child_at(0), pushStateToXfo));
+ capturer.Wait();
+ EXPECT_TRUE(capturer.is_same_document());
+ }
+
+ // Navigate the main frame to another page.
+ GURL new_url(embedded_test_server()->GetURL(
+ "/navigation_controller/simple_page_1.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), new_url));
+
+ // Go back, causing the subframe to be blocked by XFO.
+ {
+ TestNavigationObserver observer(shell()->web_contents());
+ controller.GoBack();
+ observer.Wait();
+ }
+ EXPECT_EQ(GURL("data:,"), root->child_at(0)->current_url());
+
+ // Go back again. This would have been same-document if the prior navigation
+ // had succeeded.
+ {
+ TestNavigationObserver observer(shell()->web_contents());
+ controller.GoBack();
+ observer.Wait();
+ }
+
+ // Check that the renderer is still alive.
+ EXPECT_TRUE(ExecuteScript(root->child_at(0), "console.log('Success');"));
+}
+
// If the main frame does a load, it should not be reported as a subframe
// navigation. This used to occur in the following case:
// 1. You're on a site with frames.
@@ -6983,4 +7084,31 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
}
}
+IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
+ HashNavigationVsBeforeUnloadEvent) {
+ GURL main_url(embedded_test_server()->GetURL("/title1.html"));
+ GURL hash_url(embedded_test_server()->GetURL("/title1.html#hash"));
+
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+ EXPECT_TRUE(
+ ExecuteScript(shell(),
+ R"( window.addEventListener("beforeunload", function(e) {
+ domAutomationController.send("beforeunload");
+ });
+ window.addEventListener("unload", function(e) {
+ domAutomationController.send("unload");
+ });
+ )"));
+
+ DOMMessageQueue message_queue;
+ std::vector<std::string> messages;
+ std::string message;
+ EXPECT_TRUE(NavigateToURL(shell(), hash_url));
+ while (message_queue.PopMessage(&message))
+ messages.push_back(message);
+
+ // Verify that none of "beforeunload", "unload" events fired.
+ EXPECT_THAT(messages, testing::IsEmpty());
+}
+
} // 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 108acc6d32b..ac63179b011 100644
--- a/chromium/content/browser/frame_host/navigation_controller_impl_unittest.cc
+++ b/chromium/content/browser/frame_host/navigation_controller_impl_unittest.cc
@@ -33,8 +33,6 @@
#include "content/common/frame_owner_properties.h"
#include "content/common/site_isolation_policy.h"
#include "content/common/view_messages.h"
-#include "content/public/browser/notification_registrar.h"
-#include "content/public/browser/notification_types.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/browser/web_contents_observer.h"
@@ -45,7 +43,7 @@
#include "content/public/common/url_constants.h"
#include "content/public/test/browser_side_navigation_test_utils.h"
#include "content/public/test/mock_render_process_host.h"
-#include "content/public/test/test_notification_tracker.h"
+#include "content/public/test/navigation_simulator.h"
#include "content/public/test/test_utils.h"
#include "content/test/test_render_frame_host.h"
#include "content/test/test_render_view_host.h"
@@ -198,8 +196,7 @@ class NavigationControllerTest
: public RenderViewHostImplTestHarness,
public WebContentsObserver {
public:
- NavigationControllerTest() : navigation_entry_committed_counter_(0) {
- }
+ NavigationControllerTest() {}
void SetUp() override {
RenderViewHostImplTestHarness::SetUp();
@@ -220,6 +217,16 @@ class NavigationControllerTest
navigation_entry_committed_counter_++;
}
+ void NavigationEntryChanged(
+ const EntryChangedDetails& load_details) override {
+ navigation_entry_changed_counter_++;
+ }
+
+ void NavigationListPruned(const PrunedDetails& details) override {
+ navigation_list_pruned_counter_++;
+ last_navigation_entry_pruned_details_ = details;
+ }
+
const GURL& navigated_url() const {
return navigated_url_;
}
@@ -256,18 +263,13 @@ class NavigationControllerTest
protected:
GURL navigated_url_;
- size_t navigation_entry_committed_counter_;
+ size_t navigation_entry_committed_counter_ = 0;
+ size_t navigation_entry_changed_counter_ = 0;
+ size_t navigation_list_pruned_counter_ = 0;
+ PrunedDetails last_navigation_entry_pruned_details_;
ReloadType last_reload_type_;
};
-void RegisterForAllNavNotifications(TestNotificationTracker* tracker,
- NavigationController* controller) {
- tracker->ListenFor(NOTIFICATION_NAV_LIST_PRUNED,
- Source<NavigationController>(controller));
- tracker->ListenFor(NOTIFICATION_NAV_ENTRY_CHANGED,
- Source<NavigationController>(controller));
-}
-
class TestWebContentsDelegate : public WebContentsDelegate {
public:
explicit TestWebContentsDelegate() :
@@ -365,8 +367,6 @@ TEST_F(NavigationControllerTest, Defaults) {
TEST_F(NavigationControllerTest, GoToOffset) {
NavigationControllerImpl& controller = controller_impl();
- TestNotificationTracker notifications;
- RegisterForAllNavNotifications(&notifications, &controller);
const int kNumUrls = 5;
std::vector<GURL> urls(kNumUrls);
@@ -538,8 +538,6 @@ TEST_F(NavigationControllerTestWithBrowserSideNavigation,
TEST_F(NavigationControllerTest, LoadURL) {
NavigationControllerImpl& controller = controller_impl();
- TestNotificationTracker notifications;
- RegisterForAllNavNotifications(&notifications, &controller);
const GURL url1("http://foo1");
const GURL url2("http://foo2");
@@ -549,7 +547,8 @@ TEST_F(NavigationControllerTest, LoadURL) {
int entry_id = controller.GetPendingEntry()->GetUniqueID();
// Creating a pending notification should not have issued any of the
// notifications we're listening for.
- EXPECT_EQ(0U, notifications.size());
+ EXPECT_EQ(0U, navigation_entry_changed_counter_);
+ EXPECT_EQ(0U, navigation_list_pruned_counter_);
// The load should now be pending.
EXPECT_EQ(controller.GetEntryCount(), 0);
@@ -566,7 +565,8 @@ TEST_F(NavigationControllerTest, LoadURL) {
EXPECT_EQ(0, controller.GetPendingEntry()->GetHttpStatusCode());
// We should have gotten no notifications from the preceeding checks.
- EXPECT_EQ(0U, notifications.size());
+ EXPECT_EQ(0U, navigation_entry_changed_counter_);
+ EXPECT_EQ(0U, navigation_list_pruned_counter_);
main_test_rfh()->PrepareForCommit();
main_test_rfh()->SendNavigate(entry_id, true, url1);
@@ -635,8 +635,6 @@ base::Time GetFixedTime(base::Time time) {
TEST_F(NavigationControllerTest, LoadURLSameTime) {
NavigationControllerImpl& controller = controller_impl();
- TestNotificationTracker notifications;
- RegisterForAllNavNotifications(&notifications, &controller);
// Set the clock to always return a timestamp of 1.
controller.SetGetTimestampCallbackForTest(
@@ -708,8 +706,13 @@ void CheckNavigationEntryMatchLoadParams(
TEST_F(NavigationControllerTest, LoadURLWithParams) {
// Start a navigation in order to have enough state to fake a transfer.
- contents()->NavigateAndCommit(GURL("http://foo"));
- contents()->StartNavigation(GURL("http://bar"));
+ const GURL url1("http://foo");
+ const GURL url2("http://bar");
+
+ contents()->NavigateAndCommit(url1);
+ auto navigation =
+ NavigationSimulator::CreateBrowserInitiated(url2, contents());
+ navigation->Start();
NavigationControllerImpl& controller = controller_impl();
@@ -793,15 +796,14 @@ TEST_F(NavigationControllerTest, LoadURLWithExtraParams_HttpPost) {
// the load commits (because WebCore didn't actually make a new entry).
TEST_F(NavigationControllerTest, LoadURL_SamePage) {
NavigationControllerImpl& controller = controller_impl();
- TestNotificationTracker notifications;
- RegisterForAllNavNotifications(&notifications, &controller);
const GURL url1("http://foo1");
controller.LoadURL(
url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
int entry_id = controller.GetPendingEntry()->GetUniqueID();
- EXPECT_EQ(0U, notifications.size());
+ EXPECT_EQ(0U, navigation_entry_changed_counter_);
+ EXPECT_EQ(0U, navigation_list_pruned_counter_);
main_test_rfh()->PrepareForCommit();
main_test_rfh()->SendNavigateWithTransition(
entry_id, true, url1, ui::PAGE_TRANSITION_TYPED);
@@ -816,7 +818,8 @@ TEST_F(NavigationControllerTest, LoadURL_SamePage) {
controller.LoadURL(
url1, Referrer(), ui::PAGE_TRANSITION_TYPED, new_extra_headers);
entry_id = controller.GetPendingEntry()->GetUniqueID();
- EXPECT_EQ(0U, notifications.size());
+ EXPECT_EQ(0U, navigation_entry_changed_counter_);
+ EXPECT_EQ(0U, navigation_list_pruned_counter_);
main_test_rfh()->PrepareForCommit();
main_test_rfh()->SendNavigateWithTransition(
entry_id, false, url1, ui::PAGE_TRANSITION_TYPED);
@@ -847,8 +850,6 @@ TEST_F(NavigationControllerTest, LoadURL_SamePage) {
// We should update the post state on the NavigationEntry.
TEST_F(NavigationControllerTest, LoadURL_SamePage_DifferentMethod) {
NavigationControllerImpl& controller = controller_impl();
- TestNotificationTracker notifications;
- RegisterForAllNavNotifications(&notifications, &controller);
const GURL url1("http://foo1");
@@ -889,8 +890,6 @@ TEST_F(NavigationControllerTest, LoadURL_SamePage_DifferentMethod) {
// Tests loading a URL but discarding it before the load commits.
TEST_F(NavigationControllerTest, LoadURL_Discarded) {
NavigationControllerImpl& controller = controller_impl();
- TestNotificationTracker notifications;
- RegisterForAllNavNotifications(&notifications, &controller);
const GURL url1("http://foo1");
const GURL url2("http://foo2");
@@ -898,7 +897,8 @@ TEST_F(NavigationControllerTest, LoadURL_Discarded) {
controller.LoadURL(
url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
int entry_id = controller.GetPendingEntry()->GetUniqueID();
- EXPECT_EQ(0U, notifications.size());
+ EXPECT_EQ(0U, navigation_entry_changed_counter_);
+ EXPECT_EQ(0U, navigation_list_pruned_counter_);
main_test_rfh()->PrepareForCommit();
main_test_rfh()->SendNavigate(entry_id, true, url1);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
@@ -911,7 +911,8 @@ TEST_F(NavigationControllerTest, LoadURL_Discarded) {
controller.LoadURL(
url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
controller.DiscardNonCommittedEntries();
- EXPECT_EQ(0U, notifications.size());
+ EXPECT_EQ(0U, navigation_entry_changed_counter_);
+ EXPECT_EQ(0U, navigation_list_pruned_counter_);
// Should not have produced a new session history entry.
EXPECT_EQ(controller.GetEntryCount(), 1);
@@ -931,8 +932,6 @@ TEST_F(NavigationControllerTest, LoadURL_Discarded) {
// navigates from the web page, and here we test that there is no pending entry.
TEST_F(NavigationControllerTest, LoadURL_NoPending) {
NavigationControllerImpl& controller = controller_impl();
- TestNotificationTracker notifications;
- RegisterForAllNavNotifications(&notifications, &controller);
// First make an existing committed entry.
const GURL kExistingURL1("http://eh");
@@ -946,7 +945,7 @@ TEST_F(NavigationControllerTest, LoadURL_NoPending) {
// Do a new navigation without making a pending one.
const GURL kNewURL("http://see");
- main_test_rfh()->NavigateAndCommitRendererInitiated(true, kNewURL);
+ NavigationSimulator::NavigateAndCommitFromDocument(kNewURL, main_test_rfh());
// There should no longer be any pending entry, and the second navigation we
// just made should be committed.
@@ -963,8 +962,6 @@ TEST_F(NavigationControllerTest, LoadURL_NoPending) {
// commits.
TEST_F(NavigationControllerTest, LoadURL_NewPending) {
NavigationControllerImpl& controller = controller_impl();
- TestNotificationTracker notifications;
- RegisterForAllNavNotifications(&notifications, &controller);
// First make an existing committed entry.
const GURL kExistingURL1("http://eh");
@@ -980,7 +977,8 @@ TEST_F(NavigationControllerTest, LoadURL_NewPending) {
const GURL kExistingURL2("http://bee");
controller.LoadURL(
kExistingURL2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
- EXPECT_EQ(0U, notifications.size());
+ EXPECT_EQ(0U, navigation_entry_changed_counter_);
+ EXPECT_EQ(0U, navigation_list_pruned_counter_);
// After the beforeunload but before it commits...
main_test_rfh()->PrepareForCommit();
@@ -1005,8 +1003,6 @@ TEST_F(NavigationControllerTest, LoadURL_NewPending) {
// they navigate somewhere new.
TEST_F(NavigationControllerTest, LoadURL_ExistingPending) {
NavigationControllerImpl& controller = controller_impl();
- TestNotificationTracker notifications;
- RegisterForAllNavNotifications(&notifications, &controller);
// First make some history.
const GURL kExistingURL1("http://foo/eh");
@@ -1030,7 +1026,8 @@ TEST_F(NavigationControllerTest, LoadURL_ExistingPending) {
// Now make a pending back/forward navigation. The zeroth entry should be
// pending.
controller.GoBack();
- EXPECT_EQ(0U, notifications.size());
+ EXPECT_EQ(0U, navigation_entry_changed_counter_);
+ EXPECT_EQ(0U, navigation_list_pruned_counter_);
EXPECT_EQ(0, controller.GetPendingEntryIndex());
EXPECT_EQ(1, controller.GetLastCommittedEntryIndex());
@@ -1054,8 +1051,6 @@ TEST_F(NavigationControllerTest, LoadURL_ExistingPending) {
// hits back, but before that commits, they navigate somewhere new.
TEST_F(NavigationControllerTest, LoadURL_PrivilegedPending) {
NavigationControllerImpl& controller = controller_impl();
- TestNotificationTracker notifications;
- RegisterForAllNavNotifications(&notifications, &controller);
// First make some history, starting with a privileged URL.
const GURL kExistingURL1("http://privileged");
@@ -1084,7 +1079,8 @@ TEST_F(NavigationControllerTest, LoadURL_PrivilegedPending) {
// The zeroth entry should be pending.
controller.GoBack();
foo_rfh->SendBeforeUnloadACK(true);
- EXPECT_EQ(0U, notifications.size());
+ EXPECT_EQ(0U, navigation_entry_changed_counter_);
+ EXPECT_EQ(0U, navigation_list_pruned_counter_);
EXPECT_EQ(0, controller.GetPendingEntryIndex());
EXPECT_EQ(1, controller.GetLastCommittedEntryIndex());
EXPECT_EQ(2, controller.GetPendingEntry()->bindings());
@@ -1110,8 +1106,6 @@ TEST_F(NavigationControllerTest, LoadURL_PrivilegedPending) {
// current page fires history.back().
TEST_F(NavigationControllerTest, LoadURL_BackPreemptsPending) {
NavigationControllerImpl& controller = controller_impl();
- TestNotificationTracker notifications;
- RegisterForAllNavNotifications(&notifications, &controller);
// First make some history.
const GURL kExistingURL1("http://foo/eh");
@@ -1140,7 +1134,8 @@ TEST_F(NavigationControllerTest, LoadURL_BackPreemptsPending) {
const GURL kNewURL("http://foo/see");
controller.LoadURL(
kNewURL, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
- EXPECT_EQ(0U, notifications.size());
+ EXPECT_EQ(0U, navigation_entry_changed_counter_);
+ EXPECT_EQ(0U, navigation_list_pruned_counter_);
EXPECT_EQ(-1, controller.GetPendingEntryIndex());
EXPECT_EQ(1, controller.GetLastCommittedEntryIndex());
@@ -1162,8 +1157,6 @@ TEST_F(NavigationControllerTest, LoadURL_BackPreemptsPending) {
// current blank page reloads. See http://crbug.com/77507.
TEST_F(NavigationControllerTest, LoadURL_IgnorePreemptsPending) {
NavigationControllerImpl& controller = controller_impl();
- TestNotificationTracker notifications;
- RegisterForAllNavNotifications(&notifications, &controller);
// Set a WebContentsDelegate to listen for state changes.
std::unique_ptr<TestWebContentsDelegate> delegate(
@@ -1178,7 +1171,8 @@ TEST_F(NavigationControllerTest, LoadURL_IgnorePreemptsPending) {
const GURL kNewURL("http://eh");
controller.LoadURL(
kNewURL, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
- EXPECT_EQ(0U, notifications.size());
+ EXPECT_EQ(0U, navigation_entry_changed_counter_);
+ EXPECT_EQ(0U, navigation_list_pruned_counter_);
EXPECT_EQ(-1, controller.GetPendingEntryIndex());
EXPECT_TRUE(controller.GetPendingEntry());
EXPECT_EQ(-1, controller.GetLastCommittedEntryIndex());
@@ -1205,8 +1199,6 @@ TEST_F(NavigationControllerTest, LoadURL_IgnorePreemptsPending) {
// lose a typed URL. (See http://crbug.com/9682.)
TEST_F(NavigationControllerTest, LoadURL_AbortDoesntCancelPending) {
NavigationControllerImpl& controller = controller_impl();
- TestNotificationTracker notifications;
- RegisterForAllNavNotifications(&notifications, &controller);
// Set a WebContentsDelegate to listen for state changes.
std::unique_ptr<TestWebContentsDelegate> delegate(
@@ -1219,7 +1211,8 @@ TEST_F(NavigationControllerTest, LoadURL_AbortDoesntCancelPending) {
controller.LoadURL(
kNewURL, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
main_test_rfh()->PrepareForCommit();
- EXPECT_EQ(0U, notifications.size());
+ EXPECT_EQ(0U, navigation_entry_changed_counter_);
+ EXPECT_EQ(0U, navigation_list_pruned_counter_);
EXPECT_EQ(-1, controller.GetPendingEntryIndex());
EXPECT_TRUE(controller.GetPendingEntry());
EXPECT_EQ(-1, controller.GetLastCommittedEntryIndex());
@@ -1258,8 +1251,6 @@ TEST_F(NavigationControllerTest, LoadURL_AbortDoesntCancelPending) {
// redirect and abort. See http://crbug.com/83031.
TEST_F(NavigationControllerTest, LoadURL_RedirectAbortDoesntShowPendingURL) {
NavigationControllerImpl& controller = controller_impl();
- TestNotificationTracker notifications;
- RegisterForAllNavNotifications(&notifications, &controller);
// First make an existing committed entry.
const GURL kExistingURL("http://foo/eh");
@@ -1268,6 +1259,7 @@ TEST_F(NavigationControllerTest, LoadURL_RedirectAbortDoesntShowPendingURL) {
int entry_id = controller.GetPendingEntry()->GetUniqueID();
main_test_rfh()->PrepareForCommit();
main_test_rfh()->SendNavigate(entry_id, true, kExistingURL);
+ main_test_rfh()->OnMessageReceived(FrameHostMsg_DidStopLoading(0));
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
@@ -1279,19 +1271,24 @@ TEST_F(NavigationControllerTest, LoadURL_RedirectAbortDoesntShowPendingURL) {
// Now make a pending new navigation, initiated by the renderer.
const GURL kNewURL("http://foo/bee");
- main_test_rfh()->SimulateNavigationStart(kNewURL);
- EXPECT_EQ(0U, notifications.size());
+ auto navigation =
+ NavigationSimulator::CreateRendererInitiated(kNewURL, main_test_rfh());
+ navigation->Start();
+ EXPECT_EQ(0U, navigation_entry_changed_counter_);
+ EXPECT_EQ(0U, navigation_list_pruned_counter_);
EXPECT_EQ(-1, controller.GetPendingEntryIndex());
EXPECT_TRUE(controller.GetPendingEntry());
EXPECT_EQ(0, controller.GetLastCommittedEntryIndex());
- EXPECT_EQ(1, delegate->navigation_state_change_count());
+ // The delegate should have been notified twice: once for the loading state
+ // change, and once for the url change.
+ EXPECT_EQ(2, delegate->navigation_state_change_count());
// The visible entry should be the last committed URL, not the pending one.
EXPECT_EQ(kExistingURL, controller.GetVisibleEntry()->GetURL());
// Now the navigation redirects.
const GURL kRedirectURL("http://foo/see");
- main_test_rfh()->SimulateRedirect(kRedirectURL);
+ navigation->Redirect(kRedirectURL);
// We don't want to change the NavigationEntry's url, in case it cancels.
// Prevents regression of http://crbug.com/77786.
@@ -1299,14 +1296,16 @@ TEST_F(NavigationControllerTest, LoadURL_RedirectAbortDoesntShowPendingURL) {
// It may abort before committing, if it's a download or due to a stop or
// a new navigation from the user.
- main_test_rfh()->SimulateNavigationError(kRedirectURL, net::ERR_ABORTED);
+ navigation->Fail(net::ERR_ABORTED);
// Because the pending entry is renderer initiated and not visible, we
// clear it when it fails.
EXPECT_EQ(-1, controller.GetPendingEntryIndex());
EXPECT_FALSE(controller.GetPendingEntry());
EXPECT_EQ(0, controller.GetLastCommittedEntryIndex());
- EXPECT_EQ(2, delegate->navigation_state_change_count());
+ // The delegate should have been notified twice: once for the loading state
+ // change, and once for the url change.
+ EXPECT_EQ(4, delegate->navigation_state_change_count());
// The visible entry should be the last committed URL, not the pending one,
// so that no spoof is possible.
@@ -1319,8 +1318,6 @@ TEST_F(NavigationControllerTest, LoadURL_RedirectAbortDoesntShowPendingURL) {
// at the time they committed. http://crbug.com/173672.
TEST_F(NavigationControllerTest, LoadURL_WithBindings) {
NavigationControllerImpl& controller = controller_impl();
- TestNotificationTracker notifications;
- RegisterForAllNavNotifications(&notifications, &controller);
std::vector<GURL> url_chain;
const GURL url1("http://foo1");
@@ -1377,25 +1374,24 @@ TEST_F(NavigationControllerTest, LoadURL_WithBindings) {
TEST_F(NavigationControllerTest, Reload) {
NavigationControllerImpl& controller = controller_impl();
- TestNotificationTracker notifications;
- RegisterForAllNavNotifications(&notifications, &controller);
const GURL url1("http://foo1");
controller.LoadURL(
url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
int entry_id = controller.GetPendingEntry()->GetUniqueID();
- EXPECT_EQ(0U, notifications.size());
+ EXPECT_EQ(0U, navigation_entry_changed_counter_);
+ EXPECT_EQ(0U, navigation_list_pruned_counter_);
main_test_rfh()->PrepareForCommit();
main_test_rfh()->SendNavigate(entry_id, true, url1);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
ASSERT_TRUE(controller.GetVisibleEntry());
- controller.GetVisibleEntry()->SetTitle(base::ASCIIToUTF16("Title"));
entry_id = controller.GetLastCommittedEntry()->GetUniqueID();
controller.Reload(ReloadType::NORMAL, true);
- EXPECT_EQ(0U, notifications.size());
+ EXPECT_EQ(0U, navigation_entry_changed_counter_);
+ EXPECT_EQ(0U, navigation_list_pruned_counter_);
const base::Time timestamp = controller.GetVisibleEntry()->GetTimestamp();
EXPECT_FALSE(timestamp.is_null());
@@ -1408,10 +1404,6 @@ TEST_F(NavigationControllerTest, Reload) {
EXPECT_TRUE(controller.GetPendingEntry());
EXPECT_FALSE(controller.CanGoBack());
EXPECT_FALSE(controller.CanGoForward());
- // Make sure the title has been cleared (will be redrawn just after reload).
- // Avoids a stale cached title when the new page being reloaded has no title.
- // See http://crbug.com/96041.
- EXPECT_TRUE(controller.GetVisibleEntry()->GetTitle().empty());
main_test_rfh()->PrepareForCommit();
main_test_rfh()->SendNavigate(entry_id, false, url1);
@@ -1435,8 +1427,6 @@ TEST_F(NavigationControllerTest, Reload) {
// Tests what happens when a reload navigation produces a new page.
TEST_F(NavigationControllerTest, Reload_GeneratesNewPage) {
NavigationControllerImpl& controller = controller_impl();
- TestNotificationTracker notifications;
- RegisterForAllNavNotifications(&notifications, &controller);
const GURL url1("http://foo1");
const GURL url2("http://foo2");
@@ -1451,7 +1441,8 @@ TEST_F(NavigationControllerTest, Reload_GeneratesNewPage) {
entry_id = controller.GetLastCommittedEntry()->GetUniqueID();
controller.Reload(ReloadType::NORMAL, true);
- EXPECT_EQ(0U, notifications.size());
+ EXPECT_EQ(0U, navigation_entry_changed_counter_);
+ EXPECT_EQ(0U, navigation_list_pruned_counter_);
main_test_rfh()->PrepareForCommitWithServerRedirect(url2);
main_test_rfh()->SendNavigate(entry_id, true, url2);
@@ -1510,8 +1501,6 @@ void SetOriginalURL(const GURL& url,
TEST_F(NavigationControllerTest, ReloadOriginalRequestURL) {
NavigationControllerImpl& controller = controller_impl();
- TestNotificationTracker notifications;
- RegisterForAllNavNotifications(&notifications, &controller);
const GURL original_url("http://foo1");
const GURL final_url("http://foo2");
@@ -1521,7 +1510,8 @@ TEST_F(NavigationControllerTest, ReloadOriginalRequestURL) {
controller.LoadURL(
original_url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
int entry_id = controller.GetPendingEntry()->GetUniqueID();
- EXPECT_EQ(0U, notifications.size());
+ EXPECT_EQ(0U, navigation_entry_changed_counter_);
+ EXPECT_EQ(0U, navigation_list_pruned_counter_);
main_test_rfh()->PrepareForCommitWithServerRedirect(final_url);
main_test_rfh()->SendNavigateWithModificationCallback(
entry_id, true, final_url, set_original_url_callback);
@@ -1536,9 +1526,9 @@ TEST_F(NavigationControllerTest, ReloadOriginalRequestURL) {
EXPECT_EQ(final_url, controller.GetVisibleEntry()->GetURL());
// Reload using the original URL.
- controller.GetVisibleEntry()->SetTitle(base::ASCIIToUTF16("Title"));
controller.Reload(ReloadType::ORIGINAL_REQUEST_URL, false);
- EXPECT_EQ(0U, notifications.size());
+ EXPECT_EQ(0U, navigation_entry_changed_counter_);
+ EXPECT_EQ(0U, navigation_list_pruned_counter_);
// The reload is pending. The request should point to the original URL.
EXPECT_EQ(original_url, navigated_url());
@@ -1550,11 +1540,6 @@ TEST_F(NavigationControllerTest, ReloadOriginalRequestURL) {
EXPECT_FALSE(controller.CanGoBack());
EXPECT_FALSE(controller.CanGoForward());
- // Make sure the title has been cleared (will be redrawn just after reload).
- // Avoids a stale cached title when the new page being reloaded has no title.
- // See http://crbug.com/96041.
- EXPECT_TRUE(controller.GetVisibleEntry()->GetTitle().empty());
-
// Send that the navigation has proceeded; say it got redirected again.
main_test_rfh()->PrepareForCommitWithServerRedirect(final_url);
main_test_rfh()->SendNavigate(entry_id, false, final_url);
@@ -1709,22 +1694,21 @@ TEST_F(NavigationControllerTest, GoBackWithUserAgentOverrideChange) {
// Tests what happens when we navigate back successfully
TEST_F(NavigationControllerTest, Back) {
NavigationControllerImpl& controller = controller_impl();
- TestNotificationTracker notifications;
- RegisterForAllNavNotifications(&notifications, &controller);
const GURL url1("http://foo1");
- main_test_rfh()->NavigateAndCommitRendererInitiated(true, url1);
+ NavigationSimulator::NavigateAndCommitFromDocument(url1, main_test_rfh());
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
const GURL url2("http://foo2");
- main_test_rfh()->NavigateAndCommitRendererInitiated(true, url2);
+ NavigationSimulator::NavigateAndCommitFromDocument(url2, main_test_rfh());
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
controller.GoBack();
int entry_id = controller.GetPendingEntry()->GetUniqueID();
- EXPECT_EQ(0U, notifications.size());
+ EXPECT_EQ(0U, navigation_entry_changed_counter_);
+ EXPECT_EQ(0U, navigation_list_pruned_counter_);
// We should now have a pending navigation to go back.
EXPECT_EQ(controller.GetEntryCount(), 2);
@@ -1743,8 +1727,11 @@ TEST_F(NavigationControllerTest, Back) {
EXPECT_GE(controller.GetEntryAtIndex(1)->GetTimestamp(),
controller.GetEntryAtIndex(0)->GetTimestamp());
- main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(entry_id, false, url2);
+ TestRenderFrameHost* navigating_rfh = AreAllSitesIsolatedForTesting()
+ ? contents()->GetPendingMainFrame()
+ : contents()->GetMainFrame();
+ navigating_rfh->PrepareForCommit();
+ navigating_rfh->SendNavigate(entry_id, false, url2);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
@@ -1769,8 +1756,6 @@ TEST_F(NavigationControllerTest, Back) {
// Tests what happens when a back navigation produces a new page.
TEST_F(NavigationControllerTest, Back_GeneratesNewPage) {
NavigationControllerImpl& controller = controller_impl();
- TestNotificationTracker notifications;
- RegisterForAllNavNotifications(&notifications, &controller);
const GURL url1("http://foo/1");
const GURL url2("http://foo/2");
@@ -1794,7 +1779,8 @@ TEST_F(NavigationControllerTest, Back_GeneratesNewPage) {
navigation_entry_committed_counter_ = 0;
controller.GoBack();
- EXPECT_EQ(0U, notifications.size());
+ EXPECT_EQ(0U, navigation_entry_changed_counter_);
+ EXPECT_EQ(0U, navigation_list_pruned_counter_);
// We should now have a pending navigation to go back.
EXPECT_EQ(controller.GetEntryCount(), 2);
@@ -1825,20 +1811,18 @@ TEST_F(NavigationControllerTest, Back_GeneratesNewPage) {
// Receives a back message when there is a new pending navigation entry.
TEST_F(NavigationControllerTest, Back_NewPending) {
NavigationControllerImpl& controller = controller_impl();
- TestNotificationTracker notifications;
- RegisterForAllNavNotifications(&notifications, &controller);
const GURL kUrl1("http://foo1");
const GURL kUrl2("http://foo2");
const GURL kUrl3("http://foo3");
// First navigate two places so we have some back history.
- main_test_rfh()->NavigateAndCommitRendererInitiated(true, kUrl1);
+ NavigationSimulator::NavigateAndCommitFromDocument(kUrl1, main_test_rfh());
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
// controller.LoadURL(kUrl2, ui::PAGE_TRANSITION_TYPED);
- main_test_rfh()->NavigateAndCommitRendererInitiated(true, kUrl2);
+ NavigationSimulator::NavigateAndCommitFromDocument(kUrl2, main_test_rfh());
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
@@ -1858,8 +1842,6 @@ TEST_F(NavigationControllerTest, Back_NewPending) {
// Tests what happens when we navigate forward successfully.
TEST_F(NavigationControllerTest, Forward) {
NavigationControllerImpl& controller = controller_impl();
- TestNotificationTracker notifications;
- RegisterForAllNavNotifications(&notifications, &controller);
const GURL url1("http://foo1");
const GURL url2("http://foo2");
@@ -1934,8 +1916,6 @@ TEST_F(NavigationControllerTest, Forward) {
// Tests what happens when a forward navigation produces a new page.
TEST_F(NavigationControllerTest, Forward_GeneratesNewPage) {
NavigationControllerImpl& controller = controller_impl();
- TestNotificationTracker notifications;
- RegisterForAllNavNotifications(&notifications, &controller);
const GURL url1("http://foo1");
const GURL url2("http://foo2");
@@ -1963,7 +1943,7 @@ TEST_F(NavigationControllerTest, Forward_GeneratesNewPage) {
navigation_entry_committed_counter_ = 0;
controller.GoForward();
- EXPECT_EQ(0U, notifications.size());
+ EXPECT_EQ(0U, navigation_list_pruned_counter_);
// Should now have a pending navigation to go forward.
EXPECT_EQ(controller.GetEntryCount(), 2);
@@ -1978,7 +1958,7 @@ TEST_F(NavigationControllerTest, Forward_GeneratesNewPage) {
main_test_rfh()->SendNavigate(entry2->GetUniqueID(), true, url3);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
- EXPECT_TRUE(notifications.Check1AndReset(NOTIFICATION_NAV_LIST_PRUNED));
+ EXPECT_EQ(1U, navigation_list_pruned_counter_);
EXPECT_EQ(controller.GetEntryCount(), 2);
EXPECT_EQ(controller.GetLastCommittedEntryIndex(), 1);
@@ -1993,8 +1973,6 @@ TEST_F(NavigationControllerTest, Forward_GeneratesNewPage) {
// as SAME_PAGE navigation even when we are redirected to some other page.
TEST_F(NavigationControllerTest, Redirect) {
NavigationControllerImpl& controller = controller_impl();
- TestNotificationTracker notifications;
- RegisterForAllNavNotifications(&notifications, &controller);
const GURL url1("http://foo1");
const GURL url2("http://foo2"); // Redirection target
@@ -2004,7 +1982,8 @@ TEST_F(NavigationControllerTest, Redirect) {
url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
int entry_id = controller.GetPendingEntry()->GetUniqueID();
- EXPECT_EQ(0U, notifications.size());
+ EXPECT_EQ(0U, navigation_entry_changed_counter_);
+ EXPECT_EQ(0U, navigation_list_pruned_counter_);
FrameHostMsg_DidCommitProvisionalLoad_Params params;
params.nav_entry_id = entry_id;
@@ -2035,7 +2014,8 @@ TEST_F(NavigationControllerTest, Redirect) {
params.nav_entry_id = entry_id;
params.did_create_new_entry = false;
- EXPECT_EQ(0U, notifications.size());
+ EXPECT_EQ(0U, navigation_entry_changed_counter_);
+ EXPECT_EQ(0U, navigation_list_pruned_counter_);
LoadCommittedDetailsObserver observer(contents());
main_test_rfh()->PrepareForCommit();
main_test_rfh()->SendNavigateWithParams(&params);
@@ -2059,8 +2039,6 @@ TEST_F(NavigationControllerTest, Redirect) {
// must be cleared. http://crbug.com/21245
TEST_F(NavigationControllerTest, PostThenRedirect) {
NavigationControllerImpl& controller = controller_impl();
- TestNotificationTracker notifications;
- RegisterForAllNavNotifications(&notifications, &controller);
const GURL url1("http://foo1");
const GURL url2("http://foo2"); // Redirection target
@@ -2071,7 +2049,8 @@ TEST_F(NavigationControllerTest, PostThenRedirect) {
int entry_id = controller.GetPendingEntry()->GetUniqueID();
controller.GetVisibleEntry()->SetHasPostData(true);
- EXPECT_EQ(0U, notifications.size());
+ EXPECT_EQ(0U, navigation_entry_changed_counter_);
+ EXPECT_EQ(0U, navigation_list_pruned_counter_);
FrameHostMsg_DidCommitProvisionalLoad_Params params;
params.nav_entry_id = entry_id;
@@ -2103,7 +2082,8 @@ TEST_F(NavigationControllerTest, PostThenRedirect) {
params.did_create_new_entry = false;
params.method = "GET";
- EXPECT_EQ(0U, notifications.size());
+ EXPECT_EQ(0U, navigation_entry_changed_counter_);
+ EXPECT_EQ(0U, navigation_list_pruned_counter_);
LoadCommittedDetailsObserver observer(contents());
main_test_rfh()->PrepareForCommit();
main_test_rfh()->SendNavigateWithParams(&params);
@@ -2126,8 +2106,6 @@ TEST_F(NavigationControllerTest, PostThenRedirect) {
// A redirect right off the bat should be a NEW_PAGE.
TEST_F(NavigationControllerTest, ImmediateRedirect) {
NavigationControllerImpl& controller = controller_impl();
- TestNotificationTracker notifications;
- RegisterForAllNavNotifications(&notifications, &controller);
const GURL url1("http://foo1");
const GURL url2("http://foo2"); // Redirection target
@@ -2155,7 +2133,8 @@ TEST_F(NavigationControllerTest, ImmediateRedirect) {
LoadCommittedDetailsObserver observer(contents());
- EXPECT_EQ(0U, notifications.size());
+ EXPECT_EQ(0U, navigation_entry_changed_counter_);
+ EXPECT_EQ(0U, navigation_list_pruned_counter_);
main_test_rfh()->PrepareForCommit();
main_test_rfh()->SendNavigateWithParams(&params);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
@@ -2194,7 +2173,7 @@ TEST_F(NavigationControllerTest,
const GURL url2("http://foo2");
// Start with a loaded page.
- main_test_rfh()->NavigateAndCommitRendererInitiated(true, url1);
+ NavigationSimulator::NavigateAndCommitFromDocument(url1, main_test_rfh());
EXPECT_EQ(nullptr, controller_impl().GetPendingEntry());
// Start a load of the same page again.
@@ -2228,11 +2207,9 @@ TEST_F(NavigationControllerTest,
// should be created.
TEST_F(NavigationControllerTest, NewSubframe) {
NavigationControllerImpl& controller = controller_impl();
- TestNotificationTracker notifications;
- RegisterForAllNavNotifications(&notifications, &controller);
const GURL url1("http://foo1");
- main_test_rfh()->NavigateAndCommitRendererInitiated(true, url1);
+ NavigationSimulator::NavigateAndCommitFromDocument(url1, main_test_rfh());
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
@@ -2264,7 +2241,7 @@ TEST_F(NavigationControllerTest, NewSubframe) {
// We notify of a PageState update here rather than during UpdateState for
// auto subframe navigations.
- EXPECT_TRUE(notifications.Check1AndReset(NOTIFICATION_NAV_ENTRY_CHANGED));
+ EXPECT_EQ(1u, navigation_entry_changed_counter_);
}
// Now do a new navigation in the frame.
@@ -2308,11 +2285,9 @@ TEST_F(NavigationControllerTest, NewSubframe) {
// TODO(creis): Test updating entries for history auto subframe navigations.
TEST_F(NavigationControllerTest, AutoSubframe) {
NavigationControllerImpl& controller = controller_impl();
- TestNotificationTracker notifications;
- RegisterForAllNavNotifications(&notifications, &controller);
const GURL url1("http://foo/1");
- main_test_rfh()->NavigateAndCommitRendererInitiated(true, url1);
+ NavigationSimulator::NavigateAndCommitFromDocument(url1, main_test_rfh());
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
@@ -2344,7 +2319,8 @@ TEST_F(NavigationControllerTest, AutoSubframe) {
// We notify of a PageState update here rather than during UpdateState for
// auto subframe navigations.
- EXPECT_TRUE(notifications.Check1AndReset(NOTIFICATION_NAV_ENTRY_CHANGED));
+ EXPECT_EQ(1u, navigation_entry_changed_counter_);
+ navigation_entry_changed_counter_ = 0;
}
// There should still be only one entry.
@@ -2388,7 +2364,8 @@ TEST_F(NavigationControllerTest, AutoSubframe) {
// We notify of a PageState update here rather than during UpdateState for
// auto subframe navigations.
- EXPECT_TRUE(notifications.Check1AndReset(NOTIFICATION_NAV_ENTRY_CHANGED));
+ EXPECT_EQ(1u, navigation_entry_changed_counter_);
+ navigation_entry_changed_counter_ = 0;
}
// There should still be only one entry, mostly unchanged.
@@ -2437,7 +2414,8 @@ TEST_F(NavigationControllerTest, AutoSubframe) {
// We notify of a PageState update here rather than during UpdateState for
// auto subframe navigations.
- EXPECT_TRUE(notifications.Check1AndReset(NOTIFICATION_NAV_ENTRY_CHANGED));
+ EXPECT_EQ(1u, navigation_entry_changed_counter_);
+ navigation_entry_changed_counter_ = 0;
}
// There should still be only one entry, mostly unchanged.
@@ -2458,12 +2436,10 @@ TEST_F(NavigationControllerTest, AutoSubframe) {
// Tests navigation and then going back to a subframe navigation.
TEST_F(NavigationControllerTest, BackSubframe) {
NavigationControllerImpl& controller = controller_impl();
- TestNotificationTracker notifications;
- RegisterForAllNavNotifications(&notifications, &controller);
// Main page.
const GURL url1("http://foo1");
- main_test_rfh()->NavigateAndCommitRendererInitiated(true, url1);
+ NavigationSimulator::NavigateAndCommitFromDocument(url1, main_test_rfh());
EXPECT_EQ(1U, navigation_entry_committed_counter_);
NavigationEntry* entry1 = controller.GetLastCommittedEntry();
navigation_entry_committed_counter_ = 0;
@@ -2504,7 +2480,7 @@ TEST_F(NavigationControllerTest, BackSubframe) {
// We notify of a PageState update here rather than during UpdateState for
// auto subframe navigations.
- EXPECT_TRUE(notifications.Check1AndReset(NOTIFICATION_NAV_ENTRY_CHANGED));
+ EXPECT_EQ(1u, navigation_entry_changed_counter_);
}
// First manual subframe navigation.
@@ -2609,17 +2585,15 @@ TEST_F(NavigationControllerTest, BackSubframe) {
TEST_F(NavigationControllerTest, LinkClick) {
NavigationControllerImpl& controller = controller_impl();
- TestNotificationTracker notifications;
- RegisterForAllNavNotifications(&notifications, &controller);
const GURL url1("http://foo1");
const GURL url2("http://foo2");
- main_test_rfh()->NavigateAndCommitRendererInitiated(true, url1);
+ NavigationSimulator::NavigateAndCommitFromDocument(url1, main_test_rfh());
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
- main_test_rfh()->NavigateAndCommitRendererInitiated(true, url2);
+ NavigationSimulator::NavigateAndCommitFromDocument(url2, main_test_rfh());
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
@@ -2635,12 +2609,10 @@ TEST_F(NavigationControllerTest, LinkClick) {
TEST_F(NavigationControllerTest, SameDocument) {
NavigationControllerImpl& controller = controller_impl();
- TestNotificationTracker notifications;
- RegisterForAllNavNotifications(&notifications, &controller);
// Main page.
const GURL url1("http://foo");
- main_test_rfh()->NavigateAndCommitRendererInitiated(true, url1);
+ NavigationSimulator::NavigateAndCommitFromDocument(url1, main_test_rfh());
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
@@ -2758,12 +2730,10 @@ TEST_F(NavigationControllerTest, SameDocument) {
TEST_F(NavigationControllerTest, SameDocument_Replace) {
NavigationControllerImpl& controller = controller_impl();
- TestNotificationTracker notifications;
- RegisterForAllNavNotifications(&notifications, &controller);
// Main page.
const GURL url1("http://foo");
- main_test_rfh()->NavigateAndCommitRendererInitiated(true, url1);
+ NavigationSimulator::NavigateAndCommitFromDocument(url1, main_test_rfh());
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
@@ -2798,13 +2768,11 @@ TEST_F(NavigationControllerTest, SameDocument_Replace) {
// </script>
TEST_F(NavigationControllerTest, ClientRedirectAfterInPageNavigation) {
NavigationControllerImpl& controller = controller_impl();
- TestNotificationTracker notifications;
- RegisterForAllNavNotifications(&notifications, &controller);
// Load an initial page.
{
const GURL url("http://foo/");
- main_test_rfh()->NavigateAndCommitRendererInitiated(true, url);
+ NavigationSimulator::NavigateAndCommitFromDocument(url, main_test_rfh());
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
}
@@ -2812,7 +2780,7 @@ TEST_F(NavigationControllerTest, ClientRedirectAfterInPageNavigation) {
// Navigate to a new page.
{
const GURL url("http://foo2/");
- main_test_rfh()->NavigateAndCommitRendererInitiated(true, url);
+ NavigationSimulator::NavigateAndCommitFromDocument(url, main_test_rfh());
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
}
@@ -2897,37 +2865,6 @@ TEST_F(NavigationControllerTest, PushStateWithoutPreviousEntry)
// We pass if we don't crash.
}
-// NotificationObserver implementation used in verifying we've received the
-// NOTIFICATION_NAV_LIST_PRUNED method.
-class PrunedListener : public NotificationObserver {
- public:
- explicit PrunedListener(NavigationControllerImpl* controller)
- : notification_count_(0) {
- registrar_.Add(this, NOTIFICATION_NAV_LIST_PRUNED,
- Source<NavigationController>(controller));
- }
-
- void Observe(int type,
- const NotificationSource& source,
- const NotificationDetails& details) override {
- if (type == NOTIFICATION_NAV_LIST_PRUNED) {
- notification_count_++;
- details_ = *(Details<PrunedDetails>(details).ptr());
- }
- }
-
- // Number of times NAV_LIST_PRUNED has been observed.
- int notification_count_;
-
- // Details from the last NAV_LIST_PRUNED.
- PrunedDetails details_;
-
- private:
- NotificationRegistrar registrar_;
-
- DISALLOW_COPY_AND_ASSIGN(PrunedListener);
-};
-
// Tests that we limit the number of navigation entries created correctly.
TEST_F(NavigationControllerTest, EnforceMaxNavigationCount) {
NavigationControllerImpl& controller = controller_impl();
@@ -2949,8 +2886,6 @@ TEST_F(NavigationControllerTest, EnforceMaxNavigationCount) {
EXPECT_EQ(controller.GetEntryCount(), kMaxEntryCount);
- // Created a PrunedListener to observe prune notifications.
- PrunedListener listener(&controller);
// Navigate some more.
GURL url(base::StringPrintf("http://www.a.com/%d", url_index));
@@ -2962,9 +2897,9 @@ TEST_F(NavigationControllerTest, EnforceMaxNavigationCount) {
url_index++;
// We should have got a pruned navigation.
- EXPECT_EQ(1, listener.notification_count_);
- EXPECT_TRUE(listener.details_.from_front);
- EXPECT_EQ(1, listener.details_.count);
+ EXPECT_EQ(1U, navigation_list_pruned_counter_);
+ EXPECT_TRUE(last_navigation_entry_pruned_details_.from_front);
+ EXPECT_EQ(1, last_navigation_entry_pruned_details_.count);
// We expect http://www.a.com/0 to be gone.
EXPECT_EQ(controller.GetEntryCount(), kMaxEntryCount);
@@ -3287,8 +3222,6 @@ TEST_F(NavigationControllerTest, RemoveEntryWithPending) {
// Tests the transient entry, making sure it goes away with all navigations.
TEST_F(NavigationControllerTest, TransientEntry) {
NavigationControllerImpl& controller = controller_impl();
- TestNotificationTracker notifications;
- RegisterForAllNavNotifications(&notifications, &controller);
const GURL url0("http://foo/0");
const GURL url1("http://foo/1");
@@ -3309,7 +3242,8 @@ TEST_F(NavigationControllerTest, TransientEntry) {
main_test_rfh()->PrepareForCommit();
main_test_rfh()->SendNavigate(entry_id, true, url1);
- notifications.Reset();
+ navigation_entry_changed_counter_ = 0;
+ navigation_list_pruned_counter_ = 0;
// Adding a transient with no pending entry.
std::unique_ptr<NavigationEntry> transient_entry(new NavigationEntryImpl);
@@ -3317,7 +3251,8 @@ TEST_F(NavigationControllerTest, TransientEntry) {
controller.SetTransientEntry(std::move(transient_entry));
// We should not have received any notifications.
- EXPECT_EQ(0U, notifications.size());
+ EXPECT_EQ(0U, navigation_entry_changed_counter_);
+ EXPECT_EQ(0U, navigation_list_pruned_counter_);
// Check our state.
EXPECT_EQ(transient_url, controller.GetVisibleEntry()->GetURL());
@@ -3567,8 +3502,6 @@ TEST_F(NavigationControllerTest, RendererInitiatedPendingEntries) {
// See http://crbug.com/99016.
TEST_F(NavigationControllerTest, DontShowRendererURLUntilCommit) {
NavigationControllerImpl& controller = controller_impl();
- TestNotificationTracker notifications;
- RegisterForAllNavNotifications(&notifications, &controller);
const GURL url0("http://foo/0");
const GURL url1("http://foo/1");
@@ -3600,8 +3533,6 @@ TEST_F(NavigationControllerTest, DontShowRendererURLUntilCommit) {
EXPECT_EQ(url1, controller.GetVisibleEntry()->GetURL());
EXPECT_FALSE(controller.GetPendingEntry());
EXPECT_FALSE(controller.GetLastCommittedEntry()->is_renderer_initiated());
-
- notifications.Reset();
}
// Tests that the URLs for renderer-initiated navigations in new tabs are
@@ -3610,8 +3541,6 @@ TEST_F(NavigationControllerTest, DontShowRendererURLUntilCommit) {
// See http://crbug.com/9682.
TEST_F(NavigationControllerTest, ShowRendererURLInNewTabUntilModified) {
NavigationControllerImpl& controller = controller_impl();
- TestNotificationTracker notifications;
- RegisterForAllNavNotifications(&notifications, &controller);
const GURL url("http://foo");
@@ -3637,8 +3566,6 @@ TEST_F(NavigationControllerTest, ShowRendererURLInNewTabUntilModified) {
EXPECT_TRUE(contents()->HasAccessedInitialDocument());
EXPECT_FALSE(controller.GetVisibleEntry());
EXPECT_EQ(url, controller.GetPendingEntry()->GetURL());
-
- notifications.Reset();
}
// Tests that the URLs for browser-initiated navigations in new tabs are
@@ -3647,8 +3574,6 @@ TEST_F(NavigationControllerTest, ShowRendererURLInNewTabUntilModified) {
// about:blank. See http://crbug.com/355537.
TEST_F(NavigationControllerTest, ShowBrowserURLAfterFailUntilModified) {
NavigationControllerImpl& controller = controller_impl();
- TestNotificationTracker notifications;
- RegisterForAllNavNotifications(&notifications, &controller);
const GURL url("http://foo");
@@ -3692,8 +3617,6 @@ TEST_F(NavigationControllerTest, ShowBrowserURLAfterFailUntilModified) {
EXPECT_TRUE(contents()->HasAccessedInitialDocument());
EXPECT_FALSE(controller.GetVisibleEntry());
EXPECT_FALSE(controller.GetPendingEntry());
-
- notifications.Reset();
}
// Tests that the URLs for renderer-initiated navigations in new tabs are
@@ -3702,8 +3625,6 @@ TEST_F(NavigationControllerTest, ShowBrowserURLAfterFailUntilModified) {
// about:blank. See http://crbug.com/355537.
TEST_F(NavigationControllerTest, ShowRendererURLAfterFailUntilModified) {
NavigationControllerImpl& controller = controller_impl();
- TestNotificationTracker notifications;
- RegisterForAllNavNotifications(&notifications, &controller);
const GURL url("http://foo");
@@ -3740,14 +3661,10 @@ TEST_F(NavigationControllerTest, ShowRendererURLAfterFailUntilModified) {
EXPECT_TRUE(contents()->HasAccessedInitialDocument());
EXPECT_FALSE(controller.GetVisibleEntry());
EXPECT_EQ(url, controller.GetPendingEntry()->GetURL());
-
- notifications.Reset();
}
TEST_F(NavigationControllerTest, DontShowRendererURLInNewTabAfterCommit) {
NavigationControllerImpl& controller = controller_impl();
- TestNotificationTracker notifications;
- RegisterForAllNavNotifications(&notifications, &controller);
const GURL url1("http://foo/eh");
const GURL url2("http://foo/bee");
@@ -3779,8 +3696,6 @@ TEST_F(NavigationControllerTest, DontShowRendererURLInNewTabAfterCommit) {
EXPECT_FALSE(controller.IsInitialNavigation());
EXPECT_TRUE(controller.GetVisibleEntry());
EXPECT_EQ(url1, controller.GetVisibleEntry()->GetURL());
-
- notifications.Reset();
}
// Tests that IsInPageNavigation returns appropriate results. Prevents
@@ -3805,7 +3720,7 @@ TEST_F(NavigationControllerTest, IsInPageNavigation) {
main_test_rfh()));
// Navigate to URL with no refs.
- main_test_rfh()->NavigateAndCommitRendererInitiated(false, url);
+ NavigationSimulator::NavigateAndCommitFromDocument(url, main_test_rfh());
// Reloading the page is not an in-page navigation.
EXPECT_FALSE(controller.IsURLInPageNavigation(url, url::Origin(url), false,
@@ -3818,7 +3733,8 @@ TEST_F(NavigationControllerTest, IsInPageNavigation) {
url_with_ref, url::Origin(url_with_ref), true, main_test_rfh()));
// Navigate to URL with refs.
- main_test_rfh()->NavigateAndCommitRendererInitiated(true, url_with_ref);
+ NavigationSimulator::NavigateAndCommitFromDocument(url_with_ref,
+ main_test_rfh());
// Reloading the page is not an in-page navigation.
EXPECT_FALSE(controller.IsURLInPageNavigation(
@@ -3927,7 +3843,7 @@ TEST_F(NavigationControllerTest, SameSubframe) {
NavigationControllerImpl& controller = controller_impl();
// Navigate the main frame.
const GURL url("http://www.google.com/");
- main_test_rfh()->NavigateAndCommitRendererInitiated(true, url);
+ NavigationSimulator::NavigateAndCommitFromDocument(url, main_test_rfh());
// We should be at the first navigation entry.
EXPECT_EQ(controller.GetEntryCount(), 1);
@@ -4437,8 +4353,6 @@ TEST_F(NavigationControllerTest, CopyStateFromAndPruneMaxEntries) {
const GURL url3("http://foo/3");
const GURL url4("http://foo/4");
- // Create a PrunedListener to observe prune notifications.
- PrunedListener listener(&controller);
NavigateAndCommit(url1);
NavigateAndCommit(url2);
@@ -4452,9 +4366,9 @@ TEST_F(NavigationControllerTest, CopyStateFromAndPruneMaxEntries) {
other_controller.CopyStateFromAndPrune(&controller, false);
// We should have received a pruned notification.
- EXPECT_EQ(1, listener.notification_count_);
- EXPECT_TRUE(listener.details_.from_front);
- EXPECT_EQ(1, listener.details_.count);
+ EXPECT_EQ(1U, navigation_list_pruned_counter_);
+ EXPECT_TRUE(last_navigation_entry_pruned_details_.from_front);
+ EXPECT_EQ(1, last_navigation_entry_pruned_details_.count);
// other_controller should now contain only 3 urls: url2, url3 and url4.
@@ -4523,8 +4437,6 @@ TEST_F(NavigationControllerTest, CopyStateFromAndPruneMaxEntriesReplaceEntry) {
const GURL url3("http://foo/3");
const GURL url4("http://foo/4");
- // Create a PrunedListener to observe prune notifications.
- PrunedListener listener(&controller);
NavigateAndCommit(url1);
NavigateAndCommit(url2);
@@ -4538,7 +4450,7 @@ TEST_F(NavigationControllerTest, CopyStateFromAndPruneMaxEntriesReplaceEntry) {
other_controller.CopyStateFromAndPrune(&controller, true);
// We should have received no pruned notification.
- EXPECT_EQ(0, listener.notification_count_);
+ EXPECT_EQ(0U, navigation_list_pruned_counter_);
// other_controller should now contain only 3 urls: url1, url2 and url4.
@@ -4772,8 +4684,6 @@ TEST_F(NavigationControllerTest, StopOnHistoryNavigationToCurrentPage) {
TEST_F(NavigationControllerTest, IsInitialNavigation) {
NavigationControllerImpl& controller = controller_impl();
- TestNotificationTracker notifications;
- RegisterForAllNavNotifications(&notifications, &controller);
// Initial state.
EXPECT_TRUE(controller.IsInitialNavigation());
@@ -4781,7 +4691,7 @@ TEST_F(NavigationControllerTest, IsInitialNavigation) {
// After commit, it stays false.
const GURL url1("http://foo1");
- main_test_rfh()->NavigateAndCommitRendererInitiated(true, url1);
+ NavigationSimulator::NavigateAndCommitFromDocument(url1, main_test_rfh());
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
EXPECT_FALSE(controller.IsInitialNavigation());
@@ -4810,10 +4720,9 @@ TEST_F(NavigationControllerTest, ClearFaviconOnRedirect) {
const gfx::Image kDefaultFavicon = FaviconStatus().image;
NavigationControllerImpl& controller = controller_impl();
- TestNotificationTracker notifications;
- RegisterForAllNavNotifications(&notifications, &controller);
- main_test_rfh()->NavigateAndCommitRendererInitiated(true, kPageWithFavicon);
+ NavigationSimulator::NavigateAndCommitFromDocument(kPageWithFavicon,
+ main_test_rfh());
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
@@ -4853,10 +4762,8 @@ TEST_F(NavigationControllerTest, BackNavigationDoesNotClearFavicon) {
const GURL kIconURL("http://www.a.com/1/favicon.ico");
NavigationControllerImpl& controller = controller_impl();
- TestNotificationTracker notifications;
- RegisterForAllNavNotifications(&notifications, &controller);
- main_test_rfh()->NavigateAndCommitRendererInitiated(true, kUrl1);
+ NavigationSimulator::NavigateAndCommitFromDocument(kUrl1, main_test_rfh());
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
@@ -4870,7 +4777,7 @@ TEST_F(NavigationControllerTest, BackNavigationDoesNotClearFavicon) {
favicon_status.valid = true;
// Navigate to another page and go back to the original page.
- main_test_rfh()->NavigateAndCommitRendererInitiated(true, kUrl2);
+ NavigationSimulator::NavigateAndCommitFromDocument(kUrl2, main_test_rfh());
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
main_test_rfh()->SendRendererInitiatedNavigationRequest(kUrl1, false);
@@ -4977,7 +4884,8 @@ TEST_F(NavigationControllerTest, MAYBE_PurgeScreenshot) {
TEST_F(NavigationControllerTest, PushStateUpdatesTitleAndFavicon) {
// Navigate.
- main_test_rfh()->NavigateAndCommitRendererInitiated(true, GURL("http://foo"));
+ NavigationSimulator::NavigateAndCommitFromDocument(GURL("http://foo"),
+ main_test_rfh());
// Set title and favicon.
base::string16 title(base::ASCIIToUTF16("Title"));
@@ -5171,12 +5079,10 @@ TEST_F(NavigationControllerTest, UnreachableURLGivesErrorPage) {
// resurrected.
TEST_F(NavigationControllerTest, StaleNavigationsResurrected) {
NavigationControllerImpl& controller = controller_impl();
- TestNotificationTracker notifications;
- RegisterForAllNavNotifications(&notifications, &controller);
// Start on page A.
const GURL url_a("http://foo.com/a");
- main_test_rfh()->NavigateAndCommitRendererInitiated(true, url_a);
+ NavigationSimulator::NavigateAndCommitFromDocument(url_a, main_test_rfh());
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
EXPECT_EQ(1, controller.GetEntryCount());
@@ -5184,7 +5090,7 @@ TEST_F(NavigationControllerTest, StaleNavigationsResurrected) {
// Go to page B.
const GURL url_b("http://foo.com/b");
- main_test_rfh()->NavigateAndCommitRendererInitiated(true, url_b);
+ NavigationSimulator::NavigateAndCommitFromDocument(url_b, main_test_rfh());
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
EXPECT_EQ(2, controller.GetEntryCount());
@@ -5204,7 +5110,7 @@ TEST_F(NavigationControllerTest, StaleNavigationsResurrected) {
// But the renderer unilaterally navigates to page C, pruning B.
const GURL url_c("http://foo.com/c");
- main_test_rfh()->NavigateAndCommitRendererInitiated(true, url_c);
+ NavigationSimulator::NavigateAndCommitFromDocument(url_c, main_test_rfh());
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
EXPECT_EQ(2, controller.GetEntryCount());
@@ -5235,8 +5141,6 @@ TEST_F(NavigationControllerTest, StaleNavigationsResurrected) {
// http://crbug.com/664319
TEST_F(NavigationControllerTest, MultipleNavigationsAndReload) {
NavigationControllerImpl& controller = controller_impl();
- TestNotificationTracker notifications;
- RegisterForAllNavNotifications(&notifications, &controller);
GURL initial_url("http://www.google.com");
GURL url_1("http://foo.com");
diff --git a/chromium/content/browser/frame_host/navigation_entry_impl.cc b/chromium/content/browser/frame_host/navigation_entry_impl.cc
index b9e025600c3..71e8e7fcb0b 100644
--- a/chromium/content/browser/frame_host/navigation_entry_impl.cc
+++ b/chromium/content/browser/frame_host/navigation_entry_impl.cc
@@ -135,8 +135,6 @@ bool InSameTreePosition(FrameTreeNode* frame_tree_node,
} // namespace
-int NavigationEntryImpl::kInvalidBindings = -1;
-
NavigationEntryImpl::TreeNode::TreeNode(TreeNode* parent,
FrameNavigationEntry* frame_entry)
: parent(parent), frame_entry(frame_entry) {}
diff --git a/chromium/content/browser/frame_host/navigation_entry_impl.h b/chromium/content/browser/frame_host/navigation_entry_impl.h
index 83f058ed72a..b70a51f6bae 100644
--- a/chromium/content/browser/frame_host/navigation_entry_impl.h
+++ b/chromium/content/browser/frame_host/navigation_entry_impl.h
@@ -35,8 +35,7 @@ struct CommonNavigationParams;
struct RequestNavigationParams;
struct StartNavigationParams;
-class CONTENT_EXPORT NavigationEntryImpl
- : public NON_EXPORTED_BASE(NavigationEntry) {
+class CONTENT_EXPORT NavigationEntryImpl : public NavigationEntry {
public:
// Represents a tree of FrameNavigationEntries that make up this joint session
// history item. The tree currently only tracks the main frame by default,
@@ -83,7 +82,7 @@ class CONTENT_EXPORT NavigationEntryImpl
std::unique_ptr<NavigationEntry> entry);
// The value of bindings() before it is set during commit.
- static int kInvalidBindings;
+ enum : int { kInvalidBindings = -1 };
NavigationEntryImpl();
NavigationEntryImpl(scoped_refptr<SiteInstanceImpl> instance,
diff --git a/chromium/content/browser/frame_host/navigation_entry_impl_unittest.cc b/chromium/content/browser/frame_host/navigation_entry_impl_unittest.cc
index b2353d3a534..73b50be56d7 100644
--- a/chromium/content/browser/frame_host/navigation_entry_impl_unittest.cc
+++ b/chromium/content/browser/frame_host/navigation_entry_impl_unittest.cc
@@ -16,6 +16,34 @@ using base::ASCIIToUTF16;
namespace content {
+namespace {
+
+// A test class for testing SSLStatus user data.
+class TestSSLStatusData : public SSLStatus::UserData {
+ public:
+ TestSSLStatusData() {}
+ ~TestSSLStatusData() override {}
+
+ void set_user_data_flag(bool user_data_flag) {
+ user_data_flag_ = user_data_flag;
+ }
+ bool user_data_flag() { return user_data_flag_; }
+
+ // SSLStatus implementation:
+ std::unique_ptr<SSLStatus::UserData> Clone() override {
+ std::unique_ptr<TestSSLStatusData> cloned =
+ base::MakeUnique<TestSSLStatusData>();
+ cloned->set_user_data_flag(user_data_flag_);
+ return std::move(cloned);
+ }
+
+ private:
+ bool user_data_flag_ = false;
+ DISALLOW_COPY_AND_ASSIGN(TestSSLStatusData);
+};
+
+} // namespace
+
class NavigationEntryTest : public testing::Test {
public:
NavigationEntryTest() : instance_(NULL) {
@@ -144,6 +172,25 @@ TEST_F(NavigationEntryTest, NavigationEntrySSLStatus) {
EXPECT_FALSE(!!(content_status & SSLStatus::RAN_INSECURE_CONTENT));
}
+// Tests that SSLStatus user data can be added, retrieved, and copied.
+TEST_F(NavigationEntryTest, SSLStatusUserData) {
+ // Set up an SSLStatus with some user data on it.
+ SSLStatus ssl;
+ ssl.user_data = base::MakeUnique<TestSSLStatusData>();
+ TestSSLStatusData* ssl_data =
+ static_cast<TestSSLStatusData*>(ssl.user_data.get());
+ ASSERT_TRUE(ssl_data);
+ ssl_data->set_user_data_flag(true);
+
+ // Clone the SSLStatus and test that the user data has been cloned.
+ SSLStatus cloned(ssl);
+ TestSSLStatusData* cloned_ssl_data =
+ static_cast<TestSSLStatusData*>(cloned.user_data.get());
+ ASSERT_TRUE(cloned_ssl_data);
+ EXPECT_TRUE(cloned_ssl_data->user_data_flag());
+ EXPECT_NE(cloned_ssl_data, ssl_data);
+}
+
// Test other basic accessors
TEST_F(NavigationEntryTest, NavigationEntryAccessors) {
// SiteInstance
diff --git a/chromium/content/browser/frame_host/navigation_entry_screenshot_manager.cc b/chromium/content/browser/frame_host/navigation_entry_screenshot_manager.cc
index 193392dcec7..46b61dab6f8 100644
--- a/chromium/content/browser/frame_host/navigation_entry_screenshot_manager.cc
+++ b/chromium/content/browser/frame_host/navigation_entry_screenshot_manager.cc
@@ -34,7 +34,8 @@ class ScreenshotData : public base::RefCountedThreadSafe<ScreenshotData> {
void EncodeScreenshot(const SkBitmap& bitmap, base::Closure callback) {
base::PostTaskWithTraitsAndReply(
FROM_HERE, {base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
- base::Bind(&ScreenshotData::EncodeOnWorker, this, bitmap), callback);
+ base::BindOnce(&ScreenshotData::EncodeOnWorker, this, bitmap),
+ callback);
}
scoped_refptr<base::RefCountedBytes> data() const { return data_; }
diff --git a/chromium/content/browser/frame_host/navigation_handle_impl.cc b/chromium/content/browser/frame_host/navigation_handle_impl.cc
index ec9ded6b49d..2e4d0d9ac4c 100644
--- a/chromium/content/browser/frame_host/navigation_handle_impl.cc
+++ b/chromium/content/browser/frame_host/navigation_handle_impl.cc
@@ -44,6 +44,13 @@ namespace content {
namespace {
+// Use this to get a new unique ID for a NavigationHandle during construction.
+// The returned ID is guaranteed to be nonzero (zero is the "no ID" indicator).
+int64_t GetUniqueIDInConstructor() {
+ static int64_t unique_id_counter = 0;
+ return ++unique_id_counter;
+}
+
void UpdateThrottleCheckResult(
NavigationThrottle::ThrottleCheckResult* to_update,
NavigationThrottle::ThrottleCheckResult result) {
@@ -111,6 +118,7 @@ NavigationHandleImpl::NavigationHandleImpl(
request_context_type_(REQUEST_CONTEXT_TYPE_UNSPECIFIED),
mixed_content_context_type_(
blink::WebMixedContentContextType::kBlockable),
+ navigation_id_(GetUniqueIDInConstructor()),
should_replace_current_entry_(false),
redirect_chain_(redirect_chain),
is_download_(false),
@@ -194,9 +202,9 @@ NavigationHandleImpl::~NavigationHandleImpl() {
// from the renderer need to be cleaned up. These are marked as protected in
// the RDHI, so they do not get cancelled when frames are destroyed.
if (is_transferring()) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::Bind(&NotifyAbandonedTransferNavigation, GetGlobalRequestID()));
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&NotifyAbandonedTransferNavigation,
+ GetGlobalRequestID()));
}
if (!IsRendererDebugURL(url_))
@@ -219,6 +227,10 @@ NavigatorDelegate* NavigationHandleImpl::GetDelegate() const {
return frame_tree_node_->navigator()->GetDelegate();
}
+int64_t NavigationHandleImpl::GetNavigationId() const {
+ return navigation_id_;
+}
+
const GURL& NavigationHandleImpl::GetURL() {
return url_;
}
@@ -358,8 +370,7 @@ net::HostPortPair NavigationHandleImpl::GetSocketAddress() {
void NavigationHandleImpl::Resume(NavigationThrottle* resuming_throttle) {
DCHECK(resuming_throttle);
- // TODO(csharrison): Convert to DCHECK when crbug.com/736249 is resolved.
- CHECK_EQ(resuming_throttle, GetDeferringThrottle());
+ DCHECK_EQ(resuming_throttle, GetDeferringThrottle());
ResumeInternal();
}
@@ -367,8 +378,7 @@ void NavigationHandleImpl::CancelDeferredNavigation(
NavigationThrottle* cancelling_throttle,
NavigationThrottle::ThrottleCheckResult result) {
DCHECK(cancelling_throttle);
- // TODO(csharrison): Convert to DCHECK when crbug.com/736249 is resolved.
- CHECK_EQ(cancelling_throttle, GetDeferringThrottle());
+ DCHECK_EQ(cancelling_throttle, GetDeferringThrottle());
CancelDeferredNavigationInternal(result);
}
@@ -497,9 +507,13 @@ NavigationData* NavigationHandleImpl::GetNavigationData() {
return navigation_data_.get();
}
+void NavigationHandleImpl::SetOnDeferCallbackForTesting(
+ const base::Closure& on_defer_callback) {
+ on_defer_callback_for_testing_ = on_defer_callback;
+}
+
const GlobalRequestID& NavigationHandleImpl::GetGlobalRequestID() {
- DCHECK(state_ == WILL_PROCESS_RESPONSE || state_ == DEFERRING_RESPONSE ||
- state_ == READY_TO_COMMIT);
+ DCHECK(state_ >= WILL_PROCESS_RESPONSE);
return request_id_;
}
@@ -572,8 +586,11 @@ void NavigationHandleImpl::WillStartRequest(
navigation_ui_data_ = GetDelegate()->GetNavigationUIData(this);
// Notify each throttle of the request.
+ base::Closure on_defer_callback_copy = on_defer_callback_for_testing_;
NavigationThrottle::ThrottleCheckResult result = CheckWillStartRequest();
if (result == NavigationThrottle::DEFER) {
+ if (!on_defer_callback_copy.is_null())
+ on_defer_callback_copy.Run();
// DO NOT ADD CODE: the NavigationHandle might have been destroyed during
// one of the NavigationThrottle checks.
return;
@@ -634,8 +651,11 @@ void NavigationHandleImpl::WillRedirectRequest(
}
// Notify each throttle of the request.
+ base::Closure on_defer_callback_copy = on_defer_callback_for_testing_;
NavigationThrottle::ThrottleCheckResult result = CheckWillRedirectRequest();
if (result == NavigationThrottle::DEFER) {
+ if (!on_defer_callback_copy.is_null())
+ on_defer_callback_copy.Run();
// DO NOT ADD CODE: the NavigationHandle might have been destroyed during
// one of the NavigationThrottle checks.
return;
@@ -674,8 +694,11 @@ void NavigationHandleImpl::WillProcessResponse(
transfer_callback_ = transfer_callback;
// Notify each throttle of the response.
+ base::Closure on_defer_callback_copy = on_defer_callback_for_testing_;
NavigationThrottle::ThrottleCheckResult result = CheckWillProcessResponse();
if (result == NavigationThrottle::DEFER) {
+ if (!on_defer_callback_copy.is_null())
+ on_defer_callback_copy.Run();
// DO NOT ADD CODE: the NavigationHandle might have been destroyed during
// one of the NavigationThrottle checks.
return;
@@ -978,9 +1001,12 @@ void NavigationHandleImpl::ResumeInternal() {
"Resume");
NavigationThrottle::ThrottleCheckResult result = NavigationThrottle::DEFER;
+ base::Closure on_defer_callback_copy = on_defer_callback_for_testing_;
if (state_ == DEFERRING_START) {
result = CheckWillStartRequest();
if (result == NavigationThrottle::DEFER) {
+ if (!on_defer_callback_copy.is_null())
+ on_defer_callback_copy.Run();
// DO NOT ADD CODE: the NavigationHandle might have been destroyed during
// one of the NavigationThrottle checks.
return;
@@ -988,6 +1014,8 @@ void NavigationHandleImpl::ResumeInternal() {
} else if (state_ == DEFERRING_REDIRECT) {
result = CheckWillRedirectRequest();
if (result == NavigationThrottle::DEFER) {
+ if (!on_defer_callback_copy.is_null())
+ on_defer_callback_copy.Run();
// DO NOT ADD CODE: the NavigationHandle might have been destroyed during
// one of the NavigationThrottle checks.
return;
@@ -995,6 +1023,8 @@ void NavigationHandleImpl::ResumeInternal() {
} else {
result = CheckWillProcessResponse();
if (result == NavigationThrottle::DEFER) {
+ if (!on_defer_callback_copy.is_null())
+ on_defer_callback_copy.Run();
// DO NOT ADD CODE: the NavigationHandle might have been destroyed during
// one of the NavigationThrottle checks.
return;
@@ -1077,11 +1107,6 @@ bool NavigationHandleImpl::MaybeTransferAndProceedInternal() {
return false;
}
- // Subframes shouldn't swap processes unless out-of-process iframes are
- // possible.
- if (!IsInMainFrame() && !SiteIsolationPolicy::AreCrossProcessFramesPossible())
- return true;
-
// If this is a download, do not do a cross-site check. The renderer will
// see it is a download and abort the request.
//
@@ -1108,8 +1133,7 @@ bool NavigationHandleImpl::MaybeTransferAndProceedInternal() {
// above) that a process transfer is needed. Process transfers are skipped for
// WebUI processes for now, since e.g. chrome://settings has multiple
// "cross-site" chrome:// frames, and that doesn't yet work cross-process.
- if (SiteIsolationPolicy::AreCrossProcessFramesPossible() &&
- !ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
+ if (!ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
render_frame_host_->GetProcess()->GetID())) {
should_transfer |= manager->IsRendererTransferNeededForNavigation(
render_frame_host_, url_);
diff --git a/chromium/content/browser/frame_host/navigation_handle_impl.h b/chromium/content/browser/frame_host/navigation_handle_impl.h
index fb9bf9e9e2b..5206a02934c 100644
--- a/chromium/content/browser/frame_host/navigation_handle_impl.h
+++ b/chromium/content/browser/frame_host/navigation_handle_impl.h
@@ -112,6 +112,7 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
};
// NavigationHandle implementation:
+ int64_t GetNavigationId() const override;
const GURL& GetURL() override;
SiteInstance* GetStartingSiteInstance() override;
bool IsInMainFrame() override;
@@ -177,6 +178,7 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
// Used in tests.
State state_for_testing() const { return state_; }
+ void SetOnDeferCallbackForTesting(const base::Closure& on_defer_callback);
// Whether or not the navigation has been initiated by a form submission.
// TODO(arthursonzogni): This value is correct only when PlzNavigate is
@@ -553,6 +555,9 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
SSLStatus ssl_status_;
+ // The unique id to identify this to navigation with.
+ int64_t navigation_id_;
+
// The id of the URLRequest tied to this navigation.
GlobalRequestID request_id_;
@@ -605,6 +610,10 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
// in it.
int expected_render_process_host_id_;
+ // Used in tests. Called when the navigation is deferred by one of the
+ // NavigationThrottles.
+ base::Closure on_defer_callback_for_testing_;
+
base::WeakPtrFactory<NavigationHandleImpl> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(NavigationHandleImpl);
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 7fc4394de0d..ab2c3778ee3 100644
--- a/chromium/content/browser/frame_host/navigation_handle_impl_browsertest.cc
+++ b/chromium/content/browser/frame_host/navigation_handle_impl_browsertest.cc
@@ -1465,8 +1465,9 @@ IN_PROC_BROWSER_TEST_F(PlzNavigateNavigationHandleImplBrowserTest,
GURL error_url(
net::URLRequestFailedJob::GetMockHttpUrl(net::ERR_CONNECTION_RESET));
EXPECT_NE(start_url.host(), error_url.host());
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::Bind(&net::URLRequestFailedJob::AddUrlHandler));
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&net::URLRequestFailedJob::AddUrlHandler));
{
NavigationHandleObserver observer(shell()->web_contents(), start_url);
diff --git a/chromium/content/browser/frame_host/navigation_request.cc b/chromium/content/browser/frame_host/navigation_request.cc
index 3a3d68bdc62..acefb242b65 100644
--- a/chromium/content/browser/frame_host/navigation_request.cc
+++ b/chromium/content/browser/frame_host/navigation_request.cc
@@ -7,6 +7,7 @@
#include <utility>
#include "base/memory/ptr_util.h"
+#include "base/optional.h"
#include "base/strings/string_util.h"
#include "content/browser/appcache/appcache_navigation_handle.h"
#include "content/browser/appcache/chrome_appcache_service.h"
@@ -46,6 +47,7 @@
#include "content/public/common/resource_request_body.h"
#include "content/public/common/resource_response.h"
#include "content/public/common/url_constants.h"
+#include "content/public/common/url_utils.h"
#include "content/public/common/web_preferences.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
@@ -157,13 +159,8 @@ void AddAdditionalRequestHeaders(net::HttpRequestHeaders* headers,
: user_agent_override);
// Check whether DevTools wants to override user agent for this request
- // after setting the default user agent.
- std::string devtools_user_agent =
- RenderFrameDevToolsAgentHost::UserAgentOverride(frame_tree_node);
- if (!devtools_user_agent.empty()) {
- headers->SetHeader(net::HttpRequestHeaders::kUserAgent,
- devtools_user_agent);
- }
+ // after setting the default user agent, or append throttling control header.
+ RenderFrameDevToolsAgentHost::AppendDevToolsHeaders(frame_tree_node, headers);
// Tack an 'Upgrade-Insecure-Requests' header to outgoing navigational
// requests, as described in
@@ -190,6 +187,12 @@ void AddAdditionalRequestHeaders(net::HttpRequestHeaders* headers,
headers->SetHeader(net::HttpRequestHeaders::kOrigin, origin.Serialize());
}
+// Should match the definition of
+// blink::SchemeRegistry::ShouldTreatURLSchemeAsLegacy.
+bool ShouldTreatURLSchemeAsLegacy(const GURL& url) {
+ return url.SchemeIs(url::kFtpScheme) || url.SchemeIs(url::kGopherScheme);
+}
+
} // namespace
// static
@@ -422,7 +425,7 @@ void NavigationRequest::BeginNavigation() {
// Create a navigation handle so that the correct error code can be set on
// it by OnRequestFailed().
CreateNavigationHandle();
- OnRequestFailed(false, net::ERR_BLOCKED_BY_CLIENT);
+ OnRequestFailed(false, net::ERR_BLOCKED_BY_CLIENT, base::nullopt, false);
// DO NOT ADD CODE after this. The previous call to OnRequestFailed has
// destroyed the NavigationRequest.
@@ -430,11 +433,13 @@ void NavigationRequest::BeginNavigation() {
}
if (CheckCredentialedSubresource() ==
- CredentialedSubresourceCheckResult::BLOCK_REQUEST) {
+ CredentialedSubresourceCheckResult::BLOCK_REQUEST ||
+ CheckLegacyProtocolInSubresource() ==
+ LegacyProtocolInSubresourceCheckResult::BLOCK_REQUEST) {
// Create a navigation handle so that the correct error code can be set on
// it by OnRequestFailed().
CreateNavigationHandle();
- OnRequestFailed(false, net::ERR_ABORTED);
+ OnRequestFailed(false, net::ERR_ABORTED, base::nullopt, false);
// DO NOT ADD CODE after this. The previous call to OnRequestFailed has
// destroyed the NavigationRequest.
@@ -443,7 +448,7 @@ void NavigationRequest::BeginNavigation() {
CreateNavigationHandle();
- if (ShouldMakeNetworkRequestForURL(common_params_.url) &&
+ if (IsURLHandledByNetworkStack(common_params_.url) &&
!navigation_handle_->IsSameDocument()) {
// It's safe to use base::Unretained because this NavigationRequest owns
// the NavigationHandle where the callback will be stored.
@@ -593,7 +598,7 @@ void NavigationRequest::OnRequestRedirected(
// otherwise block.
if (CheckContentSecurityPolicyFrameSrc(true /* is redirect */) ==
CONTENT_SECURITY_POLICY_CHECK_FAILED) {
- OnRequestFailed(false, net::ERR_BLOCKED_BY_CLIENT);
+ OnRequestFailed(false, net::ERR_BLOCKED_BY_CLIENT, base::nullopt, false);
// DO NOT ADD CODE after this. The previous call to OnRequestFailed has
// destroyed the NavigationRequest.
@@ -601,11 +606,10 @@ void NavigationRequest::OnRequestRedirected(
}
if (CheckCredentialedSubresource() ==
- CredentialedSubresourceCheckResult::BLOCK_REQUEST) {
- // Create a navigation handle so that the correct error code can be set on
- // it by OnRequestFailed().
- CreateNavigationHandle();
- OnRequestFailed(false, net::ERR_ABORTED);
+ CredentialedSubresourceCheckResult::BLOCK_REQUEST ||
+ CheckLegacyProtocolInSubresource() ==
+ LegacyProtocolInSubresourceCheckResult::BLOCK_REQUEST) {
+ OnRequestFailed(false, net::ERR_ABORTED, base::nullopt, false);
// DO NOT ADD CODE after this. The previous call to OnRequestFailed has
// destroyed the NavigationRequest.
@@ -737,9 +741,15 @@ void NavigationRequest::OnResponseStarted(
base::Unretained(this)));
}
-void NavigationRequest::OnRequestFailed(bool has_stale_copy_in_cache,
- int net_error) {
+// TODO(crbug.com/751941): Pass certificate_error_info to navigation throttles.
+void NavigationRequest::OnRequestFailed(
+ bool has_stale_copy_in_cache,
+ int net_error,
+ const base::Optional<net::SSLInfo>& ssl_info,
+ bool should_ssl_errors_be_fatal) {
DCHECK(state_ == STARTED || state_ == RESPONSE_STARTED);
+ // TODO(https://crbug.com/757633): Check that ssl_info.has_value() if
+ // net_error is a certificate error.
TRACE_EVENT_ASYNC_STEP_INTO1("navigation", "NavigationRequest", this,
"OnRequestFailed", "error", net_error);
state_ = FAILED;
@@ -835,10 +845,10 @@ 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::Bind(&NavigationRequest::OnRequestFailed,
- weak_factory_.GetWeakPtr(), false, error_code));
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&NavigationRequest::OnRequestFailed,
+ weak_factory_.GetWeakPtr(), false,
+ error_code, base::nullopt, false));
// DO NOT ADD CODE after this. The previous call to OnRequestFailed has
// destroyed the NavigationRequest.
@@ -892,7 +902,7 @@ void NavigationRequest::OnStartChecksComplete(
// 'Document::firstPartyForCookies()' in Blink, which walks the ancestor tree
// and verifies that all origins are PSL-matches (and special-cases extension
// URLs).
- const GURL& first_party_for_cookies =
+ const GURL& site_for_cookies =
frame_tree_node_->IsMainFrame()
? common_params_.url
: frame_tree_node_->frame_tree()->root()->current_url();
@@ -914,7 +924,7 @@ void NavigationRequest::OnStartChecksComplete(
loader_ = NavigationURLLoader::Create(
browser_context->GetResourceContext(), partition,
base::MakeUnique<NavigationRequestInfo>(
- common_params_, begin_params_, first_party_for_cookies,
+ common_params_, begin_params_, site_for_cookies,
frame_tree_node_->IsMainFrame(), parent_is_main_frame,
IsSecureFrame(frame_tree_node_->parent()),
frame_tree_node_->frame_tree_node_id(), is_for_guests_only,
@@ -933,7 +943,7 @@ void NavigationRequest::OnRedirectChecksComplete(
if (result == NavigationThrottle::CANCEL_AND_IGNORE ||
result == NavigationThrottle::CANCEL) {
// TODO(clamy): distinguish between CANCEL and CANCEL_AND_IGNORE if needed.
- OnRequestFailed(false, net::ERR_ABORTED);
+ OnRequestFailed(false, net::ERR_ABORTED, base::nullopt, false);
// DO NOT ADD CODE after this. The previous call to OnRequestFailed has
// destroyed the NavigationRequest.
@@ -942,7 +952,7 @@ void NavigationRequest::OnRedirectChecksComplete(
if (result == NavigationThrottle::BLOCK_REQUEST ||
result == NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE) {
- OnRequestFailed(false, net::ERR_BLOCKED_BY_CLIENT);
+ OnRequestFailed(false, net::ERR_BLOCKED_BY_CLIENT, base::nullopt, false);
// DO NOT ADD CODE after this. The previous call to OnRequestFailed has
// destroyed the NavigationRequest.
return;
@@ -966,7 +976,7 @@ void NavigationRequest::OnWillProcessResponseChecksComplete(
if (result == NavigationThrottle::CANCEL_AND_IGNORE ||
result == NavigationThrottle::CANCEL || !response_should_be_rendered_) {
// TODO(clamy): distinguish between CANCEL and CANCEL_AND_IGNORE.
- OnRequestFailed(false, net::ERR_ABORTED);
+ OnRequestFailed(false, net::ERR_ABORTED, base::nullopt, false);
// DO NOT ADD CODE after this. The previous call to OnRequestFailed has
// destroyed the NavigationRequest.
@@ -974,7 +984,7 @@ void NavigationRequest::OnWillProcessResponseChecksComplete(
}
if (result == NavigationThrottle::BLOCK_RESPONSE) {
- OnRequestFailed(false, net::ERR_BLOCKED_BY_RESPONSE);
+ OnRequestFailed(false, net::ERR_BLOCKED_BY_RESPONSE, base::nullopt, false);
// DO NOT ADD CODE after this. The previous call to OnRequestFailed has
// destroyed the NavigationRequest.
return;
@@ -987,7 +997,7 @@ void NavigationRequest::OnWillProcessResponseChecksComplete(
}
void NavigationRequest::CommitNavigation() {
- DCHECK(response_ || !ShouldMakeNetworkRequestForURL(common_params_.url) ||
+ DCHECK(response_ || !IsURLHandledByNetworkStack(common_params_.url) ||
navigation_handle_->IsSameDocument());
DCHECK(!common_params_.url.SchemeIs(url::kJavaScriptScheme));
@@ -1102,8 +1112,8 @@ NavigationRequest::CheckCredentialedSubresource() const {
"Subresource requests whose URLs contain embedded credentials (e.g. "
"`https://user:pass@host/`) are blocked. See "
"https://www.chromestatus.com/feature/5669008342777856 for more "
- "details. ";
- parent->AddMessageToConsole(CONSOLE_MESSAGE_LEVEL_INFO, console_message);
+ "details.";
+ parent->AddMessageToConsole(CONSOLE_MESSAGE_LEVEL_WARNING, console_message);
if (!base::FeatureList::IsEnabled(features::kBlockCredentialedSubresources))
return CredentialedSubresourceCheckResult::ALLOW_REQUEST;
@@ -1111,4 +1121,32 @@ NavigationRequest::CheckCredentialedSubresource() const {
return CredentialedSubresourceCheckResult::BLOCK_REQUEST;
}
+NavigationRequest::LegacyProtocolInSubresourceCheckResult
+NavigationRequest::CheckLegacyProtocolInSubresource() const {
+ // It only applies to subframes.
+ if (frame_tree_node_->IsMainFrame())
+ return LegacyProtocolInSubresourceCheckResult::ALLOW_REQUEST;
+
+ if (!ShouldTreatURLSchemeAsLegacy(common_params_.url))
+ return LegacyProtocolInSubresourceCheckResult::ALLOW_REQUEST;
+
+ FrameTreeNode* parent_ftn = frame_tree_node_->parent();
+ DCHECK(parent_ftn);
+ const GURL& parent_url = parent_ftn->current_url();
+ if (ShouldTreatURLSchemeAsLegacy(parent_url))
+ return LegacyProtocolInSubresourceCheckResult::ALLOW_REQUEST;
+
+ // Warn the user about the request being blocked.
+ RenderFrameHostImpl* parent = parent_ftn->current_frame_host();
+ DCHECK(parent);
+ const char* console_message =
+ "Subresource requests using legacy protocols (like `ftp:`) are blocked. "
+ "Please deliver web-accessible resources over modern protocols like "
+ "HTTPS. See https://www.chromestatus.com/feature/5709390967472128 for "
+ "details.";
+ parent->AddMessageToConsole(CONSOLE_MESSAGE_LEVEL_WARNING, console_message);
+
+ return LegacyProtocolInSubresourceCheckResult::BLOCK_REQUEST;
+}
+
} // namespace content
diff --git a/chromium/content/browser/frame_host/navigation_request.h b/chromium/content/browser/frame_host/navigation_request.h
index ad6d4fb20a8..c78665b2ca3 100644
--- a/chromium/content/browser/frame_host/navigation_request.h
+++ b/chromium/content/browser/frame_host/navigation_request.h
@@ -209,7 +209,10 @@ class CONTENT_EXPORT NavigationRequest : public NavigationURLLoaderDelegate {
bool is_stream,
mojom::URLLoaderFactoryPtrInfo
subresource_url_loader_factory_info) override;
- void OnRequestFailed(bool has_stale_copy_in_cache, int net_error) override;
+ void OnRequestFailed(bool has_stale_copy_in_cache,
+ int net_error,
+ const base::Optional<net::SSLInfo>& ssl_info,
+ bool should_ssl_errors_be_fatal) override;
void OnRequestStarted(base::TimeTicks timestamp) override;
// Called when the NavigationThrottles have been checked by the
@@ -244,6 +247,18 @@ class CONTENT_EXPORT NavigationRequest : public NavigationURLLoaderDelegate {
// request should be allowed to continue or should be blocked.
CredentialedSubresourceCheckResult CheckCredentialedSubresource() const;
+ // This enum describes the result of the legacy protocol check for
+ // the request.
+ enum class LegacyProtocolInSubresourceCheckResult {
+ ALLOW_REQUEST,
+ BLOCK_REQUEST,
+ };
+
+ // Block subresources requests that target "legacy" protocol (like "ftp") when
+ // the main document is not served from a "legacy" protocol.
+ LegacyProtocolInSubresourceCheckResult CheckLegacyProtocolInSubresource()
+ const;
+
FrameTreeNode* frame_tree_node_;
// Initialized on creation of the NavigationRequest. Sent to the renderer when
diff --git a/chromium/content/browser/frame_host/navigation_request_info.cc b/chromium/content/browser/frame_host/navigation_request_info.cc
index 65d0007a71e..3501c374cb8 100644
--- a/chromium/content/browser/frame_host/navigation_request_info.cc
+++ b/chromium/content/browser/frame_host/navigation_request_info.cc
@@ -10,7 +10,7 @@ namespace content {
NavigationRequestInfo::NavigationRequestInfo(
const CommonNavigationParams& common_params,
const BeginNavigationParams& begin_params,
- const GURL& first_party_for_cookies,
+ const GURL& site_for_cookies,
bool is_main_frame,
bool parent_is_main_frame,
bool are_ancestors_secure,
@@ -20,7 +20,7 @@ NavigationRequestInfo::NavigationRequestInfo(
blink::WebPageVisibilityState page_visibility_state)
: common_params(common_params),
begin_params(begin_params),
- first_party_for_cookies(first_party_for_cookies),
+ site_for_cookies(site_for_cookies),
is_main_frame(is_main_frame),
parent_is_main_frame(parent_is_main_frame),
are_ancestors_secure(are_ancestors_secure),
diff --git a/chromium/content/browser/frame_host/navigation_request_info.h b/chromium/content/browser/frame_host/navigation_request_info.h
index cdfc8dc0083..48c0ff43b5e 100644
--- a/chromium/content/browser/frame_host/navigation_request_info.h
+++ b/chromium/content/browser/frame_host/navigation_request_info.h
@@ -23,7 +23,7 @@ namespace content {
struct CONTENT_EXPORT NavigationRequestInfo {
NavigationRequestInfo(const CommonNavigationParams& common_params,
const BeginNavigationParams& begin_params,
- const GURL& first_party_for_cookies,
+ const GURL& site_for_cookies,
bool is_main_frame,
bool parent_is_main_frame,
bool are_ancestors_secure,
@@ -38,7 +38,7 @@ struct CONTENT_EXPORT NavigationRequestInfo {
// Usually the URL of the document in the top-level window, which may be
// checked by the third-party cookie blocking policy.
- const GURL first_party_for_cookies;
+ const GURL site_for_cookies;
const bool is_main_frame;
const bool parent_is_main_frame;
diff --git a/chromium/content/browser/frame_host/navigator.h b/chromium/content/browser/frame_host/navigator.h
index 76148e6e58f..b0c45197ab3 100644
--- a/chromium/content/browser/frame_host/navigator.h
+++ b/chromium/content/browser/frame_host/navigator.h
@@ -62,12 +62,10 @@ class CONTENT_EXPORT Navigator : public base::RefCounted<Navigator> {
const FrameHostMsg_DidFailProvisionalLoadWithError_Params& params) {};
// The RenderFrameHostImpl has failed to load the document.
- virtual void DidFailLoadWithError(
- RenderFrameHostImpl* render_frame_host,
- const GURL& url,
- int error_code,
- const base::string16& error_description,
- bool was_ignored_by_handler) {}
+ virtual void DidFailLoadWithError(RenderFrameHostImpl* render_frame_host,
+ const GURL& url,
+ int error_code,
+ const base::string16& error_description) {}
// The RenderFrameHostImpl has committed a navigation. The Navigator is
// responsible for resetting |navigation_handle| at the end of this method and
diff --git a/chromium/content/browser/frame_host/navigator_delegate.h b/chromium/content/browser/frame_host/navigator_delegate.h
index f632319fe8a..4175febda4b 100644
--- a/chromium/content/browser/frame_host/navigator_delegate.h
+++ b/chromium/content/browser/frame_host/navigator_delegate.h
@@ -49,12 +49,10 @@ class CONTENT_EXPORT NavigatorDelegate {
// events should go away in favor of the ones above.
// Document load in |render_frame_host| failed.
- virtual void DidFailLoadWithError(
- RenderFrameHostImpl* render_frame_host,
- const GURL& url,
- int error_code,
- const base::string16& error_description,
- bool was_ignored_by_handler) {}
+ virtual void DidFailLoadWithError(RenderFrameHostImpl* render_frame_host,
+ const GURL& url,
+ int error_code,
+ const base::string16& error_description) {}
// Handles post-navigation tasks in navigation BEFORE the entry has been
// committed to the NavigationController.
diff --git a/chromium/content/browser/frame_host/navigator_impl.cc b/chromium/content/browser/frame_host/navigator_impl.cc
index 044de07e777..de8778fcafc 100644
--- a/chromium/content/browser/frame_host/navigator_impl.cc
+++ b/chromium/content/browser/frame_host/navigator_impl.cc
@@ -290,12 +290,10 @@ void NavigatorImpl::DidFailLoadWithError(
RenderFrameHostImpl* render_frame_host,
const GURL& url,
int error_code,
- const base::string16& error_description,
- bool was_ignored_by_handler) {
+ const base::string16& error_description) {
if (delegate_) {
- delegate_->DidFailLoadWithError(
- render_frame_host, url, error_code,
- error_description, was_ignored_by_handler);
+ delegate_->DidFailLoadWithError(render_frame_host, url, error_code,
+ error_description);
}
}
@@ -828,10 +826,6 @@ void NavigatorImpl::RequestTransferURL(
post_body = nullptr;
}
- // This call only makes sense for subframes if OOPIFs are possible.
- DCHECK(!render_frame_host->GetParent() ||
- SiteIsolationPolicy::AreCrossProcessFramesPossible());
-
// Allow the delegate to cancel the transfer.
if (!delegate_->ShouldTransferNavigation(
render_frame_host->frame_tree_node()->IsMainFrame()))
@@ -1151,10 +1145,6 @@ void NavigatorImpl::RequestNavigation(
// We don't want to dispatch a beforeunload handler if
// is_history_navigation_in_new_child is true. This indicates a newly created
// child frame which does not have a beforunload handler.
- bool should_dispatch_beforeunload =
- !is_same_document_history_load &&
- !is_history_navigation_in_new_child &&
- frame_tree_node->current_frame_host()->ShouldDispatchBeforeUnload();
FrameMsg_Navigate_Type::Value navigation_type = GetNavigationType(
frame_tree_node->current_url(), // old_url
dest_url, // new_url
@@ -1162,6 +1152,11 @@ void NavigatorImpl::RequestNavigation(
entry, // entry
frame_entry, // frame_entry
is_same_document_history_load); // is_same_document_history_load
+ bool is_same_document =
+ FrameMsg_Navigate_Type::IsSameDocument(navigation_type);
+ bool should_dispatch_beforeunload =
+ !is_same_document && !is_history_navigation_in_new_child &&
+ frame_tree_node->current_frame_host()->ShouldDispatchBeforeUnload();
std::unique_ptr<NavigationRequest> scoped_request =
NavigationRequest::CreateBrowserInitiated(
frame_tree_node, dest_url, dest_referrer, frame_entry, entry,
diff --git a/chromium/content/browser/frame_host/navigator_impl.h b/chromium/content/browser/frame_host/navigator_impl.h
index 4ada17f9e2b..d252e364290 100644
--- a/chromium/content/browser/frame_host/navigator_impl.h
+++ b/chromium/content/browser/frame_host/navigator_impl.h
@@ -52,8 +52,7 @@ class CONTENT_EXPORT NavigatorImpl : public Navigator {
void DidFailLoadWithError(RenderFrameHostImpl* render_frame_host,
const GURL& url,
int error_code,
- const base::string16& error_description,
- bool was_ignored_by_handler) override;
+ const base::string16& error_description) override;
void DidNavigate(
RenderFrameHostImpl* render_frame_host,
const FrameHostMsg_DidCommitProvisionalLoad_Params& params,
diff --git a/chromium/content/browser/frame_host/navigator_impl_unittest.cc b/chromium/content/browser/frame_host/navigator_impl_unittest.cc
index 337ae74d41b..c6d003cc12a 100644
--- a/chromium/content/browser/frame_host/navigator_impl_unittest.cc
+++ b/chromium/content/browser/frame_host/navigator_impl_unittest.cc
@@ -27,6 +27,7 @@
#include "content/public/common/url_utils.h"
#include "content/public/test/browser_side_navigation_test_utils.h"
#include "content/public/test/mock_render_process_host.h"
+#include "content/public/test/navigation_simulator.h"
#include "content/public/test/test_utils.h"
#include "content/test/test_navigation_url_loader.h"
#include "content/test/test_render_frame_host.h"
@@ -173,10 +174,17 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
contents()->NavigateAndCommit(kUrl1);
EXPECT_TRUE(main_test_rfh()->IsRenderFrameLive());
+ main_test_rfh()->OnMessageReceived(
+ FrameHostMsg_DidStopLoading(main_test_rfh()->GetRoutingID()));
// Start a renderer-initiated non-user-initiated navigation.
process()->sink().ClearMessages();
- main_test_rfh()->SendRendererInitiatedNavigationRequest(kUrl2, false);
+ auto navigation =
+ NavigationSimulator::CreateRendererInitiated(kUrl2, main_test_rfh());
+ navigation->SetTransition(ui::PageTransitionFromInt(
+ ui::PAGE_TRANSITION_LINK | ui::PAGE_TRANSITION_CLIENT_REDIRECT));
+ navigation->SetHasUserGesture(false);
+ navigation->Start();
FrameTreeNode* node = main_test_rfh()->frame_tree_node();
NavigationRequest* request = node->navigation_request();
ASSERT_TRUE(request);
@@ -188,17 +196,16 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
EXPECT_EQ(kUrl2, request->common_params().url);
EXPECT_FALSE(request->browser_initiated());
EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
+ EXPECT_FALSE(main_test_rfh()->is_loading());
- // Have the current RenderFrameHost commit the navigation.
- scoped_refptr<ResourceResponse> response(new ResourceResponse);
- GetLoaderForNavigationRequest(request)->CallOnResponseStarted(
- response, MakeEmptyStream(), nullptr);
+ // Have the current RenderFrameHost commit the navigation
+ navigation->ReadyToCommit();
EXPECT_TRUE(DidRenderFrameHostRequestCommit(main_test_rfh()));
EXPECT_TRUE(main_test_rfh()->is_loading());
EXPECT_FALSE(node->navigation_request());
// Commit the navigation.
- main_test_rfh()->SendNavigate(0, true, kUrl2);
+ navigation->Commit();
EXPECT_TRUE(main_test_rfh()->is_active());
EXPECT_EQ(SiteInstanceImpl::GetSiteForURL(browser_context(), kUrl2),
main_test_rfh()->GetSiteInstance()->GetSiteURL());
@@ -216,12 +223,16 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
const GURL kUrl2("http://www.google.com");
contents()->NavigateAndCommit(kUrl1);
+ main_test_rfh()->OnMessageReceived(
+ FrameHostMsg_DidStopLoading(main_test_rfh()->GetRoutingID()));
EXPECT_TRUE(main_test_rfh()->IsRenderFrameLive());
int32_t site_instance_id_1 = main_test_rfh()->GetSiteInstance()->GetId();
- // Start a renderer-initiated non-user-initiated navigation.
+ // Start a renderer-initiated navigation.
process()->sink().ClearMessages();
- main_test_rfh()->SendRendererInitiatedNavigationRequest(kUrl2, false);
+ auto navigation =
+ NavigationSimulator::CreateRendererInitiated(kUrl2, main_test_rfh());
+ navigation->Start();
FrameTreeNode* node = main_test_rfh()->frame_tree_node();
NavigationRequest* request = node->navigation_request();
ASSERT_TRUE(request);
@@ -229,9 +240,9 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
// The navigation is immediately started as there's no need to wait for
// beforeUnload to be executed.
EXPECT_EQ(NavigationRequest::STARTED, request->state());
- EXPECT_FALSE(request->begin_params().has_user_gesture);
EXPECT_EQ(kUrl2, request->common_params().url);
EXPECT_FALSE(request->browser_initiated());
+ EXPECT_FALSE(main_test_rfh()->is_loading());
if (AreAllSitesIsolatedForTesting()) {
EXPECT_TRUE(GetSpeculativeRenderFrameHost(node));
} else {
@@ -239,24 +250,21 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
}
// Have the current RenderFrameHost commit the navigation.
- scoped_refptr<ResourceResponse> response(new ResourceResponse);
- GetLoaderForNavigationRequest(request)->CallOnResponseStarted(
- response, MakeEmptyStream(), nullptr);
+ navigation->ReadyToCommit();
if (AreAllSitesIsolatedForTesting()) {
+ EXPECT_EQ(navigation->GetFinalRenderFrameHost(),
+ GetSpeculativeRenderFrameHost(node));
EXPECT_TRUE(
DidRenderFrameHostRequestCommit(GetSpeculativeRenderFrameHost(node)));
} else {
EXPECT_TRUE(DidRenderFrameHostRequestCommit(main_test_rfh()));
+ EXPECT_EQ(navigation->GetFinalRenderFrameHost(), main_test_rfh());
}
- EXPECT_TRUE(main_test_rfh()->is_loading());
EXPECT_FALSE(node->navigation_request());
// Commit the navigation.
- if (AreAllSitesIsolatedForTesting()) {
- GetSpeculativeRenderFrameHost(node)->SendNavigate(0, true, kUrl2);
- } else {
- main_test_rfh()->SendNavigate(0, true, kUrl2);
- }
+ navigation->Commit();
+ EXPECT_TRUE(main_test_rfh()->is_loading());
EXPECT_TRUE(main_test_rfh()->is_active());
EXPECT_EQ(kUrl2, contents()->GetLastCommittedURL());
EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
@@ -330,7 +338,7 @@ TEST_F(NavigatorTestWithBrowserSideNavigation, BeginNavigation) {
EXPECT_EQ(kUrl2, subframe_request->common_params().url);
EXPECT_EQ(kUrl2, subframe_loader->request_info()->common_params.url);
// First party for cookies url should be that of the main frame.
- EXPECT_EQ(kUrl1, subframe_loader->request_info()->first_party_for_cookies);
+ EXPECT_EQ(kUrl1, subframe_loader->request_info()->site_for_cookies);
EXPECT_FALSE(subframe_loader->request_info()->is_main_frame);
EXPECT_TRUE(subframe_loader->request_info()->parent_is_main_frame);
EXPECT_TRUE(subframe_request->browser_initiated());
@@ -362,7 +370,7 @@ TEST_F(NavigatorTestWithBrowserSideNavigation, BeginNavigation) {
GetLoaderForNavigationRequest(main_request);
EXPECT_EQ(kUrl3, main_request->common_params().url);
EXPECT_EQ(kUrl3, main_loader->request_info()->common_params.url);
- EXPECT_EQ(kUrl3, main_loader->request_info()->first_party_for_cookies);
+ EXPECT_EQ(kUrl3, main_loader->request_info()->site_for_cookies);
EXPECT_TRUE(main_loader->request_info()->is_main_frame);
EXPECT_FALSE(main_loader->request_info()->parent_is_main_frame);
EXPECT_TRUE(main_request->browser_initiated());
@@ -627,7 +635,11 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
// Now receive a renderer-initiated user-initiated request. It should replace
// the current NavigationRequest.
- main_test_rfh()->SendRendererInitiatedNavigationRequest(kUrl2, true);
+ auto navigation =
+ NavigationSimulator::CreateRendererInitiated(kUrl2, main_test_rfh());
+ navigation->SetTransition(ui::PAGE_TRANSITION_LINK);
+ navigation->SetHasUserGesture(true);
+ navigation->Start();
NavigationRequest* request2 = node->navigation_request();
ASSERT_TRUE(request2);
EXPECT_EQ(kUrl2, request2->common_params().url);
@@ -646,9 +658,7 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
}
// Have the RenderFrameHost commit the navigation.
- scoped_refptr<ResourceResponse> response(new ResourceResponse);
- GetLoaderForNavigationRequest(request2)->CallOnResponseStarted(
- response, MakeEmptyStream(), nullptr);
+ navigation->ReadyToCommit();
if (AreAllSitesIsolatedForTesting()) {
EXPECT_TRUE(
DidRenderFrameHostRequestCommit(GetSpeculativeRenderFrameHost(node)));
@@ -657,13 +667,78 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
}
// Commit the navigation.
- main_test_rfh()->SendNavigate(0, true, kUrl2);
+ navigation->Commit();
// Confirm that the commit corresponds to the new request.
ASSERT_TRUE(main_test_rfh());
EXPECT_EQ(kUrl2, contents()->GetLastCommittedURL());
}
+// PlzNavigate: Test that a renderer-initiated user-initiated navigation is
+// canceled if a renderer-initiated non-user-initiated request is issued in the
+// meantime.
+TEST_F(NavigatorTestWithBrowserSideNavigation,
+ RendererNonUserInitiatedNavigationCancelsRendererUserInitiated) {
+ const GURL kUrl0("http://www.wikipedia.org/");
+ const GURL kUrl1("http://www.chromium.org/");
+ const GURL kUrl2("http://www.google.com/");
+
+ // Initialization.
+ contents()->NavigateAndCommit(kUrl0);
+ FrameTreeNode* node = main_test_rfh()->frame_tree_node();
+
+ // Start a renderer-initiated user-initiated navigation to the 1st URL.
+ process()->sink().ClearMessages();
+ auto user_initiated_navigation =
+ NavigationSimulator::CreateRendererInitiated(kUrl1, main_test_rfh());
+ user_initiated_navigation->SetTransition(ui::PAGE_TRANSITION_LINK);
+ user_initiated_navigation->SetHasUserGesture(true);
+ user_initiated_navigation->Start();
+ NavigationRequest* request1 = node->navigation_request();
+ ASSERT_TRUE(request1);
+ EXPECT_EQ(kUrl1, request1->common_params().url);
+ EXPECT_FALSE(request1->browser_initiated());
+ EXPECT_TRUE(request1->begin_params().has_user_gesture);
+ if (AreAllSitesIsolatedForTesting()) {
+ EXPECT_TRUE(GetSpeculativeRenderFrameHost(node));
+ } else {
+ EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
+ }
+
+ // Now receive a renderer-initiated non-user-initiated request. The previous
+ // navigation should be replaced.
+ auto non_user_initiated_navigation =
+ NavigationSimulator::CreateRendererInitiated(kUrl2, main_test_rfh());
+ non_user_initiated_navigation->SetTransition(ui::PAGE_TRANSITION_LINK);
+ non_user_initiated_navigation->SetHasUserGesture(false);
+ non_user_initiated_navigation->Start();
+
+ NavigationRequest* request2 = node->navigation_request();
+ ASSERT_TRUE(request2);
+ EXPECT_NE(request1, request2);
+ EXPECT_EQ(kUrl2, request2->common_params().url);
+ EXPECT_FALSE(request2->browser_initiated());
+ EXPECT_FALSE(request2->begin_params().has_user_gesture);
+ if (AreAllSitesIsolatedForTesting()) {
+ EXPECT_TRUE(GetSpeculativeRenderFrameHost(node));
+ } else {
+ EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
+ }
+
+ // Have the RenderFrameHost commit the navigation.
+ non_user_initiated_navigation->ReadyToCommit();
+ if (AreAllSitesIsolatedForTesting()) {
+ EXPECT_TRUE(
+ DidRenderFrameHostRequestCommit(GetSpeculativeRenderFrameHost(node)));
+ } else {
+ EXPECT_TRUE(DidRenderFrameHostRequestCommit(main_test_rfh()));
+ }
+
+ // Commit the navigation.
+ non_user_initiated_navigation->Commit();
+ EXPECT_EQ(kUrl2, contents()->GetLastCommittedURL());
+}
+
// PlzNavigate: Test that a browser-initiated navigation is NOT canceled if a
// renderer-initiated non-user-initiated request is issued in the meantime.
TEST_F(NavigatorTestWithBrowserSideNavigation,
@@ -687,7 +762,24 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
// Now receive a renderer-initiated non-user-initiated request. Nothing should
// change.
- main_test_rfh()->SendRendererInitiatedNavigationRequest(kUrl2, false);
+ {
+ CommonNavigationParams common_params;
+ common_params.url = kUrl2;
+ common_params.referrer = Referrer(kUrl0, blink::kWebReferrerPolicyDefault);
+ common_params.transition = ui::PageTransitionFromInt(
+ ui::PAGE_TRANSITION_LINK | ui::PAGE_TRANSITION_CLIENT_REDIRECT);
+ BeginNavigationParams begin_params(
+ std::string(), // headers
+ net::LOAD_NORMAL, // load_flags
+ false, // has_user_gesture
+ false, // skip_service_worker
+ REQUEST_CONTEXT_TYPE_SCRIPT,
+ blink::WebMixedContentContextType::kBlockable,
+ false, // is_form_submission
+ url::Origin(kUrl0));
+ main_test_rfh()->OnMessageReceived(FrameHostMsg_BeginNavigation(
+ main_test_rfh()->GetRoutingID(), common_params, begin_params));
+ }
NavigationRequest* request2 = node->navigation_request();
ASSERT_TRUE(request2);
EXPECT_EQ(request1, request2);
@@ -727,7 +819,12 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
// Start a renderer-initiated non-user-initiated navigation to the 1st URL.
process()->sink().ClearMessages();
- main_test_rfh()->SendRendererInitiatedNavigationRequest(kUrl1, false);
+ auto navigation1 =
+ NavigationSimulator::CreateRendererInitiated(kUrl1, main_test_rfh());
+ navigation1->SetTransition(ui::PageTransitionFromInt(
+ ui::PAGE_TRANSITION_LINK | ui::PAGE_TRANSITION_CLIENT_REDIRECT));
+ navigation1->SetHasUserGesture(false);
+ navigation1->Start();
NavigationRequest* request1 = node->navigation_request();
ASSERT_TRUE(request1);
EXPECT_EQ(kUrl1, request1->common_params().url);
@@ -743,7 +840,12 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
EXPECT_TRUE(loader1);
// Now receive a 2nd similar request that should replace the current one.
- main_test_rfh()->SendRendererInitiatedNavigationRequest(kUrl2, false);
+ auto navigation2 =
+ NavigationSimulator::CreateRendererInitiated(kUrl2, main_test_rfh());
+ navigation2->SetTransition(ui::PageTransitionFromInt(
+ ui::PAGE_TRANSITION_LINK | ui::PAGE_TRANSITION_CLIENT_REDIRECT));
+ navigation2->SetHasUserGesture(false);
+ navigation2->Start();
NavigationRequest* request2 = node->navigation_request();
EXPECT_EQ(kUrl2, request2->common_params().url);
EXPECT_FALSE(request2->browser_initiated());
@@ -758,9 +860,7 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
EXPECT_FALSE(loader1);
// Have the RenderFrameHost commit the navigation.
- scoped_refptr<ResourceResponse> response(new ResourceResponse);
- GetLoaderForNavigationRequest(request2)->CallOnResponseStarted(
- response, MakeEmptyStream(), nullptr);
+ navigation2->ReadyToCommit();
if (AreAllSitesIsolatedForTesting()) {
EXPECT_TRUE(
DidRenderFrameHostRequestCommit(GetSpeculativeRenderFrameHost(node)));
@@ -769,11 +869,15 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
}
// Commit the navigation.
- main_test_rfh()->SendNavigate(0, true, kUrl2);
+ navigation2->Commit();
EXPECT_EQ(kUrl2, contents()->GetLastCommittedURL());
- // The SiteInstance did not change.
- EXPECT_EQ(site_instance_id_0, main_test_rfh()->GetSiteInstance()->GetId());
+ // The SiteInstance did not change unless site-per-process is enabled.
+ if (AreAllSitesIsolatedForTesting()) {
+ EXPECT_NE(site_instance_id_0, main_test_rfh()->GetSiteInstance()->GetId());
+ } else {
+ EXPECT_EQ(site_instance_id_0, main_test_rfh()->GetSiteInstance()->GetId());
+ }
}
// PlzNavigate: Test that a reload navigation is properly signaled to the
@@ -951,9 +1055,10 @@ TEST_F(NavigatorTestWithBrowserSideNavigation, DataUrls) {
// Do a renderer-initiated navigation to a data url. The request should be
// sent to the IO thread.
- TestRenderFrameHost* main_rfh = main_test_rfh();
- main_rfh->SendRendererInitiatedNavigationRequest(kUrl2, true);
- EXPECT_TRUE(main_rfh->is_loading());
+ auto navigation_to_data_url =
+ NavigationSimulator::CreateRendererInitiated(kUrl2, main_test_rfh());
+ navigation_to_data_url->Start();
+ EXPECT_TRUE(main_test_rfh()->is_loading());
EXPECT_TRUE(node->navigation_request());
EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
}
diff --git a/chromium/content/browser/frame_host/render_frame_host_android.cc b/chromium/content/browser/frame_host/render_frame_host_android.cc
index 490543c7195..7a463265a94 100644
--- a/chromium/content/browser/frame_host/render_frame_host_android.cc
+++ b/chromium/content/browser/frame_host/render_frame_host_android.cc
@@ -21,11 +21,6 @@ using base::android::ScopedJavaLocalRef;
namespace content {
-// static
-bool RenderFrameHostAndroid::Register(JNIEnv* env) {
- return RegisterNativesImpl(env);
-}
-
RenderFrameHostAndroid::RenderFrameHostAndroid(
RenderFrameHostImpl* render_frame_host,
service_manager::mojom::InterfaceProviderPtr interface_provider_ptr)
diff --git a/chromium/content/browser/frame_host/render_frame_host_android.h b/chromium/content/browser/frame_host/render_frame_host_android.h
index 57680ab4311..27ffcd49e80 100644
--- a/chromium/content/browser/frame_host/render_frame_host_android.h
+++ b/chromium/content/browser/frame_host/render_frame_host_android.h
@@ -27,8 +27,6 @@ class RenderFrameHostImpl;
// native counterpart.
class RenderFrameHostAndroid : public base::SupportsUserData::Data {
public:
- static bool Register(JNIEnv* env);
-
RenderFrameHostAndroid(
RenderFrameHostImpl* render_frame_host,
service_manager::mojom::InterfaceProviderPtr interface_provider_ptr);
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 cbe7d47e32f..837b206a6fb 100644
--- a/chromium/content/browser/frame_host/render_frame_host_delegate.cc
+++ b/chromium/content/browser/frame_host/render_frame_host_delegate.cc
@@ -62,14 +62,14 @@ std::string RenderFrameHostDelegate::GetDefaultMediaDeviceID(
return std::string();
}
-AccessibilityMode RenderFrameHostDelegate::GetAccessibilityMode() const {
- return AccessibilityMode();
+ui::AXMode RenderFrameHostDelegate::GetAccessibilityMode() const {
+ return ui::AXMode();
}
RenderFrameHost* RenderFrameHostDelegate::GetGuestByInstanceID(
RenderFrameHost* render_frame_host,
int browser_plugin_instance_id) {
- return NULL;
+ return nullptr;
}
device::GeolocationContext* RenderFrameHostDelegate::GetGeolocationContext() {
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 837e3a74d4d..1d14bf0593a 100644
--- a/chromium/content/browser/frame_host/render_frame_host_delegate.h
+++ b/chromium/content/browser/frame_host/render_frame_host_delegate.h
@@ -81,6 +81,12 @@ class CONTENT_EXPORT RenderFrameHostDelegate {
const std::string& interface_name,
mojo::ScopedInterfaceEndpointHandle handle) {}
+ // Allows the delegate to filter incoming interface requests.
+ virtual void OnInterfaceRequest(
+ RenderFrameHost* render_frame_host,
+ const std::string& interface_name,
+ mojo::ScopedMessagePipeHandle* interface_pipe) {}
+
// Gets the last committed URL. See WebContents::GetLastCommittedURL for a
// description of the semantics.
virtual const GURL& GetMainFrameLastCommittedURL() const;
@@ -173,11 +179,11 @@ class CONTENT_EXPORT RenderFrameHostDelegate {
virtual std::string GetDefaultMediaDeviceID(MediaStreamType type);
// Get the accessibility mode for the WebContents that owns this frame.
- virtual AccessibilityMode GetAccessibilityMode() const;
+ virtual ui::AXMode GetAccessibilityMode() const;
// Called when accessibility events or location changes are received
// from a render frame, when the accessibility mode has the
- // AccessibilityMode::kWebContents flag set.
+ // ui::AXMode::kWebContents flag set.
virtual void AccessibilityEventReceived(
const std::vector<AXEventNotificationDetails>& details) {}
virtual void AccessibilityLocationChangesReceived(
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 346765edaef..a9c344c3cbe 100644
--- a/chromium/content/browser/frame_host/render_frame_host_impl.cc
+++ b/chromium/content/browser/frame_host/render_frame_host_impl.cc
@@ -5,6 +5,7 @@
#include "content/browser/frame_host/render_frame_host_impl.h"
#include <algorithm>
+#include <queue>
#include <utility>
#include "base/bind.h"
@@ -18,6 +19,7 @@
#include "base/process/kill.h"
#include "base/time/time.h"
#include "build/build_config.h"
+#include "cc/base/switches.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
#include "content/browser/accessibility/browser_accessibility_state_impl.h"
#include "content/browser/bluetooth/web_bluetooth_service_impl.h"
@@ -30,6 +32,7 @@
#include "content/browser/frame_host/debug_urls.h"
#include "content/browser/frame_host/frame_tree.h"
#include "content/browser/frame_host/frame_tree_node.h"
+#include "content/browser/frame_host/input/input_injector_impl.h"
#include "content/browser/frame_host/input/legacy_ipc_frame_input_handler.h"
#include "content/browser/frame_host/navigation_entry_impl.h"
#include "content/browser/frame_host/navigation_handle_impl.h"
@@ -38,7 +41,8 @@
#include "content/browser/frame_host/navigator_impl.h"
#include "content/browser/frame_host/render_frame_host_delegate.h"
#include "content/browser/frame_host/render_frame_proxy_host.h"
-#include "content/browser/frame_host/render_widget_host_view_child_frame.h"
+#include "content/browser/generic_sensor/sensor_provider_proxy_impl.h"
+#include "content/browser/geolocation/geolocation_service_impl.h"
#include "content/browser/image_capture/image_capture_impl.h"
#include "content/browser/installedapp/installed_app_provider_impl_default.h"
#include "content/browser/keyboard_lock/keyboard_lock_service_impl.h"
@@ -60,6 +64,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_base.h"
+#include "content/browser/renderer_host/render_widget_host_view_child_frame.h"
#include "content/browser/shared_worker/shared_worker_service_impl.h"
#include "content/browser/storage_partition_impl.h"
#include "content/browser/webauth/authenticator_impl.h"
@@ -82,6 +87,7 @@
#include "content/common/renderer.mojom.h"
#include "content/common/site_isolation_policy.h"
#include "content/common/swapped_out_messages.h"
+#include "content/common/widget.mojom.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"
@@ -106,19 +112,21 @@
#include "content/public/common/service_names.mojom.h"
#include "content/public/common/url_constants.h"
#include "content/public/common/url_utils.h"
-#include "device/geolocation/geolocation_context.h"
#include "device/vr/features/features.h"
#include "media/base/media_switches.h"
#include "media/media_features.h"
#include "media/mojo/interfaces/media_service.mojom.h"
#include "media/mojo/interfaces/remoting.mojom.h"
#include "media/mojo/services/media_interface_provider.h"
+#include "media/mojo/services/video_decode_stats_recorder.h"
+#include "media/mojo/services/watch_time_recorder.h"
#include "mojo/public/cpp/bindings/associated_interface_ptr.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "mojo/public/cpp/system/data_pipe.h"
#include "services/device/public/cpp/device_features.h"
#include "services/device/public/interfaces/constants.mojom.h"
#include "services/device/public/interfaces/sensor_provider.mojom.h"
+#include "services/device/public/interfaces/vibration_manager.mojom.h"
#include "services/device/public/interfaces/wake_lock.mojom.h"
#include "services/device/public/interfaces/wake_lock_context.mojom.h"
#include "services/resource_coordinator/public/cpp/resource_coordinator_features.h"
@@ -287,7 +295,7 @@ class RemoterFactoryImpl final : public media::mojom::RemoterFactory {
void CreateResourceCoordinatorFrameInterface(
RenderFrameHostImpl* render_frame_host,
resource_coordinator::mojom::CoordinationUnitRequest request) {
- render_frame_host->GetFrameResourceCoordinator()->service()->AddBinding(
+ render_frame_host->GetFrameResourceCoordinator()->AddBinding(
std::move(request));
}
@@ -335,9 +343,10 @@ void NotifyForEachFrameFromUI(
if (pending_frame_host)
routing_ids->insert(pending_frame_host->GetGlobalFrameRoutingId());
}
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::Bind(&NotifyRouteChangesOnIO, frame_callback,
- base::Passed(std::move(routing_ids))));
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&NotifyRouteChangesOnIO, frame_callback,
+ base::Passed(std::move(routing_ids))));
}
void LookupRenderFrameHostOrProxy(int process_id,
@@ -519,20 +528,33 @@ RenderFrameHostImpl::RenderFrameHostImpl(SiteInstance* site_instance,
weak_ptr_factory_.GetWeakPtr())));
if (widget_routing_id != MSG_ROUTING_NONE) {
+ mojom::WidgetPtr widget;
+ GetRemoteInterfaces()->GetInterface(&widget);
+
// TODO(avi): Once RenderViewHostImpl has-a RenderWidgetHostImpl, the main
// render frame should probably start owning the RenderWidgetHostImpl,
// so this logic checking for an already existing RWHI should be removed.
// https://crbug.com/545684
render_widget_host_ =
RenderWidgetHostImpl::FromID(GetProcess()->GetID(), widget_routing_id);
+
+ mojom::WidgetInputHandlerAssociatedPtr widget_handler;
+ if (frame_input_handler_) {
+ frame_input_handler_->GetWidgetInputHandler(
+ mojo::MakeRequest(&widget_handler));
+ }
if (!render_widget_host_) {
DCHECK(frame_tree_node->parent());
+
render_widget_host_ = new RenderWidgetHostImpl(rwh_delegate, GetProcess(),
- widget_routing_id, hidden);
+ 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());
+ render_widget_host_->SetWidget(std::move(widget));
}
+ render_widget_host_->SetWidgetInputHandler(std::move(widget_handler));
render_widget_host_->input_router()->SetFrameTreeNodeId(
frame_tree_node_->frame_tree_node_id());
}
@@ -558,8 +580,8 @@ RenderFrameHostImpl::~RenderFrameHostImpl() {
g_token_frame_map.Get().erase(*overlay_routing_token_);
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::Bind(&NotifyRenderFrameDetachedOnIO,
- GetProcess()->GetID(), routing_id_));
+ base::BindOnce(&NotifyRenderFrameDetachedOnIO,
+ GetProcess()->GetID(), routing_id_));
site_instance_->RemoveObserver(this);
@@ -743,10 +765,6 @@ RenderViewHost* RenderFrameHostImpl::GetRenderViewHost() {
return render_view_host_;
}
-service_manager::BinderRegistry* RenderFrameHostImpl::GetInterfaceRegistry() {
- return interface_registry_.get();
-}
-
service_manager::InterfaceProvider* RenderFrameHostImpl::GetRemoteInterfaces() {
return remote_interfaces_.get();
}
@@ -885,6 +903,7 @@ bool RenderFrameHostImpl::OnMessageReceived(const IPC::Message &msg) {
OnDidChangeFrameOwnerProperties)
IPC_MESSAGE_HANDLER(FrameHostMsg_UpdateTitle, OnUpdateTitle)
IPC_MESSAGE_HANDLER(FrameHostMsg_UpdateEncoding, OnUpdateEncoding)
+ IPC_MESSAGE_HANDLER(FrameHostMsg_DidBlockFramebust, OnDidBlockFramebust)
IPC_MESSAGE_HANDLER(FrameHostMsg_BeginNavigation,
OnBeginNavigation)
IPC_MESSAGE_HANDLER(FrameHostMsg_AbortNavigation, OnAbortNavigation)
@@ -1238,6 +1257,9 @@ void RenderFrameHostImpl::OnAudibleStateChanged(bool is_audible) {
else
GetProcess()->OnMediaStreamRemoved();
is_audible_ = is_audible;
+
+ GetFrameResourceCoordinator()->SetProperty(
+ resource_coordinator::mojom::PropertyType::kAudible, is_audible_);
}
void RenderFrameHostImpl::OnDidAddMessageToConsole(
@@ -1300,6 +1322,10 @@ void RenderFrameHostImpl::SetLastCommittedOrigin(const url::Origin& origin) {
CSPContext::SetSelf(origin);
}
+void RenderFrameHostImpl::SetLastCommittedUrl(const GURL& url) {
+ last_committed_url_ = url;
+}
+
void RenderFrameHostImpl::OnDetach() {
frame_tree_->RemoveFrame(frame_tree_node_);
}
@@ -1418,8 +1444,7 @@ void RenderFrameHostImpl::OnDidFailProvisionalLoadWithError(
void RenderFrameHostImpl::OnDidFailLoadWithError(
const GURL& url,
int error_code,
- const base::string16& error_description,
- bool was_ignored_by_handler) {
+ const base::string16& error_description) {
TRACE_EVENT2("navigation",
"RenderFrameHostImpl::OnDidFailProvisionalLoadWithError",
"frame_tree_node", frame_tree_node_->frame_tree_node_id(),
@@ -1429,8 +1454,7 @@ void RenderFrameHostImpl::OnDidFailLoadWithError(
GetProcess()->FilterURL(false, &validated_url);
frame_tree_node_->navigator()->DidFailLoadWithError(
- this, validated_url, error_code, error_description,
- was_ignored_by_handler);
+ this, validated_url, error_code, error_description);
}
// Called when the renderer navigates. For every frame loaded, we'll get this
@@ -1734,23 +1758,6 @@ void RenderFrameHostImpl::OnBeforeUnloadACK(
converter.ToLocalTimeTicks(
RemoteTimeTicks::FromTimeTicks(renderer_before_unload_end_time));
before_unload_end_time = browser_before_unload_end_time.ToTimeTicks();
-
- // Collect UMA on the inter-process skew.
- bool is_skew_additive = false;
- if (converter.IsSkewAdditiveForMetrics()) {
- is_skew_additive = true;
- base::TimeDelta skew = converter.GetSkewForMetrics();
- if (skew >= base::TimeDelta()) {
- UMA_HISTOGRAM_TIMES(
- "InterProcessTimeTicks.BrowserBehind_RendererToBrowser", skew);
- } else {
- UMA_HISTOGRAM_TIMES(
- "InterProcessTimeTicks.BrowserAhead_RendererToBrowser", -skew);
- }
- }
- UMA_HISTOGRAM_BOOLEAN(
- "InterProcessTimeTicks.IsSkewAdditive_RendererToBrowser",
- is_skew_additive);
}
base::TimeDelta on_before_unload_overhead_time =
@@ -1830,6 +1837,10 @@ void RenderFrameHostImpl::OnRenderProcessGone(int status, int exit_code) {
// process's channel.
remote_associated_interfaces_.reset();
+ // Any termination disablers in content loaded by the new process will
+ // be sent again.
+ sudden_termination_disabler_types_enabled_ = 0;
+
if (!is_active()) {
// If the process has died, we don't need to wait for the swap out ack from
// this RenderFrame if it is pending deletion. Complete the swap out to
@@ -1956,6 +1967,11 @@ void RenderFrameHostImpl::OnRunJavaScriptDialog(
const GURL& frame_url,
JavaScriptDialogType dialog_type,
IPC::Message* reply_msg) {
+ if (dialog_type == JavaScriptDialogType::JAVASCRIPT_DIALOG_TYPE_ALERT) {
+ GetFrameResourceCoordinator()->SendEvent(
+ resource_coordinator::mojom::Event::kAlertFired);
+ }
+
if (IsWaitingForUnloadACK()) {
SendJavaScriptDialogReply(reply_msg, true, base::string16());
return;
@@ -2259,6 +2275,10 @@ void RenderFrameHostImpl::OnUpdateEncoding(const std::string& encoding_name) {
delegate_->UpdateEncoding(this, encoding_name);
}
+void RenderFrameHostImpl::OnDidBlockFramebust(const GURL& url) {
+ // TODO(dgn): Hook this up to UI.
+}
+
void RenderFrameHostImpl::OnBeginNavigation(
const CommonNavigationParams& common_params,
const BeginNavigationParams& begin_params) {
@@ -2289,6 +2309,10 @@ void RenderFrameHostImpl::OnBeginNavigation(
return;
}
+ // Renderer processes shouldn't request error page URLs directly.
+ if (validated_params.url.SchemeIs(kChromeErrorScheme))
+ return;
+
if (waiting_for_init_) {
pendinging_navigate_ = base::MakeUnique<PendingNavigation>(
validated_params, validated_begin_params);
@@ -2314,7 +2338,6 @@ void RenderFrameHostImpl::OnAbortNavigation() {
void RenderFrameHostImpl::OnDispatchLoad() {
TRACE_EVENT1("navigation", "RenderFrameHostImpl::OnDispatchLoad",
"frame_tree_node", frame_tree_node_->frame_tree_node_id());
- CHECK(SiteIsolationPolicy::AreCrossProcessFramesPossible());
// Don't forward the load event if this RFH is pending deletion. This can
// happen in a race where this RenderFrameHost finishes loading just after
@@ -2358,9 +2381,9 @@ void RenderFrameHostImpl::OnAccessibilityEvents(
accessibility_reset_token_ = 0;
RenderWidgetHostViewBase* view = GetViewForAccessibility();
- AccessibilityMode accessibility_mode = delegate_->GetAccessibilityMode();
+ ui::AXMode accessibility_mode = delegate_->GetAccessibilityMode();
if (!accessibility_mode.is_mode_off() && view && is_active()) {
- if (accessibility_mode.has_mode(AccessibilityMode::kNativeAPIs))
+ if (accessibility_mode.has_mode(ui::AXMode::kNativeAPIs))
GetOrCreateBrowserAccessibilityManager();
std::vector<AXEventNotificationDetails> details;
@@ -2387,7 +2410,7 @@ void RenderFrameHostImpl::OnAccessibilityEvents(
details.push_back(detail);
}
- if (accessibility_mode.has_mode(AccessibilityMode::kNativeAPIs)) {
+ if (accessibility_mode.has_mode(ui::AXMode::kNativeAPIs)) {
if (browser_accessibility_manager_)
browser_accessibility_manager_->OnAccessibilityEvents(details);
}
@@ -2431,8 +2454,8 @@ void RenderFrameHostImpl::OnAccessibilityLocationChanges(
RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>(
render_view_host_->GetWidget()->GetView());
if (view && is_active()) {
- AccessibilityMode accessibility_mode = delegate_->GetAccessibilityMode();
- if (accessibility_mode.has_mode(AccessibilityMode::kNativeAPIs)) {
+ ui::AXMode accessibility_mode = delegate_->GetAccessibilityMode();
+ if (accessibility_mode.has_mode(ui::AXMode::kNativeAPIs)) {
BrowserAccessibilityManager* manager =
GetOrCreateBrowserAccessibilityManager();
if (manager)
@@ -2456,8 +2479,8 @@ void RenderFrameHostImpl::OnAccessibilityLocationChanges(
void RenderFrameHostImpl::OnAccessibilityFindInPageResult(
const AccessibilityHostMsg_FindInPageResultParams& params) {
- AccessibilityMode accessibility_mode = delegate_->GetAccessibilityMode();
- if (accessibility_mode.has_mode(AccessibilityMode::kNativeAPIs)) {
+ ui::AXMode accessibility_mode = delegate_->GetAccessibilityMode();
+ if (accessibility_mode.has_mode(ui::AXMode::kNativeAPIs)) {
BrowserAccessibilityManager* manager =
GetOrCreateBrowserAccessibilityManager();
if (manager) {
@@ -2516,8 +2539,7 @@ void RenderFrameHostImpl::OnToggleFullscreen(bool enter_fullscreen) {
// A-B-A-B hierarchy, if the bottom frame goes fullscreen, this only needs to
// notify its parent, and Blink-side logic will take care of applying
// necessary changes to the other two ancestors.
- if (enter_fullscreen &&
- SiteIsolationPolicy::AreCrossProcessFramesPossible()) {
+ if (enter_fullscreen) {
std::set<SiteInstance*> notified_instances;
notified_instances.insert(GetSiteInstance());
for (FrameTreeNode* node = frame_tree_node_; node->parent();
@@ -2841,37 +2863,37 @@ void RenderFrameHostImpl::RunCreateWindowCompleteCallback(
}
void RenderFrameHostImpl::RegisterMojoInterfaces() {
- device::GeolocationContext* geolocation_context =
- delegate_ ? delegate_->GetGeolocationContext() : NULL;
-
#if !defined(OS_ANDROID)
// The default (no-op) implementation of InstalledAppProvider. On Android, the
// real implementation is provided in Java.
- GetInterfaceRegistry()->AddInterface(
- base::Bind(&InstalledAppProviderImplDefault::Create));
+ registry_->AddInterface(base::Bind(&InstalledAppProviderImplDefault::Create));
#endif // !defined(OS_ANDROID)
- if (geolocation_context) {
- // TODO(creis): Bind process ID here so that GeolocationImpl
- // can perform permissions checks once site isolation is complete.
- // crbug.com/426384
- // NOTE: At shutdown, there is no guaranteed ordering between destruction of
- // this object and destruction of any GeolocationsImpls created via
- // the below service registry, the reason being that the destruction of the
- // latter is triggered by receiving a message that the pipe was closed from
- // the renderer side. Hence, supply the reference to this object as a weak
- // pointer.
- GetInterfaceRegistry()->AddInterface(
- base::Bind(&device::GeolocationContext::Bind,
- base::Unretained(geolocation_context)));
- }
-
- GetInterfaceRegistry()->AddInterface<device::mojom::WakeLock>(base::Bind(
+ PermissionManager* permission_manager =
+ GetProcess()->GetBrowserContext()->GetPermissionManager();
+
+ if (delegate_) {
+ device::GeolocationContext* geolocation_context =
+ delegate_->GetGeolocationContext();
+ if (geolocation_context && permission_manager) {
+ geolocation_service_.reset(new GeolocationServiceImpl(
+ geolocation_context, permission_manager, this));
+ // NOTE: Both the |interface_registry_| and |geolocation_service_| are
+ // owned by |this|, so their destruction will be triggered together.
+ // |interface_registry_| is declared after |geolocation_service_|, so it
+ // will be destroyed prior to |geolocation_service_|.
+ registry_->AddInterface(
+ base::Bind(&GeolocationServiceImpl::Bind,
+ base::Unretained(geolocation_service_.get())));
+ }
+ }
+
+ registry_->AddInterface<device::mojom::WakeLock>(base::Bind(
&RenderFrameHostImpl::BindWakeLockRequest, base::Unretained(this)));
#if defined(OS_ANDROID)
if (base::FeatureList::IsEnabled(features::kWebNfc)) {
- GetInterfaceRegistry()->AddInterface<device::mojom::NFC>(base::Bind(
+ registry_->AddInterface<device::mojom::NFC>(base::Bind(
&RenderFrameHostImpl::BindNFCRequest, base::Unretained(this)));
}
#endif
@@ -2879,56 +2901,54 @@ void RenderFrameHostImpl::RegisterMojoInterfaces() {
if (!permission_service_context_)
permission_service_context_.reset(new PermissionServiceContext(this));
- GetInterfaceRegistry()->AddInterface(
+ registry_->AddInterface(
base::Bind(&PermissionServiceContext::CreateService,
base::Unretained(permission_service_context_.get())));
- GetInterfaceRegistry()->AddInterface(base::Bind(
+ registry_->AddInterface(base::Bind(
&PresentationServiceImpl::CreateMojoService, base::Unretained(this)));
- GetInterfaceRegistry()->AddInterface(
+ registry_->AddInterface(
base::Bind(&MediaSessionServiceImpl::Create, base::Unretained(this)));
#if defined(OS_ANDROID)
// Creates a MojoRendererService, passing it a MediaPlayerRender.
- GetInterfaceRegistry()->AddInterface<media::mojom::Renderer>(
+ registry_->AddInterface<media::mojom::Renderer>(
base::Bind(&content::CreateMediaPlayerRenderer, GetProcess()->GetID(),
GetRoutingID()));
#endif // defined(OS_ANDROID)
- GetInterfaceRegistry()->AddInterface(base::Bind(
+ registry_->AddInterface(base::Bind(
base::IgnoreResult(&RenderFrameHostImpl::CreateWebBluetoothService),
base::Unretained(this)));
- GetInterfaceRegistry()->AddInterface<media::mojom::InterfaceFactory>(
+ registry_->AddInterface<media::mojom::InterfaceFactory>(
base::Bind(&RenderFrameHostImpl::BindMediaInterfaceFactoryRequest,
base::Unretained(this)));
// This is to support usage of WebSockets in cases in which there is an
// associated RenderFrame. This is important for showing the correct security
// state of the page and also honoring user override of bad certificates.
- GetInterfaceRegistry()->AddInterface(
- base::Bind(&WebSocketManager::CreateWebSocket,
- process_->GetID(),
- routing_id_));
+ registry_->AddInterface(base::Bind(&WebSocketManager::CreateWebSocket,
+ process_->GetID(), routing_id_));
#if BUILDFLAG(ENABLE_VR)
- GetInterfaceRegistry()->AddInterface<device::mojom::VRService>(base::Bind(
+ registry_->AddInterface<device::mojom::VRService>(base::Bind(
&device::VRServiceImpl::Create, GetProcess()->GetID(), GetRoutingID()));
#else
- GetInterfaceRegistry()->AddInterface<device::mojom::VRService>(
+ registry_->AddInterface<device::mojom::VRService>(
base::Bind(&IgnoreInterfaceRequest<device::mojom::VRService>));
#endif
if (RendererAudioOutputStreamFactoryContextImpl::UseMojoFactories()) {
- GetInterfaceRegistry()->AddInterface(base::BindRepeating(
+ registry_->AddInterface(base::BindRepeating(
&RenderFrameHostImpl::CreateAudioOutputStreamFactory,
base::Unretained(this)));
}
if (resource_coordinator::IsResourceCoordinatorEnabled()) {
- GetInterfaceRegistry()->AddInterface(base::Bind(
- &CreateResourceCoordinatorFrameInterface, base::Unretained(this)));
+ registry_->AddInterface(base::Bind(&CreateResourceCoordinatorFrameInterface,
+ base::Unretained(this)));
}
#if BUILDFLAG(ENABLE_WEBRTC)
@@ -2940,49 +2960,65 @@ void RenderFrameHostImpl::RegisterMojoInterfaces() {
// as a raw pointer here is safe.
MediaStreamManager* media_stream_manager =
BrowserMainLoop::GetInstance()->media_stream_manager();
- GetInterfaceRegistry()->AddInterface(
+ registry_->AddInterface(
base::Bind(&MediaDevicesDispatcherHost::Create, GetProcess()->GetID(),
- GetRoutingID(), GetProcess()
- ->GetBrowserContext()
- ->GetMediaDeviceIDSalt(),
+ GetRoutingID(),
+ GetProcess()->GetBrowserContext()->GetMediaDeviceIDSalt(),
base::Unretained(media_stream_manager)),
BrowserThread::GetTaskRunnerForThread(BrowserThread::IO));
}
#endif
#if BUILDFLAG(ENABLE_MEDIA_REMOTING)
- GetInterfaceRegistry()->AddInterface(base::Bind(
- &RemoterFactoryImpl::Bind, GetProcess()->GetID(), GetRoutingID()));
+ registry_->AddInterface(base::Bind(&RemoterFactoryImpl::Bind,
+ GetProcess()->GetID(), GetRoutingID()));
#endif // BUILDFLAG(ENABLE_MEDIA_REMOTING)
- GetInterfaceRegistry()->AddInterface(base::Bind(
- &KeyboardLockServiceImpl::CreateMojoService));
+ registry_->AddInterface(
+ base::Bind(&KeyboardLockServiceImpl::CreateMojoService));
- GetInterfaceRegistry()->AddInterface(base::Bind(&ImageCaptureImpl::Create));
+ registry_->AddInterface(base::Bind(&ImageCaptureImpl::Create));
- GetInterfaceRegistry()->AddInterface(
+ registry_->AddInterface(
base::Bind(&ForwardRequest<shape_detection::mojom::BarcodeDetection>,
shape_detection::mojom::kServiceName));
- GetInterfaceRegistry()->AddInterface(
+ registry_->AddInterface(
base::Bind(&ForwardRequest<shape_detection::mojom::FaceDetectionProvider>,
shape_detection::mojom::kServiceName));
- GetInterfaceRegistry()->AddInterface(
+ registry_->AddInterface(
base::Bind(&ForwardRequest<shape_detection::mojom::TextDetection>,
shape_detection::mojom::kServiceName));
- GetInterfaceRegistry()->AddInterface(
+ registry_->AddInterface(
base::Bind(&CreatePaymentManager, base::Unretained(this)));
if (base::FeatureList::IsEnabled(features::kWebAuth)) {
- GetInterfaceRegistry()->AddInterface(
+ registry_->AddInterface(
base::Bind(&AuthenticatorImpl::Create, base::Unretained(this)));
}
- if (base::FeatureList::IsEnabled(features::kGenericSensor)) {
- GetInterfaceRegistry()->AddInterface(
- base::Bind(&ForwardRequest<device::mojom::SensorProvider>,
- device::mojom::kServiceName));
+ if (permission_manager) {
+ sensor_provider_proxy_.reset(
+ new SensorProviderProxyImpl(permission_manager, this));
+ registry_->AddInterface(
+ base::Bind(&SensorProviderProxyImpl::Bind,
+ base::Unretained(sensor_provider_proxy_.get())));
}
+
+ registry_->AddInterface(
+ base::Bind(&ForwardRequest<device::mojom::VibrationManager>,
+ device::mojom::kServiceName));
+
+ registry_->AddInterface(
+ base::Bind(&media::WatchTimeRecorder::CreateWatchTimeRecorderProvider));
+
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ cc::switches::kEnableGpuBenchmarking)) {
+ registry_->AddInterface(
+ base::Bind(&InputInjectorImpl::Create, weak_ptr_factory_.GetWeakPtr()));
+ }
+
+ registry_->AddInterface(base::Bind(&media::VideoDecodeStatsRecorder::Create));
}
void RenderFrameHostImpl::ResetWaitingState() {
@@ -3249,7 +3285,7 @@ void RenderFrameHostImpl::CommitNavigation(
DCHECK(
(response && (body.get() || handle.is_valid())) ||
common_params.url.SchemeIs(url::kDataScheme) ||
- !ShouldMakeNetworkRequestForURL(common_params.url) ||
+ !IsURLHandledByNetworkStack(common_params.url) ||
FrameMsg_Navigate_Type::IsSameDocument(common_params.navigation_type) ||
IsRendererDebugURL(common_params.url));
UpdatePermissionsForNavigation(common_params, request_params);
@@ -3290,13 +3326,21 @@ void RenderFrameHostImpl::CommitNavigation(
common_params, request_params));
// If a network request was made, update the Previews state.
- if (ShouldMakeNetworkRequestForURL(common_params.url) &&
+ if (IsURLHandledByNetworkStack(common_params.url) &&
!FrameMsg_Navigate_Type::IsSameDocument(common_params.navigation_type)) {
last_navigation_previews_state_ = common_params.previews_state;
}
- // Released in OnStreamHandleConsumed().
- stream_handle_ = std::move(body);
+ // If this navigation is same-document, then |body| is nullptr. So without
+ // this condition, the following line would reset |stream_handle_| to nullptr.
+ // Doing this would stop any pending document load in the renderer and this
+ // same-document navigation would not load any new ones for replacement.
+ // The user would finish with a half loaded document.
+ // See https://crbug.com/769645.
+ if (!FrameMsg_Navigate_Type::IsSameDocument(common_params.navigation_type)) {
+ // Released in OnStreamHandleConsumed().
+ stream_handle_ = std::move(body);
+ }
// When navigating to a debug url, no commit is expected from the
// RenderFrameHost, nor should the throbber start. The NavigationRequest is
@@ -3340,11 +3384,11 @@ void RenderFrameHostImpl::FailedNavigation(
}
void RenderFrameHostImpl::SetUpMojoIfNeeded() {
- if (interface_registry_.get())
+ if (registry_.get())
return;
associated_registry_ = base::MakeUnique<AssociatedInterfaceRegistryImpl>();
- interface_registry_ = base::MakeUnique<service_manager::BinderRegistry>();
+ registry_ = base::MakeUnique<service_manager::BinderRegistry>();
auto make_binding = [](RenderFrameHostImpl* impl,
mojom::FrameHostAssociatedRequest request) {
@@ -3375,7 +3419,7 @@ void RenderFrameHostImpl::SetUpMojoIfNeeded() {
}
void RenderFrameHostImpl::InvalidateMojoConnection() {
- interface_registry_.reset();
+ registry_.reset();
frame_.reset();
frame_host_interface_broker_binding_.Close();
@@ -3385,6 +3429,12 @@ void RenderFrameHostImpl::InvalidateMojoConnection() {
mojo_image_downloader_.reset();
frame_resource_coordinator_.reset();
+
+ // The geolocation service and sensor provider proxy may attempt to cancel
+ // permission requests so they must be reset before the routing_id mapping is
+ // removed.
+ geolocation_service_.reset();
+ sensor_provider_proxy_.reset();
}
bool RenderFrameHostImpl::IsFocused() {
@@ -3493,15 +3543,23 @@ RenderFrameHostImpl::GetMojoImageDownloader() {
resource_coordinator::ResourceCoordinatorInterface*
RenderFrameHostImpl::GetFrameResourceCoordinator() {
- if (!frame_resource_coordinator_) {
+ if (frame_resource_coordinator_)
+ return frame_resource_coordinator_.get();
+
+ if (!resource_coordinator::IsResourceCoordinatorEnabled()) {
+ frame_resource_coordinator_ =
+ base::MakeUnique<resource_coordinator::ResourceCoordinatorInterface>(
+ nullptr, resource_coordinator::CoordinationUnitType::kFrame);
+ } else {
+ auto* connection = ServiceManagerConnection::GetForProcess();
frame_resource_coordinator_ =
base::MakeUnique<resource_coordinator::ResourceCoordinatorInterface>(
- ServiceManagerConnection::GetForProcess()->GetConnector(),
+ connection ? connection->GetConnector() : nullptr,
resource_coordinator::CoordinationUnitType::kFrame);
- if (parent_) {
- parent_->GetFrameResourceCoordinator()->AddChild(
- *frame_resource_coordinator_);
- }
+ }
+ if (parent_) {
+ parent_->GetFrameResourceCoordinator()->AddChild(
+ *frame_resource_coordinator_);
}
return frame_resource_coordinator_.get();
}
@@ -3564,7 +3622,7 @@ void RenderFrameHostImpl::SetAccessibilityCallbackForTesting(
}
void RenderFrameHostImpl::UpdateAXTreeData() {
- AccessibilityMode accessibility_mode = delegate_->GetAccessibilityMode();
+ ui::AXMode accessibility_mode = delegate_->GetAccessibilityMode();
if (accessibility_mode.is_mode_off() || !is_active()) {
return;
}
@@ -3608,8 +3666,8 @@ BrowserAccessibilityManager*
void RenderFrameHostImpl::ActivateFindInPageResultForAccessibility(
int request_id) {
- AccessibilityMode accessibility_mode = delegate_->GetAccessibilityMode();
- if (accessibility_mode.has_mode(AccessibilityMode::kNativeAPIs)) {
+ ui::AXMode accessibility_mode = delegate_->GetAccessibilityMode();
+ if (accessibility_mode.has_mode(ui::AXMode::kNativeAPIs)) {
BrowserAccessibilityManager* manager =
GetOrCreateBrowserAccessibilityManager();
if (manager)
@@ -4009,10 +4067,13 @@ void RenderFrameHostImpl::BindNFCRequest(device::mojom::NFCRequest request) {
void RenderFrameHostImpl::GetInterface(
const std::string& interface_name,
mojo::ScopedMessagePipeHandle interface_pipe) {
- if (!interface_registry_ ||
- !interface_registry_->TryBindInterface(interface_name, &interface_pipe)) {
- GetContentClient()->browser()->BindInterfaceRequestFromFrame(
- this, interface_name, std::move(interface_pipe));
+ if (!registry_ ||
+ !registry_->TryBindInterface(interface_name, &interface_pipe)) {
+ delegate_->OnInterfaceRequest(this, interface_name, &interface_pipe);
+ if (interface_pipe->is_valid()) {
+ GetContentClient()->browser()->BindInterfaceRequestFromFrame(
+ this, interface_name, std::move(interface_pipe));
+ }
}
}
@@ -4219,4 +4280,33 @@ void RenderFrameHostImpl::ForwardGetInterfaceToRenderFrame(
}
#endif
+void RenderFrameHostImpl::ForEachImmediateLocalRoot(
+ const base::Callback<void(RenderFrameHostImpl*)>& callback) {
+ if (!frame_tree_node_->child_count())
+ return;
+
+ std::queue<FrameTreeNode*> queue;
+ for (size_t index = 0; index < frame_tree_node_->child_count(); ++index)
+ queue.push(frame_tree_node_->child_at(index));
+ while (queue.size()) {
+ FrameTreeNode* current = queue.front();
+ queue.pop();
+ if (current->current_frame_host()->is_local_root()) {
+ callback.Run(current->current_frame_host());
+ } else {
+ for (size_t index = 0; index < current->child_count(); ++index)
+ queue.push(current->child_at(index));
+ }
+ }
+}
+
+void RenderFrameHostImpl::SetVisibilityForChildViews(bool visible) {
+ ForEachImmediateLocalRoot(base::Bind(
+ [](bool is_visible, RenderFrameHostImpl* frame_host) {
+ if (auto* view = frame_host->GetView())
+ return is_visible ? view->Show() : view->Hide();
+ },
+ visible));
+}
+
} // namespace content
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 c3a1726f976..9a4fa29dd7c 100644
--- a/chromium/content/browser/frame_host/render_frame_host_impl.h
+++ b/chromium/content/browser/frame_host/render_frame_host_impl.h
@@ -10,8 +10,10 @@
#include <list>
#include <map>
+#include <memory>
#include <set>
#include <string>
+#include <utility>
#include <vector>
#include "base/callback.h"
@@ -30,7 +32,6 @@
#include "content/browser/loader/global_routing_id.h"
#include "content/browser/site_instance_impl.h"
#include "content/browser/webui/web_ui_impl.h"
-#include "content/common/accessibility_mode.h"
#include "content/common/ax_content_node_data.h"
#include "content/common/content_export.h"
#include "content/common/content_security_policy/csp_context.h"
@@ -51,12 +52,14 @@
#include "mojo/public/cpp/system/data_pipe.h"
#include "net/http/http_response_headers.h"
#include "services/device/public/interfaces/wake_lock_context.mojom.h"
+#include "services/service_manager/public/cpp/binder_registry.h"
#include "third_party/WebKit/public/platform/WebFocusType.h"
#include "third_party/WebKit/public/platform/WebInsecureRequestPolicy.h"
#include "third_party/WebKit/public/platform/WebSuddenTerminationDisablerType.h"
#include "third_party/WebKit/public/platform/modules/bluetooth/web_bluetooth.mojom.h"
#include "third_party/WebKit/public/web/WebTextDirection.h"
#include "third_party/WebKit/public/web/WebTreeScopeType.h"
+#include "ui/accessibility/ax_modes.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/base/mojo/window_open_disposition.mojom.h"
#include "ui/base/page_transition_types.h"
@@ -92,6 +95,7 @@ class LegacyIPCFrameInputHandler;
class FeaturePolicy;
class FrameTree;
class FrameTreeNode;
+class GeolocationServiceImpl;
class MediaInterfaceProxy;
class NavigationHandleImpl;
class PermissionServiceContext;
@@ -104,6 +108,7 @@ class RenderWidgetHostImpl;
class RenderWidgetHostView;
class RenderWidgetHostViewBase;
class ResourceRequestBody;
+class SensorProviderProxyImpl;
class StreamHandle;
class TimeoutMonitor;
class WebBluetoothServiceImpl;
@@ -116,11 +121,11 @@ struct ResourceResponse;
class CONTENT_EXPORT RenderFrameHostImpl
: public RenderFrameHost,
public base::SupportsUserData,
- NON_EXPORTED_BASE(public mojom::FrameHost),
- NON_EXPORTED_BASE(public mojom::FrameHostInterfaceBroker),
+ public mojom::FrameHost,
+ public mojom::FrameHostInterfaceBroker,
public BrowserAccessibilityDelegate,
public SiteInstanceImpl::Observer,
- public NON_EXPORTED_BASE(service_manager::mojom::InterfaceProvider),
+ public service_manager::mojom::InterfaceProvider,
public CSPContext {
public:
using AXTreeSnapshotCallback =
@@ -175,7 +180,6 @@ class CONTENT_EXPORT RenderFrameHostImpl
void CopyImageAt(int x, int y) override;
void SaveImageAt(int x, int y) override;
RenderViewHost* GetRenderViewHost() override;
- service_manager::BinderRegistry* GetInterfaceRegistry() override;
service_manager::InterfaceProvider* GetRemoteInterfaces() override;
AssociatedInterfaceProvider* GetRemoteAssociatedInterfaces() override;
blink::WebPageVisibilityState GetVisibilityState() override;
@@ -283,9 +287,7 @@ class CONTENT_EXPORT RenderFrameHostImpl
// 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.
- void set_last_committed_url(const GURL& url) {
- last_committed_url_ = url;
- }
+ void SetLastCommittedUrl(const GURL& url);
// The most recent non-net-error URL to commit in this frame. In almost all
// cases, use GetLastCommittedURL instead.
@@ -590,7 +592,6 @@ class CONTENT_EXPORT RenderFrameHostImpl
// Returns the Mojo ImageDownloader service.
const content::mojom::ImageDownloaderPtr& GetMojoImageDownloader();
- // Returns the interface to the Global Resource Coordinator
resource_coordinator::ResourceCoordinatorInterface*
GetFrameResourceCoordinator() override;
@@ -644,6 +645,11 @@ class CONTENT_EXPORT RenderFrameHostImpl
service_manager::InterfaceProvider* GetJavaInterfaces() override;
#endif
+ // Propagates the visibility state along the immediate local roots by calling
+ // RenderWidgetHostViewChildFrame::Show()/Hide(). Calling this on a pending
+ // or speculative RenderFrameHost (that has not committed) should be avoided.
+ void SetVisibilityForChildViews(bool visible);
+
// Returns an unguessable token for this RFHI. This provides a temporary way
// to identify a RenderFrameHost that's compatible with IPC. Else, one needs
// to send pid + RoutingID, but one cannot send pid. One can get it from the
@@ -694,6 +700,7 @@ class CONTENT_EXPORT RenderFrameHostImpl
WebUIJavascriptDisallowedAfterSwapOut);
FRIEND_TEST_ALL_PREFIXES(RenderFrameHostManagerTest, LastCommittedOrigin);
FRIEND_TEST_ALL_PREFIXES(SitePerProcessBrowserTest, CrashSubframe);
+ FRIEND_TEST_ALL_PREFIXES(SitePerProcessBrowserTest, FindImmediateLocalRoots);
FRIEND_TEST_ALL_PREFIXES(SitePerProcessBrowserTest,
RenderViewHostIsNotReusedAfterDelayedSwapOutACK);
FRIEND_TEST_ALL_PREFIXES(SitePerProcessBrowserTest,
@@ -721,11 +728,9 @@ class CONTENT_EXPORT RenderFrameHostImpl
const base::TimeTicks& navigation_start);
void OnDidFailProvisionalLoadWithError(
const FrameHostMsg_DidFailProvisionalLoadWithError_Params& params);
- void OnDidFailLoadWithError(
- const GURL& url,
- int error_code,
- const base::string16& error_description,
- bool was_ignored_by_handler);
+ void OnDidFailLoadWithError(const GURL& url,
+ int error_code,
+ const base::string16& error_description);
void OnDidCommitProvisionalLoad(const IPC::Message& msg);
void OnUpdateState(const PageState& state);
void OnBeforeUnloadACK(
@@ -770,6 +775,7 @@ class CONTENT_EXPORT RenderFrameHostImpl
void OnUpdateTitle(const base::string16& title,
blink::WebTextDirection title_direction);
void OnUpdateEncoding(const std::string& encoding);
+ void OnDidBlockFramebust(const GURL& url);
void OnBeginNavigation(const CommonNavigationParams& common_params,
const BeginNavigationParams& begin_params);
void OnAbortNavigation();
@@ -973,6 +979,28 @@ class CONTENT_EXPORT RenderFrameHostImpl
// can be released.
void OnStreamHandleConsumed(const GURL& stream_url);
+ // TODO(ekaramad): One major purpose behind the API is to traverse the frame
+ // tree top-down to visit the RenderWidgetHostViews of interest in the most
+ // efficient way. We might want to revisit this API, remove it from RFHImpl,
+ // and perhaps consolidate it with some of the existing ones such as
+ // WebContentsImpl::GetRenderWidgetHostViewsInTree() into a new more
+ // appropriate API for dealing with (virtual) RenderWidgetHost(View) tree.
+ // (see https://crbug.com/754726).
+ // Runs |callback| for all the local roots immediately under this frame, i.e.
+ // local roots which are under this frame and their first ancestor which is a
+ // local root is either this frame or this frame's local root. For instance,
+ // in a frame tree such as:
+ // A0
+ // / | \
+ // B A1 E
+ // / / \ \
+ // D A2 C F
+ // RFHs at nodes B, E, D, C, and F are all local roots in the given frame tree
+ // under the root at A0, but only B, C, and E are considered immediate local
+ // roots of A0. Note that this will exclude any speculative or pending RFHs.
+ void ForEachImmediateLocalRoot(
+ const base::Callback<void(RenderFrameHostImpl*)>& callback);
+
// 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
@@ -1109,9 +1137,15 @@ class CONTENT_EXPORT RenderFrameHostImpl
// SiteInstance. May be null in tests.
std::unique_ptr<TimeoutMonitor> swapout_event_monitor_timeout_;
+ // GeolocationService which provides Geolocation.
+ std::unique_ptr<GeolocationServiceImpl> geolocation_service_;
+
+ // SensorProvider proxy which acts as a gatekeeper to the real SensorProvider.
+ std::unique_ptr<SensorProviderProxyImpl> sensor_provider_proxy_;
+
std::unique_ptr<AssociatedInterfaceRegistryImpl> associated_registry_;
- std::unique_ptr<service_manager::BinderRegistry> interface_registry_;
+ std::unique_ptr<service_manager::BinderRegistry> registry_;
std::unique_ptr<service_manager::InterfaceProvider> remote_interfaces_;
std::list<std::unique_ptr<WebBluetoothServiceImpl>> web_bluetooth_services_;
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 5db56d734dc..9f55c9a0ef3 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
@@ -5,16 +5,19 @@
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "base/macros.h"
+#include "content/browser/frame_host/navigation_handle_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/frame_messages.h"
#include "content/public/browser/javascript_dialog_manager.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/common/content_client.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
+#include "content/public/test/test_navigation_observer.h"
#include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.h"
#include "content/test/test_content_browser_client.h"
@@ -194,7 +197,7 @@ class TestJavaScriptDialogManager : public JavaScriptDialogManager,
// JavaScriptDialogManager
void RunJavaScriptDialog(WebContents* web_contents,
- const GURL& origin_url,
+ const GURL& alerting_frame_url,
JavaScriptDialogType dialog_type,
const base::string16& message_text,
const base::string16& default_prompt_text,
@@ -333,35 +336,94 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBrowserTest,
wc->SetJavaScriptDialogManagerForTesting(nullptr);
}
+namespace {
+
+// A helper to execute some script in a frame just before it is deleted, such
+// that no message loops are pumped and no sync IPC messages are processed
+// between script execution and the destruction of the RenderFrameHost .
+class ExecuteScriptBeforeRenderFrameDeletedHelper
+ : public RenderFrameDeletedObserver {
+ public:
+ ExecuteScriptBeforeRenderFrameDeletedHelper(RenderFrameHost* observed_frame,
+ const std::string& script)
+ : RenderFrameDeletedObserver(observed_frame), script_(script) {}
+
+ protected:
+ // WebContentsObserver:
+ void RenderFrameDeleted(RenderFrameHost* render_frame_host) override {
+ const bool was_deleted = deleted();
+ RenderFrameDeletedObserver::RenderFrameDeleted(render_frame_host);
+ if (deleted() && !was_deleted)
+ ExecuteScriptAsync(render_frame_host, script_);
+ }
+
+ private:
+ std::string script_;
+
+ DISALLOW_COPY_AND_ASSIGN(ExecuteScriptBeforeRenderFrameDeletedHelper);
+};
+
+} // namespace
+
// Regression test for https://crbug.com/728171 where the sync IPC channel has a
// connection error but we don't properly check for it. This occurs because we
// send a sync window.open IPC after the RenderFrameHost is destroyed.
//
-// This test reproduces the issue by calling window.close, and then
-// window.open in a task that runs immediately after window.close (which
-// internally posts a task to send the IPC). This ensures that the
-// RenderFrameHost is destroyed by the time the window.open IPC reaches the
-// browser process.
+// The test creates two WebContents rendered in the same process. The first is
+// is the window-opener of the second, so the first window can be used to relay
+// information collected during the destruction of the RenderFrame in the second
+// WebContents back to the browser process.
+//
+// The issue is then reproduced by asynchronously triggering a call to
+// window.open() in the main frame of the second WebContents in response to
+// WebContentsObserver::RenderFrameDeleted -- that is, just before the RFHI is
+// destroyed on the browser side. The test assumes that between these two
+// events, the UI message loop is not pumped, and no sync IPC messages are
+// processed on the UI thread.
+//
+// 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
+// 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
+// is not pumped, so proxied non-sync IPCs are not delivered.
+//
+// Furthermore, on Android, exercising window.open() must be delayed until after
+// content::RemoveShellView returns, as that method calls into JNI to close the
+// view corresponding to the WebContents, which will then call back into native
+// code and may run nested message loops and send sync IPC messages.
IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBrowserTest,
FrameDetached_WindowOpenIPCFails) {
NavigateToURL(shell(), GetTestUrl("", "title1.html"));
EXPECT_EQ(1u, Shell::windows().size());
- GURL test_url = GetTestUrl("render_frame_host", "window_open_and_close.html");
+ GURL test_url = GetTestUrl("render_frame_host", "window_open.html");
std::string open_script =
base::StringPrintf("popup = window.open('%s');", test_url.spec().c_str());
+ TestNavigationObserver second_contents_navigation_observer(nullptr, 1);
+ second_contents_navigation_observer.StartWatchingNewWebContents();
EXPECT_TRUE(content::ExecuteScript(shell(), open_script));
- ASSERT_EQ(2u, Shell::windows().size());
+ second_contents_navigation_observer.Wait();
+ ASSERT_EQ(2u, Shell::windows().size());
Shell* new_shell = Shell::windows()[1];
- RenderFrameDeletedObserver deleted_observer(
- new_shell->web_contents()->GetMainFrame());
+ ExecuteScriptBeforeRenderFrameDeletedHelper deleted_observer(
+ new_shell->web_contents()->GetMainFrame(), "callWindowOpen();");
+ new_shell->Close();
deleted_observer.WaitUntilDeleted();
- bool is_closed = false;
+ bool did_call_window_open = false;
EXPECT_TRUE(ExecuteScriptAndExtractBool(
- shell(), "domAutomationController.send(popup.closed)", &is_closed));
- EXPECT_TRUE(is_closed);
+ shell(), "domAutomationController.send(!!popup.didCallWindowOpen)",
+ &did_call_window_open));
+ EXPECT_TRUE(did_call_window_open);
+
+ std::string result_of_window_open;
+ EXPECT_TRUE(ExecuteScriptAndExtractString(
+ shell(), "domAutomationController.send(String(popup.resultOfWindowOpen))",
+ &result_of_window_open));
+ EXPECT_EQ("null", result_of_window_open);
}
// After a navigation, the StreamHandle must be released.
@@ -428,4 +490,186 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBrowserTest,
EXPECT_EQ(nullptr, main_frame->stream_handle_for_testing());
}
+namespace {
+void PostRequestMonitor(int* post_counter,
+ const net::test_server::HttpRequest& request) {
+ if (request.method != net::test_server::METHOD_POST)
+ return;
+ (*post_counter)++;
+ auto it = request.headers.find("Content-Type");
+ CHECK(it != request.headers.end());
+ CHECK(!it->second.empty());
+}
+} // namespace
+
+// Verifies form submits and resubmits work.
+IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBrowserTest, POSTNavigation) {
+ net::EmbeddedTestServer http_server;
+ base::FilePath content_test_data(FILE_PATH_LITERAL("content/test/data"));
+ http_server.AddDefaultHandlers(content_test_data);
+ int post_counter = 0;
+ http_server.RegisterRequestMonitor(
+ base::Bind(&PostRequestMonitor, &post_counter));
+ ASSERT_TRUE(http_server.Start());
+
+ GURL url(http_server.GetURL("/session_history/form.html"));
+ GURL post_url = http_server.GetURL("/echotitle");
+
+ // Navigate to a page with a form.
+ TestNavigationObserver observer(shell()->web_contents());
+ NavigateToURL(shell(), url);
+ EXPECT_EQ(url, observer.last_navigation_url());
+ EXPECT_TRUE(observer.last_navigation_succeeded());
+
+ // Submit the form.
+ GURL submit_url("javascript:submitForm('isubmit')");
+ NavigateToURL(shell(), submit_url);
+
+ // Check that a proper POST navigation was done.
+ EXPECT_EQ("text=&select=a",
+ base::UTF16ToASCII(shell()->web_contents()->GetTitle()));
+ EXPECT_EQ(post_url, shell()->web_contents()->GetLastCommittedURL());
+ EXPECT_TRUE(shell()
+ ->web_contents()
+ ->GetController()
+ .GetActiveEntry()
+ ->GetHasPostData());
+
+ // Reload and verify the form was submitted.
+ shell()->web_contents()->GetController().Reload(ReloadType::NORMAL, false);
+ EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
+ EXPECT_EQ("text=&select=a",
+ base::UTF16ToASCII(shell()->web_contents()->GetTitle()));
+ CHECK_EQ(2, post_counter);
+}
+
+namespace {
+
+class NavigationHandleGrabber : public WebContentsObserver {
+ public:
+ explicit NavigationHandleGrabber(WebContents* web_contents)
+ : WebContentsObserver(web_contents) {}
+
+ void ReadyToCommitNavigation(NavigationHandle* navigation_handle) override {
+ if (navigation_handle->GetURL().path() != "/title2.html")
+ return;
+ static_cast<NavigationHandleImpl*>(navigation_handle)
+ ->set_complete_callback_for_testing(
+ base::Bind(&NavigationHandleGrabber::SendingNavigationCommitted,
+ base::Unretained(this), navigation_handle));
+ }
+
+ void SendingNavigationCommitted(
+ NavigationHandle* navigation_handle,
+ NavigationThrottle::ThrottleCheckResult result) {
+ if (navigation_handle->GetURL().path() != "/title2.html")
+ return;
+ ExecuteScriptAsync(web_contents(), "document.open();");
+ }
+
+ void DidFinishNavigation(NavigationHandle* navigation_handle) override {
+ if (navigation_handle->GetURL().path() != "/title2.html")
+ return;
+ if (navigation_handle->HasCommitted())
+ committed_title2_ = true;
+ run_loop_.QuitClosure().Run();
+ }
+
+ void WaitForTitle2() { run_loop_.Run(); }
+
+ bool committed_title2() { return committed_title2_; }
+
+ private:
+ bool committed_title2_ = false;
+ base::RunLoop run_loop_;
+};
+} // namespace
+
+// Verifies that if a frame aborts a navigation right after it starts, it is
+// cancelled.
+IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBrowserTest, FastNavigationAbort) {
+ GURL url(embedded_test_server()->GetURL("/title1.html"));
+ NavigateToURL(shell(), url);
+
+ // Now make a navigation.
+ NavigationHandleGrabber observer(shell()->web_contents());
+ const base::string16 title = base::ASCIIToUTF16("done");
+ EXPECT_TRUE(ExecuteScript(shell()->web_contents(),
+ "window.location.href='/title2.html'"));
+ observer.WaitForTitle2();
+ // Flush IPCs to make sure the renderer didn't tell us to navigate. Need to
+ // make two round trips.
+ EXPECT_TRUE(ExecuteScript(shell()->web_contents(), ""));
+ EXPECT_TRUE(ExecuteScript(shell()->web_contents(), ""));
+ EXPECT_FALSE(observer.committed_title2());
+}
+
+IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBrowserTest,
+ TerminationDisablersClearedOnRendererCrash) {
+ EXPECT_TRUE(NavigateToURL(
+ shell(), GetTestUrl("render_frame_host", "beforeunload.html")));
+ EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
+
+ WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell()->web_contents());
+ RenderFrameHostImpl* main_frame =
+ static_cast<RenderFrameHostImpl*>(wc->GetMainFrame());
+
+ EXPECT_TRUE(main_frame->GetSuddenTerminationDisablerState(
+ blink::kBeforeUnloadHandler));
+
+ // Make the renderer crash.
+ RenderProcessHost* renderer_process = main_frame->GetProcess();
+ RenderProcessHostWatcher crash_observer(
+ renderer_process, RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
+ renderer_process->Shutdown(0, false);
+ crash_observer.Wait();
+
+ EXPECT_FALSE(main_frame->GetSuddenTerminationDisablerState(
+ blink::kBeforeUnloadHandler));
+
+ // This should not trigger a DCHECK once the renderer sends up the termination
+ // disabler flags.
+ shell()->web_contents()->GetController().Reload(ReloadType::NORMAL, false);
+ EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
+
+ EXPECT_TRUE(main_frame->GetSuddenTerminationDisablerState(
+ blink::kBeforeUnloadHandler));
+}
+
+// Aborted renderer-initiated navigations that don't destroy the current
+// document (e.g. no error page is displayed) must not cancel pending
+// XMLHttpRequests.
+// See https://crbug.com/762945.
+IN_PROC_BROWSER_TEST_F(
+ RenderFrameHostImplBrowserTest,
+ AbortedRendererInitiatedNavigationDoNotCancelPendingXHR) {
+ GURL main_url(embedded_test_server()->GetURL("/title1.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+ EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
+
+ // 1) Send an XHR that is slow to complete.
+ const char* send_slow_XHR =
+ "var request = new XMLHttpRequest();"
+ "request.addEventListener('abort', () => document.title = 'XHR aborted');"
+ "request.addEventListener('load', () => document.title = 'XHR loaded');"
+ "request.open('GET', '%s');"
+ "request.send();";
+ const GURL slow_url = embedded_test_server()->GetURL("/slow?1");
+ EXPECT_TRUE(content::ExecuteScript(
+ shell(), base::StringPrintf(send_slow_XHR, slow_url.spec().c_str())));
+
+ // 2) In the meantime, create a renderer-initiated navigation. It will be
+ // aborted.
+ EXPECT_TRUE(content::ExecuteScript(
+ shell(), "window.location = 'customprotocol:aborted'"));
+
+ // 3) Wait for the XHR request to complete.
+ const base::string16 XHR_aborted = base::ASCIIToUTF16("XHR aborted");
+ const base::string16 XHR_loaded = base::ASCIIToUTF16("XHR loaded");
+ TitleWatcher watcher(shell()->web_contents(), XHR_loaded);
+ watcher.AlsoWaitForTitle(XHR_aborted);
+
+ EXPECT_EQ(XHR_loaded, watcher.WaitAndGetTitle());
+}
+
} // namespace content
diff --git a/chromium/content/browser/frame_host/render_frame_host_manager.cc b/chromium/content/browser/frame_host/render_frame_host_manager.cc
index 64799aa81fa..22645479cad 100644
--- a/chromium/content/browser/frame_host/render_frame_host_manager.cc
+++ b/chromium/content/browser/frame_host/render_frame_host_manager.cc
@@ -49,6 +49,7 @@
#include "content/public/common/content_switches.h"
#include "content/public/common/referrer.h"
#include "content/public/common/url_constants.h"
+#include "content/public/common/url_utils.h"
namespace content {
@@ -882,9 +883,6 @@ void RenderFrameHostManager::OnDidUpdateName(const std::string& name,
void RenderFrameHostManager::OnDidAddContentSecurityPolicies(
const std::vector<ContentSecurityPolicyHeader>& headers) {
- if (!SiteIsolationPolicy::AreCrossProcessFramesPossible())
- return;
-
for (const auto& pair : proxy_hosts_) {
pair.second->Send(new FrameMsg_AddContentSecurityPolicies(
pair.second->GetRoutingID(), headers));
@@ -892,9 +890,6 @@ void RenderFrameHostManager::OnDidAddContentSecurityPolicies(
}
void RenderFrameHostManager::OnDidResetContentSecurityPolicy() {
- if (!SiteIsolationPolicy::AreCrossProcessFramesPossible())
- return;
-
for (const auto& pair : proxy_hosts_) {
pair.second->Send(
new FrameMsg_ResetContentSecurityPolicy(pair.second->GetRoutingID()));
@@ -903,9 +898,6 @@ void RenderFrameHostManager::OnDidResetContentSecurityPolicy() {
void RenderFrameHostManager::OnEnforceInsecureRequestPolicy(
blink::WebInsecureRequestPolicy policy) {
- if (!SiteIsolationPolicy::AreCrossProcessFramesPossible())
- return;
-
for (const auto& pair : proxy_hosts_) {
pair.second->Send(new FrameMsg_EnforceInsecureRequestPolicy(
pair.second->GetRoutingID(), policy));
@@ -935,9 +927,6 @@ void RenderFrameHostManager::OnDidChangeCollapsedState(bool collapsed) {
void RenderFrameHostManager::OnDidUpdateFrameOwnerProperties(
const FrameOwnerProperties& properties) {
- if (!SiteIsolationPolicy::AreCrossProcessFramesPossible())
- return;
-
// FrameOwnerProperties exist only for frames that have a parent.
CHECK(frame_tree_node_->parent());
SiteInstance* parent_instance =
@@ -1165,17 +1154,34 @@ RenderFrameHostManager::GetSiteInstanceForNavigation(
// other tabs in the current BrowsingInstance will be unable to script it.
// This is used for cases that require a process swap even in the
// process-per-tab model, such as WebUI pages.
- // TODO(clamy): Remove the dependency on the current entry.
- const NavigationEntry* current_entry =
- delegate_->GetLastCommittedNavigationEntryForRenderManager();
+
+ // First determine the effective URL of the current RenderFrameHost. This is
+ // the last URL it successfully committed. If it has yet to commit a URL, this
+ // falls back to the Site URL of its SiteInstance.
+ // Note: the effective URL of the current RenderFrameHost may differ from the
+ // URL of the last committed NavigationEntry, which cannot be used to decide
+ // whether to use a new SiteInstance. This happens when navigating a subframe,
+ // or when a new RenderFrameHost has been swapped in at the beginning of a
+ // navigation to replace a crashed RenderFrameHost.
BrowserContext* browser_context =
delegate_->GetControllerForRenderManager().GetBrowserContext();
- const GURL& current_effective_url = current_entry ?
- SiteInstanceImpl::GetEffectiveURL(browser_context,
- current_entry->GetURL()) :
- render_frame_host_->GetSiteInstance()->GetSiteURL();
+ const GURL& current_effective_url =
+ !render_frame_host_->last_successful_url().is_empty()
+ ? SiteInstanceImpl::GetEffectiveURL(
+ browser_context, render_frame_host_->last_successful_url())
+ : render_frame_host_->GetSiteInstance()->GetSiteURL();
+
+ // Determine if the current RenderFrameHost is in view source mode.
+ // TODO(clamy): If the current_effective_url doesn't match the last committed
+ // NavigationEntry's URL, current_is_view_source_mode should not be computed
+ // using the NavigationEntry. This can happen when a tab crashed, and a new
+ // RenderFrameHost was swapped in at the beginning of the navigation. See
+ // https://crbug.com/766630.
+ const NavigationEntry* current_entry =
+ delegate_->GetLastCommittedNavigationEntryForRenderManager();
bool current_is_view_source_mode = current_entry ?
current_entry->IsViewSourceMode() : dest_is_view_source_mode;
+
bool force_swap = ShouldSwapBrowsingInstancesForNavigation(
current_effective_url,
current_is_view_source_mode,
@@ -1280,8 +1286,7 @@ RenderFrameHostManager::DetermineSiteInstanceForURL(
// different sites. This avoids unnecessary OOPIFs on pages like
// chrome://settings, which currently has multiple "cross-site" subframes that
// don't need isolation.
- if (SiteIsolationPolicy::AreCrossProcessFramesPossible() &&
- !frame_tree_node_->IsMainFrame()) {
+ if (!frame_tree_node_->IsMainFrame()) {
SiteInstance* parent_site_instance =
frame_tree_node_->parent()->current_frame_host()->GetSiteInstance();
if (parent_site_instance->GetSiteURL().SchemeIs(kChromeUIScheme) &&
@@ -1614,7 +1619,7 @@ void RenderFrameHostManager::CreateProxiesForNewRenderFrameHost(
// Only create opener proxies if they are in the same BrowsingInstance.
if (new_instance->IsRelatedSiteInstance(old_instance)) {
CreateOpenerProxies(new_instance, frame_tree_node_);
- } else if (SiteIsolationPolicy::AreCrossProcessFramesPossible()) {
+ } else {
// Ensure that the frame tree has RenderFrameProxyHosts for the
// new SiteInstance in all nodes except the current one. We do this for
// all frames in the tree, whether they are in the same BrowsingInstance or
@@ -1629,9 +1634,6 @@ void RenderFrameHostManager::CreateProxiesForNewRenderFrameHost(
}
void RenderFrameHostManager::CreateProxiesForNewNamedFrame() {
- if (!SiteIsolationPolicy::AreCrossProcessFramesPossible())
- return;
-
DCHECK(!frame_tree_node_->frame_name().empty());
// If this is a top-level frame, create proxies for this node in the
@@ -1728,8 +1730,6 @@ std::unique_ptr<RenderFrameHostImpl> RenderFrameHostManager::CreateRenderFrame(
RenderFrameProxyHost* proxy = GetRenderFrameProxyHost(instance);
CHECK(instance);
- CHECK(SiteIsolationPolicy::AreCrossProcessFramesPossible() ||
- frame_tree_node_->IsMainFrame());
std::unique_ptr<RenderFrameHostImpl> new_render_frame_host;
bool success = true;
@@ -1745,7 +1745,6 @@ std::unique_ptr<RenderFrameHostImpl> RenderFrameHostManager::CreateRenderFrame(
if (frame_tree_node_->parent() &&
frame_tree_node_->parent()->current_frame_host()->GetSiteInstance() !=
instance) {
- CHECK(SiteIsolationPolicy::AreCrossProcessFramesPossible());
widget_routing_id = instance->GetProcess()->GetNextRoutingID();
}
@@ -1942,7 +1941,7 @@ RenderFrameHostManager::GetSiteInstanceForNavigationRequest(
// go cross-process. Check it first.
bool can_renderer_initiate_transfer =
render_frame_host_->IsRenderFrameLive() &&
- ShouldMakeNetworkRequestForURL(request.common_params().url) &&
+ IsURLHandledByNetworkStack(request.common_params().url) &&
IsRendererTransferNeededForNavigation(render_frame_host_.get(),
request.common_params().url);
@@ -2027,68 +2026,6 @@ bool RenderFrameHostManager::InitRenderFrame(
existing_proxy->InitRenderFrameProxy();
}
- // TODO(alexmos): These crash keys are temporary to track down
- // https://crbug.com/591478. Verify that the parent routing ID
- // points to a live RenderFrameProxy when this is not a remote-to-local
- // navigation (i.e., when there's no |existing_proxy|).
- if (!existing_proxy && frame_tree_node_->parent()) {
- RenderFrameProxyHost* parent_proxy = RenderFrameProxyHost::FromID(
- render_frame_host->GetProcess()->GetID(), parent_routing_id);
- if (!parent_proxy || !parent_proxy->is_render_frame_proxy_live()) {
- base::debug::SetCrashKeyValue("initrf_parent_proxy_exists",
- parent_proxy ? "yes" : "no");
-
- SiteInstance* parent_instance =
- frame_tree_node_->parent()->current_frame_host()->GetSiteInstance();
- base::debug::SetCrashKeyValue(
- "initrf_parent_is_in_same_site_instance",
- site_instance == parent_instance ? "yes" : "no");
- base::debug::SetCrashKeyValue("initrf_parent_process_is_live",
- frame_tree_node_->parent()
- ->current_frame_host()
- ->GetProcess()
- ->HasConnection()
- ? "yes"
- : "no");
- base::debug::SetCrashKeyValue(
- "initrf_render_view_is_live",
- render_frame_host->render_view_host()->IsRenderViewLive() ? "yes"
- : "no");
-
- // Collect some additional information for root's proxy if it's different
- // from the parent.
- FrameTreeNode* root = frame_tree_node_->frame_tree()->root();
- if (root != frame_tree_node_->parent()) {
- SiteInstance* root_instance =
- root->current_frame_host()->GetSiteInstance();
- base::debug::SetCrashKeyValue(
- "initrf_root_is_in_same_site_instance",
- site_instance == root_instance ? "yes" : "no");
- base::debug::SetCrashKeyValue(
- "initrf_root_is_in_same_site_instance_as_parent",
- parent_instance == root_instance ? "yes" : "no");
- base::debug::SetCrashKeyValue("initrf_root_process_is_live",
- frame_tree_node_->frame_tree()
- ->root()
- ->current_frame_host()
- ->GetProcess()
- ->HasConnection()
- ? "yes"
- : "no");
-
- RenderFrameProxyHost* top_proxy =
- root->render_manager()->GetRenderFrameProxyHost(site_instance);
- if (top_proxy) {
- base::debug::SetCrashKeyValue(
- "initrf_root_proxy_is_live",
- top_proxy->is_render_frame_proxy_live() ? "yes" : "no");
- }
- }
-
- base::debug::DumpWithoutCrashing();
- }
- }
-
return delegate_->CreateRenderFrameForRenderManager(
render_frame_host, proxy_routing_id, opener_routing_id, parent_routing_id,
previous_sibling_routing_id);
@@ -2297,10 +2234,8 @@ void RenderFrameHostManager::CommitPending() {
// Note: We do this after swapping out the old RFH because that may create
// the proxy we're looking for.
RenderFrameProxyHost* proxy_to_parent = GetProxyToParent();
- if (proxy_to_parent) {
- CHECK(SiteIsolationPolicy::AreCrossProcessFramesPossible());
+ if (proxy_to_parent)
proxy_to_parent->SetChildRWHView(render_frame_host_->GetView());
- }
// After all is done, there must never be a proxy in the list which has the
// same SiteInstance as the current RenderFrameHost.
@@ -2670,41 +2605,13 @@ void RenderFrameHostManager::CreateOpenerProxiesForFrameTree(
return;
FrameTree* frame_tree = frame_tree_node_->frame_tree();
- if (SiteIsolationPolicy::AreCrossProcessFramesPossible()) {
- // Ensure that all the nodes in the opener's FrameTree have
- // RenderFrameProxyHosts for the new SiteInstance. Only pass the node to
- // be skipped if it's in the same FrameTree.
- if (skip_this_node && skip_this_node->frame_tree() != frame_tree)
- skip_this_node = nullptr;
- frame_tree->CreateProxiesForSiteInstance(skip_this_node, instance);
- } else {
- // If any of the RenderViewHosts (current, pending, or swapped out) for this
- // FrameTree has the same SiteInstance, then we can return early and reuse
- // them. An exception is if we find a pending RenderViewHost: in this case,
- // we should still create a proxy, which will allow communicating with the
- // opener until the pending RenderView commits, or if the pending navigation
- // is canceled.
- // PlzNavigate: similarly, if a speculative RenderViewHost is present, a
- // proxy should be created.
- RenderViewHostImpl* rvh = frame_tree->GetRenderViewHost(instance);
- bool need_proxy_for_pending_rvh = (rvh == pending_render_view_host());
- bool need_proxy_for_speculative_rvh =
- IsBrowserSideNavigationEnabled() && speculative_render_frame_host_ &&
- speculative_render_frame_host_->GetRenderViewHost() == rvh;
- if (rvh && rvh->IsRenderViewLive() && !need_proxy_for_pending_rvh &&
- !need_proxy_for_speculative_rvh) {
- return;
- }
- if (rvh && !rvh->IsRenderViewLive()) {
- EnsureRenderViewInitialized(rvh, instance);
- } else {
- // Create a RenderFrameProxyHost in the given SiteInstance if none
- // exists. Since an opener can point to a subframe, do this on the root
- // frame of the current opener's frame tree.
- frame_tree->root()->render_manager()->CreateRenderFrameProxy(instance);
- }
- }
+ // Ensure that all the nodes in the opener's FrameTree have
+ // RenderFrameProxyHosts for the new SiteInstance. Only pass the node to
+ // be skipped if it's in the same FrameTree.
+ if (skip_this_node && skip_this_node->frame_tree() != frame_tree)
+ skip_this_node = nullptr;
+ frame_tree->CreateProxiesForSiteInstance(skip_this_node, instance);
}
int RenderFrameHostManager::GetOpenerRoutingID(SiteInstance* instance) {
@@ -2781,11 +2688,6 @@ bool RenderFrameHostManager::CanSubframeSwapProcess(
// history navigations. The two cannot be set simultaneously.
DCHECK(!source_instance || !dest_instance);
- // Don't swap for subframes unless we are in an OOPIF-enabled mode. We can
- // get here in tests for subframes (e.g., NavigateFrameToURL).
- if (!SiteIsolationPolicy::AreCrossProcessFramesPossible())
- return false;
-
// 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;
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 de2720501b1..b05e9aa9b5d 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
@@ -1709,16 +1709,15 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
}
// Test for crbug.com/143155. Frame tree updates during unload should not
-// interrupt the intended navigation and show swappedout:// instead.
+// interrupt the intended navigation.
// Specifically:
// 1) Open 2 tabs in an HTTP SiteInstance, with a subframe in the opener.
// 2) Send the second tab to a different foo.com SiteInstance.
-// This creates a swapped out opener for the first tab in the foo process.
+// This created a swapped out opener for the first tab in the foo process.
// 3) Navigate the first tab to the foo.com SiteInstance, and have the first
// tab's unload handler remove its frame.
-// This used to cause an update to the frame tree of the swapped out RV,
-// just as it was navigating to a real page. That pre-empted the real
-// navigation and visibly sent the tab to swappedout://.
+// In older versions of Chrome, this caused an update to the frame tree that
+// resulted in showing an internal page rather than the real page.
IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
DontPreemptNavigationWithFrameTreeUpdate) {
StartEmbeddedServer();
@@ -1884,18 +1883,10 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
EXPECT_TRUE(shell()->web_contents()->GetController().CanGoForward());
}
-// The test fails with Android ASAN with changes in v8 that seem unrelated.
-// See http://crbug.com/428329.
-#if defined(OS_ANDROID) && defined(THREAD_SANITIZER)
-#define MAYBE_ClearPendingWebUIOnCommit DISABLED_ClearPendingWebUIOnCommit
-#else
-#define MAYBE_ClearPendingWebUIOnCommit ClearPendingWebUIOnCommit
-#endif
// Ensure that pending_and_current_web_ui_ is cleared when a URL commits.
// Otherwise it might get picked up by InitRenderView when granting bindings
// to other RenderViewHosts. See http://crbug.com/330811.
-IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
- MAYBE_ClearPendingWebUIOnCommit) {
+IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, ClearPendingWebUIOnCommit) {
// Visit a WebUI page with bindings.
GURL webui_url(GURL(std::string(kChromeUIScheme) + "://" +
std::string(kChromeUIGpuHost)));
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 1434b848f80..c56b8a10570 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
@@ -46,6 +46,7 @@
#include "content/public/common/url_utils.h"
#include "content/public/test/browser_side_navigation_test_utils.h"
#include "content/public/test/mock_render_process_host.h"
+#include "content/public/test/navigation_simulator.h"
#include "content/public/test/test_notification_tracker.h"
#include "content/public/test/test_utils.h"
#include "content/test/test_content_browser_client.h"
@@ -1752,10 +1753,10 @@ TEST_F(RenderFrameHostManagerTest, DeleteFrameAfterSwapOutACK) {
EXPECT_TRUE(rfh1->is_active());
// Navigate to new site, simulating onbeforeunload approval.
- controller().LoadURL(
- kUrl2, Referrer(), ui::PAGE_TRANSITION_LINK, std::string());
+ auto navigation =
+ NavigationSimulator::CreateBrowserInitiated(kUrl2, contents());
+ navigation->ReadyToCommit();
int entry_id = controller().GetPendingEntry()->GetUniqueID();
- contents()->GetMainFrame()->PrepareForCommit();
EXPECT_TRUE(contents()->CrossProcessNavigationPending());
EXPECT_TRUE(rfh1->is_active());
TestRenderFrameHost* rfh2 = contents()->GetPendingMainFrame();
@@ -1800,10 +1801,10 @@ TEST_F(RenderFrameHostManagerTest, SwapOutFrameAfterSwapOutACK) {
rfh1->GetSiteInstance()->IncrementActiveFrameCount();
// Navigate to new site, simulating onbeforeunload approval.
- controller().LoadURL(
- kUrl2, Referrer(), ui::PAGE_TRANSITION_LINK, std::string());
+ auto navigation =
+ NavigationSimulator::CreateBrowserInitiated(kUrl2, contents());
+ navigation->ReadyToCommit();
int entry_id = controller().GetPendingEntry()->GetUniqueID();
- contents()->GetMainFrame()->PrepareForCommit();
EXPECT_TRUE(contents()->CrossProcessNavigationPending());
EXPECT_TRUE(rfh1->is_active());
TestRenderFrameHost* rfh2 = contents()->GetPendingMainFrame();
@@ -1845,11 +1846,12 @@ TEST_F(RenderFrameHostManagerTest,
site_instance->IncrementActiveFrameCount();
// Navigate to new site, simulating onbeforeunload approval.
- controller().LoadURL(
- kUrl2, Referrer(), ui::PAGE_TRANSITION_LINK, std::string());
+ auto navigation =
+ NavigationSimulator::CreateBrowserInitiated(kUrl2, contents());
+ navigation->ReadyToCommit();
int entry_id = controller().GetPendingEntry()->GetUniqueID();
- rfh1->PrepareForCommit();
EXPECT_TRUE(contents()->CrossProcessNavigationPending());
+ EXPECT_TRUE(rfh1->is_active());
TestRenderFrameHost* rfh2 = contents()->GetPendingMainFrame();
// The new page commits.
@@ -3115,7 +3117,9 @@ TEST_F(RenderFrameHostManagerTestWithBrowserSideNavigation,
// should be pending delete.
RenderFrameHostManager* manager =
main_test_rfh()->frame_tree_node()->render_manager();
- contents()->StartNavigation(kUrl2);
+ auto navigation_to_kUrl2 =
+ NavigationSimulator::CreateBrowserInitiated(kUrl2, contents());
+ navigation_to_kUrl2->ReadyToCommit();
static_cast<TestRenderFrameHost*>(manager->speculative_frame_host())
->SimulateNavigationCommit(kUrl2);
EXPECT_NE(initial_rfh, main_test_rfh());
@@ -3124,7 +3128,9 @@ TEST_F(RenderFrameHostManagerTestWithBrowserSideNavigation,
// The initial RFH receives a BeginNavigation IPC. The navigation should not
// start.
- initial_rfh->SendRendererInitiatedNavigationRequest(kUrl3, true);
+ auto navigation_to_kUrl3 =
+ NavigationSimulator::CreateRendererInitiated(kUrl3, initial_rfh);
+ navigation_to_kUrl3->Start();
EXPECT_FALSE(main_test_rfh()->frame_tree_node()->navigation_request());
}
@@ -3153,7 +3159,9 @@ TEST_F(RenderFrameHostManagerTest,
// should be pending delete.
RenderFrameHostManager* manager =
main_test_rfh()->frame_tree_node()->render_manager();
- contents()->StartNavigation(kUrl2);
+ auto navigation =
+ NavigationSimulator::CreateBrowserInitiated(kUrl2, contents());
+ navigation->ReadyToCommit();
static_cast<TestRenderFrameHost*>(manager->pending_frame_host())
->SimulateNavigationCommit(kUrl2);
EXPECT_NE(initial_rfh, main_test_rfh());
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 9b9cfbdc53c..c440d8061da 100644
--- a/chromium/content/browser/frame_host/render_frame_message_filter.cc
+++ b/chromium/content/browser/frame_host/render_frame_message_filter.cc
@@ -25,7 +25,9 @@
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/download_manager.h"
#include "content/public/browser/download_url_parameters.h"
+#include "content/public/browser/storage_partition.h"
#include "content/public/common/content_constants.h"
+#include "content/public/common/content_features.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "net/cookies/cookie_options.h"
@@ -173,11 +175,8 @@ class RenderFrameMessageFilter::OpenChannelToPpapiPluginCallback
public PpapiPluginProcessHost::PluginClient {
public:
OpenChannelToPpapiPluginCallback(RenderFrameMessageFilter* filter,
- ResourceContext* context,
IPC::Message* reply_msg)
- : RenderMessageCompletionCallback(filter, reply_msg),
- context_(context) {
- }
+ : RenderMessageCompletionCallback(filter, reply_msg) {}
void GetPpapiChannelInfo(base::ProcessHandle* renderer_handle,
int* renderer_id) override {
@@ -197,11 +196,6 @@ class RenderFrameMessageFilter::OpenChannelToPpapiPluginCallback
}
bool Incognito() override { return filter()->incognito_; }
-
- ResourceContext* GetResourceContext() override { return context_; }
-
- private:
- ResourceContext* context_;
};
#endif // ENABLE_PLUGINS
@@ -223,6 +217,20 @@ RenderFrameMessageFilter::RenderFrameMessageFilter(
render_widget_helper_(render_widget_helper),
incognito_(browser_context->IsOffTheRecord()),
render_process_id_(render_process_id) {
+ mojom::CookieManagerPtr cookie_manager;
+ BrowserContext::GetDefaultStoragePartition(browser_context)
+ ->GetNetworkContext()
+ ->GetCookieManager(mojo::MakeRequest(&cookie_manager));
+
+ // The PostTask below could finish before the constructor returns which would
+ // lead to this object being destructed prematurely.
+ AddRef();
+ base::ThreadTaskRunnerHandle::Get()->ReleaseSoon(FROM_HERE, this);
+
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&RenderFrameMessageFilter::InitializeOnIO, this,
+ cookie_manager.PassInterface()));
}
RenderFrameMessageFilter::~RenderFrameMessageFilter() {
@@ -230,6 +238,11 @@ RenderFrameMessageFilter::~RenderFrameMessageFilter() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
}
+void RenderFrameMessageFilter::InitializeOnIO(
+ mojom::CookieManagerPtrInfo cookie_manager) {
+ cookie_manager_.Bind(std::move(cookie_manager));
+}
+
bool RenderFrameMessageFilter::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(RenderFrameMessageFilter, message)
@@ -291,7 +304,7 @@ void RenderFrameMessageFilter::DownloadUrl(int render_view_id,
destination: WEBSITE
}
policy {
- cookies_allowed: true
+ cookies_allowed: YES
cookies_store: "user"
setting: "This feature cannot be disabled by settings."
chrome_policy {
@@ -320,7 +333,7 @@ void RenderFrameMessageFilter::DownloadUrl(int render_view_id,
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&DownloadUrlOnUIThread, base::Passed(&parameters)));
+ base::BindOnce(&DownloadUrlOnUIThread, base::Passed(&parameters)));
}
void RenderFrameMessageFilter::OnCreateChildFrame(
@@ -329,39 +342,37 @@ void RenderFrameMessageFilter::OnCreateChildFrame(
*new_routing_id = render_widget_helper_->GetNextRoutingID();
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&CreateChildFrameOnUI, render_process_id_,
- params.parent_routing_id, params.scope, params.frame_name,
- params.frame_unique_name, params.sandbox_flags,
- params.container_policy, params.frame_owner_properties,
- *new_routing_id));
+ base::BindOnce(&CreateChildFrameOnUI, render_process_id_,
+ params.parent_routing_id, params.scope, params.frame_name,
+ params.frame_unique_name, params.sandbox_flags,
+ params.container_policy, params.frame_owner_properties,
+ *new_routing_id));
}
-void RenderFrameMessageFilter::OnCookiesEnabled(
- int render_frame_id,
- const GURL& url,
- const GURL& first_party_for_cookies,
- bool* cookies_enabled) {
+void RenderFrameMessageFilter::OnCookiesEnabled(int render_frame_id,
+ const GURL& url,
+ const GURL& site_for_cookies,
+ bool* cookies_enabled) {
// TODO(ananta): If this render frame is associated with an automation
// channel, aka ChromeFrame then we need to retrieve cookie settings from the
// external host.
*cookies_enabled = GetContentClient()->browser()->AllowGetCookie(
- url, first_party_for_cookies, net::CookieList(), resource_context_,
+ url, site_for_cookies, net::CookieList(), resource_context_,
render_process_id_, render_frame_id);
}
void RenderFrameMessageFilter::CheckPolicyForCookies(
int render_frame_id,
const GURL& url,
- const GURL& first_party_for_cookies,
+ 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, first_party_for_cookies, cookie_list, resource_context_,
- render_process_id_, render_frame_id)) {
+ if (context && GetContentClient()->browser()->AllowGetCookie(
+ url, site_for_cookies, cookie_list, resource_context_,
+ render_process_id_, render_frame_id)) {
std::move(callback).Run(net::CookieStore::BuildCookieLine(cookie_list));
} else {
std::move(callback).Run(std::string());
@@ -410,7 +421,7 @@ void RenderFrameMessageFilter::OnRenderProcessGone() {
void RenderFrameMessageFilter::SetCookie(int32_t render_frame_id,
const GURL& url,
- const GURL& first_party_for_cookies,
+ const GURL& site_for_cookies,
const std::string& cookie) {
ChildProcessSecurityPolicyImpl* policy =
ChildProcessSecurityPolicyImpl::GetInstance();
@@ -421,19 +432,31 @@ void RenderFrameMessageFilter::SetCookie(int32_t render_frame_id,
}
net::CookieOptions options;
- if (GetContentClient()->browser()->AllowSetCookie(
- url, first_party_for_cookies, cookie, resource_context_,
- render_process_id_, render_frame_id, options)) {
- net::URLRequestContext* context = GetRequestContextForURL(url);
- // Pass a null callback since we don't care about when the 'set' completes.
- context->cookie_store()->SetCookieWithOptionsAsync(
- url, cookie, options, net::CookieStore::SetCookiesCallback());
+ if (!GetContentClient()->browser()->AllowSetCookie(
+ url, site_for_cookies, cookie, resource_context_, render_process_id_,
+ render_frame_id, options))
+ return;
+
+ if (base::FeatureList::IsEnabled(features::kNetworkService)) {
+ // TODO: modify GetRequestContextForURL to work with network service.
+ // TODO: merge this with code path below for non-network service.
+ std::unique_ptr<net::CanonicalCookie> cc =
+ net::CanonicalCookie::Create(url, cookie, base::Time::Now(), options);
+ cookie_manager_->SetCanonicalCookie(*cc, url.SchemeIsCryptographic(),
+ !options.exclude_httponly(),
+ net::CookieStore::SetCookiesCallback());
+ return;
}
+
+ net::URLRequestContext* context = GetRequestContextForURL(url);
+ // Pass a null callback since we don't care about when the 'set' completes.
+ context->cookie_store()->SetCookieWithOptionsAsync(
+ url, cookie, options, net::CookieStore::SetCookiesCallback());
}
void RenderFrameMessageFilter::GetCookies(int render_frame_id,
const GURL& url,
- const GURL& first_party_for_cookies,
+ const GURL& site_for_cookies,
GetCookiesCallback callback) {
ChildProcessSecurityPolicyImpl* policy =
ChildProcessSecurityPolicyImpl::GetInstance();
@@ -446,7 +469,7 @@ void RenderFrameMessageFilter::GetCookies(int render_frame_id,
net::CookieOptions options;
if (net::registry_controlled_domains::SameDomainOrHost(
- url, first_party_for_cookies,
+ url, site_for_cookies,
net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES)) {
// TODO(mkwst): This check ought to further distinguish between frames
// initiated in a strict or lax same-site context.
@@ -457,6 +480,17 @@ void RenderFrameMessageFilter::GetCookies(int render_frame_id,
net::CookieOptions::SameSiteCookieMode::DO_NOT_INCLUDE);
}
+ if (base::FeatureList::IsEnabled(features::kNetworkService)) {
+ // TODO: modify GetRequestContextForURL to work with network service.
+ // TODO: merge this with code path below for non-network service.
+ cookie_manager_->GetCookieList(
+ url, options,
+ base::BindOnce(&RenderFrameMessageFilter::CheckPolicyForCookies, this,
+ render_frame_id, url, site_for_cookies,
+ base::Passed(&callback)));
+ return;
+ }
+
// If we crash here, figure out what URL the renderer was requesting.
// http://crbug.com/99242
char url_buf[128];
@@ -466,9 +500,9 @@ void RenderFrameMessageFilter::GetCookies(int render_frame_id,
net::URLRequestContext* context = GetRequestContextForURL(url);
context->cookie_store()->GetCookieListWithOptionsAsync(
url, options,
- base::Bind(&RenderFrameMessageFilter::CheckPolicyForCookies, this,
- render_frame_id, url, first_party_for_cookies,
- base::Passed(&callback)));
+ base::BindOnce(&RenderFrameMessageFilter::CheckPolicyForCookies, this,
+ render_frame_id, url, site_for_cookies,
+ base::Passed(&callback)));
}
#if BUILDFLAG(ENABLE_PLUGINS)
@@ -495,8 +529,8 @@ void RenderFrameMessageFilter::OnGetPlugins(
}
PluginServiceImpl::GetInstance()->GetPlugins(
- base::Bind(&RenderFrameMessageFilter::GetPluginsCallback, this, reply_msg,
- main_frame_origin));
+ base::BindOnce(&RenderFrameMessageFilter::GetPluginsCallback, this,
+ reply_msg, main_frame_origin));
}
void RenderFrameMessageFilter::GetPluginsCallback(
@@ -544,10 +578,8 @@ void RenderFrameMessageFilter::OnOpenChannelToPepperPlugin(
const base::FilePath& path,
IPC::Message* reply_msg) {
plugin_service_->OpenChannelToPpapiPlugin(
- render_process_id_,
- path,
- profile_data_directory_,
- new OpenChannelToPpapiPluginCallback(this, resource_context_, reply_msg));
+ render_process_id_, path, profile_data_directory_,
+ new OpenChannelToPpapiPluginCallback(this, reply_msg));
}
void RenderFrameMessageFilter::OnDidCreateOutOfProcessPepperInstance(
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 3f49cc40b6d..6875eb6496c 100644
--- a/chromium/content/browser/frame_host/render_frame_message_filter.h
+++ b/chromium/content/browser/frame_host/render_frame_message_filter.h
@@ -13,6 +13,7 @@
#include "content/common/render_frame_message_filter.mojom.h"
#include "content/public/browser/browser_associated_interface.h"
#include "content/public/browser/browser_message_filter.h"
+#include "content/public/common/network_service.mojom.h"
#include "content/public/common/three_d_api_types.h"
#include "net/cookies/canonical_cookie.h"
#include "ppapi/features/features.h"
@@ -52,7 +53,7 @@ struct WebPluginInfo;
class CONTENT_EXPORT RenderFrameMessageFilter
: public BrowserMessageFilter,
public BrowserAssociatedInterface<mojom::RenderFrameMessageFilter>,
- public NON_EXPORTED_BASE(mojom::RenderFrameMessageFilter) {
+ public mojom::RenderFrameMessageFilter {
public:
RenderFrameMessageFilter(int render_process_id,
PluginServiceImpl* plugin_service,
@@ -85,17 +86,19 @@ class CONTENT_EXPORT RenderFrameMessageFilter
~RenderFrameMessageFilter() override;
+ void InitializeOnIO(mojom::CookieManagerPtrInfo cookie_manager);
+
void OnCreateChildFrame(const FrameHostMsg_CreateChildFrame_Params& params,
int* new_render_frame_id);
void OnCookiesEnabled(int render_frame_id,
const GURL& url,
- const GURL& first_party_for_cookies,
+ const GURL& site_for_cookies,
bool* cookies_enabled);
// Check the policy for getting cookies. Gets the cookies if allowed.
void CheckPolicyForCookies(int render_frame_id,
const GURL& url,
- const GURL& first_party_for_cookies,
+ const GURL& site_for_cookies,
GetCookiesCallback callback,
const net::CookieList& cookie_list);
@@ -115,11 +118,11 @@ class CONTENT_EXPORT RenderFrameMessageFilter
// mojom::RenderFrameMessageFilter:
void SetCookie(int32_t render_frame_id,
const GURL& url,
- const GURL& first_party_for_cookies,
+ const GURL& site_for_cookies,
const std::string& cookie) override;
void GetCookies(int render_frame_id,
const GURL& url,
- const GURL& first_party_for_cookies,
+ const GURL& site_for_cookies,
GetCookiesCallback callback) override;
#if BUILDFLAG(ENABLE_PLUGINS)
@@ -172,6 +175,8 @@ class CONTENT_EXPORT RenderFrameMessageFilter
// The ResourceContext which is to be used on the IO thread.
ResourceContext* resource_context_;
+ mojom::CookieManagerPtr cookie_manager_;
+
// Needed for issuing routing ids and surface ids.
scoped_refptr<RenderWidgetHelper> render_widget_helper_;
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 45391901e03..aeda6847dd2 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
@@ -205,13 +205,13 @@ IN_PROC_BROWSER_TEST_F(RenderFrameMessageFilterBrowserTest,
// to be killed.
BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)
->PostTask(FROM_HERE,
- base::Bind(
+ base::BindOnce(
[](RenderFrameHost* frame) {
GetFilterForProcess(frame->GetProcess())
- ->GetCookies(frame->GetRoutingID(),
- GURL("http://127.0.0.1/"),
- GURL("http://127.0.0.1/"),
- base::Bind([](const std::string&) {}));
+ ->GetCookies(
+ frame->GetRoutingID(), GURL("http://127.0.0.1/"),
+ GURL("http://127.0.0.1/"),
+ base::BindOnce([](const std::string&) {}));
},
iframe));
@@ -230,13 +230,16 @@ IN_PROC_BROWSER_TEST_F(RenderFrameMessageFilterBrowserTest,
tab->GetMainFrame()->GetProcess(),
RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)->PostTask(
- FROM_HERE,
- base::Bind([] (RenderFrameHost* frame) {
- GetFilterForProcess(frame->GetProcess())->SetCookie(
- frame->GetRoutingID(), GURL("https://baz.com/"),
- GURL("https://baz.com/"), "pwn=ed");
- }, main_frame));
+ BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)
+ ->PostTask(FROM_HERE, base::BindOnce(
+ [](RenderFrameHost* frame) {
+ GetFilterForProcess(frame->GetProcess())
+ ->SetCookie(frame->GetRoutingID(),
+ GURL("https://baz.com/"),
+ GURL("https://baz.com/"),
+ "pwn=ed");
+ },
+ main_frame));
main_frame_killed.Wait();
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 37f820a6090..3bba011e273 100644
--- a/chromium/content/browser/frame_host/render_frame_proxy_host.cc
+++ b/chromium/content/browser/frame_host/render_frame_proxy_host.cc
@@ -14,9 +14,9 @@
#include "content/browser/frame_host/frame_tree_node.h"
#include "content/browser/frame_host/navigator.h"
#include "content/browser/frame_host/render_frame_host_delegate.h"
-#include "content/browser/frame_host/render_widget_host_view_child_frame.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
+#include "content/browser/renderer_host/render_widget_host_view_child_frame.h"
#include "content/browser/site_instance_impl.h"
#include "content/common/frame_messages.h"
#include "content/common/frame_owner_properties.h"
@@ -108,7 +108,7 @@ RenderFrameProxyHost::~RenderFrameProxyHost() {
}
void RenderFrameProxyHost::SetChildRWHView(RenderWidgetHostView* view) {
- cross_process_frame_connector_->set_view(
+ cross_process_frame_connector_->SetView(
static_cast<RenderWidgetHostViewChildFrame*>(view));
}
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 d221c6cf302..a1abce179e5 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
@@ -12,9 +12,9 @@
#include "base/memory/ptr_util.h"
#include "base/message_loop/message_loop.h"
#include "build/build_config.h"
-#include "cc/surfaces/surface.h"
-#include "cc/surfaces/surface_manager.h"
#include "components/viz/common/surfaces/surface_sequence.h"
+#include "components/viz/service/surfaces/surface.h"
+#include "components/viz/service/surfaces/surface_manager.h"
#include "content/browser/browser_plugin/browser_plugin_guest.h"
#include "content/browser/compositor/surface_utils.h"
#include "content/browser/renderer_host/input/input_router.h"
@@ -85,6 +85,11 @@ RenderWidgetHostViewGuest::RenderWidgetHostViewGuest(
guest_(guest ? guest->AsWeakPtr() : base::WeakPtr<BrowserPluginGuest>()),
platform_view_(platform_view),
should_forward_text_selection_(false) {
+ // In tests |guest_| and therefore |owner| can be null.
+ auto* owner = GetOwnerRenderWidgetHostView();
+ if (owner)
+ SetParentFrameSinkId(owner->GetFrameSinkId());
+
gfx::NativeView view = GetNativeView();
if (view)
UpdateScreenInfo(view);
@@ -124,7 +129,7 @@ void RenderWidgetHostViewGuest::Show() {
// Since we were last shown, our renderer may have had a different surface
// set (e.g. showing an interstitial), so we resend our current surface to
// the renderer.
- if (local_surface_id_.is_valid())
+ if (last_received_local_surface_id_.is_valid())
SendSurfaceInfoToEmbedder();
}
host_->WasShown(ui::LatencyInfo());
@@ -259,10 +264,9 @@ base::string16 RenderWidgetHostViewGuest::GetSelectedText() {
return platform_view_->GetSelectedText();
}
-void RenderWidgetHostViewGuest::SetNeedsBeginFrames(
- bool needs_begin_frames) {
- if (platform_view_)
- platform_view_->SetNeedsBeginFrames(needs_begin_frames);
+void RenderWidgetHostViewGuest::SetNeedsBeginFrames(bool needs_begin_frames) {
+ if (platform_view_)
+ platform_view_->SetNeedsBeginFrames(needs_begin_frames);
}
TouchSelectionControllerClientManager*
@@ -357,14 +361,9 @@ void RenderWidgetHostViewGuest::UpdateCursor(const WebCursor& cursor) {
// and so we will always hit this code path.
if (!guest_)
return;
- if (SiteIsolationPolicy::AreCrossProcessFramesPossible()) {
- RenderWidgetHostViewBase* rwhvb = GetOwnerRenderWidgetHostView();
- if (rwhvb)
- rwhvb->UpdateCursor(cursor);
- } else {
- guest_->SendMessageToEmbedder(base::MakeUnique<BrowserPluginMsg_SetCursor>(
- guest_->browser_plugin_instance_id(), cursor));
- }
+ RenderWidgetHostViewBase* rwhvb = GetOwnerRenderWidgetHostView();
+ if (rwhvb)
+ rwhvb->UpdateCursor(cursor);
}
void RenderWidgetHostViewGuest::SetIsLoading(bool is_loading) {
@@ -453,7 +452,7 @@ void RenderWidgetHostViewGuest::UnlockMouse() {
}
void RenderWidgetHostViewGuest::DidCreateNewRendererCompositorFrameSink(
- cc::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink) {
+ viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink) {
RenderWidgetHostViewChildFrame::DidCreateNewRendererCompositorFrameSink(
renderer_compositor_frame_sink);
platform_view_->DidCreateNewRendererCompositorFrameSink(
@@ -653,9 +652,8 @@ void RenderWidgetHostViewGuest::OnHandleInputEvent(
}
if (blink::WebInputEvent::IsKeyboardEventType(event->GetType())) {
- if (!embedder->GetLastKeyboardEvent())
- return;
- NativeWebKeyboardEvent keyboard_event(*embedder->GetLastKeyboardEvent());
+ NativeWebKeyboardEvent keyboard_event(
+ *static_cast<const blink::WebKeyboardEvent*>(event));
host_->ForwardKeyboardEvent(keyboard_event);
return;
}
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 e5361f11a36..072ce96df30 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
@@ -13,7 +13,7 @@
#include "base/macros.h"
#include "build/build_config.h"
-#include "content/browser/frame_host/render_widget_host_view_child_frame.h"
+#include "content/browser/renderer_host/render_widget_host_view_child_frame.h"
#include "content/common/content_export.h"
#include "content/common/cursors/webcursor.h"
#include "third_party/WebKit/public/platform/WebInputEvent.h"
@@ -108,7 +108,7 @@ class CONTENT_EXPORT RenderWidgetHostViewGuest
bool LockMouse() override;
void UnlockMouse() override;
void DidCreateNewRendererCompositorFrameSink(
- cc::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink)
+ viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink)
override;
#if defined(OS_MACOSX)
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 31c5f789f71..32d4746e0ab 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
@@ -13,9 +13,9 @@
#include "base/test/scoped_task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
-#include "cc/surfaces/surface.h"
-#include "cc/surfaces/surface_manager.h"
#include "components/viz/common/surfaces/surface_sequence.h"
+#include "components/viz/service/surfaces/surface.h"
+#include "components/viz/service/surfaces/surface_manager.h"
#include "content/browser/browser_plugin/browser_plugin_guest.h"
#include "content/browser/compositor/test/no_transport_image_transport_factory.h"
#include "content/browser/gpu/compositor_util.h"
@@ -26,7 +26,9 @@
#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"
+#include "content/test/dummy_render_widget_host_delegate.h"
#include "content/test/fake_renderer_compositor_frame_sink.h"
+#include "content/test/mock_widget_impl.h"
#include "content/test/test_render_view_host.h"
#include "content/test/test_web_contents.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -34,21 +36,6 @@
namespace content {
namespace {
-class MockRenderWidgetHostDelegate : public RenderWidgetHostDelegate {
- public:
- MockRenderWidgetHostDelegate() {}
- ~MockRenderWidgetHostDelegate() override {}
-
- private:
- // RenderWidgetHostDelegate:
- void ExecuteEditCommand(
- const std::string& command,
- const base::Optional<base::string16>& value) override {}
- void Cut() override {}
- void Copy() override {}
- void Paste() override {}
- void SelectAll() override {}
-};
class RenderWidgetHostViewGuestTest : public testing::Test {
public:
@@ -66,8 +53,11 @@ class RenderWidgetHostViewGuestTest : public testing::Test {
MockRenderProcessHost* process_host =
new MockRenderProcessHost(browser_context_.get());
int32_t routing_id = process_host->GetNextRoutingID();
- widget_host_ =
- new RenderWidgetHostImpl(&delegate_, process_host, routing_id, false);
+ mojom::WidgetPtr widget;
+ widget_impl_ = base::MakeUnique<MockWidgetImpl>(mojo::MakeRequest(&widget));
+
+ widget_host_ = new RenderWidgetHostImpl(
+ &delegate_, process_host, routing_id, std::move(widget), false);
view_ = RenderWidgetHostViewGuest::Create(
widget_host_, NULL,
(new TestRenderWidgetHostView(widget_host_))->GetWeakPtr());
@@ -93,10 +83,11 @@ class RenderWidgetHostViewGuestTest : public testing::Test {
base::test::ScopedTaskEnvironment scoped_task_environment_;
std::unique_ptr<BrowserContext> browser_context_;
- MockRenderWidgetHostDelegate delegate_;
+ DummyRenderWidgetHostDelegate delegate_;
// Tests should set these to NULL if they've already triggered their
// destruction.
+ std::unique_ptr<MockWidgetImpl> widget_impl_;
RenderWidgetHostImpl* widget_host_;
RenderWidgetHostViewGuest* view_;
@@ -167,15 +158,18 @@ class RenderWidgetHostViewGuestSurfaceTest
web_contents_.get(), &browser_plugin_guest_delegate_);
int32_t routing_id = process_host->GetNextRoutingID();
- widget_host_ =
- new RenderWidgetHostImpl(&delegate_, process_host, routing_id, false);
+ mojom::WidgetPtr widget;
+ widget_impl_ = base::MakeUnique<MockWidgetImpl>(mojo::MakeRequest(&widget));
+
+ widget_host_ = new RenderWidgetHostImpl(
+ &delegate_, process_host, routing_id, std::move(widget), false);
view_ = RenderWidgetHostViewGuest::Create(
widget_host_, browser_plugin_guest_,
(new TestRenderWidgetHostView(widget_host_))->GetWeakPtr());
- cc::mojom::CompositorFrameSinkPtr sink;
- cc::mojom::CompositorFrameSinkRequest sink_request =
+ viz::mojom::CompositorFrameSinkPtr sink;
+ viz::mojom::CompositorFrameSinkRequest sink_request =
mojo::MakeRequest(&sink);
- cc::mojom::CompositorFrameSinkClientRequest client_request =
+ viz::mojom::CompositorFrameSinkClientRequest client_request =
mojo::MakeRequest(&renderer_compositor_frame_sink_ptr_);
renderer_compositor_frame_sink_ =
base::MakeUnique<FakeRendererCompositorFrameSink>(
@@ -202,28 +196,30 @@ class RenderWidgetHostViewGuestSurfaceTest
DCHECK(view_);
RenderWidgetHostViewChildFrame* rwhvcf =
static_cast<RenderWidgetHostViewChildFrame*>(view_);
- if (!rwhvcf->local_surface_id_.is_valid())
+ if (!rwhvcf->last_received_local_surface_id_.is_valid())
return viz::SurfaceId();
- return viz::SurfaceId(rwhvcf->frame_sink_id_, rwhvcf->local_surface_id_);
+ return viz::SurfaceId(rwhvcf->frame_sink_id_,
+ rwhvcf->last_received_local_surface_id_);
}
protected:
TestBrowserThreadBundle thread_bundle_;
std::unique_ptr<BrowserContext> browser_context_;
- MockRenderWidgetHostDelegate delegate_;
+ DummyRenderWidgetHostDelegate delegate_;
BrowserPluginGuestDelegate browser_plugin_guest_delegate_;
std::unique_ptr<TestWebContents> web_contents_;
TestBrowserPluginGuest* browser_plugin_guest_;
// Tests should set these to NULL if they've already triggered their
// destruction.
+ std::unique_ptr<MockWidgetImpl> widget_impl_;
RenderWidgetHostImpl* widget_host_;
RenderWidgetHostViewGuest* view_;
std::unique_ptr<FakeRendererCompositorFrameSink>
renderer_compositor_frame_sink_;
private:
- cc::mojom::CompositorFrameSinkClientPtr renderer_compositor_frame_sink_ptr_;
+ viz::mojom::CompositorFrameSinkClientPtr renderer_compositor_frame_sink_ptr_;
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewGuestSurfaceTest);
};
@@ -233,7 +229,7 @@ cc::CompositorFrame CreateDelegatedFrame(float scale_factor,
const gfx::Rect& damage) {
cc::CompositorFrame frame;
frame.metadata.device_scale_factor = scale_factor;
- frame.metadata.begin_frame_ack = cc::BeginFrameAck(0, 1, true);
+ frame.metadata.begin_frame_ack = viz::BeginFrameAck(0, 1, true);
std::unique_ptr<cc::RenderPass> pass = cc::RenderPass::Create();
pass->SetNew(1, gfx::Rect(size), damage, gfx::Transform());
@@ -263,14 +259,12 @@ TEST_F(RenderWidgetHostViewGuestSurfaceTest, TestGuestSurface) {
EXPECT_TRUE(id.is_valid());
#if !defined(OS_ANDROID)
- cc::SurfaceManager* manager = ImageTransportFactory::GetInstance()
- ->GetContextFactoryPrivate()
- ->GetFrameSinkManager()
- ->surface_manager();
- cc::Surface* surface = manager->GetSurfaceForId(id);
+ viz::SurfaceManager* manager = ImageTransportFactory::GetInstance()
+ ->GetContextFactoryPrivate()
+ ->GetFrameSinkManager()
+ ->surface_manager();
+ viz::Surface* surface = manager->GetSurfaceForId(id);
EXPECT_TRUE(surface);
- // There should be a SurfaceSequence created by the RWHVGuest.
- EXPECT_EQ(1u, surface->GetDestructionDependencyCount());
#endif
// Surface ID should have been passed to BrowserPluginGuest to
// be sent to the embedding renderer.
@@ -291,9 +285,6 @@ TEST_F(RenderWidgetHostViewGuestSurfaceTest, TestGuestSurface) {
#if !defined(OS_ANDROID)
surface = manager->GetSurfaceForId(id);
EXPECT_TRUE(surface);
- // Another SurfaceSequence should be created by the RWHVGuest when sending
- // SurfaceInfo to the embedder.
- EXPECT_EQ(2u, surface->GetDestructionDependencyCount());
#endif
// Surface ID should have been passed to BrowserPluginGuest to
// be sent to the embedding renderer.
diff --git a/chromium/content/browser/generic_sensor/OWNERS b/chromium/content/browser/generic_sensor/OWNERS
new file mode 100644
index 00000000000..b6de9b3bb5c
--- /dev/null
+++ b/chromium/content/browser/generic_sensor/OWNERS
@@ -0,0 +1,4 @@
+file://services/device/generic_sensor/OWNERS
+
+# COMPONENT: Blink>Sensor
+# TEAM: device-dev@chromium.org
diff --git a/chromium/content/browser/generic_sensor/sensor_provider_proxy_impl.cc b/chromium/content/browser/generic_sensor/sensor_provider_proxy_impl.cc
new file mode 100644
index 00000000000..58acf1ee514
--- /dev/null
+++ b/chromium/content/browser/generic_sensor/sensor_provider_proxy_impl.cc
@@ -0,0 +1,76 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/generic_sensor/sensor_provider_proxy_impl.h"
+
+#include <utility>
+
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/permission_manager.h"
+#include "content/public/browser/permission_type.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 "mojo/public/cpp/bindings/strong_binding.h"
+#include "services/device/public/interfaces/constants.mojom.h"
+#include "services/service_manager/public/cpp/connector.h"
+
+namespace content {
+
+SensorProviderProxyImpl::SensorProviderProxyImpl(
+ PermissionManager* permission_manager,
+ RenderFrameHost* render_frame_host)
+ : permission_manager_(permission_manager),
+ render_frame_host_(render_frame_host) {
+ DCHECK(permission_manager);
+ DCHECK(render_frame_host);
+}
+
+SensorProviderProxyImpl::~SensorProviderProxyImpl() = default;
+
+void SensorProviderProxyImpl::Bind(
+ device::mojom::SensorProviderRequest request) {
+ binding_set_.AddBinding(this, std::move(request));
+}
+
+void SensorProviderProxyImpl::GetSensor(
+ device::mojom::SensorType type,
+ device::mojom::SensorRequest sensor_request,
+ GetSensorCallback callback) {
+ ServiceManagerConnection* connection =
+ ServiceManagerConnection::GetForProcess();
+
+ if (!connection || !CheckPermission(type)) {
+ std::move(callback).Run(nullptr, nullptr);
+ return;
+ }
+
+ if (!sensor_provider_) {
+ connection->GetConnector()->BindInterface(
+ device::mojom::kServiceName, mojo::MakeRequest(&sensor_provider_));
+ sensor_provider_.set_connection_error_handler(
+ base::BindOnce(&device::mojom::SensorProviderPtr::reset,
+ base::Unretained(&sensor_provider_)));
+ }
+ sensor_provider_->GetSensor(type, std::move(sensor_request),
+ std::move(callback));
+}
+
+bool SensorProviderProxyImpl::CheckPermission(
+ device::mojom::SensorType type) const {
+ content::WebContents* web_contents =
+ content::WebContents::FromRenderFrameHost(render_frame_host_);
+ if (!web_contents)
+ return false;
+
+ const GURL& embedding_origin = web_contents->GetLastCommittedURL();
+ const GURL& requesting_origin = render_frame_host_->GetLastCommittedURL();
+
+ blink::mojom::PermissionStatus permission_status =
+ permission_manager_->GetPermissionStatus(
+ PermissionType::SENSORS, requesting_origin, embedding_origin);
+ return permission_status == blink::mojom::PermissionStatus::GRANTED;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/generic_sensor/sensor_provider_proxy_impl.h b/chromium/content/browser/generic_sensor/sensor_provider_proxy_impl.h
new file mode 100644
index 00000000000..993e8d0b138
--- /dev/null
+++ b/chromium/content/browser/generic_sensor/sensor_provider_proxy_impl.h
@@ -0,0 +1,46 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_GENERIC_SENSOR_SENSOR_PROVIDER_PROXY_IMPL_H_
+#define CONTENT_BROWSER_GENERIC_SENSOR_SENSOR_PROVIDER_PROXY_IMPL_H_
+
+#include "content/public/browser/web_contents_observer.h"
+#include "mojo/public/cpp/bindings/binding_set.h"
+#include "services/device/public/interfaces/sensor_provider.mojom.h"
+
+namespace content {
+
+class PermissionManager;
+class RenderFrameHost;
+
+// This proxy acts as a gatekeeper to the real sensor provider so that this
+// proxy can intercept sensor requests and allow or deny them based on
+// the permission statuses retrieved from a permission manager.
+class SensorProviderProxyImpl final : public device::mojom::SensorProvider {
+ public:
+ SensorProviderProxyImpl(PermissionManager* permission_manager,
+ RenderFrameHost* render_frame_host);
+ ~SensorProviderProxyImpl() override;
+
+ void Bind(device::mojom::SensorProviderRequest request);
+
+ private:
+ // SensorProvider implementation.
+ void GetSensor(device::mojom::SensorType type,
+ device::mojom::SensorRequest sensor_request,
+ GetSensorCallback callback) override;
+
+ bool CheckPermission(device::mojom::SensorType type) const;
+
+ mojo::BindingSet<device::mojom::SensorProvider> binding_set_;
+ PermissionManager* permission_manager_;
+ RenderFrameHost* render_frame_host_;
+ device::mojom::SensorProviderPtr sensor_provider_;
+
+ DISALLOW_COPY_AND_ASSIGN(SensorProviderProxyImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_GENERIC_SENSOR_SENSOR_PROVIDER_PROXY_IMPL_H_
diff --git a/chromium/content/browser/generic_sensor_browsertest.cc b/chromium/content/browser/generic_sensor_browsertest.cc
index b2e46c16146..e28b4911468 100644
--- a/chromium/content/browser/generic_sensor_browsertest.cc
+++ b/chromium/content/browser/generic_sensor_browsertest.cc
@@ -23,6 +23,7 @@
#include "mojo/public/cpp/system/buffer.h"
#include "services/device/public/cpp/generic_sensor/platform_sensor_configuration.h"
#include "services/device/public/cpp/generic_sensor/sensor_reading.h"
+#include "services/device/public/cpp/generic_sensor/sensor_traits.h"
#include "services/device/public/interfaces/constants.mojom.h"
#include "services/device/public/interfaces/sensor.mojom.h"
#include "services/device/public/interfaces/sensor_provider.mojom.h"
@@ -56,24 +57,26 @@ class FakeAmbientLightSensor : public device::mojom::Sensor {
}
void RemoveConfiguration(
- const device::PlatformSensorConfiguration& configuration,
- RemoveConfigurationCallback callback) override {
- std::move(callback).Run(true);
- }
+ const device::PlatformSensorConfiguration& configuration) override {}
void Suspend() override {}
void Resume() override {}
void ConfigureReadingChangeNotifications(bool enabled) override {}
device::PlatformSensorConfiguration GetDefaultConfiguration() {
- return device::PlatformSensorConfiguration(60 /* frequency */);
+ return device::PlatformSensorConfiguration(
+ device::SensorTraits<
+ device::mojom::SensorType::AMBIENT_LIGHT>::kDefaultFrequency);
}
device::mojom::ReportingMode GetReportingMode() {
return device::mojom::ReportingMode::ON_CHANGE;
}
- double GetMaximumSupportedFrequency() { return 60.0; }
+ double GetMaximumSupportedFrequency() {
+ return device::SensorTraits<
+ device::mojom::SensorType::AMBIENT_LIGHT>::kMaxAllowedFrequency;
+ }
double GetMinimumSupportedFrequency() { return 1.0; }
device::mojom::SensorClientRequest GetClient() {
@@ -100,9 +103,9 @@ class FakeAmbientLightSensor : public device::mojom::Sensor {
GetBufferOffset());
device::SensorReading reading;
- reading.timestamp =
+ reading.als.timestamp =
(base::TimeTicks::Now() - base::TimeTicks()).InSecondsF();
- reading.values[0] = 50;
+ reading.als.value = 50;
device::SensorReadingSharedBuffer* buffer =
static_cast<device::SensorReadingSharedBuffer*>(shared_buffer.get());
@@ -171,15 +174,16 @@ class GenericSensorBrowserTest : public ContentBrowserTest {
base::WaitableEvent::ResetPolicy::AUTOMATIC,
base::WaitableEvent::InitialState::NOT_SIGNALED) {
base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
- cmd_line->AppendSwitchASCII(switches::kEnableFeatures, "GenericSensor");
+ cmd_line->AppendSwitchASCII(switches::kEnableFeatures,
+ "GenericSensor, GenericSensorExtraClasses");
}
void SetUpOnMainThread() override {
fake_sensor_provider_ = base::MakeUnique<FakeSensorProvider>();
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&GenericSensorBrowserTest::SetBinderOnIOThread,
- base::Unretained(this)));
+ base::BindOnce(&GenericSensorBrowserTest::SetBinderOnIOThread,
+ base::Unretained(this)));
io_loop_finished_event_.Wait();
}
diff --git a/chromium/content/browser/geolocation/geolocation_service_impl.cc b/chromium/content/browser/geolocation/geolocation_service_impl.cc
new file mode 100644
index 00000000000..7df7dbf4ad1
--- /dev/null
+++ b/chromium/content/browser/geolocation/geolocation_service_impl.cc
@@ -0,0 +1,108 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/geolocation/geolocation_service_impl.h"
+
+#include "content/public/browser/permission_manager.h"
+#include "content/public/browser/permission_type.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/common/content_features.h"
+#include "device/geolocation/geolocation_context.h"
+#include "third_party/WebKit/public/platform/WebFeaturePolicyFeature.h"
+
+namespace content {
+
+GeolocationServiceImplContext::GeolocationServiceImplContext(
+ PermissionManager* permission_manager)
+ : permission_manager_(permission_manager),
+ request_id_(PermissionManager::kNoPendingOperation) {}
+
+GeolocationServiceImplContext::~GeolocationServiceImplContext() {
+ if (request_id_ == PermissionManager::kNoPendingOperation)
+ return;
+
+ CancelPermissionRequest();
+}
+
+void GeolocationServiceImplContext::RequestPermission(
+ RenderFrameHost* render_frame_host,
+ bool user_gesture,
+ const base::Callback<void(blink::mojom::PermissionStatus)>& callback) {
+ request_id_ = permission_manager_->RequestPermission(
+ PermissionType::GEOLOCATION, render_frame_host,
+ render_frame_host->GetLastCommittedURL().GetOrigin(), user_gesture,
+ // NOTE: The permission request is canceled in the destructor, so it is
+ // safe to pass |this| as Unretained.
+ base::Bind(&GeolocationServiceImplContext::HandlePermissionStatus,
+ base::Unretained(this), std::move(callback)));
+}
+
+void GeolocationServiceImplContext::CancelPermissionRequest() {
+ if (request_id_ == PermissionManager::kNoPendingOperation) {
+ mojo::ReportBadMessage(
+ "GeolocationService client may only create one Geolocation at a "
+ "time.");
+ return;
+ }
+
+ permission_manager_->CancelPermissionRequest(request_id_);
+ request_id_ = PermissionManager::kNoPendingOperation;
+}
+
+void GeolocationServiceImplContext::HandlePermissionStatus(
+ const base::Callback<void(blink::mojom::PermissionStatus)>& callback,
+ blink::mojom::PermissionStatus permission_status) {
+ request_id_ = PermissionManager::kNoPendingOperation;
+ callback.Run(permission_status);
+}
+
+GeolocationServiceImpl::GeolocationServiceImpl(
+ device::GeolocationContext* geolocation_context,
+ PermissionManager* permission_manager,
+ RenderFrameHost* render_frame_host)
+ : geolocation_context_(geolocation_context),
+ permission_manager_(permission_manager),
+ render_frame_host_(render_frame_host) {
+ DCHECK(geolocation_context);
+ DCHECK(permission_manager);
+ DCHECK(render_frame_host);
+}
+
+GeolocationServiceImpl::~GeolocationServiceImpl() {}
+
+void GeolocationServiceImpl::Bind(
+ device::mojom::GeolocationServiceRequest request) {
+ binding_set_.AddBinding(
+ this, std::move(request),
+ base::MakeUnique<GeolocationServiceImplContext>(permission_manager_));
+}
+
+void GeolocationServiceImpl::CreateGeolocation(
+ mojo::InterfaceRequest<device::mojom::Geolocation> request,
+ bool user_gesture) {
+ if (base::FeatureList::IsEnabled(features::kFeaturePolicy) &&
+ base::FeatureList::IsEnabled(features::kUseFeaturePolicyForPermissions) &&
+ !render_frame_host_->IsFeatureEnabled(
+ blink::WebFeaturePolicyFeature::kGeolocation)) {
+ return;
+ }
+
+ binding_set_.dispatch_context()->RequestPermission(
+ render_frame_host_, user_gesture,
+ // NOTE: The request is canceled by the destructor of the
+ // dispatch_context, so it is safe to bind |this| as Unretained.
+ base::Bind(&GeolocationServiceImpl::CreateGeolocationWithPermissionStatus,
+ base::Unretained(this), base::Passed(&request)));
+}
+
+void GeolocationServiceImpl::CreateGeolocationWithPermissionStatus(
+ device::mojom::GeolocationRequest request,
+ blink::mojom::PermissionStatus permission_status) {
+ if (permission_status != blink::mojom::PermissionStatus::GRANTED)
+ return;
+
+ geolocation_context_->Bind(std::move(request));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/geolocation/geolocation_service_impl.h b/chromium/content/browser/geolocation/geolocation_service_impl.h
new file mode 100644
index 00000000000..e8af52b9ade
--- /dev/null
+++ b/chromium/content/browser/geolocation/geolocation_service_impl.h
@@ -0,0 +1,85 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_GEOLOCATION_GEOLOCATION_SERVICE_IMPL_H_
+#define CONTENT_BROWSER_GEOLOCATION_GEOLOCATION_SERVICE_IMPL_H_
+
+#include "content/common/content_export.h"
+#include "device/geolocation/public/interfaces/geolocation.mojom.h"
+#include "mojo/public/cpp/bindings/binding_set.h"
+
+namespace blink {
+namespace mojom {
+enum class PermissionStatus;
+}
+} // namespace blink
+
+namespace device {
+class GeolocationContext;
+}
+
+namespace content {
+class RenderFrameHost;
+class PermissionManager;
+
+class GeolocationServiceImplContext {
+ public:
+ GeolocationServiceImplContext(PermissionManager* permission_manager_);
+ ~GeolocationServiceImplContext();
+ void RequestPermission(
+ RenderFrameHost* render_frame_host,
+ bool user_gesture,
+ const base::Callback<void(blink::mojom::PermissionStatus)>& callback);
+ void CancelPermissionRequest();
+
+ private:
+ PermissionManager* permission_manager_;
+ int request_id_;
+
+ void HandlePermissionStatus(
+ const base::Callback<void(blink::mojom::PermissionStatus)>& callback,
+ blink::mojom::PermissionStatus permission_status);
+ DISALLOW_COPY_AND_ASSIGN(GeolocationServiceImplContext);
+};
+
+class CONTENT_EXPORT GeolocationServiceImpl
+ : public device::mojom::GeolocationService {
+ public:
+ GeolocationServiceImpl(device::GeolocationContext* geolocation_context,
+ PermissionManager* permission_manager,
+ RenderFrameHost* render_frame_host);
+ ~GeolocationServiceImpl() override;
+
+ // Binds to the GeolocationService.
+ void Bind(device::mojom::GeolocationServiceRequest request);
+
+ // Creates a Geolocation instance.
+ // This may not be called a second time until the Geolocation instance has
+ // been created.
+ void CreateGeolocation(device::mojom::GeolocationRequest request,
+ bool user_gesture) override;
+
+ private:
+ // Creates the Geolocation Service.
+ void CreateGeolocationWithPermissionStatus(
+ device::mojom::GeolocationRequest request,
+ blink::mojom::PermissionStatus permission_status);
+
+ device::GeolocationContext* geolocation_context_;
+ PermissionManager* permission_manager_;
+ RenderFrameHost* render_frame_host_;
+
+ // Along with each GeolocationService, we store a
+ // GeolocationServiceImplContext which primarily exists to manage a
+ // Permission Request ID.
+ mojo::BindingSet<device::mojom::GeolocationService,
+ std::unique_ptr<GeolocationServiceImplContext>>
+ binding_set_;
+
+ DISALLOW_COPY_AND_ASSIGN(GeolocationServiceImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_GEOLOCATION_GEOLOCATION_SERVICE_IMPL_H_
diff --git a/chromium/content/browser/geolocation/geolocation_service_impl_unittest.cc b/chromium/content/browser/geolocation/geolocation_service_impl_unittest.cc
new file mode 100644
index 00000000000..7fd35508de9
--- /dev/null
+++ b/chromium/content/browser/geolocation/geolocation_service_impl_unittest.cc
@@ -0,0 +1,323 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/geolocation/geolocation_service_impl.h"
+
+#include "base/run_loop.h"
+#include "base/test/scoped_feature_list.h"
+#include "content/public/browser/permission_manager.h"
+#include "content/public/browser/permission_type.h"
+#include "content/public/common/content_features.h"
+#include "content/public/test/navigation_simulator.h"
+#include "content/test/mock_permission_manager.h"
+#include "content/test/test_render_frame_host.h"
+#include "device/geolocation/geolocation_context.h"
+#include "device/geolocation/geoposition.h"
+#include "device/geolocation/public/interfaces/geolocation.mojom.h"
+#include "device/geolocation/public/interfaces/geoposition.mojom.h"
+#include "services/service_manager/public/cpp/bind_source_info.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using base::test::ScopedFeatureList;
+using blink::mojom::PermissionStatus;
+using device::GeolocationContext;
+using device::Geoposition;
+using device::mojom::GeolocationPtr;
+using device::mojom::GeopositionPtr;
+using device::mojom::GeolocationService;
+using device::mojom::GeolocationServicePtr;
+
+typedef base::Callback<void(PermissionStatus)> PermissionCallback;
+
+namespace content {
+namespace {
+
+double kMockLatitude = 1.0;
+double kMockLongitude = 10.0;
+GURL kMainUrl = GURL("https://www.google.com/maps");
+GURL kEmbeddedUrl = GURL("https://embeddables.com/someframe");
+
+class TestPermissionManager : public MockPermissionManager {
+ public:
+ TestPermissionManager()
+ : request_id_(PermissionManager::kNoPendingOperation) {}
+ ~TestPermissionManager() override = default;
+
+ int RequestPermission(PermissionType permissions,
+ RenderFrameHost* render_frame_host,
+ const GURL& requesting_origin,
+ bool user_gesture,
+ const PermissionCallback& callback) override {
+ EXPECT_EQ(permissions, PermissionType::GEOLOCATION);
+ EXPECT_TRUE(user_gesture);
+ request_callback_.Run(callback);
+ return request_id_;
+ }
+
+ void CancelPermissionRequest(int request_id) override {
+ EXPECT_EQ(request_id, request_id_);
+ cancel_callback_.Run();
+ }
+
+ void SetRequestId(int request_id) { request_id_ = request_id; }
+
+ void SetRequestCallback(
+ const base::Callback<void(const PermissionCallback&)>& request_callback) {
+ request_callback_ = request_callback;
+ }
+
+ void SetCancelCallback(const base::Closure& cancel_callback) {
+ cancel_callback_ = cancel_callback;
+ }
+
+ private:
+ int request_id_;
+
+ base::Callback<void(const PermissionCallback&)> request_callback_;
+ base::Closure cancel_callback_;
+};
+
+class GeolocationServiceTest : public RenderViewHostImplTestHarness {
+ protected:
+ GeolocationServiceTest() {}
+
+ ~GeolocationServiceTest() override {}
+
+ void SetUp() override {
+ RenderViewHostImplTestHarness::SetUp();
+ NavigateAndCommit(kMainUrl);
+ permission_manager_.reset(new TestPermissionManager);
+ }
+
+ void CreateEmbeddedFrameAndGeolocationService() {
+ RenderFrameHost* embedded_rfh =
+ RenderFrameHostTester::For(main_rfh())->AppendChild("");
+ RenderFrameHostTester::For(embedded_rfh)->InitializeRenderFrameIfNeeded();
+ auto navigation_simulator = NavigationSimulator::CreateRendererInitiated(
+ kEmbeddedUrl, embedded_rfh);
+ navigation_simulator->Commit();
+ embedded_rfh = navigation_simulator->GetFinalRenderFrameHost();
+
+ service_.reset(new GeolocationServiceImpl(
+ &context_, permission_manager_.get(), embedded_rfh));
+ service_->Bind(mojo::MakeRequest(&service_ptr_));
+ }
+
+ GeolocationServicePtr* service_ptr() { return &service_ptr_; }
+
+ GeolocationService* service() { return &*service_ptr_; }
+
+ GeolocationContext* context() { return &context_; }
+
+ TestPermissionManager* permission_manager() {
+ return permission_manager_.get();
+ }
+
+ private:
+ std::unique_ptr<GeolocationServiceImpl> service_;
+ std::unique_ptr<TestPermissionManager> permission_manager_;
+ GeolocationServicePtr service_ptr_;
+ GeolocationContext context_;
+
+ DISALLOW_COPY_AND_ASSIGN(GeolocationServiceTest);
+};
+
+} // namespace
+
+TEST_F(GeolocationServiceTest, PermissionGrantedPolicyViolation) {
+ // The embedded frame is not whitelisted.
+ ScopedFeatureList feature_list;
+ feature_list.InitFromCommandLine(
+ features::kUseFeaturePolicyForPermissions.name, std::string());
+ CreateEmbeddedFrameAndGeolocationService();
+
+ permission_manager()->SetRequestCallback(
+ base::Bind([](const PermissionCallback& callback) {
+ ADD_FAILURE() << "Permissions checked unexpectedly.";
+ }));
+ GeolocationPtr geolocation;
+ service()->CreateGeolocation(mojo::MakeRequest(&geolocation), true);
+
+ base::RunLoop loop;
+ geolocation.set_connection_error_handler(loop.QuitClosure());
+
+ geolocation->QueryNextPosition(base::BindOnce([](GeopositionPtr geoposition) {
+ ADD_FAILURE() << "Position updated unexpectedly";
+ }));
+ auto mock_geoposition = base::MakeUnique<Geoposition>();
+ mock_geoposition->latitude = kMockLatitude;
+ mock_geoposition->longitude = kMockLongitude;
+ context()->SetOverride(std::move(mock_geoposition));
+ loop.Run();
+}
+
+TEST_F(GeolocationServiceTest, PermissionGrantedNoPolicyViolation) {
+ // Whitelist the embedded frame.
+ ScopedFeatureList feature_list;
+ feature_list.InitFromCommandLine(
+ features::kUseFeaturePolicyForPermissions.name, std::string());
+ main_test_rfh()->SimulateFeaturePolicyHeader(
+ blink::WebFeaturePolicyFeature::kGeolocation,
+ {url::Origin(kEmbeddedUrl)});
+ CreateEmbeddedFrameAndGeolocationService();
+
+ permission_manager()->SetRequestCallback(
+ base::Bind([](const PermissionCallback& callback) {
+ callback.Run(PermissionStatus::GRANTED);
+ }));
+ GeolocationPtr geolocation;
+ service()->CreateGeolocation(mojo::MakeRequest(&geolocation), true);
+
+ base::RunLoop loop;
+ geolocation.set_connection_error_handler(base::BindOnce(
+ [] { ADD_FAILURE() << "Connection error handler called unexpectedly"; }));
+
+ geolocation->QueryNextPosition(base::BindOnce(
+ [](base::Closure callback, GeopositionPtr geoposition) {
+ EXPECT_DOUBLE_EQ(kMockLatitude, geoposition->latitude);
+ EXPECT_DOUBLE_EQ(kMockLongitude, geoposition->longitude);
+ callback.Run();
+ },
+ loop.QuitClosure()));
+ auto mock_geoposition = base::MakeUnique<Geoposition>();
+ mock_geoposition->latitude = kMockLatitude;
+ mock_geoposition->longitude = kMockLongitude;
+ context()->SetOverride(std::move(mock_geoposition));
+ loop.Run();
+}
+
+TEST_F(GeolocationServiceTest, PermissionGrantedSync) {
+ CreateEmbeddedFrameAndGeolocationService();
+ permission_manager()->SetRequestCallback(
+ base::Bind([](const PermissionCallback& callback) {
+ callback.Run(PermissionStatus::GRANTED);
+ }));
+ GeolocationPtr geolocation;
+ service()->CreateGeolocation(mojo::MakeRequest(&geolocation), true);
+
+ base::RunLoop loop;
+ geolocation.set_connection_error_handler(base::BindOnce(
+ [] { ADD_FAILURE() << "Connection error handler called unexpectedly"; }));
+
+ geolocation->QueryNextPosition(base::BindOnce(
+ [](base::Closure callback, GeopositionPtr geoposition) {
+ EXPECT_DOUBLE_EQ(kMockLatitude, geoposition->latitude);
+ EXPECT_DOUBLE_EQ(kMockLongitude, geoposition->longitude);
+ callback.Run();
+ },
+ loop.QuitClosure()));
+ auto mock_geoposition = base::MakeUnique<Geoposition>();
+ mock_geoposition->latitude = kMockLatitude;
+ mock_geoposition->longitude = kMockLongitude;
+ context()->SetOverride(std::move(mock_geoposition));
+ loop.Run();
+}
+
+TEST_F(GeolocationServiceTest, PermissionDeniedSync) {
+ CreateEmbeddedFrameAndGeolocationService();
+ permission_manager()->SetRequestCallback(
+ base::Bind([](const PermissionCallback& callback) {
+ callback.Run(PermissionStatus::DENIED);
+ }));
+ GeolocationPtr geolocation;
+ service()->CreateGeolocation(mojo::MakeRequest(&geolocation), true);
+
+ base::RunLoop loop;
+ geolocation.set_connection_error_handler(loop.QuitClosure());
+
+ geolocation->QueryNextPosition(base::BindOnce([](GeopositionPtr geoposition) {
+ ADD_FAILURE() << "Position updated unexpectedly";
+ }));
+ auto mock_geoposition = base::MakeUnique<Geoposition>();
+ mock_geoposition->latitude = kMockLatitude;
+ mock_geoposition->longitude = kMockLongitude;
+ context()->SetOverride(std::move(mock_geoposition));
+ loop.Run();
+}
+
+TEST_F(GeolocationServiceTest, PermissionGrantedAsync) {
+ CreateEmbeddedFrameAndGeolocationService();
+ permission_manager()->SetRequestId(42);
+ permission_manager()->SetRequestCallback(
+ base::Bind([](const PermissionCallback& permission_callback) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(
+ [](const PermissionCallback& callback) {
+ callback.Run(PermissionStatus::GRANTED);
+ },
+ permission_callback));
+ }));
+ GeolocationPtr geolocation;
+ service()->CreateGeolocation(mojo::MakeRequest(&geolocation), true);
+
+ base::RunLoop loop;
+ geolocation.set_connection_error_handler(base::BindOnce(
+ [] { ADD_FAILURE() << "Connection error handler called unexpectedly"; }));
+
+ geolocation->QueryNextPosition(base::BindOnce(
+ [](base::Closure callback, GeopositionPtr geoposition) {
+ EXPECT_DOUBLE_EQ(kMockLatitude, geoposition->latitude);
+ EXPECT_DOUBLE_EQ(kMockLongitude, geoposition->longitude);
+ callback.Run();
+ },
+ loop.QuitClosure()));
+ auto mock_geoposition = base::MakeUnique<Geoposition>();
+ mock_geoposition->latitude = kMockLatitude;
+ mock_geoposition->longitude = kMockLongitude;
+ context()->SetOverride(std::move(mock_geoposition));
+ loop.Run();
+}
+
+TEST_F(GeolocationServiceTest, PermissionDeniedAsync) {
+ CreateEmbeddedFrameAndGeolocationService();
+ permission_manager()->SetRequestId(42);
+ permission_manager()->SetRequestCallback(
+ base::Bind([](const PermissionCallback& permission_callback) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(
+ [](const PermissionCallback& callback) {
+ callback.Run(PermissionStatus::DENIED);
+ },
+ permission_callback));
+ }));
+ GeolocationPtr geolocation;
+ service()->CreateGeolocation(mojo::MakeRequest(&geolocation), true);
+
+ base::RunLoop loop;
+ geolocation.set_connection_error_handler(loop.QuitClosure());
+
+ geolocation->QueryNextPosition(base::BindOnce([](GeopositionPtr geoposition) {
+ ADD_FAILURE() << "Position updated unexpectedly";
+ }));
+ auto mock_geoposition = base::MakeUnique<Geoposition>();
+ mock_geoposition->latitude = kMockLatitude;
+ mock_geoposition->longitude = kMockLongitude;
+ context()->SetOverride(std::move(mock_geoposition));
+ loop.Run();
+}
+
+TEST_F(GeolocationServiceTest, ServiceClosedBeforePermissionResponse) {
+ CreateEmbeddedFrameAndGeolocationService();
+ permission_manager()->SetRequestId(42);
+ GeolocationPtr geolocation;
+ service()->CreateGeolocation(mojo::MakeRequest(&geolocation), true);
+ // Don't immediately respond to the request.
+ permission_manager()->SetRequestCallback(
+ base::Bind([](const PermissionCallback& callback) {}));
+
+ base::RunLoop loop;
+ permission_manager()->SetCancelCallback(loop.QuitClosure());
+ service_ptr()->reset();
+
+ geolocation->QueryNextPosition(base::BindOnce([](GeopositionPtr geoposition) {
+ ADD_FAILURE() << "Position updated unexpectedly";
+ }));
+ auto mock_geoposition = base::MakeUnique<Geoposition>();
+ mock_geoposition->latitude = kMockLatitude;
+ mock_geoposition->longitude = kMockLongitude;
+ context()->SetOverride(std::move(mock_geoposition));
+ loop.Run();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/gpu.sb b/chromium/content/browser/gpu.sb
index bf3c5530a5d..f9297fe9f71 100644
--- a/chromium/content/browser/gpu.sb
+++ b/chromium/content/browser/gpu.sb
@@ -26,3 +26,7 @@
; https://crbug.com/515280
(if (param-true? elcap-or-later)
(allow file-read* (subpath "/System/Library/Extensions")))
+
+; Needed for VideoToolbox usage - https://crbug.com/767037
+(if (param-true? macos-1013)
+ (allow mach-lookup (global-name "com.apple.coremedia.videodecoder")))
diff --git a/chromium/content/browser/gpu/DEPS b/chromium/content/browser/gpu/DEPS
new file mode 100644
index 00000000000..24cf9495137
--- /dev/null
+++ b/chromium/content/browser/gpu/DEPS
@@ -0,0 +1,10 @@
+# TODO(crbug.com/734668): Dependencies on ozone should be removed, as content
+# embedded in mus won't be able to talk to the native ozone.
+specific_include_rules = {
+ "gpu_data_manager_impl_private\.cc": [
+ "+ui/ozone/public/ozone_switches.h",
+ ],
+ "gpu_process_host\.cc": [
+ "+ui/ozone/public",
+ ],
+}
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 9c77f8abec4..9f9759d0fb3 100644
--- a/chromium/content/browser/gpu/browser_gpu_channel_host_factory.cc
+++ b/chromium/content/browser/gpu/browser_gpu_channel_host_factory.cc
@@ -31,6 +31,10 @@
#include "services/resource_coordinator/public/interfaces/memory_instrumentation/constants.mojom.h"
#include "services/service_manager/runner/common/client_util.h"
+#if defined(USE_AURA)
+#include "ui/aura/env.h"
+#endif
+
namespace content {
BrowserGpuChannelHostFactory* BrowserGpuChannelHostFactory::instance_ = NULL;
@@ -77,8 +81,9 @@ BrowserGpuChannelHostFactory::EstablishRequest::Create(
// PostTask outside the constructor to ensure at least one reference exists.
task_runner->PostTask(
FROM_HERE,
- base::Bind(&BrowserGpuChannelHostFactory::EstablishRequest::EstablishOnIO,
- establish_request));
+ base::BindOnce(
+ &BrowserGpuChannelHostFactory::EstablishRequest::EstablishOnIO,
+ establish_request));
return establish_request;
}
@@ -136,8 +141,8 @@ void BrowserGpuChannelHostFactory::EstablishRequest::FinishOnIO() {
event_.Signal();
main_task_runner_->PostTask(
FROM_HERE,
- base::Bind(&BrowserGpuChannelHostFactory::EstablishRequest::FinishOnMain,
- this));
+ base::BindOnce(
+ &BrowserGpuChannelHostFactory::EstablishRequest::FinishOnMain, this));
}
void BrowserGpuChannelHostFactory::EstablishRequest::FinishOnMain() {
@@ -214,7 +219,7 @@ BrowserGpuChannelHostFactory::BrowserGpuChannelHostFactory()
if (!cache_dir.empty()) {
GetIOThreadTaskRunner()->PostTask(
FROM_HERE,
- base::Bind(
+ base::BindOnce(
&BrowserGpuChannelHostFactory::InitializeShaderDiskCacheOnIO,
gpu_client_id_, cache_dir));
}
@@ -251,7 +256,9 @@ BrowserGpuChannelHostFactory::AllocateSharedMemory(size_t size) {
void BrowserGpuChannelHostFactory::EstablishGpuChannel(
const gpu::GpuChannelEstablishedCallback& callback) {
- DCHECK(!service_manager::ServiceManagerIsRemote());
+#if defined(USE_AURA)
+ DCHECK_EQ(aura::Env::Mode::LOCAL, aura::Env::GetInstance()->mode());
+#endif
DCHECK(IsMainThread());
if (gpu_channel_.get() && gpu_channel_->IsLost()) {
DCHECK(!pending_request_.get());
diff --git a/chromium/content/browser/gpu/browser_gpu_memory_buffer_manager.cc b/chromium/content/browser/gpu/browser_gpu_memory_buffer_manager.cc
index 98e4f9c0e0f..ba34e093eca 100644
--- a/chromium/content/browser/gpu/browser_gpu_memory_buffer_manager.cc
+++ b/chromium/content/browser/gpu/browser_gpu_memory_buffer_manager.cc
@@ -23,7 +23,6 @@
#include "gpu/ipc/client/gpu_memory_buffer_impl.h"
#include "gpu/ipc/client/gpu_memory_buffer_impl_shared_memory.h"
#include "ui/gfx/buffer_format_util.h"
-#include "ui/gfx/gpu_memory_buffer_tracing.h"
#include "ui/gl/gl_switches.h"
namespace content {
@@ -34,7 +33,7 @@ void GpuMemoryBufferDeleted(
const gpu::GpuMemoryBufferImpl::DestructionCallback& destruction_callback,
const gpu::SyncToken& sync_token) {
destruction_task_runner->PostTask(
- FROM_HERE, base::Bind(destruction_callback, sync_token));
+ FROM_HERE, base::BindOnce(destruction_callback, sync_token));
}
BrowserGpuMemoryBufferManager* g_gpu_memory_buffer_manager = nullptr;
@@ -182,11 +181,8 @@ bool BrowserGpuMemoryBufferManager::OnMemoryDump(
ClientIdToTracingProcessId(client_id);
if (buffer.second.type == gfx::SHARED_MEMORY_BUFFER) {
- auto shared_buffer_guid = gfx::GetSharedMemoryGUIDForTracing(
- client_tracing_process_id, buffer_id);
- pmd->CreateSharedMemoryOwnershipEdge(dump->guid(), shared_buffer_guid,
- buffer.second.shared_memory_guid,
- 0 /* importance */);
+ pmd->CreateSharedMemoryOwnershipEdge(
+ dump->guid(), buffer.second.shared_memory_guid, 0 /* importance */);
} else {
auto shared_buffer_guid = gfx::GetGenericSharedGpuMemoryGUIDForTracing(
client_tracing_process_id, buffer_id);
@@ -250,7 +246,7 @@ BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferForSurface(
surface_handle);
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(
+ base::BindOnce(
&BrowserGpuMemoryBufferManager::HandleCreateGpuMemoryBufferOnIO,
base::Unretained(this), // Safe as we wait for result below.
base::Unretained(&request)));
diff --git a/chromium/content/browser/gpu/gpu_client.cc b/chromium/content/browser/gpu/gpu_client.cc
index 8963ea3c4fd..6a9b9c637fc 100644
--- a/chromium/content/browser/gpu/gpu_client.cc
+++ b/chromium/content/browser/gpu/gpu_client.cc
@@ -97,11 +97,13 @@ void GpuClient::CreateJpegDecodeAccelerator(
host->gpu_service()->CreateJpegDecodeAccelerator(std::move(jda_request));
}
-void GpuClient::CreateVideoEncodeAccelerator(
- media::mojom::VideoEncodeAcceleratorRequest vea_request) {
+void GpuClient::CreateVideoEncodeAcceleratorProvider(
+ media::mojom::VideoEncodeAcceleratorProviderRequest vea_provider_request) {
GpuProcessHost* host = GpuProcessHost::Get();
- if (host)
- host->gpu_service()->CreateVideoEncodeAccelerator(std::move(vea_request));
+ if (!host)
+ return;
+ host->gpu_service()->CreateVideoEncodeAcceleratorProvider(
+ std::move(vea_provider_request));
}
void GpuClient::CreateGpuMemoryBuffer(
diff --git a/chromium/content/browser/gpu/gpu_client.h b/chromium/content/browser/gpu/gpu_client.h
index db213b22b6f..d6181e259ac 100644
--- a/chromium/content/browser/gpu/gpu_client.h
+++ b/chromium/content/browser/gpu/gpu_client.h
@@ -34,8 +34,9 @@ class GpuClient : public ui::mojom::Gpu {
const EstablishGpuChannelCallback& callback) override;
void CreateJpegDecodeAccelerator(
media::mojom::GpuJpegDecodeAcceleratorRequest jda_request) override;
- void CreateVideoEncodeAccelerator(
- media::mojom::VideoEncodeAcceleratorRequest vea_request) override;
+ void CreateVideoEncodeAcceleratorProvider(
+ media::mojom::VideoEncodeAcceleratorProviderRequest vea_provider_request)
+ override;
void CreateGpuMemoryBuffer(
gfx::GpuMemoryBufferId id,
const gfx::Size& size,
diff --git a/chromium/content/browser/gpu/gpu_data_manager_impl.h b/chromium/content/browser/gpu/gpu_data_manager_impl.h
index e83906749a8..e278e140f48 100644
--- a/chromium/content/browser/gpu/gpu_data_manager_impl.h
+++ b/chromium/content/browser/gpu/gpu_data_manager_impl.h
@@ -41,8 +41,7 @@ namespace content {
class GpuDataManagerImplPrivate;
struct WebPreferences;
-class CONTENT_EXPORT GpuDataManagerImpl
- : public NON_EXPORTED_BASE(GpuDataManager) {
+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
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 d1b78d7b70c..4388cefba8d 100644
--- a/chromium/content/browser/gpu/gpu_data_manager_impl_private.cc
+++ b/chromium/content/browser/gpu/gpu_data_manager_impl_private.cc
@@ -34,7 +34,7 @@
#include "content/public/common/web_preferences.h"
#include "gpu/command_buffer/service/gpu_preferences.h"
#include "gpu/command_buffer/service/gpu_switches.h"
-#include "gpu/config/gpu_driver_bug_list_autogen.h"
+#include "gpu/config/gpu_driver_bug_list.h"
#include "gpu/config/gpu_driver_bug_workaround_type.h"
#include "gpu/config/gpu_finch_features.h"
#include "gpu/config/gpu_info_collector.h"
@@ -42,6 +42,7 @@
#include "gpu/config/gpu_util.h"
#include "gpu/config/software_rendering_list_autogen.h"
#include "gpu/ipc/common/memory_stats.h"
+#include "gpu/ipc/host/shader_disk_cache.h"
#include "gpu/ipc/service/switches.h"
#include "media/media_features.h"
#include "ui/base/ui_base_switches.h"
@@ -155,12 +156,15 @@ void UpdateStats(const gpu::GPUInfo& gpu_info,
max_entry_id + 1);
if (blacklisted_features.size() != 0) {
- std::vector<uint32_t> flag_entries;
- blacklist->GetDecisionEntries(&flag_entries);
- DCHECK_GT(flag_entries.size(), 0u);
- for (size_t i = 0; i < flag_entries.size(); ++i) {
- UMA_HISTOGRAM_EXACT_LINEAR("GPU.BlacklistTestResultsPerEntry",
- flag_entries[i], max_entry_id + 1);
+ const std::vector<uint32_t>& entry_indices = blacklist->GetActiveEntries();
+ DCHECK_GT(entry_indices.size(), 0u);
+ std::vector<uint32_t> entry_ids =
+ blacklist->GetEntryIDsFromIndices(entry_indices);
+ DCHECK_EQ(entry_indices.size(), entry_ids.size());
+ for (auto id : entry_ids) {
+ DCHECK_GE(max_entry_id, id);
+ UMA_HISTOGRAM_EXACT_LINEAR("GPU.BlacklistTestResultsPerEntry", id,
+ max_entry_id + 1);
}
}
@@ -216,42 +220,27 @@ void UpdateStats(const gpu::GPUInfo& gpu_info,
}
}
-void UpdateDriverBugListStats(const gpu::GpuDriverBugList* bug_list,
- const std::set<int>& workarounds) {
- uint32_t max_entry_id = bug_list->max_entry_id();
- if (max_entry_id == 0) {
- // Driver bug list was not loaded. No need to go further.
- return;
- }
-
+void UpdateDriverBugListStats(const gpu::GpuFeatureInfo& gpu_feature_info) {
// Use entry 0 to capture the total number of times that data was recorded
// in this histogram in order to have a convenient denominator to compute
// driver bug list percentages for the rest of the entries.
UMA_HISTOGRAM_SPARSE_SLOWLY("GPU.DriverBugTestResultsPerEntry", 0);
- if (workarounds.size() != 0) {
- std::vector<uint32_t> flag_entries;
- bug_list->GetDecisionEntries(&flag_entries);
- DCHECK_GT(flag_entries.size(), 0u);
- for (size_t i = 0; i < flag_entries.size(); ++i) {
- UMA_HISTOGRAM_SPARSE_SLOWLY("GPU.DriverBugTestResultsPerEntry",
- flag_entries[i]);
+ if (!gpu_feature_info.applied_gpu_driver_bug_list_entries.empty()) {
+ std::unique_ptr<gpu::GpuDriverBugList> bug_list(
+ gpu::GpuDriverBugList::Create());
+ DCHECK(bug_list.get() && bug_list->max_entry_id() > 0);
+ std::vector<uint32_t> entry_ids = bug_list->GetEntryIDsFromIndices(
+ gpu_feature_info.applied_gpu_driver_bug_list_entries);
+ DCHECK_EQ(gpu_feature_info.applied_gpu_driver_bug_list_entries.size(),
+ entry_ids.size());
+ for (auto id : entry_ids) {
+ DCHECK_GE(bug_list->max_entry_id(), id);
+ UMA_HISTOGRAM_SPARSE_SLOWLY("GPU.DriverBugTestResultsPerEntry", id);
}
}
}
-// Combine the integers into a string, seperated by ','.
-std::string IntSetToString(const std::set<int>& list) {
- std::string rt;
- for (std::set<int>::const_iterator it = list.begin();
- it != list.end(); ++it) {
- if (!rt.empty())
- rt += ",";
- rt += base::IntToString(*it);
- }
- return rt;
-}
-
#if defined(OS_MACOSX)
void DisplayReconfigCallback(CGDirectDisplayID display,
CGDisplayChangeSummaryFlags flags,
@@ -300,7 +289,7 @@ void OnVideoMemoryUsageStats(
callback,
const gpu::VideoMemoryUsageStats& stats) {
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(callback, stats));
+ base::BindOnce(callback, stats));
}
void RequestVideoMemoryUsageStats(
@@ -310,7 +299,7 @@ void RequestVideoMemoryUsageStats(
if (!host)
return;
host->gpu_service()->GetVideoMemoryUsageStats(
- base::Bind(&OnVideoMemoryUsageStats, callback));
+ base::BindOnce(&OnVideoMemoryUsageStats, callback));
}
void UpdateGpuInfoOnIO(const gpu::GPUInfo& gpu_info) {
@@ -319,7 +308,7 @@ void UpdateGpuInfoOnIO(const gpu::GPUInfo& gpu_info) {
// expect to run in the UI thread, e.g. ContentClient::SetGpuInfo()).
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(
+ base::BindOnce(
[](const gpu::GPUInfo& gpu_info) {
TRACE_EVENT0("test_gpu", "OnGraphicsInfoCollected");
GpuDataManagerImpl::GetInstance()->UpdateGpuInfo(gpu_info);
@@ -338,8 +327,7 @@ void GpuDataManagerImplPrivate::InitializeForTesting(
// Prevent all further initialization.
finalized_ = true;
- gpu::GpuControlListData gpu_driver_bug_list_data;
- InitializeImpl(gpu_blacklist_data, gpu_driver_bug_list_data, gpu_info);
+ InitializeImpl(gpu_blacklist_data, gpu_info);
}
bool GpuDataManagerImplPrivate::IsFeatureBlacklisted(int feature) const {
@@ -368,7 +356,16 @@ bool GpuDataManagerImplPrivate::IsWebGLEnabled() const {
}
bool GpuDataManagerImplPrivate::IsDriverBugWorkaroundActive(int feature) const {
- return (gpu_driver_bugs_.count(feature) == 1);
+ switch (feature) {
+ // TODO(zmo): Remove these use cases and obsolete this function.
+ case gpu::DISABLE_OVERLAY_CA_LAYERS:
+ case gpu::DONT_DISABLE_WEBGL_WHEN_COMPOSITOR_CONTEXT_LOST:
+ case gpu::WAKE_UP_GPU_BEFORE_DRAWING:
+ return gpu_feature_info_.IsWorkaroundEnabled(feature);
+ default:
+ NOTREACHED();
+ return false;
+ }
}
size_t GpuDataManagerImplPrivate::GetBlacklistedFeatureCount() const {
@@ -470,7 +467,7 @@ void GpuDataManagerImplPrivate::RequestCompleteGpuInfoIfNeeded() {
if (!host)
return;
host->gpu_service()->RequestCompleteGpuInfo(
- base::Bind(&UpdateGpuInfoOnIO));
+ base::BindOnce(&UpdateGpuInfoOnIO));
}));
}
@@ -560,7 +557,6 @@ void GpuDataManagerImplPrivate::SetGLStrings(const std::string& gl_vendor,
gpu::CollectDriverInfoGL(&gpu_info);
UpdateGpuInfo(gpu_info);
- UpdateGpuSwitchingManager(gpu_info);
UpdatePreliminaryBlacklistedFeatures();
}
@@ -658,14 +654,7 @@ void GpuDataManagerImplPrivate::Initialize() {
gpu::kSoftwareRenderingListEntryCount,
gpu::kSoftwareRenderingListEntries};
}
- gpu::GpuControlListData gpu_driver_bug_list_data;
- if (!force_software_gl &&
- !command_line->HasSwitch(switches::kDisableGpuDriverBugWorkarounds)) {
- gpu_driver_bug_list_data = {gpu::kGpuDriverBugListVersion,
- gpu::kGpuDriverBugListEntryCount,
- gpu::kGpuDriverBugListEntries};
- }
- InitializeImpl(gpu_blacklist_data, gpu_driver_bug_list_data, gpu_info);
+ InitializeImpl(gpu_blacklist_data, gpu_info);
if (in_process_gpu_) {
command_line->AppendSwitch(switches::kDisableGpuWatchdog);
@@ -693,40 +682,6 @@ void GpuDataManagerImplPrivate::UpdateGpuInfoHelper() {
UpdateBlacklistedFeatures(features);
}
- std::string command_line_disable_gl_extensions;
- std::vector<std::string> disabled_driver_bug_exts;
- // Holds references to strings in the above two variables.
- std::set<base::StringPiece> disabled_ext_set;
-
- // Merge disabled extensions from the command line with gpu driver bug list.
- if (command_line) {
- command_line_disable_gl_extensions =
- command_line->GetSwitchValueASCII(switches::kDisableGLExtensions);
- std::vector<base::StringPiece> disabled_command_line_exts =
- base::SplitStringPiece(command_line_disable_gl_extensions, ", ;",
- base::KEEP_WHITESPACE,
- base::SPLIT_WANT_NONEMPTY);
- disabled_ext_set.insert(disabled_command_line_exts.begin(),
- disabled_command_line_exts.end());
- }
-
- if (gpu_driver_bug_list_) {
- gpu_driver_bugs_ = gpu_driver_bug_list_->MakeDecision(
- gpu::GpuControlList::kOsAny, os_version, gpu_info_);
-
- disabled_driver_bug_exts = gpu_driver_bug_list_->GetDisabledExtensions();
- disabled_ext_set.insert(disabled_driver_bug_exts.begin(),
- disabled_driver_bug_exts.end());
- UpdateDriverBugListStats(gpu_driver_bug_list_.get(), gpu_driver_bugs_);
- }
- disabled_extensions_ =
- base::JoinString(std::vector<base::StringPiece>(disabled_ext_set.begin(),
- disabled_ext_set.end()),
- " ");
-
- gpu::GpuDriverBugList::AppendWorkaroundsFromCommandLine(
- &gpu_driver_bugs_, *base::CommandLine::ForCurrentProcess());
-
// We have to update GpuFeatureType before notify all the observers.
NotifyGpuInfoUpdate();
}
@@ -752,6 +707,8 @@ void GpuDataManagerImplPrivate::UpdateGpuFeatureInfo(
const gpu::GpuFeatureInfo& gpu_feature_info) {
if (!use_swiftshader_) {
gpu_feature_info_ = gpu_feature_info;
+ UpdateDriverBugListStats(gpu_feature_info);
+ NotifyGpuInfoUpdate();
}
}
@@ -778,16 +735,6 @@ void GpuDataManagerImplPrivate::AppendGpuCommandLine(
std::string use_gl =
base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
switches::kUseGL);
- if (gpu_driver_bugs_.find(gpu::DISABLE_D3D11) != gpu_driver_bugs_.end())
- command_line->AppendSwitch(switches::kDisableD3D11);
- if (gpu_driver_bugs_.find(gpu::DISABLE_ES3_GL_CONTEXT) !=
- gpu_driver_bugs_.end()) {
- command_line->AppendSwitch(switches::kDisableES3GLContext);
- }
- if (gpu_driver_bugs_.find(gpu::DISABLE_DIRECT_COMPOSITION) !=
- gpu_driver_bugs_.end()) {
- command_line->AppendSwitch(switches::kDisableDirectComposition);
- }
if (use_swiftshader_) {
command_line->AppendSwitchASCII(
switches::kUseGL, gl::kGLImplementationSwiftShaderForWebGLName);
@@ -802,30 +749,11 @@ void GpuDataManagerImplPrivate::AppendGpuCommandLine(
} else if (!use_gl.empty()) {
command_line->AppendSwitchASCII(switches::kUseGL, use_gl);
}
- if (ui::GpuSwitchingManager::GetInstance()->SupportsDualGpus())
- command_line->AppendSwitchASCII(switches::kSupportsDualGpus, "true");
- else
- command_line->AppendSwitchASCII(switches::kSupportsDualGpus, "false");
-
- if (!gpu_driver_bugs_.empty()) {
- command_line->AppendSwitchASCII(switches::kGpuDriverBugWorkarounds,
- IntSetToString(gpu_driver_bugs_));
- }
-
- if (!disabled_extensions_.empty()) {
- command_line->AppendSwitchASCII(switches::kDisableGLExtensions,
- disabled_extensions_);
- }
if (ShouldDisableAcceleratedVideoDecode(command_line)) {
command_line->AppendSwitch(switches::kDisableAcceleratedVideoDecode);
}
- if (gpu_driver_bugs_.find(gpu::CREATE_DEFAULT_GL_CONTEXT) !=
- gpu_driver_bugs_.end()) {
- command_line->AppendSwitch(switches::kCreateDefaultGLContext);
- }
-
#if defined(USE_OZONE)
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableDrmAtomic)) {
@@ -881,6 +809,10 @@ void GpuDataManagerImplPrivate::AppendGpuCommandLine(
switches::kGpuActiveDeviceID,
base::StringPrintf("0x%04x", maybe_active_gpu_device.device_id));
}
+
+ if (gpu_info_.amd_switchable) {
+ command_line->AppendSwitch(switches::kAMDSwitchable);
+ }
}
void GpuDataManagerImplPrivate::UpdateRendererWebPrefs(
@@ -915,9 +847,6 @@ void GpuDataManagerImplPrivate::UpdateRendererWebPrefs(
!command_line->HasSwitch(switches::kDisableAcceleratedVideoDecode)) {
prefs->pepper_accelerated_video_decode_enabled = true;
}
- prefs->disable_2d_canvas_copy_on_write =
- IsDriverBugWorkaroundActive(gpu::BROKEN_EGL_IMAGE_REF_COUNTING) &&
- command_line->HasSwitch(switches::kEnableThreadedTextureMailboxes);
}
void GpuDataManagerImplPrivate::UpdateGpuPreferences(
@@ -937,6 +866,9 @@ void GpuDataManagerImplPrivate::UpdateGpuPreferences(
(command_line->HasSwitch(switches::kEnableES3APIs) ||
!IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_WEBGL2)) &&
!command_line->HasSwitch(switches::kDisableES3APIs);
+
+ gpu_preferences->gpu_program_cache_size =
+ gpu::ShaderDiskCache::CacheSizeBytes();
}
void GpuDataManagerImplPrivate::DisableHardwareAcceleration() {
@@ -969,8 +901,12 @@ std::string GpuDataManagerImplPrivate::GetBlacklistVersion() const {
}
std::string GpuDataManagerImplPrivate::GetDriverBugListVersion() const {
- if (gpu_driver_bug_list_)
- return gpu_driver_bug_list_->version();
+ if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableGpuDriverBugWorkarounds)) {
+ std::unique_ptr<gpu::GpuDriverBugList> bug_list(
+ gpu::GpuDriverBugList::Create());
+ return bug_list->version();
+ }
return "0";
}
@@ -978,18 +914,20 @@ void GpuDataManagerImplPrivate::GetBlacklistReasons(
base::ListValue* reasons) const {
if (gpu_blacklist_)
gpu_blacklist_->GetReasons(reasons, "disabledFeatures");
- if (gpu_driver_bug_list_)
- gpu_driver_bug_list_->GetReasons(reasons, "workarounds");
+ if (!gpu_feature_info_.applied_gpu_driver_bug_list_entries.empty()) {
+ std::unique_ptr<gpu::GpuDriverBugList> bug_list(
+ gpu::GpuDriverBugList::Create());
+ bug_list->GetReasons(reasons, "workarounds",
+ gpu_feature_info_.applied_gpu_driver_bug_list_entries);
+ }
}
std::vector<std::string>
GpuDataManagerImplPrivate::GetDriverBugWorkarounds() const {
std::vector<std::string> workarounds;
- for (std::set<int>::const_iterator it = gpu_driver_bugs_.begin();
- it != gpu_driver_bugs_.end(); ++it) {
- workarounds.push_back(
- gpu::GpuDriverBugWorkaroundTypeToString(
- static_cast<gpu::GpuDriverBugWorkaroundType>(*it)));
+ for (auto workaround : gpu_feature_info_.enabled_gpu_driver_bug_workarounds) {
+ workarounds.push_back(gpu::GpuDriverBugWorkaroundTypeToString(
+ static_cast<gpu::GpuDriverBugWorkaroundType>(workaround)));
}
return workarounds;
}
@@ -1005,11 +943,9 @@ void GpuDataManagerImplPrivate::ProcessCrashed(
// Unretained is ok, because it's posted to UI thread, the thread
// where the singleton GpuDataManagerImpl lives until the end.
BrowserThread::PostTask(
- BrowserThread::UI,
- FROM_HERE,
- base::Bind(&GpuDataManagerImpl::ProcessCrashed,
- base::Unretained(owner_),
- exit_code));
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&GpuDataManagerImpl::ProcessCrashed,
+ base::Unretained(owner_), exit_code));
return;
}
{
@@ -1123,7 +1059,7 @@ bool GpuDataManagerImplPrivate::ShouldDisableAcceleratedVideoDecode(
void GpuDataManagerImplPrivate::GetDisabledExtensions(
std::string* disabled_extensions) const {
DCHECK(disabled_extensions);
- *disabled_extensions = disabled_extensions_;
+ *disabled_extensions = gpu_feature_info_.disabled_extensions;
}
void GpuDataManagerImplPrivate::BlockDomainFrom3DAPIs(
@@ -1142,9 +1078,9 @@ bool GpuDataManagerImplPrivate::Are3DAPIsBlocked(const GURL& top_origin_url,
// where the singleton GpuDataManagerImpl lives until the end.
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&GpuDataManagerImpl::Notify3DAPIBlocked,
- base::Unretained(owner_), top_origin_url, render_process_id,
- render_frame_id, requester));
+ base::BindOnce(&GpuDataManagerImpl::Notify3DAPIBlocked,
+ base::Unretained(owner_), top_origin_url,
+ render_process_id, render_frame_id, requester));
}
return blocked;
@@ -1202,7 +1138,6 @@ GpuDataManagerImplPrivate::~GpuDataManagerImplPrivate() {
void GpuDataManagerImplPrivate::InitializeImpl(
const gpu::GpuControlListData& gpu_blacklist_data,
- const gpu::GpuControlListData& gpu_driver_bug_list_data,
const gpu::GPUInfo& gpu_info) {
const bool log_gpu_control_list_decisions =
base::CommandLine::ForCurrentProcess()->HasSwitch(
@@ -1213,16 +1148,9 @@ void GpuDataManagerImplPrivate::InitializeImpl(
if (log_gpu_control_list_decisions)
gpu_blacklist_->EnableControlListLogging("gpu_blacklist");
}
- if (gpu_driver_bug_list_data.entry_count) {
- gpu_driver_bug_list_ =
- gpu::GpuDriverBugList::Create(gpu_driver_bug_list_data);
- if (log_gpu_control_list_decisions)
- gpu_driver_bug_list_->EnableControlListLogging("gpu_driver_bug_list");
- }
gpu_info_ = gpu_info;
UpdateGpuInfo(gpu_info);
- UpdateGpuSwitchingManager(gpu_info);
UpdatePreliminaryBlacklistedFeatures();
RunPostInitTasks();
@@ -1257,19 +1185,6 @@ void GpuDataManagerImplPrivate::UpdatePreliminaryBlacklistedFeatures() {
preliminary_blacklisted_features_initialized_ = true;
}
-void GpuDataManagerImplPrivate::UpdateGpuSwitchingManager(
- const gpu::GPUInfo& gpu_info) {
- // The vendor IDs might be 0 on non-PCI devices (like Android), but
- // the length of the vector is all we care about in most cases.
- std::vector<uint32_t> vendor_ids;
- vendor_ids.push_back(gpu_info.gpu.vendor_id);
- for (const auto& device : gpu_info.secondary_gpus) {
- vendor_ids.push_back(device.vendor_id);
- }
- ui::GpuSwitchingManager::GetInstance()->SetGpuVendorIds(vendor_ids);
- gpu::InitializeDualGpusIfSupported(gpu_driver_bugs_);
-}
-
void GpuDataManagerImplPrivate::NotifyGpuInfoUpdate() {
observer_list_->Notify(FROM_HERE, &GpuDataManagerObserver::OnGpuInfoUpdate);
}
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 a2153eacdad..333a74d6bbd 100644
--- a/chromium/content/browser/gpu/gpu_data_manager_impl_private.h
+++ b/chromium/content/browser/gpu/gpu_data_manager_impl_private.h
@@ -24,7 +24,6 @@
#include "build/build_config.h"
#include "content/browser/gpu/gpu_data_manager_impl.h"
#include "gpu/config/gpu_blacklist.h"
-#include "gpu/config/gpu_driver_bug_list.h"
namespace base {
class CommandLine;
@@ -193,7 +192,6 @@ class CONTENT_EXPORT GpuDataManagerImplPrivate {
explicit GpuDataManagerImplPrivate(GpuDataManagerImpl* owner);
void InitializeImpl(const gpu::GpuControlListData& gpu_blacklist_data,
- const gpu::GpuControlListData& gpu_driver_bug_list_data,
const gpu::GPUInfo& gpu_info);
void RunPostInitTasks();
@@ -206,10 +204,6 @@ class CONTENT_EXPORT GpuDataManagerImplPrivate {
// gpu info is collected.
void UpdatePreliminaryBlacklistedFeatures();
- // Update the GPU switching status.
- // This should only be called once at initialization time.
- void UpdateGpuSwitchingManager(const gpu::GPUInfo& gpu_info);
-
// Notify all observers whenever there is a GPU info update.
void NotifyGpuInfoUpdate();
@@ -239,12 +233,9 @@ class CONTENT_EXPORT GpuDataManagerImplPrivate {
// Eventually |blacklisted_features_| should be folded in to this.
gpu::GpuFeatureInfo gpu_feature_info_;
- std::set<int> gpu_driver_bugs_;
-
gpu::GPUInfo gpu_info_;
std::unique_ptr<gpu::GpuBlacklist> gpu_blacklist_;
- std::unique_ptr<gpu::GpuDriverBugList> gpu_driver_bug_list_;
const scoped_refptr<GpuDataManagerObserverList> observer_list_;
@@ -277,8 +268,6 @@ class CONTENT_EXPORT GpuDataManagerImplPrivate {
// True if --single-process or --in-process-gpu is passed in.
bool in_process_gpu_;
- std::string disabled_extensions_;
-
// If one tries to call a member before initialization then it is defered
// until Initialize() is completed.
std::vector<base::Closure> post_init_tasks_;
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 f5f1a9b5eee..e7d1c515ee8 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
@@ -649,33 +649,6 @@ TEST_F(GpuDataManagerImplPrivateTest, SetGLStringsDefered) {
}
#endif // OS_LINUX
-TEST_F(GpuDataManagerImplPrivateTest, GpuDriverBugListSingle) {
- ScopedGpuDataManagerImplPrivate manager;
- manager->gpu_driver_bugs_.insert(5);
-
- base::CommandLine command_line(0, NULL);
- manager->AppendGpuCommandLine(&command_line);
-
- EXPECT_TRUE(command_line.HasSwitch(switches::kGpuDriverBugWorkarounds));
- std::string args = command_line.GetSwitchValueASCII(
- switches::kGpuDriverBugWorkarounds);
- EXPECT_STREQ("5", args.c_str());
-}
-
-TEST_F(GpuDataManagerImplPrivateTest, GpuDriverBugListMultiple) {
- ScopedGpuDataManagerImplPrivate manager;
- manager->gpu_driver_bugs_.insert(5);
- manager->gpu_driver_bugs_.insert(7);
-
- base::CommandLine command_line(0, NULL);
- manager->AppendGpuCommandLine(&command_line);
-
- EXPECT_TRUE(command_line.HasSwitch(switches::kGpuDriverBugWorkarounds));
- std::string args = command_line.GetSwitchValueASCII(
- switches::kGpuDriverBugWorkarounds);
- EXPECT_STREQ("5,7", args.c_str());
-}
-
TEST_F(GpuDataManagerImplPrivateTest, BlacklistAllFeatures) {
ScopedGpuDataManagerImplPrivate manager;
EXPECT_EQ(0u, manager->GetBlacklistedFeatureCount());
diff --git a/chromium/content/browser/gpu/gpu_feature_checker_impl.h b/chromium/content/browser/gpu/gpu_feature_checker_impl.h
index a7843cc7399..6e4841d18e4 100644
--- a/chromium/content/browser/gpu/gpu_feature_checker_impl.h
+++ b/chromium/content/browser/gpu/gpu_feature_checker_impl.h
@@ -14,9 +14,8 @@
namespace content {
-class CONTENT_EXPORT GpuFeatureCheckerImpl
- : public NON_EXPORTED_BASE(GpuFeatureChecker),
- public GpuDataManagerObserver {
+class CONTENT_EXPORT GpuFeatureCheckerImpl : public GpuFeatureChecker,
+ public GpuDataManagerObserver {
public:
GpuFeatureCheckerImpl(gpu::GpuFeatureType feature,
FeatureAvailableCallback callback);
diff --git a/chromium/content/browser/gpu/gpu_internals_ui.cc b/chromium/content/browser/gpu/gpu_internals_ui.cc
index 622a11b8c4f..2d46fc8dc68 100644
--- a/chromium/content/browser/gpu/gpu_internals_ui.cc
+++ b/chromium/content/browser/gpu/gpu_internals_ui.cc
@@ -249,7 +249,7 @@ std::unique_ptr<base::DictionaryValue> GpuInfoAsDictionaryValue() {
info->Set("diagnostics", std::move(dx_info));
#endif
-#if defined(USE_X11) && !defined(OS_CHROMEOS)
+#if defined(USE_X11)
basic_info->Append(NewDescriptionValuePair(
"System visual ID", base::Uint64ToString(gpu_info.system_visual)));
basic_info->Append(NewDescriptionValuePair(
@@ -309,8 +309,12 @@ const char* BufferUsageToString(gfx::BufferUsage usage) {
return "GPU_READ";
case gfx::BufferUsage::SCANOUT:
return "SCANOUT";
+ case gfx::BufferUsage::SCANOUT_CAMERA_READ_WRITE:
+ return "SCANOUT_CAMERA_READ_WRITE";
case gfx::BufferUsage::SCANOUT_CPU_READ_WRITE:
return "SCANOUT_CPU_READ_WRITE";
+ case gfx::BufferUsage::SCANOUT_VDA_WRITE:
+ return "SCANOUT_VDA_WRITE";
case gfx::BufferUsage::GPU_READ_CPU_READ_WRITE:
return "GPU_READ_CPU_READ_WRITE";
case gfx::BufferUsage::GPU_READ_CPU_READ_WRITE_PERSISTENT:
diff --git a/chromium/content/browser/gpu/gpu_ipc_browsertests.cc b/chromium/content/browser/gpu/gpu_ipc_browsertests.cc
index 6073e193173..afdc687046a 100644
--- a/chromium/content/browser/gpu/gpu_ipc_browsertests.cc
+++ b/chromium/content/browser/gpu/gpu_ipc_browsertests.cc
@@ -15,8 +15,8 @@
#include "content/public/common/content_switches.h"
#include "content/public/test/content_browser_test.h"
#include "gpu/ipc/client/gpu_channel_host.h"
-#include "services/ui/gpu/interfaces/gpu_service.mojom.h"
#include "services/ui/public/cpp/gpu/context_provider_command_buffer.h"
+#include "services/viz/privileged/interfaces/gl/gpu_service.mojom.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkPaint.h"
#include "third_party/skia/include/core/SkSurface.h"
diff --git a/chromium/content/browser/gpu/gpu_process_host.cc b/chromium/content/browser/gpu/gpu_process_host.cc
index 8c2dd4d5d17..e1879c62de7 100644
--- a/chromium/content/browser/gpu/gpu_process_host.cc
+++ b/chromium/content/browser/gpu/gpu_process_host.cc
@@ -22,7 +22,6 @@
#include "base/message_loop/message_loop.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram_macros.h"
-#include "base/sha1.h"
#include "base/threading/thread.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/trace_event.h"
@@ -55,6 +54,7 @@
#include "gpu/command_buffer/service/gpu_preferences.h"
#include "gpu/command_buffer/service/gpu_switches.h"
#include "gpu/config/gpu_driver_bug_list.h"
+#include "gpu/config/gpu_driver_bug_workaround_type.h"
#include "gpu/ipc/host/shader_disk_cache.h"
#include "gpu/ipc/service/switches.h"
#include "ipc/ipc_channel_handle.h"
@@ -65,6 +65,7 @@
#include "services/service_manager/public/cpp/binder_registry.h"
#include "services/service_manager/public/cpp/interface_provider.h"
#include "services/service_manager/runner/common/client_util.h"
+#include "ui/base/ui_base_switches.h"
#include "ui/display/display_switches.h"
#include "ui/gfx/color_space_switches.h"
#include "ui/gfx/switches.h"
@@ -90,7 +91,7 @@
#include "ui/ozone/public/ozone_switches.h"
#endif
-#if defined(USE_X11) && !defined(OS_CHROMEOS)
+#if defined(USE_X11)
#include "ui/gfx/x/x11_switches.h" // nogncheck
#endif
@@ -98,10 +99,6 @@
#include "gpu/ipc/common/gpu_surface_tracker.h"
#endif
-#if defined(OS_MACOSX)
-#include "ui/base/ui_base_switches.h"
-#endif
-
namespace content {
bool GpuProcessHost::gpu_enabled_ = true;
@@ -115,10 +112,8 @@ namespace {
// Command-line switches to propagate to the GPU process.
static const char* const kSwitchNames[] = {
- switches::kCreateDefaultGLContext,
switches::kDisableAcceleratedVideoDecode,
switches::kDisableBreakpad,
- switches::kDisableES3GLContext,
switches::kDisableGpuRasterization,
switches::kDisableGpuSandbox,
switches::kDisableGpuWatchdog,
@@ -135,10 +130,10 @@ static const char* const kSwitchNames[] = {
switches::kEnableGpuRasterization,
switches::kEnableHeapProfiling,
switches::kEnableLogging,
+ switches::kEnableOOPRasterization,
#if defined(OS_CHROMEOS)
switches::kDisableVaapiAcceleratedVideoEncode,
#endif
- switches::kGpuDriverBugWorkarounds,
switches::kGpuStartupDialog,
switches::kGpuSandboxAllowSysVShm,
switches::kGpuSandboxFailuresFatal,
@@ -166,7 +161,7 @@ static const char* const kSwitchNames[] = {
#if defined(USE_OZONE)
switches::kOzonePlatform,
#endif
-#if defined(USE_X11) && !defined(OS_CHROMEOS)
+#if defined(USE_X11)
switches::kX11Display,
#endif
switches::kGpuTestingGLVendor,
@@ -174,8 +169,9 @@ static const char* const kSwitchNames[] = {
switches::kGpuTestingGLVersion,
switches::kDisableGpuDriverBugWorkarounds,
switches::kUsePassthroughCmdDecoder,
- switches::kEnableHDR,
- switches::kIgnoreGpuBlacklist};
+ switches::kIgnoreGpuBlacklist,
+ switches::kForceVideoOverlays,
+};
enum GPUProcessLifetimeEvent {
LAUNCHED,
@@ -242,14 +238,6 @@ class GpuSandboxedProcessLauncherDelegate
~GpuSandboxedProcessLauncherDelegate() override {}
#if defined(OS_WIN)
- bool ShouldSandbox() override {
- bool sandbox = !cmd_line_.HasSwitch(switches::kDisableGpuSandbox);
- if (!sandbox) {
- DVLOG(1) << "GPU sandbox is disabled";
- }
- return sandbox;
- }
-
bool DisableDefaultPolicy() override {
return true;
}
@@ -314,6 +302,12 @@ class GpuSandboxedProcessLauncherDelegate
#endif // OS_WIN
SandboxType GetSandboxType() override {
+#if defined(OS_WIN)
+ if (cmd_line_.HasSwitch(switches::kDisableGpuSandbox)) {
+ DVLOG(1) << "GPU sandbox is disabled";
+ return SANDBOX_TYPE_NO_SANDBOX;
+ }
+#endif
return SANDBOX_TYPE_GPU;
}
@@ -383,7 +377,6 @@ bool GpuProcessHost::ValidateHost(GpuProcessHost* host) {
// static
GpuProcessHost* GpuProcessHost::Get(GpuProcessKind kind, bool force_create) {
- DCHECK(!service_manager::ServiceManagerIsRemote());
DCHECK_CURRENTLY_ON(BrowserThread::IO);
// Don't grant further access to GPU if it is not allowed.
@@ -424,7 +417,7 @@ void GpuProcessHost::GetHasGpuProcess(
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&GpuProcessHost::GetHasGpuProcess, callback));
+ base::BindOnce(&GpuProcessHost::GetHasGpuProcess, callback));
return;
}
bool has_gpu = false;
@@ -436,7 +429,7 @@ void GpuProcessHost::GetHasGpuProcess(
}
}
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(callback, has_gpu));
+ base::BindOnce(callback, has_gpu));
}
// static
@@ -449,7 +442,7 @@ void GpuProcessHost::CallOnIO(
#endif
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&RunCallbackOnIO, kind, force_create, callback));
+ base::BindOnce(&RunCallbackOnIO, kind, force_create, callback));
}
void GpuProcessHost::BindInterface(
@@ -541,9 +534,8 @@ GpuProcessHost::~GpuProcessHost() {
status == base::TERMINATION_STATUS_PROCESS_CRASHED) {
// Windows always returns PROCESS_CRASHED on abnormal termination, as it
// doesn't have a way to distinguish the two.
- UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessExitCode",
- exit_code,
- RESULT_CODE_LAST_CODE);
+ UMA_HISTOGRAM_SPARSE_SLOWLY("GPU.GPUProcessExitCode",
+ std::max(0, std::min(100, exit_code)));
}
switch (status) {
@@ -590,7 +582,7 @@ GpuProcessHost::~GpuProcessHost() {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&OnGpuProcessHostDestroyedOnUI, host_id_, message));
+ base::BindOnce(&OnGpuProcessHostDestroyedOnUI, host_id_, message));
}
bool GpuProcessHost::Init() {
@@ -675,7 +667,7 @@ bool GpuProcessHost::OnMessageReceived(const IPC::Message& message) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
#if defined(USE_OZONE)
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(&RouteMessageToOzoneOnUI, message));
+ base::BindOnce(&RouteMessageToOzoneOnUI, message));
#endif
return true;
}
@@ -714,8 +706,8 @@ void GpuProcessHost::EstablishGpuChannel(
channel_requests_.push(callback);
gpu_service_ptr_->EstablishGpuChannel(
client_id, client_tracing_id, is_gpu_host,
- base::Bind(&GpuProcessHost::OnChannelEstablished,
- weak_ptr_factory_.GetWeakPtr(), client_id, callback));
+ base::BindOnce(&GpuProcessHost::OnChannelEstablished,
+ weak_ptr_factory_.GetWeakPtr(), client_id, callback));
if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableGpuShaderDiskCache)) {
@@ -737,8 +729,8 @@ void GpuProcessHost::CreateGpuMemoryBuffer(
create_gpu_memory_buffer_requests_.push(callback);
gpu_service_ptr_->CreateGpuMemoryBuffer(
id, size, format, usage, client_id, surface_handle,
- base::Bind(&GpuProcessHost::OnGpuMemoryBufferCreated,
- weak_ptr_factory_.GetWeakPtr()));
+ base::BindOnce(&GpuProcessHost::OnGpuMemoryBufferCreated,
+ weak_ptr_factory_.GetWeakPtr()));
}
void GpuProcessHost::DestroyGpuMemoryBuffer(gfx::GpuMemoryBufferId id,
@@ -891,8 +883,13 @@ void GpuProcessHost::DidLoseContext(bool offscreen,
// context is a serious event and blame the loss on all live
// offscreen contexts. This more robustly handles situations where
// the GPU process may not actually detect the context loss in the
- // offscreen context.
- BlockLiveOffscreenContexts();
+ // offscreen context. However, situations have been seen where the
+ // compositor's context can be lost due to driver bugs (as of this
+ // writing, on Android), so allow that possibility.
+ if (!GpuDataManagerImpl::GetInstance()->IsDriverBugWorkaroundActive(
+ gpu::DONT_DISABLE_WEBGL_WHEN_COMPOSITOR_CONTEXT_LOST)) {
+ BlockLiveOffscreenContexts();
+ }
return;
}
@@ -963,7 +960,7 @@ void GpuProcessHost::StoreShaderToDisk(int32_t client_id,
// If the cache doesn't exist then this is an off the record profile.
if (iter == client_id_to_shader_cache_.end())
return;
- iter->second->Cache(GetShaderPrefixKey(shader) + ":" + key, shader);
+ iter->second->Cache(GetShaderPrefixKey() + ":" + key, shader);
}
void GpuProcessHost::RecordLogMessage(int32_t severity,
@@ -1128,9 +1125,10 @@ void GpuProcessHost::RecordProcessCrash() {
// options).
if (process_launched_ && kind_ == GPU_PROCESS_KIND_SANDBOXED) {
if (swiftshader_rendering_) {
- UMA_HISTOGRAM_ENUMERATION("GPU.SwiftShaderLifetimeEvents",
- DIED_FIRST_TIME + swiftshader_crash_count_,
- GPU_PROCESS_LIFETIME_EVENT_MAX);
+ UMA_HISTOGRAM_EXACT_LINEAR(
+ "GPU.SwiftShaderLifetimeEvents",
+ DIED_FIRST_TIME + swiftshader_crash_count_,
+ static_cast<int>(GPU_PROCESS_LIFETIME_EVENT_MAX));
if (++swiftshader_crash_count_ >= kGpuMaxCrashCount &&
!disable_crash_limit) {
@@ -1139,10 +1137,11 @@ void GpuProcessHost::RecordProcessCrash() {
}
} else {
++gpu_crash_count_;
- UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessLifetimeEvents",
- std::min(DIED_FIRST_TIME + gpu_crash_count_,
- GPU_PROCESS_LIFETIME_EVENT_MAX - 1),
- GPU_PROCESS_LIFETIME_EVENT_MAX);
+ UMA_HISTOGRAM_EXACT_LINEAR(
+ "GPU.GPUProcessLifetimeEvents",
+ std::min(DIED_FIRST_TIME + gpu_crash_count_,
+ GPU_PROCESS_LIFETIME_EVENT_MAX - 1),
+ static_cast<int>(GPU_PROCESS_LIFETIME_EVENT_MAX));
// Allow about 1 GPU crash per hour to be removed from the crash count,
// so very occasional crashes won't eventually add up and prevent the
@@ -1172,37 +1171,29 @@ void GpuProcessHost::RecordProcessCrash() {
}
}
-std::string GpuProcessHost::GetShaderPrefixKey(const std::string& shader) {
- if (shader_prefix_key_info_.empty()) {
+std::string GpuProcessHost::GetShaderPrefixKey() {
+ if (shader_prefix_key_.empty()) {
gpu::GPUInfo info = GpuDataManagerImpl::GetInstance()->GetGPUInfo();
- shader_prefix_key_info_ =
- GetContentClient()->GetProduct() + "-" +
- info.gl_vendor + "-" + info.gl_renderer + "-" + info.driver_version +
- "-" + info.driver_vendor;
+ shader_prefix_key_ = GetContentClient()->GetProduct() + "-" +
+ info.gl_vendor + "-" + info.gl_renderer + "-" +
+ info.driver_version + "-" + info.driver_vendor;
#if defined(OS_ANDROID)
std::string build_fp =
base::android::BuildInfo::GetInstance()->android_build_fp();
// TODO(ericrk): Remove this after it's up for a few days. crbug.com/699122
CHECK(!build_fp.empty());
- shader_prefix_key_info_ += "-" + build_fp;
+ shader_prefix_key_ += "-" + build_fp;
#endif
}
- // The shader prefix key is a SHA1 hash of a set of per-machine info, such as
- // driver version and os version, as well as the shader data being cached.
- // This ensures both that the shader was not corrupted on disk, as well as
- // that the shader is correctly configured for the current hardware.
- std::string prefix;
- base::Base64Encode(base::SHA1HashString(shader_prefix_key_info_ + shader),
- &prefix);
- return prefix;
+ return shader_prefix_key_;
}
void GpuProcessHost::LoadedShader(const std::string& key,
const std::string& data) {
- std::string prefix = GetShaderPrefixKey(data);
+ std::string prefix = GetShaderPrefixKey();
bool prefix_ok = !key.compare(0, prefix.length(), prefix);
UMA_HISTOGRAM_BOOLEAN("GPU.ShaderLoadPrefixOK", prefix_ok);
if (prefix_ok) {
@@ -1212,7 +1203,7 @@ void GpuProcessHost::LoadedShader(const std::string& key,
}
}
-ui::mojom::GpuService* GpuProcessHost::gpu_service() {
+viz::mojom::GpuService* GpuProcessHost::gpu_service() {
DCHECK(gpu_service_ptr_.is_bound());
return gpu_service_ptr_.get();
}
diff --git a/chromium/content/browser/gpu/gpu_process_host.h b/chromium/content/browser/gpu/gpu_process_host.h
index a58ce352ca8..c9d096fdf2a 100644
--- a/chromium/content/browser/gpu/gpu_process_host.h
+++ b/chromium/content/browser/gpu/gpu_process_host.h
@@ -33,7 +33,7 @@
#include "mojo/public/cpp/bindings/binding.h"
#include "services/ui/gpu/interfaces/gpu_host.mojom.h"
#include "services/ui/gpu/interfaces/gpu_main.mojom.h"
-#include "services/ui/gpu/interfaces/gpu_service.mojom.h"
+#include "services/viz/privileged/interfaces/gl/gpu_service.mojom.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/gpu_memory_buffer.h"
#include "url/gurl.h"
@@ -163,7 +163,7 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
void LoadedShader(const std::string& key, const std::string& data);
- CONTENT_EXPORT ui::mojom::GpuService* gpu_service();
+ CONTENT_EXPORT viz::mojom::GpuService* gpu_service();
private:
class ConnectionFilterImpl;
@@ -227,7 +227,7 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
// Update GPU crash counters. Disable GPU if crash limit is reached.
void RecordProcessCrash();
- std::string GetShaderPrefixKey(const std::string& shader);
+ std::string GetShaderPrefixKey();
// The serial number of the GpuProcessHost / GpuProcessHostUIShim pair.
int host_id_;
@@ -292,10 +292,10 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
ClientIdToShaderCacheMap;
ClientIdToShaderCacheMap client_id_to_shader_cache_;
- std::string shader_prefix_key_info_;
+ std::string shader_prefix_key_;
ui::mojom::GpuMainAssociatedPtr gpu_main_ptr_;
- ui::mojom::GpuServicePtr gpu_service_ptr_;
+ viz::mojom::GpuServicePtr gpu_service_ptr_;
mojo::Binding<ui::mojom::GpuHost> gpu_host_binding_;
gpu::GpuProcessHostActivityFlags activity_flags_;
diff --git a/chromium/content/browser/gpu/shader_cache_factory.cc b/chromium/content/browser/gpu/shader_cache_factory.cc
index e60323de130..1d9c9332a78 100644
--- a/chromium/content/browser/gpu/shader_cache_factory.cc
+++ b/chromium/content/browser/gpu/shader_cache_factory.cc
@@ -13,22 +13,19 @@ namespace {
gpu::ShaderCacheFactory* factory_instance = nullptr;
-void CreateFactoryInstance(
- scoped_refptr<base::SingleThreadTaskRunner> cache_task_runner) {
+void CreateFactoryInstance() {
DCHECK(!factory_instance);
- factory_instance = new gpu::ShaderCacheFactory(std::move(cache_task_runner));
+ factory_instance = new gpu::ShaderCacheFactory();
}
} // namespace
void InitShaderCacheFactorySingleton(
- scoped_refptr<base::SingleThreadTaskRunner> task_runner,
- scoped_refptr<base::SingleThreadTaskRunner> cache_task_runner) {
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
if (task_runner->BelongsToCurrentThread()) {
- CreateFactoryInstance(std::move(cache_task_runner));
+ CreateFactoryInstance();
} else {
- task_runner->PostTask(FROM_HERE, base::Bind(&CreateFactoryInstance,
- std::move(cache_task_runner)));
+ task_runner->PostTask(FROM_HERE, base::BindOnce(&CreateFactoryInstance));
}
}
diff --git a/chromium/content/browser/gpu/shader_cache_factory.h b/chromium/content/browser/gpu/shader_cache_factory.h
index 1c8fbe8f4c9..0d4a94b6666 100644
--- a/chromium/content/browser/gpu/shader_cache_factory.h
+++ b/chromium/content/browser/gpu/shader_cache_factory.h
@@ -13,11 +13,8 @@ namespace content {
// Initializes the ShaderCacheFactory singleton instance. The singleton
// instance is created and used in the thread associated with |task_runner|.
-// |cache_task_runner| is associated with the thread responsible for managing
-// the disk cache.
CONTENT_EXPORT void InitShaderCacheFactorySingleton(
- scoped_refptr<base::SingleThreadTaskRunner> task_runner,
- scoped_refptr<base::SingleThreadTaskRunner> cache_task_runner);
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner);
// Returns an instance previously created by InitShaderCacheFactorySingleton().
// This can return nullptr if an instance has not yet been created.
diff --git a/chromium/content/browser/host_zoom_map_impl.cc b/chromium/content/browser/host_zoom_map_impl.cc
index 97f15ddc7da..9c7d78fa6b3 100644
--- a/chromium/content/browser/host_zoom_map_impl.cc
+++ b/chromium/content/browser/host_zoom_map_impl.cc
@@ -17,8 +17,6 @@
#include "content/common/view_messages.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/notification_service.h"
-#include "content/public/browser/notification_types.h"
#include "content/public/browser/resource_context.h"
#include "content/public/browser/site_instance.h"
#include "content/public/browser/storage_partition.h"
@@ -117,9 +115,6 @@ void HostZoomMap::SendErrorPageZoomLevelRefresh(
HostZoomMapImpl::HostZoomMapImpl()
: default_zoom_level_(0.0) {
- registrar_.Add(
- this, NOTIFICATION_RENDER_VIEW_HOST_WILL_CLOSE_RENDER_VIEW,
- NotificationService::AllSources());
}
void HostZoomMapImpl::CopyFrom(HostZoomMap* copy_interface) {
@@ -490,23 +485,6 @@ double HostZoomMapImpl::GetZoomLevelForView(const GURL& url,
net::GetHostOrSpecFromURL(url));
}
-void HostZoomMapImpl::Observe(int type,
- const NotificationSource& source,
- const NotificationDetails& details) {
- switch (type) {
- case NOTIFICATION_RENDER_VIEW_HOST_WILL_CLOSE_RENDER_VIEW: {
- int render_view_id = Source<RenderViewHost>(source)->GetRoutingID();
- int render_process_id =
- Source<RenderViewHost>(source)->GetProcess()->GetID();
- ClearTemporaryZoomLevel(render_process_id, render_view_id);
- ClearPageScaleFactorIsOneForView(render_process_id, render_view_id);
- break;
- }
- default:
- NOTREACHED() << "Unexpected preference observed.";
- }
-}
-
void HostZoomMapImpl::ClearTemporaryZoomLevel(int render_process_id,
int render_view_id) {
{
@@ -553,6 +531,12 @@ void HostZoomMapImpl::SendErrorPageZoomLevelRefresh() {
SendZoomLevelChange(std::string(), host, error_page_zoom_level);
}
+void HostZoomMapImpl::WillCloseRenderView(int render_process_id,
+ int render_view_id) {
+ ClearTemporaryZoomLevel(render_process_id, render_view_id);
+ ClearPageScaleFactorIsOneForView(render_process_id, render_view_id);
+}
+
HostZoomMapImpl::~HostZoomMapImpl() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
}
diff --git a/chromium/content/browser/host_zoom_map_impl.h b/chromium/content/browser/host_zoom_map_impl.h
index ad4c07e16c4..0ba3bc9aa93 100644
--- a/chromium/content/browser/host_zoom_map_impl.h
+++ b/chromium/content/browser/host_zoom_map_impl.h
@@ -15,17 +15,14 @@
#include "base/sequenced_task_runner_helpers.h"
#include "base/synchronization/lock.h"
#include "content/public/browser/host_zoom_map.h"
-#include "content/public/browser/notification_observer.h"
-#include "content/public/browser/notification_registrar.h"
namespace content {
class WebContentsImpl;
// HostZoomMap needs to be deleted on the UI thread because it listens
-// to notifications on there (and holds a NotificationRegistrar).
-class CONTENT_EXPORT HostZoomMapImpl : public NON_EXPORTED_BASE(HostZoomMap),
- public NotificationObserver {
+// to notifications on there.
+class CONTENT_EXPORT HostZoomMapImpl : public HostZoomMap {
public:
HostZoomMapImpl();
~HostZoomMapImpl() override;
@@ -96,13 +93,10 @@ class CONTENT_EXPORT HostZoomMapImpl : public NON_EXPORTED_BASE(HostZoomMap),
int render_process_id,
int render_view_id) const;
- // NotificationObserver implementation.
- void Observe(int type,
- const NotificationSource& source,
- const NotificationDetails& details) override;
-
void SendErrorPageZoomLevelRefresh();
+ void WillCloseRenderView(int render_process_id, int render_view_id);
+
private:
typedef std::map<std::string, double> HostZoomLevels;
typedef std::map<std::string, HostZoomLevels> SchemeHostZoomLevels;
@@ -156,8 +150,6 @@ class CONTENT_EXPORT HostZoomMapImpl : public NON_EXPORTED_BASE(HostZoomMap),
// guarantee thread safety.
mutable base::Lock lock_;
- NotificationRegistrar registrar_;
-
DISALLOW_COPY_AND_ASSIGN(HostZoomMapImpl);
};
diff --git a/chromium/content/browser/image_capture/image_capture_impl.cc b/chromium/content/browser/image_capture/image_capture_impl.cc
index 752ecd1ad0f..c3f86513a82 100644
--- a/chromium/content/browser/image_capture/image_capture_impl.cc
+++ b/chromium/content/browser/image_capture/image_capture_impl.cc
@@ -15,6 +15,7 @@
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_features.h"
#include "media/base/bind_to_current_loop.h"
+#include "media/base/scoped_callback_runner.h"
#include "media/capture/video/video_capture_device.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
@@ -22,9 +23,7 @@ namespace content {
namespace {
-void RunFailedGetPhotoStateCallback(
- ImageCaptureImpl::GetPhotoStateCallback cb) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
+media::mojom::PhotoStatePtr MakeEmptyCapabilities() {
media::mojom::PhotoStatePtr empty_capabilities =
media::mojom::PhotoState::New();
empty_capabilities->iso = media::mojom::Range::New();
@@ -37,24 +36,12 @@ void RunFailedGetPhotoStateCallback(
empty_capabilities->contrast = media::mojom::Range::New();
empty_capabilities->saturation = media::mojom::Range::New();
empty_capabilities->sharpness = media::mojom::Range::New();
- std::move(cb).Run(std::move(empty_capabilities));
-}
-
-void RunFailedSetOptionsCallback(ImageCaptureImpl::SetOptionsCallback cb) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- std::move(cb).Run(false);
-}
-
-void RunFailedTakePhotoCallback(ImageCaptureImpl::TakePhotoCallback cb) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- std::move(cb).Run(media::mojom::Blob::New());
+ return empty_capabilities;
}
-void GetPhotoStateOnIOThread(
- const std::string& source_id,
- MediaStreamManager* media_stream_manager,
- media::ScopedResultCallback<ImageCaptureImpl::GetPhotoStateCallback>
- callback) {
+void GetPhotoStateOnIOThread(const std::string& source_id,
+ MediaStreamManager* media_stream_manager,
+ ImageCaptureImpl::GetPhotoStateCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
// TODO(mcasas): Enable PhotoState collection in Windows when understood why it
@@ -70,12 +57,10 @@ void GetPhotoStateOnIOThread(
#endif
}
-void SetOptionsOnIOThread(
- const std::string& source_id,
- MediaStreamManager* media_stream_manager,
- media::mojom::PhotoSettingsPtr settings,
- media::ScopedResultCallback<ImageCaptureImpl::SetOptionsCallback>
- callback) {
+void SetOptionsOnIOThread(const std::string& source_id,
+ MediaStreamManager* media_stream_manager,
+ media::mojom::PhotoSettingsPtr settings,
+ ImageCaptureImpl::SetOptionsCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
const int session_id =
@@ -87,10 +72,9 @@ void SetOptionsOnIOThread(
session_id, std::move(settings), std::move(callback));
}
-void TakePhotoOnIOThread(
- const std::string& source_id,
- MediaStreamManager* media_stream_manager,
- media::ScopedResultCallback<ImageCaptureImpl::TakePhotoCallback> callback) {
+void TakePhotoOnIOThread(const std::string& source_id,
+ MediaStreamManager* media_stream_manager,
+ ImageCaptureImpl::TakePhotoCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
const int session_id =
@@ -122,16 +106,13 @@ void ImageCaptureImpl::GetPhotoState(const std::string& source_id,
GetPhotoStateCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- media::ScopedResultCallback<GetPhotoStateCallback> scoped_callback(
- media::BindToCurrentLoop(std::move(callback)),
- media::BindToCurrentLoop(
- base::BindOnce(&RunFailedGetPhotoStateCallback)));
-
+ GetPhotoStateCallback scoped_callback = media::ScopedCallbackRunner(
+ media::BindToCurrentLoop(std::move(callback)), MakeEmptyCapabilities());
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&GetPhotoStateOnIOThread, source_id,
- BrowserMainLoop::GetInstance()->media_stream_manager(),
- base::Passed(&scoped_callback)));
+ base::BindOnce(&GetPhotoStateOnIOThread, source_id,
+ BrowserMainLoop::GetInstance()->media_stream_manager(),
+ std::move(scoped_callback)));
}
void ImageCaptureImpl::SetOptions(const std::string& source_id,
@@ -139,30 +120,26 @@ void ImageCaptureImpl::SetOptions(const std::string& source_id,
SetOptionsCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- media::ScopedResultCallback<SetOptionsCallback> scoped_callback(
- media::BindToCurrentLoop(std::move(callback)),
- media::BindToCurrentLoop(base::Bind(&RunFailedSetOptionsCallback)));
-
+ SetOptionsCallback scoped_callback = media::ScopedCallbackRunner(
+ media::BindToCurrentLoop(std::move(callback)), false);
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&SetOptionsOnIOThread, source_id,
- BrowserMainLoop::GetInstance()->media_stream_manager(),
- base::Passed(&settings), base::Passed(&scoped_callback)));
+ base::BindOnce(&SetOptionsOnIOThread, source_id,
+ BrowserMainLoop::GetInstance()->media_stream_manager(),
+ std::move(settings), std::move(scoped_callback)));
}
void ImageCaptureImpl::TakePhoto(const std::string& source_id,
TakePhotoCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- media::ScopedResultCallback<TakePhotoCallback> scoped_callback(
- media::BindToCurrentLoop(std::move(callback)),
- media::BindToCurrentLoop(base::BindOnce(&RunFailedTakePhotoCallback)));
-
+ TakePhotoCallback scoped_callback = media::ScopedCallbackRunner(
+ media::BindToCurrentLoop(std::move(callback)), media::mojom::Blob::New());
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&TakePhotoOnIOThread, source_id,
- BrowserMainLoop::GetInstance()->media_stream_manager(),
- base::Passed(&scoped_callback)));
+ base::BindOnce(&TakePhotoOnIOThread, source_id,
+ BrowserMainLoop::GetInstance()->media_stream_manager(),
+ std::move(scoped_callback)));
}
} // namespace content
diff --git a/chromium/content/browser/indexed_db/database_impl.cc b/chromium/content/browser/indexed_db/database_impl.cc
index 0641dadd132..9799c389c24 100644
--- a/chromium/content/browser/indexed_db/database_impl.cc
+++ b/chromium/content/browser/indexed_db/database_impl.cc
@@ -330,8 +330,7 @@ void DatabaseImpl::Put(
}
UMA_HISTOGRAM_COUNTS_1000("WebCore.IndexedDB.PutBlobsCount",
blob_info.size());
- uint64_t blob_size = 0;
- total_blob_size.AssignIfValid(&blob_size);
+ uint64_t blob_size = total_blob_size.ValueOrDefault(0U);
if (blob_size != 0) {
// 1KB to 1GB.
UMA_HISTOGRAM_COUNTS_1M("WebCore.IndexedDB.PutBlobsTotalSize",
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 83b49ff670d..b3222f16278 100644
--- a/chromium/content/browser/indexed_db/indexed_db_backing_store.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_backing_store.cc
@@ -1114,6 +1114,12 @@ IndexedDBBackingStore::RecordIdentifier::RecordIdentifier()
: primary_key_(), version_(-1) {}
IndexedDBBackingStore::RecordIdentifier::~RecordIdentifier() {}
+constexpr const int IndexedDBBackingStore::kMaxJournalCleanRequests;
+constexpr const base::TimeDelta
+ IndexedDBBackingStore::kMaxJournalCleaningWindowTime;
+constexpr const base::TimeDelta
+ IndexedDBBackingStore::kInitialJournalCleaningWindowTime;
+
// static
scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Open(
IndexedDBFactory* indexed_db_factory,
@@ -1253,6 +1259,28 @@ WARN_UNUSED_RESULT Status IndexedDBBackingStore::SetUpMetadata() {
return s;
}
+leveldb::Status IndexedDBBackingStore::GetCompleteMetadata(
+ std::vector<IndexedDBDatabaseMetadata>* output) {
+ leveldb::Status status = leveldb::Status::OK();
+ std::vector<base::string16> names = GetDatabaseNames(&status);
+ if (!status.ok())
+ return status;
+ for (const base::string16& name : names) {
+ output->emplace_back();
+ bool found = false;
+ status = GetIDBDatabaseMetaData(name, &output->back(), &found);
+ output->back().name = name;
+ if (!found)
+ return Status::NotFound("Metadata not found for \"%s\".",
+ base::UTF16ToUTF8(name));
+ status = GetObjectStores(output->back().id, &output->back().object_stores);
+ if (!status.ok())
+ return status;
+ }
+
+ return status;
+}
+
bool IndexedDBBackingStore::ReadCorruptionInfo(const FilePath& path_base,
const Origin& origin,
std::string* message) {
@@ -2577,7 +2605,7 @@ class LocalWriteClosure : public FileWriterDelegate::DelegateWriteCallback,
destination: LOCAL
}
policy {
- cookies_allowed: false
+ cookies_allowed: NO
setting: "This feature cannot be disabled by settings."
policy_exception_justification: "Not implemented."
})");
@@ -2757,10 +2785,37 @@ void IndexedDBBackingStore::ReportBlobUnused(int64_t database_id,
// HasLastBackingStoreReference. It's safe because if the backing store is
// deleted, the timer will automatically be canceled on destruction.
void IndexedDBBackingStore::StartJournalCleaningTimer() {
+ ++num_aggregated_journal_cleaning_requests_;
+
+ if (execute_journal_cleaning_on_no_txns_)
+ return;
+
+ if (num_aggregated_journal_cleaning_requests_ >= kMaxJournalCleanRequests) {
+ journal_cleaning_timer_.AbandonAndStop();
+ CleanPrimaryJournalIgnoreReturn();
+ return;
+ }
+
+ base::TimeTicks now = base::TimeTicks::Now();
+
+ if (journal_cleaning_timer_window_start_ == base::TimeTicks() ||
+ !journal_cleaning_timer_.IsRunning()) {
+ journal_cleaning_timer_window_start_ = now;
+ }
+
+ base::TimeDelta time_until_max = kMaxJournalCleaningWindowTime -
+ (now - journal_cleaning_timer_window_start_);
+ base::TimeDelta delay =
+ std::min(kInitialJournalCleaningWindowTime, time_until_max);
+
+ if (delay <= base::TimeDelta::FromSeconds(0)) {
+ journal_cleaning_timer_.AbandonAndStop();
+ CleanPrimaryJournalIgnoreReturn();
+ return;
+ }
+
journal_cleaning_timer_.Start(
- FROM_HERE,
- base::TimeDelta::FromSeconds(5),
- this,
+ FROM_HERE, delay, this,
&IndexedDBBackingStore::CleanPrimaryJournalIgnoreReturn);
}
@@ -2870,6 +2925,9 @@ Status IndexedDBBackingStore::GetIndexes(
bool IndexedDBBackingStore::RemoveBlobFile(int64_t database_id,
int64_t key) const {
+#if DCHECK_IS_ON()
+ ++num_blob_files_deleted_;
+#endif
FilePath path = GetBlobFileName(database_id, key);
return base::DeleteFile(path, false);
}
@@ -2879,6 +2937,31 @@ bool IndexedDBBackingStore::RemoveBlobDirectory(int64_t database_id) const {
return base::DeleteFile(path, true);
}
+Status IndexedDBBackingStore::CleanUpBlobJournal(
+ const std::string& level_db_key) const {
+ IDB_TRACE("IndexedDBBackingStore::CleanUpBlobJournal");
+ DCHECK(!committing_transaction_count_);
+ scoped_refptr<LevelDBTransaction> journal_transaction =
+ IndexedDBClassFactory::Get()->CreateLevelDBTransaction(db_.get());
+ BlobJournalType journal;
+
+ Status s = GetBlobJournal(level_db_key, journal_transaction.get(), &journal);
+ if (!s.ok())
+ return s;
+ if (journal.empty())
+ return Status::OK();
+ s = CleanUpBlobJournalEntries(journal);
+ if (!s.ok())
+ return s;
+ ClearBlobJournal(journal_transaction.get(), level_db_key);
+ s = journal_transaction->Commit();
+ // Notify blob files cleaned even if commit fails, as files could still be
+ // deleted. |indexed_db_factory_| is null for in-memory backing stores.
+ if (indexed_db_factory_)
+ indexed_db_factory_->BlobFilesCleaned(origin_);
+ return s;
+}
+
Status IndexedDBBackingStore::CleanUpBlobJournalEntries(
const BlobJournalType& journal) const {
IDB_TRACE("IndexedDBBackingStore::CleanUpBlobJournalEntries");
@@ -2900,24 +2983,18 @@ Status IndexedDBBackingStore::CleanUpBlobJournalEntries(
return Status::OK();
}
-Status IndexedDBBackingStore::CleanUpBlobJournal(
- const std::string& level_db_key) const {
- IDB_TRACE("IndexedDBBackingStore::CleanUpBlobJournal");
- DCHECK(!committing_transaction_count_);
- scoped_refptr<LevelDBTransaction> journal_transaction =
- IndexedDBClassFactory::Get()->CreateLevelDBTransaction(db_.get());
- BlobJournalType journal;
+void IndexedDBBackingStore::WillCommitTransaction() {
+ ++committing_transaction_count_;
+}
- Status s = GetBlobJournal(level_db_key, journal_transaction.get(), &journal);
- if (!s.ok())
- return s;
- if (journal.empty())
- return Status::OK();
- s = CleanUpBlobJournalEntries(journal);
- if (!s.ok())
- return s;
- ClearBlobJournal(journal_transaction.get(), level_db_key);
- return journal_transaction->Commit();
+void IndexedDBBackingStore::DidCommitTransaction() {
+ DCHECK_GT(committing_transaction_count_, 0UL);
+ --committing_transaction_count_;
+ if (committing_transaction_count_ == 0 &&
+ execute_journal_cleaning_on_no_txns_) {
+ execute_journal_cleaning_on_no_txns_ = false;
+ CleanPrimaryJournalIgnoreReturn();
+ }
}
Status IndexedDBBackingStore::Transaction::GetBlobInfoForRecord(
@@ -2984,10 +3061,12 @@ Status IndexedDBBackingStore::Transaction::GetBlobInfoForRecord(
void IndexedDBBackingStore::CleanPrimaryJournalIgnoreReturn() {
// While a transaction is busy it is not safe to clean the journal.
- if (committing_transaction_count_ > 0)
- StartJournalCleaningTimer();
- else
- CleanUpBlobJournal(BlobJournalKey::Encode());
+ if (committing_transaction_count_ > 0) {
+ execute_journal_cleaning_on_no_txns_ = true;
+ return;
+ }
+ num_aggregated_journal_cleaning_requests_ = 0;
+ CleanUpBlobJournal(BlobJournalKey::Encode());
}
Status IndexedDBBackingStore::CreateIndex(
@@ -4008,6 +4087,22 @@ IndexedDBBackingStore::OpenIndexCursor(
return std::move(cursor);
}
+void IndexedDBBackingStore::StartPreCloseTasks() {
+ DCHECK(pre_close_task_queue_);
+ pre_close_task_queue_->Start(base::BindOnce(
+ &IndexedDBBackingStore::GetCompleteMetadata, base::Unretained(this)));
+}
+
+bool IndexedDBBackingStore::IsBlobCleanupPending() {
+ return journal_cleaning_timer_.IsRunning();
+}
+
+void IndexedDBBackingStore::ForceRunBlobCleanup() {
+ base::OnceClosure task = journal_cleaning_timer_.user_task();
+ journal_cleaning_timer_.AbandonAndStop();
+ std::move(task).Run();
+}
+
IndexedDBBackingStore::Transaction::Transaction(
IndexedDBBackingStore* backing_store)
: backing_store_(backing_store),
@@ -4171,7 +4266,7 @@ Status IndexedDBBackingStore::Transaction::CommitPhaseOne(
}
committing_ = true;
- ++backing_store_->committing_transaction_count_;
+ backing_store_->WillCommitTransaction();
if (!new_files_to_write.empty()) {
// This kicks off the writes of the new blobs, if any.
@@ -4190,8 +4285,8 @@ Status IndexedDBBackingStore::Transaction::CommitPhaseTwo() {
DCHECK(committing_);
committing_ = false;
- DCHECK_GT(backing_store_->committing_transaction_count_, 0UL);
- --backing_store_->committing_transaction_count_;
+
+ backing_store_->DidCommitTransaction();
BlobJournalType primary_journal, live_journal, saved_primary_journal,
dead_blobs;
@@ -4346,8 +4441,7 @@ void IndexedDBBackingStore::Transaction::Rollback() {
IDB_TRACE("IndexedDBBackingStore::Transaction::Rollback");
if (committing_) {
committing_ = false;
- DCHECK_GT(backing_store_->committing_transaction_count_, 0UL);
- --backing_store_->committing_transaction_count_;
+ backing_store_->DidCommitTransaction();
}
if (chained_blob_writer_.get()) {
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 3c04dabce1a..2aa7c4321c9 100644
--- a/chromium/content/browser/indexed_db/indexed_db_backing_store.h
+++ b/chromium/content/browser/indexed_db/indexed_db_backing_store.h
@@ -27,6 +27,7 @@
#include "content/browser/indexed_db/indexed_db_active_blob_registry.h"
#include "content/browser/indexed_db/indexed_db_blob_info.h"
#include "content/browser/indexed_db/indexed_db_leveldb_coding.h"
+#include "content/browser/indexed_db/indexed_db_pre_close_task_queue.h"
#include "content/browser/indexed_db/leveldb/leveldb_iterator.h"
#include "content/browser/indexed_db/leveldb/leveldb_transaction.h"
#include "content/common/content_export.h"
@@ -375,6 +376,16 @@ class CONTENT_EXPORT IndexedDBBackingStore
DISALLOW_COPY_AND_ASSIGN(Cursor);
};
+ // Schedule an immediate blob journal cleanup if we reach this number of
+ // requests.
+ static constexpr const int kMaxJournalCleanRequests = 50;
+ // Wait for a maximum of 5 seconds from the first call to the timer since the
+ // last journal cleaning.
+ static constexpr const base::TimeDelta kMaxJournalCleaningWindowTime =
+ base::TimeDelta::FromSeconds(5);
+ // Default to a 2 second timer delay before we clean up blobs.
+ static constexpr const base::TimeDelta kInitialJournalCleaningWindowTime =
+ base::TimeDelta::FromSeconds(2);
const url::Origin& origin() const { return origin_; }
IndexedDBFactory* factory() const { return indexed_db_factory_; }
@@ -585,6 +596,32 @@ class CONTENT_EXPORT IndexedDBBackingStore
blink::WebIDBCursorDirection,
leveldb::Status*);
+ IndexedDBPreCloseTaskQueue* pre_close_task_queue() {
+ return pre_close_task_queue_.get();
+ }
+
+ void SetPreCloseTaskList(std::unique_ptr<IndexedDBPreCloseTaskQueue> list) {
+ pre_close_task_queue_ = std::move(list);
+ }
+
+ // |pre_close_task_queue()| must not be null.
+ void StartPreCloseTasks();
+
+ LevelDBDatabase* db() { return db_.get(); }
+
+ // Returns true if a blob cleanup job is pending on journal_cleaning_timer_.
+ bool IsBlobCleanupPending();
+
+#if DCHECK_IS_ON()
+ int NumBlobFilesDeletedForTesting() { return num_blob_files_deleted_; }
+ int NumAggregatedJournalCleaningRequestsForTesting() const {
+ return num_aggregated_journal_cleaning_requests_;
+ }
+#endif
+
+ // Stops the journal_cleaning_timer_ and runs its pending task.
+ void ForceRunBlobCleanup();
+
protected:
friend class base::RefCounted<IndexedDBBackingStore>;
@@ -602,6 +639,9 @@ class CONTENT_EXPORT IndexedDBBackingStore
leveldb::Status SetUpMetadata();
+ leveldb::Status GetCompleteMetadata(
+ std::vector<IndexedDBDatabaseMetadata>* output);
+
virtual bool WriteBlobFile(
int64_t database_id,
const Transaction::WriteDescriptor& descriptor,
@@ -666,6 +706,10 @@ class CONTENT_EXPORT IndexedDBBackingStore
leveldb::Status CleanUpBlobJournalEntries(
const BlobJournalType& journal) const;
+ void WillCommitTransaction();
+ // Can run a journal cleaning job if one is pending.
+ void DidCommitTransaction();
+
IndexedDBFactory* indexed_db_factory_;
const url::Origin origin_;
base::FilePath blob_path_;
@@ -682,7 +726,15 @@ class CONTENT_EXPORT IndexedDBBackingStore
scoped_refptr<base::SequencedTaskRunner> task_runner_;
std::set<int> child_process_ids_granted_;
std::map<std::string, std::unique_ptr<BlobChangeRecord>> incognito_blob_map_;
+
+ bool execute_journal_cleaning_on_no_txns_ = false;
+ int num_aggregated_journal_cleaning_requests_ = 0;
base::OneShotTimer journal_cleaning_timer_;
+ base::TimeTicks journal_cleaning_timer_window_start_;
+
+#if DCHECK_IS_ON()
+ mutable int num_blob_files_deleted_ = 0;
+#endif
std::unique_ptr<LevelDBDatabase> db_;
std::unique_ptr<LevelDBComparator> comparator_;
@@ -690,6 +742,7 @@ class CONTENT_EXPORT IndexedDBBackingStore
// will hold a reference to this backing store.
IndexedDBActiveBlobRegistry active_blob_registry_;
base::OneShotTimer close_timer_;
+ std::unique_ptr<IndexedDBPreCloseTaskQueue> pre_close_task_queue_;
// Incremented whenever a transaction starts committing, decremented when
// complete. While > 0, temporary journal entries may exist so out-of-band
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 d5dc6681ffe..36b869eb3d3 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
@@ -126,6 +126,10 @@ class TestableIndexedDBBackingStore : public IndexedDBBackingStore {
const std::vector<int64_t>& removals() const { return removals_; }
void ClearRemovals() { removals_.clear(); }
+ void StartJournalCleaningTimer() override {
+ IndexedDBBackingStore::StartJournalCleaningTimer();
+ }
+
protected:
~TestableIndexedDBBackingStore() override {}
@@ -157,11 +161,6 @@ class TestableIndexedDBBackingStore : public IndexedDBBackingStore {
return true;
}
- // Timers don't play nicely with unit tests.
- void StartJournalCleaningTimer() override {
- CleanPrimaryJournalIgnoreReturn();
- }
-
private:
TestableIndexedDBBackingStore(
IndexedDBFactory* indexed_db_factory,
@@ -1009,12 +1008,28 @@ TEST_F(IndexedDBBackingStoreTestWithBlobs, LiveBlobJournal) {
RunAllBlockingPoolTasksUntilIdle();
idb_context_->TaskRunner()->PostTask(
- FROM_HERE, base::BindOnce(
- [](IndexedDBBackingStoreTestWithBlobs* test) {
- EXPECT_NE(0U, test->backing_store()->removals().size());
- EXPECT_TRUE(test->CheckBlobRemovals());
- },
- base::Unretained(this)));
+ FROM_HERE,
+ base::BindOnce(
+ [](IndexedDBBackingStoreTestWithBlobs* test) {
+ EXPECT_TRUE(test->backing_store()->IsBlobCleanupPending());
+#if DCHECK_IS_ON()
+ EXPECT_EQ(3,
+ test->backing_store()
+ ->NumAggregatedJournalCleaningRequestsForTesting());
+#endif
+ for (int i = 3; i < IndexedDBBackingStore::kMaxJournalCleanRequests;
+ ++i) {
+ test->backing_store()->StartJournalCleaningTimer();
+ }
+ EXPECT_NE(0U, test->backing_store()->removals().size());
+ EXPECT_TRUE(test->CheckBlobRemovals());
+#if DCHECK_IS_ON()
+ EXPECT_EQ(0,
+ test->backing_store()->NumBlobFilesDeletedForTesting());
+#endif
+ EXPECT_FALSE(test->backing_store()->IsBlobCleanupPending());
+ },
+ base::Unretained(this)));
RunAllBlockingPoolTasksUntilIdle();
}
diff --git a/chromium/content/browser/indexed_db/indexed_db_browsertest.cc b/chromium/content/browser/indexed_db/indexed_db_browsertest.cc
index 6d933de6588..6be1328c275 100644
--- a/chromium/content/browser/indexed_db/indexed_db_browsertest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_browsertest.cc
@@ -462,7 +462,11 @@ IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTestWithGCExposed, DISABLED_BlobDidAck) {
SimpleTest(GetTestUrl("indexeddb", "blob_did_ack.html"));
// Wait for idle so that the blob ack has time to be received/processed by
// the browser process.
+ scoped_refptr<base::ThreadTestHelper> helper =
+ base::MakeRefCounted<base::ThreadTestHelper>(GetContext()->TaskRunner());
+ ASSERT_TRUE(helper->Run());
base::RunLoop().RunUntilIdle();
+ ASSERT_TRUE(helper->Run());
content::ChromeBlobStorageContext* blob_context =
ChromeBlobStorageContext::GetFor(
shell()->web_contents()->GetBrowserContext());
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 b687171bbc5..8c8dfcffb2b 100644
--- a/chromium/content/browser/indexed_db/indexed_db_context_impl.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_context_impl.cc
@@ -470,6 +470,10 @@ void IndexedDBContextImpl::DatabaseDeleted(const Origin& origin) {
QueryDiskAndUpdateQuotaUsage(origin);
}
+void IndexedDBContextImpl::BlobFilesCleaned(const url::Origin& origin) {
+ QueryDiskAndUpdateQuotaUsage(origin);
+}
+
IndexedDBContextImpl::~IndexedDBContextImpl() {
if (factory_.get()) {
TaskRunner()->PostTask(FROM_HERE,
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 3094888698e..24b3286334f 100644
--- a/chromium/content/browser/indexed_db/indexed_db_context_impl.h
+++ b/chromium/content/browser/indexed_db/indexed_db_context_impl.h
@@ -40,8 +40,7 @@ namespace content {
class IndexedDBConnection;
-class CONTENT_EXPORT IndexedDBContextImpl
- : NON_EXPORTED_BASE(public IndexedDBContext) {
+class CONTENT_EXPORT IndexedDBContextImpl : public IndexedDBContext {
public:
// Recorded in histograms, so append only.
enum ForceCloseReason {
@@ -92,6 +91,9 @@ class CONTENT_EXPORT IndexedDBContextImpl
static base::FilePath GetBlobStoreFileName(const url::Origin& origin);
static base::FilePath GetLevelDBFileName(const url::Origin& origin);
+ // Called when blob files have been cleaned (an aggregated delayed task).
+ void BlobFilesCleaned(const url::Origin& origin);
+
// Will be null in unit tests.
storage::QuotaManagerProxy* quota_manager_proxy() const {
return quota_manager_proxy_.get();
diff --git a/chromium/content/browser/indexed_db/indexed_db_database.h b/chromium/content/browser/indexed_db/indexed_db_database.h
index b7e42cfcd5f..91791fba94c 100644
--- a/chromium/content/browser/indexed_db/indexed_db_database.h
+++ b/chromium/content/browser/indexed_db/indexed_db_database.h
@@ -46,7 +46,7 @@ class IndexedDBTransaction;
struct IndexedDBValue;
class CONTENT_EXPORT IndexedDBDatabase
- : NON_EXPORTED_BASE(public base::RefCounted<IndexedDBDatabase>) {
+ : public base::RefCounted<IndexedDBDatabase> {
public:
// Identifier is pair of (origin, database name).
using Identifier = std::pair<url::Origin, base::string16>;
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 63115286cbf..a1f300323a3 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
@@ -144,7 +144,6 @@ class IndexedDBDispatcherHostTest : public testing::Test {
false /*is_incognito*/,
browser_context_.GetPath(),
BrowserThread::GetTaskRunnerForThread(BrowserThread::IO),
- base::ThreadTaskRunnerHandle::Get().get(),
special_storage_policy_)),
context_impl_(base::MakeRefCounted<IndexedDBContextImpl>(
CreateAndReturnTempDir(&temp_dir_),
diff --git a/chromium/content/browser/indexed_db/indexed_db_factory.h b/chromium/content/browser/indexed_db/indexed_db_factory.h
index 388b0cc605b..52c6878c4a1 100644
--- a/chromium/content/browser/indexed_db/indexed_db_factory.h
+++ b/chromium/content/browser/indexed_db/indexed_db_factory.h
@@ -35,7 +35,7 @@ struct IndexedDBPendingConnection;
struct IndexedDBDataLossInfo;
class CONTENT_EXPORT IndexedDBFactory
- : NON_EXPORTED_BASE(public base::RefCountedThreadSafe<IndexedDBFactory>) {
+ : public base::RefCountedThreadSafe<IndexedDBFactory> {
public:
typedef std::multimap<url::Origin, IndexedDBDatabase*> OriginDBMap;
typedef OriginDBMap::const_iterator OriginDBMapIterator;
@@ -92,6 +92,9 @@ class CONTENT_EXPORT IndexedDBFactory
virtual void DatabaseDeleted(
const IndexedDBDatabase::Identifier& identifier) = 0;
+ // Called by IndexedDBBackingStore when blob files have been cleaned.
+ virtual void BlobFilesCleaned(const url::Origin& origin) = 0;
+
virtual size_t GetConnectionCount(const url::Origin& origin) const = 0;
protected:
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 35d68e987b0..7471d6eacfe 100644
--- a/chromium/content/browser/indexed_db/indexed_db_factory_impl.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_factory_impl.cc
@@ -9,13 +9,18 @@
#include <utility>
#include <vector>
+#include "base/feature_list.h"
#include "base/logging.h"
+#include "base/memory/ptr_util.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/time/default_clock.h"
#include "base/time/time.h"
#include "content/browser/indexed_db/indexed_db_backing_store.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_pre_close_task_queue.h"
+#include "content/browser/indexed_db/indexed_db_tombstone_sweeper.h"
#include "content/browser/indexed_db/indexed_db_tracing.h"
#include "content/browser/indexed_db/indexed_db_transaction_coordinator.h"
#include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBDatabaseException.h"
@@ -26,7 +31,27 @@ using url::Origin;
namespace content {
-const int64_t kBackingStoreGracePeriodMs = 2000;
+namespace {
+
+using PreCloseTask = IndexedDBPreCloseTaskQueue::PreCloseTask;
+
+// Time after the last connection to a database is closed and when we destroy
+// the backing store.
+const int64_t kBackingStoreGracePeriodSeconds = 2;
+// Total time we let pre-close tasks run.
+const int64_t kPreCloseTasksMaxRunPeriodSeconds = 60;
+// The number of iterations for every 'round' of the tombstone sweeper.
+const int kTombstoneSweeperRoundIterations = 1000;
+// The maximum total iterations for the tombstone sweeper.
+const int kTombstoneSweeperMaxIterations = 10 * 1000 * 1000;
+
+const base::Feature kIDBTombstoneStatistics{"IDBTombstoneStatistics",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
+const base::Feature kIDBTombstoneDeletion{"IDBTombstoneDeletion",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
+} // namespace
IndexedDBFactoryImpl::IndexedDBFactoryImpl(IndexedDBContextImpl* context)
: context_(context) {
@@ -92,11 +117,51 @@ void IndexedDBFactoryImpl::ReleaseBackingStore(const Origin& origin,
// in the mean time.
DCHECK(!backing_store_map_[origin]->close_timer()->IsRunning());
backing_store_map_[origin]->close_timer()->Start(
- FROM_HERE, base::TimeDelta::FromMilliseconds(kBackingStoreGracePeriodMs),
- base::Bind(&IndexedDBFactoryImpl::MaybeCloseBackingStore, this, origin));
+ FROM_HERE, base::TimeDelta::FromSeconds(kBackingStoreGracePeriodSeconds),
+ base::Bind(&IndexedDBFactoryImpl::MaybeStartPreCloseTasks, this, origin));
+}
+
+void IndexedDBFactoryImpl::MaybeStartPreCloseTasks(const Origin& origin) {
+ // Another reference may have been created since the maybe-close was posted,
+ // so it is necessary to check again.
+ if (!HasLastBackingStoreReference(origin))
+ return;
+
+ bool tombstone_stats_enabled =
+ base::FeatureList::IsEnabled(kIDBTombstoneStatistics);
+ bool tombstone_deletion_enabled =
+ base::FeatureList::IsEnabled(kIDBTombstoneDeletion);
+
+ if (tombstone_stats_enabled == tombstone_deletion_enabled) {
+ // We can't have both stats and deletion, so NOOP if both are enabled.
+ MaybeCloseBackingStore(origin);
+ return;
+ }
+ scoped_refptr<IndexedDBBackingStore> store = backing_store_map_[origin];
+ // TODO(next patch in this cl): Create logic about which tasks get put here.
+ // * Min time since last sweep,
+ // * Only one sweep at a time for a context (or globaly?)
+ std::list<std::unique_ptr<PreCloseTask>> tasks;
+ IndexedDBTombstoneSweeper::Mode mode =
+ tombstone_stats_enabled ? IndexedDBTombstoneSweeper::Mode::STATISTICS
+ : IndexedDBTombstoneSweeper::Mode::DELETION;
+ tasks.push_back(base::MakeUnique<IndexedDBTombstoneSweeper>(
+ mode, kTombstoneSweeperRoundIterations, kTombstoneSweeperMaxIterations,
+ store->db()->db()));
+ // TODO(dmurph): Add compaction task that compacts all indexes if we have
+ // more than X deletions.
+
+ store->SetPreCloseTaskList(base::MakeUnique<IndexedDBPreCloseTaskQueue>(
+ std::move(tasks),
+ base::BindOnce(&IndexedDBFactoryImpl::MaybeCloseBackingStore, this,
+ origin),
+ base::TimeDelta::FromSeconds(kPreCloseTasksMaxRunPeriodSeconds),
+ base::MakeUnique<base::OneShotTimer>()));
+ store->StartPreCloseTasks();
}
void IndexedDBFactoryImpl::MaybeCloseBackingStore(const Origin& origin) {
+ backing_store_map_[origin]->SetPreCloseTaskList(nullptr);
// Another reference may have opened since the maybe-close was posted, so it
// is necessary to check again.
if (HasLastBackingStoreReference(origin))
@@ -106,9 +171,15 @@ void IndexedDBFactoryImpl::MaybeCloseBackingStore(const Origin& origin) {
void IndexedDBFactoryImpl::CloseBackingStore(const Origin& origin) {
const auto& it = backing_store_map_.find(origin);
DCHECK(it != backing_store_map_.end());
- // Stop the timer (if it's running) - this may happen if the timer was started
- // and then a forced close occurs.
- it->second->close_timer()->Stop();
+ // Stop the timer and pre close tasks (if they are running) - this may happen
+ // if the timer was started and then a forced close occurs.
+ scoped_refptr<IndexedDBBackingStore>& backing_store = it->second;
+ backing_store->close_timer()->Stop();
+ backing_store->SetPreCloseTaskList(nullptr);
+
+ if (backing_store->IsBlobCleanupPending())
+ backing_store->ForceRunBlobCleanup();
+
backing_store_map_.erase(it);
}
@@ -169,8 +240,10 @@ void IndexedDBFactoryImpl::ContextDestroyed() {
// context (which nominally owns this factory) is destroyed during thread
// termination the timers must be stopped so that this factory and the
// stores can be disposed of.
- for (const auto& it : backing_store_map_)
+ for (const auto& it : backing_store_map_) {
it.second->close_timer()->Stop();
+ it.second->SetPreCloseTaskList(nullptr);
+ }
backing_store_map_.clear();
backing_stores_with_active_blobs_.clear();
context_ = NULL;
@@ -324,6 +397,13 @@ void IndexedDBFactoryImpl::DatabaseDeleted(
context_->DatabaseDeleted(identifier.first);
}
+void IndexedDBFactoryImpl::BlobFilesCleaned(const url::Origin& origin) {
+ // NULL after ContextDestroyed() called, and in some unit tests.
+ if (!context_)
+ return;
+ context_->BlobFilesCleaned(origin);
+}
+
void IndexedDBFactoryImpl::AbortTransactionsAndCompactDatabase(
base::OnceCallback<void(leveldb::Status)> callback,
const Origin& origin) {
@@ -401,7 +481,8 @@ bool IndexedDBFactoryImpl::IsBackingStorePendingClose(
const auto& it = backing_store_map_.find(origin);
if (it == backing_store_map_.end())
return false;
- return it->second->close_timer()->IsRunning();
+ return it->second->close_timer()->IsRunning() ||
+ it->second->pre_close_task_queue();
}
scoped_refptr<IndexedDBBackingStore>
@@ -430,6 +511,10 @@ scoped_refptr<IndexedDBBackingStore> IndexedDBFactoryImpl::OpenBackingStore(
const auto& it2 = backing_store_map_.find(origin);
if (it2 != backing_store_map_.end()) {
it2->second->close_timer()->Stop();
+ if (it2->second->pre_close_task_queue()) {
+ it2->second->pre_close_task_queue()->StopForNewConnection();
+ it2->second->SetPreCloseTaskList(nullptr);
+ }
return it2->second;
}
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 6182e4395d1..4f22e92ca0f 100644
--- a/chromium/content/browser/indexed_db/indexed_db_factory_impl.h
+++ b/chromium/content/browser/indexed_db/indexed_db_factory_impl.h
@@ -78,6 +78,9 @@ class CONTENT_EXPORT IndexedDBFactoryImpl : public IndexedDBFactory {
void DatabaseDeleted(
const IndexedDBDatabase::Identifier& identifier) override;
+ // Called by IndexedDBBackingStore when blob files have been cleaned.
+ void BlobFilesCleaned(const url::Origin& origin) override;
+
size_t GetConnectionCount(const url::Origin& origin) const override;
protected:
@@ -122,7 +125,10 @@ class CONTENT_EXPORT IndexedDBFactoryImpl : public IndexedDBFactory {
leveldb::Status AbortTransactions(const url::Origin& origin);
// Called internally after a database is closed, with some delay. If this
- // factory has the last reference, it will be released.
+ // factory has the last reference it will start running pre-close tasks.
+ void MaybeStartPreCloseTasks(const url::Origin& origin);
+ // Called internally after pre-close tasks. If this factory has the last
+ // reference it will be released.
void MaybeCloseBackingStore(const url::Origin& origin);
bool HasLastBackingStoreReference(const url::Origin& origin) const;
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 99153ca483b..ec343c3158c 100644
--- a/chromium/content/browser/indexed_db/indexed_db_internals_ui.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_internals_ui.cc
@@ -293,7 +293,7 @@ void IndexedDBInternalsUI::OnDownloadDataReady(
destination: LOCAL
}
policy {
- cookies_allowed: false
+ cookies_allowed: NO
setting:
"This feature cannot be disabled by settings, but it's only "
"triggered by navigating to the specified URL."
diff --git a/chromium/content/browser/indexed_db/indexed_db_leveldb_coding.cc b/chromium/content/browser/indexed_db/indexed_db_leveldb_coding.cc
index 69ac157b45f..da690f5128c 100644
--- a/chromium/content/browser/indexed_db/indexed_db_leveldb_coding.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_leveldb_coding.cc
@@ -1783,15 +1783,20 @@ IndexDataKey::IndexDataKey()
index_id_(-1),
sequence_number_(-1) {}
+IndexDataKey::IndexDataKey(IndexDataKey&& other) = default;
+
IndexDataKey::~IndexDataKey() {}
bool IndexDataKey::Decode(StringPiece* slice, IndexDataKey* result) {
KeyPrefix prefix;
if (!KeyPrefix::Decode(slice, &prefix))
return false;
- DCHECK(prefix.database_id_);
- DCHECK(prefix.object_store_id_);
- DCHECK_GE(prefix.index_id_, kMinimumIndexId);
+ if (prefix.database_id_ <= 0)
+ return false;
+ if (prefix.object_store_id_ <= 0)
+ return false;
+ if (prefix.index_id_ < kMinimumIndexId)
+ return false;
result->database_id_ = prefix.database_id_;
result->object_store_id_ = prefix.object_store_id_;
result->index_id_ = prefix.index_id_;
@@ -1870,6 +1875,11 @@ std::string IndexDataKey::EncodeMaxKey(int64_t database_id,
MaxIDBKey(), std::numeric_limits<int64_t>::max());
}
+std::string IndexDataKey::Encode() const {
+ return Encode(database_id_, object_store_id_, index_id_, encoded_user_key_,
+ encoded_primary_key_, sequence_number_);
+}
+
int64_t IndexDataKey::DatabaseId() const {
DCHECK_GE(database_id_, 0);
return database_id_;
diff --git a/chromium/content/browser/indexed_db/indexed_db_leveldb_coding.h b/chromium/content/browser/indexed_db/indexed_db_leveldb_coding.h
index d6818f76f45..88cd51e8aa5 100644
--- a/chromium/content/browser/indexed_db/indexed_db_leveldb_coding.h
+++ b/chromium/content/browser/indexed_db/indexed_db_leveldb_coding.h
@@ -453,9 +453,11 @@ class BlobEntryKey {
class IndexDataKey {
public:
- IndexDataKey();
- ~IndexDataKey();
- static bool Decode(base::StringPiece* slice, IndexDataKey* result);
+ CONTENT_EXPORT IndexDataKey();
+ CONTENT_EXPORT IndexDataKey(IndexDataKey&& other);
+ CONTENT_EXPORT ~IndexDataKey();
+ CONTENT_EXPORT static bool Decode(base::StringPiece* slice,
+ IndexDataKey* result);
CONTENT_EXPORT static std::string Encode(
int64_t database_id,
int64_t object_store_id,
@@ -467,14 +469,15 @@ class IndexDataKey {
int64_t object_store_id,
int64_t index_id,
const IndexedDBKey& user_key);
- static std::string Encode(int64_t database_id,
- int64_t object_store_id,
- int64_t index_id,
- const IndexedDBKey& user_key,
- const IndexedDBKey& user_primary_key);
- static std::string EncodeMinKey(int64_t database_id,
- int64_t object_store_id,
- int64_t index_id);
+ CONTENT_EXPORT static std::string Encode(
+ int64_t database_id,
+ int64_t object_store_id,
+ int64_t index_id,
+ const IndexedDBKey& user_key,
+ const IndexedDBKey& user_primary_key);
+ CONTENT_EXPORT static std::string EncodeMinKey(int64_t database_id,
+ int64_t object_store_id,
+ int64_t index_id);
CONTENT_EXPORT static std::string EncodeMaxKey(int64_t database_id,
int64_t object_store_id,
int64_t index_id);
@@ -484,6 +487,8 @@ class IndexDataKey {
std::unique_ptr<IndexedDBKey> user_key() const;
std::unique_ptr<IndexedDBKey> primary_key() const;
+ CONTENT_EXPORT std::string Encode() const;
+
private:
int64_t database_id_;
int64_t object_store_id_;
diff --git a/chromium/content/browser/indexed_db/indexed_db_leveldb_coding_unittest.cc b/chromium/content/browser/indexed_db/indexed_db_leveldb_coding_unittest.cc
index 5d6db97bee9..d2e4e8e775c 100644
--- a/chromium/content/browser/indexed_db/indexed_db_leveldb_coding_unittest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_leveldb_coding_unittest.cc
@@ -965,6 +965,37 @@ TEST(IndexedDBLevelDBCodingTest, ComparisonTest) {
}
}
+TEST(IndexedDBLevelDBCodingTest, IndexDataKeyEncodeDecode) {
+ std::vector<std::string> keys;
+ keys.push_back(IndexDataKey::Encode(1, 1, 30, MinIDBKey(), MinIDBKey(), 0));
+ keys.push_back(IndexDataKey::Encode(1, 1, 30, MinIDBKey(), MinIDBKey(), 1));
+ keys.push_back(
+ IndexDataKey::Encode(1, 1, 30, IndexedDBKey(ASCIIToUTF16("user key")),
+ IndexedDBKey(ASCIIToUTF16("primary key"))));
+ keys.push_back(IndexDataKey::Encode(1, 1, 30, MinIDBKey(), MaxIDBKey(), 0));
+ keys.push_back(IndexDataKey::Encode(1, 1, 30, MinIDBKey(), MaxIDBKey(), 1));
+ keys.push_back(IndexDataKey::Encode(1, 1, 30, MaxIDBKey(), MinIDBKey(), 0));
+ keys.push_back(IndexDataKey::Encode(1, 1, 30, MaxIDBKey(), MinIDBKey(), 1));
+ keys.push_back(IndexDataKey::Encode(1, 1, 30, MaxIDBKey(), MaxIDBKey(), 0));
+ keys.push_back(IndexDataKey::Encode(1, 1, 30, MaxIDBKey(), MaxIDBKey(), 1));
+ keys.push_back(IndexDataKey::Encode(1, 1, 31, MinIDBKey(), MinIDBKey(), 0));
+ keys.push_back(IndexDataKey::Encode(1, 2, 30, MinIDBKey(), MinIDBKey(), 0));
+ keys.push_back(IndexDataKey::EncodeMaxKey(
+ 1, 2, std::numeric_limits<int32_t>::max() - 1));
+
+ std::vector<IndexDataKey> obj_keys;
+ for (const std::string& key : keys) {
+ base::StringPiece piece(key);
+ IndexDataKey obj_key;
+ EXPECT_TRUE(IndexDataKey::Decode(&piece, &obj_key));
+ obj_keys.push_back(std::move(obj_key));
+ }
+
+ for (size_t i = 0; i < keys.size(); ++i) {
+ EXPECT_EQ(keys[i], obj_keys[i].Encode()) << "key at " << i;
+ }
+}
+
TEST(IndexedDBLevelDBCodingTest, EncodeVarIntVSEncodeByteTest) {
std::vector<unsigned char> test_cases;
test_cases.push_back(0);
diff --git a/chromium/content/browser/indexed_db/indexed_db_pre_close_task_queue.cc b/chromium/content/browser/indexed_db/indexed_db_pre_close_task_queue.cc
new file mode 100644
index 00000000000..fdab955dea6
--- /dev/null
+++ b/chromium/content/browser/indexed_db/indexed_db_pre_close_task_queue.cc
@@ -0,0 +1,121 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/indexed_db/indexed_db_pre_close_task_queue.h"
+
+#include "base/metrics/histogram_macros.h"
+#include "base/threading/sequenced_task_runner_handle.h"
+#include "third_party/leveldatabase/env_chromium.h"
+
+namespace content {
+
+IndexedDBPreCloseTaskQueue::PreCloseTask::~PreCloseTask() {}
+
+IndexedDBPreCloseTaskQueue::IndexedDBPreCloseTaskQueue(
+ std::list<std::unique_ptr<IndexedDBPreCloseTaskQueue::PreCloseTask>> tasks,
+ base::OnceClosure on_complete,
+ base::TimeDelta max_run_time,
+ std::unique_ptr<base::Timer> timer)
+ : tasks_(std::move(tasks)),
+ on_done_(std::move(on_complete)),
+ timeout_time_(max_run_time),
+ timeout_timer_(std::move(timer)),
+ task_runner_(base::SequencedTaskRunnerHandle::Get()),
+ ptr_factory_(this) {}
+IndexedDBPreCloseTaskQueue::~IndexedDBPreCloseTaskQueue() {}
+
+void IndexedDBPreCloseTaskQueue::StopForNewConnection() {
+ if (!started_ || done_)
+ return;
+ DCHECK(!tasks_.empty());
+ while (!tasks_.empty()) {
+ tasks_.front()->Stop(StopReason::NEW_CONNECTION);
+ tasks_.pop_front();
+ }
+ OnComplete();
+}
+
+void IndexedDBPreCloseTaskQueue::Start(
+ base::OnceCallback<leveldb::Status(std::vector<IndexedDBDatabaseMetadata>*)>
+ metadata_fetcher) {
+ DCHECK(!started_);
+ started_ = true;
+ if (tasks_.empty()) {
+ OnComplete();
+ return;
+ }
+ timeout_timer_->Start(FROM_HERE, timeout_time_,
+ base::Bind(&IndexedDBPreCloseTaskQueue::StopForTimout,
+ ptr_factory_.GetWeakPtr()));
+ leveldb::Status status = std::move(metadata_fetcher).Run(&metadata_);
+ if (!status.ok()) {
+ StopForMetadataError(status);
+ return;
+ }
+ tasks_.front()->SetMetadata(&metadata_);
+ task_runner_->PostTask(FROM_HERE,
+ base::Bind(&IndexedDBPreCloseTaskQueue::RunLoop,
+ ptr_factory_.GetWeakPtr()));
+}
+
+void IndexedDBPreCloseTaskQueue::OnComplete() {
+ DCHECK(started_);
+ DCHECK(!done_);
+ ptr_factory_.InvalidateWeakPtrs();
+ timeout_timer_->Stop();
+ done_ = true;
+ std::move(on_done_).Run();
+}
+
+void IndexedDBPreCloseTaskQueue::StopForTimout() {
+ DCHECK(started_);
+ if (done_)
+ return;
+ while (!tasks_.empty()) {
+ tasks_.front()->Stop(StopReason::TIMEOUT);
+ tasks_.pop_front();
+ }
+ OnComplete();
+}
+
+void IndexedDBPreCloseTaskQueue::StopForMetadataError(
+ const leveldb::Status& status) {
+ if (done_)
+ return;
+
+ LOCAL_HISTOGRAM_ENUMERATION(
+ "WebCore.IndexedDB.IndexedDBPreCloseTaskList.MetadataError",
+ leveldb_env::GetLevelDBStatusUMAValue(status),
+ leveldb_env::LEVELDB_STATUS_MAX);
+ while (!tasks_.empty()) {
+ tasks_.front()->Stop(StopReason::METADATA_ERROR);
+ tasks_.pop_front();
+ }
+ OnComplete();
+}
+
+void IndexedDBPreCloseTaskQueue::RunLoop() {
+ if (done_)
+ return;
+
+ if (tasks_.empty()) {
+ OnComplete();
+ return;
+ }
+
+ bool done = tasks_.front()->RunRound();
+ if (done) {
+ tasks_.pop_front();
+ if (tasks_.empty()) {
+ OnComplete();
+ return;
+ }
+ tasks_.front()->SetMetadata(&metadata_);
+ }
+ task_runner_->PostTask(FROM_HERE,
+ base::Bind(&IndexedDBPreCloseTaskQueue::RunLoop,
+ ptr_factory_.GetWeakPtr()));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/indexed_db/indexed_db_pre_close_task_queue.h b/chromium/content/browser/indexed_db/indexed_db_pre_close_task_queue.h
new file mode 100644
index 00000000000..4010a5a4271
--- /dev/null
+++ b/chromium/content/browser/indexed_db/indexed_db_pre_close_task_queue.h
@@ -0,0 +1,109 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_PRE_CLOSE_TASK_QUEUE_H_
+#define CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_PRE_CLOSE_TASK_QUEUE_H_
+
+#include <list>
+#include <memory>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
+#include "content/common/indexed_db/indexed_db_metadata.h"
+#include "third_party/leveldatabase/src/include/leveldb/status.h"
+
+namespace content {
+
+// Holds a queue of PreCloseTask's to be run after an IndexedDBBackingStore no
+// longer has any connections.
+//
+// There is a special IndexedDBMetadata fetcher task that runs beofre all the
+// other tasks, and whose output is passed to each task before they start.
+//
+// Owned by IndexedDBBackingStore.
+class CONTENT_EXPORT IndexedDBPreCloseTaskQueue {
+ public:
+ enum class StopReason {
+ // A new connection was made to the closing backing store.
+ NEW_CONNECTION,
+ // The maximum time for all tasks to complete as passed.
+ TIMEOUT,
+ // There was an error reading the database metadata.
+ METADATA_ERROR,
+ };
+
+ // Defines a task that will be run after closing an IndexedDB backing store
+ // instance. The task can be destructed at any time if the browser process is
+ // shutting down, otherwise Stop(...) will be called.
+ // Instances of this class are sequence-hostile. Each instance must only be
+ // used on the same SequencedTaskRunner.
+ class CONTENT_EXPORT PreCloseTask {
+ public:
+ virtual ~PreCloseTask();
+
+ // Called before RunRound. |metadata| is guaranteed to outlive this task.
+ virtual void SetMetadata(
+ std::vector<IndexedDBDatabaseMetadata> const* metadata) = 0;
+
+ // Tells the task to stop before completion. It will be destroyed after this
+ // call. Can be called at any time.
+ virtual void Stop(StopReason reason) = 0;
+
+ // Runs a round of work. Tasks are expected to keep round execution time
+ // small. Returns if the task is complete and can be destroyed.
+ virtual bool RunRound() = 0;
+ };
+
+ // |on_complete| must not contain a refptr to the IndexedDBBackingStore, as
+ // this would create a cycle.
+ IndexedDBPreCloseTaskQueue(std::list<std::unique_ptr<PreCloseTask>> tasks,
+ base::OnceClosure on_complete,
+ base::TimeDelta max_run_time,
+ std::unique_ptr<base::Timer> timer);
+ ~IndexedDBPreCloseTaskQueue();
+
+ bool started() const { return started_; }
+
+ // Tasks are all complete or they have been stopped.
+ bool done() const { return done_; }
+
+ // Stops all tasks and destroys them. The |on_complete| callback will be
+ // immediately called.
+ void StopForNewConnection();
+
+ // Starts running tasks. Can only be called once.
+ void Start(base::OnceCallback<leveldb::Status(
+ std::vector<IndexedDBDatabaseMetadata>*)> metadata_fetcher);
+
+ private:
+ void OnComplete();
+
+ void StopForTimout();
+ void StopForMetadataError(const leveldb::Status& status);
+
+ void RunLoop();
+
+ std::vector<IndexedDBDatabaseMetadata> metadata_;
+
+ bool started_ = false;
+ bool done_ = false;
+ std::list<std::unique_ptr<PreCloseTask>> tasks_;
+ base::OnceClosure on_done_;
+
+ base::TimeDelta timeout_time_;
+ std::unique_ptr<base::Timer> timeout_timer_;
+ scoped_refptr<base::SequencedTaskRunner> task_runner_;
+
+ base::WeakPtrFactory<IndexedDBPreCloseTaskQueue> ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(IndexedDBPreCloseTaskQueue);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_PRE_CLOSE_TASK_QUEUE_H_
diff --git a/chromium/content/browser/indexed_db/indexed_db_pre_close_task_queue_unittest.cc b/chromium/content/browser/indexed_db/indexed_db_pre_close_task_queue_unittest.cc
new file mode 100644
index 00000000000..d8ffcc5a04b
--- /dev/null
+++ b/chromium/content/browser/indexed_db/indexed_db_pre_close_task_queue_unittest.cc
@@ -0,0 +1,414 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/indexed_db/indexed_db_pre_close_task_queue.h"
+
+#include <memory>
+
+#include "base/memory/ptr_util.h"
+#include "base/run_loop.h"
+#include "base/strings/string16.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/test/scoped_task_environment.h"
+#include "base/time/time.h"
+#include "base/timer/mock_timer.h"
+#include "base/timer/timer.h"
+#include "content/common/indexed_db/indexed_db_metadata.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+using PreCloseTask = IndexedDBPreCloseTaskQueue::PreCloseTask;
+using StopReason = IndexedDBPreCloseTaskQueue::StopReason;
+
+namespace {
+constexpr base::TimeDelta kTestMaxRunTime = base::TimeDelta::FromSeconds(30);
+const base::string16 kDBName = base::ASCIIToUTF16("TestDBName");
+constexpr int64_t kDBId = 1;
+constexpr int64_t kDBVersion = 2;
+constexpr int64_t kDBMaxObjectStoreId = 29;
+
+ACTION_P2(RunClosureThenReturn, closure, ret) {
+ closure.Run();
+ return ret;
+}
+
+class MockPreCloseTask : public PreCloseTask {
+ public:
+ MockPreCloseTask() {}
+ ~MockPreCloseTask() {}
+
+ MOCK_METHOD1(SetMetadata,
+ void(std::vector<IndexedDBDatabaseMetadata> const* metadata));
+
+ MOCK_METHOD1(Stop, void(StopReason reason));
+
+ MOCK_METHOD0(RunRound, bool());
+};
+
+void SetBoolValue(bool* pointer, bool value_to_set) {
+ DCHECK(pointer);
+ *pointer = value_to_set;
+}
+
+leveldb::Status MetadataFetcher(
+ bool* called,
+ leveldb::Status return_status,
+ std::vector<IndexedDBDatabaseMetadata>* metadata,
+ std::vector<IndexedDBDatabaseMetadata>* output_metadata) {
+ *called = true;
+ *output_metadata = *metadata;
+ return return_status;
+}
+
+class IndexedDBPreCloseTaskQueueTest : public testing::Test {
+ public:
+ IndexedDBPreCloseTaskQueueTest() {
+ metadata_.push_back(IndexedDBDatabaseMetadata(kDBName, kDBId, kDBVersion,
+ kDBMaxObjectStoreId));
+ }
+ ~IndexedDBPreCloseTaskQueueTest() override {}
+
+ protected:
+ std::vector<IndexedDBDatabaseMetadata> metadata_;
+ base::test::ScopedTaskEnvironment scoped_task_environment_;
+};
+
+TEST_F(IndexedDBPreCloseTaskQueueTest, NoTasks) {
+ bool done_called = false;
+ bool metadata_called = false;
+
+ base::MockTimer* fake_timer = new base::MockTimer(true, false);
+ IndexedDBPreCloseTaskQueue queue(
+ std::list<std::unique_ptr<PreCloseTask>>(),
+ base::BindOnce(&SetBoolValue, &done_called, true), kTestMaxRunTime,
+ base::WrapUnique(fake_timer));
+
+ queue.Start(base::BindOnce(&MetadataFetcher, &metadata_called,
+ leveldb::Status::OK(), &metadata_));
+
+ EXPECT_FALSE(metadata_called);
+ EXPECT_TRUE(done_called);
+ EXPECT_TRUE(queue.started());
+ EXPECT_TRUE(queue.done());
+}
+
+TEST_F(IndexedDBPreCloseTaskQueueTest, TaskOneRound) {
+ bool done_called = false;
+ bool metadata_called = false;
+
+ MockPreCloseTask* task = new testing::StrictMock<MockPreCloseTask>();
+
+ EXPECT_CALL(*task,
+ SetMetadata(testing::Pointee(testing::ContainerEq(metadata_))));
+
+ base::MockTimer* fake_timer = new base::MockTimer(true, false);
+ std::list<std::unique_ptr<PreCloseTask>> tasks;
+ tasks.push_back(base::WrapUnique(task));
+ IndexedDBPreCloseTaskQueue queue(
+ std::move(tasks), base::BindOnce(&SetBoolValue, &done_called, true),
+ kTestMaxRunTime, base::WrapUnique(fake_timer));
+
+ queue.Start(base::BindOnce(&MetadataFetcher, &metadata_called,
+ leveldb::Status::OK(), &metadata_));
+
+ // Expect calls are posted as tasks.
+ EXPECT_CALL(*task, RunRound()).WillOnce(testing::Return(true));
+
+ scoped_task_environment_.RunUntilIdle();
+
+ EXPECT_TRUE(metadata_called);
+ EXPECT_TRUE(done_called);
+ EXPECT_TRUE(queue.started());
+ EXPECT_TRUE(queue.done());
+}
+
+TEST_F(IndexedDBPreCloseTaskQueueTest, TaskTwoRounds) {
+ bool done_called = false;
+ bool metadata_called = false;
+
+ MockPreCloseTask* task = new testing::StrictMock<MockPreCloseTask>();
+
+ EXPECT_CALL(*task,
+ SetMetadata(testing::Pointee(testing::ContainerEq(metadata_))));
+
+ base::MockTimer* fake_timer = new base::MockTimer(true, false);
+ std::list<std::unique_ptr<PreCloseTask>> tasks;
+ tasks.push_back(base::WrapUnique(task));
+ IndexedDBPreCloseTaskQueue queue(
+ std::move(tasks), base::BindOnce(&SetBoolValue, &done_called, true),
+ kTestMaxRunTime, base::WrapUnique(fake_timer));
+
+ queue.Start(base::BindOnce(&MetadataFetcher, &metadata_called,
+ leveldb::Status::OK(), &metadata_));
+
+ EXPECT_FALSE(queue.done());
+
+ {
+ base::RunLoop loop;
+
+ EXPECT_CALL(*task, RunRound())
+ .WillOnce(RunClosureThenReturn(loop.QuitClosure(), false));
+
+ loop.Run();
+ }
+
+ EXPECT_FALSE(done_called);
+ EXPECT_TRUE(queue.started());
+ EXPECT_FALSE(queue.done());
+
+ EXPECT_CALL(*task, RunRound()).WillOnce(testing::Return(true));
+ scoped_task_environment_.RunUntilIdle();
+
+ EXPECT_TRUE(metadata_called);
+ EXPECT_TRUE(done_called);
+ EXPECT_TRUE(queue.started());
+ EXPECT_TRUE(queue.done());
+}
+
+TEST_F(IndexedDBPreCloseTaskQueueTest, TwoTasks) {
+ bool done_called = false;
+ bool metadata_called = false;
+
+ MockPreCloseTask* task1 = new testing::StrictMock<MockPreCloseTask>();
+ MockPreCloseTask* task2 = new testing::StrictMock<MockPreCloseTask>();
+
+ EXPECT_CALL(*task1,
+ SetMetadata(testing::Pointee(testing::ContainerEq(metadata_))));
+
+ base::MockTimer* fake_timer = new base::MockTimer(true, false);
+ std::list<std::unique_ptr<PreCloseTask>> tasks;
+ tasks.push_back(base::WrapUnique(task1));
+ tasks.push_back(base::WrapUnique(task2));
+ IndexedDBPreCloseTaskQueue queue(
+ std::move(tasks), base::BindOnce(&SetBoolValue, &done_called, true),
+ kTestMaxRunTime, base::WrapUnique(fake_timer));
+
+ queue.Start(base::BindOnce(&MetadataFetcher, &metadata_called,
+ leveldb::Status::OK(), &metadata_));
+
+ EXPECT_FALSE(queue.done());
+
+ {
+ base::RunLoop loop;
+
+ EXPECT_CALL(*task1, RunRound())
+ .WillOnce(RunClosureThenReturn(loop.QuitClosure(), true));
+ EXPECT_CALL(*task2,
+ SetMetadata(testing::Pointee(testing::ContainerEq(metadata_))));
+
+ loop.Run();
+ }
+
+ {
+ base::RunLoop loop;
+
+ EXPECT_CALL(*task2, RunRound())
+ .WillOnce(RunClosureThenReturn(loop.QuitClosure(), true));
+
+ loop.Run();
+ }
+
+ EXPECT_TRUE(metadata_called);
+ EXPECT_TRUE(done_called);
+ EXPECT_TRUE(queue.started());
+ EXPECT_TRUE(queue.done());
+}
+
+TEST_F(IndexedDBPreCloseTaskQueueTest, StopForNewConnectionBeforeStart) {
+ bool done_called = false;
+ bool metadata_called = false;
+
+ MockPreCloseTask* task1 = new testing::StrictMock<MockPreCloseTask>();
+ MockPreCloseTask* task2 = new testing::StrictMock<MockPreCloseTask>();
+
+ EXPECT_CALL(*task1,
+ SetMetadata(testing::Pointee(testing::ContainerEq(metadata_))));
+
+ base::MockTimer* fake_timer = new base::MockTimer(true, false);
+ std::list<std::unique_ptr<PreCloseTask>> tasks;
+ tasks.push_back(base::WrapUnique(task1));
+ tasks.push_back(base::WrapUnique(task2));
+ IndexedDBPreCloseTaskQueue queue(
+ std::move(tasks), base::BindOnce(&SetBoolValue, &done_called, true),
+ kTestMaxRunTime, base::WrapUnique(fake_timer));
+
+ queue.Start(base::BindOnce(&MetadataFetcher, &metadata_called,
+ leveldb::Status::OK(), &metadata_));
+
+ EXPECT_CALL(*task1, Stop(StopReason::NEW_CONNECTION));
+ EXPECT_CALL(*task2, Stop(StopReason::NEW_CONNECTION));
+
+ queue.StopForNewConnection();
+
+ scoped_task_environment_.RunUntilIdle();
+
+ EXPECT_TRUE(metadata_called);
+ EXPECT_TRUE(done_called);
+ EXPECT_TRUE(queue.started());
+ EXPECT_TRUE(queue.done());
+}
+
+TEST_F(IndexedDBPreCloseTaskQueueTest, StopForNewConnectionAfterRound) {
+ bool done_called = false;
+ bool metadata_called = false;
+
+ MockPreCloseTask* task = new testing::StrictMock<MockPreCloseTask>();
+
+ EXPECT_CALL(*task,
+ SetMetadata(testing::Pointee(testing::ContainerEq(metadata_))));
+
+ base::MockTimer* fake_timer = new base::MockTimer(true, false);
+ std::list<std::unique_ptr<PreCloseTask>> tasks;
+ tasks.push_back(base::WrapUnique(task));
+ IndexedDBPreCloseTaskQueue queue(
+ std::move(tasks), base::BindOnce(&SetBoolValue, &done_called, true),
+ kTestMaxRunTime, base::WrapUnique(fake_timer));
+
+ queue.Start(base::BindOnce(&MetadataFetcher, &metadata_called,
+ leveldb::Status::OK(), &metadata_));
+
+ {
+ base::RunLoop loop;
+
+ EXPECT_CALL(*task, RunRound())
+ .WillOnce(RunClosureThenReturn(loop.QuitClosure(), false));
+
+ loop.Run();
+ }
+
+ EXPECT_CALL(*task, Stop(StopReason::NEW_CONNECTION));
+
+ queue.StopForNewConnection();
+
+ scoped_task_environment_.RunUntilIdle();
+
+ EXPECT_TRUE(metadata_called);
+ EXPECT_TRUE(done_called);
+ EXPECT_TRUE(queue.started());
+ EXPECT_TRUE(queue.done());
+}
+
+TEST_F(IndexedDBPreCloseTaskQueueTest, StopForNewConnectionAfterTaskCompletes) {
+ bool done_called = false;
+ bool metadata_called = false;
+
+ MockPreCloseTask* task1 = new testing::StrictMock<MockPreCloseTask>();
+ MockPreCloseTask* task2 = new testing::StrictMock<MockPreCloseTask>();
+
+ EXPECT_CALL(*task1,
+ SetMetadata(testing::Pointee(testing::ContainerEq(metadata_))));
+
+ base::MockTimer* fake_timer = new base::MockTimer(true, false);
+ std::list<std::unique_ptr<PreCloseTask>> tasks;
+ tasks.push_back(base::WrapUnique(task1));
+ tasks.push_back(base::WrapUnique(task2));
+ IndexedDBPreCloseTaskQueue queue(
+ std::move(tasks), base::BindOnce(&SetBoolValue, &done_called, true),
+ kTestMaxRunTime, base::WrapUnique(fake_timer));
+
+ queue.Start(base::BindOnce(&MetadataFetcher, &metadata_called,
+ leveldb::Status::OK(), &metadata_));
+
+ {
+ base::RunLoop loop;
+
+ EXPECT_CALL(*task1, RunRound())
+ .WillOnce(RunClosureThenReturn(loop.QuitClosure(), true));
+ EXPECT_CALL(*task2,
+ SetMetadata(testing::Pointee(testing::ContainerEq(metadata_))));
+
+ loop.Run();
+ }
+
+ EXPECT_CALL(*task2, Stop(StopReason::NEW_CONNECTION));
+
+ queue.StopForNewConnection();
+
+ scoped_task_environment_.RunUntilIdle();
+
+ EXPECT_TRUE(metadata_called);
+ EXPECT_TRUE(done_called);
+ EXPECT_TRUE(queue.started());
+ EXPECT_TRUE(queue.done());
+}
+
+TEST_F(IndexedDBPreCloseTaskQueueTest, StopForTimout) {
+ bool done_called = false;
+ bool metadata_called = false;
+
+ MockPreCloseTask* task1 = new testing::StrictMock<MockPreCloseTask>();
+ MockPreCloseTask* task2 = new testing::StrictMock<MockPreCloseTask>();
+
+ EXPECT_CALL(*task1,
+ SetMetadata(testing::Pointee(testing::ContainerEq(metadata_))));
+
+ base::MockTimer* fake_timer = new base::MockTimer(true, false);
+ std::list<std::unique_ptr<PreCloseTask>> tasks;
+ tasks.push_back(base::WrapUnique(task1));
+ tasks.push_back(base::WrapUnique(task2));
+ IndexedDBPreCloseTaskQueue queue(
+ std::move(tasks), base::BindOnce(&SetBoolValue, &done_called, true),
+ kTestMaxRunTime, base::WrapUnique(fake_timer));
+
+ queue.Start(base::BindOnce(&MetadataFetcher, &metadata_called,
+ leveldb::Status::OK(), &metadata_));
+
+ EXPECT_FALSE(queue.done());
+
+ {
+ base::RunLoop loop;
+
+ EXPECT_CALL(*task1, RunRound())
+ .WillOnce(RunClosureThenReturn(loop.QuitClosure(), true));
+ EXPECT_CALL(*task2,
+ SetMetadata(testing::Pointee(testing::ContainerEq(metadata_))));
+
+ loop.Run();
+ }
+ EXPECT_CALL(*task2, Stop(StopReason::TIMEOUT));
+
+ fake_timer->Fire();
+
+ scoped_task_environment_.RunUntilIdle();
+
+ EXPECT_TRUE(metadata_called);
+ EXPECT_TRUE(done_called);
+ EXPECT_TRUE(queue.started());
+ EXPECT_TRUE(queue.done());
+}
+
+TEST_F(IndexedDBPreCloseTaskQueueTest, MetadataError) {
+ bool done_called = false;
+ bool metadata_called = false;
+
+ MockPreCloseTask* task1 = new testing::StrictMock<MockPreCloseTask>();
+ MockPreCloseTask* task2 = new testing::StrictMock<MockPreCloseTask>();
+
+ base::MockTimer* fake_timer = new base::MockTimer(true, false);
+ std::list<std::unique_ptr<PreCloseTask>> tasks;
+ tasks.push_back(base::WrapUnique(task1));
+ tasks.push_back(base::WrapUnique(task2));
+ IndexedDBPreCloseTaskQueue queue(
+ std::move(tasks), base::BindOnce(&SetBoolValue, &done_called, true),
+ kTestMaxRunTime, base::WrapUnique(fake_timer));
+
+ EXPECT_CALL(*task1, Stop(StopReason::METADATA_ERROR));
+ EXPECT_CALL(*task2, Stop(StopReason::METADATA_ERROR));
+
+ queue.Start(base::BindOnce(&MetadataFetcher, &metadata_called,
+ leveldb::Status::IOError(""), &metadata_));
+
+ scoped_task_environment_.RunUntilIdle();
+
+ EXPECT_TRUE(metadata_called);
+ EXPECT_TRUE(done_called);
+ EXPECT_TRUE(queue.started());
+ EXPECT_TRUE(queue.done());
+}
+
+} // namespace
+
+} // namespace content
diff --git a/chromium/content/browser/indexed_db/indexed_db_quota_client_unittest.cc b/chromium/content/browser/indexed_db/indexed_db_quota_client_unittest.cc
index 8474e399864..5253c7bd773 100644
--- a/chromium/content/browser/indexed_db/indexed_db_quota_client_unittest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_quota_client_unittest.cc
@@ -49,7 +49,6 @@ class IndexedDBQuotaClientTest : public testing::Test {
scoped_refptr<storage::QuotaManager> quota_manager =
new MockQuotaManager(false /*in_memory*/, browser_context_->GetPath(),
base::ThreadTaskRunnerHandle::Get(),
- base::SequencedTaskRunnerHandle::Get(),
browser_context_->GetSpecialStoragePolicy());
idb_context_ = new IndexedDBContextImpl(
diff --git a/chromium/content/browser/indexed_db/indexed_db_tombstone_sweeper.cc b/chromium/content/browser/indexed_db/indexed_db_tombstone_sweeper.cc
new file mode 100644
index 00000000000..16ed903a7ee
--- /dev/null
+++ b/chromium/content/browser/indexed_db/indexed_db_tombstone_sweeper.cc
@@ -0,0 +1,465 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/indexed_db/indexed_db_tombstone_sweeper.h"
+
+#include "base/metrics/histogram_macros.h"
+#include "base/rand_util.h"
+#include "base/sequenced_task_runner.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/threading/sequenced_task_runner_handle.h"
+#include "base/time/tick_clock.h"
+#include "content/browser/indexed_db/indexed_db_backing_store.h"
+#include "third_party/leveldatabase/env_chromium.h"
+#include "third_party/leveldatabase/src/include/leveldb/db.h"
+#include "third_party/leveldatabase/src/include/leveldb/iterator.h"
+
+namespace content {
+namespace {
+
+using StopReason = IndexedDBPreCloseTaskQueue::StopReason;
+
+// TODO(dmurph): Make common implementation in env_chromium.h
+base::StringPiece MakeStringPiece(const leveldb::Slice& s) {
+ return base::StringPiece(s.data(), s.size());
+}
+
+} // namespace
+
+template <typename T>
+WrappingIterator<T>::WrappingIterator() {}
+
+template <typename T>
+WrappingIterator<T>::WrappingIterator(const T* container,
+ size_t start_position) {
+ container_ = container;
+ valid_ = true;
+ iterations_done_ = 0;
+ DCHECK_LT(start_position, container_->size());
+ inner_ = container_->begin();
+ std::advance(inner_, start_position);
+ DCHECK(inner_ != container_->end());
+}
+
+template <typename T>
+WrappingIterator<T>::~WrappingIterator() {}
+
+template <typename T>
+void WrappingIterator<T>::Next() {
+ DCHECK(valid_);
+ iterations_done_++;
+ if (iterations_done_ >= container_->size()) {
+ valid_ = false;
+ return;
+ }
+ inner_++;
+ if (inner_ == container_->end()) {
+ inner_ = container_->begin();
+ }
+}
+
+template <typename T>
+const typename T::value_type& WrappingIterator<T>::Value() const {
+ CHECK(valid_);
+ return *inner_;
+}
+
+IndexedDBTombstoneSweeper::IndexedDBTombstoneSweeper(Mode mode,
+ int round_iterations,
+ int max_iterations,
+ leveldb::DB* database)
+ : mode_(mode),
+ max_round_iterations_(round_iterations),
+ max_iterations_(max_iterations),
+ database_(database),
+ ptr_factory_(this) {
+ sweep_state_.start_database_seed = static_cast<size_t>(base::RandUint64());
+ sweep_state_.start_object_store_seed =
+ static_cast<size_t>(base::RandUint64());
+ sweep_state_.start_index_seed = static_cast<size_t>(base::RandUint64());
+}
+
+IndexedDBTombstoneSweeper::~IndexedDBTombstoneSweeper() {}
+
+void IndexedDBTombstoneSweeper::SetMetadata(
+ std::vector<IndexedDBDatabaseMetadata> const* metadata) {
+ database_metadata_ = metadata;
+ total_indices_ = 0;
+ for (const auto& db : *metadata) {
+ for (const auto& os_pair : db.object_stores) {
+ total_indices_ += os_pair.second.indexes.size();
+ }
+ }
+}
+
+IndexedDBTombstoneSweeper::SweepState::SweepState() = default;
+
+IndexedDBTombstoneSweeper::SweepState::~SweepState() = default;
+
+void IndexedDBTombstoneSweeper::Stop(StopReason reason) {
+ leveldb::Status s;
+ RecordUMAStats(reason, base::nullopt, s);
+}
+
+bool IndexedDBTombstoneSweeper::RunRound() {
+ DCHECK(database_metadata_);
+
+ if (database_metadata_->empty())
+ return true;
+
+ if (!start_time_) {
+ start_time_ = clock_for_testing_ ? clock_for_testing_->NowTicks()
+ : base::TimeTicks::Now();
+ }
+
+ leveldb::Status s;
+ Status status = DoSweep(&s);
+
+ if (status != Status::DONE_ERROR && mode_ == Mode::DELETION) {
+ s = FlushDeletions();
+ if (!s.ok())
+ status = Status::DONE_ERROR;
+ }
+
+ if (status == Status::SWEEPING)
+ return false;
+
+ RecordUMAStats(base::nullopt, status, s);
+ return true;
+}
+
+void IndexedDBTombstoneSweeper::RecordUMAStats(
+ base::Optional<StopReason> stop_reason,
+ base::Optional<IndexedDBTombstoneSweeper::Status> status,
+ const leveldb::Status& leveldb_error) {
+ static const char kUmaPrefix[] = "WebCore.IndexedDB.TombstoneSweeper.";
+ DCHECK(stop_reason || status);
+ DCHECK(!stop_reason || !status);
+
+ std::string uma_prefix = kUmaPrefix;
+
+ if (stop_reason) {
+ switch (stop_reason.value()) {
+ case StopReason::NEW_CONNECTION:
+ uma_prefix.append("ConnectionOpened.");
+ break;
+ case StopReason::TIMEOUT:
+ uma_prefix.append("TimeoutReached.");
+ break;
+ case StopReason::METADATA_ERROR:
+ // Metadata error statistics are recorded in the PreCloseTaskList.
+ return;
+ }
+ } else if (status) {
+ switch (status.value()) {
+ case Status::DONE_REACHED_MAX:
+ uma_prefix.append("MaxIterations.");
+ break;
+ case Status::DONE_ERROR:
+ LOCAL_HISTOGRAM_ENUMERATION(
+ "WebCore.IndexedDB.TombstoneSweeper.SweepError",
+ leveldb_env::GetLevelDBStatusUMAValue(leveldb_error),
+ leveldb_env::LEVELDB_STATUS_MAX);
+ uma_prefix.append("SweepError.");
+ break;
+ case Status::DONE_COMPLETE:
+ uma_prefix.append("Complete.");
+ break;
+ case Status::SWEEPING:
+ NOTREACHED();
+ }
+ } else {
+ NOTREACHED();
+ }
+
+ std::string uma_count_label = uma_prefix;
+ std::string uma_size_label = std::move(uma_prefix);
+
+ switch (mode_) {
+ case Mode::STATISTICS:
+ uma_count_label.append("NumTombstones");
+ uma_size_label.append("TombstonesSize");
+ break;
+ case Mode::DELETION:
+ uma_count_label.append("NumDeletedTombstones");
+ uma_size_label.append("DeletedTombstonesSize");
+ break;
+ default:
+ NOTREACHED();
+ }
+
+ // Some stats are only recorded for completed runs.
+ if (status && status.value() == Status::DONE_COMPLETE) {
+ if (start_time_) {
+ base::TimeDelta total_time =
+ (clock_for_testing_ ? clock_for_testing_->NowTicks()
+ : base::TimeTicks::Now()) -
+ start_time_.value();
+ switch (mode_) {
+ case Mode::STATISTICS:
+ LOCAL_HISTOGRAM_TIMES(
+ "WebCore.IndexedDB.TombstoneSweeper.Complete.StatsTotalTime",
+ total_time);
+ break;
+ case Mode::DELETION:
+ LOCAL_HISTOGRAM_TIMES(
+ "WebCore.IndexedDB.TombstoneSweeper.Complete.DeletionTotalTime",
+ total_time);
+ if (metrics_.seen_tombstones > 0) {
+ // Only record deletion time if we do a deletion.
+ LOCAL_HISTOGRAM_TIMES(
+ "WebCore.IndexedDB.TombstoneSweeper.Complete."
+ "DeletionCommitTime",
+ total_deletion_time_);
+ }
+ break;
+ default:
+ NOTREACHED();
+ }
+ }
+ }
+
+ base::HistogramBase* count_histogram = base::Histogram::FactoryGet(
+ uma_count_label, 1, 1000000, 50, base::HistogramBase::kNoFlags);
+ base::HistogramBase* size_histogram = base::Histogram::FactoryGet(
+ uma_size_label, 1, 1000000, 50, base::HistogramBase::kNoFlags);
+
+ if (count_histogram)
+ count_histogram->Add(metrics_.seen_tombstones);
+ if (size_histogram)
+ size_histogram->Add(metrics_.seen_tombstones_size);
+
+ // We put our max at 20 instead of 100 to reduce the number of buckets.
+ const static int kIndexPercentageBucketCount = 20;
+ LOCAL_HISTOGRAM_ENUMERATION(
+ "WebCore.IndexedDB.TombstoneSweeper.IndexScanPercent",
+ indices_scanned_ * kIndexPercentageBucketCount / total_indices_,
+ kIndexPercentageBucketCount + 1);
+}
+
+leveldb::Status IndexedDBTombstoneSweeper::FlushDeletions() {
+ if (!has_writes_)
+ return leveldb::Status::OK();
+ base::TimeTicks start = base::TimeTicks::Now();
+
+ leveldb::Status status =
+ database_->Write(leveldb::WriteOptions(), &round_deletion_batch_);
+ round_deletion_batch_.Clear();
+ has_writes_ = false;
+
+ if (!status.ok()) {
+ LOCAL_HISTOGRAM_ENUMERATION(
+ "WebCore.IndexedDB.TombstoneSweeper.DeletionWriteError",
+ leveldb_env::GetLevelDBStatusUMAValue(status),
+ leveldb_env::LEVELDB_STATUS_MAX);
+ return status;
+ }
+
+ base::TimeDelta diff = base::TimeTicks::Now() - start;
+ total_deletion_time_ += diff;
+ return status;
+}
+
+bool IndexedDBTombstoneSweeper::ShouldContinueIteration(
+ IndexedDBTombstoneSweeper::Status* sweep_status,
+ leveldb::Status* leveldb_status,
+ int* round_iterations) {
+ ++num_iterations_;
+ ++(*round_iterations);
+
+ if (!iterator_->Valid()) {
+ *leveldb_status = iterator_->status();
+ if (!leveldb_status->ok()) {
+ *sweep_status = Status::DONE_ERROR;
+ return false;
+ }
+ *sweep_status = Status::SWEEPING;
+ return true;
+ }
+ if (*round_iterations >= max_round_iterations_) {
+ *sweep_status = Status::SWEEPING;
+ return false;
+ }
+ if (num_iterations_ >= max_iterations_) {
+ *sweep_status = Status::DONE_REACHED_MAX;
+ return false;
+ }
+ return true;
+}
+
+IndexedDBTombstoneSweeper::Status IndexedDBTombstoneSweeper::DoSweep(
+ leveldb::Status* leveldb_status) {
+ int round_iterations = 0;
+ Status sweep_status;
+ if (database_metadata_->empty())
+ return Status::DONE_COMPLETE;
+
+ if (!iterator_) {
+ leveldb::ReadOptions iterator_options;
+ iterator_options.fill_cache = false;
+ iterator_options.verify_checksums = true;
+ iterator_.reset(database_->NewIterator(iterator_options));
+ }
+
+ if (!sweep_state_.database_it) {
+ size_t start_database_idx = static_cast<size_t>(
+ sweep_state_.start_database_seed % database_metadata_->size());
+ sweep_state_.database_it = WrappingIterator<DatabaseMetadataVector>(
+ database_metadata_, start_database_idx);
+ }
+ // Loop conditions facilitate starting at random index.
+ for (; sweep_state_.database_it.value().IsValid();
+ sweep_state_.database_it.value().Next()) {
+ const IndexedDBDatabaseMetadata& database =
+ sweep_state_.database_it.value().Value();
+ if (database.object_stores.empty())
+ continue;
+
+ if (!sweep_state_.object_store_it) {
+ size_t start_object_store_idx = static_cast<size_t>(
+ sweep_state_.start_object_store_seed % database.object_stores.size());
+ sweep_state_.object_store_it = WrappingIterator<ObjectStoreMetadataMap>(
+ &database.object_stores, start_object_store_idx);
+ }
+ // Loop conditions facilitate starting at random index.
+ for (; sweep_state_.object_store_it.value().IsValid();
+ sweep_state_.object_store_it.value().Next()) {
+ const IndexedDBObjectStoreMetadata& object_store =
+ sweep_state_.object_store_it.value().Value().second;
+
+ if (object_store.indexes.empty())
+ continue;
+
+ if (!sweep_state_.index_it) {
+ size_t start_index_idx = static_cast<size_t>(
+ sweep_state_.start_index_seed % object_store.indexes.size());
+ sweep_state_.index_it = WrappingIterator<IndexMetadataMap>(
+ &object_store.indexes, start_index_idx);
+ }
+ // Loop conditions facilitate starting at random index.
+ for (; sweep_state_.index_it.value().IsValid();
+ sweep_state_.index_it.value().Next()) {
+ const IndexedDBIndexMetadata& index =
+ sweep_state_.index_it.value().Value().second;
+
+ bool can_continue =
+ IterateIndex(database.id, object_store.id, index, &sweep_status,
+ leveldb_status, &round_iterations);
+ if (!can_continue)
+ return sweep_status;
+ }
+ sweep_state_.index_it = base::nullopt;
+ }
+ sweep_state_.object_store_it = base::nullopt;
+ }
+ return Status::DONE_COMPLETE;
+}
+
+bool IndexedDBTombstoneSweeper::IterateIndex(
+ int64_t database_id,
+ int64_t object_store_id,
+ const IndexedDBIndexMetadata& index,
+ IndexedDBTombstoneSweeper::Status* sweep_status,
+ leveldb::Status* leveldb_status,
+ int* round_iterations) {
+ // If the sweeper exited early from an index scan, continue where it left off.
+ if (sweep_state_.index_it_key) {
+ iterator_->Seek(sweep_state_.index_it_key.value().Encode());
+ if (!ShouldContinueIteration(sweep_status, leveldb_status,
+ round_iterations)) {
+ return false;
+ }
+ // Start at the first unvisited value.
+ iterator_->Next();
+ if (!ShouldContinueIteration(sweep_status, leveldb_status,
+ round_iterations)) {
+ return false;
+ }
+ } else {
+ iterator_->Seek(
+ IndexDataKey::EncodeMinKey(database_id, object_store_id, index.id));
+ if (!ShouldContinueIteration(sweep_status, leveldb_status,
+ round_iterations)) {
+ return false;
+ }
+ }
+
+ while (iterator_->Valid()) {
+ leveldb::Slice key_slice = iterator_->key();
+ base::StringPiece index_key_str = MakeStringPiece(key_slice);
+ size_t key_size = index_key_str.size();
+ base::StringPiece index_value_str = MakeStringPiece(iterator_->value());
+ size_t value_size = index_value_str.size();
+ // See if we've reached the end of the current index or all indexes.
+ sweep_state_.index_it_key.emplace(IndexDataKey());
+ if (!IndexDataKey::Decode(&index_key_str,
+ &sweep_state_.index_it_key.value()) ||
+ sweep_state_.index_it_key.value().IndexId() != index.id) {
+ break;
+ }
+
+ size_t entry_size = key_size + value_size;
+
+ int64_t index_data_version;
+ std::unique_ptr<IndexedDBKey> primary_key;
+
+ if (!DecodeVarInt(&index_value_str, &index_data_version)) {
+ ++metrics_.num_invalid_index_values;
+ iterator_->Next();
+ if (!ShouldContinueIteration(sweep_status, leveldb_status,
+ round_iterations)) {
+ return false;
+ }
+ continue;
+ }
+ std::string encoded_primary_key = index_value_str.as_string();
+ std::string exists_key = ExistsEntryKey::Encode(
+ database_id, object_store_id, encoded_primary_key);
+
+ std::string exists_value;
+ leveldb::Status s =
+ database_->Get(leveldb::ReadOptions(), exists_key, &exists_value);
+ if (!s.ok()) {
+ ++metrics_.num_errors_reading_exists_table;
+ iterator_->Next();
+ if (!ShouldContinueIteration(sweep_status, leveldb_status,
+ round_iterations)) {
+ return false;
+ }
+ continue;
+ }
+ base::StringPiece exists_value_piece(exists_value);
+ int64_t decoded_exists_version;
+ if (!DecodeInt(&exists_value_piece, &decoded_exists_version) ||
+ !exists_value_piece.empty()) {
+ ++metrics_.num_invalid_exists_values;
+ iterator_->Next();
+ if (!ShouldContinueIteration(sweep_status, leveldb_status,
+ round_iterations)) {
+ return false;
+ }
+ continue;
+ }
+
+ if (decoded_exists_version != index_data_version) {
+ if (mode_ == Mode::DELETION) {
+ has_writes_ = true;
+ round_deletion_batch_.Delete(key_slice);
+ }
+ ++metrics_.seen_tombstones;
+ metrics_.seen_tombstones_size += entry_size;
+ }
+
+ iterator_->Next();
+ if (!ShouldContinueIteration(sweep_status, leveldb_status,
+ round_iterations)) {
+ return false;
+ }
+ }
+ ++indices_scanned_;
+ sweep_state_.index_it_key = base::nullopt;
+ return true;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/indexed_db/indexed_db_tombstone_sweeper.h b/chromium/content/browser/indexed_db/indexed_db_tombstone_sweeper.h
new file mode 100644
index 00000000000..5ebf2265768
--- /dev/null
+++ b/chromium/content/browser/indexed_db/indexed_db_tombstone_sweeper.h
@@ -0,0 +1,194 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_TOMBSTONE_SWEEPER_H_
+#define CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_TOMBSTONE_SWEEPER_H_
+
+#include <memory>
+
+#include "base/callback.h"
+#include "base/feature_list.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "base/optional.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
+#include "content/browser/indexed_db/indexed_db_leveldb_coding.h"
+#include "content/browser/indexed_db/indexed_db_pre_close_task_queue.h"
+#include "content/common/content_export.h"
+#include "content/common/indexed_db/indexed_db_metadata.h"
+#include "third_party/leveldatabase/src/include/leveldb/status.h"
+#include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
+
+namespace base {
+class TickClock;
+}
+
+namespace leveldb {
+class DB;
+class Iterator;
+} // namespace leveldb
+
+namespace content {
+class IndexedDBBackingStore;
+
+// Facilitates iterating a whole container with an abnormal starting position.
+// If the starting position is not 0, then the iteration will wrap to the
+// beginning of the container until the starting position is reached again.
+template <typename T>
+class WrappingIterator {
+ public:
+ WrappingIterator();
+ WrappingIterator(const T* container, size_t start_position);
+ ~WrappingIterator();
+ WrappingIterator& operator=(const WrappingIterator& other) = default;
+
+ void Next();
+ bool IsValid() const { return valid_; }
+ const typename T::value_type& Value() const;
+
+ private:
+ bool valid_ = false;
+ size_t iterations_done_ = 0;
+ typename T::const_iterator inner_;
+ const T* container_ = nullptr;
+};
+
+// Sweeps the IndexedDB leveldb database looking for index tombstones. These
+// occur when the indexed fields of rows are modified, and stay around if script
+// doesn't do a cursor iteration of the database.
+//
+// Owned by the IndexedDBBackingStore.
+//
+// TODO(dmurph) Describe this class in a README.md file.
+// See bit.ly/idb-tombstone-sweeper for more information.
+class CONTENT_EXPORT IndexedDBTombstoneSweeper
+ : public IndexedDBPreCloseTaskQueue::PreCloseTask {
+ public:
+ enum class Mode {
+ // Gathers statistics and doesn't modify the database.
+ STATISTICS,
+ // Deletes the tombstones that are encountered.
+ DELETION
+ };
+
+ // The |database| must outlive this instance.
+ IndexedDBTombstoneSweeper(Mode mode,
+ int round_iterations,
+ int max_iterations,
+ leveldb::DB* database);
+ ~IndexedDBTombstoneSweeper() override;
+
+ void SetMetadata(
+ std::vector<IndexedDBDatabaseMetadata> const* metadata) override;
+
+ void Stop(IndexedDBPreCloseTaskQueue::StopReason reason) override;
+
+ bool RunRound() override;
+
+ private:
+ using DatabaseMetadataVector = std::vector<IndexedDBDatabaseMetadata>;
+ using ObjectStoreMetadataMap =
+ std::map<int64_t, IndexedDBObjectStoreMetadata>;
+ using IndexMetadataMap = std::map<int64_t, IndexedDBIndexMetadata>;
+
+ friend class IndexedDBTombstoneSweeperTest;
+
+ enum class Status { SWEEPING, DONE_REACHED_MAX, DONE_ERROR, DONE_COMPLETE };
+
+ // Contains the current sweeping state and position for the sweeper.
+ struct SweepState {
+ SweepState();
+ ~SweepState();
+
+ // Stores the random starting database seed. Not bounded.
+ size_t start_database_seed = 0;
+ base::Optional<WrappingIterator<DatabaseMetadataVector>> database_it;
+
+ // Stores the random starting object store seed. Not bounded.
+ size_t start_object_store_seed = 0;
+ base::Optional<WrappingIterator<ObjectStoreMetadataMap>> object_store_it;
+
+ // Stores the random starting object store seed. Not bounded.
+ size_t start_index_seed = 0;
+ base::Optional<WrappingIterator<IndexMetadataMap>> index_it;
+ base::Optional<IndexDataKey> index_it_key;
+ };
+
+ // Accumulated metrics that are reported at the end of sweeping.
+ struct SweepMetrics {
+ int num_invalid_index_values = 0;
+ int num_errors_reading_exists_table = 0;
+ int num_invalid_exists_values = 0;
+
+ int seen_tombstones = 0;
+ uint64_t seen_tombstones_size = 0;
+ };
+
+ void SetStartSeedsForTesting(size_t database_seed,
+ size_t object_store_seed,
+ size_t index_seed) {
+ sweep_state_.start_database_seed = database_seed;
+ sweep_state_.start_object_store_seed = object_store_seed;
+ sweep_state_.start_index_seed = index_seed;
+ }
+
+ void SetClockForTesting(base::TickClock* clock) {
+ clock_for_testing_ = clock;
+ }
+
+ // Records UMA stats based on stop or completion status, as well as the mode
+ // of the sweeper.
+ // Exactly one optional argument must be populated.
+ void RecordUMAStats(
+ base::Optional<IndexedDBPreCloseTaskQueue::StopReason> stop_reason,
+ base::Optional<Status> status,
+ const leveldb::Status& leveldb_error);
+
+ leveldb::Status FlushDeletions();
+
+ bool ShouldContinueIteration(Status* sweep_status,
+ leveldb::Status* leveldb_status,
+ int* round_iters);
+
+ Status DoSweep(leveldb::Status* status);
+
+ // Returns true if sweeper can continue iterating.
+ bool IterateIndex(int64_t database_id,
+ int64_t object_store_id,
+ const IndexedDBIndexMetadata& index,
+ Status* sweep_status,
+ leveldb::Status* leveldb_status,
+ int* round_iterations);
+
+ const Mode mode_;
+ int num_iterations_ = 0;
+ const int max_round_iterations_;
+ const int max_iterations_;
+
+ int indices_scanned_ = 0;
+ int total_indices_ = 0;
+
+ // Used to measure total time of the task.
+ base::TickClock* clock_for_testing_ = nullptr;
+ base::Optional<base::TimeTicks> start_time_;
+
+ leveldb::DB* database_ = nullptr;
+ bool has_writes_ = false;
+ leveldb::WriteBatch round_deletion_batch_;
+ base::TimeDelta total_deletion_time_;
+
+ std::vector<IndexedDBDatabaseMetadata> const* database_metadata_ = nullptr;
+ std::unique_ptr<leveldb::Iterator> iterator_;
+
+ SweepState sweep_state_;
+ SweepMetrics metrics_;
+
+ base::WeakPtrFactory<IndexedDBTombstoneSweeper> ptr_factory_;
+ DISALLOW_COPY_AND_ASSIGN(IndexedDBTombstoneSweeper);
+};
+
+} // namespace content
+#endif // CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_TOMBSTONE_SWEEPER_H_
diff --git a/chromium/content/browser/indexed_db/indexed_db_tombstone_sweeper_unittest.cc b/chromium/content/browser/indexed_db/indexed_db_tombstone_sweeper_unittest.cc
new file mode 100644
index 00000000000..73daed7bf20
--- /dev/null
+++ b/chromium/content/browser/indexed_db/indexed_db_tombstone_sweeper_unittest.cc
@@ -0,0 +1,601 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/indexed_db/indexed_db_tombstone_sweeper.h"
+
+#include <memory>
+
+#include "base/files/scoped_temp_dir.h"
+#include "base/memory/ptr_util.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/test/histogram_tester.h"
+#include "base/time/tick_clock.h"
+#include "content/browser/indexed_db/leveldb/leveldb_comparator.h"
+#include "content/browser/indexed_db/leveldb/leveldb_database.h"
+#include "content/browser/indexed_db/leveldb/mock_level_db.h"
+#include "content/common/indexed_db/indexed_db_metadata.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/leveldatabase/env_chromium.h"
+#include "third_party/leveldatabase/src/helpers/memenv/memenv.h"
+#include "third_party/leveldatabase/src/include/leveldb/db.h"
+#include "third_party/leveldatabase/src/include/leveldb/env.h"
+#include "third_party/leveldatabase/src/include/leveldb/filter_policy.h"
+#include "third_party/leveldatabase/src/include/leveldb/slice.h"
+
+namespace content {
+class BrowserContext;
+
+namespace {
+using ::testing::_;
+using ::testing::Eq;
+using ::testing::Return;
+using ::testing::StrictMock;
+using Status = ::leveldb::Status;
+using Slice = ::leveldb::Slice;
+using Mode = IndexedDBTombstoneSweeper::Mode;
+
+constexpr int kRoundIterations = 11;
+constexpr int kMaxIterations = 100;
+const base::TimeTicks kTaskStartTime =
+ base::TimeTicks() + base::TimeDelta::FromSeconds(1);
+const base::TimeTicks kTaskEndTime =
+ base::TimeTicks() + base::TimeDelta::FromSeconds(2);
+
+constexpr int64_t kDb1 = 1;
+constexpr int64_t kDb2 = 1;
+constexpr int64_t kOs1 = 3;
+constexpr int64_t kOs2 = 5;
+constexpr int64_t kOs3 = 8;
+constexpr int64_t kOs4 = 9;
+constexpr int64_t kIndex1 = 31;
+constexpr int64_t kIndex2 = 32;
+constexpr int64_t kIndex3 = 35;
+constexpr int kTombstoneSize = 33;
+
+MATCHER_P(SliceEq,
+ str,
+ std::string(negation ? "isn't" : "is") + " equal to " +
+ base::HexEncode(str.data(), str.size())) {
+ *result_listener << "which is " << base::HexEncode(arg.data(), arg.size());
+ return std::string(arg.data(), arg.size()) == str;
+};
+
+class MockTickClock : public base::TickClock {
+ public:
+ MockTickClock() {}
+ ~MockTickClock() override {}
+
+ MOCK_METHOD0(NowTicks, base::TimeTicks());
+};
+
+class Comparator : public LevelDBComparator {
+ public:
+ int Compare(const base::StringPiece& a,
+ const base::StringPiece& b) const override {
+ return content::Compare(a, b, false /*index_keys*/);
+ }
+ const char* Name() const override { return "idb_cmp1"; }
+};
+
+} // namespace
+
+class IndexedDBTombstoneSweeperTest : public testing::TestWithParam<Mode> {
+ public:
+ IndexedDBTombstoneSweeperTest() {}
+ ~IndexedDBTombstoneSweeperTest() {}
+
+ void PopulateMultiDBMetdata() {
+ // db1
+ // os1
+ // os2
+ // index1
+ // index2
+ metadata_.emplace_back(base::ASCIIToUTF16("db1"), kDb1, 1, 29);
+ auto& db1 = metadata_.back();
+ db1.object_stores[kOs1] = IndexedDBObjectStoreMetadata(
+ base::ASCIIToUTF16("os1"), kOs1, IndexedDBKeyPath(), false, 1000);
+ db1.object_stores[kOs2] = IndexedDBObjectStoreMetadata(
+ base::ASCIIToUTF16("os2"), kOs2, IndexedDBKeyPath(), false, 1000);
+ auto& os2 = db1.object_stores[kOs2];
+ os2.indexes[kIndex1] = IndexedDBIndexMetadata(
+ base::ASCIIToUTF16("index1"), kIndex1, IndexedDBKeyPath(), true, false);
+ os2.indexes[kIndex2] = IndexedDBIndexMetadata(
+ base::ASCIIToUTF16("index2"), kIndex2, IndexedDBKeyPath(), true, false);
+ // db2
+ // os3
+ // index3
+ // os4
+ metadata_.emplace_back(base::ASCIIToUTF16("db2"), kDb2, 1, 29);
+ auto& db2 = metadata_.back();
+ db2.object_stores[kOs3] = IndexedDBObjectStoreMetadata(
+ base::ASCIIToUTF16("os3"), kOs3, IndexedDBKeyPath(), false, 1000);
+ db2.object_stores[kOs4] = IndexedDBObjectStoreMetadata(
+ base::ASCIIToUTF16("os4"), kOs4, IndexedDBKeyPath(), false, 1000);
+ auto& os3 = db2.object_stores[kOs3];
+ os3.indexes[kIndex3] = IndexedDBIndexMetadata(
+ base::ASCIIToUTF16("index3"), kIndex3, IndexedDBKeyPath(), true, false);
+ }
+
+ void PopulateSingleIndexDBMetadata() {
+ // db1
+ // os1
+ // index1
+ metadata_.emplace_back(base::ASCIIToUTF16("db1"), kDb1, 1, 29);
+ auto& db1 = metadata_.back();
+ db1.object_stores[kOs1] = IndexedDBObjectStoreMetadata(
+ base::ASCIIToUTF16("os1"), kOs1, IndexedDBKeyPath(), false, 1000);
+ auto& os2 = db1.object_stores[kOs1];
+ os2.indexes[kIndex1] = IndexedDBIndexMetadata(
+ base::ASCIIToUTF16("index1"), kIndex1, IndexedDBKeyPath(), true, false);
+ }
+
+ void SetupMockDB() {
+ sweeper_ = base::MakeUnique<IndexedDBTombstoneSweeper>(
+ GetParam(), kRoundIterations, kMaxIterations, &mock_db_);
+ sweeper_->SetStartSeedsForTesting(0, 0, 0);
+ }
+
+ void SetupRealDB() {
+ comparator_.reset(new Comparator());
+ in_memory_db_ = LevelDBDatabase::OpenInMemory(comparator_.get());
+ sweeper_ = base::MakeUnique<IndexedDBTombstoneSweeper>(
+ GetParam(), kRoundIterations, kMaxIterations, in_memory_db_->db());
+ sweeper_->SetStartSeedsForTesting(0, 0, 0);
+ }
+
+ void SetClockExpectations() {
+ EXPECT_CALL(tick_clock_, NowTicks())
+ .WillOnce(testing::Return(kTaskStartTime))
+ .WillOnce(testing::Return(kTaskEndTime));
+ sweeper_->SetClockForTesting(&tick_clock_);
+ }
+
+ void SetFirstClockExpectation() {
+ EXPECT_CALL(tick_clock_, NowTicks())
+ .WillOnce(testing::Return(kTaskStartTime));
+ sweeper_->SetClockForTesting(&tick_clock_);
+ }
+
+ void ExpectUmaTombstones(int num, int size, bool reached_max = false) {
+ std::string category = reached_max ? "MaxIterations" : "Complete";
+ if (GetParam() == Mode::STATISTICS) {
+ histogram_tester_.ExpectUniqueSample(
+ "WebCore.IndexedDB.TombstoneSweeper." + category + ".NumTombstones",
+ num, 1);
+ histogram_tester_.ExpectUniqueSample(
+ "WebCore.IndexedDB.TombstoneSweeper." + category + ".TombstonesSize",
+ size, 1);
+ } else {
+ histogram_tester_.ExpectUniqueSample(
+ "WebCore.IndexedDB.TombstoneSweeper." + category +
+ ".NumDeletedTombstones",
+ num, 1);
+ histogram_tester_.ExpectUniqueSample(
+ "WebCore.IndexedDB.TombstoneSweeper." + category +
+ ".DeletedTombstonesSize",
+ size, 1);
+ }
+ }
+
+ void ExpectTaskTimeRecorded() {
+ if (GetParam() == Mode::STATISTICS) {
+ histogram_tester_.ExpectTimeBucketCount(
+ "WebCore.IndexedDB.TombstoneSweeper.Complete.StatsTotalTime",
+ base::TimeDelta::FromSeconds(1), 1);
+ } else {
+ histogram_tester_.ExpectTimeBucketCount(
+ "WebCore.IndexedDB.TombstoneSweeper.Complete.DeletionTotalTime",
+ base::TimeDelta::FromSeconds(1), 1);
+ }
+ }
+
+ void ExpectIndexEntry(leveldb::MockIterator& iterator,
+ int64_t db,
+ int64_t os,
+ int64_t index,
+ const IndexedDBKey& index_key,
+ const IndexedDBKey& primary_key,
+ int index_version) {
+ testing::InSequence sequence_enforcer;
+
+ EXPECT_CALL(iterator, key())
+ .WillOnce(Return(
+ IndexDataKey::Encode(db, os, index, index_key, primary_key)));
+ std::string value_str;
+ EncodeVarInt(index_version, &value_str);
+ EncodeIDBKey(primary_key, &value_str);
+ EXPECT_CALL(iterator, value()).WillOnce(Return(value_str));
+ }
+
+ void ExpectIndexAndExistsEntries(leveldb::MockIterator& iterator,
+ int64_t db,
+ int64_t os,
+ int64_t index,
+ const IndexedDBKey& index_key,
+ const IndexedDBKey& primary_key,
+ int index_version,
+ int exists_version) {
+ ExpectIndexEntry(iterator, db, os, index, index_key, primary_key,
+ index_version);
+
+ testing::InSequence sequence_enforcer;
+
+ std::string encoded_primary_key;
+ EncodeIDBKey(primary_key, &encoded_primary_key);
+
+ std::string exists_value;
+ EncodeVarInt(exists_version, &exists_value);
+ EXPECT_CALL(
+ mock_db_,
+ Get(_, SliceEq(ExistsEntryKey::Encode(db, os, encoded_primary_key)), _))
+ .WillOnce(testing::DoAll(testing::SetArgPointee<2>(exists_value),
+ Return(Status::OK())));
+ }
+
+ protected:
+ std::unique_ptr<Comparator> comparator_;
+ std::unique_ptr<LevelDBDatabase> in_memory_db_;
+ leveldb::MockLevelDB mock_db_;
+
+ std::unique_ptr<IndexedDBTombstoneSweeper> sweeper_;
+
+ StrictMock<MockTickClock> tick_clock_;
+
+ std::vector<IndexedDBDatabaseMetadata> metadata_;
+
+ // Used to verify recorded data.
+ base::HistogramTester histogram_tester_;
+};
+
+namespace {
+
+TEST_P(IndexedDBTombstoneSweeperTest, EmptyDB) {
+ SetupMockDB();
+ sweeper_->SetMetadata(&metadata_);
+ EXPECT_TRUE(sweeper_->RunRound());
+
+ EXPECT_TRUE(
+ histogram_tester_.GetTotalCountsForPrefix("WebCore.IndexedDB.").empty());
+}
+
+TEST_P(IndexedDBTombstoneSweeperTest, NoTombstonesComplexDB) {
+ SetupMockDB();
+ PopulateMultiDBMetdata();
+ sweeper_->SetMetadata(&metadata_);
+ SetClockExpectations();
+
+ // We'll have one index entry per index, and simulate reaching the end.
+ leveldb::MockIterator* mock_iterator = new leveldb::MockIterator();
+ EXPECT_CALL(mock_db_, NewIterator(testing::_))
+ .WillOnce(testing::Return(mock_iterator));
+
+ // First index.
+ {
+ testing::InSequence sequence_enforcer;
+ EXPECT_CALL(*mock_iterator,
+ Seek(SliceEq(IndexDataKey::EncodeMinKey(kDb1, kOs2, kIndex1))));
+ EXPECT_CALL(*mock_iterator, Valid()).Times(2).WillRepeatedly(Return(true));
+
+ ExpectIndexAndExistsEntries(*mock_iterator, kDb1, kOs2, kIndex1,
+ IndexedDBKey(10, blink::kWebIDBKeyTypeNumber),
+ IndexedDBKey(20, blink::kWebIDBKeyTypeNumber),
+ 1, 1);
+ EXPECT_CALL(*mock_iterator, Next());
+
+ EXPECT_CALL(*mock_iterator, Valid()).Times(2).WillRepeatedly(Return(true));
+ // Return the beginning of the second index, which should cause us to error
+ // & go restart our index seek.
+ ExpectIndexEntry(*mock_iterator, kDb1, kOs2, kIndex2,
+ IndexedDBKey(30, blink::kWebIDBKeyTypeNumber),
+ IndexedDBKey(10, blink::kWebIDBKeyTypeNumber), 1);
+ }
+
+ // Second index.
+ {
+ testing::InSequence sequence_enforcer;
+ EXPECT_CALL(*mock_iterator,
+ Seek(SliceEq(IndexDataKey::EncodeMinKey(kDb1, kOs2, kIndex2))));
+ EXPECT_CALL(*mock_iterator, Valid()).Times(2).WillRepeatedly(Return(true));
+ ExpectIndexAndExistsEntries(*mock_iterator, kDb1, kOs2, kIndex2,
+ IndexedDBKey(30, blink::kWebIDBKeyTypeNumber),
+ IndexedDBKey(10, blink::kWebIDBKeyTypeNumber),
+ 1, 1);
+ EXPECT_CALL(*mock_iterator, Next());
+
+ // Return next key, which should make it error
+ EXPECT_CALL(*mock_iterator, Valid()).Times(2).WillRepeatedly(Return(true));
+ ExpectIndexEntry(*mock_iterator, kDb2, kOs3, kIndex3,
+ IndexedDBKey(1501, blink::kWebIDBKeyTypeNumber),
+ IndexedDBKey(15123, blink::kWebIDBKeyTypeNumber), 12);
+ }
+
+ // Third index.
+ {
+ testing::InSequence sequence_enforcer;
+ EXPECT_CALL(*mock_iterator,
+ Seek(SliceEq(IndexDataKey::EncodeMinKey(kDb2, kOs3, kIndex3))));
+ EXPECT_CALL(*mock_iterator, Valid()).Times(2).WillRepeatedly(Return(true));
+ ExpectIndexAndExistsEntries(
+ *mock_iterator, kDb2, kOs3, kIndex3,
+ IndexedDBKey(1501, blink::kWebIDBKeyTypeNumber),
+ IndexedDBKey(15123, blink::kWebIDBKeyTypeNumber), 12, 12);
+ EXPECT_CALL(*mock_iterator, Next());
+
+ // Return next key, which should make it error
+ EXPECT_CALL(*mock_iterator, Valid()).WillOnce(Return(false));
+ EXPECT_CALL(*mock_iterator, status()).WillOnce(Return(Status::OK()));
+ EXPECT_CALL(*mock_iterator, Valid()).WillOnce(Return(false));
+ }
+
+ ASSERT_TRUE(sweeper_->RunRound());
+ ExpectTaskTimeRecorded();
+ ExpectUmaTombstones(0, 0);
+ histogram_tester_.ExpectUniqueSample(
+ "WebCore.IndexedDB.TombstoneSweeper.IndexScanPercent", 20, 1);
+}
+
+TEST_P(IndexedDBTombstoneSweeperTest, AllTombstonesComplexDB) {
+ SetupMockDB();
+ PopulateMultiDBMetdata();
+ sweeper_->SetMetadata(&metadata_);
+ SetClockExpectations();
+
+ // We'll have one index entry per index, and simulate reaching the end.
+ leveldb::MockIterator* mock_iterator = new leveldb::MockIterator();
+ EXPECT_CALL(mock_db_, NewIterator(testing::_))
+ .WillOnce(testing::Return(mock_iterator));
+
+ // First index.
+ {
+ testing::InSequence sequence_enforcer;
+ EXPECT_CALL(*mock_iterator,
+ Seek(SliceEq(IndexDataKey::EncodeMinKey(kDb1, kOs2, kIndex1))));
+ EXPECT_CALL(*mock_iterator, Valid()).Times(2).WillRepeatedly(Return(true));
+
+ ExpectIndexAndExistsEntries(*mock_iterator, kDb1, kOs2, kIndex1,
+ IndexedDBKey(10, blink::kWebIDBKeyTypeNumber),
+ IndexedDBKey(20, blink::kWebIDBKeyTypeNumber),
+ 1, 2);
+ EXPECT_CALL(*mock_iterator, Next());
+
+ EXPECT_CALL(*mock_iterator, Valid()).Times(2).WillRepeatedly(Return(true));
+ // Return the beginning of the second index, which should cause us to error
+ // & go restart our index seek.
+ ExpectIndexEntry(*mock_iterator, kDb1, kOs2, kIndex2,
+ IndexedDBKey(30, blink::kWebIDBKeyTypeNumber),
+ IndexedDBKey(10, blink::kWebIDBKeyTypeNumber), 1);
+ }
+
+ // Second index.
+ {
+ testing::InSequence sequence_enforcer;
+ EXPECT_CALL(*mock_iterator,
+ Seek(SliceEq(IndexDataKey::EncodeMinKey(kDb1, kOs2, kIndex2))));
+ EXPECT_CALL(*mock_iterator, Valid()).Times(2).WillRepeatedly(Return(true));
+ ExpectIndexAndExistsEntries(*mock_iterator, kDb1, kOs2, kIndex2,
+ IndexedDBKey(30, blink::kWebIDBKeyTypeNumber),
+ IndexedDBKey(10, blink::kWebIDBKeyTypeNumber),
+ 1, 2);
+ EXPECT_CALL(*mock_iterator, Next());
+
+ // Return next key, which should make it error
+ EXPECT_CALL(*mock_iterator, Valid()).Times(2).WillRepeatedly(Return(true));
+ ExpectIndexEntry(*mock_iterator, kDb2, kOs3, kIndex3,
+ IndexedDBKey(1501, blink::kWebIDBKeyTypeNumber),
+ IndexedDBKey(15123, blink::kWebIDBKeyTypeNumber), 12);
+ }
+
+ // Third index.
+ {
+ testing::InSequence sequence_enforcer;
+ EXPECT_CALL(*mock_iterator,
+ Seek(SliceEq(IndexDataKey::EncodeMinKey(kDb2, kOs3, kIndex3))));
+ EXPECT_CALL(*mock_iterator, Valid()).Times(2).WillRepeatedly(Return(true));
+ ExpectIndexAndExistsEntries(
+ *mock_iterator, kDb2, kOs3, kIndex3,
+ IndexedDBKey(1501, blink::kWebIDBKeyTypeNumber),
+ IndexedDBKey(15123, blink::kWebIDBKeyTypeNumber), 12, 13);
+ EXPECT_CALL(*mock_iterator, Next());
+
+ // Return next key, which should make it error
+ EXPECT_CALL(*mock_iterator, Valid()).WillOnce(Return(false));
+ EXPECT_CALL(*mock_iterator, status()).WillOnce(Return(Status::OK()));
+ EXPECT_CALL(*mock_iterator, Valid()).WillOnce(Return(false));
+ }
+
+ if (GetParam() == Mode::DELETION)
+ EXPECT_CALL(mock_db_, Write(_, _));
+
+ ASSERT_TRUE(sweeper_->RunRound());
+ ExpectTaskTimeRecorded();
+ ExpectUmaTombstones(3, kTombstoneSize * 3);
+ histogram_tester_.ExpectUniqueSample(
+ "WebCore.IndexedDB.TombstoneSweeper.IndexScanPercent", 20, 1);
+}
+
+TEST_P(IndexedDBTombstoneSweeperTest, SimpleRealDBNoTombstones) {
+ PopulateSingleIndexDBMetadata();
+ SetupRealDB();
+ sweeper_->SetMetadata(&metadata_);
+ SetClockExpectations();
+
+ for (int i = 0; i < kRoundIterations; i++) {
+ auto index_key = IndexedDBKey(i, blink::kWebIDBKeyTypeNumber);
+ auto primary_key = IndexedDBKey(i + 1, blink::kWebIDBKeyTypeNumber);
+ std::string value_str;
+ EncodeVarInt(1, &value_str);
+ EncodeIDBKey(primary_key, &value_str);
+ in_memory_db_->Put(
+ IndexDataKey::Encode(kDb1, kOs1, kIndex1, index_key, primary_key),
+ &value_str);
+
+ std::string exists_value;
+ std::string encoded_primary_key;
+ EncodeIDBKey(primary_key, &encoded_primary_key);
+ EncodeVarInt(1, &exists_value);
+ in_memory_db_->Put(ExistsEntryKey::Encode(kDb1, kOs1, encoded_primary_key),
+ &exists_value);
+ }
+
+ ASSERT_FALSE(sweeper_->RunRound());
+ EXPECT_TRUE(sweeper_->RunRound());
+
+ ExpectTaskTimeRecorded();
+ ExpectUmaTombstones(0, 0);
+ histogram_tester_.ExpectUniqueSample(
+ "WebCore.IndexedDB.TombstoneSweeper.IndexScanPercent", 20, 1);
+}
+
+TEST_P(IndexedDBTombstoneSweeperTest, SimpleRealDBWithTombstones) {
+ PopulateSingleIndexDBMetadata();
+ SetupRealDB();
+ sweeper_->SetMetadata(&metadata_);
+ SetClockExpectations();
+
+ int tombstones = 0;
+ for (int i = 0; i < kRoundIterations + 1; i++) {
+ auto index_key = IndexedDBKey(i, blink::kWebIDBKeyTypeNumber);
+ auto primary_key = IndexedDBKey(i + 1, blink::kWebIDBKeyTypeNumber);
+ std::string value_str;
+ EncodeVarInt(1, &value_str);
+ EncodeIDBKey(primary_key, &value_str);
+ in_memory_db_->Put(
+ IndexDataKey::Encode(kDb1, kOs1, kIndex1, index_key, primary_key),
+ &value_str);
+
+ std::string exists_value;
+ std::string encoded_primary_key;
+ EncodeIDBKey(primary_key, &encoded_primary_key);
+ bool tombstone = i % 2 != 0;
+ tombstones += i % 2 ? 1 : 0;
+ EncodeVarInt(tombstone ? 2 : 1, &exists_value);
+ in_memory_db_->Put(ExistsEntryKey::Encode(kDb1, kOs1, encoded_primary_key),
+ &exists_value);
+ }
+
+ ASSERT_FALSE(sweeper_->RunRound());
+ EXPECT_TRUE(sweeper_->RunRound());
+
+ ExpectTaskTimeRecorded();
+ ExpectUmaTombstones(tombstones, kTombstoneSize * tombstones);
+ histogram_tester_.ExpectUniqueSample(
+ "WebCore.IndexedDB.TombstoneSweeper.IndexScanPercent", 20, 1);
+
+ for (int i = 0; i < kRoundIterations + 1; i++) {
+ if (i % 2 == 1) {
+ std::string out;
+ bool found = false;
+ auto index_key = IndexedDBKey(i, blink::kWebIDBKeyTypeNumber);
+ auto primary_key = IndexedDBKey(i + 1, blink::kWebIDBKeyTypeNumber);
+ EXPECT_TRUE(in_memory_db_
+ ->Get(IndexDataKey::Encode(kDb1, kOs1, kIndex1, index_key,
+ primary_key),
+ &out, &found)
+ .ok());
+ EXPECT_TRUE(GetParam() == Mode::STATISTICS || !found);
+ }
+ }
+}
+
+TEST_P(IndexedDBTombstoneSweeperTest, HitMaxIters) {
+ PopulateSingleIndexDBMetadata();
+ SetupRealDB();
+ sweeper_->SetMetadata(&metadata_);
+ SetFirstClockExpectation();
+
+ for (int i = 0; i < kMaxIterations + 1; i++) {
+ auto index_key = IndexedDBKey(i, blink::kWebIDBKeyTypeNumber);
+ auto primary_key = IndexedDBKey(i + 1, blink::kWebIDBKeyTypeNumber);
+ std::string value_str;
+ EncodeVarInt(1, &value_str);
+ EncodeIDBKey(primary_key, &value_str);
+ in_memory_db_->Put(
+ IndexDataKey::Encode(kDb1, kOs1, kIndex1, index_key, primary_key),
+ &value_str);
+
+ std::string exists_value;
+ std::string encoded_primary_key;
+ EncodeIDBKey(primary_key, &encoded_primary_key);
+ EncodeVarInt(i % 2 == 0 ? 2 : 1, &exists_value);
+ in_memory_db_->Put(ExistsEntryKey::Encode(kDb1, kOs1, encoded_primary_key),
+ &exists_value);
+ }
+
+ while (!sweeper_->RunRound())
+ ;
+
+ ExpectUmaTombstones(41, kTombstoneSize * 41, true);
+ histogram_tester_.ExpectUniqueSample(
+ "WebCore.IndexedDB.TombstoneSweeper.IndexScanPercent", 0, 1);
+}
+
+TEST_P(IndexedDBTombstoneSweeperTest, LevelDBError) {
+ SetupMockDB();
+ PopulateMultiDBMetdata();
+ sweeper_->SetMetadata(&metadata_);
+ SetFirstClockExpectation();
+
+ // We'll have one index entry per index, and simulate reaching the end.
+ leveldb::MockIterator* mock_iterator = new leveldb::MockIterator();
+ EXPECT_CALL(mock_db_, NewIterator(testing::_))
+ .WillOnce(testing::Return(mock_iterator));
+
+ // First index.
+ {
+ testing::InSequence sequence_enforcer;
+ EXPECT_CALL(*mock_iterator,
+ Seek(SliceEq(IndexDataKey::EncodeMinKey(kDb1, kOs2, kIndex1))));
+ EXPECT_CALL(*mock_iterator, Valid()).Times(2).WillRepeatedly(Return(true));
+
+ ExpectIndexAndExistsEntries(*mock_iterator, kDb1, kOs2, kIndex1,
+ IndexedDBKey(10, blink::kWebIDBKeyTypeNumber),
+ IndexedDBKey(20, blink::kWebIDBKeyTypeNumber),
+ 1, 1);
+ EXPECT_CALL(*mock_iterator, Next());
+
+ EXPECT_CALL(*mock_iterator, Valid()).Times(2).WillRepeatedly(Return(true));
+ // Return the beginning of the second index, which should cause us to error
+ // & go restart our index seek.
+ ExpectIndexEntry(*mock_iterator, kDb1, kOs2, kIndex2,
+ IndexedDBKey(30, blink::kWebIDBKeyTypeNumber),
+ IndexedDBKey(10, blink::kWebIDBKeyTypeNumber), 1);
+ }
+
+ // Second index.
+ {
+ testing::InSequence sequence_enforcer;
+ EXPECT_CALL(*mock_iterator,
+ Seek(SliceEq(IndexDataKey::EncodeMinKey(kDb1, kOs2, kIndex2))));
+ EXPECT_CALL(*mock_iterator, Valid()).Times(2).WillRepeatedly(Return(true));
+ ExpectIndexAndExistsEntries(*mock_iterator, kDb1, kOs2, kIndex2,
+ IndexedDBKey(30, blink::kWebIDBKeyTypeNumber),
+ IndexedDBKey(10, blink::kWebIDBKeyTypeNumber),
+ 1, 1);
+ EXPECT_CALL(*mock_iterator, Next());
+
+ // Return read error.
+ EXPECT_CALL(*mock_iterator, Valid()).WillOnce(Return(false));
+ EXPECT_CALL(*mock_iterator, status())
+ .WillOnce(Return(Status::Corruption("Test error")));
+ }
+
+ ASSERT_TRUE(sweeper_->RunRound());
+
+ histogram_tester_.ExpectUniqueSample(
+ "WebCore.IndexedDB.TombstoneSweeper.SweepError",
+ leveldb_env::GetLevelDBStatusUMAValue(Status::Corruption("")), 1);
+ // Only finished scanning the first index.
+ histogram_tester_.ExpectUniqueSample(
+ "WebCore.IndexedDB.TombstoneSweeper.IndexScanPercent", 1 * 20 / 3, 1);
+}
+
+INSTANTIATE_TEST_CASE_P(/* No prefix needed */,
+ IndexedDBTombstoneSweeperTest,
+ testing::Values(Mode::STATISTICS, Mode::DELETION));
+
+} // namespace
+
+} // namespace content
diff --git a/chromium/content/browser/indexed_db/leveldb/leveldb_database.cc b/chromium/content/browser/indexed_db/leveldb/leveldb_database.cc
index 2e61cfd267d..ff185b0978c 100644
--- a/chromium/content/browser/indexed_db/leveldb/leveldb_database.cc
+++ b/chromium/content/browser/indexed_db/leveldb/leveldb_database.cc
@@ -7,6 +7,7 @@
#include <inttypes.h>
#include <stdint.h>
+#include <algorithm>
#include <cerrno>
#include <memory>
#include <utility>
@@ -33,15 +34,17 @@
#include "content/browser/indexed_db/leveldb/leveldb_write_batch.h"
#include "third_party/leveldatabase/env_chromium.h"
#include "third_party/leveldatabase/src/helpers/memenv/memenv.h"
-#include "third_party/leveldatabase/src/include/leveldb/cache.h"
#include "third_party/leveldatabase/src/include/leveldb/db.h"
#include "third_party/leveldatabase/src/include/leveldb/env.h"
#include "third_party/leveldatabase/src/include/leveldb/filter_policy.h"
#include "third_party/leveldatabase/src/include/leveldb/slice.h"
+
using base::StringPiece;
namespace content {
+namespace {
+
// Forcing flushes to disk at the end of a transaction guarantees that the
// data hit disk, but drastically impacts throughput when the filesystem is
// busy with background compactions. Not syncing trades off reliability for
@@ -51,92 +54,67 @@ namespace content {
// Sync writes are necessary on Windows for quota calculations; POSIX
// calculates file sizes correctly even when not synced to disk.
#if defined(OS_WIN)
-static const bool kSyncWrites = true;
+const bool kSyncWrites = true;
#else
// TODO(dgrogan): Either remove the #if block or change this back to false.
// See http://crbug.com/338385.
-static const bool kSyncWrites = true;
+const bool kSyncWrites = true;
#endif
-static leveldb::Slice MakeSlice(const StringPiece& s) {
- return leveldb::Slice(s.begin(), s.size());
-}
+class LockImpl : public LevelDBLock {
+ public:
+ explicit LockImpl(leveldb::Env* env, leveldb::FileLock* lock)
+ : env_(env), lock_(lock) {}
+ ~LockImpl() override { env_->UnlockFile(lock_); }
-static StringPiece MakeStringPiece(const leveldb::Slice& s) {
- return StringPiece(s.data(), s.size());
-}
+ private:
+ leveldb::Env* env_;
+ leveldb::FileLock* lock_;
-LevelDBDatabase::ComparatorAdapter::ComparatorAdapter(
- const LevelDBComparator* comparator)
- : comparator_(comparator) {}
+ DISALLOW_COPY_AND_ASSIGN(LockImpl);
+};
-int LevelDBDatabase::ComparatorAdapter::Compare(const leveldb::Slice& a,
- const leveldb::Slice& b) const {
- return comparator_->Compare(MakeStringPiece(a), MakeStringPiece(b));
+leveldb::Slice MakeSlice(const StringPiece& s) {
+ return leveldb::Slice(s.begin(), s.size());
}
-const char* LevelDBDatabase::ComparatorAdapter::Name() const {
- return comparator_->Name();
+StringPiece MakeStringPiece(const leveldb::Slice& s) {
+ return StringPiece(s.data(), s.size());
}
-// TODO(jsbell): Support the methods below in the future.
-void LevelDBDatabase::ComparatorAdapter::FindShortestSeparator(
- std::string* start,
- const leveldb::Slice& limit) const {}
-
-void LevelDBDatabase::ComparatorAdapter::FindShortSuccessor(
- std::string* key) const {}
+class ComparatorAdapter : public leveldb::Comparator {
+ public:
+ explicit ComparatorAdapter(const LevelDBComparator* comparator)
+ : comparator_(comparator) {}
-LevelDBSnapshot::LevelDBSnapshot(LevelDBDatabase* db)
- : db_(db->db_.get()), snapshot_(db_->GetSnapshot()) {}
+ int Compare(const leveldb::Slice& a, const leveldb::Slice& b) const override {
+ return comparator_->Compare(MakeStringPiece(a), MakeStringPiece(b));
+ }
-LevelDBSnapshot::~LevelDBSnapshot() { db_->ReleaseSnapshot(snapshot_); }
+ const char* Name() const override { return comparator_->Name(); }
-LevelDBDatabase::LevelDBDatabase(size_t max_open_iterators)
- : iterator_lru_(max_open_iterators) {
- DCHECK(max_open_iterators);
-}
-
-LevelDBDatabase::~LevelDBDatabase() {
- LOCAL_HISTOGRAM_COUNTS_10000("Storage.IndexedDB.LevelDB.MaxIterators",
- max_iterators_);
- base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
- this);
- // db_'s destructor uses comparator_adapter_; order of deletion is important.
- CloseDatabase();
- comparator_adapter_.reset();
- env_.reset();
-}
+ // TODO(jsbell): Support the methods below in the future.
+ void FindShortestSeparator(std::string* start,
+ const leveldb::Slice& limit) const override {}
-void LevelDBDatabase::CloseDatabase() {
- if (db_) {
- base::TimeTicks begin_time = base::TimeTicks::Now();
- db_.reset();
- UMA_HISTOGRAM_MEDIUM_TIMES("WebCore.IndexedDB.LevelDB.CloseTime",
- base::TimeTicks::Now() - begin_time);
- }
-}
+ void FindShortSuccessor(std::string* key) const override {}
-static size_t DefaultBlockCacheSize() {
- if (base::SysInfo::IsLowEndDevice())
- return 512 * 1024; // 512KB
- else
- return 8 * 1024 * 1024; // 8MB
-}
+ private:
+ const LevelDBComparator* comparator_;
+};
-static leveldb::Status OpenDB(
+leveldb::Status OpenDB(
leveldb::Comparator* comparator,
leveldb::Env* env,
const base::FilePath& path,
std::unique_ptr<leveldb::DB>* db,
std::unique_ptr<const leveldb::FilterPolicy>* filter_policy) {
filter_policy->reset(leveldb::NewBloomFilterPolicy(10));
- leveldb::Options options;
+ leveldb_env::Options options;
options.comparator = comparator;
options.create_if_missing = true;
options.paranoid_checks = true;
options.filter_policy = filter_policy->get();
- options.reuse_logs = leveldb_env::kDefaultLogReuseOptionValue;
options.compression = leveldb::kSnappyCompression;
options.write_buffer_size =
leveldb_env::WriteBufferSize(base::SysInfo::AmountOfTotalDiskSpace(path));
@@ -145,55 +123,13 @@ static leveldb::Status OpenDB(
// https://code.google.com/p/chromium/issues/detail?id=227313#c11
options.max_open_files = 80;
options.env = env;
-
- // A shared block cache for all IndexedDB instances across all renderers.
- // See also components/leveldb_proto/leveldb_database.cc, which has
- // its own block cache for a different (internal use-cases) set of LevelDB
- // instances.
- static leveldb::Cache* default_block_cache =
- leveldb::NewLRUCache(DefaultBlockCacheSize());
- options.block_cache = default_block_cache;
+ options.block_cache = leveldb_env::SharedWebBlockCache();
// ChromiumEnv assumes UTF8, converts back to FilePath before using.
return leveldb_env::OpenDB(options, path.AsUTF8Unsafe(), db);
}
-leveldb::Status LevelDBDatabase::Destroy(const base::FilePath& file_name) {
- leveldb::Options options;
- options.env = LevelDBEnv::Get();
- // ChromiumEnv assumes UTF8, converts back to FilePath before using.
- return leveldb::DestroyDB(file_name.AsUTF8Unsafe(), options);
-}
-
-namespace {
-class LockImpl : public LevelDBLock {
- public:
- explicit LockImpl(leveldb::Env* env, leveldb::FileLock* lock)
- : env_(env), lock_(lock) {}
- ~LockImpl() override { env_->UnlockFile(lock_); }
-
- private:
- leveldb::Env* env_;
- leveldb::FileLock* lock_;
-
- DISALLOW_COPY_AND_ASSIGN(LockImpl);
-};
-} // namespace
-
-std::unique_ptr<LevelDBLock> LevelDBDatabase::LockForTesting(
- const base::FilePath& file_name) {
- leveldb::Env* env = LevelDBEnv::Get();
- base::FilePath lock_path = file_name.AppendASCII("LOCK");
- leveldb::FileLock* lock = NULL;
- leveldb::Status status = env->LockFile(lock_path.AsUTF8Unsafe(), &lock);
- if (!status.ok())
- return std::unique_ptr<LevelDBLock>();
- DCHECK(lock);
- return base::MakeUnique<LockImpl>(env, lock);
-}
-
-static int CheckFreeSpace(const char* const type,
- const base::FilePath& file_name) {
+int CheckFreeSpace(const char* const type, const base::FilePath& file_name) {
std::string name =
std::string("WebCore.IndexedDB.LevelDB.Open") + type + "FreeDiskSpace";
int64_t free_disk_space_in_k_bytes =
@@ -221,8 +157,8 @@ static int CheckFreeSpace(const char* const type,
return clamped_disk_space_k_bytes;
}
-static void ParseAndHistogramIOErrorDetails(const std::string& histogram_name,
- const leveldb::Status& s) {
+void ParseAndHistogramIOErrorDetails(const std::string& histogram_name,
+ const leveldb::Status& s) {
leveldb_env::MethodID method;
base::File::Error error = base::File::FILE_OK;
leveldb_env::ErrorParsingResult result =
@@ -253,9 +189,8 @@ static void ParseAndHistogramIOErrorDetails(const std::string& histogram_name,
}
}
-static void ParseAndHistogramCorruptionDetails(
- const std::string& histogram_name,
- const leveldb::Status& status) {
+void ParseAndHistogramCorruptionDetails(const std::string& histogram_name,
+ const leveldb::Status& status) {
int error = leveldb_env::GetCorruptionCode(status);
DCHECK_GE(error, 0);
std::string corruption_histogram_name(histogram_name);
@@ -269,8 +204,8 @@ static void ParseAndHistogramCorruptionDetails(
base::HistogramBase::kUmaTargetedHistogramFlag)->Add(error);
}
-static void HistogramLevelDBError(const std::string& histogram_name,
- const leveldb::Status& s) {
+void HistogramLevelDBError(const std::string& histogram_name,
+ const leveldb::Status& s) {
if (s.ok()) {
NOTREACHED();
return;
@@ -301,6 +236,62 @@ static void HistogramLevelDBError(const std::string& histogram_name,
ParseAndHistogramCorruptionDetails(histogram_name, s);
}
+} // namespace
+
+LevelDBSnapshot::LevelDBSnapshot(LevelDBDatabase* db)
+ : db_(db->db_.get()), snapshot_(db_->GetSnapshot()) {}
+
+LevelDBSnapshot::~LevelDBSnapshot() {
+ db_->ReleaseSnapshot(snapshot_);
+}
+
+LevelDBDatabase::LevelDBDatabase(size_t max_open_iterators)
+ : iterator_lru_(max_open_iterators) {
+ DCHECK(max_open_iterators);
+}
+
+LevelDBDatabase::~LevelDBDatabase() {
+ LOCAL_HISTOGRAM_COUNTS_10000("Storage.IndexedDB.LevelDB.MaxIterators",
+ max_iterators_);
+ base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
+ this);
+ // db_'s destructor uses comparator_adapter_; order of deletion is important.
+ CloseDatabase();
+ comparator_adapter_.reset();
+ env_.reset();
+}
+
+void LevelDBDatabase::CloseDatabase() {
+ if (db_) {
+ base::TimeTicks begin_time = base::TimeTicks::Now();
+ db_.reset();
+ UMA_HISTOGRAM_MEDIUM_TIMES("WebCore.IndexedDB.LevelDB.CloseTime",
+ base::TimeTicks::Now() - begin_time);
+ }
+}
+
+// static
+leveldb::Status LevelDBDatabase::Destroy(const base::FilePath& file_name) {
+ leveldb_env::Options options;
+ options.env = LevelDBEnv::Get();
+ // ChromiumEnv assumes UTF8, converts back to FilePath before using.
+ return leveldb::DestroyDB(file_name.AsUTF8Unsafe(), options);
+}
+
+// static
+std::unique_ptr<LevelDBLock> LevelDBDatabase::LockForTesting(
+ const base::FilePath& file_name) {
+ leveldb::Env* env = LevelDBEnv::Get();
+ base::FilePath lock_path = file_name.AppendASCII("LOCK");
+ leveldb::FileLock* lock = NULL;
+ leveldb::Status status = env->LockFile(lock_path.AsUTF8Unsafe(), &lock);
+ if (!status.ok())
+ return std::unique_ptr<LevelDBLock>();
+ DCHECK(lock);
+ return base::MakeUnique<LockImpl>(env, lock);
+}
+
+// static
leveldb::Status LevelDBDatabase::Open(const base::FilePath& file_name,
const LevelDBComparator* comparator,
size_t max_open_cursors,
@@ -345,6 +336,7 @@ leveldb::Status LevelDBDatabase::Open(const base::FilePath& file_name,
return s;
}
+// static
std::unique_ptr<LevelDBDatabase> LevelDBDatabase::OpenInMemory(
const LevelDBComparator* comparator) {
std::unique_ptr<ComparatorAdapter> comparator_adapter(
diff --git a/chromium/content/browser/indexed_db/leveldb/leveldb_database.h b/chromium/content/browser/indexed_db/leveldb/leveldb_database.h
index ab3800e4ac3..c27dea066f0 100644
--- a/chromium/content/browser/indexed_db/leveldb/leveldb_database.h
+++ b/chromium/content/browser/indexed_db/leveldb/leveldb_database.h
@@ -10,6 +10,7 @@
#include "base/containers/mru_cache.h"
#include "base/files/file_path.h"
+#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/strings/string16.h"
#include "base/strings/string_piece.h"
@@ -64,23 +65,6 @@ class CONTENT_EXPORT LevelDBDatabase
// large. See https://crbug/696055.
static const size_t kDefaultMaxOpenIteratorsPerDatabase = 50;
- class ComparatorAdapter : public leveldb::Comparator {
- public:
- explicit ComparatorAdapter(const LevelDBComparator* comparator);
-
- int Compare(const leveldb::Slice& a,
- const leveldb::Slice& b) const override;
-
- const char* Name() const override;
-
- void FindShortestSeparator(std::string* start,
- const leveldb::Slice& limit) const override;
- void FindShortSuccessor(std::string* key) const override;
-
- private:
- const LevelDBComparator* comparator_;
- };
-
// |max_open_cursors| cannot be 0.
static leveldb::Status Open(const base::FilePath& file_name,
const LevelDBComparator* comparator,
@@ -91,8 +75,6 @@ class CONTENT_EXPORT LevelDBDatabase
static std::unique_ptr<LevelDBDatabase> OpenInMemory(
const LevelDBComparator* comparator);
static leveldb::Status Destroy(const base::FilePath& file_name);
- static std::unique_ptr<LevelDBLock> LockForTesting(
- const base::FilePath& file_name);
~LevelDBDatabase() override;
leveldb::Status Put(const base::StringPiece& key, std::string* value);
@@ -111,12 +93,18 @@ class CONTENT_EXPORT LevelDBDatabase
bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
base::trace_event::ProcessMemoryDump* pmd) override;
+ leveldb::DB* db() { return db_.get(); }
+
protected:
- LevelDBDatabase(size_t max_open_iterators);
+ explicit LevelDBDatabase(size_t max_open_iterators);
private:
friend class LevelDBSnapshot;
friend class LevelDBIteratorImpl;
+ FRIEND_TEST_ALL_PREFIXES(IndexedDBTest, DeleteFailsIfDirectoryLocked);
+
+ static std::unique_ptr<LevelDBLock> LockForTesting(
+ const base::FilePath& file_name);
// Methods for iterator pooling.
std::unique_ptr<leveldb::Iterator> CreateLevelDBIterator(
diff --git a/chromium/content/browser/indexed_db/leveldb/mock_level_db.cc b/chromium/content/browser/indexed_db/leveldb/mock_level_db.cc
new file mode 100644
index 00000000000..ed76f35416d
--- /dev/null
+++ b/chromium/content/browser/indexed_db/leveldb/mock_level_db.cc
@@ -0,0 +1,17 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/indexed_db/leveldb/mock_level_db.h"
+
+namespace leveldb {
+
+MockIterator::MockIterator() {}
+
+MockIterator::~MockIterator() {}
+
+MockLevelDB::MockLevelDB() {}
+
+MockLevelDB::~MockLevelDB() {}
+
+} // namespace leveldb
diff --git a/chromium/content/browser/indexed_db/leveldb/mock_level_db.h b/chromium/content/browser/indexed_db/leveldb/mock_level_db.h
new file mode 100644
index 00000000000..ca1484191cc
--- /dev/null
+++ b/chromium/content/browser/indexed_db/leveldb/mock_level_db.h
@@ -0,0 +1,67 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_INDEXED_DB_LEVELDB_MOCK_LEVEL_DB_H_
+#define CONTENT_BROWSER_INDEXED_DB_LEVELDB_MOCK_LEVEL_DB_H_
+
+#include "testing/gmock/include/gmock/gmock.h"
+#include "third_party/leveldatabase/src/include/leveldb/db.h"
+
+namespace leveldb {
+
+class MockIterator : public Iterator {
+ public:
+ MockIterator();
+ ~MockIterator();
+
+ MOCK_CONST_METHOD0(Valid, bool());
+
+ MOCK_METHOD0(SeekToFirst, void());
+ MOCK_METHOD0(SeekToLast, void());
+ MOCK_METHOD1(Seek, void(const Slice& target));
+
+ MOCK_METHOD0(Next, void());
+ MOCK_METHOD0(Prev, void());
+
+ MOCK_CONST_METHOD0(key, Slice());
+ MOCK_CONST_METHOD0(value, Slice());
+ MOCK_CONST_METHOD0(status, Status());
+};
+
+class MockLevelDB : public DB {
+ public:
+ MockLevelDB();
+ ~MockLevelDB();
+
+ MOCK_METHOD3(Put,
+ Status(const WriteOptions& options,
+ const Slice& key,
+ const Slice& value));
+
+ MOCK_METHOD2(Delete, Status(const WriteOptions& options, const Slice& key));
+
+ MOCK_METHOD2(Write, Status(const WriteOptions& options, WriteBatch* updates));
+
+ MOCK_METHOD3(Get,
+ Status(const ReadOptions& options,
+ const Slice& key,
+ std::string* value));
+
+ MOCK_METHOD1(NewIterator, Iterator*(const ReadOptions& options));
+
+ MOCK_METHOD0(GetSnapshot, const Snapshot*());
+
+ MOCK_METHOD1(ReleaseSnapshot, void(const Snapshot*));
+
+ MOCK_METHOD2(GetProperty, bool(const Slice& property, std::string* value));
+
+ MOCK_METHOD3(GetApproximateSizes,
+ void(const Range* range, int n, uint64_t* sizes));
+
+ MOCK_METHOD2(CompactRange, void(const Slice* begin, const Slice* end));
+};
+
+} // namespace leveldb
+
+#endif // CONTENT_BROWSER_INDEXED_DB_LEVELDB_MOCK_LEVEL_DB_H_
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 e0c76704b61..83dbe840c8d 100644
--- a/chromium/content/browser/indexed_db/mock_indexed_db_factory.h
+++ b/chromium/content/browser/indexed_db/mock_indexed_db_factory.h
@@ -83,6 +83,9 @@ class MockIndexedDBFactory : public IndexedDBFactory {
MOCK_METHOD0(ContextDestroyed, void());
MOCK_METHOD1(DatabaseDeleted,
void(const IndexedDBDatabase::Identifier& identifier));
+
+ MOCK_METHOD1(BlobFilesCleaned, void(const url::Origin& origin));
+
MOCK_CONST_METHOD1(GetConnectionCount, size_t(const url::Origin& origin));
MOCK_METHOD2(ReportOutstandingBlobs,
diff --git a/chromium/content/browser/isolated_origin_browsertest.cc b/chromium/content/browser/isolated_origin_browsertest.cc
index 838d33c6423..c516436ddc7 100644
--- a/chromium/content/browser/isolated_origin_browsertest.cc
+++ b/chromium/content/browser/isolated_origin_browsertest.cc
@@ -3,7 +3,9 @@
// found in the LICENSE file.
#include "base/command_line.h"
+#include "content/browser/bad_message.h"
#include "content/browser/child_process_security_policy_impl.h"
+#include "content/browser/storage_partition_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/common/content_switches.h"
@@ -15,6 +17,7 @@
#include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test_utils_internal.h"
+#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 "url/gurl.h"
@@ -502,4 +505,80 @@ IN_PROC_BROWSER_TEST_F(IsolatedOriginTest, IsolatedOriginWithSubdomain) {
EXPECT_EQ(isolated_instance, web_contents()->GetSiteInstance());
}
+// This class allows intercepting the OpenLocalStorage method and changing
+// the parameters to the real implementation of it.
+class StoragePartitonInterceptor
+ : public mojom::StoragePartitionServiceInterceptorForTesting {
+ public:
+ StoragePartitonInterceptor(RenderProcessHostImpl* rph) {
+ // Install a custom callback for handling errors during interface calls.
+ // This is needed because the passthrough calls that this object makes
+ // to the real implementaion of the service don't have the correct
+ // context to invoke the real error callback.
+ mojo::edk::SetDefaultProcessErrorCallback(base::Bind(
+ [](int process_id, const std::string& s) {
+ bad_message::ReceivedBadMessage(process_id,
+ bad_message::DSMF_LOAD_STORAGE);
+ },
+ rph->GetID()));
+
+ static_cast<StoragePartitionImpl*>(rph->GetStoragePartition())
+ ->Bind(rph->GetID(), mojo::MakeRequest(&storage_partition_service_));
+ }
+
+ // Allow all methods that aren't explicitly overriden to pass through
+ // unmodified.
+ mojom::StoragePartitionService* GetForwardingInterface() override {
+ return storage_partition_service_.get();
+ }
+
+ // Override this method to allow changing the origin. It simulates a
+ // renderer process sending incorrect data to the browser process, so
+ // security checks can be tested.
+ void OpenLocalStorage(const url::Origin& origin,
+ mojom::LevelDBWrapperRequest request) override {
+ url::Origin mismatched_origin(GURL("http://abc.foo.com"));
+ GetForwardingInterface()->OpenLocalStorage(mismatched_origin,
+ std::move(request));
+ }
+
+ private:
+ // Keep a pointer to the original implementation of the service, so all
+ // calls can be forwarded to it.
+ // Note: When making calls through this object, they are in-process calls,
+ // so state on the receiving side of the call will be missing the real
+ // information of which process has made the real method call.
+ mojom::StoragePartitionServicePtr storage_partition_service_;
+};
+
+void CreateTestStoragePartitionService(
+ RenderProcessHostImpl* rph,
+ mojom::StoragePartitionServiceRequest request) {
+ mojo::MakeStrongBinding(base::MakeUnique<StoragePartitonInterceptor>(rph),
+ std::move(request));
+}
+
+// Verify that an isolated renderer process cannot read localStorage of an
+// origin outside of its isolated site.
+// TODO(nasko): Write a test to verify the opposite - any non-isolated renderer
+// process cannot access data of an isolated site.
+IN_PROC_BROWSER_TEST_F(IsolatedOriginTest, LocalStorageOriginEnforcement) {
+ RenderProcessHostImpl::SetCreateStoragePartitionServiceFunction(
+ CreateTestStoragePartitionService);
+
+ GURL isolated_url(
+ embedded_test_server()->GetURL("isolated.foo.com", "/title1.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), isolated_url));
+
+ content::RenderProcessHostWatcher crash_observer(
+ shell()->web_contents()->GetMainFrame()->GetProcess(),
+ content::RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
+ // Use ignore_result here, since on Android the renderer process is
+ // terminated, but ExecuteScript still returns true. It properly returns
+ // false on all other platforms.
+ ignore_result(ExecuteScript(shell()->web_contents()->GetMainFrame(),
+ "localStorage.length;"));
+ crash_observer.Wait();
+}
+
} // namespace content
diff --git a/chromium/content/browser/keyboard_lock/keyboard_lock_service_impl.h b/chromium/content/browser/keyboard_lock/keyboard_lock_service_impl.h
index 4202eb378f2..d5576bb5121 100644
--- a/chromium/content/browser/keyboard_lock/keyboard_lock_service_impl.h
+++ b/chromium/content/browser/keyboard_lock/keyboard_lock_service_impl.h
@@ -12,7 +12,7 @@
namespace content {
class CONTENT_EXPORT KeyboardLockServiceImpl
- : public NON_EXPORTED_BASE(blink::mojom::KeyboardLockService) {
+ : public blink::mojom::KeyboardLockService {
public:
KeyboardLockServiceImpl();
~KeyboardLockServiceImpl() override;
diff --git a/chromium/content/browser/leveldb_wrapper_impl.cc b/chromium/content/browser/leveldb_wrapper_impl.cc
index 487a6401f3c..0a08a5605a8 100644
--- a/chromium/content/browser/leveldb_wrapper_impl.cc
+++ b/chromium/content/browser/leveldb_wrapper_impl.cc
@@ -19,6 +19,11 @@ void LevelDBWrapperImpl::Delegate::MigrateData(
std::move(callback).Run(nullptr);
}
+std::vector<LevelDBWrapperImpl::Change> LevelDBWrapperImpl::Delegate::FixUpData(
+ const ValueMap& data) {
+ return std::vector<Change>();
+}
+
void LevelDBWrapperImpl::Delegate::OnMapLoaded(leveldb::mojom::DatabaseError) {}
bool LevelDBWrapperImpl::s_aggressive_flushing_enabled_ = false;
@@ -345,6 +350,31 @@ void LevelDBWrapperImpl::OnMapLoaded(
bytes_used_ += it->key.size() - prefix_.size() + it->value.size();
}
+ std::vector<Change> changes = delegate_->FixUpData(*map_);
+ if (!changes.empty()) {
+ DCHECK(database_);
+ CreateCommitBatchIfNeeded();
+ for (auto& change : changes) {
+ auto it = map_->find(change.first);
+ if (!change.second) {
+ DCHECK(it != map_->end());
+ bytes_used_ -= it->first.size() + it->second.size();
+ map_->erase(it);
+ } else {
+ if (it != map_->end()) {
+ bytes_used_ -= it->second.size();
+ it->second = std::move(*change.second);
+ bytes_used_ += it->second.size();
+ } else {
+ bytes_used_ += change.first.size() + change.second->size();
+ (*map_)[change.first] = std::move(*change.second);
+ }
+ }
+ commit_batch_->changed_keys.insert(std::move(change.first));
+ }
+ CommitChanges();
+ }
+
// We proceed without using a backing store, nothing will be persisted but the
// class is functional for the lifetime of the object.
delegate_->OnMapLoaded(status);
diff --git a/chromium/content/browser/leveldb_wrapper_impl.h b/chromium/content/browser/leveldb_wrapper_impl.h
index b6d47d10df1..336d4fdaf23 100644
--- a/chromium/content/browser/leveldb_wrapper_impl.h
+++ b/chromium/content/browser/leveldb_wrapper_impl.h
@@ -40,6 +40,8 @@ class CONTENT_EXPORT LevelDBWrapperImpl : public mojom::LevelDBWrapper {
public:
using ValueMap = std::map<std::vector<uint8_t>, std::vector<uint8_t>>;
using ValueMapCallback = base::OnceCallback<void(std::unique_ptr<ValueMap>)>;
+ using Change =
+ std::pair<std::vector<uint8_t>, base::Optional<std::vector<uint8_t>>>;
class CONTENT_EXPORT Delegate {
public:
@@ -49,6 +51,9 @@ class CONTENT_EXPORT LevelDBWrapperImpl : public mojom::LevelDBWrapper {
virtual void DidCommit(leveldb::mojom::DatabaseError error) = 0;
// Called during loading if no data was found. Needs to call |callback|.
virtual void MigrateData(ValueMapCallback callback);
+ // Called during loading to give delegate a chance to modify the data as
+ // stored in the database.
+ virtual std::vector<Change> FixUpData(const ValueMap& data);
virtual void OnMapLoaded(leveldb::mojom::DatabaseError error);
};
diff --git a/chromium/content/browser/leveldb_wrapper_impl_unittest.cc b/chromium/content/browser/leveldb_wrapper_impl_unittest.cc
index 3a54e20bd76..49d3e84cb21 100644
--- a/chromium/content/browser/leveldb_wrapper_impl_unittest.cc
+++ b/chromium/content/browser/leveldb_wrapper_impl_unittest.cc
@@ -59,11 +59,19 @@ class MockDelegate : public LevelDBWrapperImpl::Delegate {
void OnMapLoaded(leveldb::mojom::DatabaseError error) override {
map_load_count_++;
}
+ std::vector<LevelDBWrapperImpl::Change> FixUpData(
+ const LevelDBWrapperImpl::ValueMap& data) override {
+ return mock_changes_;
+ }
int map_load_count() const { return map_load_count_; }
+ void set_mock_changes(std::vector<LevelDBWrapperImpl::Change> changes) {
+ mock_changes_ = std::move(changes);
+ }
private:
int map_load_count_ = 0;
+ std::vector<LevelDBWrapperImpl::Change> mock_changes_;
};
void GetCallback(const base::Closure& callback,
@@ -526,4 +534,26 @@ TEST_F(LevelDBWrapperImplTest, PurgeMemoryWithPendingChanges) {
EXPECT_EQ(delegate()->map_load_count(), 1);
}
+TEST_F(LevelDBWrapperImplTest, FixUpData) {
+ std::vector<LevelDBWrapperImpl::Change> changes;
+ changes.push_back(std::make_pair(StdStringToUint8Vector("def"),
+ StdStringToUint8Vector("foo")));
+ changes.push_back(
+ std::make_pair(StdStringToUint8Vector("123"), base::nullopt));
+ changes.push_back(std::make_pair(StdStringToUint8Vector("abc"),
+ StdStringToUint8Vector("bla")));
+ delegate()->set_mock_changes(std::move(changes));
+
+ std::vector<uint8_t> result;
+ EXPECT_FALSE(GetSync(StdStringToUint8Vector("123"), &result));
+ EXPECT_TRUE(GetSync(StdStringToUint8Vector("def"), &result));
+ EXPECT_EQ(StdStringToUint8Vector("foo"), result);
+ EXPECT_TRUE(GetSync(StdStringToUint8Vector("abc"), &result));
+ EXPECT_EQ(StdStringToUint8Vector("bla"), result);
+
+ EXPECT_FALSE(has_mock_data(kTestPrefix + std::string("123")));
+ EXPECT_EQ("foo", get_mock_data(kTestPrefix + std::string("def")));
+ EXPECT_EQ("bla", get_mock_data(kTestPrefix + std::string("abc")));
+}
+
} // namespace content
diff --git a/chromium/content/browser/loader/DEPS b/chromium/content/browser/loader/DEPS
index 28ae5824446..03317bf0cc9 100644
--- a/chromium/content/browser/loader/DEPS
+++ b/chromium/content/browser/loader/DEPS
@@ -201,6 +201,7 @@ specific_include_rules = {
"+content/browser/ssl/ssl_client_auth_handler.h",
"+content/browser/ssl/ssl_error_handler.h",
"+content/common/content_export.h",
+ "+content/common/loader_util.h",
"+content/public/browser/resource_dispatcher_host_login_delegate.h",
"+content/public/common/browser_side_navigation_policy.h",
"+content/public/common/previews_state.h",
diff --git a/chromium/content/browser/loader/async_resource_handler.cc b/chromium/content/browser/loader/async_resource_handler.cc
index c8c8dd04203..1802baff29c 100644
--- a/chromium/content/browser/loader/async_resource_handler.cc
+++ b/chromium/content/browser/loader/async_resource_handler.cc
@@ -17,7 +17,6 @@
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_number_conversions.h"
#include "base/time/time.h"
-#include "content/browser/loader/netlog_observer.h"
#include "content/browser/loader/resource_buffer.h"
#include "content/browser/loader/resource_controller.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
@@ -152,7 +151,6 @@ void AsyncResourceHandler::OnRequestRedirected(
return;
}
- NetLogObserver::PopulateResponseInfo(request(), response);
response->head.encoded_data_length = request()->GetTotalReceivedBytes();
reported_transfer_size_ = 0;
response->head.request_start = request()->creation_time();
@@ -196,7 +194,6 @@ void AsyncResourceHandler::OnResponseStarted(
return;
}
- NetLogObserver::PopulateResponseInfo(request(), response);
response->head.encoded_data_length = request()->raw_header_size();
// If the parent handler downloaded the resource to a file, grant the child
@@ -364,18 +361,11 @@ void AsyncResourceHandler::OnResponseCompleted(
sent_received_response_msg_);
int error_code = status.error();
- const ResourceRequestInfoImpl* info = GetRequestInfo();
- bool was_ignored_by_handler = info->WasIgnoredByHandler();
DCHECK(status.status() != net::URLRequestStatus::IO_PENDING);
- // If this check fails, then we're in an inconsistent state because all
- // requests ignored by the handler should be canceled (which should result in
- // the ERR_ABORTED error code).
- DCHECK(!was_ignored_by_handler || error_code == net::ERR_ABORTED);
ResourceRequestCompletionStatus request_complete_data;
request_complete_data.error_code = error_code;
- request_complete_data.was_ignored_by_handler = was_ignored_by_handler;
request_complete_data.exists_in_cache = request()->response_info().was_cached;
request_complete_data.completion_time = TimeTicks::Now();
request_complete_data.encoded_data_length =
diff --git a/chromium/content/browser/loader/cross_site_resource_handler_browsertest.cc b/chromium/content/browser/loader/cross_site_resource_handler_browsertest.cc
index 4f4bdccc254..2e986ad1ed6 100644
--- a/chromium/content/browser/loader/cross_site_resource_handler_browsertest.cc
+++ b/chromium/content/browser/loader/cross_site_resource_handler_browsertest.cc
@@ -7,6 +7,7 @@
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/memory/weak_ptr.h"
+#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
@@ -76,9 +77,10 @@ class TestResourceDispatcherHostDelegate
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&TestResourceDispatcherHostDelegate::SetTrackedURLOnIOThread,
- base::Unretained(this), tracked_url, run_on_start,
- run_loop_->QuitClosure()));
+ base::BindOnce(
+ &TestResourceDispatcherHostDelegate::SetTrackedURLOnIOThread,
+ base::Unretained(this), tracked_url, run_on_start,
+ run_loop_->QuitClosure()));
}
// Waits until the tracked URL has been requested, and the request for it has
@@ -113,7 +115,7 @@ class TestResourceDispatcherHostDelegate
weak_factory_.GetWeakPtr()));
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(run_on_start_, resume_request_on_io_thread));
+ base::BindOnce(run_on_start_, resume_request_on_io_thread));
}
~CallbackRunningResourceThrottle() override {
@@ -191,7 +193,7 @@ class CrossSiteResourceHandlerTest : public ContentBrowserTest {
void SetUpOnMainThread() override {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(
+ base::BindOnce(
&CrossSiteResourceHandlerTest::InjectResourceDispatcherHostDelegate,
base::Unretained(this)));
host_resolver()->AddRule("*", "127.0.0.1");
@@ -202,9 +204,9 @@ class CrossSiteResourceHandlerTest : public ContentBrowserTest {
void TearDownOnMainThread() override {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&CrossSiteResourceHandlerTest::
- RestoreResourceDispatcherHostDelegate,
- base::Unretained(this)));
+ base::BindOnce(&CrossSiteResourceHandlerTest::
+ RestoreResourceDispatcherHostDelegate,
+ base::Unretained(this)));
}
protected:
diff --git a/chromium/content/browser/loader/detachable_resource_handler.cc b/chromium/content/browser/loader/detachable_resource_handler.cc
index 63e22d584af..00420872b33 100644
--- a/chromium/content/browser/loader/detachable_resource_handler.cc
+++ b/chromium/content/browser/loader/detachable_resource_handler.cc
@@ -45,11 +45,6 @@ class DetachableResourceHandler::Controller : public ResourceController {
detachable_handler_->Cancel();
}
- void CancelAndIgnore() override {
- MarkAsUsed();
- detachable_handler_->CancelAndIgnore();
- }
-
void CancelWithError(int error_code) override {
MarkAsUsed();
detachable_handler_->CancelWithError(error_code);
diff --git a/chromium/content/browser/loader/intercepting_resource_handler.cc b/chromium/content/browser/loader/intercepting_resource_handler.cc
index 77b28b41240..f74db04137f 100644
--- a/chromium/content/browser/loader/intercepting_resource_handler.cc
+++ b/chromium/content/browser/loader/intercepting_resource_handler.cc
@@ -35,11 +35,6 @@ class InterceptingResourceHandler::Controller : public ResourceController {
intercepting_handler_->Cancel();
}
- void CancelAndIgnore() override {
- MarkAsUsed();
- intercepting_handler_->CancelAndIgnore();
- }
-
void CancelWithError(int error_code) override {
MarkAsUsed();
intercepting_handler_->CancelWithError(error_code);
@@ -261,8 +256,8 @@ void InterceptingResourceHandler::ResumeInternal() {
// Can't call DoLoop synchronously, as it may call into |next_handler_|
// synchronously, which is what called Resume().
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&InterceptingResourceHandler::DoLoop,
- weak_ptr_factory_.GetWeakPtr()));
+ FROM_HERE, base::BindOnce(&InterceptingResourceHandler::DoLoop,
+ weak_ptr_factory_.GetWeakPtr()));
}
void InterceptingResourceHandler::SendOnWillReadToOldHandler() {
diff --git a/chromium/content/browser/loader/loader_io_thread_notifier.cc b/chromium/content/browser/loader/loader_io_thread_notifier.cc
index a10537c9d3d..47efe2831fe 100644
--- a/chromium/content/browser/loader/loader_io_thread_notifier.cc
+++ b/chromium/content/browser/loader/loader_io_thread_notifier.cc
@@ -30,9 +30,9 @@ void LoaderIOThreadNotifier::RenderFrameDeleted(
RenderFrameHost* render_frame_host) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&NotifyRenderFrameDeletedOnIO,
- static_cast<RenderFrameHostImpl*>(render_frame_host)
- ->GetGlobalFrameRoutingId()));
+ base::BindOnce(&NotifyRenderFrameDeletedOnIO,
+ static_cast<RenderFrameHostImpl*>(render_frame_host)
+ ->GetGlobalFrameRoutingId()));
}
} // namespace content
diff --git a/chromium/content/browser/loader/mime_sniffing_resource_handler.cc b/chromium/content/browser/loader/mime_sniffing_resource_handler.cc
index 20d09f512da..482bb55c2bf 100644
--- a/chromium/content/browser/loader/mime_sniffing_resource_handler.cc
+++ b/chromium/content/browser/loader/mime_sniffing_resource_handler.cc
@@ -14,7 +14,6 @@
#include "base/single_thread_task_runner.h"
#include "base/strings/string_util.h"
#include "base/threading/thread_task_runner_handle.h"
-#include "components/mime_util/mime_util.h"
#include "content/browser/download/download_resource_handler.h"
#include "content/browser/download/download_stats.h"
#include "content/browser/loader/intercepting_resource_handler.h"
@@ -39,6 +38,7 @@
#include "net/http/http_response_headers.h"
#include "net/url_request/url_request.h"
#include "ppapi/features/features.h"
+#include "third_party/WebKit/common/mime_util/mime_util.h"
#include "url/origin.h"
namespace content {
@@ -82,11 +82,6 @@ class MimeSniffingResourceHandler::Controller : public ResourceController {
mime_handler_->Cancel();
}
- void CancelAndIgnore() override {
- MarkAsUsed();
- mime_handler_->CancelAndIgnore();
- }
-
void CancelWithError(int error_code) override {
MarkAsUsed();
mime_handler_->CancelWithError(error_code);
@@ -321,8 +316,8 @@ void MimeSniffingResourceHandler::ResumeInternal() {
// it will resume the request. Posted as a task to avoid re-entrancy into
// the calling class.
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&MimeSniffingResourceHandler::AdvanceState,
- weak_ptr_factory_.GetWeakPtr()));
+ FROM_HERE, base::BindOnce(&MimeSniffingResourceHandler::AdvanceState,
+ weak_ptr_factory_.GetWeakPtr()));
}
void MimeSniffingResourceHandler::AdvanceState() {
@@ -459,7 +454,7 @@ bool MimeSniffingResourceHandler::MaybeStartInterception() {
bool must_download = MustDownload();
if (!must_download) {
- if (mime_util::IsSupportedMimeType(mime_type))
+ if (blink::IsSupportedMimeType(mime_type))
return true;
bool handled_by_plugin;
@@ -500,8 +495,8 @@ bool MimeSniffingResourceHandler::CheckForPluginHandler(
if (stale) {
// Refresh the plugins asynchronously.
plugin_service_->GetPlugins(
- base::Bind(&MimeSniffingResourceHandler::OnPluginsLoaded,
- weak_ptr_factory_.GetWeakPtr()));
+ base::BindOnce(&MimeSniffingResourceHandler::OnPluginsLoaded,
+ weak_ptr_factory_.GetWeakPtr()));
request()->LogBlockedBy("MimeSniffingResourceHandler");
// Will complete asynchronously.
return false;
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 ff071119651..45f93a45927 100644
--- a/chromium/content/browser/loader/mime_sniffing_resource_handler_unittest.cc
+++ b/chromium/content/browser/loader/mime_sniffing_resource_handler_unittest.cc
@@ -14,6 +14,7 @@
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
+#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/loader/intercepting_resource_handler.h"
diff --git a/chromium/content/browser/loader/mock_resource_loader.cc b/chromium/content/browser/loader/mock_resource_loader.cc
index acadbfca628..6971ab411fe 100644
--- a/chromium/content/browser/loader/mock_resource_loader.cc
+++ b/chromium/content/browser/loader/mock_resource_loader.cc
@@ -27,11 +27,6 @@ class MockResourceLoader::TestResourceController : public ResourceController {
void Cancel() override { CancelWithError(net::ERR_ABORTED); }
- void CancelAndIgnore() override {
- ADD_FAILURE() << "Unexpected CancelAndIgnore call.";
- Cancel();
- }
-
void CancelWithError(int error_code) override {
mock_loader_->OnCancel(error_code);
}
diff --git a/chromium/content/browser/loader/mojo_async_resource_handler.cc b/chromium/content/browser/loader/mojo_async_resource_handler.cc
index 1a84825e28f..c4688963035 100644
--- a/chromium/content/browser/loader/mojo_async_resource_handler.cc
+++ b/chromium/content/browser/loader/mojo_async_resource_handler.cc
@@ -17,7 +17,6 @@
#include "base/strings/string_number_conversions.h"
#include "base/time/time.h"
#include "content/browser/loader/downloaded_temp_file_impl.h"
-#include "content/browser/loader/netlog_observer.h"
#include "content/browser/loader/resource_controller.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/loader/resource_request_info_impl.h"
@@ -60,7 +59,7 @@ void InitializeResourceBufferConstants() {
GetNumericArg("resource-buffer-size", &g_allocation_size);
}
-void NotReached(mojom::URLLoaderAssociatedRequest mojo_request,
+void NotReached(mojom::URLLoaderRequest mojo_request,
mojom::URLLoaderClientPtr url_loader_client) {
NOTREACHED();
}
@@ -90,7 +89,7 @@ class MojoAsyncResourceHandler::SharedWriter final
class MojoAsyncResourceHandler::WriterIOBuffer final
: public net::IOBufferWithSize {
public:
- // |data| and |size| should be gotten from |writer| via BeginWriteDataRaw.
+ // |data| and |size| should be gotten from |writer| via BeginWriteData.
// They will be accesible via IOBuffer methods. As |writer| is stored in this
// instance, |data| will be kept valid as long as the following conditions
// hold:
@@ -115,7 +114,7 @@ class MojoAsyncResourceHandler::WriterIOBuffer final
MojoAsyncResourceHandler::MojoAsyncResourceHandler(
net::URLRequest* request,
ResourceDispatcherHostImpl* rdh,
- mojom::URLLoaderAssociatedRequest mojo_request,
+ mojom::URLLoaderRequest mojo_request,
mojom::URLLoaderClientPtr url_loader_client,
ResourceType resource_type)
: ResourceHandler(request),
@@ -128,8 +127,8 @@ MojoAsyncResourceHandler::MojoAsyncResourceHandler(
InitializeResourceBufferConstants();
// This unretained pointer is safe, because |binding_| is owned by |this| and
// the callback will never be called after |this| is destroyed.
- binding_.set_connection_error_handler(
- base::Bind(&MojoAsyncResourceHandler::Cancel, base::Unretained(this)));
+ binding_.set_connection_error_handler(base::BindOnce(
+ &MojoAsyncResourceHandler::Cancel, base::Unretained(this)));
if (IsResourceTypeFrame(resource_type)) {
GetRequestInfo()->set_on_transfer(base::Bind(
@@ -157,7 +156,6 @@ void MojoAsyncResourceHandler::OnRequestRedirected(
HoldController(std::move(controller));
did_defer_on_redirect_ = true;
- NetLogObserver::PopulateResponseInfo(request(), response);
response->head.encoded_data_length = request()->GetTotalReceivedBytes();
response->head.request_start = request()->creation_time();
response->head.response_start = base::TimeTicks::Now();
@@ -179,7 +177,6 @@ void MojoAsyncResourceHandler::OnResponseStarted(
}
const ResourceRequestInfoImpl* info = GetRequestInfo();
- NetLogObserver::PopulateResponseInfo(request(), response);
response->head.encoded_data_length = request()->raw_header_size();
reported_total_received_bytes_ = response->head.encoded_data_length;
@@ -395,8 +392,8 @@ void MojoAsyncResourceHandler::SetAllocationSizeForTesting(size_t size) {
MojoResult MojoAsyncResourceHandler::BeginWrite(void** data,
uint32_t* available) {
- MojoResult result = mojo::BeginWriteDataRaw(
- shared_writer_->writer(), data, available, MOJO_WRITE_DATA_FLAG_NONE);
+ MojoResult result = shared_writer_->writer().BeginWriteData(
+ data, available, MOJO_WRITE_DATA_FLAG_NONE);
if (result == MOJO_RESULT_OK)
*available = std::min(*available, static_cast<uint32_t>(kMaxChunkSize));
else if (result == MOJO_RESULT_SHOULD_WAIT)
@@ -405,7 +402,7 @@ MojoResult MojoAsyncResourceHandler::BeginWrite(void** data,
}
MojoResult MojoAsyncResourceHandler::EndWrite(uint32_t written) {
- MojoResult result = mojo::EndWriteDataRaw(shared_writer_->writer(), written);
+ MojoResult result = shared_writer_->writer().EndWriteData(written);
if (result == MOJO_RESULT_OK) {
total_written_bytes_ += written;
handle_watcher_.ArmOrNotify();
@@ -433,8 +430,6 @@ void MojoAsyncResourceHandler::OnResponseCompleted(
buffer_ = nullptr;
handle_watcher_.Cancel();
- const ResourceRequestInfoImpl* info = GetRequestInfo();
-
// TODO(gavinp): Remove this CHECK when we figure out the cause of
// http://crbug.com/124680 . This check mirrors closely check in
// WebURLLoaderImpl::OnCompletedRequest that routes this message to a WebCore
@@ -444,17 +439,11 @@ void MojoAsyncResourceHandler::OnResponseCompleted(
sent_received_response_message_);
int error_code = status.error();
- bool was_ignored_by_handler = info->WasIgnoredByHandler();
DCHECK_NE(status.status(), net::URLRequestStatus::IO_PENDING);
- // If this check fails, then we're in an inconsistent state because all
- // requests ignored by the handler should be canceled (which should result in
- // the ERR_ABORTED error code).
- DCHECK(!was_ignored_by_handler || error_code == net::ERR_ABORTED);
ResourceRequestCompletionStatus request_complete_data;
request_complete_data.error_code = error_code;
- request_complete_data.was_ignored_by_handler = was_ignored_by_handler;
request_complete_data.exists_in_cache = request()->response_info().was_cached;
request_complete_data.completion_time = base::TimeTicks::Now();
request_complete_data.encoded_data_length =
@@ -587,12 +576,12 @@ MojoAsyncResourceHandler::CreateUploadProgressTracker(
}
void MojoAsyncResourceHandler::OnTransfer(
- mojom::URLLoaderAssociatedRequest mojo_request,
+ mojom::URLLoaderRequest mojo_request,
mojom::URLLoaderClientPtr url_loader_client) {
binding_.Unbind();
binding_.Bind(std::move(mojo_request));
- binding_.set_connection_error_handler(
- base::Bind(&MojoAsyncResourceHandler::Cancel, base::Unretained(this)));
+ binding_.set_connection_error_handler(base::BindOnce(
+ &MojoAsyncResourceHandler::Cancel, base::Unretained(this)));
url_loader_client_ = std::move(url_loader_client);
}
@@ -600,8 +589,8 @@ void MojoAsyncResourceHandler::SendUploadProgress(
const net::UploadProgress& progress) {
url_loader_client_->OnUploadProgress(
progress.position(), progress.size(),
- base::Bind(&MojoAsyncResourceHandler::OnUploadProgressACK,
- weak_factory_.GetWeakPtr()));
+ base::BindOnce(&MojoAsyncResourceHandler::OnUploadProgressACK,
+ weak_factory_.GetWeakPtr()));
}
void MojoAsyncResourceHandler::OnUploadProgressACK() {
diff --git a/chromium/content/browser/loader/mojo_async_resource_handler.h b/chromium/content/browser/loader/mojo_async_resource_handler.h
index e139f123028..68e9648f04a 100644
--- a/chromium/content/browser/loader/mojo_async_resource_handler.h
+++ b/chromium/content/browser/loader/mojo_async_resource_handler.h
@@ -18,7 +18,7 @@
#include "content/common/content_export.h"
#include "content/public/common/resource_type.h"
#include "content/public/common/url_loader.mojom.h"
-#include "mojo/public/cpp/bindings/associated_binding.h"
+#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/system/data_pipe.h"
#include "mojo/public/cpp/system/simple_watcher.h"
#include "net/base/io_buffer.h"
@@ -48,13 +48,12 @@ struct ResourceResponse;
// TODO(yhirano): Send cached metadata.
//
// This class can be inherited only for tests.
-class CONTENT_EXPORT MojoAsyncResourceHandler
- : public ResourceHandler,
- public NON_EXPORTED_BASE(mojom::URLLoader) {
+class CONTENT_EXPORT MojoAsyncResourceHandler : public ResourceHandler,
+ public mojom::URLLoader {
public:
MojoAsyncResourceHandler(net::URLRequest* request,
ResourceDispatcherHostImpl* rdh,
- mojom::URLLoaderAssociatedRequest mojo_request,
+ mojom::URLLoaderRequest mojo_request,
mojom::URLLoaderClientPtr url_loader_client,
ResourceType resource_type);
~MojoAsyncResourceHandler() override;
@@ -121,13 +120,13 @@ class CONTENT_EXPORT MojoAsyncResourceHandler
const tracked_objects::Location& from_here,
UploadProgressTracker::UploadProgressReportCallback callback);
- void OnTransfer(mojom::URLLoaderAssociatedRequest mojo_request,
+ void OnTransfer(mojom::URLLoaderRequest mojo_request,
mojom::URLLoaderClientPtr url_loader_client);
void SendUploadProgress(const net::UploadProgress& progress);
void OnUploadProgressACK();
ResourceDispatcherHostImpl* rdh_;
- mojo::AssociatedBinding<mojom::URLLoader> binding_;
+ mojo::Binding<mojom::URLLoader> binding_;
bool has_checked_for_sufficient_resources_ = false;
bool sent_received_response_message_ = false;
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 d6bf4cba787..27ccfad2c6a 100644
--- a/chromium/content/browser/loader/mojo_async_resource_handler_unittest.cc
+++ b/chromium/content/browser/loader/mojo_async_resource_handler_unittest.cc
@@ -208,7 +208,7 @@ class MojoAsyncResourceHandlerWithStubOperations
MojoAsyncResourceHandlerWithStubOperations(
net::URLRequest* request,
ResourceDispatcherHostImpl* rdh,
- mojom::URLLoaderAssociatedRequest mojo_request,
+ mojom::URLLoaderRequest mojo_request,
mojom::URLLoaderClientPtr url_loader_client)
: MojoAsyncResourceHandler(request,
rdh,
@@ -291,7 +291,7 @@ class TestURLLoaderFactory final : public mojom::URLLoaderFactory {
TestURLLoaderFactory() {}
~TestURLLoaderFactory() override {}
- void CreateLoaderAndStart(mojom::URLLoaderAssociatedRequest request,
+ void CreateLoaderAndStart(mojom::URLLoaderRequest request,
int32_t routing_id,
int32_t request_id,
uint32_t options,
@@ -303,21 +303,16 @@ class TestURLLoaderFactory final : public mojom::URLLoaderFactory {
client_ptr_ = std::move(client_ptr);
}
- mojom::URLLoaderAssociatedRequest PassLoaderRequest() {
+ mojom::URLLoaderRequest PassLoaderRequest() {
return std::move(loader_request_);
}
mojom::URLLoaderClientPtr PassClientPtr() { return std::move(client_ptr_); }
- void SyncLoad(int32_t routing_id,
- int32_t request_id,
- const ResourceRequest& url_request,
- SyncLoadCallback callback) override {
- NOTREACHED();
- }
+ void Clone(mojom::URLLoaderFactoryRequest request) override { NOTREACHED(); }
private:
- mojom::URLLoaderAssociatedRequest loader_request_;
+ mojom::URLLoaderRequest loader_request_;
mojom::URLLoaderClientPtr client_ptr_;
DISALLOW_COPY_AND_ASSIGN(TestURLLoaderFactory);
@@ -422,7 +417,7 @@ class MojoAsyncResourceHandlerTestBase {
TestResourceDispatcherHostDelegate rdh_delegate_;
ResourceDispatcherHostImpl rdh_;
mojom::URLLoaderFactoryPtr url_loader_factory_;
- mojom::URLLoaderAssociatedPtr url_loader_proxy_;
+ mojom::URLLoaderPtr url_loader_proxy_;
TestURLLoaderClient url_loader_client_;
std::unique_ptr<TestBrowserContext> browser_context_;
net::TestDelegate url_request_delegate_;
@@ -549,9 +544,8 @@ TEST_F(MojoAsyncResourceHandlerTest, OnWillReadAndOnReadCompleted) {
while (contents.size() < 2) {
char buffer[16];
uint32_t read_size = sizeof(buffer);
- MojoResult result =
- mojo::ReadDataRaw(url_loader_client_.response_body(), buffer,
- &read_size, MOJO_READ_DATA_FLAG_NONE);
+ MojoResult result = url_loader_client_.response_body().ReadData(
+ buffer, &read_size, MOJO_READ_DATA_FLAG_NONE);
if (result == MOJO_RESULT_SHOULD_WAIT) {
base::RunLoop().RunUntilIdle();
continue;
@@ -584,9 +578,8 @@ TEST_F(MojoAsyncResourceHandlerTest,
base::RunLoop().RunUntilIdle();
char buffer[16];
uint32_t read_size = sizeof(buffer);
- MojoResult result =
- mojo::ReadDataRaw(url_loader_client_.response_body(), buffer,
- &read_size, MOJO_READ_DATA_FLAG_NONE);
+ MojoResult result = url_loader_client_.response_body().ReadData(
+ buffer, &read_size, MOJO_READ_DATA_FLAG_NONE);
if (result == MOJO_RESULT_SHOULD_WAIT)
continue;
ASSERT_EQ(MOJO_RESULT_OK, result);
@@ -615,8 +608,6 @@ TEST_F(MojoAsyncResourceHandlerTest,
TEST_F(MojoAsyncResourceHandlerTest, OnResponseCompleted) {
ASSERT_TRUE(CallOnWillStartAndOnResponseStarted());
- ResourceRequestInfoImpl::ForRequest(request_.get())
- ->set_was_ignored_by_handler(false);
net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, net::OK);
base::TimeTicks now1 = base::TimeTicks::Now();
@@ -627,7 +618,6 @@ TEST_F(MojoAsyncResourceHandlerTest, OnResponseCompleted) {
url_loader_client_.RunUntilComplete();
EXPECT_TRUE(url_loader_client_.has_received_completion());
EXPECT_EQ(net::OK, url_loader_client_.completion_status().error_code);
- EXPECT_FALSE(url_loader_client_.completion_status().was_ignored_by_handler);
EXPECT_LE(now1, url_loader_client_.completion_status().completion_time);
EXPECT_LE(url_loader_client_.completion_status().completion_time, now2);
EXPECT_EQ(request_->GetTotalReceivedBytes(),
@@ -647,8 +637,6 @@ TEST_F(MojoAsyncResourceHandlerTest, OnResponseCompleted2) {
ASSERT_FALSE(url_loader_client_.has_received_response());
url_loader_client_.RunUntilResponseReceived();
- ResourceRequestInfoImpl::ForRequest(request_.get())
- ->set_was_ignored_by_handler(true);
net::URLRequestStatus status(net::URLRequestStatus::CANCELED,
net::ERR_ABORTED);
@@ -661,7 +649,6 @@ TEST_F(MojoAsyncResourceHandlerTest, OnResponseCompleted2) {
EXPECT_TRUE(url_loader_client_.has_received_completion());
EXPECT_EQ(net::ERR_ABORTED,
url_loader_client_.completion_status().error_code);
- EXPECT_TRUE(url_loader_client_.completion_status().was_ignored_by_handler);
EXPECT_LE(now1, url_loader_client_.completion_status().completion_time);
EXPECT_LE(url_loader_client_.completion_status().completion_time, now2);
EXPECT_EQ(request_->GetTotalReceivedBytes(),
@@ -716,9 +703,8 @@ TEST_F(MojoAsyncResourceHandlerTest, ResponseCompletionShouldCloseDataPipe) {
while (true) {
char buffer[16];
uint32_t read_size = sizeof(buffer);
- MojoResult result =
- mojo::ReadDataRaw(url_loader_client_.response_body(), buffer,
- &read_size, MOJO_READ_DATA_FLAG_NONE);
+ MojoResult result = url_loader_client_.response_body().ReadData(
+ buffer, &read_size, MOJO_READ_DATA_FLAG_NONE);
if (result == MOJO_RESULT_FAILED_PRECONDITION)
break;
ASSERT_TRUE(result == MOJO_RESULT_SHOULD_WAIT || result == MOJO_RESULT_OK);
@@ -750,9 +736,8 @@ TEST_F(MojoAsyncResourceHandlerTest, OutOfBandCancelDuringBodyTransmission) {
while (true) {
char buf[16];
uint32_t read_size = sizeof(buf);
- MojoResult result =
- mojo::ReadDataRaw(url_loader_client_.response_body(), buf, &read_size,
- MOJO_READ_DATA_FLAG_NONE);
+ MojoResult result = url_loader_client_.response_body().ReadData(
+ buf, &read_size, MOJO_READ_DATA_FLAG_NONE);
if (result == MOJO_RESULT_FAILED_PRECONDITION)
break;
if (result == MOJO_RESULT_SHOULD_WAIT) {
@@ -799,9 +784,8 @@ TEST_F(MojoAsyncResourceHandlerTest, BeginWriteReturnsShouldWaitOnWillRead) {
while (true) {
char buffer[16];
uint32_t read_size = sizeof(buffer);
- MojoResult result =
- mojo::ReadDataRaw(url_loader_client_.response_body(), buffer,
- &read_size, MOJO_READ_DATA_FLAG_NONE);
+ MojoResult result = url_loader_client_.response_body().ReadData(
+ buffer, &read_size, MOJO_READ_DATA_FLAG_NONE);
if (result != MOJO_RESULT_SHOULD_WAIT) {
ASSERT_EQ(MOJO_RESULT_OK, result);
ASSERT_EQ(1u, read_size);
@@ -863,9 +847,8 @@ TEST_F(MojoAsyncResourceHandlerTest,
while (true) {
char buffer[16];
uint32_t read_size = sizeof(buffer);
- MojoResult result =
- mojo::ReadDataRaw(url_loader_client_.response_body(), buffer,
- &read_size, MOJO_READ_DATA_FLAG_NONE);
+ MojoResult result = url_loader_client_.response_body().ReadData(
+ buffer, &read_size, MOJO_READ_DATA_FLAG_NONE);
if (result != MOJO_RESULT_SHOULD_WAIT) {
ASSERT_EQ(MOJO_RESULT_OK, result);
ASSERT_EQ(1u, read_size);
@@ -943,9 +926,8 @@ TEST_F(MojoAsyncResourceHandlerTest,
while (true) {
char buf[16];
uint32_t read_size = sizeof(buf);
- MojoResult result =
- mojo::ReadDataRaw(url_loader_client_.response_body(), buf, &read_size,
- MOJO_READ_DATA_FLAG_NONE);
+ MojoResult result = url_loader_client_.response_body().ReadData(
+ buf, &read_size, MOJO_READ_DATA_FLAG_NONE);
if (result == MOJO_RESULT_SHOULD_WAIT)
break;
ASSERT_EQ(MOJO_RESULT_OK, result);
@@ -1057,9 +1039,8 @@ TEST_P(MojoAsyncResourceHandlerWithAllocationSizeTest,
char buf[16];
uint32_t read_size = sizeof(buf);
- MojoResult result =
- mojo::ReadDataRaw(url_loader_client_.response_body(), buf, &read_size,
- MOJO_READ_DATA_FLAG_NONE);
+ MojoResult result = url_loader_client_.response_body().ReadData(
+ buf, &read_size, MOJO_READ_DATA_FLAG_NONE);
if (result != MOJO_RESULT_SHOULD_WAIT) {
ASSERT_EQ(MOJO_RESULT_OK, result);
actual.append(buf, read_size);
@@ -1133,9 +1114,8 @@ TEST_P(MojoAsyncResourceHandlerWithAllocationSizeTest,
while (mock_loader_->status() != MockResourceLoader::Status::CANCELED) {
char buf[256];
uint32_t read_size = sizeof(buf);
- MojoResult result =
- mojo::ReadDataRaw(url_loader_client_.response_body(), buf, &read_size,
- MOJO_READ_DATA_FLAG_NONE);
+ MojoResult result = url_loader_client_.response_body().ReadData(
+ buf, &read_size, MOJO_READ_DATA_FLAG_NONE);
ASSERT_TRUE(result == MOJO_RESULT_OK || result == MOJO_RESULT_SHOULD_WAIT);
base::RunLoop().RunUntilIdle();
}
@@ -1182,9 +1162,8 @@ TEST_P(MojoAsyncResourceHandlerWithAllocationSizeTest, CancelWhileWaiting) {
while (true) {
char buffer[16];
uint32_t read_size = sizeof(buffer);
- MojoResult result =
- mojo::ReadDataRaw(url_loader_client_.response_body(), buffer,
- &read_size, MOJO_READ_DATA_FLAG_NONE);
+ MojoResult result = url_loader_client_.response_body().ReadData(
+ buffer, &read_size, MOJO_READ_DATA_FLAG_NONE);
if (result == MOJO_RESULT_FAILED_PRECONDITION)
break;
base::RunLoop().RunUntilIdle();
@@ -1298,9 +1277,8 @@ TEST_P(
while (true) {
char buffer[16];
uint32_t read_size = sizeof(buffer);
- MojoResult result =
- mojo::ReadDataRaw(url_loader_client_.response_body(), buffer,
- &read_size, MOJO_READ_DATA_FLAG_NONE);
+ MojoResult result = url_loader_client_.response_body().ReadData(
+ buffer, &read_size, MOJO_READ_DATA_FLAG_NONE);
if (result == MOJO_RESULT_FAILED_PRECONDITION)
break;
if (result == MOJO_RESULT_SHOULD_WAIT) {
@@ -1349,9 +1327,8 @@ TEST_P(
while (true) {
char buffer[16];
uint32_t read_size = sizeof(buffer);
- MojoResult result =
- mojo::ReadDataRaw(url_loader_client_.response_body(), buffer,
- &read_size, MOJO_READ_DATA_FLAG_NONE);
+ MojoResult result = url_loader_client_.response_body().ReadData(
+ buffer, &read_size, MOJO_READ_DATA_FLAG_NONE);
if (result == MOJO_RESULT_FAILED_PRECONDITION)
break;
if (result == MOJO_RESULT_SHOULD_WAIT) {
diff --git a/chromium/content/browser/loader/navigation_resource_handler.cc b/chromium/content/browser/loader/navigation_resource_handler.cc
index 9a4cc383ce2..4a522b1291a 100644
--- a/chromium/content/browser/loader/navigation_resource_handler.cc
+++ b/chromium/content/browser/loader/navigation_resource_handler.cc
@@ -8,8 +8,8 @@
#include "base/bind.h"
#include "base/logging.h"
+#include "base/optional.h"
#include "content/browser/loader/navigation_url_loader_impl_core.h"
-#include "content/browser/loader/netlog_observer.h"
#include "content/browser/loader/resource_controller.h"
#include "content/browser/loader/resource_loader.h"
#include "content/browser/loader/resource_request_info_impl.h"
@@ -22,7 +22,23 @@
#include "content/public/browser/stream_handle.h"
#include "content/public/common/resource_response.h"
#include "net/base/net_errors.h"
+#include "net/http/transport_security_state.h"
+#include "net/ssl/ssl_info.h"
#include "net/url_request/url_request.h"
+#include "net/url_request/url_request_context.h"
+#include "url/gurl.h"
+
+namespace {
+
+// TODO(crbug.com/757633): Attach this information to net::SSLInfo instead of
+// calculating it here.
+bool ShouldSSLErrorsBeFatal(net::URLRequest* request) {
+ net::TransportSecurityState* state =
+ request->context()->transport_security_state();
+ return state->ShouldSSLErrorsBeFatal(request->url().host());
+}
+
+} // namespace
namespace content {
@@ -48,7 +64,7 @@ NavigationResourceHandler::NavigationResourceHandler(
NavigationResourceHandler::~NavigationResourceHandler() {
if (core_) {
- core_->NotifyRequestFailed(false, net::ERR_ABORTED);
+ core_->NotifyRequestFailed(false, net::ERR_ABORTED, base::nullopt, false);
DetachFromCore();
}
}
@@ -57,7 +73,7 @@ void NavigationResourceHandler::Cancel() {
if (core_) {
DetachFromCore();
if (has_controller()) {
- CancelAndIgnore();
+ LayeredResourceHandler::Cancel();
} else {
OutOfBandCancel(net::ERR_ABORTED, true /* tell_renderer */);
}
@@ -92,11 +108,10 @@ void NavigationResourceHandler::OnRequestRedirected(
// The UI thread already cancelled the navigation. Do not proceed.
if (!core_) {
- controller->CancelAndIgnore();
+ controller->Cancel();
return;
}
- NetLogObserver::PopulateResponseInfo(request(), response);
response->head.encoded_data_length = request()->GetTotalReceivedBytes();
core_->NotifyRequestRedirected(redirect_info, response);
@@ -112,13 +127,12 @@ void NavigationResourceHandler::OnResponseStarted(
// The UI thread already cancelled the navigation. Do not proceed.
if (!core_) {
- controller->CancelAndIgnore();
+ controller->Cancel();
return;
}
ResourceRequestInfoImpl* info = GetRequestInfo();
- NetLogObserver::PopulateResponseInfo(request(), response);
response->head.encoded_data_length = request()->raw_header_size();
std::unique_ptr<NavigationData> cloned_data;
@@ -147,9 +161,16 @@ void NavigationResourceHandler::OnResponseCompleted(
const net::URLRequestStatus& status,
std::unique_ptr<ResourceController> controller) {
if (core_) {
- DCHECK_NE(net::OK, status.error());
- core_->NotifyRequestFailed(request()->response_info().was_cached,
- status.error());
+ int net_error = status.error();
+ DCHECK_NE(net::OK, net_error);
+
+ base::Optional<net::SSLInfo> ssl_info;
+ if (net::IsCertStatusError(request()->ssl_info().cert_status)) {
+ ssl_info = request()->ssl_info();
+ }
+
+ core_->NotifyRequestFailed(request()->response_info().was_cached, net_error,
+ ssl_info, ShouldSSLErrorsBeFatal(request()));
DetachFromCore();
}
next_handler_->OnResponseCompleted(status, std::move(controller));
diff --git a/chromium/content/browser/loader/navigation_resource_throttle.cc b/chromium/content/browser/loader/navigation_resource_throttle.cc
index 0d791612af2..5cfee324061 100644
--- a/chromium/content/browser/loader/navigation_resource_throttle.cc
+++ b/chromium/content/browser/loader/navigation_resource_throttle.cc
@@ -50,7 +50,7 @@ void SendCheckResultToIOThread(UIChecksPerformedCallback callback,
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK_NE(result, NavigationThrottle::DEFER);
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::Bind(callback, result));
+ base::BindOnce(callback, result));
}
// Returns the NavigationHandle to use for a navigation in the frame specified
@@ -214,14 +214,15 @@ void NavigationResourceThrottle::WillStartRequest(bool* defer) {
DCHECK(request_->method() == "POST" || request_->method() == "GET");
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&CheckWillStartRequestOnUIThread, callback, render_process_id,
- render_frame_id, request_->method(), info->body(),
- Referrer::SanitizeForRequest(
- request_->url(), Referrer(GURL(request_->referrer()),
- info->GetReferrerPolicy())),
- info->HasUserGesture(), info->GetPageTransition(),
- is_external_protocol, request_context_type_,
- mixed_content_context_type_));
+ base::BindOnce(
+ &CheckWillStartRequestOnUIThread, callback, render_process_id,
+ render_frame_id, request_->method(), info->body(),
+ Referrer::SanitizeForRequest(
+ request_->url(),
+ Referrer(GURL(request_->referrer()), info->GetReferrerPolicy())),
+ info->HasUserGesture(), info->GetPageTransition(),
+ is_external_protocol, request_context_type_,
+ mixed_content_context_type_));
*defer = true;
}
@@ -263,11 +264,11 @@ void NavigationResourceThrottle::WillRedirectRequest(
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&CheckWillRedirectRequestOnUIThread, callback,
- render_process_id, render_frame_id, redirect_info.new_url,
- redirect_info.new_method, GURL(redirect_info.new_referrer),
- new_is_external_protocol, response_headers,
- request_->response_info().connection_info));
+ base::BindOnce(&CheckWillRedirectRequestOnUIThread, callback,
+ render_process_id, render_frame_id, redirect_info.new_url,
+ redirect_info.new_method, GURL(redirect_info.new_referrer),
+ new_is_external_protocol, response_headers,
+ request_->response_info().connection_info));
*defer = true;
}
@@ -316,13 +317,13 @@ void NavigationResourceThrottle::WillProcessResponse(bool* defer) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&WillProcessResponseOnUIThread, callback, render_process_id,
- render_frame_id, response_headers,
- request_->response_info().connection_info, ssl_status,
- info->GetGlobalRequestID(),
- info->should_replace_current_entry(), info->IsDownload(),
- info->is_stream(), transfer_callback,
- base::Passed(&cloned_data)));
+ base::BindOnce(&WillProcessResponseOnUIThread, callback,
+ render_process_id, render_frame_id, response_headers,
+ request_->response_info().connection_info, ssl_status,
+ info->GetGlobalRequestID(),
+ info->should_replace_current_entry(), info->IsDownload(),
+ info->is_stream(), transfer_callback,
+ base::Passed(&cloned_data)));
*defer = true;
}
@@ -349,9 +350,8 @@ void NavigationResourceThrottle::OnUIChecksPerformed(
return;
}
- if (result == NavigationThrottle::CANCEL_AND_IGNORE) {
- CancelAndIgnore();
- } else if (result == NavigationThrottle::CANCEL) {
+ if (result == NavigationThrottle::CANCEL_AND_IGNORE ||
+ result == NavigationThrottle::CANCEL) {
Cancel();
} else if (result == NavigationThrottle::BLOCK_REQUEST ||
result == NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE) {
diff --git a/chromium/content/browser/loader/navigation_url_loader_delegate.h b/chromium/content/browser/loader/navigation_url_loader_delegate.h
index 34723cf4e1c..2dbb64f3d8d 100644
--- a/chromium/content/browser/loader/navigation_url_loader_delegate.h
+++ b/chromium/content/browser/loader/navigation_url_loader_delegate.h
@@ -15,6 +15,7 @@
namespace net {
struct RedirectInfo;
+class SSLInfo;
}
namespace content {
@@ -55,8 +56,18 @@ class CONTENT_EXPORT NavigationURLLoaderDelegate {
// Called if the request fails before receving a response. |net_error| is a
// network error code for the failure. |has_stale_copy_in_cache| is true if
- // there is a stale copy of the unreachable page in cache.
- virtual void OnRequestFailed(bool has_stale_copy_in_cache, int net_error) = 0;
+ // there is a stale copy of the unreachable page in cache. |ssl_info| is the
+ // SSL info for the request. |should_ssl_errors_be_fatal| indicates
+ // whether SSL errors for the request should be fatal.
+ // If |net_error| is a certificate error, the caller should pass a value for
+ // |ssl_info|. If |net_error| is not a certificate error, |ssl_info| and
+ // |fatal_cert_error| are ignored.
+ // TODO(https://crbug.com/757633): Change "should pass a value for |ssl_info|"
+ // to "must pass..."
+ virtual void OnRequestFailed(bool has_stale_copy_in_cache,
+ int net_error,
+ const base::Optional<net::SSLInfo>& ssl_info,
+ bool should_ssl_errors_be_fatal) = 0;
// Called after the network request has begun on the IO thread at time
// |timestamp|. This is just a thread hop but is used to compare timing
diff --git a/chromium/content/browser/loader/navigation_url_loader_impl.cc b/chromium/content/browser/loader/navigation_url_loader_impl.cc
index 71d0c2cba99..6371909c0b3 100644
--- a/chromium/content/browser/loader/navigation_url_loader_impl.cc
+++ b/chromium/content/browser/loader/navigation_url_loader_impl.cc
@@ -8,6 +8,7 @@
#include "base/bind.h"
#include "base/location.h"
+#include "base/optional.h"
#include "base/trace_event/trace_event.h"
#include "content/browser/appcache/appcache_navigation_handle.h"
#include "content/browser/appcache/appcache_navigation_handle_core.h"
@@ -52,19 +53,20 @@ NavigationURLLoaderImpl::NavigationURLLoaderImpl(
appcache_handle ? appcache_handle->core() : nullptr;
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&NavigationURLLoaderImplCore::Start, core_, resource_context,
- storage_partition->GetURLRequestContext(),
- base::Unretained(storage_partition->GetFileSystemContext()),
- service_worker_handle_core, appcache_handle_core,
- base::Passed(&request_info),
- base::Passed(&navigation_ui_data)));
+ base::BindOnce(
+ &NavigationURLLoaderImplCore::Start, core_, resource_context,
+ storage_partition->GetURLRequestContext(),
+ base::Unretained(storage_partition->GetFileSystemContext()),
+ service_worker_handle_core, appcache_handle_core,
+ base::Passed(&request_info), base::Passed(&navigation_ui_data)));
}
NavigationURLLoaderImpl::~NavigationURLLoaderImpl() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&NavigationURLLoaderImplCore::CancelRequestIfNeeded, core_));
+ base::BindOnce(&NavigationURLLoaderImplCore::CancelRequestIfNeeded,
+ core_));
}
void NavigationURLLoaderImpl::FollowRedirect() {
@@ -72,7 +74,7 @@ void NavigationURLLoaderImpl::FollowRedirect() {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&NavigationURLLoaderImplCore::FollowRedirect, core_));
+ base::BindOnce(&NavigationURLLoaderImplCore::FollowRedirect, core_));
}
void NavigationURLLoaderImpl::ProceedWithResponse() {
@@ -80,7 +82,7 @@ void NavigationURLLoaderImpl::ProceedWithResponse() {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&NavigationURLLoaderImplCore::ProceedWithResponse, core_));
+ base::BindOnce(&NavigationURLLoaderImplCore::ProceedWithResponse, core_));
}
void NavigationURLLoaderImpl::NotifyRequestRedirected(
@@ -106,12 +108,15 @@ void NavigationURLLoaderImpl::NotifyResponseStarted(
ssl_status, std::move(navigation_data), request_id, is_download,
is_stream, mojom::URLLoaderFactoryPtrInfo());
}
-
-void NavigationURLLoaderImpl::NotifyRequestFailed(bool in_cache,
- int net_error) {
+void NavigationURLLoaderImpl::NotifyRequestFailed(
+ bool in_cache,
+ int net_error,
+ base::Optional<net::SSLInfo> ssl_info,
+ bool should_ssl_errors_be_fatal) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- delegate_->OnRequestFailed(in_cache, net_error);
+ delegate_->OnRequestFailed(in_cache, net_error, ssl_info,
+ should_ssl_errors_be_fatal);
}
void NavigationURLLoaderImpl::NotifyRequestStarted(base::TimeTicks timestamp) {
diff --git a/chromium/content/browser/loader/navigation_url_loader_impl.h b/chromium/content/browser/loader/navigation_url_loader_impl.h
index 5b6c2a3c626..33494583b9c 100644
--- a/chromium/content/browser/loader/navigation_url_loader_impl.h
+++ b/chromium/content/browser/loader/navigation_url_loader_impl.h
@@ -10,11 +10,13 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
+#include "base/optional.h"
#include "base/time/time.h"
#include "content/browser/loader/navigation_url_loader.h"
namespace net {
struct RedirectInfo;
+class SSLInfo;
}
namespace content {
@@ -60,8 +62,14 @@ class NavigationURLLoaderImpl : public NavigationURLLoader {
bool is_download,
bool is_stream);
- // Notifies the delegate the request failed to return a response.
- void NotifyRequestFailed(bool in_cache, int net_error);
+ // Notifies the delegate the the request has failed. If |net_error| is a
+ // certificate error, the caller must pass valid values for |ssl_info| and
+ // |fatal_cert_error|. If |net_error| is not a certificate error, |ssl_info|
+ // and |fatal_cert_error| are ignored.
+ void NotifyRequestFailed(bool in_cache,
+ int net_error,
+ base::Optional<net::SSLInfo> ssl_info,
+ bool should_ssl_errors_be_fatal);
// Notifies the delegate the begin navigation request was handled and a
// potential first network request is about to be made.
diff --git a/chromium/content/browser/loader/navigation_url_loader_impl_core.cc b/chromium/content/browser/loader/navigation_url_loader_impl_core.cc
index ba4b415d1c7..01668321e24 100644
--- a/chromium/content/browser/loader/navigation_url_loader_impl_core.cc
+++ b/chromium/content/browser/loader/navigation_url_loader_impl_core.cc
@@ -48,8 +48,8 @@ void NavigationURLLoaderImplCore::Start(
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&NavigationURLLoaderImpl::NotifyRequestStarted, loader_,
- base::TimeTicks::Now()));
+ base::BindOnce(&NavigationURLLoaderImpl::NotifyRequestStarted, loader_,
+ base::TimeTicks::Now()));
// The ResourceDispatcherHostImpl can be null in unit tests.
if (ResourceDispatcherHostImpl::Get()) {
@@ -95,8 +95,8 @@ void NavigationURLLoaderImplCore::NotifyRequestRedirected(
// response. https://crbug.com/416050
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&NavigationURLLoaderImpl::NotifyRequestRedirected, loader_,
- redirect_info, response->DeepCopy()));
+ base::BindOnce(&NavigationURLLoaderImpl::NotifyRequestRedirected, loader_,
+ redirect_info, response->DeepCopy()));
// TODO(carlosk): extend this trace to support non-PlzNavigate navigations.
// For the trace below we're using the NavigationURLLoaderImplCore as the
@@ -130,14 +130,17 @@ void NavigationURLLoaderImplCore::NotifyResponseStarted(
// response. https://crbug.com/416050
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&NavigationURLLoaderImpl::NotifyResponseStarted, loader_,
- response->DeepCopy(), base::Passed(&body), ssl_status,
- base::Passed(&navigation_data), request_id, is_download,
- is_stream));
+ base::BindOnce(&NavigationURLLoaderImpl::NotifyResponseStarted, loader_,
+ response->DeepCopy(), base::Passed(&body), ssl_status,
+ base::Passed(&navigation_data), request_id, is_download,
+ is_stream));
}
-void NavigationURLLoaderImplCore::NotifyRequestFailed(bool in_cache,
- int net_error) {
+void NavigationURLLoaderImplCore::NotifyRequestFailed(
+ bool in_cache,
+ int net_error,
+ const base::Optional<net::SSLInfo>& ssl_info,
+ bool should_ssl_errors_be_fatal) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
TRACE_EVENT_ASYNC_END0("navigation", "Navigation redirectDelay", this);
TRACE_EVENT_ASYNC_END2("navigation", "Navigation timeToResponseStarted", this,
@@ -146,8 +149,9 @@ void NavigationURLLoaderImplCore::NotifyRequestFailed(bool in_cache,
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&NavigationURLLoaderImpl::NotifyRequestFailed, loader_,
- in_cache, net_error));
+ base::BindOnce(&NavigationURLLoaderImpl::NotifyRequestFailed, loader_,
+ in_cache, net_error, ssl_info,
+ should_ssl_errors_be_fatal));
}
} // namespace content
diff --git a/chromium/content/browser/loader/navigation_url_loader_impl_core.h b/chromium/content/browser/loader/navigation_url_loader_impl_core.h
index b4044b23ec9..2d5d5f88002 100644
--- a/chromium/content/browser/loader/navigation_url_loader_impl_core.h
+++ b/chromium/content/browser/loader/navigation_url_loader_impl_core.h
@@ -83,7 +83,10 @@ class NavigationURLLoaderImplCore
bool is_stream);
// Notifies |loader_| on the UI thread that the request failed.
- void NotifyRequestFailed(bool in_cache, int net_error);
+ void NotifyRequestFailed(bool in_cache,
+ int net_error,
+ const base::Optional<net::SSLInfo>& ssl_info,
+ bool should_ssl_errors_be_fatal);
private:
friend class base::RefCountedThreadSafe<NavigationURLLoaderImplCore>;
diff --git a/chromium/content/browser/loader/navigation_url_loader_network_service.cc b/chromium/content/browser/loader/navigation_url_loader_network_service.cc
index e925cdc1f39..8a9139cc0c5 100644
--- a/chromium/content/browser/loader/navigation_url_loader_network_service.cc
+++ b/chromium/content/browser/loader/navigation_url_loader_network_service.cc
@@ -61,7 +61,7 @@ WebContents* GetWebContentsFromFrameTreeNodeID(int frame_tree_node_id) {
return WebContentsImpl::FromFrameTreeNode(frame_tree_node);
}
-net::NetworkTrafficAnnotationTag kTrafficAnnotation =
+const net::NetworkTrafficAnnotationTag kTrafficAnnotation =
net::DefineNetworkTrafficAnnotation("navigation_url_loader", R"(
semantics {
sender: "Navigation URL Loader"
@@ -78,13 +78,25 @@ net::NetworkTrafficAnnotationTag kTrafficAnnotation =
destination: WEBSITE
}
policy {
- cookies_allowed: true
+ cookies_allowed: YES
cookies_store: "user"
setting: "This feature cannot be disabled."
- policy_exception_justification:
- "Not implemented, without this type of request, Chrome would be "
- "unable to navigate to websites."
- })");
+ chrome_policy {
+ URLBlacklist {
+ URLBlacklist: { entries: '*' }
+ }
+ }
+ chrome_policy {
+ URLWhitelist {
+ URLWhitelist { }
+ }
+ }
+ }
+ comments:
+ "Chrome would be unable to navigate to websites without this type of "
+ "request. Using either URLBlacklist or URLWhitelist policies (or a "
+ "combination of both) limits the scope of these requests."
+ )");
} // namespace
@@ -105,7 +117,8 @@ class NavigationURLLoaderNetworkService::URLLoaderRequestController
: resource_request_(std::move(resource_request)),
resource_context_(resource_context),
default_url_loader_factory_getter_(default_url_loader_factory_getter),
- owner_(owner) {}
+ owner_(owner),
+ response_loader_binding_(this) {}
~URLLoaderRequestController() override {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -177,6 +190,7 @@ class NavigationURLLoaderNetworkService::URLLoaderRequestController
// This could be called multiple times.
void Restart() {
handler_index_ = 0;
+ received_response_ = false;
MaybeStartLoader(StartLoaderCallback());
}
@@ -213,6 +227,7 @@ class NavigationURLLoaderNetworkService::URLLoaderRequestController
factory = default_url_loader_factory_getter_->GetBlobFactory()->get();
} else {
factory = default_url_loader_factory_getter_->GetNetworkFactory()->get();
+ default_loader_used_ = true;
}
url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
factory,
@@ -227,6 +242,8 @@ class NavigationURLLoaderNetworkService::URLLoaderRequestController
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(url_loader_);
+ DCHECK(!response_url_loader_);
+
url_loader_->FollowRedirect();
}
@@ -242,18 +259,43 @@ class NavigationURLLoaderNetworkService::URLLoaderRequestController
const ResourceResponseHead& head,
const base::Optional<net::SSLInfo>& ssl_info,
mojom::DownloadedTempFilePtr downloaded_file) override {
+ received_response_ = true;
+ // If the default loader (network) was used to handle the URL load request
+ // we need to see if the handlers want to potentially create a new loader
+ // for the response. e.g. AppCache.
+ if (MaybeCreateLoaderForResponse(head))
+ return;
+ scoped_refptr<ResourceResponse> response(new ResourceResponse());
+ response->head = head;
+
+ // Make a copy of the ResourceResponse before it is passed to another
+ // thread.
+ //
+ // TODO(davidben): This copy could be avoided if ResourceResponse weren't
+ // reference counted and the loader stack passed unique ownership of the
+ // response. https://crbug.com/416050
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&NavigationURLLoaderNetworkService::OnReceiveResponse,
- owner_, head, ssl_info, base::Passed(&downloaded_file)));
+ base::BindOnce(&NavigationURLLoaderNetworkService::OnReceiveResponse,
+ owner_, response->DeepCopy(), ssl_info,
+ base::Passed(&downloaded_file)));
}
void OnReceiveRedirect(const net::RedirectInfo& redirect_info,
const ResourceResponseHead& head) override {
+ scoped_refptr<ResourceResponse> response(new ResourceResponse());
+ response->head = head;
+
+ // Make a copy of the ResourceResponse before it is passed to another
+ // thread.
+ //
+ // TODO(davidben): This copy could be avoided if ResourceResponse weren't
+ // reference counted and the loader stack passed unique ownership of the
+ // response. https://crbug.com/416050
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&NavigationURLLoaderNetworkService::OnReceiveRedirect,
- owner_, redirect_info, head));
+ base::BindOnce(&NavigationURLLoaderNetworkService::OnReceiveRedirect,
+ owner_, redirect_info, response->DeepCopy()));
}
void OnDataDownloaded(int64_t data_length, int64_t encoded_length) override {}
@@ -270,17 +312,56 @@ class NavigationURLLoaderNetworkService::URLLoaderRequestController
mojo::ScopedDataPipeConsumerHandle body) override {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(
+ base::BindOnce(
&NavigationURLLoaderNetworkService::OnStartLoadingResponseBody,
owner_, base::Passed(&body)));
}
void OnComplete(
const ResourceRequestCompletionStatus& completion_status) override {
+ if (completion_status.error_code != net::OK && !received_response_) {
+ // If the default loader (network) was used to handle the URL load
+ // request we need to see if the handlers want to potentially create a
+ // new loader for the response. e.g. AppCache.
+ if (MaybeCreateLoaderForResponse(ResourceResponseHead()))
+ return;
+ }
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&NavigationURLLoaderNetworkService::OnComplete, owner_,
- completion_status));
+ base::BindOnce(&NavigationURLLoaderNetworkService::OnComplete, owner_,
+ completion_status));
+ }
+
+ // Returns true if a handler wants to handle the response, i.e. return a
+ // different response. For e.g. AppCache may have fallback content to be
+ // returned for a TLD.
+ bool MaybeCreateLoaderForResponse(const ResourceResponseHead& response) {
+ if (!default_loader_used_)
+ return false;
+
+ // URLLoaderClient request pointer for response loaders, i.e loaders created
+ // for handing responses received from the network URLLoader.
+ mojom::URLLoaderClientRequest response_client_request;
+
+ for (size_t index = 0; index < handlers_.size(); ++index) {
+ if (handlers_[index]->MaybeCreateLoaderForResponse(
+ response, &response_url_loader_, &response_client_request)) {
+ OnResponseHandlerFound(std::move(response_client_request));
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // Called if we find a handler who delivers different content for the URL.
+ void OnResponseHandlerFound(
+ mojom::URLLoaderClientRequest response_client_request) {
+ response_loader_binding_.Bind(std::move(response_client_request));
+ // We reset this flag as we expect a new response from the handler.
+ default_loader_used_ = false;
+ // Disconnect from the network loader to stop receiving further data
+ // or notifications for the URL.
+ url_loader_->DisconnectClient();
}
std::vector<std::unique_ptr<URLLoaderRequestHandler>> handlers_;
@@ -305,6 +386,22 @@ class NavigationURLLoaderNetworkService::URLLoaderRequestController
// This is referenced only on the UI thread.
base::WeakPtr<NavigationURLLoaderNetworkService> owner_;
+ // Set to true if the default URLLoader (network service) was used for the
+ // current navigation.
+ bool default_loader_used_ = false;
+
+ // URLLoaderClient binding for loaders created for responses received from the
+ // network loader.
+ mojo::Binding<mojom::URLLoaderClient> response_loader_binding_;
+
+ // URLLoader instance for response loaders, i.e loaders created for handing
+ // responses received from the network URLLoader.
+ mojom::URLLoaderPtr response_url_loader_;
+
+ // Set to true if we receive a valid response from a URLLoader, i.e.
+ // URLLoaderClient::OnReceivedResponse() is called.
+ bool received_response_ = false;
+
DISALLOW_COPY_AND_ASSIGN(URLLoaderRequestController);
};
@@ -329,7 +426,7 @@ NavigationURLLoaderNetworkService::NavigationURLLoaderNetworkService(
new_request->method = request_info->common_params.method;
new_request->url = request_info->common_params.url;
- new_request->first_party_for_cookies = request_info->first_party_for_cookies;
+ new_request->site_for_cookies = request_info->site_for_cookies;
new_request->priority = net::HIGHEST;
// The code below to set fields like request_initiator, referrer, etc has
@@ -353,6 +450,7 @@ NavigationURLLoaderNetworkService::NavigationURLLoaderNetworkService(
new_request->load_flags = load_flags;
new_request->request_body = request_info->common_params.post_data.get();
+ new_request->report_raw_headers = request_info->report_raw_headers;
int frame_tree_node_id = request_info->frame_tree_node_id;
@@ -376,7 +474,7 @@ NavigationURLLoaderNetworkService::NavigationURLLoaderNetworkService(
weak_factory_.GetWeakPtr());
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(
+ base::BindOnce(
&URLLoaderRequestController::Start,
base::Unretained(request_controller_.get()),
service_worker_navigation_handle
@@ -399,14 +497,14 @@ NavigationURLLoaderNetworkService::~NavigationURLLoaderNetworkService() {
void NavigationURLLoaderNetworkService::FollowRedirect() {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&URLLoaderRequestController::FollowRedirect,
- base::Unretained(request_controller_.get())));
+ base::BindOnce(&URLLoaderRequestController::FollowRedirect,
+ base::Unretained(request_controller_.get())));
}
void NavigationURLLoaderNetworkService::ProceedWithResponse() {}
void NavigationURLLoaderNetworkService::OnReceiveResponse(
- const ResourceResponseHead& head,
+ scoped_refptr<ResourceResponse> response,
const base::Optional<net::SSLInfo>& ssl_info,
mojom::DownloadedTempFilePtr downloaded_file) {
// TODO(scottmg): This needs to do more of what
@@ -414,19 +512,17 @@ void NavigationURLLoaderNetworkService::OnReceiveResponse(
// OnStartLoadingResponseBody().
if (ssl_info && ssl_info->cert)
NavigationResourceHandler::GetSSLStatusForRequest(*ssl_info, &ssl_status_);
- response_ = base::MakeRefCounted<ResourceResponse>();
- response_->head = head;
+ response_ = std::move(response);
+ ssl_info_ = ssl_info;
}
void NavigationURLLoaderNetworkService::OnReceiveRedirect(
const net::RedirectInfo& redirect_info,
- const ResourceResponseHead& head) {
+ scoped_refptr<ResourceResponse> response) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
// TODO(kinuko): Perform the necessary check and call
// URLLoaderRequestController::Restart with the new URL??
- scoped_refptr<ResourceResponse> response(new ResourceResponse());
- response->head = head;
- delegate_->OnRequestRedirected(redirect_info, response);
+ delegate_->OnRequestRedirected(redirect_info, std::move(response));
}
void NavigationURLLoaderNetworkService::OnStartLoadingResponseBody(
@@ -449,14 +545,20 @@ void NavigationURLLoaderNetworkService::OnStartLoadingResponseBody(
void NavigationURLLoaderNetworkService::OnComplete(
const ResourceRequestCompletionStatus& completion_status) {
- if (completion_status.error_code != net::OK) {
- TRACE_EVENT_ASYNC_END2("navigation", "Navigation timeToResponseStarted",
- this, "&NavigationURLLoaderNetworkService", this,
- "success", false);
+ if (completion_status.error_code == net::OK)
+ return;
- delegate_->OnRequestFailed(completion_status.exists_in_cache,
- completion_status.error_code);
- }
+ TRACE_EVENT_ASYNC_END2("navigation", "Navigation timeToResponseStarted", this,
+ "&NavigationURLLoaderNetworkService", this, "success",
+ false);
+
+ // TODO(https://crbug.com/757633): Pass real values in the case of cert
+ // errors.
+ bool should_ssl_errors_be_fatal = true;
+
+ delegate_->OnRequestFailed(completion_status.exists_in_cache,
+ completion_status.error_code, ssl_info_,
+ should_ssl_errors_be_fatal);
}
} // namespace content
diff --git a/chromium/content/browser/loader/navigation_url_loader_network_service.h b/chromium/content/browser/loader/navigation_url_loader_network_service.h
index c15a4dade7c..79db21b2d37 100644
--- a/chromium/content/browser/loader/navigation_url_loader_network_service.h
+++ b/chromium/content/browser/loader/navigation_url_loader_network_service.h
@@ -39,11 +39,11 @@ class NavigationURLLoaderNetworkService : public NavigationURLLoader {
void FollowRedirect() override;
void ProceedWithResponse() override;
- void OnReceiveResponse(const ResourceResponseHead& head,
+ void OnReceiveResponse(scoped_refptr<ResourceResponse> response,
const base::Optional<net::SSLInfo>& ssl_info,
mojom::DownloadedTempFilePtr downloaded_file);
void OnReceiveRedirect(const net::RedirectInfo& redirect_info,
- const ResourceResponseHead& head);
+ scoped_refptr<ResourceResponse> response);
void OnStartLoadingResponseBody(mojo::ScopedDataPipeConsumerHandle body);
void OnComplete(const ResourceRequestCompletionStatus& completion_status);
@@ -53,6 +53,7 @@ class NavigationURLLoaderNetworkService : public NavigationURLLoader {
NavigationURLLoaderDelegate* delegate_;
scoped_refptr<ResourceResponse> response_;
+ base::Optional<net::SSLInfo> ssl_info_;
SSLStatus ssl_status_;
// Lives on the IO thread.
diff --git a/chromium/content/browser/loader/navigation_url_loader_unittest.cc b/chromium/content/browser/loader/navigation_url_loader_unittest.cc
index 4f6448165e6..8c5c8606d16 100644
--- a/chromium/content/browser/loader/navigation_url_loader_unittest.cc
+++ b/chromium/content/browser/loader/navigation_url_loader_unittest.cc
@@ -31,7 +31,9 @@
#include "content/test/test_navigation_url_loader_delegate.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
+#include "net/cert/cert_status_flags.h"
#include "net/http/http_response_headers.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "net/url_request/redirect_info.h"
#include "net/url_request/url_request.h"
@@ -115,6 +117,7 @@ class NavigationURLLoaderTest : public testing::Test {
url::Origin(url));
CommonNavigationParams common_params;
common_params.url = url;
+
std::unique_ptr<NavigationRequestInfo> request_info(
new NavigationRequestInfo(common_params, begin_params, url, true, false,
false, -1, false, false,
@@ -172,7 +175,7 @@ TEST_F(NavigationURLLoaderTest, Basic) {
}
// Tests that request failures are propagated correctly.
-TEST_F(NavigationURLLoaderTest, RequestFailed) {
+TEST_F(NavigationURLLoaderTest, RequestFailedNoCertError) {
TestNavigationURLLoaderDelegate delegate;
std::unique_ptr<NavigationURLLoader> loader =
MakeTestLoader(GURL("bogus:bogus"), &delegate);
@@ -180,6 +183,65 @@ TEST_F(NavigationURLLoaderTest, RequestFailed) {
// Wait for the request to fail as expected.
delegate.WaitForRequestFailed();
EXPECT_EQ(net::ERR_UNKNOWN_URL_SCHEME, delegate.net_error());
+ EXPECT_FALSE(delegate.ssl_info().has_value());
+ EXPECT_EQ(1, delegate.on_request_handled_counter());
+}
+
+// Tests that request failures are propagated correctly for a (non-fatal) cert
+// error:
+// - |ssl_info| has the expected values.
+// - |should_ssl_errors_be_fatal| is false.
+TEST_F(NavigationURLLoaderTest, RequestFailedCertError) {
+ net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
+ https_server.SetSSLConfig(net::EmbeddedTestServer::CERT_MISMATCHED_NAME);
+ ASSERT_TRUE(https_server.Start());
+
+ TestNavigationURLLoaderDelegate delegate;
+ std::unique_ptr<NavigationURLLoader> loader =
+ MakeTestLoader(https_server.GetURL("/"), &delegate);
+
+ // Wait for the request to fail as expected.
+ delegate.WaitForRequestFailed();
+ ASSERT_EQ(net::ERR_ABORTED, delegate.net_error());
+ net::SSLInfo ssl_info = delegate.ssl_info().value();
+ EXPECT_TRUE(net::MapCertStatusToNetError(ssl_info.is_valid()));
+ EXPECT_TRUE(https_server.GetCertificate()->Equals(ssl_info.cert.get()));
+ EXPECT_EQ(net::ERR_CERT_COMMON_NAME_INVALID,
+ net::MapCertStatusToNetError(ssl_info.cert_status));
+ EXPECT_FALSE(delegate.should_ssl_errors_be_fatal());
+ EXPECT_EQ(1, delegate.on_request_handled_counter());
+}
+
+// Tests that request failures are propagated correctly for a fatal cert error:
+// - |ssl_info| has the expected values.
+// - |should_ssl_errors_be_fatal| is true.
+TEST_F(NavigationURLLoaderTest, RequestFailedCertErrorFatal) {
+ net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
+ https_server.SetSSLConfig(net::EmbeddedTestServer::CERT_MISMATCHED_NAME);
+ ASSERT_TRUE(https_server.Start());
+ GURL url = https_server.GetURL("/");
+
+ // Set HSTS for the test domain in order to make SSL errors fatal.
+ net::TransportSecurityState* transport_security_state =
+ browser_context_->GetResourceContext()
+ ->GetRequestContext()
+ ->transport_security_state();
+ base::Time expiry = base::Time::Now() + base::TimeDelta::FromDays(1000);
+ bool include_subdomains = false;
+ transport_security_state->AddHSTS(url.host(), expiry, include_subdomains);
+
+ TestNavigationURLLoaderDelegate delegate;
+ std::unique_ptr<NavigationURLLoader> loader = MakeTestLoader(url, &delegate);
+
+ // Wait for the request to fail as expected.
+ delegate.WaitForRequestFailed();
+ ASSERT_EQ(net::ERR_ABORTED, delegate.net_error());
+ net::SSLInfo ssl_info = delegate.ssl_info().value();
+ EXPECT_TRUE(net::MapCertStatusToNetError(ssl_info.is_valid()));
+ EXPECT_TRUE(https_server.GetCertificate()->Equals(ssl_info.cert.get()));
+ EXPECT_EQ(net::ERR_CERT_COMMON_NAME_INVALID,
+ net::MapCertStatusToNetError(ssl_info.cert_status));
+ EXPECT_TRUE(delegate.should_ssl_errors_be_fatal());
EXPECT_EQ(1, delegate.on_request_handled_counter());
}
@@ -197,7 +259,7 @@ TEST_F(NavigationURLLoaderTest, RequestRedirected) {
delegate.redirect_info().new_url);
EXPECT_EQ("GET", delegate.redirect_info().new_method);
EXPECT_EQ(net::URLRequestTestJob::test_url_2(),
- delegate.redirect_info().new_first_party_for_cookies);
+ delegate.redirect_info().new_site_for_cookies);
EXPECT_EQ(302, delegate.redirect_response()->head.headers->response_code());
EXPECT_EQ(1, delegate.on_request_handled_counter());
diff --git a/chromium/content/browser/loader/netlog_observer.cc b/chromium/content/browser/loader/netlog_observer.cc
deleted file mode 100644
index ed30d3d35af..00000000000
--- a/chromium/content/browser/loader/netlog_observer.cc
+++ /dev/null
@@ -1,213 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/loader/netlog_observer.h"
-
-#include <stddef.h>
-
-#include "base/strings/string_util.h"
-#include "base/values.h"
-#include "content/browser/loader/resource_request_info_impl.h"
-#include "content/public/common/resource_response.h"
-#include "net/base/load_flags.h"
-#include "net/http/http_response_headers.h"
-#include "net/http/http_util.h"
-#include "net/log/net_log_capture_mode.h"
-#include "net/log/net_log_entry.h"
-#include "net/log/net_log_event_type.h"
-#include "net/log/net_log_source_type.h"
-#include "net/log/net_log_with_source.h"
-#include "net/spdy/core/spdy_header_block.h"
-#include "net/url_request/url_request.h"
-#include "net/url_request/url_request_netlog_params.h"
-
-namespace content {
-const size_t kMaxNumEntries = 1000;
-
-// static
-NetLogObserver* NetLogObserver::instance_ = NULL;
-
-// static
-base::LazyInstance<std::unique_ptr<base::ThreadChecker>>::Leaky
- NetLogObserver::io_thread_checker_;
-
-NetLogObserver::NetLogObserver() {}
-
-NetLogObserver::~NetLogObserver() {}
-
-NetLogObserver::ResourceInfo* NetLogObserver::GetResourceInfo(uint32_t id) {
- RequestToInfoMap::iterator it = request_to_info_.find(id);
- if (it != request_to_info_.end())
- return it->second.get();
- return NULL;
-}
-
-void NetLogObserver::OnAddEntry(const net::NetLogEntry& entry) {
- DCHECK(io_thread_checker_.Get().get());
-
- // The events that the Observer is interested in only occur on the IO thread.
- if (!io_thread_checker_.Get()->CalledOnValidThread())
- return;
-
- if (entry.source().type == net::NetLogSourceType::URL_REQUEST)
- OnAddURLRequestEntry(entry);
-}
-
-void NetLogObserver::OnAddURLRequestEntry(const net::NetLogEntry& entry) {
- bool is_begin = entry.phase() == net::NetLogEventPhase::BEGIN;
- bool is_end = entry.phase() == net::NetLogEventPhase::END;
-
- if (entry.type() == net::NetLogEventType::URL_REQUEST_START_JOB) {
- if (is_begin) {
- if (request_to_info_.size() > kMaxNumEntries) {
- LOG(WARNING) << "The raw headers observer url request count has grown "
- "larger than expected, resetting";
- request_to_info_.clear();
- }
-
- request_to_info_[entry.source().id] = new ResourceInfo();
- }
- return;
- } else if (entry.type() == net::NetLogEventType::REQUEST_ALIVE) {
- // Cleanup records based on the TYPE_REQUEST_ALIVE entry.
- if (is_end)
- request_to_info_.erase(entry.source().id);
- return;
- }
-
- ResourceInfo* info = GetResourceInfo(entry.source().id);
- if (!info)
- return;
-
- switch (entry.type()) {
- case net::NetLogEventType::HTTP_TRANSACTION_SEND_REQUEST_HEADERS: {
- std::unique_ptr<base::Value> event_params(entry.ParametersToValue());
- std::string request_line;
- net::HttpRequestHeaders request_headers;
-
- if (!net::HttpRequestHeaders::FromNetLogParam(
- event_params.get(), &request_headers, &request_line)) {
- NOTREACHED();
- }
-
- // We need to clear headers in case the same url_request is reused for
- // several http requests (e.g. see http://crbug.com/80157).
- info->request_headers.clear();
-
- for (net::HttpRequestHeaders::Iterator it(request_headers);
- it.GetNext();) {
- info->request_headers.push_back(std::make_pair(it.name(), it.value()));
- }
- info->request_headers_text = request_line + request_headers.ToString();
- break;
- }
- case net::NetLogEventType::HTTP_TRANSACTION_HTTP2_SEND_REQUEST_HEADERS:
- case net::NetLogEventType::HTTP_TRANSACTION_QUIC_SEND_REQUEST_HEADERS: {
- std::unique_ptr<base::Value> event_params(entry.ParametersToValue());
- net::SpdyHeaderBlock request_headers;
-
- if (!net::SpdyHeaderBlockFromNetLogParam(event_params.get(),
- &request_headers)) {
- NOTREACHED();
- }
-
- // We need to clear headers in case the same url_request is reused for
- // several http requests (e.g. see http://crbug.com/80157).
- info->request_headers.clear();
-
- for (net::SpdyHeaderBlock::const_iterator it = request_headers.begin();
- it != request_headers.end(); ++it) {
- info->request_headers.push_back(
- std::make_pair(it->first.as_string(), it->second.as_string()));
- }
- info->request_headers_text = "";
- break;
- }
- case net::NetLogEventType::HTTP_TRANSACTION_READ_RESPONSE_HEADERS: {
- std::unique_ptr<base::Value> event_params(entry.ParametersToValue());
-
- scoped_refptr<net::HttpResponseHeaders> response_headers;
-
- if (!net::HttpResponseHeaders::FromNetLogParam(event_params.get(),
- &response_headers)) {
- NOTREACHED();
- }
-
- info->http_status_code = response_headers->response_code();
- info->http_status_text = response_headers->GetStatusText();
- std::string name, value;
-
- // We need to clear headers in case the same url_request is reused for
- // several http requests (e.g. see http://crbug.com/80157).
- info->response_headers.clear();
-
- for (size_t it = 0;
- response_headers->EnumerateHeaderLines(&it, &name, &value);) {
- info->response_headers.push_back(std::make_pair(name, value));
- }
-
- if (!info->request_headers_text.empty()) {
- info->response_headers_text =
- net::HttpUtil::ConvertHeadersBackToHTTPResponse(
- response_headers->raw_headers());
- } else {
- // SPDY request.
- info->response_headers_text = "";
- }
- break;
- }
- default:
- break;
- }
-}
-
-void NetLogObserver::Attach(net::NetLog* net_log) {
- DCHECK(!instance_);
- io_thread_checker_.Get().reset(new base::ThreadChecker());
- if (net_log) {
- instance_ = new NetLogObserver();
- net_log->AddObserver(
- instance_, net::NetLogCaptureMode::IncludeCookiesAndCredentials());
- }
-}
-
-void NetLogObserver::Detach() {
- DCHECK(io_thread_checker_.Get().get() &&
- io_thread_checker_.Get()->CalledOnValidThread());
- io_thread_checker_.Get().reset();
- if (instance_) {
- // Safest not to do this in the destructor to maintain thread safety across
- // refactorings.
- instance_->net_log()->RemoveObserver(instance_);
- delete instance_;
- instance_ = NULL;
- }
-}
-
-NetLogObserver* NetLogObserver::GetInstance() {
- if (!io_thread_checker_.Get().get())
- return nullptr;
-
- DCHECK(io_thread_checker_.Get()->CalledOnValidThread());
-
- return instance_;
-}
-
-// static
-void NetLogObserver::PopulateResponseInfo(net::URLRequest* request,
- ResourceResponse* response) {
- const ResourceRequestInfoImpl* request_info =
- ResourceRequestInfoImpl::ForRequest(request);
- if (!request_info || !request_info->ShouldReportRawHeaders())
- return;
-
- uint32_t source_id = request->net_log().source().id;
- NetLogObserver* dev_tools_net_log_observer = NetLogObserver::GetInstance();
- if (dev_tools_net_log_observer == NULL)
- return;
- response->head.devtools_info =
- dev_tools_net_log_observer->GetResourceInfo(source_id);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/loader/netlog_observer.h b/chromium/content/browser/loader/netlog_observer.h
deleted file mode 100644
index 7e049bc4887..00000000000
--- a/chromium/content/browser/loader/netlog_observer.h
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_LOADER_NETLOG_OBSERVER_H_
-#define CONTENT_BROWSER_LOADER_NETLOG_OBSERVER_H_
-
-#include <stdint.h>
-
-#include "base/containers/hash_tables.h"
-#include "base/lazy_instance.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/threading/thread_checker.h"
-#include "content/public/common/resource_devtools_info.h"
-#include "net/log/net_log.h"
-
-namespace net {
-class URLRequest;
-class NetLogEntry;
-} // namespace net
-
-namespace content {
-struct ResourceResponse;
-
-// NetLogObserver watches the NetLog event stream and collects the stuff that
-// may be of interest to the client. Currently, this only includes actual
-// HTTP/SPDY headers sent and received over the network.
-//
-// As NetLogObserver shares live data with objects that live on the IO Thread,
-// it must also reside on the IO Thread. Only OnAddEntry can be called from
-// other threads.
-class CONTENT_EXPORT NetLogObserver : public net::NetLog::ThreadSafeObserver {
- typedef ResourceDevToolsInfo ResourceInfo;
-
- public:
- // net::NetLog::ThreadSafeObserver implementation:
- void OnAddEntry(const net::NetLogEntry& entry) override;
-
- // The NetLog instance is passed in via the |net_log| parameter.
- static void Attach(net::NetLog* net_log);
-
- static void Detach();
-
- // Must be called on the IO thread. May return NULL if no observers
- // are active.
- static NetLogObserver* GetInstance();
- static void PopulateResponseInfo(net::URLRequest*, ResourceResponse*);
-
- private:
- static NetLogObserver* instance_;
-
- NetLogObserver();
- ~NetLogObserver() override;
-
- ResourceInfo* GetResourceInfo(uint32_t id);
-
- void OnAddURLRequestEntry(const net::NetLogEntry& entry);
-
- typedef base::hash_map<uint32_t, scoped_refptr<ResourceInfo>>
- RequestToInfoMap;
- RequestToInfoMap request_to_info_;
-
- // Used to validate that calls to the NetLogObserver methods occur on the
- // thread it was instantiated on. Typically the IO thread.
- static base::LazyInstance<std::unique_ptr<base::ThreadChecker>>::Leaky
- io_thread_checker_;
-
- DISALLOW_COPY_AND_ASSIGN(NetLogObserver);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_LOADER_NETLOG_OBSERVER_H_
diff --git a/chromium/content/browser/loader/netlog_observer_unittest.cc b/chromium/content/browser/loader/netlog_observer_unittest.cc
deleted file mode 100644
index 9d438491af9..00000000000
--- a/chromium/content/browser/loader/netlog_observer_unittest.cc
+++ /dev/null
@@ -1,180 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <memory>
-
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "base/memory/ref_counted.h"
-#include "base/values.h"
-#include "content/browser/loader/netlog_observer.h"
-#include "content/browser/loader/resource_request_info_impl.h"
-#include "content/browser/loader/resource_requester_info.h"
-#include "content/public/common/previews_state.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"
-#include "net/base/request_priority.h"
-#include "net/log/net_log.h"
-#include "net/log/net_log_capture_mode.h"
-#include "net/log/net_log_event_type.h"
-#include "net/quic/core/quic_types.h"
-#include "net/spdy/core/spdy_header_block.h"
-#include "net/spdy/core/spdy_protocol.h"
-#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
-#include "net/url_request/url_request_context.h"
-#include "net/url_request/url_request_netlog_params.h"
-#include "net/url_request/url_request_test_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/WebKit/public/platform/WebPageVisibilityState.h"
-#include "third_party/WebKit/public/platform/WebReferrerPolicy.h"
-#include "ui/base/page_transition_types.h"
-#include "url/gurl.h"
-
-namespace content {
-
-namespace {
-
-const char kDefaultURL[] = "https://example.test";
-
-std::unique_ptr<base::Value> QuicRequestCallback(
- net::QuicStreamId stream_id,
- const net::SpdyHeaderBlock* headers,
- net::SpdyPriority priority,
- net::NetLogCaptureMode capture_mode) {
- std::unique_ptr<base::DictionaryValue> dict(
- static_cast<base::DictionaryValue*>(
- SpdyHeaderBlockNetLogCallback(headers, capture_mode).release()));
- return std::move(dict);
-}
-
-} // namespace
-
-class NetLogObserverTest : public testing::Test {
- public:
- NetLogObserverTest()
- : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP), context_(true) {}
-
- ~NetLogObserverTest() override {}
-
- void SetUp() override {
- context_.Init();
- context_.set_net_log(&net_log_);
- NetLogObserver::Attach(context_.net_log());
- request_ = context_.CreateRequest(GURL(kDefaultURL), net::DEFAULT_PRIORITY,
- nullptr, TRAFFIC_ANNOTATION_FOR_TESTS);
- resource_context_ = base::MakeUnique<MockResourceContext>(&context_);
- requester_info_ = ResourceRequesterInfo::CreateForRendererTesting(1);
- ResourceRequestInfoImpl* info = new ResourceRequestInfoImpl(
- requester_info_,
- 0, // route_id
- -1, // frame_tree_node_id
- 0, // origin_pid
- 0, // request_id
- 0, // render_frame_id
- false, // is_main_frame
- false, // parent_is_main_frame
- RESOURCE_TYPE_IMAGE, // resource_type
- ui::PAGE_TRANSITION_LINK, // transition_type
- false, // should_replace_current_entry
- false, // is_download
- false, // is_stream
- false, // allow_download
- false, // has_user_gesture
- false, // enable load timing
- false, // enable upload progress
- false, // do_not_prompt_for_login
- blink::kWebReferrerPolicyDefault, // referrer_policy
- blink::kWebPageVisibilityStateVisible, // visibility_state
- resource_context_.get(), // context
- true, // report_raw_headers
- true, // is_async
- PREVIEWS_OFF, // previews_state
- nullptr, // body
- false); // initiated_in_secure_context
- info->AssociateWithRequest(request_.get());
- std::string method = "GET";
- GURL url(kDefaultURL);
- request_->net_log().BeginEvent(
- net::NetLogEventType::URL_REQUEST_START_JOB,
- base::Bind(&net::NetLogURLRequestStartCallback, &url, &method, 0, -1));
- }
-
- void TearDown() override { NetLogObserver::Detach(); }
-
- void VerifyHeaderValue(const std::string& header,
- const std::string& expected_value) {
- scoped_refptr<ResourceResponse> response(new ResourceResponse);
-
- NetLogObserver::PopulateResponseInfo(request_.get(), response.get());
-
- int header_was_in_list = false;
- for (auto header_pair : response->head.devtools_info->request_headers) {
- if (header == header_pair.first) {
- EXPECT_EQ(expected_value, header_pair.second);
- header_was_in_list = true;
- }
- }
- EXPECT_TRUE(header_was_in_list);
- }
-
- protected:
- net::NetLog net_log_;
- TestBrowserThreadBundle thread_bundle_;
- net::TestURLRequestContext context_;
- std::unique_ptr<MockResourceContext> resource_context_;
- scoped_refptr<ResourceRequesterInfo> requester_info_;
- std::unique_ptr<net::URLRequest> request_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(NetLogObserverTest);
-};
-
-// Verify that the response info is populated with headers for HTTP jobs.
-TEST_F(NetLogObserverTest, TestHTTPEntry) {
- std::string header("header");
- std::string value("value");
- std::string request_line("HTTP request line");
-
- net::HttpRequestHeaders request_headers;
- request_headers.SetHeader(header, value);
-
- request_->net_log().AddEvent(
- net::NetLogEventType::HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
- base::Bind(&net::HttpRequestHeaders::NetLogCallback,
- base::Unretained(&request_headers), &request_line));
-
- VerifyHeaderValue(header, value);
-}
-
-// Verify that the response info is populated with headers for HTTP2 jobs.
-TEST_F(NetLogObserverTest, TestHTTP2Entry) {
- std::string header("header");
- std::string value("value");
- net::SpdyHeaderBlock request_headers;
-
- request_headers[header] = value;
- request_->net_log().AddEvent(
- net::NetLogEventType::HTTP_TRANSACTION_HTTP2_SEND_REQUEST_HEADERS,
- base::Bind(&net::SpdyHeaderBlockNetLogCallback, &request_headers));
-
- VerifyHeaderValue(header, value);
-}
-
-// Verify that the response info is populated with headers for QUIC jobs.
-TEST_F(NetLogObserverTest, TestQUICEntry) {
- std::string header("header");
- std::string value("value");
- net::SpdyHeaderBlock request_headers;
-
- request_headers[header] = value;
- request_->net_log().AddEvent(
- net::NetLogEventType::HTTP_TRANSACTION_QUIC_SEND_REQUEST_HEADERS,
- base::Bind(&QuicRequestCallback, 1, &request_headers,
- net::DEFAULT_PRIORITY));
-
- VerifyHeaderValue(header, value);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/loader/null_resource_controller.cc b/chromium/content/browser/loader/null_resource_controller.cc
index 05c3164ed38..da79bb5843e 100644
--- a/chromium/content/browser/loader/null_resource_controller.cc
+++ b/chromium/content/browser/loader/null_resource_controller.cc
@@ -19,10 +19,6 @@ void NullResourceController::Cancel() {
DCHECK(!*was_resumed_);
}
-void NullResourceController::CancelAndIgnore() {
- DCHECK(!*was_resumed_);
-}
-
void NullResourceController::CancelWithError(int error_code) {
DCHECK(!*was_resumed_);
}
diff --git a/chromium/content/browser/loader/null_resource_controller.h b/chromium/content/browser/loader/null_resource_controller.h
index b9e6caf4e51..8dd10f7102a 100644
--- a/chromium/content/browser/loader/null_resource_controller.h
+++ b/chromium/content/browser/loader/null_resource_controller.h
@@ -21,7 +21,6 @@ class NullResourceController : public ResourceController {
// ResourceController implementation:
void Cancel() override;
- void CancelAndIgnore() override;
void CancelWithError(int error_code) override;
void Resume() override;
diff --git a/chromium/content/browser/loader/redirect_to_file_resource_handler.cc b/chromium/content/browser/loader/redirect_to_file_resource_handler.cc
index 3bddfd75d30..d6acbbca87a 100644
--- a/chromium/content/browser/loader/redirect_to_file_resource_handler.cc
+++ b/chromium/content/browser/loader/redirect_to_file_resource_handler.cc
@@ -134,11 +134,6 @@ RedirectToFileResourceHandler::RedirectToFileResourceHandler(
net::URLRequest* request)
: LayeredResourceHandler(request, std::move(next_handler)),
buf_(new net::GrowableIOBuffer()),
- buf_write_pending_(false),
- write_cursor_(0),
- writer_(NULL),
- next_buffer_size_(kInitialReadBufSize),
- completed_during_write_(false),
weak_factory_(this) {}
RedirectToFileResourceHandler::~RedirectToFileResourceHandler() {
@@ -158,7 +153,12 @@ void RedirectToFileResourceHandler::
void RedirectToFileResourceHandler::OnResponseStarted(
ResourceResponse* response,
std::unique_ptr<ResourceController> controller) {
- DCHECK(writer_);
+ if (!writer_) {
+ response_pending_file_creation_ = response;
+ HoldController(std::move(controller));
+ request()->LogBlockedBy("RedirectToFileResourceHandler");
+ return;
+ }
response->head.download_file_path = writer_->path();
next_handler_->OnResponseStarted(response, std::move(controller));
}
@@ -168,12 +168,7 @@ void RedirectToFileResourceHandler::OnWillStart(
std::unique_ptr<ResourceController> controller) {
DCHECK(!writer_);
- // Defer starting the request until we have created the temporary file.
- // TODO(darin): This is sub-optimal. We should not delay starting the
- // network request like this.
- will_start_url_ = url;
- HoldController(std::move(controller));
- request()->LogBlockedBy("RedirectToFileResourceHandler");
+ // Create the file ASAP but don't block.
if (create_temporary_file_stream_.is_null()) {
CreateTemporaryFileStream(
base::Bind(&RedirectToFileResourceHandler::DidCreateTemporaryFile,
@@ -183,6 +178,7 @@ void RedirectToFileResourceHandler::OnWillStart(
base::Bind(&RedirectToFileResourceHandler::DidCreateTemporaryFile,
weak_factory_.GetWeakPtr()));
}
+ next_handler_->OnWillStart(url, std::move(controller));
}
void RedirectToFileResourceHandler::OnWillRead(
@@ -252,23 +248,30 @@ void RedirectToFileResourceHandler::DidCreateTemporaryFile(
std::unique_ptr<net::FileStream> file_stream,
ShareableFileReference* deletable_file) {
DCHECK(!writer_);
- DCHECK(has_controller());
if (error_code != base::File::FILE_OK) {
- CancelWithError(net::FileErrorToNetError(error_code));
+ if (has_controller()) {
+ CancelWithError(net::FileErrorToNetError(error_code));
+ } else {
+ OutOfBandCancel(net::FileErrorToNetError(error_code),
+ true /* tell_renderer */);
+ }
return;
}
writer_ = new Writer(this, std::move(file_stream), deletable_file);
- // Resume the request.
- request()->LogUnblocked();
- next_handler_->OnWillStart(std::move(will_start_url_), ReleaseController());
+ if (response_pending_file_creation_) {
+ scoped_refptr<ResourceResponse> response =
+ std::move(response_pending_file_creation_);
+ request()->LogUnblocked();
+ OnResponseStarted(response.get(), ReleaseController());
+ }
}
void RedirectToFileResourceHandler::DidWriteToFile(int result) {
bool failed = false;
if (result > 0) {
- next_handler_->OnDataDownloaded(result);
+ OnDataDownloaded(result);
write_cursor_ += result;
// WriteMore will resume the request if the request hasn't completed and
// there's more buffer space.
@@ -349,7 +352,7 @@ bool RedirectToFileResourceHandler::WriteMore() {
break;
if (rv <= 0)
return false;
- next_handler_->OnDataDownloaded(rv);
+ OnDataDownloaded(rv);
write_cursor_ += rv;
}
diff --git a/chromium/content/browser/loader/redirect_to_file_resource_handler.h b/chromium/content/browser/loader/redirect_to_file_resource_handler.h
index 9f642e74c4a..079b3aec049 100644
--- a/chromium/content/browser/loader/redirect_to_file_resource_handler.h
+++ b/chromium/content/browser/loader/redirect_to_file_resource_handler.h
@@ -97,6 +97,8 @@ class CONTENT_EXPORT RedirectToFileResourceHandler
bool BufIsFull() const;
+ // If populated, OnResponseStarted completion is pending on file creation.
+ scoped_refptr<ResourceResponse> response_pending_file_creation_;
CreateTemporaryFileStreamFunction create_temporary_file_stream_;
// We allocate a single, fixed-size IO buffer (buf_) used to read from the
@@ -107,24 +109,23 @@ class CONTENT_EXPORT RedirectToFileResourceHandler
// tracks the offset into buf_ that we are writing to disk.
scoped_refptr<net::GrowableIOBuffer> buf_;
- bool buf_write_pending_;
- int write_cursor_;
+ bool buf_write_pending_ = false;
+ int write_cursor_ = 0;
// Helper writer object which maintains references to the net::FileStream and
// storage::ShareableFileReference. This is maintained separately so that,
// on Windows, the temporary file isn't deleted until after it is closed.
class Writer;
- Writer* writer_;
+ Writer* writer_ = nullptr;
// |next_buffer_size_| is the size of the buffer to be allocated on the next
// OnWillRead() call. We exponentially grow the size of the buffer allocated
// when our owner fills our buffers. On the first OnWillRead() call, we
// allocate a buffer of 32k and double it in OnReadCompleted() if the buffer
// was filled, up to a maximum size of 512k.
- int next_buffer_size_;
+ int next_buffer_size_ = kInitialReadBufSize;
- bool completed_during_write_;
- GURL will_start_url_;
+ bool completed_during_write_ = false;
net::URLRequestStatus completed_status_;
base::WeakPtrFactory<RedirectToFileResourceHandler> weak_factory_;
diff --git a/chromium/content/browser/loader/redirect_to_file_resource_handler_unittest.cc b/chromium/content/browser/loader/redirect_to_file_resource_handler_unittest.cc
index aaee16de224..8dba0af7158 100644
--- a/chromium/content/browser/loader/redirect_to_file_resource_handler_unittest.cc
+++ b/chromium/content/browser/loader/redirect_to_file_resource_handler_unittest.cc
@@ -184,7 +184,7 @@ class MockFileStream : public net::FileStream {
if (result.completion_mode == CompletionMode::SYNC)
return result.result;
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(callback, result.result));
+ FROM_HERE, base::BindOnce(callback, result.result));
return net::ERR_IO_PENDING;
}
@@ -275,19 +275,24 @@ class RedirectToFileResourceHandlerTest
create_file_stream_callback_ = create_file_stream_callback;
}
- // Simulates starting the request, the response starting, and stream creation
- // completing with the specified error code. Has |test_handler_| resume the
- // request, if needed. Returns final status of |mock_loader_|.
- MockResourceLoader::Status StartAndCreateStream(base::File::Error file_error)
- WARN_UNUSED_RESULT {
- DCHECK(file_stream_);
+ void PerformOnWillStart() {
+ MockResourceLoader::Status expected_status;
+ if (GetParam() == CompletionMode::ASYNC) {
+ expected_status = MockResourceLoader::Status::CALLBACK_PENDING;
+ } else {
+ expected_status = MockResourceLoader::Status::IDLE;
+ }
+ EXPECT_EQ(expected_status, mock_loader_->OnWillStart(url_request_->url()));
+ }
- EXPECT_EQ(MockResourceLoader::Status::CALLBACK_PENDING,
- mock_loader_->OnWillStart(url_request_->url()));
+ // Sets up the file stream or error, and performs the file callback.
+ void PerformCreateFile(base::File::Error file_error) {
+ DCHECK(file_stream_);
file_stream_->set_expect_closed(file_error == base::File::FILE_OK);
if (file_error != base::File::FILE_OK)
file_stream_ = nullptr;
+
base::ResetAndReturn(&create_file_stream_callback_)
.Run(file_error, std::move(file_stream_),
// Not really used by the test, but the ResourceHandler expects it
@@ -297,6 +302,18 @@ class RedirectToFileResourceHandlerTest
storage::ShareableFileReference::DELETE_ON_FINAL_RELEASE,
base::ThreadTaskRunnerHandle::Get().get())
.get());
+ }
+
+ // Simulates starting the request, the response starting, and stream creation
+ // completing with the specified error code. Has |test_handler_| resume the
+ // request, if needed. Returns final status of |mock_loader_|.
+ MockResourceLoader::Status StartAndCreateStream(base::File::Error file_error)
+ WARN_UNUSED_RESULT {
+ PerformOnWillStart();
+
+ // Create the file right away.
+ PerformCreateFile(file_error);
+
// If this is an async test, |test_handler_| will defer the OnWillStart
// event on success (On error, its OnWillStart method is not called).
if (file_error == base::File::FILE_OK &&
@@ -389,6 +406,67 @@ TEST_P(RedirectToFileResourceHandlerTest, SingleBodyRead) {
CompleteRequestSuccessfully(test_data.size());
}
+TEST_P(RedirectToFileResourceHandlerTest, SingleBodyReadDelayedFileOnResponse) {
+ std::string test_data = CreateTestData(kMaxInitialSyncReadSize);
+
+ PerformOnWillStart();
+ if (GetParam() == CompletionMode::ASYNC) {
+ EXPECT_EQ(MockResourceLoader::Status::CALLBACK_PENDING,
+ mock_loader_->status());
+ test_handler_->Resume();
+ mock_loader_->WaitUntilIdleOrCanceled();
+ }
+ ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->status());
+ mock_loader_->OnResponseStarted(make_scoped_refptr(new ResourceResponse()));
+ ASSERT_EQ(MockResourceLoader::Status::CALLBACK_PENDING,
+ mock_loader_->status());
+
+ PerformCreateFile(base::File::FILE_OK);
+
+ if (GetParam() == CompletionMode::ASYNC) {
+ EXPECT_EQ(MockResourceLoader::Status::CALLBACK_PENDING,
+ mock_loader_->status());
+ test_handler_->Resume();
+ mock_loader_->WaitUntilIdleOrCanceled();
+ }
+ EXPECT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->status());
+
+ ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead());
+ ASSERT_EQ(MockResourceLoader::Status::IDLE,
+ mock_loader_->OnReadCompleted(test_data));
+ // Wait for the write to complete, in the async case.
+ base::RunLoop().RunUntilIdle();
+
+ CompleteRequestSuccessfully(test_data.size());
+}
+
+TEST_P(RedirectToFileResourceHandlerTest, SingleBodyReadDelayedFileError) {
+ std::string test_data = CreateTestData(0);
+
+ PerformOnWillStart();
+ if (GetParam() == CompletionMode::ASYNC) {
+ EXPECT_EQ(MockResourceLoader::Status::CALLBACK_PENDING,
+ mock_loader_->status());
+ test_handler_->Resume();
+ mock_loader_->WaitUntilIdleOrCanceled();
+ }
+ ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->status());
+ mock_loader_->OnResponseStarted(make_scoped_refptr(new ResourceResponse()));
+ ASSERT_EQ(MockResourceLoader::Status::CALLBACK_PENDING,
+ mock_loader_->status());
+
+ PerformCreateFile(base::File::FILE_ERROR_FAILED);
+
+ EXPECT_EQ(MockResourceLoader::Status::CANCELED, mock_loader_->status());
+ EXPECT_EQ(0, test_handler_->on_response_completed_called());
+ EXPECT_EQ(net::ERR_FAILED, mock_loader_->error_code());
+ ASSERT_EQ(MockResourceLoader::Status::IDLE,
+ mock_loader_->OnResponseCompleted(
+ net::URLRequestStatus::FromError(net::ERR_FAILED)));
+ EXPECT_FALSE(test_handler_->final_status().is_success());
+ EXPECT_EQ(net::ERR_FAILED, test_handler_->final_status().error());
+}
+
TEST_P(RedirectToFileResourceHandlerTest, ManySequentialBodyReads) {
const size_t kBytesPerRead = 128;
std::string test_data =
@@ -757,9 +835,17 @@ TEST_P(RedirectToFileResourceHandlerTest, CreateFileFails) {
EXPECT_EQ(0, test_handler_->on_response_completed_called());
EXPECT_EQ(net::ERR_FAILED, mock_loader_->error_code());
- ASSERT_EQ(MockResourceLoader::Status::IDLE,
- mock_loader_->OnResponseCompleted(
- net::URLRequestStatus::FromError(net::ERR_FAILED)));
+ if (GetParam() == CompletionMode::ASYNC) {
+ EXPECT_EQ(MockResourceLoader::Status::CANCELED, mock_loader_->status());
+ ASSERT_EQ(MockResourceLoader::Status::IDLE,
+ mock_loader_->OnResponseCompletedFromExternalOutOfBandCancel(
+ net::URLRequestStatus::FromError(net::ERR_FAILED)));
+ } else {
+ ASSERT_EQ(MockResourceLoader::Status::IDLE,
+ mock_loader_->OnResponseCompleted(
+ net::URLRequestStatus::FromError(net::ERR_FAILED)));
+ }
+
EXPECT_EQ(0, test_handler_->total_bytes_downloaded());
EXPECT_FALSE(test_handler_->final_status().is_success());
EXPECT_EQ(net::ERR_FAILED, test_handler_->final_status().error());
diff --git a/chromium/content/browser/loader/resource_controller.h b/chromium/content/browser/loader/resource_controller.h
index 85672556ed5..82785346fef 100644
--- a/chromium/content/browser/loader/resource_controller.h
+++ b/chromium/content/browser/loader/resource_controller.h
@@ -19,7 +19,6 @@ class CONTENT_EXPORT ResourceController {
virtual ~ResourceController() {}
virtual void Cancel() = 0;
- virtual void CancelAndIgnore() = 0;
virtual void CancelWithError(int error_code) = 0;
// Resumes the request. May only be called if the request was previously
diff --git a/chromium/content/browser/loader/resource_dispatcher_host_browsertest.cc b/chromium/content/browser/loader/resource_dispatcher_host_browsertest.cc
index cbec7a039e2..cf9923d7bb2 100644
--- a/chromium/content/browser/loader/resource_dispatcher_host_browsertest.cc
+++ b/chromium/content/browser/loader/resource_dispatcher_host_browsertest.cc
@@ -62,10 +62,10 @@ class ResourceDispatcherHostBrowserTest : public ContentBrowserTest,
base::FilePath path = GetTestFilePath("", "");
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&net::URLRequestMockHTTPJob::AddUrlHandlers, path));
+ base::BindOnce(&net::URLRequestMockHTTPJob::AddUrlHandlers, path));
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&net::URLRequestFailedJob::AddUrlHandler));
+ base::BindOnce(&net::URLRequestFailedJob::AddUrlHandler));
}
void OnDownloadCreated(DownloadManager* manager,
@@ -255,11 +255,10 @@ std::unique_ptr<net::test_server::HttpResponse> CancelOnRequest(
return nullptr;
content::BrowserThread::PostTask(
- content::BrowserThread::IO,
- FROM_HERE,
- base::Bind(&ResourceDispatcherHostImpl::CancelRequestsForProcess,
- base::Unretained(ResourceDispatcherHostImpl::Get()),
- child_id));
+ content::BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&ResourceDispatcherHostImpl::CancelRequestsForProcess,
+ base::Unretained(ResourceDispatcherHostImpl::Get()),
+ child_id));
return base::MakeUnique<net::test_server::HungResponse>();
}
@@ -708,27 +707,27 @@ class PreviewsStateResourceDispatcherHostBrowserTest
embedded_test_server()->GetURL("/title1.html")));
content::BrowserThread::PostTask(
- content::BrowserThread::IO,
- FROM_HERE,
- base::Bind(&PreviewsStateResourceDispatcherHostDelegate::SetDelegate,
- base::Unretained(delegate_.get())));
+ content::BrowserThread::IO, FROM_HERE,
+ base::BindOnce(
+ &PreviewsStateResourceDispatcherHostDelegate::SetDelegate,
+ base::Unretained(delegate_.get())));
}
void Reset(PreviewsState previews_state) {
content::BrowserThread::PostTask(
content::BrowserThread::IO, FROM_HERE,
- base::Bind(&PreviewsStateResourceDispatcherHostDelegate::Reset,
- base::Unretained(delegate_.get()), previews_state));
+ 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::Bind(&PreviewsStateResourceDispatcherHostDelegate::
- CheckResourcesRequested,
- base::Unretained(delegate_.get()),
- should_get_previews_state_called));
+ base::BindOnce(&PreviewsStateResourceDispatcherHostDelegate::
+ CheckResourcesRequested,
+ base::Unretained(delegate_.get()),
+ should_get_previews_state_called));
}
private:
@@ -848,7 +847,7 @@ class RequestDataResourceDispatcherHostDelegate
ResourceType resource_type,
std::vector<std::unique_ptr<ResourceThrottle>>* throttles) override {
requests_.push_back(base::MakeUnique<RequestDataForDelegate>(
- request->url(), request->first_party_for_cookies(), request->initiator(),
+ request->url(), request->site_for_cookies(), request->initiator(),
request->load_flags(), request->referrer()));
}
@@ -878,8 +877,8 @@ class RequestDataResourceDispatcherHostBrowserTest : public ContentBrowserTest {
content::BrowserThread::PostTask(
content::BrowserThread::IO, FROM_HERE,
- base::Bind(&RequestDataResourceDispatcherHostDelegate::SetDelegate,
- base::Unretained(delegate_.get())));
+ base::BindOnce(&RequestDataResourceDispatcherHostDelegate::SetDelegate,
+ base::Unretained(delegate_.get())));
host_resolver()->AddRule("*", "127.0.0.1");
}
diff --git a/chromium/content/browser/loader/resource_dispatcher_host_impl.cc b/chromium/content/browser/loader/resource_dispatcher_host_impl.cc
index efbdb38552a..a3ae030d861 100644
--- a/chromium/content/browser/loader/resource_dispatcher_host_impl.cc
+++ b/chromium/content/browser/loader/resource_dispatcher_host_impl.cc
@@ -111,6 +111,7 @@
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_context.h"
+#include "net/url_request/url_request_context_getter.h"
#include "net/url_request/url_request_job_factory.h"
#include "ppapi/features/features.h"
#include "storage/browser/blob/blob_data_handle.h"
@@ -134,7 +135,7 @@ using SyncLoadResultCallback =
namespace {
constexpr net::NetworkTrafficAnnotationTag kTrafficAnnotation =
- net::DefineNetworkTrafficAnnotation("resource_dispather_host",
+ net::DefineNetworkTrafficAnnotation("resource_dispatcher_host",
R"(
semantics {
sender: "Resource Dispatcher Host"
@@ -151,7 +152,7 @@ constexpr net::NetworkTrafficAnnotationTag kTrafficAnnotation =
destination: OTHER
}
policy {
- cookies_allowed: true
+ cookies_allowed: YES
cookies_store: "user or per-app cookie store"
setting: "These requests cannot be disabled."
policy_exception_justification:
@@ -222,7 +223,6 @@ void AbortRequestBeforeItStarts(
// Tell the renderer that this request was disallowed.
ResourceRequestCompletionStatus request_complete_data;
request_complete_data.error_code = net::ERR_ABORTED;
- request_complete_data.was_ignored_by_handler = false;
request_complete_data.exists_in_cache = false;
// No security info needed, connection not established.
request_complete_data.completion_time = base::TimeTicks();
@@ -371,8 +371,8 @@ ResourceDispatcherHostImpl::ResourceDispatcherHostImpl(
"We don't care about the precise value, see http://crbug.com/92889");
io_thread_task_runner_->PostTask(
- FROM_HERE,
- base::Bind(&ResourceDispatcherHostImpl::OnInit, base::Unretained(this)));
+ FROM_HERE, base::BindOnce(&ResourceDispatcherHostImpl::OnInit,
+ base::Unretained(this)));
update_load_states_timer_ = base::MakeUnique<base::RepeatingTimer>();
@@ -523,8 +523,8 @@ void ResourceDispatcherHostImpl::ReprioritizeRequest(
void ResourceDispatcherHostImpl::Shutdown() {
DCHECK(main_thread_task_runner_->BelongsToCurrentThread());
io_thread_task_runner_->PostTask(
- FROM_HERE, base::Bind(&ResourceDispatcherHostImpl::OnShutdown,
- base::Unretained(this)));
+ FROM_HERE, base::BindOnce(&ResourceDispatcherHostImpl::OnShutdown,
+ base::Unretained(this)));
}
std::unique_ptr<ResourceHandler>
@@ -888,7 +888,8 @@ void ResourceDispatcherHostImpl::OnRequestResource(
const ResourceRequest& request_data,
net::MutableNetworkTrafficAnnotationTag traffic_annotation) {
OnRequestResourceInternal(
- requester_info, routing_id, request_id, request_data, nullptr, nullptr,
+ requester_info, routing_id, request_id, false /* is_sync_load */,
+ request_data, nullptr, nullptr,
net::NetworkTrafficAnnotationTag(traffic_annotation));
}
@@ -896,8 +897,9 @@ void ResourceDispatcherHostImpl::OnRequestResourceInternal(
ResourceRequesterInfo* requester_info,
int routing_id,
int request_id,
+ bool is_sync_load,
const ResourceRequest& request_data,
- mojom::URLLoaderAssociatedRequest mojo_request,
+ mojom::URLLoaderRequest mojo_request,
mojom::URLLoaderClientPtr url_loader_client,
const net::NetworkTrafficAnnotationTag& traffic_annotation) {
DCHECK(requester_info->IsRenderer() || requester_info->IsNavigationPreload());
@@ -917,7 +919,7 @@ void ResourceDispatcherHostImpl::OnRequestResourceInternal(
request_data.render_frame_id,
request_data.url);
}
- BeginRequest(requester_info, request_id, request_data,
+ BeginRequest(requester_info, request_id, request_data, is_sync_load,
SyncLoadResultCallback(), routing_id, std::move(mojo_request),
std::move(url_loader_client), traffic_annotation);
}
@@ -938,8 +940,9 @@ void ResourceDispatcherHostImpl::OnSyncLoad(
SyncLoadResultCallback callback =
base::Bind(&HandleSyncLoadResult, requester_info->filter()->GetWeakPtr(),
base::Passed(WrapUnique(sync_result)));
- BeginRequest(requester_info, request_id, request_data, callback,
- sync_result->routing_id(), nullptr, nullptr, kTrafficAnnotation);
+ BeginRequest(requester_info, request_id, request_data,
+ true /* is_sync_load */, callback, sync_result->routing_id(),
+ nullptr, nullptr, kTrafficAnnotation);
}
bool ResourceDispatcherHostImpl::IsRequestIDInUse(
@@ -962,7 +965,7 @@ void ResourceDispatcherHostImpl::UpdateRequestForTransfer(
int request_id,
const ResourceRequest& request_data,
LoaderMap::iterator iter,
- mojom::URLLoaderAssociatedRequest mojo_request,
+ mojom::URLLoaderRequest mojo_request,
mojom::URLLoaderClientPtr url_loader_client) {
DCHECK(requester_info->IsRenderer());
int child_id = requester_info->child_id();
@@ -1045,7 +1048,7 @@ void ResourceDispatcherHostImpl::CompleteTransfer(
int request_id,
const ResourceRequest& request_data,
int route_id,
- mojom::URLLoaderAssociatedRequest mojo_request,
+ mojom::URLLoaderRequest mojo_request,
mojom::URLLoaderClientPtr url_loader_client) {
DCHECK(requester_info->IsRenderer());
// Caller should ensure that |request_data| is associated with a transfer.
@@ -1098,9 +1101,10 @@ void ResourceDispatcherHostImpl::BeginRequest(
ResourceRequesterInfo* requester_info,
int request_id,
const ResourceRequest& request_data,
+ bool is_sync_load,
const SyncLoadResultCallback& sync_result_handler, // only valid for sync
int route_id,
- mojom::URLLoaderAssociatedRequest mojo_request,
+ mojom::URLLoaderRequest mojo_request,
mojom::URLLoaderClientPtr url_loader_client,
const net::NetworkTrafficAnnotationTag& traffic_annotation) {
DCHECK(requester_info->IsRenderer() || requester_info->IsNavigationPreload());
@@ -1218,8 +1222,8 @@ void ResourceDispatcherHostImpl::BeginRequest(
base::Bind(
&ResourceDispatcherHostImpl::ContinuePendingBeginRequest,
base::Unretained(this), make_scoped_refptr(requester_info),
- request_id, request_data, sync_result_handler, route_id,
- headers, base::Passed(std::move(mojo_request)),
+ request_id, request_data, is_sync_load, sync_result_handler,
+ route_id, headers, base::Passed(std::move(mojo_request)),
base::Passed(std::move(url_loader_client)),
base::Passed(std::move(blob_handles)), traffic_annotation));
return;
@@ -1228,9 +1232,9 @@ void ResourceDispatcherHostImpl::BeginRequest(
}
}
ContinuePendingBeginRequest(
- requester_info, request_id, request_data, sync_result_handler, route_id,
- headers, std::move(mojo_request), std::move(url_loader_client),
- std::move(blob_handles), traffic_annotation,
+ requester_info, request_id, request_data, is_sync_load,
+ sync_result_handler, route_id, headers, std::move(mojo_request),
+ std::move(url_loader_client), std::move(blob_handles), traffic_annotation,
HeaderInterceptorResult::CONTINUE);
}
@@ -1238,15 +1242,17 @@ void ResourceDispatcherHostImpl::ContinuePendingBeginRequest(
scoped_refptr<ResourceRequesterInfo> requester_info,
int request_id,
const ResourceRequest& request_data,
+ bool is_sync_load,
const SyncLoadResultCallback& sync_result_handler, // only valid for sync
int route_id,
const net::HttpRequestHeaders& headers,
- mojom::URLLoaderAssociatedRequest mojo_request,
+ mojom::URLLoaderRequest mojo_request,
mojom::URLLoaderClientPtr url_loader_client,
BlobHandles blob_handles,
const net::NetworkTrafficAnnotationTag& traffic_annotation,
HeaderInterceptorResult interceptor_result) {
DCHECK(requester_info->IsRenderer() || requester_info->IsNavigationPreload());
+ DCHECK(!sync_result_handler || is_sync_load);
if (interceptor_result != HeaderInterceptorResult::CONTINUE) {
if (requester_info->IsRenderer() &&
interceptor_result == HeaderInterceptorResult::KILL) {
@@ -1265,7 +1271,6 @@ void ResourceDispatcherHostImpl::ContinuePendingBeginRequest(
bool allow_download = false;
bool do_not_prompt_for_login = false;
bool report_raw_headers = false;
- bool is_sync_load = !!sync_result_handler;
int load_flags = BuildLoadFlagsForRequest(request_data, is_sync_load);
bool is_navigation_stream_request =
IsBrowserSideNavigationEnabled() &&
@@ -1310,8 +1315,7 @@ void ResourceDispatcherHostImpl::ContinuePendingBeginRequest(
new_request->set_method(request_data.method);
- new_request->set_first_party_for_cookies(
- request_data.first_party_for_cookies);
+ new_request->set_site_for_cookies(request_data.site_for_cookies);
// The initiator should normally be present, unless this is a navigation in
// a top-level frame. It may be null for some top-level navigations (eg:
@@ -1383,7 +1387,7 @@ void ResourceDispatcherHostImpl::ContinuePendingBeginRequest(
if (request_data.resource_type == RESOURCE_TYPE_IMAGE &&
HTTP_AUTH_RELATION_BLOCKED_CROSS ==
HttpAuthRelationTypeOf(request_data.url,
- request_data.first_party_for_cookies)) {
+ request_data.site_for_cookies)) {
// Prevent third-party image content from prompting for login, as this
// is often a scam to extract credentials for another domain from the
// user. Only block image loads, as the attack applies largely to the
@@ -1501,7 +1505,7 @@ ResourceDispatcherHostImpl::CreateResourceHandler(
int route_id,
int child_id,
ResourceContext* resource_context,
- mojom::URLLoaderAssociatedRequest mojo_request,
+ mojom::URLLoaderRequest mojo_request,
mojom::URLLoaderClientPtr url_loader_client) {
DCHECK(requester_info->IsRenderer() || requester_info->IsNavigationPreload());
// TODO(pkasting): Remove ScopedTracker below once crbug.com/456331 is fixed.
@@ -1569,7 +1573,7 @@ ResourceDispatcherHostImpl::CreateResourceHandler(
std::unique_ptr<ResourceHandler>
ResourceDispatcherHostImpl::CreateBaseResourceHandler(
net::URLRequest* request,
- mojom::URLLoaderAssociatedRequest mojo_request,
+ mojom::URLLoaderRequest mojo_request,
mojom::URLLoaderClientPtr url_loader_client,
ResourceType resource_type) {
std::unique_ptr<ResourceHandler> handler;
@@ -1790,9 +1794,13 @@ ResourceRequestInfoImpl* ResourceDispatcherHostImpl::CreateRequestInfo(
false); // initiated_in_secure_context
}
-void ResourceDispatcherHostImpl::OnRenderViewHostCreated(int child_id,
- int route_id) {
- scheduler_->OnClientCreated(child_id, route_id);
+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());
}
void ResourceDispatcherHostImpl::OnRenderViewHostDeleted(int child_id,
@@ -1854,12 +1862,13 @@ void ResourceDispatcherHostImpl::CancelRequestsForRoute(
// Don't cancel navigations that are expected to live beyond this process.
if (IsTransferredNavigation(id))
any_requests_transferring = true;
- if (info->detachable_handler()) {
- info->detachable_handler()->Detach();
- } else if (!info->IsDownload() && !info->is_stream() &&
- !IsTransferredNavigation(id) &&
- (cancel_all_routes || route_id == info->GetRenderFrameID())) {
- matching_requests.push_back(id);
+ if (cancel_all_routes || route_id == info->GetRenderFrameID()) {
+ if (info->detachable_handler()) {
+ info->detachable_handler()->Detach();
+ } else if (!info->IsDownload() && !info->is_stream() &&
+ !IsTransferredNavigation(id)) {
+ matching_requests.push_back(id);
+ }
}
}
@@ -2097,7 +2106,7 @@ void ResourceDispatcherHostImpl::BeginNavigationRequest(
info.common_params.url,
resource_type,
resource_context))) {
- loader->NotifyRequestFailed(false, net::ERR_ABORTED);
+ loader->NotifyRequestFailed(false, net::ERR_ABORTED, base::nullopt, false);
return;
}
@@ -2118,8 +2127,7 @@ void ResourceDispatcherHostImpl::BeginNavigationRequest(
info.common_params.url, net::HIGHEST, nullptr, kTrafficAnnotation);
new_request->set_method(info.common_params.method);
- new_request->set_first_party_for_cookies(
- info.first_party_for_cookies);
+ new_request->set_site_for_cookies(info.site_for_cookies);
new_request->set_initiator(info.begin_params.initiator_origin);
if (info.is_main_frame) {
new_request->set_first_party_url_policy(
@@ -2144,7 +2152,8 @@ void ResourceDispatcherHostImpl::BeginNavigationRequest(
if (body) {
if (!GetBodyBlobDataHandles(body, resource_context, &blob_handles)) {
new_request->CancelWithError(net::ERR_INSUFFICIENT_RESOURCES);
- loader->NotifyRequestFailed(false, net::ERR_ABORTED);
+ loader->NotifyRequestFailed(false, net::ERR_ABORTED, base::nullopt,
+ false);
return;
}
new_request->set_upload(UploadDataStreamBuilder::Build(
@@ -2263,27 +2272,21 @@ void ResourceDispatcherHostImpl::OnRenderFrameDeleted(
void ResourceDispatcherHostImpl::OnRequestResourceWithMojo(
ResourceRequesterInfo* requester_info,
- int routing_id,
- int request_id,
+ int32_t routing_id,
+ int32_t request_id,
+ uint32_t options,
const ResourceRequest& request,
- mojom::URLLoaderAssociatedRequest mojo_request,
+ mojom::URLLoaderRequest mojo_request,
mojom::URLLoaderClientPtr url_loader_client,
const net::NetworkTrafficAnnotationTag& traffic_annotation) {
- OnRequestResourceInternal(requester_info, routing_id, request_id, request,
- std::move(mojo_request),
+ DCHECK_EQ(mojom::kURLLoadOptionNone,
+ options & ~mojom::kURLLoadOptionSynchronous);
+ bool is_sync_load = options & mojom::kURLLoadOptionSynchronous;
+ OnRequestResourceInternal(requester_info, routing_id, request_id,
+ is_sync_load, request, std::move(mojo_request),
std::move(url_loader_client), traffic_annotation);
}
-void ResourceDispatcherHostImpl::OnSyncLoadWithMojo(
- ResourceRequesterInfo* requester_info,
- int routing_id,
- int request_id,
- const ResourceRequest& request_data,
- const SyncLoadResultCallback& result_handler) {
- BeginRequest(requester_info, request_id, request_data, result_handler,
- routing_id, nullptr, nullptr, kTrafficAnnotation);
-}
-
// static
int ResourceDispatcherHostImpl::CalculateApproximateMemoryCost(
net::URLRequest* request) {
@@ -2569,8 +2572,8 @@ void ResourceDispatcherHostImpl::UpdateLoadInfo() {
// requests), we must go to the UI thread and compare the requests using their
// WebContents.
main_thread_task_runner_->PostTask(
- FROM_HERE,
- base::Bind(UpdateLoadStateOnUI, loader_delegate_, base::Passed(&infos)));
+ FROM_HERE, base::BindOnce(UpdateLoadStateOnUI, loader_delegate_,
+ base::Passed(&infos)));
}
void ResourceDispatcherHostImpl::RecordOutstandingRequestsStats() {
diff --git a/chromium/content/browser/loader/resource_dispatcher_host_impl.h b/chromium/content/browser/loader/resource_dispatcher_host_impl.h
index 49645a1d284..3ef287d8739 100644
--- a/chromium/content/browser/loader/resource_dispatcher_host_impl.h
+++ b/chromium/content/browser/loader/resource_dispatcher_host_impl.h
@@ -51,8 +51,9 @@ class RepeatingTimer;
}
namespace net {
-class URLRequest;
class HttpRequestHeaders;
+class URLRequest;
+class URLRequestContextGetter;
}
namespace storage {
@@ -162,8 +163,10 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
static const int kAvgBytesPerOutstandingRequest = 4400;
// Called when a RenderViewHost is created.
- void OnRenderViewHostCreated(int child_id,
- int route_id);
+ 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);
@@ -282,19 +285,14 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
// Called when loading a request with mojo.
void OnRequestResourceWithMojo(
ResourceRequesterInfo* requester_info,
- int routing_id,
- int request_id,
+ int32_t routing_id,
+ int32_t request_id,
+ uint32_t options,
const ResourceRequest& request,
- mojom::URLLoaderAssociatedRequest mojo_request,
+ mojom::URLLoaderRequest mojo_request,
mojom::URLLoaderClientPtr url_loader_client,
const net::NetworkTrafficAnnotationTag& traffic_annotation);
- void OnSyncLoadWithMojo(ResourceRequesterInfo* requester_info,
- int routing_id,
- int request_id,
- const ResourceRequest& request_data,
- const SyncLoadResultCallback& result_handler);
-
// Helper function for initializing the |request| passed in. By initializing
// we mean setting the |referrer| on the |request|, associating the
// ResourceRequestInfoImpl structure with the |request|, etc.
@@ -354,6 +352,7 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
DetachableResourceTimesOut);
FRIEND_TEST_ALL_PREFIXES(ResourceDispatcherHostTest,
TestProcessCancelDetachableTimesOut);
+ FRIEND_TEST_ALL_PREFIXES(ResourceDispatcherHostTest, CancelRequestsForRoute);
FRIEND_TEST_ALL_PREFIXES(SitePerProcessIgnoreCertErrorsBrowserTest,
CrossSiteRedirectCertificateStore);
FRIEND_TEST_ALL_PREFIXES(ResourceDispatcherHostTest, LoadInfo);
@@ -544,8 +543,9 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
ResourceRequesterInfo* requester_info,
int routing_id,
int request_id,
+ bool is_sync_load,
const ResourceRequest& request_data,
- mojom::URLLoaderAssociatedRequest mojo_request,
+ mojom::URLLoaderRequest mojo_request,
mojom::URLLoaderClientPtr url_loader_client,
const net::NetworkTrafficAnnotationTag& traffic_annotation);
@@ -563,7 +563,7 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
int request_id,
const ResourceRequest& request_data,
LoaderMap::iterator iter,
- mojom::URLLoaderAssociatedRequest mojo_request,
+ mojom::URLLoaderRequest mojo_request,
mojom::URLLoaderClientPtr url_loader_client);
// If |request_data| is for a request being transferred from another process,
@@ -572,16 +572,17 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
int request_id,
const ResourceRequest& request_data,
int route_id,
- mojom::URLLoaderAssociatedRequest mojo_request,
+ mojom::URLLoaderRequest mojo_request,
mojom::URLLoaderClientPtr url_loader_client);
void BeginRequest(
ResourceRequesterInfo* requester_info,
int request_id,
const ResourceRequest& request_data,
+ bool is_sync_load,
const SyncLoadResultCallback& sync_result_handler, // only valid for sync
int route_id,
- mojom::URLLoaderAssociatedRequest mojo_request,
+ mojom::URLLoaderRequest mojo_request,
mojom::URLLoaderClientPtr url_loader_client,
const net::NetworkTrafficAnnotationTag& traffic_annotation);
@@ -597,10 +598,11 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
scoped_refptr<ResourceRequesterInfo> requester_info,
int request_id,
const ResourceRequest& request_data,
+ bool is_sync_load,
const SyncLoadResultCallback& sync_result_handler, // only valid for sync
int route_id,
const net::HttpRequestHeaders& headers,
- mojom::URLLoaderAssociatedRequest mojo_request,
+ mojom::URLLoaderRequest mojo_request,
mojom::URLLoaderClientPtr url_loader_client,
BlobHandles blob_handles,
const net::NetworkTrafficAnnotationTag& traffic_annotation,
@@ -616,13 +618,13 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
int route_id,
int child_id,
ResourceContext* resource_context,
- mojom::URLLoaderAssociatedRequest mojo_request,
+ mojom::URLLoaderRequest mojo_request,
mojom::URLLoaderClientPtr url_loader_client);
// Creates either MojoAsyncResourceHandler or AsyncResourceHandler.
std::unique_ptr<ResourceHandler> CreateBaseResourceHandler(
net::URLRequest* request,
- mojom::URLLoaderAssociatedRequest mojo_request,
+ mojom::URLLoaderRequest mojo_request,
mojom::URLLoaderClientPtr url_loader_client,
ResourceType resource_type);
diff --git a/chromium/content/browser/loader/resource_dispatcher_host_unittest.cc b/chromium/content/browser/loader/resource_dispatcher_host_unittest.cc
index 433243aba2a..1f952a5fbfc 100644
--- a/chromium/content/browser/loader/resource_dispatcher_host_unittest.cc
+++ b/chromium/content/browser/loader/resource_dispatcher_host_unittest.cc
@@ -43,6 +43,7 @@
#include "content/common/navigation_params.h"
#include "content/common/resource_messages.h"
#include "content/common/view_messages.h"
+#include "content/public/browser/browser_thread.h"
#include "content/public/browser/global_request_id.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
@@ -162,7 +163,7 @@ static ResourceRequest CreateResourceRequest(const char* method,
ResourceRequest request;
request.method = std::string(method);
request.url = url;
- request.first_party_for_cookies = url; // bypass third-party cookie blocking
+ request.site_for_cookies = url; // bypass third-party cookie blocking
request.request_initiator = url::Origin(url); // ensure initiator is set
request.referrer_policy = blink::kWebReferrerPolicyDefault;
request.load_flags = 0;
@@ -911,6 +912,9 @@ class ResourceDispatcherHostTest : public testing::Test, public IPC::Sender {
browser_context_->GetResourceContext(),
web_contents_->GetRenderProcessHost()->GetID());
child_ids_.insert(web_contents_->GetRenderProcessHost()->GetID());
+ request_context_getter_ = new net::TestURLRequestContextGetter(
+ content::BrowserThread::GetTaskRunnerForThread(
+ content::BrowserThread::UI));
}
void TearDown() override {
@@ -1038,10 +1042,10 @@ class ResourceDispatcherHostTest : public testing::Test, public IPC::Sender {
new ResourceHostMsg_DataReceived_ACK(request_id));
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::Bind(&GenerateIPCMessage, scoped_refptr<ResourceRequesterInfo>(
- filter_->requester_info_for_test()),
- base::Passed(&ack)));
+ FROM_HERE, base::BindOnce(&GenerateIPCMessage,
+ scoped_refptr<ResourceRequesterInfo>(
+ filter_->requester_info_for_test()),
+ base::Passed(&ack)));
}
void WaitForRequestComplete() {
@@ -1120,6 +1124,14 @@ class ResourceDispatcherHostTest : public testing::Test, public IPC::Sender {
return filter->requester_info_for_test();
}
+ bool IsDetached(net::URLRequest* request) {
+ auto* request_info = ResourceRequestInfoImpl::ForRequest(request);
+ if (!request_info)
+ return false;
+ return request_info->detachable_handler() &&
+ request_info->detachable_handler()->is_detached();
+ }
+
content::TestBrowserThreadBundle thread_bundle_;
std::unique_ptr<TestBrowserContext> browser_context_;
std::unique_ptr<TestURLRequestJobFactory> job_factory_;
@@ -1140,6 +1152,7 @@ class ResourceDispatcherHostTest : public testing::Test, public IPC::Sender {
std::unique_ptr<base::RunLoop> wait_for_request_complete_loop_;
RenderViewHostTestEnabler render_view_host_test_enabler_;
bool auto_advance_;
+ scoped_refptr<net::TestURLRequestContextGetter> request_context_getter_;
};
void ResourceDispatcherHostTest::MakeTestRequest(int render_view_id,
@@ -1515,9 +1528,10 @@ TEST_F(ResourceDispatcherHostTest, DetachedResourceTimesOut) {
// Wait until after the delay timer times out before we start processing any
// messages.
base::OneShotTimer timer;
+ base::RunLoop run_loop;
timer.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(210),
- base::MessageLoop::current(), &base::MessageLoop::QuitWhenIdle);
- base::RunLoop().Run();
+ run_loop.QuitWhenIdleClosure());
+ run_loop.Run();
// The prefetch should be cancelled by now.
EXPECT_EQ(0, host_.pending_requests());
@@ -1850,6 +1864,52 @@ TEST_F(ResourceDispatcherHostTest, CancelInDelegate) {
CheckRequestCompleteErrorCode(msgs[0][0], net::ERR_ACCESS_DENIED);
}
+TEST_F(ResourceDispatcherHostTest, CancelRequestsForRoute) {
+ job_factory_->SetDelayedStartJobGeneration(true);
+ MakeTestRequestWithRenderFrame(0, 11, 1, net::URLRequestTestJob::test_url_1(),
+ RESOURCE_TYPE_XHR);
+ EXPECT_EQ(1, host_.pending_requests());
+
+ MakeTestRequestWithRenderFrame(0, 12, 2, net::URLRequestTestJob::test_url_2(),
+ RESOURCE_TYPE_XHR);
+ EXPECT_EQ(2, host_.pending_requests());
+
+ MakeTestRequestWithRenderFrame(0, 11, 3, net::URLRequestTestJob::test_url_3(),
+ RESOURCE_TYPE_PING);
+ EXPECT_EQ(3, host_.pending_requests());
+
+ MakeTestRequestWithRenderFrame(0, 12, 4, net::URLRequestTestJob::test_url_4(),
+ RESOURCE_TYPE_PING);
+ EXPECT_EQ(4, host_.pending_requests());
+
+ EXPECT_TRUE(host_.GetURLRequest(GlobalRequestID(filter_->child_id(), 1)));
+ EXPECT_TRUE(host_.GetURLRequest(GlobalRequestID(filter_->child_id(), 2)));
+ EXPECT_TRUE(host_.GetURLRequest(GlobalRequestID(filter_->child_id(), 3)));
+ EXPECT_TRUE(host_.GetURLRequest(GlobalRequestID(filter_->child_id(), 4)));
+
+ host_.CancelRequestsForRoute(GlobalFrameRoutingId(filter_->child_id(), 11));
+
+ EXPECT_FALSE(host_.GetURLRequest(GlobalRequestID(filter_->child_id(), 1)));
+ EXPECT_TRUE(host_.GetURLRequest(GlobalRequestID(filter_->child_id(), 2)));
+ ASSERT_TRUE(host_.GetURLRequest(GlobalRequestID(filter_->child_id(), 3)));
+ ASSERT_TRUE(host_.GetURLRequest(GlobalRequestID(filter_->child_id(), 4)));
+
+ EXPECT_TRUE(
+ IsDetached(host_.GetURLRequest(GlobalRequestID(filter_->child_id(), 3))));
+ EXPECT_FALSE(
+ IsDetached(host_.GetURLRequest(GlobalRequestID(filter_->child_id(), 4))));
+
+ CompleteStartRequest(2);
+ CompleteStartRequest(3);
+ CompleteStartRequest(4);
+
+ while (host_.pending_requests() > 0) {
+ while (net::URLRequestTestJob::ProcessOnePendingMessage()) {
+ }
+ content::RunAllBlockingPoolTasksUntilIdle();
+ }
+}
+
// Tests CancelRequestsForProcess
TEST_F(ResourceDispatcherHostTest, TestProcessCancel) {
scoped_refptr<TestFilter> test_filter = new TestFilter(
@@ -1938,7 +1998,8 @@ TEST_F(ResourceDispatcherHostTest, CancelRequestsOnRenderFrameDeleted) {
TestResourceDispatcherHostDelegate delegate;
host_.SetDelegate(&delegate);
- host_.OnRenderViewHostCreated(filter_->child_id(), 0);
+ host_.OnRenderViewHostCreated(filter_->child_id(), 0,
+ request_context_getter_.get());
// One RenderView issues a high priority request and a low priority one. Both
// should be started.
@@ -1998,10 +2059,12 @@ TEST_F(ResourceDispatcherHostTest, TestProcessCancelDetachedTimesOut) {
// Wait until after the delay timer times out before we start processing any
// messages.
+ base::RunLoop run_loop;
base::OneShotTimer timer;
- timer.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(210),
- base::MessageLoop::current(), &base::MessageLoop::QuitWhenIdle);
- base::RunLoop().Run();
+ timer.Start(
+ FROM_HERE, base::TimeDelta::FromMilliseconds(210),
+ base::Bind(&base::RunLoop::QuitWhenIdle, base::Unretained(&run_loop)));
+ run_loop.Run();
// The prefetch should be cancelled by now.
EXPECT_EQ(0, host_.pending_requests());
@@ -3691,7 +3754,8 @@ TEST_F(ResourceDispatcherHostTest, DidChangePriority) {
// Needed to enable scheduling for this child.
host_.OnRenderViewHostCreated(filter_->child_id(), // child_id
- 0); // route_id
+ 0, // route_id
+ request_context_getter_.get());
// Prevent any of these requests from completing.
job_factory_->SetDelayedCompleteJobGeneration(true);
@@ -3776,72 +3840,6 @@ TEST_F(ResourceDispatcherHostTest, ThrottleMustProcessResponseBeforeRead) {
content::RunAllBlockingPoolTasksUntilIdle();
}
-namespace {
-
-void StoreSyncLoadResult(bool* called,
- bool* was_null,
- SyncLoadResult* result_out,
- const SyncLoadResult* result) {
- *called = true;
- *was_null = !result;
-
- if (result)
- *result_out = *result;
-}
-
-} // namespace
-
-TEST_F(ResourceDispatcherHostTest, SyncLoadWithMojoSuccess) {
- ResourceRequest request = CreateResourceRequest(
- "GET", RESOURCE_TYPE_XHR, net::URLRequestTestJob::test_url_1());
- request.priority = net::MAXIMUM_PRIORITY;
-
- bool called = false;
- bool was_null = false;
- SyncLoadResult result;
- host_.OnSyncLoadWithMojo(
- GetResourceRequesterInfo(filter_.get()), 0, 1, request,
- base::Bind(&StoreSyncLoadResult, &called, &was_null, &result));
- content::RunAllBlockingPoolTasksUntilIdle();
- EXPECT_TRUE(called);
- EXPECT_FALSE(was_null);
- EXPECT_EQ(net::OK, result.error_code);
-}
-
-TEST_F(ResourceDispatcherHostTest, SyncLoadWithMojoError) {
- ResourceRequest request = CreateResourceRequest(
- "GET", RESOURCE_TYPE_XHR, net::URLRequestTestJob::test_url_error());
- request.priority = net::MAXIMUM_PRIORITY;
-
- bool called = false;
- bool was_null = false;
- SyncLoadResult result;
- host_.OnSyncLoadWithMojo(
- GetResourceRequesterInfo(filter_.get()), 0, 1, request,
- base::Bind(&StoreSyncLoadResult, &called, &was_null, &result));
- content::RunAllBlockingPoolTasksUntilIdle();
- EXPECT_TRUE(called);
- EXPECT_FALSE(was_null);
- EXPECT_EQ(net::ERR_INVALID_URL, result.error_code);
-}
-
-TEST_F(ResourceDispatcherHostTest, SyncLoadWithMojoCancel) {
- ResourceRequest request = CreateResourceRequest(
- "GET", RESOURCE_TYPE_XHR, net::URLRequestTestJob::test_url_error());
- request.priority = net::MAXIMUM_PRIORITY;
-
- bool called = false;
- bool was_null = false;
- SyncLoadResult result;
- host_.OnSyncLoadWithMojo(
- GetResourceRequesterInfo(filter_.get()), 0, 1, request,
- base::Bind(&StoreSyncLoadResult, &called, &was_null, &result));
- host_.CancelRequestsForProcess(filter_->child_id());
- content::RunAllBlockingPoolTasksUntilIdle();
- EXPECT_TRUE(called);
- EXPECT_TRUE(was_null);
-}
-
// A URLRequestTestJob that sets a test certificate on the |ssl_info|
// field of the response.
class TestHTTPSURLRequestJob : public net::URLRequestTestJob {
diff --git a/chromium/content/browser/loader/resource_handler.cc b/chromium/content/browser/loader/resource_handler.cc
index 0f875512f69..57c0bc23708 100644
--- a/chromium/content/browser/loader/resource_handler.cc
+++ b/chromium/content/browser/loader/resource_handler.cc
@@ -42,10 +42,6 @@ void ResourceHandler::Cancel() {
ReleaseController()->Cancel();
}
-void ResourceHandler::CancelAndIgnore() {
- ReleaseController()->CancelAndIgnore();
-}
-
void ResourceHandler::CancelWithError(int error_code) {
ReleaseController()->CancelWithError(error_code);
}
diff --git a/chromium/content/browser/loader/resource_handler.h b/chromium/content/browser/loader/resource_handler.h
index 2b67e0c4c32..b787b9c0d02 100644
--- a/chromium/content/browser/loader/resource_handler.h
+++ b/chromium/content/browser/loader/resource_handler.h
@@ -154,7 +154,6 @@ class CONTENT_EXPORT ResourceHandler {
// passed to HoldController and then destroy it.
void Resume();
void Cancel();
- void CancelAndIgnore();
void CancelWithError(int error_code);
// Cancels the request when the class does not currently have ownership of the
diff --git a/chromium/content/browser/loader/resource_hints_impl.cc b/chromium/content/browser/loader/resource_hints_impl.cc
index 05eb063cbb8..46faed62fe5 100644
--- a/chromium/content/browser/loader/resource_hints_impl.cc
+++ b/chromium/content/browser/loader/resource_hints_impl.cc
@@ -47,7 +47,7 @@ void OnResolveComplete(std::unique_ptr<RequestHolder> request_holder,
void PreconnectUrl(net::URLRequestContextGetter* getter,
const GURL& url,
- const GURL& first_party_for_cookies,
+ const GURL& site_for_cookies,
int count,
bool allow_credentials,
net::HttpRequestInfo::RequestMotivation motivation) {
@@ -75,7 +75,7 @@ void PreconnectUrl(net::URLRequestContextGetter* getter,
request_info.motivation = motivation;
net::NetworkDelegate* delegate = request_context->network_delegate();
- if (delegate->CanEnablePrivacyMode(url, first_party_for_cookies))
+ 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
diff --git a/chromium/content/browser/loader/resource_loader.cc b/chromium/content/browser/loader/resource_loader.cc
index 3a185938f43..a7acc5b20bb 100644
--- a/chromium/content/browser/loader/resource_loader.cc
+++ b/chromium/content/browser/loader/resource_loader.cc
@@ -25,6 +25,7 @@
#include "content/browser/service_worker/service_worker_response_info.h"
#include "content/browser/ssl/ssl_client_auth_handler.h"
#include "content/browser/ssl/ssl_manager.h"
+#include "content/common/loader_util.h"
#include "content/public/browser/resource_dispatcher_host_login_delegate.h"
#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/common/content_client.h"
@@ -47,9 +48,12 @@ using base::TimeTicks;
namespace content {
namespace {
-void PopulateResourceResponse(ResourceRequestInfoImpl* info,
- net::URLRequest* request,
- ResourceResponse* response) {
+void PopulateResourceResponse(
+ ResourceRequestInfoImpl* info,
+ net::URLRequest* request,
+ ResourceResponse* response,
+ const net::HttpRawRequestHeaders& raw_request_headers,
+ const net::HttpResponseHeaders* raw_response_headers) {
response->head.request_time = request->request_time();
response->head.response_time = request->response_time();
response->head.headers = request->response_headers();
@@ -67,6 +71,10 @@ void PopulateResourceResponse(ResourceRequestInfoImpl* info,
content::ResourceRequestInfo::ForRequest(request);
if (request_info)
response->head.previews_state = request_info->GetPreviewsState();
+ if (info->ShouldReportRawHeaders()) {
+ response->head.devtools_info =
+ BuildDevToolsInfo(*request, raw_request_headers, raw_response_headers);
+ }
response->head.effective_connection_type =
net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN;
@@ -147,11 +155,6 @@ class ResourceLoader::Controller : public ResourceController {
resource_loader_->Cancel();
}
- void CancelAndIgnore() override {
- MarkAsUsed();
- resource_loader_->CancelAndIgnore();
- }
-
void CancelWithError(int error_code) override {
MarkAsUsed();
resource_loader_->CancelWithError(error_code);
@@ -251,12 +254,6 @@ void ResourceLoader::CancelRequest(bool from_renderer) {
CancelRequestInternal(net::ERR_ABORTED, from_renderer);
}
-void ResourceLoader::CancelAndIgnore() {
- ResourceRequestInfoImpl* info = GetRequestInfo();
- info->set_was_ignored_by_handler(true);
- CancelRequest(false);
-}
-
void ResourceLoader::CancelWithError(int error_code) {
TRACE_EVENT_WITH_FLOW0("loading", "ResourceLoader::CancelWithError", this,
TRACE_EVENT_FLAG_FLOW_IN);
@@ -345,7 +342,11 @@ void ResourceLoader::OnReceivedRedirect(net::URLRequest* unused,
}
scoped_refptr<ResourceResponse> response = new ResourceResponse();
- PopulateResourceResponse(info, request_.get(), response.get());
+ PopulateResourceResponse(info, request_.get(), response.get(),
+ raw_request_headers_, raw_response_headers_.get());
+ raw_request_headers_ = net::HttpRawRequestHeaders();
+ raw_response_headers_ = nullptr;
+
delegate_->DidReceiveRedirect(this, redirect_info.new_url, response.get());
// Can't used ScopedDeferral here, because on sync completion, need to set
@@ -360,7 +361,7 @@ void ResourceLoader::OnReceivedRedirect(net::URLRequest* unused,
} else {
*defer = false;
if (delegate_->HandleExternalProtocol(this, redirect_info.new_url))
- CancelAndIgnore();
+ Cancel();
}
}
@@ -510,9 +511,9 @@ void ResourceLoader::Resume(bool called_from_resource_controller) {
// Always post a task, as synchronous resumes don't go through this
// method.
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::Bind(&ResourceLoader::ReadMore, weak_ptr_factory_.GetWeakPtr(),
- false /* handle_result_asynchronously */));
+ FROM_HERE, base::BindOnce(&ResourceLoader::ReadMore,
+ weak_ptr_factory_.GetWeakPtr(),
+ false /* handle_result_asynchronously */));
break;
case DEFERRED_READ:
if (called_from_resource_controller) {
@@ -521,8 +522,8 @@ void ResourceLoader::Resume(bool called_from_resource_controller) {
// ResumeReading does check for cancellation. Should other paths do that
// as well?
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&ResourceLoader::ResumeReading,
- weak_ptr_factory_.GetWeakPtr()));
+ FROM_HERE, base::BindOnce(&ResourceLoader::ResumeReading,
+ weak_ptr_factory_.GetWeakPtr()));
} else {
// If this was called as a result of a handler succeeding synchronously,
// force the result of the next read to be handled asynchronously, to
@@ -533,8 +534,8 @@ void ResourceLoader::Resume(bool called_from_resource_controller) {
case DEFERRED_RESPONSE_COMPLETE:
if (called_from_resource_controller) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&ResourceLoader::ResponseCompleted,
- weak_ptr_factory_.GetWeakPtr()));
+ FROM_HERE, base::BindOnce(&ResourceLoader::ResponseCompleted,
+ weak_ptr_factory_.GetWeakPtr()));
} else {
ResponseCompleted();
}
@@ -543,8 +544,8 @@ void ResourceLoader::Resume(bool called_from_resource_controller) {
if (called_from_resource_controller) {
// Delay self-destruction since we don't know how we were reached.
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&ResourceLoader::CallDidFinishLoading,
- weak_ptr_factory_.GetWeakPtr()));
+ FROM_HERE, base::BindOnce(&ResourceLoader::CallDidFinishLoading,
+ weak_ptr_factory_.GetWeakPtr()));
} else {
CallDidFinishLoading();
}
@@ -566,11 +567,19 @@ void ResourceLoader::StartRequestInternal() {
}
if (delegate_->HandleExternalProtocol(this, request_->url())) {
- CancelAndIgnore();
+ Cancel();
return;
}
started_request_ = true;
+
+ if (GetRequestInfo()->ShouldReportRawHeaders()) {
+ request_->SetRequestHeadersCallback(
+ base::Bind(&net::HttpRawRequestHeaders::Assign,
+ base::Unretained(&raw_request_headers_)));
+ request_->SetResponseHeadersCallback(base::Bind(
+ &ResourceLoader::SetRawResponseHeaders, base::Unretained(this)));
+ }
request_->Start();
delegate_->DidStartRequest(this);
@@ -617,8 +626,8 @@ void ResourceLoader::CancelRequestInternal(int error, bool from_renderer) {
// notification from the request, so we have to signal ourselves to finish
// this request.
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&ResourceLoader::ResponseCompleted,
- weak_ptr_factory_.GetWeakPtr()));
+ FROM_HERE, base::BindOnce(&ResourceLoader::ResponseCompleted,
+ weak_ptr_factory_.GetWeakPtr()));
}
}
@@ -627,7 +636,7 @@ void ResourceLoader::FollowDeferredRedirectInternal() {
GURL redirect_url = deferred_redirect_url_;
deferred_redirect_url_ = GURL();
if (delegate_->HandleExternalProtocol(this, redirect_url)) {
- CancelAndIgnore();
+ Cancel();
} else {
request_->FollowDeferredRedirect();
}
@@ -636,7 +645,10 @@ void ResourceLoader::FollowDeferredRedirectInternal() {
void ResourceLoader::CompleteResponseStarted() {
ResourceRequestInfoImpl* info = GetRequestInfo();
scoped_refptr<ResourceResponse> response = new ResourceResponse();
- PopulateResourceResponse(info, request_.get(), response.get());
+ PopulateResourceResponse(info, request_.get(), response.get(),
+ raw_request_headers_, raw_response_headers_.get());
+ raw_request_headers_ = net::HttpRawRequestHeaders();
+ raw_response_headers_ = nullptr;
delegate_->DidReceiveResponse(this, response.get());
@@ -702,8 +714,8 @@ void ResourceLoader::ReadMore(bool handle_result_async) {
// thread in case the URLRequest can provide data synchronously.
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
- base::Bind(&ResourceLoader::OnReadCompleted,
- weak_ptr_factory_.GetWeakPtr(), request_.get(), result));
+ base::BindOnce(&ResourceLoader::OnReadCompleted,
+ weak_ptr_factory_.GetWeakPtr(), request_.get(), result));
}
}
@@ -817,4 +829,9 @@ void ResourceLoader::RecordHistograms() {
}
}
+void ResourceLoader::SetRawResponseHeaders(
+ scoped_refptr<const net::HttpResponseHeaders> headers) {
+ raw_response_headers_ = headers;
+}
+
} // namespace content
diff --git a/chromium/content/browser/loader/resource_loader.h b/chromium/content/browser/loader/resource_loader.h
index 49ce93a45fd..259d498a7df 100644
--- a/chromium/content/browser/loader/resource_loader.h
+++ b/chromium/content/browser/loader/resource_loader.h
@@ -17,10 +17,12 @@
#include "content/browser/ssl/ssl_client_auth_handler.h"
#include "content/browser/ssl/ssl_error_handler.h"
#include "content/common/content_export.h"
+#include "net/http/http_raw_request_headers.h"
#include "net/url_request/url_request.h"
#include "url/gurl.h"
namespace net {
+class HttpResponseHeaders;
class X509Certificate;
}
@@ -95,7 +97,6 @@ class CONTENT_EXPORT ResourceLoader : public net::URLRequest::Delegate,
// otherwise.
void Resume(bool called_from_resource_controller);
void Cancel();
- void CancelAndIgnore();
void CancelWithError(int error_code);
void StartRequestInternal();
@@ -114,6 +115,8 @@ class CONTENT_EXPORT ResourceLoader : public net::URLRequest::Delegate,
void ResponseCompleted();
void CallDidFinishLoading();
void RecordHistograms();
+ void SetRawResponseHeaders(
+ scoped_refptr<const net::HttpResponseHeaders> headers);
bool is_deferred() const { return deferred_stage_ != DEFERRED_NONE; }
@@ -179,6 +182,9 @@ class CONTENT_EXPORT ResourceLoader : public net::URLRequest::Delegate,
scoped_refptr<net::IOBuffer> read_buffer_;
int read_buffer_size_;
+ net::HttpRawRequestHeaders raw_request_headers_;
+ scoped_refptr<const net::HttpResponseHeaders> raw_response_headers_;
+
base::ThreadChecker thread_checker_;
base::WeakPtrFactory<ResourceLoader> weak_ptr_factory_;
diff --git a/chromium/content/browser/loader/resource_loader_unittest.cc b/chromium/content/browser/loader/resource_loader_unittest.cc
index dab9d6a9aa6..1b8bc12471d 100644
--- a/chromium/content/browser/loader/resource_loader_unittest.cc
+++ b/chromium/content/browser/loader/resource_loader_unittest.cc
@@ -122,9 +122,10 @@ class LoaderDestroyingCertStore : public net::ClientCertStore {
const ClientCertListCallback& cert_selected_callback) override {
// Don't destroy |loader_| while it's on the stack.
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&LoaderDestroyingCertStore::DoCallback,
- base::Unretained(loader_), cert_selected_callback,
- on_loader_deleted_callback_));
+ FROM_HERE,
+ base::BindOnce(&LoaderDestroyingCertStore::DoCallback,
+ base::Unretained(loader_), cert_selected_callback,
+ on_loader_deleted_callback_));
}
private:
@@ -164,9 +165,9 @@ class MockClientCertURLRequestJob : public net::URLRequestTestJob {
cert_request_info->cert_authorities = test_authorities();
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
- base::Bind(&MockClientCertURLRequestJob::NotifyCertificateRequested,
- weak_factory_.GetWeakPtr(),
- base::RetainedRef(cert_request_info)));
+ base::BindOnce(&MockClientCertURLRequestJob::NotifyCertificateRequested,
+ weak_factory_.GetWeakPtr(),
+ base::RetainedRef(cert_request_info)));
}
void ContinueWithCertificate(
diff --git a/chromium/content/browser/loader/resource_message_filter.cc b/chromium/content/browser/loader/resource_message_filter.cc
index b584b3cd2fd..5f4d3a7cfd4 100644
--- a/chromium/content/browser/loader/resource_message_filter.cc
+++ b/chromium/content/browser/loader/resource_message_filter.cc
@@ -52,6 +52,10 @@ void ResourceMessageFilter::OnFilterAdded(IPC::Channel*) {
void ResourceMessageFilter::OnChannelClosing() {
DCHECK(io_thread_task_runner_->BelongsToCurrentThread());
+ // Close all additional Mojo connections opened to this object so that
+ // messages are not dispatched while it is being shut down.
+ bindings_.CloseAllBindings();
+
// Unhook us from all pending network requests so they don't get sent to a
// deleted object.
ResourceDispatcherHostImpl::Get()->CancelRequestsForProcess(
@@ -85,26 +89,21 @@ base::WeakPtr<ResourceMessageFilter> ResourceMessageFilter::GetWeakPtr() {
}
void ResourceMessageFilter::CreateLoaderAndStart(
- mojom::URLLoaderAssociatedRequest request,
+ mojom::URLLoaderRequest request,
int32_t routing_id,
int32_t request_id,
uint32_t options,
const ResourceRequest& url_request,
mojom::URLLoaderClientPtr client,
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) {
- DCHECK_EQ(options, mojom::kURLLoadOptionNone);
URLLoaderFactoryImpl::CreateLoaderAndStart(
requester_info_.get(), std::move(request), routing_id, request_id,
- url_request, std::move(client),
+ options, url_request, std::move(client),
net::NetworkTrafficAnnotationTag(traffic_annotation));
}
-void ResourceMessageFilter::SyncLoad(int32_t routing_id,
- int32_t request_id,
- const ResourceRequest& url_request,
- SyncLoadCallback callback) {
- URLLoaderFactoryImpl::SyncLoad(requester_info_.get(), routing_id, request_id,
- url_request, std::move(callback));
+void ResourceMessageFilter::Clone(mojom::URLLoaderFactoryRequest request) {
+ bindings_.AddBinding(this, std::move(request));
}
int ResourceMessageFilter::child_id() const {
diff --git a/chromium/content/browser/loader/resource_message_filter.h b/chromium/content/browser/loader/resource_message_filter.h
index b318a5526b6..f00cb19e7f4 100644
--- a/chromium/content/browser/loader/resource_message_filter.h
+++ b/chromium/content/browser/loader/resource_message_filter.h
@@ -71,7 +71,7 @@ class CONTENT_EXPORT ResourceMessageFilter
base::WeakPtr<ResourceMessageFilter> GetWeakPtr();
- void CreateLoaderAndStart(mojom::URLLoaderAssociatedRequest request,
+ void CreateLoaderAndStart(mojom::URLLoaderRequest request,
int32_t routing_id,
int32_t request_id,
uint32_t options,
@@ -79,11 +79,8 @@ class CONTENT_EXPORT ResourceMessageFilter
mojom::URLLoaderClientPtr client,
const net::MutableNetworkTrafficAnnotationTag&
traffic_annotation) override;
+ void Clone(mojom::URLLoaderFactoryRequest request) override;
- void SyncLoad(int32_t routing_id,
- int32_t request_id,
- const ResourceRequest& request,
- SyncLoadCallback callback) override;
int child_id() const;
ResourceRequesterInfo* requester_info_for_test() {
@@ -104,6 +101,11 @@ class CONTENT_EXPORT ResourceMessageFilter
bool is_channel_closed_;
scoped_refptr<ResourceRequesterInfo> requester_info_;
+ // An additional set of non-associated bindings (beyond those held by the
+ // BrowserAssociatedInterface parent class) of pipes to this object's
+ // URLLoaderFactory interface.
+ mojo::BindingSet<mojom::URLLoaderFactory> bindings_;
+
// 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 f81f45fef4b..2de58a10e89 100644
--- a/chromium/content/browser/loader/resource_request_info_impl.cc
+++ b/chromium/content/browser/loader/resource_request_info_impl.cc
@@ -27,6 +27,9 @@ int FrameTreeNodeIdFromHostIds(int render_process_host_id,
return render_frame_host ? render_frame_host->GetFrameTreeNodeId() : -1;
}
+// static
+const void* const kResourceRequestInfoImplKey = &kResourceRequestInfoImplKey;
+
} // namespace
// ----------------------------------------------------------------------------
@@ -116,7 +119,8 @@ bool ResourceRequestInfo::OriginatedFromServiceWorker(
// static
ResourceRequestInfoImpl* ResourceRequestInfoImpl::ForRequest(
net::URLRequest* request) {
- return static_cast<ResourceRequestInfoImpl*>(request->GetUserData(NULL));
+ return static_cast<ResourceRequestInfoImpl*>(
+ request->GetUserData(kResourceRequestInfoImplKey));
}
// static
@@ -169,7 +173,6 @@ ResourceRequestInfoImpl::ResourceRequestInfoImpl(
enable_load_timing_(enable_load_timing),
enable_upload_progress_(enable_upload_progress),
do_not_prompt_for_login_(do_not_prompt_for_login),
- was_ignored_by_handler_(false),
counted_as_in_flight_request_(false),
resource_type_(resource_type),
transition_type_(transition_type),
@@ -289,10 +292,6 @@ bool ResourceRequestInfoImpl::HasUserGesture() const {
return has_user_gesture_;
}
-bool ResourceRequestInfoImpl::WasIgnoredByHandler() const {
- return was_ignored_by_handler_;
-}
-
bool ResourceRequestInfoImpl::GetAssociatedRenderFrame(
int* render_process_id,
int* render_frame_id) const {
@@ -322,7 +321,7 @@ NavigationUIData* ResourceRequestInfoImpl::GetNavigationUIData() const {
}
void ResourceRequestInfoImpl::AssociateWithRequest(net::URLRequest* request) {
- request->SetUserData(nullptr, base::WrapUnique(this));
+ request->SetUserData(kResourceRequestInfoImplKey, base::WrapUnique(this));
int render_process_id;
int render_frame_id;
if (GetAssociatedRenderFrame(&render_process_id, &render_frame_id)) {
@@ -346,7 +345,7 @@ void ResourceRequestInfoImpl::UpdateForTransfer(
int origin_pid,
int request_id,
ResourceRequesterInfo* requester_info,
- mojom::URLLoaderAssociatedRequest url_loader_request,
+ mojom::URLLoaderRequest url_loader_request,
mojom::URLLoaderClientPtr url_loader_client) {
route_id_ = route_id;
render_frame_id_ = render_frame_id;
diff --git a/chromium/content/browser/loader/resource_request_info_impl.h b/chromium/content/browser/loader/resource_request_info_impl.h
index a306acb03c8..56d24b39e8b 100644
--- a/chromium/content/browser/loader/resource_request_info_impl.h
+++ b/chromium/content/browser/loader/resource_request_info_impl.h
@@ -37,8 +37,7 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo,
public base::SupportsUserData::Data {
public:
using TransferCallback =
- base::Callback<void(mojom::URLLoaderAssociatedRequest,
- mojom::URLLoaderClientPtr)>;
+ base::Callback<void(mojom::URLLoaderRequest, mojom::URLLoaderClientPtr)>;
// Returns the ResourceRequestInfoImpl associated with the given URLRequest.
CONTENT_EXPORT static ResourceRequestInfoImpl* ForRequest(
@@ -95,7 +94,6 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo,
blink::WebPageVisibilityState GetVisibilityState() const override;
ui::PageTransition GetPageTransition() const override;
bool HasUserGesture() const override;
- bool WasIgnoredByHandler() const override;
bool GetAssociatedRenderFrame(int* render_process_id,
int* render_frame_id) const override;
bool IsAsync() const override;
@@ -128,7 +126,7 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo,
int origin_pid,
int request_id,
ResourceRequesterInfo* requester_info,
- mojom::URLLoaderAssociatedRequest url_loader_request,
+ mojom::URLLoaderRequest url_loader_request,
mojom::URLLoaderClientPtr url_loader_client);
// Whether this request is part of a navigation that should replace the
@@ -156,10 +154,6 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo,
bool is_stream() const { return is_stream_; }
void set_is_stream(bool stream) { is_stream_ = stream; }
- void set_was_ignored_by_handler(bool value) {
- was_ignored_by_handler_ = value;
- }
-
// Whether this request has been counted towards the number of in flight
// requests, which is only true for requests that require a file descriptor
// for their shared memory buffer.
@@ -229,7 +223,6 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo,
bool enable_load_timing_;
bool enable_upload_progress_;
bool do_not_prompt_for_login_;
- bool was_ignored_by_handler_;
bool counted_as_in_flight_request_;
ResourceType resource_type_;
ui::PageTransition transition_type_;
diff --git a/chromium/content/browser/loader/resource_scheduler.cc b/chromium/content/browser/loader/resource_scheduler.cc
index f2b329fc159..4294b4de36e 100644
--- a/chromium/content/browser/loader/resource_scheduler.cc
+++ b/chromium/content/browser/loader/resource_scheduler.cc
@@ -6,20 +6,20 @@
#include <stdint.h>
-#include <set>
#include <string>
#include <utility>
-#include <vector>
-#include "base/feature_list.h"
+#include "base/bind.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/field_trial_params.h"
#include "base/metrics/histogram_macros.h"
+#include "base/optional.h"
+#include "base/sequenced_task_runner.h"
#include "base/stl_util.h"
+#include "base/strings/string_number_conversions.h"
#include "base/supports_user_data.h"
-#include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/trace_event.h"
#include "content/common/resource_messages.h"
#include "content/public/browser/resource_request_info.h"
@@ -28,6 +28,7 @@
#include "net/base/load_flags.h"
#include "net/base/request_priority.h"
#include "net/http/http_server_properties.h"
+#include "net/nqe/network_quality_estimator.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_context.h"
#include "url/scheme_host_port.h"
@@ -38,10 +39,18 @@ namespace {
// When kPrioritySupportedRequestsDelayable is enabled, requests for
// H2/QUIC/SPDY resources can be delayed by the ResourceScheduler just as
-// HTTP/1.1 resources are. Disabling this appears to have negative performance
-// impact, see https://crbug.com/655585.
+// HTTP/1.1 resources are. It has good impact on performance, but breaks
+// expected behavior of H2. See intent-to-unship:
+// https://groups.google.com/a/chromium.org/forum/#!topic/blink-
+// dev/ChqGX8UyHz8. We're keeping it around for finch trials to compare
+// alternatives to.
const base::Feature kPrioritySupportedRequestsDelayable{
- "PrioritySupportedRequestsDelayable", base::FEATURE_ENABLED_BY_DEFAULT};
+ "PrioritySupportedRequestsDelayable", base::FEATURE_DISABLED_BY_DEFAULT};
+
+// When enabled, low-priority H2 and QUIC requests are throttled, but only
+// when the parser is in head.
+const base::Feature kHeadPrioritySupportedRequestsDelayable{
+ "HeadPriorityRequestsDelayable", base::FEATURE_DISABLED_BY_DEFAULT};
// In the event that many resource requests are started quickly, this feature
// will periodically yield (e.g., delaying starting of requests) by posting a
@@ -52,6 +61,21 @@ const base::Feature kNetworkSchedulerYielding{
"NetworkSchedulerYielding", base::FEATURE_DISABLED_BY_DEFAULT};
const char kMaxRequestsBeforeYieldingParam[] = "MaxRequestsBeforeYieldingParam";
const int kMaxRequestsBeforeYieldingDefault = 5;
+const char kYieldMsParam[] = "MaxYieldMs";
+const int kYieldMsDefault = 0;
+
+// Based on the field trial parameters, this feature will override the value of
+// the maximum number of delayable requests allowed in flight. The number of
+// delayable requests allowed in flight will be based on the BDP ranges and the
+// corresponding number of delayable requests in flight specified in the
+// experiment configuration. Based on field trial parameters, this experiment
+// may also throttle delayable requests based on the number of non-delayable
+// requests in-flight times a weighting factor. The experiment is enabled only
+// when the effective connection type is strictly greater than
+// net::EFFECTIVE_CONNECTION_TYPE_OFFLINE and less than or equal to the maximum
+// effective connection type in the configuration.
+const base::Feature kThrottleDelayble{"ThrottleDelayable",
+ base::FEATURE_DISABLED_BY_DEFAULT};
enum StartMode {
START_SYNC,
@@ -105,7 +129,7 @@ const char* RequestStartTriggerString(RequestStartTrigger trigger) {
// The maximum number of delayable requests to allow to be in-flight at any
// point in time (across all hosts).
-static const size_t kMaxNumDelayableRequestsPerClient = 10;
+static const size_t kDefaultMaxNumDelayableRequestsPerClient = 10;
// The maximum number of requests to allow be in-flight at any point in time per
// host.
@@ -271,11 +295,10 @@ class ResourceScheduler::ScheduledResourceRequest : public ResourceThrottle {
// If can't start the request synchronously, post a task to start the
// request.
if (start_mode == START_ASYNC) {
- base::ThreadTaskRunnerHandle::Get()->PostTask(
+ scheduler_->task_runner()->PostTask(
FROM_HERE,
- base::Bind(&ScheduledResourceRequest::Start,
- weak_ptr_factory_.GetWeakPtr(),
- START_SYNC));
+ base::BindOnce(&ScheduledResourceRequest::Start,
+ weak_ptr_factory_.GetWeakPtr(), START_SYNC));
return;
}
deferred_ = false;
@@ -385,25 +408,26 @@ void ResourceScheduler::RequestQueue::Insert(
// Each client represents a tab.
class ResourceScheduler::Client {
public:
- Client(bool priority_requests_delayable,
- bool yielding_scheduler_enabled,
- int max_requests_before_yielding)
+ Client(const net::NetworkQualityEstimator* const network_quality_estimator,
+ ResourceScheduler* resource_scheduler)
: is_loaded_(false),
has_html_body_(false),
using_spdy_proxy_(false),
in_flight_delayable_count_(0),
total_layout_blocking_count_(0),
- priority_requests_delayable_(priority_requests_delayable),
num_skipped_scans_due_to_scheduled_start_(0),
started_requests_since_yielding_(0),
did_scheduler_yield_(false),
- yielding_scheduler_enabled_(yielding_scheduler_enabled),
- max_requests_before_yielding_(max_requests_before_yielding),
+ network_quality_estimator_(network_quality_estimator),
+ max_delayable_requests_(
+ resource_scheduler->throttle_delayable_.GetMaxDelayableRequests(
+ network_quality_estimator)),
+ resource_scheduler_(resource_scheduler),
weak_ptr_factory_(this) {}
~Client() {}
- void ScheduleRequest(net::URLRequest* url_request,
+ void ScheduleRequest(const net::URLRequest& url_request,
ScheduledResourceRequest* request) {
SetRequestAttributes(request, DetermineRequestAttributes(request));
ShouldStartReqResult should_start = ShouldStartRequest(request);
@@ -465,6 +489,9 @@ class ResourceScheduler::Client {
void OnNavigate() {
has_html_body_ = false;
is_loaded_ = false;
+ max_delayable_requests_ =
+ resource_scheduler_->throttle_delayable_.GetMaxDelayableRequests(
+ network_quality_estimator_);
}
void OnWillInsertBody() {
@@ -645,7 +672,9 @@ class ResourceScheduler::Client {
attributes |= kAttributeLayoutBlocking;
} else if (request->url_request()->priority() <
kDelayablePriorityThreshold) {
- if (priority_requests_delayable_) {
+ if (resource_scheduler_->priority_requests_delayable() ||
+ (resource_scheduler_->head_priority_requests_delayable() &&
+ !has_html_body_)) {
// Resources below the delayable priority threshold that are considered
// delayable.
attributes |= kAttributeDelayable;
@@ -681,15 +710,19 @@ class ResourceScheduler::Client {
void StartRequest(ScheduledResourceRequest* request,
StartMode start_mode,
RequestStartTrigger trigger) {
- started_requests_since_yielding_ += 1;
- if (started_requests_since_yielding_ == 1) {
- // This is the first started request since last yielding. Post a task to
- // reset the counter and start any yielded tasks if necessary. We post
- // this now instead of when we first yield so that if there is a pause
- // between requests the counter is reset.
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::Bind(&Client::ResumeIfYielded, weak_ptr_factory_.GetWeakPtr()));
+ if (resource_scheduler_->yielding_scheduler_enabled()) {
+ started_requests_since_yielding_ += 1;
+ if (started_requests_since_yielding_ == 1) {
+ // This is the first started request since last yielding. Post a task to
+ // reset the counter and start any yielded tasks if necessary. We post
+ // this now instead of when we first yield so that if there is a pause
+ // between requests the counter is reset.
+ resource_scheduler_->task_runner()->PostDelayedTask(
+ FROM_HERE,
+ base::BindOnce(&Client::ResumeIfYielded,
+ weak_ptr_factory_.GetWeakPtr()),
+ resource_scheduler_->yield_time());
+ }
}
// Only log on requests that were blocked by the ResourceScheduler.
@@ -700,6 +733,13 @@ class ResourceScheduler::Client {
net::NetLog::StringCallback(
"trigger", RequestStartTriggerString(trigger)));
}
+ // Record the number of delayable requests in-flight when a non-delayable
+ // request starts.
+ if (!RequestAttributesAreSet(request->attributes(), kAttributeDelayable)) {
+ UMA_HISTOGRAM_COUNTS_100(
+ "ResourceScheduler.NumDelayableRequestsInFlightAtStart.NonDelayable",
+ in_flight_delayable_count_);
+ }
InsertInFlightRequest(request);
request->Start(start_mode);
}
@@ -753,28 +793,40 @@ class ResourceScheduler::Client {
const net::HostPortPair& host_port_pair = request->host_port_pair();
- if (!priority_requests_delayable_) {
+ bool priority_delayable =
+ resource_scheduler_->priority_requests_delayable() ||
+ (resource_scheduler_->head_priority_requests_delayable() &&
+ !has_html_body_);
+
+ if (!priority_delayable) {
if (using_spdy_proxy_ && url_request.url().SchemeIs(url::kHttpScheme))
- return ShouldStartOrYieldRequest();
+ return ShouldStartOrYieldRequest(request);
url::SchemeHostPort scheme_host_port(url_request.url());
net::HttpServerProperties& http_server_properties =
*url_request.context()->http_server_properties();
-
// TODO(willchan): We should really improve this algorithm as described in
// crbug.com/164101. Also, theoretically we should not count a
// request-priority capable request against the delayable requests limit.
if (http_server_properties.SupportsRequestPriority(scheme_host_port))
- return ShouldStartOrYieldRequest();
+ return ShouldStartOrYieldRequest(request);
}
// Non-delayable requests.
if (!RequestAttributesAreSet(request->attributes(), kAttributeDelayable))
- return ShouldStartOrYieldRequest();
+ return START_REQUEST;
- if (in_flight_delayable_count_ >= kMaxNumDelayableRequestsPerClient)
+ // Delayable requests.
+ DCHECK_GE(in_flight_requests_.size(), in_flight_delayable_count_);
+ size_t num_non_delayable_requests_weighted = static_cast<size_t>(
+ resource_scheduler_->throttle_delayable_.GetCurrentNonDelayableWeight(
+ network_quality_estimator_) *
+ (in_flight_requests_.size() - in_flight_delayable_count_));
+ if ((in_flight_delayable_count_ + num_non_delayable_requests_weighted >=
+ max_delayable_requests_)) {
return DO_NOT_START_REQUEST_AND_STOP_SEARCHING;
+ }
if (ShouldKeepSearching(host_port_pair)) {
// There may be other requests for other hosts that may be allowed,
@@ -806,7 +858,7 @@ class ResourceScheduler::Client {
}
}
- return ShouldStartOrYieldRequest();
+ return START_REQUEST;
}
// It is common for a burst of messages to come from the renderer which
@@ -821,10 +873,9 @@ class ResourceScheduler::Client {
void ScheduleLoadAnyStartablePendingRequests(RequestStartTrigger trigger) {
if (num_skipped_scans_due_to_scheduled_start_ == 0) {
TRACE_EVENT0("loading", "ScheduleLoadAnyStartablePendingRequests");
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::Bind(&Client::LoadAnyStartablePendingRequests,
- weak_ptr_factory_.GetWeakPtr(), trigger));
+ resource_scheduler_->task_runner()->PostTask(
+ FROM_HERE, base::BindOnce(&Client::LoadAnyStartablePendingRequests,
+ weak_ptr_factory_.GetWeakPtr(), trigger));
}
num_skipped_scans_due_to_scheduled_start_ += 1;
}
@@ -840,11 +891,18 @@ class ResourceScheduler::Client {
// For a request that is ready to start, return START_REQUEST if the
// scheduler doesn't need to yield, else YIELD_SCHEDULER.
- ShouldStartReqResult ShouldStartOrYieldRequest() const {
+ ShouldStartReqResult ShouldStartOrYieldRequest(
+ ScheduledResourceRequest* request) const {
DCHECK_GE(started_requests_since_yielding_, 0);
- if (!yielding_scheduler_enabled_ ||
- started_requests_since_yielding_ < max_requests_before_yielding_) {
+ // Don't yield if:
+ // 1. The yielding scheduler isn't enabled
+ // 2. The resource is high priority
+ // 3. There haven't been enough recent requests to warrant yielding.
+ if (!resource_scheduler_->yielding_scheduler_enabled() ||
+ request->url_request()->priority() >= kDelayablePriorityThreshold ||
+ started_requests_since_yielding_ <
+ resource_scheduler_->max_requests_before_yielding()) {
return START_REQUEST;
}
return YIELD_SCHEDULER;
@@ -908,10 +966,6 @@ class ResourceScheduler::Client {
// The number of layout-blocking in-flight requests.
size_t total_layout_blocking_count_;
- // True if requests to servers that support priorities (e.g., H2/QUIC) can
- // be delayed.
- bool priority_requests_delayable_;
-
// The number of LoadAnyStartablePendingRequests scans that were skipped due
// to smarter task scheduling around reprioritization.
int num_skipped_scans_due_to_scheduled_start_;
@@ -924,11 +978,17 @@ class ResourceScheduler::Client {
// ResumeIfYielded task was run.
bool did_scheduler_yield_;
- // Whether or not to periodically yield when starting lots of requests.
- bool yielding_scheduler_enabled_;
+ // Network quality estimator for network aware resource scheudling. This may
+ // be null.
+ const net::NetworkQualityEstimator* const network_quality_estimator_;
+
+ // The value of the maximum number of delayable requests in flight. This gets
+ // recalculated every time an |OnNavigate| event is triggered.
+ size_t max_delayable_requests_;
- // The number of requests that can start before yielding.
- int max_requests_before_yielding_;
+ // A pointer to the resource scheduler which contains the resource scheduling
+ // configuration.
+ ResourceScheduler* resource_scheduler_;
base::WeakPtrFactory<ResourceScheduler::Client> weak_ptr_factory_;
};
@@ -936,12 +996,23 @@ class ResourceScheduler::Client {
ResourceScheduler::ResourceScheduler()
: priority_requests_delayable_(
base::FeatureList::IsEnabled(kPrioritySupportedRequestsDelayable)),
+ head_priority_requests_delayable_(base::FeatureList::IsEnabled(
+ kHeadPrioritySupportedRequestsDelayable)),
yielding_scheduler_enabled_(
base::FeatureList::IsEnabled(kNetworkSchedulerYielding)),
max_requests_before_yielding_(base::GetFieldTrialParamByFeatureAsInt(
kNetworkSchedulerYielding,
kMaxRequestsBeforeYieldingParam,
- kMaxRequestsBeforeYieldingDefault)) {}
+ kMaxRequestsBeforeYieldingDefault)),
+ yield_time_(base::TimeDelta::FromMilliseconds(
+ base::GetFieldTrialParamByFeatureAsInt(kNetworkSchedulerYielding,
+ kYieldMsParam,
+ kYieldMsDefault))),
+ task_runner_(base::ThreadTaskRunnerHandle::Get()) {
+ // Don't run the two experiments together.
+ if (priority_requests_delayable_ && head_priority_requests_delayable_)
+ priority_requests_delayable_ = false;
+}
ResourceScheduler::~ResourceScheduler() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@@ -973,7 +1044,7 @@ std::unique_ptr<ResourceThrottle> ResourceScheduler::ScheduleRequest(
}
Client* client = it->second;
- client->ScheduleRequest(url_request, request.get());
+ client->ScheduleRequest(*url_request, request.get());
return std::move(request);
}
@@ -993,15 +1064,16 @@ void ResourceScheduler::RemoveRequest(ScheduledResourceRequest* request) {
client->RemoveRequest(request);
}
-void ResourceScheduler::OnClientCreated(int child_id,
- int route_id) {
+void ResourceScheduler::OnClientCreated(
+ int child_id,
+ int route_id,
+ const net::NetworkQualityEstimator* const network_quality_estimator) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
ClientId client_id = MakeClientId(child_id, route_id);
DCHECK(!base::ContainsKey(client_map_, client_id));
- Client* client =
- new Client(priority_requests_delayable_, yielding_scheduler_enabled_,
- max_requests_before_yielding_);
+ Client* client = new Client(
+ network_quality_estimator, this);
client_map_[client_id] = client;
}
@@ -1150,4 +1222,101 @@ ResourceScheduler::ClientId ResourceScheduler::MakeClientId(
return (static_cast<ResourceScheduler::ClientId>(child_id) << 32) | route_id;
}
+ResourceScheduler::ThrottleDelayble::ThrottleDelayble()
+ : max_requests_for_bdp_ranges_(GetMaxRequestsForBDPRanges()),
+ max_effective_connection_type_(
+ net::GetEffectiveConnectionTypeForName(
+ base::GetFieldTrialParamValueByFeature(
+ kThrottleDelayble,
+ "MaxEffectiveConnectionType"))
+ .value_or(net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN)),
+ non_delayable_weight_(
+ base::GetFieldTrialParamByFeatureAsDouble(kThrottleDelayble,
+ "NonDelayableWeight",
+ 0.0)) {}
+
+ResourceScheduler::ThrottleDelayble::~ThrottleDelayble() {}
+
+size_t ResourceScheduler::ThrottleDelayble::GetMaxDelayableRequests(
+ const net::NetworkQualityEstimator* network_quality_estimator) const {
+ if (max_requests_for_bdp_ranges_.empty() || !network_quality_estimator)
+ return kDefaultMaxNumDelayableRequestsPerClient;
+
+ if (network_quality_estimator->GetEffectiveConnectionType() >
+ max_effective_connection_type_ ||
+ network_quality_estimator->GetEffectiveConnectionType() <=
+ net::EFFECTIVE_CONNECTION_TYPE_OFFLINE) {
+ return kDefaultMaxNumDelayableRequestsPerClient;
+ }
+
+ base::Optional<int32_t> bdp_kbits =
+ network_quality_estimator->GetBandwidthDelayProductKbits();
+ if (!bdp_kbits)
+ return kDefaultMaxNumDelayableRequestsPerClient;
+
+ for (const auto& range : max_requests_for_bdp_ranges_) {
+ if (bdp_kbits.value() <= range.max_bdp_kbits)
+ return range.max_requests;
+ }
+ return kDefaultMaxNumDelayableRequestsPerClient;
+}
+
+double ResourceScheduler::ThrottleDelayble::GetCurrentNonDelayableWeight(
+ const net::NetworkQualityEstimator* network_quality_estimator) const {
+ if (!network_quality_estimator) {
+ // Fall back to default behavior by setting the weight of non-delayable
+ // requests to 0 when |network_quality_estimator| is not set.
+ return 0.0;
+ }
+ net::EffectiveConnectionType effective_connection_type =
+ network_quality_estimator->GetEffectiveConnectionType();
+ if (effective_connection_type > max_effective_connection_type_ ||
+ effective_connection_type <= net::EFFECTIVE_CONNECTION_TYPE_OFFLINE) {
+ // If the effective connection type is detected as offline or unknown, or
+ // strictly better than the maximum effective connection type set in the
+ // experiment parameters, fall back to the default behavior.
+ return 0.0;
+ }
+ return non_delayable_weight_;
+}
+
+ResourceScheduler::MaxRequestsForBDPRanges
+ResourceScheduler::ThrottleDelayble::GetMaxRequestsForBDPRanges() {
+ const char max_bdp_kbits_base[] = "MaxBDPKbits";
+ const char max_delayable_requests_base[] = "MaxDelayableRequests";
+
+ MaxRequestsForBDPRanges result;
+ if (!base::FeatureList::IsEnabled(kThrottleDelayble))
+ return result;
+
+ int config_param_index = 1;
+ while (true) {
+ int64_t max_bdp_kbits;
+ size_t max_delayable_requests;
+
+ if (!base::StringToInt64(
+ base::GetFieldTrialParamValueByFeature(
+ kThrottleDelayble,
+ max_bdp_kbits_base + base::IntToString(config_param_index)),
+ &max_bdp_kbits)) {
+ DCHECK_LE(result.size(), 20u);
+ return result;
+ }
+ if (!base::StringToSizeT(
+ base::GetFieldTrialParamValueByFeature(
+ kThrottleDelayble, max_delayable_requests_base +
+ base::IntToString(config_param_index)),
+ &max_delayable_requests)) {
+ DCHECK_LE(result.size(), 20u);
+ return result;
+ }
+ // Check that the previous bandwidth delay product is strictly less than the
+ // current bandwidth delay product.
+ DCHECK(result.empty() || result.back().max_bdp_kbits < max_bdp_kbits);
+ result.push_back({max_bdp_kbits, max_delayable_requests});
+ config_param_index++;
+ }
+}
+
+
} // namespace content
diff --git a/chromium/content/browser/loader/resource_scheduler.h b/chromium/content/browser/loader/resource_scheduler.h
index 9e112298297..fdae21406d4 100644
--- a/chromium/content/browser/loader/resource_scheduler.h
+++ b/chromium/content/browser/loader/resource_scheduler.h
@@ -11,19 +11,31 @@
#include <map>
#include <memory>
#include <set>
+#include <utility>
+#include <vector>
#include "base/compiler_specific.h"
+#include "base/feature_list.h"
#include "base/macros.h"
+#include "base/memory/ref_counted.h"
#include "base/sequence_checker.h"
+#include "base/time/time.h"
#include "content/common/content_export.h"
#include "net/base/priority_queue.h"
#include "net/base/request_priority.h"
+#include "net/nqe/effective_connection_type.h"
+
+namespace base {
+class SequencedTaskRunner;
+}
namespace net {
class URLRequest;
+class NetworkQualityEstimator;
}
namespace content {
+
class ResourceThrottle;
// There is one ResourceScheduler. All renderer-initiated HTTP requests are
@@ -54,6 +66,15 @@ class ResourceThrottle;
// the URLRequest.
class CONTENT_EXPORT ResourceScheduler {
public:
+ // A struct that stores a bandwidth delay product (BDP) and the maximum number
+ // of delayable requests when the observed BDP is below (inclusive) the
+ // specified BDP.
+ struct MaxRequestsForBDPRange {
+ int64_t max_bdp_kbits;
+ size_t max_requests;
+ };
+ typedef std::vector<MaxRequestsForBDPRange> MaxRequestsForBDPRanges;
+
ResourceScheduler();
~ResourceScheduler();
@@ -68,8 +89,12 @@ class CONTENT_EXPORT ResourceScheduler {
// Signals from the UI thread, posted as tasks on the IO thread:
- // Called when a renderer is created.
- void OnClientCreated(int child_id, int route_id);
+ // Called when a renderer is created. |network_quality_estimator| is allowed
+ // to be null.
+ void OnClientCreated(
+ int child_id,
+ int route_id,
+ const net::NetworkQualityEstimator* const network_quality_estimator);
// Called when a renderer is destroyed.
void OnClientDeleted(int child_id, int route_id);
@@ -108,7 +133,42 @@ class CONTENT_EXPORT ResourceScheduler {
void ReprioritizeRequest(net::URLRequest* request,
net::RequestPriority new_priority);
+ // Public for tests.
+ static MaxRequestsForBDPRanges
+ GetMaxDelayableRequestsExperimentConfigForTests() {
+ return ThrottleDelayble::GetMaxRequestsForBDPRanges();
+ }
+
+ bool priority_requests_delayable() const {
+ return priority_requests_delayable_;
+ }
+ bool head_priority_requests_delayable() const {
+ return head_priority_requests_delayable_;
+ }
+ bool yielding_scheduler_enabled() const {
+ return yielding_scheduler_enabled_;
+ }
+ int max_requests_before_yielding() const {
+ return max_requests_before_yielding_;
+ }
+ base::TimeDelta yield_time() const { return yield_time_; }
+ base::SequencedTaskRunner* task_runner() { return task_runner_.get(); }
+
+ // Testing setters
+ void SetMaxRequestsBeforeYieldingForTesting(
+ int max_requests_before_yielding) {
+ max_requests_before_yielding_ = max_requests_before_yielding;
+ }
+ void SetYieldTimeForTesting(base::TimeDelta yield_time) {
+ yield_time_ = yield_time;
+ }
+ void SetTaskRunnerForTesting(
+ scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner) {
+ task_runner_ = std::move(sequenced_task_runner);
+ }
+
private:
+ class Client;
class RequestQueue;
class ScheduledResourceRequest;
struct RequestPriorityParams;
@@ -116,7 +176,66 @@ class CONTENT_EXPORT ResourceScheduler {
bool operator()(const ScheduledResourceRequest* a,
const ScheduledResourceRequest* b) const;
};
- class Client;
+
+ // Experiment parameters and helper functions for varying the maximum number
+ // of delayable requests in-flight based on the observed bandwidth delay
+ // product (BDP), or in the presence of non-delayable requests in-flight.
+ class ThrottleDelayble {
+ public:
+ ThrottleDelayble();
+
+ ~ThrottleDelayble();
+
+ // Returns the maximum delayable requests based on the current
+ // value of the bandwidth delay product (BDP). It falls back to the default
+ // limit on three conditions:
+ // 1. |network_quality_estimator| is null.
+ // 2. The current effective connection type is
+ // net::EFFECTIVE_CONNECTION_TYPE_OFFLINE or
+ // net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN.
+ // 3. The current value of the BDP is not in any of the ranges in
+ // |max_requests_for_bdp_ranges_|.
+ size_t GetMaxDelayableRequests(
+ const net::NetworkQualityEstimator* network_quality_estimator) const;
+
+ // This method computes the correct weight for the non-delayable requests
+ // based on the current effective connection type. If it is out of bounds,
+ // it returns 0, effectively disabling the experiment.
+ double GetCurrentNonDelayableWeight(
+ const net::NetworkQualityEstimator* network_quality_estimator) const;
+
+ private:
+ // Friend for tests.
+ friend class ResourceScheduler;
+
+ // Reads experiment parameters and creates a vector of
+ // |MaxRequestsForBDPRange| to populate |max_requests_for_bdp_ranges_|. It
+ // looks for configuration parameters with sequential numeric suffixes, and
+ // stops looking after the first failure to find an experimetal parameter.
+ // The BDP values are specified in kilobits. A sample configuration is given
+ // below:
+ // "MaxBDPKbits1": "150",
+ // "MaxDelayableRequests1": "2",
+ // "MaxBDPKbits2": "200",
+ // "MaxDelayableRequests2": "4",
+ // "MaxEffectiveConnectionType": "3G"
+ // This config implies that when BDP <= 150, then the maximum number of
+ // non-delayable requests should be limited to 2. When BDP > 150 and <= 200,
+ // it should be limited to 4. For BDP > 200, the default value should be
+ // used.
+ static MaxRequestsForBDPRanges GetMaxRequestsForBDPRanges();
+
+ // The number of delayable requests in-flight for different ranges of the
+ // bandwidth delay product (BDP).
+ const MaxRequestsForBDPRanges max_requests_for_bdp_ranges_;
+
+ // The maximum ECT for which the experiment should be enabled.
+ const net::EffectiveConnectionType max_effective_connection_type_;
+
+ // The weight of a non-delayable request when counting the effective number
+ // of non-delayable requests in-flight.
+ const double non_delayable_weight_;
+ };
typedef int64_t ClientId;
typedef std::map<ClientId, Client*> ClientMap;
@@ -138,10 +257,20 @@ class CONTENT_EXPORT ResourceScheduler {
// be delayed.
bool priority_requests_delayable_;
+ // True if requests to servers that support priorities (e.g., H2/QUIC) can
+ // be delayed while the parser is in head.
+ bool head_priority_requests_delayable_;
+
// True if the scheduler should yield between several successive calls to
// start resource requests.
bool yielding_scheduler_enabled_;
int max_requests_before_yielding_;
+ base::TimeDelta yield_time_;
+
+ const ThrottleDelayble throttle_delayable_;
+
+ // The TaskRunner to post tasks on. Can be overridden for tests.
+ scoped_refptr<base::SequencedTaskRunner> task_runner_;
SEQUENCE_CHECKER(sequence_checker_);
diff --git a/chromium/content/browser/loader/resource_scheduler_browsertest.cc b/chromium/content/browser/loader/resource_scheduler_browsertest.cc
new file mode 100644
index 00000000000..f35589b777f
--- /dev/null
+++ b/chromium/content/browser/loader/resource_scheduler_browsertest.cc
@@ -0,0 +1,90 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <map>
+#include <string>
+
+#include "base/memory/ptr_util.h"
+#include "base/metrics/field_trial.h"
+#include "base/metrics/field_trial_param_associator.h"
+#include "base/metrics/field_trial_params.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 "net/test/embedded_test_server/embedded_test_server.h"
+#include "url/gurl.h"
+
+namespace content {
+
+namespace {
+
+class ResourceSchedulerBrowserTest : public ContentBrowserTest {
+ protected:
+ ResourceSchedulerBrowserTest() : field_trial_list_(nullptr) {}
+
+ void SetUpInProcessBrowserTestFixture() override {
+ ASSERT_TRUE(embedded_test_server()->Start());
+ InitializeMaxDelayableRequestsExperiment();
+ }
+
+ void InitializeMaxDelayableRequestsExperiment() {
+ base::FieldTrialParamAssociator::GetInstance()->ClearAllParamsForTesting();
+ const char kTrialName[] = "TrialName";
+ const char kGroupName[] = "GroupName";
+ const char kMaxDelayableRequestsNetworkOverride[] =
+ "MaxDelayableRequestsNetworkOverride";
+
+ std::map<std::string, std::string> params;
+ params["MaxEffectiveConnectionType"] = "2G";
+ params["MaxBDPKbits1"] = "130";
+ params["MaxDelayableRequests1"] = "2";
+ params["MaxBDPKbits2"] = "160";
+ params["MaxDelayableRequests2"] = "4";
+
+ base::AssociateFieldTrialParams(kTrialName, kGroupName, params);
+ base::FieldTrial* field_trial =
+ base::FieldTrialList::CreateFieldTrial(kTrialName, kGroupName);
+
+ std::unique_ptr<base::FeatureList> feature_list(
+ base::MakeUnique<base::FeatureList>());
+ feature_list->RegisterFieldTrialOverride(
+ kMaxDelayableRequestsNetworkOverride,
+ base::FeatureList::OVERRIDE_ENABLE_FEATURE, field_trial);
+ feature_list_.InitWithFeatureList(std::move(feature_list));
+ }
+
+ private:
+ base::FieldTrialList field_trial_list_;
+ base::test::ScopedFeatureList feature_list_;
+};
+
+IN_PROC_BROWSER_TEST_F(ResourceSchedulerBrowserTest,
+ ResourceLoadingExperimentIncognito) {
+ GURL url(embedded_test_server()->GetURL(
+ "/resource_loading/resource_loading_non_mobile.html"));
+
+ Shell* otr_browser = CreateOffTheRecordBrowser();
+ EXPECT_TRUE(NavigateToURL(otr_browser, url));
+ int data = -1;
+ EXPECT_TRUE(
+ ExecuteScriptAndExtractInt(otr_browser, "getResourceNumber()", &data));
+ EXPECT_EQ(9, data);
+}
+
+IN_PROC_BROWSER_TEST_F(ResourceSchedulerBrowserTest,
+ ResourceLoadingExperimentNormal) {
+ GURL url(embedded_test_server()->GetURL(
+ "/resource_loading/resource_loading_non_mobile.html"));
+ Shell* browser = shell();
+ EXPECT_TRUE(NavigateToURL(browser, url));
+ int data = -1;
+ EXPECT_TRUE(
+ ExecuteScriptAndExtractInt(browser, "getResourceNumber()", &data));
+ EXPECT_EQ(9, data);
+}
+
+} // anonymous namespace
+
+} // namespace content
diff --git a/chromium/content/browser/loader/resource_scheduler_unittest.cc b/chromium/content/browser/loader/resource_scheduler_unittest.cc
index 15b1dcc019d..38f914772d9 100644
--- a/chromium/content/browser/loader/resource_scheduler_unittest.cc
+++ b/chromium/content/browser/loader/resource_scheduler_unittest.cc
@@ -4,18 +4,24 @@
#include "content/browser/loader/resource_scheduler.h"
+#include <map>
#include <memory>
+#include <set>
+#include <string>
#include <utility>
#include <vector>
#include "base/memory/ptr_util.h"
+#include "base/memory/ref_counted.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/field_trial_param_associator.h"
+#include "base/metrics/field_trial_params.h"
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/test/histogram_tester.h"
#include "base/test/mock_entropy_provider.h"
#include "base/test/scoped_feature_list.h"
+#include "base/test/test_mock_time_task_runner.h"
#include "base/timer/mock_timer.h"
#include "base/timer/timer.h"
#include "content/public/browser/resource_context.h"
@@ -28,6 +34,8 @@
#include "net/base/host_port_pair.h"
#include "net/base/request_priority.h"
#include "net/http/http_server_properties_impl.h"
+#include "net/nqe/network_quality_estimator_test_util.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_test_util.h"
@@ -51,11 +59,38 @@ const int kRouteId2 = 67;
const int kBackgroundChildId = 35;
const int kBackgroundRouteId = 43;
+// Sync below with cc file.
const char kPrioritySupportedRequestsDelayable[] =
"PrioritySupportedRequestsDelayable";
-
+const char kHeadPrioritySupportedRequestsDelayable[] =
+ "HeadPriorityRequestsDelayable";
const char kNetworkSchedulerYielding[] = "NetworkSchedulerYielding";
-const int kMaxRequestsBeforeYielding = 5; // sync with .cc.
+const size_t kMaxNumDelayableRequestsPerHostPerClient = 6;
+
+void ConfigureYieldFieldTrial(
+ int max_requests_before_yielding,
+ int max_yield_ms,
+ base::test::ScopedFeatureList* scoped_feature_list) {
+ const std::string kTrialName = "TrialName";
+ const std::string kGroupName = "GroupName"; // Value not used
+ const std::string kNetworkSchedulerYielding = "NetworkSchedulerYielding";
+
+ scoped_refptr<base::FieldTrial> trial =
+ base::FieldTrialList::CreateFieldTrial(kTrialName, kGroupName);
+
+ std::map<std::string, std::string> params;
+ params["MaxRequestsBeforeYieldingParam"] =
+ base::IntToString(max_requests_before_yielding);
+ params["MaxYieldMs"] = base::IntToString(max_yield_ms);
+ base::FieldTrialParamAssociator::GetInstance()->AssociateFieldTrialParams(
+ kTrialName, kGroupName, params);
+
+ std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
+ feature_list->RegisterFieldTrialOverride(
+ kNetworkSchedulerYielding, base::FeatureList::OVERRIDE_ENABLE_FEATURE,
+ trial.get());
+ scoped_feature_list->InitWithFeatureList(std::move(feature_list));
+}
class TestRequest : public ResourceThrottle::Delegate {
public:
@@ -96,7 +131,6 @@ class TestRequest : public ResourceThrottle::Delegate {
protected:
// ResourceThrottle::Delegate interface:
- void CancelAndIgnore() override {}
void CancelWithError(int error_code) override {}
void Resume() override { started_ = true; }
@@ -135,9 +169,10 @@ class FakeResourceContext : public ResourceContext {
class ResourceSchedulerTest : public testing::Test {
protected:
- ResourceSchedulerTest() {
+ ResourceSchedulerTest() : field_trial_list_(nullptr) {
InitializeScheduler();
context_.set_http_server_properties(&http_server_properties_);
+ context_.set_network_quality_estimator(&network_quality_estimator_);
}
~ResourceSchedulerTest() override {
@@ -153,9 +188,10 @@ class ResourceSchedulerTest : public testing::Test {
// mock_timer_.
scheduler_.reset(new ResourceScheduler());
- scheduler_->OnClientCreated(kChildId, kRouteId);
- scheduler_->OnClientCreated(
- kBackgroundChildId, kBackgroundRouteId);
+ scheduler_->OnClientCreated(kChildId, kRouteId,
+ &network_quality_estimator_);
+ scheduler_->OnClientCreated(kBackgroundChildId, kBackgroundRouteId,
+ &network_quality_estimator_);
}
void CleanupScheduler() {
@@ -171,7 +207,7 @@ class ResourceSchedulerTest : public testing::Test {
int child_id,
int route_id) {
std::unique_ptr<net::URLRequest> url_request(context_.CreateRequest(
- GURL(url), priority, NULL, TRAFFIC_ANNOTATION_FOR_TESTS));
+ GURL(url), priority, nullptr, TRAFFIC_ANNOTATION_FOR_TESTS));
return url_request;
}
@@ -254,6 +290,193 @@ class ResourceSchedulerTest : public testing::Test {
mock_timer_->Fire();
}
+ void RequestLimitOverrideConfigTestHelper(bool experiment_status) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ InitializeThrottleDelayableExperiment(&scoped_feature_list,
+ experiment_status, 0.0);
+
+ // Set BDP to 120 kbits, which lies in the first configuration bucket. Set
+ // the effective connection type to Slow-2G, which is slower than the
+ // threshold configured in |InitializeMaxDelayableRequestsExperiment|. Needs
+ // to be done before initializing the scheduler because the client is
+ // created on the call to |InitializeScheduler|, which is where the initial
+ // limits for the delayable requests in flight are computed.
+ network_quality_estimator_.set_bandwidth_delay_product_kbits(120);
+ network_quality_estimator_.set_effective_connection_type(
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G);
+ // Initialize the scheduler.
+ InitializeScheduler();
+
+ // For 2G, the typical values of RTT and bandwidth should result in the
+ // override taking effect with the experiment enabled. For this case, the
+ // new limit is 2. The limit will matter only once the page has a body,
+ // since delayable requests are not loaded before that.
+ scheduler()->OnWillInsertBody(kChildId, kRouteId);
+
+ // Throw in one high priority request to ensure that it does not matter once
+ // a body exists.
+ std::unique_ptr<TestRequest> high2(
+ NewRequest("http://host/high2", net::HIGHEST));
+ EXPECT_TRUE(high2->started());
+
+ // Should match the configuration set by
+ // |InitializeMaxDelayableRequestsExperiment|
+ const int kOverriddenNumRequests = 2;
+
+ std::vector<std::unique_ptr<TestRequest>> lows_singlehost;
+ // Queue the maximum number of delayable requests that should be started
+ // before the resource scheduler starts throttling delayable requests.
+ for (int i = 0; i < kOverriddenNumRequests; ++i) {
+ std::string url = "http://host/low" + base::IntToString(i);
+ lows_singlehost.push_back(NewRequest(url.c_str(), net::LOWEST));
+ EXPECT_TRUE(lows_singlehost[i]->started());
+ }
+
+ std::unique_ptr<TestRequest> second_last_singlehost(
+ NewRequest("http://host/s_last", net::LOWEST));
+ std::unique_ptr<TestRequest> last_singlehost(
+ NewRequest("http://host/last", net::LOWEST));
+
+ if (experiment_status) {
+ // Experiment enabled, hence requests should be limited.
+ // Second last should not start because there are |kOverridenNumRequests|
+ // delayable requests already in-flight.
+ EXPECT_FALSE(second_last_singlehost->started());
+
+ // Completion of a delayable request must result in starting of the
+ // second-last request.
+ lows_singlehost.erase(lows_singlehost.begin());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(second_last_singlehost->started());
+ EXPECT_FALSE(last_singlehost->started());
+
+ // Completion of another delayable request must result in starting of the
+ // last request.
+ lows_singlehost.erase(lows_singlehost.begin());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(last_singlehost->started());
+ } else {
+ // Requests should start because the default limit is 10.
+ EXPECT_TRUE(second_last_singlehost->started());
+ EXPECT_TRUE(last_singlehost->started());
+ }
+ }
+
+ void InitializeThrottleDelayableExperiment(
+ base::test::ScopedFeatureList* scoped_feature_list,
+ bool lower_delayable_count_enabled,
+ double non_delayable_weight) {
+ std::map<std::string, std::string> params;
+ bool experiment_enabled = false;
+ if (lower_delayable_count_enabled) {
+ experiment_enabled = true;
+ params["MaxEffectiveConnectionType"] = "2G";
+ params["MaxBDPKbits1"] = "130";
+ params["MaxDelayableRequests1"] = "2";
+ params["MaxBDPKbits2"] = "160";
+ params["MaxDelayableRequests2"] = "4";
+ }
+
+ if (non_delayable_weight > 0.0) {
+ experiment_enabled = true;
+ params["MaxEffectiveConnectionType"] = "2G";
+ params["NonDelayableWeight"] = base::DoubleToString(non_delayable_weight);
+ }
+
+ base::FieldTrialParamAssociator::GetInstance()->ClearAllParamsForTesting();
+ const char kTrialName[] = "TrialName";
+ const char kGroupName[] = "GroupName";
+
+ ASSERT_TRUE(
+ base::AssociateFieldTrialParams(kTrialName, kGroupName, params));
+ base::FieldTrial* field_trial =
+ base::FieldTrialList::CreateFieldTrial(kTrialName, kGroupName);
+ ASSERT_TRUE(field_trial);
+
+ std::unique_ptr<base::FeatureList> feature_list(
+ base::MakeUnique<base::FeatureList>());
+ feature_list->RegisterFieldTrialOverride(
+ "ThrottleDelayable",
+ experiment_enabled ? base::FeatureList::OVERRIDE_ENABLE_FEATURE
+ : base::FeatureList::OVERRIDE_DISABLE_FEATURE,
+ field_trial);
+ scoped_feature_list->InitWithFeatureList(std::move(feature_list));
+ }
+
+ void ReadConfigTestHelper(size_t num_bdp_ranges,
+ const std::string& max_ect_string) {
+ base::FieldTrialParamAssociator::GetInstance()->ClearAllParamsForTesting();
+ const char kTrialName[] = "TrialName";
+ const char kGroupName[] = "GroupName";
+ const char kThrottleDelayable[] = "ThrottleDelayable";
+
+ base::FieldTrialParamAssociator::GetInstance()->ClearAllParamsForTesting();
+ base::test::ScopedFeatureList scoped_feature_list;
+ std::map<std::string, std::string> params;
+ params["MaxEffectiveConnectionType"] = max_ect_string;
+ for (size_t bdp_range_index = 1; bdp_range_index <= num_bdp_ranges;
+ bdp_range_index++) {
+ std::string index_str = base::SizeTToString(bdp_range_index);
+ params["MaxBDPKbits" + index_str] = index_str + "00";
+ params["MaxDelayableRequests" + index_str] = index_str + "0";
+ }
+
+ base::AssociateFieldTrialParams(kTrialName, kGroupName, params);
+ base::FieldTrial* field_trial =
+ base::FieldTrialList::CreateFieldTrial(kTrialName, kGroupName);
+ std::unique_ptr<base::FeatureList> feature_list(
+ base::MakeUnique<base::FeatureList>());
+ feature_list->RegisterFieldTrialOverride(
+ kThrottleDelayable, base::FeatureList::OVERRIDE_ENABLE_FEATURE,
+ field_trial);
+ scoped_feature_list.InitWithFeatureList(std::move(feature_list));
+
+ ResourceScheduler::MaxRequestsForBDPRanges bdp_ranges =
+ ResourceScheduler::GetMaxDelayableRequestsExperimentConfigForTests();
+
+ // Check that the configuration was parsed and stored correctly.
+ ASSERT_EQ(bdp_ranges.size(), num_bdp_ranges);
+ for (size_t bdp_range_index = 1; bdp_range_index <= num_bdp_ranges;
+ bdp_range_index++) {
+ EXPECT_EQ(bdp_ranges[bdp_range_index - 1].max_bdp_kbits,
+ (int64_t)(bdp_range_index * 100));
+ EXPECT_EQ(bdp_ranges[bdp_range_index - 1].max_requests,
+ bdp_range_index * 10u);
+ }
+ }
+
+ void NonDelayableThrottlesDelayableHelper(double non_delayable_weight) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ // Should be in sync with .cc.
+ const int kDefaultMaxNumDelayableRequestsPerClient = 10;
+ // Initialize the experiment.
+ InitializeThrottleDelayableExperiment(&scoped_feature_list, false,
+ non_delayable_weight);
+ network_quality_estimator_.set_effective_connection_type(
+ net::EFFECTIVE_CONNECTION_TYPE_2G);
+
+ InitializeScheduler();
+ // Limit will only trigger after the page has a body.
+ scheduler()->OnWillInsertBody(kChildId, kRouteId);
+ // Start one non-delayable request.
+ std::unique_ptr<TestRequest> non_delayable_request(
+ NewRequest("http://host/medium", net::MEDIUM));
+ // Start |kDefaultMaxNumDelayableRequestsPerClient - 1 *
+ // |non_delayable_weight| delayable requests. They should all start.
+ std::vector<std::unique_ptr<TestRequest>> delayable_requests;
+ for (int i = 0;
+ i < kDefaultMaxNumDelayableRequestsPerClient - non_delayable_weight;
+ ++i) {
+ delayable_requests.push_back(NewRequest(
+ base::StringPrintf("http://host%d/low", i).c_str(), net::LOWEST));
+ EXPECT_TRUE(delayable_requests.back()->started());
+ }
+ // The next delayable request should not start.
+ std::unique_ptr<TestRequest> last_low(
+ NewRequest("http://lasthost/low", net::LOWEST));
+ EXPECT_FALSE(last_low->started());
+ }
+
ResourceScheduler* scheduler() {
return scheduler_.get();
}
@@ -262,7 +485,9 @@ class ResourceSchedulerTest : public testing::Test {
std::unique_ptr<ResourceScheduler> scheduler_;
base::MockTimer* mock_timer_;
net::HttpServerPropertiesImpl http_server_properties_;
+ net::TestNetworkQualityEstimator network_quality_estimator_;
net::TestURLRequestContext context_;
+ base::FieldTrialList field_trial_list_;
};
TEST_F(ResourceSchedulerTest, OneIsolatedLowRequest) {
@@ -326,115 +551,186 @@ TEST_F(ResourceSchedulerTest, MediumDoesNotBlockCriticalComplete) {
EXPECT_TRUE(lowest2->started());
}
-TEST_F(ResourceSchedulerTest, SchedulerYieldsWithFeatureEnabled) {
+TEST_F(ResourceSchedulerTest, SchedulerYieldsOnSpdy) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitFromCommandLine(kNetworkSchedulerYielding, "");
InitializeScheduler();
- // Use spdy so that we don't throttle.
- http_server_properties_.SetSupportsSpdy(
- url::SchemeHostPort("https", "spdyhost", 443), true);
+ // The second low-priority request should yield.
+ scheduler_->SetMaxRequestsBeforeYieldingForTesting(1);
- // Add enough async requests that the last one should yield.
- std::vector<std::unique_ptr<TestRequest>> requests;
- for (int i = 0; i < kMaxRequestsBeforeYielding + 1; ++i)
- requests.push_back(NewRequest("http://host/higher", net::HIGHEST));
+ // Set a custom yield time.
+ scheduler_->SetYieldTimeForTesting(base::TimeDelta::FromMilliseconds(42));
- // Verify that the number of requests before yielding started.
- for (int i = 0; i < kMaxRequestsBeforeYielding; ++i)
- EXPECT_TRUE(requests[i]->started());
+ // Use a testing task runner so that we can control time.
+ auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>();
+ scheduler_->SetTaskRunnerForTesting(task_runner);
- // The next async request should have yielded.
- EXPECT_FALSE(requests[kMaxRequestsBeforeYielding]->started());
+ http_server_properties_.SetSupportsSpdy(
+ url::SchemeHostPort("https", "spdyhost", 443), true);
- // Verify that with time the yielded request eventually runs.
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(requests[kMaxRequestsBeforeYielding]->started());
+ std::unique_ptr<TestRequest> request(
+ NewRequest("https://spdyhost/low", net::LOWEST));
+ std::unique_ptr<TestRequest> request2(
+ NewRequest("https://spdyhost/low", net::LOWEST));
+ std::unique_ptr<TestRequest> request3(
+ NewRequest("https://spdyhost/low", net::LOWEST));
+
+ // Just before the yield task runs, only the first request should have
+ // started.
+ task_runner->FastForwardBy(base::TimeDelta::FromMilliseconds(41));
+ EXPECT_TRUE(request->started());
+ EXPECT_FALSE(request2->started());
+ EXPECT_FALSE(request3->started());
+
+ // Yield is done, run the next task.
+ task_runner->FastForwardBy(base::TimeDelta::FromMilliseconds(1));
+ EXPECT_TRUE(request2->started());
+ EXPECT_FALSE(request3->started());
+
+ // Just before the yield task runs, only the first two requests should have
+ // started.
+ task_runner->FastForwardBy(base::TimeDelta::FromMilliseconds(41));
+ EXPECT_FALSE(request3->started());
+
+ // Yield is done, run the next task.
+ task_runner->FastForwardBy(base::TimeDelta::FromMilliseconds(1));
+ EXPECT_TRUE(request3->started());
}
-TEST_F(ResourceSchedulerTest, SchedulerDoesNotYieldForSyncRequests) {
+// Same as SchedulerYieldsOnSpdy but uses FieldTrial Parameters for
+// configuration.
+TEST_F(ResourceSchedulerTest, SchedulerYieldFieldTrialParams) {
base::test::ScopedFeatureList scoped_feature_list;
- scoped_feature_list.InitFromCommandLine(kNetworkSchedulerYielding, "");
+
+ ConfigureYieldFieldTrial(1 /* requests before yielding */,
+ 42 /* yield time */, &scoped_feature_list);
InitializeScheduler();
- // Use spdy so that we don't throttle.
+ // Make sure the parameters were properly set.
+ EXPECT_EQ(42, scheduler_->yield_time().InMilliseconds());
+ EXPECT_EQ(1, scheduler_->max_requests_before_yielding());
+
+ // Use a testing task runner so that we can control time.
+ auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>();
+ scheduler_->SetTaskRunnerForTesting(task_runner);
+
http_server_properties_.SetSupportsSpdy(
url::SchemeHostPort("https", "spdyhost", 443), true);
- // Add enough async requests that the last one should yield.
- std::vector<std::unique_ptr<TestRequest>> requests;
- for (int i = 0; i < kMaxRequestsBeforeYielding + 1; ++i)
- requests.push_back(NewRequest("http://host/higher", net::HIGHEST));
+ std::unique_ptr<TestRequest> request(
+ NewRequest("https://spdyhost/low", net::LOWEST));
+ std::unique_ptr<TestRequest> request2(
+ NewRequest("https://spdyhost/low", net::LOWEST));
- // Add a sync requests.
- requests.push_back(NewSyncRequest("http://host/higher", net::HIGHEST));
+ // Just before the yield task runs, only the first request should have
+ // started.
+ task_runner->FastForwardBy(base::TimeDelta::FromMilliseconds(41));
+ EXPECT_TRUE(request->started());
+ EXPECT_FALSE(request2->started());
- // Verify that the number of requests before yielding started.
- for (int i = 0; i < kMaxRequestsBeforeYielding; ++i)
- EXPECT_TRUE(requests[i]->started());
+ // Yield is done, run the next task.
+ task_runner->FastForwardBy(base::TimeDelta::FromMilliseconds(1));
+ EXPECT_TRUE(request2->started());
+}
- // The next async request should have yielded.
- EXPECT_FALSE(requests[kMaxRequestsBeforeYielding]->started());
+TEST_F(ResourceSchedulerTest, YieldingDisabled) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitFromCommandLine("", kNetworkSchedulerYielding);
+ InitializeScheduler();
- // The next sync request should have started even though async is yielding.
- EXPECT_TRUE(requests[kMaxRequestsBeforeYielding + 1]->started());
+ // We're setting a yield parameter, but no yielding will happen since it's
+ // disabled.
+ scheduler_->SetMaxRequestsBeforeYieldingForTesting(1);
- // Verify that with time the yielded request eventually runs.
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(requests[kMaxRequestsBeforeYielding]->started());
+ http_server_properties_.SetSupportsSpdy(
+ url::SchemeHostPort("https", "spdyhost", 443), true);
+
+ std::unique_ptr<TestRequest> request(
+ NewRequest("https://spdyhost/low", net::LOWEST));
+ std::unique_ptr<TestRequest> request2(
+ NewRequest("https://spdyhost/low", net::LOWEST));
+ EXPECT_TRUE(request->started());
+ EXPECT_TRUE(request2->started());
}
-TEST_F(ResourceSchedulerTest, SchedulerDoesNotYieldForAlternativeSchemes) {
+TEST_F(ResourceSchedulerTest, SchedulerDoesNotYieldH1) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitFromCommandLine(kNetworkSchedulerYielding, "");
InitializeScheduler();
- // Use spdy so that we don't throttle.
- http_server_properties_.SetSupportsSpdy(
- url::SchemeHostPort("https", "spdyhost", 443), true);
+ // Use a testing task runner so that we can control time.
+ auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>();
+ scheduler_->SetTaskRunnerForTesting(task_runner);
- // Add enough async requests that the last one should yield.
- std::vector<std::unique_ptr<TestRequest>> requests;
- for (int i = 0; i < kMaxRequestsBeforeYielding + 1; ++i)
- requests.push_back(NewRequest("http://host/higher", net::HIGHEST));
+ // Yield after each request.
+ scheduler_->SetMaxRequestsBeforeYieldingForTesting(1);
+ scheduler_->SetYieldTimeForTesting(base::TimeDelta::FromMilliseconds(42));
- // Add a non-http request.
- requests.push_back(NewRequest("zzz://host/higher", net::HIGHEST));
+ std::unique_ptr<TestRequest> request(
+ NewRequest("https://host/low", net::LOWEST));
+ std::unique_ptr<TestRequest> request2(
+ NewRequest("https://host/low", net::LOWEST));
- // Verify that the number of requests before yielding started.
- for (int i = 0; i < kMaxRequestsBeforeYielding; ++i)
- EXPECT_TRUE(requests[i]->started());
+ EXPECT_TRUE(request->started());
+ EXPECT_FALSE(request2->started());
- // The next async request should have yielded.
- EXPECT_FALSE(requests[kMaxRequestsBeforeYielding]->started());
+ // Finish the first task so that the second can start.
+ request = nullptr;
- // The non-http(s) request should have started even though async is
- // yielding.
- EXPECT_TRUE(requests[kMaxRequestsBeforeYielding + 1]->started());
+ // Run tasks without advancing time, if there were yielding the next task
+ // wouldn't start.
+ task_runner->RunUntilIdle();
- // Verify that with time the yielded request eventually runs.
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(requests[kMaxRequestsBeforeYielding]->started());
+ // The next task started, so there was no yielding.
+ EXPECT_TRUE(request2->started());
}
-TEST_F(ResourceSchedulerTest, SchedulerDoesNotYieldWithFeatureDisabled) {
+TEST_F(ResourceSchedulerTest, SchedulerDoesNotYieldAltSchemes) {
base::test::ScopedFeatureList scoped_feature_list;
- scoped_feature_list.InitFromCommandLine("", kNetworkSchedulerYielding);
+ scoped_feature_list.InitFromCommandLine(kNetworkSchedulerYielding, "");
InitializeScheduler();
+ // Yield after each request.
+ scheduler_->SetMaxRequestsBeforeYieldingForTesting(1);
+ scheduler_->SetYieldTimeForTesting(base::TimeDelta::FromMilliseconds(42));
+
+ std::unique_ptr<TestRequest> request(
+ NewRequest("yyy://host/low", net::LOWEST));
+ std::unique_ptr<TestRequest> request2(
+ NewRequest("zzz://host/low", net::LOWEST));
+
+ EXPECT_TRUE(request->started());
+ EXPECT_TRUE(request2->started());
+}
+
+TEST_F(ResourceSchedulerTest, SchedulerDoesNotYieldSyncRequests) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitFromCommandLine(kNetworkSchedulerYielding, "");
+ InitializeScheduler();
+
+ // The second low-priority request should yield.
+ scheduler_->SetMaxRequestsBeforeYieldingForTesting(1);
+
// Use spdy so that we don't throttle.
http_server_properties_.SetSupportsSpdy(
url::SchemeHostPort("https", "spdyhost", 443), true);
- // Add enough async requests that the last one would yield if yielding were
- // enabled.
- std::vector<std::unique_ptr<TestRequest>> requests;
- for (int i = 0; i < kMaxRequestsBeforeYielding + 1; ++i)
- requests.push_back(NewRequest("http://host/higher", net::HIGHEST));
+ std::unique_ptr<TestRequest> request(
+ NewRequest("https://spdyhost/low", net::LOWEST));
+ std::unique_ptr<TestRequest> request2(
+ NewRequest("https://spdyhost/low", net::LOWEST)); // yields
+
+ // Add a synchronous request, it shouldn't yield.
+ std::unique_ptr<TestRequest> sync_request(
+ NewSyncRequest("http://spdyhost/low", net::LOWEST));
+
+ EXPECT_TRUE(request->started());
+ EXPECT_FALSE(request2->started());
+ EXPECT_TRUE(sync_request->started()); // The sync request started.
- // Verify that none of the requests yield.
- for (int i = 0; i < kMaxRequestsBeforeYielding + 1; ++i)
- EXPECT_TRUE(requests[i]->started());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(request2->started());
}
TEST_F(ResourceSchedulerTest, OneLowLoadsUntilBodyInsertedExceptSpdy) {
@@ -486,6 +782,220 @@ TEST_F(ResourceSchedulerTest,
high.reset();
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(low2->started());
+ EXPECT_TRUE(low_spdy->started());
+}
+
+TEST_F(ResourceSchedulerTest, MaxRequestsPerHostForSpdyWhenNotDelayable) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitFromCommandLine("",
+ kPrioritySupportedRequestsDelayable);
+
+ InitializeScheduler();
+ http_server_properties_.SetSupportsSpdy(
+ url::SchemeHostPort("https", "spdyhost", 443), true);
+
+ // Add more than max-per-host low-priority requests.
+ std::vector<std::unique_ptr<TestRequest>> requests;
+ for (size_t i = 0; i < kMaxNumDelayableRequestsPerHostPerClient + 1; ++i)
+ requests.push_back(NewRequest("https://spdyhost/low", net::LOWEST));
+
+ // No throttling.
+ for (const auto& request : requests)
+ EXPECT_TRUE(request->started());
+}
+
+TEST_F(ResourceSchedulerTest, MaxRequestsPerHostForSpdyWhenDelayable) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitFromCommandLine(
+ kPrioritySupportedRequestsDelayable,
+ kHeadPrioritySupportedRequestsDelayable);
+
+ InitializeScheduler();
+ http_server_properties_.SetSupportsSpdy(
+ url::SchemeHostPort("https", "spdyhost", 443), true);
+
+ // Body has been reached.
+ scheduler()->OnWillInsertBody(kChildId, kRouteId);
+
+ // Add more than max-per-host low-priority requests.
+ std::vector<std::unique_ptr<TestRequest>> requests;
+ for (size_t i = 0; i < kMaxNumDelayableRequestsPerHostPerClient + 1; ++i)
+ requests.push_back(NewRequest("https://spdyhost/low", net::LOWEST));
+
+ // Only kMaxNumDelayableRequestsPerHostPerClient in body.
+ for (size_t i = 0; i < requests.size(); ++i) {
+ if (i < kMaxNumDelayableRequestsPerHostPerClient)
+ EXPECT_TRUE(requests[i]->started());
+ else
+ EXPECT_FALSE(requests[i]->started());
+ }
+}
+
+TEST_F(ResourceSchedulerTest, MaxRequestsPerHostForSpdyWhenHeadDelayable) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitFromCommandLine(
+ kHeadPrioritySupportedRequestsDelayable,
+ kPrioritySupportedRequestsDelayable);
+
+ InitializeScheduler();
+ http_server_properties_.SetSupportsSpdy(
+ url::SchemeHostPort("https", "spdyhost", 443), true);
+
+ // Body has been reached.
+ scheduler()->OnWillInsertBody(kChildId, kRouteId);
+
+ // Add more than max-per-host low-priority requests.
+ std::vector<std::unique_ptr<TestRequest>> requests;
+ for (size_t i = 0; i < kMaxNumDelayableRequestsPerHostPerClient + 1; ++i)
+ requests.push_back(NewRequest("https://spdyhost/low", net::LOWEST));
+
+ // No throttling.
+ for (const auto& request : requests)
+ EXPECT_TRUE(request->started());
+}
+
+TEST_F(ResourceSchedulerTest, ThrottlesHeadWhenHeadDelayable) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitFromCommandLine(
+ kHeadPrioritySupportedRequestsDelayable,
+ kPrioritySupportedRequestsDelayable);
+
+ InitializeScheduler();
+ http_server_properties_.SetSupportsSpdy(
+ url::SchemeHostPort("https", "spdyhost", 443), true);
+
+ // Add more than max-per-host low-priority requests.
+ std::vector<std::unique_ptr<TestRequest>> requests;
+ for (size_t i = 0; i < kMaxNumDelayableRequestsPerHostPerClient + 1; ++i)
+ requests.push_back(NewRequest("https://spdyhost/low", net::LOWEST));
+
+ // While in head, only one low-priority request is allowed.
+ for (size_t i = 0u; i < requests.size(); ++i) {
+ if (i == 0u)
+ EXPECT_TRUE(requests[i]->started());
+ else
+ EXPECT_FALSE(requests[i]->started());
+ }
+
+ // Body has been reached.
+ scheduler()->OnWillInsertBody(kChildId, kRouteId);
+ base::RunLoop().RunUntilIdle();
+
+ // No throttling.
+ for (const auto& request : requests)
+ EXPECT_TRUE(request->started());
+}
+
+TEST_F(ResourceSchedulerTest, MaxRequestsPerHostForSpdyProxyWhenNotDelayable) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitFromCommandLine("",
+ kPrioritySupportedRequestsDelayable);
+
+ InitializeScheduler();
+
+ // Body has been reached.
+ scheduler()->OnWillInsertBody(kChildId, kRouteId);
+
+ // Add more than max-per-host low-priority requests.
+ std::vector<std::unique_ptr<TestRequest>> requests;
+ for (size_t i = 0; i < kMaxNumDelayableRequestsPerHostPerClient + 1; ++i)
+ requests.push_back(NewRequest("http://host/low", net::LOWEST));
+
+ // Now the scheduler realizes these requests are for a spdy proxy.
+ scheduler()->OnReceivedSpdyProxiedHttpResponse(kChildId, kRouteId);
+ base::RunLoop().RunUntilIdle();
+
+ // No throttling.
+ for (const auto& request : requests)
+ EXPECT_TRUE(request->started());
+}
+
+TEST_F(ResourceSchedulerTest, MaxRequestsPerHostForSpdyProxyWhenDelayable) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitFromCommandLine(
+ kPrioritySupportedRequestsDelayable,
+ kHeadPrioritySupportedRequestsDelayable);
+
+ InitializeScheduler();
+
+ // Body has been reached.
+ scheduler()->OnWillInsertBody(kChildId, kRouteId);
+
+ // Add more than max-per-host low-priority requests.
+ std::vector<std::unique_ptr<TestRequest>> requests;
+ for (size_t i = 0; i < kMaxNumDelayableRequestsPerHostPerClient + 1; ++i)
+ requests.push_back(NewRequest("http://host/low", net::LOWEST));
+
+ // Now the scheduler realizes these requests are for a spdy proxy.
+ scheduler()->OnReceivedSpdyProxiedHttpResponse(kChildId, kRouteId);
+ base::RunLoop().RunUntilIdle();
+
+ // Only kMaxNumDelayableRequestsPerHostPerClient in body.
+ for (size_t i = 0; i < requests.size(); ++i) {
+ if (i < kMaxNumDelayableRequestsPerHostPerClient)
+ EXPECT_TRUE(requests[i]->started());
+ else
+ EXPECT_FALSE(requests[i]->started());
+ }
+}
+
+TEST_F(ResourceSchedulerTest, MaxRequestsPerHostForSpdyProxyWhenHeadDelayable) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitFromCommandLine(
+ kHeadPrioritySupportedRequestsDelayable,
+ kPrioritySupportedRequestsDelayable);
+
+ InitializeScheduler();
+
+ // Body has been reached.
+ scheduler()->OnWillInsertBody(kChildId, kRouteId);
+
+ // Add more than max-per-host low-priority requests.
+ std::vector<std::unique_ptr<TestRequest>> requests;
+ for (size_t i = 0; i < kMaxNumDelayableRequestsPerHostPerClient + 1; ++i)
+ requests.push_back(NewRequest("http://host/low", net::LOWEST));
+
+ // Now the scheduler realizes these requests are for a spdy proxy.
+ scheduler()->OnReceivedSpdyProxiedHttpResponse(kChildId, kRouteId);
+ base::RunLoop().RunUntilIdle();
+
+ // No throttling.
+ for (const auto& request : requests)
+ EXPECT_TRUE(request->started());
+}
+
+TEST_F(ResourceSchedulerTest, ThrottlesHeadForSpdyProxyWhenHeadDelayable) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitFromCommandLine(
+ kHeadPrioritySupportedRequestsDelayable,
+ kPrioritySupportedRequestsDelayable);
+
+ InitializeScheduler();
+
+ // Add more than max-per-host low-priority requests.
+ std::vector<std::unique_ptr<TestRequest>> requests;
+ for (size_t i = 0; i < kMaxNumDelayableRequestsPerHostPerClient + 1; ++i)
+ requests.push_back(NewRequest("http://host/low", net::LOWEST));
+
+ // Now the scheduler realizes these requests are for a spdy proxy.
+ scheduler()->OnReceivedSpdyProxiedHttpResponse(kChildId, kRouteId);
+ base::RunLoop().RunUntilIdle();
+
+ // While in head, only one low-priority request is allowed.
+ for (size_t i = 0u; i < requests.size(); ++i) {
+ if (i == 0u)
+ EXPECT_TRUE(requests[i]->started());
+ else
+ EXPECT_FALSE(requests[i]->started());
+ }
+
+ // Body has been reached.
+ scheduler()->OnWillInsertBody(kChildId, kRouteId);
+ base::RunLoop().RunUntilIdle();
+
+ // No throttling.
+ for (const auto& request : requests)
+ EXPECT_TRUE(request->started());
}
TEST_F(ResourceSchedulerTest, SpdyLowBlocksOtherLowUntilBodyInserted) {
@@ -615,7 +1125,8 @@ TEST_F(ResourceSchedulerTest, LimitedNumberOfDelayableRequestsInFlight) {
NewRequest("http://host/high", net::HIGHEST));
EXPECT_TRUE(high->started());
- const int kMaxNumDelayableRequestsPerClient = 10; // Should match the .cc.
+ const int kDefaultMaxNumDelayableRequestsPerClient =
+ 10; // Should match the .cc.
const int kMaxNumDelayableRequestsPerHost = 6;
std::vector<std::unique_ptr<TestRequest>> lows_singlehost;
// Queue up to the per-host limit (we subtract the current high-pri request).
@@ -642,8 +1153,8 @@ TEST_F(ResourceSchedulerTest, LimitedNumberOfDelayableRequestsInFlight) {
EXPECT_TRUE(last_singlehost->started());
// Queue more requests from different hosts until we reach the total limit.
- int expected_slots_left =
- kMaxNumDelayableRequestsPerClient - kMaxNumDelayableRequestsPerHost;
+ int expected_slots_left = kDefaultMaxNumDelayableRequestsPerClient -
+ kMaxNumDelayableRequestsPerHost;
EXPECT_GT(expected_slots_left, 0);
std::vector<std::unique_ptr<TestRequest>> lows_different_host;
base::RunLoop().RunUntilIdle();
@@ -690,9 +1201,10 @@ TEST_F(ResourceSchedulerTest, RaisePriorityInQueue) {
EXPECT_FALSE(request->started());
EXPECT_FALSE(idle->started());
- const int kMaxNumDelayableRequestsPerClient = 10; // Should match the .cc.
+ const int kDefaultMaxNumDelayableRequestsPerClient =
+ 10; // Should match the .cc.
std::vector<std::unique_ptr<TestRequest>> lows;
- for (int i = 0; i < kMaxNumDelayableRequestsPerClient - 1; ++i) {
+ for (int i = 0; i < kDefaultMaxNumDelayableRequestsPerClient - 1; ++i) {
string url = "http://host/low" + base::IntToString(i);
lows.push_back(NewRequest(url.c_str(), net::LOWEST));
}
@@ -722,10 +1234,11 @@ TEST_F(ResourceSchedulerTest, LowerPriority) {
EXPECT_FALSE(request->started());
EXPECT_FALSE(idle->started());
- const int kMaxNumDelayableRequestsPerClient = 10; // Should match the .cc.
+ const int kDefaultMaxNumDelayableRequestsPerClient =
+ 10; // Should match the .cc.
// 2 fewer filler requests: 1 for the "low" dummy at the start, and 1 for the
// one at the end, which will be tested.
- const int kNumFillerRequests = kMaxNumDelayableRequestsPerClient - 2;
+ const int kNumFillerRequests = kDefaultMaxNumDelayableRequestsPerClient - 2;
std::vector<std::unique_ptr<TestRequest>> lows;
for (int i = 0; i < kNumFillerRequests; ++i) {
string url = "http://host" + base::IntToString(i) + "/low";
@@ -752,9 +1265,10 @@ TEST_F(ResourceSchedulerTest, ReprioritizedRequestGoesToBackOfQueue) {
EXPECT_FALSE(request->started());
EXPECT_FALSE(idle->started());
- const int kMaxNumDelayableRequestsPerClient = 10; // Should match the .cc.
+ const int kDefaultMaxNumDelayableRequestsPerClient =
+ 10; // Should match the .cc.
std::vector<std::unique_ptr<TestRequest>> lows;
- for (int i = 0; i < kMaxNumDelayableRequestsPerClient; ++i) {
+ for (int i = 0; i < kDefaultMaxNumDelayableRequestsPerClient; ++i) {
string url = "http://host/low" + base::IntToString(i);
lows.push_back(NewRequest(url.c_str(), net::LOWEST));
}
@@ -781,9 +1295,10 @@ TEST_F(ResourceSchedulerTest, HigherIntraPriorityGoesToFrontOfQueue) {
NewRequest("http://host/high", net::HIGHEST));
std::unique_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST));
- const int kMaxNumDelayableRequestsPerClient = 10; // Should match the .cc.
+ const int kDefaultMaxNumDelayableRequestsPerClient =
+ 10; // Should match the .cc.
std::vector<std::unique_ptr<TestRequest>> lows;
- for (int i = 0; i < kMaxNumDelayableRequestsPerClient; ++i) {
+ for (int i = 0; i < kDefaultMaxNumDelayableRequestsPerClient; ++i) {
string url = "http://host/low" + base::IntToString(i);
lows.push_back(NewRequest(url.c_str(), net::IDLE));
}
@@ -866,13 +1381,14 @@ TEST_F(ResourceSchedulerTest, NewSpdyHostInDelayableRequests) {
InitializeScheduler();
scheduler()->OnWillInsertBody(kChildId, kRouteId);
- const int kMaxNumDelayableRequestsPerClient = 10; // Should match the .cc.
+ const int kDefaultMaxNumDelayableRequestsPerClient =
+ 10; // Should match the .cc.
std::unique_ptr<TestRequest> low1_spdy(
NewRequest("http://spdyhost1:8080/low", net::LOWEST));
// Cancel a request after we learn the server supports SPDY.
std::vector<std::unique_ptr<TestRequest>> lows;
- for (int i = 0; i < kMaxNumDelayableRequestsPerClient - 1; ++i) {
+ for (int i = 0; i < kDefaultMaxNumDelayableRequestsPerClient - 1; ++i) {
string url = "http://host" + base::IntToString(i) + "/low";
lows.push_back(NewRequest(url.c_str(), net::LOWEST));
}
@@ -905,13 +1421,14 @@ TEST_F(ResourceSchedulerTest, NewDelayableSpdyHostInDelayableRequests) {
InitializeScheduler();
scheduler()->OnWillInsertBody(kChildId, kRouteId);
- const int kMaxNumDelayableRequestsPerClient = 10; // Should match the .cc.
+ const int kDefaultMaxNumDelayableRequestsPerClient =
+ 10; // Should match the .cc.
std::unique_ptr<TestRequest> low1_spdy(
NewRequest("http://spdyhost1:8080/low", net::LOWEST));
// Cancel a request after we learn the server supports SPDY.
std::vector<std::unique_ptr<TestRequest>> lows;
- for (int i = 0; i < kMaxNumDelayableRequestsPerClient - 1; ++i) {
+ for (int i = 0; i < kDefaultMaxNumDelayableRequestsPerClient - 1; ++i) {
string url = "http://host" + base::IntToString(i) + "/low";
lows.push_back(NewRequest(url.c_str(), net::LOWEST));
}
@@ -941,7 +1458,8 @@ TEST_F(ResourceSchedulerTest, NewDelayableSpdyHostInDelayableRequests) {
// started at some point, or they will hang around forever and prevent other
// async revalidations to the same URL from being issued.
TEST_F(ResourceSchedulerTest, RequestStartedAfterClientDeleted) {
- scheduler_->OnClientCreated(kChildId2, kRouteId2);
+ scheduler_->OnClientCreated(kChildId2, kRouteId2,
+ &network_quality_estimator_);
std::unique_ptr<TestRequest> high(NewRequestWithChildAndRoute(
"http://host/high", net::HIGHEST, kChildId2, kRouteId2));
std::unique_ptr<TestRequest> lowest1(NewRequestWithChildAndRoute(
@@ -962,12 +1480,13 @@ TEST_F(ResourceSchedulerTest, RequestStartedAfterClientDeleted) {
// This test is to verify that requests will be started at some point
// even if they were not started by the destructor.
TEST_F(ResourceSchedulerTest, RequestStartedAfterClientDeletedManyDelayable) {
- scheduler_->OnClientCreated(kChildId2, kRouteId2);
+ scheduler_->OnClientCreated(kChildId2, kRouteId2,
+ &network_quality_estimator_);
std::unique_ptr<TestRequest> high(NewRequestWithChildAndRoute(
"http://host/high", net::HIGHEST, kChildId2, kRouteId2));
- const int kMaxNumDelayableRequestsPerClient = 10;
+ const int kDefaultMaxNumDelayableRequestsPerClient = 10;
std::vector<std::unique_ptr<TestRequest>> delayable_requests;
- for (int i = 0; i < kMaxNumDelayableRequestsPerClient + 1; ++i) {
+ for (int i = 0; i < kDefaultMaxNumDelayableRequestsPerClient + 1; ++i) {
delayable_requests.push_back(NewRequestWithChildAndRoute(
"http://host/lowest", net::LOWEST, kChildId2, kRouteId2));
}
@@ -982,6 +1501,471 @@ TEST_F(ResourceSchedulerTest, RequestStartedAfterClientDeletedManyDelayable) {
EXPECT_TRUE(lowest->started());
}
+// Tests that the maximum number of delayable requests is overridden when the
+// experiment is enabled. The BDP buckets are correct and the effective
+// connection type is also in the configuration bucket.
+TEST_F(ResourceSchedulerTest, RequestLimitOverrideEnabled) {
+ RequestLimitOverrideConfigTestHelper(true);
+}
+
+// Tests that the maximum number of delayable requests is not overridden when
+// the experiment is disabled. The BDP buckets are correct and the effective
+// connection type is also in the configuration bucket.
+TEST_F(ResourceSchedulerTest, RequestLimitOverrideDisabled) {
+ RequestLimitOverrideConfigTestHelper(false);
+}
+
+// Test that the limit is not overridden when the effective connection type is
+// not equal to any of the values provided in the experiment configuration.
+TEST_F(ResourceSchedulerTest, RequestLimitOverrideOutsideECTRange) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ InitializeThrottleDelayableExperiment(&scoped_feature_list, true, 0.0);
+ InitializeScheduler();
+ for (net::EffectiveConnectionType ect :
+ {net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN,
+ net::EFFECTIVE_CONNECTION_TYPE_OFFLINE,
+ net::EFFECTIVE_CONNECTION_TYPE_3G, net::EFFECTIVE_CONNECTION_TYPE_4G}) {
+ // Set BDP to 120 kbits, which lies in the configuration bucket. Set the
+ // effective connection type to a value for which the experiment should not
+ // be run.
+ network_quality_estimator_.set_bandwidth_delay_product_kbits(120);
+ network_quality_estimator_.set_effective_connection_type(ect);
+
+ // The limit will matter only once the page has a body, since delayable
+ // requests are not loaded before that.
+ scheduler()->OnWillInsertBody(kChildId, kRouteId);
+
+ // Throw in one high priority request to ensure that it does not matter once
+ // a body exists.
+ std::unique_ptr<TestRequest> high(
+ NewRequest("http://host/high", net::HIGHEST));
+ EXPECT_TRUE(high->started());
+
+ // Should be in sync with resource_scheduler.cc.
+ const int kDefaultMaxNumDelayableRequestsPerClient = 10;
+
+ std::vector<std::unique_ptr<TestRequest>> lows_singlehost;
+ // Queue up to the maximum limit. Use different host names to prevent the
+ // per host limit from kicking in.
+ for (int i = 0; i < kDefaultMaxNumDelayableRequestsPerClient; ++i) {
+ // Keep unique hostnames to prevent the per host limit from kicking in.
+ std::string url = "http://host" + base::IntToString(i) + "/low";
+ lows_singlehost.push_back(NewRequest(url.c_str(), net::LOWEST));
+ EXPECT_TRUE(lows_singlehost[i]->started());
+ }
+
+ std::unique_ptr<TestRequest> last_singlehost(
+ NewRequest("http://host/last", net::LOWEST));
+
+ // Last should not start because the maximum requests that can be in-flight
+ // have already started.
+ EXPECT_FALSE(last_singlehost->started());
+ }
+}
+
+// Test that the limit is not overridden when the effective connection type is
+// valid, but the bandwidth delay product (BDP) does not lie in one of the
+// buckets provided in the configuration.
+TEST_F(ResourceSchedulerTest, RequestLimitOverrideConfigOutsideBDPRange) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ InitializeThrottleDelayableExperiment(&scoped_feature_list, true, 0.0);
+ // The BDP should lie outside the provided ranges. Here, the BDP is set to
+ // 200, which lies outside the configuration BDP buckets.
+ // The effective connection type is set to Slow-2G.
+ network_quality_estimator_.set_bandwidth_delay_product_kbits(200);
+ network_quality_estimator_.set_effective_connection_type(
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G);
+ InitializeScheduler();
+
+ // The limit should be the default limit, which is 10 delayable requests
+ // in-flight. The limit will matter only once the page has a body, since
+ // delayable requests are not loaded before that.
+ scheduler()->OnWillInsertBody(kChildId, kRouteId);
+
+ // Throw in one high priority request to ensure that it does not matter once
+ // a body exists.
+ std::unique_ptr<TestRequest> high(
+ NewRequest("http://host/high", net::HIGHEST));
+ EXPECT_TRUE(high->started());
+
+ // Should be in sync with resource_scheduler.cc.
+ const int kDefaultMaxNumDelayableRequestsPerClient = 10;
+
+ std::vector<std::unique_ptr<TestRequest>> lows_singlehost;
+ // Queue up to the maximum limit. Use different host names to prevent the
+ // per host limit from kicking in.
+ for (int i = 0; i < kDefaultMaxNumDelayableRequestsPerClient; ++i) {
+ // Keep unique hostnames to prevent the per host limit from kicking in.
+ std::string url = "http://host" + base::IntToString(i) + "/low";
+ lows_singlehost.push_back(NewRequest(url.c_str(), net::LOWEST));
+ EXPECT_TRUE(lows_singlehost[i]->started());
+ }
+
+ std::unique_ptr<TestRequest> last_singlehost(
+ NewRequest("http://host/last", net::LOWEST));
+
+ // Last should not start because the maximum requests that can be in-flight
+ // have already started.
+ EXPECT_FALSE(last_singlehost->started());
+}
+
+// Test that a change in network conditions midway during loading does not
+// change the behavior of the resource scheduler.
+TEST_F(ResourceSchedulerTest, RequestLimitOverrideFixedForPageLoad) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ InitializeThrottleDelayableExperiment(&scoped_feature_list, true, 0.0);
+ // BDP value is in range for which the limit is overridden to 2. The
+ // effective connection type is set to Slow-2G.
+ network_quality_estimator_.set_bandwidth_delay_product_kbits(120);
+ network_quality_estimator_.set_effective_connection_type(
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G);
+ InitializeScheduler();
+
+ // The limit will matter only once the page has a body, since delayable
+ // requests are not loaded before that.
+ scheduler()->OnWillInsertBody(kChildId, kRouteId);
+
+ // Throw in one high priority request to ensure that it does not matter once
+ // a body exists.
+ std::unique_ptr<TestRequest> high(
+ NewRequest("http://host/high", net::HIGHEST));
+ EXPECT_TRUE(high->started());
+
+ // Should be based on the value set by
+ // |InitializeMaxDelayableRequestsExperiment| for the given range.
+ const int kOverriddenNumRequests = 2;
+
+ std::vector<std::unique_ptr<TestRequest>> lows_singlehost;
+ // Queue up to the overridden limit.
+ for (int i = 0; i < kOverriddenNumRequests; ++i) {
+ // Keep unique hostnames to prevent the per host limit from kicking in.
+ std::string url = "http://host" + base::IntToString(i) + "/low";
+ lows_singlehost.push_back(NewRequest(url.c_str(), net::LOWEST));
+ EXPECT_TRUE(lows_singlehost[i]->started());
+ }
+
+ std::unique_ptr<TestRequest> second_last_singlehost(
+ NewRequest("http://host/slast", net::LOWEST));
+
+ // This new request should not start because the limit has been reached.
+ EXPECT_FALSE(second_last_singlehost->started());
+ lows_singlehost.erase(lows_singlehost.begin());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(second_last_singlehost->started());
+
+ // Change the BDP to go outside the experiment buckets and change the network
+ // type to 2G. This should not affect the limit calculated at the beginning of
+ // the page load.
+ network_quality_estimator_.set_bandwidth_delay_product_kbits(50);
+ network_quality_estimator_.set_effective_connection_type(
+ net::EFFECTIVE_CONNECTION_TYPE_2G);
+
+ std::unique_ptr<TestRequest> last_singlehost(
+ NewRequest("http://host/last", net::LOWEST));
+
+ // Last should not start because the limit should not have changed.
+ EXPECT_FALSE(last_singlehost->started());
+}
+
+// Test that when the network quality changes such that the new limit is lower,
+// and an |OnNavigate| event occurs, the new delayable requests don't start
+// until the number of requests in flight have gone below the new limit.
+TEST_F(ResourceSchedulerTest, RequestLimitReducedAcrossPageLoads) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ InitializeThrottleDelayableExperiment(&scoped_feature_list, true, 0.0);
+ // BDP value is in range for which the limit is overridden to 4. The
+ // effective connection type is set to Slow-2G.
+ network_quality_estimator_.set_bandwidth_delay_product_kbits(150);
+ network_quality_estimator_.set_effective_connection_type(
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G);
+ InitializeScheduler();
+
+ // The limit will matter only once the page has a body, since delayable
+ // requests are not loaded before that.
+ scheduler()->OnWillInsertBody(kChildId, kRouteId);
+
+ // Throw in one high priority request to ensure that it does not matter once
+ // a body exists.
+ std::unique_ptr<TestRequest> high(
+ NewRequest("http://host/high", net::HIGHEST));
+ EXPECT_TRUE(high->started());
+
+ // The number of delayable requests allowed for the first page load.
+ const int kNumDelayableHigh = 4;
+ // The number of delayable requests allowed for the second page load.
+ const int kNumDelayableLow = 2;
+
+ std::vector<std::unique_ptr<TestRequest>> delayable_first_page;
+ // Queue up to the overridden limit.
+ for (int i = 0; i < kNumDelayableHigh; ++i) {
+ // Keep unique hostnames to prevent the per host limit from kicking in.
+ std::string url = "http://host" + base::IntToString(i) + "/low1";
+ delayable_first_page.push_back(NewRequest(url.c_str(), net::LOWEST));
+ EXPECT_TRUE(delayable_first_page[i]->started());
+ }
+ // Change the network quality so that the BDP value is in range for which the
+ // limit is overridden to 2. The effective connection type is set to
+ // Slow-2G.
+ network_quality_estimator_.set_bandwidth_delay_product_kbits(120);
+ network_quality_estimator_.set_effective_connection_type(
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G);
+ // Trigger a navigation event which will recompute limits. Also insert a body,
+ // because the limit matters only after the body exists.
+ scheduler()->OnNavigate(kChildId, kRouteId);
+ scheduler()->OnWillInsertBody(kChildId, kRouteId);
+
+ // Ensure that high priority requests still start.
+ std::unique_ptr<TestRequest> high2(
+ NewRequest("http://host/high2", net::HIGHEST));
+ EXPECT_TRUE(high->started());
+
+ // Generate requests from second page. None of them should start because the
+ // new limit is |kNumDelayableLow| and there are already |kNumDelayableHigh|
+ // requests in flight.
+ std::vector<std::unique_ptr<TestRequest>> delayable_second_page;
+ for (int i = 0; i < kNumDelayableLow; ++i) {
+ // Keep unique hostnames to prevent the per host limit from kicking in.
+ std::string url = "http://host" + base::IntToString(i) + "/low2";
+ delayable_second_page.push_back(NewRequest(url.c_str(), net::LOWEST));
+ EXPECT_FALSE(delayable_second_page[i]->started());
+ }
+
+ // Finish 2 requests from first page load.
+ for (int i = 0; i < kNumDelayableHigh - kNumDelayableLow; ++i) {
+ delayable_first_page.pop_back();
+ }
+ base::RunLoop().RunUntilIdle();
+
+ // Nothing should start because there are already |kNumDelayableLow| requests
+ // in flight.
+ for (int i = 0; i < kNumDelayableLow; ++i) {
+ EXPECT_FALSE(delayable_second_page[i]->started());
+ }
+
+ // Remove all requests from the first page.
+ delayable_first_page.clear();
+ base::RunLoop().RunUntilIdle();
+
+ // Check that the requests from page 2 have started, since now there are 2
+ // empty slots.
+ for (int i = 0; i < kNumDelayableLow; ++i) {
+ EXPECT_TRUE(delayable_second_page[i]->started());
+ }
+}
+
+// Test that a configuration without any BDP range is read correctly. In this
+// case, the resource scheduler will fall back to the default limit.
+TEST_F(ResourceSchedulerTest, ReadValidConfigTest0) {
+ ReadConfigTestHelper(0, "2G");
+}
+
+// Test that a configuration with 1 BDP range is read correctly.
+TEST_F(ResourceSchedulerTest, ReadValidConfigTest1) {
+ ReadConfigTestHelper(1, "2G");
+}
+
+// Test that a configuration with 2 BDP ranges is read correctly.
+TEST_F(ResourceSchedulerTest, ReadValidConfigTest2) {
+ ReadConfigTestHelper(2, "2G");
+}
+
+// Test that a configuration with 5 BDP ranges is read correctly.
+TEST_F(ResourceSchedulerTest, ReadValidConfigTest5) {
+ ReadConfigTestHelper(5, "2G");
+}
+
+// Test that a configuration with bad strings does not break the parser, and
+// the parser stops reading the configuration after it encounters the first
+// missing index.
+TEST_F(ResourceSchedulerTest, ReadInvalidConfigTest) {
+ base::FieldTrialParamAssociator::GetInstance()->ClearAllParamsForTesting();
+ const char kTrialName[] = "TrialName";
+ const char kGroupName[] = "GroupName";
+ const char kThrottleDelayable[] = "ThrottleDelayable";
+
+ base::test::ScopedFeatureList scoped_feature_list;
+ std::map<std::string, std::string> params;
+ params["MaxEffectiveConnectionType"] = "2G";
+ // Skip configuration parameters for index 2 to test that the parser stops
+ // when it cannot find the parameters for an index.
+ for (int bdp_range_index : {1, 3, 4}) {
+ std::string index_str = base::IntToString(bdp_range_index);
+ params["MaxBDPKbits" + index_str] = index_str + "00";
+ params["MaxDelayableRequests" + index_str] = index_str + "0";
+ }
+ // Add some bad configuration strigs to ensure that the parser does not break.
+ params["BadConfigParam1"] = "100";
+ params["BadConfigParam2"] = "100";
+
+ base::AssociateFieldTrialParams(kTrialName, kGroupName, params);
+ base::FieldTrial* field_trial =
+ base::FieldTrialList::CreateFieldTrial(kTrialName, kGroupName);
+ std::unique_ptr<base::FeatureList> feature_list(
+ base::MakeUnique<base::FeatureList>());
+ feature_list->RegisterFieldTrialOverride(
+ kThrottleDelayable, base::FeatureList::OVERRIDE_ENABLE_FEATURE,
+ field_trial);
+ scoped_feature_list.InitWithFeatureList(std::move(feature_list));
+
+ ResourceScheduler::MaxRequestsForBDPRanges bdp_ranges =
+ ResourceScheduler::GetMaxDelayableRequestsExperimentConfigForTests();
+
+ // Only the first configuration parameter must be read because a match was not
+ // found for index 2. The configuration parameters with index 3 and 4 must be
+ // ignored, even though they are valid configuration parameters.
+ EXPECT_EQ(bdp_ranges.size(), 1u);
+ EXPECT_EQ(bdp_ranges[0].max_bdp_kbits, 100);
+ EXPECT_EQ(bdp_ranges[0].max_requests, 10u);
+}
+
+// Test that the maximum effective connection type is read correctly when it is
+// set to "Slow-2G".
+TEST_F(ResourceSchedulerTest, ReadMaxECTForExperimentTestSlow2G) {
+ ReadConfigTestHelper(3, "Slow-2G");
+}
+
+// Test that the maximum effective connection type is read correctly when it is
+// set to "4G".
+TEST_F(ResourceSchedulerTest, ReadMaxECTForExperimentTest4G) {
+ ReadConfigTestHelper(3, "4G");
+}
+
+// Test that the default limit is used for delayable requests when the
+// experiment is enabled, but the current effective connection type is higher
+// than the maximum effective connection type set in the experiment
+// configuration.
+TEST_F(ResourceSchedulerTest, NonDelayableThrottlesDelayableOutsideECT) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ const double kNonDelayableWeight = 2.0;
+ const int kDefaultMaxNumDelayableRequestsPerClient =
+ 10; // Should be in sync with cc.
+ // Initialize the experiment with |kNonDelayableWeight| as the weight of
+ // non-delayable requests.
+ InitializeThrottleDelayableExperiment(&scoped_feature_list, false,
+ kNonDelayableWeight);
+ // Experiment should not run when the effective connection type is faster
+ // than 2G.
+ network_quality_estimator_.set_effective_connection_type(
+ net::EFFECTIVE_CONNECTION_TYPE_3G);
+ // Limit will only trigger after the page has a body.
+
+ InitializeScheduler();
+ scheduler()->OnWillInsertBody(kChildId, kRouteId);
+ // Insert one non-delayable request. This should not affect the number of
+ // delayable requests started.
+ std::unique_ptr<TestRequest> medium(
+ NewRequest("http://host/medium", net::MEDIUM));
+ ASSERT_TRUE(medium->started());
+ // Start |kDefaultMaxNumDelayableRequestsPerClient| delayable requests and
+ // verify that they all started.
+ std::vector<std::unique_ptr<TestRequest>> delayable_requests;
+ for (int i = 0; i < kDefaultMaxNumDelayableRequestsPerClient; ++i) {
+ delayable_requests.push_back(NewRequest(
+ base::StringPrintf("http://host%d/low", i).c_str(), net::LOWEST));
+ EXPECT_TRUE(delayable_requests.back()->started());
+ }
+}
+
+// Test that delayable requests are throttled by the right amount as the number
+// of non-delayable requests in-flight change.
+TEST_F(ResourceSchedulerTest, NonDelayableThrottlesDelayableVaryNonDelayable) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ const double kNonDelayableWeight = 2.0;
+ const int kDefaultMaxNumDelayableRequestsPerClient =
+ 10; // Should be in sync with cc.
+ // Initialize the experiment with |kNonDelayableWeight| as the weight of
+ // non-delayable requests.
+ InitializeThrottleDelayableExperiment(&scoped_feature_list, false,
+ kNonDelayableWeight);
+ network_quality_estimator_.set_effective_connection_type(
+ net::EFFECTIVE_CONNECTION_TYPE_2G);
+
+ InitializeScheduler();
+ // Limit will only trigger after the page has a body.
+ scheduler()->OnWillInsertBody(kChildId, kRouteId);
+ for (int num_non_delayable = 0; num_non_delayable < 10; ++num_non_delayable) {
+ base::RunLoop().RunUntilIdle();
+ // Start the non-delayable requests.
+ std::vector<std::unique_ptr<TestRequest>> non_delayable_requests;
+ for (int i = 0; i < num_non_delayable; ++i) {
+ non_delayable_requests.push_back(NewRequest(
+ base::StringPrintf("http://host%d/medium", i).c_str(), net::MEDIUM));
+ ASSERT_TRUE(non_delayable_requests.back()->started());
+ }
+ // Start |kDefaultMaxNumDelayableRequestsPerClient| - |num_non_delayable| *
+ // |kNonDelayableWeight| delayable requests. They should all start.
+ std::vector<std::unique_ptr<TestRequest>> delayable_requests;
+ for (int i = 0; i < kDefaultMaxNumDelayableRequestsPerClient -
+ num_non_delayable * kNonDelayableWeight;
+ ++i) {
+ delayable_requests.push_back(NewRequest(
+ base::StringPrintf("http://host%d/low", i).c_str(), net::LOWEST));
+ EXPECT_TRUE(delayable_requests.back()->started());
+ }
+ // The next delayable request should not start.
+ std::unique_ptr<TestRequest> last_low(
+ NewRequest("http://lasthost/low", net::LOWEST));
+ EXPECT_FALSE(last_low->started());
+ }
+}
+
+// Test that the default limit is used for delayable requests in the presence of
+// non-delayable requests when the non-delayable request weight is zero.
+TEST_F(ResourceSchedulerTest, NonDelayableThrottlesDelayableWeight0) {
+ NonDelayableThrottlesDelayableHelper(0.0);
+}
+
+// Test that each non-delayable request in-flight results in the reduction of
+// one in the limit of delayable requests in-flight when the non-delayable
+// request weight is 1.
+TEST_F(ResourceSchedulerTest, NonDelayableThrottlesDelayableWeight1) {
+ NonDelayableThrottlesDelayableHelper(1.0);
+}
+
+// Test that each non-delayable request in-flight results in the reduction of
+// three in the limit of delayable requests in-flight when the non-delayable
+// request weight is 3.
+TEST_F(ResourceSchedulerTest, NonDelayableThrottlesDelayableWeight3) {
+ NonDelayableThrottlesDelayableHelper(3.0);
+}
+
+// Test that UMA counts are recorded for the number of delayable requests
+// in-flight when a non-delayable request starts.
+TEST_F(ResourceSchedulerTest, NumDelayableAtStartOfNonDelayableUMA) {
+ std::unique_ptr<base::HistogramTester> histogram_tester(
+ new base::HistogramTester);
+ scheduler()->OnWillInsertBody(kChildId, kRouteId);
+ // Check that 0 is recorded when a non-delayable request starts and there are
+ // no delayable requests in-flight.
+ std::unique_ptr<TestRequest> high(
+ NewRequest("http://host/high", net::HIGHEST));
+ EXPECT_TRUE(high->started());
+ histogram_tester->ExpectUniqueSample(
+ "ResourceScheduler.NumDelayableRequestsInFlightAtStart.NonDelayable", 0,
+ 1);
+ histogram_tester.reset(new base::HistogramTester);
+ // Check that nothing is recorded when delayable request is started in the
+ // presence of a non-delayable request.
+ std::unique_ptr<TestRequest> low1(
+ NewRequest("http://host/low1", net::LOWEST));
+ EXPECT_TRUE(low1->started());
+ histogram_tester->ExpectTotalCount(
+ "ResourceScheduler.NumDelayableRequestsInFlightAtStart.NonDelayable", 0);
+ // Check that nothing is recorded when a delayable request is started in the
+ // presence of another delayable request.
+ std::unique_ptr<TestRequest> low2(
+ NewRequest("http://host/low2", net::LOWEST));
+ histogram_tester->ExpectTotalCount(
+ "ResourceScheduler.NumDelayableRequestsInFlightAtStart.NonDelayable", 0);
+ // Check that UMA is recorded when a non-delayable startes in the presence of
+ // delayable requests and that the correct value is recorded.
+ std::unique_ptr<TestRequest> high2(
+ NewRequest("http://host/high2", net::HIGHEST));
+ histogram_tester->ExpectUniqueSample(
+ "ResourceScheduler.NumDelayableRequestsInFlightAtStart.NonDelayable", 2,
+ 1);
+}
+
} // unnamed namespace
} // namespace content
diff --git a/chromium/content/browser/loader/sync_resource_handler.cc b/chromium/content/browser/loader/sync_resource_handler.cc
index 596fbc931f1..e65d9e53728 100644
--- a/chromium/content/browser/loader/sync_resource_handler.cc
+++ b/chromium/content/browser/loader/sync_resource_handler.cc
@@ -6,7 +6,6 @@
#include "base/callback_helpers.h"
#include "base/logging.h"
-#include "content/browser/loader/netlog_observer.h"
#include "content/browser/loader/resource_controller.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/loader/resource_request_info_impl.h"
@@ -46,7 +45,6 @@ void SyncResourceHandler::OnRequestRedirected(
response);
}
- NetLogObserver::PopulateResponseInfo(request(), response);
// TODO(darin): It would be much better if this could live in WebCore, but
// doing so requires API changes at all levels. Similar code exists in
// WebCore/platform/network/cf/ResourceHandleCFNet.cpp :-(
@@ -76,8 +74,6 @@ void SyncResourceHandler::OnResponseStarted(
response);
}
- NetLogObserver::PopulateResponseInfo(request(), response);
-
// We don't care about copying the status here.
result_.headers = response->head.headers;
result_.mime_type = response->head.mime_type;
@@ -87,6 +83,7 @@ void SyncResourceHandler::OnResponseStarted(
result_.response_time = response->head.response_time;
result_.load_timing = response->head.load_timing;
result_.devtools_info = response->head.devtools_info;
+ result_.socket_address = response->head.socket_address;
controller->Resume();
}
diff --git a/chromium/content/browser/loader/throttling_resource_handler.cc b/chromium/content/browser/loader/throttling_resource_handler.cc
index a106f05fb5e..e3f89d5040d 100644
--- a/chromium/content/browser/loader/throttling_resource_handler.cc
+++ b/chromium/content/browser/loader/throttling_resource_handler.cc
@@ -126,15 +126,6 @@ void ThrottlingResourceHandler::Cancel() {
ResourceHandler::Cancel();
}
-void ThrottlingResourceHandler::CancelAndIgnore() {
- if (!has_controller()) {
- OutOfBandCancel(net::ERR_ABORTED, false /* tell_renderer */);
- return;
- }
- cancelled_by_resource_throttle_ = true;
- ResourceHandler::CancelAndIgnore();
-}
-
void ThrottlingResourceHandler::CancelWithError(int error_code) {
if (!has_controller()) {
OutOfBandCancel(error_code, false /* tell_renderer */);
diff --git a/chromium/content/browser/loader/throttling_resource_handler.h b/chromium/content/browser/loader/throttling_resource_handler.h
index c089979ae5e..518ec5c0d07 100644
--- a/chromium/content/browser/loader/throttling_resource_handler.h
+++ b/chromium/content/browser/loader/throttling_resource_handler.h
@@ -50,7 +50,6 @@ class CONTENT_EXPORT ThrottlingResourceHandler
// ResourceThrottle::Delegate implementation:
void Cancel() override;
- void CancelAndIgnore() override;
void CancelWithError(int error_code) override;
void Resume() override;
diff --git a/chromium/content/browser/loader/upload_progress_tracker.h b/chromium/content/browser/loader/upload_progress_tracker.h
index 236ced27a5f..11785e51618 100644
--- a/chromium/content/browser/loader/upload_progress_tracker.h
+++ b/chromium/content/browser/loader/upload_progress_tracker.h
@@ -39,7 +39,7 @@ class CONTENT_EXPORT UploadProgressTracker {
net::URLRequest* request,
scoped_refptr<base::SequencedTaskRunner> task_runner =
base::SequencedTaskRunnerHandle::Get());
- ~UploadProgressTracker();
+ virtual ~UploadProgressTracker();
void OnAckReceived();
void OnUploadCompleted();
diff --git a/chromium/content/browser/loader/url_loader_factory_impl.cc b/chromium/content/browser/loader/url_loader_factory_impl.cc
index 1c761e55bf2..544e82cb9f7 100644
--- a/chromium/content/browser/loader/url_loader_factory_impl.cc
+++ b/chromium/content/browser/loader/url_loader_factory_impl.cc
@@ -14,25 +14,6 @@
namespace content {
-namespace {
-
-void DispatchSyncLoadResult(URLLoaderFactoryImpl::SyncLoadCallback callback,
- const SyncLoadResult* result) {
- // |result| can be null when a loading task is aborted unexpectedly. Reply
- // with a failure result on that case.
- // TODO(tzik): Test null-result case.
- if (!result) {
- SyncLoadResult failure;
- failure.error_code = net::ERR_FAILED;
- std::move(callback).Run(failure);
- return;
- }
-
- std::move(callback).Run(*result);
-}
-
-} // namespace
-
URLLoaderFactoryImpl::URLLoaderFactoryImpl(
scoped_refptr<ResourceRequesterInfo> requester_info,
const scoped_refptr<base::SingleThreadTaskRunner>& io_thread_runner)
@@ -41,6 +22,8 @@ URLLoaderFactoryImpl::URLLoaderFactoryImpl(
DCHECK((requester_info_->IsRenderer() && requester_info_->filter()) ||
requester_info_->IsNavigationPreload());
DCHECK(io_thread_task_runner_->BelongsToCurrentThread());
+ bindings_.set_connection_error_handler(base::Bind(
+ &URLLoaderFactoryImpl::OnConnectionError, base::Unretained(this)));
}
URLLoaderFactoryImpl::~URLLoaderFactoryImpl() {
@@ -48,34 +31,30 @@ URLLoaderFactoryImpl::~URLLoaderFactoryImpl() {
}
void URLLoaderFactoryImpl::CreateLoaderAndStart(
- mojom::URLLoaderAssociatedRequest request,
+ mojom::URLLoaderRequest request,
int32_t routing_id,
int32_t request_id,
uint32_t options,
const ResourceRequest& url_request,
mojom::URLLoaderClientPtr client,
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) {
- DCHECK_EQ(options, mojom::kURLLoadOptionNone);
CreateLoaderAndStart(
requester_info_.get(), std::move(request), routing_id, request_id,
- url_request, std::move(client),
+ options, url_request, std::move(client),
static_cast<net::NetworkTrafficAnnotationTag>(traffic_annotation));
}
-void URLLoaderFactoryImpl::SyncLoad(int32_t routing_id,
- int32_t request_id,
- const ResourceRequest& url_request,
- SyncLoadCallback callback) {
- SyncLoad(requester_info_.get(), routing_id, request_id, url_request,
- std::move(callback));
+void URLLoaderFactoryImpl::Clone(mojom::URLLoaderFactoryRequest request) {
+ bindings_.AddBinding(this, std::move(request));
}
// static
void URLLoaderFactoryImpl::CreateLoaderAndStart(
ResourceRequesterInfo* requester_info,
- mojom::URLLoaderAssociatedRequest request,
+ mojom::URLLoaderRequest request,
int32_t routing_id,
int32_t request_id,
+ uint32_t options,
const ResourceRequest& url_request,
mojom::URLLoaderClientPtr client,
const net::NetworkTrafficAnnotationTag& traffic_annotation) {
@@ -85,33 +64,26 @@ void URLLoaderFactoryImpl::CreateLoaderAndStart(
ResourceDispatcherHostImpl* rdh = ResourceDispatcherHostImpl::Get();
rdh->OnRequestResourceWithMojo(requester_info, routing_id, request_id,
- url_request, std::move(request),
+ options, url_request, std::move(request),
std::move(client), traffic_annotation);
}
// static
-void URLLoaderFactoryImpl::SyncLoad(ResourceRequesterInfo* requester_info,
- int32_t routing_id,
- int32_t request_id,
- const ResourceRequest& url_request,
- SyncLoadCallback callback) {
- DCHECK(ResourceDispatcherHostImpl::Get()
- ->io_thread_task_runner()
- ->BelongsToCurrentThread());
-
- ResourceDispatcherHostImpl* rdh = ResourceDispatcherHostImpl::Get();
- rdh->OnSyncLoadWithMojo(
- requester_info, routing_id, request_id, url_request,
- base::Bind(&DispatchSyncLoadResult, base::Passed(&callback)));
-}
-
void URLLoaderFactoryImpl::Create(
scoped_refptr<ResourceRequesterInfo> requester_info,
- mojo::InterfaceRequest<mojom::URLLoaderFactory> request,
+ mojom::URLLoaderFactoryRequest request,
const scoped_refptr<base::SingleThreadTaskRunner>& io_thread_runner) {
- mojo::MakeStrongBinding(base::WrapUnique(new URLLoaderFactoryImpl(
- std::move(requester_info), io_thread_runner)),
- std::move(request));
+ // This instance is effectively reference counted by the number of pipes open
+ // to it and will get deleted when all clients drop their connections.
+ // Please see OnConnectionError() for details.
+ auto* impl =
+ new URLLoaderFactoryImpl(std::move(requester_info), io_thread_runner);
+ impl->Clone(std::move(request));
+}
+
+void URLLoaderFactoryImpl::OnConnectionError() {
+ if (bindings_.empty())
+ delete this;
}
} // namespace content
diff --git a/chromium/content/browser/loader/url_loader_factory_impl.h b/chromium/content/browser/loader/url_loader_factory_impl.h
index 6177975c7ad..caa72a318a8 100644
--- a/chromium/content/browser/loader/url_loader_factory_impl.h
+++ b/chromium/content/browser/loader/url_loader_factory_impl.h
@@ -10,6 +10,7 @@
#include "base/single_thread_task_runner.h"
#include "content/common/content_export.h"
#include "content/public/common/url_loader_factory.mojom.h"
+#include "mojo/public/cpp/bindings/binding_set.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
namespace content {
@@ -23,7 +24,7 @@ class URLLoaderFactoryImpl final : public mojom::URLLoaderFactory {
public:
~URLLoaderFactoryImpl() override;
- void CreateLoaderAndStart(mojom::URLLoaderAssociatedRequest request,
+ void CreateLoaderAndStart(mojom::URLLoaderRequest request,
int32_t routing_id,
int32_t request_id,
uint32_t options,
@@ -31,26 +32,18 @@ class URLLoaderFactoryImpl final : public mojom::URLLoaderFactory {
mojom::URLLoaderClientPtr client,
const net::MutableNetworkTrafficAnnotationTag&
traffic_annotation) override;
- void SyncLoad(int32_t routing_id,
- int32_t request_id,
- const ResourceRequest& request,
- SyncLoadCallback callback) override;
+ void Clone(mojom::URLLoaderFactoryRequest request) override;
static void CreateLoaderAndStart(
ResourceRequesterInfo* requester_info,
- mojom::URLLoaderAssociatedRequest request,
+ mojom::URLLoaderRequest request,
int32_t routing_id,
int32_t request_id,
+ uint32_t options,
const ResourceRequest& url_request,
mojom::URLLoaderClientPtr client,
const net::NetworkTrafficAnnotationTag& traffic_annotation);
- static void SyncLoad(ResourceRequesterInfo* requester_info,
- int32_t routing_id,
- int32_t request_id,
- const ResourceRequest& request,
- SyncLoadCallback callback);
-
// Creates a URLLoaderFactoryImpl instance. The instance is held by the
// StrongBinding in it, so this function doesn't return the instance.
CONTENT_EXPORT static void Create(
@@ -63,6 +56,10 @@ class URLLoaderFactoryImpl final : public mojom::URLLoaderFactory {
scoped_refptr<ResourceRequesterInfo> requester_info,
const scoped_refptr<base::SingleThreadTaskRunner>& io_thread_runner);
+ void OnConnectionError();
+
+ mojo::BindingSet<mojom::URLLoaderFactory> bindings_;
+
scoped_refptr<ResourceRequesterInfo> requester_info_;
// Task runner for the IO thead.
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 c477cf63370..7d58b15a607 100644
--- a/chromium/content/browser/loader/url_loader_factory_impl_unittest.cc
+++ b/chromium/content/browser/loader/url_loader_factory_impl_unittest.cc
@@ -149,7 +149,7 @@ TEST_P(URLLoaderFactoryImplTest, GetResponse) {
constexpr int32_t kRoutingId = 81;
constexpr int32_t kRequestId = 28;
NavigationResourceThrottle::set_ui_checks_always_succeed_for_testing(true);
- mojom::URLLoaderAssociatedPtr loader;
+ mojom::URLLoaderPtr loader;
base::FilePath root;
PathService::Get(DIR_TEST_DATA, &root);
net::URLRequestMockHTTPJob::AddUrlHandlers(root);
@@ -202,8 +202,8 @@ TEST_P(URLLoaderFactoryImplTest, GetResponse) {
while (true) {
char buffer[16];
uint32_t read_size = sizeof(buffer);
- MojoResult r = mojo::ReadDataRaw(client.response_body(), buffer, &read_size,
- MOJO_READ_DATA_FLAG_NONE);
+ MojoResult r = client.response_body().ReadData(buffer, &read_size,
+ MOJO_READ_DATA_FLAG_NONE);
if (r == MOJO_RESULT_FAILED_PRECONDITION)
break;
if (r == MOJO_RESULT_SHOULD_WAIT)
@@ -228,7 +228,7 @@ TEST_P(URLLoaderFactoryImplTest, GetResponse) {
TEST_P(URLLoaderFactoryImplTest, GetFailedResponse) {
NavigationResourceThrottle::set_ui_checks_always_succeed_for_testing(true);
- mojom::URLLoaderAssociatedPtr loader;
+ mojom::URLLoaderPtr loader;
ResourceRequest request;
TestURLLoaderClient client;
net::URLRequestFailedJob::AddUrlHandler();
@@ -258,7 +258,7 @@ TEST_P(URLLoaderFactoryImplTest, GetFailedResponse) {
// In this case, the loading fails after receiving a response.
TEST_P(URLLoaderFactoryImplTest, GetFailedResponse2) {
NavigationResourceThrottle::set_ui_checks_always_succeed_for_testing(true);
- mojom::URLLoaderAssociatedPtr loader;
+ mojom::URLLoaderPtr loader;
ResourceRequest request;
TestURLLoaderClient client;
net::URLRequestFailedJob::AddUrlHandler();
@@ -287,7 +287,7 @@ TEST_P(URLLoaderFactoryImplTest, GetFailedResponse2) {
// This test tests a case where resource loading is cancelled before started.
TEST_P(URLLoaderFactoryImplTest, InvalidURL) {
- mojom::URLLoaderAssociatedPtr loader;
+ mojom::URLLoaderPtr loader;
ResourceRequest request;
TestURLLoaderClient client;
request.url = GURL();
@@ -313,7 +313,7 @@ TEST_P(URLLoaderFactoryImplTest, InvalidURL) {
// This test tests a case where resource loading is cancelled before started.
TEST_P(URLLoaderFactoryImplTest, ShouldNotRequestURL) {
- mojom::URLLoaderAssociatedPtr loader;
+ mojom::URLLoaderPtr loader;
RejectingResourceDispatcherHostDelegate rdh_delegate;
rdh_.SetDelegate(&rdh_delegate);
ResourceRequest request;
@@ -344,7 +344,7 @@ TEST_P(URLLoaderFactoryImplTest, DownloadToFile) {
constexpr int32_t kRoutingId = 1;
constexpr int32_t kRequestId = 2;
- mojom::URLLoaderAssociatedPtr loader;
+ mojom::URLLoaderPtr loader;
base::FilePath root;
PathService::Get(DIR_TEST_DATA, &root);
net::URLRequestMockHTTPJob::AddUrlHandlers(root);
@@ -412,7 +412,7 @@ TEST_P(URLLoaderFactoryImplTest, DownloadToFileFailure) {
constexpr int32_t kRoutingId = 1;
constexpr int32_t kRequestId = 2;
- mojom::URLLoaderAssociatedPtr loader;
+ mojom::URLLoaderPtr loader;
base::FilePath root;
PathService::Get(DIR_TEST_DATA, &root);
net::URLRequestSlowDownloadJob::AddUrlHandler();
@@ -471,7 +471,7 @@ TEST_P(URLLoaderFactoryImplTest, OnTransferSizeUpdated) {
constexpr int32_t kRoutingId = 81;
constexpr int32_t kRequestId = 28;
NavigationResourceThrottle::set_ui_checks_always_succeed_for_testing(true);
- mojom::URLLoaderAssociatedPtr loader;
+ mojom::URLLoaderPtr loader;
base::FilePath root;
PathService::Get(DIR_TEST_DATA, &root);
net::URLRequestMockHTTPJob::AddUrlHandlers(root);
@@ -498,8 +498,8 @@ TEST_P(URLLoaderFactoryImplTest, OnTransferSizeUpdated) {
while (true) {
char buffer[16];
uint32_t read_size = sizeof(buffer);
- MojoResult r = mojo::ReadDataRaw(client.response_body(), buffer, &read_size,
- MOJO_READ_DATA_FLAG_NONE);
+ MojoResult r = client.response_body().ReadData(buffer, &read_size,
+ MOJO_READ_DATA_FLAG_NONE);
if (r == MOJO_RESULT_FAILED_PRECONDITION)
break;
if (r == MOJO_RESULT_SHOULD_WAIT)
@@ -532,7 +532,7 @@ TEST_P(URLLoaderFactoryImplTest, CancelFromRenderer) {
constexpr int32_t kRoutingId = 81;
constexpr int32_t kRequestId = 28;
NavigationResourceThrottle::set_ui_checks_always_succeed_for_testing(true);
- mojom::URLLoaderAssociatedPtr loader;
+ mojom::URLLoaderPtr loader;
base::FilePath root;
PathService::Get(DIR_TEST_DATA, &root);
net::URLRequestFailedJob::AddUrlHandler();
diff --git a/chromium/content/browser/loader/url_loader_request_handler.cc b/chromium/content/browser/loader/url_loader_request_handler.cc
index 0925e224cfb..731e9de8cb6 100644
--- a/chromium/content/browser/loader/url_loader_request_handler.cc
+++ b/chromium/content/browser/loader/url_loader_request_handler.cc
@@ -11,4 +11,11 @@ URLLoaderRequestHandler::MaybeCreateSubresourceFactory() {
return nullptr;
}
+bool URLLoaderRequestHandler::MaybeCreateLoaderForResponse(
+ const ResourceResponseHead& response,
+ mojom::URLLoaderPtr* loader,
+ mojom::URLLoaderClientRequest* client_request) {
+ return false;
+}
+
} // namespace content \ No newline at end of file
diff --git a/chromium/content/browser/loader/url_loader_request_handler.h b/chromium/content/browser/loader/url_loader_request_handler.h
index fb0a1f4b2f3..b73661873e3 100644
--- a/chromium/content/browser/loader/url_loader_request_handler.h
+++ b/chromium/content/browser/loader/url_loader_request_handler.h
@@ -10,6 +10,7 @@
#include "base/macros.h"
#include "content/public/common/url_loader.mojom.h"
#include "content/public/common/url_loader_factory.mojom.h"
+#include "net/url_request/redirect_info.h"
namespace content {
@@ -39,6 +40,17 @@ class CONTENT_EXPORT URLLoaderRequestHandler {
// going forward. Subclasses who want to handle subresource requests etc may
// want to override this to return a custom factory.
virtual mojom::URLLoaderFactoryPtr MaybeCreateSubresourceFactory();
+
+ // Returns true if the handler creates a loader for the |response| passed.
+ // An example of where this is used is AppCache, where the handler returns
+ // fallback content for the response passed in.
+ // The URLLoader interface pointer is returned in the |loader| parameter.
+ // The interface request for the URLLoaderClient is returned in the
+ // |client_request| parameter.
+ virtual bool MaybeCreateLoaderForResponse(
+ const ResourceResponseHead& response,
+ mojom::URLLoaderPtr* loader,
+ mojom::URLLoaderClientRequest* client_request);
};
} // namespace content
diff --git a/chromium/content/browser/mach_broker_mac_unittest.cc b/chromium/content/browser/mach_broker_mac_unittest.cc
index a170d43cfc3..261f500a563 100644
--- a/chromium/content/browser/mach_broker_mac_unittest.cc
+++ b/chromium/content/browser/mach_broker_mac_unittest.cc
@@ -42,15 +42,14 @@ class MachBrokerTest : public testing::Test,
return broker_.child_process_id_map_.count(child_process_id);
}
- base::SpawnChildResult LaunchTestChild(const std::string& function,
- int child_process_id) {
+ base::Process LaunchTestChild(const std::string& function,
+ int child_process_id) {
base::AutoLock lock(broker_.GetLock());
- base::SpawnChildResult spawn_child = base::SpawnMultiProcessTestChild(
+ base::Process test_child_process = base::SpawnMultiProcessTestChild(
function, base::GetMultiProcessTestChildBaseCommandLine(),
base::LaunchOptions());
- broker_.AddPlaceholderForPid(spawn_child.process.Handle(),
- child_process_id);
- return spawn_child;
+ broker_.AddPlaceholderForPid(test_child_process.Handle(), child_process_id);
+ return test_child_process;
}
void WaitForChildExit(base::Process& process) {
@@ -92,23 +91,22 @@ TEST_F(MachBrokerTest, AddChildProcess) {
base::AutoLock lock(broker_.GetLock());
broker_.EnsureRunning();
}
- base::SpawnChildResult spawn_child =
- LaunchTestChild("MachBrokerTestChild", 7);
+ base::Process child_process = LaunchTestChild("MachBrokerTestChild", 7);
WaitForTaskPort();
- EXPECT_EQ(spawn_child.process.Handle(), received_process_);
- WaitForChildExit(spawn_child.process);
+ EXPECT_EQ(child_process.Handle(), received_process_);
+ WaitForChildExit(child_process);
EXPECT_NE(static_cast<mach_port_t>(MACH_PORT_NULL),
- broker_.TaskForPid(spawn_child.process.Handle()));
+ broker_.TaskForPid(child_process.Handle()));
EXPECT_EQ(1, GetChildProcessCount(7));
// Should be no entry for any other PID.
EXPECT_EQ(static_cast<mach_port_t>(MACH_PORT_NULL),
- broker_.TaskForPid(spawn_child.process.Handle() + 1));
+ broker_.TaskForPid(child_process.Handle() + 1));
InvalidateChildProcessId(7);
EXPECT_EQ(static_cast<mach_port_t>(MACH_PORT_NULL),
- broker_.TaskForPid(spawn_child.process.Handle()));
+ broker_.TaskForPid(child_process.Handle()));
EXPECT_EQ(0, GetChildProcessCount(7));
}
diff --git a/chromium/content/browser/manifest/manifest_icon_selector.cc b/chromium/content/browser/manifest/manifest_icon_selector.cc
index 80dc5a98af6..36edf057bb9 100644
--- a/chromium/content/browser/manifest/manifest_icon_selector.cc
+++ b/chromium/content/browser/manifest/manifest_icon_selector.cc
@@ -8,7 +8,7 @@
#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
-#include "components/mime_util/mime_util.h"
+#include "third_party/WebKit/common/mime_util/mime_util.h"
namespace content {
@@ -31,7 +31,7 @@ GURL ManifestIconSelector::FindBestMatchingIcon(
// Check for supported image MIME types.
if (!icon.type.empty() &&
- !mime_util::IsSupportedImageMimeType(base::UTF16ToUTF8(icon.type))) {
+ !blink::IsSupportedImageMimeType(base::UTF16ToUTF8(icon.type))) {
continue;
}
diff --git a/chromium/content/browser/manifest/manifest_manager_host.h b/chromium/content/browser/manifest/manifest_manager_host.h
index 149572eaae3..b94cbdb536b 100644
--- a/chromium/content/browser/manifest/manifest_manager_host.h
+++ b/chromium/content/browser/manifest/manifest_manager_host.h
@@ -6,7 +6,7 @@
#define CONTENT_BROWSER_MANIFEST_MANIFEST_MANAGER_HOST_H_
#include "base/callback_forward.h"
-#include "base/id_map.h"
+#include "base/containers/id_map.h"
#include "base/macros.h"
#include "content/common/manifest_observer.mojom.h"
#include "content/public/browser/web_contents_binding_set.h"
@@ -41,7 +41,7 @@ class ManifestManagerHost : public WebContentsObserver,
void RenderFrameDeleted(RenderFrameHost* render_frame_host) override;
private:
- using CallbackMap = IDMap<std::unique_ptr<GetManifestCallback>>;
+ using CallbackMap = base::IDMap<std::unique_ptr<GetManifestCallback>>;
blink::mojom::ManifestManager& GetManifestManager();
void OnConnectionError();
diff --git a/chromium/content/browser/media/OWNERS b/chromium/content/browser/media/OWNERS
index 760028a874d..7d1710685d7 100644
--- a/chromium/content/browser/media/OWNERS
+++ b/chromium/content/browser/media/OWNERS
@@ -1,4 +1,6 @@
file://media/OWNERS
+olka@chromium.org
+maxmorin@chromium.org
per-file media_devices_*=guidou@chromium.org
per-file midi_*=toyoshim@chromium.org
diff --git a/chromium/content/browser/media/android/browser_media_player_manager.cc b/chromium/content/browser/media/android/browser_media_player_manager.cc
index f498c4cf1f8..0671a0e90d7 100644
--- a/chromium/content/browser/media/android/browser_media_player_manager.cc
+++ b/chromium/content/browser/media/android/browser_media_player_manager.cc
@@ -93,8 +93,7 @@ BrowserMediaPlayerManager::CreateMediaPlayer(
const std::string user_agent = GetContentClient()->GetUserAgent();
auto media_player_bridge = base::MakeUnique<MediaPlayerBridge>(
media_player_params.player_id, media_player_params.url,
- media_player_params.first_party_for_cookies, user_agent, hide_url_log,
- this,
+ media_player_params.site_for_cookies, user_agent, hide_url_log, this,
base::Bind(&BrowserMediaPlayerManager::OnDecoderResourcesReleased,
weak_ptr_factory_.GetWeakPtr()),
media_player_params.frame_url, media_player_params.allow_credentials);
diff --git a/chromium/content/browser/media/android/browser_surface_view_manager.h b/chromium/content/browser/media/android/browser_surface_view_manager.h
index a15e52e3985..08039efa5e9 100644
--- a/chromium/content/browser/media/android/browser_surface_view_manager.h
+++ b/chromium/content/browser/media/android/browser_surface_view_manager.h
@@ -21,7 +21,7 @@ class RenderFrameHost;
// BrowserSurfaceViewManager creates and owns a ContentVideoView on behalf of
// a fullscreen media player. Its SurfaceView is registered so that a decoder
// in the GPU process can look it up and render to it.
-class CONTENT_EXPORT BrowserSurfaceViewManager
+class CONTENT_EXPORT BrowserSurfaceViewManager final
: public ContentVideoView::Client {
public:
explicit BrowserSurfaceViewManager(RenderFrameHost* render_frame_host);
diff --git a/chromium/content/browser/media/android/media_player_renderer.cc b/chromium/content/browser/media/android/media_player_renderer.cc
index a98c609580e..415a5a66dbe 100644
--- a/chromium/content/browser/media/android/media_player_renderer.cc
+++ b/chromium/content/browser/media/android/media_player_renderer.cc
@@ -79,7 +79,7 @@ void MediaPlayerRenderer::CreateMediaPlayer(
// Force the initialization of |media_resource_getter_| first. If it fails,
// the RenderFrameHost may have been destroyed already.
if (!GetMediaResourceGetter()) {
- DLOG(ERROR) << "Unable to retreive MediaResourceGetter";
+ DLOG(ERROR) << "Unable to retrieve MediaResourceGetter";
init_cb.Run(media::PIPELINE_ERROR_INITIALIZATION_FAILED);
return;
}
@@ -88,10 +88,11 @@ void MediaPlayerRenderer::CreateMediaPlayer(
media_player_.reset(new media::MediaPlayerBridge(
kUnusedAndIrrelevantPlayerId, url_params.media_url,
- url_params.first_party_for_cookies, user_agent,
+ url_params.site_for_cookies, user_agent,
false, // hide_url_log
- this, base::Bind(&MediaPlayerRenderer::OnDecoderResourcesReleased,
- weak_factory_.GetWeakPtr()),
+ this,
+ base::Bind(&MediaPlayerRenderer::OnDecoderResourcesReleased,
+ weak_factory_.GetWeakPtr()),
GURL(), // frame_url
true)); // allow_crendentials
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 05ff22c8ef4..ca8226d2667 100644
--- a/chromium/content/browser/media/android/media_resource_getter_impl.cc
+++ b/chromium/content/browser/media/android/media_resource_getter_impl.cc
@@ -129,7 +129,7 @@ class MediaResourceGetterTask
// Called by MediaResourceGetterImpl to start getting cookies for a URL.
void RequestCookies(const GURL& url,
- const GURL& first_party_for_cookies,
+ const GURL& site_for_cookies,
media::MediaResourceGetter::GetCookieCB callback);
// Returns the task runner that all methods should be called.
@@ -140,7 +140,7 @@ class MediaResourceGetterTask
virtual ~MediaResourceGetterTask();
void CheckPolicyForCookies(const GURL& url,
- const GURL& first_party_for_cookies,
+ const GURL& site_for_cookies,
media::MediaResourceGetter::GetCookieCB callback,
const net::CookieList& cookie_list);
@@ -195,7 +195,7 @@ net::AuthCredentials MediaResourceGetterTask::RequestAuthCredentials(
void MediaResourceGetterTask::RequestCookies(
const GURL& url,
- const GURL& first_party_for_cookies,
+ const GURL& site_for_cookies,
media::MediaResourceGetter::GetCookieCB callback) {
DCHECK(GetTaskRunner()->BelongsToCurrentThread());
ChildProcessSecurityPolicyImpl* policy =
@@ -214,7 +214,7 @@ void MediaResourceGetterTask::RequestCookies(
cookie_store->GetAllCookiesForURLAsync(
url, base::BindOnce(&MediaResourceGetterTask::CheckPolicyForCookies, this,
- url, first_party_for_cookies, std::move(callback)));
+ url, site_for_cookies, std::move(callback)));
}
scoped_refptr<base::SingleThreadTaskRunner>
@@ -224,12 +224,12 @@ MediaResourceGetterTask::GetTaskRunner() const {
void MediaResourceGetterTask::CheckPolicyForCookies(
const GURL& url,
- const GURL& first_party_for_cookies,
+ const GURL& site_for_cookies,
media::MediaResourceGetter::GetCookieCB callback,
const net::CookieList& cookie_list) {
if (GetContentClient()->browser()->AllowGetCookie(
- url, first_party_for_cookies, cookie_list,
- resource_context_, render_process_id_, render_frame_id_)) {
+ url, site_for_cookies, cookie_list, resource_context_,
+ render_process_id_, render_frame_id_)) {
net::CookieStore* cookie_store =
context_getter_->GetURLRequestContext()->cookie_store();
net::CookieOptions options;
@@ -270,7 +270,7 @@ void MediaResourceGetterImpl::GetAuthCredentials(
}
void MediaResourceGetterImpl::GetCookies(const GURL& url,
- const GURL& first_party_for_cookies,
+ const GURL& site_for_cookies,
GetCookieCB callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
scoped_refptr<MediaResourceGetterTask> task = new MediaResourceGetterTask(
@@ -282,7 +282,7 @@ void MediaResourceGetterImpl::GetCookies(const GURL& url,
task->GetTaskRunner()->PostTask(
FROM_HERE,
base::BindOnce(&MediaResourceGetterTask::RequestCookies, task, url,
- first_party_for_cookies,
+ site_for_cookies,
base::BindOnce(&ReturnResultOnUIThread, std::move(cb))));
}
diff --git a/chromium/content/browser/media/android/media_resource_getter_impl.h b/chromium/content/browser/media/android/media_resource_getter_impl.h
index 29d2c7ea702..abab2dabdf9 100644
--- a/chromium/content/browser/media/android/media_resource_getter_impl.h
+++ b/chromium/content/browser/media/android/media_resource_getter_impl.h
@@ -45,7 +45,7 @@ class MediaResourceGetterImpl : public media::MediaResourceGetter {
void GetAuthCredentials(const GURL& url,
GetAuthCredentialsCB callback) override;
void GetCookies(const GURL& url,
- const GURL& first_party_for_cookies,
+ const GURL& site_for_cookies,
GetCookieCB callback) override;
void GetPlatformPathFromURL(const GURL& url,
GetPlatformPathCB callback) override;
diff --git a/chromium/content/browser/media/audio_stream_monitor.cc b/chromium/content/browser/media/audio_stream_monitor.cc
index de5a2d96b94..427d7dddba7 100644
--- a/chromium/content/browser/media/audio_stream_monitor.cc
+++ b/chromium/content/browser/media/audio_stream_monitor.cc
@@ -96,25 +96,20 @@ void AudioStreamMonitor::StartMonitoringStream(
int render_frame_id,
int stream_id,
const ReadPowerAndClipCallback& read_power_callback) {
- BrowserThread::PostTask(BrowserThread::UI,
- FROM_HERE,
- base::Bind(&StartMonitoringHelper,
- render_process_id,
- render_frame_id,
- stream_id,
- read_power_callback));
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&StartMonitoringHelper, render_process_id, render_frame_id,
+ stream_id, read_power_callback));
}
// static
void AudioStreamMonitor::StopMonitoringStream(int render_process_id,
int render_frame_id,
int stream_id) {
- BrowserThread::PostTask(BrowserThread::UI,
- FROM_HERE,
- base::Bind(&StopMonitoringHelper,
- render_process_id,
- render_frame_id,
- stream_id));
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&StopMonitoringHelper, render_process_id, render_frame_id,
+ stream_id));
}
// static
diff --git a/chromium/content/browser/media/capture/OWNERS b/chromium/content/browser/media/capture/OWNERS
index 06e592cdeb3..c9e162eb22d 100644
--- a/chromium/content/browser/media/capture/OWNERS
+++ b/chromium/content/browser/media/capture/OWNERS
@@ -2,6 +2,10 @@ miu@chromium.org
sergeyu@chromium.org
wez@chromium.org
+# For WebRTC desktop capturer
+per-file desktop_capture_device.*=zijiehe@chromium.org
+per-file desktop_capture_device_unittest.cc=zijiehe@chromium.org
+
per-file image_capture*=mcasas@chromium.org
# TEAM: media-capture-and-streams@grotations.appspotmail.com
diff --git a/chromium/content/browser/media/capture/aura_window_capture_machine.cc b/chromium/content/browser/media/capture/aura_window_capture_machine.cc
index 1451a2ff9f4..eaa46f904a6 100644
--- a/chromium/content/browser/media/capture/aura_window_capture_machine.cc
+++ b/chromium/content/browser/media/capture/aura_window_capture_machine.cc
@@ -9,9 +9,9 @@
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
-#include "cc/output/copy_output_request.h"
-#include "cc/output/copy_output_result.h"
#include "components/viz/common/gl_helper.h"
+#include "components/viz/common/quads/copy_output_request.h"
+#include "components/viz/common/quads/copy_output_result.h"
#include "content/browser/compositor/image_transport_factory.h"
#include "content/browser/media/capture/desktop_capture_device_uma_types.h"
#include "content/public/browser/browser_thread.h"
@@ -113,9 +113,10 @@ bool AuraWindowCaptureMachine::InternalStart(
}
void AuraWindowCaptureMachine::Suspend() {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(&AuraWindowCaptureMachine::InternalSuspend,
- base::Unretained(this)));
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&AuraWindowCaptureMachine::InternalSuspend,
+ base::Unretained(this)));
}
void AuraWindowCaptureMachine::InternalSuspend() {
@@ -125,9 +126,10 @@ void AuraWindowCaptureMachine::InternalSuspend() {
}
void AuraWindowCaptureMachine::Resume() {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(&AuraWindowCaptureMachine::InternalResume,
- base::Unretained(this)));
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&AuraWindowCaptureMachine::InternalResume,
+ base::Unretained(this)));
}
void AuraWindowCaptureMachine::InternalResume() {
@@ -142,10 +144,9 @@ void AuraWindowCaptureMachine::InternalResume() {
void AuraWindowCaptureMachine::Stop(const base::Closure& callback) {
// Stops the capture machine asynchronously.
BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE, base::Bind(
- &AuraWindowCaptureMachine::InternalStop,
- base::Unretained(this),
- callback));
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&AuraWindowCaptureMachine::InternalStop,
+ base::Unretained(this), callback));
}
void AuraWindowCaptureMachine::InternalStop(const base::Closure& callback) {
@@ -178,11 +179,11 @@ void AuraWindowCaptureMachine::InternalStop(const base::Closure& callback) {
void AuraWindowCaptureMachine::MaybeCaptureForRefresh() {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&AuraWindowCaptureMachine::Capture,
- // Use of Unretained() is safe here since this task must run
- // before InternalStop().
- base::Unretained(this),
- base::TimeTicks()));
+ base::BindOnce(
+ &AuraWindowCaptureMachine::Capture,
+ // Use of Unretained() is safe here since this task must run
+ // before InternalStop().
+ base::Unretained(this), base::TimeTicks()));
}
void AuraWindowCaptureMachine::SetWindow(aura::Window* window) {
@@ -235,8 +236,8 @@ void AuraWindowCaptureMachine::Capture(base::TimeTicks event_time) {
}
if (oracle_proxy_->ObserveEventAndDecideCapture(
event, gfx::Rect(), event_time, &frame, &capture_frame_cb)) {
- std::unique_ptr<cc::CopyOutputRequest> request =
- cc::CopyOutputRequest::CreateRequest(
+ std::unique_ptr<viz::CopyOutputRequest> request =
+ viz::CopyOutputRequest::CreateRequest(
base::BindOnce(&AuraWindowCaptureMachine::DidCopyOutput,
weak_factory_.GetWeakPtr(), std::move(frame),
event_time, start_time, capture_frame_cb));
@@ -252,7 +253,7 @@ void AuraWindowCaptureMachine::DidCopyOutput(
base::TimeTicks event_time,
base::TimeTicks start_time,
const CaptureFrameCallback& capture_frame_cb,
- std::unique_ptr<cc::CopyOutputResult> result) {
+ std::unique_ptr<viz::CopyOutputResult> result) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
static bool first_call = true;
@@ -292,7 +293,7 @@ bool AuraWindowCaptureMachine::ProcessCopyOutputResponse(
scoped_refptr<media::VideoFrame> video_frame,
base::TimeTicks event_time,
const CaptureFrameCallback& capture_frame_cb,
- std::unique_ptr<cc::CopyOutputResult> result) {
+ std::unique_ptr<viz::CopyOutputResult> result) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (!desktop_window_) {
@@ -334,7 +335,7 @@ bool AuraWindowCaptureMachine::ProcessCopyOutputResponse(
}
viz::TextureMailbox texture_mailbox;
- std::unique_ptr<cc::SingleReleaseCallback> release_callback;
+ std::unique_ptr<viz::SingleReleaseCallback> release_callback;
result->TakeTexture(&texture_mailbox, &release_callback);
DCHECK(texture_mailbox.IsTexture());
if (!texture_mailbox.IsTexture()) {
@@ -377,7 +378,7 @@ void AuraWindowCaptureMachine::CopyOutputFinishedForVideo(
base::TimeTicks event_time,
const CaptureFrameCallback& capture_frame_cb,
scoped_refptr<media::VideoFrame> target,
- std::unique_ptr<cc::SingleReleaseCallback> release_callback,
+ std::unique_ptr<viz::SingleReleaseCallback> release_callback,
bool result) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -405,9 +406,10 @@ void AuraWindowCaptureMachine::OnWindowBoundsChanged(
DCHECK(desktop_window_ && window == desktop_window_);
// Post a task to update capture size after first returning to the event loop.
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
- &AuraWindowCaptureMachine::UpdateCaptureSize,
- weak_factory_.GetWeakPtr()));
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&AuraWindowCaptureMachine::UpdateCaptureSize,
+ weak_factory_.GetWeakPtr()));
}
void AuraWindowCaptureMachine::OnWindowDestroying(aura::Window* window) {
diff --git a/chromium/content/browser/media/capture/aura_window_capture_machine.h b/chromium/content/browser/media/capture/aura_window_capture_machine.h
index 5f1bd8abe20..e8de893d92e 100644
--- a/chromium/content/browser/media/capture/aura_window_capture_machine.h
+++ b/chromium/content/browser/media/capture/aura_window_capture_machine.h
@@ -18,11 +18,8 @@
#include "ui/compositor/compositor.h"
#include "ui/compositor/compositor_animation_observer.h"
-namespace cc {
-class CopyOutputResult;
-} // namespace cc
-
namespace viz {
+class CopyOutputResult;
class ReadbackYUVInterface;
}
@@ -84,7 +81,7 @@ class AuraWindowCaptureMachine : public media::VideoCaptureMachine,
base::TimeTicks event_time,
base::TimeTicks start_time,
const CaptureFrameCallback& capture_frame_cb,
- std::unique_ptr<cc::CopyOutputResult> result);
+ std::unique_ptr<viz::CopyOutputResult> result);
// A helper which does the real work for DidCopyOutput. Returns true if
// succeeded and |capture_frame_cb| will be run at some future point. Returns
@@ -93,7 +90,7 @@ class AuraWindowCaptureMachine : public media::VideoCaptureMachine,
bool ProcessCopyOutputResponse(scoped_refptr<media::VideoFrame> video_frame,
base::TimeTicks event_time,
const CaptureFrameCallback& capture_frame_cb,
- std::unique_ptr<cc::CopyOutputResult> result);
+ std::unique_ptr<viz::CopyOutputResult> result);
// ui::ContextFactoryObserver implementation.
void OnLostResources() override;
@@ -104,7 +101,7 @@ class AuraWindowCaptureMachine : public media::VideoCaptureMachine,
base::TimeTicks event_time,
const CaptureFrameCallback& capture_frame_cb,
scoped_refptr<media::VideoFrame> target,
- std::unique_ptr<cc::SingleReleaseCallback> release_callback,
+ std::unique_ptr<viz::SingleReleaseCallback> release_callback,
bool result);
// The window associated with the desktop.
diff --git a/chromium/content/browser/media/capture/desktop_capture_device.cc b/chromium/content/browser/media/capture/desktop_capture_device.cc
index 5c82401e145..7e27e9ac3b6 100644
--- a/chromium/content/browser/media/capture/desktop_capture_device.cc
+++ b/chromium/content/browser/media/capture/desktop_capture_device.cc
@@ -35,6 +35,7 @@
#include "services/device/public/interfaces/wake_lock_provider.mojom.h"
#include "services/service_manager/public/cpp/connector.h"
#include "third_party/libyuv/include/libyuv/scale_argb.h"
+#include "third_party/webrtc/modules/desktop_capture/cropped_desktop_frame.h"
#include "third_party/webrtc/modules/desktop_capture/cropping_window_capturer.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_and_cursor_composer.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_capture_options.h"
@@ -266,17 +267,20 @@ void DesktopCaptureDevice::Core::OnCaptureResult(
}
// Align to 2x2 pixel boundaries, as required by OnIncomingCapturedData() so
// it can convert the frame to I420 format.
- const webrtc::DesktopSize output_size(
+ webrtc::DesktopSize output_size(
resolution_chooser_->capture_size().width() & ~1,
resolution_chooser_->capture_size().height() & ~1);
- if (output_size.is_empty())
- return;
+ if (output_size.is_empty()) {
+ // Even RESOLUTION_POLICY_ANY_WITHIN_LIMIT is used, a non-empty size should
+ // be guaranteed.
+ output_size.set(2, 2);
+ }
size_t output_bytes = output_size.width() * output_size.height() *
webrtc::DesktopFrame::kBytesPerPixel;
const uint8_t* output_data = nullptr;
- if (frame->size().equals(webrtc::DesktopSize(1, 1))) {
+ if (frame->size().width() <= 1 || frame->size().height() <= 1) {
// On OSX We receive a 1x1 frame when the shared window is minimized. It
// cannot be subsampled to I420 and will be dropped downstream. So we
// replace it with a black frame to avoid the video appearing frozen at the
@@ -287,47 +291,68 @@ void DesktopCaptureDevice::Core::OnCaptureResult(
black_frame_->stride() * black_frame_->size().height());
}
output_data = black_frame_->data();
- } else if (!frame->size().equals(output_size)) {
- // Down-scale and/or letterbox to the target format if the frame does not
- // match the output size.
-
- // Allocate a buffer of the correct size to scale the frame into.
- // |output_frame_| is cleared whenever the output size changes, so we don't
- // need to worry about clearing out stale pixel data in letterboxed areas.
- if (!output_frame_) {
- output_frame_.reset(new webrtc::BasicDesktopFrame(output_size));
- memset(output_frame_->data(), 0, output_bytes);
- }
- DCHECK(output_frame_->size().equals(output_size));
-
- // TODO(wez): Optimize this to scale only changed portions of the output,
- // using ARGBScaleClip().
- const webrtc::DesktopRect output_rect =
- ComputeLetterboxRect(output_size, frame->size());
- uint8_t* output_rect_data =
- output_frame_->GetFrameDataAtPos(output_rect.top_left());
- libyuv::ARGBScale(frame->data(), frame->stride(), frame->size().width(),
- frame->size().height(), output_rect_data,
- output_frame_->stride(), output_rect.width(),
- output_rect.height(), libyuv::kFilterBilinear);
- output_data = output_frame_->data();
- } else if (IsFrameUnpackedOrInverted(frame.get())) {
- // If |frame| is not packed top-to-bottom then create a packed top-to-bottom
- // copy.
- // This is required if the frame is inverted (see crbug.com/306876), or if
- // |frame| is cropped form a larger frame (see crbug.com/437740).
- if (!output_frame_) {
- output_frame_.reset(new webrtc::BasicDesktopFrame(output_size));
- memset(output_frame_->data(), 0, output_bytes);
+ } else {
+ // Scaling frame with odd dimensions to even dimensions will cause
+ // blurring. See https://crbug.com/737278.
+ // Since chromium always requests frames to be with even dimensions,
+ // i.e. for I420 format and video codec, always cropping captured frame
+ // to even dimensions.
+ const int32_t frame_width = frame->size().width();
+ const int32_t frame_height = frame->size().height();
+ // TODO(braveyao): remove the check once |CreateCroppedDesktopFrame| can
+ // do this check internally.
+ if (frame_width & 1 || frame_height & 1) {
+ frame = webrtc::CreateCroppedDesktopFrame(
+ std::move(frame),
+ webrtc::DesktopRect::MakeWH(frame_width & ~1, frame_height & ~1));
}
+ DCHECK(frame);
+ DCHECK(!frame->size().is_empty());
+
+ if (!frame->size().equals(output_size)) {
+ // Down-scale and/or letterbox to the target format if the frame does
+ // not match the output size.
+
+ // Allocate a buffer of the correct size to scale the frame into.
+ // |output_frame_| is cleared whenever the output size changes, so we
+ // don't need to worry about clearing out stale pixel data in
+ // letterboxed areas.
+ if (!output_frame_) {
+ output_frame_.reset(new webrtc::BasicDesktopFrame(output_size));
+ memset(output_frame_->data(), 0, output_bytes);
+ }
+ DCHECK(output_frame_->size().equals(output_size));
+
+ // TODO(wez): Optimize this to scale only changed portions of the
+ // output, using ARGBScaleClip().
+ const webrtc::DesktopRect output_rect =
+ ComputeLetterboxRect(output_size, frame->size());
+ uint8_t* output_rect_data =
+ output_frame_->GetFrameDataAtPos(output_rect.top_left());
+ libyuv::ARGBScale(frame->data(), frame->stride(), frame->size().width(),
+ frame->size().height(), output_rect_data,
+ output_frame_->stride(), output_rect.width(),
+ output_rect.height(), libyuv::kFilterBilinear);
+ output_data = output_frame_->data();
+ } else if (IsFrameUnpackedOrInverted(frame.get())) {
+ // If |frame| is not packed top-to-bottom then create a packed
+ // top-to-bottom copy. This is required if the frame is inverted (see
+ // crbug.com/306876), or if |frame| is cropped form a larger frame (see
+ // crbug.com/437740).
+ if (!output_frame_) {
+ output_frame_.reset(new webrtc::BasicDesktopFrame(output_size));
+ memset(output_frame_->data(), 0, output_bytes);
+ }
- output_frame_->CopyPixelsFrom(*frame, webrtc::DesktopVector(),
- webrtc::DesktopRect::MakeSize(frame->size()));
- output_data = output_frame_->data();
- } else {
- // If the captured frame matches the output size, we can return the pixel
- // data directly.
- output_data = frame->data();
+ output_frame_->CopyPixelsFrom(
+ *frame, webrtc::DesktopVector(),
+ webrtc::DesktopRect::MakeSize(frame->size()));
+ output_data = output_frame_->data();
+ } else {
+ // If the captured frame matches the output size, we can return the pixel
+ // data directly.
+ output_data = frame->data();
+ }
}
base::TimeTicks now = base::TimeTicks::Now();
@@ -447,8 +472,8 @@ void DesktopCaptureDevice::AllocateAndStart(
std::unique_ptr<Client> client) {
thread_.task_runner()->PostTask(
FROM_HERE,
- base::Bind(&Core::AllocateAndStart, base::Unretained(core_.get()), params,
- base::Passed(&client)));
+ base::BindOnce(&Core::AllocateAndStart, base::Unretained(core_.get()),
+ params, base::Passed(&client)));
}
void DesktopCaptureDevice::StopAndDeAllocate() {
@@ -465,8 +490,8 @@ void DesktopCaptureDevice::SetNotificationWindowId(
if (!core_)
return;
thread_.task_runner()->PostTask(
- FROM_HERE, base::Bind(&Core::SetNotificationWindowId,
- base::Unretained(core_.get()), window_id));
+ FROM_HERE, base::BindOnce(&Core::SetNotificationWindowId,
+ base::Unretained(core_.get()), window_id));
}
DesktopCaptureDevice::DesktopCaptureDevice(
diff --git a/chromium/content/browser/media/capture/desktop_capture_device_aura.cc b/chromium/content/browser/media/capture/desktop_capture_device_aura.cc
index acd236d3198..a80e01233d3 100644
--- a/chromium/content/browser/media/capture/desktop_capture_device_aura.cc
+++ b/chromium/content/browser/media/capture/desktop_capture_device_aura.cc
@@ -43,7 +43,7 @@ DesktopCaptureDeviceAura::DesktopCaptureDeviceAura(
// |core_| owns |machine| and deletes it on UI thread so passing the raw
// pointer to the UI thread is safe here.
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(&SetCaptureSource, machine, source));
+ base::BindOnce(&SetCaptureSource, machine, source));
}
DesktopCaptureDeviceAura::~DesktopCaptureDeviceAura() {
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 b9f15e6cd06..ecc4b247429 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
@@ -173,7 +173,7 @@ bool WebContentsAudioInputStream::Impl::Open() {
initial_render_process_id_, initial_main_render_frame_id_,
base::Bind(&Impl::OnTargetChanged, this));
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(&Impl::IncrementCapturerCount, this));
+ base::BindOnce(&Impl::IncrementCapturerCount, this));
return true;
}
@@ -207,10 +207,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::Bind(&Impl::UnmuteWebContentsAudio, this));
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&Impl::UnmuteWebContentsAudio, this));
}
void WebContentsAudioInputStream::Impl::Stop() {
@@ -234,8 +232,9 @@ void WebContentsAudioInputStream::Impl::Close() {
if (state_ == OPENED) {
state_ = CONSTRUCTED;
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(&Impl::DecrementCapturerCount, this));
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&Impl::DecrementCapturerCount, this));
tracker_->Stop();
mixer_stream_->Close();
}
@@ -263,18 +262,18 @@ void WebContentsAudioInputStream::Impl::StartMirroring() {
DCHECK(thread_checker_.CalledOnValidThread());
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::Bind(&AudioMirroringManager::StartMirroring,
- base::Unretained(mirroring_manager_),
- base::RetainedRef(this)));
+ 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::Bind(&AudioMirroringManager::StopMirroring,
- base::Unretained(mirroring_manager_),
- base::RetainedRef(this)));
+ base::BindOnce(&AudioMirroringManager::StopMirroring,
+ base::Unretained(mirroring_manager_),
+ base::RetainedRef(this)));
}
void WebContentsAudioInputStream::Impl::UnmuteWebContentsAudio() {
@@ -289,12 +288,9 @@ void WebContentsAudioInputStream::Impl::QueryForMatches(
const std::set<SourceFrameRef>& candidates,
const MatchesCallback& results_callback) {
BrowserThread::PostTask(
- BrowserThread::UI,
- FROM_HERE,
- base::Bind(&Impl::QueryForMatchesOnUIThread,
- this,
- candidates,
- media::BindToCurrentLoop(results_callback)));
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&Impl::QueryForMatchesOnUIThread, this, candidates,
+ media::BindToCurrentLoop(results_callback)));
}
void WebContentsAudioInputStream::Impl::QueryForMatchesOnUIThread(
diff --git a/chromium/content/browser/media/capture/web_contents_audio_input_stream.h b/chromium/content/browser/media/capture/web_contents_audio_input_stream.h
index dd2c0c29d3a..a7047aff624 100644
--- a/chromium/content/browser/media/capture/web_contents_audio_input_stream.h
+++ b/chromium/content/browser/media/capture/web_contents_audio_input_stream.h
@@ -35,7 +35,7 @@ class AudioMirroringManager;
class WebContentsTracker;
class CONTENT_EXPORT WebContentsAudioInputStream
- : NON_EXPORTED_BASE(public media::AudioInputStream) {
+ : public media::AudioInputStream {
public:
// media::AudioInputStream implementation
bool Open() override;
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 2eeb1c08e38..715e30259df 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
@@ -171,7 +171,7 @@ class MockAudioInputCallback : public AudioInputStream::AudioInputCallback {
MOCK_METHOD4(OnData,
void(AudioInputStream* stream,
const media::AudioBus* src,
- uint32_t hardware_delay_bytes,
+ base::TimeTicks capture_time,
double volume));
MOCK_METHOD1(OnError, void(AudioInputStream* stream));
@@ -286,8 +286,8 @@ class WebContentsAudioInputStreamTest : public testing::TestWithParam<bool> {
base::WaitableEvent done(base::WaitableEvent::ResetPolicy::AUTOMATIC,
base::WaitableEvent::InitialState::NOT_SIGNALED);
BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE, base::Bind(
- &base::WaitableEvent::Signal, base::Unretained(&done)));
+ BrowserThread::IO, FROM_HERE,
+ 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 949858bfc31..59a30348350 100644
--- a/chromium/content/browser/media/capture/web_contents_audio_muter.cc
+++ b/chromium/content/browser/media/capture/web_contents_audio_muter.cc
@@ -17,8 +17,8 @@
#include "content/public/browser/web_contents.h"
#include "media/audio/audio_io.h"
#include "media/audio/audio_manager.h"
-#include "media/audio/fake_audio_worker.h"
#include "media/base/bind_to_current_loop.h"
+#include "media/base/fake_audio_worker.h"
namespace content {
@@ -87,12 +87,9 @@ class WebContentsAudioMuter::MuteDestination
void QueryForMatches(const std::set<SourceFrameRef>& candidates,
const MatchesCallback& results_callback) override {
BrowserThread::PostTask(
- BrowserThread::UI,
- FROM_HERE,
- base::Bind(&MuteDestination::QueryForMatchesOnUIThread,
- this,
- candidates,
- media::BindToCurrentLoop(results_callback)));
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&MuteDestination::QueryForMatchesOnUIThread, this,
+ candidates, media::BindToCurrentLoop(results_callback)));
}
void QueryForMatchesOnUIThread(const std::set<SourceFrameRef>& candidates,
@@ -145,9 +142,9 @@ void WebContentsAudioMuter::StartMuting() {
is_muting_ = true;
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&AudioMirroringManager::StartMirroring,
- base::Unretained(AudioMirroringManager::GetInstance()),
- base::RetainedRef(destination_)));
+ base::BindOnce(&AudioMirroringManager::StartMirroring,
+ base::Unretained(AudioMirroringManager::GetInstance()),
+ base::RetainedRef(destination_)));
}
void WebContentsAudioMuter::StopMuting() {
@@ -157,9 +154,9 @@ void WebContentsAudioMuter::StopMuting() {
is_muting_ = false;
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&AudioMirroringManager::StopMirroring,
- base::Unretained(AudioMirroringManager::GetInstance()),
- base::RetainedRef(destination_)));
+ base::BindOnce(&AudioMirroringManager::StopMirroring,
+ base::Unretained(AudioMirroringManager::GetInstance()),
+ base::RetainedRef(destination_)));
}
} // namespace content
diff --git a/chromium/content/browser/media/capture/web_contents_tracker.cc b/chromium/content/browser/media/capture/web_contents_tracker.cc
index 32ba724170a..64abe70e3bc 100644
--- a/chromium/content/browser/media/capture/web_contents_tracker.cc
+++ b/chromium/content/browser/media/capture/web_contents_tracker.cc
@@ -34,8 +34,8 @@ void WebContentsTracker::Start(int render_process_id, int main_render_frame_id,
} else {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&WebContentsTracker::StartObservingWebContents, this,
- render_process_id, main_render_frame_id));
+ base::BindOnce(&WebContentsTracker::StartObservingWebContents, this,
+ render_process_id, main_render_frame_id));
}
}
@@ -49,8 +49,8 @@ void WebContentsTracker::Stop() {
WebContentsObserver::Observe(nullptr);
} else {
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(&WebContentsTracker::Observe, this,
- static_cast<WebContents*>(nullptr)));
+ base::BindOnce(&WebContentsTracker::Observe, this,
+ static_cast<WebContents*>(nullptr)));
}
}
@@ -99,9 +99,9 @@ void WebContentsTracker::OnPossibleTargetChange(bool force_callback_run) {
return;
}
- task_runner_->PostTask(FROM_HERE,
- base::Bind(&WebContentsTracker::MaybeDoCallback, this,
- is_still_tracking()));
+ task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&WebContentsTracker::MaybeDoCallback, this,
+ is_still_tracking()));
}
void WebContentsTracker::MaybeDoCallback(bool was_still_tracking) {
@@ -166,7 +166,7 @@ void WebContentsTracker::MainFrameWasResized(bool width_changed) {
task_runner_->PostTask(
FROM_HERE,
- base::Bind(&WebContentsTracker::MaybeDoResizeCallback, this));
+ base::BindOnce(&WebContentsTracker::MaybeDoResizeCallback, this));
}
void WebContentsTracker::WebContentsDestroyed() {
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 146f3104be8..c64ba5809f2 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
@@ -471,8 +471,8 @@ bool WebContentsCaptureMachine::InternalStart(
void WebContentsCaptureMachine::Suspend() {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&WebContentsCaptureMachine::InternalSuspend,
- base::Unretained(this)));
+ base::BindOnce(&WebContentsCaptureMachine::InternalSuspend,
+ base::Unretained(this)));
}
void WebContentsCaptureMachine::InternalSuspend() {
@@ -485,9 +485,10 @@ void WebContentsCaptureMachine::InternalSuspend() {
}
void WebContentsCaptureMachine::Resume() {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(&WebContentsCaptureMachine::InternalResume,
- base::Unretained(this)));
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&WebContentsCaptureMachine::InternalResume,
+ base::Unretained(this)));
}
void WebContentsCaptureMachine::InternalResume() {
@@ -500,9 +501,10 @@ void WebContentsCaptureMachine::InternalResume() {
}
void WebContentsCaptureMachine::Stop(const base::Closure& callback) {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(&WebContentsCaptureMachine::InternalStop,
- base::Unretained(this), callback));
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&WebContentsCaptureMachine::InternalStop,
+ base::Unretained(this), callback));
}
void WebContentsCaptureMachine::InternalStop(const base::Closure& callback) {
@@ -526,10 +528,11 @@ void WebContentsCaptureMachine::InternalStop(const base::Closure& callback) {
void WebContentsCaptureMachine::MaybeCaptureForRefresh() {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&WebContentsCaptureMachine::InternalMaybeCaptureForRefresh,
- // Use of Unretained() is safe here since this task must run
- // before InternalStop().
- base::Unretained(this)));
+ base::BindOnce(
+ &WebContentsCaptureMachine::InternalMaybeCaptureForRefresh,
+ // Use of Unretained() is safe here since this task must run
+ // before InternalStop().
+ base::Unretained(this)));
}
void WebContentsCaptureMachine::InternalMaybeCaptureForRefresh() {
diff --git a/chromium/content/browser/media/capture/web_contents_video_capture_device_unittest.cc b/chromium/content/browser/media/capture/web_contents_video_capture_device_unittest.cc
index 502b06e3b8d..a291e5f0d76 100644
--- a/chromium/content/browser/media/capture/web_contents_video_capture_device_unittest.cc
+++ b/chromium/content/browser/media/capture/web_contents_video_capture_device_unittest.cc
@@ -143,7 +143,7 @@ class CaptureTestView : public TestRenderWidgetHostView {
media::FillYUV(target.get(), SkColorGetR(yuv_color_),
SkColorGetG(yuv_color_), SkColorGetB(yuv_color_));
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(callback, gfx::Rect(), true));
+ base::BindOnce(callback, gfx::Rect(), true));
}
void BeginFrameSubscription(
@@ -191,6 +191,7 @@ class CaptureTestRenderViewHost : public TestRenderViewHost {
widget_delegate,
instance->GetProcess(),
routing_id,
+ nullptr,
false /* This means: "Is not hidden." */),
delegate,
main_frame_routing_id,
@@ -371,7 +372,7 @@ class StubClientObserver {
wait_color_yuv_ == color) {
last_frame_color_yuv_ = color;
last_frame_size_ = size;
- base::MessageLoop::current()->QuitWhenIdle();
+ base::RunLoop::QuitCurrentWhenIdleDeprecated();
}
}
@@ -413,19 +414,17 @@ class StubClientObserver {
void OnError() {
error_encountered_ = true;
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
- &StubClientObserver::QuitIfConditionsMet,
- base::Unretained(this),
- kNothingYet,
- gfx::Size()));
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&StubClientObserver::QuitIfConditionsMet,
+ base::Unretained(this), kNothingYet, gfx::Size()));
}
void DidDeliverFrame(SkColor color, const gfx::Size& size) {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
- &StubClientObserver::QuitIfConditionsMet,
- base::Unretained(this),
- color,
- size));
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&StubClientObserver::QuitIfConditionsMet,
+ base::Unretained(this), color, size));
}
private:
@@ -552,8 +551,8 @@ class WebContentsVideoCaptureDeviceTest : public testing::Test {
// Schedule the update to occur when the test runs the event loop (and not
// before expectations have been set).
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(&CaptureTestView::SimulateUpdate,
- base::Unretained(test_view())));
+ base::BindOnce(&CaptureTestView::SimulateUpdate,
+ base::Unretained(test_view())));
}
void SimulateSourceSizeChange(const gfx::Size& size) {
@@ -607,8 +606,8 @@ class WebContentsVideoCaptureDeviceTest : public testing::Test {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&media::VideoCaptureDevice::RequestRefreshFrame,
- base::Unretained(device_.get())));
+ base::BindOnce(&media::VideoCaptureDevice::RequestRefreshFrame,
+ base::Unretained(device_.get())));
}
void DestroyVideoCaptureDevice() { device_.reset(); }
@@ -678,8 +677,8 @@ TEST_F(WebContentsVideoCaptureDeviceTest,
// consumer.
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&WebContentsVideoCaptureDeviceTest::ResetWebContents,
- base::Unretained(this)));
+ base::BindOnce(&WebContentsVideoCaptureDeviceTest::ResetWebContents,
+ base::Unretained(this)));
ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForError());
device()->StopAndDeAllocate();
}
diff --git a/chromium/content/browser/media/cdm_registry_impl.h b/chromium/content/browser/media/cdm_registry_impl.h
index f2bd940a92b..303f3c59b32 100644
--- a/chromium/content/browser/media/cdm_registry_impl.h
+++ b/chromium/content/browser/media/cdm_registry_impl.h
@@ -16,7 +16,7 @@ namespace content {
struct CdmInfo;
-class CONTENT_EXPORT CdmRegistryImpl : NON_EXPORTED_BASE(public CdmRegistry) {
+class CONTENT_EXPORT CdmRegistryImpl : public CdmRegistry {
public:
// Returns the CdmRegistryImpl singleton.
static CdmRegistryImpl* GetInstance();
diff --git a/chromium/content/browser/media/encrypted_media_browsertest.cc b/chromium/content/browser/media/encrypted_media_browsertest.cc
index 0a3bdc7847b..434cee39366 100644
--- a/chromium/content/browser/media/encrypted_media_browsertest.cc
+++ b/chromium/content/browser/media/encrypted_media_browsertest.cc
@@ -13,8 +13,8 @@
#include "content/shell/browser/shell.h"
#include "media/base/media.h"
#include "media/base/media_switches.h"
+#include "media/media_features.h"
#include "media/mojo/features.h"
-#include "ppapi/features/features.h"
#if defined(OS_ANDROID)
#include "base/android/build_info.h"
@@ -24,7 +24,7 @@
#include "base/win/windows_version.h"
#endif
-#if BUILDFLAG(ENABLE_MOJO_CDM) && !BUILDFLAG(ENABLE_PEPPER_CDMS)
+#if BUILDFLAG(ENABLE_MOJO_CDM) && !BUILDFLAG(ENABLE_LIBRARY_CDMS)
// When mojo CDM is enabled, External Clear Key is supported in //content/shell/
// by using mojo CDM with AesDecryptor running in the remote (e.g. GPU or
// Browser) process. When pepper CDM is supported, External Clear Key is
@@ -108,10 +108,10 @@ class EncryptedMediaTest : public MediaBrowserTest,
}
base::StringPairs query_params;
- query_params.push_back(std::make_pair("keySystem", CurrentKeySystem()));
- query_params.push_back(std::make_pair(
+ query_params.emplace_back("keySystem", CurrentKeySystem());
+ query_params.emplace_back(
"configChangeType",
- base::IntToString(static_cast<int>(config_change_type))));
+ base::IntToString(static_cast<int>(config_change_type)));
RunMediaTestPage("mse_config_change.html", query_params, kEnded, true);
}
@@ -122,11 +122,11 @@ class EncryptedMediaTest : public MediaBrowserTest,
SrcType src_type,
const std::string& expectation) {
base::StringPairs query_params;
- query_params.push_back(std::make_pair("mediaFile", media_file));
- query_params.push_back(std::make_pair("mediaType", media_type));
- query_params.push_back(std::make_pair("keySystem", key_system));
+ query_params.emplace_back("mediaFile", media_file);
+ query_params.emplace_back("mediaType", media_type);
+ query_params.emplace_back("keySystem", key_system);
if (src_type == SrcType::MSE)
- query_params.push_back(std::make_pair("useMSE", "1"));
+ query_params.emplace_back("useMSE", "1");
RunMediaTestPage(html_page, query_params, expectation, true);
}
diff --git a/chromium/content/browser/media/media_browsertest.cc b/chromium/content/browser/media/media_browsertest.cc
index 2d523d4d9c9..239bfb27fd8 100644
--- a/chromium/content/browser/media/media_browsertest.cc
+++ b/chromium/content/browser/media/media_browsertest.cc
@@ -123,7 +123,7 @@ class MediaTest : public testing::WithParamInterface<bool>,
const std::string& media_file,
bool http) {
base::StringPairs query_params;
- query_params.push_back(std::make_pair(tag, media_file));
+ query_params.emplace_back(tag, media_file);
RunMediaTestPage("player.html", query_params, kEnded, http);
}
@@ -132,9 +132,9 @@ class MediaTest : public testing::WithParamInterface<bool>,
const std::string& expected_error_substring,
bool http) {
base::StringPairs query_params;
- query_params.push_back(std::make_pair(tag, media_file));
- query_params.push_back(std::make_pair(
- "error_substr", EncodeErrorMessage(expected_error_substring)));
+ query_params.emplace_back(tag, media_file);
+ query_params.emplace_back("error_substr",
+ EncodeErrorMessage(expected_error_substring));
RunMediaTestPage("player.html", query_params, kErrorEvent, http);
}
@@ -144,7 +144,7 @@ class MediaTest : public testing::WithParamInterface<bool>,
expected += " ";
expected += base::IntToString(height);
base::StringPairs query_params;
- query_params.push_back(std::make_pair("video", media_file));
+ query_params.emplace_back("video", media_file);
RunMediaTestPage("player.html", query_params, expected, false);
}
};
@@ -196,6 +196,14 @@ IN_PROC_BROWSER_TEST_P(MediaTest, VideoBearMp4Vp9) {
PlayVideo("bear-320x240-v_frag-vp9.mp4", GetParam());
}
+IN_PROC_BROWSER_TEST_P(MediaTest, AudioBearFlacMp4) {
+ PlayAudio("bear-flac.mp4", GetParam());
+}
+
+IN_PROC_BROWSER_TEST_P(MediaTest, AudioBearFlac192kHzMp4) {
+ PlayAudio("bear-flac-192kHz.mp4", GetParam());
+}
+
// Android devices usually only support baseline, main and high.
#if !defined(OS_ANDROID)
IN_PROC_BROWSER_TEST_P(MediaTest, VideoBearHighBitDepthMp4) {
diff --git a/chromium/content/browser/media/media_canplaytype_browsertest.cc b/chromium/content/browser/media/media_canplaytype_browsertest.cc
index e10735a2eb2..6b197c711b5 100644
--- a/chromium/content/browser/media/media_canplaytype_browsertest.cc
+++ b/chromium/content/browser/media/media_canplaytype_browsertest.cc
@@ -199,12 +199,6 @@ class MediaCanPlayTypeTest : public MediaBrowserTest {
EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.4D401E, vorbis\"'"));
EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3.64001F, vorbis\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"flac\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1, flac\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3, flac\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.4D401E, flac\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3.64001F, flac\"'"));
-
EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"opus\"'"));
EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1, opus\"'"));
EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3, opus\"'"));
@@ -552,6 +546,7 @@ class MediaCanPlayTypeTest : public MediaBrowserTest {
CanPlay("'" + mime + "; codecs=\"hvc1.1.6.L93.B0,mp4a.40.5\"'"));
EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp09.00.10.08\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"flac\"'"));
EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"ac-3\"'"));
EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"ec-3\"'"));
@@ -683,15 +678,17 @@ IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_flac) {
EXPECT_EQ(kProbably, CanPlay("'audio/flac'"));
EXPECT_EQ(kProbably, CanPlay("'audio/ogg; codecs=\"flac\"'"));
+ // See CodecSupportTest_mp4 for more flac combos.
+ EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"flac\"'"));
+ EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"flac\"'"));
+
EXPECT_EQ(kNot, CanPlay("'video/flac'"));
EXPECT_EQ(kNot, CanPlay("'video/x-flac'"));
EXPECT_EQ(kNot, CanPlay("'audio/x-flac'"));
EXPECT_EQ(kNot, CanPlay("'application/x-flac'"));
EXPECT_EQ(kNot, CanPlay("'audio/flac; codecs=\"flac\"'"));
- EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"flac\"'"));
EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"flac\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/mp4; codecs=\"flac\"'"));
EXPECT_EQ(kNot, CanPlay("'audio/webm; codecs=\"flac\"'"));
EXPECT_EQ(kNot, CanPlay("'audio/flac; codecs=\"avc1\"'"));
EXPECT_EQ(kNot, CanPlay("'audio/flac; codecs=\"avc3\"'"));
@@ -733,6 +730,8 @@ IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_mp3) {
EXPECT_EQ(kNot, CanPlay("'audio/mpeg; codecs=\"mp4a.40.2\"'"));
EXPECT_EQ(kNot, CanPlay("'audio/mpeg; codecs=\"mp4a.40.02\"'"));
+ EXPECT_EQ(kNot, CanPlay("'audio/mpeg; codecs=\"flac\"'"));
+
TestMPEGUnacceptableCombinations("audio/mpeg");
// audio/mp3 does not allow any codecs parameter
@@ -752,6 +751,8 @@ IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_mp3) {
EXPECT_EQ(kNot, CanPlay("'audio/mp3; codecs=\"mp4a.40.2\"'"));
EXPECT_EQ(kNot, CanPlay("'audio/mp3; codecs=\"mp4a.40.02\"'"));
+ EXPECT_EQ(kNot, CanPlay("'audio/mp3; codecs=\"flac\"'"));
+
TestMPEGUnacceptableCombinations("audio/mp3");
EXPECT_EQ(kNot, CanPlay("'audio/mp3; codecs=\"mp3\"'"));
@@ -772,6 +773,8 @@ IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_mp3) {
EXPECT_EQ(kNot, CanPlay("'audio/x-mp3; codecs=\"mp4a.40.2\"'"));
EXPECT_EQ(kNot, CanPlay("'audio/x-mp3; codecs=\"mp4a.40.02\"'"));
+ EXPECT_EQ(kNot, CanPlay("'audio/x-mp3; codecs=\"flac\"'"));
+
TestMPEGUnacceptableCombinations("audio/x-mp3");
EXPECT_EQ(kNot, CanPlay("'audio/x-mp3; codecs=\"mp3\"'"));
}
@@ -785,6 +788,8 @@ IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_mp4) {
EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc1, mp4a.40\"'"));
EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc3, mp4a.40\"'"));
EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc1, avc3\"'"));
+ EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc1, flac\"'"));
+ EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc3, flac\"'"));
EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.42E01E\"'"));
EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.42101E\"'"));
@@ -851,9 +856,13 @@ IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_mp4) {
CanPlay("'video/mp4; codecs=\"hvc1.1.6.L93.B0, mp4a.40.5\"'"));
EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"vp09.00.10.08\"'"));
+ EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"flac\"'"));
+ EXPECT_EQ(kPropProbably,
+ CanPlay("'video/mp4; codecs=\"avc1.4D401E, flac\"'"));
+ EXPECT_EQ(kPropProbably,
+ CanPlay("'video/mp4; codecs=\"avc3.64001F, flac\"'"));
TestMPEGUnacceptableCombinations("video/mp4");
- EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"flac\"'"));
// This result is incorrect. See https://crbug.com/592889.
EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"mp3\"'"));
@@ -925,6 +934,8 @@ IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_mp4) {
EXPECT_EQ(kNot, CanPlay("'video/x-m4v; codecs=\"avc1.640028,mp4a.a6\"'"));
EXPECT_EQ(kNot, CanPlay("'video/x-m4v; codecs=\"avc1.640028,mp4a.A6\"'"));
+ EXPECT_EQ(kNot, CanPlay("'video/x-m4v; codecs=\"flac\"'"));
+
TestMPEGUnacceptableCombinations("video/x-m4v");
EXPECT_EQ(kPropMaybe, CanPlay("'audio/mp4'"));
@@ -941,6 +952,8 @@ IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_mp4) {
EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"mp4a.40.05\"'"));
EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"mp4a.40.29\"'"));
+ EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"flac\"'"));
+
EXPECT_EQ(kNot, CanPlay("'audio/mp4; codecs=\"avc1\"'"));
EXPECT_EQ(kNot, CanPlay("'audio/mp4; codecs=\"avc3\"'"));
EXPECT_EQ(kNot, CanPlay("'audio/mp4; codecs=\"avc1, mp4a.40\"'"));
@@ -964,7 +977,6 @@ IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_mp4) {
EXPECT_EQ(kNot, CanPlay("'audio/mp4; codecs=\"mp4a.A6\"'"));
TestMPEGUnacceptableCombinations("audio/mp4");
- EXPECT_EQ(kNot, CanPlay("'audio/mp4; codecs=\"flac\"'"));
// This result is incorrect. See https://crbug.com/592889.
EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"mp3\"'"));
@@ -1007,6 +1019,8 @@ IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_mp4) {
EXPECT_EQ(kNot, CanPlay("'audio/x-m4a; codecs=\"mp4a.a6\"'"));
EXPECT_EQ(kNot, CanPlay("'audio/x-m4a; codecs=\"mp4a.A6\"'"));
+ EXPECT_EQ(kNot, CanPlay("'video/x-m4a; codecs=\"flac\"'"));
+
TestMPEGUnacceptableCombinations("audio/x-m4a");
}
diff --git a/chromium/content/browser/media/media_capabilities_browsertest.cc b/chromium/content/browser/media/media_capabilities_browsertest.cc
index 3f927c14d49..de84948cb38 100644
--- a/chromium/content/browser/media/media_capabilities_browsertest.cc
+++ b/chromium/content/browser/media/media_capabilities_browsertest.cc
@@ -136,6 +136,11 @@ IN_PROC_BROWSER_TEST_F(MediaCapabilitiesTest, AudioDecodeTypes) {
CanDecodeAudio("'audio/mp4; codecs=\"mp4a.40.02\"'"));
EXPECT_EQ(kPropSupported, CanDecodeAudio("'audio/aac'"));
+ // TODO(chcunningham): Differentiate kFile vs kMediaSource support for
+ // FLAC-in-MP4, making MSE support for this contingent upon at least
+ // base::FeatureList::IsEnabled(kMseFlacInIsobmff) and kPropSupported.
+ EXPECT_EQ(kPropSupported, CanDecodeAudio("'audio/mp4; codecs=\"flac\"'"));
+
// Test a handful of invalid strings.
EXPECT_EQ(kUnsupported, CanDecodeAudio("'audio/wav; codecs=\"mp3\"'"));
EXPECT_EQ(kUnsupported, CanDecodeAudio("'audio/webm; codecs=\"vp8\"'"));
diff --git a/chromium/content/browser/media/media_devices_permission_checker_unittest.cc b/chromium/content/browser/media/media_devices_permission_checker_unittest.cc
index 08bfde3dcb1..a67f43c51e4 100644
--- a/chromium/content/browser/media/media_devices_permission_checker_unittest.cc
+++ b/chromium/content/browser/media/media_devices_permission_checker_unittest.cc
@@ -67,8 +67,9 @@ class MediaDevicesPermissionCheckerTest : public RenderViewHostImplTestHarness {
checker_.CheckPermission(
device_type, main_rfh()->GetProcess()->GetID(),
main_rfh()->GetRoutingID(),
- base::Bind(&MediaDevicesPermissionCheckerTest::CheckPermissionCallback,
- base::Unretained(this)));
+ base::BindOnce(
+ &MediaDevicesPermissionCheckerTest::CheckPermissionCallback,
+ base::Unretained(this)));
run_loop.Run();
EXPECT_TRUE(callback_run_);
diff --git a/chromium/content/browser/media/media_interface_proxy.cc b/chromium/content/browser/media/media_interface_proxy.cc
index 7992819abef..ed1f2538b86 100644
--- a/chromium/content/browser/media/media_interface_proxy.cc
+++ b/chromium/content/browser/media/media_interface_proxy.cc
@@ -158,8 +158,8 @@ void MediaInterfaceProxy::ConnectToMediaService() {
GetFrameServices());
interface_factory_ptr_.set_connection_error_handler(
- base::Bind(&MediaInterfaceProxy::OnMediaServiceConnectionError,
- base::Unretained(this)));
+ base::BindOnce(&MediaInterfaceProxy::OnMediaServiceConnectionError,
+ base::Unretained(this)));
}
void MediaInterfaceProxy::ConnectToCdmService() {
@@ -176,8 +176,8 @@ void MediaInterfaceProxy::ConnectToCdmService() {
MakeRequest(&cdm_interface_factory_ptr_), GetFrameServices());
cdm_interface_factory_ptr_.set_connection_error_handler(
- base::Bind(&MediaInterfaceProxy::OnCdmServiceConnectionError,
- base::Unretained(this)));
+ base::BindOnce(&MediaInterfaceProxy::OnCdmServiceConnectionError,
+ base::Unretained(this)));
}
} // namespace content
diff --git a/chromium/content/browser/media/media_internals.cc b/chromium/content/browser/media/media_internals.cc
index d0da23356d7..8f146027e2f 100644
--- a/chromium/content/browser/media/media_internals.cc
+++ b/chromium/content/browser/media/media_internals.cc
@@ -10,8 +10,6 @@
#include <tuple>
#include <utility>
-#include "base/containers/flat_map.h"
-#include "base/containers/flat_set.h"
#include "base/macros.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
@@ -30,10 +28,7 @@
#include "content/public/browser/web_ui.h"
#include "media/base/audio_parameters.h"
#include "media/base/media_log_event.h"
-#include "media/base/watch_time_keys.h"
#include "media/filters/gpu_video_decoder.h"
-#include "services/metrics/public/cpp/ukm_entry_builder.h"
-#include "services/metrics/public/cpp/ukm_recorder.h"
#if !defined(OS_ANDROID)
#include "media/filters/decrypting_video_decoder.h"
@@ -117,7 +112,6 @@ bool IsIncognito(int render_process_id) {
const char kAudioLogStatusKey[] = "status";
const char kAudioLogUpdateFunction[] = "media.updateAudioComponent";
-const char kWatchTimeEvent[] = "Media.WatchTime";
} // namespace
@@ -262,10 +256,10 @@ void 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::Bind(&SendWebContentsTitleHelper, cache_key, base::Passed(&dict),
- render_process_id, render_frame_id));
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&SendWebContentsTitleHelper,
+ cache_key, base::Passed(&dict),
+ render_process_id, render_frame_id));
return;
}
@@ -304,7 +298,7 @@ void AudioLogImpl::StoreComponentMetadata(int component_id,
// This class lives on the browser UI thread.
class MediaInternals::MediaInternalsUMAHandler {
public:
- explicit MediaInternalsUMAHandler(content::MediaInternals* media_internals);
+ MediaInternalsUMAHandler();
// Called when a render process is terminated. Reports the pipeline status to
// UMA for every player associated with the renderer process and then deletes
@@ -316,7 +310,6 @@ class MediaInternals::MediaInternalsUMAHandler {
const media::MediaLogEvent& event);
private:
- using WatchTimeInfo = base::flat_map<base::StringPiece, base::TimeDelta>;
struct PipelineInfo {
explicit PipelineInfo(bool is_incognito) : is_incognito(is_incognito) {}
@@ -334,8 +327,6 @@ class MediaInternals::MediaInternalsUMAHandler {
std::string video_codec_name;
std::string video_decoder;
GURL origin_url;
- WatchTimeInfo watch_time_info;
- int underflow_count = 0;
};
// Helper function to report PipelineStatus associated with a player to UMA.
@@ -344,114 +335,6 @@ class MediaInternals::MediaInternalsUMAHandler {
// Helper to generate PipelineStatus UMA name for AudioVideo streams.
std::string GetUMANameForAVStream(const PipelineInfo& player_info);
- bool ShouldReportUkmWatchTime(base::StringPiece key) {
- // EmbeddedExperience is always a file:// URL, so skip reporting.
- return !key.ends_with("EmbeddedExperience");
- }
-
- void RecordWatchTime(base::StringPiece key,
- base::TimeDelta value,
- bool is_mtbr = false) {
- base::UmaHistogramCustomTimes(
- key.as_string(), value,
- // There are a maximum of 5 underflow events possible in a given 7s
- // watch time period, so the minimum value is 1.4s.
- is_mtbr ? base::TimeDelta::FromSecondsD(1.4)
- : base::TimeDelta::FromSeconds(7),
- base::TimeDelta::FromHours(10), 50);
- }
-
- void RecordMeanTimeBetweenRebuffers(base::StringPiece key,
- base::TimeDelta value) {
- RecordWatchTime(key, value, true);
- }
-
- void RecordRebuffersCount(base::StringPiece key, int underflow_count) {
- base::UmaHistogramCounts100(key.as_string(), underflow_count);
- }
-
- void RecordWatchTimeWithFilter(
- const GURL& url,
- WatchTimeInfo* watch_time_info,
- const base::flat_set<base::StringPiece>& watch_time_filter) {
- // UKM may be unavailable in content_shell or other non-chrome/ builds; it
- // may also be unavailable if browser shutdown has started.
- const bool has_ukm = !!ukm::UkmRecorder::Get();
- std::unique_ptr<ukm::UkmEntryBuilder> builder;
-
- for (auto it = watch_time_info->begin(); it != watch_time_info->end();) {
- if (!watch_time_filter.empty() &&
- watch_time_filter.find(it->first) == watch_time_filter.end()) {
- ++it;
- continue;
- }
-
- RecordWatchTime(it->first, it->second);
-
- if (has_ukm && ShouldReportUkmWatchTime(it->first)) {
- if (!builder)
- builder = media_internals_->CreateUkmBuilder(url, kWatchTimeEvent);
-
- // Strip Media.WatchTime. prefix for UKM since they're already
- // grouped; arraysize() includes \0, so no +1 necessary for trailing
- // period.
- builder->AddMetric(it->first.substr(arraysize(kWatchTimeEvent)).data(),
- it->second.InMilliseconds());
- }
-
- it = watch_time_info->erase(it);
- }
- }
-
- enum class FinalizeType {
- EVERYTHING,
- POWER_ONLY,
- CONTROLS_ONLY,
- DISPLAY_ONLY
- };
- void FinalizeWatchTime(bool has_video,
- const GURL& url,
- int* underflow_count,
- WatchTimeInfo* watch_time_info,
- FinalizeType finalize_type) {
- // |url| may come from an untrusted source, so ensure it's valid before
- // trying to use it for watch time logging.
- if (!url.is_valid())
- return;
-
- switch (finalize_type) {
- case FinalizeType::EVERYTHING:
- // Check for watch times entries that have corresponding MTBR entries
- // and report the MTBR value using watch_time / |underflow_count|
- for (auto& mapping : rebuffer_keys_) {
- auto it = watch_time_info->find(mapping.watch_time_key);
- if (it == watch_time_info->end())
- continue;
- if (*underflow_count) {
- RecordMeanTimeBetweenRebuffers(mapping.mtbr_key,
- it->second / *underflow_count);
- }
- RecordRebuffersCount(mapping.smooth_rate_key, *underflow_count);
- }
- *underflow_count = 0;
-
- RecordWatchTimeWithFilter(url, watch_time_info,
- base::flat_set<base::StringPiece>());
- break;
- case FinalizeType::POWER_ONLY:
- RecordWatchTimeWithFilter(url, watch_time_info, watch_time_power_keys_);
- break;
- case FinalizeType::CONTROLS_ONLY:
- RecordWatchTimeWithFilter(url, watch_time_info,
- watch_time_controls_keys_);
- break;
- case FinalizeType::DISPLAY_ONLY:
- RecordWatchTimeWithFilter(url, watch_time_info,
- watch_time_display_keys_);
- break;
- }
- }
-
// Key is player id.
typedef std::map<int, PipelineInfo> PlayerInfoMap;
@@ -461,55 +344,10 @@ class MediaInternals::MediaInternalsUMAHandler {
// Stores player information per renderer.
RendererPlayerMap renderer_info_;
- // Set of all possible watch time keys.
- const base::flat_set<base::StringPiece> watch_time_keys_;
-
- // Set of only the power related watch time keys.
- const base::flat_set<base::StringPiece> watch_time_power_keys_;
-
- // Set of only the controls related watch time keys.
- const base::flat_set<base::StringPiece> watch_time_controls_keys_;
-
- // Set of only the display related watch time keys.
- const base::flat_set<base::StringPiece> watch_time_display_keys_;
-
- // Mapping of WatchTime metric keys to MeanTimeBetweenRebuffers (MTBR) and
- // smooth rate (had zero rebuffers) keys.
- struct RebufferMapping {
- base::StringPiece watch_time_key;
- base::StringPiece mtbr_key;
- base::StringPiece smooth_rate_key;
- };
- const std::vector<RebufferMapping> rebuffer_keys_;
-
- content::MediaInternals* const media_internals_;
-
DISALLOW_COPY_AND_ASSIGN(MediaInternalsUMAHandler);
};
-MediaInternals::MediaInternalsUMAHandler::MediaInternalsUMAHandler(
- content::MediaInternals* media_internals)
- : watch_time_keys_(media::GetWatchTimeKeys()),
- watch_time_power_keys_(media::GetWatchTimePowerKeys()),
- watch_time_controls_keys_(media::GetWatchTimeControlsKeys()),
- watch_time_display_keys_(media::GetWatchTimeDisplayKeys()),
- rebuffer_keys_(
- {{media::kWatchTimeAudioSrc, media::kMeanTimeBetweenRebuffersAudioSrc,
- media::kRebuffersCountAudioSrc},
- {media::kWatchTimeAudioMse, media::kMeanTimeBetweenRebuffersAudioMse,
- media::kRebuffersCountAudioMse},
- {media::kWatchTimeAudioEme, media::kMeanTimeBetweenRebuffersAudioEme,
- media::kRebuffersCountAudioEme},
- {media::kWatchTimeAudioVideoSrc,
- media::kMeanTimeBetweenRebuffersAudioVideoSrc,
- media::kRebuffersCountAudioVideoSrc},
- {media::kWatchTimeAudioVideoMse,
- media::kMeanTimeBetweenRebuffersAudioVideoMse,
- media::kRebuffersCountAudioVideoMse},
- {media::kWatchTimeAudioVideoEme,
- media::kMeanTimeBetweenRebuffersAudioVideoEme,
- media::kRebuffersCountAudioVideoEme}}),
- media_internals_(media_internals) {}
+MediaInternals::MediaInternalsUMAHandler::MediaInternalsUMAHandler() {}
void MediaInternals::MediaInternalsUMAHandler::SavePlayerState(
int render_process_id,
@@ -589,72 +427,6 @@ void MediaInternals::MediaInternalsUMAHandler::SavePlayerState(
player_info.has_reached_have_enough = true;
}
break;
- case media::MediaLogEvent::Type::WATCH_TIME_UPDATE: {
- DVLOG(2) << "Processing watch time update.";
-
- for (base::DictionaryValue::Iterator it(event.params); !it.IsAtEnd();
- it.Advance()) {
- // Don't log random histogram keys from the untrusted renderer, instead
- // ensure they are from our list of known keys. Use |key_name| from the
- // key map, since otherwise we'll end up storing a StringPiece which
- // points into the soon-to-be-destructed DictionaryValue.
- auto key_name = watch_time_keys_.find(it.key());
- if (key_name == watch_time_keys_.end())
- continue;
- player_info.watch_time_info[*key_name] =
- base::TimeDelta::FromSecondsD(it.value().GetDouble());
- }
-
- if (event.params.HasKey(media::kWatchTimeUnderflowCount)) {
- event.params.GetInteger(media::kWatchTimeUnderflowCount,
- &player_info.underflow_count);
- }
-
- if (event.params.HasKey(media::kWatchTimeFinalize)) {
- bool should_finalize;
- DCHECK(event.params.GetBoolean(media::kWatchTimeFinalize,
- &should_finalize) &&
- should_finalize);
- FinalizeWatchTime(player_info.has_video, player_info.origin_url,
- &player_info.underflow_count,
- &player_info.watch_time_info,
- FinalizeType::EVERYTHING);
- } else {
- if (event.params.HasKey(media::kWatchTimeFinalizePower)) {
- bool should_finalize;
- DCHECK(event.params.GetBoolean(media::kWatchTimeFinalizePower,
- &should_finalize) &&
- should_finalize);
- FinalizeWatchTime(player_info.has_video, player_info.origin_url,
- &player_info.underflow_count,
- &player_info.watch_time_info,
- FinalizeType::POWER_ONLY);
- }
-
- if (event.params.HasKey(media::kWatchTimeFinalizeControls)) {
- bool should_finalize;
- DCHECK(event.params.GetBoolean(media::kWatchTimeFinalizeControls,
- &should_finalize) &&
- should_finalize);
- FinalizeWatchTime(player_info.has_video, player_info.origin_url,
- &player_info.underflow_count,
- &player_info.watch_time_info,
- FinalizeType::CONTROLS_ONLY);
- }
-
- if (event.params.HasKey(media::kWatchTimeFinalizeDisplay)) {
- bool should_finalize;
- DCHECK(event.params.GetBoolean(media::kWatchTimeFinalizeDisplay,
- &should_finalize) &&
- should_finalize);
- FinalizeWatchTime(player_info.has_video, player_info.origin_url,
- &player_info.underflow_count,
- &player_info.watch_time_info,
- FinalizeType::DISPLAY_ONLY);
- }
- }
- break;
- }
case media::MediaLogEvent::Type::WEBMEDIAPLAYER_DESTROYED: {
// Upon player destruction report UMA data; if the player is not torn down
// before process exit, it will be logged during OnProcessTerminated().
@@ -663,10 +435,6 @@ void MediaInternals::MediaInternalsUMAHandler::SavePlayerState(
break;
ReportUMAForPipelineStatus(it->second);
- FinalizeWatchTime(it->second.has_video, it->second.origin_url,
- &it->second.underflow_count,
- &(it->second.watch_time_info),
- FinalizeType::EVERYTHING);
player_info_map.erase(it);
}
default:
@@ -768,9 +536,6 @@ void MediaInternals::MediaInternalsUMAHandler::OnProcessTerminated(
auto it = players_it->second.begin();
while (it != players_it->second.end()) {
ReportUMAForPipelineStatus(it->second);
- FinalizeWatchTime(it->second.has_video, it->second.origin_url,
- &it->second.underflow_count,
- &(it->second.watch_time_info), FinalizeType::EVERYTHING);
players_it->second.erase(it++);
}
renderer_info_.erase(players_it);
@@ -784,7 +549,7 @@ MediaInternals* MediaInternals::GetInstance() {
MediaInternals::MediaInternals()
: can_update_(false),
owner_ids_(),
- uma_handler_(new MediaInternalsUMAHandler(this)) {
+ uma_handler_(new MediaInternalsUMAHandler()) {
// TODO(sandersd): Is there ever a relevant case where TERMINATED is sent
// without CLOSED also being sent?
registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_CLOSED,
@@ -834,7 +599,7 @@ static bool ConvertEventToUpdate(int render_process_id,
dict.SetString("params.pipeline_error",
media::MediaLog::PipelineStatusToString(error));
} else {
- dict.Set("params", base::MakeUnique<base::Value>(event.params));
+ dict.SetKey("params", event.params.Clone());
}
*update = SerializeUpdate("media.onMediaEvent", &dict);
@@ -842,19 +607,17 @@ static bool ConvertEventToUpdate(int render_process_id,
}
void MediaInternals::OnMediaEvents(
- int render_process_id, const std::vector<media::MediaLogEvent>& events) {
+ int render_process_id,
+ const std::vector<media::MediaLogEvent>& events) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
// Notify observers that |event| has occurred.
for (const auto& event : events) {
- // Some events should not be recorded in the UI.
- if (event.type != media::MediaLogEvent::Type::WATCH_TIME_UPDATE) {
- if (CanUpdate()) {
- base::string16 update;
- if (ConvertEventToUpdate(render_process_id, event, &update))
- SendUpdate(update);
- }
- SaveEvent(render_process_id, event);
+ if (CanUpdate()) {
+ base::string16 update;
+ if (ConvertEventToUpdate(render_process_id, event, &update))
+ SendUpdate(update);
}
+ SaveEvent(render_process_id, event);
uma_handler_->SavePlayerState(render_process_id, event);
}
}
@@ -976,8 +739,9 @@ void MediaInternals::OnProcessTerminatedForTesting(int process_id) {
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::Bind(
- &MediaInternals::SendUpdate, base::Unretained(this), update));
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&MediaInternals::SendUpdate,
+ base::Unretained(this), update));
return;
}
@@ -1023,8 +787,8 @@ void MediaInternals::UpdateAudioLog(AudioLogUpdateType type,
return;
} else if (!has_entry) {
DCHECK_EQ(type, CREATE);
- audio_streams_cached_data_.Set(cache_key,
- base::MakeUnique<base::Value>(*value));
+ audio_streams_cached_data_.Set(
+ cache_key, base::MakeUnique<base::Value>(value->Clone()));
} else if (type == UPDATE_AND_DELETE) {
std::unique_ptr<base::Value> out_value;
CHECK(audio_streams_cached_data_.Remove(cache_key, &out_value));
@@ -1040,17 +804,4 @@ void MediaInternals::UpdateAudioLog(AudioLogUpdateType type,
SendUpdate(SerializeUpdate(function, value));
}
-std::unique_ptr<ukm::UkmEntryBuilder> MediaInternals::CreateUkmBuilder(
- const GURL& url,
- const char* event_name) {
- // UKM is unavailable in builds w/o chrome/ code (e.g., content_shell).
- ukm::UkmRecorder* ukm_recorder = ukm::UkmRecorder::Get();
- if (!ukm_recorder)
- return nullptr;
-
- const int32_t source_id = ukm_recorder->GetNewSourceID();
- ukm_recorder->UpdateSourceURL(source_id, url);
- return ukm_recorder->GetEntryBuilder(source_id, event_name);
-}
-
} // namespace content
diff --git a/chromium/content/browser/media/media_internals.h b/chromium/content/browser/media/media_internals.h
index 3cc1790113b..4a0fa4e1dee 100644
--- a/chromium/content/browser/media/media_internals.h
+++ b/chromium/content/browser/media/media_internals.h
@@ -29,16 +29,11 @@ namespace media {
struct MediaLogEvent;
}
-namespace ukm {
-class UkmEntryBuilder;
-}
-
namespace content {
// This class stores information about currently active media.
-class CONTENT_EXPORT MediaInternals
- : NON_EXPORTED_BASE(public media::AudioLogFactory),
- public NotificationObserver {
+class CONTENT_EXPORT MediaInternals : public media::AudioLogFactory,
+ public NotificationObserver {
public:
// Called with the update string.
typedef base::Callback<void(const base::string16&)> UpdateCallback;
@@ -126,10 +121,6 @@ class CONTENT_EXPORT MediaInternals
const std::string& function,
const base::DictionaryValue* value);
- std::unique_ptr<ukm::UkmEntryBuilder> CreateUkmBuilder(
- const GURL& url,
- const char* event_name);
-
// Must only be accessed on the UI thread.
std::vector<UpdateCallback> update_callbacks_;
diff --git a/chromium/content/browser/media/media_internals_proxy.cc b/chromium/content/browser/media/media_internals_proxy.cc
index f7a87f96e2e..dfadf6b30c4 100644
--- a/chromium/content/browser/media/media_internals_proxy.cc
+++ b/chromium/content/browser/media/media_internals_proxy.cc
@@ -40,7 +40,7 @@ void MediaInternalsProxy::GetEverything() {
// Ask MediaInternals for its data on IO thread.
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&MediaInternalsProxy::GetEverythingOnIOThread, this));
+ base::BindOnce(&MediaInternalsProxy::GetEverythingOnIOThread, this));
}
void MediaInternalsProxy::GetEverythingOnIOThread() {
diff --git a/chromium/content/browser/media/media_internals_unittest.cc b/chromium/content/browser/media/media_internals_unittest.cc
index 5900b88fea8..e355c4b2bce 100644
--- a/chromium/content/browser/media/media_internals_unittest.cc
+++ b/chromium/content/browser/media/media_internals_unittest.cc
@@ -12,17 +12,13 @@
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/test/histogram_tester.h"
#include "base/test/test_message_loop.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
-#include "components/ukm/test_ukm_recorder.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "media/base/audio_parameters.h"
#include "media/base/channel_layout.h"
#include "media/base/media_log.h"
-#include "media/base/watch_time_keys.h"
-#include "media/blink/watch_time_reporter.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/geometry/size.h"
@@ -30,7 +26,6 @@
namespace {
const int kTestComponentID = 0;
const char kTestDeviceID[] = "test-device-id";
-const char kTestOrigin[] = "https://test.google.com/";
// This class encapsulates a MediaInternals reference. It also has some useful
// methods to receive a callback, deserialize its associated data and expect
@@ -317,651 +312,4 @@ INSTANTIATE_TEST_CASE_P(
media::AudioLogFactory::AUDIO_OUTPUT_CONTROLLER,
media::AudioLogFactory::AUDIO_OUTPUT_STREAM));
-class DirectMediaLog : public media::MediaLog {
- public:
- explicit DirectMediaLog(int render_process_id)
- : render_process_id_(render_process_id),
- internals_(content::MediaInternals::GetInstance()) {}
- ~DirectMediaLog() override {}
-
- void AddEvent(std::unique_ptr<media::MediaLogEvent> event) override {
- std::vector<media::MediaLogEvent> events(1, *event);
- internals_->OnMediaEvents(render_process_id_, events);
- }
-
- private:
- const int render_process_id_;
- MediaInternals* const internals_;
-
- DISALLOW_COPY_AND_ASSIGN(DirectMediaLog);
-};
-
-class MediaInternalsWatchTimeTest : public testing::Test,
- public MediaInternalsTestBase {
- public:
- MediaInternalsWatchTimeTest()
- : render_process_id_(0),
- internals_(content::MediaInternals::GetInstance()),
- media_log_(new DirectMediaLog(render_process_id_)),
- histogram_tester_(new base::HistogramTester()),
- test_recorder_(new ukm::TestAutoSetUkmRecorder()),
- watch_time_keys_(media::GetWatchTimeKeys()),
- watch_time_power_keys_(media::GetWatchTimePowerKeys()),
- mtbr_keys_({media::kMeanTimeBetweenRebuffersAudioSrc,
- media::kMeanTimeBetweenRebuffersAudioMse,
- media::kMeanTimeBetweenRebuffersAudioEme,
- media::kMeanTimeBetweenRebuffersAudioVideoSrc,
- media::kMeanTimeBetweenRebuffersAudioVideoMse,
- media::kMeanTimeBetweenRebuffersAudioVideoEme}),
- smooth_keys_({media::kRebuffersCountAudioSrc,
- media::kRebuffersCountAudioMse,
- media::kRebuffersCountAudioEme,
- media::kRebuffersCountAudioVideoSrc,
- media::kRebuffersCountAudioVideoMse,
- media::kRebuffersCountAudioVideoEme}) {
- media_log_->AddEvent(media_log_->CreateCreatedEvent(kTestOrigin));
- }
-
- void Initialize(bool has_audio,
- bool has_video,
- bool is_mse,
- bool is_encrypted) {
- wtr_.reset(new media::WatchTimeReporter(
- has_audio, has_video, is_mse, is_encrypted, true, media_log_.get(),
- gfx::Size(800, 600),
- base::Bind(&MediaInternalsWatchTimeTest::GetCurrentMediaTime,
- base::Unretained(this))));
- wtr_->set_reporting_interval_for_testing();
- }
-
- void CycleWatchTimeReporter() {
- base::RunLoop run_loop;
- base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- run_loop.QuitClosure());
- run_loop.Run();
- }
-
- void ExpectWatchTime(const std::vector<base::StringPiece>& keys,
- base::TimeDelta value) {
- for (auto key : watch_time_keys_) {
- auto it = std::find(keys.begin(), keys.end(), key);
- if (it == keys.end()) {
- histogram_tester_->ExpectTotalCount(key.as_string(), 0);
- } else {
- histogram_tester_->ExpectUniqueSample(key.as_string(),
- value.InMilliseconds(), 1);
- }
- }
- }
-
- void ExpectHelper(const std::vector<base::StringPiece>& full_key_list,
- const std::vector<base::StringPiece>& keys,
- int64_t value) {
- for (auto key : full_key_list) {
- auto it = std::find(keys.begin(), keys.end(), key);
- if (it == keys.end())
- histogram_tester_->ExpectTotalCount(key.as_string(), 0);
- else
- histogram_tester_->ExpectUniqueSample(key.as_string(), value, 1);
- }
- }
-
- void ExpectMtbrTime(const std::vector<base::StringPiece>& keys,
- base::TimeDelta value) {
- ExpectHelper(mtbr_keys_, keys, value.InMilliseconds());
- }
-
- void ExpectZeroRebuffers(const std::vector<base::StringPiece>& keys) {
- ExpectHelper(smooth_keys_, keys, 0);
- }
-
- void ExpectRebuffers(const std::vector<base::StringPiece>& keys, int count) {
- ExpectHelper(smooth_keys_, keys, count);
- }
-
- void ExpectUkmWatchTime(size_t entry, size_t size, base::TimeDelta value) {
- ASSERT_LT(entry, test_recorder_->entries_count());
-
- const auto& metrics_vector = test_recorder_->GetEntry(entry)->metrics;
- ASSERT_EQ(size, metrics_vector.size());
-
- for (auto& sample : metrics_vector)
- EXPECT_EQ(value.InMilliseconds(), sample->value);
- }
-
- void ResetHistogramTester() {
- histogram_tester_.reset(new base::HistogramTester());
- }
-
- MOCK_METHOD0(GetCurrentMediaTime, base::TimeDelta());
-
- protected:
- const int render_process_id_;
- MediaInternals* const internals_;
- std::unique_ptr<DirectMediaLog> media_log_;
- std::unique_ptr<base::HistogramTester> histogram_tester_;
- std::unique_ptr<ukm::TestUkmRecorder> test_recorder_;
- std::unique_ptr<media::WatchTimeReporter> wtr_;
- const base::flat_set<base::StringPiece> watch_time_keys_;
- const base::flat_set<base::StringPiece> watch_time_power_keys_;
- const std::vector<base::StringPiece> mtbr_keys_;
- const std::vector<base::StringPiece> smooth_keys_;
-
- DISALLOW_COPY_AND_ASSIGN(MediaInternalsWatchTimeTest);
-};
-
-TEST_F(MediaInternalsWatchTimeTest, BasicAudio) {
- constexpr base::TimeDelta kWatchTimeEarly = base::TimeDelta::FromSeconds(5);
- constexpr base::TimeDelta kWatchTimeLate = base::TimeDelta::FromSeconds(10);
- EXPECT_CALL(*this, GetCurrentMediaTime())
- .WillOnce(testing::Return(base::TimeDelta()))
- .WillOnce(testing::Return(kWatchTimeEarly))
- .WillRepeatedly(testing::Return(kWatchTimeLate));
- Initialize(true, false, true, true);
- wtr_->OnPlaying();
-
- // No log should have been generated yet since the message loop has not had
- // any chance to pump.
- CycleWatchTimeReporter();
- ExpectWatchTime(std::vector<base::StringPiece>(), base::TimeDelta());
-
- wtr_->OnUnderflow();
- wtr_->OnUnderflow();
- CycleWatchTimeReporter();
- wtr_.reset();
-
- ExpectWatchTime({media::kWatchTimeAudioAll, media::kWatchTimeAudioMse,
- media::kWatchTimeAudioEme, media::kWatchTimeAudioAc,
- media::kWatchTimeAudioNativeControlsOff,
- media::kWatchTimeAudioEmbeddedExperience},
- kWatchTimeLate);
- ExpectMtbrTime({media::kMeanTimeBetweenRebuffersAudioMse,
- media::kMeanTimeBetweenRebuffersAudioEme},
- kWatchTimeLate / 2);
- ExpectRebuffers(
- {media::kRebuffersCountAudioMse, media::kRebuffersCountAudioEme}, 2);
-
- ASSERT_EQ(1U, test_recorder_->sources_count());
- ExpectUkmWatchTime(0, 5, kWatchTimeLate);
- EXPECT_TRUE(test_recorder_->GetSourceForUrl(kTestOrigin));
-}
-
-TEST_F(MediaInternalsWatchTimeTest, BasicVideo) {
- constexpr base::TimeDelta kWatchTimeEarly = base::TimeDelta::FromSeconds(5);
- constexpr base::TimeDelta kWatchTimeLate = base::TimeDelta::FromSeconds(10);
- EXPECT_CALL(*this, GetCurrentMediaTime())
- .WillOnce(testing::Return(base::TimeDelta()))
- .WillOnce(testing::Return(kWatchTimeEarly))
- .WillRepeatedly(testing::Return(kWatchTimeLate));
- Initialize(true, true, false, true);
- wtr_->OnPlaying();
-
- // No log should have been generated yet since the message loop has not had
- // any chance to pump.
- CycleWatchTimeReporter();
- ExpectWatchTime(std::vector<base::StringPiece>(), base::TimeDelta());
-
- wtr_->OnUnderflow();
- wtr_->OnUnderflow();
- CycleWatchTimeReporter();
- wtr_.reset();
-
- ExpectWatchTime(
- {media::kWatchTimeAudioVideoAll, media::kWatchTimeAudioVideoSrc,
- media::kWatchTimeAudioVideoEme, media::kWatchTimeAudioVideoAc,
- media::kWatchTimeAudioVideoNativeControlsOff,
- media::kWatchTimeAudioVideoDisplayInline,
- media::kWatchTimeAudioVideoEmbeddedExperience},
- kWatchTimeLate);
- ExpectMtbrTime({media::kMeanTimeBetweenRebuffersAudioVideoSrc,
- media::kMeanTimeBetweenRebuffersAudioVideoEme},
- kWatchTimeLate / 2);
- ExpectRebuffers({media::kRebuffersCountAudioVideoSrc,
- media::kRebuffersCountAudioVideoEme},
- 2);
-
- ASSERT_EQ(1U, test_recorder_->sources_count());
- ExpectUkmWatchTime(0, 6, kWatchTimeLate);
- EXPECT_TRUE(test_recorder_->GetSourceForUrl(kTestOrigin));
-}
-
-TEST_F(MediaInternalsWatchTimeTest, BasicPower) {
- constexpr base::TimeDelta kWatchTime1 = base::TimeDelta::FromSeconds(5);
- constexpr base::TimeDelta kWatchTime2 = base::TimeDelta::FromSeconds(10);
- constexpr base::TimeDelta kWatchTime3 = base::TimeDelta::FromSeconds(30);
- EXPECT_CALL(*this, GetCurrentMediaTime())
- .WillOnce(testing::Return(base::TimeDelta()))
- .WillOnce(testing::Return(kWatchTime1))
- .WillOnce(testing::Return(kWatchTime2))
- .WillOnce(testing::Return(kWatchTime2))
- .WillRepeatedly(testing::Return(kWatchTime3));
-
- Initialize(true, true, false, true);
- wtr_->OnPlaying();
- wtr_->set_is_on_battery_power_for_testing(true);
-
- // No log should have been generated yet since the message loop has not had
- // any chance to pump.
- CycleWatchTimeReporter();
- ExpectWatchTime(std::vector<base::StringPiece>(), base::TimeDelta());
-
- CycleWatchTimeReporter();
-
- // Transition back to AC power, this should generate AC watch time as well.
- wtr_->OnPowerStateChangeForTesting(false);
- CycleWatchTimeReporter();
-
- // This should finalize the power watch time on battery.
- ExpectWatchTime({media::kWatchTimeAudioVideoBattery}, kWatchTime2);
- ResetHistogramTester();
- wtr_.reset();
-
- std::vector<base::StringPiece> normal_keys = {
- media::kWatchTimeAudioVideoAll,
- media::kWatchTimeAudioVideoSrc,
- media::kWatchTimeAudioVideoEme,
- media::kWatchTimeAudioVideoNativeControlsOff,
- media::kWatchTimeAudioVideoDisplayInline,
- media::kWatchTimeAudioVideoEmbeddedExperience};
-
- for (auto key : watch_time_keys_) {
- if (key == media::kWatchTimeAudioVideoAc) {
- histogram_tester_->ExpectUniqueSample(
- key.as_string(), (kWatchTime3 - kWatchTime2).InMilliseconds(), 1);
- continue;
- }
-
- auto it = std::find(normal_keys.begin(), normal_keys.end(), key);
- if (it == normal_keys.end()) {
- histogram_tester_->ExpectTotalCount(key.as_string(), 0);
- } else {
- histogram_tester_->ExpectUniqueSample(key.as_string(),
- kWatchTime3.InMilliseconds(), 1);
- }
- }
-
- // Each finalize creates a new source and entry. We don't check the URL here
- // since the TestUkmService() helpers DCHECK() a unique URL per source.
- ASSERT_EQ(2U, test_recorder_->sources_count());
- ASSERT_EQ(2U, test_recorder_->entries_count());
- ExpectUkmWatchTime(0, 1, kWatchTime2);
- ExpectZeroRebuffers({media::kRebuffersCountAudioVideoSrc,
- media::kRebuffersCountAudioVideoEme});
-
- // Verify Media.WatchTime keys are properly stripped for UKM reporting.
- EXPECT_TRUE(test_recorder_->FindMetric(test_recorder_->GetEntry(0),
- "AudioVideo.Battery"));
-
- // Spot check one of the non-AC keys; this relies on the assumption that the
- // AC metric is not last.
- const auto& metrics_vector = test_recorder_->GetEntry(1)->metrics;
- ASSERT_EQ(6U, metrics_vector.size());
-}
-
-TEST_F(MediaInternalsWatchTimeTest, BasicControls) {
- constexpr base::TimeDelta kWatchTime1 = base::TimeDelta::FromSeconds(5);
- constexpr base::TimeDelta kWatchTime2 = base::TimeDelta::FromSeconds(10);
- constexpr base::TimeDelta kWatchTime3 = base::TimeDelta::FromSeconds(30);
- EXPECT_CALL(*this, GetCurrentMediaTime())
- .WillOnce(testing::Return(base::TimeDelta()))
- .WillOnce(testing::Return(kWatchTime1))
- .WillOnce(testing::Return(kWatchTime2))
- .WillOnce(testing::Return(kWatchTime2))
- .WillRepeatedly(testing::Return(kWatchTime3));
-
- Initialize(true, true, false, true);
- wtr_->OnNativeControlsEnabled();
- wtr_->OnPlaying();
-
- // No log should have been generated yet since the message loop has not had
- // any chance to pump.
- CycleWatchTimeReporter();
- ExpectWatchTime(std::vector<base::StringPiece>(), base::TimeDelta());
-
- CycleWatchTimeReporter();
-
- // Transition back to non-native controls, this should generate controls watch
- // time as well.
- wtr_->OnNativeControlsDisabled();
- CycleWatchTimeReporter();
-
- // This should finalize the power watch time on native controls.
- ExpectWatchTime({media::kWatchTimeAudioVideoNativeControlsOn}, kWatchTime2);
- ResetHistogramTester();
- wtr_.reset();
-
- std::vector<base::StringPiece> normal_keys = {
- media::kWatchTimeAudioVideoAll,
- media::kWatchTimeAudioVideoSrc,
- media::kWatchTimeAudioVideoEme,
- media::kWatchTimeAudioVideoAc,
- media::kWatchTimeAudioVideoDisplayInline,
- media::kWatchTimeAudioVideoEmbeddedExperience};
-
- for (auto key : watch_time_keys_) {
- if (key == media::kWatchTimeAudioVideoNativeControlsOff) {
- histogram_tester_->ExpectUniqueSample(
- key.as_string(), (kWatchTime3 - kWatchTime2).InMilliseconds(), 1);
- continue;
- }
-
- auto it = std::find(normal_keys.begin(), normal_keys.end(), key);
- if (it == normal_keys.end()) {
- histogram_tester_->ExpectTotalCount(key.as_string(), 0);
- } else {
- histogram_tester_->ExpectUniqueSample(key.as_string(),
- kWatchTime3.InMilliseconds(), 1);
- }
- }
-
- // Each finalize creates a new source and entry. We don't check the URL here
- // since the TestUkmService() helpers DCHECK() a unique URL per source.
- ASSERT_EQ(2U, test_recorder_->sources_count());
- ASSERT_EQ(2U, test_recorder_->entries_count());
- ExpectUkmWatchTime(0, 1, kWatchTime2);
-
- // Verify Media.WatchTime keys are properly stripped for UKM reporting.
- EXPECT_TRUE(test_recorder_->FindMetric(test_recorder_->GetEntry(0),
- "AudioVideo.NativeControlsOn"));
-
- // Spot check one of the non-AC keys; this relies on the assumption that the
- // AC metric is not last.
- const auto& metrics_vector = test_recorder_->GetEntry(1)->metrics;
- ASSERT_EQ(6U, metrics_vector.size());
- EXPECT_EQ(kWatchTime3.InMilliseconds(), metrics_vector.back()->value);
-}
-
-TEST_F(MediaInternalsWatchTimeTest, BasicDisplay) {
- constexpr base::TimeDelta kWatchTime1 = base::TimeDelta::FromSeconds(5);
- constexpr base::TimeDelta kWatchTime2 = base::TimeDelta::FromSeconds(10);
- constexpr base::TimeDelta kWatchTime3 = base::TimeDelta::FromSeconds(30);
- EXPECT_CALL(*this, GetCurrentMediaTime())
- .WillOnce(testing::Return(base::TimeDelta()))
- .WillOnce(testing::Return(kWatchTime1))
- .WillOnce(testing::Return(kWatchTime2))
- .WillOnce(testing::Return(kWatchTime2))
- .WillRepeatedly(testing::Return(kWatchTime3));
-
- Initialize(true, true, false, true);
- wtr_->OnDisplayTypeFullscreen();
- wtr_->OnPlaying();
-
- // No log should have been generated yet since the message loop has not had
- // any chance to pump.
- CycleWatchTimeReporter();
- ExpectWatchTime(std::vector<base::StringPiece>(), base::TimeDelta());
-
- CycleWatchTimeReporter();
-
- // Transition back to display inline, this should generate controls watch time
- // as well.
- wtr_->OnDisplayTypeInline();
- CycleWatchTimeReporter();
-
- // This should finalize the power watch time on display type.
- ExpectWatchTime({media::kWatchTimeAudioVideoDisplayFullscreen}, kWatchTime2);
- ResetHistogramTester();
- wtr_.reset();
-
- std::vector<base::StringPiece> normal_keys = {
- media::kWatchTimeAudioVideoAll,
- media::kWatchTimeAudioVideoSrc,
- media::kWatchTimeAudioVideoEme,
- media::kWatchTimeAudioVideoAc,
- media::kWatchTimeAudioVideoNativeControlsOff,
- media::kWatchTimeAudioVideoEmbeddedExperience};
-
- for (auto key : watch_time_keys_) {
- if (key == media::kWatchTimeAudioVideoDisplayInline) {
- histogram_tester_->ExpectUniqueSample(
- key.as_string(), (kWatchTime3 - kWatchTime2).InMilliseconds(), 1);
- continue;
- }
-
- auto it = std::find(normal_keys.begin(), normal_keys.end(), key);
- if (it == normal_keys.end()) {
- histogram_tester_->ExpectTotalCount(key.as_string(), 0);
- } else {
- histogram_tester_->ExpectUniqueSample(key.as_string(),
- kWatchTime3.InMilliseconds(), 1);
- }
- }
-
- // Each finalize creates a new source and entry. We don't check the URL here
- // since the TestUkmService() helpers DCHECK() a unique URL per source.
- ASSERT_EQ(2U, test_recorder_->sources_count());
- ASSERT_EQ(2U, test_recorder_->entries_count());
- ExpectUkmWatchTime(0, 1, kWatchTime2);
-
- // Verify Media.WatchTime keys are properly stripped for UKM reporting.
- EXPECT_TRUE(test_recorder_->FindMetric(test_recorder_->GetEntry(0),
- "AudioVideo.DisplayFullscreen"));
-
- // Spot check one of the non-AC keys; this relies on the assumption that the
- // AC metric is not last.
- const auto& metrics_vector = test_recorder_->GetEntry(1)->metrics;
- ASSERT_EQ(6U, metrics_vector.size());
- EXPECT_EQ(kWatchTime3.InMilliseconds(), metrics_vector.back()->value);
-}
-
-TEST_F(MediaInternalsWatchTimeTest, PowerControlsFinalize) {
- constexpr base::TimeDelta kWatchTime1 = base::TimeDelta::FromSeconds(5);
- constexpr base::TimeDelta kWatchTime2 = base::TimeDelta::FromSeconds(10);
- constexpr base::TimeDelta kWatchTime3 = base::TimeDelta::FromSeconds(30);
- EXPECT_CALL(*this, GetCurrentMediaTime())
- .WillOnce(testing::Return(base::TimeDelta()))
- .WillOnce(testing::Return(kWatchTime1))
- .WillOnce(testing::Return(kWatchTime1))
- .WillOnce(testing::Return(kWatchTime2))
- .WillOnce(testing::Return(kWatchTime2))
- .WillRepeatedly(testing::Return(kWatchTime3));
-
- Initialize(true, true, false, true);
- wtr_->OnPlaying();
-
- // No log should have been generated yet since the message loop has not had
- // any chance to pump.
- CycleWatchTimeReporter();
- ExpectWatchTime(std::vector<base::StringPiece>(), base::TimeDelta());
-
- CycleWatchTimeReporter();
-
- // Transition controls and power.
- wtr_->OnNativeControlsEnabled();
- wtr_->OnPowerStateChangeForTesting(true);
- CycleWatchTimeReporter();
-
- // This should finalize the power and controls watch times.
- ExpectWatchTime({media::kWatchTimeAudioVideoNativeControlsOff,
- media::kWatchTimeAudioVideoAc},
- kWatchTime2);
- ResetHistogramTester();
- wtr_.reset();
-}
-
-TEST_F(MediaInternalsWatchTimeTest, PowerDisplayFinalize) {
- constexpr base::TimeDelta kWatchTime1 = base::TimeDelta::FromSeconds(5);
- constexpr base::TimeDelta kWatchTime2 = base::TimeDelta::FromSeconds(10);
- constexpr base::TimeDelta kWatchTime3 = base::TimeDelta::FromSeconds(30);
- EXPECT_CALL(*this, GetCurrentMediaTime())
- .WillOnce(testing::Return(base::TimeDelta()))
- .WillOnce(testing::Return(kWatchTime1))
- .WillOnce(testing::Return(kWatchTime1))
- .WillOnce(testing::Return(kWatchTime2))
- .WillOnce(testing::Return(kWatchTime2))
- .WillRepeatedly(testing::Return(kWatchTime3));
-
- Initialize(true, true, false, true);
- wtr_->OnPlaying();
-
- // No log should have been generated yet since the message loop has not had
- // any chance to pump.
- CycleWatchTimeReporter();
- ExpectWatchTime(std::vector<base::StringPiece>(), base::TimeDelta());
-
- CycleWatchTimeReporter();
-
- // Transition display and power.
- wtr_->OnDisplayTypePictureInPicture();
- wtr_->OnPowerStateChangeForTesting(true);
- CycleWatchTimeReporter();
-
- // This should finalize the power and controls watch times.
- ExpectWatchTime(
- {media::kWatchTimeAudioVideoDisplayInline, media::kWatchTimeAudioVideoAc},
- kWatchTime2);
- ResetHistogramTester();
- wtr_.reset();
-}
-
-TEST_F(MediaInternalsWatchTimeTest, PowerDisplayControlsFinalize) {
- constexpr base::TimeDelta kWatchTime1 = base::TimeDelta::FromSeconds(5);
- constexpr base::TimeDelta kWatchTime2 = base::TimeDelta::FromSeconds(10);
- constexpr base::TimeDelta kWatchTime3 = base::TimeDelta::FromSeconds(30);
- EXPECT_CALL(*this, GetCurrentMediaTime())
- .WillOnce(testing::Return(base::TimeDelta()))
- .WillOnce(testing::Return(kWatchTime1))
- .WillOnce(testing::Return(kWatchTime1))
- .WillOnce(testing::Return(kWatchTime2))
- .WillOnce(testing::Return(kWatchTime2))
- .WillOnce(testing::Return(kWatchTime2))
- .WillRepeatedly(testing::Return(kWatchTime3));
-
- Initialize(true, true, false, true);
- wtr_->OnPlaying();
-
- // No log should have been generated yet since the message loop has not had
- // any chance to pump.
- CycleWatchTimeReporter();
- ExpectWatchTime(std::vector<base::StringPiece>(), base::TimeDelta());
-
- CycleWatchTimeReporter();
-
- // Transition display and power.
- wtr_->OnNativeControlsEnabled();
- wtr_->OnDisplayTypeFullscreen();
- wtr_->OnPowerStateChangeForTesting(true);
- CycleWatchTimeReporter();
-
- // This should finalize the power and controls watch times.
- ExpectWatchTime({media::kWatchTimeAudioVideoDisplayInline,
- media::kWatchTimeAudioVideoNativeControlsOff,
- media::kWatchTimeAudioVideoAc},
- kWatchTime2);
- ResetHistogramTester();
- wtr_.reset();
-}
-
-TEST_F(MediaInternalsWatchTimeTest, BasicHidden) {
- constexpr base::TimeDelta kWatchTimeEarly = base::TimeDelta::FromSeconds(5);
- constexpr base::TimeDelta kWatchTimeLate = base::TimeDelta::FromSeconds(10);
- EXPECT_CALL(*this, GetCurrentMediaTime())
- .WillOnce(testing::Return(base::TimeDelta()))
- .WillOnce(testing::Return(kWatchTimeEarly))
- .WillRepeatedly(testing::Return(kWatchTimeLate));
- Initialize(true, true, false, true);
- wtr_->OnHidden();
- wtr_->OnPlaying();
-
- // No log should have been generated yet since the message loop has not had
- // any chance to pump.
- CycleWatchTimeReporter();
- ExpectWatchTime(std::vector<base::StringPiece>(), base::TimeDelta());
-
- CycleWatchTimeReporter();
- wtr_.reset();
-
- ExpectWatchTime({media::kWatchTimeAudioVideoBackgroundAll,
- media::kWatchTimeAudioVideoBackgroundSrc,
- media::kWatchTimeAudioVideoBackgroundEme,
- media::kWatchTimeAudioVideoBackgroundAc,
- media::kWatchTimeAudioVideoBackgroundEmbeddedExperience},
- kWatchTimeLate);
-
- ASSERT_EQ(1U, test_recorder_->sources_count());
- ExpectUkmWatchTime(0, 4, kWatchTimeLate);
- EXPECT_TRUE(test_recorder_->GetSourceForUrl(kTestOrigin));
-}
-
-TEST_F(MediaInternalsWatchTimeTest, FinalizeWithoutWatchTime) {
- EXPECT_CALL(*this, GetCurrentMediaTime())
- .WillRepeatedly(testing::Return(base::TimeDelta()));
- Initialize(true, true, false, true);
- wtr_->OnPlaying();
- wtr_.reset();
-
- // No watch time should have been recorded even though a finalize event will
- // be sent.
- ExpectWatchTime(std::vector<base::StringPiece>(), base::TimeDelta());
- ExpectMtbrTime(std::vector<base::StringPiece>(), base::TimeDelta());
- ExpectZeroRebuffers(std::vector<base::StringPiece>());
- ASSERT_EQ(0U, test_recorder_->sources_count());
-}
-
-TEST_F(MediaInternalsWatchTimeTest, PlayerDestructionFinalizes) {
- constexpr base::TimeDelta kWatchTimeEarly = base::TimeDelta::FromSeconds(5);
- constexpr base::TimeDelta kWatchTimeLate = base::TimeDelta::FromSeconds(10);
- EXPECT_CALL(*this, GetCurrentMediaTime())
- .WillOnce(testing::Return(base::TimeDelta()))
- .WillOnce(testing::Return(kWatchTimeEarly))
- .WillRepeatedly(testing::Return(kWatchTimeLate));
- Initialize(true, true, true, true);
- wtr_->OnPlaying();
-
- // No log should have been generated yet since the message loop has not had
- // any chance to pump.
- CycleWatchTimeReporter();
- ExpectWatchTime(std::vector<base::StringPiece>(), base::TimeDelta());
-
- CycleWatchTimeReporter();
-
- media_log_->AddEvent(
- media_log_->CreateEvent(media::MediaLogEvent::WEBMEDIAPLAYER_DESTROYED));
-
- ExpectWatchTime(
- {media::kWatchTimeAudioVideoAll, media::kWatchTimeAudioVideoMse,
- media::kWatchTimeAudioVideoEme, media::kWatchTimeAudioVideoAc,
- media::kWatchTimeAudioVideoNativeControlsOff,
- media::kWatchTimeAudioVideoDisplayInline,
- media::kWatchTimeAudioVideoEmbeddedExperience},
- kWatchTimeLate);
- ExpectZeroRebuffers({media::kRebuffersCountAudioVideoMse,
- media::kRebuffersCountAudioVideoEme});
-
- ASSERT_EQ(1U, test_recorder_->sources_count());
- ExpectUkmWatchTime(0, 6, kWatchTimeLate);
- EXPECT_TRUE(test_recorder_->GetSourceForUrl(kTestOrigin));
-}
-
-TEST_F(MediaInternalsWatchTimeTest, ProcessDestructionFinalizes) {
- constexpr base::TimeDelta kWatchTimeEarly = base::TimeDelta::FromSeconds(5);
- constexpr base::TimeDelta kWatchTimeLate = base::TimeDelta::FromSeconds(10);
- EXPECT_CALL(*this, GetCurrentMediaTime())
- .WillOnce(testing::Return(base::TimeDelta()))
- .WillOnce(testing::Return(kWatchTimeEarly))
- .WillRepeatedly(testing::Return(kWatchTimeLate));
- Initialize(true, true, false, true);
- wtr_->OnPlaying();
-
- // No log should have been generated yet since the message loop has not had
- // any chance to pump.
- CycleWatchTimeReporter();
- ExpectWatchTime(std::vector<base::StringPiece>(), base::TimeDelta());
-
- CycleWatchTimeReporter();
-
- // Also verify that if UKM has already been destructed, we don't crash.
- test_recorder_.reset();
- internals_->OnProcessTerminatedForTesting(render_process_id_);
- ExpectWatchTime(
- {media::kWatchTimeAudioVideoAll, media::kWatchTimeAudioVideoSrc,
- media::kWatchTimeAudioVideoEme, media::kWatchTimeAudioVideoAc,
- media::kWatchTimeAudioVideoNativeControlsOff,
- media::kWatchTimeAudioVideoDisplayInline,
- media::kWatchTimeAudioVideoEmbeddedExperience},
- kWatchTimeLate);
- ExpectZeroRebuffers({media::kRebuffersCountAudioVideoSrc,
- media::kRebuffersCountAudioVideoEme});
-}
-
} // namespace content
diff --git a/chromium/content/browser/media/media_source_browsertest.cc b/chromium/content/browser/media/media_source_browsertest.cc
index 0070da5c096..51e62475668 100644
--- a/chromium/content/browser/media/media_source_browsertest.cc
+++ b/chromium/content/browser/media/media_source_browsertest.cc
@@ -3,6 +3,7 @@
// 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"
@@ -24,6 +25,8 @@ const char kWebMVideoOnly[] = "video/webm; codecs=\"vp8\"";
const char kWebMAudioVideo[] = "video/webm; codecs=\"vorbis, vp8\"";
#if BUILDFLAG(USE_PROPRIETARY_CODECS)
+const char kMp4FlacAudioOnly[] = "audio/mp4; codecs=\"flac\"";
+
#if BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER)
const char kMp2tAudioVideo[] = "video/mp2t; codecs=\"mp4a.40.2, avc1.42E01E\"";
#endif
@@ -45,7 +48,11 @@ class MediaSourceTest : public content::MediaBrowserTest {
void SetUpCommandLine(base::CommandLine* command_line) override {
command_line->AppendSwitch(switches::kIgnoreAutoplayRestrictionsForTests);
+ scoped_feature_list_.InitAndDisableFeature(media::kMseFlacInIsobmff);
}
+
+ protected:
+ base::test::ScopedFeatureList scoped_feature_list_;
};
IN_PROC_BROWSER_TEST_F(MediaSourceTest, Playback_VideoAudio_WebM) {
@@ -105,6 +112,12 @@ IN_PROC_BROWSER_TEST_F(MediaSourceTest, Playback_Video_WEBM_Audio_MP4) {
query_params.push_back(std::make_pair("audioFormat", "CLEAR_MP4"));
RunMediaTestPage("mse_different_containers.html", query_params, kEnded, true);
}
+
+IN_PROC_BROWSER_TEST_F(MediaSourceTest,
+ Playback_AudioOnly_FLAC_MP4_Unsupported) {
+ // The feature is disabled by test setup, so verify playback failure.
+ TestSimplePlayback("bear-flac_frag.mp4", kMp4FlacAudioOnly, kFailed);
+}
#endif
#if BUILDFLAG(USE_PROPRIETARY_CODECS)
@@ -114,4 +127,23 @@ IN_PROC_BROWSER_TEST_F(MediaSourceTest, Playback_AudioVideo_Mp2t) {
}
#endif
#endif
+
+#if BUILDFLAG(USE_PROPRIETARY_CODECS)
+class MediaSourceFlacInIsobmffTest : public content::MediaSourceTest {
+ public:
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ command_line->AppendSwitch(switches::kIgnoreAutoplayRestrictionsForTests);
+
+ // Enable MSE FLAC-in-MP4 feature.
+ scoped_feature_list_.InitAndEnableFeature(media::kMseFlacInIsobmff);
+ }
+};
+
+IN_PROC_BROWSER_TEST_F(MediaSourceFlacInIsobmffTest,
+ Playback_AudioOnly_FLAC_MP4_Supported) {
+ // The feature is enabled by test setup, so verify playback success.
+ TestSimplePlayback("bear-flac_frag.mp4", kMp4FlacAudioOnly, kEnded);
+}
+#endif
+
} // namespace content
diff --git a/chromium/content/browser/media/media_web_contents_observer.cc b/chromium/content/browser/media/media_web_contents_observer.cc
index ebecb7c8026..c28a5e9e0ca 100644
--- a/chromium/content/browser/media/media_web_contents_observer.cc
+++ b/chromium/content/browser/media/media_web_contents_observer.cc
@@ -27,6 +27,19 @@ AudibleMetrics* GetAudibleMetrics() {
return metrics;
}
+void CheckFullscreenDetectionEnabled(WebContents* web_contents) {
+#if defined(OS_ANDROID)
+ DCHECK(web_contents->GetRenderViewHost()
+ ->GetWebkitPreferences()
+ .video_fullscreen_detection_enabled)
+ << "Attempt to use method relying on fullscreen detection while "
+ << "fullscreen detection is disabled.";
+#else // defined(OS_ANDROID)
+ NOTREACHED() << "Attempt to use method relying on fullscreen detection, "
+ << "which is only enabled on Android.";
+#endif // defined(OS_ANDROID)
+}
+
} // anonymous namespace
MediaWebContentsObserver::MediaWebContentsObserver(WebContents* web_contents)
@@ -64,6 +77,7 @@ void MediaWebContentsObserver::MaybeUpdateAudibleState() {
}
bool MediaWebContentsObserver::HasActiveEffectivelyFullscreenVideo() const {
+ CheckFullscreenDetectionEnabled(web_contents_impl());
if (!web_contents()->IsFullscreen() || !fullscreen_player_)
return false;
@@ -77,6 +91,12 @@ bool MediaWebContentsObserver::HasActiveEffectivelyFullscreenVideo() const {
return true;
}
+const base::Optional<WebContentsObserver::MediaPlayerId>&
+MediaWebContentsObserver::GetFullscreenVideoMediaPlayerId() const {
+ CheckFullscreenDetectionEnabled(web_contents_impl());
+ return fullscreen_player_;
+}
+
bool MediaWebContentsObserver::OnMessageReceived(
const IPC::Message& msg,
RenderFrameHost* render_frame_host) {
diff --git a/chromium/content/browser/media/media_web_contents_observer.h b/chromium/content/browser/media/media_web_contents_observer.h
index a2409eadbcf..13cc628ac69 100644
--- a/chromium/content/browser/media/media_web_contents_observer.h
+++ b/chromium/content/browser/media/media_web_contents_observer.h
@@ -50,6 +50,9 @@ class CONTENT_EXPORT MediaWebContentsObserver : public WebContentsObserver {
// It should only be called while the WebContents is fullscreen.
bool HasActiveEffectivelyFullscreenVideo() const;
+ // Gets the MediaPlayerId of the fullscreen video if it exists.
+ const base::Optional<MediaPlayerId>& GetFullscreenVideoMediaPlayerId() const;
+
// WebContentsObserver implementation.
void WebContentsDestroyed() override;
void RenderFrameDeleted(RenderFrameHost* render_frame_host) override;
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 e778f71f066..603c5c9b6a2 100644
--- a/chromium/content/browser/media/session/audio_focus_delegate_android.cc
+++ b/chromium/content/browser/media/session/audio_focus_delegate_android.cc
@@ -12,11 +12,6 @@ using base::android::JavaParamRef;
namespace content {
-// static
-bool AudioFocusDelegateAndroid::Register(JNIEnv* env) {
- return RegisterNativesImpl(env);
-}
-
AudioFocusDelegateAndroid::AudioFocusDelegateAndroid(
MediaSessionImpl* media_session)
: media_session_(media_session) {}
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 b888b50fd3b..1c787004724 100644
--- a/chromium/content/browser/media/session/audio_focus_delegate_android.h
+++ b/chromium/content/browser/media/session/audio_focus_delegate_android.h
@@ -16,8 +16,6 @@ namespace content {
// Android. It is also proxying the JNI calls.
class AudioFocusDelegateAndroid : public AudioFocusDelegate {
public:
- static bool Register(JNIEnv* env);
-
explicit AudioFocusDelegateAndroid(MediaSessionImpl* media_session);
~AudioFocusDelegateAndroid() override;
diff --git a/chromium/content/browser/media/session/media_session_android.cc b/chromium/content/browser/media/session/media_session_android.cc
index 135e3043118..48f3e1f5e68 100644
--- a/chromium/content/browser/media/session/media_session_android.cc
+++ b/chromium/content/browser/media/session/media_session_android.cc
@@ -39,11 +39,6 @@ MediaSessionAndroid::MediaSessionAndroid(MediaSessionImpl* session)
MediaSessionAndroid::~MediaSessionAndroid() = default;
// static
-bool MediaSessionAndroid::Register(JNIEnv* env) {
- return RegisterNativesImpl(env);
-}
-
-// static
ScopedJavaLocalRef<jobject> GetMediaSessionFromWebContents(
JNIEnv* env,
const JavaParamRef<jclass>& clazz,
diff --git a/chromium/content/browser/media/session/media_session_android.h b/chromium/content/browser/media/session/media_session_android.h
index 141cce9be2c..614f4509505 100644
--- a/chromium/content/browser/media/session/media_session_android.h
+++ b/chromium/content/browser/media/session/media_session_android.h
@@ -28,8 +28,6 @@ class MediaSessionAndroid final : public MediaSessionObserver {
// avoid leaking the Java object outside.
struct JavaObjectGetter;
- static bool Register(JNIEnv* env);
-
explicit MediaSessionAndroid(MediaSessionImpl* session);
~MediaSessionAndroid() override;
diff --git a/chromium/content/browser/media/session/media_session_controller.h b/chromium/content/browser/media/session/media_session_controller.h
index a7cc5cf5190..5a35b25fd4b 100644
--- a/chromium/content/browser/media/session/media_session_controller.h
+++ b/chromium/content/browser/media/session/media_session_controller.h
@@ -24,7 +24,7 @@ class MediaWebContentsObserver;
// browser side MediaSession commands back to a player hosted in the renderer
// process.
class CONTENT_EXPORT MediaSessionController
- : NON_EXPORTED_BASE(public MediaSessionPlayerObserver) {
+ : public MediaSessionPlayerObserver {
public:
MediaSessionController(const WebContentsObserver::MediaPlayerId& id,
MediaWebContentsObserver* media_web_contents_observer);
diff --git a/chromium/content/browser/media/session/media_session_impl.cc b/chromium/content/browser/media/session/media_session_impl.cc
index 21e9925f5dd..5a2642d43ba 100644
--- a/chromium/content/browser/media/session/media_session_impl.cc
+++ b/chromium/content/browser/media/session/media_session_impl.cc
@@ -395,6 +395,24 @@ void MediaSessionImpl::Stop(SuspendType suspend_type) {
AbandonSystemAudioFocusIfNeeded();
}
+bool MediaSessionImpl::IsControllable() const {
+ // Only media session having focus Gain can be controllable unless it is
+ // inactive. Also, the session will be uncontrollable if it contains one-shot
+ // players.
+ return audio_focus_state_ != State::INACTIVE &&
+ audio_focus_type_ == AudioFocusManager::AudioFocusType::Gain &&
+ one_shot_players_.empty();
+}
+
+bool MediaSessionImpl::IsActuallyPaused() const {
+ if (routed_service_ && routed_service_->playback_state() ==
+ blink::mojom::MediaSessionPlaybackState::PLAYING) {
+ return false;
+ }
+
+ return !IsActive();
+}
+
void MediaSessionImpl::StartDucking() {
if (is_ducking_)
return;
@@ -428,24 +446,6 @@ bool MediaSessionImpl::IsSuspended() const {
return audio_focus_state_ == State::SUSPENDED;
}
-bool MediaSessionImpl::IsControllable() const {
- // Only media session having focus Gain can be controllable unless it is
- // inactive. Also, the session will be uncontrollable if it contains one-shot
- // players.
- return audio_focus_state_ != State::INACTIVE &&
- audio_focus_type_ == AudioFocusManager::AudioFocusType::Gain &&
- one_shot_players_.empty();
-}
-
-bool MediaSessionImpl::IsActuallyPaused() const {
- if (routed_service_ && routed_service_->playback_state() ==
- blink::mojom::MediaSessionPlaybackState::PLAYING) {
- return false;
- }
-
- return !IsActive();
-}
-
bool MediaSessionImpl::HasPepper() const {
return !pepper_players_.empty();
}
diff --git a/chromium/content/browser/media/session/media_session_impl.h b/chromium/content/browser/media/session/media_session_impl.h
index 5e897b0f276..407adfea5c8 100644
--- a/chromium/content/browser/media/session/media_session_impl.h
+++ b/chromium/content/browser/media/session/media_session_impl.h
@@ -11,7 +11,7 @@
#include <set>
#include "base/callback_list.h"
-#include "base/id_map.h"
+#include "base/containers/id_map.h"
#include "base/macros.h"
#include "base/observer_list.h"
#include "base/optional.h"
@@ -127,6 +127,14 @@ class MediaSessionImpl : public MediaSession,
// |type| represents the origin of the request.
CONTENT_EXPORT void Stop(MediaSession::SuspendType suspend_type) 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;
+
// Let the media session start ducking such that the volume multiplier is
// reduced.
CONTENT_EXPORT void StartDucking() override;
@@ -138,10 +146,6 @@ class MediaSessionImpl : public MediaSession,
void AddObserver(MediaSessionObserver* observer) override;
void RemoveObserver(MediaSessionObserver* observer) override;
- // Returns if the session can be controlled by Resume() and Suspend calls
- // above.
- CONTENT_EXPORT bool IsControllable() const;
-
// Returns if the session is currently active.
CONTENT_EXPORT bool IsActive() const;
@@ -253,10 +257,6 @@ class MediaSessionImpl : public MediaSession,
// ducking.
double GetVolumeMultiplier() const;
- // Compute if the actual playback state is paused by combining the
- // MediaSessionService declared state and guessed state (audio_focus_state_).
- bool IsActuallyPaused() const;
-
// Registers a MediaSessionImpl state change callback.
CONTENT_EXPORT std::unique_ptr<base::CallbackList<void(State)>::Subscription>
RegisterMediaSessionStateChangedCallbackForTest(
diff --git a/chromium/content/browser/media/session/media_session_impl_visibility_browsertest.cc b/chromium/content/browser/media/session/media_session_impl_visibility_browsertest.cc
index a5ad0b02355..95b22939bde 100644
--- a/chromium/content/browser/media/session/media_session_impl_visibility_browsertest.cc
+++ b/chromium/content/browser/media/session/media_session_impl_visibility_browsertest.cc
@@ -7,6 +7,7 @@
#include "base/command_line.h"
#include "base/location.h"
#include "base/logging.h"
+#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/test/scoped_feature_list.h"
#include "base/threading/thread_task_runner_handle.h"
diff --git a/chromium/content/browser/media/url_provision_fetcher.cc b/chromium/content/browser/media/url_provision_fetcher.cc
index 6a0c89644e7..935fe0a4e08 100644
--- a/chromium/content/browser/media/url_provision_fetcher.cc
+++ b/chromium/content/browser/media/url_provision_fetcher.cc
@@ -57,7 +57,7 @@ void URLProvisionFetcher::Retrieve(
destination: OTHER
}
policy {
- cookies_allowed: false
+ cookies_allowed: NO
setting:
"On Android, users can disable this feature by disabling Protected "
"Media Identifier permissions."
diff --git a/chromium/content/browser/memory/memory_coordinator_impl_unittest.cc b/chromium/content/browser/memory/memory_coordinator_impl_unittest.cc
index b257ce9083b..f44c9fbf85b 100644
--- a/chromium/content/browser/memory/memory_coordinator_impl_unittest.cc
+++ b/chromium/content/browser/memory/memory_coordinator_impl_unittest.cc
@@ -445,12 +445,8 @@ TEST_F(MemoryCoordinatorImplTest, MAYBE_GetStateForProcess) {
coordinator_->CreateChildMemoryCoordinator(1);
coordinator_->CreateChildMemoryCoordinator(2);
-
- base::SpawnChildResult spawn_result1 = SpawnChild("process1");
- base::Process& process1 = spawn_result1.process;
- base::SpawnChildResult spawn_result2 = SpawnChild("process2");
- base::Process& process2 = spawn_result2.process;
-
+ base::Process process1 = SpawnChild("process1");
+ base::Process process2 = SpawnChild("process2");
coordinator_->GetMockRenderProcessHost(1)->SetProcessHandle(
base::MakeUnique<base::ProcessHandle>(process1.Handle()));
coordinator_->GetMockRenderProcessHost(2)->SetProcessHandle(
diff --git a/chromium/content/browser/memory/memory_monitor_android.cc b/chromium/content/browser/memory/memory_monitor_android.cc
index 1bf1c0107c3..93a0e70e391 100644
--- a/chromium/content/browser/memory/memory_monitor_android.cc
+++ b/chromium/content/browser/memory/memory_monitor_android.cc
@@ -83,11 +83,6 @@ std::unique_ptr<MemoryMonitorAndroid> MemoryMonitorAndroid::Create() {
return base::WrapUnique(new MemoryMonitorAndroid(std::move(delegate)));
}
-// static
-bool MemoryMonitorAndroid::Register(JNIEnv* env) {
- return RegisterNativesImpl(env);
-}
-
MemoryMonitorAndroid::MemoryMonitorAndroid(std::unique_ptr<Delegate> delegate)
: delegate_(std::move(delegate)) {
DCHECK(delegate_.get());
diff --git a/chromium/content/browser/memory/memory_monitor_android.h b/chromium/content/browser/memory/memory_monitor_android.h
index 463dd985919..7f06897a6d9 100644
--- a/chromium/content/browser/memory/memory_monitor_android.h
+++ b/chromium/content/browser/memory/memory_monitor_android.h
@@ -17,8 +17,6 @@ class CONTENT_EXPORT MemoryMonitorAndroid : public MemoryMonitor {
public:
static std::unique_ptr<MemoryMonitorAndroid> Create();
- static bool Register(JNIEnv* env);
-
// C++ counter-part of ActivityManager.MemoryInfo
struct MemoryInfo {
jlong avail_mem;
diff --git a/chromium/content/browser/memory/memory_monitor_fuchsia.cc b/chromium/content/browser/memory/memory_monitor_fuchsia.cc
new file mode 100644
index 00000000000..9bcbf8d3316
--- /dev/null
+++ b/chromium/content/browser/memory/memory_monitor_fuchsia.cc
@@ -0,0 +1,17 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/memory/memory_monitor.h"
+
+#include "base/logging.h"
+
+namespace content {
+
+// TODO(crbug.com/707031): Implement this.
+std::unique_ptr<MemoryMonitor> CreateMemoryMonitor() {
+ NOTIMPLEMENTED();
+ return nullptr;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/memory/swap_metrics_delegate_uma.cc b/chromium/content/browser/memory/swap_metrics_delegate_uma.cc
new file mode 100644
index 00000000000..7745eabacb0
--- /dev/null
+++ b/chromium/content/browser/memory/swap_metrics_delegate_uma.cc
@@ -0,0 +1,43 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/memory/swap_metrics_delegate_uma.h"
+
+#include "base/metrics/histogram_macros.h"
+
+namespace content {
+
+SwapMetricsDelegateUma::SwapMetricsDelegateUma() = default;
+
+SwapMetricsDelegateUma::~SwapMetricsDelegateUma() = default;
+
+void SwapMetricsDelegateUma::OnSwapInCount(uint64_t count,
+ base::TimeDelta interval) {
+ UMA_HISTOGRAM_COUNTS_10000(
+ "Memory.Experimental.SwapInPerSecond",
+ static_cast<double>(count) / interval.InSecondsF());
+}
+
+void SwapMetricsDelegateUma::OnSwapOutCount(uint64_t count,
+ base::TimeDelta interval) {
+ UMA_HISTOGRAM_COUNTS_10000(
+ "Memory.Experimental.SwapOutPerSecond",
+ static_cast<double>(count) / interval.InSecondsF());
+}
+
+void SwapMetricsDelegateUma::OnDecompressedPageCount(uint64_t count,
+ base::TimeDelta interval) {
+ UMA_HISTOGRAM_COUNTS_10000(
+ "Memory.Experimental.DecompressedPagesPerSecond",
+ static_cast<double>(count) / interval.InSecondsF());
+}
+
+void SwapMetricsDelegateUma::OnCompressedPageCount(uint64_t count,
+ base::TimeDelta interval) {
+ UMA_HISTOGRAM_COUNTS_10000(
+ "Memory.Experimental.CompressedPagesPerSecond",
+ static_cast<double>(count) / interval.InSecondsF());
+}
+
+} // namespace content
diff --git a/chromium/content/browser/memory/swap_metrics_delegate_uma.h b/chromium/content/browser/memory/swap_metrics_delegate_uma.h
new file mode 100644
index 00000000000..33b55f56cbb
--- /dev/null
+++ b/chromium/content/browser/memory/swap_metrics_delegate_uma.h
@@ -0,0 +1,33 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_MEMORY_SWAP_METRICS_DELEGATE_UMA_H_
+#define CONTENT_BROWSER_MEMORY_SWAP_METRICS_DELEGATE_UMA_H_
+
+#include "content/public/browser/swap_metrics_driver.h"
+
+#include "base/time/time.h"
+
+namespace content {
+
+// This class records metrics related to the system's swapping behavior.
+// Metrics can be platform-specific.
+class SwapMetricsDelegateUma : public SwapMetricsDriver::Delegate {
+ public:
+ SwapMetricsDelegateUma();
+ ~SwapMetricsDelegateUma() override;
+
+ void OnSwapInCount(uint64_t count, base::TimeDelta interval) override;
+ void OnSwapOutCount(uint64_t count, base::TimeDelta interval) override;
+ void OnDecompressedPageCount(uint64_t count,
+ base::TimeDelta interval) override;
+ void OnCompressedPageCount(uint64_t count, base::TimeDelta interval) override;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(SwapMetricsDelegateUma);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_MEMORY_SWAP_METRICS_DELEGATE_UMA_H_
diff --git a/chromium/content/browser/memory/swap_metrics_driver_impl.cc b/chromium/content/browser/memory/swap_metrics_driver_impl.cc
new file mode 100644
index 00000000000..f16e904a86e
--- /dev/null
+++ b/chromium/content/browser/memory/swap_metrics_driver_impl.cc
@@ -0,0 +1,98 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/memory/swap_metrics_driver_impl.h"
+
+#include <memory>
+
+#include "base/macros.h"
+#include "base/sequence_checker.h"
+#include "base/time/time.h"
+
+namespace content {
+
+SwapMetricsDriverImpl::Delegate::Delegate() = default;
+
+SwapMetricsDriverImpl::Delegate::~Delegate() = default;
+
+SwapMetricsDriverImpl::SwapMetricsDriverImpl(
+ std::unique_ptr<Delegate> delegate,
+ const base::TimeDelta update_interval)
+ : delegate_(std::move(delegate)),
+ update_interval_(update_interval),
+ is_initialized_(false) {
+ DCHECK(delegate_);
+ DETACH_FROM_SEQUENCE(sequence_checker_);
+}
+
+SwapMetricsDriverImpl::~SwapMetricsDriverImpl() = default;
+
+SwapMetricsDriver::SwapMetricsUpdateResult
+SwapMetricsDriverImpl::InitializeMetrics() {
+ last_ticks_ = base::TimeTicks();
+ auto result = UpdateMetricsImpl();
+ if (result ==
+ SwapMetricsDriver::SwapMetricsUpdateResult::kSwapMetricsUpdateSuccess)
+ is_initialized_ = true;
+ return result;
+}
+
+bool SwapMetricsDriverImpl::IsRunning() const {
+ return timer_.IsRunning();
+}
+
+void SwapMetricsDriverImpl::PeriodicUpdateMetrics() {
+ SwapMetricsDriver::SwapMetricsUpdateResult result = UpdateMetricsImpl();
+ if (result !=
+ SwapMetricsDriver::SwapMetricsUpdateResult::kSwapMetricsUpdateSuccess)
+ Stop();
+}
+
+SwapMetricsDriver::SwapMetricsUpdateResult SwapMetricsDriverImpl::Start() {
+ DCHECK(update_interval_.InSeconds() > 0);
+
+ SwapMetricsDriver::SwapMetricsUpdateResult result = InitializeMetrics();
+ if (result !=
+ SwapMetricsDriver::SwapMetricsUpdateResult::kSwapMetricsUpdateSuccess)
+ return result;
+
+ timer_.Start(FROM_HERE, update_interval_, this,
+ &SwapMetricsDriverImpl::PeriodicUpdateMetrics);
+ return SwapMetricsDriver::SwapMetricsUpdateResult::kSwapMetricsUpdateSuccess;
+}
+
+void SwapMetricsDriverImpl::Stop() {
+ timer_.Stop();
+}
+
+SwapMetricsDriver::SwapMetricsUpdateResult
+SwapMetricsDriverImpl::UpdateMetrics() {
+ // Enforce initialization before updates.
+ DCHECK(is_initialized_);
+ return UpdateMetricsImpl();
+}
+
+SwapMetricsDriver::SwapMetricsUpdateResult
+SwapMetricsDriverImpl::UpdateMetricsImpl() {
+ // This covers all cases where metrics get updated, and is the critical secion
+ // in the driver.
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ base::TimeTicks now = base::TimeTicks::Now();
+ base::TimeDelta interval =
+ last_ticks_.is_null() ? base::TimeDelta() : now - last_ticks_;
+
+ SwapMetricsDriver::SwapMetricsUpdateResult result =
+ UpdateMetricsInternal(interval);
+ if (result !=
+ SwapMetricsDriver::SwapMetricsUpdateResult::kSwapMetricsUpdateSuccess) {
+ delegate_->OnUpdateMetricsFailed();
+ return result;
+ }
+
+ last_ticks_ = now;
+ return SwapMetricsDriver::SwapMetricsUpdateResult::kSwapMetricsUpdateSuccess;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/memory/swap_metrics_driver_impl.h b/chromium/content/browser/memory/swap_metrics_driver_impl.h
new file mode 100644
index 00000000000..8339110c697
--- /dev/null
+++ b/chromium/content/browser/memory/swap_metrics_driver_impl.h
@@ -0,0 +1,78 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_MEMORY_SWAP_METRICS_DRIVER_IMPL_H_
+#define CONTENT_BROWSER_MEMORY_SWAP_METRICS_DRIVER_IMPL_H_
+
+#include <memory>
+
+#include "base/gtest_prod_util.h"
+#include "base/sequence_checker.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
+#include "content/common/content_export.h"
+#include "content/public/browser/swap_metrics_driver.h"
+
+namespace content {
+
+// SwapMetricsDriverImpl is the platform independent portion of the
+// SwapMetricsDriver implementation.
+class CONTENT_EXPORT SwapMetricsDriverImpl : public SwapMetricsDriver {
+ public:
+ ~SwapMetricsDriverImpl() override;
+
+ // SwapMetricsDriver
+ SwapMetricsDriver::SwapMetricsUpdateResult InitializeMetrics() override;
+ bool IsRunning() const override;
+ SwapMetricsDriver::SwapMetricsUpdateResult Start() override;
+ void Stop() override;
+ SwapMetricsDriver::SwapMetricsUpdateResult UpdateMetrics() override;
+
+ protected:
+ SwapMetricsDriverImpl(std::unique_ptr<Delegate> delegate,
+ const base::TimeDelta update_interval);
+
+ // Periodically called to update swap metrics.
+ void PeriodicUpdateMetrics();
+
+ // Common swap metrics update method for both periodic and manual updates.
+ SwapMetricsDriver::SwapMetricsUpdateResult UpdateMetricsImpl();
+
+ // Platform-dependent parts of UpdateMetricsImpl(). |interval| is the elapsed
+ // time since the last UpdateMetricsImpl() call. |interval| will be zero when
+ // this function is called for the first time.
+ virtual SwapMetricsDriver::SwapMetricsUpdateResult UpdateMetricsInternal(
+ base::TimeDelta interval) = 0;
+
+ // The Delegate observing the metrics updates.
+ std::unique_ptr<Delegate> delegate_;
+
+ private:
+ FRIEND_TEST_ALL_PREFIXES(TestSwapMetricsDriver, ExpectedMetricCounts);
+ FRIEND_TEST_ALL_PREFIXES(TestSwapMetricsDriver, UpdateMetricsFail);
+
+ // The interval between metrics updates.
+ base::TimeDelta update_interval_;
+
+ // A periodic timer to update swap metrics.
+ base::RepeatingTimer timer_;
+
+ // Holds the last TimeTicks when swap metrics are updated.
+ base::TimeTicks last_ticks_;
+
+ // True if and only if InitalizeMetrics() was called, and used to enforce
+ // InitializeMetrics() is called before UpdateMetrics(). This helps
+ // code readability.
+ bool is_initialized_;
+
+ // Updating metrics is not thread safe, and this checks that
+ // UpdateMetricsImpl() is always called on the same sequence.
+ SEQUENCE_CHECKER(sequence_checker_);
+
+ DISALLOW_COPY_AND_ASSIGN(SwapMetricsDriverImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_MEMORY_SWAP_METRICS_DRIVER_IMPL_H_
diff --git a/chromium/content/browser/memory/swap_metrics_driver_impl_linux.cc b/chromium/content/browser/memory/swap_metrics_driver_impl_linux.cc
new file mode 100644
index 00000000000..0d8f19782ab
--- /dev/null
+++ b/chromium/content/browser/memory/swap_metrics_driver_impl_linux.cc
@@ -0,0 +1,66 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/memory/swap_metrics_driver_impl_linux.h"
+
+#include <memory>
+
+#include "base/memory/ptr_util.h"
+#include "base/process/process_metrics.h"
+#include "base/time/time.h"
+#include "content/public/browser/swap_metrics_driver.h"
+
+namespace content {
+
+namespace {
+
+bool HasSwap() {
+ base::SystemMemoryInfoKB memory_info;
+ if (!base::GetSystemMemoryInfo(&memory_info))
+ return false;
+ return memory_info.swap_total > 0;
+}
+
+} // namespace
+
+// static
+std::unique_ptr<SwapMetricsDriver> SwapMetricsDriver::Create(
+ std::unique_ptr<Delegate> delegate,
+ const base::TimeDelta update_interval) {
+ return HasSwap() ? base::WrapUnique<SwapMetricsDriver>(
+ new SwapMetricsDriverImplLinux(std::move(delegate),
+ update_interval))
+ : std::unique_ptr<SwapMetricsDriver>();
+}
+
+SwapMetricsDriverImplLinux::SwapMetricsDriverImplLinux(
+ std::unique_ptr<Delegate> delegate,
+ const base::TimeDelta update_interval)
+ : SwapMetricsDriverImpl(std::move(delegate), update_interval) {}
+
+SwapMetricsDriverImplLinux::~SwapMetricsDriverImplLinux() = default;
+
+SwapMetricsDriver::SwapMetricsUpdateResult
+SwapMetricsDriverImplLinux::UpdateMetricsInternal(base::TimeDelta interval) {
+ base::SystemMemoryInfoKB memory_info;
+ if (!base::GetSystemMemoryInfo(&memory_info)) {
+ return SwapMetricsDriver::SwapMetricsUpdateResult::kSwapMetricsUpdateFailed;
+ }
+
+ uint64_t in_counts = memory_info.pswpin - last_pswpin_;
+ uint64_t out_counts = memory_info.pswpout - last_pswpout_;
+ last_pswpin_ = memory_info.pswpin;
+ last_pswpout_ = memory_info.pswpout;
+
+ if (interval.is_zero())
+ return SwapMetricsDriver::SwapMetricsUpdateResult::
+ kSwapMetricsUpdateSuccess;
+
+ delegate_->OnSwapInCount(in_counts, interval);
+ delegate_->OnSwapOutCount(out_counts, interval);
+
+ return SwapMetricsDriver::SwapMetricsUpdateResult::kSwapMetricsUpdateSuccess;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/memory/swap_metrics_driver_impl_linux.h b/chromium/content/browser/memory/swap_metrics_driver_impl_linux.h
new file mode 100644
index 00000000000..6b576d60a2a
--- /dev/null
+++ b/chromium/content/browser/memory/swap_metrics_driver_impl_linux.h
@@ -0,0 +1,32 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_MEMORY_SWAP_METRICS_DRIVER_IMPL_LINUX_H_
+#define CONTENT_BROWSER_MEMORY_SWAP_METRICS_DRIVER_IMPL_LINUX_H_
+
+#include "base/time/time.h"
+#include "content/browser/memory/swap_metrics_driver_impl.h"
+
+#include <memory>
+
+namespace content {
+
+class SwapMetricsDriverImplLinux : public SwapMetricsDriverImpl {
+ public:
+ SwapMetricsDriverImplLinux(std::unique_ptr<Delegate> delegate,
+ const base::TimeDelta update_interval);
+ ~SwapMetricsDriverImplLinux() override;
+
+ protected:
+ SwapMetricsDriver::SwapMetricsUpdateResult UpdateMetricsInternal(
+ base::TimeDelta interval) override;
+
+ private:
+ uint64_t last_pswpin_ = 0;
+ uint64_t last_pswpout_ = 0;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_MEMORY_SWAP_METRICS_DRIVER_IMPL_LINUX_H_
diff --git a/chromium/content/browser/memory/swap_metrics_driver_impl_mac.cc b/chromium/content/browser/memory/swap_metrics_driver_impl_mac.cc
new file mode 100644
index 00000000000..4b4f54d41dd
--- /dev/null
+++ b/chromium/content/browser/memory/swap_metrics_driver_impl_mac.cc
@@ -0,0 +1,67 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/memory/swap_metrics_driver_impl_mac.h"
+
+#include <mach/mach.h>
+#include <mach/mach_vm.h>
+#include <memory>
+
+#include "base/mac/mach_logging.h"
+#include "base/memory/ptr_util.h"
+#include "base/time/time.h"
+
+namespace content {
+
+// static
+std::unique_ptr<SwapMetricsDriver> SwapMetricsDriver::Create(
+ std::unique_ptr<Delegate> delegate,
+ const base::TimeDelta update_interval) {
+ return base::WrapUnique<SwapMetricsDriver>(
+ new SwapMetricsDriverImplMac(std::move(delegate), update_interval));
+}
+
+SwapMetricsDriverImplMac::SwapMetricsDriverImplMac(
+ std::unique_ptr<Delegate> delegate,
+ const base::TimeDelta update_interval)
+ : SwapMetricsDriverImpl(std::move(delegate), update_interval),
+ host_(mach_host_self()) {}
+
+SwapMetricsDriverImplMac::~SwapMetricsDriverImplMac() = default;
+
+SwapMetricsDriver::SwapMetricsUpdateResult
+SwapMetricsDriverImplMac::UpdateMetricsInternal(base::TimeDelta interval) {
+ vm_statistics64_data_t statistics;
+ mach_msg_type_number_t count = HOST_VM_INFO64_COUNT;
+ kern_return_t result =
+ host_statistics64(host_.get(), HOST_VM_INFO64,
+ reinterpret_cast<host_info64_t>(&statistics), &count);
+ if (result != KERN_SUCCESS) {
+ MACH_DLOG(WARNING, result) << "host_statistics64";
+ return SwapMetricsDriver::SwapMetricsUpdateResult::kSwapMetricsUpdateFailed;
+ }
+ DCHECK_EQ(HOST_VM_INFO64_COUNT, count);
+
+ uint64_t swapins = statistics.swapins - last_swapins_;
+ uint64_t swapouts = statistics.swapouts - last_swapouts_;
+ uint64_t decompressions = statistics.decompressions - last_decompressions_;
+ uint64_t compressions = statistics.compressions - last_compressions_;
+ last_swapins_ = statistics.swapins;
+ last_swapouts_ = statistics.swapouts;
+ last_decompressions_ = statistics.decompressions;
+ last_compressions_ = statistics.compressions;
+
+ if (interval.is_zero())
+ return SwapMetricsDriver::SwapMetricsUpdateResult::
+ kSwapMetricsUpdateSuccess;
+
+ delegate_->OnSwapInCount(swapins, interval);
+ delegate_->OnSwapOutCount(swapouts, interval);
+ delegate_->OnDecompressedPageCount(decompressions, interval);
+ delegate_->OnCompressedPageCount(compressions, interval);
+
+ return SwapMetricsDriver::SwapMetricsUpdateResult::kSwapMetricsUpdateSuccess;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/memory/swap_metrics_driver_impl_mac.h b/chromium/content/browser/memory/swap_metrics_driver_impl_mac.h
new file mode 100644
index 00000000000..84ea9234d17
--- /dev/null
+++ b/chromium/content/browser/memory/swap_metrics_driver_impl_mac.h
@@ -0,0 +1,38 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_MEMORY_SWAP_METRICS_DRIVER_IMPL_MAC_H_
+#define CONTENT_BROWSER_MEMORY_SWAP_METRICS_DRIVER_IMPL_MAC_H_
+
+#include "content/browser/memory/swap_metrics_driver_impl.h"
+
+#include <memory>
+
+#include "base/mac/scoped_mach_port.h"
+#include "base/time/time.h"
+
+namespace content {
+
+class SwapMetricsDriverImplMac : public SwapMetricsDriverImpl {
+ public:
+ SwapMetricsDriverImplMac(std::unique_ptr<Delegate> delegate,
+ const base::TimeDelta update_interval);
+ ~SwapMetricsDriverImplMac() override;
+
+ protected:
+ SwapMetricsDriver::SwapMetricsUpdateResult UpdateMetricsInternal(
+ base::TimeDelta interval) override;
+
+ private:
+ base::mac::ScopedMachSendRight host_;
+
+ uint64_t last_swapins_ = 0;
+ uint64_t last_swapouts_ = 0;
+ uint64_t last_decompressions_ = 0;
+ uint64_t last_compressions_ = 0;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_MEMORY_SWAP_METRICS_DRIVER_IMPL_MAC_H_
diff --git a/chromium/content/browser/memory/swap_metrics_driver_impl_unittest.cc b/chromium/content/browser/memory/swap_metrics_driver_impl_unittest.cc
new file mode 100644
index 00000000000..a0fb69de3c2
--- /dev/null
+++ b/chromium/content/browser/memory/swap_metrics_driver_impl_unittest.cc
@@ -0,0 +1,189 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/memory/swap_metrics_driver_impl.h"
+
+#include <memory>
+
+#include "base/memory/ptr_util.h"
+#include "base/test/scoped_task_environment.h"
+#include "base/threading/platform_thread.h"
+#include "base/time/time.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+namespace {
+
+// A SwapMetricsDriver that mocks what a platform-dependent driver does, but
+// with control over when it fails so we can test error conditions.
+class MockSwapMetricsDriver : public SwapMetricsDriverImpl {
+ public:
+ MockSwapMetricsDriver(std::unique_ptr<Delegate> delegate,
+ const base::TimeDelta update_interval,
+ const bool fail_on_update)
+ : SwapMetricsDriverImpl(std::move(delegate), update_interval),
+ fail_on_update_(fail_on_update) {}
+
+ ~MockSwapMetricsDriver() override = default;
+
+ protected:
+ SwapMetricsDriver::SwapMetricsUpdateResult UpdateMetricsInternal(
+ base::TimeDelta interval) override {
+ if (fail_on_update_)
+ return SwapMetricsDriver::SwapMetricsUpdateResult::
+ kSwapMetricsUpdateFailed;
+
+ if (interval.is_zero())
+ return SwapMetricsDriver::SwapMetricsUpdateResult::
+ kSwapMetricsUpdateSuccess;
+
+ delegate_->OnSwapInCount(0, interval);
+ delegate_->OnSwapOutCount(0, interval);
+ delegate_->OnDecompressedPageCount(0, interval);
+ delegate_->OnCompressedPageCount(0, interval);
+
+ return SwapMetricsDriver::SwapMetricsUpdateResult::
+ kSwapMetricsUpdateSuccess;
+ }
+
+ private:
+ bool fail_on_update_;
+};
+
+// A SwapMetricsDriver::Delegate that counts the number of updates for each
+// metric.
+class SwapMetricsDelegateCounter : public SwapMetricsDriver::Delegate {
+ public:
+ SwapMetricsDelegateCounter()
+ : num_swap_in_updates_(0),
+ num_swap_out_updates_(0),
+ num_decompressed_updates_(0),
+ num_compressed_updates_(0),
+ num_updates_failed_(0) {}
+
+ ~SwapMetricsDelegateCounter() override = default;
+
+ void OnSwapInCount(uint64_t count, base::TimeDelta interval) override {
+ ++num_swap_in_updates_;
+ }
+
+ void OnSwapOutCount(uint64_t count, base::TimeDelta interval) override {
+ ++num_swap_out_updates_;
+ }
+
+ void OnDecompressedPageCount(uint64_t count,
+ base::TimeDelta interval) override {
+ ++num_decompressed_updates_;
+ }
+
+ void OnCompressedPageCount(uint64_t count,
+ base::TimeDelta interval) override {
+ ++num_compressed_updates_;
+ }
+
+ void OnUpdateMetricsFailed() override { ++num_updates_failed_; }
+
+ size_t num_swap_in_updates() const { return num_swap_in_updates_; }
+ size_t num_swap_out_updates() const { return num_swap_out_updates_; }
+ size_t num_decompressed_updates() const { return num_decompressed_updates_; }
+ size_t num_compressed_updates() const { return num_compressed_updates_; }
+ size_t num_updates_failed() const { return num_updates_failed_; }
+
+ private:
+ size_t num_swap_in_updates_;
+ size_t num_swap_out_updates_;
+ size_t num_decompressed_updates_;
+ size_t num_compressed_updates_;
+ size_t num_updates_failed_;
+
+ DISALLOW_COPY_AND_ASSIGN(SwapMetricsDelegateCounter);
+};
+
+// The time delta between updates must non-zero for the delegate callbacks to be
+// invoked.
+constexpr base::TimeDelta kUpdateDelay = base::TimeDelta::FromMilliseconds(50);
+
+} // namespace
+
+class TestSwapMetricsDriver : public testing::Test {
+ public:
+ static std::unique_ptr<SwapMetricsDriver> CreateDriver(
+ const base::TimeDelta update_interval,
+ bool fail_on_update) {
+ SwapMetricsDelegateCounter* delegate = new SwapMetricsDelegateCounter();
+ return base::WrapUnique<SwapMetricsDriver>(new MockSwapMetricsDriver(
+ base::WrapUnique<SwapMetricsDriver::Delegate>(delegate),
+ update_interval, fail_on_update));
+ }
+
+ protected:
+ base::test::ScopedTaskEnvironment scoped_task_environment_;
+};
+
+TEST_F(TestSwapMetricsDriver, ExpectedMetricCounts) {
+ std::unique_ptr<SwapMetricsDriver> driver =
+ CreateDriver(base::TimeDelta(), false);
+
+ auto result = driver->InitializeMetrics();
+ EXPECT_EQ(
+ SwapMetricsDriver::SwapMetricsUpdateResult::kSwapMetricsUpdateSuccess,
+ result);
+
+ base::PlatformThread::Sleep(kUpdateDelay);
+ result = driver->UpdateMetrics();
+ EXPECT_EQ(
+ SwapMetricsDriver::SwapMetricsUpdateResult::kSwapMetricsUpdateSuccess,
+ result);
+
+ base::PlatformThread::Sleep(kUpdateDelay);
+ result = driver->UpdateMetrics();
+ EXPECT_EQ(
+ SwapMetricsDriver::SwapMetricsUpdateResult::kSwapMetricsUpdateSuccess,
+ result);
+
+ auto* delegate = static_cast<SwapMetricsDelegateCounter*>(
+ static_cast<SwapMetricsDriverImpl*>(driver.get())->delegate_.get());
+
+ EXPECT_EQ(2UL, delegate->num_swap_in_updates());
+ EXPECT_EQ(2UL, delegate->num_swap_out_updates());
+ EXPECT_EQ(2UL, delegate->num_decompressed_updates());
+ EXPECT_EQ(2UL, delegate->num_compressed_updates());
+}
+
+TEST_F(TestSwapMetricsDriver, TimerStartSuccess) {
+ std::unique_ptr<SwapMetricsDriver> driver =
+ CreateDriver(base::TimeDelta::FromSeconds(60), false);
+ auto result = driver->Start();
+ EXPECT_EQ(
+ SwapMetricsDriver::SwapMetricsUpdateResult::kSwapMetricsUpdateSuccess,
+ result);
+}
+
+TEST_F(TestSwapMetricsDriver, TimerStartFail) {
+ std::unique_ptr<SwapMetricsDriver> driver =
+ CreateDriver(base::TimeDelta::FromSeconds(60), true);
+ auto result = driver->Start();
+ EXPECT_EQ(
+ SwapMetricsDriver::SwapMetricsUpdateResult::kSwapMetricsUpdateFailed,
+ result);
+}
+
+TEST_F(TestSwapMetricsDriver, UpdateMetricsFail) {
+ std::unique_ptr<SwapMetricsDriver> driver =
+ CreateDriver(base::TimeDelta::FromSeconds(60), true);
+ auto result = driver->InitializeMetrics();
+ EXPECT_EQ(
+ SwapMetricsDriver::SwapMetricsUpdateResult::kSwapMetricsUpdateFailed,
+ result);
+ result = driver->InitializeMetrics();
+ EXPECT_EQ(
+ SwapMetricsDriver::SwapMetricsUpdateResult::kSwapMetricsUpdateFailed,
+ result);
+ auto* delegate = static_cast<SwapMetricsDelegateCounter*>(
+ static_cast<SwapMetricsDriverImpl*>(driver.get())->delegate_.get());
+ EXPECT_EQ(2UL, delegate->num_updates_failed());
+}
+
+} // namespace content
diff --git a/chromium/content/browser/memory/swap_metrics_driver_impl_win.cc b/chromium/content/browser/memory/swap_metrics_driver_impl_win.cc
new file mode 100644
index 00000000000..3e3086da279
--- /dev/null
+++ b/chromium/content/browser/memory/swap_metrics_driver_impl_win.cc
@@ -0,0 +1,22 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/public/browser/swap_metrics_driver.h"
+
+#include <memory>
+
+#include "base/time/time.h"
+
+namespace content {
+
+// static
+std::unique_ptr<SwapMetricsDriver> SwapMetricsDriver::Create(
+ std::unique_ptr<Delegate> delegate,
+ const base::TimeDelta update_interval) {
+ // SwapMetricsDriver isn't available on Windows for now.
+ // TODO(bashi): Figure out a way to measure swap rates on Windows.
+ return std::unique_ptr<SwapMetricsDriver>();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/memory/swap_metrics_observer.cc b/chromium/content/browser/memory/swap_metrics_observer.cc
deleted file mode 100644
index d1d59b85c7b..00000000000
--- a/chromium/content/browser/memory/swap_metrics_observer.cc
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/memory/swap_metrics_observer.h"
-
-#include "base/bind.h"
-#include "base/threading/thread_task_runner_handle.h"
-
-namespace content {
-
-namespace {
-
-// Time between updating swap rates.
-const int kSwapMetricsIntervalSeconds = 60;
-
-} // namespace
-
-SwapMetricsObserver::SwapMetricsObserver()
- : update_interval_(
- base::TimeDelta::FromSeconds(kSwapMetricsIntervalSeconds)) {}
-
-SwapMetricsObserver::~SwapMetricsObserver() {}
-
-void SwapMetricsObserver::Start() {
- timer_.Start(FROM_HERE, update_interval_, this,
- &SwapMetricsObserver::UpdateMetrics);
-}
-
-void SwapMetricsObserver::Stop() {
- last_ticks_ = base::TimeTicks();
- timer_.Stop();
-}
-
-void SwapMetricsObserver::UpdateMetrics() {
- base::TimeTicks now = base::TimeTicks::Now();
- base::TimeDelta interval =
- last_ticks_.is_null() ? base::TimeDelta() : now - last_ticks_;
- UpdateMetricsInternal(interval);
- last_ticks_ = now;
-}
-
-} // namespace content
diff --git a/chromium/content/browser/memory/swap_metrics_observer.h b/chromium/content/browser/memory/swap_metrics_observer.h
deleted file mode 100644
index 1c8e90f424a..00000000000
--- a/chromium/content/browser/memory/swap_metrics_observer.h
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_MEMORY_SWAP_METRICS_OBSERVER_H_
-#define CONTENT_BROWSER_MEMORY_SWAP_METRICS_OBSERVER_H_
-
-#include "base/time/time.h"
-#include "base/timer/timer.h"
-
-namespace content {
-
-// This class observes system's swapping behavior to collect metrics.
-// Metrics can be platform-specific.
-class SwapMetricsObserver {
- public:
- // This returns nullptr when swap metrics are not available on the system.
- static SwapMetricsObserver* GetInstance();
-
- // Starts observing swap metrics.
- void Start();
-
- // Stop observing swap metrics.
- void Stop();
-
- protected:
- SwapMetricsObserver();
- virtual ~SwapMetricsObserver();
-
- // Periodically called to update swap metrics.
- void UpdateMetrics();
-
- // Platform-dependent parts of UpdateMetrics(). |interval| is the elapsed time
- // since the last UpdateMetrics() call. |interval| will be zero when this
- // function is called for the first time.
- virtual void UpdateMetricsInternal(base::TimeDelta interval) = 0;
-
- private:
- // The interval between metrics updates.
- base::TimeDelta update_interval_;
-
- // A periodic timer to update swap metrics.
- base::RepeatingTimer timer_;
-
- // Holds the last TimeTicks when swap metrics are updated.
- base::TimeTicks last_ticks_;
-
- DISALLOW_COPY_AND_ASSIGN(SwapMetricsObserver);
-};
-
-} // namespace
-
-#endif // CONTENT_BROWSER_MEMORY_SWAP_METRICS_OBSERVER_H_
diff --git a/chromium/content/browser/memory/swap_metrics_observer_linux.cc b/chromium/content/browser/memory/swap_metrics_observer_linux.cc
deleted file mode 100644
index 08212bf8ad4..00000000000
--- a/chromium/content/browser/memory/swap_metrics_observer_linux.cc
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/memory/swap_metrics_observer_linux.h"
-
-#include "base/metrics/histogram_macros.h"
-#include "base/process/process_metrics.h"
-
-namespace content {
-
-namespace {
-
-bool HasSwap() {
- base::SystemMemoryInfoKB memory_info;
- if (!base::GetSystemMemoryInfo(&memory_info))
- return false;
- return memory_info.swap_total > 0;
-}
-
-} // namespace
-
-// static
-SwapMetricsObserver* SwapMetricsObserver::GetInstance() {
- static SwapMetricsObserverLinux* instance =
- HasSwap() ? new SwapMetricsObserverLinux() : nullptr;
- return instance;
-}
-
-SwapMetricsObserverLinux::SwapMetricsObserverLinux() {}
-
-SwapMetricsObserverLinux::~SwapMetricsObserverLinux() {}
-
-void SwapMetricsObserverLinux::UpdateMetricsInternal(base::TimeDelta interval) {
- base::SystemMemoryInfoKB memory_info;
- if (!base::GetSystemMemoryInfo(&memory_info)) {
- Stop();
- return;
- }
-
- double in_counts = memory_info.pswpin - last_pswpin_;
- double out_counts = memory_info.pswpout - last_pswpout_;
- last_pswpin_ = memory_info.pswpin;
- last_pswpout_ = memory_info.pswpout;
-
- if (interval.is_zero())
- return;
-
- UMA_HISTOGRAM_COUNTS_10000("Memory.Experimental.SwapInPerSecond",
- in_counts / interval.InSecondsF());
- UMA_HISTOGRAM_COUNTS_10000("Memory.Experimental.SwapOutPerSecond",
- out_counts / interval.InSecondsF());
-}
-
-} // namespace content
diff --git a/chromium/content/browser/memory/swap_metrics_observer_linux.h b/chromium/content/browser/memory/swap_metrics_observer_linux.h
deleted file mode 100644
index 49c489c376f..00000000000
--- a/chromium/content/browser/memory/swap_metrics_observer_linux.h
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_MEMORY_SWAP_METRICS_OBSERVER_LINUX_H_
-#define CONTENT_BROWSER_MEMORY_SWAP_METRICS_OBSERVER_LINUX_H_
-
-#include "content/browser/memory/swap_metrics_observer.h"
-
-namespace content {
-
-class SwapMetricsObserverLinux : public SwapMetricsObserver {
- public:
- SwapMetricsObserverLinux();
- ~SwapMetricsObserverLinux() override;
-
- protected:
- void UpdateMetricsInternal(base::TimeDelta interval) override;
-
- private:
- uint64_t last_pswpin_ = 0;
- uint64_t last_pswpout_ = 0;
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_MEMORY_SWAP_METRICS_OBSERVER_LINUX_H_
diff --git a/chromium/content/browser/memory/swap_metrics_observer_mac.cc b/chromium/content/browser/memory/swap_metrics_observer_mac.cc
deleted file mode 100644
index 65f5bdab95f..00000000000
--- a/chromium/content/browser/memory/swap_metrics_observer_mac.cc
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/memory/swap_metrics_observer_mac.h"
-
-#include <mach/mach.h>
-#include <mach/mach_vm.h>
-
-#include "base/mac/mach_logging.h"
-#include "base/metrics/histogram_macros.h"
-
-namespace content {
-
-// static
-SwapMetricsObserver* SwapMetricsObserver::GetInstance() {
- static SwapMetricsObserverMac* instance = new SwapMetricsObserverMac();
- return instance;
-}
-
-SwapMetricsObserverMac::SwapMetricsObserverMac() : host_(mach_host_self()) {}
-
-SwapMetricsObserverMac::~SwapMetricsObserverMac() {}
-
-void SwapMetricsObserverMac::UpdateMetricsInternal(base::TimeDelta interval) {
- vm_statistics64_data_t statistics;
- mach_msg_type_number_t count = HOST_VM_INFO64_COUNT;
- kern_return_t result =
- host_statistics64(host_.get(), HOST_VM_INFO64,
- reinterpret_cast<host_info64_t>(&statistics), &count);
- if (result != KERN_SUCCESS) {
- MACH_DLOG(WARNING, result) << "host_statistics64";
- Stop();
- return;
- }
- DCHECK_EQ(HOST_VM_INFO64_COUNT, count);
-
- double swapins = statistics.swapins - last_swapins_;
- double swapouts = statistics.swapouts - last_swapouts_;
- double decompressions = statistics.decompressions - last_decompressions_;
- double compressions = statistics.compressions - last_compressions_;
- last_swapins_ = statistics.swapins;
- last_swapouts_ = statistics.swapouts;
- last_decompressions_ = statistics.decompressions;
- last_compressions_ = statistics.compressions;
-
- if (interval.is_zero())
- return;
-
- UMA_HISTOGRAM_COUNTS_10000("Memory.Experimental.SwapInPerSecond",
- swapins / interval.InSecondsF());
- UMA_HISTOGRAM_COUNTS_10000("Memory.Experimental.SwapOutPerSecond",
- swapouts / interval.InSecondsF());
- UMA_HISTOGRAM_COUNTS_10000("Memory.Experimental.DecompressedPagesPerSecond",
- decompressions / interval.InSecondsF());
- UMA_HISTOGRAM_COUNTS_10000("Memory.Experimental.CompressedPagesPerSecond",
- compressions / interval.InSecondsF());
-}
-
-} // namespace content
diff --git a/chromium/content/browser/memory/swap_metrics_observer_mac.h b/chromium/content/browser/memory/swap_metrics_observer_mac.h
deleted file mode 100644
index fd34e0a4dda..00000000000
--- a/chromium/content/browser/memory/swap_metrics_observer_mac.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_MEMORY_SWAP_METRICS_OBSERVER_MAC_H_
-#define CONTENT_BROWSER_MEMORY_SWAP_METRICS_OBSERVER_MAC_H_
-
-#include "content/browser/memory/swap_metrics_observer.h"
-
-#include "base/mac/scoped_mach_port.h"
-
-namespace content {
-
-class SwapMetricsObserverMac : public SwapMetricsObserver {
- public:
- SwapMetricsObserverMac();
- ~SwapMetricsObserverMac() override;
-
- protected:
- void UpdateMetricsInternal(base::TimeDelta interval) override;
-
- private:
- base::mac::ScopedMachSendRight host_;
-
- uint64_t last_swapins_ = 0;
- uint64_t last_swapouts_ = 0;
- uint64_t last_decompressions_ = 0;
- uint64_t last_compressions_ = 0;
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_MEMORY_SWAP_METRICS_OBSERVER_MAC_H_
diff --git a/chromium/content/browser/memory/swap_metrics_observer_win.cc b/chromium/content/browser/memory/swap_metrics_observer_win.cc
deleted file mode 100644
index f80a5b5fa52..00000000000
--- a/chromium/content/browser/memory/swap_metrics_observer_win.cc
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/memory/swap_metrics_observer.h"
-
-namespace content {
-
-// static
-SwapMetricsObserver* SwapMetricsObserver::GetInstance() {
- // SwapMetricsObserver isn't available on Windows for now.
- // TODO(bashi): Figure out a way to measure swap rates on Windows.
- return nullptr;
-}
-
-} // namespace content
diff --git a/chromium/content/browser/net/quota_policy_cookie_store.cc b/chromium/content/browser/net/quota_policy_cookie_store.cc
index 1fcb92626d0..b404b0548d3 100644
--- a/chromium/content/browser/net/quota_policy_cookie_store.cc
+++ b/chromium/content/browser/net/quota_policy_cookie_store.cc
@@ -93,6 +93,11 @@ void QuotaPolicyCookieStore::SetForceKeepSessionState() {
special_storage_policy_ = nullptr;
}
+void QuotaPolicyCookieStore::SetBeforeFlushCallback(
+ base::RepeatingClosure callback) {
+ persistent_store_->SetBeforeFlushCallback(std::move(callback));
+}
+
void QuotaPolicyCookieStore::Flush(base::OnceClosure callback) {
persistent_store_->Flush(std::move(callback));
}
@@ -119,12 +124,10 @@ CookieStoreConfig::CookieStoreConfig()
CookieStoreConfig::CookieStoreConfig(
const base::FilePath& path,
SessionCookieMode session_cookie_mode,
- storage::SpecialStoragePolicy* storage_policy,
- net::CookieMonsterDelegate* cookie_delegate)
+ storage::SpecialStoragePolicy* storage_policy)
: path(path),
session_cookie_mode(session_cookie_mode),
storage_policy(storage_policy),
- cookie_delegate(cookie_delegate),
crypto_delegate(nullptr),
channel_id_service(nullptr) {
CHECK(!path.empty() || session_cookie_mode == EPHEMERAL_SESSION_COOKIES);
@@ -143,8 +146,7 @@ std::unique_ptr<net::CookieStore> CreateCookieStore(
if (config.path.empty()) {
// Empty path means in-memory store.
- cookie_monster.reset(
- new net::CookieMonster(nullptr, config.cookie_delegate.get()));
+ cookie_monster.reset(new net::CookieMonster(nullptr));
} else {
scoped_refptr<base::SequencedTaskRunner> client_task_runner =
config.client_task_runner;
@@ -177,7 +179,6 @@ std::unique_ptr<net::CookieStore> CreateCookieStore(
config.storage_policy.get());
cookie_monster.reset(new net::CookieMonster(persistent_store,
- config.cookie_delegate.get(),
config.channel_id_service));
if ((config.session_cookie_mode ==
CookieStoreConfig::PERSISTANT_SESSION_COOKIES) ||
diff --git a/chromium/content/browser/net/quota_policy_cookie_store.h b/chromium/content/browser/net/quota_policy_cookie_store.h
index 8eeb3f13f00..f55b34a3a1f 100644
--- a/chromium/content/browser/net/quota_policy_cookie_store.h
+++ b/chromium/content/browser/net/quota_policy_cookie_store.h
@@ -49,6 +49,7 @@ class CONTENT_EXPORT QuotaPolicyCookieStore
void UpdateCookieAccessTime(const net::CanonicalCookie& cc) override;
void DeleteCookie(const net::CanonicalCookie& cc) override;
void SetForceKeepSessionState() override;
+ void SetBeforeFlushCallback(base::RepeatingClosure callback) override;
void Flush(base::OnceClosure callback) override;
private:
diff --git a/chromium/content/browser/net_info_browsertest.cc b/chromium/content/browser/net_info_browsertest.cc
index 0e0f334d076..16871e5ac70 100644
--- a/chromium/content/browser/net_info_browsertest.cc
+++ b/chromium/content/browser/net_info_browsertest.cc
@@ -19,6 +19,7 @@
#include "content/shell/browser/shell.h"
#include "net/base/network_change_notifier.h"
#include "net/base/network_change_notifier_factory.h"
+#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"
@@ -35,6 +36,47 @@ int GetTotalSampleCount(base::HistogramTester* tester,
return count;
}
+void VerifyRtt(base::TimeDelta expected_rtt, int32_t got_rtt_milliseconds) {
+ EXPECT_EQ(0, got_rtt_milliseconds % 50)
+ << " got_rtt_milliseconds=" << got_rtt_milliseconds;
+
+ if (expected_rtt > base::TimeDelta::FromMilliseconds(3000))
+ expected_rtt = base::TimeDelta::FromMilliseconds(3000);
+
+ // The difference between the actual and the estimate value should be within
+ // 10%. Add 50 (bucket size used in Blink) to account for the cases when the
+ // sample may spill over to the next bucket due to the added noise of 10%.
+ // 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));
+}
+
+void VerifyDownlinkKbps(double expected_kbps, double got_kbps) {
+ // First verify that |got_kbps| is a multiple of 50.
+ int quotient = static_cast<int>(got_kbps / 50);
+ // |mod| is the remainder left after dividing |got_kbps| by 50 while
+ // restricting the quotient to integer. For example, if |got_kbps| is
+ // 1050, then mod will be 0. If |got_kbps| is 1030, mod will be 30.
+ double mod = got_kbps - 50 * quotient;
+ EXPECT_LE(0.0, mod);
+ EXPECT_GT(50.0, mod);
+ // It is possible that |mod| is not exactly 0 because of floating point
+ // computations. e.g., |got_kbps| may be 99.999999, in which case |mod|
+ // will be 49.999999.
+ EXPECT_TRUE(mod < (1e-5) || (50 - mod) < 1e-5) << " got_kbps=" << got_kbps;
+
+ if (expected_kbps > 10000)
+ expected_kbps = 10000;
+
+ // The difference between the actual and the estimate value should be within
+ // 10%. Add 50 (bucket size used in Blink) to account for the cases when the
+ // 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));
+}
+
} // namespace
namespace content {
@@ -66,6 +108,7 @@ class NetInfoBrowserTest : public content::ContentBrowserTest {
}
void SetUpOnMainThread() override {
+ host_resolver()->AddRule("*", "127.0.0.1");
base::RunLoop().RunUntilIdle();
}
@@ -171,7 +214,7 @@ IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest, TwoRenderViewsInOneProcess) {
}
// Verify that when the network quality notifications are not sent, the
-// Javascript API returns a valid estimate that is multiple of 25 msec and 25
+// Javascript API returns a valid estimate that is multiple of 50 msec and 50
// kbps.
IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest,
NetworkQualityEstimatorNotInitialized) {
@@ -185,23 +228,10 @@ IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest,
EXPECT_TRUE(
NavigateToURL(shell(), embedded_test_server()->GetURL("/net_info.html")));
+ // When NQE is not initialized, the javascript calls should return default
+ // values.
EXPECT_EQ(0, RunScriptExtractInt("getRtt()"));
- EXPECT_EQ(0, RunScriptExtractInt("getRtt()") % 25);
-
- double downlink_mbps = RunScriptExtractDouble("getDownlink()");
- EXPECT_LE(0, downlink_mbps);
-
- // Verify that |downlink_mbps| is a multiple of 25 kbps. For example, a value
- // of 1.250 mbps satisfies that constraint, but a value of 1.254 mbps does
- // not.
- double fraction_part, int_part;
- fraction_part = std::modf(downlink_mbps, &int_part);
- // If |fraction_part| is a multiple of 0.025, it implies |downlink_mbps| is
- // also a multiple of 0.025, and hence |downlink_mbps| is a multiple of 25
- // kbps.
- EXPECT_EQ(0, static_cast<int>(fraction_part * 1000) % 25);
-
- EXPECT_EQ("4g", RunScriptExtractString("getEffectiveType()"));
+ VerifyDownlinkKbps(10000, RunScriptExtractDouble("getDownlink()") * 1000);
}
// Make sure the changes in the effective connection typeare notified to the
@@ -269,12 +299,9 @@ IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest, NetworkQualityChangeNotified) {
EXPECT_FALSE(
histogram_tester.GetAllSamples("NQE.RenderThreadNotified").empty());
- EXPECT_EQ(network_quality_1.http_rtt().InMilliseconds(),
- RunScriptExtractInt("getRtt()"));
- EXPECT_EQ(
- static_cast<double>(network_quality_1.downstream_throughput_kbps()) /
- 1000,
- RunScriptExtractDouble("getDownlink()"));
+ VerifyRtt(network_quality_1.http_rtt(), RunScriptExtractInt("getRtt()"));
+ VerifyDownlinkKbps(network_quality_1.downstream_throughput_kbps(),
+ RunScriptExtractDouble("getDownlink()") * 1000);
// Verify that the network quality change is accessible via Javascript API.
net::nqe::internal::NetworkQuality network_quality_2(
@@ -282,16 +309,13 @@ IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest, NetworkQualityChangeNotified) {
estimator.NotifyObserversOfRTTOrThroughputEstimatesComputed(
network_quality_2);
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(network_quality_2.http_rtt().InMilliseconds(),
- RunScriptExtractInt("getRtt()"));
- EXPECT_EQ(
- static_cast<double>(network_quality_2.downstream_throughput_kbps()) /
- 1000,
- RunScriptExtractDouble("getDownlink()"));
+ VerifyRtt(network_quality_2.http_rtt(), RunScriptExtractInt("getRtt()"));
+ VerifyDownlinkKbps(network_quality_2.downstream_throughput_kbps(),
+ RunScriptExtractDouble("getDownlink()") * 1000);
}
// Make sure the changes in the network quality are rounded to the nearest
-// 25 milliseconds or 25 kbps.
+// 50 milliseconds or 50 kbps.
IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest, NetworkQualityChangeRounded) {
base::HistogramTester histogram_tester;
net::TestNetworkQualityEstimator estimator(
@@ -302,34 +326,122 @@ IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest, NetworkQualityChangeRounded) {
// Verify that the network quality is rounded properly.
net::nqe::internal::NetworkQuality network_quality_1(
- base::TimeDelta::FromMilliseconds(123),
- base::TimeDelta::FromMilliseconds(212), 303);
+ base::TimeDelta::FromMilliseconds(103),
+ base::TimeDelta::FromMilliseconds(212), 8303);
estimator.NotifyObserversOfRTTOrThroughputEstimatesComputed(
network_quality_1);
EXPECT_TRUE(embedded_test_server()->Start());
EXPECT_TRUE(
NavigateToURL(shell(), embedded_test_server()->GetURL("/net_info.html")));
- EXPECT_EQ(125, RunScriptExtractInt("getRtt()"));
- EXPECT_EQ(0.300, RunScriptExtractDouble("getDownlink()"));
+ VerifyRtt(network_quality_1.http_rtt(), RunScriptExtractInt("getRtt()"));
+ VerifyDownlinkKbps(network_quality_1.downstream_throughput_kbps(),
+ RunScriptExtractDouble("getDownlink()") * 1000);
net::nqe::internal::NetworkQuality network_quality_2(
- base::TimeDelta::FromMilliseconds(1123),
- base::TimeDelta::FromMilliseconds(212), 1317);
+ base::TimeDelta::FromMilliseconds(1103),
+ base::TimeDelta::FromMilliseconds(212), 1307);
estimator.NotifyObserversOfRTTOrThroughputEstimatesComputed(
network_quality_2);
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(1125, RunScriptExtractInt("getRtt()"));
- EXPECT_EQ(1.325, RunScriptExtractDouble("getDownlink()"));
+ VerifyRtt(network_quality_2.http_rtt(), RunScriptExtractInt("getRtt()"));
+ VerifyDownlinkKbps(network_quality_2.downstream_throughput_kbps(),
+ RunScriptExtractDouble("getDownlink()") * 1000);
net::nqe::internal::NetworkQuality network_quality_3(
- base::TimeDelta::FromMilliseconds(12),
- base::TimeDelta::FromMilliseconds(12), 12);
+ base::TimeDelta::FromMilliseconds(2112),
+ base::TimeDelta::FromMilliseconds(2112), 2112);
estimator.NotifyObserversOfRTTOrThroughputEstimatesComputed(
network_quality_3);
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(0, RunScriptExtractInt("getRtt()"));
- EXPECT_EQ(0, RunScriptExtractDouble("getDownlink()"));
+ VerifyRtt(network_quality_3.http_rtt(), RunScriptExtractInt("getRtt()"));
+ VerifyDownlinkKbps(network_quality_3.downstream_throughput_kbps(),
+ RunScriptExtractDouble("getDownlink()") * 1000);
+}
+
+// Make sure the network quality are rounded down when it exceeds the upper
+// limit.
+IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest, NetworkQualityChangeUpperLimit) {
+ base::HistogramTester histogram_tester;
+ net::TestNetworkQualityEstimator estimator(
+ std::unique_ptr<net::ExternalEstimateProvider>(),
+ std::map<std::string, std::string>(), false, false, true, true,
+ base::MakeUnique<net::BoundTestNetLog>());
+ NetworkQualityObserverImpl impl(&estimator);
+
+ net::nqe::internal::NetworkQuality network_quality(
+ base::TimeDelta::FromMilliseconds(12003),
+ base::TimeDelta::FromMilliseconds(212), 30300);
+ estimator.NotifyObserversOfRTTOrThroughputEstimatesComputed(network_quality);
+
+ 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(),
+ 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::unique_ptr<net::ExternalEstimateProvider>(),
+ std::map<std::string, std::string>(), false, false, true, true,
+ base::MakeUnique<net::BoundTestNetLog>());
+ NetworkQualityObserverImpl impl(&estimator);
+
+ net::nqe::internal::NetworkQuality network_quality(
+ base::TimeDelta::FromMilliseconds(2000),
+ base::TimeDelta::FromMilliseconds(200), 3000);
+ estimator.NotifyObserversOfRTTOrThroughputEstimatesComputed(network_quality);
+
+ 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(),
+ RunScriptExtractDouble("getDownlink()") * 1000);
+
+ const int32_t rtt_noise_milliseconds = RunScriptExtractInt("getRtt()") - 2000;
+ const int32_t downlink_noise_kbps =
+ RunScriptExtractDouble("getDownlink()") * 1000 - 3000;
+
+ // 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(),
+ RunScriptExtractDouble("getDownlink()") * 1000);
+ EXPECT_EQ(rtt_noise_milliseconds, RunScriptExtractInt("getRtt()") - 2000);
+ EXPECT_EQ(downlink_noise_kbps,
+ RunScriptExtractDouble("getDownlink()") * 1000 - 3000);
+
+ // Verify that changing the hostname changes the noise. It is possible that
+ // the hash of a different host also maps to the same bucket among 20 buckets.
+ // Try 10 different hosts. This reduces the probability of failure of this
+ // test to (1/20)^10 = 9,7 * 10^-14.
+ for (size_t i = 0; i < 10; ++i) {
+ // The noise added is a function of the hostname. Varying the hostname
+ // should vary the noise.
+ 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(),
+ RunScriptExtractDouble("getDownlink()") * 1000);
+
+ int32_t new_rtt_noise_milliseconds = RunScriptExtractInt("getRtt()") - 2000;
+ int32_t new_downlink_noise_kbps =
+ RunScriptExtractDouble("getDownlink()") * 1000 - 3000;
+
+ if (rtt_noise_milliseconds != new_rtt_noise_milliseconds &&
+ downlink_noise_kbps != new_downlink_noise_kbps) {
+ return;
+ }
+ }
+ NOTREACHED() << "Noise not added to the network quality estimates";
}
// Make sure the minor changes (<10%) in the network quality are not notified.
@@ -350,8 +462,9 @@ IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest, NetworkQualityChangeNotNotified) {
EXPECT_TRUE(embedded_test_server()->Start());
EXPECT_TRUE(
NavigateToURL(shell(), embedded_test_server()->GetURL("/net_info.html")));
- EXPECT_EQ(1125, RunScriptExtractInt("getRtt()"));
- EXPECT_EQ(1.300, RunScriptExtractDouble("getDownlink()"));
+ VerifyRtt(network_quality_1.http_rtt(), RunScriptExtractInt("getRtt()"));
+ VerifyDownlinkKbps(network_quality_1.downstream_throughput_kbps(),
+ RunScriptExtractDouble("getDownlink()") * 1000);
// All the 3 metrics change by less than 10%. So, the observers are not
// notified.
@@ -361,8 +474,9 @@ IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest, NetworkQualityChangeNotNotified) {
estimator.NotifyObserversOfRTTOrThroughputEstimatesComputed(
network_quality_2);
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(1125, RunScriptExtractInt("getRtt()"));
- EXPECT_EQ(1.300, RunScriptExtractDouble("getDownlink()"));
+ VerifyRtt(base::TimeDelta::FromMilliseconds(1100),
+ RunScriptExtractInt("getRtt()"));
+ VerifyDownlinkKbps(1300, RunScriptExtractDouble("getDownlink()") * 1000);
// HTTP RTT has changed by more than 10% from the last notified value of
// |network_quality_1|. The observers should be notified.
@@ -372,8 +486,9 @@ IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest, NetworkQualityChangeNotNotified) {
estimator.NotifyObserversOfRTTOrThroughputEstimatesComputed(
network_quality_3);
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(2225, RunScriptExtractInt("getRtt()"));
- EXPECT_EQ(1.400, RunScriptExtractDouble("getDownlink()"));
+ VerifyRtt(base::TimeDelta::FromMilliseconds(2200),
+ RunScriptExtractInt("getRtt()"));
+ VerifyDownlinkKbps(1400, RunScriptExtractDouble("getDownlink()") * 1000);
}
} // namespace content
diff --git a/chromium/content/browser/notifications/notification_database.cc b/chromium/content/browser/notifications/notification_database.cc
index 9b00a53ecfd..614910acc56 100644
--- a/chromium/content/browser/notifications/notification_database.cc
+++ b/chromium/content/browser/notifications/notification_database.cc
@@ -122,11 +122,11 @@ NotificationDatabase::Status NotificationDatabase::Open(
filter_policy_.reset(leveldb::NewBloomFilterPolicy(10));
- leveldb::Options options;
+ leveldb_env::Options options;
options.create_if_missing = create_if_missing;
options.paranoid_checks = true;
- options.reuse_logs = leveldb_env::kDefaultLogReuseOptionValue;
options.filter_policy = filter_policy_.get();
+ options.block_cache = leveldb_env::SharedWebBlockCache();
if (IsInMemoryDatabase()) {
env_.reset(leveldb::NewMemEnv(leveldb::Env::Default()));
options.env = env_.get();
@@ -256,7 +256,7 @@ NotificationDatabase::DeleteAllNotificationDataForServiceWorkerRegistration(
NotificationDatabase::Status NotificationDatabase::Destroy() {
DCHECK(sequence_checker_.CalledOnValidSequence());
- leveldb::Options options;
+ leveldb_env::Options options;
if (IsInMemoryDatabase()) {
if (!env_)
return STATUS_OK; // The database has not been initialized.
diff --git a/chromium/content/browser/notifications/notification_event_dispatcher_impl.cc b/chromium/content/browser/notifications/notification_event_dispatcher_impl.cc
index a02d7194440..8efe1614f9e 100644
--- a/chromium/content/browser/notifications/notification_event_dispatcher_impl.cc
+++ b/chromium/content/browser/notifications/notification_event_dispatcher_impl.cc
@@ -235,7 +235,7 @@ void DoDispatchNotificationClickEvent(
&ServiceWorkerNotificationEventFinished, dispatch_complete_callback);
service_worker_registration->active_version()->RunAfterStartWorker(
ServiceWorkerMetrics::EventType::NOTIFICATION_CLICK,
- base::Bind(
+ base::BindOnce(
&DispatchNotificationClickEventOnWorker,
make_scoped_refptr(service_worker_registration->active_version()),
notification_database_data, action_index, reply, status_callback),
@@ -307,7 +307,7 @@ void DoDispatchNotificationCloseEvent(
if (by_user) {
service_worker_registration->active_version()->RunAfterStartWorker(
ServiceWorkerMetrics::EventType::NOTIFICATION_CLOSE,
- base::Bind(
+ base::BindOnce(
&DispatchNotificationCloseEventOnWorker,
make_scoped_refptr(service_worker_registration->active_version()),
notification_database_data, dispatch_event_callback),
diff --git a/chromium/content/browser/notifications/platform_notification_context_impl.h b/chromium/content/browser/notifications/platform_notification_context_impl.h
index eb7ed381e7c..af5d33522bf 100644
--- a/chromium/content/browser/notifications/platform_notification_context_impl.h
+++ b/chromium/content/browser/notifications/platform_notification_context_impl.h
@@ -42,8 +42,8 @@ class ServiceWorkerContextWrapper;
// defined in this interface must only be called on the IO thread unless
// otherwise specified.
class CONTENT_EXPORT PlatformNotificationContextImpl
- : NON_EXPORTED_BASE(public PlatformNotificationContext),
- NON_EXPORTED_BASE(public ServiceWorkerContextCoreObserver) {
+ : public PlatformNotificationContext,
+ public ServiceWorkerContextCoreObserver {
public:
// Constructs a new platform notification context. If |path| is non-empty, the
// database will be initialized in the "Platform Notifications" subdirectory
diff --git a/chromium/content/browser/payments/payment_app.proto b/chromium/content/browser/payments/payment_app.proto
index 4eaba562219..5d5fe94c2af 100644
--- a/chromium/content/browser/payments/payment_app.proto
+++ b/chromium/content/browser/payments/payment_app.proto
@@ -18,8 +18,8 @@ message StoredPaymentInstrumentImageObject {
}
message StoredPaymentInstrumentProto {
- optional string instrument_key = 1;
- optional string origin = 2;
+ optional int64 registration_id = 1;
+ optional string instrument_key = 2;
optional string name = 3;
repeated string enabled_methods = 4;
optional string stringified_capabilities = 5;
@@ -27,9 +27,16 @@ message StoredPaymentInstrumentProto {
optional string decoded_instrument_icon = 7;
}
+message StoredRelatedApplicationProto {
+ optional string platform = 1;
+ optional string id = 2;
+}
+
message StoredPaymentAppProto {
optional int64 registration_id = 1;
- optional string origin = 2;
+ optional string scope = 2;
optional string name = 3;
optional string icon = 4;
+ optional bool prefer_related_applications = 5;
+ repeated StoredRelatedApplicationProto related_applications = 6;
}
diff --git a/chromium/content/browser/payments/payment_app_browsertest.cc b/chromium/content/browser/payments/payment_app_browsertest.cc
index b4a9a947f2b..bd1d7e68f09 100644
--- a/chromium/content/browser/payments/payment_app_browsertest.cc
+++ b/chromium/content/browser/payments/payment_app_browsertest.cc
@@ -6,6 +6,7 @@
#include "base/macros.h"
#include "base/run_loop.h"
#include "content/browser/storage_partition_impl.h"
+#include "content/common/service_worker/service_worker_types.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/payment_app_provider.h"
#include "content/public/browser/web_contents.h"
@@ -21,6 +22,8 @@
namespace content {
namespace {
+using ::payments::mojom::CanMakePaymentEventData;
+using ::payments::mojom::CanMakePaymentEventDataPtr;
using ::payments::mojom::PaymentRequestEventData;
using ::payments::mojom::PaymentRequestEventDataPtr;
using ::payments::mojom::PaymentHandlerResponsePtr;
@@ -37,6 +40,13 @@ void GetAllPaymentAppsCallback(const base::Closure& done_callback,
done_callback.Run();
}
+void PaymentEventResultCallback(const base::Closure& done_callback,
+ bool* out_payment_event_result,
+ bool payment_event_result) {
+ *out_payment_event_result = payment_event_result;
+ done_callback.Run();
+}
+
void InvokePaymentAppCallback(const base::Closure& done_callback,
PaymentHandlerResponsePtr* out_response,
PaymentHandlerResponsePtr response) {
@@ -101,10 +111,94 @@ class PaymentAppBrowserTest : public ContentBrowserTest {
return registrationIds;
}
+ bool AbortPayment(int64_t registration_id) {
+ base::RunLoop run_loop;
+ bool payment_aborted = false;
+ PaymentAppProvider::GetInstance()->AbortPayment(
+ shell()->web_contents()->GetBrowserContext(), registration_id,
+ base::BindOnce(&PaymentEventResultCallback, run_loop.QuitClosure(),
+ &payment_aborted));
+ run_loop.Run();
+
+ return payment_aborted;
+ }
+
+ bool CanMakePaymentWithTestData(int64_t registration_id,
+ const std::string& supported_method) {
+ CanMakePaymentEventDataPtr event_data =
+ CreateCanMakePaymentEventData(supported_method);
+
+ base::RunLoop run_loop;
+ bool can_make_payment = false;
+ PaymentAppProvider::GetInstance()->CanMakePayment(
+ shell()->web_contents()->GetBrowserContext(), registration_id,
+ std::move(event_data),
+ base::BindOnce(&PaymentEventResultCallback, run_loop.QuitClosure(),
+ &can_make_payment));
+ run_loop.Run();
+
+ return can_make_payment;
+ }
+
PaymentHandlerResponsePtr InvokePaymentAppWithTestData(
int64_t registration_id,
const std::string& supported_method,
const std::string& instrument_key) {
+ base::RunLoop run_loop;
+ PaymentHandlerResponsePtr response;
+ PaymentAppProvider::GetInstance()->InvokePaymentApp(
+ shell()->web_contents()->GetBrowserContext(), registration_id,
+ CreatePaymentRequestEventData(supported_method, instrument_key),
+ base::BindOnce(&InvokePaymentAppCallback, run_loop.QuitClosure(),
+ &response));
+ run_loop.Run();
+
+ return response;
+ }
+
+ void ClearStoragePartitionData() {
+ // Clear data from the storage partition. Parameters are set to clear data
+ // for service workers, for all origins, for an unbounded time range.
+ base::RunLoop run_loop;
+
+ static_cast<StoragePartitionImpl*>(
+ content::BrowserContext::GetDefaultStoragePartition(
+ shell()->web_contents()->GetBrowserContext()))
+ ->ClearData(StoragePartition::REMOVE_DATA_MASK_SERVICE_WORKERS,
+ StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL, GURL(),
+ StoragePartition::OriginMatcherFunction(), base::Time(),
+ base::Time::Max(), run_loop.QuitClosure());
+
+ run_loop.Run();
+ }
+
+ private:
+ CanMakePaymentEventDataPtr CreateCanMakePaymentEventData(
+ const std::string& supported_method) {
+ CanMakePaymentEventDataPtr event_data = CanMakePaymentEventData::New();
+
+ event_data->top_level_origin = GURL("https://example.com");
+
+ event_data->payment_request_origin = GURL("https://example.com");
+
+ event_data->method_data.push_back(PaymentMethodData::New());
+ event_data->method_data[0]->supported_methods = {supported_method};
+
+ PaymentDetailsModifierPtr modifier = PaymentDetailsModifier::New();
+ modifier->total = PaymentItem::New();
+ modifier->total->amount = PaymentCurrencyAmount::New();
+ modifier->total->amount->currency = "USD";
+ modifier->total->amount->value = "55";
+ modifier->method_data = PaymentMethodData::New();
+ modifier->method_data->supported_methods = {supported_method};
+ event_data->modifiers.push_back(std::move(modifier));
+
+ return event_data;
+ }
+
+ PaymentRequestEventDataPtr CreatePaymentRequestEventData(
+ const std::string& supported_method,
+ const std::string& instrument_key) {
PaymentRequestEventDataPtr event_data = PaymentRequestEventData::New();
event_data->top_level_origin = GURL("https://example.com");
@@ -131,40 +225,80 @@ class PaymentAppBrowserTest : public ContentBrowserTest {
event_data->instrument_key = instrument_key;
- base::RunLoop run_loop;
- PaymentHandlerResponsePtr response;
- PaymentAppProvider::GetInstance()->InvokePaymentApp(
- shell()->web_contents()->GetBrowserContext(), registration_id,
- std::move(event_data),
- base::Bind(&InvokePaymentAppCallback, run_loop.QuitClosure(),
- &response));
- run_loop.Run();
-
- return response;
- }
-
- void ClearStoragePartitionData() {
- // Clear data from the storage partition. Parameters are set to clear data
- // for service workers, for all origins, for an unbounded time range.
- base::RunLoop run_loop;
-
- static_cast<StoragePartitionImpl*>(
- content::BrowserContext::GetDefaultStoragePartition(
- shell()->web_contents()->GetBrowserContext()))
- ->ClearData(StoragePartition::REMOVE_DATA_MASK_SERVICE_WORKERS,
- StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL, GURL(),
- StoragePartition::OriginMatcherFunction(), base::Time(),
- base::Time::Max(), run_loop.QuitClosure());
-
- run_loop.Run();
+ return event_data;
}
- private:
std::unique_ptr<net::EmbeddedTestServer> https_server_;
DISALLOW_COPY_AND_ASSIGN(PaymentAppBrowserTest);
};
+IN_PROC_BROWSER_TEST_F(PaymentAppBrowserTest,
+ AbortPaymentWithInvalidRegistrationId) {
+ RegisterPaymentApp();
+
+ std::vector<int64_t> registrationIds = GetAllPaymentAppRegistrationIDs();
+ ASSERT_EQ(1U, registrationIds.size());
+
+ bool payment_aborted = AbortPayment(kInvalidServiceWorkerRegistrationId);
+ ASSERT_FALSE(payment_aborted);
+
+ ClearStoragePartitionData();
+}
+
+IN_PROC_BROWSER_TEST_F(PaymentAppBrowserTest, AbortPayment) {
+ RegisterPaymentApp();
+
+ std::vector<int64_t> registrationIds = GetAllPaymentAppRegistrationIDs();
+ ASSERT_EQ(1U, registrationIds.size());
+
+ bool payment_aborted = AbortPayment(registrationIds[0]);
+ ASSERT_TRUE(payment_aborted);
+
+ ClearStoragePartitionData();
+}
+
+IN_PROC_BROWSER_TEST_F(PaymentAppBrowserTest, CanMakePayment) {
+ RegisterPaymentApp();
+
+ std::vector<int64_t> registrationIds = GetAllPaymentAppRegistrationIDs();
+ ASSERT_EQ(1U, registrationIds.size());
+
+ bool can_make_payment =
+ CanMakePaymentWithTestData(registrationIds[0], "basic-card");
+ ASSERT_TRUE(can_make_payment);
+
+ ClearStoragePartitionData();
+
+ EXPECT_EQ("https://example.com/", PopConsoleString() /* topLevelOrigin */);
+ EXPECT_EQ("https://example.com/",
+ PopConsoleString() /* paymentRequestOrigin */);
+ EXPECT_EQ("[{\"supportedMethods\":[\"basic-card\"]}]",
+ PopConsoleString() /* methodData */);
+ EXPECT_EQ(
+ "[{\"additionalDisplayItems\":[],\"supportedMethods\":[\"basic-card\"],"
+ "\"total\":{\"amount\":{\"currency\":\"USD\",\"currencySystem\":\"urn:"
+ "iso:std:iso:4217\",\"value\":\"55\"},\"label\":\"\",\"pending\":false}}"
+ "]",
+ PopConsoleString() /* modifiers */);
+}
+
+IN_PROC_BROWSER_TEST_F(PaymentAppBrowserTest, PaymentAppInvocationAndFailed) {
+ RegisterPaymentApp();
+
+ std::vector<int64_t> registrationIds = GetAllPaymentAppRegistrationIDs();
+ ASSERT_EQ(1U, registrationIds.size());
+
+ // Remove all payment apps and service workers to cause error.
+ ClearStoragePartitionData();
+
+ PaymentHandlerResponsePtr response(InvokePaymentAppWithTestData(
+ registrationIds[0], "basic-card", "basic-card-payment-app-id"));
+ ASSERT_EQ("", response->method_name);
+
+ ClearStoragePartitionData();
+}
+
IN_PROC_BROWSER_TEST_F(PaymentAppBrowserTest, PaymentAppInvocation) {
RegisterPaymentApp();
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 dbcbcb6f380..e28ae7c1331 100644
--- a/chromium/content/browser/payments/payment_app_content_unittest_base.cc
+++ b/chromium/content/browser/payments/payment_app_content_unittest_base.cc
@@ -27,11 +27,13 @@ namespace content {
namespace {
void RegisterServiceWorkerCallback(bool* called,
+ int64_t* out_registration_id,
ServiceWorkerStatusCode status,
const std::string& status_message,
int64_t registration_id) {
EXPECT_EQ(SERVICE_WORKER_OK, status) << ServiceWorkerStatusToString(status);
*called = true;
+ *out_registration_id = registration_id;
}
void UnregisterServiceWorkerCallback(bool* called,
@@ -40,6 +42,11 @@ void UnregisterServiceWorkerCallback(bool* called,
*called = true;
}
+void StopWorkerCallback(bool* called, ServiceWorkerStatusCode status) {
+ EXPECT_EQ(SERVICE_WORKER_OK, status) << ServiceWorkerStatusToString(status);
+ *called = true;
+}
+
} // namespace
class PaymentAppContentUnitTestBase::PaymentAppForWorkerTestHelper
@@ -50,21 +57,24 @@ class PaymentAppContentUnitTestBase::PaymentAppForWorkerTestHelper
last_sw_registration_id_(kInvalidServiceWorkerRegistrationId) {}
~PaymentAppForWorkerTestHelper() override {}
- void OnStartWorker(int embedded_worker_id,
- int64_t service_worker_version_id,
- const GURL& scope,
- const GURL& script_url,
- bool pause_after_download,
- mojom::ServiceWorkerEventDispatcherRequest request,
- mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo
- instance_host) override {
+ void OnStartWorker(
+ int embedded_worker_id,
+ int64_t service_worker_version_id,
+ const GURL& scope,
+ const GURL& script_url,
+ bool pause_after_download,
+ mojom::ServiceWorkerEventDispatcherRequest request,
+ mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
+ mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info)
+ override {
ServiceWorkerVersion* version =
context()->GetLiveVersion(service_worker_version_id);
last_sw_registration_id_ = version->registration_id();
last_sw_scope_ = scope;
EmbeddedWorkerTestHelper::OnStartWorker(
embedded_worker_id, service_worker_version_id, scope, script_url,
- pause_after_download, std::move(request), std::move(instance_host));
+ pause_after_download, std::move(request), std::move(instance_host),
+ std::move(provider_info));
}
void OnPaymentRequestEvent(
@@ -77,6 +87,24 @@ class PaymentAppContentUnitTestBase::PaymentAppForWorkerTestHelper
std::move(callback));
}
+ void OnCanMakePaymentEvent(
+ payments::mojom::CanMakePaymentEventDataPtr event_data,
+ payments::mojom::PaymentHandlerResponseCallbackPtr response_callback,
+ mojom::ServiceWorkerEventDispatcher::DispatchCanMakePaymentEventCallback
+ callback) override {
+ EmbeddedWorkerTestHelper::OnCanMakePaymentEvent(
+ std::move(event_data), std::move(response_callback),
+ std::move(callback));
+ }
+
+ void OnAbortPaymentEvent(
+ payments::mojom::PaymentHandlerResponseCallbackPtr response_callback,
+ mojom::ServiceWorkerEventDispatcher::DispatchCanMakePaymentEventCallback
+ callback) override {
+ EmbeddedWorkerTestHelper::OnAbortPaymentEvent(std::move(response_callback),
+ std::move(callback));
+ }
+
int64_t last_sw_registration_id_;
GURL last_sw_scope_;
@@ -110,9 +138,24 @@ PaymentManager* PaymentAppContentUnitTestBase::CreatePaymentManager(
const GURL& sw_script_url) {
// Register service worker for payment manager.
bool called = false;
+ int64_t registration_id;
+ ServiceWorkerRegistrationOptions registration_opt(scope_url);
worker_helper_->context()->RegisterServiceWorker(
- sw_script_url, ServiceWorkerRegistrationOptions(scope_url), nullptr,
- base::Bind(&RegisterServiceWorkerCallback, &called));
+ sw_script_url, registration_opt, nullptr,
+ base::Bind(&RegisterServiceWorkerCallback, &called, &registration_id));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(called);
+
+ // Ensure the worker used for installation has stopped.
+ called = false;
+ ServiceWorkerRegistration* registration =
+ worker_helper_->context()->GetLiveRegistration(registration_id);
+ EXPECT_TRUE(registration);
+ EXPECT_TRUE(registration->active_version());
+ EXPECT_FALSE(registration->waiting_version());
+ EXPECT_FALSE(registration->installing_version());
+ registration->active_version()->StopWorker(
+ base::Bind(&StopWorkerCallback, &called));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(called);
diff --git a/chromium/content/browser/payments/payment_app_context_impl.cc b/chromium/content/browser/payments/payment_app_context_impl.cc
index 9d80f0d27e5..de6c443fa37 100644
--- a/chromium/content/browser/payments/payment_app_context_impl.cc
+++ b/chromium/content/browser/payments/payment_app_context_impl.cc
@@ -25,8 +25,8 @@ void PaymentAppContextImpl::Init(
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&PaymentAppContextImpl::CreatePaymentAppDatabaseOnIO, this,
- service_worker_context));
+ base::BindOnce(&PaymentAppContextImpl::CreatePaymentAppDatabaseOnIO, this,
+ service_worker_context));
}
void PaymentAppContextImpl::Shutdown() {
@@ -34,8 +34,8 @@ void PaymentAppContextImpl::Shutdown() {
BrowserThread::PostTaskAndReply(
BrowserThread::IO, FROM_HERE,
- base::Bind(&PaymentAppContextImpl::ShutdownOnIO, this),
- base::Bind(&PaymentAppContextImpl::DidShutdown, this));
+ base::BindOnce(&PaymentAppContextImpl::ShutdownOnIO, this),
+ base::BindOnce(&PaymentAppContextImpl::DidShutdown, this));
}
void PaymentAppContextImpl::CreatePaymentManager(
@@ -44,8 +44,8 @@ void PaymentAppContextImpl::CreatePaymentManager(
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&PaymentAppContextImpl::CreatePaymentManagerOnIO, this,
- base::Passed(&request)));
+ base::BindOnce(&PaymentAppContextImpl::CreatePaymentManagerOnIO, this,
+ base::Passed(&request)));
}
void PaymentAppContextImpl::PaymentManagerHadConnectionError(
diff --git a/chromium/content/browser/payments/payment_app_database.cc b/chromium/content/browser/payments/payment_app_database.cc
index c08251072c4..5c919b446d8 100644
--- a/chromium/content/browser/payments/payment_app_database.cc
+++ b/chromium/content/browser/payments/payment_app_database.cc
@@ -33,8 +33,9 @@ const char kPaymentAppPrefix[] = "PaymentApp:";
const char kPaymentInstrumentPrefix[] = "PaymentInstrument:";
const char kPaymentInstrumentKeyInfoPrefix[] = "PaymentInstrumentKeyInfo:";
-std::string CreatePaymentAppKey(const std::string& origin) {
- return kPaymentAppPrefix + origin;
+// |pattern| is the scope URL of the service worker registration.
+std::string CreatePaymentAppKey(const std::string& pattern) {
+ return kPaymentAppPrefix + pattern;
}
std::string CreatePaymentInstrumentKey(const std::string& instrument_key) {
@@ -87,8 +88,14 @@ std::unique_ptr<StoredPaymentApp> ToStoredPaymentApp(const std::string& input) {
std::unique_ptr<StoredPaymentApp> app = base::MakeUnique<StoredPaymentApp>();
app->registration_id = app_proto.registration_id();
- app->origin = url::Origin(GURL(app_proto.origin()));
+ app->scope = GURL(app_proto.scope());
app->name = app_proto.name();
+ app->prefer_related_applications = app_proto.prefer_related_applications();
+ for (const auto& related_app : app_proto.related_applications()) {
+ app->related_applications.emplace_back(StoredRelatedApplication());
+ app->related_applications.back().platform = related_app.platform();
+ app->related_applications.back().id = related_app.id();
+ }
if (!app_proto.icon().empty()) {
std::string icon_raw_data;
@@ -190,10 +197,10 @@ void PaymentAppDatabase::WritePaymentInstrument(
base::MakeRefCounted<PaymentInstrumentIconFetcher>();
instrument_icon_fetcher_->Start(
instrument->icons, service_worker_context_,
- base::Bind(&PaymentAppDatabase::DidFetchedPaymentInstrumentIcon,
- weak_ptr_factory_.GetWeakPtr(), scope, instrument_key,
- base::Passed(std::move(instrument)),
- base::Passed(std::move(callback))));
+ base::BindOnce(&PaymentAppDatabase::DidFetchedPaymentInstrumentIcon,
+ weak_ptr_factory_.GetWeakPtr(), scope, instrument_key,
+ base::Passed(std::move(instrument)),
+ base::Passed(std::move(callback))));
} else {
service_worker_context_->FindReadyRegistrationForPattern(
scope,
@@ -245,8 +252,7 @@ void PaymentAppDatabase::FetchAndWritePaymentAppInfo(
void PaymentAppDatabase::FetchPaymentAppInfoCallback(
const GURL& scope,
FetchAndWritePaymentAppInfoCallback callback,
- const std::string& name,
- const std::string& icon) {
+ std::unique_ptr<PaymentAppInfoFetcher::PaymentAppInfo> app_info) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
payment_app_info_fetcher_ = nullptr;
@@ -255,13 +261,13 @@ void PaymentAppDatabase::FetchPaymentAppInfoCallback(
scope,
base::Bind(&PaymentAppDatabase::DidFindRegistrationToWritePaymentAppInfo,
weak_ptr_factory_.GetWeakPtr(),
- base::Passed(std::move(callback)), name, icon));
+ base::Passed(std::move(callback)),
+ base::Passed(std::move(app_info))));
}
void PaymentAppDatabase::DidFindRegistrationToWritePaymentAppInfo(
FetchAndWritePaymentAppInfoCallback callback,
- const std::string& name,
- const std::string& icon,
+ std::unique_ptr<PaymentAppInfoFetcher::PaymentAppInfo> app_info,
ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -272,10 +278,20 @@ void PaymentAppDatabase::DidFindRegistrationToWritePaymentAppInfo(
StoredPaymentAppProto payment_app_proto;
payment_app_proto.set_registration_id(registration->id());
- payment_app_proto.set_origin(
- url::Origin(registration->pattern().GetOrigin()).Serialize());
- payment_app_proto.set_name(name.empty() ? payment_app_proto.origin() : name);
- payment_app_proto.set_icon(icon);
+ payment_app_proto.set_scope(registration->pattern().spec());
+ payment_app_proto.set_name(
+ app_info->name.empty()
+ ? GURL(payment_app_proto.scope()).GetOrigin().spec()
+ : app_info->name);
+ payment_app_proto.set_icon(app_info->icon);
+ payment_app_proto.set_prefer_related_applications(
+ app_info->prefer_related_applications);
+ for (const auto& related_app : app_info->related_applications) {
+ StoredRelatedApplicationProto* related_app_proto =
+ payment_app_proto.add_related_applications();
+ related_app_proto->set_platform(related_app.platform);
+ related_app_proto->set_id(related_app.id);
+ }
std::string serialized_payment_app;
bool success = payment_app_proto.SerializeToString(&serialized_payment_app);
@@ -283,12 +299,12 @@ void PaymentAppDatabase::DidFindRegistrationToWritePaymentAppInfo(
service_worker_context_->StoreRegistrationUserData(
registration->id(), registration->pattern().GetOrigin(),
- {{CreatePaymentAppKey(registration->pattern().GetOrigin().spec()),
+ {{CreatePaymentAppKey(registration->pattern().spec()),
serialized_payment_app}},
base::Bind(&PaymentAppDatabase::DidWritePaymentApp,
weak_ptr_factory_.GetWeakPtr(),
base::Passed(std::move(callback)),
- name.empty() | icon.empty()));
+ app_info->name.empty() | app_info->icon.empty()));
}
void PaymentAppDatabase::DidWritePaymentApp(
@@ -335,7 +351,7 @@ void PaymentAppDatabase::DidReadAllPaymentApps(
std::unique_ptr<StoredPaymentApp> app =
ToStoredPaymentApp(item_of_raw_data.second);
if (app)
- apps[app->origin.GetURL()] = std::move(app);
+ apps[app->registration_id] = std::move(app);
}
if (apps.size() == 0U) {
@@ -366,12 +382,12 @@ void PaymentAppDatabase::DidReadAllPaymentInstruments(
if (!instrument_proto.ParseFromString(item_of_raw_data.second))
continue;
- GURL origin = GURL(instrument_proto.origin());
- if (!base::ContainsKey(apps, origin))
+ int64_t id = instrument_proto.registration_id();
+ if (!base::ContainsKey(apps, id))
continue;
for (const auto& method : instrument_proto.enabled_methods()) {
- apps[origin]->enabled_methods.push_back(method);
+ apps[id]->enabled_methods.push_back(method);
}
}
@@ -548,9 +564,9 @@ void PaymentAppDatabase::DidFindRegistrationToWritePaymentInstrument(
}
StoredPaymentInstrumentProto instrument_proto;
+ instrument_proto.set_registration_id(registration->id());
instrument_proto.set_decoded_instrument_icon(decoded_instrument_icon);
instrument_proto.set_instrument_key(instrument_key);
- instrument_proto.set_origin(registration->pattern().GetOrigin().spec());
instrument_proto.set_name(instrument->name);
for (const auto& method : instrument->enabled_methods) {
instrument_proto.add_enabled_methods(method);
@@ -634,7 +650,7 @@ void PaymentAppDatabase::DidGetKeysToClearPaymentInstruments(
// Clear payment app info after clearing all payment instruments.
keys_with_prefix.push_back(
- CreatePaymentAppKey(registration->pattern().GetOrigin().spec()));
+ CreatePaymentAppKey(registration->pattern().spec()));
service_worker_context_->ClearRegistrationUserData(
registration->id(), keys_with_prefix,
diff --git a/chromium/content/browser/payments/payment_app_database.h b/chromium/content/browser/payments/payment_app_database.h
index 1b88e809b9c..164aedb42e5 100644
--- a/chromium/content/browser/payments/payment_app_database.h
+++ b/chromium/content/browser/payments/payment_app_database.h
@@ -27,7 +27,7 @@ class ServiceWorkerRegistration;
class CONTENT_EXPORT PaymentAppDatabase {
public:
- using PaymentApps = std::map<GURL, std::unique_ptr<StoredPaymentApp>>;
+ using PaymentApps = std::map<int64_t, std::unique_ptr<StoredPaymentApp>>;
using ReadAllPaymentAppsCallback = base::OnceCallback<void(PaymentApps)>;
using DeletePaymentInstrumentCallback =
@@ -142,14 +142,13 @@ class CONTENT_EXPORT PaymentAppDatabase {
ServiceWorkerStatusCode status);
// FetchAndWritePaymentAppInfo callbacks.
- void FetchPaymentAppInfoCallback(const GURL& scope,
- FetchAndWritePaymentAppInfoCallback callback,
- const std::string& name,
- const std::string& icon);
+ void FetchPaymentAppInfoCallback(
+ const GURL& scope,
+ FetchAndWritePaymentAppInfoCallback callback,
+ std::unique_ptr<PaymentAppInfoFetcher::PaymentAppInfo> app_info);
void DidFindRegistrationToWritePaymentAppInfo(
FetchAndWritePaymentAppInfoCallback callback,
- const std::string& name,
- const std::string& icon,
+ std::unique_ptr<PaymentAppInfoFetcher::PaymentAppInfo> app_info,
ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration);
void DidWritePaymentApp(FetchAndWritePaymentAppInfoCallback callback,
diff --git a/chromium/content/browser/payments/payment_app_info_fetcher.cc b/chromium/content/browser/payments/payment_app_info_fetcher.cc
index cc232764fd1..89974494279 100644
--- a/chromium/content/browser/payments/payment_app_info_fetcher.cc
+++ b/chromium/content/browser/payments/payment_app_info_fetcher.cc
@@ -27,8 +27,13 @@ const int kPaymentAppMinimumIconSize = 0;
} // namespace
+PaymentAppInfoFetcher::PaymentAppInfo::PaymentAppInfo() {}
+PaymentAppInfoFetcher::PaymentAppInfo::~PaymentAppInfo() {}
+
PaymentAppInfoFetcher::PaymentAppInfoFetcher()
- : context_process_id_(-1), context_frame_id_(-1) {}
+ : context_process_id_(-1),
+ context_frame_id_(-1),
+ fetched_payment_app_info_(base::MakeUnique<PaymentAppInfo>()) {}
PaymentAppInfoFetcher::~PaymentAppInfoFetcher() {}
void PaymentAppInfoFetcher::Start(
@@ -93,10 +98,29 @@ void PaymentAppInfoFetcher::FetchPaymentAppManifestCallback(
return;
}
+ fetched_payment_app_info_->prefer_related_applications =
+ manifest.prefer_related_applications;
+ for (const auto& related_application : manifest.related_applications) {
+ fetched_payment_app_info_->related_applications.emplace_back(
+ StoredRelatedApplication());
+ if (!related_application.platform.is_null()) {
+ base::UTF16ToUTF8(
+ related_application.platform.string().c_str(),
+ related_application.platform.string().length(),
+ &(fetched_payment_app_info_->related_applications.back().platform));
+ }
+ if (!related_application.id.is_null()) {
+ base::UTF16ToUTF8(
+ related_application.id.string().c_str(),
+ related_application.id.string().length(),
+ &(fetched_payment_app_info_->related_applications.back().id));
+ }
+ }
+
if (manifest.name.is_null() ||
!base::UTF16ToUTF8(manifest.name.string().c_str(),
manifest.name.string().length(),
- &fetched_payment_app_name_)) {
+ &(fetched_payment_app_info_->name))) {
PostPaymentAppInfoFetchResultToIOThread();
return;
}
@@ -143,17 +167,16 @@ void PaymentAppInfoFetcher::OnIconFetched(const SkBitmap& icon) {
scoped_refptr<base::RefCountedMemory> raw_data = decoded_image.As1xPNGBytes();
base::Base64Encode(
base::StringPiece(raw_data->front_as<char>(), raw_data->size()),
- &fetched_payment_app_icon_);
+ &(fetched_payment_app_info_->icon));
PostPaymentAppInfoFetchResultToIOThread();
}
void PaymentAppInfoFetcher::PostPaymentAppInfoFetchResultToIOThread() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(std::move(callback_), fetched_payment_app_name_,
- fetched_payment_app_icon_));
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+ base::BindOnce(std::move(callback_),
+ std::move(fetched_payment_app_info_)));
}
} // namespace content \ No newline at end of file
diff --git a/chromium/content/browser/payments/payment_app_info_fetcher.h b/chromium/content/browser/payments/payment_app_info_fetcher.h
index 002a2dd782d..9d11b83de6c 100644
--- a/chromium/content/browser/payments/payment_app_info_fetcher.h
+++ b/chromium/content/browser/payments/payment_app_info_fetcher.h
@@ -10,6 +10,7 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
+#include "content/public/browser/stored_payment_app.h"
#include "content/public/common/manifest.h"
#include "third_party/skia/include/core/SkBitmap.h"
@@ -20,8 +21,17 @@ class PaymentAppInfoFetcher
public:
PaymentAppInfoFetcher();
+ struct PaymentAppInfo {
+ PaymentAppInfo();
+ ~PaymentAppInfo();
+
+ std::string name;
+ std::string icon;
+ bool prefer_related_applications = false;
+ std::vector<StoredRelatedApplication> related_applications;
+ };
using PaymentAppInfoFetchCallback =
- base::OnceCallback<void(const std::string&, const std::string&)>;
+ base::OnceCallback<void(std::unique_ptr<PaymentAppInfo> app_info)>;
void Start(const GURL& context_url,
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
PaymentAppInfoFetchCallback callback);
@@ -46,8 +56,7 @@ class PaymentAppInfoFetcher
int context_process_id_;
int context_frame_id_;
- std::string fetched_payment_app_name_;
- std::string fetched_payment_app_icon_;
+ std::unique_ptr<PaymentAppInfo> fetched_payment_app_info_;
DISALLOW_COPY_AND_ASSIGN(PaymentAppInfoFetcher);
};
diff --git a/chromium/content/browser/payments/payment_app_provider_impl.cc b/chromium/content/browser/payments/payment_app_provider_impl.cc
index 6d0cdd6700f..7b72610e288 100644
--- a/chromium/content/browser/payments/payment_app_provider_impl.cc
+++ b/chromium/content/browser/payments/payment_app_provider_impl.cc
@@ -13,51 +13,174 @@
#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/web_contents.h"
#include "mojo/common/time.mojom.h"
namespace content {
namespace {
-class ResponseCallback
+using ServiceWorkerStartCallback =
+ base::OnceCallback<void(scoped_refptr<ServiceWorkerVersion>,
+ ServiceWorkerStatusCode)>;
+
+// Note that one and only one of the callbacks from this class must/should be
+// called.
+class RespondWithCallbacks
: public payments::mojom::PaymentHandlerResponseCallback {
public:
- static payments::mojom::PaymentHandlerResponseCallbackPtr Create(
- int payment_request_id,
+ RespondWithCallbacks(
+ ServiceWorkerMetrics::EventType event_type,
+ scoped_refptr<ServiceWorkerVersion> service_worker_version,
+ PaymentAppProvider::InvokePaymentAppCallback callback)
+ : service_worker_version_(service_worker_version),
+ invoke_payment_app_callback_(std::move(callback)),
+ binding_(this),
+ weak_ptr_factory_(this) {
+ request_id_ = service_worker_version->StartRequest(
+ event_type, base::Bind(&RespondWithCallbacks::OnErrorStatus,
+ weak_ptr_factory_.GetWeakPtr()));
+ }
+
+ RespondWithCallbacks(
+ ServiceWorkerMetrics::EventType event_type,
scoped_refptr<ServiceWorkerVersion> service_worker_version,
- const PaymentAppProvider::InvokePaymentAppCallback callback) {
- ResponseCallback* response_callback = new ResponseCallback(
- payment_request_id, std::move(service_worker_version), callback);
+ PaymentAppProvider::PaymentEventResultCallback callback)
+ : service_worker_version_(service_worker_version),
+ payment_event_result_callback_(std::move(callback)),
+ binding_(this),
+ weak_ptr_factory_(this) {
+ request_id_ = service_worker_version->StartRequest(
+ event_type, base::Bind(&RespondWithCallbacks::OnErrorStatus,
+ weak_ptr_factory_.GetWeakPtr()));
+ }
+
+ payments::mojom::PaymentHandlerResponseCallbackPtr
+ CreateInterfacePtrAndBind() {
payments::mojom::PaymentHandlerResponseCallbackPtr callback_proxy;
- response_callback->binding_.Bind(mojo::MakeRequest(&callback_proxy));
+ binding_.Bind(mojo::MakeRequest(&callback_proxy));
return callback_proxy;
}
- ~ResponseCallback() override {}
- void OnPaymentHandlerResponse(
+ void OnResponseForPaymentRequest(
payments::mojom::PaymentHandlerResponsePtr response,
base::Time dispatch_event_time) override {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- service_worker_version_->FinishRequest(payment_request_id_, false,
+ service_worker_version_->FinishRequest(request_id_, false,
+ std::move(dispatch_event_time));
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(std::move(invoke_payment_app_callback_),
+ std::move(response)));
+
+ CloseClientWindows();
+ delete this;
+ }
+
+ void OnResponseForCanMakePayment(bool can_make_payment,
+ base::Time 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::Bind(callback_, base::Passed(std::move(response))));
+ base::BindOnce(std::move(payment_event_result_callback_),
+ can_make_payment));
+ delete this;
+ }
+
+ void OnResponseForAbortPayment(bool payment_aborted,
+ base::Time 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::BindOnce(std::move(payment_event_result_callback_),
+ payment_aborted));
+
+ CloseClientWindows();
+ delete this;
+ }
+
+ void OnErrorStatus(ServiceWorkerStatusCode service_worker_status) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(service_worker_status != SERVICE_WORKER_OK);
+
+ if (event_type_ == ServiceWorkerMetrics::EventType::PAYMENT_REQUEST) {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ 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::BindOnce(std::move(payment_event_result_callback_), false));
+ }
+
+ if (event_type_ == ServiceWorkerMetrics::EventType::PAYMENT_REQUEST ||
+ event_type_ == ServiceWorkerMetrics::EventType::ABORT_PAYMENT) {
+ CloseClientWindows();
+ }
delete this;
}
+ int request_id() { return request_id_; }
+
private:
- ResponseCallback(int payment_request_id,
- scoped_refptr<ServiceWorkerVersion> service_worker_version,
- const PaymentAppProvider::InvokePaymentAppCallback callback)
- : payment_request_id_(payment_request_id),
- service_worker_version_(service_worker_version),
- callback_(callback),
- binding_(this) {}
-
- int payment_request_id_;
+ ~RespondWithCallbacks() override {}
+
+ // Close all the windows in the payment handler service worker scope.
+ // Note that this will close not only the windows opened through
+ // PaymentRequestEvent.openWindow and Clients.openWindow(), but also the
+ // windows opened through typing the url in the ominibox only if they are in
+ // the payment handler service worker scope.
+ void CloseClientWindows() {
+ std::vector<std::pair<int, int>> ids;
+ for (const auto& controllee : service_worker_version_->controllee_map()) {
+ if (controllee.second->provider_type() ==
+ SERVICE_WORKER_PROVIDER_FOR_WINDOW) {
+ ids.emplace_back(std::make_pair(controllee.second->process_id(),
+ controllee.second->frame_id()));
+ }
+ }
+ if (ids.size() == 0)
+ return;
+
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&RespondWithCallbacks::CloseClientWindowsOnUIThread,
+ ids));
+ }
+
+ static void CloseClientWindowsOnUIThread(
+ const std::vector<std::pair<int, int>>& ids) {
+ for (const auto& id : ids) {
+ RenderFrameHost* frame_host =
+ RenderFrameHost::FromID(id.first, id.second);
+ if (frame_host == nullptr)
+ continue;
+
+ WebContents* web_contents = WebContents::FromRenderFrameHost(frame_host);
+ if (web_contents == nullptr)
+ continue;
+
+ web_contents->Close();
+ }
+ }
+
+ int request_id_;
+ ServiceWorkerMetrics::EventType event_type_;
scoped_refptr<ServiceWorkerVersion> service_worker_version_;
- const PaymentAppProvider::InvokePaymentAppCallback callback_;
+ PaymentAppProvider::InvokePaymentAppCallback invoke_payment_app_callback_;
+ PaymentAppProvider::PaymentEventResultCallback payment_event_result_callback_;
mojo::Binding<payments::mojom::PaymentHandlerResponseCallback> binding_;
+
+ base::WeakPtrFactory<RespondWithCallbacks> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(RespondWithCallbacks);
};
void DidGetAllPaymentAppsOnIO(
@@ -77,66 +200,143 @@ void GetAllPaymentAppsOnIO(
base::BindOnce(&DidGetAllPaymentAppsOnIO, std::move(callback)));
}
-void DispatchPaymentRequestEventError(
+void DispatchAbortPaymentEvent(
+ PaymentAppProvider::PaymentEventResultCallback callback,
+ scoped_refptr<ServiceWorkerVersion> active_version,
+ ServiceWorkerStatusCode service_worker_status) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (service_worker_status != SERVICE_WORKER_OK) {
+ std::move(callback).Run(false);
+ return;
+ }
+
+ DCHECK(active_version);
+
+ int event_finish_id = active_version->StartRequest(
+ ServiceWorkerMetrics::EventType::CAN_MAKE_PAYMENT,
+ base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
+
+ // This object self-deletes after either success or error callback is invoked.
+ RespondWithCallbacks* invocation_callbacks =
+ new RespondWithCallbacks(ServiceWorkerMetrics::EventType::ABORT_PAYMENT,
+ active_version, std::move(callback));
+
+ active_version->event_dispatcher()->DispatchAbortPaymentEvent(
+ invocation_callbacks->request_id(),
+ invocation_callbacks->CreateInterfacePtrAndBind(),
+ active_version->CreateSimpleEventCallback(event_finish_id));
+}
+
+void DispatchCanMakePaymentEvent(
+ payments::mojom::CanMakePaymentEventDataPtr event_data,
+ PaymentAppProvider::PaymentEventResultCallback callback,
+ scoped_refptr<ServiceWorkerVersion> active_version,
ServiceWorkerStatusCode service_worker_status) {
- NOTIMPLEMENTED();
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (service_worker_status != SERVICE_WORKER_OK) {
+ std::move(callback).Run(false);
+ return;
+ }
+
+ DCHECK(active_version);
+
+ int event_finish_id = active_version->StartRequest(
+ ServiceWorkerMetrics::EventType::CAN_MAKE_PAYMENT,
+ base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
+
+ // This object self-deletes after either success or error callback is invoked.
+ RespondWithCallbacks* invocation_callbacks = new RespondWithCallbacks(
+ ServiceWorkerMetrics::EventType::CAN_MAKE_PAYMENT, active_version,
+ std::move(callback));
+
+ active_version->event_dispatcher()->DispatchCanMakePaymentEvent(
+ invocation_callbacks->request_id(), std::move(event_data),
+ invocation_callbacks->CreateInterfacePtrAndBind(),
+ active_version->CreateSimpleEventCallback(event_finish_id));
}
void DispatchPaymentRequestEvent(
payments::mojom::PaymentRequestEventDataPtr event_data,
- const PaymentAppProvider::InvokePaymentAppCallback& callback,
- scoped_refptr<ServiceWorkerVersion> active_version) {
+ PaymentAppProvider::InvokePaymentAppCallback callback,
+ scoped_refptr<ServiceWorkerVersion> active_version,
+ ServiceWorkerStatusCode service_worker_status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (service_worker_status != SERVICE_WORKER_OK) {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(std::move(callback),
+ payments::mojom::PaymentHandlerResponse::New()));
+ return;
+ }
+
DCHECK(active_version);
- int payment_request_id = active_version->StartRequest(
- ServiceWorkerMetrics::EventType::PAYMENT_REQUEST,
- base::Bind(&DispatchPaymentRequestEventError));
int event_finish_id = active_version->StartRequest(
ServiceWorkerMetrics::EventType::PAYMENT_REQUEST,
base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
- payments::mojom::PaymentHandlerResponseCallbackPtr response_callback_ptr =
- ResponseCallback::Create(payment_request_id, active_version, callback);
- DCHECK(response_callback_ptr);
+ // This object self-deletes after either success or error callback is invoked.
+ RespondWithCallbacks* invocation_callbacks =
+ new RespondWithCallbacks(ServiceWorkerMetrics::EventType::PAYMENT_REQUEST,
+ active_version, std::move(callback));
+
active_version->event_dispatcher()->DispatchPaymentRequestEvent(
- payment_request_id, std::move(event_data),
- std::move(response_callback_ptr),
+ invocation_callbacks->request_id(), std::move(event_data),
+ invocation_callbacks->CreateInterfacePtrAndBind(),
active_version->CreateSimpleEventCallback(event_finish_id));
}
void DidFindRegistrationOnIO(
- payments::mojom::PaymentRequestEventDataPtr event_data,
- const PaymentAppProvider::InvokePaymentAppCallback& callback,
+ ServiceWorkerStartCallback callback,
ServiceWorkerStatusCode service_worker_status,
scoped_refptr<ServiceWorkerRegistration> service_worker_registration) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (service_worker_status != SERVICE_WORKER_OK)
+ if (service_worker_status != SERVICE_WORKER_OK) {
+ std::move(callback).Run(nullptr, service_worker_status);
return;
+ }
ServiceWorkerVersion* active_version =
service_worker_registration->active_version();
DCHECK(active_version);
+
+ auto done_callback = base::AdaptCallbackForRepeating(
+ base::BindOnce(std::move(callback), make_scoped_refptr(active_version)));
+
active_version->RunAfterStartWorker(
ServiceWorkerMetrics::EventType::PAYMENT_REQUEST,
- base::Bind(&DispatchPaymentRequestEvent,
- base::Passed(std::move(event_data)), callback,
- make_scoped_refptr(active_version)),
- base::Bind(&DispatchPaymentRequestEventError));
+ base::BindOnce(done_callback, service_worker_status), done_callback);
}
void FindRegistrationOnIO(
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
int64_t registration_id,
- payments::mojom::PaymentRequestEventDataPtr event_data,
- const PaymentAppProvider::InvokePaymentAppCallback& callback) {
+ ServiceWorkerStartCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
service_worker_context->FindReadyRegistrationForIdOnly(
registration_id,
- base::Bind(&DidFindRegistrationOnIO, base::Passed(std::move(event_data)),
- callback));
+ base::Bind(&DidFindRegistrationOnIO, base::Passed(std::move(callback))));
+}
+
+void StartServiceWorkerForDispatch(BrowserContext* browser_context,
+ int64_t registration_id,
+ ServiceWorkerStartCallback callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
+ BrowserContext::GetDefaultStoragePartition(browser_context));
+ scoped_refptr<ServiceWorkerContextWrapper> service_worker_context =
+ partition->GetServiceWorkerContext();
+
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&FindRegistrationOnIO, std::move(service_worker_context),
+ registration_id, std::move(callback)));
}
} // namespace
@@ -172,19 +372,36 @@ void PaymentAppProviderImpl::InvokePaymentApp(
BrowserContext* browser_context,
int64_t registration_id,
payments::mojom::PaymentRequestEventDataPtr event_data,
- const InvokePaymentAppCallback& callback) {
+ InvokePaymentAppCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
- BrowserContext::GetDefaultStoragePartition(browser_context));
- scoped_refptr<ServiceWorkerContextWrapper> service_worker_context =
- partition->GetServiceWorkerContext();
+ StartServiceWorkerForDispatch(
+ browser_context, registration_id,
+ base::BindOnce(&DispatchPaymentRequestEvent, std::move(event_data),
+ std::move(callback)));
+}
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::Bind(&FindRegistrationOnIO, std::move(service_worker_context),
- registration_id, base::Passed(std::move(event_data)),
- callback));
+void PaymentAppProviderImpl::CanMakePayment(
+ BrowserContext* browser_context,
+ int64_t registration_id,
+ payments::mojom::CanMakePaymentEventDataPtr event_data,
+ PaymentEventResultCallback callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ StartServiceWorkerForDispatch(
+ browser_context, registration_id,
+ base::BindOnce(&DispatchCanMakePaymentEvent, std::move(event_data),
+ std::move(callback)));
+}
+
+void PaymentAppProviderImpl::AbortPayment(BrowserContext* browser_context,
+ int64_t registration_id,
+ PaymentEventResultCallback callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ StartServiceWorkerForDispatch(
+ browser_context, registration_id,
+ base::BindOnce(&DispatchAbortPaymentEvent, std::move(callback)));
}
PaymentAppProviderImpl::PaymentAppProviderImpl() {}
diff --git a/chromium/content/browser/payments/payment_app_provider_impl.h b/chromium/content/browser/payments/payment_app_provider_impl.h
index 0bc54436c1d..52a7ddd1eaa 100644
--- a/chromium/content/browser/payments/payment_app_provider_impl.h
+++ b/chromium/content/browser/payments/payment_app_provider_impl.h
@@ -23,7 +23,14 @@ class CONTENT_EXPORT PaymentAppProviderImpl : public PaymentAppProvider {
void InvokePaymentApp(BrowserContext* browser_context,
int64_t registration_id,
payments::mojom::PaymentRequestEventDataPtr event_data,
- const InvokePaymentAppCallback& callback) override;
+ InvokePaymentAppCallback callback) override;
+ void CanMakePayment(BrowserContext* browser_context,
+ int64_t registration_id,
+ payments::mojom::CanMakePaymentEventDataPtr event_data,
+ PaymentEventResultCallback callback) override;
+ void AbortPayment(BrowserContext* browser_context,
+ int64_t registration_id,
+ PaymentEventResultCallback callback) override;
private:
PaymentAppProviderImpl();
diff --git a/chromium/content/browser/payments/payment_app_provider_impl_unittest.cc b/chromium/content/browser/payments/payment_app_provider_impl_unittest.cc
index 604297d8e9f..5aef1d2e88e 100644
--- a/chromium/content/browser/payments/payment_app_provider_impl_unittest.cc
+++ b/chromium/content/browser/payments/payment_app_provider_impl_unittest.cc
@@ -40,6 +40,11 @@ void InvokePaymentAppCallback(
*called = true;
}
+void PaymentEventResultCallback(bool* out_payment_event_result,
+ bool payment_event_result) {
+ *out_payment_event_result = payment_event_result;
+}
+
} // namespace
class PaymentAppProviderTest : public PaymentAppContentUnitTestBase {
@@ -69,7 +74,24 @@ class PaymentAppProviderTest : public PaymentAppContentUnitTestBase {
payments::mojom::PaymentRequestEventDataPtr event_data,
PaymentAppProvider::InvokePaymentAppCallback callback) {
PaymentAppProviderImpl::GetInstance()->InvokePaymentApp(
- browser_context(), registration_id, std::move(event_data), callback);
+ browser_context(), registration_id, std::move(event_data),
+ std::move(callback));
+ base::RunLoop().RunUntilIdle();
+ }
+
+ void CanMakePayment(int64_t registration_id,
+ payments::mojom::CanMakePaymentEventDataPtr event_data,
+ PaymentAppProvider::PaymentEventResultCallback callback) {
+ PaymentAppProviderImpl::GetInstance()->CanMakePayment(
+ browser_context(), registration_id, std::move(event_data),
+ std::move(callback));
+ base::RunLoop().RunUntilIdle();
+ }
+
+ void AbortPayment(int64_t registration_id,
+ PaymentAppProvider::PaymentEventResultCallback callback) {
+ PaymentAppProviderImpl::GetInstance()->AbortPayment(
+ browser_context(), registration_id, std::move(callback));
base::RunLoop().RunUntilIdle();
}
@@ -77,6 +99,52 @@ class PaymentAppProviderTest : public PaymentAppContentUnitTestBase {
DISALLOW_COPY_AND_ASSIGN(PaymentAppProviderTest);
};
+TEST_F(PaymentAppProviderTest, AbortPaymentTest) {
+ PaymentManager* manager = CreatePaymentManager(
+ GURL("https://example.com"), GURL("https://example.com/script.js"));
+
+ PaymentHandlerStatus status;
+ SetPaymentInstrument(manager, "payment_instrument_key",
+ payments::mojom::PaymentInstrument::New(),
+ base::BindOnce(&SetPaymentInstrumentCallback, &status));
+
+ PaymentAppProvider::PaymentApps apps;
+ GetAllPaymentApps(base::BindOnce(&GetAllPaymentAppsCallback, &apps));
+ ASSERT_EQ(1U, apps.size());
+
+ bool payment_aborted = false;
+ AbortPayment(last_sw_registration_id(),
+ base::BindOnce(&PaymentEventResultCallback, &payment_aborted));
+ ASSERT_TRUE(payment_aborted);
+}
+
+TEST_F(PaymentAppProviderTest, CanMakePaymentTest) {
+ PaymentManager* manager = CreatePaymentManager(
+ GURL("https://example.com"), GURL("https://example.com/script.js"));
+
+ PaymentHandlerStatus status;
+ SetPaymentInstrument(manager, "payment_instrument_key",
+ payments::mojom::PaymentInstrument::New(),
+ base::BindOnce(&SetPaymentInstrumentCallback, &status));
+
+ PaymentAppProvider::PaymentApps apps;
+ GetAllPaymentApps(base::BindOnce(&GetAllPaymentAppsCallback, &apps));
+ ASSERT_EQ(1U, apps.size());
+
+ payments::mojom::CanMakePaymentEventDataPtr event_data =
+ payments::mojom::CanMakePaymentEventData::New();
+ payments::mojom::PaymentMethodDataPtr methodData =
+ payments::mojom::PaymentMethodData::New();
+ methodData->supported_methods.push_back("test-method");
+ event_data->method_data.push_back(std::move(methodData));
+
+ bool can_make_payment = false;
+ CanMakePayment(
+ last_sw_registration_id(), std::move(event_data),
+ base::BindOnce(&PaymentEventResultCallback, &can_make_payment));
+ ASSERT_TRUE(can_make_payment);
+}
+
TEST_F(PaymentAppProviderTest, InvokePaymentAppTest) {
PaymentManager* manager1 = CreatePaymentManager(
GURL("https://hellopay.com/a"), GURL("https://hellopay.com/a/script.js"));
@@ -86,61 +154,96 @@ TEST_F(PaymentAppProviderTest, InvokePaymentAppTest) {
PaymentHandlerStatus status;
SetPaymentInstrument(manager1, "test_key1",
payments::mojom::PaymentInstrument::New(),
- base::Bind(&SetPaymentInstrumentCallback, &status));
+ base::BindOnce(&SetPaymentInstrumentCallback, &status));
SetPaymentInstrument(manager2, "test_key2",
payments::mojom::PaymentInstrument::New(),
- base::Bind(&SetPaymentInstrumentCallback, &status));
+ base::BindOnce(&SetPaymentInstrumentCallback, &status));
SetPaymentInstrument(manager2, "test_key3",
payments::mojom::PaymentInstrument::New(),
- base::Bind(&SetPaymentInstrumentCallback, &status));
+ base::BindOnce(&SetPaymentInstrumentCallback, &status));
PaymentAppProvider::PaymentApps apps;
- GetAllPaymentApps(base::Bind(&GetAllPaymentAppsCallback, &apps));
+ GetAllPaymentApps(base::BindOnce(&GetAllPaymentAppsCallback, &apps));
ASSERT_EQ(2U, apps.size());
+ int64_t bobpay_registration_id = last_sw_registration_id();
+ EXPECT_EQ(apps[bobpay_registration_id]->scope.spec(), "https://bobpay.com/b");
+
payments::mojom::PaymentRequestEventDataPtr event_data =
payments::mojom::PaymentRequestEventData::New();
event_data->method_data.push_back(payments::mojom::PaymentMethodData::New());
event_data->total = payments::mojom::PaymentCurrencyAmount::New();
bool called = false;
- InvokePaymentApp(apps[GURL("https://hellopay.com/")]->registration_id,
- std::move(event_data),
- base::Bind(&InvokePaymentAppCallback, &called));
+ InvokePaymentApp(bobpay_registration_id, std::move(event_data),
+ base::BindOnce(&InvokePaymentAppCallback, &called));
ASSERT_TRUE(called);
-
- EXPECT_EQ(apps[GURL("https://hellopay.com/")]->registration_id,
- last_sw_registration_id());
}
TEST_F(PaymentAppProviderTest, GetAllPaymentAppsTest) {
PaymentManager* manager1 = CreatePaymentManager(
GURL("https://hellopay.com/a"), GURL("https://hellopay.com/a/script.js"));
+ int64_t hellopay_registration_id = last_sw_registration_id();
+
+ PaymentManager* manager2 = CreatePaymentManager(
+ GURL("https://bobpay.com/b"), GURL("https://bobpay.com/b/script.js"));
+ int64_t bobpay_registration_id = last_sw_registration_id();
+
+ PaymentHandlerStatus status;
+ PaymentInstrumentPtr instrument_1 = PaymentInstrument::New();
+ instrument_1->enabled_methods.push_back("hellopay");
+ SetPaymentInstrument(manager1, "test_key1", std::move(instrument_1),
+ base::BindOnce(&SetPaymentInstrumentCallback, &status));
+
+ PaymentInstrumentPtr instrument_2 = PaymentInstrument::New();
+ instrument_2->enabled_methods.push_back("hellopay");
+ SetPaymentInstrument(manager2, "test_key2", std::move(instrument_2),
+ base::BindOnce(&SetPaymentInstrumentCallback, &status));
+
+ PaymentInstrumentPtr instrument_3 = PaymentInstrument::New();
+ instrument_3->enabled_methods.push_back("bobpay");
+ SetPaymentInstrument(manager2, "test_key3", std::move(instrument_3),
+ base::BindOnce(&SetPaymentInstrumentCallback, &status));
+
+ PaymentAppProvider::PaymentApps apps;
+ GetAllPaymentApps(base::BindOnce(&GetAllPaymentAppsCallback, &apps));
+
+ ASSERT_EQ(2U, apps.size());
+ ASSERT_EQ(1U, apps[hellopay_registration_id]->enabled_methods.size());
+ ASSERT_EQ(2U, apps[bobpay_registration_id]->enabled_methods.size());
+}
+
+TEST_F(PaymentAppProviderTest, GetAllPaymentAppsFromTheSameOriginTest) {
+ PaymentManager* manager1 = CreatePaymentManager(
+ GURL("https://bobpay.com/a"), GURL("https://bobpay.com/a/script.js"));
+ int64_t bobpay_a_registration_id = last_sw_registration_id();
+
PaymentManager* manager2 = CreatePaymentManager(
GURL("https://bobpay.com/b"), GURL("https://bobpay.com/b/script.js"));
+ int64_t bobpay_b_registration_id = last_sw_registration_id();
PaymentHandlerStatus status;
PaymentInstrumentPtr instrument_1 = PaymentInstrument::New();
instrument_1->enabled_methods.push_back("hellopay");
SetPaymentInstrument(manager1, "test_key1", std::move(instrument_1),
- base::Bind(&SetPaymentInstrumentCallback, &status));
+ base::BindOnce(&SetPaymentInstrumentCallback, &status));
PaymentInstrumentPtr instrument_2 = PaymentInstrument::New();
instrument_2->enabled_methods.push_back("hellopay");
SetPaymentInstrument(manager2, "test_key2", std::move(instrument_2),
- base::Bind(&SetPaymentInstrumentCallback, &status));
+ base::BindOnce(&SetPaymentInstrumentCallback, &status));
PaymentInstrumentPtr instrument_3 = PaymentInstrument::New();
instrument_3->enabled_methods.push_back("bobpay");
SetPaymentInstrument(manager2, "test_key3", std::move(instrument_3),
- base::Bind(&SetPaymentInstrumentCallback, &status));
+ base::BindOnce(&SetPaymentInstrumentCallback, &status));
PaymentAppProvider::PaymentApps apps;
- GetAllPaymentApps(base::Bind(&GetAllPaymentAppsCallback, &apps));
+ GetAllPaymentApps(base::BindOnce(&GetAllPaymentAppsCallback, &apps));
ASSERT_EQ(2U, apps.size());
- ASSERT_EQ(1U, apps[GURL("https://hellopay.com/")]->enabled_methods.size());
- ASSERT_EQ(2U, apps[GURL("https://bobpay.com/")]->enabled_methods.size());
+ ASSERT_EQ(1U, apps[bobpay_a_registration_id]->enabled_methods.size());
+ ASSERT_EQ(2U, apps[bobpay_b_registration_id]->enabled_methods.size());
}
} // namespace content
diff --git a/chromium/content/browser/payments/payment_instrument_icon_fetcher.cc b/chromium/content/browser/payments/payment_instrument_icon_fetcher.cc
index 3229de95d34..338b7cfec62 100644
--- a/chromium/content/browser/payments/payment_instrument_icon_fetcher.cc
+++ b/chromium/content/browser/payments/payment_instrument_icon_fetcher.cc
@@ -35,7 +35,7 @@ net::NetworkTrafficAnnotationTag g_traffic_annotation =
destination: WEBSITE
}
policy {
- cookies_allowed: false
+ cookies_allowed: NO
setting:
"This feature cannot be disabled in settings. Users can refuse to "
"install web payment apps."
@@ -132,7 +132,7 @@ void PaymentInstrumentIconFetcher::OnURLFetchComplete(
data_decoder::DecodeImage(
connector.get(), image_data, data_decoder::mojom::ImageCodec::DEFAULT,
false, data_decoder::kDefaultMaxSizeInBytes, gfx::Size(),
- base::Bind(&PaymentInstrumentIconFetcher::DecodeImageCallback, this));
+ base::BindOnce(&PaymentInstrumentIconFetcher::DecodeImageCallback, this));
}
void PaymentInstrumentIconFetcher::DecodeImageCallback(const SkBitmap& bitmap) {
diff --git a/chromium/content/browser/payments/payment_manager.cc b/chromium/content/browser/payments/payment_manager.cc
index 753fe245f98..89ada1aeb20 100644
--- a/chromium/content/browser/payments/payment_manager.cc
+++ b/chromium/content/browser/payments/payment_manager.cc
@@ -30,8 +30,8 @@ PaymentManager::PaymentManager(
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(payment_app_context);
- binding_.set_connection_error_handler(
- base::Bind(&PaymentManager::OnConnectionError, base::Unretained(this)));
+ binding_.set_connection_error_handler(base::BindOnce(
+ &PaymentManager::OnConnectionError, base::Unretained(this)));
}
void PaymentManager::Init(const std::string& context,
diff --git a/chromium/content/browser/payments/payment_manager.h b/chromium/content/browser/payments/payment_manager.h
index da77b8128d4..f4eed487f60 100644
--- a/chromium/content/browser/payments/payment_manager.h
+++ b/chromium/content/browser/payments/payment_manager.h
@@ -18,8 +18,7 @@ namespace content {
class PaymentAppContextImpl;
-class CONTENT_EXPORT PaymentManager
- : public NON_EXPORTED_BASE(payments::mojom::PaymentManager) {
+class CONTENT_EXPORT PaymentManager : public payments::mojom::PaymentManager {
public:
PaymentManager(
PaymentAppContextImpl* payment_app_context,
diff --git a/chromium/content/browser/payments/payment_manager_unittest.cc b/chromium/content/browser/payments/payment_manager_unittest.cc
index faaf3d4d5dc..94eec8bf828 100644
--- a/chromium/content/browser/payments/payment_manager_unittest.cc
+++ b/chromium/content/browser/payments/payment_manager_unittest.cc
@@ -73,7 +73,7 @@ class PaymentManagerTest : public PaymentAppContentUnitTestBase {
PaymentHandlerStatus* out_status) {
manager_->DeletePaymentInstrument(
instrument_key,
- base::Bind(&DeletePaymentInstrumentCallback, out_status));
+ base::BindOnce(&DeletePaymentInstrumentCallback, out_status));
base::RunLoop().RunUntilIdle();
}
@@ -82,36 +82,37 @@ class PaymentManagerTest : public PaymentAppContentUnitTestBase {
PaymentHandlerStatus* out_status) {
manager_->SetPaymentInstrument(
instrument_key, std::move(instrument),
- base::Bind(&SetPaymentInstrumentCallback, out_status));
+ base::BindOnce(&SetPaymentInstrumentCallback, out_status));
base::RunLoop().RunUntilIdle();
}
void KeysOfPaymentInstruments(std::vector<std::string>* out_keys,
PaymentHandlerStatus* out_status) {
- manager_->KeysOfPaymentInstruments(
- base::Bind(&KeysOfPaymentInstrumentsCallback, out_keys, out_status));
+ manager_->KeysOfPaymentInstruments(base::BindOnce(
+ &KeysOfPaymentInstrumentsCallback, out_keys, out_status));
base::RunLoop().RunUntilIdle();
}
void HasPaymentInstrument(const std::string& instrument_key,
PaymentHandlerStatus* out_status) {
manager_->HasPaymentInstrument(
- instrument_key, base::Bind(&HasPaymentInstrumentCallback, out_status));
+ instrument_key,
+ base::BindOnce(&HasPaymentInstrumentCallback, out_status));
base::RunLoop().RunUntilIdle();
}
void GetPaymentInstrument(const std::string& instrument_key,
PaymentInstrumentPtr* out_instrument,
PaymentHandlerStatus* out_status) {
- manager_->GetPaymentInstrument(
- instrument_key,
- base::Bind(&GetPaymentInstrumentCallback, out_instrument, out_status));
+ manager_->GetPaymentInstrument(instrument_key,
+ base::BindOnce(&GetPaymentInstrumentCallback,
+ out_instrument, out_status));
base::RunLoop().RunUntilIdle();
}
void ClearPaymentInstruments(PaymentHandlerStatus* out_status) {
manager_->ClearPaymentInstruments(
- base::Bind(&ClearPaymentInstrumentsCallback, out_status));
+ base::BindOnce(&ClearPaymentInstrumentsCallback, out_status));
base::RunLoop().RunUntilIdle();
}
diff --git a/chromium/content/browser/pepper_flash_settings_helper_impl.h b/chromium/content/browser/pepper_flash_settings_helper_impl.h
index cb11025bd6a..95657408bce 100644
--- a/chromium/content/browser/pepper_flash_settings_helper_impl.h
+++ b/chromium/content/browser/pepper_flash_settings_helper_impl.h
@@ -14,7 +14,7 @@ namespace content {
class CONTENT_EXPORT PepperFlashSettingsHelperImpl
: public PepperFlashSettingsHelper,
- NON_EXPORTED_BASE(public PpapiPluginProcessHost::BrokerClient) {
+ public PpapiPluginProcessHost::BrokerClient {
public:
PepperFlashSettingsHelperImpl();
diff --git a/chromium/content/browser/permissions/permission_service_context.cc b/chromium/content/browser/permissions/permission_service_context.cc
index ed873fa5526..311e0c69f74 100644
--- a/chromium/content/browser/permissions/permission_service_context.cc
+++ b/chromium/content/browser/permissions/permission_service_context.cc
@@ -30,8 +30,7 @@ class PermissionServiceContext::PermissionSubscription {
~PermissionSubscription() {
DCHECK_NE(id_, 0);
BrowserContext* browser_context = context_->GetBrowserContext();
- DCHECK(browser_context);
- if (browser_context->GetPermissionManager()) {
+ if (browser_context && browser_context->GetPermissionManager()) {
browser_context->GetPermissionManager()
->UnsubscribePermissionStatusChange(id_);
}
@@ -82,8 +81,7 @@ void PermissionServiceContext::CreateSubscription(
const url::Origin& origin,
PermissionObserverPtr observer) {
BrowserContext* browser_context = GetBrowserContext();
- DCHECK(browser_context);
- if (!browser_context->GetPermissionManager())
+ if (!browser_context || !browser_context->GetPermissionManager())
return;
auto subscription =
@@ -137,11 +135,15 @@ void PermissionServiceContext::CloseBindings(
}
BrowserContext* PermissionServiceContext::GetBrowserContext() const {
- if (!web_contents()) {
- DCHECK(render_process_host_);
+ // web_contents() may return nullptr during teardown, or when showing
+ // an interstitial.
+ if (web_contents())
+ return web_contents()->GetBrowserContext();
+
+ if (render_process_host_)
return render_process_host_->GetBrowserContext();
- }
- return web_contents()->GetBrowserContext();
+
+ return nullptr;
}
GURL PermissionServiceContext::GetEmbeddingOrigin() const {
diff --git a/chromium/content/browser/permissions/permission_service_context.h b/chromium/content/browser/permissions/permission_service_context.h
index 9ed0feeb9c5..0fa82541fbb 100644
--- a/chromium/content/browser/permissions/permission_service_context.h
+++ b/chromium/content/browser/permissions/permission_service_context.h
@@ -41,7 +41,9 @@ class CONTENT_EXPORT PermissionServiceContext : public WebContentsObserver {
// Called when the connection to a PermissionObserver has an error.
void ObserverHadConnectionError(int subscription_id);
+ // May return nullptr during teardown, or when showing an interstitial.
BrowserContext* GetBrowserContext() const;
+
GURL GetEmbeddingOrigin() const;
RenderFrameHost* render_frame_host() const;
diff --git a/chromium/content/browser/permissions/permission_service_impl.cc b/chromium/content/browser/permissions/permission_service_impl.cc
index b223db0ce96..ce9f2653018 100644
--- a/chromium/content/browser/permissions/permission_service_impl.cc
+++ b/chromium/content/browser/permissions/permission_service_impl.cc
@@ -54,6 +54,10 @@ PermissionType PermissionDescriptorToPermissionType(
return PermissionType::VIDEO_CAPTURE;
case PermissionName::BACKGROUND_SYNC:
return PermissionType::BACKGROUND_SYNC;
+ case PermissionName::SENSORS:
+ return PermissionType::SENSORS;
+ case PermissionName::ACCESSIBILITY_EVENTS:
+ return PermissionType::ACCESSIBILITY_EVENTS;
}
NOTREACHED();
@@ -79,6 +83,8 @@ blink::WebFeaturePolicyFeature PermissionTypeToFeaturePolicyFeature(
case PermissionType::DURABLE_STORAGE:
case PermissionType::BACKGROUND_SYNC:
case PermissionType::FLASH:
+ case PermissionType::SENSORS:
+ case PermissionType::ACCESSIBILITY_EVENTS:
case PermissionType::NUM:
// These aren't exposed by feature policy.
return blink::WebFeaturePolicyFeature::kNotFound;
@@ -173,10 +179,12 @@ PermissionServiceImpl::PermissionServiceImpl(PermissionServiceContext* context)
: context_(context), weak_factory_(this) {}
PermissionServiceImpl::~PermissionServiceImpl() {
- DCHECK(context_->GetBrowserContext());
+ BrowserContext* browser_context = context_->GetBrowserContext();
+ if (!browser_context)
+ return;
PermissionManager* permission_manager =
- context_->GetBrowserContext()->GetPermissionManager();
+ browser_context->GetPermissionManager();
if (!permission_manager)
return;
@@ -213,7 +221,9 @@ void PermissionServiceImpl::RequestPermissions(
// any UI, we want to still return something relevant so the current
// permission status is returned for each permission.
BrowserContext* browser_context = context_->GetBrowserContext();
- DCHECK(browser_context);
+ if (!browser_context)
+ return;
+
if (!context_->render_frame_host() ||
!browser_context->GetPermissionManager()) {
std::vector<PermissionStatus> result(permissions.size());
@@ -329,7 +339,9 @@ PermissionStatus PermissionServiceImpl::GetPermissionStatusFromType(
PermissionType type,
const url::Origin& origin) {
BrowserContext* browser_context = context_->GetBrowserContext();
- DCHECK(browser_context);
+ if (!browser_context)
+ return PermissionStatus::DENIED;
+
if (!browser_context->GetPermissionManager() ||
!AllowedByFeaturePolicy(context_->render_frame_host(), type)) {
return PermissionStatus::DENIED;
@@ -346,7 +358,9 @@ PermissionStatus PermissionServiceImpl::GetPermissionStatusFromType(
void PermissionServiceImpl::ResetPermissionStatus(PermissionType type,
const url::Origin& origin) {
BrowserContext* browser_context = context_->GetBrowserContext();
- DCHECK(browser_context);
+ if (!browser_context)
+ return;
+
if (!browser_context->GetPermissionManager())
return;
diff --git a/chromium/content/browser/permissions/permission_service_impl.h b/chromium/content/browser/permissions/permission_service_impl.h
index 1c15ff95953..678264804ea 100644
--- a/chromium/content/browser/permissions/permission_service_impl.h
+++ b/chromium/content/browser/permissions/permission_service_impl.h
@@ -6,7 +6,7 @@
#define CONTENT_BROWSER_PERMISSIONS_PERMISSION_SERVICE_IMPL_H_
#include "base/callback.h"
-#include "base/id_map.h"
+#include "base/containers/id_map.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "content/browser/permissions/permission_service_context.h"
@@ -38,7 +38,7 @@ class CONTENT_EXPORT PermissionServiceImpl
base::OnceCallback<void(blink::mojom::PermissionStatus)>;
class PendingRequest;
- using RequestsMap = IDMap<std::unique_ptr<PendingRequest>>;
+ using RequestsMap = base::IDMap<std::unique_ptr<PendingRequest>>;
// blink::mojom::PermissionService.
void HasPermission(blink::mojom::PermissionDescriptorPtr permission,
diff --git a/chromium/content/browser/plugin_private_storage_helper.cc b/chromium/content/browser/plugin_private_storage_helper.cc
index 2b25d828861..bb3d4461476 100644
--- a/chromium/content/browser/plugin_private_storage_helper.cc
+++ b/chromium/content/browser/plugin_private_storage_helper.cc
@@ -86,7 +86,7 @@ class PluginPrivateDataByOriginChecker {
void OnFileSystemOpened(base::File::Error result);
void OnDirectoryRead(const std::string& root,
base::File::Error result,
- const storage::AsyncFileUtil::EntryList& file_list,
+ storage::AsyncFileUtil::EntryList file_list,
bool has_more);
void OnFileInfo(const std::string& file_name,
base::File::Error result,
@@ -150,14 +150,14 @@ void PluginPrivateDataByOriginChecker::OnFileSystemOpened(
filesystem_context_);
file_util->ReadDirectory(
std::move(operation_context), filesystem_context_->CrackURL(GURL(root)),
- base::Bind(&PluginPrivateDataByOriginChecker::OnDirectoryRead,
- base::Unretained(this), root));
+ base::BindRepeating(&PluginPrivateDataByOriginChecker::OnDirectoryRead,
+ base::Unretained(this), root));
}
void PluginPrivateDataByOriginChecker::OnDirectoryRead(
const std::string& root,
base::File::Error result,
- const storage::AsyncFileUtil::EntryList& file_list,
+ storage::AsyncFileUtil::EntryList file_list,
bool has_more) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DVLOG(3) << __func__ << " result: " << result
diff --git a/chromium/content/browser/plugin_service_impl.h b/chromium/content/browser/plugin_service_impl.h
index 85b64dad4b9..b654bf3c98b 100644
--- a/chromium/content/browser/plugin_service_impl.h
+++ b/chromium/content/browser/plugin_service_impl.h
@@ -47,8 +47,7 @@ class PluginServiceFilter;
class ResourceContext;
struct PepperPluginInfo;
-class CONTENT_EXPORT PluginServiceImpl
- : NON_EXPORTED_BASE(public PluginService) {
+class CONTENT_EXPORT PluginServiceImpl : public PluginService {
public:
// Returns the PluginServiceImpl singleton.
static PluginServiceImpl* GetInstance();
diff --git a/chromium/content/browser/pointer_lock_browsertest.cc b/chromium/content/browser/pointer_lock_browsertest.cc
index 812944789a7..6caba57f87b 100644
--- a/chromium/content/browser/pointer_lock_browsertest.cc
+++ b/chromium/content/browser/pointer_lock_browsertest.cc
@@ -352,6 +352,19 @@ IN_PROC_BROWSER_TEST_F(PointerLockBrowserTest, PointerLockWheelEventRouting) {
// Make sure that the renderer handled the input event.
root_observer.Wait();
+ if (root_view->wheel_scroll_latching_enabled()) {
+ // When wheel scroll latching is enabled all wheel events during a scroll
+ // sequence will be sent to a single target. Send a wheel end event to the
+ // current target before sending wheel events to a new target.
+ wheel_event.delta_x = 0;
+ wheel_event.delta_y = 0;
+ wheel_event.phase = blink::WebMouseWheelEvent::kPhaseEnded;
+ router->RouteMouseWheelEvent(root_view, &wheel_event, ui::LatencyInfo());
+
+ // Make sure that the renderer handled the input event.
+ root_observer.Wait();
+ }
+
int x, y, deltaX, deltaY;
EXPECT_TRUE(ExecuteScriptAndExtractInt(
root, "window.domAutomationController.send(x);", &x));
@@ -396,6 +409,8 @@ IN_PROC_BROWSER_TEST_F(PointerLockBrowserTest, PointerLockWheelEventRouting) {
-transformed_point.y() + 15);
wheel_event.delta_x = -16;
wheel_event.delta_y = -17;
+ if (root_view->wheel_scroll_latching_enabled())
+ wheel_event.phase = blink::WebMouseWheelEvent::kPhaseBegan;
// We use root_view intentionally as the RenderWidgetHostInputEventRouter is
// responsible for correctly routing the event to the child frame.
router->RouteMouseWheelEvent(root_view, &wheel_event, ui::LatencyInfo());
diff --git a/chromium/content/browser/posix_file_descriptor_info_impl.cc b/chromium/content/browser/posix_file_descriptor_info_impl.cc
new file mode 100644
index 00000000000..50639bd7e7c
--- /dev/null
+++ b/chromium/content/browser/posix_file_descriptor_info_impl.cc
@@ -0,0 +1,111 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/posix_file_descriptor_info_impl.h"
+
+#include <utility>
+
+#include "base/memory/ptr_util.h"
+#include "base/stl_util.h"
+
+namespace content {
+
+// static
+std::unique_ptr<PosixFileDescriptorInfo> PosixFileDescriptorInfoImpl::Create() {
+ return std::unique_ptr<PosixFileDescriptorInfo>(
+ new PosixFileDescriptorInfoImpl());
+}
+
+PosixFileDescriptorInfoImpl::PosixFileDescriptorInfoImpl() {}
+
+PosixFileDescriptorInfoImpl::~PosixFileDescriptorInfoImpl() {}
+
+void PosixFileDescriptorInfoImpl::Share(int id, base::PlatformFile fd) {
+ ShareWithRegion(id, fd, base::MemoryMappedFile::Region::kWholeFile);
+}
+
+void PosixFileDescriptorInfoImpl::ShareWithRegion(
+ int id,
+ base::PlatformFile fd,
+ const base::MemoryMappedFile::Region& region) {
+ AddToMapping(id, fd, region);
+}
+
+void PosixFileDescriptorInfoImpl::Transfer(int id, base::ScopedFD fd) {
+ AddToMapping(id, fd.get(), base::MemoryMappedFile::Region::kWholeFile);
+ owned_descriptors_.push_back(std::move(fd));
+}
+
+base::PlatformFile PosixFileDescriptorInfoImpl::GetFDAt(size_t i) const {
+ return mapping_[i].first;
+}
+
+int PosixFileDescriptorInfoImpl::GetIDAt(size_t i) const {
+ return mapping_[i].second;
+}
+
+const base::MemoryMappedFile::Region& PosixFileDescriptorInfoImpl::GetRegionAt(
+ size_t i) const {
+ auto iter = ids_to_regions_.find(GetIDAt(i));
+ return (iter != ids_to_regions_.end())
+ ? iter->second
+ : base::MemoryMappedFile::Region::kWholeFile;
+}
+
+size_t PosixFileDescriptorInfoImpl::GetMappingSize() const {
+ return mapping_.size();
+}
+
+bool PosixFileDescriptorInfoImpl::HasID(int id) const {
+ for (unsigned i = 0; i < mapping_.size(); ++i) {
+ if (mapping_[i].second == id)
+ return true;
+ }
+
+ return false;
+}
+
+bool PosixFileDescriptorInfoImpl::OwnsFD(base::PlatformFile file) const {
+ return base::ContainsValue(owned_descriptors_, file);
+}
+
+base::ScopedFD PosixFileDescriptorInfoImpl::ReleaseFD(base::PlatformFile file) {
+ DCHECK(OwnsFD(file));
+
+ base::ScopedFD fd;
+ auto found =
+ std::find(owned_descriptors_.begin(), owned_descriptors_.end(), file);
+
+ std::swap(*found, fd);
+ owned_descriptors_.erase(found);
+
+ return fd;
+}
+
+void PosixFileDescriptorInfoImpl::AddToMapping(
+ int id,
+ base::PlatformFile fd,
+ const base::MemoryMappedFile::Region& region) {
+ DCHECK(!HasID(id));
+ mapping_.push_back(std::make_pair(fd, id));
+ if (region != base::MemoryMappedFile::Region::kWholeFile)
+ ids_to_regions_[id] = region;
+}
+
+const base::FileHandleMappingVector& PosixFileDescriptorInfoImpl::GetMapping()
+ const {
+ return mapping_;
+}
+
+base::FileHandleMappingVector
+PosixFileDescriptorInfoImpl::GetMappingWithIDAdjustment(int delta) const {
+ base::FileHandleMappingVector result(mapping_);
+
+ // Adding delta to each ID.
+ for (size_t i = 0; i < result.size(); ++i)
+ result[i].second += delta;
+ return result;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/file_descriptor_info_impl.h b/chromium/content/browser/posix_file_descriptor_info_impl.h
index a1a70850c9d..fd44ae1e4c8 100644
--- a/chromium/content/browser/file_descriptor_info_impl.h
+++ b/chromium/content/browser/posix_file_descriptor_info_impl.h
@@ -13,21 +13,22 @@
#include "base/files/memory_mapped_file.h"
#include "content/common/content_export.h"
-#include "content/public/browser/file_descriptor_info.h"
+#include "content/public/browser/posix_file_descriptor_info.h"
namespace content {
-class FileDescriptorInfoImpl : public FileDescriptorInfo {
+class PosixFileDescriptorInfoImpl : public PosixFileDescriptorInfo {
public:
- CONTENT_EXPORT static std::unique_ptr<FileDescriptorInfo> Create();
+ CONTENT_EXPORT static std::unique_ptr<PosixFileDescriptorInfo> Create();
- ~FileDescriptorInfoImpl() override;
+ ~PosixFileDescriptorInfoImpl() override;
void Share(int id, base::PlatformFile fd) override;
- void ShareWithRegion(int id, base::PlatformFile fd,
- const base::MemoryMappedFile::Region& region) override;
+ void ShareWithRegion(int id,
+ base::PlatformFile fd,
+ const base::MemoryMappedFile::Region& region) override;
void Transfer(int id, base::ScopedFD fd) override;
const base::FileHandleMappingVector& GetMapping() const override;
- std::unique_ptr<base::FileHandleMappingVector> GetMappingWithIDAdjustment(
+ base::FileHandleMappingVector GetMappingWithIDAdjustment(
int delta) const override;
base::PlatformFile GetFDAt(size_t i) const override;
int GetIDAt(size_t i) const override;
@@ -37,10 +38,11 @@ class FileDescriptorInfoImpl : public FileDescriptorInfo {
base::ScopedFD ReleaseFD(base::PlatformFile file) override;
private:
- FileDescriptorInfoImpl();
+ PosixFileDescriptorInfoImpl();
- void AddToMapping(int id, base::PlatformFile fd,
- const base::MemoryMappedFile::Region& region);
+ void AddToMapping(int id,
+ base::PlatformFile fd,
+ const base::MemoryMappedFile::Region& region);
bool HasID(int id) const;
base::FileHandleMappingVector mapping_;
// Maps the ID of a FD to the region to use for that FD, the whole file if not
@@ -48,6 +50,6 @@ class FileDescriptorInfoImpl : public FileDescriptorInfo {
std::map<int, base::MemoryMappedFile::Region> ids_to_regions_;
std::vector<base::ScopedFD> owned_descriptors_;
};
-}
+} // namespace content
#endif // CONTENT_BROWSER_FILE_DESCRIPTOR_INFO_IMPL_H_
diff --git a/chromium/content/browser/file_descriptor_info_impl_unittest.cc b/chromium/content/browser/posix_file_descriptor_info_impl_unittest.cc
index 1d442f79682..0500d036585 100644
--- a/chromium/content/browser/file_descriptor_info_impl_unittest.cc
+++ b/chromium/content/browser/posix_file_descriptor_info_impl_unittest.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/browser/file_descriptor_info_impl.h"
+#include "content/browser/posix_file_descriptor_info_impl.h"
#include <fcntl.h>
#include <unistd.h>
@@ -22,7 +22,7 @@ int GetSafeFd() {
// Returns true if fd was already closed. Closes fd if not closed.
// TODO(morrita) Merge with things in file_descriptor_set_posix_unittest.cc
bool VerifyClosed(int fd) {
- const int duped = dup(fd);
+ const int duped = HANDLE_EINTR(dup(fd));
if (duped != -1) {
EXPECT_NE(IGNORE_EINTR(close(duped)), -1);
EXPECT_NE(IGNORE_EINTR(close(fd)), -1);
@@ -35,11 +35,12 @@ bool VerifyClosed(int fd) {
namespace content {
-typedef testing::Test FileDescriptorInfoTest;
+typedef testing::Test PosixFileDescriptorInfoTest;
-TEST_F(FileDescriptorInfoTest, Transfer) {
+TEST_F(PosixFileDescriptorInfoTest, Transfer) {
int testingId = 42;
- std::unique_ptr<FileDescriptorInfo> target(FileDescriptorInfoImpl::Create());
+ std::unique_ptr<PosixFileDescriptorInfo> target(
+ PosixFileDescriptorInfoImpl::Create());
base::ScopedFD fd(GetSafeFd());
int raw_fd = fd.get();
@@ -53,9 +54,10 @@ TEST_F(FileDescriptorInfoTest, Transfer) {
ASSERT_TRUE(VerifyClosed(raw_fd));
}
-TEST_F(FileDescriptorInfoTest, Share) {
+TEST_F(PosixFileDescriptorInfoTest, Share) {
int testingId = 42;
- std::unique_ptr<FileDescriptorInfo> target(FileDescriptorInfoImpl::Create());
+ std::unique_ptr<PosixFileDescriptorInfo> target(
+ PosixFileDescriptorInfoImpl::Create());
base::ScopedFD fd(GetSafeFd());
int raw_fd = fd.get();
@@ -69,18 +71,19 @@ TEST_F(FileDescriptorInfoTest, Share) {
ASSERT_TRUE(!VerifyClosed(fd.release()));
}
-TEST_F(FileDescriptorInfoTest, GetMappingWithIDAdjustment) {
+TEST_F(PosixFileDescriptorInfoTest, GetMappingWithIDAdjustment) {
int testingId1 = 42;
int testingId2 = 43;
- std::unique_ptr<FileDescriptorInfo> target(FileDescriptorInfoImpl::Create());
+ std::unique_ptr<PosixFileDescriptorInfo> target(
+ PosixFileDescriptorInfoImpl::Create());
target->Transfer(testingId1, base::ScopedFD(GetSafeFd()));
target->Transfer(testingId2, base::ScopedFD(GetSafeFd()));
- std::unique_ptr<base::FileHandleMappingVector> mapping =
+ base::FileHandleMappingVector mapping =
target->GetMappingWithIDAdjustment(100);
- ASSERT_EQ((*mapping)[0].second, 142);
- ASSERT_EQ((*mapping)[1].second, 143);
+ ASSERT_EQ(mapping[0].second, 142);
+ ASSERT_EQ(mapping[1].second, 143);
}
} // namespace content
diff --git a/chromium/content/browser/ppapi_plugin_process_host.cc b/chromium/content/browser/ppapi_plugin_process_host.cc
index e6556f4bb4c..ccaf14c9484 100644
--- a/chromium/content/browser/ppapi_plugin_process_host.cc
+++ b/chromium/content/browser/ppapi_plugin_process_host.cc
@@ -69,10 +69,6 @@ class PpapiPluginSandboxedProcessLauncherDelegate
~PpapiPluginSandboxedProcessLauncherDelegate() override {}
#if defined(OS_WIN)
- bool ShouldSandbox() override {
- return !is_broker_;
- }
-
bool PreSpawnTarget(sandbox::TargetPolicy* policy) override {
if (is_broker_)
return true;
@@ -119,6 +115,10 @@ class PpapiPluginSandboxedProcessLauncherDelegate
#endif // OS_WIN
SandboxType GetSandboxType() override {
+#if defined(OS_WIN)
+ if (is_broker_)
+ return SANDBOX_TYPE_NO_SANDBOX;
+#endif // OS_WIN
return SANDBOX_TYPE_PPAPI;
}
diff --git a/chromium/content/browser/ppapi_plugin_process_host.h b/chromium/content/browser/ppapi_plugin_process_host.h
index d817d8dcd57..5623114187a 100644
--- a/chromium/content/browser/ppapi_plugin_process_host.h
+++ b/chromium/content/browser/ppapi_plugin_process_host.h
@@ -26,7 +26,6 @@
namespace content {
class BrowserChildProcessHostImpl;
-class ResourceContext;
struct PepperPluginInfo;
// Process host for PPAPI plugin and broker processes.
@@ -60,10 +59,6 @@ class PpapiPluginProcessHost : public BrowserChildProcessHostDelegate,
};
class PluginClient : public Client {
- public:
- // Returns the resource context for the renderer requesting the channel.
- virtual ResourceContext* GetResourceContext() = 0;
-
protected:
~PluginClient() override {}
};
diff --git a/chromium/content/browser/presentation/presentation_service_impl.cc b/chromium/content/browser/presentation/presentation_service_impl.cc
index d64d6141058..0cc6c1432f5 100644
--- a/chromium/content/browser/presentation/presentation_service_impl.cc
+++ b/chromium/content/browser/presentation/presentation_service_impl.cc
@@ -13,6 +13,7 @@
#include "base/stl_util.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/navigation_handle.h"
+#include "content/public/browser/presentation_request.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h"
@@ -49,6 +50,7 @@ PresentationServiceImpl::PresentationServiceImpl(
ControllerPresentationServiceDelegate* controller_delegate,
ReceiverPresentationServiceDelegate* receiver_delegate)
: WebContentsObserver(web_contents),
+ render_frame_host_(render_frame_host),
controller_delegate_(controller_delegate),
receiver_delegate_(receiver_delegate),
start_presentation_request_id_(kInvalidRequestId),
@@ -180,8 +182,11 @@ void PresentationServiceImpl::StartPresentation(
start_presentation_request_id_ = GetNextRequestId();
pending_start_presentation_cb_.reset(
new NewPresentationCallbackWrapper(std::move(callback)));
+ PresentationRequest request({render_process_id_, render_frame_id_},
+ presentation_urls,
+ render_frame_host_->GetLastCommittedOrigin());
controller_delegate_->StartPresentation(
- render_process_id_, render_frame_id_, presentation_urls,
+ request,
base::Bind(&PresentationServiceImpl::OnStartPresentationSucceeded,
weak_factory_.GetWeakPtr(), start_presentation_request_id_),
base::Bind(&PresentationServiceImpl::OnStartPresentationError,
@@ -190,7 +195,7 @@ void PresentationServiceImpl::StartPresentation(
void PresentationServiceImpl::ReconnectPresentation(
const std::vector<GURL>& presentation_urls,
- const base::Optional<std::string>& presentation_id,
+ const std::string& presentation_id,
NewPresentationCallback callback) {
DVLOG(2) << "ReconnectPresentation";
if (!controller_delegate_) {
@@ -206,9 +211,12 @@ void PresentationServiceImpl::ReconnectPresentation(
InvokeNewPresentationCallbackWithError(std::move(callback));
return;
}
+
+ PresentationRequest request({render_process_id_, render_frame_id_},
+ presentation_urls,
+ render_frame_host_->GetLastCommittedOrigin());
controller_delegate_->ReconnectPresentation(
- render_process_id_, render_frame_id_, presentation_urls,
- presentation_id.value_or(std::string()),
+ request, presentation_id,
base::Bind(&PresentationServiceImpl::OnReconnectPresentationSucceeded,
weak_factory_.GetWeakPtr(), request_id),
base::Bind(&PresentationServiceImpl::OnReconnectPresentationError,
@@ -304,8 +312,11 @@ void PresentationServiceImpl::SetDefaultPresentationUrls(
return;
default_presentation_urls_ = presentation_urls;
+ PresentationRequest request({render_process_id_, render_frame_id_},
+ presentation_urls,
+ render_frame_host_->GetLastCommittedOrigin());
controller_delegate_->SetDefaultPresentationUrls(
- render_process_id_, render_frame_id_, presentation_urls,
+ request,
base::Bind(&PresentationServiceImpl::OnDefaultPresentationStarted,
weak_factory_.GetWeakPtr()));
}
@@ -488,8 +499,12 @@ PresentationServiceImpl::NewPresentationCallbackWrapper::
PresentationServiceImpl::NewPresentationCallbackWrapper::
~NewPresentationCallbackWrapper() {
- if (!callback_.is_null())
- InvokeNewPresentationCallbackWithError(std::move(callback_));
+ if (!callback_.is_null()) {
+ std::move(callback_).Run(
+ base::nullopt,
+ PresentationError(PRESENTATION_ERROR_PRESENTATION_REQUEST_CANCELLED,
+ "The frame is navigating or being destroyed."));
+ }
}
void PresentationServiceImpl::NewPresentationCallbackWrapper::Run(
diff --git a/chromium/content/browser/presentation/presentation_service_impl.h b/chromium/content/browser/presentation/presentation_service_impl.h
index 41010426c2b..8941157754d 100644
--- a/chromium/content/browser/presentation/presentation_service_impl.h
+++ b/chromium/content/browser/presentation/presentation_service_impl.h
@@ -43,7 +43,7 @@ class RenderFrameHost;
// This class is instantiated on-demand via Mojo's ConnectToRemoteService
// from the renderer when the first presentation API request is handled.
class CONTENT_EXPORT PresentationServiceImpl
- : public NON_EXPORTED_BASE(blink::mojom::PresentationService),
+ : public blink::mojom::PresentationService,
public WebContentsObserver,
public PresentationServiceDelegate::Observer {
public:
@@ -69,7 +69,7 @@ class CONTENT_EXPORT PresentationServiceImpl
void StartPresentation(const std::vector<GURL>& presentation_urls,
NewPresentationCallback callback) override;
void ReconnectPresentation(const std::vector<GURL>& presentation_urls,
- const base::Optional<std::string>& presentation_id,
+ const std::string& presentation_id,
NewPresentationCallback callback) override;
void CloseConnection(const GURL& presentation_url,
const std::string& presentation_id) override;
@@ -238,6 +238,9 @@ class CONTENT_EXPORT PresentationServiceImpl
// |receiver_delegate| if current frame is receiver frame.
PresentationServiceDelegate* GetPresentationServiceDelegate();
+ // The RenderFrameHost associated with this object.
+ RenderFrameHost* const render_frame_host_;
+
// Embedder-specific delegate for controller to forward Presentation requests
// to. Must be nullptr if current page is receiver page or
// embedder does not support Presentation API .
diff --git a/chromium/content/browser/presentation/presentation_service_impl_unittest.cc b/chromium/content/browser/presentation/presentation_service_impl_unittest.cc
index 536817a4b7e..d3c5a14bf33 100644
--- a/chromium/content/browser/presentation/presentation_service_impl_unittest.cc
+++ b/chromium/content/browser/presentation/presentation_service_impl_unittest.cc
@@ -16,6 +16,7 @@
#include "base/run_loop.h"
#include "base/test/mock_callback.h"
#include "content/public/browser/navigation_handle.h"
+#include "content/public/browser/presentation_request.h"
#include "content/public/browser/presentation_service_delegate.h"
#include "content/public/common/presentation_connection_message.h"
#include "content/public/common/presentation_info.h"
@@ -46,6 +47,10 @@ MATCHER(OptionalIsNull, "") {
return !arg;
}
+MATCHER_P(PresentationUrlsAre, expected_urls, "") {
+ return arg.presentation_urls == expected_urls;
+}
+
// Matches content::PresentationInfo.
MATCHER_P(InfoEquals, expected, "") {
return expected.presentation_url == arg.presentation_url &&
@@ -97,42 +102,30 @@ class MockPresentationServiceDelegate
MOCK_METHOD2(Reset,
void(int render_process_id,
int routing_id));
- MOCK_METHOD4(SetDefaultPresentationUrls,
- void(int render_process_id,
- int routing_id,
- const std::vector<GURL>& default_presentation_urls,
+ MOCK_METHOD2(SetDefaultPresentationUrls,
+ void(const PresentationRequest& request,
DefaultPresentationConnectionCallback callback));
// TODO(crbug.com/729950): Use MOCK_METHOD directly once GMock gets the
// move-only type support.
- void StartPresentation(int render_process_id,
- int render_frame_id,
- const std::vector<GURL>& presentation_urls,
+ void StartPresentation(const PresentationRequest& request,
PresentationConnectionCallback success_cb,
PresentationConnectionErrorCallback error_cb) {
- StartPresentationInternal(render_process_id, render_frame_id,
- presentation_urls, success_cb, error_cb);
+ StartPresentationInternal(request, success_cb, error_cb);
}
- MOCK_METHOD5(StartPresentationInternal,
- void(int render_process_id,
- int render_frame_id,
- const std::vector<GURL>& presentation_urls,
+ MOCK_METHOD3(StartPresentationInternal,
+ void(const PresentationRequest& request,
PresentationConnectionCallback& success_cb,
PresentationConnectionErrorCallback& error_cb));
- void ReconnectPresentation(int render_process_id,
- int render_frame_id,
- const std::vector<GURL>& presentation_urls,
+ void ReconnectPresentation(const PresentationRequest& request,
const std::string& presentation_id,
PresentationConnectionCallback success_cb,
PresentationConnectionErrorCallback error_cb) {
- ReconnectPresentationInternal(render_process_id, render_frame_id,
- presentation_urls, presentation_id,
- success_cb, error_cb);
+ ReconnectPresentationInternal(request, presentation_id, success_cb,
+ error_cb);
}
- MOCK_METHOD6(ReconnectPresentationInternal,
- void(int render_process_id,
- int render_frame_id,
- const std::vector<GURL>& presentation_urls,
+ MOCK_METHOD4(ReconnectPresentationInternal,
+ void(const PresentationRequest& request,
const std::string& presentation_id,
PresentationConnectionCallback& success_cb,
PresentationConnectionErrorCallback& error_cb));
@@ -434,8 +427,8 @@ TEST_F(PresentationServiceImplTest, DelegateFails) {
}
TEST_F(PresentationServiceImplTest, SetDefaultPresentationUrls) {
- EXPECT_CALL(mock_delegate_,
- SetDefaultPresentationUrls(_, _, presentation_urls_, _))
+ EXPECT_CALL(mock_delegate_, SetDefaultPresentationUrls(
+ PresentationUrlsAre(presentation_urls_), _))
.Times(1);
service_impl_->SetDefaultPresentationUrls(presentation_urls_);
@@ -445,8 +438,9 @@ TEST_F(PresentationServiceImplTest, SetDefaultPresentationUrls) {
more_urls.push_back(presentation_url3_);
PresentationConnectionCallback callback;
- EXPECT_CALL(mock_delegate_, SetDefaultPresentationUrls(_, _, more_urls, _))
- .WillOnce(SaveArgByMove<3>(&callback));
+ EXPECT_CALL(mock_delegate_,
+ SetDefaultPresentationUrls(PresentationUrlsAre(more_urls), _))
+ .WillOnce(SaveArgByMove<1>(&callback));
service_impl_->SetDefaultPresentationUrls(more_urls);
PresentationInfo presentation_info(presentation_url2_, kPresentationId);
@@ -470,9 +464,7 @@ TEST_F(PresentationServiceImplTest,
service_impl_.reset(
new PresentationServiceImpl(rfh, contents(), &mock_delegate_, nullptr));
- EXPECT_CALL(mock_delegate_,
- SetDefaultPresentationUrls(_, _, presentation_urls_, _))
- .Times(0);
+ EXPECT_CALL(mock_delegate_, SetDefaultPresentationUrls(_, _)).Times(0);
service_impl_->SetDefaultPresentationUrls(presentation_urls_);
}
@@ -518,9 +510,7 @@ TEST_F(PresentationServiceImplTest, ListenForConnectionClose) {
}
TEST_F(PresentationServiceImplTest, SetSameDefaultPresentationUrls) {
- EXPECT_CALL(mock_delegate_,
- SetDefaultPresentationUrls(_, _, presentation_urls_, _))
- .Times(1);
+ EXPECT_CALL(mock_delegate_, SetDefaultPresentationUrls(_, _)).Times(1);
service_impl_->SetDefaultPresentationUrls(presentation_urls_);
EXPECT_TRUE(Mock::VerifyAndClearExpectations(&mock_delegate_));
@@ -532,9 +522,8 @@ TEST_F(PresentationServiceImplTest, SetSameDefaultPresentationUrls) {
TEST_F(PresentationServiceImplTest, StartPresentationSuccess) {
base::MockCallback<NewPresentationCallback> mock_presentation_cb;
base::OnceCallback<void(const PresentationInfo&)> success_cb;
- EXPECT_CALL(mock_delegate_,
- StartPresentationInternal(_, _, presentation_urls_, _, _))
- .WillOnce(SaveArgByMove<3>(&success_cb));
+ EXPECT_CALL(mock_delegate_, StartPresentationInternal(_, _, _))
+ .WillOnce(SaveArgByMove<1>(&success_cb));
service_impl_->StartPresentation(presentation_urls_,
mock_presentation_cb.Get());
EXPECT_FALSE(success_cb.is_null());
@@ -548,9 +537,8 @@ TEST_F(PresentationServiceImplTest, StartPresentationSuccess) {
TEST_F(PresentationServiceImplTest, StartPresentationError) {
base::MockCallback<NewPresentationCallback> mock_presentation_cb;
base::OnceCallback<void(const PresentationError&)> error_cb;
- EXPECT_CALL(mock_delegate_,
- StartPresentationInternal(_, _, presentation_urls_, _, _))
- .WillOnce(SaveArgByMove<4>(&error_cb));
+ EXPECT_CALL(mock_delegate_, StartPresentationInternal(_, _, _))
+ .WillOnce(SaveArgByMove<2>(&error_cb));
service_impl_->StartPresentation(presentation_urls_,
mock_presentation_cb.Get());
EXPECT_FALSE(error_cb.is_null());
@@ -560,9 +548,7 @@ TEST_F(PresentationServiceImplTest, StartPresentationError) {
}
TEST_F(PresentationServiceImplTest, StartPresentationInProgress) {
- EXPECT_CALL(mock_delegate_,
- StartPresentationInternal(_, _, presentation_urls_, _, _))
- .Times(1);
+ EXPECT_CALL(mock_delegate_, StartPresentationInternal(_, _, _)).Times(1);
// Uninvoked callbacks must outlive |service_impl_| since they get invoked
// at |service_impl_|'s destruction.
service_impl_->StartPresentation(presentation_urls_, base::Bind(&DoNothing));
@@ -579,12 +565,10 @@ TEST_F(PresentationServiceImplTest, ReconnectPresentationSuccess) {
base::MockCallback<NewPresentationCallback> mock_presentation_cb;
base::OnceCallback<void(const PresentationInfo&)> success_cb;
EXPECT_CALL(mock_delegate_,
- ReconnectPresentationInternal(_, _, presentation_urls_,
- kPresentationId, _, _))
- .WillOnce(SaveArgByMove<4>(&success_cb));
- service_impl_->ReconnectPresentation(
- presentation_urls_, base::Optional<std::string>(kPresentationId),
- mock_presentation_cb.Get());
+ ReconnectPresentationInternal(_, kPresentationId, _, _))
+ .WillOnce(SaveArgByMove<2>(&success_cb));
+ service_impl_->ReconnectPresentation(presentation_urls_, kPresentationId,
+ mock_presentation_cb.Get());
EXPECT_FALSE(success_cb.is_null());
EXPECT_CALL(mock_delegate_, ListenForConnectionStateChange(_, _, _, _))
.Times(1);
@@ -597,12 +581,10 @@ TEST_F(PresentationServiceImplTest, ReconnectPresentationError) {
base::MockCallback<NewPresentationCallback> mock_presentation_cb;
base::OnceCallback<void(const PresentationError&)> error_cb;
EXPECT_CALL(mock_delegate_,
- ReconnectPresentationInternal(_, _, presentation_urls_,
- kPresentationId, _, _))
- .WillOnce(SaveArgByMove<5>(&error_cb));
- service_impl_->ReconnectPresentation(
- presentation_urls_, base::Optional<std::string>(kPresentationId),
- mock_presentation_cb.Get());
+ ReconnectPresentationInternal(_, kPresentationId, _, _))
+ .WillOnce(SaveArgByMove<3>(&error_cb));
+ service_impl_->ReconnectPresentation(presentation_urls_, kPresentationId,
+ mock_presentation_cb.Get());
EXPECT_FALSE(error_cb.is_null());
EXPECT_CALL(mock_presentation_cb, Run(OptionalIsNull(), OptionalIsNotNull()));
std::move(error_cb).Run(
@@ -614,7 +596,7 @@ TEST_F(PresentationServiceImplTest, MaxPendingReconnectPresentationRequests) {
const char* presentation_id = "presentationId%d";
int num_requests = PresentationServiceImpl::kMaxQueuedRequests;
int i = 0;
- EXPECT_CALL(mock_delegate_, ReconnectPresentationInternal(_, _, _, _, _, _))
+ EXPECT_CALL(mock_delegate_, ReconnectPresentationInternal(_, _, _, _))
.Times(num_requests);
for (; i < num_requests; ++i) {
std::vector<GURL> urls = {GURL(base::StringPrintf(presentation_url, i))};
diff --git a/chromium/content/browser/push_messaging/push_messaging_router.cc b/chromium/content/browser/push_messaging/push_messaging_router.cc
index 7f87b2867a5..07484feabe6 100644
--- a/chromium/content/browser/push_messaging/push_messaging_router.cc
+++ b/chromium/content/browser/push_messaging/push_messaging_router.cc
@@ -104,9 +104,9 @@ void PushMessagingRouter::FindServiceWorkerRegistrationCallback(
// service worker.
version->RunAfterStartWorker(
ServiceWorkerMetrics::EventType::PUSH,
- base::Bind(&PushMessagingRouter::DeliverMessageToWorker,
- make_scoped_refptr(version), service_worker_registration,
- payload, deliver_message_callback),
+ base::BindOnce(&PushMessagingRouter::DeliverMessageToWorker,
+ make_scoped_refptr(version), service_worker_registration,
+ payload, deliver_message_callback),
base::Bind(&PushMessagingRouter::DeliverMessageEnd,
deliver_message_callback, service_worker_registration));
}
diff --git a/chromium/content/browser/quota_dispatcher_host.h b/chromium/content/browser/quota_dispatcher_host.h
index fbb60d5376d..8aebb6e044d 100644
--- a/chromium/content/browser/quota_dispatcher_host.h
+++ b/chromium/content/browser/quota_dispatcher_host.h
@@ -5,7 +5,7 @@
#ifndef CONTENT_BROWSER_QUOTA_DISPATCHER_HOST_H_
#define CONTENT_BROWSER_QUOTA_DISPATCHER_HOST_H_
-#include "base/id_map.h"
+#include "base/containers/id_map.h"
#include "base/macros.h"
#include "content/public/browser/browser_message_filter.h"
#include "storage/common/quota/quota_types.h"
@@ -52,7 +52,7 @@ class QuotaDispatcherHost : public BrowserMessageFilter {
storage::QuotaManager* quota_manager_;
scoped_refptr<QuotaPermissionContext> permission_context_;
- IDMap<std::unique_ptr<RequestDispatcher>> outstanding_requests_;
+ base::IDMap<std::unique_ptr<RequestDispatcher>> outstanding_requests_;
base::WeakPtrFactory<QuotaDispatcherHost> weak_factory_;
diff --git a/chromium/content/browser/renderer_host/DEPS b/chromium/content/browser/renderer_host/DEPS
index 7a3937947f8..9f9d3a18b5d 100644
--- a/chromium/content/browser/renderer_host/DEPS
+++ b/chromium/content/browser/renderer_host/DEPS
@@ -26,6 +26,9 @@ specific_include_rules = {
],
"render_process_host_impl\.cc": [
"+content/browser/frame_host/render_frame_message_filter.h",
+ # TODO(crbug.com/734668): Dependencies on ozone should be removed, as content
+ # embedded in mus won't be able to talk to the native ozone.
+ "+ui/ozone/public/ozone_switches.h",
],
"render_widget_host_view_mac\.mm": [
"+content/browser/frame_host",
@@ -42,17 +45,13 @@ specific_include_rules = {
"render_widget_host_view_event_handler\.cc": [
"+content/browser/frame_host",
],
- # TODO(kenrb): RenderWidgetHostViewChildFrame should eventually be moved
- # to content/renderer_host, at which time this can be removed.
# RenderWidgetHostViewGuest dependency is needed to allow for routing mouse
# events to the correct owner RenderWidgetHostViewBase. It should be removed
# when all inner WebContents are based on OOPIF structure (as opposed to
# BrowserPlugin).
+ # TODO(kenrb, wjmaclean): Remove this when RenderWidgetHostViewGuest is
+ # deleted. See https://crbug.com/533069.
"render_widget_host_input_event_router.cc": [
- "+content/browser/frame_host/render_widget_host_view_child_frame.h",
"+content/browser/frame_host/render_widget_host_view_guest.h",
],
- "touch_selection_controller_client_child_frame\.cc": [
- "+content/browser/frame_host/render_widget_host_view_child_frame.h",
- ],
}
diff --git a/chromium/content/browser/renderer_host/OWNERS b/chromium/content/browser/renderer_host/OWNERS
index 8a92367d59a..4b9055205a1 100644
--- a/chromium/content/browser/renderer_host/OWNERS
+++ b/chromium/content/browser/renderer_host/OWNERS
@@ -19,6 +19,9 @@ rjkroege@chromium.org
sadrul@chromium.org
tdresser@chromium.org
+# For surface ID propagation and synchronization
+fsamuel@chromium.org
+
# Linux sandboxing
per-file render_sandbox_host_linux.*=jln@chromium.org
per-file render_sandbox_host_linux.*=jorgelo@chromium.org
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 da3c2c764fa..4355a8cdacb 100644
--- a/chromium/content/browser/renderer_host/browser_compositor_view_mac.h
+++ b/chromium/content/browser/renderer_host/browser_compositor_view_mac.h
@@ -8,7 +8,7 @@
#include <memory>
#include "base/macros.h"
-#include "cc/scheduler/begin_frame_source.h"
+#include "components/viz/common/frame_sinks/begin_frame_source.h"
#include "content/browser/renderer_host/delegated_frame_host.h"
#include "ui/compositor/compositor.h"
#include "ui/compositor/compositor_observer.h"
@@ -38,7 +38,7 @@ class BrowserCompositorMacClient {
// is visible.
// - The RenderWidgetHostViewMac that is used to display these frames is
// attached to the NSView hierarchy of an NSWindow.
-class BrowserCompositorMac : public DelegatedFrameHostClient {
+class CONTENT_EXPORT BrowserCompositorMac : public DelegatedFrameHostClient {
public:
BrowserCompositorMac(
ui::AcceleratedWidgetMacNSView* accelerated_widget_mac_ns_view,
@@ -51,15 +51,19 @@ class BrowserCompositorMac : public DelegatedFrameHostClient {
// These will not return nullptr until Destroy is called.
DelegatedFrameHost* GetDelegatedFrameHost();
+ // Ensure that the currect compositor frame be cleared (even if it is
+ // potentially visible).
+ void ClearCompositorFrame();
+
// This may return nullptr, if this has detached itself from its
// ui::Compositor.
ui::AcceleratedWidgetMac* GetAcceleratedWidgetMac();
void DidCreateNewRendererCompositorFrameSink(
- cc::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink);
+ viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink);
void SubmitCompositorFrame(const viz::LocalSurfaceId& local_surface_id,
cc::CompositorFrame frame);
- void OnDidNotProduceFrame(const cc::BeginFrameAck& ack);
+ void OnDidNotProduceFrame(const viz::BeginFrameAck& ack);
void SetHasTransparentBackground(bool transparent);
void SetDisplayColorSpace(const gfx::ColorSpace& color_space);
void UpdateVSyncParameters(const base::TimeTicks& timebase,
@@ -105,6 +109,9 @@ class BrowserCompositorMac : public DelegatedFrameHostClient {
void OnBeginFrame() override;
bool IsAutoResizeEnabled() const override;
+ // Returns nullptr if no compositor is attached.
+ ui::Compositor* CompositorForTesting() const;
+
private:
// The state of |delegated_frame_host_| and |recyclable_compositor_| to
// manage being visible, hidden, or occluded.
@@ -163,7 +170,7 @@ class BrowserCompositorMac : public DelegatedFrameHostClient {
std::unique_ptr<ui::Layer> root_layer_;
bool has_transparent_background_ = false;
- cc::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink_ =
+ viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink_ =
nullptr;
base::WeakPtrFactory<BrowserCompositorMac> weak_factory_;
diff --git a/chromium/content/browser/renderer_host/browser_compositor_view_mac.mm b/chromium/content/browser/renderer_host/browser_compositor_view_mac.mm
index 278c7021a2f..428bef1ff74 100644
--- a/chromium/content/browser/renderer_host/browser_compositor_view_mac.mm
+++ b/chromium/content/browser/renderer_host/browser_compositor_view_mac.mm
@@ -104,7 +104,8 @@ RecyclableCompositorMac::RecyclableCompositorMac()
content::GetContextFactory(),
content::GetContextFactoryPrivate(),
ui::WindowResizeHelperMac::Get()->task_runner(),
- false /* enable_surface_synchronization */) {
+ false /* enable_surface_synchronization */,
+ false /* enable_pixel_canvas */) {
compositor_.SetAcceleratedWidget(
accelerated_widget_mac_->accelerated_widget());
Suspend();
@@ -215,6 +216,17 @@ DelegatedFrameHost* BrowserCompositorMac::GetDelegatedFrameHost() {
return delegated_frame_host_.get();
}
+void BrowserCompositorMac::ClearCompositorFrame() {
+ // Make sure that we no longer hold a compositor lock by un-suspending the
+ // compositor. This ensures that we are able to swap in a new blank frame to
+ // replace any old content.
+ // https://crbug.com/739621
+ if (recyclable_compositor_)
+ recyclable_compositor_->Unsuspend();
+ if (delegated_frame_host_)
+ delegated_frame_host_->ClearDelegatedFrame();
+}
+
void BrowserCompositorMac::CopyCompleted(
base::WeakPtr<BrowserCompositorMac> browser_compositor,
const ReadbackRequestCallback& callback,
@@ -272,7 +284,7 @@ void BrowserCompositorMac::CopyFromCompositingSurfaceToVideoFrame(
}
void BrowserCompositorMac::DidCreateNewRendererCompositorFrameSink(
- cc::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink) {
+ viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink) {
renderer_compositor_frame_sink_ = renderer_compositor_frame_sink;
delegated_frame_host_->DidCreateNewRendererCompositorFrameSink(
renderer_compositor_frame_sink_);
@@ -295,7 +307,7 @@ void BrowserCompositorMac::SubmitCompositorFrame(
std::move(frame));
}
-void BrowserCompositorMac::OnDidNotProduceFrame(const cc::BeginFrameAck& ack) {
+void BrowserCompositorMac::OnDidNotProduceFrame(const viz::BeginFrameAck& ack) {
delegated_frame_host_->DidNotProduceFrame(ack);
}
@@ -449,4 +461,10 @@ bool BrowserCompositorMac::IsAutoResizeEnabled() const {
return false;
}
+ui::Compositor* BrowserCompositorMac::CompositorForTesting() const {
+ if (recyclable_compositor_)
+ return recyclable_compositor_->compositor();
+ return nullptr;
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/clipboard_message_filter.cc b/chromium/content/browser/renderer_host/clipboard_message_filter.cc
index 8187963e5b8..820d44cac39 100644
--- a/chromium/content/browser/renderer_host/clipboard_message_filter.cc
+++ b/chromium/content/browser/renderer_host/clipboard_message_filter.cc
@@ -195,8 +195,8 @@ void ClipboardMessageFilter::ReadAndEncodeImage(const SkBitmap& bitmap,
if (gfx::PNGCodec::FastEncodeBGRASkBitmap(bitmap, false, png_data.get())) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&ClipboardMessageFilter::OnReadAndEncodeImageFinished,
- this, base::Passed(&png_data), reply_msg));
+ base::BindOnce(&ClipboardMessageFilter::OnReadAndEncodeImageFinished,
+ this, base::Passed(&png_data), reply_msg));
return;
}
}
@@ -225,7 +225,7 @@ void ClipboardMessageFilter::OnReadAndEncodeImageFinished(
// timeout to clean up eventually. See https://crbug.com/604800.
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE,
- base::Bind(&CleanupReadImageBlob, base::Passed(&blob_handle)),
+ base::BindOnce(&CleanupReadImageBlob, base::Passed(&blob_handle)),
base::TimeDelta::FromMinutes(1));
return;
}
diff --git a/chromium/content/browser/renderer_host/compositor_impl_android.cc b/chromium/content/browser/renderer_host/compositor_impl_android.cc
index 59202303b46..54fc842c170 100644
--- a/chromium/content/browser/renderer_host/compositor_impl_android.cc
+++ b/chromium/content/browser/renderer_host/compositor_impl_android.cc
@@ -36,14 +36,15 @@
#include "cc/output/output_surface_client.h"
#include "cc/output/output_surface_frame.h"
#include "cc/output/texture_mailbox_deleter.h"
-#include "cc/output/vulkan_in_process_context_provider.h"
#include "cc/raster/single_thread_task_graph_runner.h"
#include "cc/resources/ui_resource_manager.h"
#include "cc/trees/layer_tree_host.h"
#include "cc/trees/layer_tree_settings.h"
#include "components/viz/common/gl_helper.h"
#include "components/viz/common/gpu/context_provider.h"
+#include "components/viz/common/gpu/vulkan_in_process_context_provider.h"
#include "components/viz/common/surfaces/frame_sink_id_allocator.h"
+#include "components/viz/common/switches.h"
#include "components/viz/host/host_frame_sink_manager.h"
#include "components/viz/service/display/display.h"
#include "components/viz/service/display/display_scheduler.h"
@@ -76,6 +77,7 @@
#include "ui/display/screen.h"
#include "ui/gfx/color_space_switches.h"
#include "ui/gfx/swap_result.h"
+#include "ui/gl/gl_utils.h"
namespace gpu {
struct GpuProcessHostedCALayerTreeParamsMac;
@@ -100,9 +102,17 @@ class SingleThreadTaskGraphRunner : public cc::SingleThreadTaskGraphRunner {
struct CompositorDependencies {
CompositorDependencies() : frame_sink_id_allocator(kDefaultClientId) {
+ // TODO(kylechar): Switch this back to kDisableSurfaceReferences.
+ auto surface_lifetime_type =
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
+ "enable-surface-references")
+ ? viz::SurfaceManager::LifetimeType::REFERENCES
+ : viz::SurfaceManager::LifetimeType::SEQUENCES;
+
// TODO(danakj): Don't make a FrameSinkManagerImpl when display is in the
// Gpu process, instead get the mojo pointer from the Gpu process.
- frame_sink_manager_impl = base::MakeUnique<viz::FrameSinkManagerImpl>();
+ frame_sink_manager_impl =
+ std::make_unique<viz::FrameSinkManagerImpl>(surface_lifetime_type);
surface_utils::ConnectWithLocalFrameSinkManager(
&host_frame_sink_manager, frame_sink_manager_impl.get());
}
@@ -118,7 +128,7 @@ struct CompositorDependencies {
std::unique_ptr<viz::FrameSinkManagerImpl> frame_sink_manager_impl;
#if BUILDFLAG(ENABLE_VULKAN)
- scoped_refptr<cc::VulkanContextProvider> vulkan_context_provider;
+ scoped_refptr<viz::VulkanContextProvider> vulkan_context_provider;
#endif
};
@@ -128,13 +138,13 @@ base::LazyInstance<CompositorDependencies>::DestructorAtExit
const unsigned int kMaxDisplaySwapBuffers = 1U;
#if BUILDFLAG(ENABLE_VULKAN)
-scoped_refptr<cc::VulkanContextProvider> GetSharedVulkanContextProvider() {
+scoped_refptr<viz::VulkanContextProvider> GetSharedVulkanContextProvider() {
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableVulkan)) {
- scoped_refptr<cc::VulkanContextProvider> context_provider =
+ scoped_refptr<viz::VulkanContextProvider> context_provider =
g_compositor_dependencies.Get().vulkan_context_provider;
if (!*context_provider)
- *context_provider = cc::VulkanInProcessContextProvider::Create();
+ *context_provider = viz::VulkanInProcessContextProvider::Create();
return *context_provider;
}
return nullptr;
@@ -298,7 +308,8 @@ class AndroidOutputSurface : public cc::OutputSurface {
bool has_alpha,
bool use_stencil) override {
context_provider()->ContextGL()->ResizeCHROMIUM(
- size.width(), size.height(), device_scale_factor, has_alpha);
+ size.width(), size.height(), device_scale_factor,
+ gl::GetGLColorSpace(color_space), has_alpha);
}
cc::OverlayCandidateValidator* GetOverlayCandidateValidator() const override {
@@ -350,7 +361,7 @@ class AndroidOutputSurface : public cc::OutputSurface {
class VulkanOutputSurface : public cc::OutputSurface {
public:
explicit VulkanOutputSurface(
- scoped_refptr<cc::VulkanContextProvider> vulkan_context_provider,
+ scoped_refptr<viz::VulkanContextProvider> vulkan_context_provider,
scoped_refptr<base::SingleThreadTaskRunner> task_runner)
: OutputSurface(std::move(vulkan_context_provider)),
task_runner_(std::move(task_runner)),
@@ -466,7 +477,7 @@ CompositorImpl::CompositorImpl(CompositorClient* client,
num_successive_context_creation_failures_(0),
layer_tree_frame_sink_request_pending_(false),
weak_factory_(this) {
- GetFrameSinkManager()->surface_manager()->RegisterFrameSinkId(frame_sink_id_);
+ GetHostFrameSinkManager()->RegisterFrameSinkId(frame_sink_id_, this);
DCHECK(client);
DCHECK(root_window);
DCHECK(root_window->GetLayer() == nullptr);
@@ -484,8 +495,7 @@ CompositorImpl::~CompositorImpl() {
root_window_->SetLayer(nullptr);
// Clean-up any surface references.
SetSurface(NULL);
- GetFrameSinkManager()->surface_manager()->InvalidateFrameSinkId(
- frame_sink_id_);
+ GetHostFrameSinkManager()->InvalidateFrameSinkId(frame_sink_id_);
}
bool CompositorImpl::IsForSubframe() {
@@ -690,21 +700,24 @@ void CompositorImpl::HandlePendingLayerTreeFrameSinkRequest() {
return;
#endif
+ if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableTimeoutsForProfiling)) {
#if defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER) || \
defined(SYZYASAN) || defined(CYGPROFILE_INSTRUMENTATION)
- const int64_t kGpuChannelTimeoutInSeconds = 40;
+ const int64_t kGpuChannelTimeoutInSeconds = 40;
#else
- // The GPU watchdog timeout is 15 seconds (1.5x the kGpuTimeout value due to
- // logic in GpuWatchdogThread). Make this slightly longer to give the GPU a
- // chance to crash itself before crashing the browser.
- const int64_t kGpuChannelTimeoutInSeconds = 20;
+ // The GPU watchdog timeout is 15 seconds (1.5x the kGpuTimeout value due to
+ // logic in GpuWatchdogThread). Make this slightly longer to give the GPU a
+ // chance to crash itself before crashing the browser.
+ const int64_t kGpuChannelTimeoutInSeconds = 20;
#endif
- // Start the timer first, if the result comes synchronously, we want it to
- // stop in the callback.
- establish_gpu_channel_timeout_.Start(
- FROM_HERE, base::TimeDelta::FromSeconds(kGpuChannelTimeoutInSeconds),
- this, &CompositorImpl::OnGpuChannelTimeout);
+ // Start the timer first, if the result comes synchronously, we want it to
+ // stop in the callback.
+ establish_gpu_channel_timeout_.Start(
+ FROM_HERE, base::TimeDelta::FromSeconds(kGpuChannelTimeoutInSeconds),
+ this, &CompositorImpl::OnGpuChannelTimeout);
+ }
DCHECK(surface_handle_ != gpu::kNullSurfaceHandle);
BrowserMainLoop::GetInstance()
@@ -723,7 +736,7 @@ void CompositorImpl::CreateVulkanOutputSurface() {
switches::kEnableVulkan))
return;
- scoped_refptr<cc::VulkanContextProvider> vulkan_context_provider =
+ scoped_refptr<viz::VulkanContextProvider> vulkan_context_provider =
GetSharedVulkanContextProvider();
if (!vulkan_context_provider)
return;
@@ -801,7 +814,7 @@ void CompositorImpl::OnGpuChannelEstablished(
void CompositorImpl::InitializeDisplay(
std::unique_ptr<cc::OutputSurface> display_output_surface,
- scoped_refptr<cc::VulkanContextProvider> vulkan_context_provider,
+ scoped_refptr<viz::VulkanContextProvider> vulkan_context_provider,
scoped_refptr<viz::ContextProvider> context_provider) {
DCHECK(layer_tree_frame_sink_request_pending_);
@@ -900,7 +913,7 @@ void CompositorImpl::AttachLayerForReadback(scoped_refptr<cc::Layer> layer) {
}
void CompositorImpl::RequestCopyOfOutputOnRootLayer(
- std::unique_ptr<cc::CopyOutputRequest> request) {
+ std::unique_ptr<viz::CopyOutputRequest> request) {
root_window_->GetLayer()->RequestCopyOfOutput(std::move(request));
}
@@ -919,8 +932,8 @@ viz::FrameSinkId CompositorImpl::GetFrameSinkId() {
void CompositorImpl::AddChildFrameSink(const viz::FrameSinkId& frame_sink_id) {
if (has_layer_tree_frame_sink_) {
- GetFrameSinkManager()->RegisterFrameSinkHierarchy(frame_sink_id_,
- frame_sink_id);
+ GetHostFrameSinkManager()->RegisterFrameSinkHierarchy(frame_sink_id_,
+ frame_sink_id);
} else {
pending_child_frame_sink_ids_.insert(frame_sink_id);
}
@@ -933,8 +946,14 @@ void CompositorImpl::RemoveChildFrameSink(
pending_child_frame_sink_ids_.erase(it);
return;
}
- GetFrameSinkManager()->UnregisterFrameSinkHierarchy(frame_sink_id_,
- frame_sink_id);
+ GetHostFrameSinkManager()->UnregisterFrameSinkHierarchy(frame_sink_id_,
+ frame_sink_id);
+}
+
+void CompositorImpl::OnFirstSurfaceActivation(
+ const viz::SurfaceInfo& surface_info) {
+ // TODO(fsamuel): Once surface synchronization is turned on, the fallback
+ // surface should be set here.
}
bool CompositorImpl::HavePendingReadbacks() {
diff --git a/chromium/content/browser/renderer_host/compositor_impl_android.h b/chromium/content/browser/renderer_host/compositor_impl_android.h
index 8cdbe19083a..f04a6ffe0b9 100644
--- a/chromium/content/browser/renderer_host/compositor_impl_android.h
+++ b/chromium/content/browser/renderer_host/compositor_impl_android.h
@@ -18,6 +18,7 @@
#include "cc/trees/layer_tree_host_client.h"
#include "cc/trees/layer_tree_host_single_thread_client.h"
#include "components/viz/common/surfaces/frame_sink_id.h"
+#include "components/viz/host/host_frame_sink_client.h"
#include "content/common/content_export.h"
#include "content/public/browser/android/compositor.h"
#include "gpu/command_buffer/common/capabilities.h"
@@ -36,7 +37,6 @@ class AnimationHost;
class Layer;
class LayerTreeHost;
class OutputSurface;
-class VulkanContextProvider;
}
namespace viz {
@@ -44,6 +44,7 @@ class Display;
class FrameSinkId;
class FrameSinkManagerImpl;
class HostFrameSinkManager;
+class VulkanContextProvider;
}
namespace content {
@@ -57,7 +58,8 @@ class CONTENT_EXPORT CompositorImpl
public cc::LayerTreeHostClient,
public cc::LayerTreeHostSingleThreadClient,
public ui::UIResourceProvider,
- public ui::WindowAndroidCompositor {
+ public ui::WindowAndroidCompositor,
+ public viz::HostFrameSinkClient {
public:
CompositorImpl(CompositorClient* client, gfx::NativeWindow root_window);
~CompositorImpl() override;
@@ -87,7 +89,7 @@ class CONTENT_EXPORT CompositorImpl
// LayerTreeHostClient implementation.
void WillBeginMainFrame() override {}
void DidBeginMainFrame() override {}
- void BeginMainFrame(const cc::BeginFrameArgs& args) override {}
+ void BeginMainFrame(const viz::BeginFrameArgs& args) override {}
void BeginMainFrameNotExpectedSoon() override {}
void BeginMainFrameNotExpectedUntil(base::TimeTicks time) override {}
void UpdateLayerTreeHost() override;
@@ -115,12 +117,15 @@ class CONTENT_EXPORT CompositorImpl
// WindowAndroidCompositor implementation.
void AttachLayerForReadback(scoped_refptr<cc::Layer> layer) override;
void RequestCopyOfOutputOnRootLayer(
- std::unique_ptr<cc::CopyOutputRequest> request) override;
+ std::unique_ptr<viz::CopyOutputRequest> request) override;
void SetNeedsAnimate() override;
viz::FrameSinkId GetFrameSinkId() override;
void AddChildFrameSink(const viz::FrameSinkId& frame_sink_id) override;
void RemoveChildFrameSink(const viz::FrameSinkId& frame_sink_id) override;
+ // viz::HostFrameSinkClient implementation.
+ void OnFirstSurfaceActivation(const viz::SurfaceInfo& surface_info) override;
+
void SetVisible(bool visible);
void CreateLayerTreeHost();
@@ -134,7 +139,7 @@ class CONTENT_EXPORT CompositorImpl
void OnGpuChannelTimeout();
void InitializeDisplay(
std::unique_ptr<cc::OutputSurface> display_output_surface,
- scoped_refptr<cc::VulkanContextProvider> vulkan_context_provider,
+ scoped_refptr<viz::VulkanContextProvider> vulkan_context_provider,
scoped_refptr<viz::ContextProvider> context_provider);
void DidSwapBuffers();
diff --git a/chromium/content/browser/renderer_host/compositor_resize_lock.h b/chromium/content/browser/renderer_host/compositor_resize_lock.h
index 4e5a17b4c00..eab4c0b955e 100644
--- a/chromium/content/browser/renderer_host/compositor_resize_lock.h
+++ b/chromium/content/browser/renderer_host/compositor_resize_lock.h
@@ -30,8 +30,7 @@ class CompositorResizeLockClient {
};
// Used to prevent further resizes while a resize is pending.
-class CONTENT_EXPORT CompositorResizeLock
- : NON_EXPORTED_BASE(public ui::CompositorLockClient) {
+class CONTENT_EXPORT CompositorResizeLock : public ui::CompositorLockClient {
public:
CompositorResizeLock(CompositorResizeLockClient* client,
const gfx::Size& new_size);
diff --git a/chromium/content/browser/renderer_host/compositor_resize_lock_unittest.cc b/chromium/content/browser/renderer_host/compositor_resize_lock_unittest.cc
index 5199b3db716..9416bd894bd 100644
--- a/chromium/content/browser/renderer_host/compositor_resize_lock_unittest.cc
+++ b/chromium/content/browser/renderer_host/compositor_resize_lock_unittest.cc
@@ -13,9 +13,8 @@
namespace content {
namespace {
-class FakeCompositorResizeLockClient
- : public CompositorResizeLockClient,
- public NON_EXPORTED_BASE(ui::CompositorLockDelegate) {
+class FakeCompositorResizeLockClient : public CompositorResizeLockClient,
+ public ui::CompositorLockDelegate {
public:
FakeCompositorResizeLockClient() : weak_ptr_factory_(this) {}
diff --git a/chromium/content/browser/renderer_host/cursor_manager_unittest.cc b/chromium/content/browser/renderer_host/cursor_manager_unittest.cc
index e5229729cdc..86ed91c4bc9 100644
--- a/chromium/content/browser/renderer_host/cursor_manager_unittest.cc
+++ b/chromium/content/browser/renderer_host/cursor_manager_unittest.cc
@@ -13,6 +13,8 @@
#include "content/public/common/cursor_info.h"
#include "content/public/test/mock_render_process_host.h"
#include "content/public/test/test_browser_context.h"
+#include "content/test/dummy_render_widget_host_delegate.h"
+#include "content/test/mock_widget_impl.h"
#include "content/test/test_render_view_host.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -23,24 +25,6 @@ namespace content {
namespace {
-// TODO(kenrb): This mock is implemented in several unit test files, and
-// could be moved into a common header.
-class MockRenderWidgetHostDelegate : public RenderWidgetHostDelegate {
- public:
- MockRenderWidgetHostDelegate() {}
- ~MockRenderWidgetHostDelegate() override {}
-
- private:
- // RenderWidgetHostDelegate:
- void ExecuteEditCommand(
- const std::string& command,
- const base::Optional<base::string16>& value) override {}
- void Cut() override {}
- void Copy() override {}
- void Paste() override {}
- void SelectAll() override {}
-};
-
class MockRenderWidgetHostViewForCursors : public TestRenderWidgetHostView {
public:
MockRenderWidgetHostViewForCursors(RenderWidgetHost* host, bool top_view)
@@ -62,6 +46,37 @@ class MockRenderWidgetHostViewForCursors : public TestRenderWidgetHostView {
std::unique_ptr<CursorManager> cursor_manager_;
};
+class MockRenderWidgetHost : public RenderWidgetHostImpl {
+ public:
+ static MockRenderWidgetHost* Create(RenderWidgetHostDelegate* delegate,
+ RenderProcessHost* process,
+ int32_t routing_id) {
+ mojom::WidgetPtr widget;
+ std::unique_ptr<MockWidgetImpl> widget_impl =
+ base::MakeUnique<MockWidgetImpl>(mojo::MakeRequest(&widget));
+
+ return new MockRenderWidgetHost(delegate, process, routing_id,
+ std::move(widget_impl), std::move(widget));
+ }
+
+ private:
+ MockRenderWidgetHost(RenderWidgetHostDelegate* delegate,
+ RenderProcessHost* process,
+ int routing_id,
+ std::unique_ptr<MockWidgetImpl> widget_impl,
+ mojom::WidgetPtr widget)
+ : RenderWidgetHostImpl(delegate,
+ process,
+ routing_id,
+ std::move(widget),
+ false),
+ widget_impl_(std::move(widget_impl)) {}
+
+ std::unique_ptr<MockWidgetImpl> widget_impl_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockRenderWidgetHost);
+};
+
class CursorManagerTest : public testing::Test {
public:
CursorManagerTest()
@@ -78,8 +93,8 @@ class CursorManagerTest : public testing::Test {
RenderWidgetHostImpl* MakeNewWidgetHost() {
int32_t routing_id = process_host_->GetNextRoutingID();
- return new RenderWidgetHostImpl(&delegate_, process_host_.get(), routing_id,
- false);
+ return MockRenderWidgetHost::Create(&delegate_, process_host_.get(),
+ routing_id);
}
void TearDown() override {
@@ -101,7 +116,7 @@ class CursorManagerTest : public testing::Test {
// destruction.
MockRenderWidgetHostViewForCursors* top_view_;
- MockRenderWidgetHostDelegate delegate_;
+ DummyRenderWidgetHostDelegate delegate_;
private:
DISALLOW_COPY_AND_ASSIGN(CursorManagerTest);
@@ -209,4 +224,4 @@ TEST_F(CursorManagerTest, CursorOverMultipleChildViews) {
} // namespace content
-#endif // defined(USE_AURA) || defined(OS_MACOSX) \ No newline at end of file
+#endif // defined(USE_AURA) || defined(OS_MACOSX)
diff --git a/chromium/content/browser/renderer_host/database_message_filter.cc b/chromium/content/browser/renderer_host/database_message_filter.cc
index e18edde71e2..193db77a78c 100644
--- a/chromium/content/browser/renderer_host/database_message_filter.cc
+++ b/chromium/content/browser/renderer_host/database_message_filter.cc
@@ -59,19 +59,19 @@ DatabaseMessageFilter::DatabaseMessageFilter(
void DatabaseMessageFilter::OnChannelClosing() {
if (observer_added_) {
observer_added_ = false;
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- base::Bind(&DatabaseMessageFilter::RemoveObserver, this));
+ db_tracker_->task_runner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&DatabaseMessageFilter::RemoveObserver, this));
}
}
void DatabaseMessageFilter::AddObserver() {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence());
db_tracker_->AddObserver(this);
}
void DatabaseMessageFilter::RemoveObserver() {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence());
db_tracker_->RemoveObserver(this);
// If the renderer process died without closing all databases,
@@ -80,20 +80,23 @@ void DatabaseMessageFilter::RemoveObserver() {
database_connections_.RemoveAllConnections();
}
-void DatabaseMessageFilter::OverrideThreadForMessage(
- const IPC::Message& message,
- BrowserThread::ID* thread) {
- if (message.type() == DatabaseHostMsg_GetSpaceAvailable::ID)
- *thread = BrowserThread::IO;
- else if (IPC_MESSAGE_CLASS(message) == DatabaseMsgStart)
- *thread = BrowserThread::FILE;
-
+base::TaskRunner* DatabaseMessageFilter::OverrideTaskRunnerForMessage(
+ const IPC::Message& message) {
if (message.type() == DatabaseHostMsg_Opened::ID && !observer_added_) {
observer_added_ = true;
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- base::Bind(&DatabaseMessageFilter::AddObserver, this));
+ db_tracker_->task_runner()->PostTask(
+ FROM_HERE, base::BindOnce(&DatabaseMessageFilter::AddObserver, this));
}
+
+ // GetSpaceAvailable talks to the quota manager on IO thread, so avoid
+ // multiple hops.
+ if (message.type() == DatabaseHostMsg_GetSpaceAvailable::ID)
+ return BrowserThread::GetTaskRunnerForThread(BrowserThread::IO).get();
+
+ if (IPC_MESSAGE_CLASS(message) == DatabaseMsgStart)
+ return db_tracker_->task_runner();
+
+ return nullptr;
}
bool DatabaseMessageFilter::OnMessageReceived(const IPC::Message& message) {
@@ -124,9 +127,9 @@ void DatabaseMessageFilter::OnDatabaseOpenFile(
const base::string16& vfs_file_name,
int desired_flags,
IPC::PlatformFileForTransit* handle) {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence());
base::File file;
- const base::File* tracked_file = NULL;
+ const base::File* tracked_file = nullptr;
std::string origin_identifier;
base::string16 database_name;
@@ -139,7 +142,7 @@ void DatabaseMessageFilter::OnDatabaseOpenFile(
file = VfsBackend::OpenTempFileInDirectory(db_tracker_->DatabaseDirectory(),
desired_flags);
} else if (DatabaseUtil::CrackVfsFileName(vfs_file_name, &origin_identifier,
- &database_name, NULL) &&
+ &database_name, nullptr) &&
!db_tracker_->IsDatabaseScheduledForDeletion(origin_identifier,
database_name)) {
base::FilePath db_file = DatabaseUtil::GetFullFilePathForVfsFile(
@@ -179,6 +182,7 @@ void DatabaseMessageFilter::OnDatabaseDeleteFile(
const base::string16& vfs_file_name,
const bool& sync_dir,
IPC::Message* reply_msg) {
+ DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence());
DatabaseDeleteFile(vfs_file_name, sync_dir, reply_msg, kNumDeleteRetries);
}
@@ -187,7 +191,7 @@ void DatabaseMessageFilter::DatabaseDeleteFile(
bool sync_dir,
IPC::Message* reply_msg,
int reschedule_count) {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence());
// Return an error if the file name is invalid or if the file could not
// be deleted after kNumDeleteRetries attempts.
@@ -203,8 +207,8 @@ void DatabaseMessageFilter::DatabaseDeleteFile(
// WAL files can be deleted without having previously been opened.
if (!db_tracker_->HasSavedIncognitoFileHandle(vfs_file_name) &&
- DatabaseUtil::CrackVfsFileName(vfs_file_name,
- NULL, NULL, &sqlite_suffix) &&
+ DatabaseUtil::CrackVfsFileName(vfs_file_name, nullptr, nullptr,
+ &sqlite_suffix) &&
sqlite_suffix == wal_suffix) {
error_code = SQLITE_OK;
} else {
@@ -217,10 +221,11 @@ void DatabaseMessageFilter::DatabaseDeleteFile(
if ((error_code == SQLITE_IOERR_DELETE) && reschedule_count) {
// If the file could not be deleted, try again.
- BrowserThread::PostDelayedTask(
- BrowserThread::FILE, FROM_HERE,
- base::Bind(&DatabaseMessageFilter::DatabaseDeleteFile, this,
- vfs_file_name, sync_dir, reply_msg, reschedule_count - 1),
+ db_tracker_->task_runner()->PostDelayedTask(
+ FROM_HERE,
+ base::BindOnce(&DatabaseMessageFilter::DatabaseDeleteFile, this,
+ vfs_file_name, sync_dir, reply_msg,
+ reschedule_count - 1),
base::TimeDelta::FromMilliseconds(kDelayDeleteRetryMs));
return;
}
@@ -233,7 +238,7 @@ void DatabaseMessageFilter::DatabaseDeleteFile(
void DatabaseMessageFilter::OnDatabaseGetFileAttributes(
const base::string16& vfs_file_name,
int32_t* attributes) {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence());
*attributes = -1;
base::FilePath db_file =
DatabaseUtil::GetFullFilePathForVfsFile(db_tracker_.get(), vfs_file_name);
@@ -244,7 +249,7 @@ void DatabaseMessageFilter::OnDatabaseGetFileAttributes(
void DatabaseMessageFilter::OnDatabaseGetFileSize(
const base::string16& vfs_file_name,
int64_t* size) {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence());
*size = 0;
base::FilePath db_file =
DatabaseUtil::GetFullFilePathForVfsFile(db_tracker_.get(), vfs_file_name);
@@ -255,6 +260,9 @@ void DatabaseMessageFilter::OnDatabaseGetFileSize(
void DatabaseMessageFilter::OnDatabaseGetSpaceAvailable(
const url::Origin& origin,
IPC::Message* reply_msg) {
+ // Note the special case in OverrideTaskRunnerForMessage - since this
+ // interacts directy with the QuotaManager this handler is run on the IO
+ // thread to avoid unnecessary thread hops.
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(db_tracker_->quota_manager_proxy());
@@ -279,15 +287,16 @@ void DatabaseMessageFilter::OnDatabaseGetSpaceAvailable(
quota_manager->GetUsageAndQuota(
origin.GetURL(), storage::kStorageTypeTemporary,
- base::Bind(&DatabaseMessageFilter::OnDatabaseGetUsageAndQuota, this,
+ base::Bind(&DatabaseMessageFilter::OnDatabaseDidGetUsageAndQuota, this,
reply_msg));
}
-void DatabaseMessageFilter::OnDatabaseGetUsageAndQuota(
+void DatabaseMessageFilter::OnDatabaseDidGetUsageAndQuota(
IPC::Message* reply_msg,
storage::QuotaStatusCode status,
int64_t usage,
int64_t quota) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
int64_t available = 0;
if ((status == storage::kQuotaStatusOk) && (usage < quota))
available = quota - usage;
@@ -299,7 +308,7 @@ void DatabaseMessageFilter::OnDatabaseSetFileSize(
const base::string16& vfs_file_name,
int64_t size,
bool* success) {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence());
*success = false;
base::FilePath db_file =
DatabaseUtil::GetFullFilePathForVfsFile(db_tracker_.get(), vfs_file_name);
@@ -312,7 +321,7 @@ void DatabaseMessageFilter::OnDatabaseOpened(
const base::string16& database_name,
const base::string16& description,
int64_t estimated_size) {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence());
if (!IsOriginValid(origin)) {
bad_message::ReceivedBadMessage(this,
@@ -335,7 +344,7 @@ void DatabaseMessageFilter::OnDatabaseOpened(
void DatabaseMessageFilter::OnDatabaseModified(
const url::Origin& origin,
const base::string16& database_name) {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence());
if (!IsOriginValid(origin)) {
bad_message::ReceivedBadMessage(
@@ -358,7 +367,7 @@ void DatabaseMessageFilter::OnDatabaseModified(
void DatabaseMessageFilter::OnDatabaseClosed(
const url::Origin& origin,
const base::string16& database_name) {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence());
if (!IsOriginValid(origin)) {
bad_message::ReceivedBadMessage(this,
@@ -383,7 +392,7 @@ void DatabaseMessageFilter::OnHandleSqliteError(
const url::Origin& origin,
const base::string16& database_name,
int error) {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence());
if (!IsOriginValid(origin)) {
bad_message::ReceivedBadMessage(
this, bad_message::DBMF_INVALID_ORIGIN_ON_SQLITE_ERROR);
@@ -397,7 +406,7 @@ void DatabaseMessageFilter::OnDatabaseSizeChanged(
const std::string& origin_identifier,
const base::string16& database_name,
int64_t database_size) {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence());
if (database_connections_.IsOriginUsed(origin_identifier)) {
Send(new DatabaseMsg_UpdateSize(
url::Origin(storage::GetOriginFromIdentifier(origin_identifier)),
@@ -408,7 +417,7 @@ void DatabaseMessageFilter::OnDatabaseSizeChanged(
void DatabaseMessageFilter::OnDatabaseScheduledForDeletion(
const std::string& origin_identifier,
const base::string16& database_name) {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence());
Send(new DatabaseMsg_CloseImmediately(
url::Origin(storage::GetOriginFromIdentifier(origin_identifier)),
database_name));
diff --git a/chromium/content/browser/renderer_host/database_message_filter.h b/chromium/content/browser/renderer_host/database_message_filter.h
index 125dcefbb18..4f40209f88e 100644
--- a/chromium/content/browser/renderer_host/database_message_filter.h
+++ b/chromium/content/browser/renderer_host/database_message_filter.h
@@ -28,8 +28,8 @@ class DatabaseMessageFilter : public BrowserMessageFilter,
// BrowserMessageFilter implementation.
void OnChannelClosing() override;
- void OverrideThreadForMessage(const IPC::Message& message,
- BrowserThread::ID* thread) override;
+ base::TaskRunner* OverrideTaskRunnerForMessage(
+ const IPC::Message& message) override;
bool OnMessageReceived(const IPC::Message& message) override;
storage::DatabaseTracker* database_tracker() const {
@@ -44,7 +44,7 @@ class DatabaseMessageFilter : public BrowserMessageFilter,
void AddObserver();
void RemoveObserver();
- // VFS message handlers (file thread)
+ // VFS message handlers (tracker sequence)
void OnDatabaseOpenFile(const base::string16& vfs_file_name,
int desired_flags,
IPC::PlatformFileForTransit* handle);
@@ -62,12 +62,12 @@ class DatabaseMessageFilter : public BrowserMessageFilter,
// Quota message handler (io thread)
void OnDatabaseGetSpaceAvailable(const url::Origin& origin,
IPC::Message* reply_msg);
- void OnDatabaseGetUsageAndQuota(IPC::Message* reply_msg,
- storage::QuotaStatusCode status,
- int64_t usage,
- int64_t quota);
+ void OnDatabaseDidGetUsageAndQuota(IPC::Message* reply_msg,
+ storage::QuotaStatusCode status,
+ int64_t usage,
+ int64_t quota);
- // Database tracker message handlers (file thread)
+ // Database tracker message handlers (tracker sequence)
void OnDatabaseOpened(const url::Origin& origin,
const base::string16& database_name,
const base::string16& description,
@@ -80,7 +80,7 @@ class DatabaseMessageFilter : public BrowserMessageFilter,
const base::string16& database_name,
int error);
- // DatabaseTracker::Observer callbacks (file thread)
+ // DatabaseTracker::Observer callbacks (tracker sequence)
void OnDatabaseSizeChanged(const std::string& origin_identifier,
const base::string16& database_name,
int64_t database_size) override;
diff --git a/chromium/content/browser/renderer_host/delegated_frame_host.cc b/chromium/content/browser/renderer_host/delegated_frame_host.cc
index eb3a2ee83e6..b44340c33de 100644
--- a/chromium/content/browser/renderer_host/delegated_frame_host.cc
+++ b/chromium/content/browser/renderer_host/delegated_frame_host.cc
@@ -15,15 +15,15 @@
#include "base/time/default_tick_clock.h"
#include "cc/base/switches.h"
#include "cc/output/compositor_frame.h"
-#include "cc/output/copy_output_request.h"
-#include "cc/resources/single_release_callback.h"
-#include "cc/surfaces/surface.h"
-#include "cc/surfaces/surface_hittest.h"
#include "components/viz/common/gl_helper.h"
+#include "components/viz/common/quads/copy_output_request.h"
+#include "components/viz/common/quads/single_release_callback.h"
#include "components/viz/common/quads/texture_mailbox.h"
#include "components/viz/host/host_frame_sink_manager.h"
#include "components/viz/service/frame_sinks/compositor_frame_sink_support.h"
#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
+#include "components/viz/service/surfaces/surface.h"
+#include "components/viz/service/surfaces/surface_hittest.h"
#include "content/browser/compositor/surface_utils.h"
#include "content/browser/gpu/compositor_util.h"
#include "content/browser/renderer_host/compositor_resize_lock.h"
@@ -54,10 +54,9 @@ DelegatedFrameHost::DelegatedFrameHost(const viz::FrameSinkId& frame_sink_id,
frame_evictor_(new viz::FrameEvictor(this)) {
ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
factory->GetContextFactory()->AddObserver(this);
- factory->GetContextFactoryPrivate()
- ->GetFrameSinkManager()
- ->surface_manager()
- ->RegisterFrameSinkId(frame_sink_id_);
+ viz::HostFrameSinkManager* host_frame_sink_manager =
+ factory->GetContextFactoryPrivate()->GetHostFrameSinkManager();
+ host_frame_sink_manager->RegisterFrameSinkId(frame_sink_id_, this);
CreateCompositorFrameSinkSupport();
}
@@ -125,8 +124,8 @@ void DelegatedFrameHost::CopyFromCompositingSurface(
return;
}
- std::unique_ptr<cc::CopyOutputRequest> request =
- cc::CopyOutputRequest::CreateRequest(
+ std::unique_ptr<viz::CopyOutputRequest> request =
+ viz::CopyOutputRequest::CreateRequest(
base::BindOnce(&CopyFromCompositingSurfaceHasResult, output_size,
preferred_color_type, callback));
if (!src_subrect.IsEmpty())
@@ -143,8 +142,8 @@ void DelegatedFrameHost::CopyFromCompositingSurfaceToVideoFrame(
return;
}
- std::unique_ptr<cc::CopyOutputRequest> request =
- cc::CopyOutputRequest::CreateRequest(base::BindOnce(
+ std::unique_ptr<viz::CopyOutputRequest> request =
+ viz::CopyOutputRequest::CreateRequest(base::BindOnce(
&DelegatedFrameHost::CopyFromCompositingSurfaceHasResultForVideo,
AsWeakPtr(), // For caching the ReadbackYUVInterface on this class.
nullptr, std::move(target), callback));
@@ -173,18 +172,18 @@ viz::FrameSinkId DelegatedFrameHost::GetFrameSinkId() {
}
viz::SurfaceId DelegatedFrameHost::SurfaceIdAtPoint(
- cc::SurfaceHittestDelegate* delegate,
+ viz::SurfaceHittestDelegate* delegate,
const gfx::Point& point,
gfx::Point* transformed_point) {
+ *transformed_point = point;
viz::SurfaceId surface_id(frame_sink_id_, local_surface_id_);
if (!surface_id.is_valid())
return surface_id;
- cc::SurfaceHittest hittest(delegate,
- GetFrameSinkManager()->surface_manager());
+ viz::SurfaceHittest hittest(delegate,
+ GetFrameSinkManager()->surface_manager());
gfx::Transform target_transform;
viz::SurfaceId target_local_surface_id =
hittest.GetTargetSurfaceAtPoint(surface_id, point, &target_transform);
- *transformed_point = point;
if (target_local_surface_id.is_valid())
target_transform.TransformPoint(transformed_point);
return target_local_surface_id;
@@ -201,7 +200,8 @@ bool DelegatedFrameHost::TransformPointToLocalCoordSpace(
if (original_surface == surface_id)
return true;
- cc::SurfaceHittest hittest(nullptr, GetFrameSinkManager()->surface_manager());
+ viz::SurfaceHittest hittest(nullptr,
+ GetFrameSinkManager()->surface_manager());
return hittest.TransformPointToTargetSurface(original_surface, surface_id,
transformed_point);
}
@@ -223,7 +223,7 @@ void DelegatedFrameHost::SetNeedsBeginFrames(bool needs_begin_frames) {
support_->SetNeedsBeginFrame(needs_begin_frames);
}
-void DelegatedFrameHost::DidNotProduceFrame(const cc::BeginFrameAck& ack) {
+void DelegatedFrameHost::DidNotProduceFrame(const viz::BeginFrameAck& ack) {
DCHECK(!ack.has_damage);
support_->DidNotProduceFrame(ack);
}
@@ -346,8 +346,8 @@ void DelegatedFrameHost::AttemptFrameSubscriberCapture(
subscriber_texture = new OwnedMailbox(helper);
}
- std::unique_ptr<cc::CopyOutputRequest> request =
- cc::CopyOutputRequest::CreateRequest(base::BindOnce(
+ std::unique_ptr<viz::CopyOutputRequest> request =
+ viz::CopyOutputRequest::CreateRequest(base::BindOnce(
&DelegatedFrameHost::CopyFromCompositingSurfaceHasResultForVideo,
AsWeakPtr(), subscriber_texture, frame,
base::Bind(callback, present_time)));
@@ -374,11 +374,11 @@ void DelegatedFrameHost::AttemptFrameSubscriberCapture(
}
void DelegatedFrameHost::DidCreateNewRendererCompositorFrameSink(
- cc::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink) {
+ viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink) {
+ EvictDelegatedFrame();
ResetCompositorFrameSinkSupport();
renderer_compositor_frame_sink_ = renderer_compositor_frame_sink;
CreateCompositorFrameSinkSupport();
- has_frame_ = false;
}
void DelegatedFrameHost::SubmitCompositorFrame(
@@ -388,7 +388,7 @@ void DelegatedFrameHost::SubmitCompositorFrame(
DCHECK(!resize_lock_ || !client_->IsAutoResizeEnabled());
#endif
float frame_device_scale_factor = frame.metadata.device_scale_factor;
- cc::BeginFrameAck ack(frame.metadata.begin_frame_ack);
+ viz::BeginFrameAck ack(frame.metadata.begin_frame_ack);
DCHECK(!frame.render_pass_list.empty());
@@ -404,8 +404,8 @@ void DelegatedFrameHost::SubmitCompositorFrame(
gfx::ConvertRectToDIP(frame_device_scale_factor, damage_rect);
if (ShouldSkipFrame(frame_size_in_dip)) {
- std::vector<cc::ReturnedResource> resources =
- cc::TransferableResource::ReturnResources(frame.resource_list);
+ std::vector<viz::ReturnedResource> resources =
+ viz::TransferableResource::ReturnResources(frame.resource_list);
skipped_latency_info_list_.insert(skipped_latency_info_list_.end(),
frame.metadata.latency_info.begin(),
@@ -450,10 +450,6 @@ void DelegatedFrameHost::SubmitCompositorFrame(
skipped_latency_info_list_.end());
skipped_latency_info_list_.clear();
- bool result =
- support_->SubmitCompositorFrame(local_surface_id, std::move(frame));
- DCHECK(result);
-
if (local_surface_id != local_surface_id_ || !has_frame_) {
// manager must outlive compositors using it.
viz::SurfaceId surface_id(frame_sink_id_, local_surface_id);
@@ -461,12 +457,19 @@ void DelegatedFrameHost::SubmitCompositorFrame(
frame_size);
client_->DelegatedFrameHostGetLayer()->SetShowPrimarySurface(
surface_info, manager->surface_manager()->reference_factory());
- client_->DelegatedFrameHostGetLayer()->SetFallbackSurface(surface_info);
current_surface_size_ = frame_size;
current_scale_factor_ = frame_device_scale_factor;
}
has_frame_ = true;
+
+ // If surface synchronization is off, then OnFirstSurfaceActivation will be
+ // called in the same call stack and so to ensure that the fallback surface
+ // is set, then primary surface must be set prior to calling
+ // CompositorFrameSinkSupport::SubmitCompositorFrame.
+ bool result =
+ support_->SubmitCompositorFrame(local_surface_id, std::move(frame));
+ DCHECK(result);
}
local_surface_id_ = local_surface_id;
@@ -488,16 +491,21 @@ void DelegatedFrameHost::SubmitCompositorFrame(
}
void DelegatedFrameHost::ClearDelegatedFrame() {
+ // Ensure that we are able to swap in a new blank frame to replace any old
+ // content. This will result in a white flash if we switch back to this
+ // content.
+ // https://crbug.com/739621
+ released_front_lock_.reset();
EvictDelegatedFrame();
}
void DelegatedFrameHost::DidReceiveCompositorFrameAck(
- const std::vector<cc::ReturnedResource>& resources) {
+ const std::vector<viz::ReturnedResource>& resources) {
renderer_compositor_frame_sink_->DidReceiveCompositorFrameAck(resources);
}
void DelegatedFrameHost::ReclaimResources(
- const std::vector<cc::ReturnedResource>& resources) {
+ const std::vector<viz::ReturnedResource>& resources) {
renderer_compositor_frame_sink_->ReclaimResources(resources);
}
@@ -513,7 +521,13 @@ void DelegatedFrameHost::OnBeginFramePausedChanged(bool paused) {
renderer_compositor_frame_sink_->OnBeginFramePausedChanged(paused);
}
-void DelegatedFrameHost::OnBeginFrame(const cc::BeginFrameArgs& args) {
+void DelegatedFrameHost::OnFirstSurfaceActivation(
+ const viz::SurfaceInfo& surface_info) {
+ if (has_frame_)
+ client_->DelegatedFrameHostGetLayer()->SetFallbackSurface(surface_info);
+}
+
+void DelegatedFrameHost::OnBeginFrame(const viz::BeginFrameArgs& args) {
if (renderer_compositor_frame_sink_)
renderer_compositor_frame_sink_->OnBeginFrame(args);
client_->OnBeginFrame();
@@ -552,7 +566,7 @@ void DelegatedFrameHost::CopyFromCompositingSurfaceFinishedForVideo(
base::WeakPtr<DelegatedFrameHost> dfh,
const base::Callback<void(bool)>& callback,
scoped_refptr<OwnedMailbox> subscriber_texture,
- std::unique_ptr<cc::SingleReleaseCallback> release_callback,
+ std::unique_ptr<viz::SingleReleaseCallback> release_callback,
bool result) {
callback.Run(result);
@@ -578,10 +592,10 @@ void DelegatedFrameHost::CopyFromCompositingSurfaceHasResultForVideo(
scoped_refptr<OwnedMailbox> subscriber_texture,
scoped_refptr<media::VideoFrame> video_frame,
const base::Callback<void(const gfx::Rect&, bool)>& callback,
- std::unique_ptr<cc::CopyOutputResult> result) {
+ std::unique_ptr<viz::CopyOutputResult> result) {
base::ScopedClosureRunner scoped_callback_runner(
- base::Bind(callback, gfx::Rect(), false));
- base::ScopedClosureRunner scoped_return_subscriber_texture(base::Bind(
+ base::BindOnce(callback, gfx::Rect(), false));
+ base::ScopedClosureRunner scoped_return_subscriber_texture(base::BindOnce(
&ReturnSubscriberTexture, dfh, subscriber_texture, gpu::SyncToken()));
if (!dfh)
@@ -637,7 +651,7 @@ void DelegatedFrameHost::CopyFromCompositingSurfaceHasResultForVideo(
return;
viz::TextureMailbox texture_mailbox;
- std::unique_ptr<cc::SingleReleaseCallback> release_callback;
+ std::unique_ptr<viz::SingleReleaseCallback> release_callback;
result->TakeTexture(&texture_mailbox, &release_callback);
DCHECK(texture_mailbox.IsTexture());
@@ -772,10 +786,9 @@ DelegatedFrameHost::~DelegatedFrameHost() {
ResetCompositorFrameSinkSupport();
- factory->GetContextFactoryPrivate()
- ->GetFrameSinkManager()
- ->surface_manager()
- ->InvalidateFrameSinkId(frame_sink_id_);
+ viz::HostFrameSinkManager* host_frame_sink_manager =
+ factory->GetContextFactoryPrivate()->GetHostFrameSinkManager();
+ host_frame_sink_manager->InvalidateFrameSinkId(frame_sink_id_);
DCHECK(!vsync_manager_.get());
}
@@ -814,7 +827,7 @@ void DelegatedFrameHost::LockResources() {
}
void DelegatedFrameHost::RequestCopyOfOutput(
- std::unique_ptr<cc::CopyOutputRequest> request) {
+ std::unique_ptr<viz::CopyOutputRequest> request) {
// If a specific area has not been requested, set one to ensure correct
// clipping occurs.
if (!request->has_area())
@@ -836,14 +849,12 @@ void DelegatedFrameHost::UnlockResources() {
void DelegatedFrameHost::CreateCompositorFrameSinkSupport() {
DCHECK(!support_);
constexpr bool is_root = false;
- constexpr bool handles_frame_sink_id_invalidation = false;
constexpr bool needs_sync_points = true;
ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
support_ = factory->GetContextFactoryPrivate()
->GetHostFrameSinkManager()
- ->CreateCompositorFrameSinkSupport(
- this, frame_sink_id_, is_root,
- handles_frame_sink_id_invalidation, needs_sync_points);
+ ->CreateCompositorFrameSinkSupport(this, frame_sink_id_,
+ is_root, needs_sync_points);
if (compositor_)
compositor_->AddFrameSink(frame_sink_id_);
if (needs_begin_frame_)
diff --git a/chromium/content/browser/renderer_host/delegated_frame_host.h b/chromium/content/browser/renderer_host/delegated_frame_host.h
index 383422e7528..985712ce4b7 100644
--- a/chromium/content/browser/renderer_host/delegated_frame_host.h
+++ b/chromium/content/browser/renderer_host/delegated_frame_host.h
@@ -10,9 +10,10 @@
#include <vector>
#include "base/gtest_prod_util.h"
-#include "cc/output/begin_frame_args.h"
-#include "cc/output/copy_output_result.h"
-#include "cc/scheduler/begin_frame_source.h"
+#include "components/viz/common/frame_sinks/begin_frame_args.h"
+#include "components/viz/common/frame_sinks/begin_frame_source.h"
+#include "components/viz/common/quads/copy_output_result.h"
+#include "components/viz/host/host_frame_sink_client.h"
#include "components/viz/service/frame_sinks/compositor_frame_sink_support_client.h"
#include "components/viz/service/frame_sinks/frame_evictor.h"
#include "content/browser/compositor/image_transport_factory.h"
@@ -80,7 +81,8 @@ class CONTENT_EXPORT DelegatedFrameHost
public ui::CompositorVSyncManager::Observer,
public ui::ContextFactoryObserver,
public viz::FrameEvictorClient,
- public NON_EXPORTED_BASE(viz::CompositorFrameSinkSupportClient),
+ public viz::CompositorFrameSinkSupportClient,
+ public viz::HostFrameSinkClient,
public base::SupportsWeakPtr<DelegatedFrameHost> {
public:
DelegatedFrameHost(const viz::FrameSinkId& frame_sink_id,
@@ -107,18 +109,21 @@ class CONTENT_EXPORT DelegatedFrameHost
// viz::CompositorFrameSinkSupportClient implementation.
void DidReceiveCompositorFrameAck(
- const std::vector<cc::ReturnedResource>& resources) override;
- void OnBeginFrame(const cc::BeginFrameArgs& args) override;
+ const std::vector<viz::ReturnedResource>& resources) override;
+ void OnBeginFrame(const viz::BeginFrameArgs& args) override;
void ReclaimResources(
- const std::vector<cc::ReturnedResource>& resources) override;
+ const std::vector<viz::ReturnedResource>& resources) override;
void WillDrawSurface(const viz::LocalSurfaceId& id,
const gfx::Rect& damage_rect) override;
void OnBeginFramePausedChanged(bool paused) override;
+ // viz::HostFrameSinkClient implementation.
+ void OnFirstSurfaceActivation(const viz::SurfaceInfo& surface_info) override;
+
// Public interface exposed to RenderWidgetHostView.
void DidCreateNewRendererCompositorFrameSink(
- cc::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink);
+ viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink);
void SubmitCompositorFrame(const viz::LocalSurfaceId& local_surface_id,
cc::CompositorFrame frame);
void ClearDelegatedFrame();
@@ -148,7 +153,7 @@ class CONTENT_EXPORT DelegatedFrameHost
viz::FrameSinkId GetFrameSinkId();
// Returns a null SurfaceId if this DelegatedFrameHost has not yet created
// a compositor Surface.
- viz::SurfaceId SurfaceIdAtPoint(cc::SurfaceHittestDelegate* delegate,
+ viz::SurfaceId SurfaceIdAtPoint(viz::SurfaceHittestDelegate* delegate,
const gfx::Point& point,
gfx::Point* transformed_point);
@@ -170,7 +175,7 @@ class CONTENT_EXPORT DelegatedFrameHost
gfx::Point* transformed_point);
void SetNeedsBeginFrames(bool needs_begin_frames);
- void DidNotProduceFrame(const cc::BeginFrameAck& ack);
+ void DidNotProduceFrame(const viz::BeginFrameAck& ack);
// Exposed for tests.
viz::SurfaceId SurfaceIdForTesting() const {
@@ -186,7 +191,7 @@ class CONTENT_EXPORT DelegatedFrameHost
return !!released_front_lock_.get();
}
void SetRequestCopyOfOutputCallbackForTesting(
- const base::Callback<void(std::unique_ptr<cc::CopyOutputRequest>)>&
+ const base::Callback<void(std::unique_ptr<viz::CopyOutputRequest>)>&
callback) {
request_copy_of_output_callback_for_testing_ = callback;
}
@@ -204,7 +209,7 @@ class CONTENT_EXPORT DelegatedFrameHost
}
void LockResources();
void UnlockResources();
- void RequestCopyOfOutput(std::unique_ptr<cc::CopyOutputRequest> request);
+ void RequestCopyOfOutput(std::unique_ptr<viz::CopyOutputRequest> request);
bool ShouldSkipFrame(const gfx::Size& size_in_dip);
@@ -228,13 +233,13 @@ class CONTENT_EXPORT DelegatedFrameHost
scoped_refptr<OwnedMailbox> subscriber_texture,
scoped_refptr<media::VideoFrame> video_frame,
const base::Callback<void(const gfx::Rect&, bool)>& callback,
- std::unique_ptr<cc::CopyOutputResult> result);
+ std::unique_ptr<viz::CopyOutputResult> result);
static void CopyFromCompositingSurfaceFinishedForVideo(
scoped_refptr<media::VideoFrame> video_frame,
base::WeakPtr<DelegatedFrameHost> rwhva,
const base::Callback<void(bool)>& callback,
scoped_refptr<OwnedMailbox> subscriber_texture,
- std::unique_ptr<cc::SingleReleaseCallback> release_callback,
+ std::unique_ptr<viz::SingleReleaseCallback> release_callback,
bool result);
static void ReturnSubscriberTexture(
base::WeakPtr<DelegatedFrameHost> rwhva,
@@ -279,7 +284,7 @@ class CONTENT_EXPORT DelegatedFrameHost
std::unique_ptr<viz::CompositorFrameSinkSupport> support_;
gfx::Size current_surface_size_;
float current_scale_factor_;
- std::vector<cc::ReturnedResource> surface_returned_resources_;
+ std::vector<viz::ReturnedResource> surface_returned_resources_;
// This lock is the one waiting for a frame of the right size to come back
// from the renderer/GPU process. It is set from the moment the aura window
@@ -305,7 +310,7 @@ class CONTENT_EXPORT DelegatedFrameHost
// Callback used to pass the output request to the layer or to a function
// specified by a test.
- base::Callback<void(std::unique_ptr<cc::CopyOutputRequest>)>
+ base::Callback<void(std::unique_ptr<viz::CopyOutputRequest>)>
request_copy_of_output_callback_for_testing_;
// YUV readback pipeline.
@@ -314,7 +319,7 @@ class CONTENT_EXPORT DelegatedFrameHost
bool needs_begin_frame_ = false;
bool has_frame_ = false;
- cc::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink_ =
+ viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink_ =
nullptr;
std::unique_ptr<viz::FrameEvictor> frame_evictor_;
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 3df9459b18d..b05628141b8 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
@@ -17,7 +17,7 @@ class RenderWidgetHostViewAura;
// DelegatedFrameHostClient implementation for aura, not used in mus.
class CONTENT_EXPORT DelegatedFrameHostClientAura
: public DelegatedFrameHostClient,
- NON_EXPORTED_BASE(public CompositorResizeLockClient) {
+ public CompositorResizeLockClient {
public:
explicit DelegatedFrameHostClientAura(
RenderWidgetHostViewAura* render_widget_host_view);
diff --git a/chromium/content/browser/renderer_host/dwrite_font_proxy_message_filter_win.cc b/chromium/content/browser/renderer_host/dwrite_font_proxy_message_filter_win.cc
index 49c21c1b7cb..ce525f84383 100644
--- a/chromium/content/browser/renderer_host/dwrite_font_proxy_message_filter_win.cc
+++ b/chromium/content/browser/renderer_host/dwrite_font_proxy_message_filter_win.cc
@@ -22,6 +22,7 @@
#include "base/strings/string16.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/task_scheduler/post_task.h"
#include "content/common/dwrite_font_proxy_messages.h"
#include "ipc/ipc_message_macros.h"
#include "ui/gfx/win/direct_write.h"
@@ -180,7 +181,9 @@ bool CheckRequiredStylesPresent(IDWriteFontCollection* collection,
DWriteFontProxyMessageFilter::DWriteFontProxyMessageFilter()
: BrowserMessageFilter(DWriteFontProxyMsgStart),
windows_fonts_path_(GetWindowsFontsPath()),
- custom_font_file_loading_mode_(ENABLE) {}
+ custom_font_file_loading_mode_(ENABLE),
+ dwrite_io_task_runner_(base::CreateSequencedTaskRunnerWithTraits(
+ {base::TaskPriority::USER_BLOCKING, base::MayBlock()})) {}
DWriteFontProxyMessageFilter::~DWriteFontProxyMessageFilter() = default;
@@ -198,11 +201,11 @@ bool DWriteFontProxyMessageFilter::OnMessageReceived(
return handled;
}
-void DWriteFontProxyMessageFilter::OverrideThreadForMessage(
- const IPC::Message& message,
- content::BrowserThread::ID* thread) {
+base::TaskRunner* DWriteFontProxyMessageFilter::OverrideTaskRunnerForMessage(
+ const IPC::Message& message) {
if (IPC_MESSAGE_CLASS(message) == DWriteFontProxyMsgStart)
- *thread = BrowserThread::FILE_USER_BLOCKING;
+ return dwrite_io_task_runner_.get();
+ return nullptr;
}
void DWriteFontProxyMessageFilter::SetWindowsFontsPathForTesting(
@@ -458,7 +461,7 @@ void DWriteFontProxyMessageFilter::OnMapCharacters(
}
void DWriteFontProxyMessageFilter::InitializeDirectWrite() {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE_USER_BLOCKING);
+ DCHECK(dwrite_io_task_runner_->RunsTasksInCurrentSequence());
if (direct_write_initialized_)
return;
direct_write_initialized_ = true;
diff --git a/chromium/content/browser/renderer_host/dwrite_font_proxy_message_filter_win.h b/chromium/content/browser/renderer_host/dwrite_font_proxy_message_filter_win.h
index 0939c9f2018..808b78cf39f 100644
--- a/chromium/content/browser/renderer_host/dwrite_font_proxy_message_filter_win.h
+++ b/chromium/content/browser/renderer_host/dwrite_font_proxy_message_filter_win.h
@@ -14,6 +14,7 @@
#include "base/location.h"
#include "base/macros.h"
+#include "base/memory/ref_counted.h"
#include "base/strings/string16.h"
#include "content/common/content_export.h"
#include "content/public/browser/browser_message_filter.h"
@@ -23,6 +24,10 @@
struct DWriteFontStyle;
struct MapCharactersResult;
+namespace base {
+class SequencedTaskRunner;
+}
+
namespace content {
// Implements a message filter that handles the dwrite font proxy messages.
@@ -35,8 +40,7 @@ class CONTENT_EXPORT DWriteFontProxyMessageFilter
// BrowserMessageFilter:
bool OnMessageReceived(const IPC::Message& message) override;
- void OverrideThreadForMessage(const IPC::Message& message,
- content::BrowserThread::ID* thread) override;
+ base::TaskRunner* OverrideTaskRunnerForMessage(const IPC::Message&) override;
void SetWindowsFontsPathForTesting(base::string16 path);
@@ -80,6 +84,7 @@ class CONTENT_EXPORT DWriteFontProxyMessageFilter
Microsoft::WRL::ComPtr<IDWriteFontFallback> font_fallback_;
base::string16 windows_fonts_path_;
CustomFontFileLoadingMode custom_font_file_loading_mode_;
+ scoped_refptr<base::SequencedTaskRunner> dwrite_io_task_runner_;
// Temp code to help track down crbug.com/561873
std::vector<uint32_t> last_resort_fonts_;
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 83832bf26cf..a340ba74e68 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
@@ -12,7 +12,7 @@
#include "base/files/file.h"
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
-#include "base/test/test_simple_task_runner.h"
+#include "base/test/scoped_task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/win/windows_version.h"
#include "content/common/dwrite_font_proxy_messages.h"
@@ -55,8 +55,14 @@ class DWriteFontProxyMessageFilterUnitTest : public testing::Test {
std::unique_ptr<IPC::SyncMessage> deleter(message);
std::unique_ptr<IPC::MessageReplyDeserializer> serializer(
message->GetReplyDeserializer());
- filter_->OnMessageReceived(*message);
- base::RunLoop().RunUntilIdle();
+ base::TaskRunner* dwrite_io_task_runner =
+ filter_->OverrideTaskRunnerForMessage(*message);
+ dwrite_io_task_runner->PostTask(
+ FROM_HERE,
+ base::Bind(base::IgnoreResult(
+ &DWriteFontProxyMessageFilter::OnMessageReceived),
+ filter_, base::ConstRef(*message)));
+ scoped_task_environment_.RunUntilIdle();
ASSERT_NE(nullptr, filter_->GetReply());
serializer->SerializeOutputParameters(*(filter_->GetReply()));
}
@@ -74,8 +80,8 @@ class DWriteFontProxyMessageFilterUnitTest : public testing::Test {
return factory2.Get();
}
+ base::test::ScopedTaskEnvironment scoped_task_environment_;
scoped_refptr<FilterWithFakeSender> filter_;
- content::TestBrowserThreadBundle thread_bundle_;
};
TEST_F(DWriteFontProxyMessageFilterUnitTest, GetFamilyCount) {
diff --git a/chromium/content/browser/renderer_host/file_utilities_message_filter.cc b/chromium/content/browser/renderer_host/file_utilities_message_filter.cc
index f0a1e4ab6ae..e09e63e00d8 100644
--- a/chromium/content/browser/renderer_host/file_utilities_message_filter.cc
+++ b/chromium/content/browser/renderer_host/file_utilities_message_filter.cc
@@ -5,9 +5,18 @@
#include "content/browser/renderer_host/file_utilities_message_filter.h"
#include "base/files/file_util.h"
+#include "base/task_scheduler/lazy_task_runner.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/common/file_utilities_messages.h"
+namespace {
+
+base::LazySequencedTaskRunner g_file_utility_task_runner =
+ LAZY_SEQUENCED_TASK_RUNNER_INITIALIZER(
+ base::TaskTraits(base::MayBlock(), base::TaskPriority::USER_VISIBLE));
+
+} // namespace
+
namespace content {
FileUtilitiesMessageFilter::FileUtilitiesMessageFilter(int process_id)
@@ -18,11 +27,11 @@ FileUtilitiesMessageFilter::FileUtilitiesMessageFilter(int process_id)
FileUtilitiesMessageFilter::~FileUtilitiesMessageFilter() {
}
-void FileUtilitiesMessageFilter::OverrideThreadForMessage(
- const IPC::Message& message,
- BrowserThread::ID* thread) {
+base::TaskRunner* FileUtilitiesMessageFilter::OverrideTaskRunnerForMessage(
+ const IPC::Message& message) {
if (IPC_MESSAGE_CLASS(message) == FileUtilitiesMsgStart)
- *thread = BrowserThread::FILE;
+ return g_file_utility_task_runner.Get().get();
+ return nullptr;
}
bool FileUtilitiesMessageFilter::OnMessageReceived(
diff --git a/chromium/content/browser/renderer_host/file_utilities_message_filter.h b/chromium/content/browser/renderer_host/file_utilities_message_filter.h
index ccbc739a82e..7388c6cf0d9 100644
--- a/chromium/content/browser/renderer_host/file_utilities_message_filter.h
+++ b/chromium/content/browser/renderer_host/file_utilities_message_filter.h
@@ -21,8 +21,8 @@ class FileUtilitiesMessageFilter : public BrowserMessageFilter {
explicit FileUtilitiesMessageFilter(int process_id);
// BrowserMessageFilter implementation.
- void OverrideThreadForMessage(const IPC::Message& message,
- BrowserThread::ID* thread) override;
+ base::TaskRunner* OverrideTaskRunnerForMessage(
+ const IPC::Message& message) override;
bool OnMessageReceived(const IPC::Message& message) override;
private:
diff --git a/chromium/content/browser/renderer_host/frame_connector_delegate.cc b/chromium/content/browser/renderer_host/frame_connector_delegate.cc
new file mode 100644
index 00000000000..bc3509406c9
--- /dev/null
+++ b/chromium/content/browser/renderer_host/frame_connector_delegate.cc
@@ -0,0 +1,61 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/frame_connector_delegate.h"
+
+namespace content {
+
+RenderWidgetHostViewBase*
+FrameConnectorDelegate::GetParentRenderWidgetHostView() {
+ return nullptr;
+}
+
+RenderWidgetHostViewBase*
+FrameConnectorDelegate::GetRootRenderWidgetHostView() {
+ return nullptr;
+}
+
+gfx::Rect FrameConnectorDelegate::ChildFrameRect() {
+ return gfx::Rect();
+}
+
+gfx::Point FrameConnectorDelegate::TransformPointToRootCoordSpace(
+ const gfx::Point& point,
+ const viz::SurfaceId& surface_id) {
+ return gfx::Point();
+}
+
+bool FrameConnectorDelegate::TransformPointToLocalCoordSpace(
+ const gfx::Point& point,
+ const viz::SurfaceId& original_surface,
+ const viz::SurfaceId& local_surface_id,
+ gfx::Point* transformed_point) {
+ return false;
+}
+
+bool FrameConnectorDelegate::TransformPointToCoordSpaceForView(
+ const gfx::Point& point,
+ RenderWidgetHostViewBase* target_view,
+ const viz::SurfaceId& local_surface_id,
+ gfx::Point* transformed_point) {
+ return false;
+}
+
+bool FrameConnectorDelegate::HasFocus() {
+ return false;
+}
+
+bool FrameConnectorDelegate::LockMouse() {
+ return false;
+}
+
+bool FrameConnectorDelegate::IsInert() const {
+ return false;
+}
+
+bool FrameConnectorDelegate::IsHidden() const {
+ return false;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/frame_connector_delegate.h b/chromium/content/browser/renderer_host/frame_connector_delegate.h
new file mode 100644
index 00000000000..8cbaa038d1e
--- /dev/null
+++ b/chromium/content/browser/renderer_host/frame_connector_delegate.h
@@ -0,0 +1,165 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_FRAME_CONNECTOR_DELEGATE_H_
+#define CONTENT_BROWSER_RENDERER_HOST_FRAME_CONNECTOR_DELEGATE_H_
+
+#include "components/viz/common/surfaces/local_surface_id.h"
+#include "content/browser/renderer_host/event_with_latency_info.h"
+#include "content/common/content_export.h"
+#include "content/common/input/input_event_ack_state.h"
+#include "ui/gfx/geometry/rect.h"
+
+namespace blink {
+class WebGestureEvent;
+}
+
+namespace viz {
+class SurfaceId;
+class SurfaceInfo;
+struct SurfaceSequence;
+} // namespace viz
+
+namespace content {
+class RenderWidgetHostViewBase;
+class RenderWidgetHostViewChildFrame;
+class WebCursor;
+
+//
+// FrameConnectorDelegate
+//
+// An interface to be implemented by an object supplying platform semantics
+// for a child frame.
+//
+// A RenderWidgetHostViewChildFrame, specified by a call to |SetView|, uses
+// this interface to communicate renderer-originating messages such as mouse
+// cursor changes or input event ACKs to its platform.
+// CrossProcessFrameConnector implements this interface and coordinates with
+// higher-level RenderWidgetHostViews to ensure that the underlying platform
+// (e.g. Mac, Aura, Android) correctly reflects state from frames in multiple
+// processes.
+//
+// RenderWidgetHostViewChildFrame also uses this interface to query relevant
+// platform information, such as the size of the rect that the frame will draw
+// into, and whether the view currently has keyboard focus.
+class CONTENT_EXPORT FrameConnectorDelegate {
+ public:
+ virtual void SetView(RenderWidgetHostViewChildFrame* view) {}
+
+ // Returns the parent RenderWidgetHostView or nullptr if it doesn't have one.
+ virtual RenderWidgetHostViewBase* GetParentRenderWidgetHostView();
+
+ // Returns the view for the top-level frame under the same WebContents.
+ virtual RenderWidgetHostViewBase* GetRootRenderWidgetHostView();
+
+ // Notify the frame connector that the renderer process has terminated.
+ virtual void RenderProcessGone() {}
+
+ // Provide the SurfaceInfo to the embedder, which becomes a reference to the
+ // current view's Surface that is included in higher-level compositor
+ // frames.
+ virtual void SetChildFrameSurface(const viz::SurfaceInfo& surface_info,
+ const viz::SurfaceSequence& sequence) {}
+
+ // Return the rect that the RenderWidgetHostViewChildFrame's content will
+ // render into.
+ virtual gfx::Rect ChildFrameRect();
+
+ // Request that the platform change the mouse cursor when the mouse is
+ // positioned over this view's content.
+ virtual void UpdateCursor(const WebCursor& cursor) {}
+
+ // Given a point in the current view's coordinate space, return the same
+ // point transformed into the coordinate space of the top-level view's
+ // coordinate space.
+ virtual gfx::Point TransformPointToRootCoordSpace(
+ const gfx::Point& point,
+ const viz::SurfaceId& surface_id);
+
+ // Given a point in the coordinate space of a different Surface, transform
+ // it into the coordinate space for this view (corresponding to
+ // local_surface_id).
+ // TransformPointToLocalCoordSpace() can only transform points between
+ // surfaces where one is embedded (not necessarily directly) within the
+ // other, and will return false if this is not the case. For points that can
+ // be in sibling surfaces, they must first be converted to the root
+ // surface's coordinate space.
+ virtual bool TransformPointToLocalCoordSpace(
+ const gfx::Point& point,
+ const viz::SurfaceId& original_surface,
+ const viz::SurfaceId& local_surface_id,
+ gfx::Point* transformed_point);
+
+ // Transform a point into the coordinate space of the root
+ // RenderWidgetHostView, for the current view's coordinate space.
+ // Returns false if |target_view| and |view_| do not have the same root
+ // RenderWidgetHostView.
+ virtual bool TransformPointToCoordSpaceForView(
+ const gfx::Point& point,
+ RenderWidgetHostViewBase* target_view,
+ const viz::SurfaceId& local_surface_id,
+ gfx::Point* transformed_point);
+
+ // Pass acked touch events to the root view for gesture processing.
+ virtual void ForwardProcessAckedTouchEvent(
+ const TouchEventWithLatencyInfo& touch,
+ InputEventAckState ack_result) {}
+
+ // Gesture events with unused scroll deltas must be bubbled to ancestors
+ // who may consume the delta.
+ virtual void BubbleScrollEvent(const blink::WebGestureEvent& event) {}
+
+ // Determines whether the root RenderWidgetHostView (and thus the current
+ // page) has focus.
+ virtual bool HasFocus();
+
+ // Cause the root RenderWidgetHostView to become focused.
+ virtual void FocusRootView() {}
+
+ // Locks the mouse. Returns true if mouse is locked.
+ virtual bool LockMouse();
+
+ // Unlocks the mouse if the mouse is locked.
+ virtual void UnlockMouse() {}
+
+ // Returns a rect that represents the intersection of the current view's
+ // content bounds with the top-level browser viewport.
+ const gfx::Rect& ViewportIntersection() const {
+ return viewport_intersection_rect_;
+ }
+
+ // Returns the viz::LocalSurfaceId propagated from the parent to be used by
+ // this child frame.
+ const viz::LocalSurfaceId& local_surface_id() const {
+ return local_surface_id_;
+ }
+
+ // Determines whether the current view's content is inert, either because
+ // an HTMLDialogElement is being modally displayed in a higher-level frame,
+ // or because the inert attribute has been specified.
+ virtual bool IsInert() const;
+
+ // Determines whether the RenderWidgetHostViewChildFrame is hidden due to
+ // a higher-level embedder being hidden. This is distinct from the
+ // RenderWidgetHostImpl being hidden, which is a property set when
+ // RenderWidgetHostView::Hide() is called on the current view.
+ virtual bool IsHidden() const;
+
+ // Called by RenderWidgetHostViewChildFrame to update the visibility of any
+ // nested child RWHVCFs inside it.
+ virtual void SetVisibilityForChildViews(bool visible) const {}
+
+ protected:
+ virtual ~FrameConnectorDelegate() {}
+
+ // This is here rather than in the implementation class so that
+ // ViewportIntersection() can return a reference.
+ gfx::Rect viewport_intersection_rect_;
+
+ viz::LocalSurfaceId local_surface_id_;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_FRAME_CONNECTOR_DELEGATE_H_
diff --git a/chromium/content/browser/renderer_host/frame_sink_provider_impl.cc b/chromium/content/browser/renderer_host/frame_sink_provider_impl.cc
index 3fc3f0fd31c..b308029d4f4 100644
--- a/chromium/content/browser/renderer_host/frame_sink_provider_impl.cc
+++ b/chromium/content/browser/renderer_host/frame_sink_provider_impl.cc
@@ -26,8 +26,8 @@ void FrameSinkProviderImpl::Unbind() {
void FrameSinkProviderImpl::CreateForWidget(
int32_t widget_id,
- cc::mojom::CompositorFrameSinkRequest request,
- cc::mojom::CompositorFrameSinkClientPtr client) {
+ viz::mojom::CompositorFrameSinkRequest request,
+ viz::mojom::CompositorFrameSinkClientPtr client) {
RenderWidgetHostImpl* render_widget_host_impl =
RenderWidgetHostImpl::FromID(process_id_, widget_id);
if (!render_widget_host_impl) {
diff --git a/chromium/content/browser/renderer_host/frame_sink_provider_impl.h b/chromium/content/browser/renderer_host/frame_sink_provider_impl.h
index 52a7b295665..497918b690f 100644
--- a/chromium/content/browser/renderer_host/frame_sink_provider_impl.h
+++ b/chromium/content/browser/renderer_host/frame_sink_provider_impl.h
@@ -21,9 +21,10 @@ class FrameSinkProviderImpl : public mojom::FrameSinkProvider {
void Unbind();
// mojom::FrameSinkProvider implementation.
- void CreateForWidget(int32_t widget_id,
- cc::mojom::CompositorFrameSinkRequest request,
- cc::mojom::CompositorFrameSinkClientPtr client) override;
+ void CreateForWidget(
+ int32_t widget_id,
+ viz::mojom::CompositorFrameSinkRequest request,
+ viz::mojom::CompositorFrameSinkClientPtr client) override;
private:
const int32_t process_id_;
diff --git a/chromium/content/browser/renderer_host/input/fling_controller.cc b/chromium/content/browser/renderer_host/input/fling_controller.cc
new file mode 100644
index 00000000000..f3e9c0779a9
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/fling_controller.cc
@@ -0,0 +1,90 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/input/fling_controller.h"
+
+#include "content/browser/renderer_host/input/gesture_event_queue.h"
+
+using blink::WebInputEvent;
+
+namespace content {
+
+FlingController::Config::Config() {}
+
+FlingController::FlingController(
+ GestureEventQueue* gesture_event_queue,
+ TouchpadTapSuppressionControllerClient* touchpad_client,
+ const Config& config)
+ : gesture_event_queue_(gesture_event_queue),
+ touchpad_tap_suppression_controller_(
+ touchpad_client,
+ config.touchpad_tap_suppression_config),
+ touchscreen_tap_suppression_controller_(
+ gesture_event_queue,
+ config.touchscreen_tap_suppression_config) {
+ DCHECK(gesture_event_queue);
+ DCHECK(touchpad_client);
+}
+
+FlingController::~FlingController() {}
+
+bool FlingController::ShouldForwardForGFCFiltering(
+ const GestureEventWithLatencyInfo& gesture_event) const {
+ if (gesture_event.event.GetType() != WebInputEvent::kGestureFlingCancel)
+ return true;
+ return !gesture_event_queue_->ShouldDiscardFlingCancelEvent(gesture_event);
+}
+
+bool FlingController::ShouldForwardForTapSuppression(
+ const GestureEventWithLatencyInfo& gesture_event) {
+ switch (gesture_event.event.GetType()) {
+ case WebInputEvent::kGestureFlingCancel:
+ if (gesture_event.event.source_device ==
+ blink::kWebGestureDeviceTouchscreen)
+ touchscreen_tap_suppression_controller_.GestureFlingCancel();
+ else if (gesture_event.event.source_device ==
+ blink::kWebGestureDeviceTouchpad)
+ touchpad_tap_suppression_controller_.GestureFlingCancel();
+ return true;
+ case WebInputEvent::kGestureTapDown:
+ case WebInputEvent::kGestureShowPress:
+ case WebInputEvent::kGestureTapUnconfirmed:
+ case WebInputEvent::kGestureTapCancel:
+ case WebInputEvent::kGestureTap:
+ case WebInputEvent::kGestureDoubleTap:
+ case WebInputEvent::kGestureLongPress:
+ case WebInputEvent::kGestureLongTap:
+ case WebInputEvent::kGestureTwoFingerTap:
+ if (gesture_event.event.source_device ==
+ blink::kWebGestureDeviceTouchscreen) {
+ return !touchscreen_tap_suppression_controller_.FilterTapEvent(
+ gesture_event);
+ }
+ return true;
+ default:
+ return true;
+ }
+}
+
+bool FlingController::FilterGestureEvent(
+ const GestureEventWithLatencyInfo& gesture_event) {
+ return (!ShouldForwardForGFCFiltering(gesture_event) ||
+ !ShouldForwardForTapSuppression(gesture_event));
+}
+
+void FlingController::GestureFlingCancelAck(
+ blink::WebGestureDevice source_device,
+ bool processed) {
+ if (source_device == blink::kWebGestureDeviceTouchscreen)
+ touchscreen_tap_suppression_controller_.GestureFlingCancelAck(processed);
+ else if (source_device == blink::kWebGestureDeviceTouchpad)
+ touchpad_tap_suppression_controller_.GestureFlingCancelAck(processed);
+}
+
+TouchpadTapSuppressionController*
+FlingController::GetTouchpadTapSuppressionController() {
+ return &touchpad_tap_suppression_controller_;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/fling_controller.h b/chromium/content/browser/renderer_host/input/fling_controller.h
new file mode 100644
index 00000000000..8dac16987cd
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/fling_controller.h
@@ -0,0 +1,67 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef FLING_CONTROLLER_H_
+#define FLING_CONTROLLER_H_
+
+#include "content/browser/renderer_host/input/touchpad_tap_suppression_controller.h"
+#include "content/browser/renderer_host/input/touchscreen_tap_suppression_controller.h"
+
+namespace content {
+
+class GestureEventQueue;
+
+class FlingController {
+ public:
+ struct CONTENT_EXPORT Config {
+ Config();
+
+ // Controls touchpad-related tap suppression, disabled by default.
+ TapSuppressionController::Config touchpad_tap_suppression_config;
+
+ // Controls touchscreen-related tap suppression, disabled by default.
+ TapSuppressionController::Config touchscreen_tap_suppression_config;
+ };
+
+ FlingController(GestureEventQueue* gesture_event_queue,
+ TouchpadTapSuppressionControllerClient* touchpad_client,
+ const Config& config);
+
+ ~FlingController();
+
+ // Sub-filter for removing unnecessary GestureFlingCancels.
+ bool ShouldForwardForGFCFiltering(
+ const GestureEventWithLatencyInfo& gesture_event) const;
+
+ // Sub-filter for suppressing taps immediately after a GestureFlingCancel.
+ bool ShouldForwardForTapSuppression(
+ const GestureEventWithLatencyInfo& gesture_event);
+
+ bool FilterGestureEvent(const GestureEventWithLatencyInfo& gesture_event);
+
+ void GestureFlingCancelAck(blink::WebGestureDevice source_device,
+ bool processed);
+
+ // Returns the |TouchpadTapSuppressionController| instance.
+ TouchpadTapSuppressionController* GetTouchpadTapSuppressionController();
+
+ private:
+ GestureEventQueue* gesture_event_queue_;
+
+ // An object tracking the state of touchpad on the delivery of mouse events to
+ // the renderer to filter mouse immediately after a touchpad fling canceling
+ // tap.
+ TouchpadTapSuppressionController touchpad_tap_suppression_controller_;
+
+ // An object tracking the state of touchscreen on the delivery of gesture tap
+ // events to the renderer to filter taps immediately after a touchscreen fling
+ // canceling tap.
+ TouchscreenTapSuppressionController touchscreen_tap_suppression_controller_;
+
+ DISALLOW_COPY_AND_ASSIGN(FlingController);
+};
+
+} // namespace content
+
+#endif // FLING_CONTROLLER_H_
diff --git a/chromium/content/browser/renderer_host/input/gesture_event_queue.cc b/chromium/content/browser/renderer_host/input/gesture_event_queue.cc
index 0dd7c08b051..309e75c764d 100644
--- a/chromium/content/browser/renderer_host/input/gesture_event_queue.cc
+++ b/chromium/content/browser/renderer_host/input/gesture_event_queue.cc
@@ -4,6 +4,7 @@
#include "content/browser/renderer_host/input/gesture_event_queue.h"
+#include "base/auto_reset.h"
#include "base/trace_event/trace_event.h"
#include "content/browser/renderer_host/input/touchpad_tap_suppression_controller.h"
#include "content/browser/renderer_host/input/touchscreen_tap_suppression_controller.h"
@@ -15,6 +16,11 @@ using blink::WebInputEvent;
namespace content {
+GestureEventQueue::GestureEventWithLatencyInfoAndAckState::
+ GestureEventWithLatencyInfoAndAckState(
+ const GestureEventWithLatencyInfo& event)
+ : GestureEventWithLatencyInfo(event) {}
+
GestureEventQueue::Config::Config() {
}
@@ -28,13 +34,8 @@ GestureEventQueue::GestureEventQueue(
ignore_next_ack_(false),
allow_multiple_inflight_events_(
base::FeatureList::IsEnabled(features::kVsyncAlignedInputEvents)),
- touchpad_tap_suppression_controller_(
- touchpad_client,
- config.touchpad_tap_suppression_config),
- touchscreen_tap_suppression_controller_(
- this,
- config.touchscreen_tap_suppression_config),
- debounce_interval_(config.debounce_interval) {
+ debounce_interval_(config.debounce_interval),
+ fling_controller_(this, touchpad_client, config.fling_config) {
DCHECK(client);
DCHECK(touchpad_client);
}
@@ -45,8 +46,7 @@ void GestureEventQueue::QueueEvent(
const GestureEventWithLatencyInfo& gesture_event) {
TRACE_EVENT0("input", "GestureEventQueue::QueueEvent");
if (!ShouldForwardForBounceReduction(gesture_event) ||
- !ShouldForwardForGFCFiltering(gesture_event) ||
- !ShouldForwardForTapSuppression(gesture_event)) {
+ fling_controller_.FilterGestureEvent(gesture_event)) {
return;
}
@@ -57,7 +57,7 @@ bool GestureEventQueue::ShouldDiscardFlingCancelEvent(
const GestureEventWithLatencyInfo& gesture_event) const {
if (coalesced_gesture_events_.empty() && fling_in_progress_)
return false;
- GestureQueue::const_reverse_iterator it =
+ GestureQueueWithAckState::const_reverse_iterator it =
coalesced_gesture_events_.rbegin();
while (it != coalesced_gesture_events_.rend()) {
if (it->event.GetType() == WebInputEvent::kGestureFlingStart)
@@ -110,43 +110,6 @@ bool GestureEventQueue::ShouldForwardForBounceReduction(
}
}
-bool GestureEventQueue::ShouldForwardForGFCFiltering(
- const GestureEventWithLatencyInfo& gesture_event) const {
- return gesture_event.event.GetType() != WebInputEvent::kGestureFlingCancel ||
- !ShouldDiscardFlingCancelEvent(gesture_event);
-}
-
-bool GestureEventQueue::ShouldForwardForTapSuppression(
- const GestureEventWithLatencyInfo& gesture_event) {
- switch (gesture_event.event.GetType()) {
- case WebInputEvent::kGestureFlingCancel:
- if (gesture_event.event.source_device ==
- blink::kWebGestureDeviceTouchscreen)
- touchscreen_tap_suppression_controller_.GestureFlingCancel();
- else if (gesture_event.event.source_device ==
- blink::kWebGestureDeviceTouchpad)
- touchpad_tap_suppression_controller_.GestureFlingCancel();
- return true;
- case WebInputEvent::kGestureTapDown:
- case WebInputEvent::kGestureShowPress:
- case WebInputEvent::kGestureTapUnconfirmed:
- case WebInputEvent::kGestureTapCancel:
- case WebInputEvent::kGestureTap:
- case WebInputEvent::kGestureDoubleTap:
- case WebInputEvent::kGestureLongPress:
- case WebInputEvent::kGestureLongTap:
- case WebInputEvent::kGestureTwoFingerTap:
- if (gesture_event.event.source_device ==
- blink::kWebGestureDeviceTouchscreen) {
- return !touchscreen_tap_suppression_controller_.FilterTapEvent(
- gesture_event);
- }
- return true;
- default:
- return true;
- }
-}
-
void GestureEventQueue::QueueAndForwardIfNecessary(
const GestureEventWithLatencyInfo& gesture_event) {
if (allow_multiple_inflight_events_) {
@@ -212,30 +175,77 @@ void GestureEventQueue::ProcessGestureAck(InputEventAckState ack_result,
return;
}
- size_t event_index = 0;
- if (allow_multiple_inflight_events_) {
- // Events are forwarded immediately.
- // Assuming events of the same type are acked in a FIFO order, but it's
- // still possible that GestureFling events are acked before
- // GestureScroll/Pinch as they don't need to go through the queue in
- // |InputHandlerProxy::HandleInputEventWithLatencyInfo|.
- for (size_t i = 0; i < coalesced_gesture_events_.size(); ++i) {
- if (coalesced_gesture_events_[i].event.GetType() == type) {
- event_index = i;
- break;
- }
- }
- } else {
- // Events are forwarded one-by-one.
- // It's possible that the ack for the second event in an in-flight,
- // coalesced Gesture{Scroll,Pinch}Update pair is received prior to the first
- // event ack.
- if (ignore_next_ack_ && coalesced_gesture_events_.size() > 1 &&
- coalesced_gesture_events_[0].event.GetType() != type &&
- coalesced_gesture_events_[1].event.GetType() == type) {
- event_index = 1;
+ if (!allow_multiple_inflight_events_) {
+ LegacyProcessGestureAck(ack_result, type, latency);
+ return;
+ }
+
+ // ACKs could come back out of order. We want to cache them to restore the
+ // original order.
+ for (auto& outstanding_event : coalesced_gesture_events_) {
+ if (outstanding_event.ack_state() != INPUT_EVENT_ACK_STATE_UNKNOWN)
+ continue;
+ if (outstanding_event.event.GetType() == type) {
+ outstanding_event.latency.AddNewLatencyFrom(latency);
+ outstanding_event.set_ack_state(ack_result);
+ break;
}
}
+
+ AckCompletedEvents();
+}
+
+void GestureEventQueue::AckCompletedEvents() {
+ // Don't allow re-entrancy into this method otherwise
+ // the ordering of acks won't be preserved.
+ if (processing_acks_)
+ return;
+ base::AutoReset<bool> process_acks(&processing_acks_, true);
+ while (!coalesced_gesture_events_.empty()) {
+ auto iter = coalesced_gesture_events_.begin();
+ if (iter->ack_state() == INPUT_EVENT_ACK_STATE_UNKNOWN)
+ break;
+ GestureEventWithLatencyInfoAndAckState event = *iter;
+ coalesced_gesture_events_.erase(iter);
+ AckGestureEventToClient(event, event.ack_state());
+ }
+}
+
+void GestureEventQueue::AckGestureEventToClient(
+ const GestureEventWithLatencyInfo& event_with_latency,
+ InputEventAckState ack_result) {
+ DCHECK(allow_multiple_inflight_events_);
+
+ // Ack'ing an event may enqueue additional gesture events. By ack'ing the
+ // event before the forwarding of queued events below, such additional events
+ // can be coalesced with existing queued events prior to dispatch.
+ client_->OnGestureEventAck(event_with_latency, ack_result);
+
+ const bool processed = (INPUT_EVENT_ACK_STATE_CONSUMED == ack_result);
+ if (event_with_latency.event.GetType() ==
+ WebInputEvent::kGestureFlingCancel) {
+ fling_controller_.GestureFlingCancelAck(
+ event_with_latency.event.source_device, processed);
+ }
+}
+
+void GestureEventQueue::LegacyProcessGestureAck(
+ InputEventAckState ack_result,
+ WebInputEvent::Type type,
+ const ui::LatencyInfo& latency) {
+ DCHECK(!allow_multiple_inflight_events_);
+
+ // Events are forwarded one-by-one.
+ // It's possible that the ack for the second event in an in-flight,
+ // coalesced Gesture{Scroll,Pinch}Update pair is received prior to the first
+ // event ack.
+ size_t event_index = 0;
+ if (ignore_next_ack_ && coalesced_gesture_events_.size() > 1 &&
+ coalesced_gesture_events_[0].event.GetType() != type &&
+ coalesced_gesture_events_[1].event.GetType() == type) {
+ event_index = 1;
+ }
+
GestureEventWithLatencyInfo event_with_latency =
coalesced_gesture_events_[event_index];
DCHECK_EQ(event_with_latency.event.GetType(), type);
@@ -248,21 +258,13 @@ void GestureEventQueue::ProcessGestureAck(InputEventAckState ack_result,
const bool processed = (INPUT_EVENT_ACK_STATE_CONSUMED == ack_result);
if (type == WebInputEvent::kGestureFlingCancel) {
- if (event_with_latency.event.source_device ==
- blink::kWebGestureDeviceTouchscreen)
- touchscreen_tap_suppression_controller_.GestureFlingCancelAck(processed);
- else if (event_with_latency.event.source_device ==
- blink::kWebGestureDeviceTouchpad)
- touchpad_tap_suppression_controller_.GestureFlingCancelAck(processed);
+ fling_controller_.GestureFlingCancelAck(
+ event_with_latency.event.source_device, processed);
}
DCHECK_LT(event_index, coalesced_gesture_events_.size());
coalesced_gesture_events_.erase(coalesced_gesture_events_.begin() +
event_index);
- // Events have been forwarded already.
- if (allow_multiple_inflight_events_)
- return;
-
if (ignore_next_ack_) {
ignore_next_ack_ = false;
return;
@@ -293,7 +295,7 @@ void GestureEventQueue::ProcessGestureAck(InputEventAckState ack_result,
TouchpadTapSuppressionController*
GestureEventQueue::GetTouchpadTapSuppressionController() {
- return &touchpad_tap_suppression_controller_;
+ return fling_controller_.GetTouchpadTapSuppressionController();
}
void GestureEventQueue::FlingHasBeenHalted() {
@@ -313,8 +315,7 @@ void GestureEventQueue::SendScrollEndingEventsNow() {
debouncing_deferral_queue.swap(debouncing_deferral_queue_);
for (GestureQueue::const_iterator it = debouncing_deferral_queue.begin();
it != debouncing_deferral_queue.end(); it++) {
- if (ShouldForwardForGFCFiltering(*it) &&
- ShouldForwardForTapSuppression(*it)) {
+ if (!fling_controller_.FilterGestureEvent(*it)) {
QueueAndForwardIfNecessary(*it);
}
}
diff --git a/chromium/content/browser/renderer_host/input/gesture_event_queue.h b/chromium/content/browser/renderer_host/input/gesture_event_queue.h
index cad399c3e5f..de6f1274f1a 100644
--- a/chromium/content/browser/renderer_host/input/gesture_event_queue.h
+++ b/chromium/content/browser/renderer_host/input/gesture_event_queue.h
@@ -13,9 +13,7 @@
#include "base/macros.h"
#include "base/timer/timer.h"
#include "content/browser/renderer_host/event_with_latency_info.h"
-#include "content/browser/renderer_host/input/tap_suppression_controller.h"
-#include "content/browser/renderer_host/input/touchpad_tap_suppression_controller.h"
-#include "content/browser/renderer_host/input/touchscreen_tap_suppression_controller.h"
+#include "content/browser/renderer_host/input/fling_controller.h"
#include "content/common/content_export.h"
#include "content/common/input/input_event_ack_state.h"
#include "third_party/WebKit/public/platform/WebInputEvent.h"
@@ -44,11 +42,11 @@ class CONTENT_EXPORT GestureEventQueueClient {
// from the screen briefly during an in-progress scroll. Ifco this happens,
// non-GestureScrollUpdate events are queued until the de-bounce interval
// passes or another GestureScrollUpdate event occurs.
-// 2. Unnecessary GestureFlingCancel events are filtered. These are
-// GestureFlingCancels that have no corresponding GestureFlingStart in the
-// queue.
+// 2. Unnecessary GestureFlingCancel events are filtered by fling controller.
+// These are GestureFlingCancels that have no corresponding GestureFlingStart
+// in the queue.
// 3. Taps immediately after a GestureFlingCancel (caused by the same tap) are
-// filtered.
+// filtered by fling controller.
// 4. Whenever possible, events in the queue are coalesced to have as few events
// as possible and therefore maximize the chance that the event stream can be
// handled entirely by the compositor thread.
@@ -63,11 +61,7 @@ class CONTENT_EXPORT GestureEventQueue {
struct CONTENT_EXPORT Config {
Config();
- // Controls touchpad-related tap suppression, disabled by default.
- TapSuppressionController::Config touchpad_tap_suppression_config;
-
- // Controls touchscreen-related tap suppression, disabled by default.
- TapSuppressionController::Config touchscreen_tap_suppression_config;
+ FlingController::Config fling_config;
// Determines whether non-scroll gesture events are "debounced" during an
// active scroll sequence, suppressing brief scroll interruptions.
@@ -107,6 +101,11 @@ class CONTENT_EXPORT GestureEventQueue {
debouncing_deferral_queue_.empty();
}
+ // Returns |true| if the given GestureFlingCancel should be discarded
+ // as unnecessary.
+ bool ShouldDiscardFlingCancelEvent(
+ const GestureEventWithLatencyInfo& gesture_event) const;
+
void set_debounce_interval_time_ms_for_testing(int interval_ms) {
debounce_interval_ = base::TimeDelta::FromMilliseconds(interval_ms);
}
@@ -115,33 +114,27 @@ class CONTENT_EXPORT GestureEventQueue {
friend class GestureEventQueueTest;
friend class MockRenderWidgetHost;
- bool OnScrollBegin(const GestureEventWithLatencyInfo& gesture_event);
+ class GestureEventWithLatencyInfoAndAckState
+ : public GestureEventWithLatencyInfo {
+ public:
+ GestureEventWithLatencyInfoAndAckState(const GestureEventWithLatencyInfo&);
+ InputEventAckState ack_state() const { return ack_state_; }
+ void set_ack_state(InputEventAckState state) { ack_state_ = state; }
+
+ private:
+ InputEventAckState ack_state_ = INPUT_EVENT_ACK_STATE_UNKNOWN;
+ };
- // TODO(mohsen): There are a bunch of ShouldForward.../ShouldDiscard...
- // methods that are getting confusing. This should be somehow fixed. Maybe
- // while refactoring GEQ: http://crbug.com/148443.
+ bool OnScrollBegin(const GestureEventWithLatencyInfo& gesture_event);
// Inovked on the expiration of the debounce interval to release
// deferred events.
void SendScrollEndingEventsNow();
- // Returns |true| if the given GestureFlingCancel should be discarded
- // as unnecessary.
- bool ShouldDiscardFlingCancelEvent(
- const GestureEventWithLatencyInfo& gesture_event) const;
-
// Sub-filter for removing bounces from in-progress scrolls.
bool ShouldForwardForBounceReduction(
const GestureEventWithLatencyInfo& gesture_event);
- // Sub-filter for removing unnecessary GestureFlingCancels.
- bool ShouldForwardForGFCFiltering(
- const GestureEventWithLatencyInfo& gesture_event) const;
-
- // Sub-filter for suppressing taps immediately after a GestureFlingCancel.
- bool ShouldForwardForTapSuppression(
- const GestureEventWithLatencyInfo& gesture_event);
-
// Puts the events in a queue to forward them one by one; i.e., forward them
// whenever ACK for previous event is received. This queue also tries to
// coalesce events as much as possible.
@@ -153,6 +146,18 @@ class CONTENT_EXPORT GestureEventQueue {
void QueueScrollOrPinchAndForwardIfNecessary(
const GestureEventWithLatencyInfo& gesture_event);
+ // ACK completed events in order until we have reached an incomplete event.
+ // Will preserve the FIFO order as events originally arrived.
+ void AckCompletedEvents();
+ void AckGestureEventToClient(const GestureEventWithLatencyInfo&,
+ InputEventAckState);
+
+ // Used when |allow_multiple_inflight_events_| is false. Will only send next
+ // event after receiving ACK for the previous one.
+ void LegacyProcessGestureAck(InputEventAckState,
+ blink::WebInputEvent::Type,
+ const ui::LatencyInfo&);
+
// The number of sent events for which we're awaiting an ack. These events
// remain at the head of the queue until ack'ed.
size_t EventsInFlightCount() const;
@@ -176,27 +181,22 @@ class CONTENT_EXPORT GestureEventQueue {
// ack).
bool allow_multiple_inflight_events_;
- // An object tracking the state of touchpad on the delivery of mouse events to
- // the renderer to filter mouse immediately after a touchpad fling canceling
- // tap.
- // TODO(mohsen): Move touchpad tap suppression out of GestureEventQueue since
- // GEQ is meant to only be used for touchscreen gesture events.
- TouchpadTapSuppressionController touchpad_tap_suppression_controller_;
-
- // An object tracking the state of touchscreen on the delivery of gesture tap
- // events to the renderer to filter taps immediately after a touchscreen fling
- // canceling tap.
- TouchscreenTapSuppressionController touchscreen_tap_suppression_controller_;
+ bool processing_acks_ = false;
typedef std::deque<GestureEventWithLatencyInfo> GestureQueue;
-
- // Queue of coalesced gesture events not yet sent to the renderer. If
- // |ignore_next_ack_| is false, then the event at the front of the queue has
- // been sent and is awaiting an ACK, and all other events have yet to be sent.
- // If |ignore_next_ack_| is true, then the two events at the front of the
- // queue have been sent, and the second is awaiting an ACK. All other events
- // have yet to be sent.
- GestureQueue coalesced_gesture_events_;
+ typedef std::deque<GestureEventWithLatencyInfoAndAckState>
+ GestureQueueWithAckState;
+
+ // If |allow_multiple_inflight_events_|, |coalesced_gesture_events_| stores
+ // outstanding events that have been sent to the renderer but not yet been
+ // ACKed.
+ // Otherwise it stores coalesced gesture events not yet sent to the renderer.
+ // If |ignore_next_ack_| is false, then the event at the front of the queue
+ // has been sent and is awaiting an ACK, and all other events have yet to be
+ // sent. If |ignore_next_ack_| is true, then the two events at the front of
+ // the queue have been sent, and the second is awaiting an ACK. All other
+ // events have yet to be sent.
+ GestureQueueWithAckState coalesced_gesture_events_;
// Timer to release a previously deferred gesture event.
base::OneShotTimer debounce_deferring_timer_;
@@ -208,6 +208,11 @@ class CONTENT_EXPORT GestureEventQueue {
// of zero effectively disables debouncing.
base::TimeDelta debounce_interval_;
+ // An object for filtering unnecessary GFC events, as well as gestureTap/mouse
+ // events that happen immediately after touchscreen/touchpad fling canceling
+ // taps.
+ FlingController fling_controller_;
+
DISALLOW_COPY_AND_ASSIGN(GestureEventQueue);
};
diff --git a/chromium/content/browser/renderer_host/input/gesture_event_queue_unittest.cc b/chromium/content/browser/renderer_host/input/gesture_event_queue_unittest.cc
index 6f26aa1cf76..69d03e62ae7 100644
--- a/chromium/content/browser/renderer_host/input/gesture_event_queue_unittest.cc
+++ b/chromium/content/browser/renderer_host/input/gesture_event_queue_unittest.cc
@@ -19,6 +19,7 @@
#include "base/test/scoped_task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
+#include "content/browser/renderer_host/input/input_router_config_helper.h"
#include "content/browser/renderer_host/input/touchpad_tap_suppression_controller.h"
#include "content/common/input/input_event_ack_state.h"
#include "content/common/input/synthetic_web_input_event_builders.h"
@@ -63,6 +64,20 @@ class GestureEventQueueTest : public testing::Test,
queue_.reset();
}
+ void SetUpForTapSuppression(int max_cancel_to_down_time_ms,
+ int max_tap_gap_time_ms) {
+ GestureEventQueue::Config gesture_config;
+ gesture_config.fling_config.touchscreen_tap_suppression_config.enabled =
+ true;
+ gesture_config.fling_config.touchscreen_tap_suppression_config
+ .max_cancel_to_down_time =
+ base::TimeDelta::FromMilliseconds(max_cancel_to_down_time_ms);
+ gesture_config.fling_config.touchscreen_tap_suppression_config
+ .max_tap_gap_time =
+ base::TimeDelta::FromMilliseconds(max_tap_gap_time_ms);
+ queue_.reset(new GestureEventQueue(this, this, gesture_config));
+ }
+
// GestureEventQueueClient
void SendGestureEventImmediately(
const GestureEventWithLatencyInfo& event) override {
@@ -1221,6 +1236,40 @@ TEST_F(GestureEventQueueTest, DebounceDropsDeferredEvents) {
}
}
+// Test that the fling cancelling tap down event and its following tap get
+// suppressed when tap suppression is enabled.
+TEST_F(GestureEventQueueTest, TapGetsSuppressedAfterTapDownCancellsFling) {
+ SetUpForTapSuppression(400, 200);
+ SimulateGestureFlingStartEvent(0, -10, blink::kWebGestureDeviceTouchscreen);
+ EXPECT_TRUE(FlingInProgress());
+ SendInputEventACK(WebInputEvent::kGestureFlingStart,
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(1U, GetAndResetSentGestureEventCount());
+ EXPECT_EQ(1U, GetAndResetAckedGestureEventCount());
+ RunUntilIdle();
+
+ SimulateGestureEvent(WebInputEvent::kGestureFlingCancel,
+ blink::kWebGestureDeviceTouchscreen);
+ EXPECT_FALSE(FlingInProgress());
+ EXPECT_EQ(1U, GetAndResetSentGestureEventCount());
+ EXPECT_EQ(1U, GestureEventQueueSize());
+ RunUntilIdle();
+
+ // Simulate a fling cancelling tap down by sending a gesture tap down event
+ // before arrival of the fling cancel ack. The tap down must get suppressed.
+ SimulateGestureEvent(WebInputEvent::kGestureTapDown,
+ blink::kWebGestureDeviceTouchscreen);
+ SendInputEventACK(WebInputEvent::kGestureFlingCancel,
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(0U, GestureEventQueueSize());
+
+ // The tap event must get suppressed since its corresponding tap down event
+ // is suppressed.
+ SimulateGestureEvent(WebInputEvent::kGestureTap,
+ blink::kWebGestureDeviceTouchscreen);
+ EXPECT_EQ(0U, GestureEventQueueSize());
+}
+
TEST_F(GestureEventQueueTest, CoalescesSyntheticScrollBeginEndEvents) {
// Test coalescing of only GestureScrollBegin/End events.
SimulateGestureEvent(WebInputEvent::kGestureScrollUpdate,
@@ -1247,6 +1296,39 @@ TEST_F(GestureEventQueueTest, CoalescesSyntheticScrollBeginEndEvents) {
}
TEST_F(GestureEventQueueWithCompositorEventQueueTest,
+ PreserveOrderWithOutOfOrderAck) {
+ // Simulate a scroll sequence, events should be ACKed in original order.
+ SimulateGestureEvent(WebInputEvent::kGestureScrollBegin,
+ blink::kWebGestureDeviceTouchscreen);
+ SimulateGestureScrollUpdateEvent(8, -4, 1);
+ SimulateGestureEvent(WebInputEvent::kGestureScrollEnd,
+ blink::kWebGestureDeviceTouchscreen);
+
+ // All events should have been sent.
+ EXPECT_EQ(3U, GetAndResetSentGestureEventCount());
+
+ // Simulate GSB ACK.
+ SendInputEventACK(WebInputEvent::kGestureScrollBegin,
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(WebInputEvent::kGestureScrollBegin, last_acked_event().GetType());
+ EXPECT_EQ(2U, GestureEventQueueSize());
+
+ // Simulate GSE ACK first since it's usually dispatched non-blocking.
+ SendInputEventACK(WebInputEvent::kGestureScrollEnd,
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ // GSE ACK will be cached in GestureEventQueue since we haven't ACKed GSU yet.
+ EXPECT_EQ(WebInputEvent::kGestureScrollBegin, last_acked_event().GetType());
+ EXPECT_EQ(2U, GestureEventQueueSize());
+
+ // Simulate GSU ACK.
+ SendInputEventACK(WebInputEvent::kGestureScrollUpdate,
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ // Both ACKs should be released in order.
+ EXPECT_EQ(WebInputEvent::kGestureScrollEnd, last_acked_event().GetType());
+ EXPECT_EQ(0U, GestureEventQueueSize());
+}
+
+TEST_F(GestureEventQueueWithCompositorEventQueueTest,
MultipleGesturesInFlight) {
// Simulate a pinch sequence, events should be forwarded immediately.
SimulateGestureEvent(WebInputEvent::kGestureScrollBegin,
diff --git a/chromium/content/browser/renderer_host/input/input_ack_handler.h b/chromium/content/browser/renderer_host/input/input_disposition_handler.h
index 63fa500333c..eb7d7e0c891 100644
--- a/chromium/content/browser/renderer_host/input/input_ack_handler.h
+++ b/chromium/content/browser/renderer_host/input/input_disposition_handler.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_INPUT_INPUT_ACK_HANDLER_H_
-#define CONTENT_BROWSER_RENDERER_HOST_INPUT_INPUT_ACK_HANDLER_H_
+#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_INPUT_DISPOSITION_HANDLER_H_
+#define CONTENT_BROWSER_RENDERER_HOST_INPUT_INPUT_DISPOSITION_HANDLER_H_
#include "content/browser/renderer_host/event_with_latency_info.h"
#include "content/common/input/input_event_ack_state.h"
@@ -12,10 +12,10 @@
namespace content {
-// Provided customized ack response for input events.
-class CONTENT_EXPORT InputAckHandler {
+// Provided customized disposition response for input events.
+class CONTENT_EXPORT InputDispositionHandler {
public:
- virtual ~InputAckHandler() {}
+ virtual ~InputDispositionHandler() {}
// Called upon event ack receipt from the renderer.
virtual void OnKeyboardEventAck(
@@ -38,6 +38,6 @@ class CONTENT_EXPORT InputAckHandler {
virtual void OnUnexpectedEventAck(UnexpectedEventAckType type) = 0;
};
-} // namespace content
+} // namespace content
-#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_INPUT_ACK_HANDLER_H_
+#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_INPUT_DISPOSITION_HANDLER_H_
diff --git a/chromium/content/browser/renderer_host/input/input_router.h b/chromium/content/browser/renderer_host/input/input_router.h
index 47e3b0c84c6..e1f30c9a51b 100644
--- a/chromium/content/browser/renderer_host/input/input_router.h
+++ b/chromium/content/browser/renderer_host/input/input_router.h
@@ -42,9 +42,6 @@ class InputRouter : public IPC::Listener {
virtual void SendTouchEvent(
const TouchEventWithLatencyInfo& touch_event) = 0;
- // Returns the oldest queued or in-flight keyboard event sent to the router.
- virtual const NativeWebKeyboardEvent* GetLastKeyboardEvent() const = 0;
-
// Notify the router about whether the current page is mobile-optimized (i.e.,
// the site has a mobile-friendly viewport).
virtual void NotifySiteIsMobileOptimized(bool is_mobile_optimized) = 0;
@@ -62,6 +59,8 @@ class InputRouter : public IPC::Listener {
// Return the currently allowed touch-action.
virtual cc::TouchAction AllowedTouchAction() = 0;
+
+ virtual void SetForceEnableZoom(bool enabled) = 0;
};
} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/input_router_config_helper.cc b/chromium/content/browser/renderer_host/input/input_router_config_helper.cc
index c0fb67d4060..f5db6a741af 100644
--- a/chromium/content/browser/renderer_host/input/input_router_config_helper.cc
+++ b/chromium/content/browser/renderer_host/input/input_router_config_helper.cc
@@ -50,11 +50,11 @@ GestureEventQueue::Config GetGestureEventQueueConfig() {
config.debounce_interval = base::TimeDelta::FromMilliseconds(
gesture_config->scroll_debounce_interval_in_ms());
- config.touchscreen_tap_suppression_config.enabled =
+ config.fling_config.touchscreen_tap_suppression_config.enabled =
gesture_config->fling_touchscreen_tap_suppression_enabled();
- config.touchscreen_tap_suppression_config.max_cancel_to_down_time =
- base::TimeDelta::FromMilliseconds(
- gesture_config->fling_max_cancel_to_down_time_in_ms());
+ config.fling_config.touchscreen_tap_suppression_config
+ .max_cancel_to_down_time = base::TimeDelta::FromMilliseconds(
+ gesture_config->fling_max_cancel_to_down_time_in_ms());
// Tap suppression controller forwards the stashed tapDown and drops the rest
// of the stashed events when the tapDownTimer expires. If a fling cancel ack
@@ -62,16 +62,16 @@ GestureEventQueue::Config GetGestureEventQueueConfig() {
// events will be forwarded. The timer is used to avoid waiting for an
// arbitrarily late fling cancel ack. Its delay should be large enough for
// a long press to get stashed and forwarded if needed.
- config.touchscreen_tap_suppression_config.max_tap_gap_time =
+ config.fling_config.touchscreen_tap_suppression_config.max_tap_gap_time =
base::TimeDelta::FromMilliseconds(
gesture_config->long_press_time_in_ms() + 50);
- config.touchpad_tap_suppression_config.enabled =
+ config.fling_config.touchpad_tap_suppression_config.enabled =
gesture_config->fling_touchpad_tap_suppression_enabled();
- config.touchpad_tap_suppression_config.max_cancel_to_down_time =
+ config.fling_config.touchpad_tap_suppression_config.max_cancel_to_down_time =
base::TimeDelta::FromMilliseconds(
gesture_config->fling_max_cancel_to_down_time_in_ms());
- config.touchpad_tap_suppression_config.max_tap_gap_time =
+ config.fling_config.touchpad_tap_suppression_config.max_tap_gap_time =
base::TimeDelta::FromMilliseconds(
gesture_config->fling_max_tap_gap_time_in_ms());
diff --git a/chromium/content/browser/renderer_host/input/input_router_impl.cc b/chromium/content/browser/renderer_host/input/input_router_impl.cc
new file mode 100644
index 00000000000..0b60ae46213
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/input_router_impl.cc
@@ -0,0 +1,564 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/input/input_router_impl.h"
+
+#include <math.h>
+
+#include <utility>
+
+#include "base/auto_reset.h"
+#include "base/command_line.h"
+#include "base/memory/ptr_util.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/strings/string_number_conversions.h"
+#include "content/browser/renderer_host/input/gesture_event_queue.h"
+#include "content/browser/renderer_host/input/input_disposition_handler.h"
+#include "content/browser/renderer_host/input/input_router_client.h"
+#include "content/browser/renderer_host/input/legacy_touch_event_queue.h"
+#include "content/browser/renderer_host/input/passthrough_touch_event_queue.h"
+#include "content/browser/renderer_host/input/touch_event_queue.h"
+#include "content/browser/renderer_host/input/touchpad_tap_suppression_controller.h"
+#include "content/common/content_constants_internal.h"
+#include "content/common/edit_command.h"
+#include "content/common/input/input_event_ack_state.h"
+#include "content/common/input/input_handler.mojom.h"
+#include "content/common/input/web_touch_event_traits.h"
+#include "content/common/input_messages.h"
+#include "content/common/view_messages.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/browser/notification_types.h"
+#include "content/public/common/content_features.h"
+#include "content/public/common/content_switches.h"
+#include "ipc/ipc_sender.h"
+#include "ui/events/blink/blink_event_util.h"
+#include "ui/events/blink/web_input_event_traits.h"
+#include "ui/events/event.h"
+#include "ui/events/keycodes/keyboard_codes.h"
+
+using base::Time;
+using base::TimeDelta;
+using base::TimeTicks;
+using blink::WebGestureEvent;
+using blink::WebInputEvent;
+using blink::WebKeyboardEvent;
+using blink::WebMouseEvent;
+using blink::WebMouseWheelEvent;
+using blink::WebTouchEvent;
+using ui::WebInputEventTraits;
+
+namespace content {
+namespace {
+
+const char* GetEventAckName(InputEventAckState ack_result) {
+ switch (ack_result) {
+ case INPUT_EVENT_ACK_STATE_UNKNOWN:
+ return "UNKNOWN";
+ case INPUT_EVENT_ACK_STATE_CONSUMED:
+ return "CONSUMED";
+ case INPUT_EVENT_ACK_STATE_NOT_CONSUMED:
+ return "NOT_CONSUMED";
+ case INPUT_EVENT_ACK_STATE_CONSUMED_SHOULD_BUBBLE:
+ return "CONSUMED_SHOULD_BUBBLE";
+ case INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS:
+ return "NO_CONSUMER_EXISTS";
+ case INPUT_EVENT_ACK_STATE_IGNORED:
+ return "IGNORED";
+ case INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING:
+ return "SET_NON_BLOCKING";
+ case INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING_DUE_TO_FLING:
+ return "SET_NON_BLOCKING_DUE_TO_FLING";
+ }
+ DLOG(WARNING) << "Unhandled InputEventAckState in GetEventAckName.";
+ return "";
+}
+
+bool WasHandled(InputEventAckState state) {
+ switch (state) {
+ case INPUT_EVENT_ACK_STATE_CONSUMED:
+ case INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS:
+ case INPUT_EVENT_ACK_STATE_UNKNOWN:
+ return true;
+ default:
+ return false;
+ }
+}
+
+ui::WebScopedInputEvent ScaleEvent(const WebInputEvent& event, double scale) {
+ std::unique_ptr<blink::WebInputEvent> event_in_viewport =
+ ui::ScaleWebInputEvent(event, scale);
+ if (event_in_viewport)
+ return ui::WebScopedInputEvent(event_in_viewport.release());
+ return ui::WebInputEventTraits::Clone(event);
+}
+
+} // namespace
+
+InputRouterImpl::InputRouterImpl(InputRouterImplClient* client,
+ InputDispositionHandler* disposition_handler,
+ const Config& config)
+ : client_(client),
+ disposition_handler_(disposition_handler),
+ frame_tree_node_id_(-1),
+ active_renderer_fling_count_(0),
+ touch_scroll_started_sent_(false),
+ wheel_scroll_latching_enabled_(base::FeatureList::IsEnabled(
+ features::kTouchpadAndWheelScrollLatching)),
+ raf_aligned_touch_enabled_(
+ base::FeatureList::IsEnabled(features::kRafAlignedTouchInputEvents)),
+ wheel_event_queue_(this, wheel_scroll_latching_enabled_),
+ gesture_event_queue_(this, this, config.gesture_config),
+ device_scale_factor_(1.f),
+ weak_ptr_factory_(this) {
+ weak_this_ = weak_ptr_factory_.GetWeakPtr();
+
+ if (raf_aligned_touch_enabled_) {
+ touch_event_queue_.reset(
+ new PassthroughTouchEventQueue(this, config.touch_config));
+ } else {
+ touch_event_queue_.reset(
+ new LegacyTouchEventQueue(this, config.touch_config));
+ }
+
+ DCHECK(client);
+ DCHECK(disposition_handler);
+ UpdateTouchAckTimeoutEnabled();
+}
+
+InputRouterImpl::~InputRouterImpl() {}
+
+void InputRouterImpl::SendMouseEvent(
+ const MouseEventWithLatencyInfo& mouse_event) {
+ if (mouse_event.event.GetType() == WebInputEvent::kMouseDown &&
+ gesture_event_queue_.GetTouchpadTapSuppressionController()
+ ->ShouldDeferMouseDown(mouse_event))
+ return;
+ if (mouse_event.event.GetType() == WebInputEvent::kMouseUp &&
+ gesture_event_queue_.GetTouchpadTapSuppressionController()
+ ->ShouldSuppressMouseUp())
+ return;
+
+ SendMouseEventImmediately(mouse_event);
+}
+
+void InputRouterImpl::SendWheelEvent(
+ const MouseWheelEventWithLatencyInfo& wheel_event) {
+ wheel_event_queue_.QueueEvent(wheel_event);
+}
+
+void InputRouterImpl::SendKeyboardEvent(
+ const NativeWebKeyboardEventWithLatencyInfo& key_event) {
+ gesture_event_queue_.FlingHasBeenHalted();
+ mojom::WidgetInputHandler::DispatchEventCallback callback = base::BindOnce(
+ &InputRouterImpl::KeyboardEventHandled, weak_this_, key_event);
+ FilterAndSendWebInputEvent(key_event.event, key_event.latency,
+ std::move(callback));
+}
+
+void InputRouterImpl::KeyboardEventHandled(
+ const NativeWebKeyboardEventWithLatencyInfo& event,
+ InputEventAckSource source,
+ const ui::LatencyInfo& latency,
+ InputEventAckState state,
+ const base::Optional<ui::DidOverscrollParams>& overscroll,
+ const base::Optional<cc::TouchAction>& touch_action) {
+ TRACE_EVENT2("input", "InputRouterImpl::KeboardEventHandled", "type",
+ WebInputEvent::GetName(event.event.GetType()), "ack",
+ GetEventAckName(state));
+
+ if (source != InputEventAckSource::BROWSER)
+ client_->DecrementInFlightEventCount(source);
+ event.latency.AddNewLatencyFrom(latency);
+ disposition_handler_->OnKeyboardEventAck(event, state);
+
+ // WARNING: This InputRouterImpl can be deallocated at this point
+ // (i.e. in the case of Ctrl+W, where the call to
+ // HandleKeyboardEvent destroys this InputRouterImpl).
+ // TODO(jdduke): crbug.com/274029 - Make ack-triggered shutdown async.
+}
+
+void InputRouterImpl::SendGestureEvent(
+ const GestureEventWithLatencyInfo& original_gesture_event) {
+ input_stream_validator_.Validate(original_gesture_event.event);
+
+ GestureEventWithLatencyInfo gesture_event(original_gesture_event);
+
+ if (touch_action_filter_.FilterGestureEvent(&gesture_event.event))
+ return;
+
+ wheel_event_queue_.OnGestureScrollEvent(gesture_event);
+
+ if (gesture_event.event.source_device ==
+ blink::kWebGestureDeviceTouchscreen) {
+ if (gesture_event.event.GetType() ==
+ blink::WebInputEvent::kGestureScrollBegin) {
+ touch_scroll_started_sent_ = false;
+ } else if (!touch_scroll_started_sent_ &&
+ gesture_event.event.GetType() ==
+ blink::WebInputEvent::kGestureScrollUpdate) {
+ // A touch scroll hasn't really started until the first
+ // GestureScrollUpdate event. Eg. if the page consumes all touchmoves
+ // then no scrolling really ever occurs (even though we still send
+ // GestureScrollBegin).
+ touch_scroll_started_sent_ = true;
+ touch_event_queue_->PrependTouchScrollNotification();
+ }
+ touch_event_queue_->OnGestureScrollEvent(gesture_event);
+ }
+
+ gesture_event_queue_.QueueEvent(gesture_event);
+}
+
+void 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);
+}
+
+// Forwards MouseEvent without passing it through
+// TouchpadTapSuppressionController.
+void InputRouterImpl::SendMouseEventImmediately(
+ const MouseEventWithLatencyInfo& mouse_event) {
+ mojom::WidgetInputHandler::DispatchEventCallback callback = base::BindOnce(
+ &InputRouterImpl::MouseEventHandled, weak_this_, mouse_event);
+ FilterAndSendWebInputEvent(mouse_event.event, mouse_event.latency,
+ std::move(callback));
+}
+
+void InputRouterImpl::MouseEventHandled(
+ const MouseEventWithLatencyInfo& event,
+ InputEventAckSource source,
+ const ui::LatencyInfo& latency,
+ InputEventAckState state,
+ const base::Optional<ui::DidOverscrollParams>& overscroll,
+ const base::Optional<cc::TouchAction>& touch_action) {
+ TRACE_EVENT2("input", "InputRouterImpl::MouseEventHandled", "type",
+ WebInputEvent::GetName(event.event.GetType()), "ack",
+ GetEventAckName(state));
+
+ if (source != InputEventAckSource::BROWSER)
+ client_->DecrementInFlightEventCount(source);
+ event.latency.AddNewLatencyFrom(latency);
+ disposition_handler_->OnMouseEventAck(event, state);
+}
+
+void InputRouterImpl::SendTouchEventImmediately(
+ const TouchEventWithLatencyInfo& touch_event) {
+ mojom::WidgetInputHandler::DispatchEventCallback callback = base::BindOnce(
+ &InputRouterImpl::TouchEventHandled, weak_this_, touch_event);
+ FilterAndSendWebInputEvent(touch_event.event, touch_event.latency,
+ std::move(callback));
+}
+
+void InputRouterImpl::TouchEventHandled(
+ const TouchEventWithLatencyInfo& touch_event,
+ InputEventAckSource source,
+ const ui::LatencyInfo& latency,
+ InputEventAckState state,
+ const base::Optional<ui::DidOverscrollParams>& overscroll,
+ const base::Optional<cc::TouchAction>& touch_action) {
+ TRACE_EVENT2("input", "InputRouterImpl::TouchEventHandled", "type",
+ WebInputEvent::GetName(touch_event.event.GetType()), "ack",
+ GetEventAckName(state));
+ if (source != InputEventAckSource::BROWSER)
+ client_->DecrementInFlightEventCount(source);
+ touch_event.latency.AddNewLatencyFrom(latency);
+
+ // The SetTouchAction IPC occurs on a different channel so always
+ // send it in the input event ack to ensure it is available at the
+ // time the ACK is handled.
+ if (touch_action.has_value())
+ OnSetTouchAction(touch_action.value());
+
+ // |touch_event_queue_| will forward to OnTouchEventAck when appropriate.
+ touch_event_queue_->ProcessTouchAck(state, latency,
+ touch_event.event.unique_touch_event_id);
+}
+
+void InputRouterImpl::OnTouchEventAck(const TouchEventWithLatencyInfo& event,
+ InputEventAckState ack_result) {
+ // Touchstart events sent to the renderer indicate a new touch sequence, but
+ // in some cases we may filter out sending the touchstart - catch those here.
+ if (WebTouchEventTraits::IsTouchSequenceStart(event.event) &&
+ ack_result == INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS) {
+ touch_action_filter_.ResetTouchAction();
+ UpdateTouchAckTimeoutEnabled();
+ }
+ disposition_handler_->OnTouchEventAck(event, ack_result);
+
+ // Reset the touch action at the end of a touch-action sequence.
+ if (WebTouchEventTraits::IsTouchSequenceEnd(event.event)) {
+ touch_action_filter_.ResetTouchAction();
+ UpdateTouchAckTimeoutEnabled();
+ }
+}
+
+void InputRouterImpl::SendGestureEventImmediately(
+ const GestureEventWithLatencyInfo& gesture_event) {
+ mojom::WidgetInputHandler::DispatchEventCallback callback = base::BindOnce(
+ &InputRouterImpl::GestureEventHandled, weak_this_, gesture_event);
+ FilterAndSendWebInputEvent(gesture_event.event, gesture_event.latency,
+ std::move(callback));
+}
+
+void InputRouterImpl::GestureEventHandled(
+ const GestureEventWithLatencyInfo& gesture_event,
+ InputEventAckSource source,
+ const ui::LatencyInfo& latency,
+ InputEventAckState state,
+ const base::Optional<ui::DidOverscrollParams>& overscroll,
+ const base::Optional<cc::TouchAction>& touch_action) {
+ TRACE_EVENT2("input", "InputRouterImpl::GestureEventHandled", "type",
+ WebInputEvent::GetName(gesture_event.event.GetType()), "ack",
+ GetEventAckName(state));
+ if (source != InputEventAckSource::BROWSER)
+ client_->DecrementInFlightEventCount(source);
+ if (gesture_event.event.GetType() ==
+ blink::WebInputEvent::kGestureFlingStart &&
+ state == INPUT_EVENT_ACK_STATE_CONSUMED) {
+ ++active_renderer_fling_count_;
+ }
+
+ if (overscroll) {
+ DCHECK_EQ(WebInputEvent::kGestureScrollUpdate,
+ gesture_event.event.GetType());
+ OnDidOverscroll(overscroll.value());
+ }
+
+ // |gesture_event_queue_| will forward to OnGestureEventAck when appropriate.
+ gesture_event_queue_.ProcessGestureAck(state, gesture_event.event.GetType(),
+ latency);
+}
+
+void InputRouterImpl::NotifySiteIsMobileOptimized(bool is_mobile_optimized) {
+ touch_event_queue_->SetIsMobileOptimizedSite(is_mobile_optimized);
+}
+
+bool InputRouterImpl::HasPendingEvents() const {
+ return !touch_event_queue_->Empty() || !gesture_event_queue_.empty() ||
+ wheel_event_queue_.has_pending() || active_renderer_fling_count_ > 0;
+}
+
+void InputRouterImpl::SetDeviceScaleFactor(float device_scale_factor) {
+ device_scale_factor_ = device_scale_factor;
+}
+
+bool InputRouterImpl::OnMessageReceived(const IPC::Message& message) {
+ // TODO(dtapuska): Move these to mojo
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(InputRouterImpl, message)
+ IPC_MESSAGE_HANDLER(InputHostMsg_DidOverscroll, OnDidOverscroll)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_HasTouchEventHandlers,
+ OnHasTouchEventHandlers)
+ IPC_MESSAGE_HANDLER(InputHostMsg_SetTouchAction, OnSetTouchAction)
+ IPC_MESSAGE_HANDLER(InputHostMsg_SetWhiteListedTouchAction,
+ OnSetWhiteListedTouchAction)
+ IPC_MESSAGE_HANDLER(InputHostMsg_DidStopFlinging, OnDidStopFlinging)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+
+ return handled;
+}
+
+void InputRouterImpl::OnFilteringTouchEvent(const WebTouchEvent& touch_event) {
+ // The event stream given to the renderer is not guaranteed to be
+ // valid based on the current TouchEventStreamValidator rules. This event will
+ // never be given to the renderer, but in order to ensure that the event
+ // stream |output_stream_validator_| sees is valid, we give events which are
+ // filtered out to the validator. crbug.com/589111 proposes adding an
+ // additional validator for the events which are actually sent to the
+ // renderer.
+ output_stream_validator_.Validate(touch_event);
+}
+
+void InputRouterImpl::OnGestureEventAck(
+ const GestureEventWithLatencyInfo& event,
+ InputEventAckState ack_result) {
+ touch_event_queue_->OnGestureEventAck(event, ack_result);
+ disposition_handler_->OnGestureEventAck(event, ack_result);
+}
+
+void InputRouterImpl::ForwardGestureEventWithLatencyInfo(
+ const blink::WebGestureEvent& event,
+ const ui::LatencyInfo& latency_info) {
+ client_->ForwardGestureEventWithLatencyInfo(event, latency_info);
+}
+
+void InputRouterImpl::SendMouseWheelEventImmediately(
+ const MouseWheelEventWithLatencyInfo& wheel_event) {
+ mojom::WidgetInputHandler::DispatchEventCallback callback = base::BindOnce(
+ &InputRouterImpl::MouseWheelEventHandled, weak_this_, wheel_event);
+ FilterAndSendWebInputEvent(wheel_event.event, wheel_event.latency,
+ std::move(callback));
+}
+
+void InputRouterImpl::MouseWheelEventHandled(
+ const MouseWheelEventWithLatencyInfo& event,
+ InputEventAckSource source,
+ const ui::LatencyInfo& latency,
+ InputEventAckState state,
+ const base::Optional<ui::DidOverscrollParams>& overscroll,
+ const base::Optional<cc::TouchAction>& touch_action) {
+ TRACE_EVENT2("input", "InputRouterImpl::MouseWheelEventHandled", "type",
+ WebInputEvent::GetName(event.event.GetType()), "ack",
+ GetEventAckName(state));
+ if (source != InputEventAckSource::BROWSER)
+ client_->DecrementInFlightEventCount(source);
+ event.latency.AddNewLatencyFrom(latency);
+
+ if (overscroll)
+ OnDidOverscroll(overscroll.value());
+
+ wheel_event_queue_.ProcessMouseWheelAck(state, event.latency);
+}
+
+void InputRouterImpl::OnMouseWheelEventAck(
+ const MouseWheelEventWithLatencyInfo& event,
+ InputEventAckState ack_result) {
+ disposition_handler_->OnWheelEventAck(event, ack_result);
+}
+
+void InputRouterImpl::FilterAndSendWebInputEvent(
+ const WebInputEvent& input_event,
+ const ui::LatencyInfo& latency_info,
+ mojom::WidgetInputHandler::DispatchEventCallback callback) {
+ TRACE_EVENT1("input", "InputRouterImpl::FilterAndSendWebInputEvent", "type",
+ WebInputEvent::GetName(input_event.GetType()));
+ TRACE_EVENT_WITH_FLOW2(
+ "input,benchmark,devtools.timeline", "LatencyInfo.Flow",
+ TRACE_ID_DONT_MANGLE(latency_info.trace_id()),
+ TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, "step",
+ "SendInputEventUI", "frameTreeNodeId", frame_tree_node_id_);
+
+ output_stream_validator_.Validate(input_event);
+ InputEventAckState filtered_state =
+ client_->FilterInputEvent(input_event, latency_info);
+ if (WasHandled(filtered_state)) {
+ if (filtered_state != INPUT_EVENT_ACK_STATE_UNKNOWN) {
+ std::move(callback).Run(InputEventAckSource::BROWSER, latency_info,
+ filtered_state, base::nullopt, base::nullopt);
+ }
+ return;
+ }
+
+ std::unique_ptr<InputEvent> event = base::MakeUnique<InputEvent>(
+ ScaleEvent(input_event, device_scale_factor_), latency_info);
+ if (WebInputEventTraits::ShouldBlockEventStream(
+ input_event, raf_aligned_touch_enabled_,
+ wheel_scroll_latching_enabled_)) {
+ client_->IncrementInFlightEventCount(input_event.GetType());
+ client_->GetWidgetInputHandler()->DispatchEvent(std::move(event),
+ std::move(callback));
+ } else {
+ client_->GetWidgetInputHandler()->DispatchNonBlockingEvent(
+ std::move(event));
+ std::move(callback).Run(InputEventAckSource::BROWSER, latency_info,
+ INPUT_EVENT_ACK_STATE_IGNORED, base::nullopt,
+ base::nullopt);
+ }
+}
+
+void InputRouterImpl::OnDidOverscroll(const ui::DidOverscrollParams& params) {
+ client_->DidOverscroll(params);
+}
+
+void InputRouterImpl::OnHasTouchEventHandlers(bool has_handlers) {
+ TRACE_EVENT1("input", "InputRouterImpl::OnHasTouchEventHandlers",
+ "has_handlers", has_handlers);
+
+ // Lack of a touch handler indicates that the page either has no touch-action
+ // modifiers or that all its touch-action modifiers are auto. Resetting the
+ // touch-action here allows forwarding of subsequent gestures even if the
+ // underlying touches never reach the router.
+ if (!has_handlers)
+ touch_action_filter_.ResetTouchAction();
+
+ touch_event_queue_->OnHasTouchEventHandlers(has_handlers);
+ client_->OnHasTouchEventHandlers(has_handlers);
+}
+
+void InputRouterImpl::OnSetTouchAction(cc::TouchAction touch_action) {
+ // Synthetic touchstart events should get filtered out in RenderWidget.
+ DCHECK(touch_event_queue_->IsPendingAckTouchStart());
+ TRACE_EVENT1("input", "InputRouterImpl::OnSetTouchAction", "action",
+ touch_action);
+
+ touch_action_filter_.OnSetTouchAction(touch_action);
+
+ // kTouchActionNone should disable the touch ack timeout.
+ UpdateTouchAckTimeoutEnabled();
+}
+
+void InputRouterImpl::OnSetWhiteListedTouchAction(
+ cc::TouchAction white_listed_touch_action,
+ uint32_t unique_touch_event_id,
+ InputEventAckState ack_result) {
+ // TODO(hayleyferr): Catch the cases that we have filtered out sending the
+ // touchstart.
+
+ touch_action_filter_.OnSetWhiteListedTouchAction(white_listed_touch_action);
+ client_->OnSetWhiteListedTouchAction(white_listed_touch_action);
+}
+
+void InputRouterImpl::OnDidStopFlinging() {
+ DCHECK_GT(active_renderer_fling_count_, 0);
+ // Note that we're only guaranteed to get a fling end notification from the
+ // renderer, not from any other consumers. Consequently, the GestureEventQueue
+ // cannot use this bookkeeping for logic like tap suppression.
+ --active_renderer_fling_count_;
+ client_->DidStopFlinging();
+}
+
+void InputRouterImpl::UpdateTouchAckTimeoutEnabled() {
+ // kTouchActionNone will prevent scrolling, in which case the timeout serves
+ // little purpose. It's also a strong signal that touch handling is critical
+ // to page functionality, so the timeout could do more harm than good.
+ const bool touch_ack_timeout_enabled =
+ touch_action_filter_.allowed_touch_action() != cc::kTouchActionNone;
+ touch_event_queue_->SetAckTimeoutEnabled(touch_ack_timeout_enabled);
+}
+
+void InputRouterImpl::SetFrameTreeNodeId(int frame_tree_node_id) {
+ frame_tree_node_id_ = frame_tree_node_id;
+}
+
+cc::TouchAction InputRouterImpl::AllowedTouchAction() {
+ return touch_action_filter_.allowed_touch_action();
+}
+
+void InputRouterImpl::SetForceEnableZoom(bool enabled) {
+ touch_action_filter_.SetForceEnableZoom(enabled);
+}
+
+void InputRouterImpl::SetMovementXYForTouchPoints(blink::WebTouchEvent* event) {
+ for (size_t i = 0; i < event->touches_length; ++i) {
+ blink::WebTouchPoint* touch_point = &event->touches[i];
+ if (touch_point->state == blink::WebTouchPoint::kStateMoved) {
+ const gfx::Point& last_position = global_touch_position_[touch_point->id];
+ touch_point->movement_x =
+ touch_point->PositionInScreen().x - last_position.x();
+ touch_point->movement_y =
+ touch_point->PositionInScreen().y - last_position.y();
+ global_touch_position_[touch_point->id].SetPoint(
+ touch_point->PositionInScreen().x, touch_point->PositionInScreen().y);
+ } else {
+ touch_point->movement_x = 0;
+ touch_point->movement_y = 0;
+ if (touch_point->state == blink::WebTouchPoint::kStateReleased ||
+ touch_point->state == blink::WebTouchPoint::kStateCancelled) {
+ global_touch_position_.erase(touch_point->id);
+ } else if (touch_point->state == blink::WebTouchPoint::kStatePressed) {
+ DCHECK(global_touch_position_.find(touch_point->id) ==
+ global_touch_position_.end());
+ global_touch_position_[touch_point->id] =
+ gfx::Point(touch_point->PositionInScreen().x,
+ touch_point->PositionInScreen().y);
+ }
+ }
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/input_router_impl.h b/chromium/content/browser/renderer_host/input/input_router_impl.h
new file mode 100644
index 00000000000..2748e0bfe8e
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/input_router_impl.h
@@ -0,0 +1,234 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_INPUT_ROUTER_IMPL_H_
+#define CONTENT_BROWSER_RENDERER_HOST_INPUT_INPUT_ROUTER_IMPL_H_
+
+#include <stdint.h>
+
+#include <memory>
+#include <queue>
+
+#include "base/containers/flat_map.h"
+#include "base/gtest_prod_util.h"
+#include "base/macros.h"
+#include "base/time/time.h"
+#include "cc/input/touch_action.h"
+#include "content/browser/renderer_host/input/gesture_event_queue.h"
+#include "content/browser/renderer_host/input/input_router.h"
+#include "content/browser/renderer_host/input/input_router_client.h"
+#include "content/browser/renderer_host/input/mouse_wheel_event_queue.h"
+#include "content/browser/renderer_host/input/touch_action_filter.h"
+#include "content/browser/renderer_host/input/touch_event_queue.h"
+#include "content/browser/renderer_host/input/touchpad_tap_suppression_controller.h"
+#include "content/common/input/input_event_ack_source.h"
+#include "content/common/input/input_event_stream_validator.h"
+#include "content/common/input/input_handler.mojom.h"
+#include "content/public/browser/native_web_keyboard_event.h"
+
+namespace ui {
+class LatencyInfo;
+struct DidOverscrollParams;
+} // namespace ui
+
+namespace content {
+
+class InputDispositionHandler;
+
+class CONTENT_EXPORT InputRouterImplClient : public InputRouterClient {
+ public:
+ virtual mojom::WidgetInputHandler* GetWidgetInputHandler() = 0;
+};
+
+// A default implementation for browser input event routing.
+class CONTENT_EXPORT InputRouterImpl
+ : public InputRouter,
+ public GestureEventQueueClient,
+ public MouseWheelEventQueueClient,
+ public TouchEventQueueClient,
+ public TouchpadTapSuppressionControllerClient {
+ public:
+ InputRouterImpl(InputRouterImplClient* client,
+ InputDispositionHandler* disposition_handler,
+ const Config& config);
+ ~InputRouterImpl() override;
+
+ // InputRouter
+ void SendMouseEvent(const MouseEventWithLatencyInfo& mouse_event) override;
+ void SendWheelEvent(
+ const MouseWheelEventWithLatencyInfo& wheel_event) override;
+ void SendKeyboardEvent(
+ const NativeWebKeyboardEventWithLatencyInfo& key_event) override;
+ void SendGestureEvent(
+ const GestureEventWithLatencyInfo& gesture_event) override;
+ void SendTouchEvent(const TouchEventWithLatencyInfo& touch_event) override;
+ void NotifySiteIsMobileOptimized(bool is_mobile_optimized) override;
+ bool HasPendingEvents() const override;
+ void SetDeviceScaleFactor(float device_scale_factor) override;
+
+ // IPC::Listener
+ bool OnMessageReceived(const IPC::Message& message) override;
+
+ void SetFrameTreeNodeId(int frame_tree_node_id) override;
+
+ void SetForceEnableZoom(bool enabled) override;
+
+ cc::TouchAction AllowedTouchAction() override;
+
+ private:
+ friend class InputRouterImplTest;
+
+ // Keeps track of last position of touch points and sets MovementXY for them.
+ void SetMovementXYForTouchPoints(blink::WebTouchEvent* event);
+
+ // TouchpadTapSuppressionControllerClient
+ void SendMouseEventImmediately(
+ const MouseEventWithLatencyInfo& mouse_event) override;
+
+ // TouchEventQueueClient
+ void SendTouchEventImmediately(
+ const TouchEventWithLatencyInfo& touch_event) override;
+ void OnTouchEventAck(const TouchEventWithLatencyInfo& event,
+ InputEventAckState ack_result) override;
+ void OnFilteringTouchEvent(const blink::WebTouchEvent& touch_event) override;
+
+ // GestureEventFilterClient
+ void SendGestureEventImmediately(
+ const GestureEventWithLatencyInfo& gesture_event) override;
+ void OnGestureEventAck(const GestureEventWithLatencyInfo& event,
+ InputEventAckState ack_result) override;
+
+ // MouseWheelEventQueueClient
+ void SendMouseWheelEventImmediately(
+ const MouseWheelEventWithLatencyInfo& touch_event) override;
+ void OnMouseWheelEventAck(const MouseWheelEventWithLatencyInfo& event,
+ InputEventAckState ack_result) override;
+ void ForwardGestureEventWithLatencyInfo(
+ const blink::WebGestureEvent& gesture_event,
+ const ui::LatencyInfo& latency_info) override;
+
+ bool SendMoveCaret(std::unique_ptr<IPC::Message> message);
+ bool SendSelectMessage(std::unique_ptr<IPC::Message> message);
+ bool Send(IPC::Message* message);
+
+ void FilterAndSendWebInputEvent(
+ const blink::WebInputEvent& input_event,
+ const ui::LatencyInfo& latency_info,
+ mojom::WidgetInputHandler::DispatchEventCallback callback);
+
+ void KeyboardEventHandled(
+ const NativeWebKeyboardEventWithLatencyInfo& event,
+ InputEventAckSource source,
+ const ui::LatencyInfo& latency,
+ InputEventAckState state,
+ const base::Optional<ui::DidOverscrollParams>& overscroll,
+ const base::Optional<cc::TouchAction>& touch_action);
+ void MouseEventHandled(
+ const MouseEventWithLatencyInfo& event,
+ InputEventAckSource source,
+ const ui::LatencyInfo& latency,
+ InputEventAckState state,
+ const base::Optional<ui::DidOverscrollParams>& overscroll,
+ const base::Optional<cc::TouchAction>& touch_action);
+ void TouchEventHandled(
+ const TouchEventWithLatencyInfo& touch_event,
+ InputEventAckSource source,
+ const ui::LatencyInfo& latency,
+ InputEventAckState state,
+ const base::Optional<ui::DidOverscrollParams>& overscroll,
+ const base::Optional<cc::TouchAction>& touch_action);
+ void GestureEventHandled(
+ const GestureEventWithLatencyInfo& gesture_event,
+ InputEventAckSource source,
+ const ui::LatencyInfo& latency,
+ InputEventAckState state,
+ const base::Optional<ui::DidOverscrollParams>& overscroll,
+ const base::Optional<cc::TouchAction>& touch_action);
+ void MouseWheelEventHandled(
+ const MouseWheelEventWithLatencyInfo& event,
+ InputEventAckSource source,
+ const ui::LatencyInfo& latency,
+ InputEventAckState state,
+ const base::Optional<ui::DidOverscrollParams>& overscroll,
+ const base::Optional<cc::TouchAction>& touch_action);
+
+ // IPC message handlers
+ void OnDidOverscroll(const ui::DidOverscrollParams& params);
+ void OnHasTouchEventHandlers(bool has_handlers);
+ void OnSetTouchAction(cc::TouchAction touch_action);
+ void OnSetWhiteListedTouchAction(cc::TouchAction white_listed_touch_action,
+ uint32_t unique_touch_event_id,
+ InputEventAckState ack_result);
+ void OnDidStopFlinging();
+
+ // Dispatches the ack'ed event to |ack_handler_|.
+ void ProcessKeyboardAck(blink::WebInputEvent::Type type,
+ InputEventAckState ack_result,
+ const ui::LatencyInfo& latency);
+
+ // Forwards a valid |next_mouse_move_| if |type| is MouseMove.
+ void ProcessMouseAck(blink::WebInputEvent::Type type,
+ InputEventAckState ack_result,
+ const ui::LatencyInfo& latency);
+
+ // Dispatches the ack'ed event to |ack_handler_|, forwarding queued events
+ // from |coalesced_mouse_wheel_events_|.
+ void ProcessWheelAck(InputEventAckState ack_result,
+ const ui::LatencyInfo& latency);
+
+ // Forwards the event ack to |gesture_event_queue|, potentially triggering
+ // dispatch of queued gesture events.
+ void ProcessGestureAck(blink::WebInputEvent::Type type,
+ InputEventAckState ack_result,
+ const ui::LatencyInfo& latency);
+
+ // Forwards the event ack to |touch_event_queue_|, potentially triggering
+ // dispatch of queued touch events, or the creation of gesture events.
+ void ProcessTouchAck(InputEventAckState ack_result,
+ const ui::LatencyInfo& latency,
+ uint32_t unique_touch_event_id);
+
+ // Called when a touch timeout-affecting bit has changed, in turn toggling the
+ // touch ack timeout feature of the |touch_event_queue_| as appropriate. Input
+ // to that determination includes current view properties and the allowed
+ // touch action. Note that this will only affect platforms that have a
+ // non-zero touch timeout configuration.
+ void UpdateTouchAckTimeoutEnabled();
+
+ InputRouterImplClient* client_;
+ InputDispositionHandler* disposition_handler_;
+ int frame_tree_node_id_;
+
+ // Whether there are any active flings in the renderer. As the fling
+ // end notification is asynchronous, we use a count rather than a boolean
+ // to avoid races in bookkeeping when starting a new fling.
+ int active_renderer_fling_count_;
+
+ // Whether the TouchScrollStarted event has been sent for the current
+ // gesture scroll yet.
+ bool touch_scroll_started_sent_;
+
+ bool wheel_scroll_latching_enabled_;
+ bool raf_aligned_touch_enabled_;
+ MouseWheelEventQueue wheel_event_queue_;
+ std::unique_ptr<TouchEventQueue> touch_event_queue_;
+ GestureEventQueue gesture_event_queue_;
+ TouchActionFilter touch_action_filter_;
+ InputEventStreamValidator input_stream_validator_;
+ InputEventStreamValidator output_stream_validator_;
+
+ float device_scale_factor_;
+
+ // Last touch position relative to screen. Used to compute movementX/Y.
+ base::flat_map<int, gfx::Point> global_touch_position_;
+
+ base::WeakPtr<InputRouterImpl> weak_this_;
+ base::WeakPtrFactory<InputRouterImpl> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(InputRouterImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_INPUT_ROUTER_IMPL_H_
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
new file mode 100644
index 00000000000..873e82f2ca0
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/input_router_impl_unittest.cc
@@ -0,0 +1,2364 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/input/input_router_impl.h"
+
+#include <math.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include <memory>
+#include <tuple>
+#include <vector>
+
+#include "base/command_line.h"
+#include "base/location.h"
+#include "base/macros.h"
+#include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
+#include "base/single_thread_task_runner.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/test/scoped_feature_list.h"
+#include "base/test/scoped_task_environment.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "build/build_config.h"
+#include "cc/input/touch_action.h"
+#include "content/browser/renderer_host/input/gesture_event_queue.h"
+#include "content/browser/renderer_host/input/input_router_client.h"
+#include "content/browser/renderer_host/input/mock_input_disposition_handler.h"
+#include "content/browser/renderer_host/input/mock_input_router_client.h"
+#include "content/browser/renderer_host/input/mock_widget_input_handler.h"
+#include "content/common/content_constants_internal.h"
+#include "content/common/edit_command.h"
+#include "content/common/input/synthetic_web_input_event_builders.h"
+#include "content/common/input_messages.h"
+#include "content/common/view_messages.h"
+#include "content/public/common/content_features.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/test/mock_render_process_host.h"
+#include "content/public/test/test_browser_context.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/events/base_event_utils.h"
+#include "ui/events/blink/web_input_event_traits.h"
+#include "ui/events/keycodes/keyboard_codes.h"
+
+#if defined(USE_AURA)
+#include "content/browser/renderer_host/ui_events_helper.h"
+#include "ui/events/event.h"
+#endif
+
+using blink::WebGestureDevice;
+using blink::WebGestureEvent;
+using blink::WebKeyboardEvent;
+using blink::WebInputEvent;
+using blink::WebMouseEvent;
+using blink::WebMouseWheelEvent;
+using blink::WebTouchEvent;
+using blink::WebTouchPoint;
+using ui::DidOverscrollParams;
+using ui::WebInputEventTraits;
+
+namespace content {
+
+namespace {
+
+bool ShouldBlockEventStream(const blink::WebInputEvent& event) {
+ return ui::WebInputEventTraits::ShouldBlockEventStream(
+ event,
+ base::FeatureList::IsEnabled(features::kRafAlignedTouchInputEvents),
+ base::FeatureList::IsEnabled(features::kTouchpadAndWheelScrollLatching));
+}
+
+WebInputEvent& GetEventWithType(WebInputEvent::Type type) {
+ WebInputEvent* event = NULL;
+ if (WebInputEvent::IsMouseEventType(type)) {
+ static WebMouseEvent mouse;
+ event = &mouse;
+ } else if (WebInputEvent::IsTouchEventType(type)) {
+ static WebTouchEvent touch;
+ event = &touch;
+ } else if (WebInputEvent::IsKeyboardEventType(type)) {
+ static WebKeyboardEvent key;
+ event = &key;
+ } else if (WebInputEvent::IsGestureEventType(type)) {
+ static WebGestureEvent gesture;
+ event = &gesture;
+ } else if (type == WebInputEvent::kMouseWheel) {
+ static WebMouseWheelEvent wheel;
+ event = &wheel;
+ }
+ CHECK(event);
+ event->SetType(type);
+ return *event;
+}
+
+void CallCallback(mojom::WidgetInputHandler::DispatchEventCallback callback,
+ InputEventAckState state) {
+ std::move(callback).Run(InputEventAckSource::COMPOSITOR_THREAD,
+ ui::LatencyInfo(), state, base::nullopt,
+ base::nullopt);
+}
+
+void CallCallbackWithTouchAction(
+ mojom::WidgetInputHandler::DispatchEventCallback callback,
+ InputEventAckState state,
+ cc::TouchAction touch_action) {
+ std::move(callback).Run(InputEventAckSource::COMPOSITOR_THREAD,
+ ui::LatencyInfo(), state, base::nullopt,
+ touch_action);
+}
+
+enum WheelScrollingMode {
+ kWheelScrollingModeNone,
+ kWheelScrollLatching,
+ kAsyncWheelEvents,
+};
+
+} // namespace
+
+// TODO(dtapuska): Remove this class when we don't have multiple implementations
+// of InputRouters.
+class MockInputRouterImplClient : public InputRouterImplClient {
+ public:
+ mojom::WidgetInputHandler* GetWidgetInputHandler() override {
+ return &widget_input_handler_;
+ }
+
+ std::vector<MockWidgetInputHandler::DispatchedEvent>
+ GetAndResetDispatchedEvents() {
+ return widget_input_handler_.GetAndResetDispatchedEvents();
+ }
+
+ InputEventAckState FilterInputEvent(
+ const blink::WebInputEvent& input_event,
+ const ui::LatencyInfo& latency_info) override {
+ return input_router_client_.FilterInputEvent(input_event, latency_info);
+ }
+
+ void IncrementInFlightEventCount(
+ blink::WebInputEvent::Type event_type) override {
+ input_router_client_.IncrementInFlightEventCount(event_type);
+ }
+
+ void DecrementInFlightEventCount(InputEventAckSource ack_source) override {
+ input_router_client_.DecrementInFlightEventCount(ack_source);
+ }
+
+ void OnHasTouchEventHandlers(bool has_handlers) override {
+ input_router_client_.OnHasTouchEventHandlers(has_handlers);
+ }
+
+ void DidOverscroll(const ui::DidOverscrollParams& params) override {
+ input_router_client_.DidOverscroll(params);
+ }
+
+ void DidStopFlinging() override { input_router_client_.DidStopFlinging(); }
+
+ void ForwardGestureEventWithLatencyInfo(
+ const blink::WebGestureEvent& gesture_event,
+ const ui::LatencyInfo& latency_info) override {
+ input_router_client_.ForwardGestureEventWithLatencyInfo(gesture_event,
+ latency_info);
+ }
+
+ void OnSetWhiteListedTouchAction(cc::TouchAction touch_action) override {
+ input_router_client_.OnSetWhiteListedTouchAction(touch_action);
+ }
+
+ bool GetAndResetFilterEventCalled() {
+ return input_router_client_.GetAndResetFilterEventCalled();
+ }
+
+ ui::DidOverscrollParams GetAndResetOverscroll() {
+ return input_router_client_.GetAndResetOverscroll();
+ }
+
+ cc::TouchAction GetAndResetWhiteListedTouchAction() {
+ return input_router_client_.GetAndResetWhiteListedTouchAction();
+ }
+
+ void set_input_router(InputRouter* input_router) {
+ input_router_client_.set_input_router(input_router);
+ }
+
+ bool has_touch_handler() const {
+ return input_router_client_.has_touch_handler();
+ }
+
+ void set_filter_state(InputEventAckState filter_state) {
+ input_router_client_.set_filter_state(filter_state);
+ }
+ int in_flight_event_count() const {
+ return input_router_client_.in_flight_event_count();
+ }
+ void set_allow_send_event(bool allow) {
+ input_router_client_.set_allow_send_event(allow);
+ }
+ const blink::WebInputEvent* last_filter_event() const {
+ return input_router_client_.last_filter_event();
+ }
+
+ MockInputRouterClient input_router_client_;
+ MockWidgetInputHandler widget_input_handler_;
+};
+
+class InputRouterImplTest : public testing::Test {
+ public:
+ InputRouterImplTest(
+ bool raf_aligned_touch = true,
+ WheelScrollingMode wheel_scrolling_mode = kWheelScrollLatching)
+ : wheel_scroll_latching_enabled_(wheel_scrolling_mode !=
+ kWheelScrollingModeNone),
+ scoped_task_environment_(
+ base::test::ScopedTaskEnvironment::MainThreadType::UI) {
+ if (raf_aligned_touch && wheel_scrolling_mode == kAsyncWheelEvents) {
+ feature_list_.InitWithFeatures({features::kRafAlignedTouchInputEvents,
+ features::kTouchpadAndWheelScrollLatching,
+ features::kAsyncWheelEvents},
+ {});
+ } else if (raf_aligned_touch &&
+ wheel_scrolling_mode == kWheelScrollLatching) {
+ feature_list_.InitWithFeatures(
+ {features::kRafAlignedTouchInputEvents,
+ features::kTouchpadAndWheelScrollLatching},
+ {features::kAsyncWheelEvents});
+ } else if (raf_aligned_touch &&
+ wheel_scrolling_mode == kWheelScrollingModeNone) {
+ feature_list_.InitWithFeatures({features::kRafAlignedTouchInputEvents},
+ {features::kTouchpadAndWheelScrollLatching,
+ features::kAsyncWheelEvents});
+ } else if (!raf_aligned_touch &&
+ wheel_scrolling_mode == kAsyncWheelEvents) {
+ feature_list_.InitWithFeatures({features::kTouchpadAndWheelScrollLatching,
+ features::kAsyncWheelEvents},
+ {features::kRafAlignedTouchInputEvents});
+ } else if (!raf_aligned_touch &&
+ wheel_scrolling_mode == kWheelScrollLatching) {
+ feature_list_.InitWithFeatures(
+ {features::kTouchpadAndWheelScrollLatching},
+ {features::kRafAlignedTouchInputEvents, features::kAsyncWheelEvents});
+ } else { // !raf_aligned_touch && wheel_scroll_latching ==
+ // kWheelScrollingModeNone.
+ feature_list_.InitWithFeatures({},
+ {features::kRafAlignedTouchInputEvents,
+ features::kTouchpadAndWheelScrollLatching,
+ features::kAsyncWheelEvents});
+ }
+ }
+
+ ~InputRouterImplTest() override {}
+
+ protected:
+ using DispatchedEvents = std::vector<MockWidgetInputHandler::DispatchedEvent>;
+ // testing::Test
+ void SetUp() override {
+ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+ command_line->AppendSwitch(switches::kValidateInputEventStream);
+ client_.reset(new MockInputRouterImplClient());
+ disposition_handler_.reset(new MockInputDispositionHandler());
+ input_router_.reset(new InputRouterImpl(
+ client_.get(), disposition_handler_.get(), config_));
+
+ client_->set_input_router(input_router());
+ disposition_handler_->set_input_router(input_router());
+ }
+
+ void TearDown() override {
+ // Process all pending tasks to avoid leaks.
+ base::RunLoop().RunUntilIdle();
+
+ input_router_.reset();
+ client_.reset();
+ }
+
+ void SetUpForTouchAckTimeoutTest(int desktop_timeout_ms,
+ int mobile_timeout_ms) {
+ config_.touch_config.desktop_touch_ack_timeout_delay =
+ base::TimeDelta::FromMilliseconds(desktop_timeout_ms);
+ config_.touch_config.mobile_touch_ack_timeout_delay =
+ base::TimeDelta::FromMilliseconds(mobile_timeout_ms);
+ config_.touch_config.touch_ack_timeout_supported = true;
+ TearDown();
+ SetUp();
+ input_router()->NotifySiteIsMobileOptimized(false);
+ }
+
+ void SimulateKeyboardEvent(WebInputEvent::Type type) {
+ NativeWebKeyboardEventWithLatencyInfo key_event(
+ type, WebInputEvent::kNoModifiers,
+ ui::EventTimeStampToSeconds(ui::EventTimeForNow()), ui::LatencyInfo());
+ input_router_->SendKeyboardEvent(key_event);
+ }
+
+ void SimulateWheelEvent(float x,
+ float y,
+ float dX,
+ float dY,
+ int modifiers,
+ bool precise) {
+ input_router_->SendWheelEvent(MouseWheelEventWithLatencyInfo(
+ SyntheticWebMouseWheelEventBuilder::Build(x, y, dX, dY, modifiers,
+ precise)));
+ }
+
+ void SimulateWheelEventWithPhase(float x,
+ float y,
+ float dX,
+ float dY,
+ int modifiers,
+ bool precise,
+ WebMouseWheelEvent::Phase phase) {
+ WebMouseWheelEvent wheel_event = SyntheticWebMouseWheelEventBuilder::Build(
+ x, y, dX, dY, modifiers, precise);
+ wheel_event.phase = phase;
+ input_router_->SendWheelEvent(MouseWheelEventWithLatencyInfo(wheel_event));
+ }
+
+ void SimulateWheelEventPossiblyIncludingPhase(
+ bool ignore_phase,
+ float x,
+ float y,
+ float dX,
+ float dY,
+ int modifiers,
+ bool precise,
+ WebMouseWheelEvent::Phase phase) {
+ if (ignore_phase)
+ SimulateWheelEvent(x, y, dX, dY, modifiers, precise);
+ else
+ SimulateWheelEventWithPhase(x, y, dX, dY, modifiers, precise, phase);
+ }
+
+ void SimulateMouseEvent(WebInputEvent::Type type, int x, int y) {
+ input_router_->SendMouseEvent(MouseEventWithLatencyInfo(
+ SyntheticWebMouseEventBuilder::Build(type, x, y, 0)));
+ }
+
+ void SimulateWheelEventWithPhase(WebMouseWheelEvent::Phase phase) {
+ input_router_->SendWheelEvent(MouseWheelEventWithLatencyInfo(
+ SyntheticWebMouseWheelEventBuilder::Build(phase)));
+ }
+
+ void SimulateGestureEvent(WebGestureEvent gesture) {
+ if (gesture.GetType() == WebInputEvent::kGestureScrollBegin &&
+ gesture.source_device == blink::kWebGestureDeviceTouchscreen &&
+ !gesture.data.scroll_begin.delta_x_hint &&
+ !gesture.data.scroll_begin.delta_y_hint) {
+ // Ensure non-zero scroll-begin offset-hint to make the event sane,
+ // prevents unexpected filtering at TouchActionFilter.
+ gesture.data.scroll_begin.delta_y_hint = 2.f;
+ } else if (gesture.GetType() == WebInputEvent::kGestureFlingStart &&
+ gesture.source_device == blink::kWebGestureDeviceTouchscreen &&
+ !gesture.data.fling_start.velocity_x &&
+ !gesture.data.fling_start.velocity_y) {
+ // Ensure non-zero touchscreen fling velocities, as the router will
+ // validate against such.
+ gesture.data.fling_start.velocity_x = 5.f;
+ }
+
+ input_router_->SendGestureEvent(GestureEventWithLatencyInfo(gesture));
+ }
+
+ void SimulateGestureEvent(WebInputEvent::Type type,
+ WebGestureDevice source_device) {
+ SimulateGestureEvent(
+ SyntheticWebGestureEventBuilder::Build(type, source_device));
+ }
+
+ void SimulateGestureScrollUpdateEvent(float dX,
+ float dY,
+ int modifiers,
+ WebGestureDevice source_device) {
+ SimulateGestureEvent(SyntheticWebGestureEventBuilder::BuildScrollUpdate(
+ dX, dY, modifiers, source_device));
+ }
+
+ void SimulateGesturePinchUpdateEvent(float scale,
+ float anchor_x,
+ float anchor_y,
+ int modifiers,
+ WebGestureDevice source_device) {
+ SimulateGestureEvent(SyntheticWebGestureEventBuilder::BuildPinchUpdate(
+ scale, anchor_x, anchor_y, modifiers, source_device));
+ }
+
+ void SimulateGestureFlingStartEvent(float velocity_x,
+ float velocity_y,
+ WebGestureDevice source_device) {
+ SimulateGestureEvent(SyntheticWebGestureEventBuilder::BuildFling(
+ velocity_x, velocity_y, source_device));
+ }
+
+ void SetTouchTimestamp(base::TimeTicks timestamp) {
+ touch_event_.SetTimestamp(timestamp);
+ }
+
+ uint32_t SendTouchEvent() {
+ uint32_t touch_event_id = touch_event_.unique_touch_event_id;
+ input_router_->SendTouchEvent(TouchEventWithLatencyInfo(touch_event_));
+ touch_event_.ResetPoints();
+ return touch_event_id;
+ }
+
+ int PressTouchPoint(int x, int y) { return touch_event_.PressPoint(x, y); }
+
+ void MoveTouchPoint(int index, int x, int y) {
+ touch_event_.MovePoint(index, x, y);
+ }
+
+ void ReleaseTouchPoint(int index) { touch_event_.ReleasePoint(index); }
+
+ void CancelTouchPoint(int index) { touch_event_.CancelPoint(index); }
+
+ InputRouterImpl* input_router() const { return input_router_.get(); }
+
+ bool TouchEventQueueEmpty() const {
+ return input_router()->touch_event_queue_->Empty();
+ }
+
+ bool TouchEventTimeoutEnabled() const {
+ return input_router()->touch_event_queue_->IsAckTimeoutEnabled();
+ }
+
+ bool HasPendingEvents() const { return input_router_->HasPendingEvents(); }
+
+ void OnHasTouchEventHandlers(bool has_handlers) {
+ input_router_->OnMessageReceived(
+ ViewHostMsg_HasTouchEventHandlers(0, has_handlers));
+ }
+
+ void OnSetTouchAction(cc::TouchAction touch_action) {
+ input_router_->OnMessageReceived(
+ InputHostMsg_SetTouchAction(0, touch_action));
+ }
+
+ void OnSetWhiteListedTouchAction(cc::TouchAction white_listed_touch_action,
+ uint32_t unique_touch_event_id,
+ InputEventAckState ack_result) {
+ input_router_->OnMessageReceived(InputHostMsg_SetWhiteListedTouchAction(
+ 0, white_listed_touch_action, unique_touch_event_id, ack_result));
+ }
+
+ DispatchedEvents GetAndResetDispatchedEvents() {
+ return client_->GetAndResetDispatchedEvents();
+ }
+
+ static void RunTasksAndWait(base::TimeDelta delay) {
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE, base::MessageLoop::QuitWhenIdleClosure(), delay);
+ base::RunLoop().Run();
+ }
+
+ void OverscrollDispatch();
+
+ InputRouter::Config config_;
+ std::unique_ptr<MockInputRouterImplClient> client_;
+ std::unique_ptr<InputRouterImpl> input_router_;
+ std::unique_ptr<MockInputDispositionHandler> disposition_handler_;
+ bool wheel_scroll_latching_enabled_;
+
+ private:
+ base::test::ScopedTaskEnvironment scoped_task_environment_;
+ SyntheticWebTouchEvent touch_event_;
+
+ base::test::ScopedFeatureList feature_list_;
+};
+
+class InputRouterImplRafAlignedTouchDisabledTest : public InputRouterImplTest {
+ public:
+ InputRouterImplRafAlignedTouchDisabledTest()
+ : InputRouterImplTest(false, kWheelScrollingModeNone) {}
+};
+
+class InputRouterImplWheelScrollLatchingDisabledTest
+ : public InputRouterImplTest {
+ public:
+ InputRouterImplWheelScrollLatchingDisabledTest()
+ : InputRouterImplTest(true, kWheelScrollingModeNone) {}
+};
+
+class InputRouterImplAsyncWheelEventEnabledTest : public InputRouterImplTest {
+ public:
+ InputRouterImplAsyncWheelEventEnabledTest()
+ : InputRouterImplTest(true, kAsyncWheelEvents) {}
+};
+
+TEST_F(InputRouterImplTest, HandledInputEvent) {
+ client_->set_filter_state(INPUT_EVENT_ACK_STATE_CONSUMED);
+
+ // Simulate a keyboard event.
+ SimulateKeyboardEvent(WebInputEvent::kRawKeyDown);
+
+ // Make sure no input event is sent to the renderer.
+ DispatchedEvents dispatched_events = GetAndResetDispatchedEvents();
+ EXPECT_EQ(0u, dispatched_events.size());
+
+ // OnKeyboardEventAck should be triggered without actual ack.
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
+}
+
+TEST_F(InputRouterImplTest, ClientCanceledKeyboardEvent) {
+ client_->set_filter_state(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
+
+ // Simulate a keyboard event that has no consumer.
+ SimulateKeyboardEvent(WebInputEvent::kRawKeyDown);
+
+ // Make sure no input event is sent to the renderer.
+ DispatchedEvents dispatched_events = GetAndResetDispatchedEvents();
+ EXPECT_EQ(0u, dispatched_events.size());
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
+
+ // Simulate a keyboard event that should be dropped.
+ client_->set_filter_state(INPUT_EVENT_ACK_STATE_UNKNOWN);
+ SimulateKeyboardEvent(WebInputEvent::kRawKeyDown);
+
+ // Make sure no input event is sent to the renderer, and no ack is sent.
+ dispatched_events = GetAndResetDispatchedEvents();
+ EXPECT_EQ(0u, dispatched_events.size());
+ EXPECT_EQ(0U, disposition_handler_->GetAndResetAckCount());
+}
+
+// Tests ported from RenderWidgetHostTest --------------------------------------
+
+TEST_F(InputRouterImplTest, HandleKeyEventsWeSent) {
+ // Simulate a keyboard event.
+ SimulateKeyboardEvent(WebInputEvent::kRawKeyDown);
+
+ // Make sure we sent the input event to the renderer.
+ DispatchedEvents dispatched_events = GetAndResetDispatchedEvents();
+ EXPECT_EQ(1u, dispatched_events.size());
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
+ EXPECT_EQ(WebInputEvent::kRawKeyDown,
+ disposition_handler_->acked_keyboard_event().GetType());
+}
+
+TEST_F(InputRouterImplTest, CoalescesWheelEvents) {
+ // Simulate wheel events.
+ SimulateWheelEventPossiblyIncludingPhase(
+ !wheel_scroll_latching_enabled_, 0, 0, 0, -5, 0, false,
+ WebMouseWheelEvent::kPhaseBegan); // sent directly
+ SimulateWheelEventPossiblyIncludingPhase(
+ !wheel_scroll_latching_enabled_, 0, 0, 0, -10, 0, false,
+ WebMouseWheelEvent::kPhaseChanged); // enqueued
+ SimulateWheelEventPossiblyIncludingPhase(
+ !wheel_scroll_latching_enabled_, 0, 0, 8, -6, 0, false,
+ WebMouseWheelEvent::kPhaseChanged); // coalesced into previous event
+ SimulateWheelEventPossiblyIncludingPhase(
+ !wheel_scroll_latching_enabled_, 0, 0, 9, -7, 1, false,
+ WebMouseWheelEvent::kPhaseChanged); // enqueued, different modifiers
+ SimulateWheelEventPossiblyIncludingPhase(
+ !wheel_scroll_latching_enabled_, 0, 0, 0, -10, 0, false,
+ WebMouseWheelEvent::kPhaseChanged); // enqueued, different modifiers
+ // Explicitly verify that PhaseEnd isn't coalesced to avoid bugs like
+ // https://crbug.com/154740.
+ SimulateWheelEventWithPhase(WebMouseWheelEvent::kPhaseEnded); // enqueued
+
+ // Check that only the first event was sent.
+ DispatchedEvents dispatched_events = GetAndResetDispatchedEvents();
+ EXPECT_EQ(1u, dispatched_events.size());
+ ASSERT_EQ(WebInputEvent::kMouseWheel,
+ dispatched_events.at(0).event_->web_event->GetType());
+ const WebMouseWheelEvent* wheel_event =
+ static_cast<const WebMouseWheelEvent*>(
+ dispatched_events.at(0).event_->web_event.get());
+ EXPECT_EQ(0, wheel_event->delta_x);
+ EXPECT_EQ(-5, wheel_event->delta_y);
+
+ // Check that the ACK sends the second message immediately.
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ // The coalesced events can queue up a delayed ack
+ // so that additional input events can be processed before
+ // we turn off coalescing.
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
+ dispatched_events = GetAndResetDispatchedEvents();
+ EXPECT_EQ(1u, dispatched_events.size());
+ ASSERT_EQ(WebInputEvent::kMouseWheel,
+ dispatched_events.at(0).event_->web_event->GetType());
+ wheel_event = static_cast<const WebMouseWheelEvent*>(
+ dispatched_events.at(0).event_->web_event.get());
+ EXPECT_EQ(8, wheel_event->delta_x);
+ EXPECT_EQ(-10 + -6, wheel_event->delta_y); // coalesced
+
+ // Ack the second event (which had the third coalesced into it).
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
+ dispatched_events = GetAndResetDispatchedEvents();
+ EXPECT_EQ(1u, dispatched_events.size());
+ ASSERT_EQ(WebInputEvent::kMouseWheel,
+ dispatched_events.at(0).event_->web_event->GetType());
+ wheel_event = static_cast<const WebMouseWheelEvent*>(
+ dispatched_events.at(0).event_->web_event.get());
+ EXPECT_EQ(9, wheel_event->delta_x);
+ EXPECT_EQ(-7, wheel_event->delta_y);
+
+ // Ack the fourth event.
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
+ dispatched_events = GetAndResetDispatchedEvents();
+ EXPECT_EQ(1u, dispatched_events.size());
+ ASSERT_EQ(WebInputEvent::kMouseWheel,
+ dispatched_events.at(0).event_->web_event->GetType());
+ wheel_event = static_cast<const WebMouseWheelEvent*>(
+ dispatched_events.at(0).event_->web_event.get());
+ EXPECT_EQ(0, wheel_event->delta_x);
+ EXPECT_EQ(-10, wheel_event->delta_y);
+
+ // Ack the fifth event.
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
+ dispatched_events = GetAndResetDispatchedEvents();
+ EXPECT_EQ(1u, dispatched_events.size());
+ ASSERT_EQ(WebInputEvent::kMouseWheel,
+ dispatched_events.at(0).event_->web_event->GetType());
+ wheel_event = static_cast<const WebMouseWheelEvent*>(
+ dispatched_events.at(0).event_->web_event.get());
+ EXPECT_EQ(0, wheel_event->delta_x);
+ EXPECT_EQ(0, wheel_event->delta_y);
+ EXPECT_EQ(WebMouseWheelEvent::kPhaseEnded, wheel_event->phase);
+
+ // After the final ack, the queue should be empty.
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
+ dispatched_events = GetAndResetDispatchedEvents();
+ EXPECT_EQ(0u, dispatched_events.size());
+}
+
+// Tests that touch-events are queued properly.
+TEST_F(InputRouterImplRafAlignedTouchDisabledTest, TouchEventQueue) {
+ OnHasTouchEventHandlers(true);
+
+ PressTouchPoint(1, 1);
+ SendTouchEvent();
+ EXPECT_TRUE(client_->GetAndResetFilterEventCalled());
+ DispatchedEvents dispatched_events = GetAndResetDispatchedEvents();
+ EXPECT_EQ(1u, dispatched_events.size());
+ EXPECT_FALSE(TouchEventQueueEmpty());
+
+ // The second touch should not be sent since one is already in queue.
+ MoveTouchPoint(0, 5, 5);
+ SendTouchEvent();
+ EXPECT_FALSE(client_->GetAndResetFilterEventCalled());
+ EXPECT_EQ(0u, GetAndResetDispatchedEvents().size());
+ EXPECT_FALSE(TouchEventQueueEmpty());
+
+ // Receive an ACK for the first touch-event.
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_FALSE(TouchEventQueueEmpty());
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
+ EXPECT_EQ(WebInputEvent::kTouchStart,
+ disposition_handler_->acked_touch_event().event.GetType());
+ dispatched_events = GetAndResetDispatchedEvents();
+ EXPECT_EQ(1U, dispatched_events.size());
+
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_TRUE(TouchEventQueueEmpty());
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
+ EXPECT_EQ(WebInputEvent::kTouchMove,
+ disposition_handler_->acked_touch_event().event.GetType());
+ EXPECT_EQ(0U, GetAndResetDispatchedEvents().size());
+}
+
+// Tests that touch-events are sent properly.
+TEST_F(InputRouterImplTest, TouchEventQueue) {
+ OnHasTouchEventHandlers(true);
+
+ PressTouchPoint(1, 1);
+ SendTouchEvent();
+ EXPECT_TRUE(client_->GetAndResetFilterEventCalled());
+ DispatchedEvents touch_start_event = GetAndResetDispatchedEvents();
+ EXPECT_EQ(1U, touch_start_event.size());
+ EXPECT_FALSE(TouchEventQueueEmpty());
+
+ // The second touch should be sent right away.
+ MoveTouchPoint(0, 5, 5);
+ SendTouchEvent();
+ DispatchedEvents touch_move_event = GetAndResetDispatchedEvents();
+ EXPECT_TRUE(client_->GetAndResetFilterEventCalled());
+ EXPECT_EQ(1U, touch_move_event.size());
+ EXPECT_FALSE(TouchEventQueueEmpty());
+
+ // Receive an ACK for the first touch-event.
+ CallCallback(std::move(touch_start_event.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_FALSE(TouchEventQueueEmpty());
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
+ EXPECT_EQ(WebInputEvent::kTouchStart,
+ disposition_handler_->acked_touch_event().event.GetType());
+ EXPECT_EQ(0U, GetAndResetDispatchedEvents().size());
+
+ CallCallback(std::move(touch_move_event.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_TRUE(TouchEventQueueEmpty());
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
+ EXPECT_EQ(WebInputEvent::kTouchMove,
+ disposition_handler_->acked_touch_event().event.GetType());
+ EXPECT_EQ(0U, GetAndResetDispatchedEvents().size());
+}
+
+// Tests that the touch-queue is emptied after a page stops listening for touch
+// events and the outstanding ack is received.
+TEST_F(InputRouterImplTest, TouchEventQueueFlush) {
+ OnHasTouchEventHandlers(true);
+ EXPECT_TRUE(client_->has_touch_handler());
+ EXPECT_EQ(0U, GetAndResetDispatchedEvents().size());
+ EXPECT_TRUE(TouchEventQueueEmpty());
+
+ // Send a touch-press event.
+ PressTouchPoint(1, 1);
+ SendTouchEvent();
+ MoveTouchPoint(0, 2, 2);
+ MoveTouchPoint(0, 3, 3);
+ EXPECT_FALSE(TouchEventQueueEmpty());
+ DispatchedEvents dispatched_events = GetAndResetDispatchedEvents();
+ EXPECT_EQ(1U, dispatched_events.size());
+
+ // The page stops listening for touch-events. Note that flushing is deferred
+ // until the outstanding ack is received.
+ OnHasTouchEventHandlers(false);
+ EXPECT_FALSE(client_->has_touch_handler());
+ EXPECT_EQ(0U, GetAndResetDispatchedEvents().size());
+ EXPECT_FALSE(TouchEventQueueEmpty());
+
+ // After the ack, the touch-event queue should be empty, and none of the
+ // flushed touch-events should have been sent to the renderer.
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(0U, GetAndResetDispatchedEvents().size());
+ EXPECT_TRUE(TouchEventQueueEmpty());
+}
+
+TEST_F(InputRouterImplTest, UnhandledWheelEvent) {
+ // Simulate wheel events.
+ SimulateWheelEventPossiblyIncludingPhase(!wheel_scroll_latching_enabled_, 0,
+ 0, 0, -5, 0, false,
+ WebMouseWheelEvent::kPhaseBegan);
+ SimulateWheelEventPossiblyIncludingPhase(!wheel_scroll_latching_enabled_, 0,
+ 0, 0, -10, 0, false,
+ WebMouseWheelEvent::kPhaseChanged);
+
+ // Check that only the first event was sent.
+ DispatchedEvents dispatched_events = GetAndResetDispatchedEvents();
+ EXPECT_EQ(1U, dispatched_events.size());
+
+ // Indicate that the wheel event was unhandled.
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+
+ dispatched_events = GetAndResetDispatchedEvents();
+
+ // There should be a ScrollBegin, MouseWheel sent.
+ EXPECT_EQ(2U, dispatched_events.size());
+
+ ASSERT_EQ(WebInputEvent::kGestureScrollBegin,
+ dispatched_events.at(0).event_->web_event->GetType());
+ ASSERT_EQ(WebInputEvent::kMouseWheel,
+ dispatched_events.at(1).event_->web_event->GetType());
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+
+ // Check that the ack for ScrollBegin, MouseWheel were
+ // processed.
+ EXPECT_EQ(2U, disposition_handler_->GetAndResetAckCount());
+ EXPECT_EQ(disposition_handler_->acked_wheel_event().delta_y, -5);
+
+ DispatchedEvents gesture_scroll_update = GetAndResetDispatchedEvents();
+ EXPECT_EQ(1U, gesture_scroll_update.size());
+ CallCallback(std::move(gesture_scroll_update.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
+
+ // Ack the mouse wheel event.
+ CallCallback(std::move(dispatched_events.at(1).callback_),
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
+
+ dispatched_events = GetAndResetDispatchedEvents();
+ EXPECT_EQ(1U, dispatched_events.size());
+ ASSERT_EQ(WebInputEvent::kGestureScrollUpdate,
+ dispatched_events.at(0).event_->web_event->GetType());
+
+ // Check that the correct unhandled wheel event was received.
+ EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED,
+ disposition_handler_->acked_wheel_event_state());
+ EXPECT_EQ(disposition_handler_->acked_wheel_event().delta_y, -10);
+
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+
+ // Check that the ack for ScrollUpdate were processed.
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
+}
+TEST_F(InputRouterImplWheelScrollLatchingDisabledTest, UnhandledWheelEvent) {
+ // Simulate wheel events.
+ SimulateWheelEventPossiblyIncludingPhase(!wheel_scroll_latching_enabled_, 0,
+ 0, 0, -5, 0, false,
+ WebMouseWheelEvent::kPhaseBegan);
+ SimulateWheelEventPossiblyIncludingPhase(!wheel_scroll_latching_enabled_, 0,
+ 0, 0, -10, 0, false,
+ WebMouseWheelEvent::kPhaseChanged);
+
+ // Check that only the first event was sent.
+ DispatchedEvents dispatched_events = GetAndResetDispatchedEvents();
+ EXPECT_EQ(1U, dispatched_events.size());
+
+ // Indicate that the wheel event was unhandled.
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+
+ dispatched_events = GetAndResetDispatchedEvents();
+
+ // Check that the ack for MouseWheel and GestureScrollBegin
+ // was processed.
+ EXPECT_EQ(2U, disposition_handler_->GetAndResetAckCount());
+ EXPECT_EQ(disposition_handler_->acked_wheel_event().delta_y, -5);
+
+ // There should be a ScrollBegin, ScrollUpdate and MouseWheel sent.
+ EXPECT_EQ(3U, dispatched_events.size());
+
+ ASSERT_EQ(WebInputEvent::kGestureScrollBegin,
+ dispatched_events.at(0).event_->web_event->GetType());
+ ASSERT_EQ(WebInputEvent::kGestureScrollUpdate,
+ dispatched_events.at(1).event_->web_event->GetType());
+ ASSERT_EQ(WebInputEvent::kMouseWheel,
+ dispatched_events.at(2).event_->web_event->GetType());
+
+ // Ack the ScrollUpdate
+ CallCallback(std::move(dispatched_events.at(1).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+
+ // Check that the ack for ScrollBegin, ScrollUpdate were
+ // processed.
+ EXPECT_EQ(2U, disposition_handler_->GetAndResetAckCount());
+
+ // The GestureScrollUpdate ACK releases the GestureScrollEnd.
+ EXPECT_EQ(1U, GetAndResetDispatchedEvents().size());
+
+ // Ack the MouseWheel.
+ CallCallback(std::move(dispatched_events.at(2).callback_),
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+
+ EXPECT_EQ(2U, disposition_handler_->GetAndResetAckCount());
+
+ // There should be a ScrollBegin and ScrollUpdate sent.
+ dispatched_events = GetAndResetDispatchedEvents();
+ EXPECT_EQ(2U, dispatched_events.size());
+ ASSERT_EQ(WebInputEvent::kGestureScrollBegin,
+ dispatched_events.at(0).event_->web_event->GetType());
+ ASSERT_EQ(WebInputEvent::kGestureScrollUpdate,
+ dispatched_events.at(1).event_->web_event->GetType());
+
+ // Check that the correct unhandled wheel event was received.
+ EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED,
+ disposition_handler_->acked_wheel_event_state());
+ EXPECT_EQ(disposition_handler_->acked_wheel_event().delta_y, -10);
+
+ CallCallback(std::move(dispatched_events.at(1).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ // The GestureScrollUpdate ACK releases the GestureScrollEnd.
+ EXPECT_EQ(1U, GetAndResetDispatchedEvents().size());
+
+ // Check that the ack for the ScrollUpdate and ScrollEnd
+ // were processed.
+ EXPECT_EQ(2U, disposition_handler_->GetAndResetAckCount());
+}
+
+TEST_F(InputRouterImplAsyncWheelEventEnabledTest, UnhandledWheelEvent) {
+ // Simulate wheel events.
+ SimulateWheelEventWithPhase(0, 0, 0, -5, 0, false,
+ WebMouseWheelEvent::kPhaseBegan);
+ SimulateWheelEventWithPhase(0, 0, 0, -10, 0, false,
+ WebMouseWheelEvent::kPhaseChanged);
+
+ // Check that only the first event was sent.
+ DispatchedEvents dispatched_events = GetAndResetDispatchedEvents();
+ EXPECT_EQ(1U, dispatched_events.size());
+
+ // Indicate that the wheel event was unhandled.
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+
+ // There should be a ScrollBegin and second MouseWheel sent.
+ dispatched_events = GetAndResetDispatchedEvents();
+ EXPECT_EQ(2U, dispatched_events.size());
+ ASSERT_EQ(WebInputEvent::kGestureScrollBegin,
+ dispatched_events.at(0).event_->web_event->GetType());
+ ASSERT_EQ(WebInputEvent::kMouseWheel,
+ dispatched_events.at(1).event_->web_event->GetType());
+
+ // Indicate that the GestureScrollBegin event was consumed.
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+
+ // Check that the ack for the first MouseWheel, ScrollBegin, and the second
+ // MouseWheel were processed.
+ EXPECT_EQ(3U, disposition_handler_->GetAndResetAckCount());
+
+ // There should be a ScrollUpdate sent.
+ dispatched_events = GetAndResetDispatchedEvents();
+ EXPECT_EQ(1U, dispatched_events.size());
+
+ // The last acked wheel event should be the second one since the input router
+ // has already sent the immediate ack for the second wheel event.
+ EXPECT_EQ(disposition_handler_->acked_wheel_event().delta_y, -10);
+ EXPECT_EQ(INPUT_EVENT_ACK_STATE_IGNORED,
+ disposition_handler_->acked_wheel_event_state());
+
+ // Ack the gesture scroll update.
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+
+ // Check that the ack for the coalesced ScrollUpdate were processed.
+ EXPECT_EQ(
+ -15,
+ disposition_handler_->acked_gesture_event().data.scroll_update.delta_y);
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
+}
+
+TEST_F(InputRouterImplTest, TouchTypesIgnoringAck) {
+ OnHasTouchEventHandlers(true);
+ // Only acks for TouchCancel should always be ignored.
+ ASSERT_TRUE(
+ ShouldBlockEventStream(GetEventWithType(WebInputEvent::kTouchStart)));
+ ASSERT_TRUE(
+ ShouldBlockEventStream(GetEventWithType(WebInputEvent::kTouchMove)));
+ ASSERT_TRUE(
+ ShouldBlockEventStream(GetEventWithType(WebInputEvent::kTouchEnd)));
+
+ // Precede the TouchCancel with an appropriate TouchStart;
+ PressTouchPoint(1, 1);
+ SendTouchEvent();
+ DispatchedEvents dispatched_events = GetAndResetDispatchedEvents();
+ EXPECT_EQ(1U, dispatched_events.size());
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ ASSERT_EQ(1U, disposition_handler_->GetAndResetAckCount());
+ ASSERT_EQ(0, client_->in_flight_event_count());
+
+ // The TouchCancel has no callback.
+ CancelTouchPoint(0);
+ SendTouchEvent();
+ dispatched_events = GetAndResetDispatchedEvents();
+ EXPECT_EQ(1U, dispatched_events.size());
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
+ EXPECT_EQ(0, client_->in_flight_event_count());
+ EXPECT_FALSE(HasPendingEvents());
+ EXPECT_FALSE(dispatched_events.at(0).callback_);
+ EXPECT_EQ(0U, GetAndResetDispatchedEvents().size());
+ EXPECT_EQ(0U, disposition_handler_->GetAndResetAckCount());
+ EXPECT_FALSE(HasPendingEvents());
+}
+
+TEST_F(InputRouterImplTest, GestureTypesIgnoringAck) {
+ // We test every gesture type, ensuring that the stream of gestures is valid.
+ const WebInputEvent::Type eventTypes[] = {
+ WebInputEvent::kGestureTapDown, WebInputEvent::kGestureShowPress,
+ WebInputEvent::kGestureTapCancel, WebInputEvent::kGestureScrollBegin,
+ WebInputEvent::kGestureFlingStart, WebInputEvent::kGestureFlingCancel,
+ WebInputEvent::kGestureTapDown, WebInputEvent::kGestureTap,
+ WebInputEvent::kGestureTapDown, WebInputEvent::kGestureLongPress,
+ WebInputEvent::kGestureTapCancel, WebInputEvent::kGestureLongTap,
+ WebInputEvent::kGestureTapDown, WebInputEvent::kGestureTapUnconfirmed,
+ WebInputEvent::kGestureTapCancel, WebInputEvent::kGestureTapDown,
+ WebInputEvent::kGestureDoubleTap, WebInputEvent::kGestureTapDown,
+ WebInputEvent::kGestureTapCancel, WebInputEvent::kGestureTwoFingerTap,
+ WebInputEvent::kGestureTapDown, WebInputEvent::kGestureTapCancel,
+ WebInputEvent::kGestureScrollBegin, WebInputEvent::kGestureScrollUpdate,
+ WebInputEvent::kGesturePinchBegin, WebInputEvent::kGesturePinchUpdate,
+ WebInputEvent::kGesturePinchEnd, WebInputEvent::kGestureScrollEnd};
+ for (size_t i = 0; i < arraysize(eventTypes); ++i) {
+ WebInputEvent::Type type = eventTypes[i];
+ if (ShouldBlockEventStream(GetEventWithType(type))) {
+ SimulateGestureEvent(type, blink::kWebGestureDeviceTouchscreen);
+ DispatchedEvents dispatched_events = GetAndResetDispatchedEvents();
+
+ if (type == WebInputEvent::kGestureScrollUpdate)
+ EXPECT_EQ(2U, dispatched_events.size());
+ else
+ EXPECT_EQ(1U, dispatched_events.size());
+ EXPECT_EQ(0U, disposition_handler_->GetAndResetAckCount());
+ EXPECT_EQ(1, client_->in_flight_event_count());
+ EXPECT_TRUE(HasPendingEvents());
+
+ CallCallback(
+ std::move(
+ dispatched_events.at(dispatched_events.size() - 1).callback_),
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+
+ EXPECT_EQ(0U, GetAndResetDispatchedEvents().size());
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
+ EXPECT_EQ(0, client_->in_flight_event_count());
+ EXPECT_FALSE(HasPendingEvents());
+ continue;
+ }
+
+ SimulateGestureEvent(type, blink::kWebGestureDeviceTouchscreen);
+ EXPECT_EQ(1U, GetAndResetDispatchedEvents().size());
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
+ EXPECT_EQ(0, client_->in_flight_event_count());
+ EXPECT_FALSE(HasPendingEvents());
+ }
+}
+
+TEST_F(InputRouterImplTest, MouseTypesIgnoringAck) {
+ int start_type = static_cast<int>(WebInputEvent::kMouseDown);
+ int end_type = static_cast<int>(WebInputEvent::kContextMenu);
+ ASSERT_LT(start_type, end_type);
+ for (int i = start_type; i <= end_type; ++i) {
+ WebInputEvent::Type type = static_cast<WebInputEvent::Type>(i);
+
+ SimulateMouseEvent(type, 0, 0);
+ DispatchedEvents dispatched_events = GetAndResetDispatchedEvents();
+ EXPECT_EQ(1U, dispatched_events.size());
+
+ if (ShouldBlockEventStream(GetEventWithType(type))) {
+ EXPECT_EQ(0U, disposition_handler_->GetAndResetAckCount());
+ EXPECT_EQ(1, client_->in_flight_event_count());
+
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(0U, GetAndResetDispatchedEvents().size());
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
+ EXPECT_EQ(0, client_->in_flight_event_count());
+ } else {
+ // Note: events which don't block the event stream immediately receive
+ // synthetic ACKs.
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
+ EXPECT_EQ(0, client_->in_flight_event_count());
+ }
+ }
+}
+
+// Guard against breaking changes to the list of ignored event ack types in
+// |WebInputEventTraits::ShouldBlockEventStream|.
+TEST_F(InputRouterImplTest, RequiredEventAckTypes) {
+ const WebInputEvent::Type kRequiredEventAckTypes[] = {
+ WebInputEvent::kMouseMove,
+ WebInputEvent::kMouseWheel,
+ WebInputEvent::kRawKeyDown,
+ WebInputEvent::kKeyDown,
+ WebInputEvent::kKeyUp,
+ WebInputEvent::kChar,
+ WebInputEvent::kGestureScrollUpdate,
+ WebInputEvent::kGestureFlingStart,
+ WebInputEvent::kGestureFlingCancel,
+ WebInputEvent::kGesturePinchUpdate,
+ WebInputEvent::kTouchStart,
+ WebInputEvent::kTouchMove};
+ for (size_t i = 0; i < arraysize(kRequiredEventAckTypes); ++i) {
+ const WebInputEvent::Type required_ack_type = kRequiredEventAckTypes[i];
+ ASSERT_TRUE(ShouldBlockEventStream(GetEventWithType(required_ack_type)));
+ }
+}
+// Test that GestureShowPress, GestureTapDown and GestureTapCancel events don't
+// wait for ACKs.
+TEST_F(InputRouterImplTest, GestureTypesIgnoringAckInterleaved) {
+ // Interleave a few events that do and do not ignore acks, ensuring that
+ // ack-ignoring events aren't dispatched until all prior events which observe
+ // their ack disposition have been dispatched.
+
+ SimulateGestureEvent(WebInputEvent::kGestureScrollBegin,
+ blink::kWebGestureDeviceTouchscreen);
+ DispatchedEvents dispatched_events = GetAndResetDispatchedEvents();
+ EXPECT_EQ(1U, dispatched_events.size());
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
+ EXPECT_EQ(0, client_->in_flight_event_count());
+
+ SimulateGestureEvent(WebInputEvent::kGestureScrollUpdate,
+ blink::kWebGestureDeviceTouchscreen);
+ dispatched_events = GetAndResetDispatchedEvents();
+ EXPECT_EQ(2U, dispatched_events.size());
+ EXPECT_EQ(0U, disposition_handler_->GetAndResetAckCount());
+ EXPECT_EQ(1, client_->in_flight_event_count());
+
+ SimulateGestureEvent(WebInputEvent::kGestureTapDown,
+ blink::kWebGestureDeviceTouchscreen);
+ EXPECT_EQ(0U, GetAndResetDispatchedEvents().size());
+ EXPECT_EQ(0U, disposition_handler_->GetAndResetAckCount());
+ EXPECT_EQ(1, client_->in_flight_event_count());
+
+ SimulateGestureEvent(WebInputEvent::kGestureScrollUpdate,
+ blink::kWebGestureDeviceTouchscreen);
+ EXPECT_EQ(0U, GetAndResetDispatchedEvents().size());
+ EXPECT_EQ(0U, disposition_handler_->GetAndResetAckCount());
+
+ SimulateGestureEvent(WebInputEvent::kGestureShowPress,
+ blink::kWebGestureDeviceTouchscreen);
+ EXPECT_EQ(0U, GetAndResetDispatchedEvents().size());
+ EXPECT_EQ(0U, disposition_handler_->GetAndResetAckCount());
+
+ SimulateGestureEvent(WebInputEvent::kGestureScrollUpdate,
+ blink::kWebGestureDeviceTouchscreen);
+ EXPECT_EQ(0U, GetAndResetDispatchedEvents().size());
+ EXPECT_EQ(0U, disposition_handler_->GetAndResetAckCount());
+
+ SimulateGestureEvent(WebInputEvent::kGestureTapCancel,
+ blink::kWebGestureDeviceTouchscreen);
+ EXPECT_EQ(0U, GetAndResetDispatchedEvents().size());
+ EXPECT_EQ(0U, disposition_handler_->GetAndResetAckCount());
+
+ // Now ack each ack-respecting event. Ack-ignoring events should not be
+ // dispatched until all prior events which observe ack disposition have been
+ // fired, at which point they should be sent immediately. They should also
+ // have no effect on the in-flight event count.
+ CallCallback(std::move(dispatched_events.at(1).callback_),
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ dispatched_events = GetAndResetDispatchedEvents();
+ EXPECT_EQ(2U, dispatched_events.size());
+ EXPECT_EQ(2U, disposition_handler_->GetAndResetAckCount());
+ EXPECT_EQ(1, client_->in_flight_event_count());
+
+ // Ack the GestureScrollUpdate
+ CallCallback(std::move(dispatched_events.at(1).callback_),
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ dispatched_events = GetAndResetDispatchedEvents();
+ EXPECT_EQ(2U, dispatched_events.size());
+ EXPECT_EQ(2U, disposition_handler_->GetAndResetAckCount());
+ EXPECT_EQ(1, client_->in_flight_event_count());
+
+ // Ack the GestureScrollUpdate
+ CallCallback(std::move(dispatched_events.at(1).callback_),
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(1U, GetAndResetDispatchedEvents().size());
+ EXPECT_EQ(2U, disposition_handler_->GetAndResetAckCount());
+ EXPECT_EQ(0, client_->in_flight_event_count());
+}
+
+// Test that GestureShowPress events don't get out of order due to
+// ignoring their acks.
+TEST_F(InputRouterImplTest, GestureShowPressIsInOrder) {
+ SimulateGestureEvent(WebInputEvent::kGestureScrollBegin,
+ blink::kWebGestureDeviceTouchscreen);
+ DispatchedEvents dispatched_events = GetAndResetDispatchedEvents();
+ EXPECT_EQ(1U, dispatched_events.size());
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
+
+ // GesturePinchBegin ignores its ack.
+ SimulateGestureEvent(WebInputEvent::kGesturePinchBegin,
+ blink::kWebGestureDeviceTouchscreen);
+ dispatched_events = GetAndResetDispatchedEvents();
+ EXPECT_EQ(1U, dispatched_events.size());
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
+
+ // GesturePinchUpdate waits for an ack.
+ // This also verifies that GesturePinchUpdates for touchscreen are sent
+ // to the renderer (in contrast to the TrackpadPinchUpdate test).
+ SimulateGestureEvent(WebInputEvent::kGesturePinchUpdate,
+ blink::kWebGestureDeviceTouchscreen);
+ dispatched_events = GetAndResetDispatchedEvents();
+ EXPECT_EQ(1U, dispatched_events.size());
+ EXPECT_EQ(0U, disposition_handler_->GetAndResetAckCount());
+
+ SimulateGestureEvent(WebInputEvent::kGestureShowPress,
+ blink::kWebGestureDeviceTouchscreen);
+ EXPECT_EQ(0U, GetAndResetDispatchedEvents().size());
+ // The ShowPress, though it ignores ack, is still stuck in the queue
+ // behind the PinchUpdate which requires an ack.
+ EXPECT_EQ(0U, disposition_handler_->GetAndResetAckCount());
+
+ SimulateGestureEvent(WebInputEvent::kGestureShowPress,
+ blink::kWebGestureDeviceTouchscreen);
+ EXPECT_EQ(0U, GetAndResetDispatchedEvents().size());
+ // ShowPress has entered the queue.
+ EXPECT_EQ(0U, disposition_handler_->GetAndResetAckCount());
+
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ // Now that the Tap has been ACKed, the ShowPress events should receive
+ // synthetic acks, and fire immediately.
+ EXPECT_EQ(2U, GetAndResetDispatchedEvents().size());
+ EXPECT_EQ(3U, disposition_handler_->GetAndResetAckCount());
+}
+
+// Test that touch ack timeout behavior is properly configured for
+// mobile-optimized sites and allowed touch actions.
+TEST_F(InputRouterImplTest, TouchAckTimeoutConfigured) {
+ const int kDesktopTimeoutMs = 1;
+ const int kMobileTimeoutMs = 0;
+ SetUpForTouchAckTimeoutTest(kDesktopTimeoutMs, kMobileTimeoutMs);
+ ASSERT_TRUE(TouchEventTimeoutEnabled());
+
+ // Verify that the touch ack timeout fires upon the delayed ack.
+ PressTouchPoint(1, 1);
+ SendTouchEvent();
+ EXPECT_EQ(0U, disposition_handler_->GetAndResetAckCount());
+ DispatchedEvents dispatched_events = GetAndResetDispatchedEvents();
+ EXPECT_EQ(1U, dispatched_events.size());
+ RunTasksAndWait(base::TimeDelta::FromMilliseconds(kDesktopTimeoutMs + 1));
+
+ // The timed-out event should have been ack'ed.
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
+ EXPECT_EQ(0U, GetAndResetDispatchedEvents().size());
+
+ // Ack'ing the timed-out event should fire a TouchCancel.
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(0U, disposition_handler_->GetAndResetAckCount());
+ EXPECT_EQ(1U, GetAndResetDispatchedEvents().size());
+
+ // The remainder of the touch sequence should be dropped.
+ ReleaseTouchPoint(0);
+ SendTouchEvent();
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
+ EXPECT_EQ(0U, GetAndResetDispatchedEvents().size());
+ ASSERT_TRUE(TouchEventTimeoutEnabled());
+
+ // A mobile-optimized site should use the mobile timeout. For this test that
+ // timeout value is 0, which disables the timeout.
+ input_router()->NotifySiteIsMobileOptimized(true);
+ EXPECT_FALSE(TouchEventTimeoutEnabled());
+
+ input_router()->NotifySiteIsMobileOptimized(false);
+ EXPECT_TRUE(TouchEventTimeoutEnabled());
+
+ // kTouchActionNone (and no other touch-action) should disable the timeout.
+ OnHasTouchEventHandlers(true);
+ PressTouchPoint(1, 1);
+ SendTouchEvent();
+ DispatchedEvents touch_press_event2 = GetAndResetDispatchedEvents();
+ EXPECT_EQ(1U, touch_press_event2.size());
+ OnSetTouchAction(cc::kTouchActionPanY);
+ EXPECT_TRUE(TouchEventTimeoutEnabled());
+ ReleaseTouchPoint(0);
+ SendTouchEvent();
+ DispatchedEvents touch_release_event2 = GetAndResetDispatchedEvents();
+ EXPECT_EQ(1U, touch_release_event2.size());
+ CallCallback(std::move(touch_press_event2.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ CallCallback(std::move(touch_release_event2.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+
+ PressTouchPoint(1, 1);
+ SendTouchEvent();
+ DispatchedEvents touch_press_event3 = GetAndResetDispatchedEvents();
+ OnSetTouchAction(cc::kTouchActionNone);
+ EXPECT_FALSE(TouchEventTimeoutEnabled());
+ ReleaseTouchPoint(0);
+ SendTouchEvent();
+ DispatchedEvents touch_release_event3 = GetAndResetDispatchedEvents();
+ CallCallback(std::move(touch_press_event3.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ CallCallback(std::move(touch_release_event3.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+
+ // As the touch-action is reset by a new touch sequence, the timeout behavior
+ // should be restored.
+ PressTouchPoint(1, 1);
+ SendTouchEvent();
+ EXPECT_TRUE(TouchEventTimeoutEnabled());
+}
+
+// Test that a touch sequenced preceded by kTouchActionNone is not affected by
+// the touch timeout.
+TEST_F(InputRouterImplTest,
+ TouchAckTimeoutDisabledForTouchSequenceAfterTouchActionNone) {
+ const int kDesktopTimeoutMs = 1;
+ const int kMobileTimeoutMs = 2;
+ SetUpForTouchAckTimeoutTest(kDesktopTimeoutMs, kMobileTimeoutMs);
+ ASSERT_TRUE(TouchEventTimeoutEnabled());
+ OnHasTouchEventHandlers(true);
+
+ // Start a touch sequence.
+ PressTouchPoint(1, 1);
+ SendTouchEvent();
+ DispatchedEvents dispatched_events = GetAndResetDispatchedEvents();
+ EXPECT_EQ(1U, dispatched_events.size());
+
+ // kTouchActionNone should disable the timeout.
+ OnSetTouchAction(cc::kTouchActionNone);
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
+ EXPECT_FALSE(TouchEventTimeoutEnabled());
+
+ MoveTouchPoint(0, 1, 2);
+ SendTouchEvent();
+ dispatched_events = GetAndResetDispatchedEvents();
+ EXPECT_FALSE(TouchEventTimeoutEnabled());
+ EXPECT_EQ(1U, dispatched_events.size());
+
+ // Delay the move ack. The timeout should not fire.
+ RunTasksAndWait(base::TimeDelta::FromMilliseconds(kDesktopTimeoutMs + 1));
+ EXPECT_EQ(0U, disposition_handler_->GetAndResetAckCount());
+ EXPECT_EQ(0U, GetAndResetDispatchedEvents().size());
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
+
+ // End the touch sequence.
+ ReleaseTouchPoint(0);
+ SendTouchEvent();
+ dispatched_events = GetAndResetDispatchedEvents();
+ EXPECT_EQ(1U, dispatched_events.size());
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_TRUE(TouchEventTimeoutEnabled());
+ disposition_handler_->GetAndResetAckCount();
+ GetAndResetDispatchedEvents();
+
+ // Start another touch sequence. This should restore the touch timeout.
+ PressTouchPoint(1, 1);
+ SendTouchEvent();
+ EXPECT_TRUE(TouchEventTimeoutEnabled());
+ EXPECT_EQ(1U, GetAndResetDispatchedEvents().size());
+ EXPECT_EQ(0U, disposition_handler_->GetAndResetAckCount());
+
+ // Wait for the touch ack timeout to fire.
+ RunTasksAndWait(base::TimeDelta::FromMilliseconds(kDesktopTimeoutMs + 1));
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
+}
+
+// Test that TouchActionFilter::ResetTouchAction is called before the
+// first touch event for a touch sequence reaches the renderer.
+TEST_F(InputRouterImplTest, TouchActionResetBeforeEventReachesRenderer) {
+ OnHasTouchEventHandlers(true);
+
+ // Sequence 1.
+ PressTouchPoint(1, 1);
+ SendTouchEvent();
+ DispatchedEvents touch_press_event1 = GetAndResetDispatchedEvents();
+ EXPECT_EQ(1U, touch_press_event1.size());
+ OnSetTouchAction(cc::kTouchActionNone);
+ MoveTouchPoint(0, 50, 50);
+ SendTouchEvent();
+ DispatchedEvents touch_move_event1 = GetAndResetDispatchedEvents();
+ EXPECT_EQ(1U, touch_move_event1.size());
+ ReleaseTouchPoint(0);
+ SendTouchEvent();
+ DispatchedEvents touch_release_event1 = GetAndResetDispatchedEvents();
+ EXPECT_EQ(1U, touch_release_event1.size());
+
+ // Sequence 2.
+ PressTouchPoint(1, 1);
+ SendTouchEvent();
+ DispatchedEvents touch_press_event2 = GetAndResetDispatchedEvents();
+ EXPECT_EQ(1U, touch_press_event2.size());
+ MoveTouchPoint(0, 50, 50);
+ SendTouchEvent();
+ DispatchedEvents touch_move_event2 = GetAndResetDispatchedEvents();
+ EXPECT_EQ(1U, touch_move_event2.size());
+ ReleaseTouchPoint(0);
+ SendTouchEvent();
+ DispatchedEvents touch_release_event2 = GetAndResetDispatchedEvents();
+ EXPECT_EQ(1U, touch_release_event2.size());
+
+ CallCallback(std::move(touch_press_event1.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ CallCallback(std::move(touch_move_event1.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+
+ // Ensure touch action is still none, as the next touch start hasn't been
+ // acked yet. ScrollBegin and ScrollEnd don't require acks.
+ SimulateGestureEvent(WebInputEvent::kGestureScrollBegin,
+ blink::kWebGestureDeviceTouchscreen);
+ EXPECT_EQ(0U, GetAndResetDispatchedEvents().size());
+ SimulateGestureEvent(WebInputEvent::kGestureScrollEnd,
+ blink::kWebGestureDeviceTouchscreen);
+ EXPECT_EQ(0U, GetAndResetDispatchedEvents().size());
+
+ // This allows the next touch sequence to start.
+ CallCallback(std::move(touch_release_event1.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+
+ // Ensure touch action has been set to auto, as a new touch sequence has
+ // started.
+ CallCallback(std::move(touch_press_event2.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ CallCallback(std::move(touch_move_event2.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(0U, GetAndResetDispatchedEvents().size());
+ SimulateGestureEvent(WebInputEvent::kGestureScrollBegin,
+ blink::kWebGestureDeviceTouchscreen);
+ DispatchedEvents gesture_scroll_begin = GetAndResetDispatchedEvents();
+ EXPECT_EQ(1U, gesture_scroll_begin.size());
+ CallCallback(std::move(gesture_scroll_begin.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ SimulateGestureEvent(WebInputEvent::kGestureScrollEnd,
+ blink::kWebGestureDeviceTouchscreen);
+ EXPECT_EQ(1U, GetAndResetDispatchedEvents().size());
+ CallCallback(std::move(touch_release_event2.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+}
+
+// Test that TouchActionFilter::ResetTouchAction is called when a new touch
+// sequence has no consumer.
+TEST_F(InputRouterImplTest, TouchActionResetWhenTouchHasNoConsumer) {
+ OnHasTouchEventHandlers(true);
+
+ // Sequence 1.
+ PressTouchPoint(1, 1);
+ SendTouchEvent();
+ DispatchedEvents touch_press_event1 = GetAndResetDispatchedEvents();
+ EXPECT_EQ(1U, touch_press_event1.size());
+ MoveTouchPoint(0, 50, 50);
+ SendTouchEvent();
+ DispatchedEvents touch_move_event1 = GetAndResetDispatchedEvents();
+ EXPECT_EQ(1U, touch_move_event1.size());
+ OnSetTouchAction(cc::kTouchActionNone);
+ CallCallback(std::move(touch_press_event1.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ CallCallback(std::move(touch_move_event1.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+
+ ReleaseTouchPoint(0);
+ SendTouchEvent();
+ DispatchedEvents touch_release_event1 = GetAndResetDispatchedEvents();
+ EXPECT_EQ(1U, touch_move_event1.size());
+
+ // Sequence 2
+ PressTouchPoint(1, 1);
+ SendTouchEvent();
+ DispatchedEvents touch_press_event2 = GetAndResetDispatchedEvents();
+ EXPECT_EQ(1U, touch_press_event2.size());
+ MoveTouchPoint(0, 50, 50);
+ SendTouchEvent();
+ ReleaseTouchPoint(0);
+ SendTouchEvent();
+ EXPECT_EQ(2U, GetAndResetDispatchedEvents().size());
+
+ // Ensure we have touch-action:none. ScrollBegin and ScrollEnd don't require
+ // acks.
+ SimulateGestureEvent(WebInputEvent::kGestureScrollBegin,
+ blink::kWebGestureDeviceTouchscreen);
+ EXPECT_EQ(0U, GetAndResetDispatchedEvents().size());
+ SimulateGestureEvent(WebInputEvent::kGestureScrollEnd,
+ blink::kWebGestureDeviceTouchscreen);
+ EXPECT_EQ(0U, GetAndResetDispatchedEvents().size());
+
+ CallCallback(std::move(touch_release_event1.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ CallCallback(std::move(touch_press_event2.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
+
+ // Ensure touch action has been set to auto, as the touch had no consumer.
+ EXPECT_EQ(0U, GetAndResetDispatchedEvents().size());
+ SimulateGestureEvent(WebInputEvent::kGestureScrollBegin,
+ blink::kWebGestureDeviceTouchscreen);
+ DispatchedEvents dispatched_events = GetAndResetDispatchedEvents();
+ EXPECT_EQ(1U, dispatched_events.size());
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ SimulateGestureEvent(WebInputEvent::kGestureScrollEnd,
+ blink::kWebGestureDeviceTouchscreen);
+ EXPECT_EQ(1U, GetAndResetDispatchedEvents().size());
+}
+
+// Test that TouchActionFilter::ResetTouchAction is called when the touch
+// handler is removed.
+TEST_F(InputRouterImplTest, TouchActionResetWhenTouchHandlerRemoved) {
+ // Touch sequence with touch handler.
+ OnHasTouchEventHandlers(true);
+ PressTouchPoint(1, 1);
+ SendTouchEvent();
+ MoveTouchPoint(0, 50, 50);
+ SendTouchEvent();
+ OnSetTouchAction(cc::kTouchActionNone);
+ ReleaseTouchPoint(0);
+ SendTouchEvent();
+ DispatchedEvents dispatched_events = GetAndResetDispatchedEvents();
+ EXPECT_EQ(3U, dispatched_events.size());
+
+ // Ensure we have touch-action:none, suppressing scroll events.
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(0U, GetAndResetDispatchedEvents().size());
+ CallCallback(std::move(dispatched_events.at(1).callback_),
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(0U, GetAndResetDispatchedEvents().size());
+ SimulateGestureEvent(WebInputEvent::kGestureScrollBegin,
+ blink::kWebGestureDeviceTouchscreen);
+ EXPECT_EQ(0U, GetAndResetDispatchedEvents().size());
+
+ CallCallback(std::move(dispatched_events.at(2).callback_),
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ SimulateGestureEvent(WebInputEvent::kGestureScrollEnd,
+ blink::kWebGestureDeviceTouchscreen);
+ EXPECT_EQ(0U, GetAndResetDispatchedEvents().size());
+
+ // Sequence without a touch handler. Note that in this case, the view may not
+ // necessarily forward touches to the router (as no touch handler exists).
+ OnHasTouchEventHandlers(false);
+
+ // Ensure touch action has been set to auto, as the touch handler has been
+ // removed.
+ SimulateGestureEvent(WebInputEvent::kGestureScrollBegin,
+ blink::kWebGestureDeviceTouchscreen);
+ dispatched_events = GetAndResetDispatchedEvents();
+ EXPECT_EQ(1U, dispatched_events.size());
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ SimulateGestureEvent(WebInputEvent::kGestureScrollEnd,
+ blink::kWebGestureDeviceTouchscreen);
+ EXPECT_EQ(1U, GetAndResetDispatchedEvents().size());
+}
+
+// Tests that async touch-moves are ack'd from the browser side.
+TEST_F(InputRouterImplTest, AsyncTouchMoveAckedImmediately) {
+ OnHasTouchEventHandlers(true);
+
+ PressTouchPoint(1, 1);
+ SendTouchEvent();
+ EXPECT_TRUE(client_->GetAndResetFilterEventCalled());
+ DispatchedEvents dispatched_events = GetAndResetDispatchedEvents();
+ EXPECT_EQ(1U, dispatched_events.size());
+ EXPECT_FALSE(TouchEventQueueEmpty());
+
+ // Receive an ACK for the first touch-event.
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
+ SimulateGestureEvent(WebInputEvent::kGestureScrollBegin,
+ blink::kWebGestureDeviceTouchscreen);
+ dispatched_events = GetAndResetDispatchedEvents();
+ EXPECT_EQ(1U, dispatched_events.size());
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
+ SimulateGestureEvent(WebInputEvent::kGestureScrollUpdate,
+ blink::kWebGestureDeviceTouchscreen);
+ EXPECT_EQ(0U, disposition_handler_->GetAndResetAckCount());
+ EXPECT_EQ(2U, GetAndResetDispatchedEvents().size());
+
+ // Now send an async move.
+ MoveTouchPoint(0, 5, 5);
+ SendTouchEvent();
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
+ EXPECT_EQ(1U, GetAndResetDispatchedEvents().size());
+}
+
+// Test that the double tap gesture depends on the touch action of the first
+// tap.
+TEST_F(InputRouterImplTest, DoubleTapGestureDependsOnFirstTap) {
+ OnHasTouchEventHandlers(true);
+
+ // Sequence 1.
+ PressTouchPoint(1, 1);
+ SendTouchEvent();
+ OnSetTouchAction(cc::kTouchActionNone);
+ DispatchedEvents dispatched_events = GetAndResetDispatchedEvents();
+ EXPECT_EQ(1U, dispatched_events.size());
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+
+ ReleaseTouchPoint(0);
+ SendTouchEvent();
+
+ // Sequence 2
+ PressTouchPoint(1, 1);
+ SendTouchEvent();
+
+ // First tap.
+ SimulateGestureEvent(WebInputEvent::kGestureTapDown,
+ blink::kWebGestureDeviceTouchscreen);
+
+ // The GestureTapUnconfirmed is converted into a tap, as the touch action is
+ // none.
+ SimulateGestureEvent(WebInputEvent::kGestureTapUnconfirmed,
+ blink::kWebGestureDeviceTouchscreen);
+ dispatched_events = GetAndResetDispatchedEvents();
+ EXPECT_EQ(4U, dispatched_events.size());
+ // This test will become invalid if GestureTap stops requiring an ack.
+ ASSERT_TRUE(
+ ShouldBlockEventStream(GetEventWithType(WebInputEvent::kGestureTap)));
+ EXPECT_EQ(3, client_->in_flight_event_count());
+
+ CallCallback(std::move(dispatched_events.at(3).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(2, client_->in_flight_event_count());
+
+ // This tap gesture is dropped, since the GestureTapUnconfirmed was turned
+ // into a tap.
+ SimulateGestureEvent(WebInputEvent::kGestureTap,
+ blink::kWebGestureDeviceTouchscreen);
+ EXPECT_EQ(0U, GetAndResetDispatchedEvents().size());
+
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ CallCallback(std::move(dispatched_events.at(1).callback_),
+ INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
+
+ // Second Tap.
+ EXPECT_EQ(0U, GetAndResetDispatchedEvents().size());
+ SimulateGestureEvent(WebInputEvent::kGestureTapDown,
+ blink::kWebGestureDeviceTouchscreen);
+ dispatched_events = GetAndResetDispatchedEvents();
+ EXPECT_EQ(1U, dispatched_events.size());
+
+ // Although the touch-action is now auto, the double tap still won't be
+ // dispatched, because the first tap occured when the touch-action was none.
+ SimulateGestureEvent(WebInputEvent::kGestureDoubleTap,
+ blink::kWebGestureDeviceTouchscreen);
+ dispatched_events = GetAndResetDispatchedEvents();
+ EXPECT_EQ(1U, dispatched_events.size());
+ // This test will become invalid if GestureDoubleTap stops requiring an ack.
+ ASSERT_TRUE(ShouldBlockEventStream(
+ GetEventWithType(WebInputEvent::kGestureDoubleTap)));
+ EXPECT_EQ(1, client_->in_flight_event_count());
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(0, client_->in_flight_event_count());
+}
+
+// Test that the double tap gesture depends on the touch action of the first
+// tap.
+TEST_F(InputRouterImplRafAlignedTouchDisabledTest,
+ DoubleTapGestureDependsOnFirstTap) {
+ OnHasTouchEventHandlers(true);
+
+ // Sequence 1.
+ PressTouchPoint(1, 1);
+ SendTouchEvent();
+ OnSetTouchAction(cc::kTouchActionNone);
+ DispatchedEvents dispatched_events = GetAndResetDispatchedEvents();
+ EXPECT_EQ(1U, dispatched_events.size());
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+
+ ReleaseTouchPoint(0);
+ SendTouchEvent();
+
+ // Sequence 2
+ PressTouchPoint(1, 1);
+ SendTouchEvent();
+
+ // First tap.
+ SimulateGestureEvent(WebInputEvent::kGestureTapDown,
+ blink::kWebGestureDeviceTouchscreen);
+
+ // The GestureTapUnconfirmed is converted into a tap, as the touch action is
+ // none.
+ SimulateGestureEvent(WebInputEvent::kGestureTapUnconfirmed,
+ blink::kWebGestureDeviceTouchscreen);
+ dispatched_events = GetAndResetDispatchedEvents();
+ EXPECT_EQ(3U, dispatched_events.size());
+ // This test will become invalid if GestureTap stops requiring an ack.
+ ASSERT_TRUE(
+ ShouldBlockEventStream(GetEventWithType(WebInputEvent::kGestureTap)));
+ EXPECT_EQ(2, client_->in_flight_event_count());
+ CallCallback(std::move(dispatched_events.at(2).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+
+ EXPECT_EQ(1, client_->in_flight_event_count());
+
+ // This tap gesture is dropped, since the GestureTapUnconfirmed was turned
+ // into a tap.
+ SimulateGestureEvent(WebInputEvent::kGestureTap,
+ blink::kWebGestureDeviceTouchscreen);
+ EXPECT_EQ(0U, GetAndResetDispatchedEvents().size());
+
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+
+ dispatched_events = GetAndResetDispatchedEvents();
+ EXPECT_EQ(1U, dispatched_events.size());
+ ASSERT_EQ(WebInputEvent::kTouchStart,
+ dispatched_events.at(0).event_->web_event->GetType());
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
+
+ // Second Tap.
+ SimulateGestureEvent(WebInputEvent::kGestureTapDown,
+ blink::kWebGestureDeviceTouchscreen);
+ EXPECT_EQ(1U, GetAndResetDispatchedEvents().size());
+
+ // Although the touch-action is now auto, the double tap still won't be
+ // dispatched, because the first tap occured when the touch-action was none.
+ SimulateGestureEvent(WebInputEvent::kGestureDoubleTap,
+ blink::kWebGestureDeviceTouchscreen);
+ dispatched_events = GetAndResetDispatchedEvents();
+ EXPECT_EQ(1U, dispatched_events.size());
+ // This test will become invalid if GestureDoubleTap stops requiring an ack.
+ ASSERT_TRUE(ShouldBlockEventStream(
+ GetEventWithType(WebInputEvent::kGestureDoubleTap)));
+ EXPECT_EQ(1, client_->in_flight_event_count());
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(0, client_->in_flight_event_count());
+}
+
+// Test that GesturePinchUpdate is handled specially for trackpad
+TEST_F(InputRouterImplTest, TouchpadPinchUpdate) {
+ // GesturePinchUpdate for trackpad sends synthetic wheel events.
+ // Note that the Touchscreen case is verified as NOT doing this as
+ // part of the ShowPressIsInOrder test.
+
+ SimulateGesturePinchUpdateEvent(1.5f, 20, 25, 0,
+ blink::kWebGestureDeviceTouchpad);
+
+ // Verify we actually sent a special wheel event to the renderer.
+ DispatchedEvents dispatched_events = GetAndResetDispatchedEvents();
+ EXPECT_EQ(1U, dispatched_events.size());
+ const WebInputEvent* input_event =
+ dispatched_events.at(0).event_->web_event.get();
+ ASSERT_EQ(WebInputEvent::kGesturePinchUpdate, input_event->GetType());
+ const WebGestureEvent* gesture_event =
+ static_cast<const WebGestureEvent*>(input_event);
+ EXPECT_EQ(20, gesture_event->x);
+ EXPECT_EQ(25, gesture_event->y);
+ EXPECT_EQ(20, gesture_event->global_x);
+ EXPECT_EQ(25, gesture_event->global_y);
+
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+
+ // Check that the correct unhandled pinch event was received.
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
+ ASSERT_EQ(WebInputEvent::kGesturePinchUpdate,
+ disposition_handler_->ack_event_type());
+ EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED,
+ disposition_handler_->ack_state());
+ EXPECT_EQ(
+ 1.5f,
+ disposition_handler_->acked_gesture_event().data.pinch_update.scale);
+ EXPECT_EQ(0, client_->in_flight_event_count());
+
+ // Second a second pinch event.
+ SimulateGesturePinchUpdateEvent(0.3f, 20, 25, 0,
+ blink::kWebGestureDeviceTouchpad);
+ dispatched_events = GetAndResetDispatchedEvents();
+ EXPECT_EQ(1U, dispatched_events.size());
+ input_event = dispatched_events.at(0).event_->web_event.get();
+ ASSERT_EQ(WebInputEvent::kGesturePinchUpdate, input_event->GetType());
+ gesture_event = static_cast<const WebGestureEvent*>(input_event);
+
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+
+ // Check that the correct HANDLED pinch event was received.
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
+ EXPECT_EQ(WebInputEvent::kGesturePinchUpdate,
+ disposition_handler_->ack_event_type());
+ EXPECT_EQ(INPUT_EVENT_ACK_STATE_CONSUMED, disposition_handler_->ack_state());
+ EXPECT_FLOAT_EQ(
+ 0.3f,
+ disposition_handler_->acked_gesture_event().data.pinch_update.scale);
+}
+
+// Test proper handling of touchpad Gesture{Pinch,Scroll}Update sequences.
+TEST_F(InputRouterImplTest, TouchpadPinchAndScrollUpdate) {
+ // The first scroll should be sent immediately.
+ SimulateGestureScrollUpdateEvent(1.5f, 0.f, 0,
+ blink::kWebGestureDeviceTouchpad);
+ SimulateGestureEvent(WebInputEvent::kGestureScrollUpdate,
+ blink::kWebGestureDeviceTouchpad);
+ DispatchedEvents dispatched_events = GetAndResetDispatchedEvents();
+ EXPECT_EQ(1U, dispatched_events.size());
+ EXPECT_EQ(1, client_->in_flight_event_count());
+
+ // Subsequent scroll and pinch events should remain queued, coalescing as
+ // more trackpad events arrive.
+ SimulateGesturePinchUpdateEvent(1.5f, 20, 25, 0,
+ blink::kWebGestureDeviceTouchpad);
+ ASSERT_EQ(0U, GetAndResetDispatchedEvents().size());
+ EXPECT_EQ(1, client_->in_flight_event_count());
+
+ SimulateGestureScrollUpdateEvent(1.5f, 1.5f, 0,
+ blink::kWebGestureDeviceTouchpad);
+ ASSERT_EQ(0U, GetAndResetDispatchedEvents().size());
+ EXPECT_EQ(1, client_->in_flight_event_count());
+
+ SimulateGesturePinchUpdateEvent(1.5f, 20, 25, 0,
+ blink::kWebGestureDeviceTouchpad);
+ ASSERT_EQ(0U, GetAndResetDispatchedEvents().size());
+ EXPECT_EQ(1, client_->in_flight_event_count());
+
+ SimulateGestureScrollUpdateEvent(0.f, 1.5f, 0,
+ blink::kWebGestureDeviceTouchpad);
+ ASSERT_EQ(0U, GetAndResetDispatchedEvents().size());
+ EXPECT_EQ(1, client_->in_flight_event_count());
+
+ // Ack'ing the first scroll should trigger both the coalesced scroll and the
+ // coalesced pinch events (which is sent to the renderer as a wheel event).
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
+ dispatched_events = GetAndResetDispatchedEvents();
+ EXPECT_EQ(2U, dispatched_events.size());
+ EXPECT_EQ(2, client_->in_flight_event_count());
+
+ // Ack the second scroll.
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ ASSERT_EQ(0U, GetAndResetDispatchedEvents().size());
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
+ EXPECT_EQ(1, client_->in_flight_event_count());
+
+ // Ack the wheel event.
+ CallCallback(std::move(dispatched_events.at(1).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ ASSERT_EQ(0U, GetAndResetDispatchedEvents().size());
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
+ EXPECT_EQ(0, client_->in_flight_event_count());
+}
+
+// Test proper routing of overscroll notifications received either from
+// event acks or from |DidOverscroll| IPC messages.
+void InputRouterImplTest::OverscrollDispatch() {
+ DidOverscrollParams overscroll;
+ overscroll.accumulated_overscroll = gfx::Vector2dF(-14, 14);
+ overscroll.latest_overscroll_delta = gfx::Vector2dF(-7, 0);
+ overscroll.current_fling_velocity = gfx::Vector2dF(-1, 0);
+
+ input_router_->OnMessageReceived(InputHostMsg_DidOverscroll(0, overscroll));
+ DidOverscrollParams client_overscroll = client_->GetAndResetOverscroll();
+ EXPECT_EQ(overscroll.accumulated_overscroll,
+ client_overscroll.accumulated_overscroll);
+ EXPECT_EQ(overscroll.latest_overscroll_delta,
+ client_overscroll.latest_overscroll_delta);
+ EXPECT_EQ(overscroll.current_fling_velocity,
+ client_overscroll.current_fling_velocity);
+
+ DidOverscrollParams wheel_overscroll;
+ wheel_overscroll.accumulated_overscroll = gfx::Vector2dF(7, -7);
+ wheel_overscroll.latest_overscroll_delta = gfx::Vector2dF(3, 0);
+ wheel_overscroll.current_fling_velocity = gfx::Vector2dF(1, 0);
+
+ SimulateWheelEventPossiblyIncludingPhase(!wheel_scroll_latching_enabled_, 0,
+ 0, 3, 0, 0, false,
+ WebMouseWheelEvent::kPhaseBegan);
+ DispatchedEvents dispatched_events = GetAndResetDispatchedEvents();
+ EXPECT_EQ(1U, dispatched_events.size());
+
+ std::move(dispatched_events.at(0).callback_)
+ .Run(InputEventAckSource::COMPOSITOR_THREAD, ui::LatencyInfo(),
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED,
+ DidOverscrollParams(wheel_overscroll), base::nullopt);
+
+ client_overscroll = client_->GetAndResetOverscroll();
+ EXPECT_EQ(wheel_overscroll.accumulated_overscroll,
+ client_overscroll.accumulated_overscroll);
+ EXPECT_EQ(wheel_overscroll.latest_overscroll_delta,
+ client_overscroll.latest_overscroll_delta);
+ EXPECT_EQ(wheel_overscroll.current_fling_velocity,
+ client_overscroll.current_fling_velocity);
+}
+
+TEST_F(InputRouterImplTest, OverscrollDispatch) {
+ OverscrollDispatch();
+}
+TEST_F(InputRouterImplWheelScrollLatchingDisabledTest, OverscrollDispatch) {
+ OverscrollDispatch();
+}
+TEST_F(InputRouterImplAsyncWheelEventEnabledTest, OverscrollDispatch) {
+ OverscrollDispatch();
+}
+
+// Test proper routing of whitelisted touch action notifications received from
+// |SetWhiteListedTouchAction| IPC messages.
+TEST_F(InputRouterImplTest, OnSetWhiteListedTouchAction) {
+ cc::TouchAction touch_action = cc::kTouchActionPanY;
+ OnSetWhiteListedTouchAction(touch_action, 0,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ cc::TouchAction white_listed_touch_action =
+ client_->GetAndResetWhiteListedTouchAction();
+ EXPECT_EQ(touch_action, white_listed_touch_action);
+}
+
+// Tests that touch event stream validation passes when events are filtered
+// out. See crbug.com/581231 for details.
+TEST_F(InputRouterImplTest, TouchValidationPassesWithFilteredInputEvents) {
+ // Touch sequence with touch handler.
+ OnHasTouchEventHandlers(true);
+ PressTouchPoint(1, 1);
+ SendTouchEvent();
+ DispatchedEvents dispatched_events = GetAndResetDispatchedEvents();
+ EXPECT_EQ(1U, dispatched_events.size());
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
+
+ PressTouchPoint(1, 1);
+ SendTouchEvent();
+ dispatched_events = GetAndResetDispatchedEvents();
+ EXPECT_EQ(1U, dispatched_events.size());
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
+
+ // This event will be filtered out, since no consumer exists.
+ ReleaseTouchPoint(1);
+ SendTouchEvent();
+ dispatched_events = GetAndResetDispatchedEvents();
+ EXPECT_EQ(0U, dispatched_events.size());
+
+ // If the validator didn't see the filtered out release event, it will crash
+ // now, upon seeing a press for a touch which it believes to be still pressed.
+ PressTouchPoint(1, 1);
+ SendTouchEvent();
+ dispatched_events = GetAndResetDispatchedEvents();
+ EXPECT_EQ(1U, dispatched_events.size());
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
+}
+
+TEST_F(InputRouterImplTest, TouchActionInCallback) {
+ OnHasTouchEventHandlers(true);
+
+ // Send a touchstart
+ PressTouchPoint(1, 1);
+ SendTouchEvent();
+ DispatchedEvents dispatched_events = GetAndResetDispatchedEvents();
+ EXPECT_EQ(1U, dispatched_events.size());
+ CallCallbackWithTouchAction(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED,
+ cc::TouchAction::kTouchActionNone);
+ ASSERT_EQ(1U, disposition_handler_->GetAndResetAckCount());
+ EXPECT_EQ(cc::TouchAction::kTouchActionNone,
+ input_router_->AllowedTouchAction());
+}
+
+namespace {
+
+class InputRouterImplScaleEventTest : public InputRouterImplTest {
+ public:
+ InputRouterImplScaleEventTest() {}
+
+ void SetUp() override {
+ InputRouterImplTest::SetUp();
+ input_router_->SetDeviceScaleFactor(2.f);
+ }
+
+ template <typename T>
+ const T* GetSentWebInputEvent() {
+ EXPECT_EQ(1u, dispatched_events_.size());
+
+ return static_cast<const T*>(
+ dispatched_events_.at(0).event_->web_event.get());
+ }
+
+ template <typename T>
+ const T* GetFilterWebInputEvent() const {
+ return static_cast<const T*>(client_->last_filter_event());
+ }
+
+ void UpdateDispatchedEvents() {
+ dispatched_events_ = GetAndResetDispatchedEvents();
+ }
+
+ protected:
+ DispatchedEvents dispatched_events_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(InputRouterImplScaleEventTest);
+};
+
+class InputRouterImplScaleMouseEventTest
+ : public InputRouterImplScaleEventTest {
+ public:
+ InputRouterImplScaleMouseEventTest() {}
+
+ void RunMouseEventTest(const std::string& name, WebInputEvent::Type type) {
+ SCOPED_TRACE(name);
+ SimulateMouseEvent(type, 10, 10);
+ UpdateDispatchedEvents();
+ const WebMouseEvent* sent_event = GetSentWebInputEvent<WebMouseEvent>();
+ EXPECT_EQ(20, sent_event->PositionInWidget().x);
+ EXPECT_EQ(20, sent_event->PositionInWidget().y);
+
+ const WebMouseEvent* filter_event = GetFilterWebInputEvent<WebMouseEvent>();
+ EXPECT_EQ(10, filter_event->PositionInWidget().x);
+ EXPECT_EQ(10, filter_event->PositionInWidget().y);
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(InputRouterImplScaleMouseEventTest);
+};
+
+} // namespace
+
+TEST_F(InputRouterImplScaleMouseEventTest, ScaleMouseEventTest) {
+ RunMouseEventTest("Enter", WebInputEvent::kMouseEnter);
+ RunMouseEventTest("Down", WebInputEvent::kMouseDown);
+ RunMouseEventTest("Move", WebInputEvent::kMouseMove);
+ RunMouseEventTest("Up", WebInputEvent::kMouseUp);
+}
+
+TEST_F(InputRouterImplScaleEventTest, ScaleMouseWheelEventTest) {
+ SimulateWheelEventWithPhase(5, 5, 10, 10, 0, false,
+ WebMouseWheelEvent::kPhaseBegan);
+ UpdateDispatchedEvents();
+
+ const WebMouseWheelEvent* sent_event =
+ GetSentWebInputEvent<WebMouseWheelEvent>();
+ EXPECT_EQ(10, sent_event->PositionInWidget().x);
+ EXPECT_EQ(10, sent_event->PositionInWidget().y);
+ EXPECT_EQ(20, sent_event->delta_x);
+ EXPECT_EQ(20, sent_event->delta_y);
+ EXPECT_EQ(2, sent_event->wheel_ticks_x);
+ EXPECT_EQ(2, sent_event->wheel_ticks_y);
+
+ const WebMouseWheelEvent* filter_event =
+ GetFilterWebInputEvent<WebMouseWheelEvent>();
+ EXPECT_EQ(5, filter_event->PositionInWidget().x);
+ EXPECT_EQ(5, filter_event->PositionInWidget().y);
+ EXPECT_EQ(10, filter_event->delta_x);
+ EXPECT_EQ(10, filter_event->delta_y);
+ EXPECT_EQ(1, filter_event->wheel_ticks_x);
+ EXPECT_EQ(1, filter_event->wheel_ticks_y);
+
+ EXPECT_EQ(sent_event->acceleration_ratio_x,
+ filter_event->acceleration_ratio_x);
+ EXPECT_EQ(sent_event->acceleration_ratio_y,
+ filter_event->acceleration_ratio_y);
+}
+
+namespace {
+
+class InputRouterImplScaleTouchEventTest
+ : public InputRouterImplScaleEventTest {
+ public:
+ InputRouterImplScaleTouchEventTest() {}
+
+ // Test tests if two finger touch event at (10, 20) and (100, 200) are
+ // properly scaled. The touch event must be generated ans flushed into
+ // the message sink prior to this method.
+ void RunTouchEventTest(const std::string& name, WebTouchPoint::State state) {
+ SCOPED_TRACE(name);
+ const WebTouchEvent* sent_event = GetSentWebInputEvent<WebTouchEvent>();
+ ASSERT_EQ(2u, sent_event->touches_length);
+ EXPECT_EQ(state, sent_event->touches[0].state);
+ EXPECT_EQ(20, sent_event->touches[0].PositionInWidget().x);
+ EXPECT_EQ(40, sent_event->touches[0].PositionInWidget().y);
+ EXPECT_EQ(10, sent_event->touches[0].PositionInScreen().x);
+ EXPECT_EQ(20, sent_event->touches[0].PositionInScreen().y);
+ EXPECT_EQ(2, sent_event->touches[0].radius_x);
+ EXPECT_EQ(2, sent_event->touches[0].radius_y);
+
+ EXPECT_EQ(200, sent_event->touches[1].PositionInWidget().x);
+ EXPECT_EQ(400, sent_event->touches[1].PositionInWidget().y);
+ EXPECT_EQ(100, sent_event->touches[1].PositionInScreen().x);
+ EXPECT_EQ(200, sent_event->touches[1].PositionInScreen().y);
+ EXPECT_EQ(2, sent_event->touches[1].radius_x);
+ EXPECT_EQ(2, sent_event->touches[1].radius_y);
+
+ const WebTouchEvent* filter_event = GetFilterWebInputEvent<WebTouchEvent>();
+ ASSERT_EQ(2u, filter_event->touches_length);
+ EXPECT_EQ(10, filter_event->touches[0].PositionInWidget().x);
+ EXPECT_EQ(20, filter_event->touches[0].PositionInWidget().y);
+ EXPECT_EQ(10, filter_event->touches[0].PositionInScreen().x);
+ EXPECT_EQ(20, filter_event->touches[0].PositionInScreen().y);
+ EXPECT_EQ(1, filter_event->touches[0].radius_x);
+ EXPECT_EQ(1, filter_event->touches[0].radius_y);
+
+ EXPECT_EQ(100, filter_event->touches[1].PositionInWidget().x);
+ EXPECT_EQ(200, filter_event->touches[1].PositionInWidget().y);
+ EXPECT_EQ(100, filter_event->touches[1].PositionInScreen().x);
+ EXPECT_EQ(200, filter_event->touches[1].PositionInScreen().y);
+ EXPECT_EQ(1, filter_event->touches[1].radius_x);
+ EXPECT_EQ(1, filter_event->touches[1].radius_y);
+ }
+
+ void FlushTouchEvent(WebInputEvent::Type type) {
+ SendTouchEvent();
+ UpdateDispatchedEvents();
+ EXPECT_EQ(1u, dispatched_events_.size());
+ if (dispatched_events_.at(0).callback_) {
+ CallCallback(std::move(dispatched_events_.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ }
+ ASSERT_TRUE(TouchEventQueueEmpty());
+ }
+
+ void ReleaseTouchPointAndAck(int index) {
+ ReleaseTouchPoint(index);
+ SendTouchEvent();
+ UpdateDispatchedEvents();
+ EXPECT_EQ(1u, dispatched_events_.size());
+ CallCallback(std::move(dispatched_events_.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(InputRouterImplScaleTouchEventTest);
+};
+
+} // namespace
+
+TEST_F(InputRouterImplScaleTouchEventTest, ScaleTouchEventTest) {
+ // Press
+ PressTouchPoint(10, 20);
+ PressTouchPoint(100, 200);
+ FlushTouchEvent(WebInputEvent::kTouchStart);
+
+ RunTouchEventTest("Press", WebTouchPoint::kStatePressed);
+ ReleaseTouchPointAndAck(1);
+ ReleaseTouchPointAndAck(0);
+
+ // Move
+ PressTouchPoint(0, 0);
+ PressTouchPoint(0, 0);
+ FlushTouchEvent(WebInputEvent::kTouchStart);
+
+ MoveTouchPoint(0, 10, 20);
+ MoveTouchPoint(1, 100, 200);
+ FlushTouchEvent(WebInputEvent::kTouchMove);
+ RunTouchEventTest("Move", WebTouchPoint::kStateMoved);
+ ReleaseTouchPointAndAck(1);
+ ReleaseTouchPointAndAck(0);
+
+ // Release
+ PressTouchPoint(10, 20);
+ PressTouchPoint(100, 200);
+ FlushTouchEvent(WebInputEvent::kTouchMove);
+
+ ReleaseTouchPoint(0);
+ ReleaseTouchPoint(1);
+ FlushTouchEvent(WebInputEvent::kTouchEnd);
+ RunTouchEventTest("Release", WebTouchPoint::kStateReleased);
+
+ // Cancel
+ PressTouchPoint(10, 20);
+ PressTouchPoint(100, 200);
+ FlushTouchEvent(WebInputEvent::kTouchStart);
+
+ CancelTouchPoint(0);
+ CancelTouchPoint(1);
+ FlushTouchEvent(WebInputEvent::kTouchCancel);
+ RunTouchEventTest("Cancel", WebTouchPoint::kStateCancelled);
+}
+
+namespace {
+
+class InputRouterImplScaleGestureEventTest
+ : public InputRouterImplScaleEventTest {
+ public:
+ InputRouterImplScaleGestureEventTest() {}
+
+ WebGestureEvent BuildGestureEvent(WebInputEvent::Type type,
+ const gfx::Point& point) {
+ WebGestureEvent event = SyntheticWebGestureEventBuilder::Build(
+ type, blink::kWebGestureDeviceTouchpad);
+ event.global_x = event.x = point.x();
+ event.global_y = event.y = point.y();
+ return event;
+ }
+
+ void TestTap(const std::string& name, WebInputEvent::Type type) {
+ SCOPED_TRACE(name);
+ const gfx::Point orig(10, 20), scaled(20, 40);
+ WebGestureEvent event = BuildGestureEvent(type, orig);
+ event.data.tap.width = 30;
+ event.data.tap.height = 40;
+ SimulateGestureEvent(event);
+ FlushGestureEvent(type);
+
+ const WebGestureEvent* sent_event = GetSentWebInputEvent<WebGestureEvent>();
+ TestLocationInSentEvent(sent_event, orig, scaled);
+ EXPECT_EQ(60, sent_event->data.tap.width);
+ EXPECT_EQ(80, sent_event->data.tap.height);
+
+ const WebGestureEvent* filter_event =
+ GetFilterWebInputEvent<WebGestureEvent>();
+ TestLocationInFilterEvent(filter_event, orig);
+ EXPECT_EQ(30, filter_event->data.tap.width);
+ EXPECT_EQ(40, filter_event->data.tap.height);
+ }
+
+ void TestLongPress(const std::string& name, WebInputEvent::Type type) {
+ const gfx::Point orig(10, 20), scaled(20, 40);
+ WebGestureEvent event = BuildGestureEvent(type, orig);
+ event.data.long_press.width = 30;
+ event.data.long_press.height = 40;
+ SimulateGestureEvent(event);
+ FlushGestureEvent(type);
+ const WebGestureEvent* sent_event = GetSentWebInputEvent<WebGestureEvent>();
+ TestLocationInSentEvent(sent_event, orig, scaled);
+ EXPECT_EQ(60, sent_event->data.long_press.width);
+ EXPECT_EQ(80, sent_event->data.long_press.height);
+
+ const WebGestureEvent* filter_event =
+ GetFilterWebInputEvent<WebGestureEvent>();
+ TestLocationInFilterEvent(filter_event, orig);
+ EXPECT_EQ(30, filter_event->data.long_press.width);
+ EXPECT_EQ(40, filter_event->data.long_press.height);
+ }
+
+ void FlushGestureEvent(WebInputEvent::Type type) {
+ UpdateDispatchedEvents();
+ EXPECT_EQ(1u, dispatched_events_.size());
+ if (dispatched_events_.at(0).callback_) {
+ CallCallback(std::move(dispatched_events_.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ }
+ }
+
+ void TestLocationInSentEvent(const WebGestureEvent* sent_event,
+ const gfx::Point& orig,
+ const gfx::Point& scaled) {
+ EXPECT_EQ(20, sent_event->x);
+ EXPECT_EQ(40, sent_event->y);
+ EXPECT_EQ(10, sent_event->global_x);
+ EXPECT_EQ(20, sent_event->global_y);
+ }
+
+ void TestLocationInFilterEvent(const WebGestureEvent* filter_event,
+ const gfx::Point& point) {
+ EXPECT_EQ(10, filter_event->x);
+ EXPECT_EQ(20, filter_event->y);
+ EXPECT_EQ(10, filter_event->global_x);
+ EXPECT_EQ(20, filter_event->global_y);
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(InputRouterImplScaleGestureEventTest);
+};
+
+} // namespace
+
+TEST_F(InputRouterImplScaleGestureEventTest, GestureScrollUpdate) {
+ SimulateGestureScrollUpdateEvent(10.f, 20, 0,
+ blink::kWebGestureDeviceTouchpad);
+ FlushGestureEvent(WebInputEvent::kGestureScrollUpdate);
+ const WebGestureEvent* sent_event = GetSentWebInputEvent<WebGestureEvent>();
+
+ EXPECT_EQ(20.f, sent_event->data.scroll_update.delta_x);
+ EXPECT_EQ(40.f, sent_event->data.scroll_update.delta_y);
+
+ const WebGestureEvent* filter_event =
+ GetFilterWebInputEvent<WebGestureEvent>();
+ EXPECT_EQ(10.f, filter_event->data.scroll_update.delta_x);
+ EXPECT_EQ(20.f, filter_event->data.scroll_update.delta_y);
+}
+
+TEST_F(InputRouterImplScaleGestureEventTest, GestureScrollBegin) {
+ SimulateGestureEvent(SyntheticWebGestureEventBuilder::BuildScrollBegin(
+ 10.f, 20.f, blink::kWebGestureDeviceTouchscreen));
+ FlushGestureEvent(WebInputEvent::kGestureScrollBegin);
+
+ const WebGestureEvent* sent_event = GetSentWebInputEvent<WebGestureEvent>();
+ EXPECT_EQ(20.f, sent_event->data.scroll_begin.delta_x_hint);
+ EXPECT_EQ(40.f, sent_event->data.scroll_begin.delta_y_hint);
+
+ const WebGestureEvent* filter_event =
+ GetFilterWebInputEvent<WebGestureEvent>();
+ EXPECT_EQ(10.f, filter_event->data.scroll_begin.delta_x_hint);
+ EXPECT_EQ(20.f, filter_event->data.scroll_begin.delta_y_hint);
+}
+
+TEST_F(InputRouterImplScaleGestureEventTest, GesturePinchUpdate) {
+ const gfx::Point orig(10, 20), scaled(20, 40);
+ SimulateGesturePinchUpdateEvent(1.5f, orig.x(), orig.y(), 0,
+ blink::kWebGestureDeviceTouchpad);
+ FlushGestureEvent(WebInputEvent::kGesturePinchUpdate);
+ const WebGestureEvent* sent_event = GetSentWebInputEvent<WebGestureEvent>();
+ TestLocationInSentEvent(sent_event, orig, scaled);
+ EXPECT_EQ(1.5f, sent_event->data.pinch_update.scale);
+
+ const WebGestureEvent* filter_event =
+ GetFilterWebInputEvent<WebGestureEvent>();
+ TestLocationInFilterEvent(filter_event, orig);
+ EXPECT_EQ(1.5f, filter_event->data.pinch_update.scale);
+}
+
+TEST_F(InputRouterImplScaleGestureEventTest, GestureTapDown) {
+ const gfx::Point orig(10, 20), scaled(20, 40);
+ WebGestureEvent event =
+ BuildGestureEvent(WebInputEvent::kGestureTapDown, orig);
+ event.data.tap_down.width = 30;
+ event.data.tap_down.height = 40;
+ SimulateGestureEvent(event);
+ FlushGestureEvent(WebInputEvent::kGestureTapDown);
+ const WebGestureEvent* sent_event = GetSentWebInputEvent<WebGestureEvent>();
+ TestLocationInSentEvent(sent_event, orig, scaled);
+ EXPECT_EQ(60, sent_event->data.tap_down.width);
+ EXPECT_EQ(80, sent_event->data.tap_down.height);
+
+ const WebGestureEvent* filter_event =
+ GetFilterWebInputEvent<WebGestureEvent>();
+ TestLocationInFilterEvent(filter_event, orig);
+ EXPECT_EQ(30, filter_event->data.tap_down.width);
+ EXPECT_EQ(40, filter_event->data.tap_down.height);
+}
+
+TEST_F(InputRouterImplScaleGestureEventTest, GestureTapOthers) {
+ TestTap("GestureDoubleTap", WebInputEvent::kGestureDoubleTap);
+ TestTap("GestureTap", WebInputEvent::kGestureTap);
+ TestTap("GestureTapUnconfirmed", WebInputEvent::kGestureTapUnconfirmed);
+}
+
+TEST_F(InputRouterImplScaleGestureEventTest, GestureShowPress) {
+ const gfx::Point orig(10, 20), scaled(20, 40);
+ WebGestureEvent event =
+ BuildGestureEvent(WebInputEvent::kGestureShowPress, orig);
+ event.data.show_press.width = 30;
+ event.data.show_press.height = 40;
+ SimulateGestureEvent(event);
+ FlushGestureEvent(WebInputEvent::kGestureShowPress);
+
+ const WebGestureEvent* sent_event = GetSentWebInputEvent<WebGestureEvent>();
+ TestLocationInSentEvent(sent_event, orig, scaled);
+ EXPECT_EQ(60, sent_event->data.show_press.width);
+ EXPECT_EQ(80, sent_event->data.show_press.height);
+
+ const WebGestureEvent* filter_event =
+ GetFilterWebInputEvent<WebGestureEvent>();
+ TestLocationInFilterEvent(filter_event, orig);
+ EXPECT_EQ(30, filter_event->data.show_press.width);
+ EXPECT_EQ(40, filter_event->data.show_press.height);
+}
+
+TEST_F(InputRouterImplScaleGestureEventTest, GestureLongPress) {
+ TestLongPress("LongPress", WebInputEvent::kGestureLongPress);
+ TestLongPress("LongPap", WebInputEvent::kGestureLongTap);
+}
+
+TEST_F(InputRouterImplScaleGestureEventTest, GestureTwoFingerTap) {
+ WebGestureEvent event = BuildGestureEvent(WebInputEvent::kGestureTwoFingerTap,
+ gfx::Point(10, 20));
+ event.data.two_finger_tap.first_finger_width = 30;
+ event.data.two_finger_tap.first_finger_height = 40;
+ SimulateGestureEvent(event);
+ FlushGestureEvent(WebInputEvent::kGestureTwoFingerTap);
+
+ const WebGestureEvent* sent_event = GetSentWebInputEvent<WebGestureEvent>();
+ EXPECT_EQ(20, sent_event->x);
+ EXPECT_EQ(40, sent_event->y);
+ EXPECT_EQ(60, sent_event->data.two_finger_tap.first_finger_width);
+ EXPECT_EQ(80, sent_event->data.two_finger_tap.first_finger_height);
+
+ const WebGestureEvent* filter_event =
+ GetFilterWebInputEvent<WebGestureEvent>();
+ EXPECT_EQ(10, filter_event->x);
+ EXPECT_EQ(20, filter_event->y);
+ EXPECT_EQ(30, filter_event->data.two_finger_tap.first_finger_width);
+ EXPECT_EQ(40, filter_event->data.two_finger_tap.first_finger_height);
+}
+
+TEST_F(InputRouterImplScaleGestureEventTest, GestureFlingStart) {
+ const gfx::Point orig(10, 20), scaled(20, 40);
+ WebGestureEvent event =
+ BuildGestureEvent(WebInputEvent::kGestureFlingStart, orig);
+ event.data.fling_start.velocity_x = 30;
+ event.data.fling_start.velocity_y = 40;
+ SimulateGestureEvent(event);
+ FlushGestureEvent(WebInputEvent::kGestureFlingStart);
+
+ const WebGestureEvent* sent_event = GetSentWebInputEvent<WebGestureEvent>();
+ TestLocationInSentEvent(sent_event, orig, scaled);
+ EXPECT_EQ(60, sent_event->data.fling_start.velocity_x);
+ EXPECT_EQ(80, sent_event->data.fling_start.velocity_y);
+
+ const WebGestureEvent* filter_event =
+ GetFilterWebInputEvent<WebGestureEvent>();
+ TestLocationInFilterEvent(filter_event, orig);
+ EXPECT_EQ(30, filter_event->data.fling_start.velocity_x);
+ EXPECT_EQ(40, filter_event->data.fling_start.velocity_y);
+}
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/legacy_input_router_impl.cc b/chromium/content/browser/renderer_host/input/legacy_input_router_impl.cc
index 3300222b6ab..ff807e388fe 100644
--- a/chromium/content/browser/renderer_host/input/legacy_input_router_impl.cc
+++ b/chromium/content/browser/renderer_host/input/legacy_input_router_impl.cc
@@ -14,7 +14,7 @@
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_number_conversions.h"
#include "content/browser/renderer_host/input/gesture_event_queue.h"
-#include "content/browser/renderer_host/input/input_ack_handler.h"
+#include "content/browser/renderer_host/input/input_disposition_handler.h"
#include "content/browser/renderer_host/input/input_router_client.h"
#include "content/browser/renderer_host/input/legacy_touch_event_queue.h"
#include "content/browser/renderer_host/input/passthrough_touch_event_queue.h"
@@ -58,6 +58,8 @@ const char* GetEventAckName(InputEventAckState ack_result) {
return "CONSUMED";
case INPUT_EVENT_ACK_STATE_NOT_CONSUMED:
return "NOT_CONSUMED";
+ case INPUT_EVENT_ACK_STATE_CONSUMED_SHOULD_BUBBLE:
+ return "CONSUMED_SHOULD_BUBBLE";
case INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS:
return "NO_CONSUMER_EXISTS";
case INPUT_EVENT_ACK_STATE_IGNORED:
@@ -73,14 +75,15 @@ const char* GetEventAckName(InputEventAckState ack_result) {
} // namespace
-LegacyInputRouterImpl::LegacyInputRouterImpl(IPC::Sender* sender,
- InputRouterClient* client,
- InputAckHandler* ack_handler,
- int routing_id,
- const Config& config)
+LegacyInputRouterImpl::LegacyInputRouterImpl(
+ IPC::Sender* sender,
+ InputRouterClient* client,
+ InputDispositionHandler* disposition_handler,
+ int routing_id,
+ const Config& config)
: sender_(sender),
client_(client),
- ack_handler_(ack_handler),
+ disposition_handler_(disposition_handler),
routing_id_(routing_id),
frame_tree_node_id_(-1),
select_message_pending_(false),
@@ -105,7 +108,7 @@ LegacyInputRouterImpl::LegacyInputRouterImpl(IPC::Sender* sender,
DCHECK(sender);
DCHECK(client);
- DCHECK(ack_handler);
+ DCHECK(disposition_handler);
UpdateTouchAckTimeoutEnabled();
}
@@ -219,13 +222,6 @@ void LegacyInputRouterImpl::SendGestureEventImmediately(
FilterAndSendWebInputEvent(gesture_event.event, gesture_event.latency);
}
-const NativeWebKeyboardEvent* LegacyInputRouterImpl::GetLastKeyboardEvent()
- const {
- if (key_queue_.empty())
- return NULL;
- return &key_queue_.front().event;
-}
-
void LegacyInputRouterImpl::NotifySiteIsMobileOptimized(
bool is_mobile_optimized) {
touch_event_queue_->SetIsMobileOptimizedSite(is_mobile_optimized);
@@ -273,7 +269,7 @@ void LegacyInputRouterImpl::OnTouchEventAck(
touch_action_filter_.ResetTouchAction();
UpdateTouchAckTimeoutEnabled();
}
- ack_handler_->OnTouchEventAck(event, ack_result);
+ disposition_handler_->OnTouchEventAck(event, ack_result);
// Reset the touch action at the end of a touch-action sequence.
if (WebTouchEventTraits::IsTouchSequenceEnd(event.event)) {
@@ -298,7 +294,7 @@ void LegacyInputRouterImpl::OnGestureEventAck(
const GestureEventWithLatencyInfo& event,
InputEventAckState ack_result) {
touch_event_queue_->OnGestureEventAck(event, ack_result);
- ack_handler_->OnGestureEventAck(event, ack_result);
+ disposition_handler_->OnGestureEventAck(event, ack_result);
}
void LegacyInputRouterImpl::ForwardGestureEventWithLatencyInfo(
@@ -315,7 +311,7 @@ void LegacyInputRouterImpl::SendMouseWheelEventImmediately(
void LegacyInputRouterImpl::OnMouseWheelEventAck(
const MouseWheelEventWithLatencyInfo& event,
InputEventAckState ack_result) {
- ack_handler_->OnWheelEventAck(event, ack_result);
+ disposition_handler_->OnWheelEventAck(event, ack_result);
}
bool LegacyInputRouterImpl::SendSelectMessage(
@@ -424,12 +420,6 @@ bool LegacyInputRouterImpl::OfferToRenderer(
const WebInputEvent& input_event,
const ui::LatencyInfo& latency_info,
InputEventDispatchType dispatch_type) {
- DCHECK(input_event.GetType() != blink::WebInputEvent::kGestureFlingStart ||
- static_cast<const blink::WebGestureEvent&>(input_event)
- .data.fling_start.velocity_x != 0.0 ||
- static_cast<const blink::WebGestureEvent&>(input_event)
- .data.fling_start.velocity_y != 0.0);
-
// This conversion is temporary. WebInputEvent should be generated
// directly from ui::Event with the viewport coordinates. See
// crbug.com/563730.
@@ -460,6 +450,11 @@ void LegacyInputRouterImpl::OnInputEventAck(const InputEventAck& ack) {
OnDidOverscroll(*ack.overscroll);
}
+ // Since input messages over mojo require the touch action in the
+ // ACK we mirror that behavior in Chrome IPC for simplicity.
+ if (ack.touch_action.has_value())
+ OnSetTouchAction(ack.touch_action.value());
+
ProcessInputEventAck(ack.type, ack.state, ack.latency,
ack.unique_touch_event_id, RENDERER);
}
@@ -514,7 +509,12 @@ void LegacyInputRouterImpl::OnSetTouchAction(cc::TouchAction touch_action) {
}
void LegacyInputRouterImpl::OnSetWhiteListedTouchAction(
- cc::TouchAction white_listed_touch_action) {
+ cc::TouchAction white_listed_touch_action,
+ uint32_t unique_touch_event_id,
+ InputEventAckState ack_result) {
+ // TODO(hayleyferr): Catch the cases that we have filtered out sending the
+ // touchstart.
+
touch_action_filter_.OnSetWhiteListedTouchAction(white_listed_touch_action);
client_->OnSetWhiteListedTouchAction(white_listed_touch_action);
}
@@ -560,7 +560,8 @@ void LegacyInputRouterImpl::ProcessInputEventAck(
} else if (WebInputEvent::IsGestureEventType(event_type)) {
ProcessGestureAck(event_type, ack_result, latency_info);
} else if (event_type != WebInputEvent::kUndefined) {
- ack_handler_->OnUnexpectedEventAck(InputAckHandler::BAD_ACK_MESSAGE);
+ disposition_handler_->OnUnexpectedEventAck(
+ InputDispositionHandler::BAD_ACK_MESSAGE);
}
}
@@ -568,18 +569,20 @@ void LegacyInputRouterImpl::ProcessKeyboardAck(blink::WebInputEvent::Type type,
InputEventAckState ack_result,
const ui::LatencyInfo& latency) {
if (key_queue_.empty()) {
- ack_handler_->OnUnexpectedEventAck(InputAckHandler::UNEXPECTED_ACK);
+ disposition_handler_->OnUnexpectedEventAck(
+ InputDispositionHandler::UNEXPECTED_ACK);
} else if (key_queue_.front().event.GetType() != type) {
// Something must be wrong. Clear the |key_queue_| and char event
// suppression so that we can resume from the error.
key_queue_.clear();
- ack_handler_->OnUnexpectedEventAck(InputAckHandler::UNEXPECTED_EVENT_TYPE);
+ disposition_handler_->OnUnexpectedEventAck(
+ InputDispositionHandler::UNEXPECTED_EVENT_TYPE);
} else {
NativeWebKeyboardEventWithLatencyInfo front_item = key_queue_.front();
front_item.latency.AddNewLatencyFrom(latency);
key_queue_.pop_front();
- ack_handler_->OnKeyboardEventAck(front_item, ack_result);
+ disposition_handler_->OnKeyboardEventAck(front_item, ack_result);
// WARNING: This LegacyInputRouterImpl can be deallocated at this point
// (i.e. in the case of Ctrl+W, where the call to
// HandleKeyboardEvent destroys this LegacyInputRouterImpl).
@@ -591,12 +594,13 @@ void LegacyInputRouterImpl::ProcessMouseAck(blink::WebInputEvent::Type type,
InputEventAckState ack_result,
const ui::LatencyInfo& latency) {
if (mouse_event_queue_.empty()) {
- ack_handler_->OnUnexpectedEventAck(InputAckHandler::UNEXPECTED_ACK);
+ disposition_handler_->OnUnexpectedEventAck(
+ InputDispositionHandler::UNEXPECTED_ACK);
} else {
MouseEventWithLatencyInfo front_item = mouse_event_queue_.front();
front_item.latency.AddNewLatencyFrom(latency);
mouse_event_queue_.pop_front();
- ack_handler_->OnMouseEventAck(front_item, ack_result);
+ disposition_handler_->OnMouseEventAck(front_item, ack_result);
}
}
@@ -642,6 +646,10 @@ cc::TouchAction LegacyInputRouterImpl::AllowedTouchAction() {
return touch_action_filter_.allowed_touch_action();
}
+void LegacyInputRouterImpl::SetForceEnableZoom(bool enabled) {
+ touch_action_filter_.SetForceEnableZoom(enabled);
+}
+
void LegacyInputRouterImpl::SetMovementXYForTouchPoints(
blink::WebTouchEvent* event) {
for (size_t i = 0; i < event->touches_length; ++i) {
diff --git a/chromium/content/browser/renderer_host/input/legacy_input_router_impl.h b/chromium/content/browser/renderer_host/input/legacy_input_router_impl.h
index fe456f42542..a48ea9a59eb 100644
--- a/chromium/content/browser/renderer_host/input/legacy_input_router_impl.h
+++ b/chromium/content/browser/renderer_host/input/legacy_input_router_impl.h
@@ -36,7 +36,7 @@ struct DidOverscrollParams;
namespace content {
-class InputAckHandler;
+class InputDispositionHandler;
class InputRouterClient;
struct InputEventAck;
@@ -45,15 +45,15 @@ struct InputEventAck;
// Chrome IPC which is deprecated. This class will be replaced with a Mojo
// backed transport. See crbug.com/722928.
class CONTENT_EXPORT LegacyInputRouterImpl
- : public NON_EXPORTED_BASE(InputRouter),
- public NON_EXPORTED_BASE(GestureEventQueueClient),
- public NON_EXPORTED_BASE(MouseWheelEventQueueClient),
- public NON_EXPORTED_BASE(TouchEventQueueClient),
- public NON_EXPORTED_BASE(TouchpadTapSuppressionControllerClient) {
+ : public InputRouter,
+ public GestureEventQueueClient,
+ public MouseWheelEventQueueClient,
+ public TouchEventQueueClient,
+ public TouchpadTapSuppressionControllerClient {
public:
LegacyInputRouterImpl(IPC::Sender* sender,
InputRouterClient* client,
- InputAckHandler* ack_handler,
+ InputDispositionHandler* disposition_handler,
int routing_id,
const Config& config);
~LegacyInputRouterImpl() override;
@@ -69,7 +69,6 @@ class CONTENT_EXPORT LegacyInputRouterImpl
void SendGestureEvent(
const GestureEventWithLatencyInfo& gesture_event) override;
void SendTouchEvent(const TouchEventWithLatencyInfo& touch_event) override;
- const NativeWebKeyboardEvent* GetLastKeyboardEvent() const override;
void NotifySiteIsMobileOptimized(bool is_mobile_optimized) override;
bool HasPendingEvents() const override;
void SetDeviceScaleFactor(float device_scale_factor) override;
@@ -81,6 +80,8 @@ class CONTENT_EXPORT LegacyInputRouterImpl
cc::TouchAction AllowedTouchAction() override;
+ void SetForceEnableZoom(bool enabled) override;
+
int routing_id() const { return routing_id_; }
private:
@@ -150,7 +151,9 @@ class CONTENT_EXPORT LegacyInputRouterImpl
void OnSelectMessageAck();
void OnHasTouchEventHandlers(bool has_handlers);
void OnSetTouchAction(cc::TouchAction touch_action);
- void OnSetWhiteListedTouchAction(cc::TouchAction white_listed_touch_action);
+ void OnSetWhiteListedTouchAction(cc::TouchAction white_listed_touch_action,
+ uint32_t unique_touch_event_id,
+ InputEventAckState ack_result);
void OnDidStopFlinging();
// Indicates the source of an ack provided to |ProcessInputEventAck()|.
@@ -200,7 +203,7 @@ class CONTENT_EXPORT LegacyInputRouterImpl
IPC::Sender* sender_;
InputRouterClient* client_;
- InputAckHandler* ack_handler_;
+ InputDispositionHandler* disposition_handler_;
int routing_id_;
int frame_tree_node_id_;
diff --git a/chromium/content/browser/renderer_host/input/legacy_input_router_impl_perftest.cc b/chromium/content/browser/renderer_host/input/legacy_input_router_impl_perftest.cc
index b723d200bc6..ec9557bfe40 100644
--- a/chromium/content/browser/renderer_host/input/legacy_input_router_impl_perftest.cc
+++ b/chromium/content/browser/renderer_host/input/legacy_input_router_impl_perftest.cc
@@ -10,7 +10,7 @@
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/test/scoped_task_environment.h"
-#include "content/browser/renderer_host/input/input_ack_handler.h"
+#include "content/browser/renderer_host/input/input_disposition_handler.h"
#include "content/browser/renderer_host/input/input_router_client.h"
#include "content/browser/renderer_host/input/legacy_input_router_impl.h"
#include "content/common/input_messages.h"
@@ -33,12 +33,12 @@ namespace content {
namespace {
-class NullInputAckHandler : public InputAckHandler {
+class NullInputDispositionHandler : public InputDispositionHandler {
public:
- NullInputAckHandler() : ack_count_(0) {}
- ~NullInputAckHandler() override {}
+ NullInputDispositionHandler() : ack_count_(0) {}
+ ~NullInputDispositionHandler() override {}
- // InputAckHandler
+ // InputDispositionHandler
void OnKeyboardEventAck(const NativeWebKeyboardEventWithLatencyInfo& event,
InputEventAckState ack_result) override {
++ack_count_;
@@ -228,17 +228,17 @@ class LegacyInputRouterImplPerfTest : public testing::Test {
void SetUp() override {
sender_.reset(new NullIPCSender());
client_.reset(new NullInputRouterClient());
- ack_handler_.reset(new NullInputAckHandler());
+ disposition_handler_.reset(new NullInputDispositionHandler());
input_router_.reset(new LegacyInputRouterImpl(
- sender_.get(), client_.get(), ack_handler_.get(), MSG_ROUTING_NONE,
- InputRouter::Config()));
+ sender_.get(), client_.get(), disposition_handler_.get(),
+ MSG_ROUTING_NONE, InputRouter::Config()));
}
void TearDown() override {
base::RunLoop().RunUntilIdle();
input_router_.reset();
- ack_handler_.reset();
+ disposition_handler_.reset();
client_.reset();
sender_.reset();
}
@@ -272,9 +272,11 @@ class LegacyInputRouterImplPerfTest : public testing::Test {
return sender_->GetAndResetSentEventCount();
}
- size_t GetAndResetAckCount() { return ack_handler_->GetAndResetAckCount(); }
+ size_t GetAndResetAckCount() {
+ return disposition_handler_->GetAndResetAckCount();
+ }
- size_t AckCount() const { return ack_handler_->ack_count(); }
+ size_t AckCount() const { return disposition_handler_->ack_count(); }
int64_t NextLatencyID() { return ++last_input_id_; }
@@ -353,7 +355,7 @@ class LegacyInputRouterImplPerfTest : public testing::Test {
int64_t last_input_id_;
std::unique_ptr<NullIPCSender> sender_;
std::unique_ptr<NullInputRouterClient> client_;
- std::unique_ptr<NullInputAckHandler> ack_handler_;
+ std::unique_ptr<NullInputDispositionHandler> disposition_handler_;
std::unique_ptr<LegacyInputRouterImpl> input_router_;
};
diff --git a/chromium/content/browser/renderer_host/input/legacy_input_router_impl_unittest.cc b/chromium/content/browser/renderer_host/input/legacy_input_router_impl_unittest.cc
index 71c5e148a8c..19129b2bdfa 100644
--- a/chromium/content/browser/renderer_host/input/legacy_input_router_impl_unittest.cc
+++ b/chromium/content/browser/renderer_host/input/legacy_input_router_impl_unittest.cc
@@ -27,7 +27,7 @@
#include "cc/input/touch_action.h"
#include "content/browser/renderer_host/input/gesture_event_queue.h"
#include "content/browser/renderer_host/input/input_router_client.h"
-#include "content/browser/renderer_host/input/mock_input_ack_handler.h"
+#include "content/browser/renderer_host/input/mock_input_disposition_handler.h"
#include "content/browser/renderer_host/input/mock_input_router_client.h"
#include "content/common/content_constants_internal.h"
#include "content/common/edit_command.h"
@@ -210,14 +210,14 @@ class LegacyInputRouterImplTest : public testing::Test {
browser_context_.reset(new TestBrowserContext());
process_.reset(new MockRenderProcessHost(browser_context_.get()));
client_.reset(new MockInputRouterClient());
- ack_handler_.reset(new MockInputAckHandler());
+ disposition_handler_.reset(new MockInputDispositionHandler());
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
command_line->AppendSwitch(switches::kValidateInputEventStream);
input_router_.reset(new LegacyInputRouterImpl(process_.get(), client_.get(),
- ack_handler_.get(),
+ disposition_handler_.get(),
MSG_ROUTING_NONE, config_));
client_->set_input_router(input_router());
- ack_handler_->set_input_router(input_router());
+ disposition_handler_->set_input_router(input_router());
}
void TearDown() override {
@@ -414,9 +414,11 @@ class LegacyInputRouterImplTest : public testing::Test {
InputHostMsg_SetTouchAction(0, touch_action));
}
- void OnSetWhiteListedTouchAction(cc::TouchAction white_listed_touch_action) {
- input_router_->OnMessageReceived(
- InputHostMsg_SetWhiteListedTouchAction(0, white_listed_touch_action));
+ void OnSetWhiteListedTouchAction(cc::TouchAction white_listed_touch_action,
+ uint32_t unique_touch_event_id,
+ InputEventAckState ack_result) {
+ input_router_->OnMessageReceived(InputHostMsg_SetWhiteListedTouchAction(
+ 0, white_listed_touch_action, unique_touch_event_id, ack_result));
}
size_t GetSentMessageCountAndResetSink() {
@@ -438,7 +440,7 @@ class LegacyInputRouterImplTest : public testing::Test {
InputRouter::Config config_;
std::unique_ptr<MockRenderProcessHost> process_;
std::unique_ptr<MockInputRouterClient> client_;
- std::unique_ptr<MockInputAckHandler> ack_handler_;
+ std::unique_ptr<MockInputDispositionHandler> disposition_handler_;
std::unique_ptr<LegacyInputRouterImpl> input_router_;
bool wheel_scroll_latching_enabled_;
@@ -725,11 +727,7 @@ TEST_F(LegacyInputRouterImplTest, HandledInputEvent) {
EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
// OnKeyboardEventAck should be triggered without actual ack.
- EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
-
- // As the event was acked already, keyboard event queue should be
- // empty.
- ASSERT_EQ(NULL, input_router_->GetLastKeyboardEvent());
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
}
TEST_F(LegacyInputRouterImplTest, ClientCanceledKeyboardEvent) {
@@ -740,7 +738,7 @@ TEST_F(LegacyInputRouterImplTest, ClientCanceledKeyboardEvent) {
// Make sure no input event is sent to the renderer.
EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
- EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
// Simulate a keyboard event that should be dropped.
client_->set_filter_state(INPUT_EVENT_ACK_STATE_UNKNOWN);
@@ -748,14 +746,14 @@ TEST_F(LegacyInputRouterImplTest, ClientCanceledKeyboardEvent) {
// Make sure no input event is sent to the renderer, and no ack is sent.
EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
- EXPECT_EQ(0U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(0U, disposition_handler_->GetAndResetAckCount());
}
TEST_F(LegacyInputRouterImplTest, NoncorrespondingKeyEvents) {
SimulateKeyboardEvent(WebInputEvent::kRawKeyDown);
SendInputEventACK(WebInputEvent::kKeyUp, INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_TRUE(ack_handler_->unexpected_event_ack_called());
+ EXPECT_TRUE(disposition_handler_->unexpected_event_ack_called());
}
// Tests ported from RenderWidgetHostTest -------------------------------------
@@ -763,9 +761,6 @@ TEST_F(LegacyInputRouterImplTest, NoncorrespondingKeyEvents) {
TEST_F(LegacyInputRouterImplTest, HandleKeyEventsWeSent) {
// Simulate a keyboard event.
SimulateKeyboardEvent(WebInputEvent::kRawKeyDown);
- ASSERT_TRUE(input_router_->GetLastKeyboardEvent());
- EXPECT_EQ(WebInputEvent::kRawKeyDown,
- input_router_->GetLastKeyboardEvent()->GetType());
// Make sure we sent the input event to the renderer.
EXPECT_TRUE(
@@ -775,9 +770,9 @@ TEST_F(LegacyInputRouterImplTest, HandleKeyEventsWeSent) {
// Send the simulated response from the renderer back.
SendInputEventACK(WebInputEvent::kRawKeyDown,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
EXPECT_EQ(WebInputEvent::kRawKeyDown,
- ack_handler_->acked_keyboard_event().GetType());
+ disposition_handler_->acked_keyboard_event().GetType());
}
TEST_F(LegacyInputRouterImplTest, IgnoreKeyEventsWeDidntSend) {
@@ -785,7 +780,7 @@ TEST_F(LegacyInputRouterImplTest, IgnoreKeyEventsWeDidntSend) {
SendInputEventACK(WebInputEvent::kRawKeyDown,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_EQ(0U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(0U, disposition_handler_->GetAndResetAckCount());
}
TEST_F(LegacyInputRouterImplTest, CoalescesWheelEvents) {
@@ -827,7 +822,7 @@ TEST_F(LegacyInputRouterImplTest, CoalescesWheelEvents) {
// so that additional input events can be processed before
// we turn off coalescing.
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
EXPECT_TRUE(
process_->sink().GetUniqueMessageMatching(InputMsg_HandleInputEvent::ID));
input_event = GetInputEventFromMessage(*process_->sink().GetMessageAt(0));
@@ -840,7 +835,7 @@ TEST_F(LegacyInputRouterImplTest, CoalescesWheelEvents) {
// Ack the second event (which had the third coalesced into it).
SendInputEventACK(WebInputEvent::kMouseWheel, INPUT_EVENT_ACK_STATE_CONSUMED);
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
EXPECT_TRUE(
process_->sink().GetUniqueMessageMatching(InputMsg_HandleInputEvent::ID));
input_event = GetInputEventFromMessage(*process_->sink().GetMessageAt(0));
@@ -853,7 +848,7 @@ TEST_F(LegacyInputRouterImplTest, CoalescesWheelEvents) {
// Ack the fourth event.
SendInputEventACK(WebInputEvent::kMouseWheel, INPUT_EVENT_ACK_STATE_CONSUMED);
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
EXPECT_TRUE(
process_->sink().GetUniqueMessageMatching(InputMsg_HandleInputEvent::ID));
input_event = GetInputEventFromMessage(*process_->sink().GetMessageAt(0));
@@ -866,7 +861,7 @@ TEST_F(LegacyInputRouterImplTest, CoalescesWheelEvents) {
// Ack the fifth event.
SendInputEventACK(WebInputEvent::kMouseWheel, INPUT_EVENT_ACK_STATE_CONSUMED);
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
EXPECT_TRUE(
process_->sink().GetUniqueMessageMatching(InputMsg_HandleInputEvent::ID));
input_event = GetInputEventFromMessage(*process_->sink().GetMessageAt(0));
@@ -880,7 +875,7 @@ TEST_F(LegacyInputRouterImplTest, CoalescesWheelEvents) {
// After the final ack, the queue should be empty.
SendInputEventACK(WebInputEvent::kMouseWheel, INPUT_EVENT_ACK_STATE_CONSUMED);
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
}
@@ -905,17 +900,17 @@ TEST_F(LegacyInputRouterImplRafAlignedTouchDisabledTest, TouchEventQueue) {
SendTouchEventACK(WebInputEvent::kTouchStart, INPUT_EVENT_ACK_STATE_CONSUMED,
touch_press_event_id);
EXPECT_FALSE(TouchEventQueueEmpty());
- EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
EXPECT_EQ(WebInputEvent::kTouchStart,
- ack_handler_->acked_touch_event().event.GetType());
+ disposition_handler_->acked_touch_event().event.GetType());
EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
SendTouchEventACK(WebInputEvent::kTouchMove, INPUT_EVENT_ACK_STATE_CONSUMED,
touch_move_event_id);
EXPECT_TRUE(TouchEventQueueEmpty());
- EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
EXPECT_EQ(WebInputEvent::kTouchMove,
- ack_handler_->acked_touch_event().event.GetType());
+ disposition_handler_->acked_touch_event().event.GetType());
EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
}
@@ -940,17 +935,17 @@ TEST_F(LegacyInputRouterImplTest, TouchEventQueue) {
SendTouchEventACK(WebInputEvent::kTouchStart, INPUT_EVENT_ACK_STATE_CONSUMED,
touch_press_event_id);
EXPECT_FALSE(TouchEventQueueEmpty());
- EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
EXPECT_EQ(WebInputEvent::kTouchStart,
- ack_handler_->acked_touch_event().event.GetType());
+ disposition_handler_->acked_touch_event().event.GetType());
EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
SendTouchEventACK(WebInputEvent::kTouchMove, INPUT_EVENT_ACK_STATE_CONSUMED,
touch_move_event_id);
EXPECT_TRUE(TouchEventQueueEmpty());
- EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
EXPECT_EQ(WebInputEvent::kTouchMove,
- ack_handler_->acked_touch_event().event.GetType());
+ disposition_handler_->acked_touch_event().event.GetType());
EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
}
@@ -1065,11 +1060,12 @@ TEST_F(LegacyInputRouterImplTest, MAYBE_AckedTouchEventState) {
for (size_t i = 0; i < arraysize(acks); ++i) {
SendTouchEventACK(acks[i], INPUT_EVENT_ACK_STATE_NOT_CONSUMED,
touch_event_ids[i]);
- EXPECT_EQ(acks[i], ack_handler_->acked_touch_event().event.GetType());
+ EXPECT_EQ(acks[i],
+ disposition_handler_->acked_touch_event().event.GetType());
std::vector<std::unique_ptr<ui::TouchEvent>> acked;
- MakeUITouchEventsFromWebTouchEvents(ack_handler_->acked_touch_event(),
- &acked, coordinate_system);
+ MakeUITouchEventsFromWebTouchEvents(
+ disposition_handler_->acked_touch_event(), &acked, coordinate_system);
bool success = EventListIsSubset(acked, expected_events);
EXPECT_TRUE(success) << "Failed on step: " << i;
if (!success)
@@ -1104,25 +1100,25 @@ void LegacyInputRouterImplTest::UnhandledWheelEvent() {
// Check that the ack for the MouseWheel and ScrollBegin
// were processed.
- EXPECT_EQ(2U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(2U, disposition_handler_->GetAndResetAckCount());
// There should be a ScrollBegin and ScrollUpdate, MouseWheel sent.
EXPECT_EQ(3U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(ack_handler_->acked_wheel_event().delta_y, -5);
+ EXPECT_EQ(disposition_handler_->acked_wheel_event().delta_y, -5);
SendInputEventACK(WebInputEvent::kGestureScrollUpdate,
INPUT_EVENT_ACK_STATE_CONSUMED);
if (wheel_scroll_latching_enabled_) {
// Check that the ack for ScrollUpdate were processed.
- EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
} else {
// The GestureScrollUpdate ACK releases the GestureScrollEnd.
EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
// Check that the ack for the ScrollUpdate and ScrollEnd
// were processed.
- EXPECT_EQ(2U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(2U, disposition_handler_->GetAndResetAckCount());
}
SendInputEventACK(WebInputEvent::kMouseWheel,
@@ -1131,31 +1127,31 @@ void LegacyInputRouterImplTest::UnhandledWheelEvent() {
if (wheel_scroll_latching_enabled_) {
// There should be a ScrollUpdate sent.
EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
} else {
// There should be a ScrollBegin and ScrollUpdate sent.
EXPECT_EQ(2U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(2U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(2U, disposition_handler_->GetAndResetAckCount());
}
// Check that the correct unhandled wheel event was received.
EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED,
- ack_handler_->acked_wheel_event_state());
- EXPECT_EQ(ack_handler_->acked_wheel_event().delta_y, -10);
+ disposition_handler_->acked_wheel_event_state());
+ EXPECT_EQ(disposition_handler_->acked_wheel_event().delta_y, -10);
SendInputEventACK(WebInputEvent::kGestureScrollUpdate,
INPUT_EVENT_ACK_STATE_CONSUMED);
if (wheel_scroll_latching_enabled_) {
// Check that the ack for ScrollUpdate were processed.
- EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
} else {
// The GestureScrollUpdate ACK releases the GestureScrollEnd.
EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
// Check that the ack for the ScrollUpdate and ScrollEnd
// were processed.
- EXPECT_EQ(2U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(2U, disposition_handler_->GetAndResetAckCount());
}
}
@@ -1186,24 +1182,25 @@ TEST_F(LegacyInputRouterImplAsyncWheelEventEnabledTest, UnhandledWheelEvent) {
// Check that the ack for the first MouseWheel, ScrollBegin, and the second
// MouseWheel were processed.
- EXPECT_EQ(3U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(3U, disposition_handler_->GetAndResetAckCount());
// There should be a ScrollBegin, MouseWheel, and coalesced ScrollUpdate sent.
EXPECT_EQ(3U, GetSentMessageCountAndResetSink());
// The last acked wheel event should be the second one since the input router
// has already sent the immediate ack for the second wheel event.
- EXPECT_EQ(ack_handler_->acked_wheel_event().delta_y, -10);
+ EXPECT_EQ(disposition_handler_->acked_wheel_event().delta_y, -10);
EXPECT_EQ(INPUT_EVENT_ACK_STATE_IGNORED,
- ack_handler_->acked_wheel_event_state());
+ disposition_handler_->acked_wheel_event_state());
SendInputEventACK(WebInputEvent::kGestureScrollUpdate,
INPUT_EVENT_ACK_STATE_CONSUMED);
// Check that the ack for the coalesced ScrollUpdate were processed.
- EXPECT_EQ(-15,
- ack_handler_->acked_gesture_event().data.scroll_update.delta_y);
- EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(
+ -15,
+ disposition_handler_->acked_gesture_event().data.scroll_update.delta_y);
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
}
TEST_F(LegacyInputRouterImplTest, TouchTypesIgnoringAck) {
@@ -1222,20 +1219,20 @@ TEST_F(LegacyInputRouterImplTest, TouchTypesIgnoringAck) {
SendTouchEventACK(WebInputEvent::kTouchStart, INPUT_EVENT_ACK_STATE_CONSUMED,
touch_press_event_id);
ASSERT_EQ(1U, GetSentMessageCountAndResetSink());
- ASSERT_EQ(1U, ack_handler_->GetAndResetAckCount());
+ ASSERT_EQ(1U, disposition_handler_->GetAndResetAckCount());
ASSERT_EQ(0, client_->in_flight_event_count());
// The TouchCancel ack is always ignored.
CancelTouchPoint(0);
uint32_t touch_cancel_event_id = SendTouchEvent();
EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
EXPECT_EQ(0, client_->in_flight_event_count());
EXPECT_FALSE(HasPendingEvents());
SendTouchEventACK(WebInputEvent::kTouchCancel,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED, touch_cancel_event_id);
EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(0U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(0U, disposition_handler_->GetAndResetAckCount());
EXPECT_FALSE(HasPendingEvents());
}
@@ -1264,13 +1261,13 @@ TEST_F(LegacyInputRouterImplTest, GestureTypesIgnoringAck) {
EXPECT_EQ(2U, GetSentMessageCountAndResetSink());
else
EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(0U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(0U, disposition_handler_->GetAndResetAckCount());
EXPECT_EQ(1, client_->in_flight_event_count());
EXPECT_TRUE(HasPendingEvents());
SendInputEventACK(type, INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
EXPECT_EQ(0, client_->in_flight_event_count());
EXPECT_FALSE(HasPendingEvents());
continue;
@@ -1278,7 +1275,7 @@ TEST_F(LegacyInputRouterImplTest, GestureTypesIgnoringAck) {
SimulateGestureEvent(type, blink::kWebGestureDeviceTouchscreen);
EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
EXPECT_EQ(0, client_->in_flight_event_count());
EXPECT_FALSE(HasPendingEvents());
}
@@ -1295,17 +1292,17 @@ TEST_F(LegacyInputRouterImplTest, MouseTypesIgnoringAck) {
EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
if (ShouldBlockEventStream(GetEventWithType(type))) {
- EXPECT_EQ(0U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(0U, disposition_handler_->GetAndResetAckCount());
EXPECT_EQ(1, client_->in_flight_event_count());
SendInputEventACK(type, INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
EXPECT_EQ(0, client_->in_flight_event_count());
} else {
// Note: events which don't block the event stream immediately receive
// synthetic ACKs.
- EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
EXPECT_EQ(0, client_->in_flight_event_count());
}
}
@@ -1344,40 +1341,40 @@ TEST_F(LegacyInputRouterImplTest, GestureTypesIgnoringAckInterleaved) {
blink::kWebGestureDeviceTouchscreen);
SendScrollBeginAckIfNeeded(INPUT_EVENT_ACK_STATE_CONSUMED);
ASSERT_EQ(1U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
EXPECT_EQ(0, client_->in_flight_event_count());
SimulateGestureEvent(WebInputEvent::kGestureScrollUpdate,
blink::kWebGestureDeviceTouchscreen);
ASSERT_EQ(2U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(0U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(0U, disposition_handler_->GetAndResetAckCount());
EXPECT_EQ(1, client_->in_flight_event_count());
SimulateGestureEvent(WebInputEvent::kGestureTapDown,
blink::kWebGestureDeviceTouchscreen);
EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(0U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(0U, disposition_handler_->GetAndResetAckCount());
EXPECT_EQ(1, client_->in_flight_event_count());
SimulateGestureEvent(WebInputEvent::kGestureScrollUpdate,
blink::kWebGestureDeviceTouchscreen);
EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(0U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(0U, disposition_handler_->GetAndResetAckCount());
SimulateGestureEvent(WebInputEvent::kGestureShowPress,
blink::kWebGestureDeviceTouchscreen);
EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(0U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(0U, disposition_handler_->GetAndResetAckCount());
SimulateGestureEvent(WebInputEvent::kGestureScrollUpdate,
blink::kWebGestureDeviceTouchscreen);
EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(0U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(0U, disposition_handler_->GetAndResetAckCount());
SimulateGestureEvent(WebInputEvent::kGestureTapCancel,
blink::kWebGestureDeviceTouchscreen);
EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(0U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(0U, disposition_handler_->GetAndResetAckCount());
// Now ack each ack-respecting event. Ack-ignoring events should not be
// dispatched until all prior events which observe ack disposition have been
@@ -1386,19 +1383,19 @@ TEST_F(LegacyInputRouterImplTest, GestureTypesIgnoringAckInterleaved) {
SendInputEventACK(WebInputEvent::kGestureScrollUpdate,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
EXPECT_EQ(2U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(2U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(2U, disposition_handler_->GetAndResetAckCount());
EXPECT_EQ(1, client_->in_flight_event_count());
SendInputEventACK(WebInputEvent::kGestureScrollUpdate,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
EXPECT_EQ(2U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(2U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(2U, disposition_handler_->GetAndResetAckCount());
EXPECT_EQ(1, client_->in_flight_event_count());
SendInputEventACK(WebInputEvent::kGestureScrollUpdate,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(2U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(2U, disposition_handler_->GetAndResetAckCount());
EXPECT_EQ(0, client_->in_flight_event_count());
}
@@ -1409,13 +1406,13 @@ TEST_F(LegacyInputRouterImplTest, GestureShowPressIsInOrder) {
blink::kWebGestureDeviceTouchscreen);
SendScrollBeginAckIfNeeded(INPUT_EVENT_ACK_STATE_CONSUMED);
EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
// GesturePinchBegin ignores its ack.
SimulateGestureEvent(WebInputEvent::kGesturePinchBegin,
blink::kWebGestureDeviceTouchscreen);
EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
// GesturePinchUpdate waits for an ack.
// This also verifies that GesturePinchUpdates for touchscreen are sent
@@ -1423,27 +1420,27 @@ TEST_F(LegacyInputRouterImplTest, GestureShowPressIsInOrder) {
SimulateGestureEvent(WebInputEvent::kGesturePinchUpdate,
blink::kWebGestureDeviceTouchscreen);
EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(0U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(0U, disposition_handler_->GetAndResetAckCount());
SimulateGestureEvent(WebInputEvent::kGestureShowPress,
blink::kWebGestureDeviceTouchscreen);
EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
// The ShowPress, though it ignores ack, is still stuck in the queue
// behind the PinchUpdate which requires an ack.
- EXPECT_EQ(0U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(0U, disposition_handler_->GetAndResetAckCount());
SimulateGestureEvent(WebInputEvent::kGestureShowPress,
blink::kWebGestureDeviceTouchscreen);
EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
// ShowPress has entered the queue.
- EXPECT_EQ(0U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(0U, disposition_handler_->GetAndResetAckCount());
SendInputEventACK(WebInputEvent::kGesturePinchUpdate,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
// Now that the Tap has been ACKed, the ShowPress events should receive
// synthetic acks, and fire immediately.
EXPECT_EQ(2U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(3U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(3U, disposition_handler_->GetAndResetAckCount());
}
// Test that touch ack timeout behavior is properly configured for
@@ -1457,24 +1454,24 @@ TEST_F(LegacyInputRouterImplTest, TouchAckTimeoutConfigured) {
// Verify that the touch ack timeout fires upon the delayed ack.
PressTouchPoint(1, 1);
uint32_t touch_press_event_id1 = SendTouchEvent();
- EXPECT_EQ(0U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(0U, disposition_handler_->GetAndResetAckCount());
EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
RunTasksAndWait(base::TimeDelta::FromMilliseconds(kDesktopTimeoutMs + 1));
// The timed-out event should have been ack'ed.
- EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
// Ack'ing the timed-out event should fire a TouchCancel.
SendTouchEventACK(WebInputEvent::kTouchStart, INPUT_EVENT_ACK_STATE_CONSUMED,
touch_press_event_id1);
- EXPECT_EQ(0U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(0U, disposition_handler_->GetAndResetAckCount());
EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
// The remainder of the touch sequence should be dropped.
ReleaseTouchPoint(0);
SendTouchEvent();
- EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
ASSERT_TRUE(TouchEventTimeoutEnabled());
@@ -1536,7 +1533,7 @@ TEST_F(LegacyInputRouterImplTest,
OnSetTouchAction(cc::kTouchActionNone);
SendTouchEventACK(WebInputEvent::kTouchStart, INPUT_EVENT_ACK_STATE_CONSUMED,
touch_press_event_id);
- EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
EXPECT_FALSE(TouchEventTimeoutEnabled());
MoveTouchPoint(0, 1, 2);
@@ -1546,11 +1543,11 @@ TEST_F(LegacyInputRouterImplTest,
// Delay the move ack. The timeout should not fire.
RunTasksAndWait(base::TimeDelta::FromMilliseconds(kDesktopTimeoutMs + 1));
- EXPECT_EQ(0U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(0U, disposition_handler_->GetAndResetAckCount());
EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
SendTouchEventACK(WebInputEvent::kTouchMove, INPUT_EVENT_ACK_STATE_CONSUMED,
touch_move_event_id);
- EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
// End the touch sequence.
ReleaseTouchPoint(0);
@@ -1558,7 +1555,7 @@ TEST_F(LegacyInputRouterImplTest,
SendTouchEventACK(WebInputEvent::kTouchEnd, INPUT_EVENT_ACK_STATE_CONSUMED,
touch_release_event_id);
EXPECT_TRUE(TouchEventTimeoutEnabled());
- ack_handler_->GetAndResetAckCount();
+ disposition_handler_->GetAndResetAckCount();
GetSentMessageCountAndResetSink();
// Start another touch sequence. This should restore the touch timeout.
@@ -1566,11 +1563,11 @@ TEST_F(LegacyInputRouterImplTest,
SendTouchEvent();
EXPECT_TRUE(TouchEventTimeoutEnabled());
EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(0U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(0U, disposition_handler_->GetAndResetAckCount());
// Wait for the touch ack timeout to fire.
RunTasksAndWait(base::TimeDelta::FromMilliseconds(kDesktopTimeoutMs + 1));
- EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
}
// Test that TouchActionFilter::ResetTouchAction is called before the
@@ -1745,21 +1742,21 @@ TEST_F(LegacyInputRouterImplTest, AsyncTouchMoveAckedImmediately) {
// Receive an ACK for the first touch-event.
SendTouchEventACK(WebInputEvent::kTouchStart, INPUT_EVENT_ACK_STATE_CONSUMED,
touch_press_event_id);
- EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
SimulateGestureEvent(WebInputEvent::kGestureScrollBegin,
blink::kWebGestureDeviceTouchscreen);
SendScrollBeginAckIfNeeded(INPUT_EVENT_ACK_STATE_CONSUMED);
- EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
SimulateGestureEvent(WebInputEvent::kGestureScrollUpdate,
blink::kWebGestureDeviceTouchscreen);
- EXPECT_EQ(0U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(0U, disposition_handler_->GetAndResetAckCount());
EXPECT_EQ(2U, GetSentMessageCountAndResetSink());
// Now send an async move.
MoveTouchPoint(0, 5, 5);
SendTouchEvent();
- EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
}
@@ -1924,10 +1921,14 @@ TEST_F(LegacyInputRouterImplTest, TouchpadPinchUpdate) {
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
// Check that the correct unhandled pinch event was received.
- EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
- ASSERT_EQ(WebInputEvent::kGesturePinchUpdate, ack_handler_->ack_event_type());
- EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, ack_handler_->ack_state());
- EXPECT_EQ(1.5f, ack_handler_->acked_gesture_event().data.pinch_update.scale);
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
+ ASSERT_EQ(WebInputEvent::kGesturePinchUpdate,
+ disposition_handler_->ack_event_type());
+ EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED,
+ disposition_handler_->ack_state());
+ EXPECT_EQ(
+ 1.5f,
+ disposition_handler_->acked_gesture_event().data.pinch_update.scale);
EXPECT_EQ(0, client_->in_flight_event_count());
// Second a second pinch event.
@@ -1943,11 +1944,13 @@ TEST_F(LegacyInputRouterImplTest, TouchpadPinchUpdate) {
INPUT_EVENT_ACK_STATE_CONSUMED);
// Check that the correct HANDLED pinch event was received.
- EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
- EXPECT_EQ(WebInputEvent::kGesturePinchUpdate, ack_handler_->ack_event_type());
- EXPECT_EQ(INPUT_EVENT_ACK_STATE_CONSUMED, ack_handler_->ack_state());
- EXPECT_FLOAT_EQ(0.3f,
- ack_handler_->acked_gesture_event().data.pinch_update.scale);
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
+ EXPECT_EQ(WebInputEvent::kGesturePinchUpdate,
+ disposition_handler_->ack_event_type());
+ EXPECT_EQ(INPUT_EVENT_ACK_STATE_CONSUMED, disposition_handler_->ack_state());
+ EXPECT_FLOAT_EQ(
+ 0.3f,
+ disposition_handler_->acked_gesture_event().data.pinch_update.scale);
}
// Test proper handling of touchpad Gesture{Pinch,Scroll}Update sequences.
@@ -1986,7 +1989,7 @@ TEST_F(LegacyInputRouterImplTest, TouchpadPinchAndScrollUpdate) {
// coalesced pinch events (which is sent to the renderer as a wheel event).
SendInputEventACK(WebInputEvent::kGestureScrollUpdate,
INPUT_EVENT_ACK_STATE_CONSUMED);
- EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
EXPECT_EQ(2U, GetSentMessageCountAndResetSink());
EXPECT_EQ(2, client_->in_flight_event_count());
@@ -1994,14 +1997,14 @@ TEST_F(LegacyInputRouterImplTest, TouchpadPinchAndScrollUpdate) {
SendInputEventACK(WebInputEvent::kGestureScrollUpdate,
INPUT_EVENT_ACK_STATE_CONSUMED);
EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
EXPECT_EQ(1, client_->in_flight_event_count());
// Ack the wheel event.
SendInputEventACK(WebInputEvent::kGesturePinchUpdate,
INPUT_EVENT_ACK_STATE_CONSUMED);
EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
EXPECT_EQ(0, client_->in_flight_event_count());
}
@@ -2059,8 +2062,8 @@ TEST_F(LegacyInputRouterImplAsyncWheelEventEnabledTest, OverscrollDispatch) {
// |SetWhiteListedTouchAction| IPC messages.
TEST_F(LegacyInputRouterImplTest, OnSetWhiteListedTouchAction) {
cc::TouchAction touch_action = cc::kTouchActionPanY;
- input_router_->OnMessageReceived(
- InputHostMsg_SetWhiteListedTouchAction(0, touch_action));
+ input_router_->OnMessageReceived(InputHostMsg_SetWhiteListedTouchAction(
+ 0, touch_action, 0, INPUT_EVENT_ACK_STATE_NOT_CONSUMED));
cc::TouchAction white_listed_touch_action =
client_->GetAndResetWhiteListedTouchAction();
EXPECT_EQ(touch_action, white_listed_touch_action);
diff --git a/chromium/content/browser/renderer_host/input/legacy_ipc_widget_input_handler.cc b/chromium/content/browser/renderer_host/input/legacy_ipc_widget_input_handler.cc
index 12f039cf7e7..270c3a6e9c7 100644
--- a/chromium/content/browser/renderer_host/input/legacy_ipc_widget_input_handler.cc
+++ b/chromium/content/browser/renderer_host/input/legacy_ipc_widget_input_handler.cc
@@ -13,15 +13,32 @@
namespace content {
namespace {
-std::vector<blink::WebCompositionUnderline> ConvertToBlinkUnderline(
- const std::vector<ui::CompositionUnderline>& ui_underlines) {
- std::vector<blink::WebCompositionUnderline> underlines;
- for (const auto& underline : ui_underlines) {
- underlines.emplace_back(blink::WebCompositionUnderline(
- underline.start_offset, underline.end_offset, underline.color,
- underline.thick, underline.background_color));
+
+blink::WebImeTextSpan::Type ConvertUiImeTextSpanTypeToBlinkType(
+ ui::ImeTextSpan::Type type) {
+ switch (type) {
+ case ui::ImeTextSpan::Type::kComposition:
+ return blink::WebImeTextSpan::Type::kComposition;
+ case ui::ImeTextSpan::Type::kSuggestion:
+ return blink::WebImeTextSpan::Type::kSuggestion;
}
- return underlines;
+
+ NOTREACHED();
+ return blink::WebImeTextSpan::Type::kComposition;
+}
+
+std::vector<blink::WebImeTextSpan> ConvertToBlinkImeTextSpan(
+ const std::vector<ui::ImeTextSpan>& ui_ime_text_spans) {
+ std::vector<blink::WebImeTextSpan> ime_text_spans;
+ for (const auto& ime_text_span : ui_ime_text_spans) {
+ ime_text_spans.emplace_back(blink::WebImeTextSpan(
+ ConvertUiImeTextSpanTypeToBlinkType(ime_text_span.type),
+ ime_text_span.start_offset, ime_text_span.end_offset,
+ ime_text_span.underline_color, ime_text_span.thick,
+ ime_text_span.background_color,
+ ime_text_span.suggestion_highlight_color, ime_text_span.suggestions));
+ }
+ return ime_text_spans;
}
} // namespace
@@ -29,7 +46,6 @@ std::vector<blink::WebCompositionUnderline> ConvertToBlinkUnderline(
LegacyIPCWidgetInputHandler::LegacyIPCWidgetInputHandler(
LegacyInputRouterImpl* input_router)
: input_router_(input_router) {}
-
LegacyIPCWidgetInputHandler::~LegacyIPCWidgetInputHandler() {}
void LegacyIPCWidgetInputHandler::SetFocus(bool focused) {
@@ -52,25 +68,25 @@ void LegacyIPCWidgetInputHandler::CursorVisibilityChanged(bool visible) {
void LegacyIPCWidgetInputHandler::ImeSetComposition(
const base::string16& text,
- const std::vector<ui::CompositionUnderline>& ui_underlines,
+ const std::vector<ui::ImeTextSpan>& ui_ime_text_spans,
const gfx::Range& range,
int32_t start,
int32_t end) {
- std::vector<blink::WebCompositionUnderline> underlines =
- ConvertToBlinkUnderline(ui_underlines);
+ std::vector<blink::WebImeTextSpan> ime_text_spans =
+ ConvertToBlinkImeTextSpan(ui_ime_text_spans);
SendInput(base::MakeUnique<InputMsg_ImeSetComposition>(
- input_router_->routing_id(), text, underlines, range, start, end));
+ input_router_->routing_id(), text, ime_text_spans, range, start, end));
}
void LegacyIPCWidgetInputHandler::ImeCommitText(
const base::string16& text,
- const std::vector<ui::CompositionUnderline>& ui_underlines,
+ const std::vector<ui::ImeTextSpan>& ui_ime_text_spans,
const gfx::Range& range,
int32_t relative_cursor_position) {
- std::vector<blink::WebCompositionUnderline> underlines =
- ConvertToBlinkUnderline(ui_underlines);
+ std::vector<blink::WebImeTextSpan> ime_text_spans =
+ ConvertToBlinkImeTextSpan(ui_ime_text_spans);
SendInput(base::MakeUnique<InputMsg_ImeCommitText>(
- input_router_->routing_id(), text, underlines, range,
+ input_router_->routing_id(), text, ime_text_spans, range,
relative_cursor_position));
}
diff --git a/chromium/content/browser/renderer_host/input/legacy_ipc_widget_input_handler.h b/chromium/content/browser/renderer_host/input/legacy_ipc_widget_input_handler.h
index 9bc8f0c6a50..7bfd9e75f10 100644
--- a/chromium/content/browser/renderer_host/input/legacy_ipc_widget_input_handler.h
+++ b/chromium/content/browser/renderer_host/input/legacy_ipc_widget_input_handler.h
@@ -27,14 +27,13 @@ class CONTENT_EXPORT LegacyIPCWidgetInputHandler
void SetEditCommandsForNextKeyEvent(
const std::vector<EditCommand>& commands) override;
void CursorVisibilityChanged(bool visible) override;
- void ImeSetComposition(
- const base::string16& text,
- const std::vector<ui::CompositionUnderline>& underlines,
- const gfx::Range& range,
- int32_t start,
- int32_t end) override;
+ void ImeSetComposition(const base::string16& text,
+ const std::vector<ui::ImeTextSpan>& ime_text_spans,
+ const gfx::Range& range,
+ int32_t start,
+ int32_t end) override;
void ImeCommitText(const base::string16& text,
- const std::vector<ui::CompositionUnderline>& underlines,
+ const std::vector<ui::ImeTextSpan>& ime_text_spans,
const gfx::Range& range,
int32_t relative_cursor_position) override;
void ImeFinishComposingText(bool keep_selection) override;
diff --git a/chromium/content/browser/renderer_host/input/mock_input_ack_handler.cc b/chromium/content/browser/renderer_host/input/mock_input_disposition_handler.cc
index cf68acae121..17e700190aa 100644
--- a/chromium/content/browser/renderer_host/input/mock_input_ack_handler.cc
+++ b/chromium/content/browser/renderer_host/input/mock_input_disposition_handler.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/browser/renderer_host/input/mock_input_ack_handler.h"
+#include "content/browser/renderer_host/input/mock_input_disposition_handler.h"
#include "content/browser/renderer_host/input/input_router.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -17,24 +17,24 @@ using blink::WebTouchPoint;
namespace content {
-MockInputAckHandler::MockInputAckHandler()
+MockInputDispositionHandler::MockInputDispositionHandler()
: input_router_(NULL),
ack_count_(0),
unexpected_event_ack_called_(false),
ack_event_type_(WebInputEvent::kUndefined),
ack_state_(INPUT_EVENT_ACK_STATE_UNKNOWN) {}
-MockInputAckHandler::~MockInputAckHandler() {}
+MockInputDispositionHandler::~MockInputDispositionHandler() {}
-void MockInputAckHandler::OnKeyboardEventAck(
+void MockInputDispositionHandler::OnKeyboardEventAck(
const NativeWebKeyboardEventWithLatencyInfo& event,
- InputEventAckState ack_result) {
+ InputEventAckState ack_result) {
VLOG(1) << __FUNCTION__ << " called!";
acked_key_event_.reset(new NativeWebKeyboardEvent(event.event));
RecordAckCalled(event.event.GetType(), ack_result);
}
-void MockInputAckHandler::OnMouseEventAck(
+void MockInputDispositionHandler::OnMouseEventAck(
const MouseEventWithLatencyInfo& event,
InputEventAckState ack_result) {
VLOG(1) << __FUNCTION__ << " called!";
@@ -42,7 +42,7 @@ void MockInputAckHandler::OnMouseEventAck(
RecordAckCalled(event.event.GetType(), ack_result);
}
-void MockInputAckHandler::OnWheelEventAck(
+void MockInputDispositionHandler::OnWheelEventAck(
const MouseWheelEventWithLatencyInfo& event,
InputEventAckState ack_result) {
VLOG(1) << __FUNCTION__ << " called!";
@@ -51,7 +51,7 @@ void MockInputAckHandler::OnWheelEventAck(
RecordAckCalled(event.event.GetType(), ack_result);
}
-void MockInputAckHandler::OnTouchEventAck(
+void MockInputDispositionHandler::OnTouchEventAck(
const TouchEventWithLatencyInfo& event,
InputEventAckState ack_result) {
VLOG(1) << __FUNCTION__ << " called!";
@@ -63,7 +63,7 @@ void MockInputAckHandler::OnTouchEventAck(
input_router_->SendGestureEvent(*gesture_followup_event_);
}
-void MockInputAckHandler::OnGestureEventAck(
+void MockInputDispositionHandler::OnGestureEventAck(
const GestureEventWithLatencyInfo& event,
InputEventAckState ack_result) {
VLOG(1) << __FUNCTION__ << " called!";
@@ -71,19 +71,21 @@ void MockInputAckHandler::OnGestureEventAck(
RecordAckCalled(event.event.GetType(), ack_result);
}
-void MockInputAckHandler::OnUnexpectedEventAck(UnexpectedEventAckType type) {
+void MockInputDispositionHandler::OnUnexpectedEventAck(
+ UnexpectedEventAckType type) {
VLOG(1) << __FUNCTION__ << " called!";
unexpected_event_ack_called_ = true;
}
-size_t MockInputAckHandler::GetAndResetAckCount() {
+size_t MockInputDispositionHandler::GetAndResetAckCount() {
size_t ack_count = ack_count_;
ack_count_ = 0;
return ack_count;
}
-void MockInputAckHandler::RecordAckCalled(blink::WebInputEvent::Type type,
- InputEventAckState ack_result) {
+void MockInputDispositionHandler::RecordAckCalled(
+ blink::WebInputEvent::Type type,
+ InputEventAckState ack_result) {
ack_event_type_ = type;
++ack_count_;
ack_state_ = ack_result;
diff --git a/chromium/content/browser/renderer_host/input/mock_input_ack_handler.h b/chromium/content/browser/renderer_host/input/mock_input_disposition_handler.h
index 4452f650523..56ed6f57a28 100644
--- a/chromium/content/browser/renderer_host/input/mock_input_ack_handler.h
+++ b/chromium/content/browser/renderer_host/input/mock_input_disposition_handler.h
@@ -2,26 +2,26 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_MOCK_INPUT_ACK_HANDLER_H_
-#define CONTENT_BROWSER_RENDERER_HOST_INPUT_MOCK_INPUT_ACK_HANDLER_H_
+#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_MOCK_INPUT_DISPOSITION_HANDLER_H_
+#define CONTENT_BROWSER_RENDERER_HOST_INPUT_MOCK_INPUT_DISPOSITION_HANDLER_H_
#include <stddef.h>
#include <memory>
#include <utility>
-#include "content/browser/renderer_host/input/input_ack_handler.h"
+#include "content/browser/renderer_host/input/input_disposition_handler.h"
namespace content {
class InputRouter;
-class MockInputAckHandler : public InputAckHandler {
+class MockInputDispositionHandler : public InputDispositionHandler {
public:
- MockInputAckHandler();
- ~MockInputAckHandler() override;
+ MockInputDispositionHandler();
+ ~MockInputDispositionHandler() override;
- // InputAckHandler
+ // InputDispositionHandler
void OnKeyboardEventAck(const NativeWebKeyboardEventWithLatencyInfo& event,
InputEventAckState ack_result) override;
void OnMouseEventAck(const MouseEventWithLatencyInfo& event,
@@ -97,4 +97,4 @@ class MockInputAckHandler : public InputAckHandler {
} // namespace content
-#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_MOCK_INPUT_ACK_HANDLER_H_
+#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_MOCK_INPUT_DISPOSITION_HANDLER_H_
diff --git a/chromium/content/browser/renderer_host/input/mock_widget_input_handler.cc b/chromium/content/browser/renderer_host/input/mock_widget_input_handler.cc
new file mode 100644
index 00000000000..79b0e4f2bae
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/mock_widget_input_handler.cc
@@ -0,0 +1,93 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/input/mock_widget_input_handler.h"
+
+#include "content/browser/renderer_host/input/input_router.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using base::TimeDelta;
+using blink::WebGestureEvent;
+using blink::WebInputEvent;
+using blink::WebMouseEvent;
+using blink::WebMouseWheelEvent;
+using blink::WebTouchEvent;
+using blink::WebTouchPoint;
+
+namespace content {
+
+MockWidgetInputHandler::MockWidgetInputHandler() {}
+
+MockWidgetInputHandler::~MockWidgetInputHandler() {}
+
+void MockWidgetInputHandler::SetFocus(bool focused) {}
+
+void MockWidgetInputHandler::MouseCaptureLost() {}
+
+void MockWidgetInputHandler::SetEditCommandsForNextKeyEvent(
+ const std::vector<content::EditCommand>& commands) {
+ edit_commands_ = commands;
+}
+
+void MockWidgetInputHandler::CursorVisibilityChanged(bool visible) {}
+
+void MockWidgetInputHandler::ImeSetComposition(
+ const base::string16& text,
+ const std::vector<ui::ImeTextSpan>& ime_text_spans,
+ const gfx::Range& range,
+ int32_t start,
+ int32_t end) {}
+
+void MockWidgetInputHandler::ImeCommitText(
+ const base::string16& text,
+ const std::vector<ui::ImeTextSpan>& ime_text_spans,
+ const gfx::Range& range,
+ int32_t relative_cursor_position) {}
+
+void MockWidgetInputHandler::ImeFinishComposingText(bool keep_selection) {}
+
+void MockWidgetInputHandler::RequestTextInputStateUpdate() {}
+
+void MockWidgetInputHandler::RequestCompositionUpdates(bool immediate_request,
+ bool monitor_request) {}
+
+void MockWidgetInputHandler::DispatchEvent(
+ std::unique_ptr<content::InputEvent> event,
+ DispatchEventCallback callback) {
+ dispatched_events_.emplace_back(
+ DispatchedEvent(std::move(event), std::move(callback)));
+}
+
+void MockWidgetInputHandler::DispatchNonBlockingEvent(
+ std::unique_ptr<content::InputEvent> event) {
+ dispatched_events_.emplace_back(
+ DispatchedEvent(std::move(event), DispatchEventCallback()));
+}
+
+std::vector<MockWidgetInputHandler::DispatchedEvent>
+MockWidgetInputHandler::GetAndResetDispatchedEvents() {
+ std::vector<DispatchedEvent> dispatched_events;
+ dispatched_events_.swap(dispatched_events);
+ return dispatched_events;
+}
+
+std::vector<content::EditCommand>
+MockWidgetInputHandler::GetAndResetEditCommands() {
+ std::vector<content::EditCommand> edit_commands;
+ edit_commands_.swap(edit_commands);
+ return edit_commands;
+}
+
+MockWidgetInputHandler::DispatchedEvent::DispatchedEvent(
+ DispatchedEvent&& other)
+ : event_(std::move(other.event_)), callback_(std::move(other.callback_)) {}
+
+MockWidgetInputHandler::DispatchedEvent::DispatchedEvent(
+ std::unique_ptr<content::InputEvent> event,
+ DispatchEventCallback callback)
+ : event_(std::move(event)), callback_(std::move(callback)) {}
+
+MockWidgetInputHandler::DispatchedEvent::~DispatchedEvent() {}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/mock_widget_input_handler.h b/chromium/content/browser/renderer_host/input/mock_widget_input_handler.h
new file mode 100644
index 00000000000..de206904713
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/mock_widget_input_handler.h
@@ -0,0 +1,68 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_MOCK_WIDGET_INPUT_HANDLER_H_
+#define CONTENT_BROWSER_RENDERER_HOST_INPUT_MOCK_WIDGET_INPUT_HANDLER_H_
+
+#include <stddef.h>
+
+#include <memory>
+#include <utility>
+
+#include "content/common/input/input_handler.mojom.h"
+
+namespace content {
+
+class MockWidgetInputHandler : public mojom::WidgetInputHandler {
+ public:
+ MockWidgetInputHandler();
+ ~MockWidgetInputHandler() override;
+
+ class DispatchedEvent {
+ public:
+ DispatchedEvent(DispatchedEvent&& other);
+
+ DispatchedEvent(std::unique_ptr<content::InputEvent> event,
+ DispatchEventCallback callback);
+ ~DispatchedEvent();
+ std::unique_ptr<content::InputEvent> event_;
+ DispatchEventCallback callback_;
+ };
+
+ // mojom::WidgetInputHandler override.
+ void SetFocus(bool focused) override;
+ void MouseCaptureLost() override;
+ void SetEditCommandsForNextKeyEvent(
+ const std::vector<content::EditCommand>& commands) override;
+ void CursorVisibilityChanged(bool visible) override;
+ void ImeSetComposition(const base::string16& text,
+ const std::vector<ui::ImeTextSpan>& ime_text_spans,
+ const gfx::Range& range,
+ int32_t start,
+ int32_t end) override;
+ void ImeCommitText(const base::string16& text,
+ const std::vector<ui::ImeTextSpan>& ime_text_spans,
+ const gfx::Range& range,
+ int32_t relative_cursor_position) override;
+ void ImeFinishComposingText(bool keep_selection) override;
+ void RequestTextInputStateUpdate() override;
+ void RequestCompositionUpdates(bool immediate_request,
+ bool monitor_request) override;
+
+ void DispatchEvent(std::unique_ptr<content::InputEvent> event,
+ DispatchEventCallback callback) override;
+ void DispatchNonBlockingEvent(
+ std::unique_ptr<content::InputEvent> event) override;
+
+ std::vector<DispatchedEvent> GetAndResetDispatchedEvents();
+ std::vector<content::EditCommand> GetAndResetEditCommands();
+
+ private:
+ std::vector<DispatchedEvent> dispatched_events_;
+ std::vector<content::EditCommand> edit_commands_;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_MOCK_INPUT_ACK_HANDLER_H_
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 b9c0e4bf651..7358b3db18c 100644
--- a/chromium/content/browser/renderer_host/input/mouse_latency_browsertest.cc
+++ b/chromium/content/browser/renderer_host/input/mouse_latency_browsertest.cc
@@ -71,7 +71,7 @@ class MouseLatencyBrowserTest : public ContentBrowserTest {
std::unique_ptr<base::Value> trace_data =
base::JSONReader::Read(trace_data_string->data());
ASSERT_TRUE(trace_data);
- trace_data_ = *trace_data;
+ trace_data_ = trace_data->Clone();
runner_->Quit();
}
@@ -159,7 +159,7 @@ IN_PROC_BROWSER_TEST_F(MouseLatencyBrowserTest,
StartTracing();
DoSyncClick(gfx::PointF(100, 100));
- const base::Value trace_data = StopTracing();
+ const base::Value& trace_data = StopTracing();
const base::DictionaryValue* trace_data_dict;
trace_data.GetAsDictionary(&trace_data_dict);
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 9b850fd39f8..96eead4ef61 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
@@ -186,6 +186,10 @@ void MouseWheelEventQueue::ProcessMouseWheelAck(
}
if (needs_update) {
+ // It is possible that the wheel event with phaseBegan is consumed and
+ // no GSB is sent.
+ if (needs_scroll_begin_)
+ SendScrollBegin(scroll_update, false);
ui::LatencyInfo latency = ui::LatencyInfo(ui::SourceEventType::WHEEL);
latency.AddLatencyNumber(
ui::INPUT_EVENT_LATENCY_GENERATE_SCROLL_UPDATE_FROM_MOUSE_WHEEL, 0,
@@ -193,9 +197,9 @@ void MouseWheelEventQueue::ProcessMouseWheelAck(
client_->ForwardGestureEventWithLatencyInfo(scroll_update, latency);
}
- if (current_phase_ended) {
- // Send GSE with if scroll latching is enabled and no fling is going
- // to happen next.
+ if (current_phase_ended && needs_scroll_end_) {
+ // Send GSE when scroll latching is enabled, GSB is sent, and no fling
+ // is going to happen next.
SendScrollEnd(scroll_update, false);
}
} else { // !enable_scroll_latching_
diff --git a/chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker.cc b/chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker.cc
index f7fb38a4341..e858ea85f9e 100644
--- a/chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker.cc
+++ b/chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker.cc
@@ -80,62 +80,62 @@ void AddLatencyInfoComponentIds(LatencyInfo* latency,
void RecordEQTAccuracy(base::TimeDelta queueing_time,
base::TimeDelta expected_queueing_time) {
- float expected_queueing_time_ms = expected_queueing_time.InMillisecondsF();
+ float queueing_time_ms = queueing_time.InMillisecondsF();
- if (expected_queueing_time_ms < 10) {
+ if (queueing_time_ms < 10) {
UMA_HISTOGRAM_TIMES(
"RendererScheduler."
- "QueueingDurationWhenExpectedQueueingTime_LessThan.10ms",
- queueing_time);
+ "ExpectedQueueingTimeWhenQueueingTime_LessThan.10ms",
+ expected_queueing_time);
}
- if (expected_queueing_time_ms < 150) {
+ if (queueing_time_ms < 150) {
UMA_HISTOGRAM_TIMES(
"RendererScheduler."
- "QueueingDurationWhenExpectedQueueingTime_LessThan.150ms",
- queueing_time);
+ "ExpectedQueueingTimeWhenQueueingTime_LessThan.150ms",
+ expected_queueing_time);
}
- if (expected_queueing_time_ms < 300) {
+ if (queueing_time_ms < 300) {
UMA_HISTOGRAM_TIMES(
"RendererScheduler."
- "QueueingDurationWhenExpectedQueueingTime_LessThan.300ms",
- queueing_time);
+ "ExpectedQueueingTimeWhenQueueingTime_LessThan.300ms",
+ expected_queueing_time);
}
- if (expected_queueing_time_ms < 450) {
+ if (queueing_time_ms < 450) {
UMA_HISTOGRAM_TIMES(
"RendererScheduler."
- "QueueingDurationWhenExpectedQueueingTime_LessThan.450ms",
- queueing_time);
+ "ExpectedQueueingTimeWhenQueueingTime_LessThan.450ms",
+ expected_queueing_time);
}
- if (expected_queueing_time_ms > 10) {
+ if (queueing_time_ms > 10) {
UMA_HISTOGRAM_TIMES(
"RendererScheduler."
- "QueueingDurationWhenExpectedQueueingTime_GreaterThan.10ms",
- queueing_time);
+ "ExpectedQueueingTimeWhenQueueingTime_GreaterThan.10ms",
+ expected_queueing_time);
}
- if (expected_queueing_time_ms > 150) {
+ if (queueing_time_ms > 150) {
UMA_HISTOGRAM_TIMES(
"RendererScheduler."
- "QueueingDurationWhenExpectedQueueingTime_GreaterThan.150ms",
- queueing_time);
+ "ExpectedQueueingTimeWhenQueueingTime_GreaterThan.150ms",
+ expected_queueing_time);
}
- if (expected_queueing_time_ms > 300) {
+ if (queueing_time_ms > 300) {
UMA_HISTOGRAM_TIMES(
"RendererScheduler."
- "QueueingDurationWhenExpectedQueueingTime_GreaterThan.300ms",
- queueing_time);
+ "ExpectedQueueingTimeWhenQueueingTime_GreaterThan.300ms",
+ expected_queueing_time);
}
- if (expected_queueing_time_ms > 450) {
+ if (queueing_time_ms > 450) {
UMA_HISTOGRAM_TIMES(
"RendererScheduler."
- "QueueingDurationWhenExpectedQueueingTime_GreaterThan.450ms",
- queueing_time);
+ "ExpectedQueueingTimeWhenQueueingTime_GreaterThan.450ms",
+ expected_queueing_time);
}
}
diff --git a/chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker.h b/chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker.h
index 84aa2554089..4e5d5c56b97 100644
--- a/chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker.h
+++ b/chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker.h
@@ -24,7 +24,7 @@ class RenderWidgetHostDelegate;
// Utility class for tracking the latency of events passing through
// a given RenderWidgetHost.
class CONTENT_EXPORT RenderWidgetHostLatencyTracker
- : NON_EXPORTED_BASE(public ui::LatencyTracker) {
+ : public ui::LatencyTracker {
public:
explicit RenderWidgetHostLatencyTracker(bool metric_sampling);
~RenderWidgetHostLatencyTracker();
diff --git a/chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker_unittest.cc b/chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker_unittest.cc
index ca8efa8a440..459fac321db 100644
--- a/chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker_unittest.cc
+++ b/chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker_unittest.cc
@@ -1300,11 +1300,15 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, WheelDuringMultiFingerTouch) {
TEST_F(RenderWidgetHostLatencyTrackerTest, ExpectedQueueingTimeAccuracy) {
// These numbers are sensitive to where the histogram buckets are.
- int event_timestamps_ms[] = {11, 25, 35};
-
- for (float expected_queueing_time_ms : {2, 15, 200, 400}) {
- base::TimeDelta expected_queueing_time =
- base::TimeDelta::FromMilliseconds(expected_queueing_time_ms);
+ base::TimeTicks event_timestamp =
+ base::TimeTicks() + base::TimeDelta::FromMilliseconds(11);
+ int expected_queueing_time_ms = 1;
+ base::TimeDelta expected_queueing_time =
+ base::TimeDelta::FromMilliseconds(expected_queueing_time_ms);
+
+ for (float queueing_time_ms : {2, 15, 200, 400}) {
+ base::TimeDelta queueing_time =
+ base::TimeDelta::FromMilliseconds(queueing_time_ms);
SyntheticWebTouchEvent event;
// Touch start.
event.PressPoint(1, 1);
@@ -1319,22 +1323,15 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, ExpectedQueueingTimeAccuracy) {
fake_latency.set_source_event_type(ui::SourceEventType::TOUCH);
fake_latency.AddLatencyNumberWithTimestamp(
ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
- tracker()->latency_component_id(), 0,
- base::TimeTicks() +
- base::TimeDelta::FromMilliseconds(event_timestamps_ms[0]),
- 1);
+ tracker()->latency_component_id(), 0, event_timestamp, 1);
fake_latency.AddLatencyNumberWithTimestamp(
ui::INPUT_EVENT_LATENCY_RENDERER_MAIN_COMPONENT, 0, 0,
- base::TimeTicks() +
- base::TimeDelta::FromMilliseconds(event_timestamps_ms[1]),
- 1);
+ event_timestamp + queueing_time, 1);
fake_latency.AddLatencyNumberWithTimestamp(
ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT, 0, 0,
- base::TimeTicks() +
- base::TimeDelta::FromMilliseconds(event_timestamps_ms[2]),
- 1);
+ event_timestamp + queueing_time, 1);
// Call ComputeInputLatencyHistograms directly to avoid OnInputEventAck
// overwriting components.
@@ -1346,51 +1343,44 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, ExpectedQueueingTimeAccuracy) {
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
}
- EXPECT_THAT(
- histogram_tester().GetAllSamples(
- "RendererScheduler."
- "QueueingDurationWhenExpectedQueueingTime_LessThan.10ms"),
- ElementsAre(Bucket(event_timestamps_ms[1] - event_timestamps_ms[0], 1)));
+ EXPECT_THAT(histogram_tester().GetAllSamples(
+ "RendererScheduler."
+ "ExpectedQueueingTimeWhenQueueingTime_LessThan.10ms"),
+ ElementsAre(Bucket(expected_queueing_time_ms, 1)));
- EXPECT_THAT(
- histogram_tester().GetAllSamples(
- "RendererScheduler."
- "QueueingDurationWhenExpectedQueueingTime_LessThan.150ms"),
- ElementsAre(Bucket(event_timestamps_ms[1] - event_timestamps_ms[0], 2)));
+ EXPECT_THAT(histogram_tester().GetAllSamples(
+ "RendererScheduler."
+ "ExpectedQueueingTimeWhenQueueingTime_LessThan.150ms"),
+ ElementsAre(Bucket(expected_queueing_time_ms, 2)));
- EXPECT_THAT(
- histogram_tester().GetAllSamples(
- "RendererScheduler."
- "QueueingDurationWhenExpectedQueueingTime_LessThan.300ms"),
- ElementsAre(Bucket(event_timestamps_ms[1] - event_timestamps_ms[0], 3)));
+ EXPECT_THAT(histogram_tester().GetAllSamples(
+ "RendererScheduler."
+ "ExpectedQueueingTimeWhenQueueingTime_LessThan.300ms"),
+ ElementsAre(Bucket(expected_queueing_time_ms, 3)));
- EXPECT_THAT(
- histogram_tester().GetAllSamples(
- "RendererScheduler."
- "QueueingDurationWhenExpectedQueueingTime_LessThan.450ms"),
- ElementsAre(Bucket(event_timestamps_ms[1] - event_timestamps_ms[0], 4)));
+ EXPECT_THAT(histogram_tester().GetAllSamples(
+ "RendererScheduler."
+ "ExpectedQueueingTimeWhenQueueingTime_LessThan.450ms"),
+ ElementsAre(Bucket(expected_queueing_time_ms, 4)));
- EXPECT_THAT(
- histogram_tester().GetAllSamples(
- "RendererScheduler."
- "QueueingDurationWhenExpectedQueueingTime_GreaterThan.10ms"),
- ElementsAre(Bucket(event_timestamps_ms[1] - event_timestamps_ms[0], 3)));
+ EXPECT_THAT(histogram_tester().GetAllSamples(
+ "RendererScheduler."
+ "ExpectedQueueingTimeWhenQueueingTime_GreaterThan.10ms"),
+ ElementsAre(Bucket(expected_queueing_time_ms, 3)));
- EXPECT_THAT(
- histogram_tester().GetAllSamples(
- "RendererScheduler."
- "QueueingDurationWhenExpectedQueueingTime_GreaterThan.150ms"),
- ElementsAre(Bucket(event_timestamps_ms[1] - event_timestamps_ms[0], 2)));
+ EXPECT_THAT(histogram_tester().GetAllSamples(
+ "RendererScheduler."
+ "ExpectedQueueingTimeWhenQueueingTime_GreaterThan.150ms"),
+ ElementsAre(Bucket(expected_queueing_time_ms, 2)));
- EXPECT_THAT(
- histogram_tester().GetAllSamples(
- "RendererScheduler."
- "QueueingDurationWhenExpectedQueueingTime_GreaterThan.300ms"),
- ElementsAre(Bucket(event_timestamps_ms[1] - event_timestamps_ms[0], 1)));
+ EXPECT_THAT(histogram_tester().GetAllSamples(
+ "RendererScheduler."
+ "ExpectedQueueingTimeWhenQueueingTime_GreaterThan.300ms"),
+ ElementsAre(Bucket(expected_queueing_time_ms, 1)));
EXPECT_THAT(histogram_tester().GetAllSamples(
"RendererScheduler."
- "QueueingDurationWhenExpectedQueueingTime_GreaterThan.450ms"),
+ "ExpectedQueueingTimeWhenQueueingTime_GreaterThan.450ms"),
ElementsAre());
}
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 3c5dcdc066d..44308e011ed 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_gesture_controller.cc
+++ b/chromium/content/browser/renderer_host/input/synthetic_gesture_controller.cc
@@ -28,13 +28,13 @@ SyntheticGestureController::~SyntheticGestureController() {}
void SyntheticGestureController::QueueSyntheticGesture(
std::unique_ptr<SyntheticGesture> synthetic_gesture,
- const OnGestureCompleteCallback& completion_callback) {
+ OnGestureCompleteCallback completion_callback) {
DCHECK(synthetic_gesture);
bool was_empty = pending_gesture_queue_.IsEmpty();
pending_gesture_queue_.Push(std::move(synthetic_gesture),
- completion_callback);
+ std::move(completion_callback));
if (was_empty)
StartGesture(*pending_gesture_queue_.FrontGesture());
@@ -95,14 +95,14 @@ void SyntheticGestureController::StartGesture(const SyntheticGesture& gesture) {
void SyntheticGestureController::StopGesture(
const SyntheticGesture& gesture,
- const OnGestureCompleteCallback& completion_callback,
+ OnGestureCompleteCallback completion_callback,
SyntheticGesture::Result result) {
DCHECK_NE(result, SyntheticGesture::GESTURE_RUNNING);
TRACE_EVENT_ASYNC_END0("input,benchmark",
"SyntheticGestureController::running",
&gesture);
- completion_callback.Run(result);
+ std::move(completion_callback).Run(result);
}
SyntheticGestureController::GestureAndCallbackQueue::GestureAndCallbackQueue() {
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 5ed093af694..cbb44036c9e 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_gesture_controller.h
+++ b/chromium/content/browser/renderer_host/input/synthetic_gesture_controller.h
@@ -41,11 +41,11 @@ class CONTENT_EXPORT SyntheticGestureController {
std::unique_ptr<SyntheticGestureTarget> gesture_target);
virtual ~SyntheticGestureController();
- typedef base::Callback<void(SyntheticGesture::Result)>
+ typedef base::OnceCallback<void(SyntheticGesture::Result)>
OnGestureCompleteCallback;
void QueueSyntheticGesture(
std::unique_ptr<SyntheticGesture> synthetic_gesture,
- const OnGestureCompleteCallback& completion_callback);
+ OnGestureCompleteCallback completion_callback);
bool DispatchNextEvent(base::TimeTicks = base::TimeTicks::Now());
@@ -55,7 +55,7 @@ class CONTENT_EXPORT SyntheticGestureController {
void StartTimer();
void StartGesture(const SyntheticGesture& gesture);
void StopGesture(const SyntheticGesture& gesture,
- const OnGestureCompleteCallback& completion_callback,
+ OnGestureCompleteCallback completion_callback,
SyntheticGesture::Result result);
Delegate* const delegate_;
@@ -68,9 +68,9 @@ class CONTENT_EXPORT SyntheticGestureController {
GestureAndCallbackQueue();
~GestureAndCallbackQueue();
void Push(std::unique_ptr<SyntheticGesture> gesture,
- const OnGestureCompleteCallback& callback) {
+ OnGestureCompleteCallback callback) {
gestures_.push_back(std::move(gesture));
- callbacks_.push(callback);
+ callbacks_.push(std::move(callback));
}
void Pop() {
gestures_.erase(gestures_.begin());
@@ -78,8 +78,11 @@ class CONTENT_EXPORT SyntheticGestureController {
result_of_current_gesture_ = SyntheticGesture::GESTURE_RUNNING;
}
SyntheticGesture* FrontGesture() { return gestures_.front().get(); }
- OnGestureCompleteCallback& FrontCallback() {
- return callbacks_.front();
+ OnGestureCompleteCallback FrontCallback() {
+ // TODO(dtapuska): This is odd moving the top callback. Pop really
+ // should be rewritten to take two output parameters then we can
+ // remove FrontGesture/FrontCallback.
+ return std::move(callbacks_.front());
}
bool IsEmpty() const {
CHECK(gestures_.empty() == callbacks_.empty());
diff --git a/chromium/content/browser/renderer_host/input/synthetic_gesture_target_android.cc b/chromium/content/browser/renderer_host/input/synthetic_gesture_target_android.cc
index c050922c9bc..7a64bdf6632 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_gesture_target_android.cc
+++ b/chromium/content/browser/renderer_host/input/synthetic_gesture_target_android.cc
@@ -4,69 +4,83 @@
#include "content/browser/renderer_host/input/synthetic_gesture_target_android.h"
-#include "content/browser/android/content_view_core.h"
-#include "content/browser/renderer_host/render_widget_host_impl.h"
-#include "jni/MotionEventSynthesizer_jni.h"
+#include "base/trace_event/trace_event.h"
+#include "jni/SyntheticGestureTarget_jni.h"
#include "third_party/WebKit/public/platform/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebMouseEvent.h"
+#include "third_party/WebKit/public/platform/WebMouseWheelEvent.h"
+#include "third_party/WebKit/public/platform/WebTouchEvent.h"
+#include "ui/android/view_android.h"
#include "ui/gfx/android/view_configuration.h"
+using base::android::JavaParamRef;
+using base::android::ScopedJavaLocalRef;
+using blink::WebInputEvent;
+using blink::WebMouseEvent;
+using blink::WebMouseWheelEvent;
using blink::WebTouchEvent;
namespace content {
SyntheticGestureTargetAndroid::SyntheticGestureTargetAndroid(
RenderWidgetHostImpl* host,
- base::android::ScopedJavaLocalRef<jobject> touch_event_synthesizer)
- : SyntheticGestureTargetBase(host),
- touch_event_synthesizer_(touch_event_synthesizer) {
- DCHECK(!touch_event_synthesizer_.is_null());
+ ui::ViewAndroid* view)
+ : SyntheticGestureTargetBase(host), view_(view) {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ java_ref_.Reset(
+ Java_SyntheticGestureTarget_create(env, view->GetContainerView()));
}
-SyntheticGestureTargetAndroid::~SyntheticGestureTargetAndroid() {
-}
+SyntheticGestureTargetAndroid::~SyntheticGestureTargetAndroid() = default;
-void SyntheticGestureTargetAndroid::TouchSetPointer(
- JNIEnv* env, int index, int x, int y, int id) {
+void SyntheticGestureTargetAndroid::TouchSetPointer(int index,
+ int x,
+ int y,
+ int id) {
TRACE_EVENT0("input", "SyntheticGestureTargetAndroid::TouchSetPointer");
- Java_MotionEventSynthesizer_setPointer(env, touch_event_synthesizer_, index,
- x, y, id);
+ JNIEnv* env = base::android::AttachCurrentThread();
+ float scale_factor = view_->GetDipScale();
+ Java_SyntheticGestureTarget_setPointer(
+ env, java_ref_, index, x * scale_factor, y * scale_factor, id);
}
-void SyntheticGestureTargetAndroid::TouchSetScrollDeltas(
- JNIEnv* env, int x, int y, int dx, int dy) {
+void SyntheticGestureTargetAndroid::TouchSetScrollDeltas(int x,
+ int y,
+ int dx,
+ int dy) {
TRACE_EVENT0("input", "SyntheticGestureTargetAndroid::TouchSetScrollDeltas");
- Java_MotionEventSynthesizer_setScrollDeltas(env, touch_event_synthesizer_, x,
- y, dx, dy);
+ JNIEnv* env = base::android::AttachCurrentThread();
+ float scale_factor = view_->GetDipScale();
+ Java_SyntheticGestureTarget_setScrollDeltas(
+ env, java_ref_, x * scale_factor, y * scale_factor, dx * scale_factor,
+ dy * scale_factor);
}
-void SyntheticGestureTargetAndroid::TouchInject(JNIEnv* env,
- Action action,
+void SyntheticGestureTargetAndroid::TouchInject(MotionEventAction action,
int pointer_count,
int64_t time_in_ms) {
TRACE_EVENT0("input", "SyntheticGestureTargetAndroid::TouchInject");
- Java_MotionEventSynthesizer_inject(env, touch_event_synthesizer_,
- static_cast<int>(action), pointer_count,
+ JNIEnv* env = base::android::AttachCurrentThread();
+ Java_SyntheticGestureTarget_inject(env, java_ref_, action, pointer_count,
time_in_ms);
}
void SyntheticGestureTargetAndroid::DispatchWebTouchEventToPlatform(
- const blink::WebTouchEvent& web_touch, const ui::LatencyInfo&) {
- JNIEnv* env = base::android::AttachCurrentThread();
-
- SyntheticGestureTargetAndroid::Action action =
- SyntheticGestureTargetAndroid::ActionInvalid;
+ const WebTouchEvent& web_touch,
+ const ui::LatencyInfo&) {
+ MotionEventAction action = MOTION_EVENT_ACTION_INVALID;
switch (web_touch.GetType()) {
- case blink::WebInputEvent::kTouchStart:
- action = SyntheticGestureTargetAndroid::ActionStart;
+ case WebInputEvent::kTouchStart:
+ action = MOTION_EVENT_ACTION_START;
break;
- case blink::WebInputEvent::kTouchMove:
- action = SyntheticGestureTargetAndroid::ActionMove;
+ case WebInputEvent::kTouchMove:
+ action = MOTION_EVENT_ACTION_MOVE;
break;
- case blink::WebInputEvent::kTouchCancel:
- action = SyntheticGestureTargetAndroid::ActionCancel;
+ case WebInputEvent::kTouchCancel:
+ action = MOTION_EVENT_ACTION_CANCEL;
break;
- case blink::WebInputEvent::kTouchEnd:
- action = SyntheticGestureTargetAndroid::ActionEnd;
+ case WebInputEvent::kTouchEnd:
+ action = MOTION_EVENT_ACTION_END;
break;
default:
NOTREACHED();
@@ -74,28 +88,27 @@ void SyntheticGestureTargetAndroid::DispatchWebTouchEventToPlatform(
const unsigned num_touches = web_touch.touches_length;
for (unsigned i = 0; i < num_touches; ++i) {
const blink::WebTouchPoint* point = &web_touch.touches[i];
- TouchSetPointer(env, i, point->PositionInWidget().x,
- point->PositionInWidget().y, point->id);
+ TouchSetPointer(i, point->PositionInWidget().x, point->PositionInWidget().y,
+ point->id);
}
- TouchInject(env, action, num_touches,
+ TouchInject(action, num_touches,
static_cast<int64_t>(web_touch.TimeStampSeconds() * 1000.0));
}
void SyntheticGestureTargetAndroid::DispatchWebMouseWheelEventToPlatform(
- const blink::WebMouseWheelEvent& web_wheel, const ui::LatencyInfo&) {
- JNIEnv* env = base::android::AttachCurrentThread();
- TouchSetScrollDeltas(env, web_wheel.PositionInWidget().x,
+ const WebMouseWheelEvent& web_wheel,
+ const ui::LatencyInfo&) {
+ TouchSetScrollDeltas(web_wheel.PositionInWidget().x,
web_wheel.PositionInWidget().y, web_wheel.delta_x,
web_wheel.delta_y);
- Java_MotionEventSynthesizer_inject(
- env, touch_event_synthesizer_,
- static_cast<int>(SyntheticGestureTargetAndroid::ActionScroll), 1,
- static_cast<int64_t>(web_wheel.TimeStampSeconds() * 1000.0));
+ TouchInject(MOTION_EVENT_ACTION_SCROLL, 1,
+ static_cast<int64_t>(web_wheel.TimeStampSeconds() * 1000.0));
}
void SyntheticGestureTargetAndroid::DispatchWebMouseEventToPlatform(
- const blink::WebMouseEvent& web_mouse, const ui::LatencyInfo&) {
+ const WebMouseEvent& web_mouse,
+ const ui::LatencyInfo&) {
CHECK(false);
}
diff --git a/chromium/content/browser/renderer_host/input/synthetic_gesture_target_android.h b/chromium/content/browser/renderer_host/input/synthetic_gesture_target_android.h
index f1b4b0b45ac..ed665bc581b 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_gesture_target_android.h
+++ b/chromium/content/browser/renderer_host/input/synthetic_gesture_target_android.h
@@ -5,20 +5,24 @@
#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_GESTURE_TARGET_ANDROID_H_
#define CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_GESTURE_TARGET_ANDROID_H_
-#include <stdint.h>
-
#include "base/android/jni_android.h"
-#include "base/macros.h"
-#include "base/time/time.h"
+#include "base/android/scoped_java_ref.h"
#include "content/browser/renderer_host/input/synthetic_gesture_target_base.h"
+#include "content/public/browser/android/motion_event_action.h"
+
+namespace ui {
+class LatencyInfo;
+class ViewAndroid;
+} // namespace ui
namespace content {
+// Owned by |SyntheticGestureController|. Keeps a strong pointer to Java object,
+// which get destroyed together with the controller.
class SyntheticGestureTargetAndroid : public SyntheticGestureTargetBase {
public:
- SyntheticGestureTargetAndroid(
- RenderWidgetHostImpl* host,
- base::android::ScopedJavaLocalRef<jobject> touch_event_synthesizer);
+ SyntheticGestureTargetAndroid(RenderWidgetHostImpl* host,
+ ui::ViewAndroid* view);
~SyntheticGestureTargetAndroid() override;
// SyntheticGestureTargetBase:
@@ -35,30 +39,18 @@ class SyntheticGestureTargetAndroid : public SyntheticGestureTargetBase {
// SyntheticGestureTarget:
SyntheticGestureParams::GestureSourceType
GetDefaultSyntheticGestureSourceType() const override;
-
float GetTouchSlopInDips() const override;
-
float GetMinScalingSpanInDips() const override;
private:
- // Enum values below need to be kept in sync with MotionEventSynthesizer.java.
- enum Action {
- ActionInvalid = -1,
- ActionStart = 0,
- ActionMove = 1,
- ActionCancel = 2,
- ActionEnd = 3,
- ActionScroll = 4
- };
-
- void TouchSetPointer(JNIEnv* env, int index, int x, int y, int id);
- void TouchSetScrollDeltas(JNIEnv* env, int x, int y, int dx, int dy);
- void TouchInject(JNIEnv* env,
- Action action,
+ void TouchSetPointer(int index, int x, int y, int id);
+ void TouchSetScrollDeltas(int x, int y, int dx, int dy);
+ void TouchInject(MotionEventAction action,
int pointer_count,
int64_t time_in_ms);
- base::android::ScopedJavaGlobalRef<jobject> touch_event_synthesizer_;
+ ui::ViewAndroid* const view_;
+ base::android::ScopedJavaGlobalRef<jobject> java_ref_;
DISALLOW_COPY_AND_ASSIGN(SyntheticGestureTargetAndroid);
};
diff --git a/chromium/content/browser/renderer_host/input/synthetic_gesture_target_aura.cc b/chromium/content/browser/renderer_host/input/synthetic_gesture_target_aura.cc
index 08f560fa8f5..c5f82d5d97a 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_gesture_target_aura.cc
+++ b/chromium/content/browser/renderer_host/input/synthetic_gesture_target_aura.cc
@@ -68,6 +68,17 @@ void SyntheticGestureTargetAura::DispatchWebTouchEventToPlatform(
void SyntheticGestureTargetAura::DispatchWebMouseWheelEventToPlatform(
const blink::WebMouseWheelEvent& web_wheel,
const ui::LatencyInfo&) {
+ if (web_wheel.phase == blink::WebMouseWheelEvent::kPhaseEnded) {
+ DCHECK(
+ !render_widget_host()->GetView()->IsRenderWidgetHostViewChildFrame() &&
+ !render_widget_host()->GetView()->IsRenderWidgetHostViewGuest());
+ // Send the pending wheel end event immediately.
+ static_cast<RenderWidgetHostViewAura*>(render_widget_host()->GetView())
+ ->event_handler()
+ ->mouse_wheel_phase_handler()
+ .DispatchPendingWheelEndEvent();
+ return;
+ }
ui::MouseWheelEvent wheel_event(
gfx::Vector2d(web_wheel.delta_x, web_wheel.delta_y), gfx::Point(),
gfx::Point(), ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE);
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 ba0757bcc6c..3740118e2fa 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_pointer_action.cc
+++ b/chromium/content/browser/renderer_host/input/synthetic_pointer_action.cc
@@ -51,6 +51,9 @@ SyntheticPointerAction::GestureState
SyntheticPointerAction::ForwardTouchOrMouseInputEvents(
const base::TimeTicks& timestamp,
SyntheticGestureTarget* target) {
+ if (!params_.params.size())
+ return DONE;
+
DCHECK_LT(num_actions_dispatched_, params_.params.size());
SyntheticPointerActionListParams::ParamList& param_list =
params_.params[num_actions_dispatched_];
@@ -85,4 +88,4 @@ SyntheticPointerAction::ForwardTouchOrMouseInputEvents(
return RUNNING;
}
-} // namespace content \ No newline at end of file
+} // namespace content
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 abf6780cc33..cb244a653fb 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
@@ -704,6 +704,15 @@ TEST_F(SyntheticPointerActionTest, PointerPenAction) {
param3, 1, buttons, SyntheticGestureParams::PEN_INPUT));
}
+TEST_F(SyntheticPointerActionTest, EmptyParams) {
+ CreateSyntheticPointerActionTarget<MockSyntheticPointerPenActionTarget>();
+ pointer_action_.reset(new SyntheticPointerAction(params_));
+
+ ForwardSyntheticPointerAction();
+ EXPECT_EQ(1, num_success_);
+ EXPECT_EQ(0, num_failure_);
+}
+
} // namespace
} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/synthetic_smooth_move_gesture.cc b/chromium/content/browser/renderer_host/input/synthetic_smooth_move_gesture.cc
index 66900a8539e..e150a80753b 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_smooth_move_gesture.cc
+++ b/chromium/content/browser/renderer_host/input/synthetic_smooth_move_gesture.cc
@@ -51,8 +51,8 @@ SyntheticSmoothMoveGesture::SyntheticSmoothMoveGesture(
SyntheticSmoothMoveGestureParams params)
: params_(params),
current_move_segment_start_position_(params.start_point),
- state_(SETUP) {
-}
+ state_(SETUP),
+ needs_scroll_begin_(true) {}
SyntheticSmoothMoveGesture::~SyntheticSmoothMoveGesture() {}
@@ -149,8 +149,6 @@ void SyntheticSmoothMoveGesture::ForwardTouchInputEvents(
void SyntheticSmoothMoveGesture::ForwardMouseWheelInputEvents(
const base::TimeTicks& timestamp,
SyntheticGestureTarget* target) {
- blink::WebMouseWheelEvent::Phase phase =
- blink::WebMouseWheelEvent::kPhaseChanged;
switch (state_) {
case STARTED:
if (MoveIsNoOp()) {
@@ -159,7 +157,6 @@ void SyntheticSmoothMoveGesture::ForwardMouseWheelInputEvents(
}
ComputeNextMoveSegment();
state_ = MOVING;
- phase = blink::WebMouseWheelEvent::kPhaseBegan;
// Fall through to forward the first event.
case MOVING: {
// Even though WebMouseWheelEvents take floating point deltas,
@@ -173,7 +170,16 @@ void SyntheticSmoothMoveGesture::ForwardMouseWheelInputEvents(
gfx::Vector2d delta_discrete =
FloorTowardZero(current_move_segment_total_delta -
current_move_segment_total_delta_discrete_);
- ForwardMouseWheelEvent(target, delta_discrete, phase, event_timestamp);
+
+ blink::WebMouseWheelEvent::Phase phase =
+ needs_scroll_begin_ ? blink::WebMouseWheelEvent::kPhaseBegan
+ : blink::WebMouseWheelEvent::kPhaseChanged;
+ // Only send wheel events if they have non-zero deltas.
+ if (delta_discrete.x() || delta_discrete.y()) {
+ ForwardMouseWheelEvent(target, delta_discrete, phase, event_timestamp);
+ if (phase == blink::WebMouseWheelEvent::kPhaseBegan)
+ needs_scroll_begin_ = false;
+ }
current_move_segment_total_delta_discrete_ += delta_discrete;
if (FinishedCurrentMoveSegment(event_timestamp)) {
@@ -183,9 +189,11 @@ void SyntheticSmoothMoveGesture::ForwardMouseWheelInputEvents(
ForwardMouseWheelInputEvents(timestamp, target);
} else {
state_ = DONE;
+ // Forward a wheel event with phase ended and zero deltas.
ForwardMouseWheelEvent(target, gfx::Vector2d(),
blink::WebMouseWheelEvent::kPhaseEnded,
event_timestamp);
+ needs_scroll_begin_ = true;
}
}
} break;
diff --git a/chromium/content/browser/renderer_host/input/synthetic_smooth_move_gesture.h b/chromium/content/browser/renderer_host/input/synthetic_smooth_move_gesture.h
index 6b6099b044e..87015ac39d2 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_smooth_move_gesture.h
+++ b/chromium/content/browser/renderer_host/input/synthetic_smooth_move_gesture.h
@@ -103,6 +103,8 @@ class CONTENT_EXPORT SyntheticSmoothMoveGesture : public SyntheticGesture {
int current_move_segment_;
base::TimeTicks current_move_segment_start_time_;
base::TimeTicks current_move_segment_stop_time_;
+ // Used to set phase information for synthetic wheel events.
+ bool needs_scroll_begin_;
DISALLOW_COPY_AND_ASSIGN(SyntheticSmoothMoveGesture);
};
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 efaa80cb4e7..4eb1d583127 100644
--- a/chromium/content/browser/renderer_host/input/touch_action_filter.cc
+++ b/chromium/content/browser/renderer_host/input/touch_action_filter.cc
@@ -38,6 +38,7 @@ TouchActionFilter::TouchActionFilter()
: suppress_manipulation_events_(false),
drop_current_tap_ending_event_(false),
allow_current_double_tap_event_(true),
+ force_enable_zoom_(false),
allowed_touch_action_(cc::kTouchActionAuto),
white_listed_touch_action_(cc::kTouchActionAuto) {}
@@ -172,6 +173,11 @@ void TouchActionFilter::OnSetTouchAction(cc::TouchAction touch_action) {
// 2. Only subtractive - eg. can't trigger scrolling on a element that
// otherwise has scrolling disabling by the addition of a finger.
allowed_touch_action_ &= touch_action;
+
+ // When user enabled force enable zoom, we should always allow pinch-zoom
+ // except for touch-action:none.
+ if (force_enable_zoom_ && allowed_touch_action_ != cc::kTouchActionNone)
+ allowed_touch_action_ |= cc::kTouchActionPinchZoom;
}
void TouchActionFilter::ReportAndResetTouchAction() {
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 8b12c43e715..44002ed8582 100644
--- a/chromium/content/browser/renderer_host/input/touch_action_filter.h
+++ b/chromium/content/browser/renderer_host/input/touch_action_filter.h
@@ -50,6 +50,8 @@ class CONTENT_EXPORT TouchActionFilter {
cc::TouchAction allowed_touch_action() const { return allowed_touch_action_; }
+ void SetForceEnableZoom(bool enabled) { force_enable_zoom_ = enabled; }
+
private:
bool ShouldSuppressManipulation(const blink::WebGestureEvent&);
bool FilterManipulationEventAndResetState();
@@ -67,6 +69,9 @@ class CONTENT_EXPORT TouchActionFilter {
// and the next DoubleTap.
bool allow_current_double_tap_event_;
+ // Force enable zoom for Accessibility.
+ bool force_enable_zoom_;
+
// What touch actions are currently permitted.
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 66253b3ef2c..d1b94179777 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
@@ -470,118 +470,134 @@ TEST(TouchActionFilterTest, MultiTouch) {
EXPECT_TRUE(filter.FilterGestureEvent(&scroll_end));
}
-TEST(TouchActionFilterTest, Pinch) {
- TouchActionFilter filter;
+class TouchActionFilterPinchTest : public testing::Test {
+ public:
+ void RunTest(bool force_enable_zoom) {
+ TouchActionFilter filter;
+ filter.SetForceEnableZoom(force_enable_zoom);
- WebGestureEvent scroll_begin =
- SyntheticWebGestureEventBuilder::BuildScrollBegin(2, 3, kSourceDevice, 2);
- WebGestureEvent pinch_begin = SyntheticWebGestureEventBuilder::Build(
- WebInputEvent::kGesturePinchBegin, kSourceDevice);
- WebGestureEvent pinch_update =
- SyntheticWebGestureEventBuilder::BuildPinchUpdate(1.2f, 5, 5, 0,
- kSourceDevice);
- WebGestureEvent pinch_end = SyntheticWebGestureEventBuilder::Build(
- WebInputEvent::kGesturePinchEnd, kSourceDevice);
- WebGestureEvent scroll_end = SyntheticWebGestureEventBuilder::Build(
- WebInputEvent::kGestureScrollEnd, kSourceDevice);
+ WebGestureEvent scroll_begin =
+ SyntheticWebGestureEventBuilder::BuildScrollBegin(2, 3, kSourceDevice,
+ 2);
+ WebGestureEvent pinch_begin = SyntheticWebGestureEventBuilder::Build(
+ WebInputEvent::kGesturePinchBegin, kSourceDevice);
+ WebGestureEvent pinch_update =
+ SyntheticWebGestureEventBuilder::BuildPinchUpdate(1.2f, 5, 5, 0,
+ kSourceDevice);
+ WebGestureEvent pinch_end = SyntheticWebGestureEventBuilder::Build(
+ WebInputEvent::kGesturePinchEnd, kSourceDevice);
+ WebGestureEvent scroll_end = SyntheticWebGestureEventBuilder::Build(
+ WebInputEvent::kGestureScrollEnd, kSourceDevice);
- // Pinch is allowed with touch-action: auto.
- filter.ResetTouchAction();
- filter.OnSetTouchAction(cc::kTouchActionAuto);
- EXPECT_FALSE(filter.FilterGestureEvent(&scroll_begin));
- EXPECT_FALSE(filter.FilterGestureEvent(&pinch_begin));
- EXPECT_FALSE(filter.FilterGestureEvent(&pinch_update));
- EXPECT_FALSE(filter.FilterGestureEvent(&pinch_end));
- EXPECT_FALSE(filter.FilterGestureEvent(&scroll_end));
+ // Pinch is allowed with touch-action: auto.
+ filter.ResetTouchAction();
+ filter.OnSetTouchAction(cc::kTouchActionAuto);
+ EXPECT_FALSE(filter.FilterGestureEvent(&scroll_begin));
+ EXPECT_FALSE(filter.FilterGestureEvent(&pinch_begin));
+ EXPECT_FALSE(filter.FilterGestureEvent(&pinch_update));
+ EXPECT_FALSE(filter.FilterGestureEvent(&pinch_end));
+ EXPECT_FALSE(filter.FilterGestureEvent(&scroll_end));
- // Pinch is not allowed with touch-action: none.
- filter.ResetTouchAction();
- filter.OnSetTouchAction(cc::kTouchActionNone);
- EXPECT_TRUE(filter.FilterGestureEvent(&scroll_begin));
- EXPECT_TRUE(filter.FilterGestureEvent(&pinch_begin));
- EXPECT_TRUE(filter.FilterGestureEvent(&pinch_update));
- EXPECT_TRUE(filter.FilterGestureEvent(&pinch_end));
- EXPECT_TRUE(filter.FilterGestureEvent(&pinch_begin));
- EXPECT_TRUE(filter.FilterGestureEvent(&pinch_update));
- EXPECT_TRUE(filter.FilterGestureEvent(&pinch_end));
- EXPECT_TRUE(filter.FilterGestureEvent(&scroll_end));
+ // Pinch is not allowed with touch-action: none.
+ filter.ResetTouchAction();
+ filter.OnSetTouchAction(cc::kTouchActionNone);
+ EXPECT_TRUE(filter.FilterGestureEvent(&scroll_begin));
+ EXPECT_TRUE(filter.FilterGestureEvent(&pinch_begin));
+ EXPECT_TRUE(filter.FilterGestureEvent(&pinch_update));
+ EXPECT_TRUE(filter.FilterGestureEvent(&pinch_end));
+ EXPECT_TRUE(filter.FilterGestureEvent(&pinch_begin));
+ EXPECT_TRUE(filter.FilterGestureEvent(&pinch_update));
+ EXPECT_TRUE(filter.FilterGestureEvent(&pinch_end));
+ EXPECT_TRUE(filter.FilterGestureEvent(&scroll_end));
- // Pinch is not allowed with touch-action: pan-x pan-y.
- filter.ResetTouchAction();
- filter.OnSetTouchAction(cc::kTouchActionPan);
- EXPECT_TRUE(filter.FilterGestureEvent(&scroll_begin));
- EXPECT_TRUE(filter.FilterGestureEvent(&pinch_begin));
- EXPECT_TRUE(filter.FilterGestureEvent(&pinch_update));
- EXPECT_TRUE(filter.FilterGestureEvent(&pinch_end));
- EXPECT_TRUE(filter.FilterGestureEvent(&scroll_end));
+ // Pinch is not allowed with touch-action: pan-x pan-y except for force
+ // enable zoom.
+ filter.ResetTouchAction();
+ filter.OnSetTouchAction(cc::kTouchActionPan);
+ EXPECT_NE(filter.FilterGestureEvent(&scroll_begin), force_enable_zoom);
+ EXPECT_NE(filter.FilterGestureEvent(&pinch_begin), force_enable_zoom);
+ EXPECT_NE(filter.FilterGestureEvent(&pinch_update), force_enable_zoom);
+ EXPECT_NE(filter.FilterGestureEvent(&pinch_end), force_enable_zoom);
+ EXPECT_NE(filter.FilterGestureEvent(&scroll_end), force_enable_zoom);
- // Pinch is allowed with touch-action: manipulation.
- filter.ResetTouchAction();
- filter.OnSetTouchAction(cc::kTouchActionManipulation);
- EXPECT_FALSE(filter.FilterGestureEvent(&scroll_begin));
- EXPECT_FALSE(filter.FilterGestureEvent(&pinch_begin));
- EXPECT_FALSE(filter.FilterGestureEvent(&pinch_update));
- EXPECT_FALSE(filter.FilterGestureEvent(&pinch_end));
- EXPECT_FALSE(filter.FilterGestureEvent(&scroll_end));
+ // Pinch is allowed with touch-action: manipulation.
+ filter.ResetTouchAction();
+ filter.OnSetTouchAction(cc::kTouchActionManipulation);
+ EXPECT_FALSE(filter.FilterGestureEvent(&scroll_begin));
+ EXPECT_FALSE(filter.FilterGestureEvent(&pinch_begin));
+ EXPECT_FALSE(filter.FilterGestureEvent(&pinch_update));
+ EXPECT_FALSE(filter.FilterGestureEvent(&pinch_end));
+ EXPECT_FALSE(filter.FilterGestureEvent(&scroll_end));
- // Pinch state is automatically reset at the end of a scroll.
- filter.ResetTouchAction();
- EXPECT_FALSE(filter.FilterGestureEvent(&scroll_begin));
- EXPECT_FALSE(filter.FilterGestureEvent(&pinch_begin));
- EXPECT_FALSE(filter.FilterGestureEvent(&pinch_update));
- EXPECT_FALSE(filter.FilterGestureEvent(&pinch_end));
- EXPECT_FALSE(filter.FilterGestureEvent(&scroll_end));
+ // Pinch state is automatically reset at the end of a scroll.
+ filter.ResetTouchAction();
+ EXPECT_FALSE(filter.FilterGestureEvent(&scroll_begin));
+ EXPECT_FALSE(filter.FilterGestureEvent(&pinch_begin));
+ EXPECT_FALSE(filter.FilterGestureEvent(&pinch_update));
+ EXPECT_FALSE(filter.FilterGestureEvent(&pinch_end));
+ EXPECT_FALSE(filter.FilterGestureEvent(&scroll_end));
- // Pinching is only computed at GestureScrollBegin time.
- filter.ResetTouchAction();
- filter.OnSetTouchAction(cc::kTouchActionAuto);
- EXPECT_FALSE(filter.FilterGestureEvent(&scroll_begin));
- EXPECT_FALSE(filter.FilterGestureEvent(&pinch_begin));
- EXPECT_FALSE(filter.FilterGestureEvent(&pinch_update));
- EXPECT_FALSE(filter.FilterGestureEvent(&pinch_end));
- filter.OnSetTouchAction(cc::kTouchActionNone);
- EXPECT_FALSE(filter.FilterGestureEvent(&pinch_begin));
- EXPECT_FALSE(filter.FilterGestureEvent(&pinch_update));
- EXPECT_FALSE(filter.FilterGestureEvent(&pinch_end));
- filter.OnSetTouchAction(cc::kTouchActionAuto);
- EXPECT_FALSE(filter.FilterGestureEvent(&pinch_begin));
- EXPECT_FALSE(filter.FilterGestureEvent(&pinch_update));
- EXPECT_FALSE(filter.FilterGestureEvent(&pinch_end));
- EXPECT_FALSE(filter.FilterGestureEvent(&scroll_end));
+ // Pinching is only computed at GestureScrollBegin time.
+ filter.ResetTouchAction();
+ filter.OnSetTouchAction(cc::kTouchActionAuto);
+ EXPECT_FALSE(filter.FilterGestureEvent(&scroll_begin));
+ EXPECT_FALSE(filter.FilterGestureEvent(&pinch_begin));
+ EXPECT_FALSE(filter.FilterGestureEvent(&pinch_update));
+ EXPECT_FALSE(filter.FilterGestureEvent(&pinch_end));
+ filter.OnSetTouchAction(cc::kTouchActionNone);
+ EXPECT_FALSE(filter.FilterGestureEvent(&pinch_begin));
+ EXPECT_FALSE(filter.FilterGestureEvent(&pinch_update));
+ EXPECT_FALSE(filter.FilterGestureEvent(&pinch_end));
+ filter.OnSetTouchAction(cc::kTouchActionAuto);
+ EXPECT_FALSE(filter.FilterGestureEvent(&pinch_begin));
+ EXPECT_FALSE(filter.FilterGestureEvent(&pinch_update));
+ EXPECT_FALSE(filter.FilterGestureEvent(&pinch_end));
+ EXPECT_FALSE(filter.FilterGestureEvent(&scroll_end));
- // Once a pinch has started, any change in state won't affect the pinch
- // gestures since it is computed in GestureScrollBegin.
- filter.ResetTouchAction();
- filter.OnSetTouchAction(cc::kTouchActionAuto);
- EXPECT_FALSE(filter.FilterGestureEvent(&scroll_begin));
- EXPECT_FALSE(filter.FilterGestureEvent(&pinch_begin));
- filter.OnSetTouchAction(cc::kTouchActionNone);
- EXPECT_FALSE(filter.FilterGestureEvent(&pinch_update));
- EXPECT_FALSE(filter.FilterGestureEvent(&pinch_end));
- EXPECT_FALSE(filter.FilterGestureEvent(&pinch_begin));
- EXPECT_FALSE(filter.FilterGestureEvent(&pinch_update));
- EXPECT_FALSE(filter.FilterGestureEvent(&pinch_end));
- EXPECT_FALSE(filter.FilterGestureEvent(&scroll_end));
+ // Once a pinch has started, any change in state won't affect the pinch
+ // gestures since it is computed in GestureScrollBegin.
+ filter.ResetTouchAction();
+ filter.OnSetTouchAction(cc::kTouchActionAuto);
+ EXPECT_FALSE(filter.FilterGestureEvent(&scroll_begin));
+ EXPECT_FALSE(filter.FilterGestureEvent(&pinch_begin));
+ filter.OnSetTouchAction(cc::kTouchActionNone);
+ EXPECT_FALSE(filter.FilterGestureEvent(&pinch_update));
+ EXPECT_FALSE(filter.FilterGestureEvent(&pinch_end));
+ EXPECT_FALSE(filter.FilterGestureEvent(&pinch_begin));
+ EXPECT_FALSE(filter.FilterGestureEvent(&pinch_update));
+ EXPECT_FALSE(filter.FilterGestureEvent(&pinch_end));
+ EXPECT_FALSE(filter.FilterGestureEvent(&scroll_end));
- // Scrolling is allowed when two fingers are down.
- filter.ResetTouchAction();
- filter.OnSetTouchAction(cc::kTouchActionPinchZoom);
- EXPECT_FALSE(filter.FilterGestureEvent(&scroll_begin));
- EXPECT_FALSE(filter.FilterGestureEvent(&pinch_begin));
- EXPECT_FALSE(filter.FilterGestureEvent(&pinch_update));
- EXPECT_FALSE(filter.FilterGestureEvent(&pinch_end));
- EXPECT_FALSE(filter.FilterGestureEvent(&scroll_end));
+ // Scrolling is allowed when two fingers are down.
+ filter.ResetTouchAction();
+ filter.OnSetTouchAction(cc::kTouchActionPinchZoom);
+ EXPECT_FALSE(filter.FilterGestureEvent(&scroll_begin));
+ EXPECT_FALSE(filter.FilterGestureEvent(&pinch_begin));
+ EXPECT_FALSE(filter.FilterGestureEvent(&pinch_update));
+ EXPECT_FALSE(filter.FilterGestureEvent(&pinch_end));
+ EXPECT_FALSE(filter.FilterGestureEvent(&scroll_end));
- // A pinch event sequence with only one pointer is equivalent to a scroll
- // gesture, so disallowed as a pinch gesture.
- scroll_begin.data.scroll_begin.pointer_count = 1;
- filter.ResetTouchAction();
- filter.OnSetTouchAction(cc::kTouchActionPinchZoom);
- EXPECT_TRUE(filter.FilterGestureEvent(&scroll_begin));
- EXPECT_TRUE(filter.FilterGestureEvent(&pinch_begin));
- EXPECT_TRUE(filter.FilterGestureEvent(&pinch_update));
- EXPECT_TRUE(filter.FilterGestureEvent(&pinch_end));
- EXPECT_TRUE(filter.FilterGestureEvent(&scroll_end));
+ // A pinch event sequence with only one pointer is equivalent to a scroll
+ // gesture, so disallowed as a pinch gesture.
+ scroll_begin.data.scroll_begin.pointer_count = 1;
+ filter.ResetTouchAction();
+ filter.OnSetTouchAction(cc::kTouchActionPinchZoom);
+ EXPECT_TRUE(filter.FilterGestureEvent(&scroll_begin));
+ EXPECT_TRUE(filter.FilterGestureEvent(&pinch_begin));
+ EXPECT_TRUE(filter.FilterGestureEvent(&pinch_update));
+ EXPECT_TRUE(filter.FilterGestureEvent(&pinch_end));
+ EXPECT_TRUE(filter.FilterGestureEvent(&scroll_end));
+ }
+};
+
+TEST_F(TouchActionFilterPinchTest, Pinch) {
+ RunTest(false);
+}
+
+// Enables force enable zoom will override touch-action except for
+// touch-action: none.
+TEST_F(TouchActionFilterPinchTest, ForceEnableZoom) {
+ RunTest(true);
}
TEST(TouchActionFilterTest, DoubleTapWithTouchActionAuto) {
diff --git a/chromium/content/browser/renderer_host/input/touch_emulator.cc b/chromium/content/browser/renderer_host/input/touch_emulator.cc
index f0e3f01b960..e564e4e5abf 100644
--- a/chromium/content/browser/renderer_host/input/touch_emulator.cc
+++ b/chromium/content/browser/renderer_host/input/touch_emulator.cc
@@ -33,12 +33,17 @@ namespace content {
namespace {
ui::GestureProvider::Config GetEmulatorGestureProviderConfig(
- ui::GestureProviderConfigType config_type) {
+ ui::GestureProviderConfigType config_type,
+ TouchEmulator::Mode mode) {
ui::GestureProvider::Config config =
ui::GetGestureProviderConfig(config_type);
config.gesture_begin_end_types_enabled = false;
config.gesture_detector_config.swipe_enabled = false;
config.gesture_detector_config.two_finger_tap_enabled = false;
+ if (mode == TouchEmulator::Mode::kInjectingTouchEvents) {
+ config.gesture_detector_config.longpress_timeout = base::TimeDelta::Max();
+ config.gesture_detector_config.showpress_timeout = base::TimeDelta::Max();
+ }
return config;
}
@@ -85,15 +90,23 @@ void TouchEmulator::ResetState() {
pinch_gesture_active_ = false;
}
-void TouchEmulator::Enable(ui::GestureProviderConfigType config_type) {
- if (!gesture_provider_ || gesture_provider_config_type_ != config_type) {
+void TouchEmulator::Enable(Mode mode,
+ ui::GestureProviderConfigType config_type) {
+ if (gesture_provider_ && mode_ != mode)
+ client_->SetCursor(pointer_cursor_);
+
+ if (!gesture_provider_ || gesture_provider_config_type_ != config_type ||
+ mode_ != mode) {
+ mode_ = mode;
gesture_provider_config_type_ = config_type;
gesture_provider_.reset(new ui::FilteredGestureProvider(
- GetEmulatorGestureProviderConfig(config_type), this));
- // TODO(dgozman): Use synthetic secondary touch to support multi-touch.
- gesture_provider_->SetMultiTouchZoomSupportEnabled(false);
+ GetEmulatorGestureProviderConfig(config_type, mode), this));
gesture_provider_->SetDoubleTapSupportForPageEnabled(double_tap_enabled_);
+ // TODO(dgozman): Use synthetic secondary touch to support multi-touch.
+ gesture_provider_->SetMultiTouchZoomSupportEnabled(
+ mode != Mode::kEmulatingTouchFromMouse);
}
+
UpdateCursor();
}
@@ -101,9 +114,12 @@ void TouchEmulator::Disable() {
if (!enabled())
return;
+ mode_ = Mode::kEmulatingTouchFromMouse;
CancelTouch();
gesture_provider_.reset();
- UpdateCursor();
+ std::queue<base::OnceClosure> empty;
+ injected_touch_completion_callbacks_.swap(empty);
+ client_->SetCursor(pointer_cursor_);
ResetState();
}
@@ -157,7 +173,7 @@ gfx::SizeF TouchEmulator::InitCursorFromResource(
}
bool TouchEmulator::HandleMouseEvent(const WebMouseEvent& mouse_event) {
- if (!enabled())
+ if (!enabled() || mode_ != Mode::kEmulatingTouchFromMouse)
return false;
if (mouse_event.button == WebMouseEvent::Button::kRight &&
@@ -205,7 +221,7 @@ bool TouchEmulator::HandleMouseEvent(const WebMouseEvent& mouse_event) {
}
bool TouchEmulator::HandleMouseWheelEvent(const WebMouseWheelEvent& event) {
- if (!enabled())
+ if (!enabled() || mode_ != Mode::kEmulatingTouchFromMouse)
return false;
// Send mouse wheel for easy scrolling when there is no active touch.
@@ -213,7 +229,7 @@ bool TouchEmulator::HandleMouseWheelEvent(const WebMouseWheelEvent& event) {
}
bool TouchEmulator::HandleKeyboardEvent(const WebKeyboardEvent& event) {
- if (!enabled())
+ if (!enabled() || mode_ != Mode::kEmulatingTouchFromMouse)
return false;
if (!UpdateShiftPressed((event.GetModifiers() & WebInputEvent::kShiftKey) !=
@@ -251,12 +267,12 @@ bool TouchEmulator::HandleTouchEvent(const blink::WebTouchEvent& event) {
return false;
}
-void TouchEmulator::HandleEmulatedTouchEvent(blink::WebTouchEvent event) {
+bool TouchEmulator::HandleEmulatedTouchEvent(blink::WebTouchEvent event) {
DCHECK(gesture_provider_);
event.unique_touch_event_id = ui::GetNextTouchEventId();
auto result = gesture_provider_->OnTouchEvent(MotionEventWeb(event));
if (!result.succeeded)
- return;
+ return true;
const bool event_consumed = true;
const bool is_source_touch_event_set_non_blocking = false;
@@ -265,7 +281,7 @@ void TouchEmulator::HandleEmulatedTouchEvent(blink::WebTouchEvent event) {
gesture_provider_->OnTouchEventAck(event.unique_touch_event_id,
event_consumed,
is_source_touch_event_set_non_blocking);
- return;
+ return true;
}
bool is_sequence_start = WebTouchEventTraits::IsTouchSequenceStart(event);
@@ -274,7 +290,7 @@ void TouchEmulator::HandleEmulatedTouchEvent(blink::WebTouchEvent event) {
gesture_provider_->OnTouchEventAck(event.unique_touch_event_id,
event_consumed,
is_source_touch_event_set_non_blocking);
- return;
+ return true;
}
if (is_sequence_start)
@@ -282,6 +298,7 @@ void TouchEmulator::HandleEmulatedTouchEvent(blink::WebTouchEvent event) {
event.moved_beyond_slop_region = result.moved_beyond_slop_region;
client_->ForwardEmulatedTouchEvent(event);
+ return false;
}
bool TouchEmulator::HandleTouchEventAck(
@@ -292,10 +309,12 @@ bool TouchEmulator::HandleTouchEventAck(
emulated_stream_active_sequence_count_--;
const bool event_consumed = ack_result == INPUT_EVENT_ACK_STATE_CONSUMED;
- if (gesture_provider_)
+ if (gesture_provider_) {
gesture_provider_->OnTouchEventAck(
event.unique_touch_event_id, event_consumed,
InputEventAckStateIsSetNonBlocking(ack_result));
+ }
+ OnInjectedTouchCompleted();
return true;
}
@@ -372,9 +391,28 @@ void TouchEmulator::OnGestureEvent(const ui::GestureEventData& gesture) {
}
}
+void TouchEmulator::InjectTouchEvent(const blink::WebTouchEvent& event,
+ base::OnceClosure callback) {
+ DCHECK(enabled() && mode_ == Mode::kInjectingTouchEvents);
+ touch_event_ = event;
+ injected_touch_completion_callbacks_.push(std::move(callback));
+ if (HandleEmulatedTouchEvent(touch_event_))
+ OnInjectedTouchCompleted();
+}
+
+void TouchEmulator::OnInjectedTouchCompleted() {
+ if (injected_touch_completion_callbacks_.empty())
+ return;
+ if (!injected_touch_completion_callbacks_.front().is_null())
+ std::move(injected_touch_completion_callbacks_.front()).Run();
+ injected_touch_completion_callbacks_.pop();
+}
+
void TouchEmulator::CancelTouch() {
- if (!emulated_stream_active_sequence_count_ || !enabled())
+ if (!emulated_stream_active_sequence_count_ || !enabled() ||
+ mode_ != Mode::kEmulatingTouchFromMouse) {
return;
+ }
WebTouchEventTraits::ResetTypeAndTouchStates(
WebInputEvent::kTouchCancel,
@@ -385,13 +423,13 @@ void TouchEmulator::CancelTouch() {
}
void TouchEmulator::UpdateCursor() {
- if (!enabled())
- client_->SetCursor(pointer_cursor_);
- else
+ DCHECK(enabled());
+ if (mode_ == Mode::kEmulatingTouchFromMouse)
client_->SetCursor(InPinchGestureMode() ? pinch_cursor_ : touch_cursor_);
}
bool TouchEmulator::UpdateShiftPressed(bool shift_pressed) {
+ DCHECK(enabled() && mode_ == Mode::kEmulatingTouchFromMouse);
if (shift_pressed_ == shift_pressed)
return false;
shift_pressed_ = shift_pressed;
diff --git a/chromium/content/browser/renderer_host/input/touch_emulator.h b/chromium/content/browser/renderer_host/input/touch_emulator.h
index 8e8a976c260..3bed9e730eb 100644
--- a/chromium/content/browser/renderer_host/input/touch_emulator.h
+++ b/chromium/content/browser/renderer_host/input/touch_emulator.h
@@ -6,7 +6,9 @@
#define CONTENT_BROWSER_RENDERER_HOST_INPUT_TOUCH_EMULATOR_H_
#include <memory>
+#include <queue>
+#include "base/callback.h"
#include "base/macros.h"
#include "content/browser/renderer_host/input/touch_emulator_client.h"
#include "content/common/cursors/webcursor.h"
@@ -24,13 +26,22 @@ class WebMouseWheelEvent;
namespace content {
-// Emulates touch input with mouse and keyboard.
+// Emulates touch input. See TouchEmulator::Mode for more details.
class CONTENT_EXPORT TouchEmulator : public ui::GestureProviderClient {
public:
+ enum class Mode {
+ // Emulator will consume incoming mouse events and transform them
+ // into touches and gestures.
+ kEmulatingTouchFromMouse,
+ // Emulator will not consume incoming mouse events and instead will
+ // wait for manually injected touch events.
+ kInjectingTouchEvents
+ };
+
TouchEmulator(TouchEmulatorClient* client, float device_scale_factor);
~TouchEmulator() override;
- void Enable(ui::GestureProviderConfigType config_type);
+ void Enable(Mode mode, ui::GestureProviderConfigType config_type);
void Disable();
// Call when device scale factor changes.
@@ -56,6 +67,11 @@ class CONTENT_EXPORT TouchEmulator : public ui::GestureProviderClient {
bool HandleTouchEventAck(const blink::WebTouchEvent& event,
InputEventAckState ack_result);
+ // Injects a touch event to be processed for gestures and optionally
+ // forwarded to the client. Only works in kInjectingTouchEvents mode.
+ void InjectTouchEvent(const blink::WebTouchEvent& event,
+ base::OnceClosure completion_callback);
+
// Cancel any touches, for example, when focus is lost.
void CancelTouch();
@@ -86,8 +102,12 @@ class CONTENT_EXPORT TouchEmulator : public ui::GestureProviderClient {
void ScrollEnd(const blink::WebGestureEvent& event);
// Offers the emulated event to |gesture_provider_|, conditionally forwarding
- // it to the client if appropriate.
- void HandleEmulatedTouchEvent(blink::WebTouchEvent event);
+ // it to the client if appropriate. Returns whether event was handled
+ // synchronously, and there will be no ack.
+ bool HandleEmulatedTouchEvent(blink::WebTouchEvent event);
+
+ // Called when ack for injected touch has been received.
+ void OnInjectedTouchCompleted();
TouchEmulatorClient* const client_;
@@ -96,6 +116,7 @@ class CONTENT_EXPORT TouchEmulator : public ui::GestureProviderClient {
// emulation. It does not intercept any events.
std::unique_ptr<ui::FilteredGestureProvider> gesture_provider_;
ui::GestureProviderConfigType gesture_provider_config_type_;
+ Mode mode_;
bool double_tap_enabled_;
bool use_2x_cursors_;
@@ -128,6 +149,8 @@ class CONTENT_EXPORT TouchEmulator : public ui::GestureProviderClient {
float pinch_scale_;
bool pinch_gesture_active_;
+ std::queue<base::OnceClosure> injected_touch_completion_callbacks_;
+
DISALLOW_COPY_AND_ASSIGN(TouchEmulator);
};
diff --git a/chromium/content/browser/renderer_host/input/touch_emulator_unittest.cc b/chromium/content/browser/renderer_host/input/touch_emulator_unittest.cc
index 139d5a66d08..03f5a2470c2 100644
--- a/chromium/content/browser/renderer_host/input/touch_emulator_unittest.cc
+++ b/chromium/content/browser/renderer_host/input/touch_emulator_unittest.cc
@@ -50,7 +50,8 @@ class TouchEmulatorTest : public testing::Test,
void SetUp() override {
emulator_.reset(new TouchEmulator(this, 1.0f));
emulator_->SetDoubleTapSupportForPageEnabled(false);
- emulator_->Enable(ui::GestureProviderConfigType::GENERIC_MOBILE);
+ emulator_->Enable(TouchEmulator::Mode::kEmulatingTouchFromMouse,
+ ui::GestureProviderConfigType::GENERIC_MOBILE);
}
void TearDown() override {
@@ -229,6 +230,16 @@ class TouchEmulatorTest : public testing::Test,
return true;
}
+ void InjectTouchEvent(WebInputEvent::Type type,
+ WebTouchPoint::State state,
+ int x,
+ int y) {
+ last_mouse_x_ = x;
+ last_mouse_y_ = y;
+ WebTouchEvent event = MakeTouchEvent(type, state, x, y);
+ emulator()->InjectTouchEvent(event, base::OnceClosure());
+ }
+
void AckOldestTouchEvent() {
DCHECK(touch_events_to_ack_.size());
WebTouchEvent event = touch_events_to_ack_[0];
@@ -385,7 +396,8 @@ TEST_F(TouchEmulatorTest, DisableAndReenable) {
MouseMove(300, 300);
EXPECT_EQ("", ExpectedEvents());
- emulator()->Enable(ui::GestureProviderConfigType::GENERIC_MOBILE);
+ emulator()->Enable(TouchEmulator::Mode::kEmulatingTouchFromMouse,
+ ui::GestureProviderConfigType::GENERIC_MOBILE);
MouseDown(300, 300);
EXPECT_EQ("TouchStart GestureTapDown", ExpectedEvents());
MouseDrag(300, 400);
@@ -417,7 +429,8 @@ TEST_F(TouchEmulatorTest, DisableAndReenableDifferentConfig) {
MouseMove(300, 300);
EXPECT_EQ("", ExpectedEvents());
- emulator()->Enable(ui::GestureProviderConfigType::GENERIC_DESKTOP);
+ emulator()->Enable(TouchEmulator::Mode::kEmulatingTouchFromMouse,
+ ui::GestureProviderConfigType::GENERIC_DESKTOP);
MouseDown(300, 300);
EXPECT_EQ("TouchStart GestureTapDown", ExpectedEvents());
MouseDrag(300, 400);
@@ -477,7 +490,8 @@ TEST_F(TouchEmulatorTest, MouseWheel) {
emulator()->Disable();
EXPECT_EQ("TouchCancel GestureTapCancel", ExpectedEvents());
EXPECT_TRUE(SendMouseWheelEvent());
- emulator()->Enable(ui::GestureProviderConfigType::GENERIC_MOBILE);
+ emulator()->Enable(TouchEmulator::Mode::kEmulatingTouchFromMouse,
+ ui::GestureProviderConfigType::GENERIC_MOBILE);
EXPECT_TRUE(SendMouseWheelEvent());
}
@@ -503,7 +517,8 @@ TEST_F(TouchEmulatorTest, MultipleTouchStreams) {
EXPECT_EQ("", ExpectedEvents());
// Re-enabling in the middle of a touch sequence should not affect this.
emulator()->Disable();
- emulator()->Enable(ui::GestureProviderConfigType::GENERIC_MOBILE);
+ emulator()->Enable(TouchEmulator::Mode::kEmulatingTouchFromMouse,
+ ui::GestureProviderConfigType::GENERIC_MOBILE);
MouseDrag(300, 300);
EXPECT_EQ("", ExpectedEvents());
MouseUp(300, 300);
@@ -518,7 +533,8 @@ TEST_F(TouchEmulatorTest, MultipleTouchStreams) {
EXPECT_TRUE(TouchEnd(20, 20, false));
EXPECT_TRUE(TouchStart(30, 30, false));
AckOldestTouchEvent(); // TouchStart.
- emulator()->Enable(ui::GestureProviderConfigType::GENERIC_MOBILE);
+ emulator()->Enable(TouchEmulator::Mode::kEmulatingTouchFromMouse,
+ ui::GestureProviderConfigType::GENERIC_MOBILE);
AckOldestTouchEvent(); // TouchMove.
AckOldestTouchEvent(); // TouchEnd.
MouseDown(300, 200);
@@ -585,15 +601,32 @@ TEST_F(TouchEmulatorTest, CursorScaleFactor) {
EXPECT_EQ(1.0f, GetCursorScaleFactor());
emulator()->SetDeviceScaleFactor(3.0f);
EXPECT_EQ(1.0f, GetCursorScaleFactor());
- emulator()->Enable(ui::GestureProviderConfigType::GENERIC_MOBILE);
+ emulator()->Enable(TouchEmulator::Mode::kEmulatingTouchFromMouse,
+ ui::GestureProviderConfigType::GENERIC_MOBILE);
EXPECT_EQ(2.0f, GetCursorScaleFactor());
emulator()->SetDeviceScaleFactor(1.0f);
EXPECT_EQ(1.0f, GetCursorScaleFactor());
TouchEmulator another(this, 4.0f);
EXPECT_EQ(1.0f, GetCursorScaleFactor());
- another.Enable(ui::GestureProviderConfigType::GENERIC_MOBILE);
+ another.Enable(TouchEmulator::Mode::kEmulatingTouchFromMouse,
+ ui::GestureProviderConfigType::GENERIC_MOBILE);
EXPECT_EQ(2.0f, GetCursorScaleFactor());
}
+TEST_F(TouchEmulatorTest, InjectingTouchEventsMode) {
+ emulator()->Enable(TouchEmulator::Mode::kInjectingTouchEvents,
+ ui::GestureProviderConfigType::GENERIC_MOBILE);
+ InjectTouchEvent(WebInputEvent::kTouchStart, WebTouchPoint::kStatePressed,
+ 100, 200);
+ EXPECT_EQ("TouchStart GestureTapDown", ExpectedEvents());
+ InjectTouchEvent(WebInputEvent::kTouchMove, WebTouchPoint::kStateMoved, 200,
+ 200);
+ EXPECT_EQ("TouchMove GestureTapCancel GestureScrollBegin GestureScrollUpdate",
+ ExpectedEvents());
+ InjectTouchEvent(WebInputEvent::kTouchEnd, WebTouchPoint::kStateReleased, 200,
+ 200);
+ EXPECT_EQ("TouchEnd GestureScrollEnd", ExpectedEvents());
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/touch_selection_controller_client_aura.cc b/chromium/content/browser/renderer_host/input/touch_selection_controller_client_aura.cc
index 19cc95df2bf..1a213a88391 100644
--- a/chromium/content/browser/renderer_host/input/touch_selection_controller_client_aura.cc
+++ b/chromium/content/browser/renderer_host/input/touch_selection_controller_client_aura.cc
@@ -93,6 +93,17 @@ void TouchSelectionControllerClientAura::EnvPreTargetHandler::OnMouseEvent(
DCHECK_NE(ui::TouchSelectionController::INACTIVE,
selection_controller_->active_status());
+ // Avoid adjusting the handles on synthesized or events
+ // generated from touch as this can clear an active selection
+ // generated by the pen.
+ if (event->flags() & (ui::EF_IS_SYNTHESIZED | ui::EF_FROM_TOUCH))
+ return;
+
+ // Don't hide handles for pen input.
+ if (event->pointer_details().pointer_type ==
+ ui::EventPointerType::POINTER_TYPE_PEN)
+ return;
+
// If mouse events are not enabled, this mouse event is synthesized from a
// touch event in which case we don't want to deactivate touch selection.
aura::client::CursorClient* cursor_client =
@@ -180,6 +191,10 @@ bool TouchSelectionControllerClientAura::HandleContextMenu(
return false;
}
+void TouchSelectionControllerClientAura::DidStopFlinging() {
+ OnScrollCompleted();
+}
+
void TouchSelectionControllerClientAura::UpdateClientSelectionBounds(
const gfx::SelectionBound& start,
const gfx::SelectionBound& end) {
diff --git a/chromium/content/browser/renderer_host/input/touch_selection_controller_client_aura.h b/chromium/content/browser/renderer_host/input/touch_selection_controller_client_aura.h
index 69b11118f27..700ed1c1371 100644
--- a/chromium/content/browser/renderer_host/input/touch_selection_controller_client_aura.h
+++ b/chromium/content/browser/renderer_host/input/touch_selection_controller_client_aura.h
@@ -55,6 +55,7 @@ class CONTENT_EXPORT TouchSelectionControllerClientAura
const gfx::SelectionBound& end);
// TouchSelectionControllerClientManager.
+ void DidStopFlinging() override;
void UpdateClientSelectionBounds(
const gfx::SelectionBound& start,
const gfx::SelectionBound& end,
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 2753ce12ff6..4dacb673768 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
@@ -10,8 +10,8 @@
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
#include "base/test/test_timeouts.h"
-#include "content/browser/frame_host/render_widget_host_view_child_frame.h"
#include "content/browser/renderer_host/render_widget_host_view_aura.h"
+#include "content/browser/renderer_host/render_widget_host_view_child_frame.h"
#include "content/browser/renderer_host/render_widget_host_view_event_handler.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/overscroll_configuration.h"
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 6d4902908af..884a3c0f265 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
@@ -4,9 +4,9 @@
#include "content/browser/renderer_host/input/touch_selection_controller_client_child_frame.h"
-#include "content/browser/frame_host/render_widget_host_view_child_frame.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_view_child_frame.h"
#include "content/common/content_switches_internal.h"
#include "content/common/view_messages.h"
#include "content/public/browser/touch_selection_controller_client_manager.h"
@@ -31,6 +31,10 @@ TouchSelectionControllerClientChildFrame::
manager_->InvalidateClient(this);
}
+void TouchSelectionControllerClientChildFrame::DidStopFlinging() {
+ manager_->DidStopFlinging();
+}
+
void TouchSelectionControllerClientChildFrame::UpdateSelectionBoundsIfNeeded(
const cc::Selection<gfx::SelectionBound>& selection,
float device_scale_factor) {
diff --git a/chromium/content/browser/renderer_host/input/touch_selection_controller_client_child_frame.h b/chromium/content/browser/renderer_host/input/touch_selection_controller_client_child_frame.h
index 4f8137ee6bc..9a9af9662b9 100644
--- a/chromium/content/browser/renderer_host/input/touch_selection_controller_client_child_frame.h
+++ b/chromium/content/browser/renderer_host/input/touch_selection_controller_client_child_frame.h
@@ -31,6 +31,7 @@ class CONTENT_EXPORT TouchSelectionControllerClientChildFrame
TouchSelectionControllerClientManager* manager);
~TouchSelectionControllerClientChildFrame() override;
+ void DidStopFlinging();
void UpdateSelectionBoundsIfNeeded(
const cc::Selection<gfx::SelectionBound>& selection,
float device_scale_factor);
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 c2b32519b52..de89adaf9d0 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
@@ -43,6 +43,10 @@ gfx::SelectionBound ScaleSelectionBound(const gfx::SelectionBound& bound,
} // namespace
// TouchSelectionControllerClientManager implementation.
+void TouchSelectionControllerClientManagerAndroid::DidStopFlinging() {
+ // TODO(wjmaclean): determine what, if anything, needs to happen here.
+}
+
void TouchSelectionControllerClientManagerAndroid::UpdateClientSelectionBounds(
const gfx::SelectionBound& start,
const gfx::SelectionBound& end,
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 ff406582c7f..27349a8887b 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
@@ -25,6 +25,7 @@ class TouchSelectionControllerClientManagerAndroid
float page_scale_factor() { return page_scale_factor_; }
// TouchSelectionControllerClientManager implementation.
+ void DidStopFlinging() override;
void UpdateClientSelectionBounds(
const gfx::SelectionBound& start,
const gfx::SelectionBound& end,
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 5434a6031a5..2b619cc0a7e 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
@@ -379,6 +379,35 @@ TEST(WebInputEventBuilderMacTest, USDvorakAlnumNSEventToKeyCode) {
}
}
+// 'Dvorak - QWERTY Command' layout will map the key back to QWERTY when Command
+// is pressed.
+// e.g. Key 'b' maps to 'x' but 'Command-b' remains 'Command-b'.
+TEST(WebInputEventBuilderMacTest, USDvorakQWERTYCommand) {
+ struct DomKeyTestCase {
+ int mac_key_code;
+ unichar cmd_character;
+ } table[] = {{kVK_ANSI_0, '0'}, {kVK_ANSI_1, '1'}, {kVK_ANSI_2, '2'},
+ {kVK_ANSI_3, '3'}, {kVK_ANSI_4, '4'}, {kVK_ANSI_5, '5'},
+ {kVK_ANSI_6, '6'}, {kVK_ANSI_7, '7'}, {kVK_ANSI_8, '8'},
+ {kVK_ANSI_9, '9'}, {kVK_ANSI_A, 'a'}, {kVK_ANSI_B, 'b'},
+ {kVK_ANSI_C, 'c'}, {kVK_ANSI_D, 'd'}, {kVK_ANSI_E, 'e'},
+ {kVK_ANSI_F, 'f'}, {kVK_ANSI_G, 'g'}, {kVK_ANSI_H, 'h'},
+ {kVK_ANSI_I, 'i'}, {kVK_ANSI_J, 'j'}, {kVK_ANSI_K, 'k'},
+ {kVK_ANSI_L, 'l'}, {kVK_ANSI_M, 'm'}, {kVK_ANSI_N, 'n'},
+ {kVK_ANSI_O, 'o'}, {kVK_ANSI_P, 'p'}, {kVK_ANSI_Q, 'q'},
+ {kVK_ANSI_R, 'r'}, {kVK_ANSI_S, 's'}, {kVK_ANSI_T, 't'},
+ {kVK_ANSI_U, 'u'}, {kVK_ANSI_V, 'v'}, {kVK_ANSI_W, 'w'},
+ {kVK_ANSI_X, 'x'}, {kVK_ANSI_Y, 'y'}, {kVK_ANSI_Z, 'z'}};
+
+ for (const DomKeyTestCase& entry : table) {
+ NSEvent* mac_event = BuildFakeKeyEvent(
+ entry.mac_key_code, entry.cmd_character, NSCommandKeyMask, NSKeyDown);
+ WebKeyboardEvent web_event = WebKeyboardEventBuilder::Build(mac_event);
+ EXPECT_EQ(ui::DomKey::FromCharacter(entry.cmd_character),
+ web_event.dom_key);
+ }
+}
+
// Test conversion from key combination with Control to DomKey.
// TODO(chongz): Move DomKey tests for all platforms into one place.
// http://crbug.com/587589
diff --git a/chromium/content/browser/renderer_host/input/wheel_scroll_latching_browsertest.cc b/chromium/content/browser/renderer_host/input/wheel_scroll_latching_browsertest.cc
index b19d544363b..69797f51ed0 100644
--- a/chromium/content/browser/renderer_host/input/wheel_scroll_latching_browsertest.cc
+++ b/chromium/content/browser/renderer_host/input/wheel_scroll_latching_browsertest.cc
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "base/run_loop.h"
#include "base/test/scoped_feature_list.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_input_event_router.h"
@@ -231,4 +232,4 @@ IN_PROC_BROWSER_TEST_F(WheelScrollLatchingDisabledBrowserTest,
WheelEventTargetTest();
}
-} // namespace content \ No newline at end of file
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/legacy_render_widget_host_win.cc b/chromium/content/browser/renderer_host/legacy_render_widget_host_win.cc
index 91c4d4f4ebf..74d9147cf66 100644
--- a/chromium/content/browser/renderer_host/legacy_render_widget_host_win.cc
+++ b/chromium/content/browser/renderer_host/legacy_render_widget_host_win.cc
@@ -128,9 +128,9 @@ bool LegacyRenderWidgetHostHWND::Init() {
IID_PPV_ARGS(&window_accessible_));
DCHECK(SUCCEEDED(hr));
- AccessibilityMode mode =
+ ui::AXMode mode =
BrowserAccessibilityStateImpl::GetInstance()->accessibility_mode();
- if (!mode.has_mode(AccessibilityMode::kNativeAPIs)) {
+ if (!mode.has_mode(ui::AXMode::kNativeAPIs)) {
// Attempt to detect screen readers or other clients who want full
// accessibility support, by seeing if they respond to this event.
NotifyWinEvent(EVENT_SYSTEM_ALERT, hwnd(), kIdScreenReaderHoneyPot,
@@ -175,7 +175,7 @@ LRESULT LegacyRenderWidgetHostHWND::OnGetObject(UINT message,
// enable basic accessibility support. (Full screen reader support is
// detected later when specific more advanced APIs are accessed.)
BrowserAccessibilityStateImpl::GetInstance()->AddAccessibilityModeFlags(
- AccessibilityMode::kNativeAPIs | AccessibilityMode::kWebContents);
+ ui::AXMode::kNativeAPIs | ui::AXMode::kWebContents);
return static_cast<LRESULT>(0L);
}
diff --git a/chromium/content/browser/renderer_host/legacy_render_widget_host_win.h b/chromium/content/browser/renderer_host/legacy_render_widget_host_win.h
index b89060ed802..8cb8b832e31 100644
--- a/chromium/content/browser/renderer_host/legacy_render_widget_host_win.h
+++ b/chromium/content/browser/renderer_host/legacy_render_widget_host_win.h
@@ -56,14 +56,15 @@ class RenderWidgetHostViewAura;
// HWND instead of the DesktopWindowTreeHostWin.
class CONTENT_EXPORT LegacyRenderWidgetHostHWND
: public ATL::CWindowImpl<LegacyRenderWidgetHostHWND,
- NON_EXPORTED_BASE(ATL::CWindow),
- ATL::CWinTraits<WS_CHILD> > {
+ ATL::CWindow,
+ ATL::CWinTraits<WS_CHILD>> {
public:
DECLARE_WND_CLASS_EX(L"Chrome_RenderWidgetHostHWND", CS_DBLCLKS, 0);
typedef ATL::CWindowImpl<LegacyRenderWidgetHostHWND,
- NON_EXPORTED_BASE(ATL::CWindow),
- ATL::CWinTraits<WS_CHILD> > Base;
+ ATL::CWindow,
+ ATL::CWinTraits<WS_CHILD>>
+ Base;
// Creates and returns an instance of the LegacyRenderWidgetHostHWND class on
// successful creation of a child window parented to the parent window passed
diff --git a/chromium/content/browser/renderer_host/media/OWNERS b/chromium/content/browser/renderer_host/media/OWNERS
index 2840890798b..68a9bdcf515 100644
--- a/chromium/content/browser/renderer_host/media/OWNERS
+++ b/chromium/content/browser/renderer_host/media/OWNERS
@@ -4,6 +4,8 @@ file://media/OWNERS
emircan@chromium.org
guidou@chromium.org
tommi@chromium.org
+olka@chromium.org
+maxmorin@chromium.org
per-file *video*=mcasas@chromium.org
per-file *video*=chfremer@chromium.org
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 876e1138d5d..7e765dac40f 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
@@ -8,6 +8,7 @@
#include <utility>
#include "base/bind.h"
+#include "base/callback.h"
#include "base/command_line.h"
#include "base/metrics/histogram_macros.h"
#include "build/build_config.h"
@@ -28,9 +29,18 @@ namespace content {
const int AudioInputDeviceManager::kFakeOpenSessionId = 1;
namespace {
+
// Starting id for the first capture session.
const int kFirstSessionId = AudioInputDeviceManager::kFakeOpenSessionId + 1;
+
+#if defined(OS_CHROMEOS)
+void SetKeyboardMicStreamActiveOnUIThread(bool active) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ chromeos::CrasAudioHandler::Get()->SetKeyboardMicActive(active);
}
+#endif
+
+} // namespace
AudioInputDeviceManager::AudioInputDeviceManager(
media::AudioSystem* audio_system)
@@ -123,34 +133,67 @@ void AudioInputDeviceManager::Close(int session_id) {
}
#if defined(OS_CHROMEOS)
-void AudioInputDeviceManager::RegisterKeyboardMicStream(
- base::OnceClosure callback) {
+AudioInputDeviceManager::KeyboardMicRegistration::KeyboardMicRegistration()
+ : shared_registration_count_(nullptr) {}
+
+AudioInputDeviceManager::KeyboardMicRegistration::KeyboardMicRegistration(
+ KeyboardMicRegistration&& other)
+ : shared_registration_count_(other.shared_registration_count_) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ other.shared_registration_count_ = nullptr;
+}
+
+AudioInputDeviceManager::KeyboardMicRegistration&
+AudioInputDeviceManager::KeyboardMicRegistration::operator=(
+ KeyboardMicRegistration&& other) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DeregisterIfNeeded();
+ shared_registration_count_ = other.shared_registration_count_;
+ return *this;
+}
- ++keyboard_mic_streams_count_;
- if (keyboard_mic_streams_count_ == 1) {
- BrowserThread::PostTaskAndReply(
- BrowserThread::UI, FROM_HERE,
- base::BindOnce(
- &AudioInputDeviceManager::SetKeyboardMicStreamActiveOnUIThread,
- this, true),
- std::move(callback));
- } else {
- std::move(callback).Run();
+AudioInputDeviceManager::KeyboardMicRegistration::~KeyboardMicRegistration() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DeregisterIfNeeded();
+}
+
+AudioInputDeviceManager::KeyboardMicRegistration::KeyboardMicRegistration(
+ int* shared_registration_count)
+ : shared_registration_count_(shared_registration_count) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+}
+
+void AudioInputDeviceManager::KeyboardMicRegistration::DeregisterIfNeeded() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ if (shared_registration_count_) {
+ --*shared_registration_count_;
+ DCHECK_GE(*shared_registration_count_, 0);
+ if (*shared_registration_count_ == 0) {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&SetKeyboardMicStreamActiveOnUIThread, false));
+ }
}
+
+ // Since we removed our registration, we unset the counter pointer to
+ // indicate this.
+ shared_registration_count_ = nullptr;
}
-void AudioInputDeviceManager::UnregisterKeyboardMicStream() {
+void AudioInputDeviceManager::RegisterKeyboardMicStream(
+ base::OnceCallback<void(KeyboardMicRegistration)> callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- --keyboard_mic_streams_count_;
- DCHECK_GE(keyboard_mic_streams_count_, 0);
- if (keyboard_mic_streams_count_ == 0) {
- BrowserThread::PostTask(
+ ++keyboard_mic_streams_count_;
+ if (keyboard_mic_streams_count_ == 1) {
+ BrowserThread::PostTaskAndReply(
BrowserThread::UI, FROM_HERE,
- base::BindOnce(
- &AudioInputDeviceManager::SetKeyboardMicStreamActiveOnUIThread,
- this, false));
+ base::BindOnce(&SetKeyboardMicStreamActiveOnUIThread, true),
+ base::BindOnce(std::move(callback),
+ KeyboardMicRegistration(&keyboard_mic_streams_count_)));
+ } else {
+ std::move(callback).Run(
+ KeyboardMicRegistration(&keyboard_mic_streams_count_));
}
}
#endif
@@ -168,25 +211,16 @@ void AudioInputDeviceManager::OpenedOnIOThread(
UMA_HISTOGRAM_TIMES("Media.AudioInputDeviceManager.OpenOnDeviceThreadTime",
base::TimeTicks::Now() - start_time);
- media::AudioParameters valid_input_params =
- input_params.IsValid()
- ? input_params
- : media::AudioParameters::UnavailableDeviceParams();
-
StreamDeviceInfo info(device.type, device.name, device.id);
info.session_id = session_id;
- info.device.input.sample_rate = valid_input_params.sample_rate();
- info.device.input.channel_layout = valid_input_params.channel_layout();
- info.device.input.frames_per_buffer = valid_input_params.frames_per_buffer();
- info.device.input.effects = valid_input_params.effects();
- info.device.input.mic_positions = valid_input_params.mic_positions();
+ info.device.input = input_params.IsValid()
+ ? input_params
+ : media::AudioParameters::UnavailableDeviceParams();
info.device.matched_output_device_id = matched_output_device_id;
- info.device.matched_output.sample_rate = matched_output_params.sample_rate();
- info.device.matched_output.channel_layout =
- matched_output_params.channel_layout();
- info.device.matched_output.frames_per_buffer =
- matched_output_params.frames_per_buffer();
- info.device.matched_output.effects = matched_output_params.effects();
+ info.device.matched_output =
+ matched_output_params.IsValid()
+ ? matched_output_params
+ : media::AudioParameters::UnavailableDeviceParams();
devices_.push_back(info);
@@ -213,12 +247,4 @@ AudioInputDeviceManager::GetDevice(int session_id) {
return devices_.end();
}
-#if defined(OS_CHROMEOS)
-void AudioInputDeviceManager::SetKeyboardMicStreamActiveOnUIThread(
- bool active) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- chromeos::CrasAudioHandler::Get()->SetKeyboardMicActive(active);
-}
-#endif
-
} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/audio_input_device_manager.h b/chromium/content/browser/renderer_host/media/audio_input_device_manager.h
index a2923c9b287..85bf2b789fe 100644
--- a/chromium/content/browser/renderer_host/media/audio_input_device_manager.h
+++ b/chromium/content/browser/renderer_host/media/audio_input_device_manager.h
@@ -54,13 +54,40 @@ class CONTENT_EXPORT AudioInputDeviceManager : public MediaStreamProvider {
void Close(int session_id) override;
#if defined(OS_CHROMEOS)
- // Registers and unregisters that a stream using keyboard mic has been opened
- // or closed. Keeps count of how many such streams are open and activates and
+ // Owns a keyboard mic stream registration.
+ class KeyboardMicRegistration {
+ public:
+ // No registration.
+ KeyboardMicRegistration();
+
+ KeyboardMicRegistration(KeyboardMicRegistration&& other);
+ KeyboardMicRegistration& operator=(KeyboardMicRegistration&& other);
+
+ ~KeyboardMicRegistration();
+
+ private:
+ friend class AudioInputDeviceManager;
+
+ explicit KeyboardMicRegistration(int* shared_registration_count);
+
+ void DeregisterIfNeeded();
+
+ // Null to indicate that there is no stream registration. This points to
+ // a member of the AudioInputDeviceManager, which lives as long as the IO
+ // thread, so the pointer will be valid for the lifetime of the
+ // registration.
+ int* shared_registration_count_;
+ };
+
+ // Registers that a stream using keyboard mic has been opened or closed.
+ // Keeps count of how many such streams are open and activates and
// inactivates the keyboard mic accordingly. The (in)activation is done on the
- // UI thread and for the register case a callback must therefor be provided
- // which is called when activated.
- void RegisterKeyboardMicStream(base::OnceClosure callback);
- void UnregisterKeyboardMicStream();
+ // UI thread and for the register case a callback must therefore be provided
+ // which is called when activated. Deregistration is done when the
+ // registration object is destructed or assigned to, which should only be
+ // done on the IO thread.
+ void RegisterKeyboardMicStream(
+ base::OnceCallback<void(KeyboardMicRegistration)> callback);
#endif
private:
@@ -83,11 +110,6 @@ class CONTENT_EXPORT AudioInputDeviceManager : public MediaStreamProvider {
// device is found, it will return devices_.end().
StreamDeviceList::iterator GetDevice(int session_id);
-#if defined(OS_CHROMEOS)
- // Calls Cras audio handler and sets keyboard mic active status.
- void SetKeyboardMicStreamActiveOnUIThread(bool active);
-#endif
-
// Only accessed on Browser::IO thread.
base::ObserverList<MediaStreamProviderListener> listeners_;
int next_capture_session_id_;
diff --git a/chromium/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc b/chromium/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc
index cfb976b0ee7..e23191fcfff 100644
--- a/chromium/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc
@@ -101,7 +101,7 @@ class MAYBE_AudioInputDeviceManagerTest : public testing::Test {
void WaitForOpenCompletion() {
media::WaitableMessageLoopEvent event;
audio_manager_->GetTaskRunner()->PostTaskAndReply(
- FROM_HERE, base::Bind(&base::DoNothing), event.GetClosure());
+ FROM_HERE, base::BindOnce(&base::DoNothing), event.GetClosure());
// Runs the loop and waits for the audio thread to call event's
// closure.
event.RunAndWait();
@@ -303,7 +303,7 @@ TEST_F(MAYBE_AudioInputDeviceManagerTest, AccessInvalidSession) {
class AudioInputDeviceManagerNoDevicesTest
: public MAYBE_AudioInputDeviceManagerTest {
public:
- AudioInputDeviceManagerNoDevicesTest(){};
+ AudioInputDeviceManagerNoDevicesTest() {}
protected:
void Initialize() override {
@@ -341,13 +341,8 @@ TEST_F(AudioInputDeviceManagerNoDevicesTest,
// Expects that device parameters stored by the manager are valid.
const StreamDeviceInfo* device_info =
manager_->GetOpenedDeviceInfoById(session_id);
- EXPECT_TRUE(
- media::AudioParameters(media::AudioParameters::AUDIO_FAKE,
- static_cast<media::ChannelLayout>(
- device_info->device.input.channel_layout),
- device_info->device.input.sample_rate, 16,
- device_info->device.input.frames_per_buffer)
- .IsValid());
+ EXPECT_TRUE(device_info->device.input.IsValid());
+ EXPECT_TRUE(device_info->device.matched_output.IsValid());
manager_->Close(session_id);
EXPECT_CALL(*audio_input_listener_,
diff --git a/chromium/content/browser/renderer_host/media/audio_input_renderer_host.cc b/chromium/content/browser/renderer_host/media/audio_input_renderer_host.cc
index dc96e627591..eb8e80120af 100644
--- a/chromium/content/browser/renderer_host/media/audio_input_renderer_host.cc
+++ b/chromium/content/browser/renderer_host/media/audio_input_renderer_host.cc
@@ -7,6 +7,7 @@
#include <utility>
#include "base/bind.h"
+#include "base/callback.h"
#include "base/command_line.h"
#include "base/files/file.h"
#include "base/memory/shared_memory.h"
@@ -25,6 +26,7 @@
#include "content/browser/renderer_host/media/audio_input_sync_writer.h"
#include "content/browser/renderer_host/media/media_stream_manager.h"
#include "content/browser/webrtc/webrtc_internals.h"
+#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents_media_capture_id.h"
#include "media/audio/audio_device_description.h"
#include "media/base/audio_bus.h"
@@ -51,6 +53,18 @@ void LogMessage(int stream_id, const std::string& msg, bool add_prefix) {
DVLOG(1) << message;
}
+void NotifyProcessHostStreamAdded(int render_process_id) {
+ auto* process_host = RenderProcessHost::FromID(render_process_id);
+ if (process_host)
+ process_host->OnMediaStreamAdded();
+}
+
+void NotifyProcessHostStreamRemoved(int render_process_id) {
+ auto* process_host = RenderProcessHost::FromID(render_process_id);
+ if (process_host)
+ process_host->OnMediaStreamRemoved();
+}
+
} // namespace
struct AudioInputRendererHost::AudioEntry {
@@ -74,15 +88,13 @@ struct AudioInputRendererHost::AudioEntry {
// Set to true after we called Close() for the controller.
bool pending_close;
- // If this entry's layout has a keyboard mic channel.
- bool has_keyboard_mic;
+#if defined(OS_CHROMEOS)
+ AudioInputDeviceManager::KeyboardMicRegistration keyboard_mic_registration;
+#endif
};
AudioInputRendererHost::AudioEntry::AudioEntry()
- : stream_id(0),
- pending_close(false),
- has_keyboard_mic(false) {
-}
+ : stream_id(0), pending_close(false) {}
AudioInputRendererHost::AudioEntry::~AudioEntry() {
}
@@ -163,8 +175,8 @@ void AudioInputRendererHost::OnMuted(media::AudioInputController* controller,
bool is_muted) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&AudioInputRendererHost::DoNotifyMutedState, this,
- base::RetainedRef(controller), is_muted));
+ base::BindOnce(&AudioInputRendererHost::DoNotifyMutedState, this,
+ base::RetainedRef(controller), is_muted));
}
void AudioInputRendererHost::set_renderer_pid(int32_t renderer_pid) {
@@ -287,7 +299,8 @@ void AudioInputRendererHost::OnCreateStream(
base::BindOnce(&AudioInputRendererHost::DoCreateStream, this,
stream_id, render_frame_id, session_id, config));
} else {
- DoCreateStream(stream_id, render_frame_id, session_id, config);
+ DoCreateStream(stream_id, render_frame_id, session_id, config,
+ AudioInputDeviceManager::KeyboardMicRegistration());
}
#else
DoCreateStream(stream_id, render_frame_id, session_id, config);
@@ -298,7 +311,12 @@ void AudioInputRendererHost::DoCreateStream(
int stream_id,
int render_frame_id,
int session_id,
- const AudioInputHostMsg_CreateStream_Config& config) {
+ const AudioInputHostMsg_CreateStream_Config& config
+#if defined(OS_CHROMEOS)
+ ,
+ AudioInputDeviceManager::KeyboardMicRegistration keyboard_mic_registration
+#endif
+ ) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK_GT(render_frame_id, 0);
@@ -306,7 +324,6 @@ void AudioInputRendererHost::DoCreateStream(
// media::AudioParameters is validated in the deserializer.
if (LookupById(stream_id)) {
SendErrorMessage(stream_id, STREAM_ALREADY_EXISTS);
- MaybeUnregisterKeyboardMicStream(config);
return;
}
@@ -318,7 +335,6 @@ void AudioInputRendererHost::DoCreateStream(
SendErrorMessage(stream_id, PERMISSION_DENIED);
DLOG(WARNING) << "No permission has been granted to input stream with "
<< "session_id=" << session_id;
- MaybeUnregisterKeyboardMicStream(config);
return;
}
@@ -345,7 +361,6 @@ void AudioInputRendererHost::DoCreateStream(
if (!entry->writer) {
SendErrorMessage(stream_id, SYNC_WRITER_INIT_FAILED);
- MaybeUnregisterKeyboardMicStream(config);
return;
}
@@ -384,15 +399,11 @@ void AudioInputRendererHost::DoCreateStream(
if (!entry->controller.get()) {
SendErrorMessage(stream_id, STREAM_CREATE_ERROR);
- MaybeUnregisterKeyboardMicStream(config);
return;
}
#if defined(OS_CHROMEOS)
- if (config.params.channel_layout() ==
- media::CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC) {
- entry->has_keyboard_mic = true;
- }
+ entry->keyboard_mic_registration = std::move(keyboard_mic_registration);
#endif
const std::string log_message = oss.str();
@@ -407,6 +418,11 @@ void AudioInputRendererHost::DoCreateStream(
MediaInternals::GetInstance()->SetWebContentsTitleForAudioLogEntry(
stream_id, render_process_id_, render_frame_id, audio_log_.get());
+ // Prevent process backgrounding while audio input is active:
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&NotifyProcessHostStreamAdded, render_process_id_));
+
#if BUILDFLAG(ENABLE_WEBRTC)
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
@@ -485,6 +501,10 @@ void AudioInputRendererHost::CloseAndDeleteStream(AudioEntry* entry) {
base::BindOnce(&AudioInputRendererHost::DeleteEntry, this, entry));
entry->pending_close = true;
audio_log_->OnClosed(entry->stream_id);
+
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&NotifyProcessHostStreamRemoved, render_process_id_));
}
}
@@ -492,13 +512,6 @@ void AudioInputRendererHost::DeleteEntry(AudioEntry* entry) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
LogMessage(entry->stream_id, "DeleteEntry: stream is now closed", true);
-#if defined(OS_CHROMEOS)
- if (entry->has_keyboard_mic) {
- media_stream_manager_->audio_input_device_manager()
- ->UnregisterKeyboardMicStream();
- }
-#endif
-
// Delete the entry when this method goes out of scope.
std::unique_ptr<AudioEntry> entry_deleter(entry);
@@ -540,17 +553,6 @@ AudioInputRendererHost::AudioEntry* AudioInputRendererHost::LookupByController(
return nullptr;
}
-void AudioInputRendererHost::MaybeUnregisterKeyboardMicStream(
- const AudioInputHostMsg_CreateStream_Config& config) {
-#if defined(OS_CHROMEOS)
- if (config.params.channel_layout() ==
- media::CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC) {
- media_stream_manager_->audio_input_device_manager()
- ->UnregisterKeyboardMicStream();
- }
-#endif
-}
-
#if BUILDFLAG(ENABLE_WEBRTC)
void AudioInputRendererHost::MaybeEnableDebugRecordingForId(int stream_id) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
diff --git a/chromium/content/browser/renderer_host/media/audio_input_renderer_host.h b/chromium/content/browser/renderer_host/media/audio_input_renderer_host.h
index 281a83a5659..083a0b2c2e8 100644
--- a/chromium/content/browser/renderer_host/media/audio_input_renderer_host.h
+++ b/chromium/content/browser/renderer_host/media/audio_input_renderer_host.h
@@ -31,6 +31,7 @@
#include <string>
#include "base/memory/ref_counted.h"
+#include "content/browser/renderer_host/media/audio_input_device_manager.h"
#include "content/common/media/audio_messages.h"
#include "content/public/browser/browser_message_filter.h"
#include "media/audio/audio_input_controller.h"
@@ -149,10 +150,16 @@ class CONTENT_EXPORT AudioInputRendererHost
// |session_id| is used to identify the device that should be used for the
// stream. Upon success/failure, the peer is notified via the
// NotifyStreamCreated message.
- void DoCreateStream(int stream_id,
- int render_frame_id,
- int session_id,
- const AudioInputHostMsg_CreateStream_Config& config);
+ void DoCreateStream(
+ int stream_id,
+ int render_frame_id,
+ int session_id,
+ const AudioInputHostMsg_CreateStream_Config& config
+#if defined(OS_CHROMEOS)
+ ,
+ AudioInputDeviceManager::KeyboardMicRegistration registration
+#endif
+ );
// Record the audio input stream referenced by |stream_id|.
void OnRecordStream(int stream_id);
@@ -209,11 +216,6 @@ class CONTENT_EXPORT AudioInputRendererHost
// event is received.
AudioEntry* LookupByController(media::AudioInputController* controller);
- // If ChromeOS and |config|'s layout has keyboard mic, unregister in
- // AudioInputDeviceManager.
- void MaybeUnregisterKeyboardMicStream(
- const AudioInputHostMsg_CreateStream_Config& config);
-
#if BUILDFLAG(ENABLE_WEBRTC)
// TODO(grunell): Move debug recording handling to AudioManager.
void MaybeEnableDebugRecordingForId(int stream_id);
diff --git a/chromium/content/browser/renderer_host/media/audio_input_renderer_host_unittest.cc b/chromium/content/browser/renderer_host/media/audio_input_renderer_host_unittest.cc
index c441897609a..f6bc81fe894 100644
--- a/chromium/content/browser/renderer_host/media/audio_input_renderer_host_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/audio_input_renderer_host_unittest.cc
@@ -116,7 +116,6 @@ class AudioInputRendererHostWithInterception : public AudioInputRendererHost {
private:
bool Send(IPC::Message* message) override {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(AudioInputRendererHostWithInterception, *message)
@@ -270,8 +269,8 @@ class AudioInputRendererHostTest : public testing::Test {
audio_manager_.reset(new media::FakeAudioManager(
base::MakeUnique<media::TestAudioThread>(), &log_factory_));
audio_system_ = media::AudioSystemImpl::Create(audio_manager_.get());
- media_stream_manager_ =
- base::MakeUnique<MediaStreamManager>(audio_system_.get());
+ media_stream_manager_ = base::MakeUnique<MediaStreamManager>(
+ audio_system_.get(), audio_manager_->GetTaskRunner());
airh_ = new AudioInputRendererHostWithInterception(
kRenderProcessId, kRendererPid, media::AudioManager::Get(),
media_stream_manager_.get(), AudioMirroringManager::GetInstance(),
@@ -552,8 +551,8 @@ TEST_F(AudioInputRendererHostTest, TabCaptureStream) {
controls.audio.stream_source = kMediaStreamSourceTab;
std::string request_label = media_stream_manager_->MakeMediaAccessRequest(
kRenderProcessId, kRenderFrameId, 0, controls, SecurityOrigin(),
- base::Bind([](const MediaStreamDevices& devices,
- std::unique_ptr<MediaStreamUIProxy>) {}));
+ base::BindOnce([](const MediaStreamDevices& devices,
+ std::unique_ptr<MediaStreamUIProxy>) {}));
base::RunLoop().RunUntilIdle();
int session_id = Open("Tab capture", controls.audio.device_id);
diff --git a/chromium/content/browser/renderer_host/media/audio_input_sync_writer.cc b/chromium/content/browser/renderer_host/media/audio_input_sync_writer.cc
index 54123bd6019..723b6fc5b36 100644
--- a/chromium/content/browser/renderer_host/media/audio_input_sync_writer.cc
+++ b/chromium/content/browser/renderer_host/media/audio_input_sync_writer.cc
@@ -153,7 +153,7 @@ std::unique_ptr<AudioInputSyncWriter> AudioInputSyncWriter::Create(
void AudioInputSyncWriter::Write(const AudioBus* data,
double volume,
bool key_pressed,
- uint32_t hardware_delay_bytes) {
+ base::TimeTicks capture_time) {
TRACE_EVENT0("audio", "AudioInputSyncWriter::Write");
++write_count_;
CheckTimeSinceLastWrite();
@@ -182,7 +182,7 @@ void AudioInputSyncWriter::Write(const AudioBus* data,
// Write the current data to the shared memory if there is room, otherwise
// put it in the fifo.
if (number_of_filled_segments_ < audio_buses_.size()) {
- WriteParametersToCurrentSegment(volume, key_pressed, hardware_delay_bytes);
+ WriteParametersToCurrentSegment(volume, key_pressed, capture_time);
// Copy data into shared memory using pre-allocated audio buses.
data->CopyTo(audio_buses_[current_segment_id_].get());
@@ -192,7 +192,7 @@ void AudioInputSyncWriter::Write(const AudioBus* data,
trailing_write_to_fifo_count_ = 0;
} else {
- if (!PushDataToFifo(data, volume, key_pressed, hardware_delay_bytes))
+ if (!PushDataToFifo(data, volume, key_pressed, capture_time))
write_error = true;
++write_to_fifo_count_;
@@ -251,7 +251,7 @@ void AudioInputSyncWriter::AddToNativeLog(const std::string& message) {
bool AudioInputSyncWriter::PushDataToFifo(const AudioBus* data,
double volume,
bool key_pressed,
- uint32_t hardware_delay_bytes) {
+ base::TimeTicks capture_time) {
if (overflow_buses_.size() == kMaxOverflowBusesSize) {
// We use |write_error_count_| for capping number of log messages.
// |write_error_count_| also includes socket Send() errors, but those should
@@ -277,7 +277,7 @@ bool AudioInputSyncWriter::PushDataToFifo(const AudioBus* data,
}
// Push parameters to fifo.
- OverflowParams params = { volume, hardware_delay_bytes, key_pressed };
+ OverflowParams params = {volume, key_pressed, capture_time};
overflow_params_.push_back(params);
// Push audio data to fifo.
@@ -307,7 +307,7 @@ bool AudioInputSyncWriter::WriteDataFromFifoToSharedMemory() {
// Write parameters to shared memory.
WriteParametersToCurrentSegment((*params_it).volume,
(*params_it).key_pressed,
- (*params_it).hardware_delay_bytes);
+ (*params_it).capture_time);
// Copy data from the fifo into shared memory using pre-allocated audio
// buses.
@@ -337,7 +337,7 @@ bool AudioInputSyncWriter::WriteDataFromFifoToSharedMemory() {
void AudioInputSyncWriter::WriteParametersToCurrentSegment(
double volume,
bool key_pressed,
- uint32_t hardware_delay_bytes) {
+ base::TimeTicks capture_time) {
uint8_t* ptr = static_cast<uint8_t*>(shared_memory_->memory());
CHECK_LT(current_segment_id_, audio_buses_.size());
ptr += current_segment_id_ * shared_memory_segment_size_;
@@ -345,7 +345,8 @@ void AudioInputSyncWriter::WriteParametersToCurrentSegment(
buffer->params.volume = volume;
buffer->params.size = audio_bus_memory_size_;
buffer->params.key_pressed = key_pressed;
- buffer->params.hardware_delay_bytes = hardware_delay_bytes;
+ buffer->params.capture_time =
+ (capture_time - base::TimeTicks()).InMicroseconds();
buffer->params.id = next_buffer_id_;
}
diff --git a/chromium/content/browser/renderer_host/media/audio_input_sync_writer.h b/chromium/content/browser/renderer_host/media/audio_input_sync_writer.h
index 125a0bb18d8..4777418a5fb 100644
--- a/chromium/content/browser/renderer_host/media/audio_input_sync_writer.h
+++ b/chromium/content/browser/renderer_host/media/audio_input_sync_writer.h
@@ -64,7 +64,7 @@ class CONTENT_EXPORT AudioInputSyncWriter
void Write(const media::AudioBus* data,
double volume,
bool key_pressed,
- uint32_t hardware_delay_bytes) override;
+ base::TimeTicks capture_time) override;
void Close() override;
@@ -84,7 +84,7 @@ class CONTENT_EXPORT AudioInputSyncWriter
bool PushDataToFifo(const media::AudioBus* data,
double volume,
bool key_pressed,
- uint32_t hardware_delay_bytes);
+ base::TimeTicks capture_time);
// Writes as much data as possible from the fifo (|overflow_buses_|) to the
// shared memory ring buffer. Returns true if all operations were successful,
@@ -94,7 +94,7 @@ class CONTENT_EXPORT AudioInputSyncWriter
// Write audio parameters to current segment in shared memory.
void WriteParametersToCurrentSegment(double volume,
bool key_pressed,
- uint32_t hardware_delay_bytes);
+ base::TimeTicks capture_time);
// Signals over the socket that data has been written to the current segment.
// Updates counters and returns true if successful. Logs error and returns
@@ -167,8 +167,8 @@ class CONTENT_EXPORT AudioInputSyncWriter
std::vector<std::unique_ptr<media::AudioBus>> overflow_buses_;
struct OverflowParams {
double volume;
- uint32_t hardware_delay_bytes;
bool key_pressed;
+ base::TimeTicks capture_time;
};
std::deque<OverflowParams> overflow_params_;
diff --git a/chromium/content/browser/renderer_host/media/audio_input_sync_writer_unittest.cc b/chromium/content/browser/renderer_host/media/audio_input_sync_writer_unittest.cc
index e68c294c5a9..985582c77f3 100644
--- a/chromium/content/browser/renderer_host/media/audio_input_sync_writer_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/audio_input_sync_writer_unittest.cc
@@ -25,7 +25,6 @@
#include "testing/gtest/include/gtest/gtest.h"
using ::testing::_;
-using base::TimeDelta;
using media::AudioBus;
using media::AudioParameters;
@@ -179,7 +178,7 @@ TEST_F(AudioInputSyncWriterTest, SingleWriteAndRead) {
EXPECT_CALL(*writer_.get(), AddToNativeLog(_))
.Times(GetTotalNumberOfExpectedLogCalls(0));
- writer_->Write(audio_bus_.get(), 0, false, 0);
+ writer_->Write(audio_bus_.get(), 0, false, base::TimeTicks::Now());
EXPECT_TRUE(TestSocketAndFifoExpectations(1, 0, 0));
socket_->Read(1);
@@ -191,7 +190,7 @@ TEST_F(AudioInputSyncWriterTest, MultipleWritesAndReads) {
.Times(GetTotalNumberOfExpectedLogCalls(0));
for (int i = 1; i <= 2 * kSegments; ++i) {
- writer_->Write(audio_bus_.get(), 0, false, 0);
+ writer_->Write(audio_bus_.get(), 0, false, base::TimeTicks::Now());
EXPECT_TRUE(TestSocketAndFifoExpectations(1, 0, 0));
socket_->Read(1);
EXPECT_TRUE(TestSocketAndFifoExpectations(0, 1 * sizeof(uint32_t), 0));
@@ -204,14 +203,14 @@ TEST_F(AudioInputSyncWriterTest, MultipleWritesNoReads) {
// Fill the ring buffer.
for (int i = 1; i <= kSegments; ++i) {
- writer_->Write(audio_bus_.get(), 0, false, 0);
+ writer_->Write(audio_bus_.get(), 0, false, base::TimeTicks::Now());
EXPECT_TRUE(TestSocketAndFifoExpectations(i, 0, 0));
}
// Now the ring buffer is full, do more writes. We should start filling the
// fifo and should get one extra log call for that.
for (size_t i = 1; i <= kSegments; ++i) {
- writer_->Write(audio_bus_.get(), 0, false, 0);
+ writer_->Write(audio_bus_.get(), 0, false, base::TimeTicks::Now());
EXPECT_TRUE(TestSocketAndFifoExpectations(kSegments, 0, i));
}
}
@@ -222,7 +221,7 @@ TEST_F(AudioInputSyncWriterTest, FillAndEmptyRingBuffer) {
// Fill the ring buffer.
for (int i = 1; i <= kSegments; ++i) {
- writer_->Write(audio_bus_.get(), 0, false, 0);
+ writer_->Write(audio_bus_.get(), 0, false, base::TimeTicks::Now());
}
EXPECT_TRUE(TestSocketAndFifoExpectations(kSegments, 0, 0));
@@ -236,13 +235,13 @@ TEST_F(AudioInputSyncWriterTest, FillAndEmptyRingBuffer) {
// Fill up again. The first write should do receive until that queue is
// empty.
for (int i = kSegments - buffers_to_read + 1; i <= kSegments; ++i) {
- writer_->Write(audio_bus_.get(), 0, false, 0);
+ writer_->Write(audio_bus_.get(), 0, false, base::TimeTicks::Now());
EXPECT_TRUE(TestSocketAndFifoExpectations(i, 0, 0));
}
// Another write, should put the data in the fifo, and render an extra log
// call.
- writer_->Write(audio_bus_.get(), 0, false, 0);
+ writer_->Write(audio_bus_.get(), 0, false, base::TimeTicks::Now());
EXPECT_TRUE(TestSocketAndFifoExpectations(kSegments, 0, 1));
// Empty the ring buffer.
@@ -252,7 +251,7 @@ TEST_F(AudioInputSyncWriterTest, FillAndEmptyRingBuffer) {
// Another write, should do receive until that queue is empty and write both
// the data in the fifo and the new data, and render a log call.
- writer_->Write(audio_bus_.get(), 0, false, 0);
+ writer_->Write(audio_bus_.get(), 0, false, base::TimeTicks::Now());
EXPECT_TRUE(TestSocketAndFifoExpectations(2, 0, 0));
// Read the two data blocks.
@@ -266,19 +265,19 @@ TEST_F(AudioInputSyncWriterTest, FillRingBufferAndFifo) {
// Fill the ring buffer.
for (int i = 1; i <= kSegments; ++i) {
- writer_->Write(audio_bus_.get(), 0, false, 0);
+ writer_->Write(audio_bus_.get(), 0, false, base::TimeTicks::Now());
}
EXPECT_TRUE(TestSocketAndFifoExpectations(kSegments, 0, 0));
// Fill the fifo. Should render one log call for starting filling it.
const size_t max_fifo_size = AudioInputSyncWriter::kMaxOverflowBusesSize;
for (size_t i = 1; i <= max_fifo_size; ++i) {
- writer_->Write(audio_bus_.get(), 0, false, 0);
+ writer_->Write(audio_bus_.get(), 0, false, base::TimeTicks::Now());
}
EXPECT_TRUE(TestSocketAndFifoExpectations(kSegments, 0, max_fifo_size));
// Another write, data should be dropped and render one log call.
- writer_->Write(audio_bus_.get(), 0, false, 0);
+ writer_->Write(audio_bus_.get(), 0, false, base::TimeTicks::Now());
EXPECT_TRUE(TestSocketAndFifoExpectations(kSegments, 0, max_fifo_size));
}
@@ -288,14 +287,14 @@ TEST_F(AudioInputSyncWriterTest, MultipleFillAndEmptyRingBufferAndPartOfFifo) {
// Fill the ring buffer.
for (int i = 1; i <= kSegments; ++i) {
- writer_->Write(audio_bus_.get(), 0, false, 0);
+ writer_->Write(audio_bus_.get(), 0, false, base::TimeTicks::Now());
}
EXPECT_TRUE(TestSocketAndFifoExpectations(kSegments, 0, 0));
// Write more data, should be put in the fifo and render one log call for
// starting filling it.
for (size_t i = 1; i <= 2 * kSegments; ++i) {
- writer_->Write(audio_bus_.get(), 0, false, 0);
+ writer_->Write(audio_bus_.get(), 0, false, base::TimeTicks::Now());
}
EXPECT_TRUE(TestSocketAndFifoExpectations(kSegments, 0, 2 * kSegments));
@@ -306,7 +305,7 @@ TEST_F(AudioInputSyncWriterTest, MultipleFillAndEmptyRingBufferAndPartOfFifo) {
// Another write should fill up the ring buffer with data from the fifo and
// put this data into the fifo.
- writer_->Write(audio_bus_.get(), 0, false, 0);
+ writer_->Write(audio_bus_.get(), 0, false, base::TimeTicks::Now());
EXPECT_TRUE(TestSocketAndFifoExpectations(kSegments, 0, kSegments + 1));
// Empty the ring buffer again.
@@ -316,7 +315,7 @@ TEST_F(AudioInputSyncWriterTest, MultipleFillAndEmptyRingBufferAndPartOfFifo) {
// Another write should fill up the ring buffer with data from the fifo and
// put this data into the fifo.
- writer_->Write(audio_bus_.get(), 0, false, 0);
+ writer_->Write(audio_bus_.get(), 0, false, base::TimeTicks::Now());
EXPECT_TRUE(TestSocketAndFifoExpectations(kSegments, 0, 2));
// Empty the ring buffer again.
@@ -326,7 +325,7 @@ TEST_F(AudioInputSyncWriterTest, MultipleFillAndEmptyRingBufferAndPartOfFifo) {
// Another write should put the remaining data in the fifo in the ring buffer
// together with this data. Should render a log call for emptying the fifo.
- writer_->Write(audio_bus_.get(), 0, false, 0);
+ writer_->Write(audio_bus_.get(), 0, false, base::TimeTicks::Now());
EXPECT_TRUE(TestSocketAndFifoExpectations(3, 0, 0));
// Read the remaining data.
@@ -336,13 +335,13 @@ TEST_F(AudioInputSyncWriterTest, MultipleFillAndEmptyRingBufferAndPartOfFifo) {
// Fill the ring buffer and part of the fifo. Should render one log call for
// starting filling it.
for (int i = 1; i <= kSegments + 2; ++i) {
- writer_->Write(audio_bus_.get(), 0, false, 0);
+ writer_->Write(audio_bus_.get(), 0, false, base::TimeTicks::Now());
}
EXPECT_TRUE(TestSocketAndFifoExpectations(kSegments, 0, 2));
// Empty both. Should render a log call for emptying the fifo.
socket_->Read(kSegments);
- writer_->Write(audio_bus_.get(), 0, false, 0);
+ writer_->Write(audio_bus_.get(), 0, false, base::TimeTicks::Now());
socket_->Read(3);
EXPECT_TRUE(TestSocketAndFifoExpectations(0, 3 * sizeof(uint32_t), 0));
}
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 9bdfbc9eb9f..b19c997861d 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
@@ -131,11 +131,10 @@ void AudioOutputAuthorizationHandler::RequestDeviceAuthorization(
if (info && !info->device.matched_output_device_id.empty()) {
media::AudioParameters params(
media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
- static_cast<media::ChannelLayout>(
- info->device.matched_output.channel_layout),
- info->device.matched_output.sample_rate, 16,
- info->device.matched_output.frames_per_buffer);
- params.set_effects(info->device.matched_output.effects);
+ info->device.matched_output.channel_layout(),
+ info->device.matched_output.sample_rate(), 16,
+ info->device.matched_output.frames_per_buffer());
+ params.set_effects(info->device.matched_output.effects());
// 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.
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 acf34d7b3e5..684afb7cc54 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
@@ -102,8 +102,8 @@ class AudioOutputAuthorizationHandlerTest : public RenderViewHostTestHarness {
audio_manager_ = base::MakeUnique<media::FakeAudioManager>(
base::MakeUnique<media::AudioThreadImpl>(), &log_factory_);
audio_system_ = media::AudioSystemImpl::Create(audio_manager_.get());
- media_stream_manager_ =
- base::MakeUnique<MediaStreamManager>(audio_system_.get());
+ media_stream_manager_ = base::MakeUnique<MediaStreamManager>(
+ audio_system_.get(), audio_manager_->GetTaskRunner());
// Make sure everything is done initializing:
SyncWithAllThreads();
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 e67344656ac..86b76e7e64a 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
@@ -24,6 +24,8 @@
#include "media/audio/audio_thread_impl.h"
#include "media/audio/fake_audio_log_factory.h"
#include "media/audio/fake_audio_manager.h"
+#include "media/base/bind_to_current_loop.h"
+#include "media/base/gmock_callback_support.h"
#include "media/base/media_switches.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -354,33 +356,41 @@ class AudioOutputDelegateTest : public testing::Test {
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, done);
}
+ void TrampolineToUI(base::Closure done,
+ std::unique_ptr<AudioOutputDelegateImpl> delegate) {
+ // Destruct and then sync since destruction will post some tasks.
+ delegate.reset();
+ SyncWithAllThreads();
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, done);
+ }
+
void ErrorTest(base::Closure done) {
EXPECT_CALL(media_observer_,
OnCreatingAudioStream(kRenderProcessId, kRenderFrameId));
EXPECT_CALL(event_handler_, GotOnStreamCreated());
- EXPECT_CALL(event_handler_, OnStreamError(kStreamId));
EXPECT_CALL(mirroring_manager_,
AddDiverter(kRenderProcessId, kRenderFrameId, NotNull()));
+ EXPECT_CALL(mirroring_manager_, RemoveDiverter(NotNull()));
- {
- auto socket = base::MakeUnique<base::CancelableSyncSocket>();
- auto reader = AudioSyncReader::Create(Params(), socket.get());
- AudioOutputDelegateImpl delegate(
- std::move(reader), std::move(socket), &event_handler_,
- audio_manager_.get(),
- log_factory_.CreateAudioLog(
- media::AudioLogFactory::AUDIO_OUTPUT_CONTROLLER),
- &mirroring_manager_, &media_observer_, kStreamId, kRenderFrameId,
- kRenderProcessId, Params(), kDefaultDeviceId);
-
- delegate.GetControllerForTesting()->OnError();
-
- SyncWithAllThreads();
-
- EXPECT_CALL(mirroring_manager_, RemoveDiverter(NotNull()));
- }
- SyncWithAllThreads();
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, done);
+ auto socket = base::MakeUnique<base::CancelableSyncSocket>();
+ auto reader = AudioSyncReader::Create(Params(), socket.get());
+ auto delegate = base::MakeUnique<AudioOutputDelegateImpl>(
+ std::move(reader), std::move(socket), &event_handler_,
+ audio_manager_.get(),
+ log_factory_.CreateAudioLog(
+ media::AudioLogFactory::AUDIO_OUTPUT_CONTROLLER),
+ &mirroring_manager_, &media_observer_, kStreamId, kRenderFrameId,
+ kRenderProcessId, Params(), kDefaultDeviceId);
+
+ delegate->GetControllerForTesting()->OnError();
+
+ // Errors are deferred by AudioOutputController, so wait for the error; pass
+ // the delegate along since destructing it will close the stream and void
+ // the purpose of this test.
+ EXPECT_CALL(event_handler_, OnStreamError(kStreamId))
+ .WillOnce(media::RunClosure(media::BindToCurrentLoop(base::Bind(
+ &AudioOutputDelegateTest::TrampolineToUI, base::Unretained(this),
+ done, base::Passed(&delegate)))));
}
void CreateAndDestroyTest(base::Closure done) {
@@ -487,8 +497,9 @@ class AudioOutputDelegateTest : public testing::Test {
CHECK(!task_runner->BelongsToCurrentThread());
base::WaitableEvent e = {base::WaitableEvent::ResetPolicy::MANUAL,
base::WaitableEvent::InitialState::NOT_SIGNALED};
- task_runner->PostTask(FROM_HERE, base::Bind(&base::WaitableEvent::Signal,
- base::Unretained(&e)));
+ task_runner->PostTask(
+ FROM_HERE,
+ base::BindOnce(&base::WaitableEvent::Signal, base::Unretained(&e)));
e.Wait();
}
@@ -497,25 +508,28 @@ class AudioOutputDelegateTest : public testing::Test {
TEST_F(AudioOutputDelegateTest, Create) {
base::RunLoop l;
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::Bind(&AudioOutputDelegateTest::CreateTest,
- base::Unretained(this), l.QuitClosure()));
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&AudioOutputDelegateTest::CreateTest,
+ base::Unretained(this), l.QuitClosure()));
l.Run();
}
TEST_F(AudioOutputDelegateTest, Play) {
base::RunLoop l;
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::Bind(&AudioOutputDelegateTest::PlayTest,
- base::Unretained(this), l.QuitClosure()));
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&AudioOutputDelegateTest::PlayTest, base::Unretained(this),
+ l.QuitClosure()));
l.Run();
}
TEST_F(AudioOutputDelegateTest, Pause) {
base::RunLoop l;
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::Bind(&AudioOutputDelegateTest::PauseTest,
- base::Unretained(this), l.QuitClosure()));
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&AudioOutputDelegateTest::PauseTest,
+ base::Unretained(this), l.QuitClosure()));
l.Run();
}
@@ -523,40 +537,44 @@ TEST_F(AudioOutputDelegateTest, PlayPausePlay) {
base::RunLoop l;
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&AudioOutputDelegateTest::PlayPausePlayTest,
- base::Unretained(this), l.QuitClosure()));
+ base::BindOnce(&AudioOutputDelegateTest::PlayPausePlayTest,
+ base::Unretained(this), l.QuitClosure()));
l.Run();
}
TEST_F(AudioOutputDelegateTest, PlayPlay) {
base::RunLoop l;
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::Bind(&AudioOutputDelegateTest::PlayPlayTest,
- base::Unretained(this), l.QuitClosure()));
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&AudioOutputDelegateTest::PlayPlayTest,
+ base::Unretained(this), l.QuitClosure()));
l.Run();
}
TEST_F(AudioOutputDelegateTest, PlayDivert) {
base::RunLoop l;
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::Bind(&AudioOutputDelegateTest::PlayDivertTest,
- base::Unretained(this), l.QuitClosure()));
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&AudioOutputDelegateTest::PlayDivertTest,
+ base::Unretained(this), l.QuitClosure()));
l.Run();
}
TEST_F(AudioOutputDelegateTest, CreateDivert) {
base::RunLoop l;
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::Bind(&AudioOutputDelegateTest::CreateDivertTest,
- base::Unretained(this), l.QuitClosure()));
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&AudioOutputDelegateTest::CreateDivertTest,
+ base::Unretained(this), l.QuitClosure()));
l.Run();
}
TEST_F(AudioOutputDelegateTest, Error) {
base::RunLoop l;
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::Bind(&AudioOutputDelegateTest::ErrorTest,
- base::Unretained(this), l.QuitClosure()));
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&AudioOutputDelegateTest::ErrorTest,
+ base::Unretained(this), l.QuitClosure()));
l.Run();
}
@@ -564,8 +582,8 @@ TEST_F(AudioOutputDelegateTest, CreateAndDestroy) {
base::RunLoop l;
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&AudioOutputDelegateTest::CreateAndDestroyTest,
- base::Unretained(this), l.QuitClosure()));
+ base::BindOnce(&AudioOutputDelegateTest::CreateAndDestroyTest,
+ base::Unretained(this), l.QuitClosure()));
l.Run();
}
@@ -573,8 +591,8 @@ TEST_F(AudioOutputDelegateTest, PlayAndDestroy) {
base::RunLoop l;
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&AudioOutputDelegateTest::PlayAndDestroyTest,
- base::Unretained(this), l.QuitClosure()));
+ base::BindOnce(&AudioOutputDelegateTest::PlayAndDestroyTest,
+ base::Unretained(this), l.QuitClosure()));
l.Run();
}
@@ -582,8 +600,8 @@ TEST_F(AudioOutputDelegateTest, ErrorAndDestroy) {
base::RunLoop l;
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&AudioOutputDelegateTest::PlayAndDestroyTest,
- base::Unretained(this), l.QuitClosure()));
+ base::BindOnce(&AudioOutputDelegateTest::PlayAndDestroyTest,
+ base::Unretained(this), l.QuitClosure()));
l.Run();
}
diff --git a/chromium/content/browser/renderer_host/media/audio_renderer_host.cc b/chromium/content/browser/renderer_host/media/audio_renderer_host.cc
index 68be4e29559..b22f85da903 100644
--- a/chromium/content/browser/renderer_host/media/audio_renderer_host.cc
+++ b/chromium/content/browser/renderer_host/media/audio_renderer_host.cc
@@ -202,11 +202,13 @@ void AudioRendererHost::AuthorizationCompleted(
const std::string& raw_device_id,
const std::string& device_id_for_renderer) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ UMALogDeviceAuthorizationTime(auth_start_time);
+
auto auth_data = authorizations_.find(stream_id);
if (auth_data == authorizations_.end())
return; // Stream was closed before finishing authorization
- UMALogDeviceAuthorizationTime(auth_start_time);
if (status == media::OUTPUT_DEVICE_STATUS_OK) {
auth_data->second.first = true;
auth_data->second.second = raw_device_id;
diff --git a/chromium/content/browser/renderer_host/media/audio_renderer_host_unittest.cc b/chromium/content/browser/renderer_host/media/audio_renderer_host_unittest.cc
index 91888375f02..ab76c47aead 100644
--- a/chromium/content/browser/renderer_host/media/audio_renderer_host_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/audio_renderer_host_unittest.cc
@@ -206,12 +206,16 @@ class AudioRendererHostTest : public RenderViewHostTestHarness {
void SetUp() override {
base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kUseFakeDeviceForMediaStream);
+ // MediaStreamManager depends on legacy TestBrowserThreadBundle behavior.
+ // TODO: Remove once MediaStreamManager is ported to TaskScheduler.
+ DisableScopedTaskEnvironment();
+
RenderViewHostTestHarness::SetUp();
audio_manager_ =
base::MakeUnique<FakeAudioManagerWithAssociations>(&log_factory_);
audio_system_ = media::AudioSystemImpl::Create(audio_manager_.get());
- media_stream_manager_ =
- base::MakeUnique<MediaStreamManager>(audio_system_.get());
+ media_stream_manager_ = base::MakeUnique<MediaStreamManager>(
+ audio_system_.get(), audio_manager_->GetTaskRunner());
auth_run_loop_ = base::MakeUnique<base::RunLoop>();
host_ = base::MakeRefCounted<MockAudioRendererHost>(
auth_run_loop_.get(), process()->GetID(), audio_manager_.get(),
diff --git a/chromium/content/browser/renderer_host/media/audio_sync_reader.cc b/chromium/content/browser/renderer_host/media/audio_sync_reader.cc
index 2d1755d81e6..bc2ce151436 100644
--- a/chromium/content/browser/renderer_host/media/audio_sync_reader.cc
+++ b/chromium/content/browser/renderer_host/media/audio_sync_reader.cc
@@ -72,6 +72,7 @@ AudioSyncReader::AudioSyncReader(
reinterpret_cast<AudioOutputBuffer*>(shared_memory_->memory());
output_bus_ = AudioBus::WrapMemory(params, buffer->audio);
output_bus_->Zero();
+ output_bus_->set_is_bitstream_format(params.IsBitstreamFormat());
}
AudioSyncReader::~AudioSyncReader() {
@@ -199,10 +200,21 @@ void AudioSyncReader::Read(AudioBus* dest) {
trailing_renderer_missed_callback_count_ = 0;
- if (mute_audio_)
+ // Zeroed buffers may be discarded immediately when outputing compressed
+ // bitstream.
+ if (mute_audio_ && !output_bus_->is_bitstream_format()) {
dest->Zero();
- else
- output_bus_->CopyTo(dest);
+ return;
+ }
+
+ if (output_bus_->is_bitstream_format()) {
+ // For bitstream formats, we need the real data size and PCM frame count.
+ AudioOutputBuffer* buffer =
+ reinterpret_cast<AudioOutputBuffer*>(shared_memory_->memory());
+ output_bus_->SetBitstreamDataSize(buffer->params.bitstream_data_size);
+ output_bus_->SetBitstreamFrames(buffer->params.bitstream_frames);
+ }
+ output_bus_->CopyTo(dest);
}
void AudioSyncReader::Close() {
diff --git a/chromium/content/browser/renderer_host/media/audio_sync_reader.h b/chromium/content/browser/renderer_host/media/audio_sync_reader.h
index d7dce0ec884..c0fbf1ccfef 100644
--- a/chromium/content/browser/renderer_host/media/audio_sync_reader.h
+++ b/chromium/content/browser/renderer_host/media/audio_sync_reader.h
@@ -35,7 +35,7 @@ namespace content {
// transmitting audio packets between the browser process and the renderer
// process.
class CONTENT_EXPORT AudioSyncReader
- : public NON_EXPORTED_BASE(media::AudioOutputController::SyncReader) {
+ : public media::AudioOutputController::SyncReader {
public:
// Create() automatically initializes the AudioSyncReader correctly,
// and should be strongly preferred over calling the constructor directly!
diff --git a/chromium/content/browser/renderer_host/media/in_process_launched_video_capture_device.cc b/chromium/content/browser/renderer_host/media/in_process_launched_video_capture_device.cc
index 41d70f74059..e8f2f720c58 100644
--- a/chromium/content/browser/renderer_host/media/in_process_launched_video_capture_device.cc
+++ b/chromium/content/browser/renderer_host/media/in_process_launched_video_capture_device.cc
@@ -45,9 +45,10 @@ InProcessLaunchedVideoCaptureDevice::~InProcessLaunchedVideoCaptureDevice() {
media::VideoCaptureDevice* device_ptr = device_.release();
device_task_runner_->PostTask(
FROM_HERE,
- base::Bind(&StopAndReleaseDeviceOnDeviceThread, device_ptr,
- base::Bind([](scoped_refptr<base::SingleThreadTaskRunner>) {},
- device_task_runner_)));
+ base::BindOnce(
+ &StopAndReleaseDeviceOnDeviceThread, device_ptr,
+ base::Bind([](scoped_refptr<base::SingleThreadTaskRunner>) {},
+ device_task_runner_)));
}
void InProcessLaunchedVideoCaptureDevice::GetPhotoState(
@@ -58,8 +59,8 @@ void InProcessLaunchedVideoCaptureDevice::GetPhotoState(
// guaranteed to run before the task that destroys the |device|.
device_task_runner_->PostTask(
FROM_HERE,
- base::Bind(&media::VideoCaptureDevice::GetPhotoState,
- base::Unretained(device_.get()), base::Passed(&callback)));
+ base::BindOnce(&media::VideoCaptureDevice::GetPhotoState,
+ base::Unretained(device_.get()), base::Passed(&callback)));
}
void InProcessLaunchedVideoCaptureDevice::SetPhotoOptions(
@@ -70,9 +71,10 @@ void InProcessLaunchedVideoCaptureDevice::SetPhotoOptions(
// was scheduled for shutdown and destruction, and because this task is
// guaranteed to run before the task that destroys the |device|.
device_task_runner_->PostTask(
- FROM_HERE, base::Bind(&media::VideoCaptureDevice::SetPhotoOptions,
- base::Unretained(device_.get()),
- base::Passed(&settings), base::Passed(&callback)));
+ FROM_HERE,
+ base::BindOnce(&media::VideoCaptureDevice::SetPhotoOptions,
+ base::Unretained(device_.get()), base::Passed(&settings),
+ base::Passed(&callback)));
}
void InProcessLaunchedVideoCaptureDevice::TakePhoto(
@@ -83,8 +85,8 @@ void InProcessLaunchedVideoCaptureDevice::TakePhoto(
// guaranteed to run before the task that destroys the |device|.
device_task_runner_->PostTask(
FROM_HERE,
- base::Bind(&media::VideoCaptureDevice::TakePhoto,
- base::Unretained(device_.get()), base::Passed(&callback)));
+ base::BindOnce(&media::VideoCaptureDevice::TakePhoto,
+ base::Unretained(device_.get()), base::Passed(&callback)));
}
void InProcessLaunchedVideoCaptureDevice::MaybeSuspendDevice() {
@@ -93,8 +95,8 @@ void InProcessLaunchedVideoCaptureDevice::MaybeSuspendDevice() {
// was scheduled for shutdown and destruction, and because this task is
// guaranteed to run before the task that destroys the |device|.
device_task_runner_->PostTask(
- FROM_HERE, base::Bind(&media::VideoCaptureDevice::MaybeSuspend,
- base::Unretained(device_.get())));
+ FROM_HERE, base::BindOnce(&media::VideoCaptureDevice::MaybeSuspend,
+ base::Unretained(device_.get())));
}
void InProcessLaunchedVideoCaptureDevice::ResumeDevice() {
@@ -102,9 +104,9 @@ void InProcessLaunchedVideoCaptureDevice::ResumeDevice() {
// Unretained() is safe to use here because |device| would be null if it
// was scheduled for shutdown and destruction, and because this task is
// guaranteed to run before the task that destroys the |device|.
- device_task_runner_->PostTask(FROM_HERE,
- base::Bind(&media::VideoCaptureDevice::Resume,
- base::Unretained(device_.get())));
+ device_task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&media::VideoCaptureDevice::Resume,
+ base::Unretained(device_.get())));
}
void InProcessLaunchedVideoCaptureDevice::RequestRefreshFrame() {
@@ -113,8 +115,8 @@ void InProcessLaunchedVideoCaptureDevice::RequestRefreshFrame() {
// was scheduled for shutdown and destruction, and because this task is
// guaranteed to run before the task that destroys the |device|.
device_task_runner_->PostTask(
- FROM_HERE, base::Bind(&media::VideoCaptureDevice::RequestRefreshFrame,
- base::Unretained(device_.get())));
+ FROM_HERE, base::BindOnce(&media::VideoCaptureDevice::RequestRefreshFrame,
+ base::Unretained(device_.get())));
}
void InProcessLaunchedVideoCaptureDevice::SetDesktopCaptureWindowIdAsync(
@@ -125,10 +127,10 @@ void InProcessLaunchedVideoCaptureDevice::SetDesktopCaptureWindowIdAsync(
// device is destroyed on the device_task_runner_ and |done_cb|
// guarantees that |this| stays alive.
device_task_runner_->PostTask(
- FROM_HERE, base::Bind(&InProcessLaunchedVideoCaptureDevice::
- SetDesktopCaptureWindowIdOnDeviceThread,
- base::Unretained(this), device_.get(), window_id,
- base::Passed(&done_cb)));
+ FROM_HERE, base::BindOnce(&InProcessLaunchedVideoCaptureDevice::
+ SetDesktopCaptureWindowIdOnDeviceThread,
+ base::Unretained(this), device_.get(),
+ window_id, base::Passed(&done_cb)));
}
void InProcessLaunchedVideoCaptureDevice::OnUtilizationReport(
@@ -139,9 +141,9 @@ void InProcessLaunchedVideoCaptureDevice::OnUtilizationReport(
// was scheduled for shutdown and destruction, and because this task is
// guaranteed to run before the task that destroys the |device|.
device_task_runner_->PostTask(
- FROM_HERE, base::Bind(&media::VideoCaptureDevice::OnUtilizationReport,
- base::Unretained(device_.get()), frame_feedback_id,
- utilization));
+ FROM_HERE, base::BindOnce(&media::VideoCaptureDevice::OnUtilizationReport,
+ base::Unretained(device_.get()),
+ frame_feedback_id, utilization));
}
void InProcessLaunchedVideoCaptureDevice::
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 10825692587..9a8444f1392 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
@@ -16,9 +16,10 @@ void EnsureMonitorCaptureDevices() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&MediaStreamManager::EnsureDeviceMonitorStarted,
- base::Unretained(
- BrowserMainLoop::GetInstance()->media_stream_manager())));
+ base::BindOnce(
+ &MediaStreamManager::EnsureDeviceMonitorStarted,
+ base::Unretained(
+ BrowserMainLoop::GetInstance()->media_stream_manager())));
}
} // namespace
@@ -58,8 +59,8 @@ void MediaCaptureDevicesImpl::AddVideoCaptureObserver(
if (media_stream_manager != nullptr) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&MediaStreamManager::AddVideoCaptureObserver,
- base::Unretained(media_stream_manager), observer));
+ base::BindOnce(&MediaStreamManager::AddVideoCaptureObserver,
+ base::Unretained(media_stream_manager), observer));
} else {
DVLOG(3) << "media_stream_manager is null.";
}
@@ -71,8 +72,8 @@ void MediaCaptureDevicesImpl::RemoveAllVideoCaptureObservers() {
if (media_stream_manager != nullptr) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&MediaStreamManager::RemoveAllVideoCaptureObservers,
- base::Unretained(media_stream_manager)));
+ base::BindOnce(&MediaStreamManager::RemoveAllVideoCaptureObservers,
+ base::Unretained(media_stream_manager)));
} else {
DVLOG(3) << "media_stream_manager is null.";
}
@@ -85,8 +86,8 @@ void MediaCaptureDevicesImpl::OnAudioCaptureDevicesChanged(
} else {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&MediaCaptureDevicesImpl::UpdateAudioDevicesOnUIThread,
- base::Unretained(this), devices));
+ base::BindOnce(&MediaCaptureDevicesImpl::UpdateAudioDevicesOnUIThread,
+ base::Unretained(this), devices));
}
}
@@ -97,8 +98,8 @@ void MediaCaptureDevicesImpl::OnVideoCaptureDevicesChanged(
} else {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&MediaCaptureDevicesImpl::UpdateVideoDevicesOnUIThread,
- base::Unretained(this), devices));
+ 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 f75a4dd9e7d..6f749221d05 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
@@ -6,6 +6,7 @@
#include <stddef.h>
+#include <algorithm>
#include <utility>
#include <vector>
@@ -331,9 +332,9 @@ void MediaDevicesDispatcherHost::CheckPermissionsForEnumerateDevices(
DCHECK_CURRENTLY_ON(BrowserThread::IO);
permission_checker_->CheckPermissions(
requested_types, render_process_id_, render_frame_id_,
- base::Bind(&MediaDevicesDispatcherHost::DoEnumerateDevices,
- weak_factory_.GetWeakPtr(), requested_types,
- base::Passed(&client_callback), security_origin));
+ base::BindOnce(&MediaDevicesDispatcherHost::DoEnumerateDevices,
+ weak_factory_.GetWeakPtr(), requested_types,
+ base::Passed(&client_callback), security_origin));
}
void MediaDevicesDispatcherHost::DoEnumerateDevices(
@@ -455,6 +456,13 @@ media::VideoCaptureFormats MediaDevicesDispatcherHost::GetVideoInputFormats(
media_stream_manager_->video_capture_manager()->GetDeviceSupportedFormats(
device_id, &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());
+
return formats;
}
@@ -523,8 +531,8 @@ void MediaDevicesDispatcherHost::GotAudioInputEnumeration(
for (size_t i = 0; i < num_pending_audio_input_parameters_; ++i) {
media_stream_manager_->audio_system()->GetInputStreamParameters(
current_audio_input_capabilities_[i].device_id,
- base::Bind(&MediaDevicesDispatcherHost::GotAudioInputParameters,
- weak_factory_.GetWeakPtr(), i));
+ base::BindOnce(&MediaDevicesDispatcherHost::GotAudioInputParameters,
+ weak_factory_.GetWeakPtr(), i));
}
}
diff --git a/chromium/content/browser/renderer_host/media/media_devices_dispatcher_host_unittest.cc b/chromium/content/browser/renderer_host/media/media_devices_dispatcher_host_unittest.cc
index 724663bf229..7cc37705a90 100644
--- a/chromium/content/browser/renderer_host/media/media_devices_dispatcher_host_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/media_devices_dispatcher_host_unittest.cc
@@ -17,6 +17,7 @@
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "content/browser/renderer_host/media/in_process_video_capture_provider.h"
#include "content/browser/renderer_host/media/media_stream_manager.h"
#include "content/browser/renderer_host/media/media_stream_ui_proxy.h"
#include "content/browser/renderer_host/media/video_capture_manager.h"
@@ -30,6 +31,7 @@
#include "media/audio/test_audio_thread.h"
#include "media/base/media_switches.h"
#include "media/capture/video/fake_video_capture_device_factory.h"
+#include "media/capture/video/video_capture_system_impl.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -46,7 +48,10 @@ namespace {
const int kProcessId = 5;
const int kRenderId = 6;
const size_t kNumFakeVideoDevices = 3;
-const char kDefaultVideoDeviceID[] = "/dev/video2";
+const char kNormalVideoDeviceID[] = "/dev/video0";
+const char kNoFormatsVideoDeviceID[] = "/dev/video1";
+const char kZeroResolutionVideoDeviceID[] = "/dev/video2";
+const char* const kDefaultVideoDeviceID = kZeroResolutionVideoDeviceID;
const char kDefaultAudioDeviceID[] = "fake_audio_input_2";
void PhysicalDevicesEnumerated(base::Closure quit_closure,
@@ -83,16 +88,26 @@ class MediaDevicesDispatcherHostTest : public testing::TestWithParam<GURL> {
// Make sure we use fake devices to avoid long delays.
base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
switches::kUseFakeDeviceForMediaStream,
- base::StringPrintf("device-count=%zu, video-input-default-id=%s, "
+ base::StringPrintf("video-input-default-id=%s, "
"audio-input-default-id=%s",
- kNumFakeVideoDevices, kDefaultVideoDeviceID,
- kDefaultAudioDeviceID));
+ kDefaultVideoDeviceID, kDefaultAudioDeviceID));
audio_manager_.reset(new media::MockAudioManager(
base::MakeUnique<media::TestAudioThread>()));
audio_system_ = media::AudioSystemImpl::Create(audio_manager_.get());
- media_stream_manager_ =
- base::MakeUnique<MediaStreamManager>(audio_system_.get());
+ auto video_capture_device_factory =
+ base::MakeUnique<media::FakeVideoCaptureDeviceFactory>();
+ video_capture_device_factory_ = video_capture_device_factory.get();
+ auto video_capture_system = base::MakeUnique<media::VideoCaptureSystemImpl>(
+ std::move(video_capture_device_factory));
+ auto video_capture_provider =
+ base::MakeUnique<InProcessVideoCaptureProvider>(
+ std::move(video_capture_system),
+ base::ThreadTaskRunnerHandle::Get());
+
+ media_stream_manager_ = base::MakeUnique<MediaStreamManager>(
+ audio_system_.get(), audio_manager_->GetTaskRunner(),
+ std::move(video_capture_provider));
host_ = base::MakeUnique<MediaDevicesDispatcherHost>(
kProcessId, kRenderId, browser_context_.GetMediaDeviceIDSalt(),
media_stream_manager_.get());
@@ -101,6 +116,26 @@ class MediaDevicesDispatcherHostTest : public testing::TestWithParam<GURL> {
~MediaDevicesDispatcherHostTest() override { audio_manager_->Shutdown(); }
void SetUp() override {
+ std::vector<media::FakeVideoCaptureDeviceSettings> fake_video_devices(
+ kNumFakeVideoDevices);
+ // A regular video device
+ fake_video_devices[0].device_id = kNormalVideoDeviceID;
+ fake_video_devices[0].supported_formats = {
+ {gfx::Size(640, 480), 30.0, media::PIXEL_FORMAT_I420},
+ {gfx::Size(800, 600), 30.0, media::PIXEL_FORMAT_I420},
+ {gfx::Size(1020, 780), 30.0, media::PIXEL_FORMAT_I420},
+ {gfx::Size(1920, 1080), 20.0, media::PIXEL_FORMAT_I420},
+ };
+ // A video device that does not report any formats
+ fake_video_devices[1].device_id = kNoFormatsVideoDeviceID;
+ ASSERT_TRUE(fake_video_devices[1].supported_formats.empty());
+ // A video device that reports a 0x0 resolution.
+ fake_video_devices[2].device_id = kZeroResolutionVideoDeviceID;
+ fake_video_devices[2].supported_formats = {
+ {gfx::Size(0, 0), 0.0, media::PIXEL_FORMAT_I420},
+ };
+ video_capture_device_factory_->SetToCustomDevicesConfig(fake_video_devices);
+
base::RunLoop run_loop;
MediaDevicesManager::BoolDeviceTypes devices_to_enumerate;
devices_to_enumerate[MEDIA_DEVICE_TYPE_AUDIO_INPUT] = true;
@@ -133,13 +168,13 @@ class MediaDevicesDispatcherHostTest : public testing::TestWithParam<GURL> {
EXPECT_EQ(kNumFakeVideoDevices, capabilities.size());
EXPECT_EQ(expected_first_device_id, capabilities[0]->device_id);
for (const auto& capability : capabilities) {
+ // Always expect at least one format
EXPECT_GT(capability->formats.size(), 1u);
- EXPECT_GT(capability->formats[0].frame_size.width(), 1);
- EXPECT_GT(capability->formats[0].frame_size.height(), 1);
- EXPECT_GT(capability->formats[0].frame_rate, 1);
- EXPECT_GT(capability->formats[1].frame_size.width(), 1);
- EXPECT_GT(capability->formats[1].frame_size.height(), 1);
- EXPECT_GT(capability->formats[1].frame_rate, 1);
+ for (auto& format : capability->formats) {
+ EXPECT_GE(format.frame_size.width(), 1);
+ EXPECT_GE(format.frame_size.height(), 1);
+ EXPECT_GE(format.frame_rate, 0.0);
+ }
}
}
@@ -180,8 +215,8 @@ class MediaDevicesDispatcherHostTest : public testing::TestWithParam<GURL> {
base::RunLoop run_loop;
host_->EnumerateDevices(
enumerate_audio_input, enumerate_video_input, enumerate_audio_output,
- base::Bind(&MediaDevicesDispatcherHostTest::DevicesEnumerated,
- base::Unretained(this), run_loop.QuitClosure()));
+ base::BindOnce(&MediaDevicesDispatcherHostTest::DevicesEnumerated,
+ base::Unretained(this), run_loop.QuitClosure()));
run_loop.Run();
ASSERT_FALSE(enumerated_devices_.empty());
@@ -314,6 +349,7 @@ class MediaDevicesDispatcherHostTest : public testing::TestWithParam<GURL> {
std::unique_ptr<media::AudioManager> audio_manager_;
std::unique_ptr<media::AudioSystem> audio_system_;
+ media::FakeVideoCaptureDeviceFactory* video_capture_device_factory_;
content::TestBrowserContext browser_context_;
MediaDeviceEnumeration physical_devices_;
url::Origin origin_;
@@ -373,10 +409,9 @@ TEST_P(MediaDevicesDispatcherHostTest, GetVideoInputCapabilities) {
base::RunLoop run_loop;
EXPECT_CALL(*this, MockVideoInputCapabilitiesCallback())
.WillOnce(InvokeWithoutArgs([&run_loop]() { run_loop.Quit(); }));
- host_->GetVideoInputCapabilities(
- base::Bind(
- &MediaDevicesDispatcherHostTest::VideoInputCapabilitiesCallback,
- base::Unretained(this)));
+ host_->GetVideoInputCapabilities(base::BindOnce(
+ &MediaDevicesDispatcherHostTest::VideoInputCapabilitiesCallback,
+ base::Unretained(this)));
run_loop.Run();
}
@@ -384,7 +419,7 @@ TEST_P(MediaDevicesDispatcherHostTest, GetAudioInputCapabilities) {
base::RunLoop run_loop;
EXPECT_CALL(*this, MockAudioInputCapabilitiesCallback())
.WillOnce(InvokeWithoutArgs([&run_loop]() { run_loop.Quit(); }));
- host_->GetAudioInputCapabilities(base::Bind(
+ host_->GetAudioInputCapabilities(base::BindOnce(
&MediaDevicesDispatcherHostTest::AudioInputCapabilitiesCallback,
base::Unretained(this)));
run_loop.Run();
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 9011fca6314..e6690a4102c 100644
--- a/chromium/content/browser/renderer_host/media/media_devices_manager.cc
+++ b/chromium/content/browser/renderer_host/media/media_devices_manager.cc
@@ -273,17 +273,10 @@ void MediaDevicesManager::StartMonitoringOnUIThread() {
// TODO(erikchen): Remove ScopedTracker below once crbug.com/458404 is
// fixed.
- tracked_objects::ScopedTracker tracking_profile2(
- FROM_HERE_WITH_EXPLICIT_FUNCTION(
- "458404 MediaDevicesManager::GetTaskRunner"));
- const scoped_refptr<base::SingleThreadTaskRunner> task_runner =
- audio_system_->GetTaskRunner();
- // TODO(erikchen): Remove ScopedTracker below once crbug.com/458404 is
- // fixed.
tracked_objects::ScopedTracker tracking_profile3(
FROM_HERE_WITH_EXPLICIT_FUNCTION(
"458404 MediaDevicesManager::DeviceMonitorMac::StartMonitoring"));
- browser_main_loop->device_monitor_mac()->StartMonitoring(task_runner);
+ browser_main_loop->device_monitor_mac()->StartMonitoring();
}
#endif
@@ -355,16 +348,15 @@ void MediaDevicesManager::EnumerateAudioDevices(bool is_input) {
is_input ? MEDIA_DEVICE_TYPE_AUDIO_INPUT : MEDIA_DEVICE_TYPE_AUDIO_OUTPUT;
if (use_fake_devices_) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&MediaDevicesManager::DevicesEnumerated,
- weak_factory_.GetWeakPtr(), type,
- GetFakeAudioDevices(is_input)));
+ FROM_HERE, base::BindOnce(&MediaDevicesManager::DevicesEnumerated,
+ weak_factory_.GetWeakPtr(), type,
+ GetFakeAudioDevices(is_input)));
return;
}
audio_system_->GetDeviceDescriptions(
- base::Bind(&MediaDevicesManager::AudioDevicesEnumerated,
- weak_factory_.GetWeakPtr(), type),
- is_input);
+ is_input, base::BindOnce(&MediaDevicesManager::AudioDevicesEnumerated,
+ weak_factory_.GetWeakPtr(), type));
}
void MediaDevicesManager::VideoInputDevicesEnumerated(
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 68046699bff..0858145d3aa 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
@@ -4,25 +4,59 @@
#include "content/browser/renderer_host/media/media_stream_dispatcher_host.h"
-#include <algorithm>
-
-#include "content/browser/browser_main_loop.h"
-#include "content/common/media/media_stream_messages.h"
-#include "content/common/media/media_stream_options.h"
-#include "content/public/browser/render_process_host.h"
-#include "content/public/common/content_switches.h"
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/logging.h"
+#include "content/browser/renderer_host/media/media_stream_manager.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"
#include "url/origin.h"
namespace content {
+namespace {
+
+void BindMediaStreamDispatcherRequest(
+ int render_process_id,
+ int render_frame_id,
+ mojom::MediaStreamDispatcherRequest request) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ RenderFrameHost* render_frame_host =
+ RenderFrameHost::FromID(render_process_id, render_frame_id);
+ if (render_frame_host)
+ render_frame_host->GetRemoteInterfaces()->GetInterface(std::move(request));
+}
+
+} // namespace
+
MediaStreamDispatcherHost::MediaStreamDispatcherHost(
int render_process_id,
const std::string& salt,
MediaStreamManager* media_stream_manager)
- : BrowserMessageFilter(MediaStreamMsgStart),
- render_process_id_(render_process_id),
+ : render_process_id_(render_process_id),
salt_(salt),
- media_stream_manager_(media_stream_manager) {}
+ media_stream_manager_(media_stream_manager) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ bindings_.set_connection_error_handler(base::Bind(
+ &MediaStreamDispatcherHost::CancelAllRequests, base::Unretained(this)));
+}
+
+MediaStreamDispatcherHost::~MediaStreamDispatcherHost() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ bindings_.CloseAllBindings();
+ CancelAllRequests();
+}
+
+void MediaStreamDispatcherHost::BindRequest(
+ mojom::MediaStreamDispatcherHostRequest request) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ bindings_.AddBinding(this, std::move(request));
+}
void MediaStreamDispatcherHost::StreamGenerated(
int render_frame_id,
@@ -30,38 +64,34 @@ void MediaStreamDispatcherHost::StreamGenerated(
const std::string& label,
const StreamDeviceInfoArray& audio_devices,
const StreamDeviceInfoArray& video_devices) {
+ DVLOG(1) << __func__ << " label= " << label;
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DVLOG(1) << "MediaStreamDispatcherHost::StreamGenerated("
- << ", {label = " << label << "})";
- Send(new MediaStreamMsg_StreamGenerated(
- render_frame_id, page_request_id, label, audio_devices, video_devices));
+ GetMediaStreamDispatcherForFrame(render_frame_id)
+ ->OnStreamGenerated(page_request_id, label, audio_devices, video_devices);
}
void MediaStreamDispatcherHost::StreamGenerationFailed(
int render_frame_id,
int page_request_id,
- content::MediaStreamRequestResult result) {
+ MediaStreamRequestResult result) {
+ DVLOG(1) << __func__ << " page_request_id=" << page_request_id
+ << " result=" << result;
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DVLOG(1) << "MediaStreamDispatcherHost::StreamGenerationFailed("
- << ", {page_request_id = " << page_request_id << "}"
- << ", { result= " << result << "})";
- Send(new MediaStreamMsg_StreamGenerationFailed(render_frame_id,
- page_request_id,
- result));
+ GetMediaStreamDispatcherForFrame(render_frame_id)
+ ->OnStreamGenerationFailed(page_request_id, result);
}
void MediaStreamDispatcherHost::DeviceStopped(int render_frame_id,
const std::string& label,
const StreamDeviceInfo& device) {
+ DVLOG(1) << __func__ << " label=" << label << " type=" << device.device.type
+ << " device_id=" << device.device.id;
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DVLOG(1) << "MediaStreamDispatcherHost::DeviceStopped("
- << "{label = " << label << "}, "
- << "{type = " << device.device.type << "}, "
- << "{device_id = " << device.device.id << "})";
- Send(new MediaStreamMsg_DeviceStopped(render_frame_id, label, device));
+ GetMediaStreamDispatcherForFrame(render_frame_id)
+ ->OnDeviceStopped(label, device);
}
void MediaStreamDispatcherHost::DeviceOpened(
@@ -69,121 +99,147 @@ void MediaStreamDispatcherHost::DeviceOpened(
int page_request_id,
const std::string& label,
const StreamDeviceInfo& video_device) {
+ DVLOG(1) << __func__ << " page_request_id=" << page_request_id;
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ GetMediaStreamDispatcherForFrame(render_frame_id)
+ ->OnDeviceOpened(page_request_id, label, video_device);
+}
+
+mojom::MediaStreamDispatcher*
+MediaStreamDispatcherHost::GetMediaStreamDispatcherForFrame(
+ int render_frame_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ auto it = dispatchers_.find(render_frame_id);
+ if (it != dispatchers_.end())
+ return it->second.get();
+
+ mojom::MediaStreamDispatcherPtr dispatcher;
+ auto dispatcher_request = mojo::MakeRequest(&dispatcher);
+ dispatcher.set_connection_error_handler(base::BindOnce(
+ &MediaStreamDispatcherHost::OnMediaStreamDispatcherConnectionError,
+ base::Unretained(this), render_frame_id));
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&BindMediaStreamDispatcherRequest, render_process_id_,
+ render_frame_id, std::move(dispatcher_request)));
+ dispatchers_[render_frame_id] = std::move(dispatcher);
+
+ return dispatchers_[render_frame_id].get();
+}
+
+void MediaStreamDispatcherHost::OnMediaStreamDispatcherConnectionError(
+ int render_frame_id) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DVLOG(1) << "MediaStreamDispatcherHost::DeviceOpened("
- << ", {page_request_id = " << page_request_id << "})";
-
- Send(new MediaStreamMsg_DeviceOpened(
- render_frame_id, page_request_id, label, video_device));
-}
-
-bool MediaStreamDispatcherHost::OnMessageReceived(const IPC::Message& message) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(MediaStreamDispatcherHost, message)
- IPC_MESSAGE_HANDLER(MediaStreamHostMsg_GenerateStream, OnGenerateStream)
- IPC_MESSAGE_HANDLER(MediaStreamHostMsg_CancelGenerateStream,
- OnCancelGenerateStream)
- IPC_MESSAGE_HANDLER(MediaStreamHostMsg_StopStreamDevice,
- OnStopStreamDevice)
- IPC_MESSAGE_HANDLER(MediaStreamHostMsg_OpenDevice,
- OnOpenDevice)
- IPC_MESSAGE_HANDLER(MediaStreamHostMsg_CloseDevice,
- OnCloseDevice)
- IPC_MESSAGE_HANDLER(MediaStreamHostMsg_SetCapturingLinkSecured,
- OnSetCapturingLinkSecured)
- IPC_MESSAGE_HANDLER(MediaStreamHostMsg_StreamStarted, OnStreamStarted)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
-}
-
-void MediaStreamDispatcherHost::OnChannelClosing() {
- DVLOG(1) << "MediaStreamDispatcherHost::OnChannelClosing";
-
- // Since the IPC sender is gone, close all requesting/requested streams.
+
+ dispatchers_.erase(render_frame_id);
+}
+
+void MediaStreamDispatcherHost::CancelAllRequests() {
+ if (!bindings_.empty())
+ return;
+
media_stream_manager_->CancelAllRequests(render_process_id_);
}
-MediaStreamDispatcherHost::~MediaStreamDispatcherHost() {
+void MediaStreamDispatcherHost::DeviceOpenFailed(int render_frame_id,
+ int page_request_id) {
+ DVLOG(1) << __func__ << " page_request_id=" << page_request_id;
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ GetMediaStreamDispatcherForFrame(render_frame_id)
+ ->OnDeviceOpenFailed(page_request_id);
}
-void MediaStreamDispatcherHost::OnGenerateStream(
- int render_frame_id,
- int page_request_id,
+void MediaStreamDispatcherHost::GenerateStream(
+ int32_t render_frame_id,
+ int32_t page_request_id,
const StreamControls& controls,
const url::Origin& security_origin,
bool user_gesture) {
- DVLOG(1) << "MediaStreamDispatcherHost::OnGenerateStream(" << render_frame_id
- << ", " << page_request_id << ", ["
- << " audio:" << controls.audio.requested
- << " video:" << controls.video.requested << " ], " << security_origin
- << ", " << user_gesture << ")";
+ DVLOG(1) << __func__ << " render_frame_id=" << render_frame_id
+ << " page_request_id=" << page_request_id
+ << " audio=" << controls.audio.requested
+ << " video=" << controls.video.requested
+ << " security_origin=" << security_origin
+ << " user_gesture=" << user_gesture;
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (!MediaStreamManager::IsOriginAllowed(render_process_id_, security_origin))
+ if (!MediaStreamManager::IsOriginAllowed(render_process_id_,
+ security_origin)) {
+ StreamGenerationFailed(render_frame_id, page_request_id,
+ MEDIA_DEVICE_INVALID_SECURITY_ORIGIN_DEPRECATED);
return;
+ }
media_stream_manager_->GenerateStream(
this, render_process_id_, render_frame_id, salt_, page_request_id,
controls, security_origin, user_gesture);
}
-void MediaStreamDispatcherHost::OnCancelGenerateStream(int render_frame_id,
- int page_request_id) {
- DVLOG(1) << "MediaStreamDispatcherHost::OnCancelGenerateStream("
- << render_frame_id << ", "
- << page_request_id << ")";
+void MediaStreamDispatcherHost::CancelGenerateStream(int render_frame_id,
+ int page_request_id) {
+ DVLOG(1) << __func__ << " render_frame_id=" << render_frame_id
+ << " page_request_id=" << page_request_id;
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
media_stream_manager_->CancelRequest(render_process_id_, render_frame_id,
page_request_id);
}
-void MediaStreamDispatcherHost::OnStopStreamDevice(
- int render_frame_id,
- const std::string& device_id) {
- DVLOG(1) << "MediaStreamDispatcherHost::OnStopStreamDevice("
- << render_frame_id << ", "
- << device_id << ")";
+void MediaStreamDispatcherHost::StopStreamDevice(int32_t render_frame_id,
+ const std::string& device_id) {
+ DVLOG(1) << __func__ << " render_frame_id=" << render_frame_id
+ << " device_id=" << device_id;
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
media_stream_manager_->StopStreamDevice(render_process_id_, render_frame_id,
device_id);
}
-void MediaStreamDispatcherHost::OnOpenDevice(
- int render_frame_id,
- int page_request_id,
- const std::string& device_id,
- MediaStreamType type,
- const url::Origin& security_origin) {
- DVLOG(1) << "MediaStreamDispatcherHost::OnOpenDevice(" << render_frame_id
- << ", " << page_request_id << ", device_id: " << device_id.c_str()
- << ", type: " << type << ", " << security_origin << ")";
-
- if (!MediaStreamManager::IsOriginAllowed(render_process_id_, security_origin))
+void MediaStreamDispatcherHost::OpenDevice(int32_t render_frame_id,
+ int32_t page_request_id,
+ const std::string& device_id,
+ MediaStreamType type,
+ const url::Origin& security_origin) {
+ DVLOG(1) << __func__ << " render_frame_id=" << render_frame_id
+ << " page_request_id=" << page_request_id
+ << " device_id=" << device_id << " type=" << type
+ << " security_origin=" << security_origin;
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (!MediaStreamManager::IsOriginAllowed(render_process_id_,
+ security_origin)) {
+ DeviceOpenFailed(render_frame_id, page_request_id);
return;
+ }
media_stream_manager_->OpenDevice(this, render_process_id_, render_frame_id,
salt_, page_request_id, device_id, type,
security_origin);
}
-void MediaStreamDispatcherHost::OnCloseDevice(
- int render_frame_id,
- const std::string& label) {
- DVLOG(1) << "MediaStreamDispatcherHost::OnCloseDevice("
- << render_frame_id << ", "
- << label << ")";
+void MediaStreamDispatcherHost::CloseDevice(const std::string& label) {
+ DVLOG(1) << __func__ << " label= " << label;
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
media_stream_manager_->CancelRequest(label);
}
-void MediaStreamDispatcherHost::OnSetCapturingLinkSecured(int session_id,
- MediaStreamType type,
- bool is_secure) {
+void MediaStreamDispatcherHost::SetCapturingLinkSecured(int32_t session_id,
+ MediaStreamType type,
+ bool is_secure) {
+ DVLOG(1) << __func__ << " session_id=" << session_id << " type=" << type
+ << " is_secure=" << is_secure;
DCHECK_CURRENTLY_ON(BrowserThread::IO);
media_stream_manager_->SetCapturingLinkSecured(render_process_id_, session_id,
type, is_secure);
}
-void MediaStreamDispatcherHost::OnStreamStarted(const std::string& label) {
+void MediaStreamDispatcherHost::StreamStarted(const std::string& label) {
+ DVLOG(1) << __func__ << " label= " << label;
DCHECK_CURRENTLY_ON(BrowserThread::IO);
media_stream_manager_->OnStreamStarted(label);
diff --git a/chromium/content/browser/renderer_host/media/media_stream_dispatcher_host.h b/chromium/content/browser/renderer_host/media/media_stream_dispatcher_host.h
index f74da885e72..614cb6deaf4 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_dispatcher_host.h
+++ b/chromium/content/browser/renderer_host/media/media_stream_dispatcher_host.h
@@ -7,20 +7,18 @@
#include <map>
#include <string>
-#include <utility>
-#include <vector>
#include "base/macros.h"
-#include "content/browser/renderer_host/media/media_stream_manager.h"
#include "content/browser/renderer_host/media/media_stream_requester.h"
#include "content/common/content_export.h"
+#include "content/common/media/media_stream.mojom.h"
#include "content/common/media/media_stream_options.h"
-#include "content/public/browser/browser_message_filter.h"
-#include "content/public/browser/resource_context.h"
+#include "mojo/public/cpp/bindings/binding_set.h"
namespace url {
class Origin;
}
+
namespace content {
class MediaStreamManager;
@@ -28,12 +26,16 @@ class MediaStreamManager;
// MediaStreamDispatcherHost is a delegate for Media Stream API messages used by
// MediaStreamImpl. There is one MediaStreamDispatcherHost per
// RenderProcessHost, the former owned by the latter.
-class CONTENT_EXPORT MediaStreamDispatcherHost : public BrowserMessageFilter,
- public MediaStreamRequester {
+class CONTENT_EXPORT MediaStreamDispatcherHost
+ : public mojom::MediaStreamDispatcherHost,
+ public MediaStreamRequester {
public:
MediaStreamDispatcherHost(int render_process_id,
const std::string& salt,
MediaStreamManager* media_stream_manager);
+ ~MediaStreamDispatcherHost() override;
+
+ void BindRequest(mojom::MediaStreamDispatcherHostRequest request);
// MediaStreamRequester implementation.
void StreamGenerated(int render_frame_id,
@@ -41,10 +43,9 @@ class CONTENT_EXPORT MediaStreamDispatcherHost : public BrowserMessageFilter,
const std::string& label,
const StreamDeviceInfoArray& audio_devices,
const StreamDeviceInfoArray& video_devices) override;
- void StreamGenerationFailed(
- int render_frame_id,
- int page_request_id,
- content::MediaStreamRequestResult result) override;
+ void StreamGenerationFailed(int render_frame_id,
+ int page_request_id,
+ MediaStreamRequestResult result) override;
void DeviceStopped(int render_frame_id,
const std::string& label,
const StreamDeviceInfo& device) override;
@@ -53,49 +54,47 @@ class CONTENT_EXPORT MediaStreamDispatcherHost : public BrowserMessageFilter,
const std::string& label,
const StreamDeviceInfo& video_device) override;
- // BrowserMessageFilter implementation.
- bool OnMessageReceived(const IPC::Message& message) override;
- void OnChannelClosing() override;
-
- protected:
- ~MediaStreamDispatcherHost() override;
+ void SetMediaStreamDispatcherForTesting(
+ int render_frame_id,
+ mojom::MediaStreamDispatcherPtr dispatcher) {
+ dispatchers_[render_frame_id] = std::move(dispatcher);
+ }
private:
friend class MockMediaStreamDispatcherHost;
- void OnGenerateStream(int render_frame_id,
- int page_request_id,
- const StreamControls& controls,
- const url::Origin& security_origin,
- bool user_gesture);
- void OnCancelGenerateStream(int render_frame_id,
- int page_request_id);
- void OnStopStreamDevice(int render_frame_id,
- const std::string& device_id);
-
- void OnOpenDevice(int render_frame_id,
- int page_request_id,
- const std::string& device_id,
- MediaStreamType type,
- const url::Origin& security_origin);
-
- void OnCloseDevice(int render_frame_id,
- const std::string& label);
-
- void StoreRequest(int render_frame_id,
- int page_request_id,
- const std::string& label);
-
- // IPC message handler: Set if the video capturing is secure.
- void OnSetCapturingLinkSecured(int session_id,
- content::MediaStreamType type,
- bool is_secure);
-
- void OnStreamStarted(const std::string& label);
-
- int render_process_id_;
+ mojom::MediaStreamDispatcher* GetMediaStreamDispatcherForFrame(
+ int render_frame_id);
+ void OnMediaStreamDispatcherConnectionError(int render_frame_id);
+ void CancelAllRequests();
+ void DeviceOpenFailed(int render_frame_id, int page_request_id);
+
+ // mojom::MediaStreamDispatcherHost implementation
+ void GenerateStream(int32_t render_frame_id,
+ int32_t request_id,
+ const StreamControls& controls,
+ const url::Origin& security_origin,
+ bool user_gesture) override;
+ void CancelGenerateStream(int32_t render_frame_id,
+ int32_t request_id) override;
+ void StopStreamDevice(int32_t render_frame_id,
+ const std::string& device_id) override;
+ void OpenDevice(int32_t render_frame_id,
+ int32_t request_id,
+ const std::string& device_id,
+ MediaStreamType type,
+ const url::Origin& security_origin) override;
+ void CloseDevice(const std::string& label) override;
+ void SetCapturingLinkSecured(int32_t session_id,
+ MediaStreamType type,
+ bool is_secure) override;
+ void StreamStarted(const std::string& label) override;
+
+ const int render_process_id_;
std::string salt_;
MediaStreamManager* media_stream_manager_;
+ std::map<int, mojom::MediaStreamDispatcherPtr> dispatchers_;
+ mojo::BindingSet<mojom::MediaStreamDispatcherHost> bindings_;
DISALLOW_COPY_AND_ASSIGN(MediaStreamDispatcherHost);
};
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 5fb06440245..18e6e96aa0a 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
@@ -13,35 +13,27 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/command_line.h"
-#include "base/location.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/system_monitor/system_monitor.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
-#include "content/browser/browser_thread_impl.h"
#include "content/browser/renderer_host/media/audio_input_device_manager.h"
#include "content/browser/renderer_host/media/media_stream_manager.h"
#include "content/browser/renderer_host/media/media_stream_ui_proxy.h"
#include "content/browser/renderer_host/media/mock_video_capture_provider.h"
#include "content/browser/renderer_host/media/video_capture_manager.h"
-#include "content/common/media/media_stream_messages.h"
#include "content/common/media/media_stream_options.h"
-#include "content/public/browser/browser_context.h"
#include "content/public/browser/media_device_id.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_browser_thread_bundle.h"
-#include "content/test/test_content_browser_client.h"
-#include "content/test/test_content_client.h"
-#include "ipc/ipc_message_macros.h"
#include "media/audio/audio_device_description.h"
#include "media/audio/audio_system_impl.h"
#include "media/audio/mock_audio_manager.h"
#include "media/audio/test_audio_thread.h"
#include "media/base/media_switches.h"
-#include "media/capture/video/fake_video_capture_device_factory.h"
-#include "net/url_request/url_request_context.h"
+#include "mojo/public/cpp/bindings/binding_set.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
@@ -52,11 +44,9 @@
#endif
using ::testing::_;
-using ::testing::DeleteArg;
-using ::testing::DoAll;
using ::testing::InSequence;
using ::testing::Invoke;
-using ::testing::Return;
+using ::testing::InvokeWithoutArgs;
using ::testing::SaveArg;
namespace content {
@@ -87,25 +77,24 @@ void AudioInputDevicesEnumerated(base::Closure quit_closure,
} // anonymous namespace
class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost,
- public TestContentBrowserClient {
+ public mojom::MediaStreamDispatcher {
public:
MockMediaStreamDispatcherHost(
const std::string& salt,
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
MediaStreamManager* manager)
: MediaStreamDispatcherHost(kProcessId, salt, manager),
- task_runner_(task_runner),
- current_ipc_(NULL) {}
+ task_runner_(task_runner) {}
+ ~MockMediaStreamDispatcherHost() override {}
// A list of mock methods.
- MOCK_METHOD4(OnStreamGenerated,
- void(int routing_id, int request_id, int audio_array_size,
+ MOCK_METHOD3(OnStreamGenerationSuccess,
+ void(int request_id,
+ int audio_array_size,
int video_array_size));
- MOCK_METHOD3(OnStreamGenerationFailed, void(int routing_id,
- int request_id,
- MediaStreamRequestResult result));
- MOCK_METHOD1(OnDeviceStopped, void(int routing_id));
- MOCK_METHOD2(OnDeviceOpened, void(int routing_id, int request_id));
+ MOCK_METHOD2(OnStreamGenerationFailure,
+ void(int request_id, MediaStreamRequestResult result));
+ MOCK_METHOD0(OnDeviceStopSuccess, void());
// Accessor to private functions.
void OnGenerateStream(int render_frame_id,
@@ -114,13 +103,13 @@ class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost,
const url::Origin& security_origin,
const base::Closure& quit_closure) {
quit_closures_.push(quit_closure);
- MediaStreamDispatcherHost::OnGenerateStream(
- render_frame_id, page_request_id, controls, security_origin, false);
+ MediaStreamDispatcherHost::GenerateStream(render_frame_id, page_request_id,
+ controls, security_origin, false);
}
void OnStopStreamDevice(int render_frame_id,
const std::string& device_id) {
- MediaStreamDispatcherHost::OnStopStreamDevice(render_frame_id, device_id);
+ MediaStreamDispatcherHost::StopStreamDevice(render_frame_id, device_id);
}
void OnOpenDevice(int render_frame_id,
@@ -130,12 +119,44 @@ class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost,
const url::Origin& security_origin,
const base::Closure& quit_closure) {
quit_closures_.push(quit_closure);
- MediaStreamDispatcherHost::OnOpenDevice(
- render_frame_id, page_request_id, device_id, type, security_origin);
+ MediaStreamDispatcherHost::OpenDevice(render_frame_id, page_request_id,
+ device_id, type, security_origin);
}
void OnStreamStarted(const std::string label) {
- MediaStreamDispatcherHost::OnStreamStarted(label);
+ MediaStreamDispatcherHost::StreamStarted(label);
+ }
+
+ // mojom::MediaStreamDispatcher implementation.
+ void OnStreamGenerated(int32_t request_id,
+ const std::string& label,
+ const StreamDeviceInfoArray& audio_array,
+ const StreamDeviceInfoArray& video_array) override {
+ OnStreamGeneratedInternal(request_id, label, audio_array, video_array);
+ }
+
+ void OnStreamGenerationFailed(int32_t request_id,
+ MediaStreamRequestResult result) override {
+ OnStreamGenerationFailedInternal(request_id, result);
+ }
+
+ void OnDeviceOpened(int32_t request_id,
+ const std::string& label,
+ const StreamDeviceInfo& device_info) override {
+ OnDeviceOpenedInternal(request_id, label, device_info);
+ }
+
+ void OnDeviceOpenFailed(int32_t request_id) override {}
+
+ void OnDeviceStopped(const std::string& label,
+ const StreamDeviceInfo& device_info) override {
+ OnDeviceStoppedInternal(label, device_info);
+ }
+
+ mojom::MediaStreamDispatcherPtr CreateInterfacePtrAndBind() {
+ mojom::MediaStreamDispatcherPtr dispatcher;
+ bindings_.AddBinding(this, mojo::MakeRequest(&dispatcher));
+ return dispatcher;
}
std::string label_;
@@ -144,42 +165,14 @@ class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost,
StreamDeviceInfo opened_device_;
private:
- ~MockMediaStreamDispatcherHost() override {}
-
- // This method is used to dispatch IPC messages to the renderer. We intercept
- // these messages here and dispatch to our mock methods to verify the
- // conversation between this object and the renderer.
- bool Send(IPC::Message* message) override {
- CHECK(message);
- current_ipc_ = message;
-
- // In this method we dispatch the messages to the corresponding handlers as
- // if we are the renderer.
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(MockMediaStreamDispatcherHost, *message)
- IPC_MESSAGE_HANDLER(MediaStreamMsg_StreamGenerated,
- OnStreamGeneratedInternal)
- IPC_MESSAGE_HANDLER(MediaStreamMsg_StreamGenerationFailed,
- OnStreamGenerationFailedInternal)
- IPC_MESSAGE_HANDLER(MediaStreamMsg_DeviceStopped, OnDeviceStoppedInternal)
- IPC_MESSAGE_HANDLER(MediaStreamMsg_DeviceOpened, OnDeviceOpenedInternal)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- EXPECT_TRUE(handled);
-
- delete message;
- current_ipc_ = NULL;
- return true;
- }
-
// These handler methods do minimal things and delegate to the mock methods.
void OnStreamGeneratedInternal(
int request_id,
std::string label,
StreamDeviceInfoArray audio_device_list,
StreamDeviceInfoArray video_device_list) {
- OnStreamGenerated(current_ipc_->routing_id(), request_id,
- audio_device_list.size(), video_device_list.size());
+ OnStreamGenerationSuccess(request_id, audio_device_list.size(),
+ video_device_list.size());
// Simulate the stream started event back to host for UI testing.
OnStreamStarted(label);
@@ -193,27 +186,26 @@ class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost,
video_devices_ = video_device_list;
}
- void OnStreamGenerationFailedInternal(
- int request_id,
- content::MediaStreamRequestResult result) {
- OnStreamGenerationFailed(current_ipc_->routing_id(), request_id, result);
+ void OnStreamGenerationFailedInternal(int request_id,
+ MediaStreamRequestResult result) {
+ OnStreamGenerationFailure(request_id, result);
if (!quit_closures_.empty()) {
base::Closure quit_closure = quit_closures_.front();
quit_closures_.pop();
task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&quit_closure));
}
- label_ = "";
+ label_.clear();
}
void OnDeviceStoppedInternal(const std::string& label,
- const content::StreamDeviceInfo& device) {
+ const StreamDeviceInfo& device) {
if (IsVideoMediaType(device.device.type))
EXPECT_TRUE(StreamDeviceInfo::IsEqual(device, video_devices_[0]));
if (IsAudioInputMediaType(device.device.type))
EXPECT_TRUE(StreamDeviceInfo::IsEqual(device, audio_devices_[0]));
- OnDeviceStopped(current_ipc_->routing_id());
+ OnDeviceStopSuccess();
}
void OnDeviceOpenedInternal(int request_id,
@@ -226,8 +218,8 @@ class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost,
opened_device_ = device;
}
+ mojo::BindingSet<mojom::MediaStreamDispatcher> bindings_;
const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
- IPC::Message* current_ipc_;
std::queue<base::Closure> quit_closures_;
};
@@ -246,8 +238,7 @@ class MockMediaStreamUIProxy : public FakeMediaStreamUIProxy {
class MediaStreamDispatcherHostTest : public testing::Test {
public:
MediaStreamDispatcherHostTest()
- : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
- old_browser_client_(NULL),
+ : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP),
origin_(GURL("https://test.com")) {
audio_manager_.reset(new media::MockAudioManager(
base::MakeUnique<media::TestAudioThread>()));
@@ -260,16 +251,15 @@ class MediaStreamDispatcherHostTest : public testing::Test {
mock_video_capture_provider_ = mock_video_capture_provider.get();
// Create our own MediaStreamManager.
media_stream_manager_ = base::MakeUnique<MediaStreamManager>(
- audio_system_.get(), std::move(mock_video_capture_provider));
+ audio_system_.get(), audio_manager_->GetTaskRunner(),
+ std::move(mock_video_capture_provider));
- host_ = new MockMediaStreamDispatcherHost(
+ host_ = base::MakeUnique<MockMediaStreamDispatcherHost>(
browser_context_.GetMediaDeviceIDSalt(),
base::ThreadTaskRunnerHandle::Get(), media_stream_manager_.get());
-
- // Use the fake content client and browser.
- content_client_.reset(new TestContentClient());
- SetContentClient(content_client_.get());
- old_browser_client_ = SetBrowserClientForTesting(host_.get());
+ mojom::MediaStreamDispatcherPtr dispatcher =
+ host_->CreateInterfacePtrAndBind();
+ host_->SetMediaStreamDispatcherForTesting(kRenderId, std::move(dispatcher));
#if defined(OS_CHROMEOS)
chromeos::CrasAudioHandler::InitializeForTesting();
@@ -322,7 +312,7 @@ class MediaStreamDispatcherHostTest : public testing::Test {
ASSERT_GT(audio_device_descriptions_.size(), 0u);
}
- void TearDown() override { host_->OnChannelClosing(); }
+ void TearDown() override { host_.reset(); }
protected:
virtual void SetupFakeUI(bool expect_started) {
@@ -343,10 +333,9 @@ class MediaStreamDispatcherHostTest : public testing::Test {
: 0;
int expected_video_array_size =
(controls.video.requested && !stub_video_device_ids_.empty()) ? 1 : 0;
- EXPECT_CALL(*host_.get(), OnStreamGenerated(render_frame_id,
- page_request_id,
- expected_audio_array_size,
- expected_video_array_size));
+ EXPECT_CALL(*host_, OnStreamGenerationSuccess(page_request_id,
+ expected_audio_array_size,
+ expected_video_array_size));
host_->OnGenerateStream(render_frame_id, page_request_id, controls, origin_,
run_loop.QuitClosure());
run_loop.Run();
@@ -362,10 +351,8 @@ class MediaStreamDispatcherHostTest : public testing::Test {
const StreamControls& controls,
MediaStreamRequestResult expected_result) {
base::RunLoop run_loop;
- EXPECT_CALL(*host_.get(),
- OnStreamGenerationFailed(render_frame_id,
- page_request_id,
- expected_result));
+ EXPECT_CALL(*host_,
+ OnStreamGenerationFailure(page_request_id, expected_result));
host_->OnGenerateStream(render_frame_id, page_request_id, controls,
origin_, run_loop.QuitClosure());
run_loop.Run();
@@ -409,17 +396,17 @@ class MediaStreamDispatcherHostTest : public testing::Test {
media::AudioDeviceDescriptions::const_iterator audio_it =
audio_device_descriptions_.begin();
for (; audio_it != audio_device_descriptions_.end(); ++audio_it) {
- if (content::DoesMediaDeviceIDMatchHMAC(
- browser_context_.GetMediaDeviceIDSalt(), origin,
- devices[i].device.id, audio_it->unique_id)) {
+ if (DoesMediaDeviceIDMatchHMAC(browser_context_.GetMediaDeviceIDSalt(),
+ origin, devices[i].device.id,
+ audio_it->unique_id)) {
EXPECT_FALSE(found_match);
found_match = true;
}
}
for (const std::string& device_id : stub_video_device_ids_) {
- if (content::DoesMediaDeviceIDMatchHMAC(
- browser_context_.GetMediaDeviceIDSalt(), origin,
- devices[i].device.id, device_id)) {
+ if (DoesMediaDeviceIDMatchHMAC(browser_context_.GetMediaDeviceIDSalt(),
+ origin, devices[i].device.id,
+ device_id)) {
EXPECT_FALSE(found_match);
found_match = true;
}
@@ -448,15 +435,13 @@ class MediaStreamDispatcherHostTest : public testing::Test {
return true;
}
- scoped_refptr<MockMediaStreamDispatcherHost> host_;
+ std::unique_ptr<MockMediaStreamDispatcherHost> host_;
std::unique_ptr<MediaStreamManager> media_stream_manager_;
- content::TestBrowserThreadBundle thread_bundle_;
+ TestBrowserThreadBundle thread_bundle_;
std::unique_ptr<media::AudioManager> audio_manager_;
std::unique_ptr<media::AudioSystem> audio_system_;
MockMediaStreamUIProxy* stream_ui_;
- ContentBrowserClient* old_browser_client_;
- std::unique_ptr<ContentClient> content_client_;
- content::TestBrowserContext browser_context_;
+ TestBrowserContext browser_context_;
media::AudioDeviceDescriptions audio_device_descriptions_;
std::vector<std::string> stub_video_device_ids_;
url::Origin origin_;
@@ -506,7 +491,7 @@ TEST_F(MediaStreamDispatcherHostTest, GenerateStreamWithAudioAndVideo) {
TEST_F(MediaStreamDispatcherHostTest, GenerateStreamWithDepthVideo) {
// We specify to generate both audio and video stream.
StreamControls controls(true, true);
- std::string source_id = content::GetHMACForMediaDeviceID(
+ std::string source_id = GetHMACForMediaDeviceID(
browser_context_.GetMediaDeviceIDSalt(), origin_, kDepthVideoDeviceId);
// |source_id| corresponds to the depth device. As we can generate only one
// video stream using GenerateStreamAndWaitForResult, we use
@@ -608,6 +593,10 @@ TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsDifferentRenderId) {
const int session_id1 = host_->video_devices_.front().session_id;
// Generate second stream from another render frame.
+ mojom::MediaStreamDispatcherPtr dispatcher =
+ host_->CreateInterfacePtrAndBind();
+ host_->SetMediaStreamDispatcherForTesting(kRenderId + 1,
+ std::move(dispatcher));
SetupFakeUI(true);
GenerateStreamAndWaitForResult(kRenderId + 1, kPageRequestId + 1, controls);
@@ -632,12 +621,10 @@ TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsWithoutWaiting) {
SetupFakeUI(true);
{
InSequence s;
- EXPECT_CALL(*host_.get(),
- OnStreamGenerated(kRenderId, kPageRequestId, 0, 1));
+ EXPECT_CALL(*host_, OnStreamGenerationSuccess(kPageRequestId, 0, 1));
// Generate second stream.
- EXPECT_CALL(*host_.get(),
- OnStreamGenerated(kRenderId, kPageRequestId + 1, 0, 1));
+ EXPECT_CALL(*host_, OnStreamGenerationSuccess(kPageRequestId + 1, 0, 1));
}
base::RunLoop run_loop1;
base::RunLoop run_loop2;
@@ -659,7 +646,7 @@ TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsWithSourceId) {
media::AudioDeviceDescriptions::const_iterator audio_it =
audio_device_descriptions_.begin();
for (; audio_it != audio_device_descriptions_.end(); ++audio_it) {
- std::string source_id = content::GetHMACForMediaDeviceID(
+ std::string source_id = GetHMACForMediaDeviceID(
browser_context_.GetMediaDeviceIDSalt(), origin_, audio_it->unique_id);
ASSERT_FALSE(source_id.empty());
StreamControls controls(true, true);
@@ -671,7 +658,7 @@ TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsWithSourceId) {
}
for (const std::string& device_id : stub_video_device_ids_) {
- std::string source_id = content::GetHMACForMediaDeviceID(
+ std::string source_id = GetHMACForMediaDeviceID(
browser_context_.GetMediaDeviceIDSalt(), origin_, device_id);
ASSERT_FALSE(source_id.empty());
StreamControls controls(true, true);
@@ -781,8 +768,7 @@ TEST_F(MediaStreamDispatcherHostTest,
EXPECT_EQ(host_->video_devices_.size(), 1u);
// Generate a second stream.
- EXPECT_CALL(*host_.get(),
- OnStreamGenerated(kRenderId, kPageRequestId + 1, 0, 1));
+ EXPECT_CALL(*host_, OnStreamGenerationSuccess(kPageRequestId + 1, 0, 1));
base::RunLoop run_loop1;
host_->OnGenerateStream(kRenderId, kPageRequestId + 1, controls, origin_,
@@ -796,7 +782,7 @@ TEST_F(MediaStreamDispatcherHostTest,
EXPECT_EQ(host_->video_devices_.size(), 1u);
}
-TEST_F(MediaStreamDispatcherHostTest, CancelPendingStreamsOnChannelClosing) {
+TEST_F(MediaStreamDispatcherHostTest, CancelPendingStreams) {
StreamControls controls(false, true);
base::RunLoop run_loop;
@@ -808,12 +794,11 @@ TEST_F(MediaStreamDispatcherHostTest, CancelPendingStreamsOnChannelClosing) {
run_loop.QuitClosure());
}
- // Calling OnChannelClosing() to cancel all the pending requests.
- host_->OnChannelClosing();
+ media_stream_manager_->CancelAllRequests(kProcessId);
run_loop.RunUntilIdle();
}
-TEST_F(MediaStreamDispatcherHostTest, StopGeneratedStreamsOnChannelClosing) {
+TEST_F(MediaStreamDispatcherHostTest, StopGeneratedStreams) {
StreamControls controls(false, true);
// Create first group of streams.
@@ -823,8 +808,7 @@ TEST_F(MediaStreamDispatcherHostTest, StopGeneratedStreamsOnChannelClosing) {
GenerateStreamAndWaitForResult(kRenderId, kPageRequestId + i, controls);
}
- // Calling OnChannelClosing() to cancel all the pending/generated streams.
- host_->OnChannelClosing();
+ media_stream_manager_->CancelAllRequests(kProcessId);
base::RunLoop().RunUntilIdle();
}
@@ -832,8 +816,7 @@ TEST_F(MediaStreamDispatcherHostTest, CloseFromUI) {
StreamControls controls(false, true);
base::Closure close_callback;
- std::unique_ptr<MockMediaStreamUIProxy> stream_ui(
- new MockMediaStreamUIProxy());
+ auto stream_ui = base::MakeUnique<MockMediaStreamUIProxy>();
EXPECT_CALL(*stream_ui, MockOnStarted(_))
.WillOnce(SaveArg<0>(&close_callback));
media_stream_manager_->UseFakeUIForTests(std::move(stream_ui));
@@ -844,7 +827,7 @@ TEST_F(MediaStreamDispatcherHostTest, CloseFromUI) {
EXPECT_EQ(host_->video_devices_.size(), 1u);
ASSERT_FALSE(close_callback.is_null());
- EXPECT_CALL(*host_.get(), OnDeviceStopped(kRenderId));
+ EXPECT_CALL(*host_, OnDeviceStopSuccess());
close_callback.Run();
base::RunLoop().RunUntilIdle();
}
@@ -861,8 +844,8 @@ TEST_F(MediaStreamDispatcherHostTest, VideoDeviceUnplugged) {
stub_video_device_ids_.clear();
base::RunLoop run_loop;
- EXPECT_CALL(*host_.get(), OnDeviceStopped(kRenderId))
- .WillOnce(testing::InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
+ EXPECT_CALL(*host_, OnDeviceStopSuccess())
+ .WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
media_stream_manager_->media_devices_manager()->OnDevicesChanged(
base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE);
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 661136c6f5a..74f43a3ccd7 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_manager.cc
+++ b/chromium/content/browser/renderer_host/media/media_stream_manager.cc
@@ -27,6 +27,7 @@
#include "base/threading/thread_local.h"
#include "build/build_config.h"
#include "content/browser/child_process_security_policy_impl.h"
+#include "content/browser/gpu/browser_gpu_memory_buffer_manager.h"
#include "content/browser/renderer_host/media/audio_input_device_manager.h"
#include "content/browser/renderer_host/media/in_process_video_capture_provider.h"
#include "content/browser/renderer_host/media/media_capture_devices_impl.h"
@@ -399,11 +400,14 @@ void MediaStreamManager::SendMessageToNativeLog(const std::string& message) {
msm->AddLogMessageOnIOThread(message);
}
-MediaStreamManager::MediaStreamManager(media::AudioSystem* audio_system)
- : MediaStreamManager(audio_system, nullptr) {}
+MediaStreamManager::MediaStreamManager(
+ media::AudioSystem* audio_system,
+ scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner)
+ : MediaStreamManager(audio_system, std::move(audio_task_runner), nullptr) {}
MediaStreamManager::MediaStreamManager(
media::AudioSystem* audio_system,
+ scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner,
std::unique_ptr<VideoCaptureProvider> video_capture_provider)
: audio_system_(audio_system),
#if defined(OS_WIN)
@@ -415,7 +419,7 @@ MediaStreamManager::MediaStreamManager(
if (!video_capture_provider) {
scoped_refptr<base::SingleThreadTaskRunner> device_task_runner =
- audio_system_->GetTaskRunner();
+ std::move(audio_task_runner);
#if defined(OS_WIN)
// Use an STA Video Capture Thread to try to avoid crashes on enumeration of
// buggy third party Direct Show modules, http://crbug.com/428958.
@@ -434,7 +438,8 @@ MediaStreamManager::MediaStreamManager(
video_capture_provider = InProcessVideoCaptureProvider::CreateInstance(
base::MakeUnique<media::VideoCaptureSystemImpl>(
media::VideoCaptureDeviceFactory::CreateFactory(
- BrowserThread::GetTaskRunnerForThread(BrowserThread::UI))),
+ BrowserThread::GetTaskRunnerForThread(BrowserThread::UI),
+ BrowserGpuMemoryBufferManager::current())),
std::move(device_task_runner));
}
}
@@ -1175,10 +1180,10 @@ bool MediaStreamManager::FindExistingRequestedDeviceInfo(
*existing_device_info = device_info;
// Make sure that the audio |effects| reflect what the request
// is set to and not what the capabilities are.
- FilterAudioEffects(request->controls,
- &existing_device_info->device.input.effects);
- EnableHotwordEffect(request->controls,
- &existing_device_info->device.input.effects);
+ int effects = existing_device_info->device.input.effects();
+ FilterAudioEffects(request->controls, &effects);
+ EnableHotwordEffect(request->controls, &effects);
+ existing_device_info->device.input.set_effects(effects);
*existing_request_state = request->state(device_info.device.type);
return true;
}
@@ -1308,6 +1313,7 @@ void MediaStreamManager::Opened(MediaStreamType stream_type,
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DVLOG(1) << "Opened({stream_type = " << stream_type << "} "
<< "{capture_session_id = " << capture_session_id << "})";
+
// Find the request(s) containing this device and mark it as used.
// It can be used in several requests since the same device can be
// requested from the same web page.
@@ -1336,10 +1342,10 @@ void MediaStreamManager::Opened(MediaStreamType stream_type,
// parameters to the default settings (including supported effects),
// we need to adjust those settings here according to what the
// request asks for.
- FilterAudioEffects(request->controls,
- &device_info.device.input.effects);
- EnableHotwordEffect(request->controls,
- &device_info.device.input.effects);
+ int effects = device_info.device.input.effects();
+ FilterAudioEffects(request->controls, &effects);
+ EnableHotwordEffect(request->controls, &effects);
+ device_info.device.input.set_effects(effects);
device_info.device.matched_output = info->device.matched_output;
}
@@ -1504,8 +1510,14 @@ void MediaStreamManager::HandleAccessRequestResponse(
if (sample_rate <= 0 || sample_rate > 96000)
sample_rate = 44100;
- device_info.device.input.sample_rate = sample_rate;
- device_info.device.input.channel_layout = media::CHANNEL_LAYOUT_STEREO;
+ media::AudioParameters params(
+ device_info.device.input.format(), media::CHANNEL_LAYOUT_STEREO,
+ sample_rate, device_info.device.input.bits_per_sample(),
+ device_info.device.input.frames_per_buffer());
+ params.set_effects(device_info.device.input.effects());
+ params.set_mic_positions(device_info.device.input.mic_positions());
+ DCHECK(params.IsValid());
+ device_info.device.input = params;
}
if (device_info.device.type == request->audio_type())
diff --git a/chromium/content/browser/renderer_host/media/media_stream_manager.h b/chromium/content/browser/renderer_host/media/media_stream_manager.h
index 359409812cc..0e6450a7a9e 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_manager.h
+++ b/chromium/content/browser/renderer_host/media/media_stream_manager.h
@@ -86,12 +86,15 @@ class CONTENT_EXPORT MediaStreamManager
// logging from webrtcLoggingPrivate API. Safe to call from any thread.
static void SendMessageToNativeLog(const std::string& message);
- explicit MediaStreamManager(media::AudioSystem* audio_system);
+ MediaStreamManager(
+ media::AudioSystem* audio_system,
+ scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner);
// |audio_system| is required but defaults will be used if either
// |video_capture_system| or |device_task_runner| are null.
- explicit MediaStreamManager(
+ MediaStreamManager(
media::AudioSystem* audio_system,
+ scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner,
std::unique_ptr<VideoCaptureProvider> video_capture_provider);
~MediaStreamManager() override;
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 f0e968a689b..e553472228b 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
@@ -168,8 +168,8 @@ class MediaStreamManagerTest : public ::testing::Test {
: thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {
audio_manager_.reset(new MockAudioManager());
audio_system_ = media::AudioSystemImpl::Create(audio_manager_.get());
- media_stream_manager_ =
- base::MakeUnique<MediaStreamManager>(audio_system_.get());
+ media_stream_manager_ = base::MakeUnique<MediaStreamManager>(
+ audio_system_.get(), audio_manager_->GetTaskRunner());
base::RunLoop().RunUntilIdle();
}
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 7afc300c9eb..3a332afadd8 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
@@ -116,8 +116,10 @@ void PeerConnectionTrackerHost::OnGetUserMedia(
}
void PeerConnectionTrackerHost::OnSuspend() {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(&PeerConnectionTrackerHost::SendOnSuspendOnUIThread, this));
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&PeerConnectionTrackerHost::SendOnSuspendOnUIThread,
+ this));
}
void PeerConnectionTrackerHost::SendOnSuspendOnUIThread() {
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 e12a3bc2f97..2de123d9cbc 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
@@ -222,7 +222,7 @@ TEST(RenderFrameAudioOutputStreamFactoryTest, CreateStream) {
provider->Acquire(
mojo::MakeRequest(&output_stream), params,
- base::Bind(&MockClient::StreamCreated, base::Unretained(&client)));
+ base::BindOnce(&MockClient::StreamCreated, base::Unretained(&client)));
base::RunLoop().RunUntilIdle();
ASSERT_NE(event_handler, nullptr);
@@ -282,7 +282,7 @@ TEST(RenderFrameAudioOutputStreamFactoryTest, ConnectionError_DeletesStream) {
provider->Acquire(
mojo::MakeRequest(&output_stream), GetTestAudioParameters(),
- base::Bind(&MockClient::StreamCreated, base::Unretained(&client)));
+ base::BindOnce(&MockClient::StreamCreated, base::Unretained(&client)));
base::RunLoop().RunUntilIdle();
ASSERT_NE(event_handler, nullptr);
EXPECT_FALSE(delegate_is_destructed);
@@ -315,7 +315,7 @@ TEST(RenderFrameAudioOutputStreamFactoryTest, DelegateError_DeletesStream) {
provider->Acquire(
mojo::MakeRequest(&output_stream), GetTestAudioParameters(),
- base::Bind(&MockClient::StreamCreated, base::Unretained(&client)));
+ base::BindOnce(&MockClient::StreamCreated, base::Unretained(&client)));
base::RunLoop().RunUntilIdle();
ASSERT_NE(event_handler, nullptr);
EXPECT_FALSE(delegate_is_destructed);
diff --git a/chromium/content/browser/renderer_host/media/renderer_audio_output_stream_factory_context_impl_unittest.cc b/chromium/content/browser/renderer_host/media/renderer_audio_output_stream_factory_context_impl_unittest.cc
deleted file mode 100644
index 4bd58d298c7..00000000000
--- a/chromium/content/browser/renderer_host/media/renderer_audio_output_stream_factory_context_impl_unittest.cc
+++ /dev/null
@@ -1,380 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/renderer_host/media/renderer_audio_output_stream_factory_context_impl.h"
-
-#include <utility>
-
-#include "base/bind.h"
-#include "base/memory/shared_memory.h"
-#include "base/memory/shared_memory_handle.h"
-#include "base/message_loop/message_loop.h"
-#include "base/run_loop.h"
-#include "base/single_thread_task_runner.h"
-#include "base/sync_socket.h"
-#include "cc/base/math_util.h"
-#include "content/browser/renderer_host/media/media_stream_manager.h"
-#include "content/common/media/renderer_audio_output_stream_factory.mojom.h"
-#include "content/public/browser/browser_thread.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 "media/audio/audio_manager_base.h"
-#include "media/audio/audio_output_controller.h"
-#include "media/audio/audio_system_impl.h"
-#include "media/audio/audio_thread_impl.h"
-#include "media/audio/fake_audio_log_factory.h"
-#include "media/audio/simple_sources.h"
-#include "media/base/audio_parameters.h"
-#include "media/base/media_switches.h"
-#include "mojo/public/cpp/bindings/binding.h"
-#include "mojo/public/cpp/system/platform_handle.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace content {
-
-namespace {
-
-using testing::_;
-using testing::StrictMock;
-using testing::Return;
-using testing::Test;
-using AudioOutputStreamFactory = mojom::RendererAudioOutputStreamFactory;
-using AudioOutputStreamFactoryPtr =
- mojo::InterfacePtr<AudioOutputStreamFactory>;
-using AudioOutputStreamFactoryRequest =
- mojo::InterfaceRequest<AudioOutputStreamFactory>;
-using AudioOutputStream = media::mojom::AudioOutputStream;
-using AudioOutputStreamPtr = mojo::InterfacePtr<AudioOutputStream>;
-using AudioOutputStreamRequest = mojo::InterfaceRequest<AudioOutputStream>;
-using AudioOutputStreamProvider = media::mojom::AudioOutputStreamProvider;
-using AudioOutputStreamProviderPtr =
- mojo::InterfacePtr<AudioOutputStreamProvider>;
-using AudioOutputStreamProviderRequest =
- mojo::InterfaceRequest<AudioOutputStreamProvider>;
-
-const int kRenderProcessId = 42;
-const int kRenderFrameId = 24;
-const int kNoSessionId = 0;
-const float kWaveFrequency = 440.f;
-const int kChannels = 1;
-const int kBuffers = 1000;
-const int kSampleFrequency = 44100;
-const int kBitsPerSample = 16;
-const int kSamplesPerBuffer = kSampleFrequency / 100;
-const char kSalt[] = "salt";
-
-std::unique_ptr<media::AudioOutputStream::AudioSourceCallback>
-GetTestAudioSource() {
- return base::MakeUnique<media::SineWaveAudioSource>(kChannels, kWaveFrequency,
- kSampleFrequency);
-}
-
-media::AudioParameters GetTestAudioParameters() {
- return media::AudioParameters(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
- media::CHANNEL_LAYOUT_MONO, kSampleFrequency,
- kBitsPerSample, kSamplesPerBuffer);
-}
-
-void SyncWith(scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
- CHECK(task_runner);
- CHECK(!task_runner->BelongsToCurrentThread());
- base::WaitableEvent e = {base::WaitableEvent::ResetPolicy::MANUAL,
- base::WaitableEvent::InitialState::NOT_SIGNALED};
- task_runner->PostTask(FROM_HERE, base::BindOnce(&base::WaitableEvent::Signal,
- base::Unretained(&e)));
- e.Wait();
-}
-
-void SyncWithAllThreads() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- // New tasks might be posted while we are syncing, but in every iteration at
- // least one task will be run. 20 iterations should be enough for our code.
- for (int i = 0; i < 20; ++i) {
- {
- base::MessageLoop::ScopedNestableTaskAllower allower(
- base::MessageLoop::current());
- base::RunLoop().RunUntilIdle();
- }
- SyncWith(BrowserThread::GetTaskRunnerForThread(BrowserThread::IO));
- SyncWith(media::AudioManager::Get()->GetWorkerTaskRunner());
- }
-}
-
-class MockAudioManager : public media::AudioManagerBase {
- public:
- MockAudioManager(std::unique_ptr<media::AudioThread> audio_thread,
- media::AudioLogFactory* audio_log_factory)
- : media::AudioManagerBase(std::move(audio_thread), audio_log_factory) {
- ON_CALL(*this, HasAudioOutputDevices()).WillByDefault(Return(true));
- }
-
- ~MockAudioManager() override = default;
-
- MOCK_METHOD2(MakeLinearOutputStream,
- media::AudioOutputStream*(const media::AudioParameters& params,
- const LogCallback& log_callback));
- MOCK_METHOD3(MakeLowLatencyOutputStream,
- media::AudioOutputStream*(const media::AudioParameters& params,
- const std::string& device_id,
- const LogCallback& log_callback));
- MOCK_METHOD3(MakeLinearInputStream,
- media::AudioInputStream*(const media::AudioParameters& params,
- const std::string& device_id,
- const LogCallback& log_callback));
- MOCK_METHOD3(MakeLowLatencyInputStream,
- media::AudioInputStream*(const media::AudioParameters& params,
- const std::string& device_id,
- const LogCallback& log_callback));
-
- protected:
- MOCK_METHOD0(HasAudioOutputDevices, bool());
- MOCK_METHOD0(HasAudioInputDevices, bool());
- MOCK_METHOD0(GetName, const char*());
- media::AudioParameters GetPreferredOutputStreamParameters(
- const std::string& device_id,
- const media::AudioParameters& params) {
- return GetTestAudioParameters();
- }
-};
-
-class MockAudioOutputStream : public media::AudioOutputStream,
- public base::PlatformThread::Delegate {
- public:
- explicit MockAudioOutputStream(MockAudioManager* audio_manager)
- : done_(base::WaitableEvent::ResetPolicy::MANUAL,
- base::WaitableEvent::InitialState::NOT_SIGNALED),
- audio_manager_(audio_manager) {}
-
- ~MockAudioOutputStream() override {
- base::PlatformThread::Join(thread_handle_);
- }
-
- void Start(AudioSourceCallback* callback) override {
- callback_ = callback;
- EXPECT_TRUE(base::PlatformThread::CreateWithPriority(
- 0, this, &thread_handle_, base::ThreadPriority::REALTIME_AUDIO));
- }
-
- void Stop() override {
- done_.Wait();
- callback_ = nullptr;
- }
-
- bool Open() override { return true; }
- void SetVolume(double volume) override {}
- void GetVolume(double* volume) override { *volume = 1; }
- void Close() override {
- Stop();
- audio_manager_->ReleaseOutputStream(this);
- }
-
- void ThreadMain() override {
- std::unique_ptr<media::AudioOutputStream::AudioSourceCallback>
- expected_audio = GetTestAudioSource();
- media::AudioParameters params = GetTestAudioParameters();
- std::unique_ptr<media::AudioBus> dest = media::AudioBus::Create(params);
- std::unique_ptr<media::AudioBus> expected_buffer =
- media::AudioBus::Create(params);
- for (int i = 0; i < kBuffers; ++i) {
- expected_audio->OnMoreData(base::TimeDelta(), base::TimeTicks::Now(), 0,
- expected_buffer.get());
- callback_->OnMoreData(base::TimeDelta(), base::TimeTicks::Now(), 0,
- dest.get());
- for (int frame = 0; frame < params.frames_per_buffer(); ++frame) {
- // Using EXPECT here causes massive log spam in case of a broken test,
- // and ASSERT causes it to hang, so we use CHECK.
- CHECK(cc::MathUtil::IsFloatNearlyTheSame(
- expected_buffer->channel(0)[frame], dest->channel(0)[frame]))
- << "Got " << dest->channel(0)[frame] << ", expected "
- << expected_buffer->channel(0)[frame];
- }
- }
- done_.Signal();
- }
-
- private:
- base::OnceClosure sync_closure_;
- base::PlatformThreadHandle thread_handle_;
- base::WaitableEvent done_;
- MockAudioManager* audio_manager_;
- AudioSourceCallback* callback_;
-};
-
-void AuthCallback(base::OnceClosure sync_closure,
- media::OutputDeviceStatus* status_out,
- media::AudioParameters* params_out,
- std::string* id_out,
- media::OutputDeviceStatus status,
- const media::AudioParameters& params,
- const std::string& id) {
- *status_out = status;
- *params_out = params;
- *id_out = id;
- std::move(sync_closure).Run();
-}
-
-// "Renderer-side" audio client. Provides the signal given by
-// GetTestAudioSource() from a dedicated thread when given sync socket and
-// shared memory.
-// TODO(maxmorin): Replace with an instance of the real client, when it exists.
-class TestIPCClient : public base::PlatformThread::Delegate {
- public:
- TestIPCClient() {}
-
- ~TestIPCClient() override { base::PlatformThread::Join(thread_handle_); }
-
- // Starts thread, sets up IPC primitives and sends signal on thread.
- void Start(mojo::ScopedSharedBufferHandle shared_buffer,
- mojo::ScopedHandle socket_handle) {
- EXPECT_TRUE(socket_handle.is_valid());
- // Set up socket.
- base::PlatformFile fd;
- mojo::UnwrapPlatformFile(std::move(socket_handle), &fd);
- socket_ = base::MakeUnique<base::CancelableSyncSocket>(fd);
- EXPECT_NE(socket_->handle(), base::CancelableSyncSocket::kInvalidHandle);
-
- // Set up memory.
- EXPECT_TRUE(shared_buffer.is_valid());
- size_t memory_length;
- base::SharedMemoryHandle shmem_handle;
- bool read_only;
- EXPECT_EQ(
- mojo::UnwrapSharedMemoryHandle(std::move(shared_buffer), &shmem_handle,
- &memory_length, &read_only),
- MOJO_RESULT_OK);
- EXPECT_EQ(memory_length, sizeof(media::AudioOutputBufferParameters) +
- media::AudioBus::CalculateMemorySize(
- GetTestAudioParameters()));
- EXPECT_EQ(read_only, false);
- memory_ = base::MakeUnique<base::SharedMemory>(shmem_handle, read_only);
- EXPECT_TRUE(memory_->Map(memory_length));
-
- EXPECT_TRUE(base::PlatformThread::CreateWithPriority(
- 0, this, &thread_handle_, base::ThreadPriority::REALTIME_AUDIO));
- }
-
- void ThreadMain() override {
- std::unique_ptr<media::AudioOutputStream::AudioSourceCallback>
- audio_source = GetTestAudioSource();
-
- media::AudioOutputBuffer* buffer =
- reinterpret_cast<media::AudioOutputBuffer*>(memory_->memory());
- std::unique_ptr<media::AudioBus> output_bus =
- media::AudioBus::WrapMemory(GetTestAudioParameters(), buffer->audio);
-
- // Send s.
- for (uint32_t i = 0; i < kBuffers;) {
- uint32_t pending_data = 0;
- size_t bytes_read = socket_->Receive(&pending_data, sizeof(pending_data));
- // Use check here, since there's a risk of hangs in case of a bug.
- PCHECK(sizeof(pending_data) == bytes_read)
- << "Tried to read " << sizeof(pending_data) << " bytes but only read "
- << bytes_read << " bytes";
- CHECK_EQ(0u, pending_data);
-
- ++i;
- audio_source->OnMoreData(base::TimeDelta(), base::TimeTicks(), 0,
- output_bus.get());
-
- size_t bytes_written = socket_->Send(&i, sizeof(i));
- PCHECK(sizeof(pending_data) == bytes_written)
- << "Tried to write " << sizeof(pending_data)
- << " bytes but only wrote " << bytes_written << " bytes";
- }
- }
-
- private:
- base::PlatformThreadHandle thread_handle_;
- std::unique_ptr<base::CancelableSyncSocket> socket_;
- std::unique_ptr<base::SharedMemory> memory_;
-};
-
-} // namespace
-
-// TODO(maxmorin): Add test for play, pause and set volume.
-class RendererAudioOutputStreamFactoryIntegrationTest : public Test {
- public:
- RendererAudioOutputStreamFactoryIntegrationTest()
- : media_stream_manager_(),
- thread_bundle_(TestBrowserThreadBundle::Options::REAL_IO_THREAD),
- log_factory_(),
- audio_manager_(
- new MockAudioManager(base::MakeUnique<media::AudioThreadImpl>(),
- &log_factory_)),
- audio_system_(media::AudioSystemImpl::Create(audio_manager_.get())) {
- media_stream_manager_ =
- base::MakeUnique<MediaStreamManager>(audio_system_.get());
- }
-
- ~RendererAudioOutputStreamFactoryIntegrationTest() override {
- audio_manager_->Shutdown();
- }
-
- UniqueAudioOutputStreamFactoryPtr CreateAndBindFactory(
- AudioOutputStreamFactoryRequest request) {
- factory_context_.reset(new RendererAudioOutputStreamFactoryContextImpl(
- kRenderProcessId, audio_system_.get(), audio_manager_.get(),
- media_stream_manager_.get(), kSalt));
- return RenderFrameAudioOutputStreamFactoryHandle::CreateFactory(
- factory_context_.get(), kRenderFrameId, std::move(request));
- }
-
- std::unique_ptr<MediaStreamManager> media_stream_manager_;
- TestBrowserThreadBundle thread_bundle_;
- media::FakeAudioLogFactory log_factory_;
- std::unique_ptr<media::AudioManager> audio_manager_;
- std::unique_ptr<media::AudioSystem> audio_system_;
- std::unique_ptr<RendererAudioOutputStreamFactoryContextImpl,
- BrowserThread::DeleteOnIOThread>
- factory_context_;
-};
-
-TEST_F(RendererAudioOutputStreamFactoryIntegrationTest, StreamIntegrationTest) {
- // Sets up the factory on the IO thread and runs client code on the UI thread.
- // Send a sine wave from the client and makes sure it's received by the output
- // stream.
- MockAudioOutputStream* stream = new MockAudioOutputStream(
- static_cast<MockAudioManager*>(audio_manager_.get()));
-
- // Make sure the mock audio manager uses our mock stream.
- EXPECT_CALL(*static_cast<MockAudioManager*>(audio_manager_.get()),
- MakeLowLatencyOutputStream(_, "", _))
- .WillOnce(Return(stream));
-
- AudioOutputStreamFactoryPtr factory_ptr;
- auto factory_handle = CreateAndBindFactory(mojo::MakeRequest(&factory_ptr));
-
- AudioOutputStreamProviderPtr provider_ptr;
- base::RunLoop loop;
- media::OutputDeviceStatus status;
- media::AudioParameters params;
- std::string id;
- factory_ptr->RequestDeviceAuthorization(
- mojo::MakeRequest(&provider_ptr), kNoSessionId, "default",
- base::BindOnce(&AuthCallback, loop.QuitWhenIdleClosure(),
- base::Unretained(&status), base::Unretained(&params),
- base::Unretained(&id)));
- loop.Run();
- ASSERT_EQ(status, media::OUTPUT_DEVICE_STATUS_OK);
- ASSERT_EQ(GetTestAudioParameters().AsHumanReadableString(),
- params.AsHumanReadableString());
- ASSERT_TRUE(id.empty());
-
- AudioOutputStreamPtr stream_ptr;
- {
- TestIPCClient client;
- provider_ptr->Acquire(
- mojo::MakeRequest(&stream_ptr), params,
- base::Bind(&TestIPCClient::Start, base::Unretained(&client)));
- SyncWithAllThreads();
- stream_ptr->Play();
- SyncWithAllThreads();
- } // Joining client thread.
- stream_ptr.reset();
- SyncWithAllThreads();
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/service_launched_video_capture_device.cc b/chromium/content/browser/renderer_host/media/service_launched_video_capture_device.cc
index 43b0e49591b..1d12c4c72e9 100644
--- a/chromium/content/browser/renderer_host/media/service_launched_video_capture_device.cc
+++ b/chromium/content/browser/renderer_host/media/service_launched_video_capture_device.cc
@@ -12,9 +12,9 @@ ServiceLaunchedVideoCaptureDevice::ServiceLaunchedVideoCaptureDevice(
: device_(std::move(device)),
connection_lost_cb_(std::move(connection_lost_cb)) {
// Unretained |this| is safe, because |this| owns |device_|.
- device_.set_connection_error_handler(
- base::Bind(&ServiceLaunchedVideoCaptureDevice::OnLostConnectionToDevice,
- base::Unretained(this)));
+ device_.set_connection_error_handler(base::BindOnce(
+ &ServiceLaunchedVideoCaptureDevice::OnLostConnectionToDevice,
+ base::Unretained(this)));
}
ServiceLaunchedVideoCaptureDevice::~ServiceLaunchedVideoCaptureDevice() {
@@ -24,9 +24,9 @@ ServiceLaunchedVideoCaptureDevice::~ServiceLaunchedVideoCaptureDevice() {
void ServiceLaunchedVideoCaptureDevice::GetPhotoState(
media::VideoCaptureDevice::GetPhotoStateCallback callback) const {
DCHECK(sequence_checker_.CalledOnValidSequence());
- device_->GetPhotoState(
- base::Bind(&ServiceLaunchedVideoCaptureDevice::OnGetPhotoStateResponse,
- base::Unretained(this), base::Passed(&callback)));
+ device_->GetPhotoState(base::BindOnce(
+ &ServiceLaunchedVideoCaptureDevice::OnGetPhotoStateResponse,
+ base::Unretained(this), base::Passed(&callback)));
}
void ServiceLaunchedVideoCaptureDevice::SetPhotoOptions(
@@ -35,16 +35,17 @@ void ServiceLaunchedVideoCaptureDevice::SetPhotoOptions(
DCHECK(sequence_checker_.CalledOnValidSequence());
device_->SetPhotoOptions(
std::move(settings),
- base::Bind(&ServiceLaunchedVideoCaptureDevice::OnSetPhotoOptionsResponse,
- base::Unretained(this), base::Passed(&callback)));
+ base::BindOnce(
+ &ServiceLaunchedVideoCaptureDevice::OnSetPhotoOptionsResponse,
+ base::Unretained(this), base::Passed(&callback)));
}
void ServiceLaunchedVideoCaptureDevice::TakePhoto(
media::VideoCaptureDevice::TakePhotoCallback callback) {
DCHECK(sequence_checker_.CalledOnValidSequence());
device_->TakePhoto(
- base::Bind(&ServiceLaunchedVideoCaptureDevice::OnTakePhotoResponse,
- base::Unretained(this), base::Passed(&callback)));
+ base::BindOnce(&ServiceLaunchedVideoCaptureDevice::OnTakePhotoResponse,
+ base::Unretained(this), base::Passed(&callback)));
}
void ServiceLaunchedVideoCaptureDevice::MaybeSuspendDevice() {
@@ -88,7 +89,7 @@ void ServiceLaunchedVideoCaptureDevice::OnGetPhotoStateResponse(
media::mojom::PhotoStatePtr capabilities) const {
if (!capabilities)
return;
- callback.Run(std::move(capabilities));
+ std::move(callback).Run(std::move(capabilities));
}
void ServiceLaunchedVideoCaptureDevice::OnSetPhotoOptionsResponse(
@@ -96,7 +97,7 @@ void ServiceLaunchedVideoCaptureDevice::OnSetPhotoOptionsResponse(
bool success) {
if (!success)
return;
- callback.Run(true);
+ std::move(callback).Run(true);
}
void ServiceLaunchedVideoCaptureDevice::OnTakePhotoResponse(
@@ -104,7 +105,7 @@ void ServiceLaunchedVideoCaptureDevice::OnTakePhotoResponse(
media::mojom::BlobPtr blob) {
if (!blob)
return;
- callback.Run(std::move(blob));
+ std::move(callback).Run(std::move(blob));
}
} // namespace content
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 5dcae9a08be..1f6dce22068 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
@@ -15,20 +15,12 @@ namespace content {
namespace {
void ConcludeLaunchDeviceWithSuccess(
- bool abort_requested,
const media::VideoCaptureParams& params,
video_capture::mojom::DevicePtr device,
base::WeakPtr<media::VideoFrameReceiver> receiver,
base::OnceClosure connection_lost_cb,
VideoCaptureDeviceLauncher::Callbacks* callbacks,
base::OnceClosure done_cb) {
- if (abort_requested) {
- device.reset();
- callbacks->OnDeviceLaunchAborted();
- base::ResetAndReturn(&done_cb).Run();
- return;
- }
-
auto receiver_adapter =
base::MakeUnique<video_capture::ReceiverMediaToMojoAdapter>(
base::MakeUnique<media::VideoFrameReceiverOnTaskRunner>(
@@ -46,8 +38,10 @@ void ConcludeLaunchDeviceWithSuccess(
void ConcludeLaunchDeviceWithFailure(
bool abort_requested,
+ std::unique_ptr<VideoCaptureFactoryDelegate> device_factory,
VideoCaptureDeviceLauncher::Callbacks* callbacks,
base::OnceClosure done_cb) {
+ device_factory.reset();
if (abort_requested)
callbacks->OnDeviceLaunchAborted();
else
@@ -58,17 +52,14 @@ void ConcludeLaunchDeviceWithFailure(
} // anonymous namespace
ServiceVideoCaptureDeviceLauncher::ServiceVideoCaptureDeviceLauncher(
- video_capture::mojom::DeviceFactoryPtr* device_factory,
- base::OnceClosure destruction_cb)
- : device_factory_(device_factory),
- destruction_cb_(std::move(destruction_cb)),
+ ConnectToDeviceFactoryCB connect_to_device_factory_cb)
+ : connect_to_device_factory_cb_(std::move(connect_to_device_factory_cb)),
state_(State::READY_TO_LAUNCH),
callbacks_(nullptr) {}
ServiceVideoCaptureDeviceLauncher::~ServiceVideoCaptureDeviceLauncher() {
DCHECK(sequence_checker_.CalledOnValidSequence());
DCHECK(state_ == State::READY_TO_LAUNCH);
- base::ResetAndReturn(&destruction_cb_).Run();
}
void ServiceVideoCaptureDeviceLauncher::LaunchDeviceAsync(
@@ -88,35 +79,36 @@ void ServiceVideoCaptureDeviceLauncher::LaunchDeviceAsync(
return;
}
+ connect_to_device_factory_cb_.Run(&device_factory_);
if (!device_factory_->is_bound()) {
// This can happen when the ServiceVideoCaptureProvider owning
// |device_factory_| loses connection to the service process and resets
// |device_factory_|.
- ConcludeLaunchDeviceWithFailure(false, callbacks, std::move(done_cb));
+ ConcludeLaunchDeviceWithFailure(false, std::move(device_factory_),
+ callbacks, std::move(done_cb));
return;
}
video_capture::mojom::DevicePtr device;
auto device_request = mojo::MakeRequest(&device);
// Ownership of |done_cb| is moved to |this|. It is not sufficient to attach
- // it to the callback passed to |(*device_factory_)->CreateDevice()|, because
+ // it to the callback passed to |device_factory_->CreateDevice()|, because
// |device_factory_| may get torn down before the callback is invoked.
done_cb_ = std::move(done_cb);
callbacks_ = callbacks;
// Use of Unretained(this) is safe, because |done_cb_| guarantees that |this|
// stays alive.
device.set_connection_error_handler(
- base::Bind(&ServiceVideoCaptureDeviceLauncher::
- OnConnectionLostWhileWaitingForCallback,
- base::Unretained(this)));
- (*device_factory_)
- ->CreateDevice(
- device_id, std::move(device_request),
- base::Bind(
- // Use of Unretained |this| is safe, because |done_cb_| guarantees
- // that |this| stays alive.
- &ServiceVideoCaptureDeviceLauncher::OnCreateDeviceCallback,
- base::Unretained(this), params, base::Passed(&device),
- std::move(receiver), base::Passed(&connection_lost_cb)));
+ base::BindOnce(&ServiceVideoCaptureDeviceLauncher::
+ OnConnectionLostWhileWaitingForCallback,
+ base::Unretained(this)));
+ device_factory_->CreateDevice(
+ device_id, std::move(device_request),
+ base::BindOnce(
+ // Use of Unretained |this| is safe, because |done_cb_| guarantees
+ // that |this| stays alive.
+ &ServiceVideoCaptureDeviceLauncher::OnCreateDeviceCallback,
+ base::Unretained(this), params, base::Passed(&device),
+ std::move(receiver), base::Passed(&connection_lost_cb)));
state_ = State::DEVICE_START_IN_PROGRESS;
}
@@ -135,20 +127,28 @@ void ServiceVideoCaptureDeviceLauncher::OnCreateDeviceCallback(
DCHECK(sequence_checker_.CalledOnValidSequence());
DCHECK(callbacks_);
DCHECK(done_cb_);
- device.set_connection_error_handler(base::Bind(&base::DoNothing));
+ device.set_connection_error_handler(base::BindOnce(&base::DoNothing));
const bool abort_requested = (state_ == State::DEVICE_START_ABORTING);
state_ = State::READY_TO_LAUNCH;
Callbacks* callbacks = callbacks_;
callbacks_ = nullptr;
switch (result_code) {
case video_capture::mojom::DeviceAccessResultCode::SUCCESS:
+ if (abort_requested) {
+ device.reset();
+ device_factory_.reset();
+ callbacks->OnDeviceLaunchAborted();
+ base::ResetAndReturn(&done_cb_).Run();
+ return;
+ }
ConcludeLaunchDeviceWithSuccess(
- abort_requested, params, std::move(device), std::move(receiver),
+ params, std::move(device), std::move(receiver),
std::move(connection_lost_cb), callbacks, std::move(done_cb_));
return;
case video_capture::mojom::DeviceAccessResultCode::ERROR_DEVICE_NOT_FOUND:
case video_capture::mojom::DeviceAccessResultCode::NOT_INITIALIZED:
- ConcludeLaunchDeviceWithFailure(abort_requested, callbacks,
+ ConcludeLaunchDeviceWithFailure(abort_requested,
+ std::move(device_factory_), callbacks,
std::move(done_cb_));
return;
}
@@ -162,8 +162,8 @@ void ServiceVideoCaptureDeviceLauncher::
state_ = State::READY_TO_LAUNCH;
Callbacks* callbacks = callbacks_;
callbacks_ = nullptr;
- ConcludeLaunchDeviceWithFailure(abort_requested, callbacks,
- std::move(done_cb_));
+ ConcludeLaunchDeviceWithFailure(abort_requested, std::move(device_factory_),
+ callbacks, std::move(done_cb_));
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/service_video_capture_device_launcher.h b/chromium/content/browser/renderer_host/media/service_video_capture_device_launcher.h
index 4159b8f821f..94b4f1cfb60 100644
--- a/chromium/content/browser/renderer_host/media/service_video_capture_device_launcher.h
+++ b/chromium/content/browser/renderer_host/media/service_video_capture_device_launcher.h
@@ -5,6 +5,7 @@
#ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_SERVICE_VIDEO_CAPTURE_DEVICE_LAUNCHER_H_
#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_SERVICE_VIDEO_CAPTURE_DEVICE_LAUNCHER_H_
+#include "content/browser/renderer_host/media/video_capture_factory_delegate.h"
#include "content/browser/renderer_host/media/video_capture_provider.h"
#include "content/public/common/media_stream_request.h"
#include "services/video_capture/public/interfaces/device_factory.mojom.h"
@@ -16,9 +17,12 @@ namespace content {
class CONTENT_EXPORT ServiceVideoCaptureDeviceLauncher
: public VideoCaptureDeviceLauncher {
public:
+ // Receives an instance via output parameter |factory|.
+ using ConnectToDeviceFactoryCB = base::RepeatingCallback<void(
+ std::unique_ptr<VideoCaptureFactoryDelegate>* factory)>;
+
explicit ServiceVideoCaptureDeviceLauncher(
- video_capture::mojom::DeviceFactoryPtr* device_factory,
- base::OnceClosure destruction_cb);
+ ConnectToDeviceFactoryCB connect_to_device_factory_cb);
~ServiceVideoCaptureDeviceLauncher() override;
// VideoCaptureDeviceLauncher implementation.
@@ -49,8 +53,8 @@ class CONTENT_EXPORT ServiceVideoCaptureDeviceLauncher
void OnConnectionLostWhileWaitingForCallback();
- video_capture::mojom::DeviceFactoryPtr* const device_factory_;
- base::OnceClosure destruction_cb_;
+ ConnectToDeviceFactoryCB connect_to_device_factory_cb_;
+ std::unique_ptr<VideoCaptureFactoryDelegate> device_factory_;
State state_;
base::SequenceChecker sequence_checker_;
base::OnceClosure done_cb_;
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 40cfde8bcc8..0a6bae1d3c8 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
@@ -9,6 +9,7 @@
#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 "mojo/public/cpp/bindings/binding.h"
#include "services/video_capture/public/interfaces/device_factory.mojom.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -68,7 +69,23 @@ class ServiceVideoCaptureDeviceLauncherTest : public testing::Test {
base::MakeUnique<mojo::Binding<video_capture::mojom::DeviceFactory>>(
&mock_device_factory_, mojo::MakeRequest(&device_factory_));
launcher_ = base::MakeUnique<ServiceVideoCaptureDeviceLauncher>(
- &device_factory_, base::BindOnce(&base::DoNothing));
+ connect_to_device_factory_cb_.Get());
+ launcher_has_connected_to_device_factory_ = false;
+ launcher_has_released_device_factory_ = false;
+
+ ON_CALL(connect_to_device_factory_cb_, Run(_))
+ .WillByDefault(Invoke(
+ [this](std::unique_ptr<VideoCaptureFactoryDelegate>* out_factory) {
+ launcher_has_connected_to_device_factory_ = true;
+ *out_factory = base::MakeUnique<VideoCaptureFactoryDelegate>(
+ &device_factory_, release_connection_cb_.Get());
+ }));
+
+ ON_CALL(release_connection_cb_, Run())
+ .WillByDefault(InvokeWithoutArgs([this]() {
+ launcher_has_released_device_factory_ = true;
+ wait_for_release_connection_cb_.Quit();
+ }));
}
void TearDown() override {}
@@ -85,14 +102,19 @@ class ServiceVideoCaptureDeviceLauncherTest : public testing::Test {
std::unique_ptr<ServiceVideoCaptureDeviceLauncher> launcher_;
base::MockCallback<base::OnceClosure> connection_lost_cb_;
base::MockCallback<base::OnceClosure> done_cb_;
+ base::MockCallback<
+ ServiceVideoCaptureDeviceLauncher::ConnectToDeviceFactoryCB>
+ connect_to_device_factory_cb_;
+ base::MockCallback<base::OnceClosure> release_connection_cb_;
+ bool launcher_has_connected_to_device_factory_;
+ bool launcher_has_released_device_factory_;
+ base::RunLoop wait_for_release_connection_cb_;
private:
DISALLOW_COPY_AND_ASSIGN(ServiceVideoCaptureDeviceLauncherTest);
};
TEST_F(ServiceVideoCaptureDeviceLauncherTest, LaunchingDeviceSucceeds) {
- base::RunLoop run_loop;
-
EXPECT_CALL(mock_device_factory_, DoCreateDevice(kStubDeviceId, _, _))
.WillOnce(Invoke([](const std::string& device_id,
video_capture::mojom::DeviceRequest* device_request,
@@ -112,21 +134,27 @@ TEST_F(ServiceVideoCaptureDeviceLauncherTest, LaunchingDeviceSucceeds) {
},
std::move(*device_request), std::move(callback)));
}));
+
EXPECT_CALL(mock_callbacks_, DoOnDeviceLaunched(_)).Times(1);
EXPECT_CALL(mock_callbacks_, OnDeviceLaunchAborted()).Times(0);
EXPECT_CALL(mock_callbacks_, OnDeviceLaunchFailed()).Times(0);
EXPECT_CALL(connection_lost_cb_, Run()).Times(0);
- EXPECT_CALL(done_cb_, Run()).WillOnce(InvokeWithoutArgs([&run_loop]() {
- run_loop.Quit();
- }));
+ base::RunLoop wait_for_done_cb;
+ EXPECT_CALL(done_cb_, Run())
+ .WillOnce(InvokeWithoutArgs(
+ [&wait_for_done_cb]() { wait_for_done_cb.Quit(); }));
// Exercise
launcher_->LaunchDeviceAsync(
kStubDeviceId, content::MEDIA_DEVICE_VIDEO_CAPTURE, kArbitraryParams,
kNullReceiver, connection_lost_cb_.Get(), &mock_callbacks_,
done_cb_.Get());
+ wait_for_done_cb.Run();
- run_loop.Run();
+ launcher_.reset();
+ wait_for_release_connection_cb_.Run();
+ EXPECT_TRUE(launcher_has_connected_to_device_factory_);
+ EXPECT_TRUE(launcher_has_released_device_factory_);
}
TEST_F(ServiceVideoCaptureDeviceLauncherTest,
@@ -192,6 +220,9 @@ void ServiceVideoCaptureDeviceLauncherTest::RunLaunchingDeviceIsAbortedTest(
std::move(create_device_success_answer_cb).Run();
step_2_run_loop.Run();
+
+ EXPECT_TRUE(launcher_has_connected_to_device_factory_);
+ EXPECT_TRUE(launcher_has_released_device_factory_);
}
TEST_F(ServiceVideoCaptureDeviceLauncherTest,
@@ -232,7 +263,6 @@ TEST_F(ServiceVideoCaptureDeviceLauncherTest,
kStubDeviceId, content::MEDIA_DEVICE_VIDEO_CAPTURE, kArbitraryParams,
kNullReceiver, connection_lost_cb_.Get(), &mock_callbacks_,
done_cb_.Get());
-
run_loop.Run();
}
@@ -350,6 +380,11 @@ TEST_F(ServiceVideoCaptureDeviceLauncherTest,
// Exercise step 2: The service cuts/loses the connection
device_request_owned_by_service = nullptr;
step_2_run_loop.Run();
+
+ launcher_.reset();
+ wait_for_release_connection_cb_.Run();
+ EXPECT_TRUE(launcher_has_connected_to_device_factory_);
+ EXPECT_TRUE(launcher_has_released_device_factory_);
}
} // namespace content
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 a1bd6e0dd1a..44155f18886 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,6 +5,7 @@
#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_factory_delegate.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/service_manager_connection.h"
#include "media/base/scoped_callback_runner.h"
@@ -46,7 +47,7 @@ ServiceVideoCaptureProvider::ServiceVideoCaptureProvider(
std::unique_ptr<ServiceConnector> service_connector)
: service_connector_(std::move(service_connector)),
usage_count_(0),
- has_created_device_launcher_(false),
+ launcher_has_connected_to_device_factory_(false),
weak_ptr_factory_(this) {
DETACH_FROM_SEQUENCE(sequence_checker_);
}
@@ -73,10 +74,18 @@ void ServiceVideoCaptureProvider::GetDeviceInfosAsync(
std::unique_ptr<VideoCaptureDeviceLauncher>
ServiceVideoCaptureProvider::CreateDeviceLauncher() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ return base::MakeUnique<ServiceVideoCaptureDeviceLauncher>(
+ base::BindRepeating(&ServiceVideoCaptureProvider::ConnectToDeviceFactory,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+void ServiceVideoCaptureProvider::ConnectToDeviceFactory(
+ std::unique_ptr<VideoCaptureFactoryDelegate>* out_factory) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
IncreaseUsageCount();
LazyConnectToService();
- has_created_device_launcher_ = true;
- return base::MakeUnique<ServiceVideoCaptureDeviceLauncher>(
+ launcher_has_connected_to_device_factory_ = true;
+ *out_factory = base::MakeUnique<VideoCaptureFactoryDelegate>(
&device_factory_,
base::BindOnce(&ServiceVideoCaptureProvider::DecreaseUsageCount,
weak_ptr_factory_.GetWeakPtr()));
@@ -89,7 +98,7 @@ void ServiceVideoCaptureProvider::LazyConnectToService() {
video_capture::uma::LogVideoCaptureServiceEvent(
video_capture::uma::BROWSER_CONNECTING_TO_SERVICE);
if (time_of_last_uninitialize_ != base::TimeTicks()) {
- if (has_created_device_launcher_) {
+ if (launcher_has_connected_to_device_factory_) {
video_capture::uma::LogDurationUntilReconnectAfterCapture(
base::TimeTicks::Now() - time_of_last_uninitialize_);
} else {
@@ -98,16 +107,16 @@ void ServiceVideoCaptureProvider::LazyConnectToService() {
}
}
- has_created_device_launcher_ = false;
+ launcher_has_connected_to_device_factory_ = false;
time_of_last_connect_ = base::TimeTicks::Now();
service_connector_->BindFactoryProvider(&device_factory_provider_);
device_factory_provider_->ConnectToDeviceFactory(
mojo::MakeRequest(&device_factory_));
// Unretained |this| is safe, because |this| owns |device_factory_|.
- device_factory_.set_connection_error_handler(
- base::Bind(&ServiceVideoCaptureProvider::OnLostConnectionToDeviceFactory,
- base::Unretained(this)));
+ device_factory_.set_connection_error_handler(base::BindOnce(
+ &ServiceVideoCaptureProvider::OnLostConnectionToDeviceFactory,
+ base::Unretained(this)));
}
void ServiceVideoCaptureProvider::OnDeviceInfosReceived(
@@ -150,7 +159,7 @@ void ServiceVideoCaptureProvider::UninitializeInternal(
switch (reason) {
case ReasonForUninitialize::kShutdown:
case ReasonForUninitialize::kUnused:
- if (has_created_device_launcher_) {
+ if (launcher_has_connected_to_device_factory_) {
video_capture::uma::LogVideoCaptureServiceEvent(
video_capture::uma::
BROWSER_CLOSING_CONNECTION_TO_SERVICE_AFTER_CAPTURE);
diff --git a/chromium/content/browser/renderer_host/media/service_video_capture_provider.h b/chromium/content/browser/renderer_host/media/service_video_capture_provider.h
index 5b2231ef1de..85cd9660b01 100644
--- a/chromium/content/browser/renderer_host/media/service_video_capture_provider.h
+++ b/chromium/content/browser/renderer_host/media/service_video_capture_provider.h
@@ -12,6 +12,8 @@
namespace content {
+class VideoCaptureFactoryDelegate;
+
// Implementation of VideoCaptureProvider that uses the "video_capture" service.
// Connects to the service lazily on demand and disconnects from the service as
// soon as all previously handed out VideoCaptureDeviceLauncher instances have
@@ -41,6 +43,8 @@ class CONTENT_EXPORT ServiceVideoCaptureProvider : public VideoCaptureProvider {
private:
enum class ReasonForUninitialize { kShutdown, kUnused, kConnectionLost };
+ void ConnectToDeviceFactory(
+ std::unique_ptr<VideoCaptureFactoryDelegate>* out_factory);
void LazyConnectToService();
void OnDeviceInfosReceived(GetDeviceInfosCallback result_callback,
const std::vector<media::VideoCaptureDeviceInfo>&);
@@ -58,7 +62,7 @@ class CONTENT_EXPORT ServiceVideoCaptureProvider : public VideoCaptureProvider {
int usage_count_;
SEQUENCE_CHECKER(sequence_checker_);
- bool has_created_device_launcher_;
+ bool launcher_has_connected_to_device_factory_;
base::TimeTicks time_of_last_connect_;
base::TimeTicks time_of_last_uninitialize_;
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 18c274a700b..4564428541e 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
@@ -20,6 +20,10 @@ using testing::_;
namespace content {
+static const std::string kStubDeviceId = "StubDevice";
+static const media::VideoCaptureParams kArbitraryParams;
+static const base::WeakPtr<media::VideoFrameReceiver> kNullReceiver;
+
class MockServiceConnector
: public ServiceVideoCaptureProvider::ServiceConnector {
public:
@@ -60,6 +64,20 @@ class MockDeviceFactory : public video_capture::mojom::DeviceFactory {
CreateDeviceCallback& callback));
};
+class MockVideoCaptureDeviceLauncherCallbacks
+ : public VideoCaptureDeviceLauncher::Callbacks {
+ public:
+ void OnDeviceLaunched(
+ std::unique_ptr<LaunchedVideoCaptureDevice> device) override {
+ DoOnDeviceLaunched(&device);
+ }
+
+ MOCK_METHOD1(DoOnDeviceLaunched,
+ void(std::unique_ptr<LaunchedVideoCaptureDevice>* device));
+ MOCK_METHOD0(OnDeviceLaunchFailed, void());
+ MOCK_METHOD0(OnDeviceLaunchAborted, void());
+};
+
class ServiceVideoCaptureProviderTest : public testing::Test {
public:
ServiceVideoCaptureProviderTest()
@@ -199,8 +217,8 @@ TEST_F(ServiceVideoCaptureProviderTest,
// Tests that |ServiceVideoCaptureProvider| does not close the connection to the
// service while at least one previously handed out VideoCaptureDeviceLauncher
-// instance is still alive. Then confirms that it closes the connection as soon
-// as the last VideoCaptureDeviceLauncher instance is released.
+// instance is still using it. Then confirms that it closes the connection as
+// soon as the last VideoCaptureDeviceLauncher instance is released.
TEST_F(ServiceVideoCaptureProviderTest,
KeepsServiceConnectionWhileDeviceLauncherAlive) {
ON_CALL(mock_device_factory_, DoGetDeviceInfos(_))
@@ -209,10 +227,26 @@ TEST_F(ServiceVideoCaptureProviderTest,
std::vector<media::VideoCaptureDeviceInfo> arbitrarily_empty_results;
base::ResetAndReturn(&callback).Run(arbitrarily_empty_results);
}));
+ ON_CALL(mock_device_factory_, DoCreateDevice(_, _, _))
+ .WillByDefault(
+ Invoke([](const std::string& device_id,
+ video_capture::mojom::DeviceRequest* device_request,
+ video_capture::mojom::DeviceFactory::CreateDeviceCallback&
+ callback) {
+ base::ResetAndReturn(&callback).Run(
+ video_capture::mojom::DeviceAccessResultCode::SUCCESS);
+ }));
+ MockVideoCaptureDeviceLauncherCallbacks mock_callbacks;
// Exercise part 1: Create a device launcher and hold on to it.
auto device_launcher_1 = provider_->CreateDeviceLauncher();
+ base::RunLoop wait_for_launch_1;
+ device_launcher_1->LaunchDeviceAsync(
+ kStubDeviceId, content::MEDIA_DEVICE_VIDEO_CAPTURE, kArbitraryParams,
+ kNullReceiver, base::BindOnce(&base::DoNothing), &mock_callbacks,
+ wait_for_launch_1.QuitClosure());
wait_for_connection_to_service_.Run();
+ wait_for_launch_1.Run();
// Monitor if connection gets closed
bool connection_has_been_closed = false;
@@ -257,6 +291,12 @@ TEST_F(ServiceVideoCaptureProviderTest,
// Exercise part 3: Create and release another device launcher
auto device_launcher_2 = provider_->CreateDeviceLauncher();
+ base::RunLoop wait_for_launch_2;
+ device_launcher_2->LaunchDeviceAsync(
+ kStubDeviceId, content::MEDIA_DEVICE_VIDEO_CAPTURE, kArbitraryParams,
+ kNullReceiver, base::BindOnce(&base::DoNothing), &mock_callbacks,
+ wait_for_launch_2.QuitClosure());
+ wait_for_launch_2.Run();
device_launcher_2.reset();
{
base::RunLoop give_provider_chance_to_disconnect;
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 e4c37d1e64a..8ca0ad0af59 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_browsertest.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_browsertest.cc
@@ -130,8 +130,9 @@ class VideoCaptureBrowserTest : public ContentBrowserTest,
if (post_to_end_of_message_queue) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
- base::Bind(&VideoCaptureBrowserTest::TearDownCaptureDeviceOnIOThread,
- base::Unretained(this), continuation, false));
+ base::BindOnce(
+ &VideoCaptureBrowserTest::TearDownCaptureDeviceOnIOThread,
+ base::Unretained(this), continuation, false));
return;
}
@@ -237,8 +238,9 @@ IN_PROC_BROWSER_TEST_P(VideoCaptureBrowserTest, StartAndImmediatelyStop) {
std::move(quit_run_loop_on_current_thread_cb), true);
BrowserThread::PostTask(
content::BrowserThread::IO, FROM_HERE,
- base::Bind(&VideoCaptureBrowserTest::SetUpAndStartCaptureDeviceOnIOThread,
- base::Unretained(this), std::move(after_start_continuation)));
+ base::BindOnce(
+ &VideoCaptureBrowserTest::SetUpAndStartCaptureDeviceOnIOThread,
+ base::Unretained(this), std::move(after_start_continuation)));
run_loop.Run();
}
@@ -326,8 +328,9 @@ IN_PROC_BROWSER_TEST_P(VideoCaptureBrowserTest,
base::Closure do_nothing;
BrowserThread::PostTask(
content::BrowserThread::IO, FROM_HERE,
- base::Bind(&VideoCaptureBrowserTest::SetUpAndStartCaptureDeviceOnIOThread,
- base::Unretained(this), std::move(do_nothing)));
+ base::BindOnce(
+ &VideoCaptureBrowserTest::SetUpAndStartCaptureDeviceOnIOThread,
+ base::Unretained(this), std::move(do_nothing)));
run_loop.Run();
EXPECT_FALSE(must_wait_for_gpu_decode_to_start);
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 3dcb7a4b21c..72c6257dbae 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_controller.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_controller.cc
@@ -536,8 +536,8 @@ void VideoCaptureController::CreateAndStartDeviceAsync(
device_launch_observer_ = observer;
device_launcher_->LaunchDeviceAsync(
device_id_, stream_type_, params, GetWeakPtrForIOThread(),
- base::Bind(&VideoCaptureController::OnDeviceConnectionLost,
- GetWeakPtrForIOThread()),
+ base::BindOnce(&VideoCaptureController::OnDeviceConnectionLost,
+ GetWeakPtrForIOThread()),
this, std::move(done_cb));
}
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 124f533df70..593039d5a5a 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
@@ -97,18 +97,18 @@ class MockVideoCaptureControllerEventHandler
DoBufferReady(id, frame_info->coded_size);
if (enable_auto_return_buffer_on_buffer_ready_) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&VideoCaptureController::ReturnBuffer,
- base::Unretained(controller_), id, this,
- buffer_id, resource_utilization_));
+ FROM_HERE, base::BindOnce(&VideoCaptureController::ReturnBuffer,
+ base::Unretained(controller_), id, this,
+ buffer_id, resource_utilization_));
}
}
void OnEnded(VideoCaptureControllerID id) override {
DoEnded(id);
// OnEnded() must respond by (eventually) unregistering the client.
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::Bind(base::IgnoreResult(&VideoCaptureController::RemoveClient),
- base::Unretained(controller_), id, this));
+ FROM_HERE, base::BindOnce(base::IgnoreResult(
+ &VideoCaptureController::RemoveClient),
+ base::Unretained(controller_), id, this));
}
VideoCaptureController* controller_;
@@ -266,17 +266,17 @@ TEST_F(VideoCaptureControllerTest, AddAndRemoveClients) {
controller_->StopSession(200); // Session 200 does not exist anymore
// Clients in controller: [B/2]
ASSERT_EQ(1, controller_->GetClientCount())
- << "Stopping non-existant session 200 should be a no-op.";
+ << "Stopping non-existent session 200 should be a no-op.";
controller_->StopSession(256); // Session 256 never existed.
// Clients in controller: [B/2]
ASSERT_EQ(1, controller_->GetClientCount())
- << "Stopping non-existant session 256 should be a no-op.";
+ << "Stopping non-existent session 256 should be a no-op.";
ASSERT_EQ(static_cast<int>(kInvalidMediaCaptureSessionId),
controller_->RemoveClient(client_a_route_1, client_a_.get()))
<< "Removing already-removed client A/1 should fail.";
// Clients in controller: [B/2]
ASSERT_EQ(1, controller_->GetClientCount())
- << "Removing non-existant session 200 should be a no-op.";
+ << "Removing non-existent session 200 should be a no-op.";
ASSERT_EQ(400, controller_->RemoveClient(client_b_route_2, client_b_.get()))
<< "Removing client B/2 should return its session_id.";
// Clients in controller: []
diff --git a/chromium/content/browser/renderer_host/media/video_capture_factory_delegate.cc b/chromium/content/browser/renderer_host/media/video_capture_factory_delegate.cc
new file mode 100644
index 00000000000..4b3c0b0d16e
--- /dev/null
+++ b/chromium/content/browser/renderer_host/media/video_capture_factory_delegate.cc
@@ -0,0 +1,28 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/media/video_capture_factory_delegate.h"
+
+namespace content {
+
+VideoCaptureFactoryDelegate::VideoCaptureFactoryDelegate(
+ video_capture::mojom::DeviceFactoryPtr* device_factory,
+ base::OnceClosure destruction_cb)
+ : device_factory_(device_factory),
+ destruction_cb_(std::move(destruction_cb)) {}
+
+VideoCaptureFactoryDelegate::~VideoCaptureFactoryDelegate() {
+ base::ResetAndReturn(&destruction_cb_).Run();
+}
+
+void VideoCaptureFactoryDelegate::CreateDevice(
+ const std::string& device_id,
+ ::video_capture::mojom::DeviceRequest device_request,
+ video_capture::mojom::DeviceFactory::CreateDeviceCallback callback) {
+ DCHECK(device_factory_->is_bound());
+ (*device_factory_)
+ ->CreateDevice(device_id, std::move(device_request), std::move(callback));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/video_capture_factory_delegate.h b/chromium/content/browser/renderer_host/media/video_capture_factory_delegate.h
new file mode 100644
index 00000000000..dc27e295c27
--- /dev/null
+++ b/chromium/content/browser/renderer_host/media/video_capture_factory_delegate.h
@@ -0,0 +1,42 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_CAPTURE_FACTORY_DELEGATE_H_
+#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_CAPTURE_FACTORY_DELEGATE_H_
+
+#include "content/common/content_export.h"
+#include "services/video_capture/public/interfaces/device_factory.mojom.h"
+
+namespace content {
+
+// Forwards calls to a given video_capture::mojom::DeviceFactoryPtr and invokes
+// a given OnceClosure on destruction.
+// Before calling CreatDevice(), clients must verify that is_bound() returns
+// true. When is_bound() returns false, calling CreateDevice() is illegal.
+// Note: This can happen when the ServiceVideoCaptureProvider owning
+// |device_factory_| loses connection to the service process and resets
+// |device_factory_|.
+class CONTENT_EXPORT VideoCaptureFactoryDelegate {
+ public:
+ VideoCaptureFactoryDelegate(
+ video_capture::mojom::DeviceFactoryPtr* device_factory,
+ base::OnceClosure destruction_cb);
+
+ ~VideoCaptureFactoryDelegate();
+
+ bool is_bound() { return device_factory_->is_bound(); }
+
+ void CreateDevice(
+ const std::string& device_id,
+ ::video_capture::mojom::DeviceRequest device_request,
+ video_capture::mojom::DeviceFactory::CreateDeviceCallback callback);
+
+ private:
+ video_capture::mojom::DeviceFactoryPtr* const device_factory_;
+ base::OnceClosure destruction_cb_;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_CAPTURE_FACTORY_DELEGATE_H_
diff --git a/chromium/content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.cc b/chromium/content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.cc
index 69700089573..22fbcb8d2d3 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.cc
@@ -73,8 +73,8 @@ void VideoCaptureGpuJpegDecoder::Initialize() {
const scoped_refptr<base::SingleThreadTaskRunner> current_task_runner(
base::ThreadTaskRunnerHandle::Get());
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(&EstablishGpuChannelOnUIThread,
- current_task_runner, AsWeakPtr()));
+ base::BindOnce(&EstablishGpuChannelOnUIThread,
+ current_task_runner, AsWeakPtr()));
}
VideoCaptureGpuJpegDecoder::STATUS VideoCaptureGpuJpegDecoder::GetStatus()
@@ -267,8 +267,9 @@ void VideoCaptureGpuJpegDecoder::GpuChannelEstablishedOnUIThread(
DCHECK_CURRENTLY_ON(BrowserThread::UI);
task_runner->PostTask(
- FROM_HERE, base::Bind(&VideoCaptureGpuJpegDecoder::FinishInitialization,
- weak_this, std::move(gpu_channel_host)));
+ FROM_HERE,
+ base::BindOnce(&VideoCaptureGpuJpegDecoder::FinishInitialization,
+ weak_this, std::move(gpu_channel_host)));
}
void VideoCaptureGpuJpegDecoder::FinishInitialization(
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 d9a2b4ef1af..da26a5c4694 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_host.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_host.cc
@@ -106,8 +106,8 @@ VideoCaptureHost::~VideoCaptureHost() {
// destroyed on UI thread.
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&RenderProcessHostDelegate::NotifyAllStreamsRemoved,
- base::Unretained(render_process_host_delegate_.get())));
+ base::BindOnce(&RenderProcessHostDelegate::NotifyAllStreamsRemoved,
+ base::Unretained(render_process_host_delegate_.get())));
BrowserThread::DeleteSoon(BrowserThread::UI, FROM_HERE,
render_process_host_delegate_.release());
}
@@ -117,8 +117,8 @@ void VideoCaptureHost::OnError(VideoCaptureControllerID controller_id) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&VideoCaptureHost::DoError, weak_factory_.GetWeakPtr(),
- controller_id));
+ base::BindOnce(&VideoCaptureHost::DoError, weak_factory_.GetWeakPtr(),
+ controller_id));
}
void VideoCaptureHost::OnBufferCreated(VideoCaptureControllerID controller_id,
@@ -165,8 +165,8 @@ void VideoCaptureHost::OnEnded(VideoCaptureControllerID controller_id) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&VideoCaptureHost::DoEnded, weak_factory_.GetWeakPtr(),
- controller_id));
+ base::BindOnce(&VideoCaptureHost::DoEnded, weak_factory_.GetWeakPtr(),
+ controller_id));
}
void VideoCaptureHost::OnStarted(VideoCaptureControllerID controller_id) {
@@ -182,8 +182,8 @@ void VideoCaptureHost::OnStarted(VideoCaptureControllerID controller_id) {
// is destroyed on UI thread.
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&RenderProcessHostDelegate::NotifyStreamAdded,
- base::Unretained(render_process_host_delegate_.get())));
+ base::BindOnce(&RenderProcessHostDelegate::NotifyStreamAdded,
+ base::Unretained(render_process_host_delegate_.get())));
}
}
@@ -209,8 +209,8 @@ void VideoCaptureHost::Start(int32_t device_id,
// is destroyed on UI thread.
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&RenderProcessHostDelegate::NotifyStreamAdded,
- base::Unretained(render_process_host_delegate_.get())));
+ base::BindOnce(&RenderProcessHostDelegate::NotifyStreamAdded,
+ base::Unretained(render_process_host_delegate_.get())));
return;
}
@@ -238,8 +238,8 @@ void VideoCaptureHost::Stop(int32_t device_id) {
// destroyed on UI thread.
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&RenderProcessHostDelegate::NotifyStreamRemoved,
- base::Unretained(render_process_host_delegate_.get())));
+ base::BindOnce(&RenderProcessHostDelegate::NotifyStreamRemoved,
+ base::Unretained(render_process_host_delegate_.get())));
}
void VideoCaptureHost::Pause(int32_t device_id) {
@@ -354,8 +354,8 @@ void VideoCaptureHost::DoError(VideoCaptureControllerID controller_id) {
// destroyed on UI thread.
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&RenderProcessHostDelegate::NotifyStreamRemoved,
- base::Unretained(render_process_host_delegate_.get())));
+ base::BindOnce(&RenderProcessHostDelegate::NotifyStreamRemoved,
+ base::Unretained(render_process_host_delegate_.get())));
}
void VideoCaptureHost::DoEnded(VideoCaptureControllerID controller_id) {
@@ -374,8 +374,8 @@ void VideoCaptureHost::DoEnded(VideoCaptureControllerID controller_id) {
// destroyed on UI thread.
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&RenderProcessHostDelegate::NotifyStreamRemoved,
- base::Unretained(render_process_host_delegate_.get())));
+ base::BindOnce(&RenderProcessHostDelegate::NotifyStreamRemoved,
+ base::Unretained(render_process_host_delegate_.get())));
}
void VideoCaptureHost::OnControllerAdded(
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 bc4f061eb9c..09fe221a7f2 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_manager.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_manager.cc
@@ -170,8 +170,8 @@ int VideoCaptureManager::Open(const MediaStreamDevice& device) {
// |capture_session_id| to the caller of this function before using that same
// id in a listener event.
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&VideoCaptureManager::OnOpened, this, device.type,
- capture_session_id));
+ FROM_HERE, base::BindOnce(&VideoCaptureManager::OnOpened, this,
+ device.type, capture_session_id));
return capture_session_id;
}
@@ -200,8 +200,8 @@ void VideoCaptureManager::Close(int capture_session_id) {
// Notify listeners asynchronously, and forget the session.
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&VideoCaptureManager::OnClosed, this,
- session_it->second.type, capture_session_id));
+ FROM_HERE, base::BindOnce(&VideoCaptureManager::OnClosed, this,
+ session_it->second.type, capture_session_id));
sessions_.erase(session_it);
}
@@ -258,8 +258,8 @@ void VideoCaptureManager::DoStopDevice(VideoCaptureController* controller) {
// ReleaseDeviceAsnyc() is executing, we pass it shared ownership to
// |controller|.
controller->ReleaseDeviceAsync(
- base::Bind([](scoped_refptr<VideoCaptureController>) {},
- GetControllerSharedRef(controller)));
+ base::BindOnce([](scoped_refptr<VideoCaptureController>) {},
+ GetControllerSharedRef(controller)));
}
void VideoCaptureManager::ProcessDeviceStartRequestQueue() {
@@ -302,10 +302,10 @@ void VideoCaptureManager::ProcessDeviceStartRequestQueue() {
// controller->parameters, and simplify if this is not the case.
controller->CreateAndStartDeviceAsync(
request->params(), static_cast<VideoCaptureDeviceLaunchObserver*>(this),
- base::Bind([](scoped_refptr<VideoCaptureManager>,
- scoped_refptr<VideoCaptureController>) {},
- scoped_refptr<VideoCaptureManager>(this),
- GetControllerSharedRef(controller)));
+ base::BindOnce([](scoped_refptr<VideoCaptureManager>,
+ scoped_refptr<VideoCaptureController>) {},
+ scoped_refptr<VideoCaptureManager>(this),
+ GetControllerSharedRef(controller)));
}
void VideoCaptureManager::OnDeviceLaunched(VideoCaptureController* controller) {
@@ -591,8 +591,8 @@ void VideoCaptureManager::MaybePostDesktopCaptureWindowId(
existing_device->SetDesktopCaptureWindowIdAsync(
window_id_it->second,
- base::Bind([](scoped_refptr<VideoCaptureManager>) {},
- scoped_refptr<VideoCaptureManager>(this)));
+ base::BindOnce([](scoped_refptr<VideoCaptureManager>) {},
+ scoped_refptr<VideoCaptureManager>(this)));
notification_window_ids_.erase(window_id_it);
}
diff --git a/chromium/content/browser/renderer_host/media/video_capture_unittest.cc b/chromium/content/browser/renderer_host/media/video_capture_unittest.cc
index f87d522b937..276f0cfc813 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_unittest.cc
@@ -130,8 +130,8 @@ class VideoCaptureTest : public testing::Test,
switches::kUseFakeDeviceForMediaStream);
base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kUseFakeUIForMediaStream);
- media_stream_manager_ =
- base::MakeUnique<MediaStreamManager>(audio_system_.get());
+ media_stream_manager_ = base::MakeUnique<MediaStreamManager>(
+ audio_system_.get(), audio_manager_->GetTaskRunner());
// Create a Host and connect it to a simulated IPC channel.
host_.reset(new VideoCaptureHost(0 /* render_process_id */,
diff --git a/chromium/content/browser/renderer_host/native_web_keyboard_event_android.cc b/chromium/content/browser/renderer_host/native_web_keyboard_event_android.cc
index fe935554ba6..ece07f945ea 100644
--- a/chromium/content/browser/renderer_host/native_web_keyboard_event_android.cc
+++ b/chromium/content/browser/renderer_host/native_web_keyboard_event_android.cc
@@ -9,20 +9,6 @@
#include "ui/events/base_event_utils.h"
#include "ui/gfx/native_widget_types.h"
-namespace {
-
-jobject NewGlobalRefForKeyEvent(jobject key_event) {
- if (key_event == nullptr) return nullptr;
- return base::android::AttachCurrentThread()->NewGlobalRef(key_event);
-}
-
-void DeleteGlobalRefForKeyEvent(jobject key_event) {
- if (key_event != nullptr)
- base::android::AttachCurrentThread()->DeleteGlobalRef(key_event);
-}
-
-}
-
namespace content {
NativeWebKeyboardEvent::NativeWebKeyboardEvent(blink::WebInputEvent::Type type,
@@ -40,6 +26,10 @@ NativeWebKeyboardEvent::NativeWebKeyboardEvent(blink::WebInputEvent::Type type,
skip_in_browser(false) {}
NativeWebKeyboardEvent::NativeWebKeyboardEvent(
+ const blink::WebKeyboardEvent& web_event)
+ : WebKeyboardEvent(web_event), os_event(nullptr), skip_in_browser(false) {}
+
+NativeWebKeyboardEvent::NativeWebKeyboardEvent(
JNIEnv* env,
const base::android::JavaRef<jobject>& android_key_event,
blink::WebInputEvent::Type type,
@@ -61,28 +51,25 @@ NativeWebKeyboardEvent::NativeWebKeyboardEvent(
os_event(nullptr),
skip_in_browser(false) {
if (!android_key_event.is_null())
- os_event = NewGlobalRefForKeyEvent(android_key_event.obj());
+ os_event.Reset(android_key_event);
}
NativeWebKeyboardEvent::NativeWebKeyboardEvent(
const NativeWebKeyboardEvent& other)
: WebKeyboardEvent(other),
- os_event(NewGlobalRefForKeyEvent(other.os_event)),
- skip_in_browser(other.skip_in_browser) {
-}
+ os_event(other.os_event),
+ skip_in_browser(other.skip_in_browser) {}
NativeWebKeyboardEvent& NativeWebKeyboardEvent::operator=(
const NativeWebKeyboardEvent& other) {
WebKeyboardEvent::operator=(other);
- os_event = NewGlobalRefForKeyEvent(other.os_event);
+ os_event = other.os_event;
skip_in_browser = other.skip_in_browser;
return *this;
}
-NativeWebKeyboardEvent::~NativeWebKeyboardEvent() {
- DeleteGlobalRefForKeyEvent(os_event);
-}
+NativeWebKeyboardEvent::~NativeWebKeyboardEvent() {}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/native_web_keyboard_event_aura.cc b/chromium/content/browser/renderer_host/native_web_keyboard_event_aura.cc
index 53e401bd43a..8525570084d 100644
--- a/chromium/content/browser/renderer_host/native_web_keyboard_event_aura.cc
+++ b/chromium/content/browser/renderer_host/native_web_keyboard_event_aura.cc
@@ -8,6 +8,7 @@
#include "ui/events/base_event_utils.h"
#include "ui/events/blink/web_input_event.h"
#include "ui/events/event.h"
+#include "ui/events/keycodes/dom/keycode_converter.h"
namespace {
@@ -19,6 +20,78 @@ ui::Event* CopyEvent(const ui::Event* event) {
return event ? ui::Event::Clone(*event).release() : nullptr;
}
+int WebEventModifiersToEventFlags(int modifiers) {
+ int flags = 0;
+ if (modifiers & blink::WebInputEvent::kShiftKey)
+ flags |= ui::EF_SHIFT_DOWN;
+ if (modifiers & blink::WebInputEvent::kControlKey)
+ flags |= ui::EF_CONTROL_DOWN;
+ if (modifiers & blink::WebInputEvent::kAltKey)
+ flags |= ui::EF_ALT_DOWN;
+ if (modifiers & blink::WebInputEvent::kMetaKey)
+ flags |= ui::EF_COMMAND_DOWN;
+ if (modifiers & blink::WebInputEvent::kAltGrKey)
+ flags |= ui::EF_ALTGR_DOWN;
+ if (modifiers & blink::WebInputEvent::kNumLockOn)
+ flags |= ui::EF_NUM_LOCK_ON;
+ if (modifiers & blink::WebInputEvent::kCapsLockOn)
+ flags |= ui::EF_CAPS_LOCK_ON;
+ if (modifiers & blink::WebInputEvent::kScrollLockOn)
+ flags |= ui::EF_SCROLL_LOCK_ON;
+ if (modifiers & blink::WebInputEvent::kLeftButtonDown)
+ flags |= ui::EF_LEFT_MOUSE_BUTTON;
+ if (modifiers & blink::WebInputEvent::kMiddleButtonDown)
+ flags |= ui::EF_MIDDLE_MOUSE_BUTTON;
+ if (modifiers & blink::WebInputEvent::kRightButtonDown)
+ flags |= ui::EF_RIGHT_MOUSE_BUTTON;
+ if (modifiers & blink::WebInputEvent::kBackButtonDown)
+ flags |= ui::EF_BACK_MOUSE_BUTTON;
+ if (modifiers & blink::WebInputEvent::kForwardButtonDown)
+ flags |= ui::EF_FORWARD_MOUSE_BUTTON;
+ if (modifiers & blink::WebInputEvent::kIsAutoRepeat)
+ flags |= ui::EF_IS_REPEAT;
+ if (modifiers & blink::WebInputEvent::kIsTouchAccessibility)
+ flags |= ui::EF_TOUCH_ACCESSIBILITY;
+ return flags;
+}
+
+class TranslatedKeyEvent : public ui::KeyEvent {
+ public:
+ static TranslatedKeyEvent* Create(const blink::WebKeyboardEvent& web_event) {
+ ui::EventType type = ui::ET_KEY_RELEASED;
+ bool is_char = false;
+ if (web_event.GetType() == blink::WebInputEvent::kChar) {
+ is_char = true;
+ type = ui::ET_KEY_PRESSED;
+ } else if (web_event.GetType() == blink::WebInputEvent::kRawKeyDown ||
+ web_event.GetType() == blink::WebInputEvent::kKeyDown) {
+ type = ui::ET_KEY_PRESSED;
+ }
+ // look up the DomCode in the table because we can't trust the
+ // WebKeyboardEvent as it came from the renderer.
+ return new TranslatedKeyEvent(
+ type, static_cast<ui::KeyboardCode>(web_event.windows_key_code),
+ ui::KeycodeConverter::NativeKeycodeToDomCode(web_event.native_key_code),
+ WebEventModifiersToEventFlags(web_event.GetModifiers()),
+ web_event.dom_key,
+ base::TimeTicks() +
+ base::TimeDelta::FromSecondsD(web_event.TimeStampSeconds()),
+ is_char);
+ }
+
+ private:
+ TranslatedKeyEvent(ui::EventType type,
+ ui::KeyboardCode keyboard_code,
+ ui::DomCode dom_code,
+ int flags,
+ ui::DomKey dom_key,
+ base::TimeTicks time,
+ bool is_char)
+ : KeyEvent(type, keyboard_code, dom_code, flags, dom_key, time) {
+ set_is_char(is_char);
+ }
+};
+
} // namespace
using blink::WebKeyboardEvent;
@@ -39,6 +112,12 @@ NativeWebKeyboardEvent::NativeWebKeyboardEvent(blink::WebInputEvent::Type type,
os_event(nullptr),
skip_in_browser(false) {}
+NativeWebKeyboardEvent::NativeWebKeyboardEvent(
+ const blink::WebKeyboardEvent& web_event)
+ : WebKeyboardEvent(web_event), os_event(nullptr), skip_in_browser(false) {
+ os_event = TranslatedKeyEvent::Create(web_event);
+}
+
NativeWebKeyboardEvent::NativeWebKeyboardEvent(gfx::NativeEvent native_event)
: NativeWebKeyboardEvent(static_cast<ui::KeyEvent&>(*native_event)) {
}
diff --git a/chromium/content/browser/renderer_host/native_web_keyboard_event_mac.mm b/chromium/content/browser/renderer_host/native_web_keyboard_event_mac.mm
index 9740bd65ee7..572fa1cd09b 100644
--- a/chromium/content/browser/renderer_host/native_web_keyboard_event_mac.mm
+++ b/chromium/content/browser/renderer_host/native_web_keyboard_event_mac.mm
@@ -12,6 +12,34 @@
namespace content {
+namespace {
+
+int modifiersForEvent(int modifiers) {
+ int flags = 0;
+ if (modifiers & blink::WebInputEvent::kControlKey)
+ flags |= NSControlKeyMask;
+ if (modifiers & blink::WebInputEvent::kShiftKey)
+ flags |= NSShiftKeyMask;
+ if (modifiers & blink::WebInputEvent::kAltKey)
+ flags |= NSAlternateKeyMask;
+ if (modifiers & blink::WebInputEvent::kMetaKey)
+ flags |= NSCommandKeyMask;
+ if (modifiers & blink::WebInputEvent::kCapsLockOn)
+ flags |= NSAlphaShiftKeyMask;
+ return flags;
+}
+
+size_t WebKeyboardEventTextLength(const blink::WebUChar* text) {
+ size_t text_length = 0;
+ while (text_length < blink::WebKeyboardEvent::kTextLengthCap &&
+ text[text_length]) {
+ ++text_length;
+ }
+ return text_length;
+}
+
+} // namepsace
+
NativeWebKeyboardEvent::NativeWebKeyboardEvent(blink::WebInputEvent::Type type,
int modifiers,
base::TimeTicks timestamp)
@@ -26,6 +54,42 @@ NativeWebKeyboardEvent::NativeWebKeyboardEvent(blink::WebInputEvent::Type type,
os_event(NULL),
skip_in_browser(false) {}
+NativeWebKeyboardEvent::NativeWebKeyboardEvent(
+ const blink::WebKeyboardEvent& web_event)
+ : WebKeyboardEvent(web_event), os_event(nullptr), skip_in_browser(false) {
+ NSEventType type = NSKeyUp;
+ int flags = modifiersForEvent(web_event.GetModifiers());
+ if (web_event.GetType() == blink::WebInputEvent::kChar ||
+ web_event.GetType() == blink::WebInputEvent::kRawKeyDown ||
+ web_event.GetType() == blink::WebInputEvent::kKeyDown) {
+ type = NSKeyDown;
+ }
+ size_t text_length = WebKeyboardEventTextLength(web_event.text);
+ size_t unmod_text_length =
+ WebKeyboardEventTextLength(web_event.unmodified_text);
+
+ if (text_length == 0)
+ type = NSFlagsChanged;
+
+ NSString* text =
+ [[[NSString alloc] initWithCharacters:web_event.text length:text_length]
+ autorelease];
+ NSString* unmodified_text =
+ [[[NSString alloc] initWithCharacters:web_event.unmodified_text
+ length:unmod_text_length] autorelease];
+
+ os_event = [[NSEvent keyEventWithType:type
+ location:NSZeroPoint
+ modifierFlags:flags
+ timestamp:web_event.TimeStampSeconds()
+ windowNumber:0
+ context:nil
+ characters:text
+ charactersIgnoringModifiers:unmodified_text
+ isARepeat:NO
+ keyCode:web_event.native_key_code] retain];
+}
+
NativeWebKeyboardEvent::NativeWebKeyboardEvent(gfx::NativeEvent native_event)
: WebKeyboardEvent(WebKeyboardEventBuilder::Build(native_event)),
os_event([native_event retain]),
diff --git a/chromium/content/browser/renderer_host/offscreen_canvas_provider_impl.cc b/chromium/content/browser/renderer_host/offscreen_canvas_provider_impl.cc
index c2cb711f3df..279340bc2e5 100644
--- a/chromium/content/browser/renderer_host/offscreen_canvas_provider_impl.cc
+++ b/chromium/content/browser/renderer_host/offscreen_canvas_provider_impl.cc
@@ -48,8 +48,8 @@ void OffscreenCanvasProviderImpl::CreateOffscreenCanvasSurface(
void OffscreenCanvasProviderImpl::CreateCompositorFrameSink(
const viz::FrameSinkId& frame_sink_id,
- cc::mojom::CompositorFrameSinkClientPtr client,
- cc::mojom::CompositorFrameSinkRequest request) {
+ viz::mojom::CompositorFrameSinkClientPtr client,
+ viz::mojom::CompositorFrameSinkRequest request) {
// TODO(kylechar): Kill the renderer too.
if (frame_sink_id.client_id() != renderer_client_id_) {
DLOG(ERROR) << "Invalid client id " << frame_sink_id;
diff --git a/chromium/content/browser/renderer_host/offscreen_canvas_provider_impl.h b/chromium/content/browser/renderer_host/offscreen_canvas_provider_impl.h
index ad768691a18..dec6f8be5a7 100644
--- a/chromium/content/browser/renderer_host/offscreen_canvas_provider_impl.h
+++ b/chromium/content/browser/renderer_host/offscreen_canvas_provider_impl.h
@@ -40,8 +40,8 @@ class CONTENT_EXPORT OffscreenCanvasProviderImpl
blink::mojom::OffscreenCanvasSurfaceRequest request) override;
void CreateCompositorFrameSink(
const viz::FrameSinkId& frame_sink_id,
- cc::mojom::CompositorFrameSinkClientPtr client,
- cc::mojom::CompositorFrameSinkRequest request) override;
+ viz::mojom::CompositorFrameSinkClientPtr client,
+ viz::mojom::CompositorFrameSinkRequest request) override;
private:
friend class OffscreenCanvasProviderImplTest;
diff --git a/chromium/content/browser/renderer_host/offscreen_canvas_provider_impl_unittest.cc b/chromium/content/browser/renderer_host/offscreen_canvas_provider_impl_unittest.cc
index 97840255a15..82d7aaa384f 100644
--- a/chromium/content/browser/renderer_host/offscreen_canvas_provider_impl_unittest.cc
+++ b/chromium/content/browser/renderer_host/offscreen_canvas_provider_impl_unittest.cc
@@ -11,11 +11,11 @@
#include "base/memory/ptr_util.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
-#include "cc/ipc/compositor_frame_sink.mojom.h"
#include "cc/output/compositor_frame.h"
#include "content/browser/compositor/surface_utils.h"
#include "content/browser/compositor/test/no_transport_image_transport_factory.h"
#include "content/browser/renderer_host/offscreen_canvas_surface_impl.h"
+#include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/WebKit/public/platform/modules/offscreencanvas/offscreen_canvas_surface.mojom.h"
@@ -55,7 +55,7 @@ class StubOffscreenCanvasSurfaceClient
private:
// blink::mojom::OffscreenCanvasSurfaceClient:
- void OnSurfaceCreated(const viz::SurfaceInfo& surface_info) override {
+ void OnFirstSurfaceActivation(const viz::SurfaceInfo& surface_info) override {
last_surface_info_ = surface_info;
}
@@ -67,27 +67,27 @@ class StubOffscreenCanvasSurfaceClient
// Stub CompositorFrameSinkClient that does nothing.
class StubCompositorFrameSinkClient
- : public cc::mojom::CompositorFrameSinkClient {
+ : public viz::mojom::CompositorFrameSinkClient {
public:
StubCompositorFrameSinkClient() : binding_(this) {}
~StubCompositorFrameSinkClient() override {}
- cc::mojom::CompositorFrameSinkClientPtr GetInterfacePtr() {
- cc::mojom::CompositorFrameSinkClientPtr client;
+ viz::mojom::CompositorFrameSinkClientPtr GetInterfacePtr() {
+ viz::mojom::CompositorFrameSinkClientPtr client;
binding_.Bind(mojo::MakeRequest(&client));
return client;
}
private:
- // cc::mojom::CompositorFrameSinkClient:
+ // viz::mojom::CompositorFrameSinkClient:
void DidReceiveCompositorFrameAck(
- const std::vector<cc::ReturnedResource>& resources) override {}
- void OnBeginFrame(const cc::BeginFrameArgs& begin_frame_args) override {}
+ const std::vector<viz::ReturnedResource>& resources) override {}
+ void OnBeginFrame(const viz::BeginFrameArgs& begin_frame_args) override {}
void OnBeginFramePausedChanged(bool paused) override {}
void ReclaimResources(
- const std::vector<cc::ReturnedResource>& resources) override {}
+ const std::vector<viz::ReturnedResource>& resources) override {}
- mojo::Binding<cc::mojom::CompositorFrameSinkClient> binding_;
+ mojo::Binding<viz::mojom::CompositorFrameSinkClient> binding_;
DISALLOW_COPY_AND_ASSIGN(StubCompositorFrameSinkClient);
};
@@ -96,9 +96,9 @@ class StubCompositorFrameSinkClient
cc::CompositorFrame MakeCompositorFrame() {
cc::CompositorFrame frame;
frame.metadata.begin_frame_ack.source_id =
- cc::BeginFrameArgs::kManualSourceId;
+ viz::BeginFrameArgs::kManualSourceId;
frame.metadata.begin_frame_ack.sequence_number =
- cc::BeginFrameArgs::kStartingFrameNumber;
+ viz::BeginFrameArgs::kStartingFrameNumber;
frame.metadata.device_scale_factor = 1.0f;
auto render_pass = cc::RenderPass::Create();
@@ -198,7 +198,7 @@ TEST_F(OffscreenCanvasProviderImplTest,
EXPECT_THAT(GetAllCanvases(), ElementsAre(kFrameSinkA));
// Mimic connection from the renderer main or worker thread to browser.
- cc::mojom::CompositorFrameSinkPtr compositor_frame_sink;
+ viz::mojom::CompositorFrameSinkPtr compositor_frame_sink;
StubCompositorFrameSinkClient compositor_frame_sink_client;
provider()->CreateCompositorFrameSink(
kFrameSinkA, compositor_frame_sink_client.GetInterfacePtr(),
@@ -206,7 +206,9 @@ TEST_F(OffscreenCanvasProviderImplTest,
// Renderer submits a CompositorFrame with |local_id|.
const viz::LocalSurfaceId local_id(1, base::UnguessableToken::Create());
- compositor_frame_sink->SubmitCompositorFrame(local_id, MakeCompositorFrame());
+ compositor_frame_sink->SubmitCompositorFrame(
+ local_id, MakeCompositorFrame(), nullptr,
+ base::TimeTicks::Now().since_origin().InMicroseconds());
RunUntilIdle();
@@ -279,7 +281,7 @@ TEST_F(OffscreenCanvasProviderImplTest, ProviderClosesConnections) {
// OffscreenCanvasSurface connection fails.
TEST_F(OffscreenCanvasProviderImplTest, ClientConnectionWrongOrder) {
// Mimic connection from the renderer main or worker thread.
- cc::mojom::CompositorFrameSinkPtr compositor_frame_sink;
+ viz::mojom::CompositorFrameSinkPtr compositor_frame_sink;
StubCompositorFrameSinkClient compositor_frame_sink_client;
// Try to connect CompositorFrameSink without first making
// OffscreenCanvasSurface connection. This should fail.
diff --git a/chromium/content/browser/renderer_host/offscreen_canvas_surface_impl.cc b/chromium/content/browser/renderer_host/offscreen_canvas_surface_impl.cc
index 8db30247c42..f6f5435697c 100644
--- a/chromium/content/browser/renderer_host/offscreen_canvas_surface_impl.cc
+++ b/chromium/content/browser/renderer_host/offscreen_canvas_surface_impl.cc
@@ -10,6 +10,7 @@
#include "base/memory/ptr_util.h"
#include "components/viz/host/host_frame_sink_manager.h"
#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
+#include "components/viz/service/surfaces/surface_manager.h"
#include "content/browser/compositor/surface_utils.h"
namespace content {
@@ -28,23 +29,22 @@ OffscreenCanvasSurfaceImpl::OffscreenCanvasSurfaceImpl(
frame_sink_id_(frame_sink_id),
parent_frame_sink_id_(parent_frame_sink_id) {
binding_.set_connection_error_handler(
- base::Bind(&OffscreenCanvasSurfaceImpl::OnSurfaceConnectionClosed,
- base::Unretained(this)));
- host_frame_sink_manager_->AddObserver(this);
+ base::BindOnce(&OffscreenCanvasSurfaceImpl::OnSurfaceConnectionClosed,
+ base::Unretained(this)));
+ host_frame_sink_manager_->RegisterFrameSinkId(frame_sink_id_, this);
}
OffscreenCanvasSurfaceImpl::~OffscreenCanvasSurfaceImpl() {
if (has_created_compositor_frame_sink_) {
host_frame_sink_manager_->UnregisterFrameSinkHierarchy(
parent_frame_sink_id_, frame_sink_id_);
- host_frame_sink_manager_->DestroyCompositorFrameSink(frame_sink_id_);
+ host_frame_sink_manager_->InvalidateFrameSinkId(frame_sink_id_);
}
- host_frame_sink_manager_->RemoveObserver(this);
}
void OffscreenCanvasSurfaceImpl::CreateCompositorFrameSink(
- cc::mojom::CompositorFrameSinkClientPtr client,
- cc::mojom::CompositorFrameSinkRequest request) {
+ viz::mojom::CompositorFrameSinkClientPtr client,
+ viz::mojom::CompositorFrameSinkRequest request) {
if (has_created_compositor_frame_sink_) {
DLOG(ERROR) << "CreateCompositorFrameSink() called more than once.";
return;
@@ -58,24 +58,26 @@ void OffscreenCanvasSurfaceImpl::CreateCompositorFrameSink(
has_created_compositor_frame_sink_ = true;
}
-void OffscreenCanvasSurfaceImpl::OnSurfaceCreated(
+void OffscreenCanvasSurfaceImpl::OnFirstSurfaceActivation(
const viz::SurfaceInfo& surface_info) {
- if (surface_info.id().frame_sink_id() != frame_sink_id_)
- return;
+ DCHECK_EQ(surface_info.id().frame_sink_id(), frame_sink_id_);
local_surface_id_ = surface_info.id().local_surface_id();
if (client_)
- client_->OnSurfaceCreated(surface_info);
+ client_->OnFirstSurfaceActivation(surface_info);
}
void OffscreenCanvasSurfaceImpl::Require(const viz::SurfaceId& surface_id,
const viz::SurfaceSequence& sequence) {
- GetFrameSinkManager()->surface_manager()->RequireSequence(surface_id,
- sequence);
+ auto* surface_manager = GetFrameSinkManager()->surface_manager();
+ if (!surface_manager->using_surface_references())
+ surface_manager->RequireSequence(surface_id, sequence);
}
void OffscreenCanvasSurfaceImpl::Satisfy(const viz::SurfaceSequence& sequence) {
- GetFrameSinkManager()->surface_manager()->SatisfySequence(sequence);
+ auto* surface_manager = GetFrameSinkManager()->surface_manager();
+ if (!surface_manager->using_surface_references())
+ surface_manager->SatisfySequence(sequence);
}
void OffscreenCanvasSurfaceImpl::OnSurfaceConnectionClosed() {
diff --git a/chromium/content/browser/renderer_host/offscreen_canvas_surface_impl.h b/chromium/content/browser/renderer_host/offscreen_canvas_surface_impl.h
index 36192ef392a..93e5be1a399 100644
--- a/chromium/content/browser/renderer_host/offscreen_canvas_surface_impl.h
+++ b/chromium/content/browser/renderer_host/offscreen_canvas_surface_impl.h
@@ -9,7 +9,7 @@
#include "base/compiler_specific.h"
#include "components/viz/common/surfaces/frame_sink_id.h"
#include "components/viz/common/surfaces/surface_info.h"
-#include "components/viz/host/frame_sink_observer.h"
+#include "components/viz/host/host_frame_sink_client.h"
#include "components/viz/host/host_frame_sink_manager.h"
#include "content/common/content_export.h"
#include "mojo/public/cpp/bindings/binding.h"
@@ -21,7 +21,7 @@ namespace content {
// connections to both the renderer and frame sink manager.
class CONTENT_EXPORT OffscreenCanvasSurfaceImpl
: public blink::mojom::OffscreenCanvasSurface,
- public NON_EXPORTED_BASE(viz::FrameSinkObserver) {
+ public viz::HostFrameSinkClient {
public:
using DestroyCallback = base::OnceCallback<void()>;
@@ -48,11 +48,12 @@ class CONTENT_EXPORT OffscreenCanvasSurfaceImpl
// offscreen canvas client. The corresponding private interface will be owned
// here to control CompositorFrameSink lifetime. This should only ever be
// called once.
- void CreateCompositorFrameSink(cc::mojom::CompositorFrameSinkClientPtr client,
- cc::mojom::CompositorFrameSinkRequest request);
+ void CreateCompositorFrameSink(
+ viz::mojom::CompositorFrameSinkClientPtr client,
+ viz::mojom::CompositorFrameSinkRequest request);
- // FrameSinkObserver implementation.
- void OnSurfaceCreated(const viz::SurfaceInfo& surface_info) override;
+ // viz::HostFrameSinkClient implementation.
+ void OnFirstSurfaceActivation(const viz::SurfaceInfo& surface_info) override;
// blink::mojom::OffscreenCanvasSurface implementation.
void Require(const viz::SurfaceId& surface_id,
diff --git a/chromium/content/browser/renderer_host/overscroll_configuration.cc b/chromium/content/browser/renderer_host/overscroll_configuration.cc
index 2fc311f37ca..80f975bcdd2 100644
--- a/chromium/content/browser/renderer_host/overscroll_configuration.cc
+++ b/chromium/content/browser/renderer_host/overscroll_configuration.cc
@@ -16,7 +16,7 @@ const float kVertThresholdComplete = 0.20f;
const float kHorizThresholdStartTouchscreen = 50.f;
const float kHorizThresholdStartTouchpad = 50.f;
-const float kVertThresholdStart = 0.f;
+const float kVertThresholdStart = 50.f;
float GetHorizontalStartThresholdMultiplier() {
base::CommandLine* cmd = base::CommandLine::ForCurrentProcess();
diff --git a/chromium/content/browser/renderer_host/overscroll_controller.cc b/chromium/content/browser/renderer_host/overscroll_controller.cc
index d72d729295b..a94911152de 100644
--- a/chromium/content/browser/renderer_host/overscroll_controller.cc
+++ b/chromium/content/browser/renderer_host/overscroll_controller.cc
@@ -11,7 +11,6 @@
#include "content/browser/renderer_host/overscroll_controller_delegate.h"
#include "content/public/browser/overscroll_configuration.h"
#include "content/public/common/content_switches.h"
-#include "third_party/WebKit/public/platform/WebMouseWheelEvent.h"
using blink::WebInputEvent;
@@ -19,9 +18,9 @@ namespace content {
namespace {
-bool IsScrollEndEffectEnabled() {
+bool IsPullToRefreshEnabled() {
return base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
- switches::kScrollEndEffect) == "1";
+ switches::kPullToRefresh) == "1";
}
bool IsGestureEventFromTouchpad(const blink::WebInputEvent& event) {
@@ -90,31 +89,22 @@ bool OverscrollController::WillHandleEvent(const blink::WebInputEvent& event) {
if (!ShouldProcessEvent(event))
return false;
+ if (event.GetType() == blink::WebInputEvent::kGestureScrollBegin ||
+ event.GetType() == blink::WebInputEvent::kGestureScrollEnd ||
+ (event.GetType() == blink::WebInputEvent::kGestureScrollUpdate &&
+ overscroll_mode_ == OVERSCROLL_NONE)) {
+ // Will handle events when processing ACKs to ensure the correct order.
+ return false;
+ }
+
bool reset_scroll_state = false;
if (scroll_state_ != STATE_UNKNOWN ||
overscroll_delta_x_ || overscroll_delta_y_) {
switch (event.GetType()) {
- case blink::WebInputEvent::kGestureScrollEnd:
- // Avoid resetting the state on GestureScrollEnd generated
- // from the touchpad since it is sent based on a timeout.
- reset_scroll_state = !IsGestureEventFromTouchpad(event);
- break;
-
case blink::WebInputEvent::kGestureFlingStart:
reset_scroll_state = true;
break;
- case blink::WebInputEvent::kMouseWheel: {
- const blink::WebMouseWheelEvent& wheel =
- static_cast<const blink::WebMouseWheelEvent&>(event);
- if (!wheel.has_precise_scrolling_deltas ||
- wheel.phase == blink::WebMouseWheelEvent::kPhaseEnded ||
- wheel.phase == blink::WebMouseWheelEvent::kPhaseCancelled) {
- reset_scroll_state = true;
- }
- break;
- }
-
default:
if (blink::WebInputEvent::IsMouseEventType(event.GetType()) ||
blink::WebInputEvent::IsKeyboardEventType(event.GetType())) {
@@ -124,8 +114,10 @@ bool OverscrollController::WillHandleEvent(const blink::WebInputEvent& event) {
}
}
- if (reset_scroll_state)
+ if (reset_scroll_state) {
scroll_state_ = STATE_UNKNOWN;
+ locked_mode_ = OVERSCROLL_NONE;
+ }
if (DispatchEventCompletesAction(event)) {
CompleteAction();
@@ -149,7 +141,6 @@ bool OverscrollController::WillHandleEvent(const blink::WebInputEvent& event) {
overscroll_delta_x_ = overscroll_delta_y_ = 0.f;
}
-
return false;
}
@@ -163,8 +154,7 @@ void OverscrollController::ReceivedEventACK(const blink::WebInputEvent& event,
// has been scrolled, then there is not going to be an overscroll gesture,
// until the current scroll ends, and a new scroll gesture starts.
if (scroll_state_ == STATE_UNKNOWN &&
- (event.GetType() == blink::WebInputEvent::kMouseWheel ||
- event.GetType() == blink::WebInputEvent::kGestureScrollUpdate)) {
+ event.GetType() == blink::WebInputEvent::kGestureScrollUpdate) {
scroll_state_ = STATE_CONTENT_SCROLLING;
}
return;
@@ -183,6 +173,7 @@ void OverscrollController::DiscardingGestureEvent(
void OverscrollController::Reset() {
overscroll_mode_ = OVERSCROLL_NONE;
+ locked_mode_ = OVERSCROLL_NONE;
overscroll_source_ = OverscrollSource::NONE;
overscroll_delta_x_ = overscroll_delta_y_ = 0.f;
scroll_state_ = STATE_UNKNOWN;
@@ -190,6 +181,7 @@ void OverscrollController::Reset() {
void OverscrollController::Cancel() {
SetOverscrollMode(OVERSCROLL_NONE, OverscrollSource::NONE);
+ locked_mode_ = OVERSCROLL_NONE;
overscroll_delta_x_ = overscroll_delta_y_ = 0.f;
scroll_state_ = STATE_UNKNOWN;
}
@@ -243,9 +235,7 @@ bool OverscrollController::DispatchEventCompletesAction (
}
}
- const gfx::Size size = overscroll_source_ == OverscrollSource::TOUCHPAD
- ? delegate_->GetDisplaySize()
- : delegate_->GetVisibleSize();
+ const gfx::Size size = delegate_->GetDisplaySize();
if (size.IsEmpty())
return false;
@@ -265,20 +255,9 @@ bool OverscrollController::DispatchEventCompletesAction (
bool OverscrollController::DispatchEventResetsState(
const blink::WebInputEvent& event) const {
switch (event.GetType()) {
- case blink::WebInputEvent::kMouseWheel: {
- // Only wheel events with precise deltas (i.e. from trackpad) contribute
- // to the overscroll gesture.
- const blink::WebMouseWheelEvent& wheel =
- static_cast<const blink::WebMouseWheelEvent&>(event);
- return !wheel.has_precise_scrolling_deltas;
- }
-
- // Avoid resetting overscroll on GestureScrollBegin/End generated
- // from the touchpad since it is sent based on a timeout.
+ // GestureScrollBegin/End ACK will reset overscroll state when necessary.
case blink::WebInputEvent::kGestureScrollBegin:
case blink::WebInputEvent::kGestureScrollEnd:
- return !IsGestureEventFromTouchpad(event);
-
case blink::WebInputEvent::kGestureScrollUpdate:
case blink::WebInputEvent::kGestureFlingCancel:
return false;
@@ -294,14 +273,36 @@ bool OverscrollController::ProcessEventForOverscroll(
const blink::WebInputEvent& event) {
bool event_processed = false;
switch (event.GetType()) {
- case blink::WebInputEvent::kMouseWheel: {
- const blink::WebMouseWheelEvent& wheel =
- static_cast<const blink::WebMouseWheelEvent&>(event);
- if (!wheel.has_precise_scrolling_deltas)
+ case blink::WebInputEvent::kGestureScrollBegin: {
+ // Avoid resetting the state on GestureScrollBegin generated
+ // from the touchpad since it is sent based on a timeout.
+ if (overscroll_mode_ != OVERSCROLL_NONE &&
+ !IsGestureEventFromTouchpad(event)) {
+ SetOverscrollMode(OVERSCROLL_NONE, OverscrollSource::NONE);
+ }
+ break;
+ }
+ case blink::WebInputEvent::kGestureScrollEnd: {
+ // Avoid resetting the state on GestureScrollEnd generated
+ // from the touchpad since it is sent based on a timeout.
+ bool reset_scroll_state = !IsGestureEventFromTouchpad(event);
+
+ if (reset_scroll_state)
+ scroll_state_ = STATE_UNKNOWN;
+
+ if (DispatchEventCompletesAction(event)) {
+ CompleteAction();
+ break;
+ }
+
+ if (!reset_scroll_state)
break;
- event_processed =
- ProcessOverscroll(wheel.delta_x * wheel.acceleration_ratio_x,
- wheel.delta_y * wheel.acceleration_ratio_y, true);
+
+ if (overscroll_mode_ != OVERSCROLL_NONE) {
+ SetOverscrollMode(OVERSCROLL_NONE, OverscrollSource::NONE);
+ } else {
+ overscroll_delta_x_ = overscroll_delta_y_ = 0.f;
+ }
break;
}
case blink::WebInputEvent::kGestureScrollUpdate: {
@@ -351,9 +352,10 @@ bool OverscrollController::ProcessEventForOverscroll(
bool OverscrollController::ProcessOverscroll(float delta_x,
float delta_y,
bool is_touchpad) {
- if (scroll_state_ != STATE_CONTENT_SCROLLING)
+ if (scroll_state_ != STATE_CONTENT_SCROLLING) {
overscroll_delta_x_ += delta_x;
- overscroll_delta_y_ += delta_y;
+ overscroll_delta_y_ += delta_y;
+ }
const float horiz_threshold = GetOverscrollConfig(
is_touchpad ? OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START_TOUCHPAD
@@ -369,6 +371,7 @@ bool OverscrollController::ProcessOverscroll(float delta_x,
if (delegate_) {
base::Optional<float> cap = delegate_->GetMaxOverscrollDelta();
if (cap) {
+ DCHECK_LE(0.f, cap.value());
switch (overscroll_mode_) {
case OVERSCROLL_WEST:
case OVERSCROLL_EAST:
@@ -398,10 +401,10 @@ bool OverscrollController::ProcessOverscroll(float delta_x,
fabs(overscroll_delta_y_) > fabs(overscroll_delta_x_) * kMinRatio)
new_mode = overscroll_delta_y_ > 0.f ? OVERSCROLL_SOUTH : OVERSCROLL_NORTH;
- // The vertical oversrcoll currently does not have any UX effects other then
- // for the scroll end effect, so testing if it is enabled.
+ // The vertical overscroll is used for pull-to-refresh. Enable it only if
+ // pull-to-refresh is enabled.
if ((new_mode == OVERSCROLL_SOUTH || new_mode == OVERSCROLL_NORTH) &&
- !IsScrollEndEffectEnabled())
+ !IsPullToRefreshEnabled())
new_mode = OVERSCROLL_NONE;
if (overscroll_mode_ == OVERSCROLL_NONE) {
@@ -446,9 +449,7 @@ bool OverscrollController::ProcessOverscroll(float delta_x,
void OverscrollController::CompleteAction() {
if (delegate_)
delegate_->OnOverscrollComplete(overscroll_mode_);
- overscroll_mode_ = OVERSCROLL_NONE;
- overscroll_source_ = OverscrollSource::NONE;
- overscroll_delta_x_ = overscroll_delta_y_ = 0.f;
+ Reset();
}
void OverscrollController::SetOverscrollMode(OverscrollMode mode,
@@ -459,13 +460,22 @@ void OverscrollController::SetOverscrollMode(OverscrollMode mode,
// If the mode changes to NONE, source is also NONE.
DCHECK(mode != OVERSCROLL_NONE || source == OverscrollSource::NONE);
+ // When setting to a non-NONE mode and there is a locked mode, don't set the
+ // mode if the new mode is not the same as the locked mode.
+ if (mode != OVERSCROLL_NONE && locked_mode_ != OVERSCROLL_NONE &&
+ mode != locked_mode_) {
+ return;
+ }
+
OverscrollMode old_mode = overscroll_mode_;
overscroll_mode_ = mode;
overscroll_source_ = source;
- if (overscroll_mode_ == OVERSCROLL_NONE)
+ if (overscroll_mode_ == OVERSCROLL_NONE) {
overscroll_delta_x_ = overscroll_delta_y_ = 0.f;
- else
+ } else {
scroll_state_ = STATE_OVERSCROLLING;
+ locked_mode_ = overscroll_mode_;
+ }
if (delegate_)
delegate_->OnOverscrollModeChange(old_mode, overscroll_mode_, source);
}
diff --git a/chromium/content/browser/renderer_host/overscroll_controller.h b/chromium/content/browser/renderer_host/overscroll_controller.h
index 479dab63c4c..62e44583e9e 100644
--- a/chromium/content/browser/renderer_host/overscroll_controller.h
+++ b/chromium/content/browser/renderer_host/overscroll_controller.h
@@ -122,6 +122,11 @@ class OverscrollController {
// The current state of overscroll gesture.
OverscrollMode overscroll_mode_ = OVERSCROLL_NONE;
+ // When set to something other than OVERSCROLL_NONE, the overscroll cannot
+ // switch to any other mode, except to OVERSCROLL_NONE. This is set when an
+ // overscroll is started until the touch sequence is completed.
+ OverscrollMode locked_mode_ = OVERSCROLL_NONE;
+
// Source of the current overscroll gesture.
OverscrollSource overscroll_source_ = OverscrollSource::NONE;
diff --git a/chromium/content/browser/renderer_host/overscroll_controller_delegate.h b/chromium/content/browser/renderer_host/overscroll_controller_delegate.h
index 74c3ff4f1ca..0ae76bac8f8 100644
--- a/chromium/content/browser/renderer_host/overscroll_controller_delegate.h
+++ b/chromium/content/browser/renderer_host/overscroll_controller_delegate.h
@@ -22,9 +22,6 @@ class CONTENT_EXPORT OverscrollControllerDelegate {
OverscrollControllerDelegate() {}
virtual ~OverscrollControllerDelegate() {}
- // Get the size of the view corresponding to the delegate.
- virtual gfx::Size GetVisibleSize() const = 0;
-
// Get the size of the display containing the view corresponding to the
// delegate.
virtual gfx::Size GetDisplaySize() const = 0;
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 d791db160e6..a06a26558aa 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.cc
+++ b/chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.cc
@@ -162,7 +162,8 @@ bool P2PSocketDispatcherHost::OnMessageReceived(const IPC::Message& message) {
void P2PSocketDispatcherHost::OnIPAddressChanged() {
// Notify the renderer about changes to list of network interfaces.
network_list_task_runner_->PostTask(
- FROM_HERE, base::Bind(&P2PSocketDispatcherHost::DoGetNetworkList, this));
+ FROM_HERE,
+ base::BindOnce(&P2PSocketDispatcherHost::DoGetNetworkList, this));
}
void P2PSocketDispatcherHost::StartRtpDump(
@@ -189,12 +190,9 @@ void P2PSocketDispatcherHost::StopRtpDumpOnUIThread(bool incoming,
bool outgoing) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
BrowserThread::PostTask(
- BrowserThread::IO,
- FROM_HERE,
- base::Bind(&P2PSocketDispatcherHost::StopRtpDumpOnIOThread,
- this,
- incoming,
- outgoing));
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&P2PSocketDispatcherHost::StopRtpDumpOnIOThread, this,
+ incoming, outgoing));
}
P2PSocketDispatcherHost::~P2PSocketDispatcherHost() {
@@ -217,7 +215,8 @@ void P2PSocketDispatcherHost::OnStartNetworkNotifications() {
}
network_list_task_runner_->PostTask(
- FROM_HERE, base::Bind(&P2PSocketDispatcherHost::DoGetNetworkList, this));
+ FROM_HERE,
+ base::BindOnce(&P2PSocketDispatcherHost::DoGetNetworkList, this));
}
void P2PSocketDispatcherHost::OnStopNetworkNotifications() {
@@ -351,8 +350,8 @@ void P2PSocketDispatcherHost::DoGetNetworkList() {
default_ipv6_local_address_ = GetDefaultLocalAddress(AF_INET6);
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&P2PSocketDispatcherHost::SendNetworkList, this, list,
- default_ipv4_local_address_, default_ipv6_local_address_));
+ base::BindOnce(&P2PSocketDispatcherHost::SendNetworkList, this, list,
+ default_ipv4_local_address_, default_ipv6_local_address_));
}
void P2PSocketDispatcherHost::SendNetworkList(
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host.cc b/chromium/content/browser/renderer_host/p2p/socket_host.cc
index c2e9c2b18f1..70b4482d725 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host.cc
+++ b/chromium/content/browser/renderer_host/p2p/socket_host.cc
@@ -275,9 +275,10 @@ void P2PSocketHost::DumpRtpPacket(const char* packet,
// thread only.
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&P2PSocketHost::DumpRtpPacketOnIOThread,
- weak_ptr_factory_.GetWeakPtr(), base::Passed(&header_buffer),
- header_length, rtp_packet_length, incoming));
+ base::BindOnce(&P2PSocketHost::DumpRtpPacketOnIOThread,
+ weak_ptr_factory_.GetWeakPtr(),
+ base::Passed(&header_buffer), header_length,
+ rtp_packet_length, incoming));
}
void P2PSocketHost::DumpRtpPacketOnIOThread(
@@ -296,8 +297,8 @@ void P2PSocketHost::DumpRtpPacketOnIOThread(
// |packet_dump_callback_| must be called on the UI thread.
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(packet_dump_callback_, base::Passed(&packet_header),
- header_length, packet_length, incoming));
+ base::BindOnce(packet_dump_callback_, base::Passed(&packet_header),
+ header_length, packet_length, incoming));
}
void P2PSocketHost::IncrementDelayedPackets() {
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_tcp.cc b/chromium/content/browser/renderer_host/p2p/socket_host_tcp.cc
index 1961e1b0491..9f536022f69 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host_tcp.cc
+++ b/chromium/content/browser/renderer_host/p2p/socket_host_tcp.cc
@@ -133,8 +133,8 @@ bool P2PSocketHostTcpBase::Init(const net::IPEndPoint& local_address,
// happen here. This is okay, as from the caller's point of view,
// the connect always happens asynchronously.
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&P2PSocketHostTcpBase::OnConnected,
- base::Unretained(this), status));
+ FROM_HERE, base::BindOnce(&P2PSocketHostTcpBase::OnConnected,
+ base::Unretained(this), status));
}
return state_ != STATE_ERROR;
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_test_utils.cc b/chromium/content/browser/renderer_host/p2p/socket_host_test_utils.cc
index ec7a5e69e89..631f558268b 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host_test_utils.cc
+++ b/chromium/content/browser/renderer_host/p2p/socket_host_test_utils.cc
@@ -81,10 +81,10 @@ int FakeSocket::Write(net::IOBuffer* buf, int buf_len,
DCHECK(!write_pending_);
if (async_write_) {
-
- base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, base::Bind(
- &FakeSocket::DoAsyncWrite, base::Unretained(this),
- scoped_refptr<net::IOBuffer>(buf), buf_len, callback));
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&FakeSocket::DoAsyncWrite, base::Unretained(this),
+ scoped_refptr<net::IOBuffer>(buf), buf_len, callback));
write_pending_ = true;
return net::ERR_IO_PENDING;
}
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 1e0deb759f7..f90f8e268fd 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
@@ -97,9 +97,9 @@ void DidOpenFile(base::WeakPtr<PepperFileIOHost> file_host,
if (file_host) {
callback.Run(std::move(file), on_close_callback);
} else {
- task_runner->PostTaskAndReply(FROM_HERE,
- base::Bind(&FileCloser, base::Passed(&file)),
- base::Bind(&DidCloseFile, on_close_callback));
+ task_runner->PostTaskAndReply(
+ FROM_HERE, base::BindOnce(&FileCloser, base::Passed(&file)),
+ base::BindOnce(&DidCloseFile, on_close_callback));
}
}
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 70e29a73411..9deb174d129 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
@@ -69,7 +69,7 @@ PepperFileSystemBrowserHost::~PepperFileSystemBrowserHost() {
if (!files_.empty()) {
file_system_context_->default_file_task_runner()->PostTask(
FROM_HERE,
- base::Bind(&QuotaReservation::OnClientCrash, quota_reservation_));
+ base::BindOnce(&QuotaReservation::OnClientCrash, quota_reservation_));
}
// All FileRefs and FileIOs that reference us must have been destroyed. Cancel
@@ -147,9 +147,8 @@ void PepperFileSystemBrowserHost::CloseQuotaFile(
}
file_system_context_->default_file_task_runner()->PostTask(
- FROM_HERE,
- base::Bind(
- &QuotaReservation::CloseFile, quota_reservation_, id, file_growth));
+ FROM_HERE, base::BindOnce(&QuotaReservation::CloseFile,
+ quota_reservation_, id, file_growth));
}
int32_t PepperFileSystemBrowserHost::OnHostMsgOpen(
@@ -378,13 +377,11 @@ int32_t PepperFileSystemBrowserHost::OnHostMsgReserveQuota(
std::max<int64_t>(kMinimumQuotaReservationSize, amount);
file_system_context_->default_file_task_runner()->PostTask(
FROM_HERE,
- base::Bind(&QuotaReservation::ReserveQuota,
- quota_reservation_,
- reservation_amount,
- file_growths,
- base::Bind(&PepperFileSystemBrowserHost::GotReservedQuota,
- weak_factory_.GetWeakPtr(),
- context->MakeReplyMessageContext())));
+ base::BindOnce(&QuotaReservation::ReserveQuota, quota_reservation_,
+ reservation_amount, file_growths,
+ base::Bind(&PepperFileSystemBrowserHost::GotReservedQuota,
+ weak_factory_.GetWeakPtr(),
+ context->MakeReplyMessageContext())));
return PP_OK_COMPLETIONPENDING;
}
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 a8a1a3e5630..f5c86d89bde 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
@@ -143,14 +143,10 @@ int32_t PepperHostResolverMessageFilter::OnMsgResolve(
return PP_ERROR_FAILED;
BrowserThread::PostTask(
- BrowserThread::IO,
- FROM_HERE,
- base::Bind(&PepperHostResolverMessageFilter::DoResolve,
- this,
- context->MakeReplyMessageContext(),
- host_port,
- hint,
- browser_context->GetResourceContext()));
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&PepperHostResolverMessageFilter::DoResolve, this,
+ context->MakeReplyMessageContext(), host_port, hint,
+ browser_context->GetResourceContext()));
return PP_OK_COMPLETIONPENDING;
}
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.cc b/chromium/content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.cc
index ea05dc43be6..db1ace000c1 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.cc
@@ -209,10 +209,9 @@ int32_t PepperInternalFileRefBackend::ReadDirectoryEntries(
new storage::FileSystemOperation::FileEntryList;
GetFileSystemContext()->operation_runner()->ReadDirectory(
GetFileSystemURL(),
- base::Bind(&PepperInternalFileRefBackend::ReadDirectoryComplete,
- weak_factory_.GetWeakPtr(),
- reply_context,
- base::Owned(accumulated_file_list)));
+ base::BindRepeating(&PepperInternalFileRefBackend::ReadDirectoryComplete,
+ weak_factory_.GetWeakPtr(), reply_context,
+ base::Owned(accumulated_file_list)));
return PP_OK_COMPLETIONPENDING;
}
@@ -220,7 +219,7 @@ void PepperInternalFileRefBackend::ReadDirectoryComplete(
ppapi::host::ReplyMessageContext context,
storage::FileSystemOperation::FileEntryList* accumulated_file_list,
base::File::Error error,
- const storage::FileSystemOperation::FileEntryList& file_list,
+ storage::FileSystemOperation::FileEntryList file_list,
bool has_more) {
accumulated_file_list->insert(
accumulated_file_list->end(), file_list.begin(), file_list.end());
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.h b/chromium/content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.h
index 95734fe723a..deab6c7b498 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.h
+++ b/chromium/content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.h
@@ -68,7 +68,7 @@ class PepperInternalFileRefBackend : public PepperFileRefBackend {
ppapi::host::ReplyMessageContext context,
storage::FileSystemOperation::FileEntryList* accumulated_file_list,
base::File::Error error,
- const storage::FileSystemOperation::FileEntryList& file_list,
+ storage::FileSystemOperation::FileEntryList file_list,
bool has_more);
scoped_refptr<storage::FileSystemContext> GetFileSystemContext() const;
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 00b43ad23e9..abb4407b458 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
@@ -123,13 +123,9 @@ int32_t PepperTCPServerSocketMessageFilter::OnMsgListen(
}
BrowserThread::PostTask(
- BrowserThread::IO,
- FROM_HERE,
- base::Bind(&PepperTCPServerSocketMessageFilter::DoListen,
- this,
- context->MakeReplyMessageContext(),
- addr,
- backlog));
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&PepperTCPServerSocketMessageFilter::DoListen, this,
+ context->MakeReplyMessageContext(), addr, backlog));
return PP_OK_COMPLETIONPENDING;
}
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 bc94706eea5..827b3cb7161 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
@@ -233,12 +233,10 @@ int32_t PepperTCPSocketMessageFilter::OnMsgBind(
bind_input_addr_ = net_addr;
- BrowserThread::PostTask(BrowserThread::IO,
- FROM_HERE,
- base::Bind(&PepperTCPSocketMessageFilter::DoBind,
- this,
- context->MakeReplyMessageContext(),
- net_addr));
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&PepperTCPSocketMessageFilter::DoBind, this,
+ context->MakeReplyMessageContext(), net_addr));
return PP_OK_COMPLETIONPENDING;
}
@@ -272,14 +270,11 @@ int32_t PepperTCPSocketMessageFilter::OnMsgConnect(
if (!browser_context || !browser_context->GetResourceContext())
return PP_ERROR_FAILED;
- BrowserThread::PostTask(BrowserThread::IO,
- FROM_HERE,
- base::Bind(&PepperTCPSocketMessageFilter::DoConnect,
- this,
- context->MakeReplyMessageContext(),
- host,
- port,
- browser_context->GetResourceContext()));
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&PepperTCPSocketMessageFilter::DoConnect, this,
+ context->MakeReplyMessageContext(), host, port,
+ browser_context->GetResourceContext()));
return PP_OK_COMPLETIONPENDING;
}
@@ -300,12 +295,9 @@ int32_t PepperTCPSocketMessageFilter::OnMsgConnectWithNetAddress(
}
BrowserThread::PostTask(
- BrowserThread::IO,
- FROM_HERE,
- base::Bind(&PepperTCPSocketMessageFilter::DoConnectWithNetAddress,
- this,
- context->MakeReplyMessageContext(),
- net_addr));
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&PepperTCPSocketMessageFilter::DoConnectWithNetAddress,
+ this, context->MakeReplyMessageContext(), net_addr));
return PP_OK_COMPLETIONPENDING;
}
@@ -452,12 +444,10 @@ int32_t PepperTCPSocketMessageFilter::OnMsgListen(
return PP_ERROR_NOACCESS;
}
- BrowserThread::PostTask(BrowserThread::IO,
- FROM_HERE,
- base::Bind(&PepperTCPSocketMessageFilter::DoListen,
- this,
- context->MakeReplyMessageContext(),
- backlog));
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&PepperTCPSocketMessageFilter::DoListen, this,
+ context->MakeReplyMessageContext(), backlog));
return PP_OK_COMPLETIONPENDING;
}
@@ -967,9 +957,10 @@ void PepperTCPSocketMessageFilter::OpenFirewallHole(
pepper_socket_utils::FirewallHoleOpenCallback callback =
base::Bind(&PepperTCPSocketMessageFilter::OnFirewallHoleOpened, this,
context, pp_result);
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(&pepper_socket_utils::OpenTCPFirewallHole,
- local_addr, callback));
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&pepper_socket_utils::OpenTCPFirewallHole, local_addr,
+ callback));
}
void PepperTCPSocketMessageFilter::OnFirewallHoleOpened(
@@ -981,8 +972,8 @@ void PepperTCPSocketMessageFilter::OnFirewallHoleOpened(
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&PepperTCPSocketMessageFilter::OnListenCompleted, this,
- context, result));
+ base::BindOnce(&PepperTCPSocketMessageFilter::OnListenCompleted, this,
+ context, result));
}
#endif // defined(OS_CHROMEOS)
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 41ab65feed1..91a62eb3dc5 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
@@ -291,12 +291,10 @@ int32_t PepperUDPSocketMessageFilter::OnMsgBind(
return PP_ERROR_NOACCESS;
}
- BrowserThread::PostTask(BrowserThread::IO,
- FROM_HERE,
- base::Bind(&PepperUDPSocketMessageFilter::DoBind,
- this,
- context->MakeReplyMessageContext(),
- addr));
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&PepperUDPSocketMessageFilter::DoBind, this,
+ context->MakeReplyMessageContext(), addr));
return PP_OK_COMPLETIONPENDING;
}
@@ -318,13 +316,10 @@ int32_t PepperUDPSocketMessageFilter::OnMsgSendTo(
return PP_ERROR_NOACCESS;
}
- BrowserThread::PostTask(BrowserThread::IO,
- FROM_HERE,
- base::Bind(&PepperUDPSocketMessageFilter::DoSendTo,
- this,
- context->MakeReplyMessageContext(),
- data,
- addr));
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&PepperUDPSocketMessageFilter::DoSendTo, this,
+ context->MakeReplyMessageContext(), data, addr));
return PP_OK_COMPLETIONPENDING;
}
@@ -529,9 +524,10 @@ void PepperUDPSocketMessageFilter::OpenFirewallHole(
DCHECK_CURRENTLY_ON(BrowserThread::IO);
pepper_socket_utils::FirewallHoleOpenCallback callback = base::Bind(
&PepperUDPSocketMessageFilter::OnFirewallHoleOpened, this, bind_complete);
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(&pepper_socket_utils::OpenUDPFirewallHole,
- local_address, callback));
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&pepper_socket_utils::OpenUDPFirewallHole, local_address,
+ callback));
}
void PepperUDPSocketMessageFilter::OnFirewallHoleOpened(
diff --git a/chromium/content/browser/renderer_host/pepper/quota_reservation.cc b/chromium/content/browser/renderer_host/pepper/quota_reservation.cc
index 2cc43000193..932c7dd645d 100644
--- a/chromium/content/browser/renderer_host/pepper/quota_reservation.cc
+++ b/chromium/content/browser/renderer_host/pepper/quota_reservation.cc
@@ -121,10 +121,9 @@ void QuotaReservation::GotReservedQuota(const ReserveQuotaCallback& callback,
if (file_system_context_.get()) {
BrowserThread::PostTask(
- BrowserThread::IO,
- FROM_HERE,
- base::Bind(
- callback, quota_reservation_->remaining_quota(), file_sizes));
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(callback, quota_reservation_->remaining_quota(),
+ file_sizes));
} else {
// Unit testing code path.
callback.Run(quota_reservation_->remaining_quota(), file_sizes);
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 fe4448b599c..03ade3604d1 100644
--- a/chromium/content/browser/renderer_host/pepper/quota_reservation_unittest.cc
+++ b/chromium/content/browser/renderer_host/pepper/quota_reservation_unittest.cc
@@ -49,8 +49,8 @@ class FakeBackend : public QuotaReservationManager::QuotaBackend {
int64_t delta,
const QuotaReservationManager::ReserveQuotaCallback& callback) override {
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::Bind(base::IgnoreResult(callback), base::File::FILE_OK, delta));
+ FROM_HERE, base::BindOnce(base::IgnoreResult(callback),
+ base::File::FILE_OK, delta));
}
void ReleaseReservedQuota(const GURL& origin,
diff --git a/chromium/content/browser/renderer_host/render_message_filter.cc b/chromium/content/browser/renderer_host/render_message_filter.cc
index 2a31b249435..1cb7860296b 100644
--- a/chromium/content/browser/renderer_host/render_message_filter.cc
+++ b/chromium/content/browser/renderer_host/render_message_filter.cc
@@ -300,9 +300,9 @@ void RenderMessageFilter::OnCacheableMetadataAvailableForCacheStorage(
cache_storage_context_->cache_manager()->OpenCache(
cache_storage_origin.GetURL(), cache_storage_cache_name,
- base::Bind(&RenderMessageFilter::OnCacheStorageOpenCallback,
- weak_ptr_factory_.GetWeakPtr(), url, expected_response_time,
- buf, data.size()));
+ base::BindOnce(&RenderMessageFilter::OnCacheStorageOpenCallback,
+ weak_ptr_factory_.GetWeakPtr(), url,
+ expected_response_time, buf, data.size()));
}
void RenderMessageFilter::OnCacheStorageOpenCallback(
@@ -317,8 +317,8 @@ void RenderMessageFilter::OnCacheStorageOpenCallback(
CacheStorageCache* cache = cache_handle->value();
if (!cache)
return;
- cache->WriteSideData(base::Bind(&NoOpCacheStorageErrorCallback,
- base::Passed(std::move(cache_handle))),
+ cache->WriteSideData(base::BindOnce(&NoOpCacheStorageErrorCallback,
+ base::Passed(std::move(cache_handle))),
url, expected_response_time, buf, buf_len);
}
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 68ded245456..b42768de86a 100644
--- a/chromium/content/browser/renderer_host/render_process_host_browsertest.cc
+++ b/chromium/content/browser/renderer_host/render_process_host_browsertest.cc
@@ -230,7 +230,7 @@ IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, SpareRenderProcessHostKilled) {
spare_renderer->AddObserver(this); // For process_exit_callback.
// Should reply with a bad message and cause process death.
- service->DoSomething(base::Bind(&base::DoNothing));
+ service->DoSomething(base::BindOnce(&base::DoNothing));
run_loop.Run();
// The spare RenderProcessHost should disappear when its process dies.
@@ -425,7 +425,7 @@ IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, KillProcessOnBadMojoMessage) {
set_process_exit_callback(run_loop.QuitClosure());
// Should reply with a bad message and cause process death.
- service->DoSomething(base::Bind(&base::DoNothing));
+ service->DoSomething(base::BindOnce(&base::DoNothing));
run_loop.Run();
@@ -462,6 +462,8 @@ class MediaStopObserver : public WebContentsObserver {
#define KillProcessZerosAudioStreams DISABLED_KillProcessZerosAudioStreams
#endif
IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, KillProcessZerosAudioStreams) {
+ // TODO(maxmorin): This test only uses an output stream. There should be a
+ // similar test for input streams.
embedded_test_server()->ServeFilesFromSourceDirectory(
media::GetTestDataPath());
ASSERT_TRUE(embedded_test_server()->Start());
@@ -497,7 +499,7 @@ IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, KillProcessZerosAudioStreams) {
// must run after these notifications have been delivered.
base::RunLoop run_loop;
set_process_exit_callback(media::BindToCurrentLoop(run_loop.QuitClosure()));
- service->DoSomething(base::Bind(&base::DoNothing));
+ service->DoSomething(base::BindOnce(&base::DoNothing));
run_loop.Run();
}
@@ -525,6 +527,10 @@ IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, KillProcessZerosAudioStreams) {
#define StopResetsVideoCaptureStreams DISABLED_StopResetsVideoCaptureStreams
#define KillProcessZerosVideoCaptureStreams \
DISABLED_KillProcessZerosVideoCaptureStreams
+#define GetUserMediaAudioOnlyIncrementsMediaStreams \
+ DISABLED_GetUserMediaAudioOnlyIncrementsMediaStreams
+#define KillProcessZerosAudioCaptureStreams \
+ DISABLED_KillProcessZerosAudioCaptureStreams
#endif // BUILDFLAG(ENABLE_WEBRTC)
// Tests that video capture stream count increments when getUserMedia() is
@@ -585,7 +591,72 @@ IN_PROC_BROWSER_TEST_F(RenderProcessHostTest,
// Force a bad message event to occur which will terminate the renderer.
base::RunLoop run_loop;
set_process_exit_callback(media::BindToCurrentLoop(run_loop.QuitClosure()));
- service->DoSomething(base::Bind(&base::DoNothing));
+ service->DoSomething(base::BindOnce(&base::DoNothing));
+ run_loop.Run();
+ }
+
+ {
+ // 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()));
+ run_loop.Run();
+ }
+
+ EXPECT_EQ(0, rph->get_media_stream_count_for_testing());
+ EXPECT_EQ(1, process_exits_);
+ EXPECT_EQ(0, host_destructions_);
+ if (!host_destructions_)
+ rph->RemoveObserver(this);
+}
+
+// Tests that media stream count increments when getUserMedia() is
+// called with audio only.
+IN_PROC_BROWSER_TEST_F(RenderProcessHostTest,
+ GetUserMediaAudioOnlyIncrementsMediaStreams) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+ NavigateToURL(shell(),
+ embedded_test_server()->GetURL("/media/getusermedia.html"));
+ RenderProcessHostImpl* rph = static_cast<RenderProcessHostImpl*>(
+ shell()->web_contents()->GetMainFrame()->GetProcess());
+ std::string result;
+ EXPECT_TRUE(ExecuteScriptAndExtractString(
+ shell(), "getUserMediaAndExpectSuccess({video: false, audio: true});",
+ &result))
+ << "Failed to execute javascript.";
+ EXPECT_EQ(1, rph->get_media_stream_count_for_testing());
+}
+
+// Tests that media stream counts (used for process priority
+// calculations) are properly set and cleared during media playback and renderer
+// terminations for audio only streams.
+IN_PROC_BROWSER_TEST_F(RenderProcessHostTest,
+ KillProcessZerosAudioCaptureStreams) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+ NavigateToURL(shell(),
+ embedded_test_server()->GetURL("/media/getusermedia.html"));
+ RenderProcessHostImpl* rph = static_cast<RenderProcessHostImpl*>(
+ shell()->web_contents()->GetMainFrame()->GetProcess());
+ std::string result;
+ EXPECT_TRUE(ExecuteScriptAndExtractString(
+ shell(), "getUserMediaAndExpectSuccess({video: false, audio: true});",
+ &result))
+ << "Failed to execute javascript.";
+ EXPECT_EQ(1, rph->get_media_stream_count_for_testing());
+
+ host_destructions_ = 0;
+ process_exits_ = 0;
+ rph->AddObserver(this);
+
+ mojom::TestServicePtr service;
+ BindInterface(rph, &service);
+
+ {
+ // Force a bad message event to occur which will terminate the renderer.
+ base::RunLoop run_loop;
+ set_process_exit_callback(media::BindToCurrentLoop(run_loop.QuitClosure()));
+ service->DoSomething(base::BindOnce(&base::DoNothing));
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 8f0da9c5dad..678135b37ee 100644
--- a/chromium/content/browser/renderer_host/render_process_host_impl.cc
+++ b/chromium/content/browser/renderer_host/render_process_host_impl.cc
@@ -56,6 +56,7 @@
#include "components/metrics/single_sample_metrics.h"
#include "components/tracing/common/tracing_switches.h"
#include "components/viz/common/resources/buffer_to_texture_target_map.h"
+#include "components/viz/common/switches.h"
#include "components/viz/service/display_embedder/server_shared_bitmap_manager.h"
#include "content/browser/appcache/appcache_dispatcher_host.h"
#include "content/browser/appcache/chrome_appcache_service.h"
@@ -146,7 +147,6 @@
#include "content/common/service_manager/service_manager_connection_impl.h"
#include "content/common/site_isolation_policy.h"
#include "content/common/view_messages.h"
-#include "content/common/worker_url_loader_factory_provider.mojom.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
@@ -248,7 +248,6 @@
#include "content/browser/renderer_host/p2p/socket_dispatcher_host.h"
#include "content/browser/webrtc/webrtc_internals.h"
#include "content/common/media/aec_dump_messages.h"
-#include "content/common/media/media_stream_messages.h"
#endif
#if BUILDFLAG(USE_MINIKIN_HYPHENATION)
@@ -335,7 +334,7 @@ bool has_done_stun_trials = false;
#endif
// the global list of all renderer processes
-base::LazyInstance<IDMap<RenderProcessHost*>>::Leaky g_all_hosts =
+base::LazyInstance<base::IDMap<RenderProcessHost*>>::Leaky g_all_hosts =
LAZY_INSTANCE_INITIALIZER;
// Map of site to process, to ensure we only have one RenderProcessHost per
@@ -418,7 +417,8 @@ class RendererSandboxedProcessLauncherDelegate
return GetContentClient()->browser()->PreSpawnRenderer(policy);
}
-#elif defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
+#elif defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) && \
+ !defined(OS_FUCHSIA)
ZygoteHandle GetZygote() override {
const base::CommandLine& browser_command_line =
*base::CommandLine::ForCurrentProcess();
@@ -684,7 +684,7 @@ void CreateMemoryCoordinatorHandle(
void CreateResourceCoordinatorProcessInterface(
RenderProcessHostImpl* render_process_host,
resource_coordinator::mojom::CoordinationUnitRequest request) {
- render_process_host->GetProcessResourceCoordinator()->service()->AddBinding(
+ render_process_host->GetProcessResourceCoordinator()->AddBinding(
std::move(request));
}
@@ -699,52 +699,6 @@ void ForwardShapeDetectionRequest(R request) {
std::move(request));
}
-class WorkerURLLoaderFactoryProviderImpl
- : public mojom::WorkerURLLoaderFactoryProvider {
- public:
- static void Create(
- int render_process_id,
- scoped_refptr<ResourceMessageFilter> resource_message_filter,
- scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
- mojom::WorkerURLLoaderFactoryProviderRequest request) {
- DCHECK(base::FeatureList::IsEnabled(features::kOffMainThreadFetch));
- mojo::MakeStrongBinding(
- base::MakeUnique<WorkerURLLoaderFactoryProviderImpl>(
- render_process_id, resource_message_filter->GetWeakPtr(),
- std::move(service_worker_context)),
- std::move(request));
- }
- WorkerURLLoaderFactoryProviderImpl(
- int render_process_id,
- base::WeakPtr<ResourceMessageFilter> resource_message_filter,
- scoped_refptr<ServiceWorkerContextWrapper> service_worker_context)
- : render_process_id_(render_process_id),
- url_loader_factory_binding_(resource_message_filter.get()),
- service_worker_context_(std::move(service_worker_context)) {}
- ~WorkerURLLoaderFactoryProviderImpl() override {}
-
- void GetURLLoaderFactoryAndRegisterClient(
- mojom::URLLoaderFactoryAssociatedRequest loader_request,
- mojom::ServiceWorkerWorkerClientAssociatedPtrInfo client_ptr_info,
- int service_worker_provider_id) override {
- url_loader_factory_binding_.Bind(std::move(loader_request));
- service_worker_context_->BindWorkerFetchContext(render_process_id_,
- service_worker_provider_id,
- std::move(client_ptr_info));
- }
-
- void GetURLLoaderFactory(
- mojom::URLLoaderFactoryAssociatedRequest loader_request) override {
- url_loader_factory_binding_.Bind(std::move(loader_request));
- }
-
- private:
- const int render_process_id_;
- mojo::AssociatedBinding<mojom::URLLoaderFactory> url_loader_factory_binding_;
-
- scoped_refptr<ServiceWorkerContextWrapper> service_worker_context_;
-};
-
class RenderProcessHostIsReadyObserver : public RenderProcessHostObserver {
public:
RenderProcessHostIsReadyObserver(RenderProcessHost* render_process_host,
@@ -771,8 +725,8 @@ class RenderProcessHostIsReadyObserver : public RenderProcessHostObserver {
void PostTask() {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&RenderProcessHostIsReadyObserver::CallTask,
- weak_factory_.GetWeakPtr()));
+ base::BindOnce(&RenderProcessHostIsReadyObserver::CallTask,
+ weak_factory_.GetWeakPtr()));
}
void CallTask() {
@@ -1059,9 +1013,19 @@ class UnmatchedServiceWorkerProcessTracker
SiteProcessIDPairSet site_process_set_;
};
+void CopyFeatureSwitch(const base::CommandLine& src,
+ base::CommandLine* dest,
+ const char* switch_name) {
+ std::vector<std::string> features = FeaturesFromSwitch(src, switch_name);
+ if (!features.empty())
+ dest->AppendSwitchASCII(switch_name, base::JoinString(features, ","));
+}
+
} // namespace
-RendererMainThreadFactoryFunction g_renderer_main_thread_factory = NULL;
+RendererMainThreadFactoryFunction g_renderer_main_thread_factory = nullptr;
+RenderProcessHostImpl::CreateStoragePartitionServiceFunction
+ g_create_storage_partition = nullptr;
base::MessageLoop* g_in_process_thread;
@@ -1283,14 +1247,17 @@ RenderProcessHostImpl::RenderProcessHostImpl(
is_self_deleted_(false),
#endif
pending_views_(0),
- service_worker_ref_count_(0),
- shared_worker_ref_count_(0),
- is_worker_ref_count_disabled_(false),
+ keep_alive_ref_count_(0),
+ is_keep_alive_ref_count_disabled_(false),
route_provider_binding_(this),
visible_widgets_(0),
- is_process_backgrounded_(kLaunchingProcessIsBackgrounded),
- boost_priority_for_pending_views_(
- kLaunchingProcessIsBoostedForPendingView),
+ priority_({
+ kLaunchingProcessIsBackgrounded,
+ kLaunchingProcessIsBoostedForPendingView,
+#if defined(OS_ANDROID)
+ ChildProcessImportance::NORMAL,
+#endif
+ }),
id_(ChildProcessHostImpl::GenerateChildProcessUniqueId()),
browser_context_(browser_context),
storage_partition_impl_(storage_partition_impl),
@@ -1337,8 +1304,8 @@ RenderProcessHostImpl::RenderProcessHostImpl(
!base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableGpuShaderDiskCache)) {
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::Bind(&CacheShaderInfo, GetID(),
- storage_partition_impl_->GetPath()));
+ base::BindOnce(&CacheShaderInfo, GetID(),
+ storage_partition_impl_->GetPath()));
}
push_messaging_manager_.reset(new PushMessagingManager(
@@ -1382,6 +1349,11 @@ void RenderProcessHostImpl::RegisterRendererMainThreadFactory(
g_renderer_main_thread_factory = create;
}
+void RenderProcessHostImpl::SetCreateStoragePartitionServiceFunction(
+ CreateStoragePartitionServiceFunction function) {
+ g_create_storage_partition = function;
+}
+
RenderProcessHostImpl::~RenderProcessHostImpl() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
#ifndef NDEBUG
@@ -1407,7 +1379,7 @@ RenderProcessHostImpl::~RenderProcessHostImpl() {
if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableGpuShaderDiskCache)) {
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::Bind(&RemoveShaderInfo, GetID()));
+ base::BindOnce(&RemoveShaderInfo, GetID()));
}
}
@@ -1728,8 +1700,6 @@ void RenderProcessHostImpl::CreateMessageFilters() {
peer_connection_tracker_host_ = new PeerConnectionTrackerHost(
GetID(), webrtc_eventlog_host_.GetWeakPtr());
AddFilter(peer_connection_tracker_host_.get());
- AddFilter(new MediaStreamDispatcherHost(
- GetID(), browser_context->GetMediaDeviceIDSalt(), media_stream_manager));
AddFilter(new MediaStreamTrackMetricsHost());
#endif
#if BUILDFLAG(ENABLE_PLUGINS)
@@ -1912,22 +1882,22 @@ void RenderProcessHostImpl::RegisterMojoInterfaces() {
registry->AddInterface(base::Bind(&RenderProcessHostImpl::CreateMusGpuRequest,
base::Unretained(this)));
+ MediaStreamManager* media_stream_manager =
+ BrowserMainLoop::GetInstance()->media_stream_manager();
+
registry->AddInterface(
- base::Bind(&VideoCaptureHost::Create, GetID(),
- BrowserMainLoop::GetInstance()->media_stream_manager()));
+ base::Bind(&VideoCaptureHost::Create, GetID(), media_stream_manager));
+
+#if BUILDFLAG(ENABLE_WEBRTC)
+ registry->AddInterface(base::Bind(
+ &RenderProcessHostImpl::CreateMediaStreamDispatcherHost,
+ base::Unretained(this), GetBrowserContext()->GetMediaDeviceIDSalt(),
+ media_stream_manager));
+#endif
registry->AddInterface(
base::Bind(&metrics::CreateSingleSampleMetricsProvider));
- if (base::FeatureList::IsEnabled(features::kOffMainThreadFetch)) {
- scoped_refptr<ServiceWorkerContextWrapper> service_worker_context(
- static_cast<ServiceWorkerContextWrapper*>(
- storage_partition_impl_->GetServiceWorkerContext()));
- registry->AddInterface(
- base::Bind(&WorkerURLLoaderFactoryProviderImpl::Create, GetID(),
- resource_message_filter_, service_worker_context));
- }
-
registry->AddInterface(
base::Bind(&CreateReportingServiceProxy, storage_partition_impl_));
@@ -2033,7 +2003,7 @@ void RenderProcessHostImpl::BindFrameSinkProvider(
}
void RenderProcessHostImpl::BindSharedBitmapAllocationNotifier(
- cc::mojom::SharedBitmapAllocationNotifierRequest request) {
+ viz::mojom::SharedBitmapAllocationNotifierRequest request) {
shared_bitmap_allocation_notifier_impl_.Bind(std::move(request));
}
@@ -2041,7 +2011,12 @@ void RenderProcessHostImpl::CreateStoragePartitionService(
mojom::StoragePartitionServiceRequest request) {
if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableMojoLocalStorage)) {
- storage_partition_impl_->Bind(std::move(request));
+ if (g_create_storage_partition) {
+ g_create_storage_partition(this, std::move(request));
+ return;
+ }
+
+ storage_partition_impl_->Bind(id_, std::move(request));
}
}
@@ -2056,7 +2031,7 @@ void RenderProcessHostImpl::CreateURLLoaderFactory(
NOTREACHED();
return;
}
- storage_partition_impl_->network_context()->CreateURLLoaderFactory(
+ storage_partition_impl_->GetNetworkContext()->CreateURLLoaderFactory(
std::move(request), id_);
}
@@ -2091,59 +2066,38 @@ const base::TimeTicks& RenderProcessHostImpl::GetInitTimeForNavigationMetrics()
}
bool RenderProcessHostImpl::IsProcessBackgrounded() const {
- return is_process_backgrounded_;
+ return priority_.background;
}
-size_t RenderProcessHostImpl::GetWorkerRefCount() const {
+void RenderProcessHostImpl::IncrementKeepAliveRefCount() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- return service_worker_ref_count_ + shared_worker_ref_count_;
+ DCHECK(!is_keep_alive_ref_count_disabled_);
+ ++keep_alive_ref_count_;
}
-void RenderProcessHostImpl::IncrementServiceWorkerRefCount() {
+void RenderProcessHostImpl::DecrementKeepAliveRefCount() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- DCHECK(!is_worker_ref_count_disabled_);
- ++service_worker_ref_count_;
-}
-
-void RenderProcessHostImpl::DecrementServiceWorkerRefCount() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- DCHECK(!is_worker_ref_count_disabled_);
- DCHECK_GT(GetWorkerRefCount(), 0U);
- --service_worker_ref_count_;
- if (GetWorkerRefCount() == 0)
+ DCHECK(!is_keep_alive_ref_count_disabled_);
+ DCHECK_GT(keep_alive_ref_count_, 0U);
+ --keep_alive_ref_count_;
+ if (keep_alive_ref_count_ == 0)
Cleanup();
}
-void RenderProcessHostImpl::IncrementSharedWorkerRefCount() {
+void RenderProcessHostImpl::DisableKeepAliveRefCount() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- DCHECK(!is_worker_ref_count_disabled_);
- ++shared_worker_ref_count_;
-}
-
-void RenderProcessHostImpl::DecrementSharedWorkerRefCount() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- DCHECK(!is_worker_ref_count_disabled_);
- DCHECK_GT(GetWorkerRefCount(), 0U);
- --shared_worker_ref_count_;
- if (GetWorkerRefCount() == 0)
- Cleanup();
-}
-
-void RenderProcessHostImpl::ForceReleaseWorkerRefCounts() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- DCHECK(!is_worker_ref_count_disabled_);
- is_worker_ref_count_disabled_ = true;
- if (!GetWorkerRefCount())
+ DCHECK(!is_keep_alive_ref_count_disabled_);
+ is_keep_alive_ref_count_disabled_ = true;
+ if (!keep_alive_ref_count_)
return;
- service_worker_ref_count_ = 0;
- shared_worker_ref_count_ = 0;
+ keep_alive_ref_count_ = 0;
// Cleaning up will also remove this from the SpareRenderProcessHostManager.
Cleanup();
}
-bool RenderProcessHostImpl::IsWorkerRefCountDisabled() {
+bool RenderProcessHostImpl::IsKeepAliveRefCountDisabled() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- return is_worker_ref_count_disabled_;
+ return is_keep_alive_ref_count_disabled_;
}
void RenderProcessHostImpl::PurgeAndSuspend() {
@@ -2160,10 +2114,18 @@ mojom::Renderer* RenderProcessHostImpl::GetRendererInterface() {
resource_coordinator::ResourceCoordinatorInterface*
RenderProcessHostImpl::GetProcessResourceCoordinator() {
- if (!process_resource_coordinator_) {
+ if (process_resource_coordinator_)
+ return process_resource_coordinator_.get();
+
+ if (!resource_coordinator::IsResourceCoordinatorEnabled()) {
+ process_resource_coordinator_ =
+ base::MakeUnique<resource_coordinator::ResourceCoordinatorInterface>(
+ nullptr, resource_coordinator::CoordinationUnitType::kProcess);
+ } else {
+ auto* connection = ServiceManagerConnection::GetForProcess();
process_resource_coordinator_ =
base::MakeUnique<resource_coordinator::ResourceCoordinatorInterface>(
- ServiceManagerConnection::GetForProcess()->GetConnector(),
+ connection ? connection->GetConnector() : nullptr,
resource_coordinator::CoordinationUnitType::kProcess);
}
return process_resource_coordinator_.get();
@@ -2260,6 +2222,30 @@ int RenderProcessHostImpl::VisibleWidgetCount() const {
return visible_widgets_;
}
+#if defined(OS_ANDROID)
+void RenderProcessHostImpl::UpdateWidgetImportance(
+ ChildProcessImportance old_value,
+ ChildProcessImportance new_value) {
+ DCHECK_NE(old_value, new_value);
+ DCHECK(widget_importance_counts_[static_cast<size_t>(old_value)]);
+ widget_importance_counts_[static_cast<size_t>(old_value)]--;
+ widget_importance_counts_[static_cast<size_t>(new_value)]++;
+ UpdateProcessPriority();
+}
+
+ChildProcessImportance RenderProcessHostImpl::ComputeEffectiveImportance() {
+ ChildProcessImportance importance = ChildProcessImportance::NORMAL;
+ for (size_t i = 0u; i < arraysize(widget_importance_counts_); ++i) {
+ DCHECK_GE(widget_importance_counts_[i], 0);
+ if (widget_importance_counts_[i]) {
+ // No early out. Highest importance wins.
+ importance = static_cast<ChildProcessImportance>(i);
+ }
+ }
+ return importance;
+}
+#endif
+
RendererAudioOutputStreamFactoryContext*
RenderProcessHostImpl::GetRendererAudioOutputStreamFactoryContext() {
if (!audio_output_stream_factory_context_) {
@@ -2381,7 +2367,7 @@ RenderProcessHostImpl::GetSpareRenderProcessHostForTesting() {
}
bool RenderProcessHostImpl::HostHasNotBeenUsed() {
- return IsUnused() && listeners_.IsEmpty() && GetWorkerRefCount() == 0 &&
+ return IsUnused() && listeners_.IsEmpty() && keep_alive_ref_count_ == 0 &&
pending_views_ == 0;
}
@@ -2504,7 +2490,6 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kDisableAcceleratedJpegDecoding,
switches::kDisableAcceleratedVideoDecode,
switches::kDisableBackgroundTimerThrottling,
- switches::kDisableBlinkFeatures,
switches::kDisableBreakpad,
switches::kDisablePreferCompositingToLCDText,
switches::kDisableDatabases,
@@ -2542,13 +2527,11 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kDisableV8IdleTasks,
switches::kDisableWebGLImageChromium,
switches::kDomAutomationController,
- switches::kEnableBlinkFeatures,
switches::kEnableBrowserSideNavigation,
switches::kEnableDisplayList2dCanvas,
switches::kEnableDistanceFieldText,
switches::kEnableExperimentalCanvasFeatures,
switches::kEnableExperimentalWebPlatformFeatures,
- switches::kEnableHDR,
switches::kEnableHeapProfiling,
switches::kEnableGPUClientLogging,
switches::kEnableGpuClientTracing,
@@ -2560,6 +2543,7 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kEnableLCDText,
switches::kEnableLogging,
switches::kEnableNetworkInformationDownlinkMax,
+ switches::kEnableOOPRasterization,
switches::kEnablePinch,
switches::kEnablePluginPlaceholderTesting,
switches::kEnablePreciseMemoryInfo,
@@ -2588,6 +2572,7 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kForceGpuMemAvailableMb,
switches::kForceGpuRasterization,
switches::kForceOverlayFullscreenVideo,
+ switches::kForceVideoOverlays,
switches::kFullMemoryCrashReport,
switches::kIgnoreAutoplayRestrictionsForTests,
switches::kIPCConnectionTimeout,
@@ -2636,10 +2621,8 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
// also be added to chrome/browser/chromeos/login/chrome_restart_request.cc.
cc::switches::kDisableCompositedAntialiasing,
cc::switches::kDisableThreadedAnimation,
- cc::switches::kDisallowNonExactResourceReuse,
cc::switches::kEnableGpuBenchmarking,
cc::switches::kEnableLayerLists,
- cc::switches::kEnableSurfaceSynchronization,
cc::switches::kEnableTileCompression,
cc::switches::kShowCompositedLayerBorders,
cc::switches::kShowFPSCounter,
@@ -2650,6 +2633,9 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
cc::switches::kSlowDownRasterScaleFactor,
cc::switches::kBrowserControlsHideThreshold,
cc::switches::kBrowserControlsShowThreshold,
+ cc::switches::kRunAllCompositorStagesBeforeDraw,
+ switches::kDisableSurfaceReferences,
+ switches::kEnableSurfaceSynchronization,
#if BUILDFLAG(ENABLE_PLUGINS)
switches::kEnablePepperTesting,
@@ -2658,6 +2644,7 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kDisableWebRtcHWDecoding,
switches::kDisableWebRtcHWEncoding,
switches::kEnableWebRtcSrtpAesGcm,
+ switches::kEnableWebRtcSrtpEncryptedHeaders,
switches::kEnableWebRtcStunOrigin,
switches::kEnforceWebRtcIPPermissionCheck,
switches::kForceWebRtcIPHandlingPolicy,
@@ -2665,6 +2652,7 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
#endif
switches::kEnableLowEndDeviceMode,
switches::kDisableLowEndDeviceMode,
+ switches::kDisallowNonExactResourceReuse,
#if defined(OS_ANDROID)
switches::kDisableMediaSessionAPI,
switches::kRendererWaitForJavaDebugger,
@@ -2745,6 +2733,9 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
renderer_cmd->AppendSwitch(switches::kNoSandbox);
}
#endif
+
+ CopyFeatureSwitch(browser_cmd, renderer_cmd, switches::kEnableBlinkFeatures);
+ CopyFeatureSwitch(browser_cmd, renderer_cmd, switches::kDisableBlinkFeatures);
}
base::ProcessHandle RenderProcessHostImpl::GetHandle() const {
@@ -2793,9 +2784,9 @@ bool RenderProcessHostImpl::FastShutdownIfPossible(size_t page_count,
if (!skip_unload_handlers && !SuddenTerminationAllowed())
return false;
- if (GetWorkerRefCount() != 0) {
- if (survive_for_worker_start_time_.is_null())
- survive_for_worker_start_time_ = base::TimeTicks::Now();
+ if (keep_alive_ref_count_ != 0) {
+ if (keep_alive_start_time_.is_null())
+ keep_alive_start_time_ = base::TimeTicks::Now();
return false;
}
@@ -2917,9 +2908,10 @@ void RenderProcessHostImpl::OnChannelConnected(int32_t peer_pid) {
// Inform AudioInputRendererHost about the new render process PID.
// AudioInputRendererHost is reference counted, so its lifetime is
// guaranteed during the lifetime of the closure.
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::Bind(&AudioInputRendererHost::set_renderer_pid,
- audio_input_renderer_host_, peer_pid));
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&AudioInputRendererHost::set_renderer_pid,
+ audio_input_renderer_host_, peer_pid));
}
void RenderProcessHostImpl::OnChannelError() {
@@ -2988,14 +2980,15 @@ void RenderProcessHostImpl::Cleanup() {
}
delayed_cleanup_needed_ = false;
- // Records the time when the process starts surviving for workers for UMA.
- if (listeners_.IsEmpty() && GetWorkerRefCount() > 0 &&
- survive_for_worker_start_time_.is_null()) {
- survive_for_worker_start_time_ = base::TimeTicks::Now();
+ // Records the time when the process starts kept alive by the ref count for
+ // UMA.
+ if (listeners_.IsEmpty() && keep_alive_ref_count_ > 0 &&
+ keep_alive_start_time_.is_null()) {
+ keep_alive_start_time_ = base::TimeTicks::Now();
}
// Until there are no other owners of this object, we can't delete ourselves.
- if (!listeners_.IsEmpty() || GetWorkerRefCount() != 0)
+ if (!listeners_.IsEmpty() || keep_alive_ref_count_ != 0)
return;
#if BUILDFLAG(ENABLE_WEBRTC)
@@ -3003,10 +2996,9 @@ void RenderProcessHostImpl::Cleanup() {
ClearWebRtcLogMessageCallback();
#endif
- if (!survive_for_worker_start_time_.is_null()) {
- UMA_HISTOGRAM_LONG_TIMES(
- "SharedWorker.RendererSurviveForWorkerTime",
- base::TimeTicks::Now() - survive_for_worker_start_time_);
+ if (!keep_alive_start_time_.is_null()) {
+ UMA_HISTOGRAM_LONG_TIMES("BrowserRenderProcessHost.KeepAliveDuration",
+ base::TimeTicks::Now() - keep_alive_start_time_);
}
// We cannot clean up twice; if this fails, there is an issue with our
@@ -3080,11 +3072,26 @@ void RenderProcessHostImpl::RemovePendingView() {
}
void RenderProcessHostImpl::AddWidget(RenderWidgetHost* widget) {
- widgets_.insert(static_cast<RenderWidgetHostImpl*>(widget));
+ RenderWidgetHostImpl* widget_impl =
+ static_cast<RenderWidgetHostImpl*>(widget);
+ widgets_.insert(widget_impl);
+#if defined(OS_ANDROID)
+ widget_importance_counts_[static_cast<size_t>(widget_impl->importance())]++;
+ UpdateProcessPriority();
+#endif
}
void RenderProcessHostImpl::RemoveWidget(RenderWidgetHost* widget) {
- widgets_.erase(static_cast<RenderWidgetHostImpl*>(widget));
+ RenderWidgetHostImpl* widget_impl =
+ static_cast<RenderWidgetHostImpl*>(widget);
+ widgets_.erase(widget_impl);
+
+#if defined(OS_ANDROID)
+ ChildProcessImportance importance = widget_impl->importance();
+ DCHECK(widget_importance_counts_[static_cast<size_t>(importance)]);
+ widget_importance_counts_[static_cast<size_t>(importance)]--;
+ UpdateProcessPriority();
+#endif
}
void RenderProcessHostImpl::SetSuddenTerminationAllowed(bool enabled) {
@@ -3121,8 +3128,8 @@ void RenderProcessHostImpl::EnableAudioDebugRecordings(
// Not null if RenderProcessHostImpl::Init has already been called.
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&AudioInputRendererHost::EnableDebugRecording,
- audio_input_renderer_host_, file));
+ base::BindOnce(&AudioInputRendererHost::EnableDebugRecording,
+ audio_input_renderer_host_, file));
}
}
@@ -3133,9 +3140,9 @@ void RenderProcessHostImpl::DisableAudioDebugRecordings() {
// for avoiding races between enable and disable. Nothing is done on the
// sequence.
GetAecDumpFileTaskRunner().PostTaskAndReply(
- FROM_HERE, base::Bind(&base::DoNothing),
- base::Bind(&RenderProcessHostImpl::SendDisableAecDumpToRenderer,
- weak_factory_.GetWeakPtr()));
+ FROM_HERE, base::BindOnce(&base::DoNothing),
+ base::BindOnce(&RenderProcessHostImpl::SendDisableAecDumpToRenderer,
+ weak_factory_.GetWeakPtr()));
// AudioInputRendererHost is reference counted, so it's lifetime is
// guaranteed during the lifetime of the closure.
@@ -3143,8 +3150,8 @@ void RenderProcessHostImpl::DisableAudioDebugRecordings() {
// Not null if RenderProcessHostImpl::Init has already been called.
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&AudioInputRendererHost::DisableDebugRecording,
- audio_input_renderer_host_));
+ base::BindOnce(&AudioInputRendererHost::DisableDebugRecording,
+ audio_input_renderer_host_));
}
}
@@ -3198,9 +3205,9 @@ RenderProcessHostImpl::StartRtpDump(
return WebRtcStopRtpDumpCallback();
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::Bind(&P2PSocketDispatcherHost::StartRtpDump,
- p2p_socket_dispatcher_host_, incoming,
- outgoing, packet_callback));
+ base::BindOnce(&P2PSocketDispatcherHost::StartRtpDump,
+ p2p_socket_dispatcher_host_, incoming,
+ outgoing, packet_callback));
if (stop_rtp_dump_callback_.is_null()) {
stop_rtp_dump_callback_ =
@@ -3316,8 +3323,8 @@ bool RenderProcessHostImpl::IsSuitableHost(RenderProcessHost* host,
// URL to reuse this process if the URL has the same site.
return lock_state == ChildProcessSecurityPolicyImpl::CheckOriginLockResult::
HAS_EQUAL_LOCK;
- } else if (!host->IsUnused() &&
- SiteInstanceImpl::ShouldLockToOrigin(browser_context, site_url)) {
+ } else if (!host->IsUnused() && SiteInstanceImpl::ShouldLockToOrigin(
+ browser_context, host, site_url)) {
// Otherwise, if this process has been used to host any other content, it
// cannot be reused if the destination site indeed requires a dedicated
// process and can be locked to just that site.
@@ -3556,6 +3563,12 @@ RenderProcessHost* RenderProcessHostImpl::GetProcessHostForSiteInstance(
UnmatchedServiceWorkerProcessTracker::Register(
browser_context, render_process_host, site_url);
}
+
+ // Make sure the chosen process is in the correct StoragePartition for the
+ // SiteInstance.
+ CHECK(render_process_host->InSameStoragePartition(
+ BrowserContext::GetStoragePartition(browser_context, site_instance)));
+
return render_process_host;
}
@@ -3649,7 +3662,7 @@ void RenderProcessHostImpl::ProcessDied(bool already_dead,
RemoveUserData(kSessionStorageHolderKey);
- IDMap<IPC::Listener*>::iterator iter(&listeners_);
+ base::IDMap<IPC::Listener*>::iterator iter(&listeners_);
while (!iter.IsAtEnd()) {
iter.GetCurrentValue()->OnMessageReceived(FrameHostMsg_RenderProcessGone(
iter.GetCurrentKey(), static_cast<int>(status), exit_code));
@@ -3672,6 +3685,8 @@ void RenderProcessHostImpl::ProcessDied(bool already_dead,
// request for FrameSinkProvider so make sure frame_sink_provider_ is ready
// for that.
frame_sink_provider_.Unbind();
+ if (renderer_host_binding_.is_bound())
+ renderer_host_binding_.Unbind();
shared_bitmap_allocation_notifier_impl_.ChildDied();
@@ -3734,38 +3749,35 @@ void RenderProcessHostImpl::SuddenTerminationChanged(bool enabled) {
void RenderProcessHostImpl::UpdateProcessPriority() {
if (!child_process_launcher_.get() || child_process_launcher_->IsStarting()) {
- is_process_backgrounded_ = kLaunchingProcessIsBackgrounded;
- boost_priority_for_pending_views_ =
+ priority_.background = kLaunchingProcessIsBackgrounded;
+ priority_.boost_for_pending_views =
kLaunchingProcessIsBoostedForPendingView;
return;
}
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDisableRendererPriorityManagement)) {
- return;
- }
+ const ChildProcessLauncherPriority priority = {
+ // We background a process as soon as it hosts no active audio/video streams
+ // and no visible widgets -- the callers must call this function whenever we
+ // transition in/out of those states.
+ visible_widgets_ == 0 && media_stream_count_ == 0 &&
+ !base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableRendererBackgrounding),
+ // boost_for_pending_views
+ !!pending_views_,
+#if defined(OS_ANDROID)
+ ComputeEffectiveImportance(),
+#endif
+ };
- // We background a process as soon as it hosts no active audio/video streams
- // and no visible widgets -- the callers must call this function whenever we
- // transition in/out of those states.
- const bool should_background =
- visible_widgets_ == 0 && media_stream_count_ == 0 &&
- !base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDisableRendererBackgrounding);
const bool should_background_changed =
- is_process_backgrounded_ != should_background;
- const bool has_pending_views = !!pending_views_;
-
- if (!should_background_changed &&
- boost_priority_for_pending_views_ == has_pending_views) {
+ priority_.background != priority.background;
+ if (priority_ == priority)
return;
- }
TRACE_EVENT2("renderer_host", "RenderProcessHostImpl::UpdateProcessPriority",
- "should_background", should_background, "has_pending_views",
- has_pending_views);
- is_process_backgrounded_ = should_background;
- boost_priority_for_pending_views_ = has_pending_views;
+ "should_background", priority.background, "has_pending_views",
+ priority.boost_for_pending_views);
+ priority_ = priority;
#if defined(OS_WIN)
// The cbstext.dll loads as a global GetMessage hook in the browser process
@@ -3783,14 +3795,13 @@ void RenderProcessHostImpl::UpdateProcessPriority() {
// tasks executing at lowered priority ahead of it or simply by not being
// swiftly scheduled by the OS per the low process priority
// (http://crbug.com/398103).
- child_process_launcher_->SetProcessPriority(should_background,
- has_pending_views);
+ child_process_launcher_->SetProcessPriority(priority_);
// Notify the child process of background state. Note
- // |boost_priority_for_pending_views_| state is not sent to renderer simply
+ // |priority_.boost_for_pending_views| state is not sent to renderer simply
// due to lack of need.
if (should_background_changed)
- Send(new ChildProcessMsg_SetProcessBackgrounded(should_background));
+ Send(new ChildProcessMsg_SetProcessBackgrounded(priority.background));
}
void RenderProcessHostImpl::OnProcessLaunched() {
@@ -3803,7 +3814,7 @@ void RenderProcessHostImpl::OnProcessLaunched() {
if (child_process_launcher_) {
DCHECK(child_process_launcher_->GetProcess().IsValid());
- DCHECK_EQ(kLaunchingProcessIsBackgrounded, is_process_backgrounded_);
+ DCHECK_EQ(kLaunchingProcessIsBackgrounded, priority_.background);
// Unpause the channel now that the process is launched. We don't flush it
// yet to ensure that any initialization messages sent here (e.g., things
@@ -3817,18 +3828,18 @@ void RenderProcessHostImpl::OnProcessLaunched() {
}
// Not all platforms launch processes in the same backgrounded state. Make
- // sure |is_process_backgrounded_| reflects this platform's initial process
+ // sure |priority_.background| reflects this platform's initial process
// state.
#if defined(OS_MACOSX)
- is_process_backgrounded_ =
+ priority_.background =
child_process_launcher_->GetProcess().IsProcessBackgrounded(
MachBroker::GetInstance());
#elif defined(OS_ANDROID)
// Android child process priority works differently and cannot be queried
// directly from base::Process.
- DCHECK_EQ(kLaunchingProcessIsBackgrounded, is_process_backgrounded_);
+ DCHECK_EQ(kLaunchingProcessIsBackgrounded, priority_.background);
#else
- is_process_backgrounded_ =
+ priority_.background =
child_process_launcher_->GetProcess().IsProcessBackgrounded();
#endif // defined(OS_MACOSX)
@@ -3837,7 +3848,7 @@ void RenderProcessHostImpl::OnProcessLaunched() {
// their first commit is made. A better long term solution would be to be
// aware of the tab's visibility at this point. https://crbug.com/560446.
// This is still needed on Android which uses
- // |boost_priority_for_pending_views_| and requires RenderProcessHostImpl to
+ // |priority_.boost_for_pending_views| and requires RenderProcessHostImpl to
// propagate priority changes immediately to ChildProcessLauncher.
#if defined(OS_ANDROID)
UpdateProcessPriority();
@@ -3869,6 +3880,10 @@ void RenderProcessHostImpl::OnProcessLaunched() {
observer.RenderProcessReady(this);
}
+ GetProcessResourceCoordinator()->SetProperty(
+ resource_coordinator::mojom::PropertyType::kPID,
+ base::GetProcId(GetHandle()));
+
#if BUILDFLAG(ENABLE_WEBRTC)
if (WebRTCInternals::GetInstance()->IsAudioDebugRecordingsEnabled()) {
EnableAudioDebugRecordings(
@@ -3975,18 +3990,31 @@ RenderProcessHost* RenderProcessHostImpl::FindReusableProcessHostForSite(
}
#if BUILDFLAG(ENABLE_WEBRTC)
+void RenderProcessHostImpl::CreateMediaStreamDispatcherHost(
+ const std::string& salt,
+ MediaStreamManager* media_stream_manager,
+ mojom::MediaStreamDispatcherHostRequest request) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ if (!media_stream_dispatcher_host_) {
+ media_stream_dispatcher_host_.reset(
+ new MediaStreamDispatcherHost(GetID(), salt, media_stream_manager));
+ }
+ media_stream_dispatcher_host_->BindRequest(std::move(request));
+}
+
void RenderProcessHostImpl::OnRegisterAecDumpConsumer(int id) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&RenderProcessHostImpl::RegisterAecDumpConsumerOnUIThread,
- weak_factory_.GetWeakPtr(), id));
+ base::BindOnce(&RenderProcessHostImpl::RegisterAecDumpConsumerOnUIThread,
+ weak_factory_.GetWeakPtr(), id));
}
void RenderProcessHostImpl::OnUnregisterAecDumpConsumer(int id) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&RenderProcessHostImpl::UnregisterAecDumpConsumerOnUIThread,
- weak_factory_.GetWeakPtr(), id));
+ base::BindOnce(
+ &RenderProcessHostImpl::UnregisterAecDumpConsumerOnUIThread,
+ weak_factory_.GetWeakPtr(), id));
}
void RenderProcessHostImpl::RegisterAecDumpConsumerOnUIThread(int 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 c6d104c258c..dd7df59cb5c 100644
--- a/chromium/content/browser/renderer_host/render_process_host_impl.h
+++ b/chromium/content/browser/renderer_host/render_process_host_impl.h
@@ -32,6 +32,7 @@
#include "content/common/associated_interfaces.mojom.h"
#include "content/common/content_export.h"
#include "content/common/indexed_db/indexed_db.mojom.h"
+#include "content/common/media/media_stream.mojom.h"
#include "content/common/media/renderer_audio_output_stream_factory.mojom.h"
#include "content/common/renderer.mojom.h"
#include "content/common/renderer_host.mojom.h"
@@ -54,6 +55,7 @@
#if defined(OS_ANDROID)
#include "content/browser/android/synchronous_compositor_browser_filter.h"
+#include "content/public/browser/android/child_process_importance.h"
#endif
namespace base {
@@ -70,6 +72,7 @@ class IndexedDBDispatcherHost;
class InProcessChildThreadParams;
class NotificationMessageFilter;
#if BUILDFLAG(ENABLE_WEBRTC)
+class MediaStreamDispatcherHost;
class P2PSocketDispatcherHost;
#endif
class PermissionServiceContext;
@@ -112,9 +115,9 @@ class CONTENT_EXPORT RenderProcessHostImpl
: public RenderProcessHost,
public ChildProcessLauncher::Client,
public ui::GpuSwitchingObserver,
- public NON_EXPORTED_BASE(mojom::RouteProvider),
- public NON_EXPORTED_BASE(mojom::AssociatedInterfaceProvider),
- public NON_EXPORTED_BASE(mojom::RendererHost) {
+ public mojom::RouteProvider,
+ public mojom::AssociatedInterfaceProvider,
+ public mojom::RendererHost {
public:
// Use the spare RenderProcessHost if it exists, or create a new one. This
// should be the usual way to get a new RenderProcessHost.
@@ -171,6 +174,11 @@ class CONTENT_EXPORT RenderProcessHostImpl
void RemovePendingView() override;
void AddWidget(RenderWidgetHost* widget) override;
void RemoveWidget(RenderWidgetHost* widget) override;
+#if defined(OS_ANDROID)
+ void UpdateWidgetImportance(ChildProcessImportance old_value,
+ ChildProcessImportance new_value) override;
+ ChildProcessImportance ComputeEffectiveImportance() override;
+#endif
void SetSuddenTerminationAllowed(bool enabled) override;
bool SuddenTerminationAllowed() const override;
IPC::ChannelProxy* GetChannel() override;
@@ -200,13 +208,10 @@ class CONTENT_EXPORT RenderProcessHostImpl
override;
const base::TimeTicks& GetInitTimeForNavigationMetrics() const override;
bool IsProcessBackgrounded() const override;
- size_t GetWorkerRefCount() const override;
- void IncrementServiceWorkerRefCount() override;
- void DecrementServiceWorkerRefCount() override;
- void IncrementSharedWorkerRefCount() override;
- void DecrementSharedWorkerRefCount() override;
- void ForceReleaseWorkerRefCounts() override;
- bool IsWorkerRefCountDisabled() override;
+ void IncrementKeepAliveRefCount() override;
+ void DecrementKeepAliveRefCount() override;
+ void DisableKeepAliveRefCount() override;
+ bool IsKeepAliveRefCountDisabled() override;
void PurgeAndSuspend() override;
void Resume() override;
mojom::Renderer* GetRendererInterface() override;
@@ -306,6 +311,15 @@ class CONTENT_EXPORT RenderProcessHostImpl
static void RegisterRendererMainThreadFactory(
RendererMainThreadFactoryFunction create);
+ // Allows external code to supply a function which creates a
+ // StoragePartitionService. Used for supplying test versions of the
+ // service.
+ using CreateStoragePartitionServiceFunction =
+ void (*)(RenderProcessHostImpl* rph,
+ mojom::StoragePartitionServiceRequest request);
+ static void SetCreateStoragePartitionServiceFunction(
+ CreateStoragePartitionServiceFunction function);
+
RenderFrameMessageFilter* render_frame_message_filter_for_testing() const {
return render_frame_message_filter_.get();
}
@@ -396,6 +410,7 @@ class CONTENT_EXPORT RenderProcessHostImpl
private:
friend class ChildProcessLauncherBrowserTest_ChildSpawnFail_Test;
friend class VisitRelayingRenderProcessHost;
+ friend class StoragePartitonInterceptor;
class ConnectionFilterController;
class ConnectionFilterImpl;
@@ -439,7 +454,7 @@ class CONTENT_EXPORT RenderProcessHostImpl
blink::mojom::OffscreenCanvasProviderRequest request);
void BindFrameSinkProvider(mojom::FrameSinkProviderRequest request);
void BindSharedBitmapAllocationNotifier(
- cc::mojom::SharedBitmapAllocationNotifierRequest request);
+ viz::mojom::SharedBitmapAllocationNotifierRequest request);
void CreateStoragePartitionService(
mojom::StoragePartitionServiceRequest request);
void CreateRendererHost(mojom::RendererHostRequest request);
@@ -492,6 +507,10 @@ class CONTENT_EXPORT RenderProcessHostImpl
const GURL& site_url);
#if BUILDFLAG(ENABLE_WEBRTC)
+ void CreateMediaStreamDispatcherHost(
+ const std::string& salt,
+ MediaStreamManager* media_stream_manager,
+ mojom::MediaStreamDispatcherHostRequest request);
void OnRegisterAecDumpConsumer(int id);
void OnUnregisterAecDumpConsumer(int id);
void RegisterAecDumpConsumerOnUIThread(int id);
@@ -547,16 +566,11 @@ class CONTENT_EXPORT RenderProcessHostImpl
scoped_refptr<ConnectionFilterController> connection_filter_controller_;
service_manager::mojom::ServicePtr test_service_;
- // The number of service workers running in this process.
- size_t service_worker_ref_count_;
- // See comments for IncrementSharedWorkerRefCount() and
- // DecrementSharedWorkerRefCount(). This is more like a boolean flag and not
- // actually the number of shared workers running in this process.
- size_t shared_worker_ref_count_;
+ size_t keep_alive_ref_count_;
- // Set in ForceReleaseWorkerRefCounts. When true, worker ref counts must no
- // longer be modified.
- bool is_worker_ref_count_disabled_;
+ // Set in DisableKeepAliveRefCount(). When true, |keep_alive_ref_count_| must
+ // no longer be modified.
+ bool is_keep_alive_ref_count_disabled_;
// Whether this host is never suitable for reuse as determined in the
// MayReuseHost() function.
@@ -564,7 +578,7 @@ class CONTENT_EXPORT RenderProcessHostImpl
// The registered IPC listener objects. When this list is empty, we should
// delete ourselves.
- IDMap<IPC::Listener*> listeners_;
+ base::IDMap<IPC::Listener*> listeners_;
// Mojo interfaces provided to the child process are registered here if they
// need consistent delivery ordering with legacy IPC, and are process-wide in
@@ -580,16 +594,18 @@ class CONTENT_EXPORT RenderProcessHostImpl
// backgrounded.
int32_t visible_widgets_;
+#if defined(OS_ANDROID)
+ // Track count of number of widgets with each possible ChildProcessImportance
+ // value.
+ int32_t widget_importance_counts_[static_cast<size_t>(
+ ChildProcessImportance::COUNT)] = {0};
+
+#endif
+
// The set of widgets in this RenderProcessHostImpl.
std::set<RenderWidgetHostImpl*> widgets_;
- // Whether this process currently has backgrounded priority. Tracked so that
- // UpdateProcessPriority() can avoid redundantly setting the priority.
- bool is_process_backgrounded_;
- // Same as |pending_views_| but keep this in sync with value passed to
- // |child_process_launcher_|, so need a separate state. This is used to
- // compute process priority on some platforms.
- bool boost_priority_for_pending_views_;
+ ChildProcessLauncherPriority priority_;
// Used to allow a RenderWidgetHost to intercept various messages on the
// IO thread.
@@ -694,6 +710,9 @@ class CONTENT_EXPORT RenderProcessHostImpl
scoped_refptr<base::SequencedTaskRunner>
audio_debug_recordings_file_task_runner_;
+
+ std::unique_ptr<MediaStreamDispatcherHost, BrowserThread::DeleteOnIOThread>
+ media_stream_dispatcher_host_;
#endif
// Forwards messages between WebRTCInternals in the browser process
@@ -703,7 +722,7 @@ class CONTENT_EXPORT RenderProcessHostImpl
scoped_refptr<PeerConnectionTrackerHost> peer_connection_tracker_host_;
// Records the time when the process starts surviving for workers for UMA.
- base::TimeTicks survive_for_worker_start_time_;
+ base::TimeTicks keep_alive_start_time_;
// Context shared for each mojom::PermissionService instance created for this
// RPH.
diff --git a/chromium/content/browser/renderer_host/render_process_host_unittest.cc b/chromium/content/browser/renderer_host/render_process_host_unittest.cc
index 5213d106171..f57dbe0be4c 100644
--- a/chromium/content/browser/renderer_host/render_process_host_unittest.cc
+++ b/chromium/content/browser/renderer_host/render_process_host_unittest.cc
@@ -18,6 +18,7 @@
#include "content/public/common/content_constants.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/mock_render_process_host.h"
+#include "content/public/test/navigation_simulator.h"
#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_utils.h"
#include "content/test/test_render_frame_host.h"
@@ -123,7 +124,6 @@ TEST_F(RenderProcessHostUnitTest, ReuseCommittedSite) {
site_instance->set_process_reuse_policy(
SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
EXPECT_NE(main_test_rfh()->GetProcess(), site_instance->GetProcess());
-
// Now add a subframe that navigates to kUrl1. Getting a RenderProcessHost
// with the REUSE_PENDING_OR_COMMITTED_SITE policy for kUrl1 should now
// return the process of the subframe RFH.
@@ -134,21 +134,8 @@ TEST_F(RenderProcessHostUnitTest, ReuseCommittedSite) {
ParsedFeaturePolicyHeader(), FrameOwnerProperties());
TestRenderFrameHost* subframe = static_cast<TestRenderFrameHost*>(
contents()->GetFrameTree()->root()->child_at(0)->current_frame_host());
- {
- FrameHostMsg_DidCommitProvisionalLoad_Params params;
- params.nav_entry_id = 0;
- params.frame_unique_name = unique_name;
- params.did_create_new_entry = false;
- params.url = kUrl1;
- params.transition = ui::PAGE_TRANSITION_AUTO_SUBFRAME;
- params.should_update_history = false;
- params.gesture = NavigationGestureUser;
- params.method = "GET";
- params.page_state = PageState::CreateFromURL(kUrl1);
- subframe->SendRendererInitiatedNavigationRequest(kUrl1, false);
- subframe->PrepareForCommit();
- subframe->SendNavigateWithParams(&params);
- }
+ subframe = static_cast<TestRenderFrameHost*>(
+ NavigationSimulator::NavigateAndCommitFromDocument(kUrl1, subframe));
site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl1);
site_instance->set_process_reuse_policy(
SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
@@ -402,7 +389,9 @@ TEST_F(RenderProcessHostUnitTest, ReuseNavigationProcess) {
// Start a navigation. Now Getting RenderProcessHost with the
// REUSE_PENDING_OR_COMMITTED_SITE policy should return the current process.
- main_test_rfh()->SimulateNavigationStart(kUrl1);
+ auto navigation =
+ NavigationSimulator::CreateRendererInitiated(kUrl1, main_test_rfh());
+ navigation->Start();
site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl1);
site_instance->set_process_reuse_policy(
SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
@@ -411,8 +400,7 @@ TEST_F(RenderProcessHostUnitTest, ReuseNavigationProcess) {
// Finish the navigation and start a new cross-site one. Getting
// RenderProcessHost with the REUSE_PENDING_OR_COMMITTED_SITE policy should
// return the process of the speculative RenderFrameHost.
- main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(0, true, kUrl1);
+ navigation->Commit();
contents()->GetController().LoadURL(kUrl2, Referrer(),
ui::PAGE_TRANSITION_TYPED, std::string());
main_test_rfh()->SendBeforeUnloadACK(true);
@@ -643,12 +631,17 @@ TEST_F(RenderProcessHostUnitTest, ReuseSiteURLChanges) {
// REUSE_PENDING_OR_COMMITTED_SITE policy should now return the process of the
// main RFH, as it is now registered with the modified site URL.
contents()->GetController().Reload(ReloadType::NORMAL, false);
- main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(0, true, kUrl);
+ TestRenderFrameHost* rfh = main_test_rfh();
+ // In --site-per-process, the reload will use the pending/speculative RFH
+ // instead of the current one.
+ if (contents()->GetPendingMainFrame())
+ rfh = contents()->GetPendingMainFrame();
+ rfh->PrepareForCommit();
+ rfh->SendNavigate(0, true, kUrl);
site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
site_instance->set_process_reuse_policy(
SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
- EXPECT_EQ(main_test_rfh()->GetProcess(), site_instance->GetProcess());
+ EXPECT_EQ(rfh->GetProcess(), site_instance->GetProcess());
// Remove the custom ContentBrowserClient. Site URLs are back to normal.
// Getting a RenderProcessHost with the REUSE_PENDING_OR_COMMITTED_SITE policy
@@ -658,18 +651,20 @@ TEST_F(RenderProcessHostUnitTest, ReuseSiteURLChanges) {
site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
site_instance->set_process_reuse_policy(
SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
- EXPECT_NE(main_test_rfh()->GetProcess(), site_instance->GetProcess());
+ EXPECT_NE(rfh->GetProcess(), site_instance->GetProcess());
// Reload. Getting a RenderProcessHost with the
// REUSE_PENDING_OR_COMMITTED_SITE policy should now return the process of the
// main RFH, as it is now registered with the regular site URL.
contents()->GetController().Reload(ReloadType::NORMAL, false);
- main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(0, true, kUrl);
+ rfh = contents()->GetPendingMainFrame() ? contents()->GetPendingMainFrame()
+ : main_test_rfh();
+ rfh->PrepareForCommit();
+ rfh->SendNavigate(0, true, kUrl);
site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
site_instance->set_process_reuse_policy(
SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
- EXPECT_EQ(main_test_rfh()->GetProcess(), site_instance->GetProcess());
+ EXPECT_EQ(rfh->GetProcess(), site_instance->GetProcess());
}
// Tests that RenderProcessHost reuse works correctly even if the site URL of a
@@ -693,7 +688,9 @@ TEST_F(RenderProcessHostUnitTest, ReuseExpectedSiteURLChanges) {
// Start a navigation. Getting a RenderProcessHost with the
// REUSE_PENDING_OR_COMMITTED_SITE policy should now return the process of the
// main RFH.
- main_test_rfh()->SimulateNavigationStart(kUrl);
+ auto navigation =
+ NavigationSimulator::CreateRendererInitiated(kUrl, main_test_rfh());
+ navigation->Start();
site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
site_instance->set_process_reuse_policy(
SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
@@ -714,8 +711,7 @@ TEST_F(RenderProcessHostUnitTest, ReuseExpectedSiteURLChanges) {
// Have the navigation commit. Getting a RenderProcessHost with the
// REUSE_PENDING_OR_COMMITTED_SITE policy should now return the process of the
// main RFH, as it was registered with the modified site URL at commit time.
- main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(0, true, kUrl);
+ navigation->Commit();
site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
site_instance->set_process_reuse_policy(
SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
diff --git a/chromium/content/browser/renderer_host/render_view_host_factory.cc b/chromium/content/browser/renderer_host/render_view_host_factory.cc
index 8804439968d..831b6c7e8ca 100644
--- a/chromium/content/browser/renderer_host/render_view_host_factory.cc
+++ b/chromium/content/browser/renderer_host/render_view_host_factory.cc
@@ -51,7 +51,7 @@ RenderViewHost* RenderViewHostFactory::Create(
return new RenderViewHostImpl(
instance,
base::MakeUnique<RenderWidgetHostImpl>(
- widget_delegate, instance->GetProcess(), routing_id, hidden),
+ widget_delegate, instance->GetProcess(), routing_id, nullptr, hidden),
delegate, main_frame_routing_id, swapped_out,
true /* has_initialized_audio_host */);
}
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 256ad4eadc7..d13991763fd 100644
--- a/chromium/content/browser/renderer_host/render_view_host_impl.cc
+++ b/chromium/content/browser/renderer_host/render_view_host_impl.cc
@@ -229,9 +229,12 @@ RenderViewHostImpl::RenderViewHostImpl(
if (ResourceDispatcherHostImpl::Get()) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&ResourceDispatcherHostImpl::OnRenderViewHostCreated,
- base::Unretained(ResourceDispatcherHostImpl::Get()),
- GetProcess()->GetID(), GetRoutingID()));
+ base::BindOnce(
+ &ResourceDispatcherHostImpl::OnRenderViewHostCreated,
+ base::Unretained(ResourceDispatcherHostImpl::Get()),
+ GetProcess()->GetID(), GetRoutingID(),
+ base::RetainedRef(
+ GetProcess()->GetStoragePartition()->GetURLRequestContext())));
}
close_timeout_.reset(new TimeoutMonitor(base::Bind(
@@ -244,9 +247,9 @@ RenderViewHostImpl::~RenderViewHostImpl() {
if (ResourceDispatcherHostImpl::Get()) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&ResourceDispatcherHostImpl::OnRenderViewHostDeleted,
- base::Unretained(ResourceDispatcherHostImpl::Get()),
- GetProcess()->GetID(), GetRoutingID()));
+ base::BindOnce(&ResourceDispatcherHostImpl::OnRenderViewHostDeleted,
+ base::Unretained(ResourceDispatcherHostImpl::Get()),
+ GetProcess()->GetID(), GetRoutingID()));
}
delegate_->RenderViewDeleted(this);
GetProcess()->RemoveObserver(this);
@@ -323,12 +326,6 @@ bool RenderViewHostImpl::CreateRenderView(
params->page_zoom_level = delegate_->GetPendingPageZoomLevel();
bool force_srgb_image_decode_color_space = false;
- // Pretend that HDR displays are sRGB so that we do not have inconsistent
- // coloring.
- // TODO(ccameron): Disable this once color correct rasterization is functional
- // https://crbug.com/701942
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableHDR))
- force_srgb_image_decode_color_space = true;
// When color correct rendering is enabled, the image_decode_color_space
// parameter should not be used (and all users of it should be using sRGB).
if (base::FeatureList::IsEnabled(features::kColorCorrectRendering))
@@ -474,6 +471,13 @@ WebPreferences RenderViewHostImpl::ComputeWebkitPrefs() {
prefs.primary_hover_type =
ui::GetPrimaryHoverType(prefs.available_hover_types);
+// TODO(dtapuska): Enable barrel button selection drag support on Android.
+// crbug.com/758042
+#if defined(OS_WIN)
+ prefs.barrel_button_for_drag_enabled =
+ base::FeatureList::IsEnabled(features::kDirectManipulationStylus);
+#endif // defined(OS_WIN)
+
#if defined(OS_ANDROID)
prefs.video_fullscreen_orientation_lock_enabled =
base::FeatureList::IsEnabled(media::kVideoFullscreenOrientationLock) &&
@@ -569,10 +573,10 @@ void RenderViewHostImpl::ClosePage() {
// TODO(creis): Should this be moved to Shutdown? It may not be called for
// RenderViewHosts that have been swapped out.
- NotificationService::current()->Notify(
- NOTIFICATION_RENDER_VIEW_HOST_WILL_CLOSE_RENDER_VIEW,
- Source<RenderViewHost>(this),
- NotificationService::NoDetails());
+#if !defined(OS_ANDROID)
+ static_cast<HostZoomMapImpl*>(HostZoomMap::Get(GetSiteInstance()))
+ ->WillCloseRenderView(GetProcess()->GetID(), GetRoutingID());
+#endif
Send(new ViewMsg_ClosePage(GetRoutingID()));
} else {
@@ -668,13 +672,11 @@ void RenderViewHostImpl::DirectoryEnumerationFinished(
void RenderViewHostImpl::RenderWidgetWillSetIsLoading(bool is_loading) {
if (ResourceDispatcherHostImpl::Get()) {
BrowserThread::PostTask(
- BrowserThread::IO,
- FROM_HERE,
- base::Bind(&ResourceDispatcherHostImpl::OnRenderViewHostSetIsLoading,
- base::Unretained(ResourceDispatcherHostImpl::Get()),
- GetProcess()->GetID(),
- GetRoutingID(),
- is_loading));
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(
+ &ResourceDispatcherHostImpl::OnRenderViewHostSetIsLoading,
+ base::Unretained(ResourceDispatcherHostImpl::Get()),
+ GetProcess()->GetID(), GetRoutingID(), is_loading));
}
}
@@ -881,6 +883,9 @@ void RenderViewHostImpl::OnWebkitPreferencesChanged() {
return;
updating_web_preferences_ = true;
UpdateWebkitPreferences(ComputeWebkitPrefs());
+#if defined(OS_ANDROID)
+ GetWidget()->SetForceEnableZoom(web_preferences_->force_enable_zoom);
+#endif
updating_web_preferences_ = false;
}
@@ -928,7 +933,7 @@ void RenderViewHostImpl::SelectWordAroundCaret() {
}
void RenderViewHostImpl::PostRenderViewReady() {
- GetProcess()->PostTaskWhenProcessIsReady(base::Bind(
+ 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 7e0cc57bddb..d9667c321aa 100644
--- a/chromium/content/browser/renderer_host/render_view_host_impl.h
+++ b/chromium/content/browser/renderer_host/render_view_host_impl.h
@@ -294,8 +294,8 @@ class CONTENT_EXPORT RenderViewHostImpl : public RenderViewHost,
// Tracks whether the main frame RenderFrameHost is swapped out. Unlike
// is_active_, this is false when the frame is pending swap out or deletion.
- // TODO(creis): Remove this when we no longer use swappedout://.
- // See http://crbug.com/357747.
+ // TODO(creis): Remove this when we no longer filter IPCs after swap out.
+ // See https://crbug.com/745091.
bool is_swapped_out_;
// Routing ID for the main frame's RenderFrameHost.
diff --git a/chromium/content/browser/renderer_host/render_view_host_unittest.cc b/chromium/content/browser/renderer_host/render_view_host_unittest.cc
index 6b13c091395..132ed24e33a 100644
--- a/chromium/content/browser/renderer_host/render_view_host_unittest.cc
+++ b/chromium/content/browser/renderer_host/render_view_host_unittest.cc
@@ -22,6 +22,7 @@
#include "content/public/common/drop_data.h"
#include "content/public/common/url_constants.h"
#include "content/public/test/mock_render_process_host.h"
+#include "content/test/mock_widget_impl.h"
#include "content/test/test_content_browser_client.h"
#include "content/test/test_render_view_host.h"
#include "content/test/test_web_contents.h"
@@ -31,15 +32,6 @@
namespace content {
-class WidgetImpl : public mojom::Widget {
- public:
- explicit WidgetImpl(mojo::InterfaceRequest<mojom::Widget> request)
- : binding_(this, std::move(request)) {}
-
- private:
- mojo::Binding<mojom::Widget> binding_;
-};
-
class RenderViewHostTestBrowserClient : public TestContentBrowserClient {
public:
RenderViewHostTestBrowserClient() {}
@@ -90,8 +82,8 @@ TEST_F(RenderViewHostTest, CreateFullscreenWidget) {
int32_t routing_id = process()->GetNextRoutingID();
mojom::WidgetPtr widget;
- std::unique_ptr<WidgetImpl> widget_impl =
- base::MakeUnique<WidgetImpl>(mojo::MakeRequest(&widget));
+ std::unique_ptr<MockWidgetImpl> widget_impl =
+ base::MakeUnique<MockWidgetImpl>(mojo::MakeRequest(&widget));
test_rvh()->CreateNewFullscreenWidget(routing_id, std::move(widget));
}
diff --git a/chromium/content/browser/renderer_host/render_widget_helper.cc b/chromium/content/browser/renderer_host/render_widget_helper.cc
index 9c1be294e4b..101cec2db35 100644
--- a/chromium/content/browser/renderer_host/render_widget_helper.cc
+++ b/chromium/content/browser/renderer_host/render_widget_helper.cc
@@ -52,10 +52,9 @@ void RenderWidgetHelper::Init(
render_process_id_ = render_process_id;
resource_dispatcher_host_ = resource_dispatcher_host;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::Bind(&AddWidgetHelper,
- render_process_id_, make_scoped_refptr(this)));
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&AddWidgetHelper, render_process_id_,
+ make_scoped_refptr(this)));
}
int RenderWidgetHelper::GetNextRoutingID() {
@@ -75,9 +74,8 @@ void RenderWidgetHelper::ResumeDeferredNavigation(
const GlobalRequestID& request_id) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&RenderWidgetHelper::OnResumeDeferredNavigation,
- this,
- request_id));
+ base::BindOnce(&RenderWidgetHelper::OnResumeDeferredNavigation, this,
+ request_id));
}
void RenderWidgetHelper::OnResumeDeferredNavigation(
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 0a22d86b302..b72bce8d718 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_impl.cc
@@ -42,6 +42,7 @@
#include "content/browser/renderer_host/dip_util.h"
#include "content/browser/renderer_host/frame_metadata_util.h"
#include "content/browser/renderer_host/input/input_router_config_helper.h"
+#include "content/browser/renderer_host/input/input_router_impl.h"
#include "content/browser/renderer_host/input/legacy_input_router_impl.h"
#include "content/browser/renderer_host/input/synthetic_gesture.h"
#include "content/browser/renderer_host/input/synthetic_gesture_controller.h"
@@ -73,6 +74,7 @@
#include "content/public/browser/render_widget_host_iterator.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/common/content_constants.h"
+#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/result_codes.h"
#include "content/public/common/web_preferences.h"
@@ -83,8 +85,9 @@
#include "skia/ext/image_operations.h"
#include "skia/ext/platform_canvas.h"
#include "storage/browser/fileapi/isolated_context.h"
-#include "third_party/WebKit/public/web/WebCompositionUnderline.h"
+#include "third_party/WebKit/public/web/WebImeTextSpan.h"
#include "ui/base/clipboard/clipboard.h"
+#include "ui/base/ui_base_switches.h"
#include "ui/display/display_switches.h"
#include "ui/events/blink/web_input_event_traits.h"
#include "ui/events/event.h"
@@ -256,6 +259,54 @@ std::vector<DropData::Metadata> DropDataToMetaData(const DropData& drop_data) {
return metadata;
}
+class UnboundWidgetInputHandler : public mojom::WidgetInputHandler {
+ public:
+ void SetFocus(bool focused) override {
+ DLOG(WARNING) << "Input request on unbound interface";
+ }
+ void MouseCaptureLost() override {
+ DLOG(WARNING) << "Input request on unbound interface";
+ }
+ void SetEditCommandsForNextKeyEvent(
+ const std::vector<content::EditCommand>& commands) override {
+ DLOG(WARNING) << "Input request on unbound interface";
+ }
+ void CursorVisibilityChanged(bool visible) override {
+ DLOG(WARNING) << "Input request on unbound interface";
+ }
+ void ImeSetComposition(const base::string16& text,
+ const std::vector<ui::ImeTextSpan>& ime_text_spans,
+ const gfx::Range& range,
+ int32_t start,
+ int32_t end) override {
+ DLOG(WARNING) << "Input request on unbound interface";
+ }
+ void ImeCommitText(const base::string16& text,
+ const std::vector<ui::ImeTextSpan>& ime_text_spans,
+ const gfx::Range& range,
+ int32_t relative_cursor_position) override {
+ DLOG(WARNING) << "Input request on unbound interface";
+ }
+ void ImeFinishComposingText(bool keep_selection) override {
+ DLOG(WARNING) << "Input request on unbound interface";
+ }
+ void RequestTextInputStateUpdate() override {
+ DLOG(WARNING) << "Input request on unbound interface";
+ }
+ void RequestCompositionUpdates(bool immediate_request,
+ bool monitor_request) override {
+ DLOG(WARNING) << "Input request on unbound interface";
+ }
+ void DispatchEvent(std::unique_ptr<content::InputEvent> event,
+ DispatchEventCallback callback) override {
+ DLOG(WARNING) << "Input request on unbound interface";
+ }
+ void DispatchNonBlockingEvent(
+ std::unique_ptr<content::InputEvent> event) override {
+ DLOG(WARNING) << "Input request on unbound interface";
+ }
+};
+
} // namespace
///////////////////////////////////////////////////////////////////////////////
@@ -264,6 +315,7 @@ std::vector<DropData::Metadata> DropDataToMetaData(const DropData& drop_data) {
RenderWidgetHostImpl::RenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
RenderProcessHost* process,
int32_t routing_id,
+ mojom::WidgetPtr widget,
bool hidden)
: renderer_initialized_(false),
destroyed_(false),
@@ -308,7 +360,6 @@ RenderWidgetHostImpl::RenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
CHECK(delegate_);
CHECK_NE(MSG_ROUTING_NONE, routing_id_);
latency_tracker_.SetDelegate(delegate_);
-
DCHECK(base::TaskScheduler::GetInstance())
<< "Ref. Prerequisite section of post_task.h";
#if defined(OS_WIN)
@@ -321,6 +372,8 @@ RenderWidgetHostImpl::RenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
}
#endif
+ SetWidget(std::move(widget));
+
std::pair<RoutingIDWidgetMap::iterator, bool> result =
g_routing_id_widget_map.Get().insert(std::make_pair(
RenderWidgetHostID(process->GetID(), routing_id_), this));
@@ -336,11 +389,7 @@ RenderWidgetHostImpl::RenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
latency_tracker_.Initialize(routing_id_, GetProcess()->GetID());
- input_router_.reset(new LegacyInputRouterImpl(
- process_, this, this, routing_id_, GetInputRouterConfigForPlatform()));
- legacy_widget_input_handler_ = base::MakeUnique<LegacyIPCWidgetInputHandler>(
- static_cast<LegacyInputRouterImpl*>(input_router_.get()));
-
+ SetupInputRouter();
touch_emulator_.reset();
if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
@@ -551,8 +600,6 @@ bool RenderWidgetHostImpl::OnMessageReceived(const IPC::Message &msg) {
IPC_BEGIN_MESSAGE_MAP(RenderWidgetHostImpl, msg)
IPC_MESSAGE_HANDLER(FrameHostMsg_RenderProcessGone, OnRenderProcessGone)
IPC_MESSAGE_HANDLER(FrameHostMsg_HittestData, OnHittestData)
- IPC_MESSAGE_HANDLER(InputHostMsg_QueueSyntheticGesture,
- OnQueueSyntheticGesture)
IPC_MESSAGE_HANDLER(InputHostMsg_ImeCancelComposition,
OnImeCancelComposition)
IPC_MESSAGE_HANDLER(ViewHostMsg_Close, OnClose)
@@ -673,18 +720,21 @@ void RenderWidgetHostImpl::WasShown(const ui::LatencyInfo& latency_info) {
WasResized();
}
+#if defined(OS_ANDROID)
+void RenderWidgetHostImpl::SetImportance(ChildProcessImportance importance) {
+ if (importance_ == importance)
+ return;
+ ChildProcessImportance old = importance_;
+ importance_ = importance;
+ process_->UpdateWidgetImportance(old, importance_);
+}
+#endif
+
bool RenderWidgetHostImpl::GetResizeParams(ResizeParams* resize_params) {
*resize_params = ResizeParams();
GetScreenInfo(&resize_params->screen_info);
- // Pretend that HDR displays are sRGB so that we do not have inconsistent
- // coloring.
- // TODO(ccameron): Disable this once color correct rasterization is functional
- // https://crbug.com/701942
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableHDR))
- resize_params->screen_info.color_space = gfx::ColorSpace::CreateSRGB();
-
if (delegate_) {
resize_params->is_fullscreen_granted =
delegate_->IsFullscreenForCurrentTab();
@@ -1114,7 +1164,8 @@ void RenderWidgetHostImpl::ForwardGestureEvent(
void RenderWidgetHostImpl::ForwardGestureEventWithLatencyInfo(
const blink::WebGestureEvent& gesture_event,
const ui::LatencyInfo& latency) {
- TRACE_EVENT0("input", "RenderWidgetHostImpl::ForwardGestureEvent");
+ TRACE_EVENT1("input", "RenderWidgetHostImpl::ForwardGestureEvent", "type",
+ WebInputEvent::GetName(gesture_event.GetType()));
// Early out if necessary, prior to performing latency logic.
if (ShouldDropInputEvents())
return;
@@ -1316,7 +1367,7 @@ void RenderWidgetHostImpl::ForwardKeyboardEventWithCommands(
void RenderWidgetHostImpl::QueueSyntheticGesture(
std::unique_ptr<SyntheticGesture> synthetic_gesture,
- const base::Callback<void(SyntheticGesture::Result)>& on_complete) {
+ base::OnceCallback<void(SyntheticGesture::Result)> on_complete) {
if (!synthetic_gesture_controller_ && view_) {
synthetic_gesture_controller_ =
base::MakeUnique<SyntheticGestureController>(
@@ -1324,7 +1375,7 @@ void RenderWidgetHostImpl::QueueSyntheticGesture(
}
if (synthetic_gesture_controller_) {
synthetic_gesture_controller_->QueueSyntheticGesture(
- std::move(synthetic_gesture), on_complete);
+ std::move(synthetic_gesture), std::move(on_complete));
}
}
@@ -1486,6 +1537,10 @@ void RenderWidgetHostImpl::SetCursor(const CursorInfo& cursor_info) {
}
mojom::WidgetInputHandler* RenderWidgetHostImpl::GetWidgetInputHandler() {
+ if (associated_widget_input_handler_)
+ return associated_widget_input_handler_.get();
+ if (widget_input_handler_)
+ return widget_input_handler_.get();
return legacy_widget_input_handler_.get();
}
@@ -1531,11 +1586,6 @@ void RenderWidgetHostImpl::GetSnapshotFromBrowser(
Send(new ViewMsg_ForceRedraw(GetRoutingID(), latency_info));
}
-const NativeWebKeyboardEvent*
- RenderWidgetHostImpl::GetLastKeyboardEvent() const {
- return input_router_->GetLastKeyboardEvent();
-}
-
void RenderWidgetHostImpl::SelectionChanged(const base::string16& text,
uint32_t offset,
const gfx::Range& range) {
@@ -1697,11 +1747,9 @@ void RenderWidgetHostImpl::RendererExited(base::TerminationStatus status,
// renderer. Otherwise it may be stuck waiting for the old renderer to ack an
// event. (In particular, the above call to view_->RenderProcessGone will
// destroy the aura window, which may dispatch a synthetic mouse move.)
- input_router_.reset(new LegacyInputRouterImpl(
- process_, this, this, routing_id_, GetInputRouterConfigForPlatform()));
- legacy_widget_input_handler_ = base::MakeUnique<LegacyIPCWidgetInputHandler>(
- static_cast<LegacyInputRouterImpl*>(input_router_.get()));
-
+ SetupInputRouter();
+ associated_widget_input_handler_ = nullptr;
+ widget_input_handler_ = nullptr;
synthetic_gesture_controller_.reset();
last_received_frame_token_ = 0;
@@ -1729,21 +1777,21 @@ void RenderWidgetHostImpl::NotifyTextDirection() {
void RenderWidgetHostImpl::ImeSetComposition(
const base::string16& text,
- const std::vector<ui::CompositionUnderline>& underlines,
+ const std::vector<ui::ImeTextSpan>& ime_text_spans,
const gfx::Range& replacement_range,
int selection_start,
int selection_end) {
GetWidgetInputHandler()->ImeSetComposition(
- text, underlines, replacement_range, selection_start, selection_end);
+ text, ime_text_spans, replacement_range, selection_start, selection_end);
}
void RenderWidgetHostImpl::ImeCommitText(
const base::string16& text,
- const std::vector<ui::CompositionUnderline>& underlines,
+ const std::vector<ui::ImeTextSpan>& ime_text_spans,
const gfx::Range& replacement_range,
int relative_cursor_pos) {
- GetWidgetInputHandler()->ImeCommitText(text, underlines, replacement_range,
- relative_cursor_pos);
+ GetWidgetInputHandler()->ImeCommitText(
+ text, ime_text_spans, replacement_range, relative_cursor_pos);
}
void RenderWidgetHostImpl::ImeFinishComposingText(bool keep_selection) {
@@ -1751,9 +1799,9 @@ void RenderWidgetHostImpl::ImeFinishComposingText(bool keep_selection) {
}
void RenderWidgetHostImpl::ImeCancelComposition() {
- GetWidgetInputHandler()->ImeSetComposition(
- base::string16(), std::vector<ui::CompositionUnderline>(),
- gfx::Range::InvalidRange(), 0, 0);
+ GetWidgetInputHandler()->ImeSetComposition(base::string16(),
+ std::vector<ui::ImeTextSpan>(),
+ gfx::Range::InvalidRange(), 0, 0);
}
void RenderWidgetHostImpl::RejectMouseLockOrUnlockIfNecessary() {
@@ -1942,9 +1990,9 @@ void RenderWidgetHostImpl::OnRequestMove(const gfx::Rect& pos) {
}
}
-void RenderWidgetHostImpl::DidNotProduceFrame(const cc::BeginFrameAck& ack) {
+void RenderWidgetHostImpl::DidNotProduceFrame(const viz::BeginFrameAck& ack) {
// |has_damage| is not transmitted.
- cc::BeginFrameAck modified_ack = ack;
+ viz::BeginFrameAck modified_ack = ack;
modified_ack.has_damage = false;
if (view_)
@@ -1989,8 +2037,8 @@ void RenderWidgetHostImpl::OnUpdateRect(
new_auto_size_ = params.view_size;
if (post_callback) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&RenderWidgetHostImpl::DelayedAutoResized,
- weak_factory_.GetWeakPtr()));
+ FROM_HERE, base::BindOnce(&RenderWidgetHostImpl::DelayedAutoResized,
+ weak_factory_.GetWeakPtr()));
}
}
@@ -2024,22 +2072,6 @@ void RenderWidgetHostImpl::DidUpdateBackingStore(
WasResized();
}
-void RenderWidgetHostImpl::OnQueueSyntheticGesture(
- const SyntheticGesturePacket& gesture_packet) {
- // Only allow untrustworthy gestures if explicitly enabled.
- if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
- cc::switches::kEnableGpuBenchmarking)) {
- bad_message::ReceivedBadMessage(GetProcess(),
- bad_message::RWH_SYNTHETIC_GESTURE);
- return;
- }
-
- QueueSyntheticGesture(
- SyntheticGesture::Create(*gesture_packet.gesture_params()),
- base::Bind(&RenderWidgetHostImpl::OnSyntheticGestureCompleted,
- weak_factory_.GetWeakPtr()));
-}
-
void RenderWidgetHostImpl::OnSetCursor(const WebCursor& cursor) {
SetCursor(cursor);
}
@@ -2080,19 +2112,13 @@ void RenderWidgetHostImpl::OnAutoscrollEnd() {
input_router_->SendGestureEvent(GestureEventWithLatencyInfo(end_event));
}
-void RenderWidgetHostImpl::SetTouchEventEmulationEnabled(
- bool enabled, ui::GestureProviderConfigType config_type) {
- if (enabled) {
- if (!touch_emulator_) {
- touch_emulator_.reset(new TouchEmulator(
- this,
- view_.get() ? content::GetScaleFactorForView(view_.get()) : 1.0f));
- }
- touch_emulator_->Enable(config_type);
- } else {
- if (touch_emulator_)
- touch_emulator_->Disable();
+TouchEmulator* RenderWidgetHostImpl::GetTouchEmulator() {
+ if (!touch_emulator_) {
+ touch_emulator_.reset(new TouchEmulator(
+ this,
+ view_.get() ? content::GetScaleFactorForView(view_.get()) : 1.0f));
}
+ return touch_emulator_.get();
}
void RenderWidgetHostImpl::OnTextInputStateChanged(
@@ -2363,13 +2389,6 @@ void RenderWidgetHostImpl::OnUnexpectedEventAck(UnexpectedEventAckType type) {
}
}
-void RenderWidgetHostImpl::OnSyntheticGestureCompleted(
- SyntheticGesture::Result result) {
- // TODO(dtapuska): Define mojo interface for InputHostMsg's and this will be a
- // callback for completing InputHostMsg_QueueSyntheticGesture.
- process_->Send(new InputMsg_SyntheticGestureCompleted(GetRoutingID()));
-}
-
bool RenderWidgetHostImpl::ShouldDropInputEvents() const {
return ignore_input_events_ || process_->IgnoreInputEvents() || !delegate_;
}
@@ -2561,8 +2580,8 @@ void RenderWidgetHostImpl::RequestCompositionUpdates(bool immediate_request,
}
void RenderWidgetHostImpl::RequestCompositorFrameSink(
- cc::mojom::CompositorFrameSinkRequest request,
- cc::mojom::CompositorFrameSinkClientPtr client) {
+ viz::mojom::CompositorFrameSinkRequest request,
+ viz::mojom::CompositorFrameSinkClientPtr client) {
if (compositor_frame_sink_binding_.is_bound())
compositor_frame_sink_binding_.Close();
compositor_frame_sink_binding_.Bind(
@@ -2583,7 +2602,23 @@ void RenderWidgetHostImpl::SetNeedsBeginFrame(bool needs_begin_frame) {
void RenderWidgetHostImpl::SubmitCompositorFrame(
const viz::LocalSurfaceId& local_surface_id,
- cc::CompositorFrame frame) {
+ cc::CompositorFrame frame,
+ viz::mojom::HitTestRegionListPtr hit_test_region_list,
+ uint64_t submit_time) {
+ // TODO(gklassen): Route hit-test data to appropriate HitTestAggregator.
+ TRACE_EVENT_FLOW_END0(TRACE_DISABLED_BY_DEFAULT("cc.debug.ipc"),
+ "SubmitCompositorFrame", local_surface_id.local_id());
+ bool tracing_enabled;
+ TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("cc.debug.ipc"),
+ &tracing_enabled);
+ if (tracing_enabled) {
+ base::TimeDelta elapsed = base::TimeTicks::Now().since_origin() -
+ base::TimeDelta::FromMicroseconds(submit_time);
+ TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.ipc"),
+ "SubmitCompositorFrame::TimeElapsed",
+ TRACE_EVENT_SCOPE_THREAD,
+ "elapsed time:", elapsed.InMicroseconds());
+ }
auto new_surface_properties =
RenderWidgetSurfaceProperties::FromCompositorFrame(frame);
@@ -2608,6 +2643,7 @@ void RenderWidgetHostImpl::SubmitCompositorFrame(
saved_frame_.frame = std::move(frame);
saved_frame_.local_surface_id = local_surface_id;
saved_frame_.max_shared_bitmap_sequence_number = max_sequence_number;
+ saved_frame_.hit_test_region_list = std::move(hit_test_region_list);
TRACE_EVENT_ASYNC_BEGIN2("renderer_host", "PauseCompositorFrameSink", this,
"LastRegisteredSequenceNumber",
last_registered_sequence_number,
@@ -2644,8 +2680,8 @@ void RenderWidgetHostImpl::SubmitCompositorFrame(
view_->SubmitCompositorFrame(local_surface_id, std::move(frame));
view_->DidReceiveRendererFrame();
} else {
- std::vector<cc::ReturnedResource> resources =
- cc::TransferableResource::ReturnResources(frame.resource_list);
+ std::vector<viz::ReturnedResource> resources =
+ viz::TransferableResource::ReturnResources(frame.resource_list);
renderer_compositor_frame_sink_->DidReceiveCompositorFrameAck(resources);
}
@@ -2718,12 +2754,54 @@ device::mojom::WakeLock* RenderWidgetHostImpl::GetWakeLock() {
void RenderWidgetHostImpl::DidAllocateSharedBitmap(uint32_t sequence_number) {
if (saved_frame_.local_surface_id.is_valid() &&
sequence_number >= saved_frame_.max_shared_bitmap_sequence_number) {
- SubmitCompositorFrame(saved_frame_.local_surface_id,
- std::move(saved_frame_.frame));
+ bool tracing_enabled;
+ TRACE_EVENT_CATEGORY_GROUP_ENABLED(
+ TRACE_DISABLED_BY_DEFAULT("cc.debug.ipc"), &tracing_enabled);
+ SubmitCompositorFrame(
+ saved_frame_.local_surface_id, std::move(saved_frame_.frame),
+ std::move(saved_frame_.hit_test_region_list),
+ tracing_enabled ? base::TimeTicks::Now().since_origin().InMicroseconds()
+ : 0);
saved_frame_.local_surface_id = viz::LocalSurfaceId();
compositor_frame_sink_binding_.ResumeIncomingMethodCallProcessing();
TRACE_EVENT_ASYNC_END0("renderer_host", "PauseCompositorFrameSink", this);
}
}
+void RenderWidgetHostImpl::SetupInputRouter() {
+ if (base::FeatureList::IsEnabled(features::kMojoInputMessages)) {
+ input_router_.reset(
+ new InputRouterImpl(this, this, GetInputRouterConfigForPlatform()));
+ // TODO(dtapuska): Remove the need for the unbound interface. It is
+ // possible that a RVHI may make calls to a WidgetInputHandler when
+ // the main frame is remote. This is because of ordering issues during
+ // widget shutdown, so we present an UnboundWidgetInputHandler had
+ // DLOGS the message calls.
+ legacy_widget_input_handler_ =
+ base::MakeUnique<UnboundWidgetInputHandler>();
+ } else {
+ input_router_.reset(new LegacyInputRouterImpl(
+ process_, this, this, routing_id_, GetInputRouterConfigForPlatform()));
+ legacy_widget_input_handler_ =
+ base::MakeUnique<LegacyIPCWidgetInputHandler>(
+ static_cast<LegacyInputRouterImpl*>(input_router_.get()));
+ }
+}
+
+void RenderWidgetHostImpl::SetForceEnableZoom(bool enabled) {
+ input_router_->SetForceEnableZoom(enabled);
+}
+
+void RenderWidgetHostImpl::SetWidgetInputHandler(
+ mojom::WidgetInputHandlerAssociatedPtr widget_input_handler) {
+ associated_widget_input_handler_ = std::move(widget_input_handler);
+}
+
+void RenderWidgetHostImpl::SetWidget(mojom::WidgetPtr widget) {
+ if (widget && base::FeatureList::IsEnabled(features::kMojoInputMessages)) {
+ widget_input_handler_.reset();
+ widget->GetWidgetInputHandler(mojo::MakeRequest(&widget_input_handler_));
+ }
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_widget_host_impl.h b/chromium/content/browser/renderer_host/render_widget_host_impl.h
index 43d1ad1d191..b75d5e75df8 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_impl.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_impl.h
@@ -25,13 +25,12 @@
#include "base/time/time.h"
#include "base/timer/elapsed_timer.h"
#include "build/build_config.h"
-#include "cc/ipc/compositor_frame_sink.mojom.h"
#include "components/viz/common/quads/shared_bitmap.h"
#include "components/viz/common/surfaces/frame_sink_id.h"
#include "components/viz/service/display_embedder/shared_bitmap_allocation_notifier_impl.h"
#include "content/browser/renderer_host/event_with_latency_info.h"
-#include "content/browser/renderer_host/input/input_ack_handler.h"
-#include "content/browser/renderer_host/input/input_router_client.h"
+#include "content/browser/renderer_host/input/input_disposition_handler.h"
+#include "content/browser/renderer_host/input/input_router_impl.h"
#include "content/browser/renderer_host/input/legacy_ipc_widget_input_handler.h"
#include "content/browser/renderer_host/input/render_widget_host_latency_tracker.h"
#include "content/browser/renderer_host/input/synthetic_gesture.h"
@@ -42,22 +41,26 @@
#include "content/common/drag_event_source_info.h"
#include "content/common/input/input_event_ack_state.h"
#include "content/common/input/input_handler.mojom.h"
-#include "content/common/input/synthetic_gesture_packet.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/page_zoom.h"
#include "content/public/common/url_constants.h"
#include "ipc/ipc_listener.h"
#include "mojo/public/cpp/bindings/binding.h"
+#include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom.h"
#include "third_party/WebKit/public/platform/WebDisplayMode.h"
#include "ui/base/ime/text_input_mode.h"
#include "ui/base/ime/text_input_type.h"
#include "ui/base/ui_base_types.h"
-#include "ui/events/gesture_detection/gesture_provider_config_helper.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/latency/latency_info.h"
+#if defined(OS_ANDROID)
+#include "content/public/browser/android/child_process_importance.h"
+#endif
+
#if defined(OS_MACOSX)
#include "services/device/public/interfaces/wake_lock.mojom.h"
#endif
@@ -101,12 +104,12 @@ struct TextInputState;
// embedders of content, and adds things only visible to content.
class CONTENT_EXPORT RenderWidgetHostImpl
: public RenderWidgetHost,
- public InputRouterClient,
- public InputAckHandler,
+ public InputRouterImplClient,
+ public InputDispositionHandler,
public TouchEmulatorClient,
- public NON_EXPORTED_BASE(SyntheticGestureController::Delegate),
- public NON_EXPORTED_BASE(cc::mojom::CompositorFrameSink),
- public NON_EXPORTED_BASE(viz::SharedBitmapAllocationObserver),
+ public SyntheticGestureController::Delegate,
+ public viz::mojom::CompositorFrameSink,
+ public viz::SharedBitmapAllocationObserver,
public IPC::Listener {
public:
// |routing_id| must not be MSG_ROUTING_NONE.
@@ -115,7 +118,9 @@ class CONTENT_EXPORT RenderWidgetHostImpl
RenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
RenderProcessHost* process,
int32_t routing_id,
+ mojom::WidgetPtr widget_interface,
bool hidden);
+
~RenderWidgetHostImpl() override;
// Similar to RenderWidgetHost::FromID, but returning the Impl object.
@@ -212,7 +217,6 @@ class CONTENT_EXPORT RenderWidgetHostImpl
void DragSourceSystemDragEnded() override;
void FilterDropData(DropData* drop_data) override;
void SetCursor(const CursorInfo& cursor_info) override;
- mojom::WidgetInputHandler* GetWidgetInputHandler();
// Notification that the screen info has changed.
void NotifyScreenInfoChanged();
@@ -231,8 +235,6 @@ class CONTENT_EXPORT RenderWidgetHostImpl
void GetSnapshotFromBrowser(const GetSnapshotFromBrowserCallback& callback,
bool from_surface);
- const NativeWebKeyboardEvent* GetLastKeyboardEvent() const;
-
// Sets the View of this RenderWidgetHost.
void SetView(RenderWidgetHostViewBase* view);
@@ -274,6 +276,13 @@ class CONTENT_EXPORT RenderWidgetHostImpl
void WasHidden();
void WasShown(const ui::LatencyInfo& latency_info);
+#if defined(OS_ANDROID)
+ // Set the importance of widget. The importance is passed onto
+ // RenderProcessHost which aggregates importance of all of its widgets.
+ void SetImportance(ChildProcessImportance importance);
+ ChildProcessImportance importance() const { return importance_; }
+#endif
+
// Returns true if the RenderWidget is hidden.
bool is_hidden() const { return is_hidden_; }
@@ -378,9 +387,8 @@ class CONTENT_EXPORT RenderWidgetHostImpl
const blink::WebMouseWheelEvent& wheel_event,
const ui::LatencyInfo& latency); // Virtual for testing.
- // Enables/disables touch emulation using mouse event. See TouchEmulator.
- void SetTouchEventEmulationEnabled(
- bool enabled, ui::GestureProviderConfigType config_type);
+ // Returns an emulator for this widget. See TouchEmulator for more details.
+ TouchEmulator* GetTouchEmulator();
// TouchEmulatorClient implementation.
void ForwardEmulatedGestureEvent(
@@ -395,7 +403,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl
// callback when the gesture is finished running.
void QueueSyntheticGesture(
std::unique_ptr<SyntheticGesture> synthetic_gesture,
- const base::Callback<void(SyntheticGesture::Result)>& on_complete);
+ base::OnceCallback<void(SyntheticGesture::Result)> on_complete);
void CancelUpdateTextDirection();
@@ -414,12 +422,11 @@ class CONTENT_EXPORT RenderWidgetHostImpl
// (on Windows);
// * when it receives a "preedit_changed" signal of GtkIMContext (on Linux);
// * when markedText of NSTextInput is called (on Mac).
- void ImeSetComposition(
- const base::string16& text,
- const std::vector<ui::CompositionUnderline>& underlines,
- const gfx::Range& replacement_range,
- int selection_start,
- int selection_end);
+ void ImeSetComposition(const base::string16& text,
+ const std::vector<ui::ImeTextSpan>& ime_text_spans,
+ const gfx::Range& replacement_range,
+ int selection_start,
+ int selection_end);
// Deletes the ongoing composition if any, inserts the specified text, and
// moves the cursor.
@@ -429,7 +436,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl
// * when it receives a "commit" signal of GtkIMContext (on Linux);
// * when insertText of NSTextInput is called (on Mac).
void ImeCommitText(const base::string16& text,
- const std::vector<ui::CompositionUnderline>& underlines,
+ const std::vector<ui::ImeTextSpan>& ime_text_spans,
const gfx::Range& replacement_range,
int relative_cursor_pos);
@@ -505,6 +512,8 @@ class CONTENT_EXPORT RenderWidgetHostImpl
InputRouter* input_router() { return input_router_.get(); }
+ void SetForceEnableZoom(bool);
+
// Get the BrowserAccessibilityManager for the root of the frame tree,
BrowserAccessibilityManager* GetRootBrowserAccessibilityManager();
@@ -570,8 +579,8 @@ class CONTENT_EXPORT RenderWidgetHostImpl
void RequestCompositionUpdates(bool immediate_request, bool monitor_updates);
void RequestCompositorFrameSink(
- cc::mojom::CompositorFrameSinkRequest request,
- cc::mojom::CompositorFrameSinkClientPtr client);
+ viz::mojom::CompositorFrameSinkRequest request,
+ viz::mojom::CompositorFrameSinkClientPtr client);
const cc::CompositorFrameMetadata& last_frame_metadata() {
return last_frame_metadata_;
@@ -579,16 +588,28 @@ class CONTENT_EXPORT RenderWidgetHostImpl
bool HasGestureStopped() override;
- // cc::mojom::CompositorFrameSink implementation.
+ // viz::mojom::CompositorFrameSink implementation.
void SetNeedsBeginFrame(bool needs_begin_frame) override;
- void SubmitCompositorFrame(const viz::LocalSurfaceId& local_surface_id,
- cc::CompositorFrame frame) override;
- void DidNotProduceFrame(const cc::BeginFrameAck& ack) override;
+ void SubmitCompositorFrame(
+ const viz::LocalSurfaceId& local_surface_id,
+ cc::CompositorFrame frame,
+ viz::mojom::HitTestRegionListPtr hit_test_region_list,
+ uint64_t submit_time) override;
+ void DidNotProduceFrame(const viz::BeginFrameAck& ack) override;
// Signals that a frame with token |frame_token| was finished processing. If
// there are any queued messages belonging to it, they will be processed.
void DidProcessFrame(uint32_t frame_token);
+ // An associated WidgetInputHandler should be set if the RWHI is associated
+ // with a RenderFrameHost. Using an associated channel will allow the
+ // interface calls processed on the FrameInputHandler to be processed in order
+ // with the interface calls processed on the WidgetInputHandler.
+ void SetWidgetInputHandler(
+ mojom::WidgetInputHandlerAssociatedPtr widget_input_handler);
+ mojom::WidgetInputHandler* GetWidgetInputHandler() override;
+ void SetWidget(mojom::WidgetPtr widget);
+
protected:
// ---------------------------------------------------------------------------
// The following method is overridden by RenderViewHost to send upwards to
@@ -649,7 +670,6 @@ class CONTENT_EXPORT RenderWidgetHostImpl
void OnSetTooltipText(const base::string16& tooltip_text,
blink::WebTextDirection text_direction_hint);
void OnUpdateRect(const ViewHostMsg_UpdateRect_Params& params);
- void OnQueueSyntheticGesture(const SyntheticGesturePacket& gesture_packet);
void OnSetCursor(const WebCursor& cursor);
void OnAutoscrollStart(const gfx::PointF& position);
void OnAutoscrollFling(const gfx::Vector2dF& velocity);
@@ -720,8 +740,6 @@ class CONTENT_EXPORT RenderWidgetHostImpl
InputEventAckState ack_result) override;
void OnUnexpectedEventAck(UnexpectedEventAckType type) override;
- void OnSyntheticGestureCompleted(SyntheticGesture::Result result);
-
// Called when there is a new auto resize (using a post to avoid a stack
// which may get in recursive loops).
void DelayedAutoResized();
@@ -761,6 +779,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl
// viz::SharedBitmapAllocationObserver implementation.
void DidAllocateSharedBitmap(
uint32_t last_shared_bitmap_sequence_number) override;
+ void SetupInputRouter();
#if defined(OS_MACOSX)
device::mojom::WakeLock* GetWakeLock();
@@ -795,6 +814,12 @@ class CONTENT_EXPORT RenderWidgetHostImpl
// most recent call to process_->WidgetRestored() / WidgetHidden().
bool is_hidden_;
+#if defined(OS_ANDROID)
+ // Tracks the current importance of widget, so the old value can be passed to
+ // RenderProcessHost on changes.
+ ChildProcessImportance importance_ = ChildProcessImportance::NORMAL;
+#endif
+
// Set if we are waiting for a repaint ack for the view.
bool repaint_ack_pending_;
@@ -977,8 +1002,8 @@ class CONTENT_EXPORT RenderWidgetHostImpl
viz::LocalSurfaceId last_local_surface_id_;
RenderWidgetSurfaceProperties last_surface_properties_;
- mojo::Binding<cc::mojom::CompositorFrameSink> compositor_frame_sink_binding_;
- cc::mojom::CompositorFrameSinkClientPtr renderer_compositor_frame_sink_;
+ mojo::Binding<viz::mojom::CompositorFrameSink> compositor_frame_sink_binding_;
+ viz::mojom::CompositorFrameSinkClientPtr renderer_compositor_frame_sink_;
cc::CompositorFrameMetadata last_frame_metadata_;
@@ -996,9 +1021,17 @@ class CONTENT_EXPORT RenderWidgetHostImpl
viz::LocalSurfaceId local_surface_id;
cc::CompositorFrame frame;
uint32_t max_shared_bitmap_sequence_number = 0;
+ viz::mojom::HitTestRegionListPtr hit_test_region_list;
} saved_frame_;
- std::unique_ptr<LegacyIPCWidgetInputHandler> legacy_widget_input_handler_;
+ // If the |associated_widget_input_handler_| is set it should always be
+ // used to ensure in order delivery of related messages that may occur
+ // at the frame input level; see FrameInputHandler. Note that when the
+ // RWHI wraps a WebPagePopup widget it will only have a
+ // a |widget_input_handler_|.
+ mojom::WidgetInputHandlerAssociatedPtr associated_widget_input_handler_;
+ mojom::WidgetInputHandlerPtr widget_input_handler_;
+ std::unique_ptr<mojom::WidgetInputHandler> legacy_widget_input_handler_;
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 0730057c333..6a5d184755b 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
@@ -8,12 +8,12 @@
#include "base/metrics/histogram_macros.h"
#include "cc/quads/surface_draw_quad.h"
-#include "cc/surfaces/surface_manager.h"
-#include "content/browser/frame_host/render_widget_host_view_child_frame.h"
+#include "components/viz/service/surfaces/surface_manager.h"
#include "content/browser/frame_host/render_widget_host_view_guest.h"
#include "content/browser/renderer_host/cursor_manager.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
+#include "content/browser/renderer_host/render_widget_host_view_child_frame.h"
#include "content/common/frame_messages.h"
#include "third_party/WebKit/public/platform/WebInputEvent.h"
#include "ui/events/blink/web_input_event_traits.h"
@@ -287,8 +287,11 @@ void RenderWidgetHostInputEventRouter::RouteMouseWheelEvent(
if (!root_view->TransformPointToCoordSpaceForView(
gfx::Point(event->PositionInWidget().x,
event->PositionInWidget().y),
- target, &transformed_point))
+ target, &transformed_point)) {
+ root_view->WheelEventAck(*event,
+ INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
return;
+ }
} else if (root_view->wheel_scroll_latching_enabled()) {
if (event->phase == blink::WebMouseWheelEvent::kPhaseBegan) {
wheel_target_.target = FindEventTarget(
@@ -316,8 +319,10 @@ void RenderWidgetHostInputEventRouter::RouteMouseWheelEvent(
&transformed_point);
}
- if (!target)
+ if (!target) {
+ root_view->WheelEventAck(*event, INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
return;
+ }
event->SetPositionInWidget(transformed_point.x(), transformed_point.y());
target->ProcessMouseWheelEvent(*event, latency);
@@ -405,8 +410,10 @@ void RenderWidgetHostInputEventRouter::RouteTouchEvent(
const ui::LatencyInfo& latency) {
switch (event->GetType()) {
case blink::WebInputEvent::kTouchStart: {
+ int current_active_touches = active_touches_;
active_touches_ += CountChangedTouchPoints(*event);
- if (active_touches_ == 1) {
+ DCHECK(active_touches_);
+ if (!current_active_touches) {
// Since this is the first touch, it defines the target for the rest
// of this sequence.
DCHECK(!touch_target_.target);
@@ -428,8 +435,12 @@ void RenderWidgetHostInputEventRouter::RouteTouchEvent(
touchscreen_gesture_target_map_[event->unique_touch_event_id] =
touch_target_;
- if (!touch_target_.target)
+ if (!touch_target_.target) {
+ TouchEventWithLatencyInfo touch_with_latency(*event, latency);
+ root_view->ProcessAckedTouchEvent(
+ touch_with_latency, INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
return;
+ }
if (touch_target_.target == bubbling_gesture_scroll_target_.target) {
SendGestureScrollEnd(
@@ -446,21 +457,31 @@ void RenderWidgetHostInputEventRouter::RouteTouchEvent(
break;
}
case blink::WebInputEvent::kTouchMove:
- if (touch_target_.target) {
- TransformEventTouchPositions(event, touch_target_.delta);
- touch_target_.target->ProcessTouchEvent(*event, latency);
+ if (!touch_target_.target) {
+ TouchEventWithLatencyInfo touch_with_latency(*event, latency);
+ root_view->ProcessAckedTouchEvent(
+ touch_with_latency, INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
+ return;
}
+
+ TransformEventTouchPositions(event, touch_target_.delta);
+ touch_target_.target->ProcessTouchEvent(*event, latency);
break;
case blink::WebInputEvent::kTouchEnd:
case blink::WebInputEvent::kTouchCancel:
- // It might be safer to test active_touches_ and only decrement it if it's
- // non-zero, since active_touches_ can be reset to 0 in
- // OnRenderWidgetHostViewBaseDestroyed, and this can happen between the
- // TouchStart and a subsequent TouchMove/End/Cancel.
- DCHECK(active_touches_);
- active_touches_ -= CountChangedTouchPoints(*event);
- if (!touch_target_.target)
+ // Test active_touches_ before decrementing, since its value can be
+ // reset to 0 in OnRenderWidgetHostViewBaseDestroyed, and this can
+ // happen between the TouchStart and a subsequent TouchMove/End/Cancel.
+ if (active_touches_)
+ active_touches_ -= CountChangedTouchPoints(*event);
+ DCHECK_GE(active_touches_, 0);
+
+ if (!touch_target_.target) {
+ TouchEventWithLatencyInfo touch_with_latency(*event, latency);
+ root_view->ProcessAckedTouchEvent(
+ touch_with_latency, INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
return;
+ }
TransformEventTouchPositions(event, touch_target_.delta);
touch_target_.target->ProcessTouchEvent(*event, latency);
@@ -898,8 +919,11 @@ void RenderWidgetHostInputEventRouter::RouteTouchscreenGestureEvent(
}
}
- if (!touchscreen_gesture_target_.target)
+ if (!touchscreen_gesture_target_.target) {
+ root_view->GestureEventAck(*event,
+ INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
return;
+ }
// TODO(mohsen): Add tests to check event location.
event->x += touchscreen_gesture_target_.delta.x();
@@ -936,8 +960,11 @@ void RenderWidgetHostInputEventRouter::RouteTouchpadGestureEvent(
}
}
- if (!touchpad_gesture_target_.target)
+ if (!touchpad_gesture_target_.target) {
+ root_view->GestureEventAck(*event,
+ INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
return;
+ }
// TODO(mohsen): Add tests to check event location.
event->x += touchpad_gesture_target_.delta.x();
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 4da69ae8a14..d319c1a3716 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
@@ -14,8 +14,8 @@
#include "base/containers/hash_tables.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
-#include "cc/surfaces/surface_hittest_delegate.h"
#include "components/viz/common/surfaces/surface_id.h"
+#include "components/viz/service/surfaces/surface_hittest_delegate.h"
#include "content/browser/renderer_host/render_widget_host_view_base_observer.h"
#include "content/common/content_export.h"
#include "ui/gfx/geometry/vector2d.h"
@@ -103,7 +103,7 @@ class CONTENT_EXPORT RenderWidgetHostInputEventRouter
bool ignored_for_hittest;
};
- class HittestDelegate : public cc::SurfaceHittestDelegate {
+ class HittestDelegate : public viz::SurfaceHittestDelegate {
public:
HittestDelegate(const std::unordered_map<viz::SurfaceId,
HittestData,
@@ -185,6 +185,7 @@ class CONTENT_EXPORT RenderWidgetHostInputEventRouter
hittest_data_;
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostInputEventRouter);
+ friend class RenderWidgetHostInputEventRouterTest;
FRIEND_TEST_ALL_PREFIXES(SitePerProcessBrowserTest,
InputEventRouterGestureTargetMapTest);
FRIEND_TEST_ALL_PREFIXES(SitePerProcessBrowserTest,
diff --git a/chromium/content/browser/renderer_host/render_widget_host_input_event_router_unittest.cc b/chromium/content/browser/renderer_host/render_widget_host_input_event_router_unittest.cc
new file mode 100644
index 00000000000..035728454c5
--- /dev/null
+++ b/chromium/content/browser/renderer_host/render_widget_host_input_event_router_unittest.cc
@@ -0,0 +1,282 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/render_widget_host_input_event_router.h"
+
+#include "base/run_loop.h"
+#include "base/test/scoped_task_environment.h"
+#include "content/browser/renderer_host/render_widget_host_impl.h"
+#include "content/public/test/mock_render_process_host.h"
+#include "content/public/test/test_browser_context.h"
+#include "content/test/dummy_render_widget_host_delegate.h"
+#include "content/test/mock_widget_impl.h"
+#include "content/test/test_render_view_host.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+namespace {
+
+// Used as a target for the RenderWidgetHostInputEventRouter. We record what
+// events were forwarded to us in order to verify that the events are being
+// routed correctly.
+class MockRenderWidgetHostView : public TestRenderWidgetHostView {
+ public:
+ MockRenderWidgetHostView(RenderWidgetHost* rwh)
+ : TestRenderWidgetHostView(rwh),
+ last_gesture_seen_(blink::WebInputEvent::kUndefined) {}
+ ~MockRenderWidgetHostView() override {}
+
+ void ProcessGestureEvent(const blink::WebGestureEvent& event,
+ const ui::LatencyInfo&) override {
+ last_gesture_seen_ = event.GetType();
+ }
+
+ void ProcessAckedTouchEvent(const TouchEventWithLatencyInfo& touch,
+ InputEventAckState ack_result) override {
+ unique_id_for_last_touch_ack_ = touch.event.unique_touch_event_id;
+ }
+
+ blink::WebInputEvent::Type last_gesture_seen() { return last_gesture_seen_; }
+ uint32_t last_id_for_touch_ack() { return unique_id_for_last_touch_ack_; }
+
+ void Reset() { last_gesture_seen_ = blink::WebInputEvent::kUndefined; }
+
+ private:
+ blink::WebInputEvent::Type last_gesture_seen_;
+ uint32_t unique_id_for_last_touch_ack_ = 0;
+};
+
+// The RenderWidgetHostInputEventRouter uses the root RWHV for hittesting, so
+// here we stub out the hittesting logic so we can control which RWHV will be
+// the result of a hittest by the RWHIER.
+class MockRootRenderWidgetHostView : public MockRenderWidgetHostView {
+ public:
+ MockRootRenderWidgetHostView(
+ RenderWidgetHost* rwh,
+ std::map<MockRenderWidgetHostView*, viz::FrameSinkId>& frame_sink_id_map)
+ : MockRenderWidgetHostView(rwh), frame_sink_id_map_(frame_sink_id_map) {}
+ ~MockRootRenderWidgetHostView() override {}
+
+ viz::FrameSinkId FrameSinkIdAtPoint(viz::SurfaceHittestDelegate*,
+ const gfx::Point&,
+ gfx::Point*) override {
+ return frame_sink_id_map_[current_hittest_result_];
+ }
+
+ void SetHittestResult(MockRenderWidgetHostView* view) {
+ current_hittest_result_ = view;
+ }
+
+ private:
+ std::map<MockRenderWidgetHostView*, viz::FrameSinkId>& frame_sink_id_map_;
+ MockRenderWidgetHostView* current_hittest_result_;
+};
+
+} // namespace
+
+class RenderWidgetHostInputEventRouterTest : public testing::Test {
+ public:
+ RenderWidgetHostInputEventRouterTest()
+ : scoped_task_environment_(
+ base::test::ScopedTaskEnvironment::MainThreadType::UI) {}
+
+ protected:
+ // testing::Test:
+ void SetUp() override {
+ browser_context_ = base::MakeUnique<TestBrowserContext>();
+ process_host1_ =
+ base::MakeUnique<MockRenderProcessHost>(browser_context_.get());
+ process_host2_ =
+ base::MakeUnique<MockRenderProcessHost>(browser_context_.get());
+ mojom::WidgetPtr widget1;
+ widget_impl1_ =
+ base::MakeUnique<MockWidgetImpl>(mojo::MakeRequest(&widget1));
+ widget_host1_ = base::MakeUnique<RenderWidgetHostImpl>(
+ &delegate_, process_host1_.get(), process_host1_->GetNextRoutingID(),
+ std::move(widget1), false);
+ mojom::WidgetPtr widget2;
+ widget_impl2_ =
+ base::MakeUnique<MockWidgetImpl>(mojo::MakeRequest(&widget2));
+ widget_host2_ = base::MakeUnique<RenderWidgetHostImpl>(
+ &delegate_, process_host2_.get(), process_host2_->GetNextRoutingID(),
+ std::move(widget2), false);
+
+ view_root_ = base::MakeUnique<MockRootRenderWidgetHostView>(
+ widget_host1_.get(), frame_sink_id_map_);
+ view_other_ =
+ base::MakeUnique<MockRenderWidgetHostView>(widget_host2_.get());
+
+ // Set up the RWHIER's FrameSinkId to RWHV map so that we can control the
+ // result of RWHIER's hittesting.
+ frame_sink_id_map_ = {{view_root_.get(), viz::FrameSinkId(1, 1)},
+ {view_other_.get(), viz::FrameSinkId(2, 2)}};
+ rwhier_.AddFrameSinkIdOwner(frame_sink_id_map_[view_root_.get()],
+ view_root_.get());
+ rwhier_.AddFrameSinkIdOwner(frame_sink_id_map_[view_other_.get()],
+ view_other_.get());
+ }
+
+ void TearDown() override { base::RunLoop().RunUntilIdle(); }
+
+ RenderWidgetHostViewBase* touch_target() {
+ return rwhier_.touch_target_.target;
+ }
+ RenderWidgetHostViewBase* touchscreen_gesture_target() {
+ return rwhier_.touchscreen_gesture_target_.target;
+ }
+
+ // Needed by RenderWidgetHostImpl constructor.
+ base::test::ScopedTaskEnvironment scoped_task_environment_;
+
+ DummyRenderWidgetHostDelegate delegate_;
+ std::unique_ptr<BrowserContext> browser_context_;
+ std::unique_ptr<MockRenderProcessHost> process_host1_;
+ std::unique_ptr<MockRenderProcessHost> process_host2_;
+ std::unique_ptr<MockWidgetImpl> widget_impl1_;
+ std::unique_ptr<RenderWidgetHostImpl> widget_host1_;
+ std::unique_ptr<MockWidgetImpl> widget_impl2_;
+ std::unique_ptr<RenderWidgetHostImpl> widget_host2_;
+
+ std::unique_ptr<MockRootRenderWidgetHostView> view_root_;
+ std::unique_ptr<MockRenderWidgetHostView> view_other_;
+
+ std::map<MockRenderWidgetHostView*, viz::FrameSinkId> frame_sink_id_map_;
+
+ RenderWidgetHostInputEventRouter rwhier_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostInputEventRouterTest);
+};
+
+// Make sure that when a touch scroll crosses out of the area for a
+// RenderWidgetHostView, the RenderWidgetHostInputEventRouter continues to
+// route gesture events to the same RWHV until the end of the gesture.
+// See crbug.com/739831
+TEST_F(RenderWidgetHostInputEventRouterTest,
+ DoNotChangeTargetViewDuringTouchScrollGesture) {
+ // Simulate the touch and gesture events produced from scrolling on a
+ // touchscreen.
+
+ // We start the touch in the area for |view_other_|.
+ view_root_->SetHittestResult(view_other_.get());
+
+ blink::WebTouchEvent touch_event(blink::WebInputEvent::kTouchStart,
+ blink::WebInputEvent::kNoModifiers,
+ blink::WebInputEvent::kTimeStampForTesting);
+ touch_event.touches_length = 1;
+ touch_event.touches[0].state = blink::WebTouchPoint::kStatePressed;
+ touch_event.unique_touch_event_id = 1;
+
+ rwhier_.RouteTouchEvent(view_root_.get(), &touch_event,
+ ui::LatencyInfo(ui::SourceEventType::TOUCH));
+ EXPECT_EQ(view_other_.get(), touch_target());
+
+ blink::WebGestureEvent gesture_event(
+ blink::WebInputEvent::kGestureTapDown, blink::WebInputEvent::kNoModifiers,
+ blink::WebInputEvent::kTimeStampForTesting);
+ gesture_event.source_device = blink::kWebGestureDeviceTouchscreen;
+ gesture_event.unique_touch_event_id = touch_event.unique_touch_event_id;
+
+ rwhier_.RouteGestureEvent(view_root_.get(), &gesture_event,
+ ui::LatencyInfo(ui::SourceEventType::TOUCH));
+ EXPECT_EQ(view_other_.get(), touchscreen_gesture_target());
+ EXPECT_EQ(blink::WebInputEvent::kGestureTapDown,
+ view_other_->last_gesture_seen());
+ EXPECT_NE(blink::WebInputEvent::kGestureTapDown,
+ view_root_->last_gesture_seen());
+
+ touch_event.SetType(blink::WebInputEvent::kTouchMove);
+ touch_event.touches[0].state = blink::WebTouchPoint::kStateMoved;
+ touch_event.unique_touch_event_id += 1;
+ rwhier_.RouteTouchEvent(view_root_.get(), &touch_event,
+ ui::LatencyInfo(ui::SourceEventType::TOUCH));
+
+ gesture_event.SetType(blink::WebInputEvent::kGestureTapCancel);
+ gesture_event.unique_touch_event_id = touch_event.unique_touch_event_id;
+ rwhier_.RouteGestureEvent(view_root_.get(), &gesture_event,
+ ui::LatencyInfo(ui::SourceEventType::TOUCH));
+
+ gesture_event.SetType(blink::WebInputEvent::kGestureScrollBegin);
+ rwhier_.RouteGestureEvent(view_root_.get(), &gesture_event,
+ ui::LatencyInfo(ui::SourceEventType::TOUCH));
+
+ gesture_event.SetType(blink::WebInputEvent::kGestureScrollUpdate);
+ rwhier_.RouteGestureEvent(view_root_.get(), &gesture_event,
+ ui::LatencyInfo(ui::SourceEventType::TOUCH));
+
+ touch_event.unique_touch_event_id += 1;
+ rwhier_.RouteTouchEvent(view_root_.get(), &touch_event,
+ ui::LatencyInfo(ui::SourceEventType::TOUCH));
+ gesture_event.unique_touch_event_id = touch_event.unique_touch_event_id;
+ rwhier_.RouteGestureEvent(view_root_.get(), &gesture_event,
+ ui::LatencyInfo(ui::SourceEventType::TOUCH));
+
+ // Now the touch moves out of |view_other_| and into |view_root_|, but
+ // |view_other_| should continue to be the target for gesture events.
+ view_root_->SetHittestResult(view_root_.get());
+ view_root_->Reset();
+ view_other_->Reset();
+
+ touch_event.unique_touch_event_id += 1;
+ rwhier_.RouteTouchEvent(view_root_.get(), &touch_event,
+ ui::LatencyInfo(ui::SourceEventType::TOUCH));
+ gesture_event.unique_touch_event_id = touch_event.unique_touch_event_id;
+ rwhier_.RouteGestureEvent(view_root_.get(), &gesture_event,
+ ui::LatencyInfo(ui::SourceEventType::TOUCH));
+
+ EXPECT_EQ(view_other_.get(), touch_target());
+ EXPECT_EQ(view_other_.get(), touchscreen_gesture_target());
+ EXPECT_EQ(blink::WebInputEvent::kGestureScrollUpdate,
+ view_other_->last_gesture_seen());
+ EXPECT_NE(blink::WebInputEvent::kGestureScrollUpdate,
+ view_root_->last_gesture_seen());
+
+ touch_event.SetType(blink::WebInputEvent::kTouchEnd);
+ touch_event.touches[0].state = blink::WebTouchPoint::kStateReleased;
+ touch_event.unique_touch_event_id += 1;
+ rwhier_.RouteTouchEvent(view_root_.get(), &touch_event,
+ ui::LatencyInfo(ui::SourceEventType::TOUCH));
+
+ gesture_event.SetType(blink::WebInputEvent::kGestureScrollEnd);
+ gesture_event.unique_touch_event_id = touch_event.unique_touch_event_id;
+ rwhier_.RouteGestureEvent(view_root_.get(), &gesture_event,
+ ui::LatencyInfo(ui::SourceEventType::TOUCH));
+
+ EXPECT_EQ(blink::WebInputEvent::kGestureScrollEnd,
+ view_other_->last_gesture_seen());
+ EXPECT_NE(blink::WebInputEvent::kGestureScrollEnd,
+ view_root_->last_gesture_seen());
+}
+
+// Ensure that when RenderWidgetHostInputEventRouter receives an unexpected
+// touch event, it calls the root view's method to Ack the event before
+// dropping it.
+TEST_F(RenderWidgetHostInputEventRouterTest, EnsureDroppedTouchEventsAreAcked) {
+ // Send a touch move without a touch start.
+ blink::WebTouchEvent touch_move_event(
+ blink::WebInputEvent::kTouchMove, blink::WebInputEvent::kNoModifiers,
+ blink::WebInputEvent::kTimeStampForTesting);
+ touch_move_event.touches_length = 1;
+ touch_move_event.touches[0].state = blink::WebTouchPoint::kStatePressed;
+ touch_move_event.unique_touch_event_id = 1;
+
+ rwhier_.RouteTouchEvent(view_root_.get(), &touch_move_event,
+ ui::LatencyInfo(ui::SourceEventType::TOUCH));
+ EXPECT_EQ(view_root_->last_id_for_touch_ack(), 1lu);
+
+ // Send a touch cancel without a touch start.
+ blink::WebTouchEvent touch_cancel_event(
+ blink::WebInputEvent::kTouchCancel, blink::WebInputEvent::kNoModifiers,
+ blink::WebInputEvent::kTimeStampForTesting);
+ touch_cancel_event.touches_length = 1;
+ touch_cancel_event.touches[0].state = blink::WebTouchPoint::kStateCancelled;
+ touch_cancel_event.unique_touch_event_id = 2;
+
+ rwhier_.RouteTouchEvent(view_root_.get(), &touch_cancel_event,
+ ui::LatencyInfo(ui::SourceEventType::TOUCH));
+ EXPECT_EQ(view_root_->last_id_for_touch_ack(), 2lu);
+}
+
+} // namespace content
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 45d9cb20d4c..077cf8e8990 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_unittest.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_unittest.cc
@@ -21,6 +21,8 @@
#include "build/build_config.h"
#include "content/browser/gpu/compositor_util.h"
#include "content/browser/renderer_host/input/legacy_input_router_impl.h"
+#include "content/browser/renderer_host/input/mock_widget_input_handler.h"
+#include "content/browser/renderer_host/input/touch_emulator.h"
#include "content/browser/renderer_host/render_view_host_delegate_view.h"
#include "content/browser/renderer_host/render_widget_host_delegate.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
@@ -36,12 +38,14 @@
#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/test/fake_renderer_compositor_frame_sink.h"
+#include "content/test/mock_widget_impl.h"
#include "content/test/test_render_view_host.h"
#include "mojo/public/cpp/bindings/interface_request.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/display/screen.h"
#include "ui/events/base_event_utils.h"
#include "ui/events/blink/web_input_event_traits.h"
+#include "ui/events/gesture_detection/gesture_provider_config_helper.h"
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/gfx/canvas.h"
@@ -124,15 +128,12 @@ class MockInputRouter : public InputRouter {
client_->FilterInputEvent(touch_event.event, touch_event.latency) ==
INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
}
- const NativeWebKeyboardEvent* GetLastKeyboardEvent() const override {
- NOTREACHED();
- return NULL;
- }
void NotifySiteIsMobileOptimized(bool is_mobile_optimized) override {}
bool HasPendingEvents() const override { return false; }
void SetDeviceScaleFactor(float device_scale_factor) override {}
void SetFrameTreeNodeId(int frameTreeNodeId) override {}
cc::TouchAction AllowedTouchAction() override { return cc::kTouchActionAuto; }
+ void SetForceEnableZoom(bool enabled) override {}
// IPC::Listener
bool OnMessageReceived(const IPC::Message& message) override {
@@ -157,17 +158,6 @@ class MockInputRouter : public InputRouter {
class MockRenderWidgetHost : public RenderWidgetHostImpl {
public:
- MockRenderWidgetHost(RenderWidgetHostDelegate* delegate,
- RenderProcessHost* process,
- int routing_id)
- : RenderWidgetHostImpl(
- delegate,
- process,
- routing_id,
- false),
- new_content_rendering_timeout_fired_(false) {
- acked_touch_event_type_ = blink::WebInputEvent::kUndefined;
- }
// Allow poking at a few private members.
using RenderWidgetHostImpl::GetResizeParams;
@@ -196,11 +186,17 @@ class MockRenderWidgetHost : public RenderWidgetHostImpl {
}
void DisableGestureDebounce() {
- input_router_.reset(new LegacyInputRouterImpl(
- process_, this, this, routing_id_, InputRouter::Config()));
- legacy_widget_input_handler_ =
- base::MakeUnique<LegacyIPCWidgetInputHandler>(
- static_cast<LegacyInputRouterImpl*>(input_router_.get()));
+ if (base::FeatureList::IsEnabled(features::kMojoInputMessages)) {
+ input_router_.reset(
+ new InputRouterImpl(this, this, InputRouter::Config()));
+ legacy_widget_input_handler_ = nullptr;
+ } else {
+ input_router_.reset(new LegacyInputRouterImpl(
+ process_, this, this, routing_id_, InputRouter::Config()));
+ legacy_widget_input_handler_ =
+ base::MakeUnique<LegacyIPCWidgetInputHandler>(
+ static_cast<LegacyInputRouterImpl*>(input_router_.get()));
+ }
}
WebInputEvent::Type acked_touch_event_type() const {
@@ -220,6 +216,26 @@ class MockRenderWidgetHost : public RenderWidgetHostImpl {
return processed_frame_messages_count_;
}
+ static MockRenderWidgetHost* Create(RenderWidgetHostDelegate* delegate,
+ RenderProcessHost* process,
+ int32_t routing_id) {
+ mojom::WidgetPtr widget;
+ std::unique_ptr<MockWidgetImpl> widget_impl =
+ base::MakeUnique<MockWidgetImpl>(mojo::MakeRequest(&widget));
+
+ return new MockRenderWidgetHost(delegate, process, routing_id,
+ std::move(widget_impl), std::move(widget));
+ }
+
+ mojom::WidgetInputHandler* GetWidgetInputHandler() override {
+ if (base::FeatureList::IsEnabled(features::kMojoInputMessages)) {
+ return &mock_widget_input_handler_;
+ }
+ return RenderWidgetHostImpl::GetWidgetInputHandler();
+ }
+
+ MockWidgetInputHandler mock_widget_input_handler_;
+
protected:
void NotifyNewContentRenderingTimeoutForTesting() override {
new_content_rendering_timeout_fired_ = true;
@@ -229,10 +245,27 @@ class MockRenderWidgetHost : public RenderWidgetHostImpl {
WebInputEvent::Type acked_touch_event_type_;
private:
+ MockRenderWidgetHost(RenderWidgetHostDelegate* delegate,
+ RenderProcessHost* process,
+ int routing_id,
+ std::unique_ptr<MockWidgetImpl> widget_impl,
+ mojom::WidgetPtr widget)
+ : RenderWidgetHostImpl(delegate,
+ process,
+ routing_id,
+ std::move(widget),
+ false),
+ new_content_rendering_timeout_fired_(false),
+ widget_impl_(std::move(widget_impl)) {
+ acked_touch_event_type_ = blink::WebInputEvent::kUndefined;
+ }
+
void ProcessSwapMessages(std::vector<IPC::Message> messages) override {
processed_frame_messages_count_++;
}
uint32_t processed_frame_messages_count_ = 0;
+ std::unique_ptr<MockWidgetImpl> widget_impl_;
+
DISALLOW_COPY_AND_ASSIGN(MockRenderWidgetHost);
};
@@ -241,13 +274,13 @@ namespace {
cc::CompositorFrame MakeCompositorFrame(float scale_factor, gfx::Size size) {
cc::CompositorFrame frame;
frame.metadata.device_scale_factor = scale_factor;
- frame.metadata.begin_frame_ack = cc::BeginFrameAck(0, 1, true);
+ frame.metadata.begin_frame_ack = viz::BeginFrameAck(0, 1, true);
std::unique_ptr<cc::RenderPass> pass = cc::RenderPass::Create();
pass->SetNew(1, gfx::Rect(size), gfx::Rect(), gfx::Transform());
frame.render_pass_list.push_back(std::move(pass));
if (!size.IsEmpty()) {
- cc::TransferableResource resource;
+ viz::TransferableResource resource;
resource.id = 1;
frame.resource_list.push_back(std::move(resource));
}
@@ -337,19 +370,6 @@ class TestView : public TestRenderWidgetHostView {
return mock_physical_backing_size_;
return TestRenderWidgetHostView::GetPhysicalBackingSize();
}
-#if defined(USE_AURA)
- ~TestView() override {
- // Simulate the mouse exit event dispatched when an aura window is
- // destroyed. (MakeWebMouseEventFromAuraEvent translates ET_MOUSE_EXITED
- // into WebInputEvent::MouseMove.)
- WebMouseEvent event =
- SyntheticWebMouseEventBuilder::Build(WebInputEvent::kMouseMove);
- event.SetTimeStampSeconds(
- ui::EventTimeStampToSeconds(ui::EventTimeForNow()));
- rwh_->input_router()->SendMouseEvent(
- MouseEventWithLatencyInfo(event, ui::LatencyInfo()));
- }
-#endif
protected:
WebMouseWheelEvent unhandled_wheel_event_;
@@ -519,11 +539,14 @@ enum WheelScrollingMode {
kAsyncWheelEvents,
};
+enum class UseMojoInputMessages { kEnabled, kDisabled };
+
// RenderWidgetHostTest --------------------------------------------------------
class RenderWidgetHostTest : public testing::Test {
public:
RenderWidgetHostTest(
+ UseMojoInputMessages input_messages_mode = UseMojoInputMessages::kEnabled,
WheelScrollingMode wheel_scrolling_mode = kWheelScrollLatching)
: process_(NULL),
handle_key_press_event_(false),
@@ -531,26 +554,35 @@ class RenderWidgetHostTest : public testing::Test {
simulated_event_time_delta_seconds_(0),
wheel_scroll_latching_enabled_(wheel_scrolling_mode !=
kWheelScrollingModeNone) {
+ std::vector<base::StringPiece> features;
+ std::vector<base::StringPiece> disabled_features;
+ if (input_messages_mode == UseMojoInputMessages::kEnabled) {
+ features.push_back(features::kMojoInputMessages.name);
+ } else {
+ disabled_features.push_back(features::kMojoInputMessages.name);
+ }
+
switch (wheel_scrolling_mode) {
case kWheelScrollingModeNone:
- feature_list_.InitWithFeatures(
- {features::kRafAlignedTouchInputEvents},
- {features::kTouchpadAndWheelScrollLatching,
- features::kAsyncWheelEvents});
+ features.push_back(features::kRafAlignedTouchInputEvents.name);
+ disabled_features.push_back(
+ features::kTouchpadAndWheelScrollLatching.name);
+ disabled_features.push_back(features::kAsyncWheelEvents.name);
break;
case kWheelScrollLatching:
- feature_list_.InitWithFeatures(
- {features::kRafAlignedTouchInputEvents,
- features::kTouchpadAndWheelScrollLatching},
- {features::kAsyncWheelEvents});
+ features.push_back(features::kRafAlignedTouchInputEvents.name);
+ features.push_back(features::kTouchpadAndWheelScrollLatching.name);
+ disabled_features.push_back(features::kAsyncWheelEvents.name);
break;
case kAsyncWheelEvents:
- feature_list_.InitWithFeatures(
- {features::kRafAlignedTouchInputEvents,
- features::kTouchpadAndWheelScrollLatching,
- features::kAsyncWheelEvents},
- {});
+ features.push_back(features::kRafAlignedTouchInputEvents.name);
+ features.push_back(features::kTouchpadAndWheelScrollLatching.name);
+ features.push_back(features::kAsyncWheelEvents.name);
+ break;
}
+ feature_list_.InitFromCommandLine(base::JoinString(features, ","),
+ base::JoinString(disabled_features, ","));
+
last_simulated_event_time_seconds_ =
ui::EventTimeStampToSeconds(ui::EventTimeForNow());
}
@@ -584,8 +616,8 @@ class RenderWidgetHostTest : public testing::Test {
screen_.reset(aura::TestScreen::Create(gfx::Size()));
display::Screen::SetScreenInstance(screen_.get());
#endif
- host_.reset(new MockRenderWidgetHost(delegate_.get(), process_,
- process_->GetNextRoutingID()));
+ host_.reset(MockRenderWidgetHost::Create(delegate_.get(), process_,
+ process_->GetNextRoutingID()));
view_.reset(new TestView(host_.get()));
ConfigureView(view_.get());
host_->SetView(view_.get());
@@ -593,10 +625,10 @@ class RenderWidgetHostTest : public testing::Test {
host_->Init();
host_->DisableGestureDebounce();
- cc::mojom::CompositorFrameSinkPtr sink;
- cc::mojom::CompositorFrameSinkRequest sink_request =
+ viz::mojom::CompositorFrameSinkPtr sink;
+ viz::mojom::CompositorFrameSinkRequest sink_request =
mojo::MakeRequest(&sink);
- cc::mojom::CompositorFrameSinkClientRequest client_request =
+ viz::mojom::CompositorFrameSinkClientRequest client_request =
mojo::MakeRequest(&renderer_compositor_frame_sink_ptr_);
renderer_compositor_frame_sink_ =
base::MakeUnique<FakeRendererCompositorFrameSink>(
@@ -797,8 +829,11 @@ class RenderWidgetHostTest : public testing::Test {
}
void UnhandledWheelEvent();
+ void UnhandledWheelEventMojoInputDisabled();
void HandleWheelEvent();
+ void HandleWheelEventMojoInputDisabled();
void InputEventRWHLatencyComponent();
+ void InputEventRWHLatencyComponentMojoInputDisabled();
std::unique_ptr<TestBrowserContext> browser_context_;
RenderWidgetHostProcess* process_; // Deleted automatically by the widget.
@@ -820,23 +855,47 @@ class RenderWidgetHostTest : public testing::Test {
TestBrowserThreadBundle thread_bundle_;
base::test::ScopedFeatureList feature_list_;
- cc::mojom::CompositorFrameSinkClientPtr renderer_compositor_frame_sink_ptr_;
+ viz::mojom::CompositorFrameSinkClientPtr renderer_compositor_frame_sink_ptr_;
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostTest);
};
+class RenderWidgetHostMojoInputDisabledTest : public RenderWidgetHostTest {
+ public:
+ RenderWidgetHostMojoInputDisabledTest()
+ : RenderWidgetHostTest(UseMojoInputMessages::kDisabled) {}
+};
+
class RenderWidgetHostWheelScrollLatchingDisabledTest
: public RenderWidgetHostTest {
public:
RenderWidgetHostWheelScrollLatchingDisabledTest()
- : RenderWidgetHostTest(kWheelScrollingModeNone) {}
+ : RenderWidgetHostTest(UseMojoInputMessages::kEnabled,
+ kWheelScrollingModeNone) {}
};
class RenderWidgetHostAsyncWheelEventsEnabledTest
: public RenderWidgetHostTest {
public:
RenderWidgetHostAsyncWheelEventsEnabledTest()
- : RenderWidgetHostTest(kAsyncWheelEvents) {}
+ : RenderWidgetHostTest(UseMojoInputMessages::kEnabled,
+ kAsyncWheelEvents) {}
+};
+
+class RenderWidgetHostWheelScrollLatchingMojoInputDisabledTest
+ : public RenderWidgetHostTest {
+ public:
+ RenderWidgetHostWheelScrollLatchingMojoInputDisabledTest()
+ : RenderWidgetHostTest(UseMojoInputMessages::kDisabled,
+ kWheelScrollingModeNone) {}
+};
+
+class RenderWidgetHostAsyncWheelEventsEnabledMojoInputDisabledTest
+ : public RenderWidgetHostTest {
+ public:
+ RenderWidgetHostAsyncWheelEventsEnabledMojoInputDisabledTest()
+ : RenderWidgetHostTest(UseMojoInputMessages::kDisabled,
+ kAsyncWheelEvents) {}
};
#if GTEST_HAS_PARAM_TEST
@@ -848,6 +907,13 @@ class RenderWidgetHostWithSourceTest
public testing::WithParamInterface<WebGestureDevice> {};
#endif // GTEST_HAS_PARAM_TEST
+void CallCallback(mojom::WidgetInputHandler::DispatchEventCallback callback,
+ InputEventAckState state) {
+ std::move(callback).Run(InputEventAckSource::COMPOSITOR_THREAD,
+ ui::LatencyInfo(), state, base::nullopt,
+ base::nullopt);
+}
+
} // namespace
// -----------------------------------------------------------------------------
@@ -1099,7 +1165,8 @@ TEST_F(RenderWidgetHostTest, HiddenPaint) {
EXPECT_TRUE(std::get<0>(needs_repaint));
}
-TEST_F(RenderWidgetHostTest, IgnoreKeyEventsHandledByRenderer) {
+TEST_F(RenderWidgetHostMojoInputDisabledTest,
+ IgnoreKeyEventsHandledByRenderer) {
// Simulate a keyboard event.
SimulateKeyboardEvent(WebInputEvent::kRawKeyDown);
@@ -1113,7 +1180,22 @@ TEST_F(RenderWidgetHostTest, IgnoreKeyEventsHandledByRenderer) {
EXPECT_FALSE(delegate_->unhandled_keyboard_event_called());
}
-TEST_F(RenderWidgetHostTest, SendEditCommandsBeforeKeyEvent) {
+TEST_F(RenderWidgetHostTest, IgnoreKeyEventsHandledByRenderer) {
+ // Simulate a keyboard event.
+ SimulateKeyboardEvent(WebInputEvent::kRawKeyDown);
+
+ // Make sure we sent the input event to the renderer.
+ std::vector<MockWidgetInputHandler::DispatchedEvent> dispatched_events =
+ host_->mock_widget_input_handler_.GetAndResetDispatchedEvents();
+ EXPECT_EQ(1u, dispatched_events.size());
+
+ // Send the simulated response from the renderer back.
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_FALSE(delegate_->unhandled_keyboard_event_called());
+}
+
+TEST_F(RenderWidgetHostMojoInputDisabledTest, SendEditCommandsBeforeKeyEvent) {
// Clear any messages unrelated to this test.
process_->sink().ClearMessages();
EXPECT_EQ(0U, process_->sink().message_count());
@@ -1133,7 +1215,25 @@ TEST_F(RenderWidgetHostTest, SendEditCommandsBeforeKeyEvent) {
SendInputEventACK(WebInputEvent::kRawKeyDown, INPUT_EVENT_ACK_STATE_CONSUMED);
}
-TEST_F(RenderWidgetHostTest, PreHandleRawKeyDownEvent) {
+TEST_F(RenderWidgetHostTest, SendEditCommandsBeforeKeyEvent) {
+ // Simulate a keyboard event.
+ SimulateKeyboardEventWithCommands(WebInputEvent::kRawKeyDown);
+
+ // Make sure we sent commands and key event to the renderer.
+ std::vector<content::EditCommand> edit_commands =
+ host_->mock_widget_input_handler_.GetAndResetEditCommands();
+ EXPECT_EQ(1u, edit_commands.size());
+
+ std::vector<MockWidgetInputHandler::DispatchedEvent> dispatched_events =
+ host_->mock_widget_input_handler_.GetAndResetDispatchedEvents();
+ EXPECT_EQ(1u, dispatched_events.size());
+
+ // Send the simulated response from the renderer back.
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+}
+
+TEST_F(RenderWidgetHostMojoInputDisabledTest, PreHandleRawKeyDownEvent) {
// Simulate the situation that the browser handled the key down event during
// pre-handle phrase.
delegate_->set_prehandle_keyboard_event(true);
@@ -1180,7 +1280,60 @@ TEST_F(RenderWidgetHostTest, PreHandleRawKeyDownEvent) {
delegate_->unhandled_keyboard_event_type());
}
-TEST_F(RenderWidgetHostTest, RawKeyDownShortcutEvent) {
+TEST_F(RenderWidgetHostTest, PreHandleRawKeyDownEvent) {
+ // Simulate the situation that the browser handled the key down event during
+ // pre-handle phrase.
+ delegate_->set_prehandle_keyboard_event(true);
+
+ // Simulate a keyboard event.
+ SimulateKeyboardEventWithCommands(WebInputEvent::kRawKeyDown);
+
+ EXPECT_TRUE(delegate_->prehandle_keyboard_event_called());
+ EXPECT_EQ(WebInputEvent::kRawKeyDown,
+ delegate_->prehandle_keyboard_event_type());
+
+ // Make sure the commands and key event are not sent to the renderer.
+ std::vector<MockWidgetInputHandler::DispatchedEvent> dispatched_events =
+ host_->mock_widget_input_handler_.GetAndResetDispatchedEvents();
+ EXPECT_EQ(0u, dispatched_events.size());
+
+ // The browser won't pre-handle a Char event.
+ delegate_->set_prehandle_keyboard_event(false);
+
+ // Forward the Char event.
+ SimulateKeyboardEvent(WebInputEvent::kChar);
+
+ // Make sure the Char event is suppressed.
+ dispatched_events =
+ host_->mock_widget_input_handler_.GetAndResetDispatchedEvents();
+ EXPECT_EQ(0u, dispatched_events.size());
+
+ // Forward the KeyUp event.
+ SimulateKeyboardEvent(WebInputEvent::kKeyUp);
+
+ // Make sure the KeyUp event is suppressed.
+ dispatched_events =
+ host_->mock_widget_input_handler_.GetAndResetDispatchedEvents();
+ EXPECT_EQ(0u, dispatched_events.size());
+
+ // Simulate a new RawKeyDown event.
+ SimulateKeyboardEvent(WebInputEvent::kRawKeyDown);
+ dispatched_events =
+ host_->mock_widget_input_handler_.GetAndResetDispatchedEvents();
+ EXPECT_EQ(1u, dispatched_events.size());
+ EXPECT_EQ(WebInputEvent::kRawKeyDown,
+ dispatched_events.at(0).event_->web_event->GetType());
+
+ // Send the simulated response from the renderer back.
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+
+ EXPECT_TRUE(delegate_->unhandled_keyboard_event_called());
+ EXPECT_EQ(WebInputEvent::kRawKeyDown,
+ delegate_->unhandled_keyboard_event_type());
+}
+
+TEST_F(RenderWidgetHostMojoInputDisabledTest, RawKeyDownShortcutEvent) {
// Simulate the situation that the browser marks the key down as a keyboard
// shortcut, but doesn't consume it in the pre-handle phase.
delegate_->set_prehandle_keyboard_event_is_shortcut(true);
@@ -1233,7 +1386,67 @@ TEST_F(RenderWidgetHostTest, RawKeyDownShortcutEvent) {
EXPECT_EQ(WebInputEvent::kKeyUp, delegate_->unhandled_keyboard_event_type());
}
-void RenderWidgetHostTest::UnhandledWheelEvent() {
+TEST_F(RenderWidgetHostTest, RawKeyDownShortcutEvent) {
+ // Simulate the situation that the browser marks the key down as a keyboard
+ // shortcut, but doesn't consume it in the pre-handle phase.
+ delegate_->set_prehandle_keyboard_event_is_shortcut(true);
+
+ // Simulate a keyboard event.
+ SimulateKeyboardEvent(WebInputEvent::kRawKeyDown);
+
+ EXPECT_TRUE(delegate_->prehandle_keyboard_event_called());
+ EXPECT_EQ(WebInputEvent::kRawKeyDown,
+ delegate_->prehandle_keyboard_event_type());
+
+ // Make sure the RawKeyDown event is sent to the renderer.
+ std::vector<MockWidgetInputHandler::DispatchedEvent> dispatched_events =
+ host_->mock_widget_input_handler_.GetAndResetDispatchedEvents();
+ EXPECT_EQ(1u, dispatched_events.size());
+ EXPECT_EQ(WebInputEvent::kRawKeyDown,
+ dispatched_events.at(0).event_->web_event->GetType());
+
+ // Send the simulated response from the renderer back.
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(WebInputEvent::kRawKeyDown,
+ delegate_->unhandled_keyboard_event_type());
+
+ // The browser won't pre-handle a Char event.
+ delegate_->set_prehandle_keyboard_event_is_shortcut(false);
+
+ // Forward the Char event.
+ SimulateKeyboardEvent(WebInputEvent::kChar);
+
+ // The Char event is not suppressed; the renderer will ignore it
+ // if the preceding RawKeyDown shortcut goes unhandled.
+ dispatched_events =
+ host_->mock_widget_input_handler_.GetAndResetDispatchedEvents();
+ EXPECT_EQ(1u, dispatched_events.size());
+ EXPECT_EQ(WebInputEvent::kChar,
+ dispatched_events.at(0).event_->web_event->GetType());
+
+ // Send the simulated response from the renderer back.
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(WebInputEvent::kChar, delegate_->unhandled_keyboard_event_type());
+
+ // Forward the KeyUp event.
+ SimulateKeyboardEvent(WebInputEvent::kKeyUp);
+
+ // Make sure only KeyUp was sent to the renderer.
+ dispatched_events =
+ host_->mock_widget_input_handler_.GetAndResetDispatchedEvents();
+ EXPECT_EQ(1u, dispatched_events.size());
+ EXPECT_EQ(WebInputEvent::kKeyUp,
+ dispatched_events.at(0).event_->web_event->GetType());
+
+ // Send the simulated response from the renderer back.
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(WebInputEvent::kKeyUp, delegate_->unhandled_keyboard_event_type());
+}
+
+void RenderWidgetHostTest::UnhandledWheelEventMojoInputDisabled() {
SimulateWheelEventPossiblyIncludingPhase(-5, 0, 0, true,
WebMouseWheelEvent::kPhaseBegan);
@@ -1249,6 +1462,36 @@ void RenderWidgetHostTest::UnhandledWheelEvent() {
EXPECT_EQ(1, view_->unhandled_wheel_event_count());
EXPECT_EQ(-5, view_->unhandled_wheel_event().delta_x);
}
+TEST_F(RenderWidgetHostMojoInputDisabledTest, UnhandledWheelEvent) {
+ UnhandledWheelEventMojoInputDisabled();
+}
+TEST_F(RenderWidgetHostWheelScrollLatchingMojoInputDisabledTest,
+ UnhandledWheelEvent) {
+ UnhandledWheelEventMojoInputDisabled();
+}
+TEST_F(RenderWidgetHostAsyncWheelEventsEnabledMojoInputDisabledTest,
+ UnhandledWheelEvent) {
+ UnhandledWheelEventMojoInputDisabled();
+}
+
+void RenderWidgetHostTest::UnhandledWheelEvent() {
+ SimulateWheelEventPossiblyIncludingPhase(-5, 0, 0, true,
+ WebMouseWheelEvent::kPhaseBegan);
+
+ std::vector<MockWidgetInputHandler::DispatchedEvent> dispatched_events =
+ host_->mock_widget_input_handler_.GetAndResetDispatchedEvents();
+ EXPECT_EQ(1u, dispatched_events.size());
+ EXPECT_EQ(WebInputEvent::kMouseWheel,
+ dispatched_events.at(0).event_->web_event->GetType());
+
+ // Send the simulated response from the renderer back.
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+
+ EXPECT_TRUE(delegate_->handle_wheel_event_called());
+ EXPECT_EQ(1, view_->unhandled_wheel_event_count());
+ EXPECT_EQ(-5, view_->unhandled_wheel_event().delta_x);
+}
TEST_F(RenderWidgetHostTest, UnhandledWheelEvent) {
UnhandledWheelEvent();
}
@@ -1259,7 +1502,7 @@ TEST_F(RenderWidgetHostAsyncWheelEventsEnabledTest, UnhandledWheelEvent) {
UnhandledWheelEvent();
}
-void RenderWidgetHostTest::HandleWheelEvent() {
+void RenderWidgetHostTest::HandleWheelEventMojoInputDisabled() {
// Indicate that we're going to handle this wheel event
delegate_->set_handle_wheel_event(true);
@@ -1281,6 +1524,41 @@ void RenderWidgetHostTest::HandleWheelEvent() {
// and that it suppressed the unhandled wheel event handler.
EXPECT_EQ(0, view_->unhandled_wheel_event_count());
}
+TEST_F(RenderWidgetHostMojoInputDisabledTest, HandleWheelEvent) {
+ HandleWheelEventMojoInputDisabled();
+}
+TEST_F(RenderWidgetHostWheelScrollLatchingMojoInputDisabledTest,
+ HandleWheelEvent) {
+ HandleWheelEventMojoInputDisabled();
+}
+TEST_F(RenderWidgetHostAsyncWheelEventsEnabledMojoInputDisabledTest,
+ HandleWheelEvent) {
+ HandleWheelEventMojoInputDisabled();
+}
+
+void RenderWidgetHostTest::HandleWheelEvent() {
+ // Indicate that we're going to handle this wheel event
+ delegate_->set_handle_wheel_event(true);
+
+ SimulateWheelEventPossiblyIncludingPhase(-5, 0, 0, true,
+ WebMouseWheelEvent::kPhaseBegan);
+
+ std::vector<MockWidgetInputHandler::DispatchedEvent> dispatched_events =
+ host_->mock_widget_input_handler_.GetAndResetDispatchedEvents();
+ EXPECT_EQ(1u, dispatched_events.size());
+ EXPECT_EQ(WebInputEvent::kMouseWheel,
+ dispatched_events.at(0).event_->web_event->GetType());
+
+ // Send the simulated response from the renderer back.
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+
+ // ensure the wheel event handler was invoked
+ EXPECT_TRUE(delegate_->handle_wheel_event_called());
+
+ // and that it suppressed the unhandled wheel event handler.
+ EXPECT_EQ(0, view_->unhandled_wheel_event_count());
+}
TEST_F(RenderWidgetHostTest, HandleWheelEvent) {
HandleWheelEvent();
}
@@ -1291,7 +1569,7 @@ TEST_F(RenderWidgetHostAsyncWheelEventsEnabledTest, HandleWheelEvent) {
HandleWheelEvent();
}
-TEST_F(RenderWidgetHostTest, UnhandledGestureEvent) {
+TEST_F(RenderWidgetHostMojoInputDisabledTest, UnhandledGestureEvent) {
SimulateGestureEvent(WebInputEvent::kGestureTwoFingerTap,
blink::kWebGestureDeviceTouchscreen);
@@ -1307,6 +1585,24 @@ TEST_F(RenderWidgetHostTest, UnhandledGestureEvent) {
EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, view_->ack_result());
}
+TEST_F(RenderWidgetHostTest, UnhandledGestureEvent) {
+ SimulateGestureEvent(WebInputEvent::kGestureTwoFingerTap,
+ blink::kWebGestureDeviceTouchscreen);
+
+ std::vector<MockWidgetInputHandler::DispatchedEvent> dispatched_events =
+ host_->mock_widget_input_handler_.GetAndResetDispatchedEvents();
+ EXPECT_EQ(1u, dispatched_events.size());
+ EXPECT_EQ(WebInputEvent::kGestureTwoFingerTap,
+ dispatched_events.at(0).event_->web_event->GetType());
+
+ // Send the simulated response from the renderer back.
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+
+ EXPECT_EQ(WebInputEvent::kGestureTwoFingerTap, view_->gesture_event_type());
+ EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, view_->ack_result());
+}
+
// Test that the hang monitor timer expires properly if a new timer is started
// while one is in progress (see crbug.com/11007).
TEST_F(RenderWidgetHostTest, DontPostponeHangMonitorTimeout) {
@@ -1439,7 +1735,7 @@ TEST_F(RenderWidgetHostTest, NewContentRenderingTimeout) {
host_->StartNewContentRenderingTimeout(5);
cc::CompositorFrame frame = MakeCompositorFrame(1.f, frame_size);
frame.metadata.content_source_id = 5;
- host_->SubmitCompositorFrame(local_surface_id, std::move(frame));
+ host_->SubmitCompositorFrame(local_surface_id, std::move(frame), nullptr, 0);
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, base::MessageLoop::QuitWhenIdleClosure(),
TimeDelta::FromMicroseconds(20));
@@ -1453,7 +1749,7 @@ TEST_F(RenderWidgetHostTest, NewContentRenderingTimeout) {
host_->StartNewContentRenderingTimeout(10);
frame = MakeCompositorFrame(1.f, frame_size);
frame.metadata.content_source_id = 9;
- host_->SubmitCompositorFrame(local_surface_id, std::move(frame));
+ host_->SubmitCompositorFrame(local_surface_id, std::move(frame), nullptr, 0);
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, base::MessageLoop::QuitWhenIdleClosure(),
TimeDelta::FromMicroseconds(20));
@@ -1466,7 +1762,7 @@ TEST_F(RenderWidgetHostTest, NewContentRenderingTimeout) {
// attempt to start the timer. The timer shouldn't fire.
frame = MakeCompositorFrame(1.f, frame_size);
frame.metadata.content_source_id = 7;
- host_->SubmitCompositorFrame(local_surface_id, std::move(frame));
+ host_->SubmitCompositorFrame(local_surface_id, std::move(frame), nullptr, 0);
host_->StartNewContentRenderingTimeout(7);
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, base::MessageLoop::QuitWhenIdleClosure(),
@@ -1500,9 +1796,10 @@ TEST_F(RenderWidgetHostTest, SwapCompositorFrameWithBadSourceId) {
{
// First swap a frame with an invalid ID.
cc::CompositorFrame frame = MakeCompositorFrame(1.f, frame_size);
- frame.metadata.begin_frame_ack = cc::BeginFrameAck(0, 1, true);
+ frame.metadata.begin_frame_ack = viz::BeginFrameAck(0, 1, true);
frame.metadata.content_source_id = 99;
- host_->SubmitCompositorFrame(local_surface_id, std::move(frame));
+ host_->SubmitCompositorFrame(local_surface_id, std::move(frame), nullptr,
+ 0);
EXPECT_FALSE(
static_cast<TestView*>(host_->GetView())->did_swap_compositor_frame());
static_cast<TestView*>(host_->GetView())->reset_did_swap_compositor_frame();
@@ -1512,7 +1809,8 @@ TEST_F(RenderWidgetHostTest, SwapCompositorFrameWithBadSourceId) {
// Test with a valid content ID as a control.
cc::CompositorFrame frame = MakeCompositorFrame(1.f, frame_size);
frame.metadata.content_source_id = 100;
- host_->SubmitCompositorFrame(local_surface_id, std::move(frame));
+ host_->SubmitCompositorFrame(local_surface_id, std::move(frame), nullptr,
+ 0);
EXPECT_TRUE(
static_cast<TestView*>(host_->GetView())->did_swap_compositor_frame());
static_cast<TestView*>(host_->GetView())->reset_did_swap_compositor_frame();
@@ -1524,18 +1822,20 @@ TEST_F(RenderWidgetHostTest, SwapCompositorFrameWithBadSourceId) {
// the corresponding DidCommitProvisionalLoad (it's a race).
cc::CompositorFrame frame = MakeCompositorFrame(1.f, frame_size);
frame.metadata.content_source_id = 101;
- host_->SubmitCompositorFrame(local_surface_id, std::move(frame));
+ host_->SubmitCompositorFrame(local_surface_id, std::move(frame), nullptr,
+ 0);
EXPECT_TRUE(
static_cast<TestView*>(host_->GetView())->did_swap_compositor_frame());
}
}
-TEST_F(RenderWidgetHostTest, TouchEmulator) {
+TEST_F(RenderWidgetHostMojoInputDisabledTest, TouchEmulator) {
simulated_event_time_delta_seconds_ = 0.1;
// Immediately ack all touches instead of sending them to the renderer.
host_->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, false));
- host_->SetTouchEventEmulationEnabled(
- true, ui::GestureProviderConfigType::GENERIC_MOBILE);
+ host_->GetTouchEmulator()->Enable(
+ TouchEmulator::Mode::kEmulatingTouchFromMouse,
+ ui::GestureProviderConfigType::GENERIC_MOBILE);
process_->sink().ClearMessages();
view_->set_bounds(gfx::Rect(0, 0, 400, 200));
view_->Show();
@@ -1638,8 +1938,7 @@ TEST_F(RenderWidgetHostTest, TouchEmulator) {
EXPECT_EQ(0U, process_->sink().message_count());
// Turn off emulation during a pinch.
- host_->SetTouchEventEmulationEnabled(
- false, ui::GestureProviderConfigType::GENERIC_MOBILE);
+ host_->GetTouchEmulator()->Disable();
EXPECT_EQ(WebInputEvent::kTouchCancel, host_->acked_touch_event_type());
EXPECT_EQ("GesturePinchEnd GestureScrollEnd",
GetInputMessageTypes(process_));
@@ -1653,8 +1952,9 @@ TEST_F(RenderWidgetHostTest, TouchEmulator) {
EXPECT_EQ(0U, process_->sink().message_count());
// Turn on emulation.
- host_->SetTouchEventEmulationEnabled(
- true, ui::GestureProviderConfigType::GENERIC_MOBILE);
+ host_->GetTouchEmulator()->Enable(
+ TouchEmulator::Mode::kEmulatingTouchFromMouse,
+ ui::GestureProviderConfigType::GENERIC_MOBILE);
EXPECT_EQ(0U, process_->sink().message_count());
// Another touch.
@@ -1675,14 +1975,244 @@ TEST_F(RenderWidgetHostTest, TouchEmulator) {
INPUT_EVENT_ACK_STATE_CONSUMED);
// Turn off emulation during a scroll.
- host_->SetTouchEventEmulationEnabled(
- false, ui::GestureProviderConfigType::GENERIC_MOBILE);
+ host_->GetTouchEmulator()->Disable();
EXPECT_EQ(WebInputEvent::kTouchCancel, host_->acked_touch_event_type());
EXPECT_EQ("GestureScrollEnd", GetInputMessageTypes(process_));
EXPECT_EQ(0U, process_->sink().message_count());
}
+TEST_F(RenderWidgetHostTest, TouchEmulator) {
+ simulated_event_time_delta_seconds_ = 0.1;
+ // Immediately ack all touches instead of sending them to the renderer.
+ host_->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, false));
+ host_->GetTouchEmulator()->Enable(
+ TouchEmulator::Mode::kEmulatingTouchFromMouse,
+ ui::GestureProviderConfigType::GENERIC_MOBILE);
+ process_->sink().ClearMessages();
+ view_->set_bounds(gfx::Rect(0, 0, 400, 200));
+ view_->Show();
+
+ SimulateMouseEvent(WebInputEvent::kMouseMove, 10, 10, 0, false);
+ std::vector<MockWidgetInputHandler::DispatchedEvent> dispatched_events =
+ host_->mock_widget_input_handler_.GetAndResetDispatchedEvents();
+ EXPECT_EQ(0u, dispatched_events.size());
+
+ // Mouse press becomes touch start which in turn becomes tap.
+ SimulateMouseEvent(WebInputEvent::kMouseDown, 10, 10, 0, true);
+ EXPECT_EQ(WebInputEvent::kTouchStart, host_->acked_touch_event_type());
+ dispatched_events =
+ host_->mock_widget_input_handler_.GetAndResetDispatchedEvents();
+ EXPECT_EQ(1u, dispatched_events.size());
+ EXPECT_EQ(WebInputEvent::kGestureTapDown,
+ dispatched_events.at(0).event_->web_event->GetType());
+
+ // Mouse drag generates touch move, cancels tap and starts scroll.
+ SimulateMouseEvent(WebInputEvent::kMouseMove, 10, 30, 0, true);
+ dispatched_events =
+ host_->mock_widget_input_handler_.GetAndResetDispatchedEvents();
+ EXPECT_EQ(3u, dispatched_events.size());
+ EXPECT_EQ(WebInputEvent::kGestureTapCancel,
+ dispatched_events.at(0).event_->web_event->GetType());
+ EXPECT_EQ(WebInputEvent::kGestureScrollBegin,
+ dispatched_events.at(1).event_->web_event->GetType());
+ EXPECT_EQ(WebInputEvent::kTouchScrollStarted,
+ dispatched_events.at(2).event_->web_event->GetType());
+ if (dispatched_events.at(1).callback_) {
+ CallCallback(std::move(dispatched_events.at(1).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ }
+ EXPECT_EQ(WebInputEvent::kTouchMove, host_->acked_touch_event_type());
+ dispatched_events =
+ host_->mock_widget_input_handler_.GetAndResetDispatchedEvents();
+ EXPECT_EQ(1u, dispatched_events.size());
+ EXPECT_EQ(WebInputEvent::kGestureScrollUpdate,
+ dispatched_events.at(0).event_->web_event->GetType());
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ // Mouse drag with shift becomes pinch.
+ SimulateMouseEvent(WebInputEvent::kMouseMove, 10, 40,
+ WebInputEvent::kShiftKey, true);
+ EXPECT_EQ(WebInputEvent::kTouchMove, host_->acked_touch_event_type());
+
+ dispatched_events =
+ host_->mock_widget_input_handler_.GetAndResetDispatchedEvents();
+ EXPECT_EQ(1u, dispatched_events.size());
+ EXPECT_EQ(WebInputEvent::kGesturePinchBegin,
+ dispatched_events.at(0).event_->web_event->GetType());
+
+ SimulateMouseEvent(WebInputEvent::kMouseMove, 10, 50,
+ WebInputEvent::kShiftKey, true);
+ EXPECT_EQ(WebInputEvent::kTouchMove, host_->acked_touch_event_type());
+
+ dispatched_events =
+ host_->mock_widget_input_handler_.GetAndResetDispatchedEvents();
+ EXPECT_EQ(1u, dispatched_events.size());
+ EXPECT_EQ(WebInputEvent::kGesturePinchUpdate,
+ dispatched_events.at(0).event_->web_event->GetType());
+
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+
+ // Mouse drag without shift becomes scroll again.
+ SimulateMouseEvent(WebInputEvent::kMouseMove, 10, 60, 0, true);
+ EXPECT_EQ(WebInputEvent::kTouchMove, host_->acked_touch_event_type());
+
+ dispatched_events =
+ host_->mock_widget_input_handler_.GetAndResetDispatchedEvents();
+ EXPECT_EQ(2u, dispatched_events.size());
+ EXPECT_EQ(WebInputEvent::kGesturePinchEnd,
+ dispatched_events.at(0).event_->web_event->GetType());
+ EXPECT_EQ(WebInputEvent::kGestureScrollUpdate,
+ dispatched_events.at(1).event_->web_event->GetType());
+ CallCallback(std::move(dispatched_events.at(1).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+
+ SimulateMouseEvent(WebInputEvent::kMouseMove, 10, 70, 0, true);
+ EXPECT_EQ(WebInputEvent::kTouchMove, host_->acked_touch_event_type());
+ dispatched_events =
+ host_->mock_widget_input_handler_.GetAndResetDispatchedEvents();
+ EXPECT_EQ(1u, dispatched_events.size());
+ EXPECT_EQ(WebInputEvent::kGestureScrollUpdate,
+ dispatched_events.at(0).event_->web_event->GetType());
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+
+ SimulateMouseEvent(WebInputEvent::kMouseUp, 10, 70, 0, true);
+ EXPECT_EQ(WebInputEvent::kTouchEnd, host_->acked_touch_event_type());
+ dispatched_events =
+ host_->mock_widget_input_handler_.GetAndResetDispatchedEvents();
+ EXPECT_EQ(1u, dispatched_events.size());
+ EXPECT_EQ(WebInputEvent::kGestureScrollEnd,
+ dispatched_events.at(0).event_->web_event->GetType());
+
+ // Mouse move does nothing.
+ SimulateMouseEvent(WebInputEvent::kMouseMove, 10, 80, 0, false);
+ dispatched_events =
+ host_->mock_widget_input_handler_.GetAndResetDispatchedEvents();
+ EXPECT_EQ(0u, dispatched_events.size());
+
+ // Another mouse down continues scroll.
+ SimulateMouseEvent(WebInputEvent::kMouseDown, 10, 80, 0, true);
+ EXPECT_EQ(WebInputEvent::kTouchStart, host_->acked_touch_event_type());
+ dispatched_events =
+ host_->mock_widget_input_handler_.GetAndResetDispatchedEvents();
+ EXPECT_EQ(1u, dispatched_events.size());
+ EXPECT_EQ(WebInputEvent::kGestureTapDown,
+ dispatched_events.at(0).event_->web_event->GetType());
+ SimulateMouseEvent(WebInputEvent::kMouseMove, 10, 100, 0, true);
+ EXPECT_EQ(WebInputEvent::kTouchMove, host_->acked_touch_event_type());
+ dispatched_events =
+ host_->mock_widget_input_handler_.GetAndResetDispatchedEvents();
+ EXPECT_EQ(3u, dispatched_events.size());
+ EXPECT_EQ(WebInputEvent::kGestureTapCancel,
+ dispatched_events.at(0).event_->web_event->GetType());
+ EXPECT_EQ(WebInputEvent::kGestureScrollBegin,
+ dispatched_events.at(1).event_->web_event->GetType());
+ EXPECT_EQ(WebInputEvent::kTouchScrollStarted,
+ dispatched_events.at(2).event_->web_event->GetType());
+ if (dispatched_events.at(1).callback_) {
+ CallCallback(std::move(dispatched_events.at(1).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ }
+ dispatched_events =
+ host_->mock_widget_input_handler_.GetAndResetDispatchedEvents();
+ EXPECT_EQ(1u, dispatched_events.size());
+ EXPECT_EQ(WebInputEvent::kGestureScrollUpdate,
+ dispatched_events.at(0).event_->web_event->GetType());
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ // Another pinch.
+ SimulateMouseEvent(WebInputEvent::kMouseMove, 10, 110,
+ WebInputEvent::kShiftKey, true);
+ EXPECT_EQ(WebInputEvent::kTouchMove, host_->acked_touch_event_type());
+ dispatched_events =
+ host_->mock_widget_input_handler_.GetAndResetDispatchedEvents();
+ EXPECT_EQ(1u, dispatched_events.size());
+ EXPECT_EQ(WebInputEvent::kGesturePinchBegin,
+ dispatched_events.at(0).event_->web_event->GetType());
+ SimulateMouseEvent(WebInputEvent::kMouseMove, 10, 120,
+ WebInputEvent::kShiftKey, true);
+ EXPECT_EQ(WebInputEvent::kTouchMove, host_->acked_touch_event_type());
+ dispatched_events =
+ host_->mock_widget_input_handler_.GetAndResetDispatchedEvents();
+ EXPECT_EQ(1u, dispatched_events.size());
+ EXPECT_EQ(WebInputEvent::kGesturePinchUpdate,
+ dispatched_events.at(0).event_->web_event->GetType());
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+
+ // Turn off emulation during a pinch.
+ host_->GetTouchEmulator()->Disable();
+ EXPECT_EQ(WebInputEvent::kTouchCancel, host_->acked_touch_event_type());
+ dispatched_events =
+ host_->mock_widget_input_handler_.GetAndResetDispatchedEvents();
+ EXPECT_EQ(2u, dispatched_events.size());
+ EXPECT_EQ(WebInputEvent::kGesturePinchEnd,
+ dispatched_events.at(0).event_->web_event->GetType());
+ EXPECT_EQ(WebInputEvent::kGestureScrollEnd,
+ dispatched_events.at(1).event_->web_event->GetType());
+
+ // Mouse event should pass untouched.
+ SimulateMouseEvent(WebInputEvent::kMouseMove, 10, 10,
+ WebInputEvent::kShiftKey, true);
+ dispatched_events =
+ host_->mock_widget_input_handler_.GetAndResetDispatchedEvents();
+ EXPECT_EQ(1u, dispatched_events.size());
+ EXPECT_EQ(WebInputEvent::kMouseMove,
+ dispatched_events.at(0).event_->web_event->GetType());
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+
+ // Turn on emulation.
+ host_->GetTouchEmulator()->Enable(
+ TouchEmulator::Mode::kEmulatingTouchFromMouse,
+ ui::GestureProviderConfigType::GENERIC_MOBILE);
+
+ // Another touch.
+ SimulateMouseEvent(WebInputEvent::kMouseDown, 10, 10, 0, true);
+ EXPECT_EQ(WebInputEvent::kTouchStart, host_->acked_touch_event_type());
+ dispatched_events =
+ host_->mock_widget_input_handler_.GetAndResetDispatchedEvents();
+ EXPECT_EQ(1u, dispatched_events.size());
+ EXPECT_EQ(WebInputEvent::kGestureTapDown,
+ dispatched_events.at(0).event_->web_event->GetType());
+
+ // Scroll.
+ SimulateMouseEvent(WebInputEvent::kMouseMove, 10, 30, 0, true);
+ EXPECT_EQ(WebInputEvent::kTouchMove, host_->acked_touch_event_type());
+ dispatched_events =
+ host_->mock_widget_input_handler_.GetAndResetDispatchedEvents();
+ EXPECT_EQ(3u, dispatched_events.size());
+ EXPECT_EQ(WebInputEvent::kGestureTapCancel,
+ dispatched_events.at(0).event_->web_event->GetType());
+ EXPECT_EQ(WebInputEvent::kGestureScrollBegin,
+ dispatched_events.at(1).event_->web_event->GetType());
+ EXPECT_EQ(WebInputEvent::kTouchScrollStarted,
+ dispatched_events.at(2).event_->web_event->GetType());
+ if (dispatched_events.at(1).callback_) {
+ CallCallback(std::move(dispatched_events.at(1).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ }
+ dispatched_events =
+ host_->mock_widget_input_handler_.GetAndResetDispatchedEvents();
+ EXPECT_EQ(1u, dispatched_events.size());
+ EXPECT_EQ(WebInputEvent::kGestureScrollUpdate,
+ dispatched_events.at(0).event_->web_event->GetType());
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+
+ // Turn off emulation during a scroll.
+ host_->GetTouchEmulator()->Disable();
+ EXPECT_EQ(WebInputEvent::kTouchCancel, host_->acked_touch_event_type());
+
+ dispatched_events =
+ host_->mock_widget_input_handler_.GetAndResetDispatchedEvents();
+ EXPECT_EQ(1u, dispatched_events.size());
+ EXPECT_EQ(WebInputEvent::kGestureScrollEnd,
+ dispatched_events.at(0).event_->web_event->GetType());
+}
+
TEST_F(RenderWidgetHostTest, IgnoreInputEvent) {
host_->SetupForInputRouterTest();
@@ -1848,7 +2378,7 @@ void CheckLatencyInfoComponentInGestureScrollUpdate(
// or ForwardXXXEventWithLatencyInfo(), LatencyInfo component
// ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT will always present in the
// event's LatencyInfo.
-void RenderWidgetHostTest::InputEventRWHLatencyComponent() {
+void RenderWidgetHostTest::InputEventRWHLatencyComponentMojoInputDisabled() {
host_->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, true));
process_->sink().ClearMessages();
@@ -1905,6 +2435,111 @@ void RenderWidgetHostTest::InputEventRWHLatencyComponent() {
CheckLatencyInfoComponentInMessage(process_, GetLatencyComponentId(),
WebInputEvent::kTouchStart);
}
+TEST_F(RenderWidgetHostMojoInputDisabledTest, InputEventRWHLatencyComponent) {
+ InputEventRWHLatencyComponentMojoInputDisabled();
+}
+TEST_F(RenderWidgetHostWheelScrollLatchingMojoInputDisabledTest,
+ InputEventRWHLatencyComponent) {
+ InputEventRWHLatencyComponentMojoInputDisabled();
+}
+TEST_F(RenderWidgetHostAsyncWheelEventsEnabledMojoInputDisabledTest,
+ InputEventRWHLatencyComponent) {
+ InputEventRWHLatencyComponentMojoInputDisabled();
+}
+
+void CheckLatencyInfoComponentInMessage(
+ std::vector<MockWidgetInputHandler::DispatchedEvent>& dispatched_events,
+ int64_t component_id,
+ WebInputEvent::Type expected_type) {
+ EXPECT_EQ(1u, dispatched_events.size());
+ EXPECT_TRUE(dispatched_events.at(0).event_->web_event->GetType() ==
+ expected_type);
+ EXPECT_TRUE(dispatched_events.at(0).event_->latency_info.FindLatency(
+ ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, component_id, NULL));
+ if (dispatched_events.at(0).callback_) {
+ CallCallback(std::move(dispatched_events.at(0).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ }
+}
+
+void CheckLatencyInfoComponentInGestureScrollUpdate(
+ std::vector<MockWidgetInputHandler::DispatchedEvent>& dispatched_events,
+ int64_t component_id) {
+ EXPECT_EQ(2u, dispatched_events.size());
+ EXPECT_EQ(WebInputEvent::kTouchScrollStarted,
+ dispatched_events.at(0).event_->web_event->GetType());
+
+ EXPECT_EQ(WebInputEvent::kGestureScrollUpdate,
+ dispatched_events.at(1).event_->web_event->GetType());
+ EXPECT_TRUE(dispatched_events.at(1).event_->latency_info.FindLatency(
+ ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, component_id, NULL));
+ CallCallback(std::move(dispatched_events.at(1).callback_),
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+}
+
+// Tests that after input event passes through RWHI through ForwardXXXEvent()
+// or ForwardXXXEventWithLatencyInfo(), LatencyInfo component
+// ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT will always present in the
+// event's LatencyInfo.
+void RenderWidgetHostTest::InputEventRWHLatencyComponent() {
+ host_->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, true));
+
+ // Tests RWHI::ForwardWheelEvent().
+ SimulateWheelEventPossiblyIncludingPhase(-5, 0, 0, true,
+ WebMouseWheelEvent::kPhaseBegan);
+ std::vector<MockWidgetInputHandler::DispatchedEvent> dispatched_events =
+ host_->mock_widget_input_handler_.GetAndResetDispatchedEvents();
+ CheckLatencyInfoComponentInMessage(dispatched_events, GetLatencyComponentId(),
+ WebInputEvent::kMouseWheel);
+
+ // Tests RWHI::ForwardWheelEventWithLatencyInfo().
+ SimulateWheelEventWithLatencyInfoAndPossiblyPhase(
+ -5, 0, 0, true, ui::LatencyInfo(), WebMouseWheelEvent::kPhaseChanged);
+ dispatched_events =
+ host_->mock_widget_input_handler_.GetAndResetDispatchedEvents();
+ CheckLatencyInfoComponentInMessage(dispatched_events, GetLatencyComponentId(),
+ WebInputEvent::kMouseWheel);
+
+ // Tests RWHI::ForwardMouseEvent().
+ SimulateMouseEvent(WebInputEvent::kMouseMove);
+ dispatched_events =
+ host_->mock_widget_input_handler_.GetAndResetDispatchedEvents();
+ CheckLatencyInfoComponentInMessage(dispatched_events, GetLatencyComponentId(),
+ WebInputEvent::kMouseMove);
+
+ // Tests RWHI::ForwardMouseEventWithLatencyInfo().
+ SimulateMouseEventWithLatencyInfo(WebInputEvent::kMouseMove,
+ ui::LatencyInfo());
+ dispatched_events =
+ host_->mock_widget_input_handler_.GetAndResetDispatchedEvents();
+ CheckLatencyInfoComponentInMessage(dispatched_events, GetLatencyComponentId(),
+ WebInputEvent::kMouseMove);
+
+ // Tests RWHI::ForwardGestureEvent().
+ SimulateGestureEvent(WebInputEvent::kGestureScrollBegin,
+ blink::kWebGestureDeviceTouchscreen);
+ dispatched_events =
+ host_->mock_widget_input_handler_.GetAndResetDispatchedEvents();
+ CheckLatencyInfoComponentInMessage(dispatched_events, GetLatencyComponentId(),
+ WebInputEvent::kGestureScrollBegin);
+
+ // Tests RWHI::ForwardGestureEventWithLatencyInfo().
+ SimulateGestureEventWithLatencyInfo(WebInputEvent::kGestureScrollUpdate,
+ blink::kWebGestureDeviceTouchscreen,
+ ui::LatencyInfo());
+ dispatched_events =
+ host_->mock_widget_input_handler_.GetAndResetDispatchedEvents();
+ CheckLatencyInfoComponentInGestureScrollUpdate(dispatched_events,
+ GetLatencyComponentId());
+
+ // Tests RWHI::ForwardTouchEventWithLatencyInfo().
+ PressTouchPoint(0, 1);
+ SendTouchEvent();
+ dispatched_events =
+ host_->mock_widget_input_handler_.GetAndResetDispatchedEvents();
+ CheckLatencyInfoComponentInMessage(dispatched_events, GetLatencyComponentId(),
+ WebInputEvent::kTouchStart);
+}
TEST_F(RenderWidgetHostTest, InputEventRWHLatencyComponent) {
InputEventRWHLatencyComponent();
}
@@ -2038,7 +2673,7 @@ TEST_F(RenderWidgetHostTest, FrameToken_MessageThenFrame) {
cc::CompositorFrame frame = MakeCompositorFrame(1.f, frame_size);
frame.metadata.frame_token = frame_token;
- host_->SubmitCompositorFrame(local_surface_id, std::move(frame));
+ host_->SubmitCompositorFrame(local_surface_id, std::move(frame), nullptr, 0);
EXPECT_EQ(0u, host_->queued_messages_.size());
EXPECT_EQ(1u, host_->processed_frame_messages_count());
}
@@ -2058,7 +2693,7 @@ TEST_F(RenderWidgetHostTest, FrameToken_FrameThenMessage) {
cc::CompositorFrame frame = MakeCompositorFrame(1.f, frame_size);
frame.metadata.frame_token = frame_token;
- host_->SubmitCompositorFrame(local_surface_id, std::move(frame));
+ host_->SubmitCompositorFrame(local_surface_id, std::move(frame), nullptr, 0);
EXPECT_EQ(0u, host_->queued_messages_.size());
EXPECT_EQ(0u, host_->processed_frame_messages_count());
@@ -2096,13 +2731,13 @@ TEST_F(RenderWidgetHostTest, FrameToken_MultipleMessagesThenTokens) {
cc::CompositorFrame frame = MakeCompositorFrame(1.f, frame_size);
frame.metadata.frame_token = frame_token1;
- host_->SubmitCompositorFrame(local_surface_id, std::move(frame));
+ host_->SubmitCompositorFrame(local_surface_id, std::move(frame), nullptr, 0);
EXPECT_EQ(1u, host_->queued_messages_.size());
EXPECT_EQ(1u, host_->processed_frame_messages_count());
frame = MakeCompositorFrame(1.f, frame_size);
frame.metadata.frame_token = frame_token2;
- host_->SubmitCompositorFrame(local_surface_id, std::move(frame));
+ host_->SubmitCompositorFrame(local_surface_id, std::move(frame), nullptr, 0);
EXPECT_EQ(0u, host_->queued_messages_.size());
EXPECT_EQ(2u, host_->processed_frame_messages_count());
}
@@ -2125,13 +2760,13 @@ TEST_F(RenderWidgetHostTest, FrameToken_MultipleTokensThenMessages) {
cc::CompositorFrame frame = MakeCompositorFrame(1.f, frame_size);
frame.metadata.frame_token = frame_token1;
- host_->SubmitCompositorFrame(local_surface_id, std::move(frame));
+ host_->SubmitCompositorFrame(local_surface_id, std::move(frame), nullptr, 0);
EXPECT_EQ(0u, host_->queued_messages_.size());
EXPECT_EQ(0u, host_->processed_frame_messages_count());
frame = MakeCompositorFrame(1.f, frame_size);
frame.metadata.frame_token = frame_token2;
- host_->SubmitCompositorFrame(local_surface_id, std::move(frame));
+ host_->SubmitCompositorFrame(local_surface_id, std::move(frame), nullptr, 0);
EXPECT_EQ(0u, host_->queued_messages_.size());
EXPECT_EQ(0u, host_->processed_frame_messages_count());
@@ -2174,7 +2809,7 @@ TEST_F(RenderWidgetHostTest, FrameToken_DroppedFrame) {
cc::CompositorFrame frame = MakeCompositorFrame(1.f, frame_size);
frame.metadata.frame_token = frame_token2;
- host_->SubmitCompositorFrame(local_surface_id, std::move(frame));
+ host_->SubmitCompositorFrame(local_surface_id, std::move(frame), nullptr, 0);
EXPECT_EQ(0u, host_->queued_messages_.size());
EXPECT_EQ(2u, host_->processed_frame_messages_count());
}
@@ -2209,7 +2844,7 @@ TEST_F(RenderWidgetHostTest, FrameToken_RendererCrash) {
cc::CompositorFrame frame = MakeCompositorFrame(1.f, frame_size);
frame.metadata.frame_token = frame_token2;
- host_->SubmitCompositorFrame(local_surface_id, std::move(frame));
+ host_->SubmitCompositorFrame(local_surface_id, std::move(frame), nullptr, 0);
EXPECT_EQ(0u, host_->queued_messages_.size());
EXPECT_EQ(0u, host_->processed_frame_messages_count());
@@ -2225,7 +2860,7 @@ TEST_F(RenderWidgetHostTest, FrameToken_RendererCrash) {
frame = MakeCompositorFrame(1.f, frame_size);
frame.metadata.frame_token = frame_token3;
- host_->SubmitCompositorFrame(local_surface_id, std::move(frame));
+ host_->SubmitCompositorFrame(local_surface_id, std::move(frame), nullptr, 0);
EXPECT_EQ(0u, host_->queued_messages_.size());
EXPECT_EQ(1u, host_->processed_frame_messages_count());
}
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_android.cc b/chromium/content/browser/renderer_host/render_widget_host_view_android.cc
index b7b8c479c26..f4f522da9a5 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
@@ -26,23 +26,25 @@
#include "cc/layers/layer.h"
#include "cc/layers/surface_layer.h"
#include "cc/output/compositor_frame.h"
-#include "cc/output/copy_output_request.h"
-#include "cc/output/copy_output_result.h"
#include "cc/output/latency_info_swap_promise.h"
-#include "cc/resources/single_release_callback.h"
-#include "cc/surfaces/surface.h"
-#include "cc/surfaces/surface_hittest.h"
#include "cc/trees/layer_tree_host.h"
#include "components/viz/common/gl_helper.h"
+#include "components/viz/common/quads/copy_output_request.h"
+#include "components/viz/common/quads/copy_output_result.h"
+#include "components/viz/common/quads/single_release_callback.h"
#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
+#include "components/viz/service/surfaces/surface.h"
+#include "components/viz/service/surfaces/surface_hittest.h"
#include "content/browser/accessibility/browser_accessibility_manager_android.h"
#include "content/browser/accessibility/web_contents_accessibility_android.h"
#include "content/browser/android/composited_touch_handle_drawable.h"
#include "content/browser/android/content_view_core.h"
#include "content/browser/android/ime_adapter_android.h"
#include "content/browser/android/overscroll_controller_android.h"
+#include "content/browser/android/popup_zoomer.h"
#include "content/browser/android/selection_popup_controller.h"
#include "content/browser/android/synchronous_compositor_host.h"
+#include "content/browser/android/text_suggestion_host_android.h"
#include "content/browser/compositor/surface_utils.h"
#include "content/browser/devtools/render_frame_devtools_agent_host.h"
#include "content/browser/gpu/browser_gpu_channel_host_factory.h"
@@ -84,6 +86,7 @@
#include "third_party/khronos/GLES2/gl2.h"
#include "third_party/khronos/GLES2/gl2ext.h"
#include "third_party/skia/include/core/SkCanvas.h"
+#include "ui/android/view_android_observer.h"
#include "ui/android/window_android.h"
#include "ui/android/window_android_compositor.h"
#include "ui/base/layout.h"
@@ -292,7 +295,7 @@ void ReleaseGLHelper() {
void CopyFromCompositingSurfaceFinished(
const ReadbackRequestCallback& callback,
- std::unique_ptr<cc::SingleReleaseCallback> release_callback,
+ std::unique_ptr<viz::SingleReleaseCallback> release_callback,
std::unique_ptr<SkBitmap> bitmap,
const base::TimeTicks& start_time,
scoped_refptr<PendingReadbackLock> readback_lock,
@@ -357,7 +360,7 @@ void PrepareTextureCopyOutputResult(
const base::TimeTicks& start_time,
const ReadbackRequestCallback& callback,
scoped_refptr<PendingReadbackLock> readback_lock,
- std::unique_ptr<cc::CopyOutputResult> result) {
+ std::unique_ptr<viz::CopyOutputResult> result) {
base::ScopedClosureRunner scoped_callback_runner(
base::Bind(callback, SkBitmap(), READBACK_FAILED));
TRACE_EVENT0("cc",
@@ -365,7 +368,7 @@ void PrepareTextureCopyOutputResult(
if (!result->HasTexture() || result->IsEmpty() || result->size().IsEmpty())
return;
viz::TextureMailbox texture_mailbox;
- std::unique_ptr<cc::SingleReleaseCallback> release_callback;
+ std::unique_ptr<viz::SingleReleaseCallback> release_callback;
result->TakeTexture(&texture_mailbox, &release_callback);
DCHECK(texture_mailbox.IsTexture());
if (!texture_mailbox.IsTexture())
@@ -455,6 +458,7 @@ RenderWidgetHostViewAndroid::RenderWidgetHostViewAndroid(
content_view_core_(nullptr),
ime_adapter_android_(nullptr),
selection_popup_controller_(nullptr),
+ text_suggestion_host_(nullptr),
background_color_(SK_ColorWHITE),
cached_background_color_(SK_ColorWHITE),
view_(this),
@@ -615,10 +619,10 @@ void RenderWidgetHostViewAndroid::LostFocus() {
}
void RenderWidgetHostViewAndroid::Focus() {
- // TODO(boliu): Make sure rwhva/rwh focus state stays in sync with CVC, and
- // ideally properly implements "request focus". See crbug.com/746099.
- host_->Focus();
- OnFocusInternal();
+ if (view_.HasFocus())
+ GotFocus();
+ else
+ view_.RequestFocus();
}
void RenderWidgetHostViewAndroid::OnFocusInternal() {
@@ -632,10 +636,7 @@ void RenderWidgetHostViewAndroid::LostFocusInternal() {
}
bool RenderWidgetHostViewAndroid::HasFocus() const {
- if (!content_view_core_)
- return false; // ContentViewCore not created yet.
-
- return content_view_core_->HasFocus();
+ return view_.HasFocus();
}
bool RenderWidgetHostViewAndroid::IsSurfaceAvailableForCopy() const {
@@ -744,7 +745,10 @@ float RenderWidgetHostViewAndroid::GetBottomControlsHeight() const {
}
void RenderWidgetHostViewAndroid::UpdateCursor(const WebCursor& cursor) {
- // There are no cursors on Android.
+ CursorInfo cursor_info;
+ cursor.GetCursorInfo(&cursor_info);
+ view_.OnCursorChanged(cursor_info.type, cursor_info.custom_image,
+ cursor_info.hotspot);
}
void RenderWidgetHostViewAndroid::SetIsLoading(bool is_loading) {
@@ -845,7 +849,7 @@ viz::SurfaceId RenderWidgetHostViewAndroid::SurfaceIdForTesting() const {
}
viz::FrameSinkId RenderWidgetHostViewAndroid::FrameSinkIdAtPoint(
- cc::SurfaceHittestDelegate* delegate,
+ viz::SurfaceHittestDelegate* delegate,
const gfx::Point& point,
gfx::Point* transformed_point) {
if (!delegated_frame_host_)
@@ -859,8 +863,8 @@ viz::FrameSinkId RenderWidgetHostViewAndroid::FrameSinkIdAtPoint(
viz::SurfaceId surface_id = delegated_frame_host_->SurfaceId();
if (surface_id.is_valid()) {
- cc::SurfaceHittest hittest(delegate,
- GetFrameSinkManager()->surface_manager());
+ viz::SurfaceHittest hittest(delegate,
+ GetFrameSinkManager()->surface_manager());
gfx::Transform target_transform;
surface_id = hittest.GetTargetSurfaceAtPoint(surface_id, point_in_pixels,
&target_transform);
@@ -923,7 +927,8 @@ bool RenderWidgetHostViewAndroid::TransformPointToLocalCoordSpace(
return true;
*transformed_point = point_in_pixels;
- cc::SurfaceHittest hittest(nullptr, GetFrameSinkManager()->surface_manager());
+ viz::SurfaceHittest hittest(nullptr,
+ GetFrameSinkManager()->surface_manager());
if (!hittest.TransformPointToTargetSurface(original_surface, surface_id,
transformed_point))
return false;
@@ -958,17 +963,26 @@ RenderWidgetHostViewAndroid::GetWeakPtrAndroid() {
}
bool RenderWidgetHostViewAndroid::OnTouchEvent(
- const ui::MotionEvent& event) {
+ const ui::MotionEventAndroid& event) {
+ RecordToolTypeForActionDown(event);
+
+ if (event.for_touch_handle())
+ return OnTouchHandleEvent(event);
+
if (!host_ || !host_->delegate())
return false;
ComputeEventLatencyOSTouchHistograms(event);
+ // Receiving any other touch event before the double-tap timeout expires
+ // cancels opening the spellcheck menu.
+ if (text_suggestion_host_)
+ text_suggestion_host_->StopSpellCheckMenuTimer();
+
// If a browser-based widget consumes the touch event, it's critical that
// touch event interception be disabled. This avoids issues with
// double-handling for embedder-detected gestures like side swipe.
- if (touch_selection_controller_ &&
- touch_selection_controller_->WillHandleTouchEvent(event)) {
+ if (OnTouchHandleEvent(event)) {
RequestDisallowInterceptTouchEvent();
return true;
}
@@ -987,8 +1001,7 @@ bool RenderWidgetHostViewAndroid::OnTouchEvent(
event, result.moved_beyond_slop_region);
ui::LatencyInfo latency_info(ui::SourceEventType::TOUCH);
latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
- if (host_->delegate()->GetInputEventRouter() &&
- SiteIsolationPolicy::AreCrossProcessFramesPossible()) {
+ if (host_->delegate()->GetInputEventRouter()) {
host_->delegate()->GetInputEventRouter()->RouteTouchEvent(this, &web_event,
latency_info);
} else {
@@ -1035,8 +1048,7 @@ void RenderWidgetHostViewAndroid::ResetGestureDetection() {
latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
blink::WebTouchEvent web_event =
ui::CreateWebTouchEventFromMotionEvent(*cancel_event, causes_scrolling);
- if (SiteIsolationPolicy::AreCrossProcessFramesPossible() &&
- host_->delegate()->GetInputEventRouter()) {
+ if (host_->delegate()->GetInputEventRouter()) {
host_->delegate()->GetInputEventRouter()->RouteTouchEvent(
this, &web_event, latency_info);
} else {
@@ -1157,17 +1169,16 @@ void RenderWidgetHostViewAndroid::CopyFromSurface(
void RenderWidgetHostViewAndroid::ShowDisambiguationPopup(
const gfx::Rect& rect_pixels, const SkBitmap& zoomed_bitmap) {
- if (!content_view_core_)
+ if (!popup_zoomer_)
return;
- content_view_core_->ShowDisambiguationPopup(rect_pixels, zoomed_bitmap);
+ popup_zoomer_->ShowPopup(rect_pixels, zoomed_bitmap);
}
std::unique_ptr<SyntheticGestureTarget>
RenderWidgetHostViewAndroid::CreateSyntheticGestureTarget() {
return std::unique_ptr<SyntheticGestureTarget>(
- new SyntheticGestureTargetAndroid(
- host_, content_view_core_->CreateMotionEventSynthesizer()));
+ new SyntheticGestureTargetAndroid(host_, &view_));
}
void RenderWidgetHostViewAndroid::SendReclaimCompositorResources(
@@ -1188,7 +1199,7 @@ void RenderWidgetHostViewAndroid::DidReceiveCompositorFrameAck() {
}
void RenderWidgetHostViewAndroid::ReclaimResources(
- const std::vector<cc::ReturnedResource>& resources) {
+ const std::vector<viz::ReturnedResource>& resources) {
if (resources.empty())
return;
std::copy(resources.begin(), resources.end(),
@@ -1198,7 +1209,7 @@ void RenderWidgetHostViewAndroid::ReclaimResources(
}
void RenderWidgetHostViewAndroid::DidCreateNewRendererCompositorFrameSink(
- cc::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink) {
+ viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink) {
if (!delegated_frame_host_) {
DCHECK(!using_browser_compositor_);
// We don't expect RendererCompositorFrameSink on Android WebView.
@@ -1254,7 +1265,7 @@ void RenderWidgetHostViewAndroid::SubmitCompositorFrame(
ack_callbacks_.push(ack_callback);
- cc::BeginFrameAck ack = frame.metadata.begin_frame_ack;
+ viz::BeginFrameAck ack = frame.metadata.begin_frame_ack;
if (!has_content) {
DestroyDelegatedContent();
@@ -1292,7 +1303,7 @@ void RenderWidgetHostViewAndroid::DestroyDelegatedContent() {
}
void RenderWidgetHostViewAndroid::OnDidNotProduceFrame(
- const cc::BeginFrameAck& ack) {
+ const viz::BeginFrameAck& ack) {
if (!delegated_frame_host_) {
// We are not using the browser compositor and there's no DisplayScheduler
// that needs to be notified about the BeginFrameAck, so we can drop it.
@@ -1305,7 +1316,7 @@ void RenderWidgetHostViewAndroid::OnDidNotProduceFrame(
}
void RenderWidgetHostViewAndroid::AcknowledgeBeginFrame(
- const cc::BeginFrameAck& ack) {
+ const viz::BeginFrameAck& ack) {
if (begin_frame_source_)
begin_frame_source_->DidFinishFrame(this);
}
@@ -1611,7 +1622,7 @@ void RenderWidgetHostViewAndroid::HideInternal() {
}
void RenderWidgetHostViewAndroid::SetBeginFrameSource(
- cc::BeginFrameSource* begin_frame_source) {
+ viz::BeginFrameSource* begin_frame_source) {
if (begin_frame_source_ == begin_frame_source)
return;
@@ -1630,7 +1641,7 @@ void RenderWidgetHostViewAndroid::AddBeginFrameRequest(
// Note that if we don't currently have a BeginFrameSource, outstanding begin
// frame requests will be pushed if/when we get one during
// |StartObservingRootWindow()| or when the DelegatedFrameHostAndroid sets it.
- cc::BeginFrameSource* source = begin_frame_source_;
+ viz::BeginFrameSource* source = begin_frame_source_;
if (source && outstanding_begin_frame_requests_ && !prior_requests)
source->AddObserver(this);
}
@@ -1640,7 +1651,7 @@ void RenderWidgetHostViewAndroid::ClearBeginFrameRequest(
uint32_t prior_requests = outstanding_begin_frame_requests_;
outstanding_begin_frame_requests_ = prior_requests & ~request;
- cc::BeginFrameSource* source = begin_frame_source_;
+ viz::BeginFrameSource* source = begin_frame_source_;
if (source && !outstanding_begin_frame_requests_ && prior_requests)
source->RemoveObserver(this);
}
@@ -1690,7 +1701,7 @@ void RenderWidgetHostViewAndroid::StopObservingRootWindow() {
DCHECK(!begin_frame_source_);
}
-void RenderWidgetHostViewAndroid::SendBeginFrame(cc::BeginFrameArgs args) {
+void RenderWidgetHostViewAndroid::SendBeginFrame(viz::BeginFrameArgs args) {
TRACE_EVENT2("cc", "RenderWidgetHostViewAndroid::SendBeginFrame",
"frame_number", args.sequence_number, "frame_time_us",
args.frame_time.ToInternalValue());
@@ -1791,6 +1802,14 @@ InputEventAckState RenderWidgetHostViewAndroid::FilterInputEvent(
return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
}
+InputEventAckState RenderWidgetHostViewAndroid::FilterChildGestureEvent(
+ const blink::WebGestureEvent& gesture_event) {
+ if (overscroll_controller_ &&
+ overscroll_controller_->WillHandleGestureEvent(gesture_event))
+ return INPUT_EVENT_ACK_STATE_CONSUMED;
+ return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
+}
+
BrowserAccessibilityManager*
RenderWidgetHostViewAndroid::CreateBrowserAccessibilityManager(
BrowserAccessibilityDelegate* delegate, bool for_root_frame) {
@@ -1825,6 +1844,11 @@ void RenderWidgetHostViewAndroid::SendKeyEvent(
if (!target_host)
return;
+ // Receiving a key event before the double-tap timeout expires cancels opening
+ // the spellcheck menu. If the suggestion menu is open, we close the menu.
+ if (text_suggestion_host_)
+ text_suggestion_host_->OnKeyEvent();
+
ui::LatencyInfo latency_info;
if (event.GetType() == blink::WebInputEvent::kRawKeyDown ||
event.GetType() == blink::WebInputEvent::kChar) {
@@ -1863,8 +1887,7 @@ void RenderWidgetHostViewAndroid::SendMouseEvent(
if (!host_ || !host_->delegate())
return;
- if (SiteIsolationPolicy::AreCrossProcessFramesPossible() &&
- host_->delegate()->GetInputEventRouter()) {
+ if (host_->delegate()->GetInputEventRouter()) {
host_->delegate()->GetInputEventRouter()->RouteMouseEvent(
this, &mouse_event, ui::LatencyInfo());
} else {
@@ -1904,9 +1927,7 @@ void RenderWidgetHostViewAndroid::SendMouseWheelEvent(
ui::LatencyInfo latency_info(ui::SourceEventType::WHEEL);
latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
blink::WebMouseWheelEvent wheel_event(event);
- bool should_route_event =
- SiteIsolationPolicy::AreCrossProcessFramesPossible() &&
- host_->delegate()->GetInputEventRouter();
+ bool should_route_event = !!host_->delegate()->GetInputEventRouter();
if (wheel_scroll_latching_enabled()) {
mouse_wheel_phase_handler_.AddPhaseIfNeededAndScheduleEndEvent(
wheel_event, should_route_event);
@@ -1980,9 +2001,7 @@ void RenderWidgetHostViewAndroid::SendGestureEvent(
mouse_wheel_phase_handler_.IgnorePendingWheelEndEvent();
}
}
- bool should_route_event =
- SiteIsolationPolicy::AreCrossProcessFramesPossible() &&
- host_->delegate()->GetInputEventRouter();
+ bool should_route_event = !!host_->delegate()->GetInputEventRouter();
if (should_route_event) {
blink::WebGestureEvent gesture_event(event);
host_->delegate()->GetInputEventRouter()->RouteGestureEvent(
@@ -2088,11 +2107,13 @@ void RenderWidgetHostViewAndroid::SetContentViewCore(
resize = true;
if (content_view_core_) {
content_view_core_->RemoveObserver(this);
+ view_.RemoveObserver(this);
view_.RemoveFromParent();
view_.GetLayer()->RemoveFromParent();
}
if (content_view_core) {
content_view_core->AddObserver(this);
+ view_.AddObserver(this);
ui::ViewAndroid* parent_view = content_view_core->GetViewAndroid();
parent_view->AddChild(&view_);
parent_view->GetLayer()->AddChild(view_.GetLayer());
@@ -2137,15 +2158,6 @@ RenderWidgetHostViewAndroid::GetTouchSelectionControllerClientManager() {
return touch_selection_controller_client_manager_.get();
}
-bool RenderWidgetHostViewAndroid::OnTouchEvent(
- const ui::MotionEventAndroid& event,
- bool for_touch_handle) {
- RecordToolTypeForActionDown(event);
-
- // TODO(jinsukkim): Remove this distinction.
- return for_touch_handle ? OnTouchHandleEvent(event) : OnTouchEvent(event);
-}
-
bool RenderWidgetHostViewAndroid::OnMouseEvent(
const ui::MotionEventAndroid& event) {
RecordToolTypeForActionDown(event);
@@ -2203,6 +2215,9 @@ void RenderWidgetHostViewAndroid::OnRootWindowVisibilityChanged(bool visible) {
}
void RenderWidgetHostViewAndroid::OnAttachedToWindow() {
+ if (!content_view_core_)
+ return;
+
if (is_showing_)
StartObservingRootWindow();
DCHECK(view_.GetWindowAndroid());
@@ -2233,20 +2248,21 @@ void RenderWidgetHostViewAndroid::OnDetachCompositor() {
delegated_frame_host_->DetachFromCompositor();
}
-void RenderWidgetHostViewAndroid::OnBeginFrame(const cc::BeginFrameArgs& args) {
+void RenderWidgetHostViewAndroid::OnBeginFrame(
+ const viz::BeginFrameArgs& args) {
TRACE_EVENT0("cc,benchmark", "RenderWidgetHostViewAndroid::OnBeginFrame");
if (!host_) {
OnDidNotProduceFrame(
- cc::BeginFrameAck(args.source_id, args.sequence_number, false));
+ viz::BeginFrameAck(args.source_id, args.sequence_number, false));
return;
}
// In sync mode, we disregard missed frame args to ensure that
// SynchronousCompositorBrowserFilter::SyncStateAfterVSync will be called
// during WindowAndroid::WindowBeginFrameSource::OnVSync() observer iteration.
- if (sync_compositor_ && args.type == cc::BeginFrameArgs::MISSED) {
+ if (sync_compositor_ && args.type == viz::BeginFrameArgs::MISSED) {
OnDidNotProduceFrame(
- cc::BeginFrameAck(args.source_id, args.sequence_number, false));
+ viz::BeginFrameAck(args.source_id, args.sequence_number, false));
return;
}
@@ -2261,11 +2277,11 @@ void RenderWidgetHostViewAndroid::OnBeginFrame(const cc::BeginFrameArgs& args) {
SendBeginFrame(args);
} else {
OnDidNotProduceFrame(
- cc::BeginFrameAck(args.source_id, args.sequence_number, false));
+ viz::BeginFrameAck(args.source_id, args.sequence_number, false));
}
}
-const cc::BeginFrameArgs& RenderWidgetHostViewAndroid::LastUsedBeginFrameArgs()
+const viz::BeginFrameArgs& RenderWidgetHostViewAndroid::LastUsedBeginFrameArgs()
const {
return last_begin_frame_args_;
}
@@ -2404,4 +2420,11 @@ void RenderWidgetHostViewAndroid::CreateOverscrollControllerIfPossible() {
overscroll_refresh_handler, compositor, view_.GetDipScale());
}
+void RenderWidgetHostViewAndroid::SetOverscrollControllerForTesting(
+ ui::OverscrollRefreshHandler* overscroll_refresh_handler) {
+ overscroll_controller_ = base::MakeUnique<OverscrollControllerAndroid>(
+ overscroll_refresh_handler, view_.GetWindowAndroid()->GetCompositor(),
+ view_.GetDipScale());
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_android.h b/chromium/content/browser/renderer_host/render_widget_host_view_android.h
index 5ca4c011f33..5b99f6d709e 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
@@ -19,8 +19,8 @@
#include "base/memory/weak_ptr.h"
#include "base/process/process.h"
#include "cc/input/selection.h"
-#include "cc/output/begin_frame_args.h"
-#include "cc/scheduler/begin_frame_source.h"
+#include "components/viz/common/frame_sinks/begin_frame_args.h"
+#include "components/viz/common/frame_sinks/begin_frame_source.h"
#include "components/viz/service/frame_sinks/frame_evictor.h"
#include "content/browser/android/content_view_core_observer.h"
#include "content/browser/renderer_host/input/mouse_wheel_phase_handler.h"
@@ -44,6 +44,7 @@
namespace ui {
class MotionEventAndroid;
+class OverscrollRefreshHandler;
struct DidOverscrollParams;
}
@@ -51,11 +52,13 @@ namespace content {
class ContentViewCore;
class ImeAdapterAndroid;
class OverscrollControllerAndroid;
+class PopupZoomer;
class RenderWidgetHost;
class RenderWidgetHostImpl;
class SelectionPopupController;
class SynchronousCompositorHost;
class SynchronousCompositorClient;
+class TextSuggestionHostAndroid;
class TouchSelectionControllerClientManagerAndroid;
class WebContentsAccessibilityAndroid;
struct NativeWebKeyboardEvent;
@@ -67,6 +70,7 @@ struct ContextMenuParams;
class CONTENT_EXPORT RenderWidgetHostViewAndroid
: public RenderWidgetHostViewBase,
public ui::GestureProviderClient,
+ public ui::ViewAndroidObserver,
public ui::ViewClient,
public ui::WindowAndroidObserver,
public viz::FrameEvictorClient,
@@ -75,7 +79,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
public content::ContentViewCoreObserver,
public content::TextInputManager::Observer,
public ui::DelegatedFrameHostAndroid::Client,
- public cc::BeginFrameObserver {
+ public viz::BeginFrameObserver {
public:
RenderWidgetHostViewAndroid(RenderWidgetHostImpl* widget,
ContentViewCore* content_view_core);
@@ -142,6 +146,8 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
InputEventAckState ack_result) override;
InputEventAckState FilterInputEvent(
const blink::WebInputEvent& input_event) override;
+ InputEventAckState FilterChildGestureEvent(
+ const blink::WebGestureEvent& gesture_event) override;
void GestureEventAck(const blink::WebGestureEvent& event,
InputEventAckState ack_result) override;
BrowserAccessibilityManager* CreateBrowserAccessibilityManager(
@@ -149,11 +155,11 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
bool LockMouse() override;
void UnlockMouse() override;
void DidCreateNewRendererCompositorFrameSink(
- cc::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink)
+ viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink)
override;
void SubmitCompositorFrame(const viz::LocalSurfaceId& local_surface_id,
cc::CompositorFrame frame) override;
- void OnDidNotProduceFrame(const cc::BeginFrameAck& ack) override;
+ void OnDidNotProduceFrame(const viz::BeginFrameAck& ack) override;
void ClearCompositorFrame() override;
void SetIsInVR(bool is_in_vr) override;
bool IsInVR() const override;
@@ -166,7 +172,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
void OnDidNavigateMainFrameToNewPage() override;
void SetNeedsBeginFrames(bool needs_begin_frames) override;
viz::FrameSinkId GetFrameSinkId() override;
- viz::FrameSinkId FrameSinkIdAtPoint(cc::SurfaceHittestDelegate* delegate,
+ viz::FrameSinkId FrameSinkIdAtPoint(viz::SurfaceHittestDelegate* delegate,
const gfx::Point& point,
gfx::Point* transformed_point) override;
void ProcessMouseEvent(const blink::WebMouseEvent& event,
@@ -188,12 +194,15 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
GetTouchSelectionControllerClientManager() override;
// ui::ViewClient implementation.
- bool OnTouchEvent(const ui::MotionEventAndroid& m,
- bool for_touch_handle) override;
+ bool OnTouchEvent(const ui::MotionEventAndroid& m) override;
bool OnMouseEvent(const ui::MotionEventAndroid& m) override;
bool OnMouseWheelEvent(const ui::MotionEventAndroid& event) override;
void OnPhysicalBackingSizeChanged() override;
+ // ui::ViewAndroidObserver implementation:
+ void OnAttachedToWindow() override;
+ void OnDetachedFromWindow() override;
+
// ui::GestureProviderClient implementation.
void OnGestureEvent(const ui::GestureEventData& gesture) override;
@@ -208,8 +217,6 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
// content::ContentViewCoreObserver implementation.
void OnContentViewCoreDestroyed() override;
- void OnAttachedToWindow() override;
- void OnDetachedFromWindow() override;
// viz::FrameEvictor implementation
void EvictDelegatedFrame() override;
@@ -231,14 +238,14 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
std::unique_ptr<ui::TouchHandleDrawable> CreateDrawable() override;
// DelegatedFrameHostAndroid::Client implementation.
- void SetBeginFrameSource(cc::BeginFrameSource* begin_frame_source) override;
+ void SetBeginFrameSource(viz::BeginFrameSource* begin_frame_source) override;
void DidReceiveCompositorFrameAck() override;
void ReclaimResources(
- const std::vector<cc::ReturnedResource>& resources) override;
+ const std::vector<viz::ReturnedResource>& resources) override;
- // cc::BeginFrameObserver implementation.
- void OnBeginFrame(const cc::BeginFrameArgs& args) override;
- const cc::BeginFrameArgs& LastUsedBeginFrameArgs() const override;
+ // viz::BeginFrameObserver implementation.
+ void OnBeginFrame(const viz::BeginFrameArgs& args) override;
+ const viz::BeginFrameArgs& LastUsedBeginFrameArgs() const override;
void OnBeginFrameSourcePausedChanged(bool paused) override;
// Non-virtual methods
@@ -255,13 +262,19 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
void set_ime_adapter(ImeAdapterAndroid* ime_adapter) {
ime_adapter_android_ = ime_adapter;
}
+ void set_popup_zoomer(PopupZoomer* popup_zoomer) {
+ popup_zoomer_ = popup_zoomer;
+ }
void set_selection_popup_controller(SelectionPopupController* controller) {
selection_popup_controller_ = controller;
}
+ void set_text_suggestion_host(
+ TextSuggestionHostAndroid* text_suggestion_host) {
+ text_suggestion_host_ = text_suggestion_host;
+ }
base::WeakPtr<RenderWidgetHostViewAndroid> GetWeakPtrAndroid();
- bool OnTouchEvent(const ui::MotionEvent& event);
bool OnTouchHandleEvent(const ui::MotionEvent& event);
int GetTouchHandleHeight();
void ResetGestureDetection();
@@ -315,6 +328,9 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
void SetSelectionControllerClientForTesting(
std::unique_ptr<ui::TouchSelectionControllerClient> client);
+ void SetOverscrollControllerForTesting(
+ ui::OverscrollRefreshHandler* overscroll_refresh_handler);
+
void GotFocus();
void LostFocus();
@@ -350,11 +366,11 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
};
void AddBeginFrameRequest(BeginFrameRequestType request);
void ClearBeginFrameRequest(BeginFrameRequestType request);
- void AcknowledgeBeginFrame(const cc::BeginFrameAck& ack);
+ void AcknowledgeBeginFrame(const viz::BeginFrameAck& ack);
void StartObservingRootWindow();
void StopObservingRootWindow();
void SendBeginFramePaused();
- void SendBeginFrame(cc::BeginFrameArgs args);
+ void SendBeginFrame(viz::BeginFrameArgs args);
bool Animate(base::TimeTicks frame_time);
void RequestDisallowInterceptTouchEvent();
@@ -377,8 +393,8 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
RenderWidgetHostImpl* host_;
// The begin frame source being observed. Null if none.
- cc::BeginFrameSource* begin_frame_source_;
- cc::BeginFrameArgs last_begin_frame_args_;
+ viz::BeginFrameSource* begin_frame_source_;
+ viz::BeginFrameArgs last_begin_frame_args_;
bool begin_frame_paused_ = false;
// Indicates whether and for what reason a request for begin frames has been
@@ -399,7 +415,9 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
ContentViewCore* content_view_core_;
ImeAdapterAndroid* ime_adapter_android_;
+ PopupZoomer* popup_zoomer_;
SelectionPopupController* selection_popup_controller_;
+ TextSuggestionHostAndroid* text_suggestion_host_;
// The background color of the widget.
SkColor background_color_;
@@ -412,7 +430,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
// Manages the Compositor Frames received from the renderer.
std::unique_ptr<ui::DelegatedFrameHostAndroid> delegated_frame_host_;
- std::vector<cc::ReturnedResource> surface_returned_resources_;
+ std::vector<viz::ReturnedResource> surface_returned_resources_;
// The most recent surface size that was pushed to the surface layer.
gfx::Size current_surface_size_;
@@ -461,7 +479,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
gfx::Point prev_mousedown_point_;
int left_click_count_ = 0;
- cc::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink_ =
+ viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink_ =
nullptr;
base::ObserverList<DestructionObserver> destruction_observers_;
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 1ff9dfd8476..5c4591f23a1 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
@@ -19,10 +19,10 @@
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "cc/layers/layer.h"
-#include "cc/output/copy_output_request.h"
-#include "cc/output/copy_output_result.h"
#include "cc/trees/layer_tree_settings.h"
#include "components/viz/common/gl_helper.h"
+#include "components/viz/common/quads/copy_output_request.h"
+#include "components/viz/common/quads/copy_output_result.h"
#include "components/viz/common/quads/texture_mailbox.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
#include "content/browser/accessibility/browser_accessibility_state_impl.h"
@@ -61,7 +61,7 @@
#include "services/service_manager/public/cpp/interface_provider.h"
#include "services/ui/public/interfaces/window_manager_constants.mojom.h"
#include "third_party/WebKit/public/platform/WebInputEvent.h"
-#include "third_party/WebKit/public/web/WebCompositionUnderline.h"
+#include "third_party/WebKit/public/web/WebImeTextSpan.h"
#include "ui/accessibility/platform/aura_window_properties.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/client/cursor_client.h"
@@ -113,7 +113,7 @@
#include "ui/gfx/gdi_util.h"
#endif
-#if defined(USE_X11) && !defined(OS_CHROMEOS)
+#if defined(USE_X11)
#include "content/browser/accessibility/browser_accessibility_auralinux.h"
#endif
@@ -157,6 +157,11 @@ class WinScreenKeyboardObserver : public ui::OnScreenKeyboardObserver {
host_view_->SetInsets(gfx::Insets());
}
+ ~WinScreenKeyboardObserver() override {
+ if (auto* instance = ui::OnScreenKeyboardDisplayManager::GetInstance())
+ instance->RemoveObserver(this);
+ }
+
// base::win::OnScreenKeyboardObserver overrides.
void OnKeyboardVisible(const gfx::Rect& keyboard_rect_pixels) override {
gfx::Point location_in_pixels =
@@ -583,7 +588,7 @@ gfx::NativeViewAccessible RenderWidgetHostViewAura::GetNativeViewAccessible() {
host_->GetOrCreateRootBrowserAccessibilityManager();
if (manager)
return ToBrowserAccessibilityWin(manager->GetRoot())->GetCOM();
-#elif defined(USE_X11) && !defined(OS_CHROMEOS)
+#elif defined(USE_X11)
BrowserAccessibilityManager* manager =
host_->GetOrCreateRootBrowserAccessibilityManager();
if (manager)
@@ -904,7 +909,7 @@ void RenderWidgetHostViewAura::OnLegacyWindowDestroyed() {
#endif
void RenderWidgetHostViewAura::DidCreateNewRendererCompositorFrameSink(
- cc::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink) {
+ viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink) {
renderer_compositor_frame_sink_ = renderer_compositor_frame_sink;
if (delegated_frame_host_) {
delegated_frame_host_->DidCreateNewRendererCompositorFrameSink(
@@ -954,7 +959,7 @@ void RenderWidgetHostViewAura::SubmitCompositorFrame(
}
void RenderWidgetHostViewAura::OnDidNotProduceFrame(
- const cc::BeginFrameAck& ack) {
+ const viz::BeginFrameAck& ack) {
if (delegated_frame_host_)
delegated_frame_host_->DidNotProduceFrame(ack);
}
@@ -1197,7 +1202,7 @@ void RenderWidgetHostViewAura::SetCompositionText(
// TODO(suzhe): due to a bug of webkit, we can't use selection range with
// composition string. See: https://bugs.webkit.org/show_bug.cgi?id=37788
text_input_manager_->GetActiveWidget()->ImeSetComposition(
- composition.text, composition.underlines, gfx::Range::InvalidRange(),
+ composition.text, composition.ime_text_spans, gfx::Range::InvalidRange(),
composition.selection.end(), composition.selection.end());
has_composition_text_ = !composition.text.empty();
@@ -1224,8 +1229,7 @@ void RenderWidgetHostViewAura::InsertText(const base::string16& text) {
if (text_input_manager_ && text_input_manager_->GetActiveWidget()) {
if (text.length())
text_input_manager_->GetActiveWidget()->ImeCommitText(
- text, std::vector<ui::CompositionUnderline>(),
- gfx::Range::InvalidRange(), 0);
+ text, std::vector<ui::ImeTextSpan>(), gfx::Range::InvalidRange(), 0);
else if (has_composition_text_)
text_input_manager_->GetActiveWidget()->ImeFinishComposingText(false);
}
@@ -1601,11 +1605,11 @@ bool RenderWidgetHostViewAura::HasHitTestMask() const {
void RenderWidgetHostViewAura::GetHitTestMask(gfx::Path* mask) const {
}
-void RenderWidgetHostViewAura::OnWindowSurfaceChanged(
+void RenderWidgetHostViewAura::OnFirstSurfaceActivation(
const viz::SurfaceInfo& surface_info) {
if (!is_guest_view_hack_)
return;
- host_->GetView()->OnSurfaceChanged(surface_info);
+ host_->GetView()->OnFirstSurfaceActivation(surface_info);
}
////////////////////////////////////////////////////////////////////////////////
@@ -1629,21 +1633,24 @@ void RenderWidgetHostViewAura::OnMouseEvent(ui::MouseEvent* event) {
}
viz::FrameSinkId RenderWidgetHostViewAura::FrameSinkIdAtPoint(
- cc::SurfaceHittestDelegate* delegate,
+ viz::SurfaceHittestDelegate* delegate,
const gfx::Point& point,
gfx::Point* transformed_point) {
DCHECK(device_scale_factor_ != 0.0f);
+ // TODO: this shouldn't be used with aura-mus, so that the null check so
+ // go away and become a DCHECK.
+ if (!delegated_frame_host_) {
+ *transformed_point = point;
+ return GetFrameSinkId();
+ }
+
// The surface hittest happens in device pixels, so we need to convert the
// |point| from DIPs to pixels before hittesting.
gfx::Point point_in_pixels =
gfx::ConvertPointToPixel(device_scale_factor_, point);
- // TODO: this shouldn't be used with aura-mus, so that the null check so
- // go away and become a DCHECK.
- viz::SurfaceId id = delegated_frame_host_
- ? delegated_frame_host_->SurfaceIdAtPoint(
- delegate, point_in_pixels, transformed_point)
- : viz::SurfaceId();
+ viz::SurfaceId id = delegated_frame_host_->SurfaceIdAtPoint(
+ delegate, point_in_pixels, transformed_point);
*transformed_point =
gfx::ConvertPointToDIP(device_scale_factor_, *transformed_point);
@@ -1845,7 +1852,7 @@ void RenderWidgetHostViewAura::OnWindowFocused(aura::Window* gained_focus,
// RenderWidgetHostViewAura, aura::WindowTreeHostObserver implementation:
void RenderWidgetHostViewAura::OnHostMovedInPixels(
- const aura::WindowTreeHost* host,
+ aura::WindowTreeHost* host,
const gfx::Point& new_origin_in_pixels) {
TRACE_EVENT1("ui", "RenderWidgetHostViewAura::OnHostMovedInPixels",
"new_origin_in_pixels", new_origin_in_pixels.ToString());
@@ -1897,14 +1904,6 @@ RenderWidgetHostViewAura::~RenderWidgetHostViewAura() {
// RenderWidgetHostViewAura::OnWindowDestroying and the pointer should
// be set to NULL.
DCHECK(!legacy_render_widget_host_HWND_);
- if (virtual_keyboard_requested_) {
- DCHECK(keyboard_observer_.get());
- ui::OnScreenKeyboardDisplayManager* osk_display_manager =
- ui::OnScreenKeyboardDisplayManager::GetInstance();
- DCHECK(osk_display_manager);
- osk_display_manager->RemoveObserver(keyboard_observer_.get());
- }
-
#endif
if (text_input_manager_)
@@ -2156,8 +2155,6 @@ void RenderWidgetHostViewAura::InternalSetBounds(const gfx::Rect& rect) {
// a Window::SetBoundsInternal call.
if (!in_bounds_changed_)
window_->SetBounds(rect);
- if (IsMus())
- local_surface_id_ = aura::WindowMus::Get(window_)->GetLocalSurfaceId();
host_->WasResized();
if (delegated_frame_host_)
delegated_frame_host_->WasResized();
@@ -2319,7 +2316,7 @@ viz::FrameSinkId RenderWidgetHostViewAura::GetFrameSinkId() {
}
viz::LocalSurfaceId RenderWidgetHostViewAura::GetLocalSurfaceId() const {
- return local_surface_id_;
+ return window_->GetLocalSurfaceId();
}
viz::SurfaceId RenderWidgetHostViewAura::SurfaceIdForTesting() const {
@@ -2393,7 +2390,7 @@ void RenderWidgetHostViewAura::OnTextSelectionChanged(
if (!focused_view)
return;
-#if defined(USE_X11) && !defined(OS_CHROMEOS)
+#if defined(USE_X11)
const TextInputManager::TextSelection* selection =
GetTextInputManager()->GetTextSelection(focused_view);
if (selection->selected_text().length()) {
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 83b22a13a2c..243679d6c55 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
@@ -21,8 +21,8 @@
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "build/build_config.h"
-#include "cc/output/begin_frame_args.h"
-#include "cc/scheduler/begin_frame_source.h"
+#include "components/viz/common/frame_sinks/begin_frame_args.h"
+#include "components/viz/common/frame_sinks/begin_frame_source.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
#include "content/browser/compositor/image_transport_factory.h"
#include "content/browser/compositor/owned_mailbox.h"
@@ -79,7 +79,7 @@ class TouchSelectionControllerClientAura;
// RenderWidgetHostView class hierarchy described in render_widget_host_view.h.
class CONTENT_EXPORT RenderWidgetHostViewAura
: public RenderWidgetHostViewBase,
- NON_EXPORTED_BASE(public RenderWidgetHostViewEventHandler::Delegate),
+ public RenderWidgetHostViewEventHandler::Delegate,
public TextInputManager::Observer,
public ui::TextInputClient,
public display::DisplayObserver,
@@ -171,17 +171,17 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
bool LockMouse() override;
void UnlockMouse() override;
void DidCreateNewRendererCompositorFrameSink(
- cc::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink)
+ viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink)
override;
void SubmitCompositorFrame(const viz::LocalSurfaceId& local_surface_id,
cc::CompositorFrame frame) override;
- void OnDidNotProduceFrame(const cc::BeginFrameAck& ack) override;
+ void OnDidNotProduceFrame(const viz::BeginFrameAck& ack) override;
void ClearCompositorFrame() override;
void DidStopFlinging() override;
void OnDidNavigateMainFrameToNewPage() override;
viz::FrameSinkId GetFrameSinkId() override;
viz::LocalSurfaceId GetLocalSurfaceId() const override;
- viz::FrameSinkId FrameSinkIdAtPoint(cc::SurfaceHittestDelegate* delegate,
+ viz::FrameSinkId FrameSinkIdAtPoint(viz::SurfaceHittestDelegate* delegate,
const gfx::Point& point,
gfx::Point* transformed_point) override;
void ProcessMouseEvent(const blink::WebMouseEvent& event,
@@ -258,7 +258,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
void OnWindowTargetVisibilityChanged(bool visible) override;
bool HasHitTestMask() const override;
void GetHitTestMask(gfx::Path* mask) const override;
- void OnWindowSurfaceChanged(const viz::SurfaceInfo& surface_info) override;
+ void OnFirstSurfaceActivation(const viz::SurfaceInfo& surface_info) override;
// Overridden from ui::EventHandler:
void OnKeyEvent(ui::KeyEvent* event) override;
@@ -278,7 +278,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
aura::Window* lost_focus) override;
// Overridden from aura::WindowTreeHostObserver:
- void OnHostMovedInPixels(const aura::WindowTreeHost* host,
+ void OnHostMovedInPixels(aura::WindowTreeHost* host,
const gfx::Point& new_origin_in_pixels) override;
#if defined(OS_WIN)
@@ -602,7 +602,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
float device_scale_factor_;
- cc::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink_ =
+ viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink_ =
nullptr;
// While this is a ui::EventHandler for targetting, |event_handler_| actually
@@ -610,7 +610,6 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
std::unique_ptr<RenderWidgetHostViewEventHandler> event_handler_;
viz::FrameSinkId frame_sink_id_;
- viz::LocalSurfaceId local_surface_id_;
std::unique_ptr<CursorManager> cursor_manager_;
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 41400782a1f..122f0acfd13 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
@@ -23,19 +23,19 @@
#include "base/test/simple_test_tick_clock.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
-#include "cc/output/begin_frame_args.h"
#include "cc/output/compositor_frame.h"
#include "cc/output/compositor_frame_metadata.h"
-#include "cc/output/copy_output_request.h"
-#include "cc/surfaces/surface.h"
-#include "cc/test/begin_frame_args_test.h"
-#include "cc/test/fake_external_begin_frame_source.h"
-#include "cc/test/fake_surface_observer.h"
+#include "components/viz/common/frame_sinks/begin_frame_args.h"
#include "components/viz/common/gl_helper.h"
+#include "components/viz/common/quads/copy_output_request.h"
#include "components/viz/common/surfaces/local_surface_id_allocator.h"
#include "components/viz/service/display_embedder/server_shared_bitmap_manager.h"
#include "components/viz/service/display_embedder/shared_bitmap_allocation_notifier_impl.h"
#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
+#include "components/viz/service/surfaces/surface.h"
+#include "components/viz/test/begin_frame_args_test.h"
+#include "components/viz/test/fake_external_begin_frame_source.h"
+#include "components/viz/test/fake_surface_observer.h"
#include "content/browser/browser_thread_impl.h"
#include "content/browser/compositor/test/no_transport_image_transport_factory.h"
#include "content/browser/frame_host/render_widget_host_view_guest.h"
@@ -65,6 +65,7 @@
#include "content/public/test/mock_render_process_host.h"
#include "content/public/test/test_browser_context.h"
#include "content/test/fake_renderer_compositor_frame_sink.h"
+#include "content/test/mock_widget_impl.h"
#include "content/test/test_render_view_host.h"
#include "content/test/test_web_contents.h"
#include "ipc/ipc_message.h"
@@ -150,21 +151,21 @@ class TestOverscrollDelegate : public OverscrollControllerDelegate {
OverscrollMode current_mode() const { return current_mode_; }
OverscrollMode completed_mode() const { return completed_mode_; }
+ const std::vector<OverscrollMode>& historical_modes() const {
+ return historical_modes_;
+ }
float delta_x() const { return delta_x_; }
float delta_y() const { return delta_y_; }
void Reset() {
current_mode_ = OVERSCROLL_NONE;
completed_mode_ = OVERSCROLL_NONE;
+ historical_modes_.clear();
delta_x_ = delta_y_ = 0.f;
}
private:
// Overridden from OverscrollControllerDelegate:
- gfx::Size GetVisibleSize() const override {
- return view_->IsShowing() ? view_->GetViewBounds().size() : gfx::Size();
- }
-
gfx::Size GetDisplaySize() const override {
return display::Screen::GetScreen()
->GetDisplayNearestView(view_->GetNativeView())
@@ -188,6 +189,7 @@ class TestOverscrollDelegate : public OverscrollControllerDelegate {
OverscrollSource source) override {
EXPECT_EQ(current_mode_, old_mode);
current_mode_ = new_mode;
+ historical_modes_.push_back(new_mode);
delta_x_ = delta_y_ = 0.f;
}
@@ -199,6 +201,8 @@ class TestOverscrollDelegate : public OverscrollControllerDelegate {
base::Optional<float> delta_cap_;
OverscrollMode current_mode_;
OverscrollMode completed_mode_;
+ std::vector<OverscrollMode> historical_modes_;
+
float delta_x_;
float delta_y_;
@@ -437,10 +441,10 @@ class FakeRenderWidgetHostViewAura : public RenderWidgetHostViewAura {
~FakeRenderWidgetHostViewAura() override {}
void CreateNewRendererCompositorFrameSink() {
- cc::mojom::CompositorFrameSinkPtr sink;
- cc::mojom::CompositorFrameSinkRequest sink_request =
+ viz::mojom::CompositorFrameSinkPtr sink;
+ viz::mojom::CompositorFrameSinkRequest sink_request =
mojo::MakeRequest(&sink);
- cc::mojom::CompositorFrameSinkClientRequest client_request =
+ viz::mojom::CompositorFrameSinkClientRequest client_request =
mojo::MakeRequest(&renderer_compositor_frame_sink_ptr_);
renderer_compositor_frame_sink_ =
base::MakeUnique<FakeRendererCompositorFrameSink>(
@@ -464,7 +468,7 @@ class FakeRenderWidgetHostViewAura : public RenderWidgetHostViewAura {
window()->GetHost()->compositor());
}
- void InterceptCopyOfOutput(std::unique_ptr<cc::CopyOutputRequest> request) {
+ void InterceptCopyOfOutput(std::unique_ptr<viz::CopyOutputRequest> request) {
last_copy_request_ = std::move(request);
if (last_copy_request_->has_texture_mailbox()) {
// Give the resulting texture a size.
@@ -490,7 +494,7 @@ class FakeRenderWidgetHostViewAura : public RenderWidgetHostViewAura {
return GetDelegatedFrameHost()->ReleasedFrontLockActiveForTesting();
}
- void ReclaimResources(const std::vector<cc::ReturnedResource>& resources) {
+ void ReclaimResources(const std::vector<viz::ReturnedResource>& resources) {
GetDelegatedFrameHost()->ReclaimResources(resources);
}
@@ -508,14 +512,14 @@ class FakeRenderWidgetHostViewAura : public RenderWidgetHostViewAura {
}
gfx::Size last_frame_size_;
- std::unique_ptr<cc::CopyOutputRequest> last_copy_request_;
+ std::unique_ptr<viz::CopyOutputRequest> last_copy_request_;
FakeWindowEventDispatcher* dispatcher_;
std::unique_ptr<FakeRendererCompositorFrameSink>
renderer_compositor_frame_sink_;
private:
FakeDelegatedFrameHostClientAura* delegated_frame_host_client_;
- cc::mojom::CompositorFrameSinkClientPtr renderer_compositor_frame_sink_ptr_;
+ viz::mojom::CompositorFrameSinkClientPtr renderer_compositor_frame_sink_ptr_;
DISALLOW_COPY_AND_ASSIGN(FakeRenderWidgetHostViewAura);
};
@@ -557,13 +561,7 @@ class MockWindowObserver : public aura::WindowObserver {
class MockRenderWidgetHostImpl : public RenderWidgetHostImpl {
public:
- MockRenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
- RenderProcessHost* process,
- int32_t routing_id)
- : RenderWidgetHostImpl(delegate, process, routing_id, false) {
- set_renderer_initialized(true);
- lastWheelOrTouchEventLatencyInfo = ui::LatencyInfo();
- }
+ ~MockRenderWidgetHostImpl() override {}
// Extracts |latency_info| for wheel event, and stores it in
// |lastWheelOrTouchEventLatencyInfo|.
@@ -585,7 +583,35 @@ class MockRenderWidgetHostImpl : public RenderWidgetHostImpl {
lastWheelOrTouchEventLatencyInfo = ui::LatencyInfo(ui_latency);
}
+ static MockRenderWidgetHostImpl* Create(RenderWidgetHostDelegate* delegate,
+ RenderProcessHost* process,
+ int32_t routing_id) {
+ mojom::WidgetPtr widget;
+ std::unique_ptr<MockWidgetImpl> widget_impl =
+ base::MakeUnique<MockWidgetImpl>(mojo::MakeRequest(&widget));
+
+ return new MockRenderWidgetHostImpl(delegate, process, routing_id,
+ std::move(widget_impl),
+ std::move(widget));
+ }
ui::LatencyInfo lastWheelOrTouchEventLatencyInfo;
+
+ private:
+ MockRenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
+ RenderProcessHost* process,
+ int32_t routing_id,
+ std::unique_ptr<MockWidgetImpl> widget_impl,
+ mojom::WidgetPtr widget)
+ : RenderWidgetHostImpl(delegate,
+ process,
+ routing_id,
+ std::move(widget),
+ false),
+ widget_impl_(std::move(widget_impl)) {
+ lastWheelOrTouchEventLatencyInfo = ui::LatencyInfo();
+ }
+
+ std::unique_ptr<MockWidgetImpl> widget_impl_;
};
const WebInputEvent* GetInputEventFromMessage(const IPC::Message& message) {
@@ -636,8 +662,8 @@ class RenderWidgetHostViewAuraTest : public testing::Test {
int32_t routing_id = process_host_->GetNextRoutingID();
delegates_.push_back(base::WrapUnique(new MockRenderWidgetHostDelegate));
- parent_host_ = new RenderWidgetHostImpl(delegates_.back().get(),
- process_host_, routing_id, false);
+ parent_host_ = MockRenderWidgetHostImpl::Create(delegates_.back().get(),
+ process_host_, routing_id);
delegates_.back()->set_widget_host(parent_host_);
parent_view_ =
new RenderWidgetHostViewAura(parent_host_, is_guest_view_hack_);
@@ -648,8 +674,8 @@ class RenderWidgetHostViewAuraTest : public testing::Test {
routing_id = process_host_->GetNextRoutingID();
delegates_.push_back(base::WrapUnique(new MockRenderWidgetHostDelegate));
- widget_host_ = new MockRenderWidgetHostImpl(delegates_.back().get(),
- process_host_, routing_id);
+ widget_host_ = MockRenderWidgetHostImpl::Create(delegates_.back().get(),
+ process_host_, routing_id);
delegates_.back()->set_widget_host(widget_host_);
widget_host_->Init();
view_ = new FakeRenderWidgetHostViewAura(widget_host_, is_guest_view_hack_);
@@ -762,7 +788,8 @@ class RenderWidgetHostViewAuraTest : public testing::Test {
void EnableWheelScrollLatching() {
feature_list_.InitFromCommandLine(
- features::kTouchpadAndWheelScrollLatching.name, "");
+ features::kTouchpadAndWheelScrollLatching.name,
+ features::kMojoInputMessages.name);
}
void DisableWheelScrollLatching() {
@@ -1629,14 +1656,15 @@ TEST_F(RenderWidgetHostViewAuraTest, SetCompositionText) {
composition_text.text = base::ASCIIToUTF16("|a|b");
// Focused segment
- composition_text.underlines.push_back(
- ui::CompositionUnderline(0, 3, 0xff000000, true, 0x78563412));
+ composition_text.ime_text_spans.push_back(ui::ImeTextSpan(
+ ui::ImeTextSpan::Type::kComposition, 0, 3, 0xff000000, true, 0x78563412));
// Non-focused segment, with different background color.
- composition_text.underlines.push_back(
- ui::CompositionUnderline(3, 4, 0xff000000, false, 0xefcdab90));
+ composition_text.ime_text_spans.push_back(
+ ui::ImeTextSpan(ui::ImeTextSpan::Type::kComposition, 3, 4, 0xff000000,
+ false, 0xefcdab90));
- const ui::CompositionUnderlines& underlines = composition_text.underlines;
+ const ui::ImeTextSpans& ime_text_spans = composition_text.ime_text_spans;
// Caret is at the end. (This emulates Japanese MSIME 2007 and later)
composition_text.selection = gfx::Range(4);
@@ -1653,15 +1681,17 @@ TEST_F(RenderWidgetHostViewAuraTest, SetCompositionText) {
InputMsg_ImeSetComposition::Read(msg, &params);
// composition text
EXPECT_EQ(composition_text.text, std::get<0>(params));
- // underlines
- ASSERT_EQ(underlines.size(), std::get<1>(params).size());
- for (size_t i = 0; i < underlines.size(); ++i) {
- EXPECT_EQ(underlines[i].start_offset,
+ // ime spans
+ ASSERT_EQ(ime_text_spans.size(), std::get<1>(params).size());
+ for (size_t i = 0; i < ime_text_spans.size(); ++i) {
+ EXPECT_EQ(ime_text_spans[i].start_offset,
std::get<1>(params)[i].start_offset);
- EXPECT_EQ(underlines[i].end_offset, std::get<1>(params)[i].end_offset);
- EXPECT_EQ(underlines[i].color, std::get<1>(params)[i].color);
- EXPECT_EQ(underlines[i].thick, std::get<1>(params)[i].thick);
- EXPECT_EQ(underlines[i].background_color,
+ EXPECT_EQ(ime_text_spans[i].end_offset,
+ std::get<1>(params)[i].end_offset);
+ EXPECT_EQ(ime_text_spans[i].underline_color,
+ std::get<1>(params)[i].underline_color);
+ EXPECT_EQ(ime_text_spans[i].thick, std::get<1>(params)[i].thick);
+ EXPECT_EQ(ime_text_spans[i].background_color,
std::get<1>(params)[i].background_color);
}
EXPECT_EQ(gfx::Range::InvalidRange(), std::get<2>(params));
@@ -1685,12 +1715,13 @@ TEST_F(RenderWidgetHostViewAuraTest, FinishCompositionByMouse) {
composition_text.text = base::ASCIIToUTF16("|a|b");
// Focused segment
- composition_text.underlines.push_back(
- ui::CompositionUnderline(0, 3, 0xff000000, true, 0x78563412));
+ composition_text.ime_text_spans.push_back(ui::ImeTextSpan(
+ ui::ImeTextSpan::Type::kComposition, 0, 3, 0xff000000, true, 0x78563412));
// Non-focused segment, with different background color.
- composition_text.underlines.push_back(
- ui::CompositionUnderline(3, 4, 0xff000000, false, 0xefcdab90));
+ composition_text.ime_text_spans.push_back(
+ ui::ImeTextSpan(ui::ImeTextSpan::Type::kComposition, 3, 4, 0xff000000,
+ false, 0xefcdab90));
// Caret is at the end. (This emulates Japanese MSIME 2007 and later)
composition_text.selection = gfx::Range(4);
@@ -2439,13 +2470,13 @@ cc::CompositorFrame MakeDelegatedFrame(float scale_factor,
gfx::Rect damage) {
cc::CompositorFrame frame;
frame.metadata.device_scale_factor = scale_factor;
- frame.metadata.begin_frame_ack = cc::BeginFrameAck(0, 1, true);
+ frame.metadata.begin_frame_ack = viz::BeginFrameAck(0, 1, true);
std::unique_ptr<cc::RenderPass> pass = cc::RenderPass::Create();
pass->SetNew(1, gfx::Rect(size), damage, gfx::Transform());
frame.render_pass_list.push_back(std::move(pass));
if (!size.IsEmpty()) {
- cc::TransferableResource resource;
+ viz::TransferableResource resource;
resource.id = 1;
frame.resource_list.push_back(std::move(resource));
}
@@ -2466,8 +2497,8 @@ TEST_F(RenderWidgetHostViewAuraTest, ReturnedResources) {
sink_->ClearMessages();
// Accumulate some returned resources. This should trigger an IPC.
- std::vector<cc::ReturnedResource> resources;
- cc::ReturnedResource resource;
+ std::vector<viz::ReturnedResource> resources;
+ viz::ReturnedResource resource;
resource.id = 1;
resources.push_back(resource);
view_->renderer_compositor_frame_sink_->Reset();
@@ -2482,11 +2513,11 @@ TEST_F(RenderWidgetHostViewAuraTest, ReturnedResources) {
// This test verifies that when the compositor_frame_sink_id changes, the old
// resources are not returned.
TEST_F(RenderWidgetHostViewAuraTest, TwoOutputSurfaces) {
- cc::FakeSurfaceObserver manager_observer;
+ viz::FakeSurfaceObserver manager_observer;
ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
- cc::SurfaceManager* manager = factory->GetContextFactoryPrivate()
- ->GetFrameSinkManager()
- ->surface_manager();
+ viz::SurfaceManager* manager = factory->GetContextFactoryPrivate()
+ ->GetFrameSinkManager()
+ ->surface_manager();
manager->AddObserver(&manager_observer);
gfx::Size view_size(100, 100);
@@ -2502,7 +2533,7 @@ TEST_F(RenderWidgetHostViewAuraTest, TwoOutputSurfaces) {
// Submit a frame with resources.
cc::CompositorFrame frame = MakeDelegatedFrame(1.f, view_size, view_rect);
- cc::TransferableResource resource;
+ viz::TransferableResource resource;
resource.id = 1;
frame.resource_list.push_back(resource);
view_->SubmitCompositorFrame(kArbitraryLocalSurfaceId, std::move(frame));
@@ -2519,7 +2550,7 @@ TEST_F(RenderWidgetHostViewAuraTest, TwoOutputSurfaces) {
// Report that the surface is drawn to trigger an ACK.
view_->renderer_compositor_frame_sink_->Reset();
- cc::Surface* surface = manager->GetSurfaceForId(view_->surface_id());
+ viz::Surface* surface = manager->GetSurfaceForId(view_->surface_id());
EXPECT_TRUE(surface);
surface->RunDrawCallback();
view_->renderer_compositor_frame_sink_->Flush();
@@ -2617,43 +2648,6 @@ TEST_F(RenderWidgetHostViewAuraTest, SwapNotifiesWindow) {
view_->window_->RemoveObserver(&observer);
}
-// Mirroring the layers for a window should cause Surface destruction to
-// depend on both layers.
-TEST_F(RenderWidgetHostViewAuraTest, MirrorLayers) {
- gfx::Size view_size(100, 100);
- gfx::Rect view_rect(view_size);
- aura::Window* const root = parent_view_->GetNativeView()->GetRootWindow();
-
- view_->InitAsChild(nullptr);
- aura::client::ParentWindowWithContext(
- view_->GetNativeView(), root, gfx::Rect());
- view_->SetSize(view_size);
- view_->Show();
-
- view_->SubmitCompositorFrame(kArbitraryLocalSurfaceId,
- MakeDelegatedFrame(1.f, view_size, view_rect));
- std::unique_ptr<ui::LayerTreeOwner> mirror(wm::MirrorLayers(
- view_->GetNativeView(), false /* sync_bounds */));
-
- viz::SurfaceId id = view_->GetDelegatedFrameHost()->SurfaceIdForTesting();
- if (id.is_valid()) {
- ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
- cc::SurfaceManager* manager = factory->GetContextFactoryPrivate()
- ->GetFrameSinkManager()
- ->surface_manager();
- cc::Surface* surface = manager->GetSurfaceForId(id);
- EXPECT_TRUE(surface);
-
- // An orphaned mirror should not be a destruction dependency.
- EXPECT_EQ(1u, surface->GetDestructionDependencyCount());
-
- // Both layers should be destruction dependencies.
- root->layer()->Add(mirror->root());
- EXPECT_EQ(2u, surface->GetDestructionDependencyCount());
- root->layer()->Remove(mirror->root());
- }
-}
-
// If the view size is larger than the compositor frame then extra layers
// should be created to fill the gap.
TEST_F(RenderWidgetHostViewAuraTest, DelegatedFrameGutter) {
@@ -2664,7 +2658,6 @@ TEST_F(RenderWidgetHostViewAuraTest, DelegatedFrameGutter) {
viz::LocalSurfaceId medium_id = local_surface_id_allocator_.GenerateId();
// Prevent the DelegatedFrameHost from skipping frames.
- // XXX
view_->DisableResizeLock();
view_->InitAsChild(nullptr);
@@ -3149,8 +3142,8 @@ TEST_F(RenderWidgetHostViewAuraTest, DiscardDelegatedFrames) {
for (size_t i = 0; i < renderer_count; ++i) {
int32_t routing_id = process_host_->GetNextRoutingID();
delegates_.push_back(base::WrapUnique(new MockRenderWidgetHostDelegate));
- hosts[i] = new RenderWidgetHostImpl(delegates_.back().get(), process_host_,
- routing_id, false);
+ hosts[i] = MockRenderWidgetHostImpl::Create(delegates_.back().get(),
+ process_host_, routing_id);
delegates_.back()->set_widget_host(hosts[i]);
hosts[i]->Init();
views[i] = new FakeRenderWidgetHostViewAura(hosts[i], false);
@@ -3323,8 +3316,8 @@ TEST_F(RenderWidgetHostViewAuraTest, DiscardDelegatedFramesWithLocking) {
for (size_t i = 0; i < renderer_count; ++i) {
int32_t routing_id = process_host_->GetNextRoutingID();
delegates_.push_back(base::WrapUnique(new MockRenderWidgetHostDelegate));
- hosts[i] = new RenderWidgetHostImpl(delegates_.back().get(), process_host_,
- routing_id, false);
+ hosts[i] = MockRenderWidgetHostImpl::Create(delegates_.back().get(),
+ process_host_, routing_id);
delegates_.back()->set_widget_host(hosts[i]);
hosts[i]->Init();
views[i] = new FakeRenderWidgetHostViewAura(hosts[i], false);
@@ -3395,9 +3388,10 @@ TEST_F(RenderWidgetHostViewAuraTest, DiscardDelegatedFramesWithMemoryPressure) {
// Create a bunch of renderers.
for (size_t i = 0; i < renderer_count; ++i) {
int32_t routing_id = process_host_->GetNextRoutingID();
+
delegates_.push_back(base::WrapUnique(new MockRenderWidgetHostDelegate));
- hosts[i] = new RenderWidgetHostImpl(delegates_.back().get(), process_host_,
- routing_id, false);
+ hosts[i] = MockRenderWidgetHostImpl::Create(delegates_.back().get(),
+ process_host_, routing_id);
delegates_.back()->set_widget_host(hosts[i]);
hosts[i]->Init();
views[i] = new FakeRenderWidgetHostViewAura(hosts[i], false);
@@ -3483,11 +3477,11 @@ TEST_F(RenderWidgetHostViewAuraTest, ForwardsBeginFrameAcks) {
gfx::Rect());
view_->SetSize(view_rect.size());
- cc::FakeSurfaceObserver observer;
+ viz::FakeSurfaceObserver observer;
ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
- cc::SurfaceManager* surface_manager = factory->GetContextFactoryPrivate()
- ->GetFrameSinkManager()
- ->surface_manager();
+ viz::SurfaceManager* surface_manager = factory->GetContextFactoryPrivate()
+ ->GetFrameSinkManager()
+ ->surface_manager();
surface_manager->AddObserver(&observer);
view_->SetNeedsBeginFrames(true);
@@ -3495,7 +3489,7 @@ TEST_F(RenderWidgetHostViewAuraTest, ForwardsBeginFrameAcks) {
{
// Ack from CompositorFrame is forwarded.
- cc::BeginFrameAck ack(source_id, 5, true);
+ viz::BeginFrameAck ack(source_id, 5, true);
cc::CompositorFrame frame = MakeDelegatedFrame(1.f, frame_size, view_rect);
frame.metadata.begin_frame_ack = ack;
view_->SubmitCompositorFrame(local_surface_id, std::move(frame));
@@ -3505,7 +3499,7 @@ TEST_F(RenderWidgetHostViewAuraTest, ForwardsBeginFrameAcks) {
{
// Explicit ack through OnDidNotProduceFrame is forwarded.
- cc::BeginFrameAck ack(source_id, 6, false);
+ viz::BeginFrameAck ack(source_id, 6, false);
view_->OnDidNotProduceFrame(ack);
EXPECT_EQ(ack, observer.last_ack());
}
@@ -3578,10 +3572,10 @@ class RenderWidgetHostViewAuraCopyRequestTest
}
void ReleaseSwappedFrame() {
- std::unique_ptr<cc::CopyOutputRequest> request =
+ std::unique_ptr<viz::CopyOutputRequest> request =
std::move(view_->last_copy_request_);
request->SendTextureResult(view_rect_.size(), request->texture_mailbox(),
- std::unique_ptr<cc::SingleReleaseCallback>());
+ std::unique_ptr<viz::SingleReleaseCallback>());
RunLoopUntilCallback();
}
@@ -3691,7 +3685,7 @@ TEST_F(RenderWidgetHostViewAuraCopyRequestTest, DestroyedAfterCopyRequest) {
SubmitCompositorFrame();
EXPECT_EQ(1, callback_count_);
- std::unique_ptr<cc::CopyOutputRequest> request =
+ std::unique_ptr<viz::CopyOutputRequest> request =
std::move(view_->last_copy_request_);
// Destroy the RenderWidgetHostViewAura and ImageTransportFactory.
@@ -3700,7 +3694,7 @@ TEST_F(RenderWidgetHostViewAuraCopyRequestTest, DestroyedAfterCopyRequest) {
// Send the result after-the-fact. It goes nowhere since DelegatedFrameHost
// has been destroyed.
request->SendTextureResult(view_rect_.size(), request->texture_mailbox(),
- std::unique_ptr<cc::SingleReleaseCallback>());
+ std::unique_ptr<viz::SingleReleaseCallback>());
// Because the copy request callback may be holding state within it, that
// state must handle the RWHVA and ImageTransportFactory going away before the
@@ -3721,7 +3715,7 @@ TEST_F(RenderWidgetHostViewAuraCopyRequestTest, PresentTime) {
// Start our fake clock from a non-zero, but not an even multiple of the
// interval, value to differentiate it from our initialization state.
const base::TimeDelta kDefaultInterval =
- cc::BeginFrameArgs::DefaultInterval();
+ viz::BeginFrameArgs::DefaultInterval();
tick_clock_->Advance(kDefaultInterval / 3);
// Swap the first frame without any vsync information.
@@ -4178,7 +4172,8 @@ void RenderWidgetHostViewAuraOverscrollTest::WheelScrollOverscrollToggle() {
EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
// Continue to scroll in the reverse direction enough to initiate overscroll
- // in that direction.
+ // in that direction. However, overscroll should not be initiated as the
+ // overscroll mode is locked to east mode.
SimulateWheelEventPossiblyIncludingPhase(-55, 0, 0, true,
WebMouseWheelEvent::kPhaseChanged);
if (wheel_scrolling_mode_ == kAsyncWheelEvents) {
@@ -4205,11 +4200,11 @@ void RenderWidgetHostViewAuraOverscrollTest::WheelScrollOverscrollToggle() {
ExpectGestureScrollEndForWheelScrolling(true);
}
- EXPECT_EQ(OVERSCROLL_WEST, overscroll_mode());
- EXPECT_EQ(OverscrollSource::TOUCHPAD, overscroll_source());
- EXPECT_EQ(OVERSCROLL_WEST, overscroll_delegate()->current_mode());
+ EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
+ EXPECT_EQ(OverscrollSource::NONE, overscroll_source());
+ EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
EXPECT_EQ(-75.f, overscroll_delta_x());
- EXPECT_EQ(-25.f, overscroll_delegate()->delta_x());
+ EXPECT_EQ(0.f, overscroll_delegate()->delta_x());
EXPECT_EQ(0.f, overscroll_delegate()->delta_y());
}
TEST_F(RenderWidgetHostViewAuraOverscrollTest, WheelScrollOverscrollToggle) {
@@ -4484,7 +4479,7 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest, GestureScrollOverscrolls) {
EXPECT_EQ(55.f, overscroll_delta_x());
EXPECT_EQ(-5.f, overscroll_delta_y());
EXPECT_EQ(5.f, overscroll_delegate()->delta_x());
- EXPECT_EQ(-5.f, overscroll_delegate()->delta_y());
+ EXPECT_EQ(0.f, overscroll_delegate()->delta_y());
EXPECT_EQ(2U, GetSentMessageCountAndResetSink());
// Send another gesture update event. This event should be consumed by the
@@ -4497,7 +4492,7 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest, GestureScrollOverscrolls) {
EXPECT_EQ(65.f, overscroll_delta_x());
EXPECT_EQ(-10.f, overscroll_delta_y());
EXPECT_EQ(15.f, overscroll_delegate()->delta_x());
- EXPECT_EQ(-10.f, overscroll_delegate()->delta_y());
+ EXPECT_EQ(0.f, overscroll_delegate()->delta_y());
EXPECT_EQ(0U, sink_->message_count());
// Now send a scroll end. This should cancel the overscroll gesture, and send
@@ -4536,7 +4531,7 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest, OverscrollDeltaCap) {
EXPECT_EQ(55.f, overscroll_delta_x());
EXPECT_EQ(-5.f, overscroll_delta_y());
EXPECT_EQ(5.f, overscroll_delegate()->delta_x());
- EXPECT_EQ(-5.f, overscroll_delegate()->delta_y());
+ EXPECT_EQ(0.f, overscroll_delegate()->delta_y());
EXPECT_EQ(2U, GetSentMessageCountAndResetSink());
// Scroll beyond overscroll cap. Overscroll delta should not surpass the cap.
@@ -4547,7 +4542,7 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest, OverscrollDeltaCap) {
EXPECT_EQ(100.f, overscroll_delta_x());
EXPECT_EQ(-10.f, overscroll_delta_y());
EXPECT_EQ(50.f, overscroll_delegate()->delta_x());
- EXPECT_EQ(-10.f, overscroll_delegate()->delta_y());
+ EXPECT_EQ(0.f, overscroll_delegate()->delta_y());
EXPECT_EQ(0U, sink_->message_count());
// Scroll back a bit. Since the extra scroll after cap in previous step is
@@ -4559,7 +4554,7 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest, OverscrollDeltaCap) {
EXPECT_EQ(90.f, overscroll_delta_x());
EXPECT_EQ(-15.f, overscroll_delta_y());
EXPECT_EQ(40.f, overscroll_delegate()->delta_x());
- EXPECT_EQ(-15.f, overscroll_delegate()->delta_y());
+ EXPECT_EQ(0.f, overscroll_delegate()->delta_y());
EXPECT_EQ(0U, sink_->message_count());
// End overscrolling.
@@ -4860,7 +4855,7 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest,
EXPECT_EQ(OVERSCROLL_EAST, overscroll_delegate()->current_mode());
EXPECT_EQ(55.f, overscroll_delta_x());
EXPECT_EQ(5.f, overscroll_delegate()->delta_x());
- EXPECT_EQ(-5.f, overscroll_delegate()->delta_y());
+ EXPECT_EQ(0.f, overscroll_delegate()->delta_y());
// Send end event.
SimulateGestureEvent(blink::WebInputEvent::kGestureScrollEnd,
@@ -4900,7 +4895,7 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest,
EXPECT_EQ(OVERSCROLL_EAST, overscroll_delegate()->current_mode());
EXPECT_EQ(235.f, overscroll_delta_x());
EXPECT_EQ(185.f, overscroll_delegate()->delta_x());
- EXPECT_EQ(-5.f, overscroll_delegate()->delta_y());
+ EXPECT_EQ(0.f, overscroll_delegate()->delta_y());
// Send end event.
SimulateGestureEvent(blink::WebInputEvent::kGestureScrollEnd,
@@ -4953,6 +4948,65 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest, OverscrollDirectionChange) {
EXPECT_EQ(OverscrollSource::NONE, overscroll_source());
}
+TEST_F(RenderWidgetHostViewAuraOverscrollTest,
+ CompleteOverscrollOnGestureScrollEndAck) {
+ SetUpOverscrollEnvironment();
+
+ SimulateGestureEvent(WebInputEvent::kGestureScrollBegin,
+ blink::kWebGestureDeviceTouchscreen);
+ SendScrollBeginAckIfNeeded(INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
+ EXPECT_EQ(OverscrollSource::NONE, overscroll_source());
+ EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
+ EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->completed_mode());
+ EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+
+ // Send GSU to trigger overscroll.
+ SimulateGestureScrollUpdateEvent(300, -5, 0);
+ // Send GSE immediately before ACKing GSU.
+ SimulateGestureEvent(WebInputEvent::kGestureScrollEnd,
+ blink::kWebGestureDeviceTouchscreen);
+
+ // Now ACK the GSU. Should see a completed overscroll.
+ SendInputEventACK(WebInputEvent::kGestureScrollUpdate,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
+ EXPECT_EQ(OverscrollSource::NONE, overscroll_source());
+ EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
+ EXPECT_EQ(OVERSCROLL_EAST, overscroll_delegate()->completed_mode());
+}
+
+TEST_F(RenderWidgetHostViewAuraOverscrollTest,
+ InterleavedScrollUpdateAckAndScrollEnd) {
+ SetUpOverscrollEnvironment();
+
+ SimulateGestureEvent(WebInputEvent::kGestureScrollBegin,
+ blink::kWebGestureDeviceTouchscreen);
+ SendScrollBeginAckIfNeeded(INPUT_EVENT_ACK_STATE_CONSUMED);
+
+ // Send the first GSU which shouldn't trigger overscroll.
+ SimulateGestureScrollUpdateEvent(30, -5, 0);
+ SendInputEventACK(WebInputEvent::kGestureScrollUpdate,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+
+ EXPECT_EQ(0U, overscroll_delegate()->historical_modes().size());
+
+ // Send the second GSU which should be able to trigger overscroll if combined.
+ SimulateGestureScrollUpdateEvent(30, -5, 0);
+
+ // Send GSE immediately before ACKing GSU.
+ SimulateGestureEvent(WebInputEvent::kGestureScrollEnd,
+ blink::kWebGestureDeviceTouchscreen);
+
+ // Now ACK the second GSU, should see overscroll being triggered and cleared.
+ SendInputEventACK(WebInputEvent::kGestureScrollUpdate,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+
+ EXPECT_EQ(2U, overscroll_delegate()->historical_modes().size());
+ EXPECT_EQ(OVERSCROLL_EAST, overscroll_delegate()->historical_modes().at(0));
+ EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->historical_modes().at(1));
+}
+
void RenderWidgetHostViewAuraOverscrollTest::
OverscrollDirectionChangeMouseWheel() {
SetUpOverscrollEnvironment();
@@ -4996,31 +5050,37 @@ void RenderWidgetHostViewAuraOverscrollTest::
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
ExpectGestureScrollEndForWheelScrolling(false);
- // Since it was unhandled; the overscroll should now be west
- EXPECT_EQ(OVERSCROLL_WEST, overscroll_mode());
- EXPECT_EQ(OverscrollSource::TOUCHPAD, overscroll_source());
- EXPECT_EQ(OVERSCROLL_WEST, overscroll_delegate()->current_mode());
+ // ScrollUpdate is not consumed, however, overscroll controller will not
+ // initiate west overscroll as it is now locked in east mode.
+ EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
+ EXPECT_EQ(OverscrollSource::NONE, overscroll_source());
+ EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
SimulateWheelEventPossiblyIncludingPhase(-20, 0, 0, true,
WebMouseWheelEvent::kPhaseChanged);
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
- if (wheel_scrolling_mode_ != kAsyncWheelEvents) {
+ if (wheel_scrolling_mode_ == kAsyncWheelEvents) {
+ // MouseWheel and ScrollUpdate will be queued events.
+ EXPECT_EQ(2U, GetSentMessageCountAndResetSink());
+ } else {
+ // MouseWheel will be queued event.
+ EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
SendInputEventACK(WebInputEvent::kMouseWheel,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- }
- // wheel event ack generates gesture scroll update; which gets consumed
- // solely by the overflow controller.
- if (!wheel_scroll_latching_enabled_) {
- // No ScrollUpdates, only ScrollBegin and ScrollEnd will be queued events.
- EXPECT_EQ(2U, GetSentMessageCountAndResetSink());
- } else {
- EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
+ // Wheel event ack generates gesture scroll update; which is not consumed by
+ // the overscroll controller.
+ if (wheel_scroll_latching_enabled_) {
+ // ScrollUpdate will be queued event.
+ EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+ } else {
+ // ScrollBegin and ScrollUpdate will be queued events.
+ EXPECT_EQ(2U, GetSentMessageCountAndResetSink());
+ }
}
- EXPECT_EQ(OVERSCROLL_WEST, overscroll_mode());
- EXPECT_EQ(OverscrollSource::TOUCHPAD, overscroll_source());
- EXPECT_EQ(OVERSCROLL_WEST, overscroll_delegate()->current_mode());
+ EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
+ EXPECT_EQ(OverscrollSource::NONE, overscroll_source());
+ EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
}
TEST_F(RenderWidgetHostViewAuraOverscrollTest,
OverscrollDirectionChangeMouseWheel) {
@@ -5585,6 +5645,13 @@ void RenderWidgetHostViewAuraOverscrollTest::ScrollDeltasResetOnEnd() {
EXPECT_EQ(0.f, overscroll_delta_x());
EXPECT_EQ(0.f, overscroll_delta_y());
+ // A wheel event with phase ended is sent before a GSB with touchscreen
+ // device.
+ SimulateWheelEventPossiblyIncludingPhase(0, 0, 0, true,
+ WebMouseWheelEvent::kPhaseEnded);
+ SendInputEventACK(WebInputEvent::kMouseWheel,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+
// Scroll gesture.
SimulateGestureEvent(WebInputEvent::kGestureScrollBegin,
blink::kWebGestureDeviceTouchscreen);
@@ -5601,15 +5668,16 @@ void RenderWidgetHostViewAuraOverscrollTest::ScrollDeltasResetOnEnd() {
EXPECT_EQ(0.f, overscroll_delta_x());
EXPECT_EQ(0.f, overscroll_delta_y());
- // Wheel event scroll ending with a fling.
+ // Wheel event scroll ending with a fling. This is the first wheel event after
+ // touchscreen scrolling ends so it will have phase = kPhaseBegan.
SimulateWheelEventPossiblyIncludingPhase(5, 0, 0, true,
- WebMouseWheelEvent::kPhaseChanged);
- if (wheel_scrolling_mode_ != kAsyncWheelEvents) {
- SendInputEventACK(WebInputEvent::kMouseWheel,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- }
+ WebMouseWheelEvent::kPhaseBegan);
+ SendInputEventACK(WebInputEvent::kMouseWheel,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ SendScrollBeginAckIfNeeded(INPUT_EVENT_ACK_STATE_CONSUMED);
SendInputEventACK(WebInputEvent::kGestureScrollUpdate,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+
SimulateWheelEventPossiblyIncludingPhase(10, -5, 0, true,
WebMouseWheelEvent::kPhaseChanged);
if (wheel_scrolling_mode_ != kAsyncWheelEvents) {
@@ -5622,9 +5690,6 @@ void RenderWidgetHostViewAuraOverscrollTest::ScrollDeltasResetOnEnd() {
EXPECT_EQ(OverscrollSource::NONE, overscroll_source());
EXPECT_EQ(15.f, overscroll_delta_x());
EXPECT_EQ(-5.f, overscroll_delta_y());
- SimulateGestureEvent(WebInputEvent::kGestureScrollBegin,
- blink::kWebGestureDeviceTouchscreen);
- SendScrollBeginAckIfNeeded(INPUT_EVENT_ACK_STATE_CONSUMED);
SimulateGestureFlingStartEvent(0.f, 0.1f, blink::kWebGestureDeviceTouchpad);
EXPECT_EQ(0.f, overscroll_delta_x());
EXPECT_EQ(0.f, overscroll_delta_y());
@@ -5929,10 +5994,11 @@ class InputMethodAuraTestBase : public RenderWidgetHostViewAuraTest {
return process_host;
}
- RenderWidgetHostImpl* CreateRenderWidgetHostForProcess(
+ MockRenderWidgetHostImpl* CreateRenderWidgetHostForProcess(
MockRenderProcessHost* process_host) {
- return new RenderWidgetHostImpl(render_widget_host_delegate(), process_host,
- process_host->GetNextRoutingID(), false);
+ return MockRenderWidgetHostImpl::Create(render_widget_host_delegate(),
+ process_host,
+ process_host->GetNextRoutingID());
}
TestRenderWidgetHostView* CreateViewForProcess(
@@ -6235,7 +6301,7 @@ TEST_F(InputMethodStateAuraTest, GetSelectionRange) {
}
}
-#if defined(USE_X11) && !defined(OS_CHROMEOS)
+#if defined(USE_X11)
// This test will verify that after selection, the selected text is written to
// the clipboard from the focused widget.
TEST_F(InputMethodStateAuraTest, SelectedTextCopiedToClipboard) {
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 ebf64e9cd8c..69c338c37b5 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
@@ -399,7 +399,7 @@ viz::LocalSurfaceId RenderWidgetHostViewBase::GetLocalSurfaceId() const {
}
viz::FrameSinkId RenderWidgetHostViewBase::FrameSinkIdAtPoint(
- cc::SurfaceHittestDelegate* delegate,
+ viz::SurfaceHittestDelegate* delegate,
const gfx::Point& point,
gfx::Point* transformed_point) {
NOTREACHED();
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 9a124eb9377..faec1e5bb3b 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
@@ -18,7 +18,6 @@
#include "base/process/kill.h"
#include "base/strings/string16.h"
#include "build/build_config.h"
-#include "cc/ipc/compositor_frame_sink.mojom.h"
#include "cc/output/compositor_frame.h"
#include "components/viz/common/surfaces/surface_id.h"
#include "content/browser/renderer_host/event_with_latency_info.h"
@@ -27,6 +26,7 @@
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/common/screen_info.h"
#include "ipc/ipc_listener.h"
+#include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom.h"
#include "third_party/WebKit/public/platform/modules/screen_orientation/WebScreenOrientationType.h"
#include "third_party/WebKit/public/web/WebPopupType.h"
#include "third_party/WebKit/public/web/WebTextDirection.h"
@@ -57,16 +57,13 @@ class WebMouseEvent;
class WebMouseWheelEvent;
}
-namespace cc {
-class SurfaceHittestDelegate;
-}
-
namespace ui {
class LatencyInfo;
struct DidOverscrollParams;
}
namespace viz {
+class SurfaceHittestDelegate;
class SurfaceInfo;
}
@@ -230,14 +227,15 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView,
// expected not to return resources belonging to the old
// RendererCompositorFrameSink after this method finishes.
virtual void DidCreateNewRendererCompositorFrameSink(
- cc::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink) = 0;
+ viz::mojom::CompositorFrameSinkClient*
+ renderer_compositor_frame_sink) = 0;
virtual void SubmitCompositorFrame(
const viz::LocalSurfaceId& local_surface_id,
cc::CompositorFrame frame) = 0;
- virtual void OnDidNotProduceFrame(const cc::BeginFrameAck& ack) {}
- virtual void OnSurfaceChanged(const viz::SurfaceInfo& surface_info) {}
+ virtual void OnDidNotProduceFrame(const viz::BeginFrameAck& ack) {}
+ virtual void OnFirstSurfaceActivation(const viz::SurfaceInfo& surface_info) {}
// This method exists to allow removing of displayed graphics, after a new
// page has been loaded, to prevent the displayed URL from being out of sync
@@ -257,8 +255,11 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView,
virtual void DidStopFlinging() {}
// Returns the ID associated with the CompositorFrameSink of this view.
+ // TODO(fsamuel): Return by const ref.
virtual viz::FrameSinkId GetFrameSinkId();
+ // Returns the LocalSurfaceId allocated by the parent client for this view.
+ // TODO(fsamuel): Return by const ref.
virtual viz::LocalSurfaceId GetLocalSurfaceId() const;
// When there are multiple RenderWidgetHostViews for a single page, input
@@ -267,7 +268,7 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView,
// properly handle the event (i.e. it has focus for keyboard events, or has
// been identified by hit testing mouse, touch or gesture events).
virtual viz::FrameSinkId FrameSinkIdAtPoint(
- cc::SurfaceHittestDelegate* delegate,
+ viz::SurfaceHittestDelegate* delegate,
const gfx::Point& point,
gfx::Point* transformed_point);
virtual void ProcessKeyboardEvent(const NativeWebKeyboardEvent& event,
diff --git a/chromium/content/browser/frame_host/render_widget_host_view_child_frame.cc b/chromium/content/browser/renderer_host/render_widget_host_view_child_frame.cc
index e9a90ca4539..fc5197ab84e 100644
--- a/chromium/content/browser/frame_host/render_widget_host_view_child_frame.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_child_frame.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/browser/frame_host/render_widget_host_view_child_frame.h"
+#include "content/browser/renderer_host/render_widget_host_view_child_frame.h"
#include <algorithm>
#include <utility>
@@ -13,18 +13,18 @@
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
-#include "cc/output/copy_output_request.h"
-#include "cc/output/copy_output_result.h"
-#include "cc/surfaces/surface.h"
-#include "cc/surfaces/surface_manager.h"
+#include "components/viz/common/quads/copy_output_request.h"
+#include "components/viz/common/quads/copy_output_result.h"
#include "components/viz/host/host_frame_sink_manager.h"
#include "components/viz/service/frame_sinks/compositor_frame_sink_support.h"
#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
+#include "components/viz/service/surfaces/surface.h"
+#include "components/viz/service/surfaces/surface_manager.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
#include "content/browser/browser_plugin/browser_plugin_guest.h"
#include "content/browser/compositor/surface_utils.h"
-#include "content/browser/frame_host/cross_process_frame_connector.h"
#include "content/browser/gpu/compositor_util.h"
+#include "content/browser/renderer_host/frame_connector_delegate.h"
#include "content/browser/renderer_host/input/touch_selection_controller_client_child_frame.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_delegate.h"
@@ -43,7 +43,22 @@
#include "ui/gfx/geometry/size_f.h"
#include "ui/touch_selection/touch_selection_controller.h"
+#if defined(USE_AURA)
+#include "ui/aura/env.h"
+#endif
+
namespace content {
+namespace {
+
+bool IsUsingMus() {
+#if defined(USE_AURA)
+ return aura::Env::GetInstance()->mode() == aura::Env::Mode::MUS;
+#else
+ return false;
+#endif
+}
+
+} // namespace
// static
RenderWidgetHostViewChildFrame* RenderWidgetHostViewChildFrame::Create(
@@ -65,20 +80,23 @@ RenderWidgetHostViewChildFrame::RenderWidgetHostViewChildFrame(
frame_connector_(nullptr),
background_color_(SK_ColorWHITE),
weak_factory_(this) {
- if (!service_manager::ServiceManagerIsRemote()) {
- GetFrameSinkManager()->surface_manager()->RegisterFrameSinkId(
- frame_sink_id_);
+ if (!IsUsingMus()) {
+ GetHostFrameSinkManager()->RegisterFrameSinkId(frame_sink_id_, this);
CreateCompositorFrameSinkSupport();
}
}
RenderWidgetHostViewChildFrame::~RenderWidgetHostViewChildFrame() {
- if (!service_manager::ServiceManagerIsRemote()) {
+ // TODO(wjmaclean): The next two lines are a speculative fix for
+ // https://crbug.com/760074, based on the theory that perhaps something is
+ // destructing the class without calling Destroy() first.
+ if (frame_connector_)
+ DetachFromTouchSelectionClientManagerIfNecessary();
+
+ if (!IsUsingMus()) {
ResetCompositorFrameSinkSupport();
- if (GetFrameSinkManager()) {
- GetFrameSinkManager()->surface_manager()->InvalidateFrameSinkId(
- frame_sink_id_);
- }
+ if (GetHostFrameSinkManager())
+ GetHostFrameSinkManager()->InvalidateFrameSinkId(frame_sink_id_);
}
}
@@ -103,19 +121,14 @@ void RenderWidgetHostViewChildFrame::
selection_controller_client_.reset();
}
-void RenderWidgetHostViewChildFrame::SetCrossProcessFrameConnector(
- CrossProcessFrameConnector* frame_connector) {
+void RenderWidgetHostViewChildFrame::SetFrameConnectorDelegate(
+ FrameConnectorDelegate* frame_connector) {
if (frame_connector_ == frame_connector)
return;
if (frame_connector_) {
- if (parent_frame_sink_id_.is_valid() &&
- !service_manager::ServiceManagerIsRemote()) {
- GetFrameSinkManager()->UnregisterFrameSinkHierarchy(parent_frame_sink_id_,
- frame_sink_id_);
- }
- parent_frame_sink_id_ = viz::FrameSinkId();
- local_surface_id_ = viz::LocalSurfaceId();
+ SetParentFrameSinkId(viz::FrameSinkId());
+ last_received_local_surface_id_ = viz::LocalSurfaceId();
// Unlocks the mouse if this RenderWidgetHostView holds the lock.
UnlockMouse();
@@ -126,12 +139,8 @@ void RenderWidgetHostViewChildFrame::SetCrossProcessFrameConnector(
RenderWidgetHostViewBase* parent_view =
frame_connector_->GetParentRenderWidgetHostView();
if (parent_view) {
- parent_frame_sink_id_ = parent_view->GetFrameSinkId();
- DCHECK(parent_frame_sink_id_.is_valid());
- if (!service_manager::ServiceManagerIsRemote()) {
- GetFrameSinkManager()->RegisterFrameSinkHierarchy(parent_frame_sink_id_,
- frame_sink_id_);
- }
+ DCHECK(parent_view->GetFrameSinkId().is_valid());
+ SetParentFrameSinkId(parent_view->GetFrameSinkId());
}
auto* root_view = frame_connector_->GetRootRenderWidgetHostView();
@@ -144,9 +153,8 @@ void RenderWidgetHostViewChildFrame::SetCrossProcessFrameConnector(
auto* manager = root_view->GetTouchSelectionControllerClientManager();
if (manager) {
- // We will only have a manager on Aura (and eventually Android).
- // TODO(wjmaclean): update this comment when TSE OOPIF support becomes
- // available on Android.
+ // We have managers in Aura and Android, as well as outside of content/.
+ // There is no manager for Mac OS.
selection_controller_client_ =
base::MakeUnique<TouchSelectionControllerClientChildFrame>(this,
manager);
@@ -165,8 +173,7 @@ void RenderWidgetHostViewChildFrame::OnManagerWillDestroy(
selection_controller_client_.reset();
}
-void RenderWidgetHostViewChildFrame::InitAsChild(
- gfx::NativeView parent_view) {
+void RenderWidgetHostViewChildFrame::InitAsChild(gfx::NativeView parent_view) {
NOTREACHED();
}
@@ -187,8 +194,7 @@ void RenderWidgetHostViewChildFrame::SetBounds(const gfx::Rect& rect) {
}
}
-void RenderWidgetHostViewChildFrame::Focus() {
-}
+void RenderWidgetHostViewChildFrame::Focus() {}
bool RenderWidgetHostViewChildFrame::HasFocus() const {
if (frame_connector_)
@@ -203,13 +209,23 @@ bool RenderWidgetHostViewChildFrame::IsSurfaceAvailableForCopy() const {
void RenderWidgetHostViewChildFrame::Show() {
if (!host_->is_hidden())
return;
+
+ if (!CanBecomeVisible())
+ return;
+
host_->WasShown(ui::LatencyInfo());
+
+ if (frame_connector_)
+ frame_connector_->SetVisibilityForChildViews(true);
}
void RenderWidgetHostViewChildFrame::Hide() {
if (host_->is_hidden())
return;
host_->WasHidden();
+
+ if (frame_connector_)
+ frame_connector_->SetVisibilityForChildViews(false);
}
bool RenderWidgetHostViewChildFrame::IsShowing() {
@@ -344,8 +360,8 @@ void RenderWidgetHostViewChildFrame::Destroy() {
// have already been cleared when RenderWidgetHostViewBase notified its
// observers of our impending destruction.
if (frame_connector_) {
- frame_connector_->set_view(nullptr);
- SetCrossProcessFrameConnector(nullptr);
+ frame_connector_->SetView(nullptr);
+ SetFrameConnectorDelegate(nullptr);
}
// We notify our observers about shutdown here since we are about to release
@@ -399,15 +415,17 @@ void RenderWidgetHostViewChildFrame::UpdateViewportIntersection(
void RenderWidgetHostViewChildFrame::SetIsInert() {
if (host_ && frame_connector_) {
host_->Send(new ViewMsg_SetIsInert(host_->GetRoutingID(),
- frame_connector_->is_inert()));
+ frame_connector_->IsInert()));
}
}
void RenderWidgetHostViewChildFrame::GestureEventAck(
const blink::WebGestureEvent& event,
InputEventAckState ack_result) {
- bool not_consumed = ack_result == INPUT_EVENT_ACK_STATE_NOT_CONSUMED ||
- ack_result == INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS;
+ bool should_bubble =
+ ack_result == INPUT_EVENT_ACK_STATE_NOT_CONSUMED ||
+ ack_result == INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS ||
+ ack_result == INPUT_EVENT_ACK_STATE_CONSUMED_SHOULD_BUBBLE;
if (!frame_connector_)
return;
@@ -418,7 +436,7 @@ void RenderWidgetHostViewChildFrame::GestureEventAck(
// frame_connector_ decides to forward them for bubbling if the
// GestureScrollBegin event is forwarded.
if ((event.GetType() == blink::WebInputEvent::kGestureScrollBegin &&
- not_consumed) ||
+ should_bubble) ||
event.GetType() == blink::WebInputEvent::kGestureScrollUpdate ||
event.GetType() == blink::WebInputEvent::kGestureScrollEnd ||
event.GetType() == blink::WebInputEvent::kGestureFlingStart) {
@@ -432,7 +450,7 @@ void RenderWidgetHostViewChildFrame::GestureEventAck(
// always forwarded and handled according to current scroll state in the
// RenderWidgetHostInputEventRouter.
if ((event.GetType() == blink::WebInputEvent::kGestureScrollUpdate &&
- not_consumed) ||
+ should_bubble) ||
event.GetType() == blink::WebInputEvent::kGestureScrollEnd ||
event.GetType() == blink::WebInputEvent::kGestureFlingStart) {
frame_connector_->BubbleScrollEvent(event);
@@ -441,31 +459,55 @@ void RenderWidgetHostViewChildFrame::GestureEventAck(
}
void RenderWidgetHostViewChildFrame::DidReceiveCompositorFrameAck(
- const std::vector<cc::ReturnedResource>& resources) {
- renderer_compositor_frame_sink_->DidReceiveCompositorFrameAck(resources);
+ const std::vector<viz::ReturnedResource>& resources) {
+ if (renderer_compositor_frame_sink_)
+ renderer_compositor_frame_sink_->DidReceiveCompositorFrameAck(resources);
}
void RenderWidgetHostViewChildFrame::DidCreateNewRendererCompositorFrameSink(
- cc::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink) {
+ viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink) {
ResetCompositorFrameSinkSupport();
renderer_compositor_frame_sink_ = renderer_compositor_frame_sink;
CreateCompositorFrameSinkSupport();
has_frame_ = false;
}
+void RenderWidgetHostViewChildFrame::SetParentFrameSinkId(
+ const viz::FrameSinkId& parent_frame_sink_id) {
+ if (parent_frame_sink_id_ == parent_frame_sink_id || IsUsingMus())
+ return;
+
+ auto* host_frame_sink_manager = GetHostFrameSinkManager();
+
+ // Unregister hierarchy for the current parent, only if set.
+ if (parent_frame_sink_id_.is_valid()) {
+ host_frame_sink_manager->UnregisterFrameSinkHierarchy(parent_frame_sink_id_,
+ frame_sink_id_);
+ }
+
+ parent_frame_sink_id_ = parent_frame_sink_id;
+
+ // Register hierarchy for the new parent, only if set.
+ if (parent_frame_sink_id_.is_valid()) {
+ host_frame_sink_manager->RegisterFrameSinkHierarchy(parent_frame_sink_id_,
+ frame_sink_id_);
+ }
+}
+
void RenderWidgetHostViewChildFrame::ProcessCompositorFrame(
const viz::LocalSurfaceId& local_surface_id,
cc::CompositorFrame frame) {
- current_surface_size_ = frame.render_pass_list.back()->output_rect.size();
- current_surface_scale_factor_ = frame.metadata.device_scale_factor;
+ current_surface_size_ = frame.size_in_pixels();
+ current_surface_scale_factor_ = frame.device_scale_factor();
bool result =
support_->SubmitCompositorFrame(local_surface_id, std::move(frame));
DCHECK(result);
has_frame_ = true;
- if (local_surface_id_ != local_surface_id || HasEmbedderChanged()) {
- local_surface_id_ = local_surface_id;
+ if (last_received_local_surface_id_ != local_surface_id ||
+ HasEmbedderChanged()) {
+ last_received_local_surface_id_ = local_surface_id;
SendSurfaceInfoToEmbedder();
}
@@ -478,15 +520,18 @@ void RenderWidgetHostViewChildFrame::ProcessCompositorFrame(
}
void RenderWidgetHostViewChildFrame::SendSurfaceInfoToEmbedder() {
- if (service_manager::ServiceManagerIsRemote())
+ if (IsUsingMus())
return;
+ // TODO(kylechar): Remove sequence generation and only send surface info.
+ // See https://crbug.com/676384.
viz::SurfaceSequence sequence =
viz::SurfaceSequence(frame_sink_id_, next_surface_sequence_++);
- cc::SurfaceManager* manager = GetFrameSinkManager()->surface_manager();
- viz::SurfaceId surface_id(frame_sink_id_, local_surface_id_);
+ viz::SurfaceManager* manager = GetFrameSinkManager()->surface_manager();
+ viz::SurfaceId surface_id(frame_sink_id_, last_received_local_surface_id_);
// The renderer process will satisfy this dependency when it creates a
// SurfaceLayer.
- manager->RequireSequence(surface_id, sequence);
+ if (!manager->using_surface_references())
+ manager->RequireSequence(surface_id, sequence);
viz::SurfaceInfo surface_info(surface_id, current_surface_scale_factor_,
current_surface_size_);
SendSurfaceInfoToEmbedderImpl(surface_info, sequence);
@@ -510,16 +555,10 @@ void RenderWidgetHostViewChildFrame::SubmitCompositorFrame(
}
void RenderWidgetHostViewChildFrame::OnDidNotProduceFrame(
- const cc::BeginFrameAck& ack) {
+ const viz::BeginFrameAck& ack) {
support_->DidNotProduceFrame(ack);
}
-void RenderWidgetHostViewChildFrame::OnSurfaceChanged(
- const viz::SurfaceInfo& surface_info) {
- viz::SurfaceSequence sequence(frame_sink_id_, next_surface_sequence_++);
- SendSurfaceInfoToEmbedderImpl(surface_info, sequence);
-}
-
void RenderWidgetHostViewChildFrame::ProcessFrameSwappedCallbacks() {
// We only use callbacks once, therefore we make a new list for registration
// before we start, and discard the old list entries when we are done.
@@ -551,6 +590,11 @@ void RenderWidgetHostViewChildFrame::ProcessAckedTouchEvent(
frame_connector_->ForwardProcessAckedTouchEvent(touch, ack_result);
}
+void RenderWidgetHostViewChildFrame::DidStopFlinging() {
+ if (selection_controller_client_)
+ selection_controller_client_->DidStopFlinging();
+}
+
bool RenderWidgetHostViewChildFrame::LockMouse() {
if (frame_connector_)
return frame_connector_->LockMouse();
@@ -574,6 +618,12 @@ viz::FrameSinkId RenderWidgetHostViewChildFrame::GetFrameSinkId() {
return frame_sink_id_;
}
+viz::LocalSurfaceId RenderWidgetHostViewChildFrame::GetLocalSurfaceId() const {
+ if (frame_connector_)
+ return frame_connector_->local_surface_id();
+ return viz::LocalSurfaceId();
+}
+
void RenderWidgetHostViewChildFrame::ProcessKeyboardEvent(
const NativeWebKeyboardEvent& event,
const ui::LatencyInfo& latency) {
@@ -616,11 +666,11 @@ void RenderWidgetHostViewChildFrame::ProcessGestureEvent(
gfx::Point RenderWidgetHostViewChildFrame::TransformPointToRootCoordSpace(
const gfx::Point& point) {
- if (!frame_connector_ || !local_surface_id_.is_valid())
+ if (!frame_connector_ || !last_received_local_surface_id_.is_valid())
return point;
return frame_connector_->TransformPointToRootCoordSpace(
- point, viz::SurfaceId(frame_sink_id_, local_surface_id_));
+ point, viz::SurfaceId(frame_sink_id_, last_received_local_surface_id_));
}
bool RenderWidgetHostViewChildFrame::TransformPointToLocalCoordSpace(
@@ -628,19 +678,20 @@ bool RenderWidgetHostViewChildFrame::TransformPointToLocalCoordSpace(
const viz::SurfaceId& original_surface,
gfx::Point* transformed_point) {
*transformed_point = point;
- if (!frame_connector_ || !local_surface_id_.is_valid())
+ if (!frame_connector_ || !last_received_local_surface_id_.is_valid())
return false;
return frame_connector_->TransformPointToLocalCoordSpace(
point, original_surface,
- viz::SurfaceId(frame_sink_id_, local_surface_id_), transformed_point);
+ viz::SurfaceId(frame_sink_id_, last_received_local_surface_id_),
+ transformed_point);
}
bool RenderWidgetHostViewChildFrame::TransformPointToCoordSpaceForView(
const gfx::Point& point,
RenderWidgetHostViewBase* target_view,
gfx::Point* transformed_point) {
- if (!frame_connector_ || !local_surface_id_.is_valid())
+ if (!frame_connector_ || !last_received_local_surface_id_.is_valid())
return false;
if (target_view == this) {
@@ -649,7 +700,8 @@ bool RenderWidgetHostViewChildFrame::TransformPointToCoordSpaceForView(
}
return frame_connector_->TransformPointToCoordSpaceForView(
- point, target_view, viz::SurfaceId(frame_sink_id_, local_surface_id_),
+ point, target_view,
+ viz::SurfaceId(frame_sink_id_, last_received_local_surface_id_),
transformed_point);
}
@@ -667,7 +719,7 @@ void RenderWidgetHostViewChildFrame::WillSendScreenRects() {
// spammy way to do this, but triggering on SendScreenRects() is reasonable
// until somebody figures that out. RWHVCF::Init() is too early.
if (frame_connector_) {
- UpdateViewportIntersection(frame_connector_->viewport_intersection());
+ UpdateViewportIntersection(frame_connector_->ViewportIntersection());
SetIsInert();
}
}
@@ -678,8 +730,7 @@ RenderWidgetHostViewChildFrame::GetAcceleratedWidgetMac() const {
return nullptr;
}
-void RenderWidgetHostViewChildFrame::SetActive(bool active) {
-}
+void RenderWidgetHostViewChildFrame::SetActive(bool active) {}
void RenderWidgetHostViewChildFrame::ShowDefinitionForSelection() {
if (frame_connector_) {
@@ -692,8 +743,7 @@ bool RenderWidgetHostViewChildFrame::SupportsSpeech() const {
return false;
}
-void RenderWidgetHostViewChildFrame::SpeakSelection() {
-}
+void RenderWidgetHostViewChildFrame::SpeakSelection() {}
bool RenderWidgetHostViewChildFrame::IsSpeaking() const {
return false;
@@ -733,8 +783,8 @@ void RenderWidgetHostViewChildFrame::SubmitSurfaceCopyRequest(
DCHECK(IsSurfaceAvailableForCopy());
DCHECK(support_);
- std::unique_ptr<cc::CopyOutputRequest> request =
- cc::CopyOutputRequest::CreateRequest(
+ std::unique_ptr<viz::CopyOutputRequest> request =
+ viz::CopyOutputRequest::CreateRequest(
base::BindOnce(&CopyFromCompositingSurfaceHasResult, output_size,
preferred_color_type, callback));
if (!src_subrect.IsEmpty())
@@ -744,22 +794,31 @@ void RenderWidgetHostViewChildFrame::SubmitSurfaceCopyRequest(
}
bool RenderWidgetHostViewChildFrame::HasAcceleratedSurface(
- const gfx::Size& desired_size) {
+ const gfx::Size& desired_size) {
return false;
}
void RenderWidgetHostViewChildFrame::ReclaimResources(
- const std::vector<cc::ReturnedResource>& resources) {
- renderer_compositor_frame_sink_->ReclaimResources(resources);
+ const std::vector<viz::ReturnedResource>& resources) {
+ if (renderer_compositor_frame_sink_)
+ renderer_compositor_frame_sink_->ReclaimResources(resources);
}
void RenderWidgetHostViewChildFrame::OnBeginFrame(
- const cc::BeginFrameArgs& args) {
- renderer_compositor_frame_sink_->OnBeginFrame(args);
+ const viz::BeginFrameArgs& args) {
+ if (renderer_compositor_frame_sink_)
+ renderer_compositor_frame_sink_->OnBeginFrame(args);
}
void RenderWidgetHostViewChildFrame::OnBeginFramePausedChanged(bool paused) {
- renderer_compositor_frame_sink_->OnBeginFramePausedChanged(paused);
+ if (renderer_compositor_frame_sink_)
+ renderer_compositor_frame_sink_->OnBeginFramePausedChanged(paused);
+}
+
+void RenderWidgetHostViewChildFrame::OnFirstSurfaceActivation(
+ const viz::SurfaceInfo& surface_info) {
+ viz::SurfaceSequence sequence(frame_sink_id_, next_surface_sequence_++);
+ SendSurfaceInfoToEmbedderImpl(surface_info, sequence);
}
void RenderWidgetHostViewChildFrame::SetNeedsBeginFrames(
@@ -790,10 +849,22 @@ InputEventAckState RenderWidgetHostViewChildFrame::FilterInputEvent(
}
}
- // TODO(mcnee): Allow the root RWHV to consume the child's
- // GestureScrollUpdates. This is needed to prevent the child from consuming
- // them after the root has started an overscroll.
- // See crbug.com/713368
+ // Allow the root RWHV a chance to consume the child's GestureScrollUpdates
+ // in case the root needs to prevent the child from scrolling. For example,
+ // if the root has started an overscroll gesture, it needs to process the
+ // scroll events that would normally be processed by the child.
+ // TODO(mcnee): Once BrowserPlugin is removed, investigate routing these
+ // GestureScrollUpdates directly to the root RWHV during an overscroll
+ // gesture. The way resending of scroll events from a plugin works would cause
+ // issues with this approach in terms of valid input streams.
+ // See crbug.com/751782
+ if (frame_connector_ &&
+ input_event.GetType() == blink::WebInputEvent::kGestureScrollUpdate) {
+ const blink::WebGestureEvent& gesture_event =
+ static_cast<const blink::WebGestureEvent&>(input_event);
+ return frame_connector_->GetRootRenderWidgetHostView()
+ ->FilterChildGestureEvent(gesture_event);
+ }
return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
}
@@ -812,7 +883,8 @@ InputEventAckState RenderWidgetHostViewChildFrame::FilterChildGestureEvent(
BrowserAccessibilityManager*
RenderWidgetHostViewChildFrame::CreateBrowserAccessibilityManager(
- BrowserAccessibilityDelegate* delegate, bool for_root_frame) {
+ BrowserAccessibilityDelegate* delegate,
+ bool for_root_frame) {
return BrowserAccessibilityManager::Create(
BrowserAccessibilityManager::GetEmptyDocument(), delegate);
}
@@ -829,23 +901,21 @@ bool RenderWidgetHostViewChildFrame::IsChildFrameForTesting() const {
}
viz::SurfaceId RenderWidgetHostViewChildFrame::SurfaceIdForTesting() const {
- return viz::SurfaceId(frame_sink_id_, local_surface_id_);
+ return viz::SurfaceId(frame_sink_id_, last_received_local_surface_id_);
}
void RenderWidgetHostViewChildFrame::CreateCompositorFrameSinkSupport() {
- if (service_manager::ServiceManagerIsRemote())
+ if (IsUsingMus())
return;
DCHECK(!support_);
constexpr bool is_root = false;
- constexpr bool handles_frame_sink_id_invalidation = false;
constexpr bool needs_sync_points = true;
support_ = GetHostFrameSinkManager()->CreateCompositorFrameSinkSupport(
- this, frame_sink_id_, is_root, handles_frame_sink_id_invalidation,
- needs_sync_points);
+ this, frame_sink_id_, is_root, needs_sync_points);
if (parent_frame_sink_id_.is_valid()) {
- GetFrameSinkManager()->RegisterFrameSinkHierarchy(parent_frame_sink_id_,
- frame_sink_id_);
+ GetHostFrameSinkManager()->RegisterFrameSinkHierarchy(parent_frame_sink_id_,
+ frame_sink_id_);
}
if (host_->needs_begin_frames())
support_->SetNeedsBeginFrame(true);
@@ -855,8 +925,8 @@ void RenderWidgetHostViewChildFrame::ResetCompositorFrameSinkSupport() {
if (!support_)
return;
if (parent_frame_sink_id_.is_valid()) {
- GetFrameSinkManager()->UnregisterFrameSinkHierarchy(parent_frame_sink_id_,
- frame_sink_id_);
+ GetHostFrameSinkManager()->UnregisterFrameSinkHierarchy(
+ parent_frame_sink_id_, frame_sink_id_);
}
support_.reset();
}
@@ -901,4 +971,21 @@ gfx::Point RenderWidgetHostViewChildFrame::GetViewOriginInRoot() const {
return gfx::Point();
}
+bool RenderWidgetHostViewChildFrame::CanBecomeVisible() {
+ if (!frame_connector_)
+ return true;
+
+ if (frame_connector_->IsHidden())
+ return false;
+
+ RenderWidgetHostViewBase* parent_view = GetParentView();
+ if (!parent_view || !parent_view->IsRenderWidgetHostViewChildFrame()) {
+ // Root frame does not have a CSS visibility property.
+ return true;
+ }
+
+ return static_cast<RenderWidgetHostViewChildFrame*>(parent_view)
+ ->CanBecomeVisible();
+}
+
} // namespace content
diff --git a/chromium/content/browser/frame_host/render_widget_host_view_child_frame.h b/chromium/content/browser/renderer_host/render_widget_host_view_child_frame.h
index 297163e0450..e994ab27f96 100644
--- a/chromium/content/browser/frame_host/render_widget_host_view_child_frame.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_child_frame.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_FRAME_HOST_RENDER_WIDGET_HOST_VIEW_CHILD_FRAME_H_
-#define CONTENT_BROWSER_FRAME_HOST_RENDER_WIDGET_HOST_VIEW_CHILD_FRAME_H_
+#ifndef CONTENT_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_VIEW_CHILD_FRAME_H_
+#define CONTENT_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_VIEW_CHILD_FRAME_H_
#include <stddef.h>
#include <stdint.h>
@@ -16,10 +16,11 @@
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "build/build_config.h"
-#include "cc/resources/returned_resource.h"
-#include "cc/scheduler/begin_frame_source.h"
+#include "components/viz/common/frame_sinks/begin_frame_source.h"
+#include "components/viz/common/resources/returned_resource.h"
#include "components/viz/common/surfaces/surface_info.h"
#include "components/viz/common/surfaces/surface_sequence.h"
+#include "components/viz/host/host_frame_sink_client.h"
#include "components/viz/service/frame_sinks/compositor_frame_sink_support_client.h"
#include "content/browser/compositor/image_transport_factory.h"
#include "content/browser/renderer_host/event_with_latency_info.h"
@@ -36,7 +37,7 @@ class CompositorFrameSinkSupport;
}
namespace content {
-class CrossProcessFrameConnector;
+class FrameConnectorDelegate;
class RenderWidgetHost;
class RenderWidgetHostImpl;
class RenderWidgetHostViewChildFrameTest;
@@ -54,13 +55,13 @@ class TouchSelectionControllerClientChildFrame;
class CONTENT_EXPORT RenderWidgetHostViewChildFrame
: public RenderWidgetHostViewBase,
public TouchSelectionControllerClientManager::Observer,
- public NON_EXPORTED_BASE(viz::CompositorFrameSinkSupportClient) {
+ public viz::CompositorFrameSinkSupportClient,
+ public viz::HostFrameSinkClient {
public:
static RenderWidgetHostViewChildFrame* Create(RenderWidgetHost* widget);
~RenderWidgetHostViewChildFrame() override;
- void SetCrossProcessFrameConnector(
- CrossProcessFrameConnector* frame_connector);
+ void SetFrameConnectorDelegate(FrameConnectorDelegate* frame_connector);
// This functions registers single-use callbacks that want to be notified when
// the next frame is swapped. The callback is triggered by
@@ -115,21 +116,22 @@ class CONTENT_EXPORT RenderWidgetHostViewChildFrame
void GestureEventAck(const blink::WebGestureEvent& event,
InputEventAckState ack_result) override;
void DidCreateNewRendererCompositorFrameSink(
- cc::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink)
+ viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink)
override;
void SubmitCompositorFrame(const viz::LocalSurfaceId& local_surface_id,
cc::CompositorFrame frame) override;
- void OnDidNotProduceFrame(const cc::BeginFrameAck& ack) override;
- void OnSurfaceChanged(const viz::SurfaceInfo& surface_info) override;
+ void OnDidNotProduceFrame(const viz::BeginFrameAck& ack) override;
// Since the URL of content rendered by this class is not displayed in
// the URL bar, this method does not need an implementation.
void ClearCompositorFrame() override {}
gfx::Rect GetBoundsInRootWindow() override;
void ProcessAckedTouchEvent(const TouchEventWithLatencyInfo& touch,
InputEventAckState ack_result) override;
+ void DidStopFlinging() override;
bool LockMouse() override;
void UnlockMouse() override;
viz::FrameSinkId GetFrameSinkId() override;
+ viz::LocalSurfaceId GetLocalSurfaceId() const override;
void ProcessKeyboardEvent(const NativeWebKeyboardEvent& event,
const ui::LatencyInfo& latency) override;
void ProcessMouseEvent(const blink::WebMouseEvent& event,
@@ -169,22 +171,26 @@ class CONTENT_EXPORT RenderWidgetHostViewChildFrame
InputEventAckState FilterChildGestureEvent(
const blink::WebGestureEvent& gesture_event) override;
BrowserAccessibilityManager* CreateBrowserAccessibilityManager(
- BrowserAccessibilityDelegate* delegate, bool for_root_frame) override;
+ BrowserAccessibilityDelegate* delegate,
+ bool for_root_frame) override;
// viz::CompositorFrameSinkSupportClient implementation.
void DidReceiveCompositorFrameAck(
- const std::vector<cc::ReturnedResource>& resources) override;
- void OnBeginFrame(const cc::BeginFrameArgs& args) override;
+ const std::vector<viz::ReturnedResource>& resources) override;
+ void OnBeginFrame(const viz::BeginFrameArgs& args) override;
void ReclaimResources(
- const std::vector<cc::ReturnedResource>& resources) override;
+ const std::vector<viz::ReturnedResource>& resources) override;
void WillDrawSurface(const viz::LocalSurfaceId& id,
const gfx::Rect& damage_rect) override {}
void OnBeginFramePausedChanged(bool paused) override;
+ // viz::HostFrameSinkClient implementation.
+ void OnFirstSurfaceActivation(const viz::SurfaceInfo& surface_info) override;
+
// Exposed for tests.
bool IsChildFrameForTesting() const override;
viz::SurfaceId SurfaceIdForTesting() const override;
- CrossProcessFrameConnector* FrameConnectorForTesting() const {
+ FrameConnectorDelegate* FrameConnectorForTesting() const {
return frame_connector_;
}
@@ -221,6 +227,10 @@ class CONTENT_EXPORT RenderWidgetHostViewChildFrame
explicit RenderWidgetHostViewChildFrame(RenderWidgetHost* widget);
void Init();
+ // Sets |parent_frame_sink_id_| and registers frame sink hierarchy. If the
+ // parent was already set then it also unregisters hierarchy.
+ void SetParentFrameSinkId(const viz::FrameSinkId& parent_frame_sink_id);
+
void ProcessCompositorFrame(const viz::LocalSurfaceId& local_surface_id,
cc::CompositorFrame frame);
@@ -243,7 +253,7 @@ class CONTENT_EXPORT RenderWidgetHostViewChildFrame
// Surface-related state.
std::unique_ptr<viz::CompositorFrameSinkSupport> support_;
- viz::LocalSurfaceId local_surface_id_;
+ viz::LocalSurfaceId last_received_local_surface_id_;
uint32_t next_surface_sequence_;
gfx::Size current_surface_size_;
float current_surface_scale_factor_;
@@ -251,13 +261,19 @@ class CONTENT_EXPORT RenderWidgetHostViewChildFrame
// frame_connector_ provides a platform abstraction. Messages
// sent through it are routed to the embedding renderer process.
- CrossProcessFrameConnector* frame_connector_;
+ FrameConnectorDelegate* frame_connector_;
base::WeakPtr<RenderWidgetHostViewChildFrame> AsWeakPtr() {
return weak_factory_.GetWeakPtr();
}
private:
+ FRIEND_TEST_ALL_PREFIXES(SitePerProcessBrowserTest,
+ HiddenOOPIFWillNotGenerateCompositorFrames);
+ FRIEND_TEST_ALL_PREFIXES(
+ SitePerProcessBrowserTest,
+ HiddenOOPIFWillNotGenerateCompositorFramesAfterNavigation);
+
virtual void SendSurfaceInfoToEmbedderImpl(
const viz::SurfaceInfo& surface_info,
const viz::SurfaceSequence& sequence);
@@ -273,6 +289,11 @@ class CONTENT_EXPORT RenderWidgetHostViewChildFrame
virtual bool HasEmbedderChanged();
+ // Returns false if the view cannot be shown. This is the case where the frame
+ // associated with this view or a cross process ancestor frame has been hidden
+ // using CSS.
+ bool CanBecomeVisible();
+
using FrameSwappedCallbackList = std::deque<std::unique_ptr<base::Closure>>;
// Since frame-drawn callbacks are "fire once", we use std::deque to make
// it convenient to swap() when processing the list.
@@ -282,7 +303,7 @@ class CONTENT_EXPORT RenderWidgetHostViewChildFrame
viz::FrameSinkId parent_frame_sink_id_;
bool has_frame_ = false;
- cc::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink_ =
+ viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink_ =
nullptr;
// The background color of the widget.
@@ -297,4 +318,4 @@ class CONTENT_EXPORT RenderWidgetHostViewChildFrame
} // namespace content
-#endif // CONTENT_BROWSER_FRAME_HOST_RENDER_WIDGET_HOST_VIEW_CHILD_FRAME_H_
+#endif // CONTENT_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_VIEW_CHILD_FRAME_H_
diff --git a/chromium/content/browser/frame_host/render_widget_host_view_child_frame_browsertest.cc b/chromium/content/browser/renderer_host/render_widget_host_view_child_frame_browsertest.cc
index 12a0d80d112..17495c87fbd 100644
--- a/chromium/content/browser/frame_host/render_widget_host_view_child_frame_browsertest.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_child_frame_browsertest.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "base/macros.h"
+#include "base/run_loop.h"
#include "components/viz/common/surfaces/surface_id.h"
#include "components/viz/common/surfaces/surface_sequence.h"
#include "content/browser/frame_host/frame_tree_node.h"
@@ -45,9 +46,7 @@ class RenderWidgetHostViewChildFrameTest : public ContentBrowserTest {
EXPECT_EQ(expected_screen_width_, width);
}
- void set_expected_screen_width(int width) {
- expected_screen_width_ = width;
- }
+ void set_expected_screen_width(int width) { expected_screen_width_ = width; }
private:
int expected_screen_width_;
@@ -61,7 +60,8 @@ IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewChildFrameTest, Screen) {
NavigateToURL(shell(), main_url);
FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
- ->GetFrameTree()->root();
+ ->GetFrameTree()
+ ->root();
// Load cross-site page into iframe.
GURL cross_site_url(
@@ -70,7 +70,8 @@ IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewChildFrameTest, Screen) {
int main_frame_screen_width = 0;
ExecuteScriptAndGetValue(shell()->web_contents()->GetMainFrame(),
- "window.screen.width")->GetAsInteger(&main_frame_screen_width);
+ "window.screen.width")
+ ->GetAsInteger(&main_frame_screen_width);
set_expected_screen_width(main_frame_screen_width);
EXPECT_FALSE(main_frame_screen_width == 0);
@@ -151,7 +152,7 @@ class SurfaceRefMessageFilter : public BrowserMessageFilter {
const viz::SurfaceSequence sequence) {
content::BrowserThread::PostTask(
content::BrowserThread::UI, FROM_HERE,
- base::Bind(&SurfaceRefMessageFilter::OnRequireOnUI, this));
+ base::BindOnce(&SurfaceRefMessageFilter::OnRequireOnUI, this));
}
void OnRequireOnUI() {
@@ -163,7 +164,7 @@ class SurfaceRefMessageFilter : public BrowserMessageFilter {
void OnSatisfy(const viz::SurfaceSequence sequence) {
content::BrowserThread::PostTask(
content::BrowserThread::UI, FROM_HERE,
- base::Bind(&SurfaceRefMessageFilter::OnSatisfyOnUI, this));
+ base::BindOnce(&SurfaceRefMessageFilter::OnSatisfyOnUI, this));
}
void OnSatisfyOnUI() {
@@ -182,8 +183,9 @@ class SurfaceRefMessageFilter : public BrowserMessageFilter {
// Test that when a child frame submits its first compositor frame, the
// embedding renderer process properly acquires and releases references to the
// new Surface. See https://crbug.com/701175.
+// TODO(crbug.com/676384): Delete test with the rest of SurfaceSequence code.
IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewChildFrameTest,
- ChildFrameSurfaceReference) {
+ DISABLED_ChildFrameSurfaceReference) {
EXPECT_TRUE(NavigateToURL(
shell(), embedded_test_server()->GetURL(
"a.com", "/cross_site_iframe_factory.html?a(a)")));
diff --git a/chromium/content/browser/frame_host/render_widget_host_view_child_frame_unittest.cc b/chromium/content/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc
index 4f6f571f6f4..ae65a4fa3e8 100644
--- a/chromium/content/browser/frame_host/render_widget_host_view_child_frame_unittest.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/browser/frame_host/render_widget_host_view_child_frame.h"
+#include "content/browser/renderer_host/render_widget_host_view_child_frame.h"
#include <stdint.h>
@@ -15,22 +15,24 @@
#include "base/test/scoped_task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
-#include "cc/surfaces/surface.h"
-#include "cc/surfaces/surface_manager.h"
-#include "cc/test/begin_frame_args_test.h"
-#include "cc/test/fake_external_begin_frame_source.h"
#include "components/viz/common/surfaces/surface_sequence.h"
#include "components/viz/service/frame_sinks/compositor_frame_sink_support.h"
+#include "components/viz/service/surfaces/surface.h"
+#include "components/viz/service/surfaces/surface_manager.h"
+#include "components/viz/test/begin_frame_args_test.h"
+#include "components/viz/test/fake_external_begin_frame_source.h"
#include "content/browser/compositor/test/no_transport_image_transport_factory.h"
-#include "content/browser/frame_host/cross_process_frame_connector.h"
#include "content/browser/gpu/compositor_util.h"
+#include "content/browser/renderer_host/frame_connector_delegate.h"
#include "content/browser/renderer_host/render_widget_host_delegate.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/common/view_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"
+#include "content/test/dummy_render_widget_host_delegate.h"
#include "content/test/fake_renderer_compositor_frame_sink.h"
+#include "content/test/mock_widget_impl.h"
#include "content/test/test_render_view_host.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/compositor/compositor.h"
@@ -42,27 +44,12 @@ const viz::LocalSurfaceId kArbitraryLocalSurfaceId(
1,
base::UnguessableToken::Deserialize(2, 3));
-class MockRenderWidgetHostDelegate : public RenderWidgetHostDelegate {
- public:
- MockRenderWidgetHostDelegate() {}
- ~MockRenderWidgetHostDelegate() override {}
- private:
- void ExecuteEditCommand(
- const std::string& command,
- const base::Optional<base::string16>& value) override {}
-
- void Cut() override {}
- void Copy() override {}
- void Paste() override {}
- void SelectAll() override {}
-};
-
} // namespace
-class MockCrossProcessFrameConnector : public CrossProcessFrameConnector {
+class MockFrameConnectorDelegate : public FrameConnectorDelegate {
public:
- MockCrossProcessFrameConnector() : CrossProcessFrameConnector(nullptr) {}
- ~MockCrossProcessFrameConnector() override {}
+ MockFrameConnectorDelegate() : FrameConnectorDelegate() {}
+ ~MockFrameConnectorDelegate() override {}
void SetChildFrameSurface(const viz::SurfaceInfo& surface_info,
const viz::SurfaceSequence& sequence) override {
@@ -98,17 +85,19 @@ class RenderWidgetHostViewChildFrameTest : public testing::Test {
MockRenderProcessHost* process_host =
new MockRenderProcessHost(browser_context_.get());
int32_t routing_id = process_host->GetNextRoutingID();
- widget_host_ =
- new RenderWidgetHostImpl(&delegate_, process_host, routing_id, false);
+ mojom::WidgetPtr widget;
+ widget_impl_ = base::MakeUnique<MockWidgetImpl>(mojo::MakeRequest(&widget));
+ widget_host_ = new RenderWidgetHostImpl(
+ &delegate_, process_host, routing_id, std::move(widget), false);
view_ = RenderWidgetHostViewChildFrame::Create(widget_host_);
- test_frame_connector_ = new MockCrossProcessFrameConnector();
- view_->SetCrossProcessFrameConnector(test_frame_connector_);
+ test_frame_connector_ = new MockFrameConnectorDelegate();
+ view_->SetFrameConnectorDelegate(test_frame_connector_);
- cc::mojom::CompositorFrameSinkPtr sink;
- cc::mojom::CompositorFrameSinkRequest sink_request =
+ viz::mojom::CompositorFrameSinkPtr sink;
+ viz::mojom::CompositorFrameSinkRequest sink_request =
mojo::MakeRequest(&sink);
- cc::mojom::CompositorFrameSinkClientRequest client_request =
+ viz::mojom::CompositorFrameSinkClientRequest client_request =
mojo::MakeRequest(&renderer_compositor_frame_sink_ptr_);
renderer_compositor_frame_sink_ =
base::MakeUnique<FakeRendererCompositorFrameSink>(
@@ -134,11 +123,12 @@ class RenderWidgetHostViewChildFrameTest : public testing::Test {
}
viz::SurfaceId GetSurfaceId() const {
- return viz::SurfaceId(view_->frame_sink_id_, view_->local_surface_id_);
+ return viz::SurfaceId(view_->frame_sink_id_,
+ view_->last_received_local_surface_id_);
}
viz::LocalSurfaceId GetLocalSurfaceId() const {
- return view_->local_surface_id_;
+ return view_->last_received_local_surface_id_;
}
void ClearCompositorSurfaceIfNecessary() {
@@ -149,18 +139,19 @@ class RenderWidgetHostViewChildFrameTest : public testing::Test {
base::test::ScopedTaskEnvironment scoped_task_environment_;
std::unique_ptr<BrowserContext> browser_context_;
- MockRenderWidgetHostDelegate delegate_;
+ DummyRenderWidgetHostDelegate delegate_;
// Tests should set these to NULL if they've already triggered their
// destruction.
+ std::unique_ptr<MockWidgetImpl> widget_impl_;
RenderWidgetHostImpl* widget_host_;
RenderWidgetHostViewChildFrame* view_;
- MockCrossProcessFrameConnector* test_frame_connector_;
+ MockFrameConnectorDelegate* test_frame_connector_;
std::unique_ptr<FakeRendererCompositorFrameSink>
renderer_compositor_frame_sink_;
private:
- cc::mojom::CompositorFrameSinkClientPtr renderer_compositor_frame_sink_ptr_;
+ viz::mojom::CompositorFrameSinkClientPtr renderer_compositor_frame_sink_ptr_;
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewChildFrameTest);
};
@@ -170,7 +161,7 @@ cc::CompositorFrame CreateDelegatedFrame(float scale_factor,
const gfx::Rect& damage) {
cc::CompositorFrame frame;
frame.metadata.device_scale_factor = scale_factor;
- frame.metadata.begin_frame_ack = cc::BeginFrameAck(0, 1, true);
+ frame.metadata.begin_frame_ack = viz::BeginFrameAck(0, 1, true);
std::unique_ptr<cc::RenderPass> pass = cc::RenderPass::Create();
pass->SetNew(1, gfx::Rect(size), damage, gfx::Transform());
@@ -179,6 +170,12 @@ cc::CompositorFrame CreateDelegatedFrame(float scale_factor,
}
TEST_F(RenderWidgetHostViewChildFrameTest, VisibilityTest) {
+ // Calling show and hide also needs to be propagated to child frame by the
+ // |frame_connector_| which itself requires a |frame_proxy_in_parent_renderer|
+ // (set to nullptr for MockFrameConnectorDelegate). To avoid crashing the test
+ // |frame_connector_| is to set to nullptr.
+ view_->SetFrameConnectorDelegate(nullptr);
+
view_->Show();
ASSERT_TRUE(view_->IsShowing());
@@ -205,16 +202,14 @@ TEST_F(RenderWidgetHostViewChildFrameTest, SwapCompositorFrame) {
if (id.is_valid()) {
#if !defined(OS_ANDROID)
ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
- cc::SurfaceManager* manager = factory->GetContextFactoryPrivate()
- ->GetFrameSinkManager()
- ->surface_manager();
- cc::Surface* surface = manager->GetSurfaceForId(id);
+ viz::SurfaceManager* manager = factory->GetContextFactoryPrivate()
+ ->GetFrameSinkManager()
+ ->surface_manager();
+ viz::Surface* surface = manager->GetSurfaceForId(id);
EXPECT_TRUE(surface);
- // There should be a SurfaceSequence created by the RWHVChildFrame.
- EXPECT_EQ(1u, surface->GetDestructionDependencyCount());
#endif
- // Surface ID should have been passed to CrossProcessFrameConnector to
+ // Surface ID should have been passed to FrameConnectorDelegate to
// be sent to the embedding renderer.
EXPECT_EQ(viz::SurfaceInfo(id, scale_factor, view_size),
test_frame_connector_->last_surface_info_);
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 ed267bcdaba..02614b2e7ef 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
@@ -891,10 +891,6 @@ bool RenderWidgetHostViewEventHandler::ShouldRouteEvent(
if (host_->delegate() && !host_->delegate()->IsWidgetForMainFrame(host_))
return false;
- // ScrollEvents get transformed into MouseWheel events, and so are treated
- // the same as mouse events for routing purposes.
- if (event->IsMouseEvent() || event->type() == ui::ET_SCROLL)
- result = result && SiteIsolationPolicy::AreCrossProcessFramesPossible();
return result;
}
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 24815cc76da..b5449d502d4 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
@@ -111,6 +111,10 @@ class CONTENT_EXPORT RenderWidgetHostViewEventHandler
// fullscreen.
void TrackHost(aura::Window* reference_window);
+ MouseWheelPhaseHandler& mouse_wheel_phase_handler() {
+ return mouse_wheel_phase_handler_;
+ }
+
#if defined(OS_WIN)
// Sets the ContextMenuParams when a context menu is triggered. Required for
// subsequent event processing.
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_frame_subscriber.h b/chromium/content/browser/renderer_host/render_widget_host_view_frame_subscriber.h
index 4211ef7a4a8..09c312227fe 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_frame_subscriber.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_frame_subscriber.h
@@ -7,7 +7,7 @@
#include "base/callback.h"
#include "base/time/time.h"
-#include "cc/output/copy_output_request.h"
+#include "components/viz/common/quads/copy_output_request.h"
namespace gfx {
class Rect;
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 fe03c9a72a8..72664cd9237 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
@@ -37,7 +37,7 @@
#import "ui/base/cocoa/command_dispatcher.h"
#include "ui/base/cocoa/remote_layer_api.h"
#import "ui/base/cocoa/tool_tip_base_view.h"
-#include "ui/base/ime/composition_underline.h"
+#include "ui/base/ime/ime_text_span.h"
#include "ui/display/display_observer.h"
namespace content {
@@ -72,7 +72,6 @@ struct TextInputState;
responderDelegate_;
BOOL canBeKeyView_;
BOOL closeOnDeactivate_;
- BOOL opaque_;
std::unique_ptr<content::RenderWidgetHostViewMacEditCommandHelper>
editCommand_helper_;
@@ -82,6 +81,9 @@ struct TextInputState;
// The cursor for the page. This is passed up from the renderer.
base::scoped_nsobject<NSCursor> currentCursor_;
+ // Is YES if the cursor is hidden by key events.
+ BOOL cursorHidden_;
+
// Variables used by our implementaion of the NSTextInput protocol.
// An input method of Mac calls the methods of this protocol not only to
// notify an application of its status, but also to retrieve the status of
@@ -125,7 +127,7 @@ struct TextInputState;
NSRange markedTextSelectedRange_;
// Underline information of the |markedText_|.
- std::vector<ui::CompositionUnderline> underlines_;
+ std::vector<ui::ImeTextSpan> ime_text_spans_;
// Replacement range information received from |setMarkedText:|.
gfx::Range setMarkedTextReplacementRange_;
@@ -208,7 +210,6 @@ struct TextInputState;
- (void)setCanBeKeyView:(BOOL)can;
- (void)setCloseOnDeactivate:(BOOL)b;
-- (void)setOpaque:(BOOL)opaque;
// True for always-on-top special windows (e.g. Balloons and Panels).
- (BOOL)acceptsMouseEventsWhenInactive;
// Cancel ongoing composition (abandon the marked text).
@@ -326,11 +327,11 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
void FocusedNodeChanged(bool is_editable_node,
const gfx::Rect& node_bounds_in_screen) override;
void DidCreateNewRendererCompositorFrameSink(
- cc::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink)
+ viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink)
override;
void SubmitCompositorFrame(const viz::LocalSurfaceId& local_surface_id,
cc::CompositorFrame frame) override;
- void OnDidNotProduceFrame(const cc::BeginFrameAck& ack) override;
+ void OnDidNotProduceFrame(const viz::BeginFrameAck& ack) override;
void ClearCompositorFrame() override;
BrowserAccessibilityManager* CreateBrowserAccessibilityManager(
BrowserAccessibilityDelegate* delegate, bool for_root_frame) override;
@@ -349,7 +350,7 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
override;
viz::FrameSinkId GetFrameSinkId() override;
- viz::FrameSinkId FrameSinkIdAtPoint(cc::SurfaceHittestDelegate* delegate,
+ viz::FrameSinkId FrameSinkIdAtPoint(viz::SurfaceHittestDelegate* delegate,
const gfx::Point& point,
gfx::Point* transformed_point) override;
// Returns true when we can do SurfaceHitTesting for the event type.
@@ -426,9 +427,9 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
WebContents* GetWebContents();
- // Applies background color without notifying the RenderWidget about
- // opaqueness changes.
- void UpdateBackgroundColorFromRenderer(SkColor color);
+ // Set the color of the background CALayer shown when no content is ready to
+ // see.
+ void SetBackgroundLayerColor(SkColor color);
bool HasPendingWheelEndEventForTesting() {
return mouse_wheel_phase_handler_.HasPendingWheelEndEvent();
@@ -446,6 +447,9 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
// Delegated frame management and compositor interface.
std::unique_ptr<BrowserCompositorMac> browser_compositor_;
+ BrowserCompositorMac* BrowserCompositorForTesting() const {
+ return browser_compositor_.get();
+ }
// Set when the currently-displayed frame is the minimum scale. Used to
// determine if pinch gestures need to be thresholded.
@@ -586,9 +590,18 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
// Whether a request for begin frames has been issued.
bool needs_begin_frames_;
- // The background color of the web content. This color will be drawn when the
- // web content is not able to draw in time.
- SkColor background_color_ = SK_ColorTRANSPARENT;
+ // Whether or not the background is opaque as determined by calls to
+ // SetBackgroundColor. The default value is opaque.
+ bool background_is_opaque_ = true;
+
+ // The color of the background CALayer, stored as a SkColor for efficient
+ // comparison. Initially transparent so that the embedding NSView shows
+ // through.
+ SkColor background_layer_color_ = SK_ColorTRANSPARENT;
+
+ // The background color of the last frame that was swapped. This is not
+ // applied until the swap completes (see comments in
+ // AcceleratedWidgetSwapCompleted).
SkColor last_frame_root_background_color_ = SK_ColorTRANSPARENT;
std::unique_ptr<CursorManager> cursor_manager_;
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 79e4cc1a047..84897ae416f 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
@@ -206,7 +206,6 @@ RenderWidgetHostView* GetRenderWidgetHostViewToUse(
styleMask:windowStyle
backing:bufferingType
defer:deferCreation]) {
- [self setOpaque:NO];
[self setBackgroundColor:[NSColor clearColor]];
[self startObservingClicks];
}
@@ -281,7 +280,7 @@ blink::WebColor WebColorFromNSColor(NSColor *color) {
// Extract underline information from an attributed string. Mostly copied from
// third_party/WebKit/Source/WebKit/mac/WebView/WebHTMLView.mm
void ExtractUnderlines(NSAttributedString* string,
- std::vector<ui::CompositionUnderline>* underlines) {
+ std::vector<ui::ImeTextSpan>* ime_text_spans) {
int length = [[string string] length];
int i = 0;
while (i < length) {
@@ -296,9 +295,9 @@ void ExtractUnderlines(NSAttributedString* string,
color = WebColorFromNSColor(
[colorAttr colorUsingColorSpaceName:NSDeviceRGBColorSpace]);
}
- underlines->push_back(
- ui::CompositionUnderline(range.location, NSMaxRange(range), color,
- [style intValue] > 1, SK_ColorTRANSPARENT));
+ ime_text_spans->push_back(ui::ImeTextSpan(
+ ui::ImeTextSpan::Type::kComposition, range.location,
+ NSMaxRange(range), color, [style intValue] > 1, SK_ColorTRANSPARENT));
}
i = range.location + range.length;
}
@@ -422,7 +421,7 @@ void RenderWidgetHostViewMac::AcceleratedWidgetSwapCompleted() {
// swapped. See RenderWidgetHostViewAura for more details. Note that this is
// done only after the swap has completed, so that the background is not set
// before the frame is up.
- UpdateBackgroundColorFromRenderer(last_frame_root_background_color_);
+ SetBackgroundLayerColor(last_frame_root_background_color_);
if (display_link_)
display_link_->NotifyCurrentTime(base::TimeTicks::Now());
@@ -1422,7 +1421,7 @@ void RenderWidgetHostViewMac::FocusedNodeChanged(
}
void RenderWidgetHostViewMac::DidCreateNewRendererCompositorFrameSink(
- cc::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink) {
+ viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink) {
browser_compositor_->DidCreateNewRendererCompositorFrameSink(
renderer_compositor_frame_sink);
}
@@ -1443,12 +1442,12 @@ void RenderWidgetHostViewMac::SubmitCompositorFrame(
}
void RenderWidgetHostViewMac::OnDidNotProduceFrame(
- const cc::BeginFrameAck& ack) {
+ const viz::BeginFrameAck& ack) {
browser_compositor_->OnDidNotProduceFrame(ack);
}
void RenderWidgetHostViewMac::ClearCompositorFrame() {
- browser_compositor_->GetDelegatedFrameHost()->ClearDelegatedFrame();
+ browser_compositor_->ClearCompositorFrame();
}
gfx::Rect RenderWidgetHostViewMac::GetBoundsInRootWindow() {
@@ -1520,7 +1519,7 @@ viz::FrameSinkId RenderWidgetHostViewMac::GetFrameSinkId() {
}
viz::FrameSinkId RenderWidgetHostViewMac::FrameSinkIdAtPoint(
- cc::SurfaceHittestDelegate* delegate,
+ viz::SurfaceHittestDelegate* delegate,
const gfx::Point& point,
gfx::Point* transformed_point) {
// The surface hittest happens in device pixels, so we need to convert the
@@ -1547,8 +1546,7 @@ bool RenderWidgetHostViewMac::ShouldRouteEvent(
DCHECK(WebInputEvent::IsMouseEventType(event.GetType()) ||
event.GetType() == WebInputEvent::kMouseWheel);
return render_widget_host_->delegate() &&
- render_widget_host_->delegate()->GetInputEventRouter() &&
- SiteIsolationPolicy::AreCrossProcessFramesPossible();
+ render_widget_host_->delegate()->GetInputEventRouter();
}
void RenderWidgetHostViewMac::ProcessMouseEvent(
@@ -1639,34 +1637,37 @@ void RenderWidgetHostViewMac::ShowDefinitionForSelection() {
}
void RenderWidgetHostViewMac::SetBackgroundColor(SkColor color) {
- if (color == background_color_)
- return;
-
- // The renderer will feed its color back to us with the first CompositorFrame.
- // We short-cut here to show a sensible color before that happens.
- UpdateBackgroundColorFromRenderer(color);
+ // This is called by the embedding code prior to the first frame appearing,
+ // to set a reasonable color to show before the web content generates its
+ // first frame. This will be overridden by the web contents.
+ SetBackgroundLayerColor(color);
DCHECK(SkColorGetA(color) == SK_AlphaOPAQUE ||
SkColorGetA(color) == SK_AlphaTRANSPARENT);
bool opaque = SkColorGetA(color) == SK_AlphaOPAQUE;
- if (render_widget_host_)
- render_widget_host_->SetBackgroundOpaque(opaque);
+ if (background_is_opaque_ != opaque) {
+ background_is_opaque_ = opaque;
+ browser_compositor_->SetHasTransparentBackground(!opaque);
+ if (render_widget_host_)
+ render_widget_host_->SetBackgroundOpaque(opaque);
+ }
}
SkColor RenderWidgetHostViewMac::background_color() const {
- return background_color_;
-}
-
-void RenderWidgetHostViewMac::UpdateBackgroundColorFromRenderer(SkColor color) {
- if (color == background_color_)
+ // This is used to specify a color to temporarily show while waiting for web
+ // content. This should never return transparent, since that will cause bugs
+ // where views are initialized as having a transparent background
+ // inappropriately.
+ // https://crbug.com/735407
+ if (background_layer_color_ == SK_ColorTRANSPARENT)
+ return SK_ColorWHITE;
+ return background_layer_color_;
+}
+
+void RenderWidgetHostViewMac::SetBackgroundLayerColor(SkColor color) {
+ if (color == background_layer_color_)
return;
- background_color_ = color;
-
- bool opaque = SkColorGetA(color) == SK_AlphaOPAQUE;
-
- [cocoa_view_ setOpaque:opaque];
-
- browser_compositor_->SetHasTransparentBackground(!opaque);
+ background_layer_color_ = color;
ScopedCAActionDisabler disabler;
base::ScopedCFTypeRef<CGColorRef> cg_color(
@@ -1770,7 +1771,6 @@ void RenderWidgetHostViewMac::OnDisplayMetricsChanged(
renderWidgetHostView_.reset(r);
canBeKeyView_ = YES;
- opaque_ = NO;
pinchHasReachedZoomThreshold_ = false;
isStylusEnteringProximity_ = false;
@@ -1796,6 +1796,13 @@ void RenderWidgetHostViewMac::OnDisplayMetricsChanged(
[[NSNotificationCenter defaultCenter] removeObserver:self];
+ // Update and cache the new input context. Otherwise,
+ // [NSTextInputContext currentInputContext] might still hold on to this
+ // view's NSTextInputContext even after it's deallocated.
+ // See http://crbug.com/684388.
+ [[self window] makeFirstResponder:nil];
+ [NSApp updateWindows];
+
[super dealloc];
}
@@ -1866,10 +1873,6 @@ void RenderWidgetHostViewMac::OnDisplayMetricsChanged(
closeOnDeactivate_ = b;
}
-- (void)setOpaque:(BOOL)opaque {
- opaque_ = opaque;
-}
-
- (BOOL)shouldIgnoreMouseEvent:(NSEvent*)theEvent {
NSWindow* window = [self window];
// If this is a background window, don't handle mouse movement events. This
@@ -1995,6 +1998,9 @@ void RenderWidgetHostViewMac::OnDisplayMetricsChanged(
[self finishComposingText];
}
+ if (type == NSMouseMoved)
+ cursorHidden_ = NO;
+
WebMouseEvent event =
WebMouseEventBuilder::Build(theEvent, self, pointerType_);
ui::LatencyInfo latency_info(ui::SourceEventType::OTHER);
@@ -2162,8 +2168,10 @@ void RenderWidgetHostViewMac::OnDisplayMetricsChanged(
widgetHost->ForwardKeyboardEventWithLatencyInfo(event, latency_info);
// Possibly autohide the cursor.
- if ([self shouldAutohideCursorForEvent:theEvent])
+ if ([self shouldAutohideCursorForEvent:theEvent]) {
[NSCursor setHiddenUntilMouseMoves:YES];
+ cursorHidden_ = YES;
+ }
return;
}
@@ -2188,7 +2196,7 @@ void RenderWidgetHostViewMac::OnDisplayMetricsChanged(
textToBeInserted_.clear();
markedText_.clear();
markedTextSelectedRange_ = NSMakeRange(NSNotFound, 0);
- underlines_.clear();
+ ime_text_spans_.clear();
setMarkedTextReplacementRange_ = gfx::Range::InvalidRange();
unmarkTextCalled_ = NO;
hasEditCommands_ = NO;
@@ -2250,8 +2258,7 @@ void RenderWidgetHostViewMac::OnDisplayMetricsChanged(
BOOL textInserted = NO;
if (textToBeInserted_.length() >
((hasMarkedText_ || oldHasMarkedText) ? 0u : 1u)) {
- widgetHost->ImeCommitText(textToBeInserted_,
- std::vector<ui::CompositionUnderline>(),
+ widgetHost->ImeCommitText(textToBeInserted_, std::vector<ui::ImeTextSpan>(),
gfx::Range::InvalidRange(), 0);
textInserted = YES;
}
@@ -2263,7 +2270,7 @@ void RenderWidgetHostViewMac::OnDisplayMetricsChanged(
// composition node in WebKit.
// When marked text is available, |markedTextSelectedRange_| will be the
// range being selected inside the marked text.
- widgetHost->ImeSetComposition(markedText_, underlines_,
+ widgetHost->ImeSetComposition(markedText_, ime_text_spans_,
setMarkedTextReplacementRange_,
markedTextSelectedRange_.location,
NSMaxRange(markedTextSelectedRange_));
@@ -2332,8 +2339,10 @@ void RenderWidgetHostViewMac::OnDisplayMetricsChanged(
}
// Possibly autohide the cursor.
- if ([self shouldAutohideCursorForEvent:theEvent])
+ if ([self shouldAutohideCursorForEvent:theEvent]) {
[NSCursor setHiddenUntilMouseMoves:YES];
+ cursorHidden_ = YES;
+ }
}
- (void)forceTouchEvent:(NSEvent*)theEvent {
@@ -2587,6 +2596,23 @@ void RenderWidgetHostViewMac::OnDisplayMetricsChanged(
// cancels the gesture, all remaining touches are forwarded to the content
// scroll logic. The user cannot trigger the navigation logic again.
- (void)scrollWheel:(NSEvent*)event {
+#if defined(MAC_OS_X_VERSION_10_11) && \
+ MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_11
+ // When linking against the 10.11 (or later) SDK and running on 10.11 or
+ // later, check the phase of the event and specially handle the "begin" and
+ // "end" phases.
+ if (base::mac::IsAtLeastOS10_11()) {
+ if (event.phase == NSEventPhaseBegan) {
+ [self handleBeginGestureWithEvent:event];
+ }
+
+ if (event.phase == NSEventPhaseEnded ||
+ event.phase == NSEventPhaseCancelled) {
+ [self handleEndGestureWithEvent:event];
+ }
+ }
+#endif
+
if (responderDelegate_ &&
[responderDelegate_ respondsToSelector:@selector(handleEvent:)]) {
BOOL handled = [responderDelegate_ handleEvent:event];
@@ -3295,7 +3321,7 @@ extern NSString *NSTextInputReplacementRangeAttributeName;
hasMarkedText_ = NO;
markedText_.clear();
markedTextSelectedRange_ = NSMakeRange(NSNotFound, 0);
- underlines_.clear();
+ ime_text_spans_.clear();
// If we are handling a key down event, then FinishComposingText() will be
// called in keyEvent: method.
@@ -3324,13 +3350,14 @@ extern NSString *NSTextInputReplacementRangeAttributeName;
markedText_ = base::SysNSStringToUTF16(im_text);
hasMarkedText_ = (length > 0);
- underlines_.clear();
+ ime_text_spans_.clear();
if (isAttributedString) {
- ExtractUnderlines(string, &underlines_);
+ ExtractUnderlines(string, &ime_text_spans_);
} else {
// Use a thin black underline by default.
- underlines_.push_back(ui::CompositionUnderline(0, length, SK_ColorBLACK,
- false, SK_ColorTRANSPARENT));
+ ime_text_spans_.push_back(
+ ui::ImeTextSpan(ui::ImeTextSpan::Type::kComposition, 0, length,
+ SK_ColorBLACK, false, SK_ColorTRANSPARENT));
}
// If we are handling a key down event, then SetComposition() will be
@@ -3345,7 +3372,7 @@ extern NSString *NSTextInputReplacementRangeAttributeName;
} else {
if (renderWidgetHostView_->GetActiveWidget()) {
renderWidgetHostView_->GetActiveWidget()->ImeSetComposition(
- markedText_, underlines_, gfx::Range(replacementRange),
+ markedText_, ime_text_spans_, gfx::Range(replacementRange),
newSelRange.location, NSMaxRange(newSelRange));
}
}
@@ -3404,8 +3431,8 @@ extern NSString *NSTextInputReplacementRangeAttributeName;
gfx::Range replacement_range(replacementRange);
if (renderWidgetHostView_->GetActiveWidget()) {
renderWidgetHostView_->GetActiveWidget()->ImeCommitText(
- base::SysNSStringToUTF16(im_text),
- std::vector<ui::CompositionUnderline>(), replacement_range, 0);
+ base::SysNSStringToUTF16(im_text), std::vector<ui::ImeTextSpan>(),
+ replacement_range, 0);
}
}
@@ -3557,6 +3584,12 @@ extern NSString *NSTextInputReplacementRangeAttributeName;
currentCursor_.reset([cursor retain]);
[[self window] invalidateCursorRectsForView:self];
+
+ // NSWindow's invalidateCursorRectsForView: resets cursor rects but does not
+ // update the cursor instantly. The cursor is updated when the mouse moves.
+ // Update the cursor by setting the current cursor if not hidden.
+ if (!cursorHidden_)
+ [currentCursor_ set];
}
- (void)popupWindowWillClose:(NSNotification *)notification {
@@ -3598,10 +3631,6 @@ extern NSString *NSTextInputReplacementRangeAttributeName;
return YES;
}
-- (BOOL)isOpaque {
- return opaque_;
-}
-
// "-webkit-app-region: drag | no-drag" is implemented on Mac by excluding
// regions that are not draggable. (See ControlRegionView in
// native_app_window_cocoa.mm). This requires the render host view to be
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 b24bdafb502..56d457ddded 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
@@ -19,6 +19,7 @@
#include "content/common/input_messages.h"
#include "content/public/test/mock_render_process_host.h"
#include "content/public/test/test_browser_context.h"
+#include "content/test/mock_widget_impl.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"
@@ -140,9 +141,12 @@ TEST_F(RenderWidgetHostViewMacEditCommandHelperWithTaskEnvTest,
base::mac::ScopedNSAutoreleasePool pool;
int32_t routing_id = process_host->GetNextRoutingID();
+ mojom::WidgetPtr widget;
+ std::unique_ptr<MockWidgetImpl> widget_impl =
+ base::MakeUnique<MockWidgetImpl>(mojo::MakeRequest(&widget));
- RenderWidgetHostImpl* render_widget =
- new RenderWidgetHostImpl(&delegate, process_host, routing_id, false);
+ RenderWidgetHostImpl* render_widget = new RenderWidgetHostImpl(
+ &delegate, process_host, routing_id, std::move(widget), false);
ui::WindowResizeHelperMac::Get()->Init(base::ThreadTaskRunnerHandle::Get());
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 ef72d1745ec..0e01de741ae 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
@@ -36,6 +36,7 @@
#include "content/public/test/mock_render_process_host.h"
#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_utils.h"
+#include "content/test/mock_widget_impl.h"
#include "content/test/test_render_view_host.h"
#include "gpu/ipc/common/gpu_messages.h"
#include "gpu/ipc/service/image_transport_surface.h"
@@ -236,13 +237,7 @@ class MockRenderWidgetHostDelegate : public RenderWidgetHostDelegate {
class MockRenderWidgetHostImpl : public RenderWidgetHostImpl {
public:
- MockRenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
- RenderProcessHost* process,
- int32_t routing_id)
- : RenderWidgetHostImpl(delegate, process, routing_id, false) {
- set_renderer_initialized(true);
- lastWheelEventLatencyInfo = ui::LatencyInfo();
- }
+ ~MockRenderWidgetHostImpl() override {}
// Extracts |latency_info| and stores it in |lastWheelEventLatencyInfo|.
void ForwardWheelEventWithLatencyInfo (
@@ -257,8 +252,36 @@ class MockRenderWidgetHostImpl : public RenderWidgetHostImpl {
MOCK_METHOD0(Blur, void());
ui::LatencyInfo lastWheelEventLatencyInfo;
+ static MockRenderWidgetHostImpl* Create(RenderWidgetHostDelegate* delegate,
+ RenderProcessHost* process,
+ int32_t routing_id) {
+ mojom::WidgetPtr widget;
+ std::unique_ptr<MockWidgetImpl> widget_impl =
+ base::MakeUnique<MockWidgetImpl>(mojo::MakeRequest(&widget));
+
+ return new MockRenderWidgetHostImpl(delegate, process, routing_id,
+ std::move(widget_impl),
+ std::move(widget));
+ }
private:
+ MockRenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
+ RenderProcessHost* process,
+ int32_t routing_id,
+ std::unique_ptr<MockWidgetImpl> widget_impl,
+ mojom::WidgetPtr widget)
+ : RenderWidgetHostImpl(delegate,
+ process,
+ routing_id,
+ std::move(widget),
+ false),
+ widget_impl_(std::move(widget_impl)) {
+ set_renderer_initialized(true);
+ lastWheelEventLatencyInfo = ui::LatencyInfo();
+ }
+
+ std::unique_ptr<MockWidgetImpl> widget_impl_;
+
DISALLOW_COPY_AND_ASSIGN(MockRenderWidgetHostImpl);
};
@@ -339,11 +362,18 @@ NSEvent* MockScrollWheelEventWithMomentumPhase(SEL mockPhaseSelector,
class RenderWidgetHostViewMacTest : public RenderViewHostImplTestHarness {
public:
- RenderWidgetHostViewMacTest() : rwhv_mac_(nullptr), old_rwhv_(nullptr) {
+ RenderWidgetHostViewMacTest(bool scroll_latching = false)
+ : rwhv_mac_(nullptr),
+ scroll_latching_(scroll_latching),
+ old_rwhv_(nullptr) {
std::unique_ptr<base::SimpleTestTickClock> mock_clock(
new base::SimpleTestTickClock());
mock_clock->Advance(base::TimeDelta::FromMilliseconds(100));
ui::SetEventTickClockForTesting(std::move(mock_clock));
+ if (scroll_latching)
+ EnableWheelScrollLatching();
+ else
+ DisableWheelScrollLatching();
}
void SetUp() override {
@@ -397,8 +427,22 @@ class RenderWidgetHostViewMacTest : public RenderViewHostImplTestHarness {
return base::UTF16ToUTF8(rwhv_mac_->GetTextSelection()->selected_text());
}
+ void EnableWheelScrollLatching() {
+ feature_list_.InitFromCommandLine(
+ features::kTouchpadAndWheelScrollLatching.name, "");
+ }
+
+ void DisableWheelScrollLatching() {
+ feature_list_.InitFromCommandLine(
+ "", features::kTouchpadAndWheelScrollLatching.name);
+ }
+
+ void IgnoreEmptyUnhandledWheelEventWithWheelGestures();
+ void ScrollWheelEndEventDelivery();
+
RenderWidgetHostViewMac* rwhv_mac_;
base::scoped_nsobject<RenderWidgetHostViewCocoa> rwhv_cocoa_;
+ bool scroll_latching_;
private:
// This class isn't derived from PlatformTest.
@@ -406,6 +450,8 @@ class RenderWidgetHostViewMacTest : public RenderViewHostImplTestHarness {
RenderWidgetHostView* old_rwhv_;
+ base::test::ScopedFeatureList feature_list_;
+
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewMacTest);
};
@@ -460,8 +506,8 @@ TEST_F(RenderWidgetHostViewMacTest, FullscreenCloseOnEscape) {
new MockRenderProcessHost(&browser_context);
int32_t routing_id = process_host->GetNextRoutingID();
// Owned by its |cocoa_view()|.
- RenderWidgetHostImpl* rwh =
- new RenderWidgetHostImpl(&delegate, process_host, routing_id, false);
+ MockRenderWidgetHostImpl* rwh =
+ MockRenderWidgetHostImpl::Create(&delegate, process_host, routing_id);
RenderWidgetHostViewMac* view = new RenderWidgetHostViewMac(rwh, false);
view->InitAsFullscreen(rwhv_mac_);
@@ -494,8 +540,8 @@ TEST_F(RenderWidgetHostViewMacTest, AcceleratorDestroy) {
new MockRenderProcessHost(&browser_context);
int32_t routing_id = process_host->GetNextRoutingID();
// Owned by its |cocoa_view()|.
- RenderWidgetHostImpl* rwh =
- new RenderWidgetHostImpl(&delegate, process_host, routing_id, false);
+ MockRenderWidgetHostImpl* rwh =
+ MockRenderWidgetHostImpl::Create(&delegate, process_host, routing_id);
RenderWidgetHostViewMac* view = new RenderWidgetHostViewMac(rwh, false);
view->InitAsFullscreen(rwhv_mac_);
@@ -527,7 +573,7 @@ TEST_F(RenderWidgetHostViewMacTest, FilterNonPrintableCharacter) {
MockRenderWidgetHostDelegate delegate;
int32_t routing_id = process_host->GetNextRoutingID();
MockRenderWidgetHostImpl* host =
- new MockRenderWidgetHostImpl(&delegate, process_host, routing_id);
+ MockRenderWidgetHostImpl::Create(&delegate, process_host, routing_id);
RenderWidgetHostViewMac* view = new RenderWidgetHostViewMac(host, false);
// Simulate ctrl+F12, will produce a private use character but shouldn't
@@ -573,7 +619,7 @@ TEST_F(RenderWidgetHostViewMacTest, InvalidKeyCode) {
MockRenderWidgetHostDelegate delegate;
int32_t routing_id = process_host->GetNextRoutingID();
MockRenderWidgetHostImpl* host =
- new MockRenderWidgetHostImpl(&delegate, process_host, routing_id);
+ MockRenderWidgetHostImpl::Create(&delegate, process_host, routing_id);
RenderWidgetHostViewMac* view = new RenderWidgetHostViewMac(host, false);
// Simulate "Convert" key on JIS PC keyboard, will generate a |NSFlagsChanged|
@@ -954,7 +1000,7 @@ TEST_F(RenderWidgetHostViewMacTest, BlurAndFocusOnSetActive) {
// Owned by its |cocoa_view()|.
int32_t routing_id = process_host->GetNextRoutingID();
MockRenderWidgetHostImpl* rwh =
- new MockRenderWidgetHostImpl(&delegate, process_host, routing_id);
+ MockRenderWidgetHostImpl::Create(&delegate, process_host, routing_id);
RenderWidgetHostViewMac* view = new RenderWidgetHostViewMac(rwh, false);
base::scoped_nsobject<CocoaTestHelperWindow> window(
@@ -998,7 +1044,7 @@ TEST_F(RenderWidgetHostViewMacTest, LastWheelEventLatencyInfoExists) {
MockRenderWidgetHostDelegate delegate;
int32_t routing_id = process_host->GetNextRoutingID();
MockRenderWidgetHostImpl* host =
- new MockRenderWidgetHostImpl(&delegate, process_host, routing_id);
+ MockRenderWidgetHostImpl::Create(&delegate, process_host, routing_id);
RenderWidgetHostViewMac* view = new RenderWidgetHostViewMac(host, false);
process_host->sink().ClearMessages();
@@ -1036,7 +1082,7 @@ TEST_F(RenderWidgetHostViewMacTest, SourceEventTypeExistsInLatencyInfo) {
MockRenderWidgetHostDelegate delegate;
int32_t routing_id = process_host->GetNextRoutingID();
MockRenderWidgetHostImpl* host =
- new MockRenderWidgetHostImpl(&delegate, process_host, routing_id);
+ MockRenderWidgetHostImpl::Create(&delegate, process_host, routing_id);
RenderWidgetHostViewMac* view = new RenderWidgetHostViewMac(host, false);
process_host->sink().ClearMessages();
@@ -1051,7 +1097,7 @@ TEST_F(RenderWidgetHostViewMacTest, SourceEventTypeExistsInLatencyInfo) {
host->ShutdownAndDestroyWidget(true);
}
-TEST_F(RenderWidgetHostViewMacTest, ScrollWheelEndEventDelivery) {
+void RenderWidgetHostViewMacTest::ScrollWheelEndEventDelivery() {
// Initialize the view associated with a MockRenderWidgetHostImpl, rather than
// the MockRenderProcessHost that is set up by the test harness which mocks
// out |OnMessageReceived()|.
@@ -1062,7 +1108,7 @@ TEST_F(RenderWidgetHostViewMacTest, ScrollWheelEndEventDelivery) {
MockRenderWidgetHostDelegate delegate;
int32_t routing_id = process_host->GetNextRoutingID();
MockRenderWidgetHostImpl* host =
- new MockRenderWidgetHostImpl(&delegate, process_host, routing_id);
+ MockRenderWidgetHostImpl::Create(&delegate, process_host, routing_id);
RenderWidgetHostViewMac* view = new RenderWidgetHostViewMac(host, false);
process_host->sink().ClearMessages();
@@ -1088,11 +1134,21 @@ TEST_F(RenderWidgetHostViewMacTest, ScrollWheelEndEventDelivery) {
NSEvent* event2 = MockScrollWheelEventWithPhase(@selector(phaseEnded), 0);
[NSApp postEvent:event2 atStart:NO];
base::RunLoop().RunUntilIdle();
- ASSERT_EQ(1U, process_host->sink().message_count());
+ if (scroll_latching_) {
+ // The wheel event with phaseEnded won't be sent to the render view
+ // immediately, instead the mouse_wheel_phase_handler will wait for 100ms
+ // to see if a wheel event with momentumPhase began arrives or not.
+ ASSERT_EQ(0U, process_host->sink().message_count());
+ } else {
+ ASSERT_EQ(1U, process_host->sink().message_count());
+ }
// Clean up.
host->ShutdownAndDestroyWidget(true);
}
+TEST_F(RenderWidgetHostViewMacTest, ScrollWheelEndEventDelivery) {
+ ScrollWheelEndEventDelivery();
+}
TEST_F(RenderWidgetHostViewMacTest, PointerEventWithEraserType) {
// Initialize the view associated with a MockRenderWidgetHostImpl, rather than
@@ -1105,7 +1161,7 @@ TEST_F(RenderWidgetHostViewMacTest, PointerEventWithEraserType) {
MockRenderWidgetHostDelegate delegate;
int32_t routing_id = process_host->GetNextRoutingID();
MockRenderWidgetHostImpl* host =
- new MockRenderWidgetHostImpl(&delegate, process_host, routing_id);
+ MockRenderWidgetHostImpl::Create(&delegate, process_host, routing_id);
RenderWidgetHostViewMac* view = new RenderWidgetHostViewMac(host, false);
process_host->sink().ClearMessages();
@@ -1140,7 +1196,7 @@ TEST_F(RenderWidgetHostViewMacTest, PointerEventWithPenType) {
MockRenderWidgetHostDelegate delegate;
int32_t routing_id = process_host->GetNextRoutingID();
MockRenderWidgetHostImpl* host =
- new MockRenderWidgetHostImpl(&delegate, process_host, routing_id);
+ MockRenderWidgetHostImpl::Create(&delegate, process_host, routing_id);
RenderWidgetHostViewMac* view = new RenderWidgetHostViewMac(host, false);
process_host->sink().ClearMessages();
@@ -1175,7 +1231,7 @@ TEST_F(RenderWidgetHostViewMacTest, PointerEventWithMouseType) {
MockRenderWidgetHostDelegate delegate;
int32_t routing_id = process_host->GetNextRoutingID();
MockRenderWidgetHostImpl* host =
- new MockRenderWidgetHostImpl(&delegate, process_host, routing_id);
+ MockRenderWidgetHostImpl::Create(&delegate, process_host, routing_id);
RenderWidgetHostViewMac* view = new RenderWidgetHostViewMac(host, false);
process_host->sink().ClearMessages();
@@ -1192,8 +1248,8 @@ TEST_F(RenderWidgetHostViewMacTest, PointerEventWithMouseType) {
host->ShutdownAndDestroyWidget(true);
}
-TEST_F(RenderWidgetHostViewMacTest,
- IgnoreEmptyUnhandledWheelEventWithWheelGestures) {
+void RenderWidgetHostViewMacTest::
+ IgnoreEmptyUnhandledWheelEventWithWheelGestures() {
// Initialize the view associated with a MockRenderWidgetHostImpl, rather than
// the MockRenderProcessHost that is set up by the test harness which mocks
// out |OnMessageReceived()|.
@@ -1204,7 +1260,7 @@ TEST_F(RenderWidgetHostViewMacTest,
MockRenderWidgetHostDelegate delegate;
int32_t routing_id = process_host->GetNextRoutingID();
MockRenderWidgetHostImpl* host =
- new MockRenderWidgetHostImpl(&delegate, process_host, routing_id);
+ MockRenderWidgetHostImpl::Create(&delegate, process_host, routing_id);
RenderWidgetHostViewMac* view = new RenderWidgetHostViewMac(host, false);
process_host->sink().ClearMessages();
@@ -1226,7 +1282,21 @@ TEST_F(RenderWidgetHostViewMacTest,
std::unique_ptr<IPC::Message> response1(
new InputHostMsg_HandleInputEvent_ACK(0, unhandled_ack));
host->OnMessageReceived(*response1);
- ASSERT_EQ(2U, process_host->sink().message_count());
+
+ if (scroll_latching_) {
+ // Only wheel event ack exists since GSB event is blocking.
+ ASSERT_EQ(1U, process_host->sink().message_count());
+ // Send GSB ack.
+ InputEventAck unhandled_scroll_ack(
+ InputEventAckSource::COMPOSITOR_THREAD,
+ blink::WebInputEvent::kGestureScrollBegin,
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ std::unique_ptr<IPC::Message> scroll_response1(
+ new InputHostMsg_HandleInputEvent_ACK(0, unhandled_scroll_ack));
+ host->OnMessageReceived(*scroll_response1);
+ } else {
+ ASSERT_EQ(2U, process_host->sink().message_count());
+ }
process_host->sink().ClearMessages();
InputEventAck unhandled_scroll_ack(InputEventAckSource::COMPOSITOR_THREAD,
@@ -1243,7 +1313,12 @@ TEST_F(RenderWidgetHostViewMacTest,
// Send another wheel event, this time for scrolling by 0 lines (empty event).
NSEvent* event2 = MockScrollWheelEventWithPhase(@selector(phaseChanged), 0);
[view->cocoa_view() scrollWheel:event2];
- ASSERT_EQ(2U, process_host->sink().message_count());
+ if (scroll_latching_) {
+ ASSERT_EQ(1U, process_host->sink().message_count());
+ } else {
+ // The second message will be nonblocking GSB's ack.
+ ASSERT_EQ(2U, process_host->sink().message_count());
+ }
// Indicate that the wheel event was also unhandled.
std::unique_ptr<IPC::Message> response2(
@@ -1256,6 +1331,10 @@ TEST_F(RenderWidgetHostViewMacTest,
// Clean up.
host->ShutdownAndDestroyWidget(true);
}
+TEST_F(RenderWidgetHostViewMacTest,
+ IgnoreEmptyUnhandledWheelEventWithWheelGestures) {
+ IgnoreEmptyUnhandledWheelEventWithWheelGestures();
+}
// Tests that when view initiated shutdown happens (i.e. RWHView is deleted
// before RWH), we clean up properly and don't leak the RWHVGuest.
@@ -1269,7 +1348,7 @@ TEST_F(RenderWidgetHostViewMacTest, GuestViewDoesNotLeak) {
// Owned by its |cocoa_view()|.
MockRenderWidgetHostImpl* rwh =
- new MockRenderWidgetHostImpl(&delegate, process_host, routing_id);
+ MockRenderWidgetHostImpl::Create(&delegate, process_host, routing_id);
RenderWidgetHostViewMac* view = new RenderWidgetHostViewMac(rwh, true);
// Add a delegate to the view.
@@ -1304,6 +1383,9 @@ TEST_F(RenderWidgetHostViewMacTest, GuestViewDoesNotLeak) {
// RenderWidgetHostTest.Background. This test has some additional checks for
// Mac.
TEST_F(RenderWidgetHostViewMacTest, Background) {
+ const IPC::Message* set_background = nullptr;
+ std::tuple<bool> sent_background;
+
TestBrowserContext browser_context;
MockRenderProcessHost* process_host =
new MockRenderProcessHost(&browser_context);
@@ -1311,53 +1393,70 @@ TEST_F(RenderWidgetHostViewMacTest, Background) {
MockRenderWidgetHostDelegate delegate;
int32_t routing_id = process_host->GetNextRoutingID();
MockRenderWidgetHostImpl* host =
- new MockRenderWidgetHostImpl(&delegate, process_host, routing_id);
+ MockRenderWidgetHostImpl::Create(&delegate, process_host, routing_id);
RenderWidgetHostViewMac* view = new RenderWidgetHostViewMac(host, false);
- EXPECT_EQ(static_cast<unsigned>(SK_ColorTRANSPARENT),
- view->background_color());
- EXPECT_FALSE([view->cocoa_view() isOpaque]);
+ // If no color has been specified then default color of white should be
+ // returned.
+ EXPECT_EQ(static_cast<unsigned>(SK_ColorWHITE), view->background_color());
- view->SetBackgroundColor(SK_ColorWHITE);
- EXPECT_NE(static_cast<unsigned>(SK_ColorTRANSPARENT),
- view->background_color());
- EXPECT_TRUE([view->cocoa_view() isOpaque]);
+ // Set the color to red. The background is initially assumed to be opaque, so
+ // no opacity message change should be sent.
+ view->SetBackgroundColor(SK_ColorRED);
+ EXPECT_EQ(static_cast<unsigned>(SK_ColorRED), view->background_color());
+ set_background = process_host->sink().GetUniqueMessageMatching(
+ ViewMsg_SetBackgroundOpaque::ID);
+ ASSERT_FALSE(set_background);
- const IPC::Message* set_background;
+ // Set the color to blue. This should not send an opacity message.
+ view->SetBackgroundColor(SK_ColorBLUE);
+ EXPECT_EQ(static_cast<unsigned>(SK_ColorBLUE), view->background_color());
set_background = process_host->sink().GetUniqueMessageMatching(
ViewMsg_SetBackgroundOpaque::ID);
- ASSERT_TRUE(set_background);
- std::tuple<bool> sent_background;
- ViewMsg_SetBackgroundOpaque::Read(set_background, &sent_background);
- EXPECT_TRUE(std::get<0>(sent_background));
+ ASSERT_FALSE(set_background);
- // Try setting it back.
+ // Set the color back to transparent. The background color should now be
+ // reported as the default (white), and a transparency change message should
+ // be sent.
process_host->sink().ClearMessages();
view->SetBackgroundColor(SK_ColorTRANSPARENT);
- EXPECT_EQ(static_cast<unsigned>(SK_ColorTRANSPARENT),
- view->background_color());
- EXPECT_FALSE([view->cocoa_view() isOpaque]);
+ EXPECT_EQ(static_cast<unsigned>(SK_ColorWHITE), view->background_color());
set_background = process_host->sink().GetUniqueMessageMatching(
ViewMsg_SetBackgroundOpaque::ID);
ASSERT_TRUE(set_background);
ViewMsg_SetBackgroundOpaque::Read(set_background, &sent_background);
EXPECT_FALSE(std::get<0>(sent_background));
+ // Set the color to red. This should send an opacity message.
+ process_host->sink().ClearMessages();
+ view->SetBackgroundColor(SK_ColorBLUE);
+ EXPECT_EQ(static_cast<unsigned>(SK_ColorBLUE), view->background_color());
+ set_background = process_host->sink().GetUniqueMessageMatching(
+ ViewMsg_SetBackgroundOpaque::ID);
+ ASSERT_TRUE(set_background);
+ ViewMsg_SetBackgroundOpaque::Read(set_background, &sent_background);
+ EXPECT_TRUE(std::get<0>(sent_background));
+
host->ShutdownAndDestroyWidget(true);
}
class RenderWidgetHostViewMacWithWheelScrollLatchingEnabledTest
: public RenderWidgetHostViewMacTest {
public:
- RenderWidgetHostViewMacWithWheelScrollLatchingEnabledTest() {
- feature_list_.InitFromCommandLine(
- features::kTouchpadAndWheelScrollLatching.name, "");
- }
-
- private:
- base::test::ScopedFeatureList feature_list_;
+ RenderWidgetHostViewMacWithWheelScrollLatchingEnabledTest()
+ : RenderWidgetHostViewMacTest(true) {}
};
+TEST_F(RenderWidgetHostViewMacWithWheelScrollLatchingEnabledTest,
+ IgnoreEmptyUnhandledWheelEventWithWheelGestures) {
+ IgnoreEmptyUnhandledWheelEventWithWheelGestures();
+}
+
+TEST_F(RenderWidgetHostViewMacWithWheelScrollLatchingEnabledTest,
+ ScrollWheelEndEventDelivery) {
+ ScrollWheelEndEventDelivery();
+}
+
// When wheel scroll latching is enabled, wheel end events are not sent
// immediately, instead we start a timer to see if momentum phase of the scroll
// starts or not.
@@ -1373,7 +1472,7 @@ TEST_F(RenderWidgetHostViewMacWithWheelScrollLatchingEnabledTest,
MockRenderWidgetHostDelegate delegate;
int32_t routing_id = process_host->GetNextRoutingID();
MockRenderWidgetHostImpl* host =
- new MockRenderWidgetHostImpl(&delegate, process_host, routing_id);
+ MockRenderWidgetHostImpl::Create(&delegate, process_host, routing_id);
RenderWidgetHostViewMac* view = new RenderWidgetHostViewMac(host, false);
process_host->sink().ClearMessages();
@@ -1420,7 +1519,7 @@ TEST_F(RenderWidgetHostViewMacWithWheelScrollLatchingEnabledTest,
MockRenderWidgetHostDelegate delegate;
int32_t routing_id = process_host->GetNextRoutingID();
MockRenderWidgetHostImpl* host =
- new MockRenderWidgetHostImpl(&delegate, process_host, routing_id);
+ MockRenderWidgetHostImpl::Create(&delegate, process_host, routing_id);
RenderWidgetHostViewMac* view = new RenderWidgetHostViewMac(host, false);
process_host->sink().ClearMessages();
@@ -1477,7 +1576,7 @@ TEST_F(RenderWidgetHostViewMacWithWheelScrollLatchingEnabledTest,
MockRenderWidgetHostDelegate delegate;
int32_t routing_id = process_host->GetNextRoutingID();
MockRenderWidgetHostImpl* host =
- new MockRenderWidgetHostImpl(&delegate, process_host, routing_id);
+ MockRenderWidgetHostImpl::Create(&delegate, process_host, routing_id);
RenderWidgetHostViewMac* view = new RenderWidgetHostViewMac(host, false);
process_host->sink().ClearMessages();
@@ -1537,8 +1636,8 @@ class RenderWidgetHostViewMacPinchTest : public RenderWidgetHostViewMacTest {
process_host_->Init();
delegate_.reset(new MockRenderWidgetHostDelegate);
int32_t routing_id = process_host_->GetNextRoutingID();
- host_.reset(new MockRenderWidgetHostImpl(delegate_.get(),
- process_host_.get(), routing_id));
+ host_.reset(MockRenderWidgetHostImpl::Create(
+ delegate_.get(), process_host_.get(), routing_id));
view_ = new RenderWidgetHostViewMac(host_.get(), false);
cocoa_view_.reset([view_->cocoa_view() retain]);
process_host_->sink().ClearMessages();
@@ -1724,7 +1823,7 @@ TEST_F(RenderWidgetHostViewMacTest, EventLatencyOSMouseWheelHistogram) {
MockRenderWidgetHostDelegate delegate;
int32_t routing_id = process_host->GetNextRoutingID();
MockRenderWidgetHostImpl* host =
- new MockRenderWidgetHostImpl(&delegate, process_host, routing_id);
+ MockRenderWidgetHostImpl::Create(&delegate, process_host, routing_id);
RenderWidgetHostViewMac* view = new RenderWidgetHostViewMac(host, false);
process_host->sink().ClearMessages();
@@ -1774,9 +1873,9 @@ class InputMethodMacTest : public RenderWidgetHostViewMacTest {
child_process_host_ = new MockRenderProcessHost(&browser_context_);
RenderWidgetHostDelegate* rwh_delegate =
RenderWidgetHostImpl::From(rvh()->GetWidget())->delegate();
- child_widget_ = new RenderWidgetHostImpl(
+ child_widget_ = MockRenderWidgetHostImpl::Create(
rwh_delegate, child_process_host_,
- child_process_host_->GetNextRoutingID(), false);
+ child_process_host_->GetNextRoutingID());
child_view_ = new TestRenderWidgetHostView(child_widget_);
text_input_manager_ = rwh_delegate->GetTextInputManager();
tab_widget_ = RenderWidgetHostImpl::From(rvh()->GetWidget());
@@ -2089,4 +2188,14 @@ TEST_F(RenderWidgetHostViewMacTest, ForwardKeyEquivalentsOnlyIfKey) {
rwhv_mac_->release_pepper_fullscreen_window_for_testing();
}
+TEST_F(RenderWidgetHostViewMacTest, ClearCompositorFrame) {
+ BrowserCompositorMac* browser_compositor =
+ rwhv_mac_->BrowserCompositorForTesting();
+ EXPECT_NE(browser_compositor->CompositorForTesting(), nullptr);
+ EXPECT_TRUE(browser_compositor->CompositorForTesting()->IsLocked());
+ rwhv_mac_->ClearCompositorFrame();
+ EXPECT_NE(browser_compositor->CompositorForTesting(), nullptr);
+ EXPECT_FALSE(browser_compositor->CompositorForTesting()->IsLocked());
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/sandbox_ipc_linux.cc b/chromium/content/browser/renderer_host/sandbox_ipc_linux.cc
index c2cae8d5a0f..3d0b33417ef 100644
--- a/chromium/content/browser/renderer_host/sandbox_ipc_linux.cc
+++ b/chromium/content/browser/renderer_host/sandbox_ipc_linux.cc
@@ -18,7 +18,7 @@
#include "base/macros.h"
#include "base/memory/shared_memory.h"
#include "base/posix/eintr_wrapper.h"
-#include "base/posix/unix_domain_socket_linux.h"
+#include "base/posix/unix_domain_socket.h"
#include "base/process/launch.h"
#include "base/strings/string_number_conversions.h"
#include "content/browser/renderer_host/font_utils_linux.h"
diff --git a/chromium/content/browser/renderer_host/text_input_client_mac_unittest.mm b/chromium/content/browser/renderer_host/text_input_client_mac_unittest.mm
index 73c1be83da2..2cda8306141 100644
--- a/chromium/content/browser/renderer_host/text_input_client_mac_unittest.mm
+++ b/chromium/content/browser/renderer_host/text_input_client_mac_unittest.mm
@@ -19,6 +19,7 @@
#include "content/common/text_input_client_messages.h"
#include "content/public/test/mock_render_process_host.h"
#include "content/public/test/test_browser_context.h"
+#include "content/test/mock_widget_impl.h"
#include "ipc/ipc_test_sink.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/gtest_mac.h"
@@ -58,7 +59,12 @@ class TextInputClientMacTest : public testing::Test {
RenderProcessHost* rph =
process_factory_.CreateRenderProcessHost(&browser_context_);
int32_t routing_id = rph->GetNextRoutingID();
- widget_.reset(new RenderWidgetHostImpl(&delegate_, rph, routing_id, false));
+ mojom::WidgetPtr widget;
+ mock_widget_impl_ =
+ base::MakeUnique<MockWidgetImpl>(mojo::MakeRequest(&widget));
+
+ widget_.reset(new RenderWidgetHostImpl(&delegate_, rph, routing_id,
+ std::move(widget), false));
}
void TearDown() override {
@@ -106,6 +112,7 @@ class TextInputClientMacTest : public testing::Test {
MockRenderProcessHostFactory process_factory_;
MockRenderWidgetHostDelegate delegate_;
std::unique_ptr<RenderWidgetHostImpl> widget_;
+ std::unique_ptr<MockWidgetImpl> mock_widget_impl_;
base::Thread thread_;
};
diff --git a/chromium/content/browser/resource_loading_browsertest.cc b/chromium/content/browser/resource_loading_browsertest.cc
index b245ac16717..f04dbfe8d33 100644
--- a/chromium/content/browser/resource_loading_browsertest.cc
+++ b/chromium/content/browser/resource_loading_browsertest.cc
@@ -22,11 +22,11 @@ IN_PROC_BROWSER_TEST_F(ResourceLoadingBrowserTest,
ResourceLoadingAvoidDoubleDownloads) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL url = embedded_test_server()->GetURL(kResourceLoadingNonMobilePage);
- NavigateToURL(shell(), url);
+ EXPECT_TRUE(NavigateToURL(shell(), url));
int data = -1;
EXPECT_TRUE(
ExecuteScriptAndExtractInt(shell(), "getResourceNumber()", &data));
- EXPECT_EQ(2, data);
+ EXPECT_EQ(9, data);
}
} // namespace content
diff --git a/chromium/content/browser/resources/accessibility/OWNERS b/chromium/content/browser/resources/accessibility/OWNERS
index 5ec44f48081..697dba28c57 100644
--- a/chromium/content/browser/resources/accessibility/OWNERS
+++ b/chromium/content/browser/resources/accessibility/OWNERS
@@ -1,5 +1,4 @@
-aboxhall@chromium.org
-dmazzoni@chromium.org
+file://ui/accessibility/OWNERS
# TEAM: chromium-accessibility@chromium.org
-# COMPONENT: UI>Accessibility
+# COMPONENT: Internals>Accessibility
diff --git a/chromium/content/browser/resources/accessibility/accessibility.js b/chromium/content/browser/resources/accessibility/accessibility.js
index c805b364082..4750364882f 100644
--- a/chromium/content/browser/resources/accessibility/accessibility.js
+++ b/chromium/content/browser/resources/accessibility/accessibility.js
@@ -7,23 +7,23 @@ cr.define('accessibility', function() {
// Note: keep these values in sync with the values in
// content/common/accessibility_mode_enums.h
- const AccessibilityMode = {
+ const AXMode = {
kNativeAPIs: 1 << 0,
kWebContents: 1 << 1,
kInlineTextBoxes: 1 << 2,
kScreenReader: 1 << 3,
kHTML: 1 << 4,
- get kAccessibilityModeWebContentsOnly() {
- return AccessibilityMode.kWebContents |
- AccessibilityMode.kInlineTextBoxes | AccessibilityMode.kScreenReader |
- AccessibilityMode.kHTML;
+ get kAXModeWebContentsOnly() {
+ return AXMode.kWebContents |
+ AXMode.kInlineTextBoxes | AXMode.kScreenReader |
+ AXMode.kHTML;
},
- get kAccessibilityModeComplete() {
- return AccessibilityMode.kNativeAPIs | AccessibilityMode.kWebContents |
- AccessibilityMode.kInlineTextBoxes | AccessibilityMode.kScreenReader |
- AccessibilityMode.kHTML;
+ get kAXModeComplete() {
+ return AXMode.kNativeAPIs | AXMode.kWebContents |
+ AXMode.kInlineTextBoxes | AXMode.kScreenReader |
+ AXMode.kHTML;
}
};
@@ -110,12 +110,12 @@ cr.define('accessibility', function() {
siteInfo.appendChild(formatValue(data, properties[j]));
row.appendChild(siteInfo);
- row.appendChild(createModeElement(AccessibilityMode.kNativeAPIs, data))
- row.appendChild(createModeElement(AccessibilityMode.kWebContents, data))
- row.appendChild(createModeElement(AccessibilityMode.kInlineTextBoxes,
+ row.appendChild(createModeElement(AXMode.kNativeAPIs, data))
+ row.appendChild(createModeElement(AXMode.kWebContents, data))
+ row.appendChild(createModeElement(AXMode.kInlineTextBoxes,
data))
- row.appendChild(createModeElement(AccessibilityMode.kScreenReader, data))
- row.appendChild(createModeElement(AccessibilityMode.kHTML, data))
+ row.appendChild(createModeElement(AXMode.kScreenReader, data))
+ row.appendChild(createModeElement(AXMode.kHTML, data))
row.appendChild(document.createTextNode(' | '));
@@ -154,15 +154,15 @@ cr.define('accessibility', function() {
function getNameForAccessibilityMode(mode) {
switch (mode) {
- case AccessibilityMode.kNativeAPIs:
+ case AXMode.kNativeAPIs:
return "native"
- case AccessibilityMode.kWebContents:
+ case AXMode.kWebContents:
return "web"
- case AccessibilityMode.kInlineTextBoxes:
+ case AXMode.kInlineTextBoxes:
return "inline text"
- case AccessibilityMode.kScreenReader:
+ case AXMode.kScreenReader:
return "screen reader"
- case AccessibilityMode.kHTML:
+ case AXMode.kHTML:
return "html"
}
return "unknown"
diff --git a/chromium/content/browser/resources/media/dump_creator.js b/chromium/content/browser/resources/media/dump_creator.js
index be913705f07..88f2c65263c 100644
--- a/chromium/content/browser/resources/media/dump_creator.js
+++ b/chromium/content/browser/resources/media/dump_creator.js
@@ -89,22 +89,22 @@ var DumpCreator = (function() {
DumpCreator.prototype = {
// Mark the diagnostic audio recording checkbox checked.
- enableAudioDebugRecordings: function() {
+ setAudioDebugRecordingsCheckbox: function() {
this.root_.getElementsByTagName('input')[0].checked = true;
},
// Mark the diagnostic audio recording checkbox unchecked.
- disableAudioDebugRecordings: function() {
+ clearAudioDebugRecordingsCheckbox: function() {
this.root_.getElementsByTagName('input')[0].checked = false;
},
// Mark the event log recording checkbox checked.
- enableEventLogRecordings: function() {
+ setEventLogRecordingsCheckbox: function() {
this.root_.getElementsByTagName('input')[1].checked = true;
},
// Mark the event log recording checkbox unchecked.
- disableEventLogRecordings: function() {
+ clearEventLogRecordingsCheckbox: function() {
this.root_.getElementsByTagName('input')[1].checked = false;
},
diff --git a/chromium/content/browser/resources/media/media_internals.css b/chromium/content/browser/resources/media/media_internals.css
index ba0997c93a9..7daaa773c62 100644
--- a/chromium/content/browser/resources/media/media_internals.css
+++ b/chromium/content/browser/resources/media/media_internals.css
@@ -126,6 +126,7 @@ h3 {
#clipboard-dialog {
top: 0;
bottom: 0;
+ padding-top: 0;
}
::backdrop {
@@ -187,6 +188,7 @@ label.selectable-button {
padding: 6px;
margin: 4px 0;
line-height: 1.4;
+ word-break: break-all;
}
input.selectable-button {
diff --git a/chromium/content/browser/resources/media/media_internals.html b/chromium/content/browser/resources/media/media_internals.html
index 24801d88316..e624b5a2419 100644
--- a/chromium/content/browser/resources/media/media_internals.html
+++ b/chromium/content/browser/resources/media/media_internals.html
@@ -123,6 +123,7 @@ found in the LICENSE file.
</tabpanels>
</tabbox>
<dialog id="clipboard-dialog">
+ <p>Ctrl+C to copy to clipboard, unfocus to exit.</p>
<textarea id="clipboard-textarea" rows="30" cols="80"></textarea>
</dialog>
<script src="media_internals.js"></script>
diff --git a/chromium/content/browser/resources/media/stats_graph_helper.js b/chromium/content/browser/resources/media/stats_graph_helper.js
index da6566312a3..daa28866f6a 100644
--- a/chromium/content/browser/resources/media/stats_graph_helper.js
+++ b/chromium/content/browser/resources/media/stats_graph_helper.js
@@ -299,7 +299,7 @@ function ensureStatsGraphTopContainer(peerConnectionElement, report) {
container.firstChild.firstChild.className =
STATS_GRAPH_CONTAINER_HEADING_CLASS;
container.firstChild.firstChild.textContent =
- 'Stats graphs for ' + report.id;
+ 'Stats graphs for ' + report.id + ' (' + report.type + ')';
var statsType = getSsrcReportType(report);
if (statsType != '')
container.firstChild.firstChild.textContent += ' (' + statsType + ')';
@@ -346,7 +346,7 @@ function createBweCompoundLegend(peerConnectionElement, reportId) {
for (var prop in bweCompoundGraphConfig) {
var div = document.createElement('div');
legend.appendChild(div);
- div.innerHTML = '<input type=checkbox checked></input>' + prop;
+ div.innerHTML = '<input type=checkbox checked>' + prop;
div.style.color = bweCompoundGraphConfig[prop].color;
div.dataSeriesId = reportId + '-' + prop;
div.graphViewId =
diff --git a/chromium/content/browser/resources/media/webrtc_internals.js b/chromium/content/browser/resources/media/webrtc_internals.js
index 8ada8ade8d3..4c279a4d304 100644
--- a/chromium/content/browser/resources/media/webrtc_internals.js
+++ b/chromium/content/browser/resources/media/webrtc_internals.js
@@ -327,7 +327,7 @@ function removeGetUserMediaForRenderer(data) {
* cancelled, i.e. recordings have not been enabled.
*/
function audioDebugRecordingsFileSelectionCancelled() {
- dumpCreator.disableAudioDebugRecordings();
+ dumpCreator.clearAudioDebugRecordingsCheckbox();
}
@@ -336,12 +336,23 @@ function audioDebugRecordingsFileSelectionCancelled() {
* cancelled, i.e. recordings have not been enabled.
*/
function eventLogRecordingsFileSelectionCancelled() {
- dumpCreator.disableEventLogRecordings();
+ dumpCreator.clearEventLogRecordingsCheckbox();
}
+
+/**
+ * Notification that audio debug recordings are enabled. Used e.g. on page load
+ * to update the UI to reflect the recording state.
+ */
+function setAudioDebugRecordingsEnabled() {
+ dumpCreator.setAudioDebugRecordingsCheckbox();
+}
+
+
/**
- * Set
+ * Notification that event log recordings are enabled. Used e.g. on page load
+ * to update the UI to reflect the recording state.
*/
-function enableAudioDebugRecordings() {
- dumpCreator.enableAudioDebugRecordings();
+function setEventLogRecordingsEnabled() {
+ dumpCreator.setEventLogRecordingsCheckbox();
}
diff --git a/chromium/content/browser/screen_orientation/screen_orientation_provider.h b/chromium/content/browser/screen_orientation/screen_orientation_provider.h
index f525e0eb9df..1f2b7c7c4c3 100644
--- a/chromium/content/browser/screen_orientation/screen_orientation_provider.h
+++ b/chromium/content/browser/screen_orientation/screen_orientation_provider.h
@@ -24,7 +24,7 @@ class WebContents;
// Handles screen orientation lock/unlock. Platforms which wish to provide
// custom implementations can provide a factory for ScreenOrientationDelegate.
class CONTENT_EXPORT ScreenOrientationProvider
- : NON_EXPORTED_BASE(public device::mojom::ScreenOrientation),
+ : public device::mojom::ScreenOrientation,
public WebContentsObserver {
public:
ScreenOrientationProvider(WebContents* web_contents);
diff --git a/chromium/content/browser/security_exploit_browsertest.cc b/chromium/content/browser/security_exploit_browsertest.cc
index 6f0ec5aa974..e0aa8143d38 100644
--- a/chromium/content/browser/security_exploit_browsertest.cc
+++ b/chromium/content/browser/security_exploit_browsertest.cc
@@ -38,9 +38,11 @@
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
+#include "content/public/test/test_navigation_observer.h"
#include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test_utils_internal.h"
+#include "content/test/mock_widget_impl.h"
#include "content/test/test_content_browser_client.h"
#include "ipc/ipc_security_test_util.h"
#include "net/dns/mock_host_resolver.h"
@@ -137,7 +139,7 @@ ResourceRequest CreateXHRRequest(const char* url) {
ResourceRequest CreateXHRRequestWithOrigin(const char* origin) {
ResourceRequest request = CreateXHRRequest("http://bar.com/simple_page.html");
- request.first_party_for_cookies = GURL(origin);
+ request.site_for_cookies = GURL(origin);
request.headers = base::StringPrintf("Origin: %s\r\n", origin);
return request;
}
@@ -178,15 +180,6 @@ void TryCreateDuplicateRequestIds(Shell* shell, bool block_loaders) {
} // namespace
-class WidgetImpl : public mojom::Widget {
- public:
- explicit WidgetImpl(mojo::InterfaceRequest<mojom::Widget> request)
- : binding_(this, std::move(request)) {}
-
- private:
- mojo::Binding<mojom::Widget> binding_;
-};
-
// The goal of these tests will be to "simulate" exploited renderer processes,
// which can send arbitrary IPC messages and confuse browser process internal
// state, leading to security bugs. We are trying to verify that the browser
@@ -308,8 +301,8 @@ IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest,
EXPECT_NE(MSG_ROUTING_NONE, duplicate_routing_id);
mojom::WidgetPtr widget;
- std::unique_ptr<WidgetImpl> widget_impl =
- base::MakeUnique<WidgetImpl>(mojo::MakeRequest(&widget));
+ std::unique_ptr<MockWidgetImpl> widget_impl =
+ base::MakeUnique<MockWidgetImpl>(mojo::MakeRequest(&widget));
// Since this test executes on the UI thread and hopping threads might cause
// different timing in the test, let's simulate a CreateNewWidget call coming
@@ -639,4 +632,84 @@ IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest,
EXPECT_FALSE(exit_observer.did_exit_normally());
}
+// Test that forging a frame's unique name and commit won't allow changing the
+// PageState of a cross-process FrameNavigationEntry.
+// See https://crbug.com/766262.
+IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, PageStateToWrongEntry) {
+ IsolateAllSitesForTesting(base::CommandLine::ForCurrentProcess());
+
+ // Commit a page with nested iframes and a separate cross-process iframe.
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(a(a),b)"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+ NavigationEntryImpl* back_entry = static_cast<NavigationEntryImpl*>(
+ shell()->web_contents()->GetController().GetLastCommittedEntry());
+ int nav_entry_id = back_entry->GetUniqueID();
+
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+ FrameTreeNode* child0_0 = root->child_at(0)->child_at(0);
+ std::string child0_0_unique_name = child0_0->unique_name();
+ FrameTreeNode* child1 = root->child_at(1);
+ GURL child1_url = child1->current_url();
+ int child1_pid = child1->current_frame_host()->GetProcess()->GetID();
+ PageState child1_page_state = back_entry->GetFrameEntry(child1)->page_state();
+
+ // Add a history item in the nested frame. It's important to do it there and
+ // not the main frame for the repro to work, since we don't walk the subtree
+ // when navigating back/forward between same document items.
+ TestNavigationObserver fragment_observer(shell()->web_contents());
+ EXPECT_TRUE(ExecuteScript(child0_0, "location.href = '#foo';"));
+ fragment_observer.Wait();
+
+ // Simulate a name change IPC from the nested iframe, matching the cross-site
+ // iframe's unique name.
+ child0_0->SetFrameName("foo", child1->unique_name());
+
+ // Simulate a back navigation from the now renamed nested iframe, which would
+ // put a PageState on the cross-site iframe's FrameNavigationEntry. Forge a
+ // data URL within the PageState that differs from child1_url.
+ FrameHostMsg_DidCommitProvisionalLoad_Params params;
+ params.nav_entry_id = nav_entry_id;
+ params.frame_unique_name = "";
+ params.did_create_new_entry = false;
+ params.url = GURL("about:blank");
+ params.transition = ui::PAGE_TRANSITION_AUTO_SUBFRAME;
+ params.should_update_history = false;
+ params.gesture = NavigationGestureAuto;
+ params.was_within_same_document = false;
+ params.method = "GET";
+ params.page_state = PageState::CreateFromURL(GURL("data:text/html,foo"));
+ params.origin = url::Origin(GURL("about:blank"));
+
+ FrameHostMsg_DidCommitProvisionalLoad msg(
+ child0_0->current_frame_host()->routing_id(), params);
+ IPC::IpcSecurityTestUtil::PwnMessageReceived(
+ child0_0->current_frame_host()->GetProcess()->GetChannel(), msg);
+
+ // Make sure we haven't changed the FrameNavigationEntry. An attack would
+ // modify the PageState but leave the SiteInstance as it was.
+ EXPECT_EQ(child1->current_frame_host()->GetSiteInstance(),
+ back_entry->GetFrameEntry(child1)->site_instance());
+ EXPECT_EQ(child1_page_state, back_entry->GetFrameEntry(child1)->page_state());
+
+ // Put the frame's unique name back.
+ child0_0->SetFrameName("bar", child0_0_unique_name);
+
+ // Go forward after the fake back navigation.
+ TestNavigationObserver forward_observer(shell()->web_contents());
+ shell()->web_contents()->GetController().GoForward();
+ forward_observer.Wait();
+
+ // Go back to the possibly corrupted entry and ensure we didn't load the data
+ // URL in the previous process. A test failure here would appear as a failure
+ // of the URL check and not the process ID check.
+ TestNavigationObserver back_observer(shell()->web_contents());
+ shell()->web_contents()->GetController().GoBack();
+ back_observer.Wait();
+ EXPECT_EQ(child1_pid, child1->current_frame_host()->GetProcess()->GetID());
+ ASSERT_EQ(child1_url, child1->current_url());
+}
+
} // namespace content
diff --git a/chromium/content/browser/service_manager/service_manager_context.cc b/chromium/content/browser/service_manager/service_manager_context.cc
index 5f5ebb7f963..1cb8bee7c17 100644
--- a/chromium/content/browser/service_manager/service_manager_context.cc
+++ b/chromium/content/browser/service_manager/service_manager_context.cc
@@ -18,6 +18,7 @@
#include "base/process/process_handle.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/task_scheduler/post_task.h"
#include "content/browser/child_process_launcher.h"
#include "content/browser/gpu/gpu_process_host.h"
#include "content/browser/service_manager/common_browser_interfaces.h"
@@ -293,6 +294,14 @@ ServiceManagerContext::ServiceManagerContext() {
pid_receiver->SetPID(base::GetCurrentProcId());
service_manager::EmbeddedServiceInfo device_info;
+
+ // This task runner may be used by some device service implementation bits to
+ // interface with dbus client code, which in turn imposes some subtle thread
+ // affinity on the clients. We therefore require a single-thread runner.
+ scoped_refptr<base::SingleThreadTaskRunner> device_blocking_task_runner =
+ base::CreateSingleThreadTaskRunnerWithTraits(
+ {base::MayBlock(), base::TaskPriority::BACKGROUND});
+
#if defined(OS_ANDROID)
JNIEnv* env = base::android::AttachCurrentThread();
base::android::ScopedJavaGlobalRef<jobject> java_nfc_delegate;
@@ -302,15 +311,13 @@ ServiceManagerContext::ServiceManagerContext() {
// See the comments on wake_lock_context_host.h and ContentNfcDelegate.java
// respectively for comments on those parameters.
device_info.factory =
- base::Bind(&device::CreateDeviceService,
- BrowserThread::GetTaskRunnerForThread(BrowserThread::FILE),
+ base::Bind(&device::CreateDeviceService, device_blocking_task_runner,
BrowserThread::GetTaskRunnerForThread(BrowserThread::IO),
base::Bind(&WakeLockContextHost::GetNativeViewForContext),
std::move(java_nfc_delegate));
#else
device_info.factory =
- base::Bind(&device::CreateDeviceService,
- BrowserThread::GetTaskRunnerForThread(BrowserThread::FILE),
+ base::Bind(&device::CreateDeviceService, device_blocking_task_runner,
BrowserThread::GetTaskRunnerForThread(BrowserThread::IO));
#endif
device_info.task_runner = base::ThreadTaskRunnerHandle::Get();
diff --git a/chromium/content/browser/service_worker/DEPS b/chromium/content/browser/service_worker/DEPS
index 743a2f3baec..b85fe4e879a 100644
--- a/chromium/content/browser/service_worker/DEPS
+++ b/chromium/content/browser/service_worker/DEPS
@@ -1,3 +1,4 @@
include_rules = [
"+third_party/leveldatabase",
+ "+third_party/WebKit/public/web/worker_content_settings_proxy.mojom.h",
]
diff --git a/chromium/content/browser/service_worker/browser_side_service_worker_event_dispatcher.cc b/chromium/content/browser/service_worker/browser_side_service_worker_event_dispatcher.cc
new file mode 100644
index 00000000000..ae9a55b37f3
--- /dev/null
+++ b/chromium/content/browser/service_worker/browser_side_service_worker_event_dispatcher.cc
@@ -0,0 +1,340 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/service_worker/browser_side_service_worker_event_dispatcher.h"
+
+#include "base/callback.h"
+#include "content/browser/service_worker/service_worker_version.h"
+#include "content/common/service_worker/service_worker_utils.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
+
+namespace content {
+
+// BrowserSideServiceWorkerEventDispatcher::ResponseCallback ----------------
+
+// ResponseCallback is owned by the callback that is passed to
+// ServiceWorkerVersion::StartRequest*(), and held in pending_requests_
+// until FinishRequest() is called.
+//
+// This forwards callbacks to the controllee-side's ResponseCallback
+// (|forwarding_callback|, implemented by ServiceWorkerSubresourceLoader),
+// which is the original initiator of the FetchEvent for subresource fetch:
+//
+// SubresourceLoader <-> BrowserSideEventDispatcher <-> EventDispatcher
+// (controllee) [browser-process] (controller)
+//
+// (Eventually SubresourceLoader should directly dispatch events to
+// the controller's EventDispatcher)
+class BrowserSideServiceWorkerEventDispatcher::ResponseCallback
+ : public mojom::ServiceWorkerFetchResponseCallback {
+ public:
+ // |forwarding_callback| is implemented by the controllee's SubresourceLoader.
+ ResponseCallback(
+ mojom::ServiceWorkerFetchResponseCallbackRequest request,
+ mojom::ServiceWorkerFetchResponseCallbackPtr forwarding_callback,
+ ServiceWorkerVersion* version)
+ : binding_(this, std::move(request)),
+ forwarding_callback_(std::move(forwarding_callback)),
+ version_(version) {}
+ ~ResponseCallback() override { DCHECK(fetch_event_id_.has_value()); }
+
+ void set_fetch_event_id(int id) {
+ DCHECK(!fetch_event_id_);
+ fetch_event_id_ = id;
+ }
+
+ // Implements mojom::ServiceWorkerFetchResponseCallback.
+ void OnResponse(const ServiceWorkerResponse& response,
+ base::Time dispatch_event_time) override {
+ // Calling FinishRequest will destroy |this|, so save the callback now.
+ auto callback = std::move(forwarding_callback_);
+ if (!version_->FinishRequest(fetch_event_id_.value(),
+ true /* was_handled */, dispatch_event_time)) {
+ NOTREACHED() << "Should only receive one reply per event";
+ }
+ callback->OnResponse(response, dispatch_event_time);
+ }
+ void OnResponseBlob(const ServiceWorkerResponse& response,
+ storage::mojom::BlobPtr body_as_blob,
+ base::Time dispatch_event_time) override {
+ // Calling FinishRequest will destroy |this|, so save the callback now.
+ auto callback = std::move(forwarding_callback_);
+ if (!version_->FinishRequest(fetch_event_id_.value(),
+ true /* was_handled */, dispatch_event_time)) {
+ NOTREACHED() << "Should only receive one reply per event";
+ }
+ callback->OnResponseBlob(response, std::move(body_as_blob),
+ dispatch_event_time);
+ }
+ void OnResponseStream(
+ const ServiceWorkerResponse& response,
+ blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
+ base::Time dispatch_event_time) override {
+ // Calling FinishRequest will destroy |this|, so save the callback now.
+ auto callback = std::move(forwarding_callback_);
+ if (!version_->FinishRequest(fetch_event_id_.value(),
+ true /* was_handled */, dispatch_event_time)) {
+ NOTREACHED() << "Should only receive one reply per event";
+ }
+ callback->OnResponseStream(response, std::move(body_as_stream),
+ dispatch_event_time);
+ }
+ void OnFallback(base::Time dispatch_event_time) override {
+ // Calling FinishRequest will destroy |this|, so save the callback now.
+ auto callback = std::move(forwarding_callback_);
+ if (!version_->FinishRequest(fetch_event_id_.value(),
+ false /* was_handled */,
+ dispatch_event_time)) {
+ NOTREACHED() << "Should only receive one reply per event";
+ }
+ callback->OnFallback(dispatch_event_time);
+ }
+
+ private:
+ mojo::Binding<mojom::ServiceWorkerFetchResponseCallback> binding_;
+ mojom::ServiceWorkerFetchResponseCallbackPtr forwarding_callback_;
+ ServiceWorkerVersion* version_; // Owns |this| via pending_requests_.
+ // Must be set to a non-nullopt value before the corresponding mojo
+ // handle is passed to the other end (i.e. before any of OnResponse*
+ // is called).
+ base::Optional<int> fetch_event_id_;
+ DISALLOW_COPY_AND_ASSIGN(ResponseCallback);
+};
+
+// BrowserSideServiceWorkerEventDispatcher ----------------------------------
+
+BrowserSideServiceWorkerEventDispatcher::
+ BrowserSideServiceWorkerEventDispatcher(
+ ServiceWorkerVersion* receiver_version)
+ : receiver_version_(receiver_version), weak_factory_(this) {
+ DCHECK(receiver_version_);
+}
+
+BrowserSideServiceWorkerEventDispatcher::
+ ~BrowserSideServiceWorkerEventDispatcher() = default;
+
+mojom::ServiceWorkerEventDispatcherPtrInfo
+BrowserSideServiceWorkerEventDispatcher::CreateEventDispatcherPtrInfo() {
+ mojom::ServiceWorkerEventDispatcherPtrInfo dispatcher_ptr_info;
+ incoming_event_bindings_.AddBinding(this,
+ mojo::MakeRequest(&dispatcher_ptr_info));
+ return dispatcher_ptr_info;
+}
+
+void BrowserSideServiceWorkerEventDispatcher::DispatchInstallEvent(
+ mojom::ServiceWorkerInstallEventMethodsAssociatedPtrInfo client,
+ DispatchInstallEventCallback callback) {
+ NOTREACHED();
+}
+
+void BrowserSideServiceWorkerEventDispatcher::DispatchActivateEvent(
+ DispatchActivateEventCallback callback) {
+ NOTREACHED();
+}
+
+void BrowserSideServiceWorkerEventDispatcher::DispatchBackgroundFetchAbortEvent(
+ const std::string& tag,
+ DispatchBackgroundFetchAbortEventCallback callback) {
+ NOTREACHED();
+}
+
+void BrowserSideServiceWorkerEventDispatcher::DispatchBackgroundFetchClickEvent(
+ const std::string& tag,
+ mojom::BackgroundFetchState state,
+ DispatchBackgroundFetchClickEventCallback callback) {
+ NOTREACHED();
+}
+
+void BrowserSideServiceWorkerEventDispatcher::DispatchBackgroundFetchFailEvent(
+ const std::string& tag,
+ const std::vector<BackgroundFetchSettledFetch>& fetches,
+ DispatchBackgroundFetchFailEventCallback callback) {
+ NOTREACHED();
+}
+
+void BrowserSideServiceWorkerEventDispatcher::DispatchBackgroundFetchedEvent(
+ const std::string& tag,
+ const std::vector<BackgroundFetchSettledFetch>& fetches,
+ DispatchBackgroundFetchedEventCallback callback) {
+ NOTREACHED();
+}
+
+void BrowserSideServiceWorkerEventDispatcher::DispatchExtendableMessageEvent(
+ mojom::ExtendableMessageEventPtr event,
+ DispatchExtendableMessageEventCallback callback) {
+ NOTIMPLEMENTED();
+}
+
+void BrowserSideServiceWorkerEventDispatcher::DispatchFetchEvent(
+ int incoming_fetch_event_id,
+ const ServiceWorkerFetchRequest& request,
+ mojom::FetchEventPreloadHandlePtr preload_handle,
+ mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
+ DispatchFetchEventCallback callback) {
+ DVLOG(1) << "FetchEvent [" << incoming_fetch_event_id << "] "
+ << request.url.spec();
+ DCHECK(fetch_event_callbacks_.find(incoming_fetch_event_id) ==
+ fetch_event_callbacks_.end());
+ fetch_event_callbacks_[incoming_fetch_event_id] = std::move(callback);
+
+ if (receiver_version_->running_status() == EmbeddedWorkerStatus::RUNNING) {
+ DispatchFetchEventInternal(incoming_fetch_event_id, request,
+ std::move(preload_handle),
+ std::move(response_callback));
+ return;
+ }
+
+ // TODO(kinuko): Support ForeignFetch if it turns out that we need it.
+ DCHECK_NE(ServiceWorkerFetchType::FOREIGN_FETCH, request.fetch_type);
+ // Only subresource requests should come here (as the other end of pipe for
+ // this event dispatcher is passed to the renderer's SubresourceLoader).
+ DCHECK_EQ(REQUEST_CONTEXT_FRAME_TYPE_NONE, request.frame_type);
+
+ receiver_version_->RunAfterStartWorker(
+ ServiceWorkerMetrics::EventType::FETCH_SUB_RESOURCE,
+ base::Bind(
+ &BrowserSideServiceWorkerEventDispatcher::DispatchFetchEventInternal,
+ weak_factory_.GetWeakPtr(), incoming_fetch_event_id, request,
+ base::Passed(&preload_handle), base::Passed(&response_callback)),
+ base::Bind(
+ &BrowserSideServiceWorkerEventDispatcher::DidFailToStartWorker,
+ weak_factory_.GetWeakPtr(),
+ base::Bind(
+ &BrowserSideServiceWorkerEventDispatcher::DidFailToDispatchFetch,
+ weak_factory_.GetWeakPtr(), incoming_fetch_event_id, nullptr)));
+}
+
+void BrowserSideServiceWorkerEventDispatcher::DispatchFetchEventInternal(
+ int incoming_fetch_event_id,
+ const ServiceWorkerFetchRequest& request,
+ mojom::FetchEventPreloadHandlePtr preload_handle,
+ mojom::ServiceWorkerFetchResponseCallbackPtr incoming_response_callback) {
+ mojom::ServiceWorkerFetchResponseCallbackPtr mojo_response_callback_ptr;
+ auto response_callback = base::MakeUnique<ResponseCallback>(
+ mojo::MakeRequest(&mojo_response_callback_ptr),
+ std::move(incoming_response_callback), receiver_version_);
+ ResponseCallback* response_callback_rawptr = response_callback.get();
+
+ // TODO(kinuko): No timeout support for now; support timeout.
+ int fetch_event_id = receiver_version_->StartRequest(
+ ServiceWorkerMetrics::EventType::FETCH_SUB_RESOURCE,
+ base::Bind(
+ &BrowserSideServiceWorkerEventDispatcher::DidFailToDispatchFetch,
+ weak_factory_.GetWeakPtr(), incoming_fetch_event_id,
+ base::Passed(&response_callback)));
+ int event_finish_id = receiver_version_->StartRequest(
+ ServiceWorkerMetrics::EventType::FETCH_WAITUNTIL,
+ // NoOp as the same error callback should be handled by the other
+ // StartRequest above.
+ base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
+
+ response_callback_rawptr->set_fetch_event_id(fetch_event_id);
+
+ receiver_version_->event_dispatcher()->DispatchFetchEvent(
+ fetch_event_id, request, std::move(preload_handle),
+ std::move(mojo_response_callback_ptr),
+ base::BindOnce(
+ &BrowserSideServiceWorkerEventDispatcher::DidDispatchFetchEvent,
+ weak_factory_.GetWeakPtr(), incoming_fetch_event_id,
+ event_finish_id));
+}
+
+void BrowserSideServiceWorkerEventDispatcher::DispatchNotificationClickEvent(
+ const std::string& notification_id,
+ const PlatformNotificationData& notification_data,
+ int action_index,
+ const base::Optional<base::string16>& reply,
+ DispatchNotificationClickEventCallback callback) {
+ NOTREACHED();
+}
+
+void BrowserSideServiceWorkerEventDispatcher::DispatchNotificationCloseEvent(
+ const std::string& notification_id,
+ const PlatformNotificationData& notification_data,
+ DispatchNotificationCloseEventCallback callback) {
+ NOTREACHED();
+}
+
+void BrowserSideServiceWorkerEventDispatcher::DispatchPushEvent(
+ const PushEventPayload& payload,
+ DispatchPushEventCallback callback) {
+ NOTREACHED();
+}
+
+void BrowserSideServiceWorkerEventDispatcher::DispatchSyncEvent(
+ const std::string& tag,
+ blink::mojom::BackgroundSyncEventLastChance last_chance,
+ DispatchSyncEventCallback callback) {
+ NOTREACHED();
+}
+
+void BrowserSideServiceWorkerEventDispatcher::DispatchAbortPaymentEvent(
+ int payment_request_id,
+ payments::mojom::PaymentHandlerResponseCallbackPtr response_callback,
+ DispatchAbortPaymentEventCallback callback) {
+ NOTREACHED();
+}
+
+void BrowserSideServiceWorkerEventDispatcher::DispatchCanMakePaymentEvent(
+ int payment_request_id,
+ payments::mojom::CanMakePaymentEventDataPtr event_data,
+ payments::mojom::PaymentHandlerResponseCallbackPtr response_callback,
+ DispatchCanMakePaymentEventCallback callback) {
+ NOTREACHED();
+}
+
+void BrowserSideServiceWorkerEventDispatcher::DispatchPaymentRequestEvent(
+ int payment_request_id,
+ payments::mojom::PaymentRequestEventDataPtr event_data,
+ payments::mojom::PaymentHandlerResponseCallbackPtr response_callback,
+ DispatchPaymentRequestEventCallback callback) {
+ NOTREACHED();
+}
+
+void BrowserSideServiceWorkerEventDispatcher::Ping(PingCallback callback) {
+ NOTREACHED();
+}
+
+void BrowserSideServiceWorkerEventDispatcher::DidFailToStartWorker(
+ const StatusCallback& callback,
+ ServiceWorkerStatusCode status) {
+ // TODO(kinuko): Should log the failures.
+ DCHECK_NE(SERVICE_WORKER_OK, status);
+ std::move(callback).Run(status);
+}
+
+void BrowserSideServiceWorkerEventDispatcher::DidFailToDispatchFetch(
+ int incoming_fetch_event_id,
+ std::unique_ptr<ResponseCallback> response_callback,
+ ServiceWorkerStatusCode status) {
+ // TODO(kinuko): Should log the failures.
+ DCHECK_NE(SERVICE_WORKER_OK, status);
+ CompleteDispatchFetchEvent(incoming_fetch_event_id, status, base::Time());
+}
+
+void BrowserSideServiceWorkerEventDispatcher::DidDispatchFetchEvent(
+ int incoming_fetch_event_id,
+ int event_finish_id,
+ ServiceWorkerStatusCode status,
+ base::Time dispatch_event_time) {
+ receiver_version_->FinishRequest(event_finish_id,
+ status != SERVICE_WORKER_ERROR_ABORT,
+ dispatch_event_time);
+ CompleteDispatchFetchEvent(incoming_fetch_event_id, status,
+ dispatch_event_time);
+}
+
+void BrowserSideServiceWorkerEventDispatcher::CompleteDispatchFetchEvent(
+ int incoming_fetch_event_id,
+ ServiceWorkerStatusCode status,
+ base::Time dispatch_event_time) {
+ DVLOG(1) << "CompleteFetch [" << incoming_fetch_event_id
+ << "] status:" << status;
+ auto found = fetch_event_callbacks_.find(incoming_fetch_event_id);
+ DCHECK(found != fetch_event_callbacks_.end());
+ std::move(found->second).Run(status, dispatch_event_time);
+ fetch_event_callbacks_.erase(found);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/service_worker/browser_side_service_worker_event_dispatcher.h b/chromium/content/browser/service_worker/browser_side_service_worker_event_dispatcher.h
new file mode 100644
index 00000000000..92e2e9cd37b
--- /dev/null
+++ b/chromium/content/browser/service_worker/browser_side_service_worker_event_dispatcher.h
@@ -0,0 +1,143 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_SERVICE_WORKER_BROWSER_SIDE_SERVICE_WORKER_EVENT_DISPATCHER_H_
+#define CONTENT_BROWSER_SERVICE_WORKER_BROWSER_SIDE_SERVICE_WORKER_EVENT_DISPATCHER_H_
+
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "content/browser/service_worker/service_worker_metrics.h"
+#include "content/common/service_worker/service_worker_event_dispatcher.mojom.h"
+#include "mojo/public/cpp/bindings/binding_set.h"
+
+namespace content {
+
+class ServiceWorkerVersion;
+
+// Temporary class until we start to have ServiceWorkerVersion-like object
+// in the renderer.
+//
+// BrowserSideServiceWorkerEventDispatcher forward events to a
+// ServiceWorkerVersion. It's the browser-side implementation of
+// mojom::ServiceWorkerEventDispatcher, used by the renderer to dispatch
+// events initiated by a controllee to its controlling service worker.
+// The short-term plan is for it to be used to dispatch fetch events directly
+// to the service worker instead of relying on ServiceWorkerURLRequestJob.
+// The (slightly) longer term plan is to have this in the renderer and
+// dispatch events directly from the page to the ServiceWorker without going
+// through the browser process.
+//
+// TODO(kinuko): this should probably eventually replace ServiceWorkerHandle
+// and get state changes.
+class BrowserSideServiceWorkerEventDispatcher
+ : public mojom::ServiceWorkerEventDispatcher {
+ public:
+ explicit BrowserSideServiceWorkerEventDispatcher(
+ ServiceWorkerVersion* receiver_version);
+ ~BrowserSideServiceWorkerEventDispatcher() override;
+
+ mojom::ServiceWorkerEventDispatcherPtrInfo CreateEventDispatcherPtrInfo();
+
+ // mojom::ServiceWorkerEventDispatcher:
+ void DispatchInstallEvent(
+ mojom::ServiceWorkerInstallEventMethodsAssociatedPtrInfo client,
+ DispatchInstallEventCallback callback) override;
+ void DispatchActivateEvent(DispatchActivateEventCallback callback) override;
+ void DispatchBackgroundFetchAbortEvent(
+ const std::string& tag,
+ DispatchBackgroundFetchAbortEventCallback callback) override;
+ void DispatchBackgroundFetchClickEvent(
+ const std::string& tag,
+ mojom::BackgroundFetchState state,
+ DispatchBackgroundFetchClickEventCallback callback) override;
+ void DispatchBackgroundFetchFailEvent(
+ const std::string& tag,
+ const std::vector<BackgroundFetchSettledFetch>& fetches,
+ DispatchBackgroundFetchFailEventCallback callback) override;
+ void DispatchBackgroundFetchedEvent(
+ const std::string& tag,
+ const std::vector<BackgroundFetchSettledFetch>& fetches,
+ DispatchBackgroundFetchedEventCallback callback) override;
+ void DispatchExtendableMessageEvent(
+ mojom::ExtendableMessageEventPtr event,
+ DispatchExtendableMessageEventCallback callback) override;
+ void DispatchFetchEvent(
+ int fetch_event_id,
+ const ServiceWorkerFetchRequest& request,
+ mojom::FetchEventPreloadHandlePtr preload_handle,
+ mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
+ DispatchFetchEventCallback callback) override;
+ void DispatchNotificationClickEvent(
+ const std::string& notification_id,
+ const PlatformNotificationData& notification_data,
+ int action_index,
+ const base::Optional<base::string16>& reply,
+ DispatchNotificationClickEventCallback callback) override;
+ void DispatchNotificationCloseEvent(
+ const std::string& notification_id,
+ const PlatformNotificationData& notification_data,
+ DispatchNotificationCloseEventCallback callback) override;
+ void DispatchPushEvent(const PushEventPayload& payload,
+ DispatchPushEventCallback callback) override;
+ void DispatchSyncEvent(
+ const std::string& tag,
+ blink::mojom::BackgroundSyncEventLastChance last_chance,
+ DispatchSyncEventCallback callback) override;
+ void DispatchAbortPaymentEvent(
+ int payment_request_id,
+ payments::mojom::PaymentHandlerResponseCallbackPtr response_callback,
+ DispatchAbortPaymentEventCallback callback) override;
+ void DispatchCanMakePaymentEvent(
+ int payment_request_id,
+ payments::mojom::CanMakePaymentEventDataPtr event_data,
+ payments::mojom::PaymentHandlerResponseCallbackPtr response_callback,
+ DispatchCanMakePaymentEventCallback callback) override;
+ void DispatchPaymentRequestEvent(
+ int payment_request_id,
+ payments::mojom::PaymentRequestEventDataPtr event_data,
+ payments::mojom::PaymentHandlerResponseCallbackPtr response_callback,
+ DispatchPaymentRequestEventCallback callback) override;
+ void Ping(PingCallback callback) override;
+
+ private:
+ class ResponseCallback;
+ using StatusCallback = base::Callback<void(ServiceWorkerStatusCode)>;
+
+ void DispatchFetchEventInternal(
+ int incoming_fetch_event_id,
+ const ServiceWorkerFetchRequest& request,
+ mojom::FetchEventPreloadHandlePtr preload_handle,
+ mojom::ServiceWorkerFetchResponseCallbackPtr response_callback);
+ void DidFailToStartWorker(const StatusCallback& callback,
+ ServiceWorkerStatusCode status);
+ void DidFailToDispatchFetch(int incoming_fetch_event_id,
+ std::unique_ptr<ResponseCallback> callback,
+ ServiceWorkerStatusCode status);
+ void DidDispatchFetchEvent(int incoming_fetch_event_id,
+ int event_finish_id,
+ ServiceWorkerStatusCode status,
+ base::Time dispatch_event_time);
+ void CompleteDispatchFetchEvent(int incoming_fetch_event_id,
+ ServiceWorkerStatusCode status,
+ base::Time dispatch_event_time);
+
+ // Connected to ServiceWorkerNetworkProvider's of the controllees (and of the
+ // browser, when this object starts to live in the renderer process).
+ mojo::BindingSet<mojom::ServiceWorkerEventDispatcher>
+ incoming_event_bindings_;
+
+ // Not owned; this proxy should go away before the version goes away.
+ ServiceWorkerVersion* receiver_version_;
+
+ std::map<int /* request_id */, DispatchFetchEventCallback>
+ fetch_event_callbacks_;
+
+ base::WeakPtrFactory<BrowserSideServiceWorkerEventDispatcher> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(BrowserSideServiceWorkerEventDispatcher);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_SERVICE_WORKER_BROWSER_SIDE_SERVICE_WORKER_EVENT_DISPATCHER_H_
diff --git a/chromium/content/browser/service_worker/embedded_worker_instance.cc b/chromium/content/browser/service_worker/embedded_worker_instance.cc
index d2b92c5bfe3..c7dfe861128 100644
--- a/chromium/content/browser/service_worker/embedded_worker_instance.cc
+++ b/chromium/content/browser/service_worker/embedded_worker_instance.cc
@@ -15,8 +15,10 @@
#include "content/browser/devtools/service_worker_devtools_manager.h"
#include "content/browser/service_worker/embedded_worker_registry.h"
#include "content/browser/service_worker/embedded_worker_status.h"
+#include "content/browser/service_worker/service_worker_content_settings_proxy_impl.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/common/content_switches_internal.h"
+#include "content/common/renderer.mojom.h"
#include "content/common/service_worker/embedded_worker_messages.h"
#include "content/common/service_worker/embedded_worker_settings.h"
#include "content/common/service_worker/embedded_worker_start_params.h"
@@ -80,13 +82,14 @@ using SetupProcessCallback = base::OnceCallback<void(
// registering with DevTools. Called on the UI thread. Calls |callback| on the
// IO thread. |context| and |weak_context| are only for passing to DevTools and
// must not be dereferenced here on the UI thread.
-void SetupOnUIThread(base::WeakPtr<ServiceWorkerProcessManager> process_manager,
- bool can_use_existing_process,
- std::unique_ptr<EmbeddedWorkerStartParams> params,
- mojom::EmbeddedWorkerInstanceClientRequest request,
- ServiceWorkerContextCore* context,
- base::WeakPtr<ServiceWorkerContextCore> weak_context,
- SetupProcessCallback callback) {
+void SetupOnUIThread(
+ base::WeakPtr<ServiceWorkerProcessManager> process_manager,
+ bool can_use_existing_process,
+ std::unique_ptr<EmbeddedWorkerStartParams> params,
+ mojom::EmbeddedWorkerInstanceClientAssociatedRequest request,
+ ServiceWorkerContextCore* context,
+ base::WeakPtr<ServiceWorkerContextCore> weak_context,
+ SetupProcessCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
auto process_info =
base::MakeUnique<ServiceWorkerProcessManager::AllocatedProcessInfo>();
@@ -120,8 +123,10 @@ void SetupOnUIThread(base::WeakPtr<ServiceWorkerProcessManager> process_manager,
// Bind |request|, which is attached to |EmbeddedWorkerInstance::client_|, to
// the process. If the process dies, |client_|'s connection error callback
// will be called on the IO thread.
- if (request.is_pending())
- BindInterface(rph, std::move(request));
+ if (request.is_pending()) {
+ rph->GetRendererInterface()->SetUpEmbeddedWorkerChannelForServiceWorker(
+ std::move(request));
+ }
// Register to DevTools and update params accordingly.
const int routing_id = rph->GetNextRoutingID();
@@ -153,15 +158,6 @@ void SetupOnUIThread(base::WeakPtr<ServiceWorkerProcessManager> process_manager,
std::move(process_info), std::move(devtools_proxy)));
}
-void CallDetach(EmbeddedWorkerInstance* instance) {
- // This could be called on the UI thread if |client_| still be valid when the
- // message loop on the UI thread gets destructed.
- // TODO(shimazu): Remove this after https://crbug.com/604762 is fixed
- if (!BrowserThread::CurrentlyOn(BrowserThread::IO))
- return;
- instance->Detach();
-}
-
bool HasSentStartWorker(EmbeddedWorkerInstance::StartingPhase phase) {
switch (phase) {
case EmbeddedWorkerInstance::NOT_STARTING:
@@ -194,32 +190,30 @@ class EmbeddedWorkerInstance::DevToolsProxy {
~DevToolsProxy() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- BrowserThread::PostTask(
- BrowserThread::UI,
- FROM_HERE,
- base::Bind(NotifyWorkerDestroyedOnUI,
- process_id_, agent_route_id_));
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::BindOnce(NotifyWorkerDestroyedOnUI,
+ process_id_, agent_route_id_));
}
void NotifyWorkerReadyForInspection() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(NotifyWorkerReadyForInspectionOnUI,
- process_id_, agent_route_id_));
+ base::BindOnce(NotifyWorkerReadyForInspectionOnUI,
+ process_id_, agent_route_id_));
}
void NotifyWorkerVersionInstalled() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(NotifyWorkerVersionInstalledOnUI,
- process_id_, agent_route_id_));
+ base::BindOnce(NotifyWorkerVersionInstalledOnUI,
+ process_id_, agent_route_id_));
}
void NotifyWorkerVersionDoomed() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(NotifyWorkerVersionDoomedOnUI,
- process_id_, agent_route_id_));
+ base::BindOnce(NotifyWorkerVersionDoomedOnUI,
+ process_id_, agent_route_id_));
}
bool ShouldNotifyWorkerStopIgnored() const {
@@ -286,7 +280,7 @@ class EmbeddedWorkerInstance::StartTask {
StartTask(EmbeddedWorkerInstance* instance,
const GURL& script_url,
- mojom::EmbeddedWorkerInstanceClientRequest request)
+ mojom::EmbeddedWorkerInstanceClientAssociatedRequest request)
: instance_(instance),
request_(std::move(request)),
state_(ProcessAllocationState::NOT_ALLOCATED),
@@ -295,14 +289,14 @@ class EmbeddedWorkerInstance::StartTask {
weak_factory_(this) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
TRACE_EVENT_NESTABLE_ASYNC_BEGIN1("ServiceWorker",
- "EmbeddedWorkerInstance::Start",
- instance_, "Script", script_url.spec());
+ "EmbeddedWorkerInstance::Start", this,
+ "Script", script_url.spec());
}
~StartTask() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
TRACE_EVENT_NESTABLE_ASYNC_END0("ServiceWorker",
- "EmbeddedWorkerInstance::Start", instance_);
+ "EmbeddedWorkerInstance::Start", this);
if (!instance_->context_)
return;
@@ -358,7 +352,7 @@ class EmbeddedWorkerInstance::StartTask {
params->service_worker_version_id) < kMaxSameProcessFailureCount;
DCHECK_EQ(params->embedded_worker_id, instance_->embedded_worker_id_);
TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("ServiceWorker", "ALLOCATING_PROCESS",
- instance_);
+ this);
// Hop to the UI thread for process allocation and setup. We will continue
// on the IO thread in StartTask::OnSetupCompleted().
BrowserThread::PostTask(
@@ -375,6 +369,9 @@ class EmbeddedWorkerInstance::StartTask {
static void RunStartCallback(StartTask* task,
ServiceWorkerStatusCode status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ TRACE_EVENT_NESTABLE_ASYNC_END1("ServiceWorker", "INITIALIZING_ON_RENDERER",
+ task, "Status",
+ ServiceWorkerStatusToString(status));
StatusCallback callback = task->start_callback_;
task->start_callback_.Reset();
callback.Run(status);
@@ -393,7 +390,7 @@ class EmbeddedWorkerInstance::StartTask {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (status != SERVICE_WORKER_OK) {
TRACE_EVENT_NESTABLE_ASYNC_END1("ServiceWorker", "ALLOCATING_PROCESS",
- instance_, "Error",
+ this, "Error",
ServiceWorkerStatusToString(status));
StatusCallback callback = start_callback_;
start_callback_.Reset();
@@ -405,7 +402,7 @@ class EmbeddedWorkerInstance::StartTask {
ServiceWorkerMetrics::StartSituation start_situation =
process_info->start_situation;
TRACE_EVENT_NESTABLE_ASYNC_END1(
- "ServiceWorker", "ALLOCATING_PROCESS", instance_, "StartSituation",
+ "ServiceWorker", "ALLOCATING_PROCESS", this, "StartSituation",
ServiceWorkerMetrics::StartSituationToString(start_situation));
if (is_installed_) {
ServiceWorkerMetrics::RecordProcessCreated(
@@ -434,7 +431,8 @@ class EmbeddedWorkerInstance::StartTask {
instance_->OnStartFailed(callback, status);
// |this| may be destroyed.
}
-
+ TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("ServiceWorker",
+ "INITIALIZING_ON_RENDERER", this);
// |this|'s work is done here, but |instance_| still uses its state until
// startup is complete.
}
@@ -442,9 +440,8 @@ class EmbeddedWorkerInstance::StartTask {
// |instance_| must outlive |this|.
EmbeddedWorkerInstance* instance_;
- // Ownership is transferred by base::Passed() to a task after process
- // allocation.
- mojom::EmbeddedWorkerInstanceClientRequest request_;
+ // Ownership is transferred by a PostTask() call after process allocation.
+ mojom::EmbeddedWorkerInstanceClientAssociatedRequest request_;
StatusCallback start_callback_;
ProcessAllocationState state_;
@@ -477,6 +474,7 @@ EmbeddedWorkerInstance::~EmbeddedWorkerInstance() {
void EmbeddedWorkerInstance::Start(
std::unique_ptr<EmbeddedWorkerStartParams> params,
+ ProviderInfoGetter provider_info_getter,
mojom::ServiceWorkerEventDispatcherRequest dispatcher_request,
mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info,
const StatusCallback& callback) {
@@ -486,7 +484,7 @@ void EmbeddedWorkerInstance::Start(
// |this| may be destroyed by the callback.
return;
}
- DCHECK(status_ == EmbeddedWorkerStatus::STOPPED);
+ DCHECK_EQ(EmbeddedWorkerStatus::STOPPED, status_);
DCHECK(!params->pause_after_download || !params->is_installed);
DCHECK_NE(kInvalidServiceWorkerVersionId, params->service_worker_version_id);
@@ -495,6 +493,8 @@ void EmbeddedWorkerInstance::Start(
status_ = EmbeddedWorkerStatus::STARTING;
starting_phase_ = ALLOCATING_PROCESS;
network_accessed_for_script_ = false;
+ provider_info_getter_ = std::move(provider_info_getter);
+
for (auto& observer : listener_list_)
observer.OnStarting();
@@ -503,11 +503,10 @@ void EmbeddedWorkerInstance::Start(
params->wait_for_debugger = false;
params->settings.v8_cache_options = GetV8CacheOptions();
- mojom::EmbeddedWorkerInstanceClientRequest request =
+ mojom::EmbeddedWorkerInstanceClientAssociatedRequest request =
mojo::MakeRequest(&client_);
client_.set_connection_error_handler(
- base::Bind(&CallDetach, base::Unretained(this)));
-
+ base::BindOnce(&EmbeddedWorkerInstance::Detach, base::Unretained(this)));
pending_dispatcher_request_ = std::move(dispatcher_request);
pending_installed_scripts_info_ = std::move(installed_scripts_info);
@@ -516,7 +515,7 @@ void EmbeddedWorkerInstance::Start(
inflight_start_task_->Start(std::move(params), callback);
}
-bool EmbeddedWorkerInstance::Stop() {
+void EmbeddedWorkerInstance::Stop() {
DCHECK(status_ == EmbeddedWorkerStatus::STARTING ||
status_ == EmbeddedWorkerStatus::RUNNING)
<< static_cast<int>(status_);
@@ -524,21 +523,20 @@ bool EmbeddedWorkerInstance::Stop() {
// Abort an inflight start task.
inflight_start_task_.reset();
+ // Don't send the StopWorker message if the StartWorker message hasn't
+ // been sent.
if (status_ == EmbeddedWorkerStatus::STARTING &&
!HasSentStartWorker(starting_phase())) {
- // Don't send the StopWorker message when the StartWorker message hasn't
- // been sent.
- // TODO(shimazu): Invoke OnStopping/OnStopped after the legacy IPC path is
- // removed.
- OnDetached();
- return false;
+ ReleaseProcess();
+ for (auto& observer : listener_list_)
+ observer.OnStopped(EmbeddedWorkerStatus::STARTING /* old_status */);
+ return;
}
- client_->StopWorker();
+ client_->StopWorker();
status_ = EmbeddedWorkerStatus::STOPPING;
for (auto& observer : listener_list_)
observer.OnStopping();
- return true;
}
void EmbeddedWorkerInstance::StopIfIdle() {
@@ -645,20 +643,21 @@ ServiceWorkerStatusCode EmbeddedWorkerInstance::SendStartWorker(
mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo host_ptr_info;
instance_host_binding_.Bind(mojo::MakeRequest(&host_ptr_info));
+ blink::mojom::WorkerContentSettingsProxyPtr content_settings_proxy_ptr_info;
+ content_settings_ = base::MakeUnique<ServiceWorkerContentSettingsProxyImpl>(
+ params->script_url, context_,
+ mojo::MakeRequest(&content_settings_proxy_ptr_info));
+
const bool is_script_streaming = !pending_installed_scripts_info_.is_null();
inflight_start_task_->set_start_worker_sent_time(base::TimeTicks::Now());
+ mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info =
+ std::move(provider_info_getter_).Run(process_id());
client_->StartWorker(*params, std::move(pending_dispatcher_request_),
std::move(pending_installed_scripts_info_),
- std::move(host_ptr_info));
+ std::move(host_ptr_info), std::move(provider_info),
+ std::move(content_settings_proxy_ptr_info));
registry_->BindWorkerToProcess(process_id(), embedded_worker_id());
OnStartWorkerMessageSent(is_script_streaming);
- if (starting_phase() == SCRIPT_STREAMING) {
- TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("ServiceWorker",
- "SENT_START_WITH_SCRIPT_STREAMING", this);
- } else {
- TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("ServiceWorker", "SENT_START_WORKER",
- this);
- }
return SERVICE_WORKER_OK;
}
@@ -683,14 +682,10 @@ void EmbeddedWorkerInstance::OnReadyForInspection() {
}
void EmbeddedWorkerInstance::OnScriptReadStarted() {
- TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("ServiceWorker", "SCRIPT_READING_CACHE",
- this);
starting_phase_ = SCRIPT_READ_STARTED;
}
void EmbeddedWorkerInstance::OnScriptReadFinished() {
- TRACE_EVENT_NESTABLE_ASYNC_END0("ServiceWorker", "SCRIPT_READING_CACHE",
- this);
starting_phase_ = SCRIPT_READ_FINISHED;
}
@@ -709,22 +704,6 @@ void EmbeddedWorkerInstance::OnScriptLoaded() {
source = LoadSource::HTTP_CACHE;
}
- switch (starting_phase_) {
- case SCRIPT_DOWNLOADING:
- TRACE_EVENT_NESTABLE_ASYNC_END0("ServiceWorker", "SCRIPT_DOWNLOADING",
- this);
- break;
- case SCRIPT_STREAMING:
- TRACE_EVENT_NESTABLE_ASYNC_END0("ServiceWorker",
- "SENT_START_WITH_SCRIPT_STREAMING", this);
- break;
- default:
- TRACE_EVENT_NESTABLE_ASYNC_END1(
- "ServiceWorker", "SCRIPT_LOADING", this, "Source",
- ServiceWorkerMetrics::LoadSourceToString(source));
- break;
- }
-
// Don't record the time when script streaming is enabled because
// OnScriptLoaded is called at the different timing.
if (starting_phase_ != SCRIPT_STREAMING && !step_time_.is_null()) {
@@ -733,8 +712,6 @@ void EmbeddedWorkerInstance::OnScriptLoaded() {
}
// Renderer side has started to launch the worker thread.
- TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("ServiceWorker", "LAUNCHING_WORKER_THREAD",
- this);
starting_phase_ = SCRIPT_LOADED;
for (auto& observer : listener_list_)
observer.OnScriptLoaded();
@@ -742,8 +719,6 @@ void EmbeddedWorkerInstance::OnScriptLoaded() {
}
void EmbeddedWorkerInstance::OnURLJobCreatedForMainScript() {
- TRACE_EVENT_NESTABLE_ASYNC_END0("ServiceWorker", "SENT_START_WORKER", this);
- TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("ServiceWorker", "SCRIPT_LOADING", this);
if (!inflight_start_task_)
return;
@@ -764,24 +739,10 @@ void EmbeddedWorkerInstance::OnWorkerVersionDoomed() {
devtools_proxy_->NotifyWorkerVersionDoomed();
}
-void EmbeddedWorkerInstance::OnThreadStarted(int thread_id, int provider_id) {
+void EmbeddedWorkerInstance::OnThreadStarted(int thread_id) {
if (!context_ || !inflight_start_task_)
return;
- ServiceWorkerProviderHost* provider_host =
- context_->GetProviderHost(process_id(), provider_id);
- if (!provider_host) {
- bad_message::ReceivedBadMessage(
- process_id(), bad_message::SWDH_WORKER_SCRIPT_LOAD_NO_HOST);
- return;
- }
-
- provider_host->SetReadyToSendMessagesToWorker(thread_id);
-
- TRACE_EVENT_NESTABLE_ASYNC_END0("ServiceWorker", "LAUNCHING_WORKER_THREAD",
- this);
- // Renderer side has started to evaluate the loaded worker script.
- TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("ServiceWorker", "EVALUATING_SCRIPT", this);
starting_phase_ = THREAD_STARTED;
if (!step_time_.is_null()) {
base::TimeDelta duration = UpdateStepTime();
@@ -799,13 +760,6 @@ void EmbeddedWorkerInstance::OnScriptLoadFailed() {
return;
// starting_phase_ may be SCRIPT_READ_FINISHED in case of reading from cache.
- if (starting_phase_ == SCRIPT_DOWNLOADING) {
- TRACE_EVENT_NESTABLE_ASYNC_END0("ServiceWorker", "SCRIPT_DOWNLOADING",
- this);
- }
- TRACE_EVENT_NESTABLE_ASYNC_END1("ServiceWorker", "SCRIPT_LOADING", this,
- "Error", "Script load failed.");
-
for (auto& observer : listener_list_)
observer.OnScriptLoadFailed();
}
@@ -817,8 +771,6 @@ void EmbeddedWorkerInstance::OnScriptEvaluated(bool success) {
DCHECK_EQ(EmbeddedWorkerStatus::STARTING, status_);
// Renderer side has completed evaluating the loaded worker script.
- TRACE_EVENT_NESTABLE_ASYNC_END1("ServiceWorker", "EVALUATING_SCRIPT", this,
- "Success", success);
starting_phase_ = SCRIPT_EVALUATED;
if (!step_time_.is_null()) {
base::TimeDelta duration = UpdateStepTime();
@@ -827,12 +779,6 @@ void EmbeddedWorkerInstance::OnScriptEvaluated(bool success) {
start_situation_);
}
- if (success) {
- // Renderer side has started the final preparations to complete the start
- // process.
- TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("ServiceWorker",
- "WAITING_FOR_START_COMPLETE", this);
- }
base::WeakPtr<EmbeddedWorkerInstance> weak_this = weak_factory_.GetWeakPtr();
StartTask::RunStartCallback(
inflight_start_task_.get(),
@@ -854,10 +800,7 @@ void EmbeddedWorkerInstance::OnStarted(
std::move(start_timing), inflight_start_task_->start_worker_sent_time(),
start_situation_);
}
-
- TRACE_EVENT_NESTABLE_ASYNC_END0("ServiceWorker", "WAITING_FOR_START_COMPLETE",
- this);
- DCHECK(status_ == EmbeddedWorkerStatus::STARTING);
+ DCHECK_EQ(EmbeddedWorkerStatus::STARTING, status_);
status_ = EmbeddedWorkerStatus::RUNNING;
inflight_start_task_.reset();
for (auto& observer : listener_list_)
@@ -873,18 +816,19 @@ void EmbeddedWorkerInstance::OnStopped() {
observer.OnStopped(old_status);
}
-void EmbeddedWorkerInstance::OnDetached() {
+void EmbeddedWorkerInstance::Detach() {
+ // Temporary CHECK for debugging https://crbug.com/750267.
+ CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (status() == EmbeddedWorkerStatus::STOPPED)
+ return;
+ registry_->DetachWorker(process_id(), embedded_worker_id());
+
EmbeddedWorkerStatus old_status = status_;
ReleaseProcess();
for (auto& observer : listener_list_)
observer.OnDetached(old_status);
}
-void EmbeddedWorkerInstance::Detach() {
- registry_->DetachWorker(process_id(), embedded_worker_id());
- OnDetached();
-}
-
base::WeakPtr<EmbeddedWorkerInstance> EmbeddedWorkerInstance::AsWeakPtr() {
return weak_factory_.GetWeakPtr();
}
@@ -947,8 +891,6 @@ void EmbeddedWorkerInstance::SetDevToolsAttached(bool attached) {
}
void EmbeddedWorkerInstance::OnNetworkAccessedForScriptLoad() {
- TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("ServiceWorker", "SCRIPT_DOWNLOADING",
- this);
starting_phase_ = SCRIPT_DOWNLOADING;
network_accessed_for_script_ = true;
}
@@ -957,7 +899,6 @@ void EmbeddedWorkerInstance::ReleaseProcess() {
// Abort an inflight start task.
inflight_start_task_.reset();
- client_.reset();
instance_host_binding_.Close();
devtools_proxy_.reset();
process_handle_.reset();
diff --git a/chromium/content/browser/service_worker/embedded_worker_instance.h b/chromium/content/browser/service_worker/embedded_worker_instance.h
index 5f9fa245f39..4c0633236c1 100644
--- a/chromium/content/browser/service_worker/embedded_worker_instance.h
+++ b/chromium/content/browser/service_worker/embedded_worker_instance.h
@@ -42,6 +42,7 @@ namespace content {
class EmbeddedWorkerRegistry;
struct EmbeddedWorkerStartParams;
+class ServiceWorkerContentSettingsProxyImpl;
class ServiceWorkerContextCore;
// This gives an interface to control one EmbeddedWorker instance, which
@@ -50,7 +51,7 @@ class ServiceWorkerContextCore;
//
// Owned by ServiceWorkerVersion. Lives on the IO thread.
class CONTENT_EXPORT EmbeddedWorkerInstance
- : NON_EXPORTED_BASE(public mojom::EmbeddedWorkerInstanceHost) {
+ : public mojom::EmbeddedWorkerInstanceHost {
public:
class DevToolsProxy;
typedef base::Callback<void(ServiceWorkerStatusCode)> StatusCallback;
@@ -75,6 +76,10 @@ class CONTENT_EXPORT EmbeddedWorkerInstance
STARTING_PHASE_MAX_VALUE,
};
+ using ProviderInfoGetter =
+ base::OnceCallback<mojom::ServiceWorkerProviderInfoForStartWorkerPtr(
+ int /* process_id */)>;
+
class Listener {
public:
virtual ~Listener() {}
@@ -86,11 +91,22 @@ class CONTENT_EXPORT EmbeddedWorkerInstance
virtual void OnThreadStarted() {}
virtual void OnStarted() {}
+ // Called when status changed to STOPPING. The renderer has been sent a Stop
+ // IPC message and OnStopped() will be called upon successful completion.
virtual void OnStopping() {}
- // Received ACK from renderer that the worker context terminated.
+
+ // Called when status changed to STOPPED. Usually, this is called upon
+ // receiving an ACK from renderer that the worker context terminated.
+ // OnStopped() is also called if Stop() aborted an ongoing start attempt
+ // even before the Start IPC message was sent to the renderer. In this
+ // case, OnStopping() is not called; the worker is "stopped" immediately
+ // (the Start IPC is never sent).
virtual void OnStopped(EmbeddedWorkerStatus old_status) {}
- // The browser-side IPC endpoint for communication with the worker died.
+
+ // Called when the browser-side IPC endpoint for communication with the
+ // worker died. When this is called, status is STOPPED.
virtual void OnDetached(EmbeddedWorkerStatus old_status) {}
+
virtual void OnScriptLoaded() {}
virtual void OnScriptLoadFailed() {}
virtual void OnReportException(const base::string16& error_message,
@@ -115,15 +131,23 @@ class CONTENT_EXPORT EmbeddedWorkerInstance
// to start the worker. If the worker is already installed,
// |installed_scripts_info| holds information about its scripts; otherwise,
// it is null.
+ // |provider_info_getter| is called when this instance
+ // allocates a process and is ready to send a StartWorker message.
void Start(std::unique_ptr<EmbeddedWorkerStartParams> params,
+ ProviderInfoGetter provider_info_getter,
mojom::ServiceWorkerEventDispatcherRequest dispatcher_request,
mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info,
const StatusCallback& callback);
- // Stops the worker. It is invalid to call this when the worker is
- // not in STARTING or RUNNING status.
- // This returns false when StopWorker IPC couldn't be sent to the worker.
- bool Stop();
+ // Stops the worker. It is invalid to call this when the worker is not in
+ // STARTING or RUNNING status.
+ //
+ // Stop() typically sends a Stop IPC to the renderer, and this instance enters
+ // STOPPING status, with Listener::OnStopped() called upon completion. It can
+ // synchronously complete if this instance is STARTING but the Start IPC
+ // message has not yet been sent. In that case, the start procedure is
+ // aborted, and this instance enters STOPPED status.
+ void Stop();
// Stops the worker if the worker is not being debugged (i.e. devtools is
// not attached). This method is called by a stop-worker timer to kill
@@ -190,6 +214,11 @@ class CONTENT_EXPORT EmbeddedWorkerInstance
static std::string StatusToString(EmbeddedWorkerStatus status);
static std::string StartingPhaseToString(StartingPhase phase);
+ // 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
+ // about the renderer-side worker, and frees this instance up to start a new
+ // worker.
void Detach();
base::WeakPtr<EmbeddedWorkerInstance> AsWeakPtr();
@@ -232,7 +261,7 @@ class CONTENT_EXPORT EmbeddedWorkerInstance
void OnScriptLoaded() override;
// Notifies the corresponding provider host that the thread has started and is
// ready to receive messages.
- void OnThreadStarted(int thread_id, int provider_id) override;
+ void OnThreadStarted(int thread_id) override;
void OnScriptLoadFailed() override;
// Fires the callback passed to Start().
void OnScriptEvaluated(bool success) override;
@@ -251,10 +280,6 @@ class CONTENT_EXPORT EmbeddedWorkerInstance
int line_number,
const GURL& source_url) override;
- // Called when ServiceWorkerDispatcherHost for the worker died while it was
- // running.
- void OnDetached();
-
// Called back from Registry when the worker instance sends message
// to the browser (i.e. EmbeddedWorker observers).
// Returns false if the message is not handled.
@@ -288,7 +313,7 @@ class CONTENT_EXPORT EmbeddedWorkerInstance
int thread_id_;
// |client_| is used to send messages to the renderer process.
- mojom::EmbeddedWorkerInstanceClientPtr client_;
+ mojom::EmbeddedWorkerInstanceClientAssociatedPtr client_;
// Binding for EmbeddedWorkerInstanceHost, runs on IO thread.
mojo::AssociatedBinding<EmbeddedWorkerInstanceHost> instance_host_binding_;
@@ -303,6 +328,9 @@ class CONTENT_EXPORT EmbeddedWorkerInstance
mojom::ServiceWorkerEventDispatcherRequest pending_dispatcher_request_;
mojom::ServiceWorkerInstalledScriptsInfoPtr pending_installed_scripts_info_;
+ // This is set at Start and used on SendStartWorker.
+ ProviderInfoGetter provider_info_getter_;
+
// Whether devtools is attached or not.
bool devtools_attached_;
@@ -322,6 +350,7 @@ class CONTENT_EXPORT EmbeddedWorkerInstance
// Used for UMA. The start time of the current start sequence step.
base::TimeTicks step_time_;
+ std::unique_ptr<ServiceWorkerContentSettingsProxyImpl> content_settings_;
base::WeakPtrFactory<EmbeddedWorkerInstance> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(EmbeddedWorkerInstance);
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 fe7a3bcca34..adcca129881 100644
--- a/chromium/content/browser/service_worker/embedded_worker_instance_unittest.cc
+++ b/chromium/content/browser/service_worker/embedded_worker_instance_unittest.cc
@@ -44,6 +44,30 @@ void SaveStatusAndCall(ServiceWorkerStatusCode* out,
} // namespace
+class ProviderHostEndpoints : public mojom::ServiceWorkerContainerHost {
+ public:
+ ProviderHostEndpoints() : binding_(this) {}
+
+ ~ProviderHostEndpoints() override {}
+
+ mojom::ServiceWorkerProviderInfoForStartWorkerPtr CreateProviderInfoPtr() {
+ DCHECK(!binding_.is_bound());
+ DCHECK(!client_.is_bound());
+ // Just keep the endpoints.
+ mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info =
+ mojom::ServiceWorkerProviderInfoForStartWorker::New();
+ binding_.Bind(mojo::MakeRequest(&provider_info->host_ptr_info));
+ provider_info->client_request = mojo::MakeRequest(&client_);
+ return provider_info;
+ }
+
+ private:
+ mojom::ServiceWorkerContainerAssociatedPtr client_;
+ mojo::AssociatedBinding<mojom::ServiceWorkerContainerHost> binding_;
+
+ DISALLOW_COPY_AND_ASSIGN(ProviderHostEndpoints);
+};
+
class EmbeddedWorkerInstanceTest : public testing::Test,
public EmbeddedWorkerInstance::Listener {
protected:
@@ -82,7 +106,7 @@ class EmbeddedWorkerInstanceTest : public testing::Test,
RecordEvent(DETACHED, old_status);
}
- bool OnMessageReceived(const IPC::Message& message) override { return false; }
+ bool OnMessageReceived(const IPC::Message&) override { return false; }
void SetUp() override {
helper_.reset(new EmbeddedWorkerTestHelper(base::FilePath()));
@@ -98,7 +122,7 @@ class EmbeddedWorkerInstanceTest : public testing::Test,
std::unique_ptr<EmbeddedWorkerStartParams> params =
CreateStartParams(id, pattern, url);
worker->Start(
- std::move(params), CreateEventDispatcher(),
+ std::move(params), CreateProviderInfoGetter(), CreateEventDispatcher(),
GetInstalledScriptsInfoPtr(),
base::Bind(&SaveStatusAndCall, &status, run_loop.QuitClosure()));
run_loop.Run();
@@ -117,6 +141,18 @@ class EmbeddedWorkerInstanceTest : public testing::Test,
return params;
}
+ mojom::ServiceWorkerProviderInfoForStartWorkerPtr CreateProviderInfo(
+ int /* process_id */) {
+ provider_host_endpoints_.emplace_back(
+ base::MakeUnique<ProviderHostEndpoints>());
+ return provider_host_endpoints_.back()->CreateProviderInfoPtr();
+ }
+
+ EmbeddedWorkerInstance::ProviderInfoGetter CreateProviderInfoGetter() {
+ return base::BindOnce(&EmbeddedWorkerInstanceTest::CreateProviderInfo,
+ base::Unretained(this));
+ }
+
mojom::ServiceWorkerEventDispatcherRequest CreateEventDispatcher() {
dispatchers_.emplace_back();
return mojo::MakeRequest(&dispatchers_.back());
@@ -160,6 +196,7 @@ class EmbeddedWorkerInstanceTest : public testing::Test,
std::vector<mojom::ServiceWorkerEventDispatcherPtr> dispatchers_;
std::vector<mojom::ServiceWorkerInstalledScriptsManagerPtr>
installed_scripts_managers_;
+ std::vector<std::unique_ptr<ProviderHostEndpoints>> provider_host_endpoints_;
TestBrowserThreadBundle thread_bundle_;
std::unique_ptr<EmbeddedWorkerTestHelper> helper_;
@@ -176,14 +213,16 @@ class StalledInStartWorkerHelper : public EmbeddedWorkerTestHelper {
StalledInStartWorkerHelper() : EmbeddedWorkerTestHelper(base::FilePath()) {}
~StalledInStartWorkerHelper() override {}
- void OnStartWorker(int embedded_worker_id,
- int64_t service_worker_version_id,
- const GURL& scope,
- const GURL& script_url,
- bool pause_after_download,
- mojom::ServiceWorkerEventDispatcherRequest request,
- mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo
- instance_host) override {
+ void OnStartWorker(
+ int embedded_worker_id,
+ int64_t service_worker_version_id,
+ const GURL& scope,
+ const GURL& script_url,
+ bool pause_after_download,
+ mojom::ServiceWorkerEventDispatcherRequest request,
+ mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
+ mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info)
+ override {
if (force_stall_in_start_) {
// Prepare for OnStopWorker().
instance_host_ptr_map_[embedded_worker_id].Bind(std::move(instance_host));
@@ -192,7 +231,8 @@ class StalledInStartWorkerHelper : public EmbeddedWorkerTestHelper {
}
EmbeddedWorkerTestHelper::OnStartWorker(
embedded_worker_id, service_worker_version_id, scope, script_url,
- pause_after_download, std::move(request), std::move(instance_host));
+ pause_after_download, std::move(request), std::move(instance_host),
+ std::move(provider_info));
}
void OnStopWorker(int embedded_worker_id) override {
@@ -237,7 +277,8 @@ TEST_F(EmbeddedWorkerInstanceTest, StartAndStop) {
std::unique_ptr<EmbeddedWorkerStartParams> params =
CreateStartParams(service_worker_version_id, pattern, url);
worker->Start(
- std::move(params), CreateEventDispatcher(), GetInstalledScriptsInfoPtr(),
+ std::move(params), CreateProviderInfoGetter(), CreateEventDispatcher(),
+ GetInstalledScriptsInfoPtr(),
base::Bind(&SaveStatusAndCall, &status, run_loop.QuitClosure()));
EXPECT_EQ(EmbeddedWorkerStatus::STARTING, worker->status());
run_loop.Run();
@@ -249,7 +290,7 @@ TEST_F(EmbeddedWorkerInstanceTest, StartAndStop) {
EXPECT_EQ(helper_->mock_render_process_id(), worker->process_id());
// Stop the worker.
- EXPECT_TRUE(worker->Stop());
+ worker->Stop();
EXPECT_EQ(EmbeddedWorkerStatus::STOPPING, worker->status());
base::RunLoop().RunUntilIdle();
@@ -294,7 +335,7 @@ TEST_F(EmbeddedWorkerInstanceTest, ForceNewProcess) {
std::unique_ptr<EmbeddedWorkerStartParams> params =
CreateStartParams(service_worker_version_id, pattern, url);
worker->Start(
- std::move(params), CreateEventDispatcher(),
+ std::move(params), CreateProviderInfoGetter(), CreateEventDispatcher(),
GetInstalledScriptsInfoPtr(),
base::Bind(&SaveStatusAndCall, &status, run_loop.QuitClosure()));
run_loop.Run();
@@ -303,7 +344,7 @@ TEST_F(EmbeddedWorkerInstanceTest, ForceNewProcess) {
// The worker should be using the default render process.
EXPECT_EQ(helper_->mock_render_process_id(), worker->process_id());
- EXPECT_TRUE(worker->Stop());
+ worker->Stop();
base::RunLoop().RunUntilIdle();
}
@@ -320,7 +361,7 @@ TEST_F(EmbeddedWorkerInstanceTest, ForceNewProcess) {
std::unique_ptr<EmbeddedWorkerStartParams> params =
CreateStartParams(service_worker_version_id, pattern, url);
worker->Start(
- std::move(params), CreateEventDispatcher(),
+ std::move(params), CreateProviderInfoGetter(), CreateEventDispatcher(),
GetInstalledScriptsInfoPtr(),
base::Bind(&SaveStatusAndCall, &status, run_loop.QuitClosure()));
EXPECT_EQ(EmbeddedWorkerStatus::STARTING, worker->status());
@@ -330,7 +371,7 @@ TEST_F(EmbeddedWorkerInstanceTest, ForceNewProcess) {
EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, worker->status());
// The worker should be using the new render process.
EXPECT_EQ(helper_->new_render_process_id(), worker->process_id());
- EXPECT_TRUE(worker->Stop());
+ worker->Stop();
base::RunLoop().RunUntilIdle();
}
}
@@ -375,7 +416,7 @@ TEST_F(EmbeddedWorkerInstanceTest, StopWhenDevToolsAttached) {
// Calling Stop() actually stops the worker regardless of whether devtools
// is attached or not.
- EXPECT_TRUE(worker->Stop());
+ worker->Stop();
base::RunLoop().RunUntilIdle();
EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, worker->status());
}
@@ -402,7 +443,7 @@ TEST_F(EmbeddedWorkerInstanceTest, RemoveWorkerInSharedProcess) {
std::unique_ptr<EmbeddedWorkerStartParams> params =
CreateStartParams(version_id1, pattern, url);
worker1->Start(
- std::move(params), CreateEventDispatcher(),
+ std::move(params), CreateProviderInfoGetter(), CreateEventDispatcher(),
GetInstalledScriptsInfoPtr(),
base::Bind(&SaveStatusAndCall, &status, run_loop.QuitClosure()));
run_loop.Run();
@@ -416,7 +457,7 @@ TEST_F(EmbeddedWorkerInstanceTest, RemoveWorkerInSharedProcess) {
std::unique_ptr<EmbeddedWorkerStartParams> params =
CreateStartParams(version_id2, pattern, url);
worker2->Start(
- std::move(params), CreateEventDispatcher(),
+ std::move(params), CreateProviderInfoGetter(), CreateEventDispatcher(),
GetInstalledScriptsInfoPtr(),
base::Bind(&SaveStatusAndCall, &status, run_loop.QuitClosure()));
run_loop.Run();
@@ -455,7 +496,8 @@ TEST_F(EmbeddedWorkerInstanceTest, DetachDuringProcessAllocation) {
std::unique_ptr<EmbeddedWorkerStartParams> params =
CreateStartParams(version_id, scope, url);
worker->Start(
- std::move(params), CreateEventDispatcher(), GetInstalledScriptsInfoPtr(),
+ std::move(params), CreateProviderInfoGetter(), CreateEventDispatcher(),
+ GetInstalledScriptsInfoPtr(),
base::Bind(&SaveStatusAndCall, &status, base::Bind(&base::DoNothing)));
worker->Detach();
base::RunLoop().RunUntilIdle();
@@ -488,7 +530,8 @@ TEST_F(EmbeddedWorkerInstanceTest, DetachAfterSendingStartWorkerMessage) {
std::unique_ptr<EmbeddedWorkerStartParams> params =
CreateStartParams(version_id, scope, url);
worker->Start(
- std::move(params), CreateEventDispatcher(), GetInstalledScriptsInfoPtr(),
+ std::move(params), CreateProviderInfoGetter(), CreateEventDispatcher(),
+ GetInstalledScriptsInfoPtr(),
base::Bind(&SaveStatusAndCall, &status, base::Bind(&base::DoNothing)));
base::RunLoop().RunUntilIdle();
@@ -528,7 +571,8 @@ TEST_F(EmbeddedWorkerInstanceTest, StopDuringProcessAllocation) {
std::unique_ptr<EmbeddedWorkerStartParams> params =
CreateStartParams(version_id, scope, url);
worker->Start(
- std::move(params), CreateEventDispatcher(), GetInstalledScriptsInfoPtr(),
+ std::move(params), CreateProviderInfoGetter(), CreateEventDispatcher(),
+ GetInstalledScriptsInfoPtr(),
base::Bind(&SaveStatusAndCall, &status, base::Bind(&base::DoNothing)));
worker->Stop();
base::RunLoop().RunUntilIdle();
@@ -542,7 +586,7 @@ TEST_F(EmbeddedWorkerInstanceTest, StopDuringProcessAllocation) {
// "PROCESS_ALLOCATED" event should not be recorded.
ASSERT_EQ(1u, events_.size());
- EXPECT_EQ(DETACHED, events_[0].type);
+ EXPECT_EQ(STOPPED, events_[0].type);
EXPECT_EQ(EmbeddedWorkerStatus::STARTING, events_[0].status);
events_.clear();
@@ -551,7 +595,8 @@ TEST_F(EmbeddedWorkerInstanceTest, StopDuringProcessAllocation) {
std::unique_ptr<base::RunLoop> run_loop(new base::RunLoop);
params = CreateStartParams(version_id, scope, url);
worker->Start(
- std::move(params), CreateEventDispatcher(), GetInstalledScriptsInfoPtr(),
+ std::move(params), CreateProviderInfoGetter(), CreateEventDispatcher(),
+ GetInstalledScriptsInfoPtr(),
base::Bind(&SaveStatusAndCall, &status, run_loop->QuitClosure()));
run_loop->Run();
@@ -603,7 +648,8 @@ TEST_F(EmbeddedWorkerInstanceTest, StopDuringPausedAfterDownload) {
CreateStartParams(version_id, scope, url);
params->pause_after_download = true;
worker->Start(
- std::move(params), CreateEventDispatcher(), GetInstalledScriptsInfoPtr(),
+ std::move(params), CreateProviderInfoGetter(), CreateEventDispatcher(),
+ GetInstalledScriptsInfoPtr(),
base::Bind(&SaveStatusAndCall, &status, base::Bind(&base::DoNothing)));
base::RunLoop().RunUntilIdle();
@@ -633,7 +679,8 @@ TEST_F(EmbeddedWorkerInstanceTest, StopAfterSendingStartWorkerMessage) {
std::unique_ptr<EmbeddedWorkerStartParams> params =
CreateStartParams(version_id, scope, url);
worker->Start(
- std::move(params), CreateEventDispatcher(), GetInstalledScriptsInfoPtr(),
+ std::move(params), CreateProviderInfoGetter(), CreateEventDispatcher(),
+ GetInstalledScriptsInfoPtr(),
base::Bind(&SaveStatusAndCall, &status, base::Bind(&base::DoNothing)));
base::RunLoop().RunUntilIdle();
@@ -666,7 +713,8 @@ TEST_F(EmbeddedWorkerInstanceTest, StopAfterSendingStartWorkerMessage) {
params = CreateStartParams(version_id, scope, url);
worker->Start(
- std::move(params), CreateEventDispatcher(), GetInstalledScriptsInfoPtr(),
+ std::move(params), CreateProviderInfoGetter(), CreateEventDispatcher(),
+ GetInstalledScriptsInfoPtr(),
base::Bind(&SaveStatusAndCall, &status, run_loop->QuitClosure()));
run_loop->Run();
@@ -697,7 +745,8 @@ TEST_F(EmbeddedWorkerInstanceTest, Detach) {
std::unique_ptr<EmbeddedWorkerStartParams> params =
CreateStartParams(version_id, pattern, url);
worker->Start(
- std::move(params), CreateEventDispatcher(), GetInstalledScriptsInfoPtr(),
+ std::move(params), CreateProviderInfoGetter(), CreateEventDispatcher(),
+ GetInstalledScriptsInfoPtr(),
base::Bind(&SaveStatusAndCall, &status, run_loop.QuitClosure()));
run_loop.Run();
@@ -731,15 +780,18 @@ TEST_F(EmbeddedWorkerInstanceTest, FailToSendStartIPC) {
// Attempt to start the worker.
std::unique_ptr<EmbeddedWorkerStartParams> params =
CreateStartParams(version_id, pattern, url);
- worker->Start(std::move(params), CreateEventDispatcher(),
- GetInstalledScriptsInfoPtr(),
+ worker->Start(std::move(params), CreateProviderInfoGetter(),
+ CreateEventDispatcher(), GetInstalledScriptsInfoPtr(),
base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
base::RunLoop().RunUntilIdle();
- // Worker should handle the failure of binding as detach.
- ASSERT_EQ(1u, events_.size());
- EXPECT_EQ(DETACHED, events_[0].type);
- EXPECT_EQ(EmbeddedWorkerStatus::STARTING, events_[0].status);
+ // Worker should handle the failure of binding on the remote side as detach.
+ ASSERT_EQ(3u, events_.size());
+ EXPECT_EQ(PROCESS_ALLOCATED, events_[0].type);
+ EXPECT_EQ(START_WORKER_MESSAGE_SENT, events_[1].type);
+ EXPECT_EQ(DETACHED, events_[2].type);
+ EXPECT_EQ(EmbeddedWorkerStatus::STARTING, events_[2].status);
+ EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, worker->status());
}
class FailEmbeddedWorkerInstanceClientImpl
@@ -750,12 +802,13 @@ class FailEmbeddedWorkerInstanceClientImpl
: EmbeddedWorkerTestHelper::MockEmbeddedWorkerInstanceClient(helper) {}
private:
- void StartWorker(
- const EmbeddedWorkerStartParams& /* unused */,
- mojom::ServiceWorkerEventDispatcherRequest /* unused */,
- mojom::ServiceWorkerInstalledScriptsInfoPtr /* unused */,
- mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo /* unused */)
- override {
+ void StartWorker(const EmbeddedWorkerStartParams&,
+ mojom::ServiceWorkerEventDispatcherRequest,
+ mojom::ServiceWorkerInstalledScriptsInfoPtr /* unused */,
+ mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo,
+ mojom::ServiceWorkerProviderInfoForStartWorkerPtr,
+ blink::mojom::WorkerContentSettingsProxyPtr
+ content_settings_proxy) override {
helper_->mock_instance_clients()->clear();
}
};
@@ -780,8 +833,8 @@ TEST_F(EmbeddedWorkerInstanceTest, RemoveRemoteInterface) {
// Attempt to start the worker.
std::unique_ptr<EmbeddedWorkerStartParams> params =
CreateStartParams(version_id, pattern, url);
- worker->Start(std::move(params), CreateEventDispatcher(),
- GetInstalledScriptsInfoPtr(),
+ worker->Start(std::move(params), CreateProviderInfoGetter(),
+ CreateEventDispatcher(), GetInstalledScriptsInfoPtr(),
base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
base::RunLoop().RunUntilIdle();
@@ -837,8 +890,8 @@ TEST_F(EmbeddedWorkerInstanceTest, AddMessageToConsole) {
std::make_pair(blink::WebConsoleMessage::kLevelVerbose, "");
std::unique_ptr<EmbeddedWorkerStartParams> params =
CreateStartParams(version_id, pattern, url);
- worker->Start(std::move(params), CreateEventDispatcher(),
- GetInstalledScriptsInfoPtr(),
+ worker->Start(std::move(params), CreateProviderInfoGetter(),
+ CreateEventDispatcher(), GetInstalledScriptsInfoPtr(),
base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
worker->AddMessageToConsole(test_message.first, test_message.second);
base::RunLoop().RunUntilIdle();
diff --git a/chromium/content/browser/service_worker/embedded_worker_registry.cc b/chromium/content/browser/service_worker/embedded_worker_registry.cc
index d4ce51f4f03..52daac22a31 100644
--- a/chromium/content/browser/service_worker/embedded_worker_registry.cc
+++ b/chromium/content/browser/service_worker/embedded_worker_registry.cc
@@ -94,29 +94,6 @@ void EmbeddedWorkerRegistry::OnDevToolsAttached(int embedded_worker_id) {
lifetime_tracker_.AbortTiming(embedded_worker_id);
}
-void EmbeddedWorkerRegistry::RemoveProcess(int process_id) {
- std::map<int, std::set<int> >::iterator found =
- worker_process_map_.find(process_id);
- if (found != worker_process_map_.end()) {
- const std::set<int>& worker_set = worker_process_map_[process_id];
- for (std::set<int>::const_iterator it = worker_set.begin();
- it != worker_set.end();
- ++it) {
- int embedded_worker_id = *it;
- DCHECK(base::ContainsKey(worker_map_, embedded_worker_id));
- // RemoveProcess is typically called after the running workers on the
- // process have been stopped, so if there is a running worker at this
- // point somehow the worker thread has lost contact with the browser
- // process.
- // Set the worker's status to STOPPED so a new thread can be created for
- // this version. Use OnDetached rather than OnStopped so UMA doesn't
- // record it as a normal stoppage.
- worker_map_[embedded_worker_id]->OnDetached();
- }
- worker_process_map_.erase(found);
- }
-}
-
EmbeddedWorkerInstance* EmbeddedWorkerRegistry::GetWorker(
int embedded_worker_id) {
WorkerInstanceMap::iterator found = worker_map_.find(embedded_worker_id);
diff --git a/chromium/content/browser/service_worker/embedded_worker_registry.h b/chromium/content/browser/service_worker/embedded_worker_registry.h
index 897d23b565e..4ff60bc386e 100644
--- a/chromium/content/browser/service_worker/embedded_worker_registry.h
+++ b/chromium/content/browser/service_worker/embedded_worker_registry.h
@@ -34,7 +34,7 @@ class ServiceWorkerContextCore;
// Hangs off ServiceWorkerContextCore (its reference is also held by each
// EmbeddedWorkerInstance). Operated only on IO thread.
class CONTENT_EXPORT EmbeddedWorkerRegistry
- : public NON_EXPORTED_BASE(base::RefCounted<EmbeddedWorkerRegistry>) {
+ : public base::RefCounted<EmbeddedWorkerRegistry> {
public:
static scoped_refptr<EmbeddedWorkerRegistry> Create(
const base::WeakPtr<ServiceWorkerContextCore>& contxet);
@@ -51,10 +51,11 @@ class CONTENT_EXPORT EmbeddedWorkerRegistry
// This doesn't actually start or stop the worker.
std::unique_ptr<EmbeddedWorkerInstance> CreateWorker();
- // Stop all active workers, even if they're handling events.
+ // Stop all running workers, even if they're handling events.
void Shutdown();
- // Called by EmbeddedWorkerInstance to do some necessary work in the registry.
+ // Called by EmbeddedWorkerInstance when it starts or stops. This registry
+ // keeps track of running workers.
bool OnWorkerStarted(int process_id, int embedded_worker_id);
void OnWorkerStopped(int process_id, int embedded_worker_id);
@@ -62,14 +63,6 @@ class CONTENT_EXPORT EmbeddedWorkerRegistry
// it.
void OnDevToolsAttached(int embedded_worker_id);
- // Removes information about the service workers running on the process and
- // calls ServiceWorkerVersion::OnDetached() on each. Called when the process
- // is terminated. Under normal operation, the workers should already have
- // been stopped before the process is terminated, in which case this function
- // does nothing. But in some cases the process can be terminated unexpectedly
- // or the workers can fail to stop cleanly.
- void RemoveProcess(int process_id);
-
// Returns an embedded worker instance for given |embedded_worker_id|.
EmbeddedWorkerInstance* GetWorker(int embedded_worker_id);
@@ -102,9 +95,10 @@ class CONTENT_EXPORT EmbeddedWorkerRegistry
// |process_id| could be invalid (i.e. ChildProcessHost::kInvalidUniqueID)
// if it's not running.
void RemoveWorker(int process_id, int embedded_worker_id);
- // DetachWorker is called when EmbeddedWorkerInstance releases a process.
- // |process_id| could be invalid (i.e. ChildProcessHost::kInvalidUniqueID)
- // if it's not running.
+
+ // Removes the bookkeeping that binds the worker to the process. This is
+ // called instead of WorkerStopped() in cases when the worker could not be
+ // cleanly stopped, e.g., because connection with the renderer was lost.
void DetachWorker(int process_id, int embedded_worker_id);
EmbeddedWorkerInstance* GetWorkerForMessage(int process_id,
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 9ecf8cd05fe..0cf7c5f9d70 100644
--- a/chromium/content/browser/service_worker/embedded_worker_test_helper.cc
+++ b/chromium/content/browser/service_worker/embedded_worker_test_helper.cc
@@ -25,6 +25,7 @@
#include "content/browser/service_worker/service_worker_dispatcher_host.h"
#include "content/browser/service_worker/service_worker_test_utils.h"
#include "content/common/background_fetch/background_fetch_types.h"
+#include "content/common/renderer.mojom.h"
#include "content/common/service_worker/embedded_worker_messages.h"
#include "content/common/service_worker/embedded_worker_start_params.h"
#include "content/common/service_worker/service_worker_event_dispatcher.mojom.h"
@@ -33,8 +34,11 @@
#include "content/public/common/push_event_payload.h"
#include "content/public/test/mock_render_process_host.h"
#include "content/public/test/test_browser_context.h"
+#include "mojo/public/cpp/bindings/associated_binding_set.h"
#include "mojo/public/cpp/bindings/interface_request.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "services/network/public/interfaces/fetch_api.mojom.h"
+#include "storage/common/blob_storage/blob_handle.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
@@ -74,7 +78,9 @@ void EmbeddedWorkerTestHelper::MockEmbeddedWorkerInstanceClient::StartWorker(
const EmbeddedWorkerStartParams& params,
mojom::ServiceWorkerEventDispatcherRequest dispatcher_request,
mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info,
- mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host) {
+ mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
+ mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info,
+ blink::mojom::WorkerContentSettingsProxyPtr content_settings_proxy) {
if (!helper_)
return;
@@ -86,7 +92,8 @@ void EmbeddedWorkerTestHelper::MockEmbeddedWorkerInstanceClient::StartWorker(
EXPECT_EQ(EmbeddedWorkerStatus::STARTING, worker->status());
helper_->OnStartWorkerStub(params, std::move(dispatcher_request),
- std::move(instance_host));
+ std::move(instance_host),
+ std::move(provider_info));
}
void EmbeddedWorkerTestHelper::MockEmbeddedWorkerInstanceClient::StopWorker() {
@@ -118,8 +125,7 @@ void EmbeddedWorkerTestHelper::MockEmbeddedWorkerInstanceClient::
// static
void EmbeddedWorkerTestHelper::MockEmbeddedWorkerInstanceClient::Bind(
const base::WeakPtr<EmbeddedWorkerTestHelper>& helper,
- mojo::ScopedMessagePipeHandle request_handle) {
- mojom::EmbeddedWorkerInstanceClientRequest request(std::move(request_handle));
+ mojom::EmbeddedWorkerInstanceClientAssociatedRequest request) {
std::vector<std::unique_ptr<MockEmbeddedWorkerInstanceClient>>* clients =
helper->mock_instance_clients();
size_t next_client_index = helper->mock_instance_clients_next_index_;
@@ -138,7 +144,7 @@ void EmbeddedWorkerTestHelper::MockEmbeddedWorkerInstanceClient::Bind(
}
class EmbeddedWorkerTestHelper::MockServiceWorkerEventDispatcher
- : public NON_EXPORTED_BASE(mojom::ServiceWorkerEventDispatcher) {
+ : public mojom::ServiceWorkerEventDispatcher {
public:
static void Create(const base::WeakPtr<EmbeddedWorkerTestHelper>& helper,
int thread_id,
@@ -254,6 +260,28 @@ class EmbeddedWorkerTestHelper::MockServiceWorkerEventDispatcher
NOTIMPLEMENTED();
}
+ void DispatchAbortPaymentEvent(
+ int payment_request_id,
+ payments::mojom::PaymentHandlerResponseCallbackPtr response_callback,
+ DispatchAbortPaymentEventCallback callback) override {
+ if (!helper_)
+ return;
+ helper_->OnAbortPaymentEventStub(std::move(response_callback),
+ std::move(callback));
+ }
+
+ void DispatchCanMakePaymentEvent(
+ int payment_request_id,
+ payments::mojom::CanMakePaymentEventDataPtr event_data,
+ payments::mojom::PaymentHandlerResponseCallbackPtr response_callback,
+ DispatchCanMakePaymentEventCallback callback) override {
+ if (!helper_)
+ return;
+ helper_->OnCanMakePaymentEventStub(std::move(event_data),
+ std::move(response_callback),
+ std::move(callback));
+ }
+
void DispatchPaymentRequestEvent(
int payment_request_id,
payments::mojom::PaymentRequestEventDataPtr event_data,
@@ -282,41 +310,104 @@ class EmbeddedWorkerTestHelper::MockServiceWorkerEventDispatcher
const int thread_id_;
};
+class EmbeddedWorkerTestHelper::MockRendererInterface : public mojom::Renderer {
+ public:
+ explicit MockRendererInterface(base::WeakPtr<EmbeddedWorkerTestHelper> helper)
+ : helper_(helper) {}
+
+ void AddBinding(mojom::RendererAssociatedRequest request) {
+ bindings_.AddBinding(this, std::move(request));
+ }
+
+ private:
+ void CreateView(mojom::CreateViewParamsPtr) override { NOTREACHED(); }
+ void CreateFrame(mojom::CreateFrameParamsPtr) override { NOTREACHED(); }
+ void SetUpEmbeddedWorkerChannelForServiceWorker(
+ mojom::EmbeddedWorkerInstanceClientAssociatedRequest client_request)
+ override {
+ MockEmbeddedWorkerInstanceClient::Bind(helper_, std::move(client_request));
+ }
+ void CreateFrameProxy(
+ int32_t routing_id,
+ int32_t render_view_routing_id,
+ int32_t opener_routing_id,
+ int32_t parent_routing_id,
+ const FrameReplicationState& replicated_state) override {
+ NOTREACHED();
+ }
+ void OnNetworkConnectionChanged(
+ net::NetworkChangeNotifier::ConnectionType type,
+ double max_bandwidth_mbps) override {
+ NOTREACHED();
+ }
+ void OnNetworkQualityChanged(net::EffectiveConnectionType type,
+ base::TimeDelta http_rtt,
+ base::TimeDelta transport_rtt,
+ double bandwidth_kbps) override {
+ NOTREACHED();
+ }
+ void SetWebKitSharedTimersSuspended(bool suspend) override { NOTREACHED(); }
+ void UpdateScrollbarTheme(
+ mojom::UpdateScrollbarThemeParamsPtr params) override {
+ NOTREACHED();
+ }
+ void OnSystemColorsChanged(int32_t aqua_color_variant,
+ const std::string& highlight_text_color,
+ const std::string& highlight_color) override {
+ NOTREACHED();
+ }
+ void PurgePluginListCache(bool reload_pages) override { NOTREACHED(); }
+
+ base::WeakPtr<EmbeddedWorkerTestHelper> helper_;
+ mojo::AssociatedBindingSet<mojom::Renderer> bindings_;
+};
+
EmbeddedWorkerTestHelper::EmbeddedWorkerTestHelper(
const base::FilePath& user_data_directory)
- : browser_context_(new TestBrowserContext),
- render_process_host_(new MockRenderProcessHost(browser_context_.get())),
+ : browser_context_(base::MakeUnique<TestBrowserContext>()),
+ render_process_host_(
+ base::MakeUnique<MockRenderProcessHost>(browser_context_.get())),
new_render_process_host_(
- new MockRenderProcessHost(browser_context_.get())),
- wrapper_(new ServiceWorkerContextWrapper(browser_context_.get())),
+ base::MakeUnique<MockRenderProcessHost>(browser_context_.get())),
+ wrapper_(base::MakeRefCounted<ServiceWorkerContextWrapper>(
+ browser_context_.get())),
mock_instance_clients_next_index_(0),
next_thread_id_(0),
- next_provider_id_(1000),
mock_render_process_id_(render_process_host_->GetID()),
new_mock_render_process_id_(new_render_process_host_->GetID()),
weak_factory_(this) {
- std::unique_ptr<MockServiceWorkerDatabaseTaskManager> database_task_manager(
- new MockServiceWorkerDatabaseTaskManager(
- base::ThreadTaskRunnerHandle::Get()));
- wrapper_->InitInternal(user_data_directory, std::move(database_task_manager),
- base::ThreadTaskRunnerHandle::Get(), nullptr, nullptr,
- nullptr, nullptr);
+ scoped_refptr<base::SequencedTaskRunner> database_task_runner =
+ base::ThreadTaskRunnerHandle::Get();
+ wrapper_->InitInternal(user_data_directory, std::move(database_task_runner),
+ nullptr, nullptr, nullptr, nullptr);
wrapper_->process_manager()->SetProcessIdForTest(mock_render_process_id());
wrapper_->process_manager()->SetNewProcessIdForTest(new_render_process_id());
scoped_refptr<ServiceWorkerDispatcherHost> dispatcher_host(
- new MockServiceWorkerDispatcherHost(
+ base::MakeRefCounted<MockServiceWorkerDispatcherHost>(
mock_render_process_id_, browser_context_->GetResourceContext(),
this));
dispatcher_host->Init(wrapper_.get());
dispatcher_hosts_[mock_render_process_id_] = std::move(dispatcher_host);
- render_process_host_->OverrideBinderForTesting(
- mojom::EmbeddedWorkerInstanceClient::Name_,
- base::Bind(&MockEmbeddedWorkerInstanceClient::Bind, AsWeakPtr()));
- new_render_process_host_->OverrideBinderForTesting(
- mojom::EmbeddedWorkerInstanceClient::Name_,
- base::Bind(&MockEmbeddedWorkerInstanceClient::Bind, AsWeakPtr()));
+ // Install a mocked mojom::Renderer interface to catch requests to
+ // establish Mojo connection for EWInstanceClient.
+ mock_renderer_interface_ =
+ base::MakeUnique<MockRendererInterface>(AsWeakPtr());
+
+ auto renderer_interface_ptr =
+ base::MakeUnique<mojom::RendererAssociatedPtr>();
+ mock_renderer_interface_->AddBinding(
+ mojo::MakeIsolatedRequest(renderer_interface_ptr.get()));
+ render_process_host_->OverrideRendererInterfaceForTesting(
+ std::move(renderer_interface_ptr));
+
+ auto new_renderer_interface_ptr =
+ base::MakeUnique<mojom::RendererAssociatedPtr>();
+ mock_renderer_interface_->AddBinding(
+ mojo::MakeIsolatedRequest(new_renderer_interface_ptr.get()));
+ new_render_process_host_->OverrideRendererInterfaceForTesting(
+ std::move(new_renderer_interface_ptr));
}
EmbeddedWorkerTestHelper::~EmbeddedWorkerTestHelper() {
@@ -378,6 +469,11 @@ void EmbeddedWorkerTestHelper::ShutdownContext() {
wrapper_ = NULL;
}
+ServiceWorkerDispatcherHost*
+EmbeddedWorkerTestHelper::GetDispatcherHostForProcess(int process_id) {
+ return dispatcher_hosts_[process_id].get();
+}
+
// static
net::HttpResponseInfo EmbeddedWorkerTestHelper::CreateHttpResponseInfo() {
net::HttpResponseInfo info;
@@ -397,7 +493,8 @@ void EmbeddedWorkerTestHelper::OnStartWorker(
const GURL& script_url,
bool pause_after_download,
mojom::ServiceWorkerEventDispatcherRequest request,
- mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host) {
+ mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
+ mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info) {
EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
ASSERT_TRUE(worker);
MockServiceWorkerEventDispatcher::Create(AsWeakPtr(), worker->thread_id(),
@@ -407,6 +504,9 @@ void EmbeddedWorkerTestHelper::OnStartWorker(
service_worker_version_id;
embedded_worker_id_instance_host_ptr_map_[embedded_worker_id].Bind(
std::move(instance_host));
+ ServiceWorkerRemoteProviderEndpoint* provider_endpoint =
+ &embedded_worker_id_remote_provider_map_[embedded_worker_id];
+ provider_endpoint->BindWithProviderInfo(std::move(provider_info));
SimulateWorkerReadyForInspection(embedded_worker_id);
SimulateWorkerScriptCached(embedded_worker_id);
@@ -416,8 +516,7 @@ void EmbeddedWorkerTestHelper::OnStartWorker(
}
void EmbeddedWorkerTestHelper::OnResumeAfterDownload(int embedded_worker_id) {
- SimulateWorkerThreadStarted(GetNextThreadId(), embedded_worker_id,
- GetNextProviderId());
+ SimulateWorkerThreadStarted(GetNextThreadId(), embedded_worker_id);
SimulateWorkerScriptEvaluated(embedded_worker_id, true /* success */);
SimulateWorkerStarted(embedded_worker_id);
}
@@ -491,10 +590,10 @@ void EmbeddedWorkerTestHelper::OnFetchEvent(
response_callback->OnResponse(
ServiceWorkerResponse(
base::MakeUnique<std::vector<GURL>>(), 200, "OK",
- blink::kWebServiceWorkerResponseTypeDefault,
+ network::mojom::FetchResponseType::kDefault,
base::MakeUnique<ServiceWorkerHeaderMap>(), std::string(), 0,
- blink::kWebServiceWorkerResponseErrorUnknown, base::Time(),
- false /* is_in_cache_storage */,
+ nullptr /* blob */, blink::kWebServiceWorkerResponseErrorUnknown,
+ base::Time(), false /* is_in_cache_storage */,
std::string() /* cache_storage_cache_name */,
base::MakeUnique<
ServiceWorkerHeaderList>() /* cors_exposed_header_names */),
@@ -526,12 +625,39 @@ void EmbeddedWorkerTestHelper::OnNotificationCloseEvent(
std::move(callback).Run(SERVICE_WORKER_OK, base::Time::Now());
}
+void EmbeddedWorkerTestHelper::OnAbortPaymentEvent(
+ payments::mojom::PaymentHandlerResponseCallbackPtr response_callback,
+ mojom::ServiceWorkerEventDispatcher::DispatchAbortPaymentEventCallback
+ callback) {
+ response_callback->OnResponseForAbortPayment(true, base::Time::Now());
+ std::move(callback).Run(SERVICE_WORKER_OK, base::Time::Now());
+}
+
+void EmbeddedWorkerTestHelper::OnCanMakePaymentEvent(
+ payments::mojom::CanMakePaymentEventDataPtr event_data,
+ payments::mojom::PaymentHandlerResponseCallbackPtr response_callback,
+ mojom::ServiceWorkerEventDispatcher::DispatchCanMakePaymentEventCallback
+ callback) {
+ bool can_make_payment = false;
+ for (const auto& method_data : event_data->method_data) {
+ for (const auto& method : method_data->supported_methods) {
+ if (method == "test-method") {
+ can_make_payment = true;
+ break;
+ }
+ }
+ }
+ response_callback->OnResponseForCanMakePayment(can_make_payment,
+ base::Time::Now());
+ std::move(callback).Run(SERVICE_WORKER_OK, base::Time::Now());
+}
+
void EmbeddedWorkerTestHelper::OnPaymentRequestEvent(
payments::mojom::PaymentRequestEventDataPtr event_data,
payments::mojom::PaymentHandlerResponseCallbackPtr response_callback,
mojom::ServiceWorkerEventDispatcher::DispatchPaymentRequestEventCallback
callback) {
- response_callback->OnPaymentHandlerResponse(
+ response_callback->OnResponseForPaymentRequest(
payments::mojom::PaymentHandlerResponse::New(), base::Time::Now());
std::move(callback).Run(SERVICE_WORKER_OK, base::Time::Now());
}
@@ -578,22 +704,12 @@ void EmbeddedWorkerTestHelper::SimulateWorkerScriptLoaded(
void EmbeddedWorkerTestHelper::SimulateWorkerThreadStarted(
int thread_id,
- int embedded_worker_id,
- int provider_id) {
+ int embedded_worker_id) {
EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
ASSERT_TRUE(worker);
ASSERT_TRUE(embedded_worker_id_instance_host_ptr_map_[embedded_worker_id]);
-
- // Prepare a provider host to be used by following OnThreadStarted().
- std::unique_ptr<ServiceWorkerProviderHost> host =
- CreateProviderHostForServiceWorkerContext(
- worker->process_id(), provider_id, true /* is_parent_frame_secure */,
- context()->AsWeakPtr(),
- &embedded_worker_id_remote_provider_map_[embedded_worker_id]);
- context()->AddProviderHost(std::move(host));
-
embedded_worker_id_instance_host_ptr_map_[embedded_worker_id]
- ->OnThreadStarted(thread_id, provider_id);
+ ->OnThreadStarted(thread_id);
base::RunLoop().RunUntilIdle();
}
@@ -622,6 +738,7 @@ void EmbeddedWorkerTestHelper::SimulateWorkerStopped(int embedded_worker_id) {
if (worker) {
ASSERT_TRUE(embedded_worker_id_instance_host_ptr_map_[embedded_worker_id]);
embedded_worker_id_instance_host_ptr_map_[embedded_worker_id]->OnStopped();
+ embedded_worker_id_remote_provider_map_.erase(embedded_worker_id);
base::RunLoop().RunUntilIdle();
}
}
@@ -634,17 +751,20 @@ void EmbeddedWorkerTestHelper::SimulateSend(IPC::Message* message) {
void EmbeddedWorkerTestHelper::OnStartWorkerStub(
const EmbeddedWorkerStartParams& params,
mojom::ServiceWorkerEventDispatcherRequest request,
- mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host) {
+ mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
+ mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info) {
EmbeddedWorkerInstance* worker =
registry()->GetWorker(params.embedded_worker_id);
ASSERT_TRUE(worker);
EXPECT_EQ(EmbeddedWorkerStatus::STARTING, worker->status());
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
- base::Bind(&EmbeddedWorkerTestHelper::OnStartWorker, AsWeakPtr(),
- params.embedded_worker_id, params.service_worker_version_id,
- params.scope, params.script_url, params.pause_after_download,
- base::Passed(&request), base::Passed(&instance_host)));
+ base::BindOnce(&EmbeddedWorkerTestHelper::OnStartWorker, AsWeakPtr(),
+ params.embedded_worker_id,
+ params.service_worker_version_id, params.scope,
+ params.script_url, params.pause_after_download,
+ base::Passed(&request), base::Passed(&instance_host),
+ base::Passed(&provider_info)));
}
void EmbeddedWorkerTestHelper::OnResumeAfterDownloadStub(
@@ -652,14 +772,15 @@ void EmbeddedWorkerTestHelper::OnResumeAfterDownloadStub(
EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
ASSERT_TRUE(worker);
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&EmbeddedWorkerTestHelper::OnResumeAfterDownload,
- AsWeakPtr(), embedded_worker_id));
+ FROM_HERE,
+ base::BindOnce(&EmbeddedWorkerTestHelper::OnResumeAfterDownload,
+ AsWeakPtr(), embedded_worker_id));
}
void EmbeddedWorkerTestHelper::OnStopWorkerStub(int embedded_worker_id) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&EmbeddedWorkerTestHelper::OnStopWorker,
- AsWeakPtr(), embedded_worker_id));
+ FROM_HERE, base::BindOnce(&EmbeddedWorkerTestHelper::OnStopWorker,
+ AsWeakPtr(), embedded_worker_id));
}
void EmbeddedWorkerTestHelper::OnMessageToWorkerStub(
@@ -675,8 +796,8 @@ void EmbeddedWorkerTestHelper::OnActivateEventStub(
mojom::ServiceWorkerEventDispatcher::DispatchActivateEventCallback
callback) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&EmbeddedWorkerTestHelper::OnActivateEvent,
- AsWeakPtr(), base::Passed(&callback)));
+ FROM_HERE, base::BindOnce(&EmbeddedWorkerTestHelper::OnActivateEvent,
+ AsWeakPtr(), base::Passed(&callback)));
}
void EmbeddedWorkerTestHelper::OnBackgroundFetchAbortEventStub(
@@ -685,8 +806,8 @@ void EmbeddedWorkerTestHelper::OnBackgroundFetchAbortEventStub(
DispatchBackgroundFetchAbortEventCallback callback) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
- base::Bind(&EmbeddedWorkerTestHelper::OnBackgroundFetchAbortEvent,
- AsWeakPtr(), tag, base::Passed(&callback)));
+ base::BindOnce(&EmbeddedWorkerTestHelper::OnBackgroundFetchAbortEvent,
+ AsWeakPtr(), tag, base::Passed(&callback)));
}
void EmbeddedWorkerTestHelper::OnBackgroundFetchClickEventStub(
@@ -696,8 +817,8 @@ void EmbeddedWorkerTestHelper::OnBackgroundFetchClickEventStub(
DispatchBackgroundFetchClickEventCallback callback) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
- base::Bind(&EmbeddedWorkerTestHelper::OnBackgroundFetchClickEvent,
- AsWeakPtr(), tag, state, base::Passed(&callback)));
+ base::BindOnce(&EmbeddedWorkerTestHelper::OnBackgroundFetchClickEvent,
+ AsWeakPtr(), tag, state, base::Passed(&callback)));
}
void EmbeddedWorkerTestHelper::OnBackgroundFetchFailEventStub(
@@ -707,8 +828,8 @@ void EmbeddedWorkerTestHelper::OnBackgroundFetchFailEventStub(
DispatchBackgroundFetchFailEventCallback callback) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
- base::Bind(&EmbeddedWorkerTestHelper::OnBackgroundFetchFailEvent,
- AsWeakPtr(), tag, fetches, base::Passed(&callback)));
+ base::BindOnce(&EmbeddedWorkerTestHelper::OnBackgroundFetchFailEvent,
+ AsWeakPtr(), tag, fetches, base::Passed(&callback)));
}
void EmbeddedWorkerTestHelper::OnBackgroundFetchedEventStub(
@@ -718,8 +839,8 @@ void EmbeddedWorkerTestHelper::OnBackgroundFetchedEventStub(
callback) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
- base::Bind(&EmbeddedWorkerTestHelper::OnBackgroundFetchedEvent,
- AsWeakPtr(), tag, fetches, base::Passed(&callback)));
+ base::BindOnce(&EmbeddedWorkerTestHelper::OnBackgroundFetchedEvent,
+ AsWeakPtr(), tag, fetches, base::Passed(&callback)));
}
void EmbeddedWorkerTestHelper::OnExtendableMessageEventStub(
@@ -728,8 +849,9 @@ void EmbeddedWorkerTestHelper::OnExtendableMessageEventStub(
callback) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
- base::Bind(&EmbeddedWorkerTestHelper::OnExtendableMessageEvent,
- AsWeakPtr(), base::Passed(&event), base::Passed(&callback)));
+ base::BindOnce(&EmbeddedWorkerTestHelper::OnExtendableMessageEvent,
+ AsWeakPtr(), base::Passed(&event),
+ base::Passed(&callback)));
}
void EmbeddedWorkerTestHelper::OnInstallEventStub(
@@ -738,8 +860,8 @@ void EmbeddedWorkerTestHelper::OnInstallEventStub(
callback) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
- base::Bind(&EmbeddedWorkerTestHelper::OnInstallEvent, AsWeakPtr(),
- base::Passed(&client), base::Passed(&callback)));
+ base::BindOnce(&EmbeddedWorkerTestHelper::OnInstallEvent, AsWeakPtr(),
+ base::Passed(&client), base::Passed(&callback)));
}
void EmbeddedWorkerTestHelper::OnFetchEventStub(
@@ -751,11 +873,11 @@ void EmbeddedWorkerTestHelper::OnFetchEventStub(
FetchCallback finish_callback) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
- base::Bind(&EmbeddedWorkerTestHelper::OnFetchEvent, AsWeakPtr(),
- thread_id_embedded_worker_id_map_[thread_id], fetch_event_id,
- request, base::Passed(&preload_handle),
- base::Passed(&response_callback),
- base::Passed(&finish_callback)));
+ base::BindOnce(&EmbeddedWorkerTestHelper::OnFetchEvent, AsWeakPtr(),
+ thread_id_embedded_worker_id_map_[thread_id],
+ fetch_event_id, request, base::Passed(&preload_handle),
+ base::Passed(&response_callback),
+ base::Passed(&finish_callback)));
}
void EmbeddedWorkerTestHelper::OnNotificationClickEventStub(
@@ -766,9 +888,10 @@ void EmbeddedWorkerTestHelper::OnNotificationClickEventStub(
mojom::ServiceWorkerEventDispatcher::DispatchNotificationClickEventCallback
callback) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&EmbeddedWorkerTestHelper::OnNotificationClickEvent,
- AsWeakPtr(), notification_id, notification_data,
- action_index, reply, base::Passed(&callback)));
+ FROM_HERE,
+ base::BindOnce(&EmbeddedWorkerTestHelper::OnNotificationClickEvent,
+ AsWeakPtr(), notification_id, notification_data,
+ action_index, reply, base::Passed(&callback)));
}
void EmbeddedWorkerTestHelper::OnNotificationCloseEventStub(
@@ -777,17 +900,41 @@ void EmbeddedWorkerTestHelper::OnNotificationCloseEventStub(
mojom::ServiceWorkerEventDispatcher::DispatchNotificationCloseEventCallback
callback) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&EmbeddedWorkerTestHelper::OnNotificationCloseEvent,
- AsWeakPtr(), notification_id, notification_data,
- base::Passed(&callback)));
+ FROM_HERE,
+ base::BindOnce(&EmbeddedWorkerTestHelper::OnNotificationCloseEvent,
+ AsWeakPtr(), notification_id, notification_data,
+ base::Passed(&callback)));
}
void EmbeddedWorkerTestHelper::OnPushEventStub(
const PushEventPayload& payload,
mojom::ServiceWorkerEventDispatcher::DispatchPushEventCallback callback) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&EmbeddedWorkerTestHelper::OnPushEvent, AsWeakPtr(),
- payload, base::Passed(&callback)));
+ FROM_HERE, base::BindOnce(&EmbeddedWorkerTestHelper::OnPushEvent,
+ AsWeakPtr(), payload, base::Passed(&callback)));
+}
+
+void EmbeddedWorkerTestHelper::OnAbortPaymentEventStub(
+ payments::mojom::PaymentHandlerResponseCallbackPtr response_callback,
+ mojom::ServiceWorkerEventDispatcher::DispatchAbortPaymentEventCallback
+ callback) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(&EmbeddedWorkerTestHelper::OnAbortPaymentEvent,
+ AsWeakPtr(), base::Passed(&response_callback),
+ base::Passed(&callback)));
+}
+
+void EmbeddedWorkerTestHelper::OnCanMakePaymentEventStub(
+ payments::mojom::CanMakePaymentEventDataPtr event_data,
+ payments::mojom::PaymentHandlerResponseCallbackPtr response_callback,
+ mojom::ServiceWorkerEventDispatcher::DispatchCanMakePaymentEventCallback
+ callback) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&EmbeddedWorkerTestHelper::OnCanMakePaymentEvent,
+ AsWeakPtr(), base::Passed(&event_data),
+ base::Passed(&response_callback),
+ base::Passed(&callback)));
}
void EmbeddedWorkerTestHelper::OnPaymentRequestEventStub(
@@ -797,9 +944,10 @@ void EmbeddedWorkerTestHelper::OnPaymentRequestEventStub(
callback) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
- base::Bind(&EmbeddedWorkerTestHelper::OnPaymentRequestEvent, AsWeakPtr(),
- base::Passed(&event_data), base::Passed(&response_callback),
- base::Passed(&callback)));
+ base::BindOnce(&EmbeddedWorkerTestHelper::OnPaymentRequestEvent,
+ AsWeakPtr(), base::Passed(&event_data),
+ base::Passed(&response_callback),
+ base::Passed(&callback)));
}
EmbeddedWorkerRegistry* EmbeddedWorkerTestHelper::registry() {
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 e85d6e85095..ee99525689b 100644
--- a/chromium/content/browser/service_worker/embedded_worker_test_helper.h
+++ b/chromium/content/browser/service_worker/embedded_worker_test_helper.h
@@ -24,7 +24,7 @@
#include "content/common/service_worker/service_worker_status_code.h"
#include "ipc/ipc_listener.h"
#include "ipc/ipc_test_sink.h"
-#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/associated_binding.h"
#include "net/http/http_response_info.h"
#include "url/gurl.h"
@@ -59,7 +59,6 @@ struct ServiceWorkerFetchRequest;
// methods to add their own logic/verification code.
//
// See embedded_worker_instance_unittest.cc for example usages.
-//
class EmbeddedWorkerTestHelper : public IPC::Sender,
public IPC::Listener {
public:
@@ -75,8 +74,9 @@ class EmbeddedWorkerTestHelper : public IPC::Sender,
base::WeakPtr<EmbeddedWorkerTestHelper> helper);
~MockEmbeddedWorkerInstanceClient() override;
- static void Bind(const base::WeakPtr<EmbeddedWorkerTestHelper>& helper,
- mojo::ScopedMessagePipeHandle request);
+ static void Bind(
+ const base::WeakPtr<EmbeddedWorkerTestHelper>& helper,
+ mojom::EmbeddedWorkerInstanceClientAssociatedRequest request);
protected:
// mojom::EmbeddedWorkerInstanceClient implementation.
@@ -84,7 +84,9 @@ class EmbeddedWorkerTestHelper : public IPC::Sender,
const EmbeddedWorkerStartParams& params,
mojom::ServiceWorkerEventDispatcherRequest dispatcher_request,
mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info,
- mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host)
+ mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
+ mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info,
+ blink::mojom::WorkerContentSettingsProxyPtr content_settings_proxy)
override;
void StopWorker() override;
void ResumeAfterDownload() override;
@@ -92,7 +94,7 @@ class EmbeddedWorkerTestHelper : public IPC::Sender,
const std::string& message) override;
base::WeakPtr<EmbeddedWorkerTestHelper> helper_;
- mojo::Binding<mojom::EmbeddedWorkerInstanceClient> binding_;
+ mojo::AssociatedBinding<mojom::EmbeddedWorkerInstanceClient> binding_;
base::Optional<int> embedded_worker_id_;
@@ -115,7 +117,7 @@ class EmbeddedWorkerTestHelper : public IPC::Sender,
// IPC::Listener implementation.
bool OnMessageReceived(const IPC::Message& msg) override;
- // Register a mojo endpoint object derived from
+ // Registers a Mojo endpoint object derived from
// MockEmbeddedWorkerInstanceClient.
void RegisterMockInstanceClient(
std::unique_ptr<MockEmbeddedWorkerInstanceClient> client);
@@ -148,7 +150,6 @@ class EmbeddedWorkerTestHelper : public IPC::Sender,
void ShutdownContext();
int GetNextThreadId() { return next_thread_id_++; }
- int GetNextProviderId() { return next_provider_id_++; }
int mock_render_process_id() const { return mock_render_process_id_; }
MockRenderProcessHost* mock_render_process_host() {
@@ -164,6 +165,8 @@ class EmbeddedWorkerTestHelper : public IPC::Sender,
TestBrowserContext* browser_context() { return browser_context_.get(); }
+ ServiceWorkerDispatcherHost* GetDispatcherHostForProcess(int process_id);
+
base::WeakPtr<EmbeddedWorkerTestHelper> AsWeakPtr() {
return weak_factory_.GetWeakPtr();
}
@@ -181,7 +184,8 @@ class EmbeddedWorkerTestHelper : public IPC::Sender,
const GURL& script_url,
bool pause_after_download,
mojom::ServiceWorkerEventDispatcherRequest request,
- mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host);
+ mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
+ mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info);
virtual void OnResumeAfterDownload(int embedded_worker_id);
// StopWorker IPC handler routed through MockEmbeddedWorkerInstanceClient.
// This calls SimulateWorkerStopped() by default.
@@ -241,6 +245,15 @@ class EmbeddedWorkerTestHelper : public IPC::Sender,
virtual void OnPushEvent(
const PushEventPayload& payload,
mojom::ServiceWorkerEventDispatcher::DispatchPushEventCallback callback);
+ virtual void OnAbortPaymentEvent(
+ payments::mojom::PaymentHandlerResponseCallbackPtr response_callback,
+ mojom::ServiceWorkerEventDispatcher::DispatchAbortPaymentEventCallback
+ callback);
+ virtual void OnCanMakePaymentEvent(
+ payments::mojom::CanMakePaymentEventDataPtr data,
+ payments::mojom::PaymentHandlerResponseCallbackPtr response_callback,
+ mojom::ServiceWorkerEventDispatcher::DispatchCanMakePaymentEventCallback
+ callback);
virtual void OnPaymentRequestEvent(
payments::mojom::PaymentRequestEventDataPtr data,
payments::mojom::PaymentHandlerResponseCallbackPtr response_callback,
@@ -252,9 +265,7 @@ class EmbeddedWorkerTestHelper : public IPC::Sender,
void SimulateWorkerReadyForInspection(int embedded_worker_id);
void SimulateWorkerScriptCached(int embedded_worker_id);
void SimulateWorkerScriptLoaded(int embedded_worker_id);
- void SimulateWorkerThreadStarted(int thread_id,
- int embedded_worker_id,
- int provider_id);
+ void SimulateWorkerThreadStarted(int thread_id, int embedded_worker_id);
void SimulateWorkerScriptEvaluated(int embedded_worker_id, bool success);
void SimulateWorkerStarted(int embedded_worker_id);
void SimulateWorkerStopped(int embedded_worker_id);
@@ -264,11 +275,13 @@ class EmbeddedWorkerTestHelper : public IPC::Sender,
private:
class MockServiceWorkerEventDispatcher;
+ class MockRendererInterface;
void OnStartWorkerStub(
const EmbeddedWorkerStartParams& params,
mojom::ServiceWorkerEventDispatcherRequest request,
- mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host);
+ mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
+ mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info);
void OnResumeAfterDownloadStub(int embedded_worker_id);
void OnStopWorkerStub(int embedded_worker_id);
void OnMessageToWorkerStub(int thread_id,
@@ -326,6 +339,15 @@ class EmbeddedWorkerTestHelper : public IPC::Sender,
void OnPushEventStub(
const PushEventPayload& payload,
mojom::ServiceWorkerEventDispatcher::DispatchPushEventCallback callback);
+ void OnAbortPaymentEventStub(
+ payments::mojom::PaymentHandlerResponseCallbackPtr response_callback,
+ mojom::ServiceWorkerEventDispatcher::DispatchAbortPaymentEventCallback
+ callback);
+ void OnCanMakePaymentEventStub(
+ payments::mojom::CanMakePaymentEventDataPtr data,
+ payments::mojom::PaymentHandlerResponseCallbackPtr response_callback,
+ mojom::ServiceWorkerEventDispatcher::DispatchCanMakePaymentEventCallback
+ callback);
void OnPaymentRequestEventStub(
payments::mojom::PaymentRequestEventDataPtr data,
payments::mojom::PaymentHandlerResponseCallbackPtr response_callback,
@@ -340,12 +362,12 @@ class EmbeddedWorkerTestHelper : public IPC::Sender,
IPC::TestSink sink_;
+ std::unique_ptr<MockRendererInterface> mock_renderer_interface_;
std::vector<std::unique_ptr<MockEmbeddedWorkerInstanceClient>>
mock_instance_clients_;
size_t mock_instance_clients_next_index_;
int next_thread_id_;
- int next_provider_id_;
int mock_render_process_id_;
int new_mock_render_process_id_;
diff --git a/chromium/content/browser/service_worker/foreign_fetch_request_handler.cc b/chromium/content/browser/service_worker/foreign_fetch_request_handler.cc
index f358e13ee15..da36f683986 100644
--- a/chromium/content/browser/service_worker/foreign_fetch_request_handler.cc
+++ b/chromium/content/browser/service_worker/foreign_fetch_request_handler.cc
@@ -270,7 +270,7 @@ void ForeignFetchRequestHandler::DidFindRegistration(
web_contents_getter = request_info->GetWebContentsGetterForRequest();
if (!GetContentClient()->browser()->AllowServiceWorker(
- registration->pattern(), job->request()->first_party_for_cookies(),
+ registration->pattern(), job->request()->site_for_cookies(),
resource_context_, web_contents_getter)) {
job->FallbackToNetwork();
return;
diff --git a/chromium/content/browser/service_worker/foreign_fetch_request_handler_unittest.cc b/chromium/content/browser/service_worker/foreign_fetch_request_handler_unittest.cc
index 5a71f324f7f..5f6382b7aee 100644
--- a/chromium/content/browser/service_worker/foreign_fetch_request_handler_unittest.cc
+++ b/chromium/content/browser/service_worker/foreign_fetch_request_handler_unittest.cc
@@ -6,6 +6,7 @@
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
+#include "base/test/simple_test_clock.h"
#include "base/test/simple_test_tick_clock.h"
#include "content/browser/browser_thread_impl.h"
#include "content/browser/service_worker/embedded_worker_test_helper.h"
@@ -50,6 +51,10 @@ int kMockProviderId = 1;
const char* kValidUrl = "https://valid.example.com/foo/bar";
+// This timestamp is set to a time after the expiry timestamp of the expired
+// tokens in this test, but before the expiry timestamp of the valid ones.
+double kNowTimestamp = 1500000000;
+
void EmptyCallback() {}
} // namespace
@@ -79,6 +84,12 @@ class ForeignFetchRequestHandlerTest : public testing::Test {
kVersionId, context()->AsWeakPtr());
version_->set_foreign_fetch_scopes({kScope});
+ // Fix the time for testing to kNowTimestamp
+ std::unique_ptr<base::SimpleTestClock> clock =
+ base::MakeUnique<base::SimpleTestClock>();
+ clock->SetNow(base::Time::FromDoubleT(kNowTimestamp));
+ version_->SetClockForTesting(std::move(clock));
+
context()->storage()->LazyInitialize(base::Bind(&EmptyCallback));
base::RunLoop().RunUntilIdle();
@@ -172,17 +183,6 @@ class ForeignFetchRequestHandlerTest : public testing::Test {
}
void CreateServiceWorkerTypeProviderHost() {
- remote_endpoints_.emplace_back();
- std::unique_ptr<ServiceWorkerProviderHost> host =
- CreateProviderHostForServiceWorkerContext(
- helper_->mock_render_process_id(), kMockProviderId,
- true /* is_parent_frame_secure */, helper_->context()->AsWeakPtr(),
- &remote_endpoints_.back());
- EXPECT_FALSE(
- context()->GetProviderHost(host->process_id(), host->provider_id()));
- provider_host_ = host->AsWeakPtr();
- context()->AddProviderHost(std::move(host));
-
// Create another worker whose requests will be intercepted by the foreign
// fetch event handler.
scoped_refptr<ServiceWorkerRegistration> registration =
@@ -206,7 +206,16 @@ class ForeignFetchRequestHandlerTest : public testing::Test {
base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
base::RunLoop().RunUntilIdle();
- provider_host_->running_hosted_version_ = version;
+ remote_endpoints_.emplace_back();
+ std::unique_ptr<ServiceWorkerProviderHost> host =
+ CreateProviderHostForServiceWorkerContext(
+ helper_->mock_render_process_id(),
+ true /* is_parent_frame_secure */, version.get(),
+ helper_->context()->AsWeakPtr(), &remote_endpoints_.back());
+ EXPECT_FALSE(
+ context()->GetProviderHost(host->process_id(), host->provider_id()));
+ provider_host_ = host->AsWeakPtr();
+ context()->AddProviderHost(std::move(host));
}
private:
diff --git a/chromium/content/browser/service_worker/link_header_support.cc b/chromium/content/browser/service_worker/link_header_support.cc
index 32ce5777969..d38fb21002f 100644
--- a/chromium/content/browser/service_worker/link_header_support.cc
+++ b/chromium/content/browser/service_worker/link_header_support.cc
@@ -7,6 +7,7 @@
#include "base/command_line.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
+#include "base/time/time.h"
#include "components/link_header_util/link_header_util.h"
#include "content/browser/loader/resource_message_filter.h"
#include "content/browser/loader/resource_request_info_impl.h"
@@ -42,7 +43,8 @@ void HandleServiceWorkerLink(
if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableExperimentalWebPlatformFeatures) &&
- !TrialTokenValidator::RequestEnablesFeature(request, "ForeignFetch")) {
+ !TrialTokenValidator::RequestEnablesFeature(request, "ForeignFetch",
+ base::Time::Now())) {
// TODO(mek): Log attempt to use without having correct token?
return;
}
@@ -109,8 +111,7 @@ void HandleServiceWorkerLink(
return;
if (!GetContentClient()->browser()->AllowServiceWorker(
- scope_url, request->first_party_for_cookies(),
- request_info->GetContext(),
+ scope_url, request->site_for_cookies(), request_info->GetContext(),
request_info->GetWebContentsGetterForRequest()))
return;
diff --git a/chromium/content/browser/service_worker/link_header_support_unittest.cc b/chromium/content/browser/service_worker/link_header_support_unittest.cc
index 5ea3f1dd2c9..3213df6a7d2 100644
--- a/chromium/content/browser/service_worker/link_header_support_unittest.cc
+++ b/chromium/content/browser/service_worker/link_header_support_unittest.cc
@@ -106,17 +106,6 @@ class LinkHeaderServiceWorkerTest : public ::testing::Test {
}
void CreateServiceWorkerProviderHost() {
- remote_endpoints_.emplace_back();
- std::unique_ptr<ServiceWorkerProviderHost> host =
- CreateProviderHostForServiceWorkerContext(
- render_process_id(), kMockProviderId,
- true /* is_parent_frame_secure */, context()->AsWeakPtr(),
- &remote_endpoints_.back());
- provider_host_ = host->AsWeakPtr();
- EXPECT_FALSE(
- context()->GetProviderHost(host->process_id(), host->provider_id()));
- context()->AddProviderHost(std::move(host));
-
scoped_refptr<ServiceWorkerRegistration> registration =
new ServiceWorkerRegistration(
ServiceWorkerRegistrationOptions(GURL("https://host/scope")), 1L,
@@ -125,7 +114,15 @@ class LinkHeaderServiceWorkerTest : public ::testing::Test {
registration.get(), GURL("https://host/script.js"), 1L,
context()->AsWeakPtr());
- provider_host_->running_hosted_version_ = version;
+ remote_endpoints_.emplace_back();
+ std::unique_ptr<ServiceWorkerProviderHost> host =
+ CreateProviderHostForServiceWorkerContext(
+ render_process_id(), true /* is_parent_frame_secure */,
+ version.get(), context()->AsWeakPtr(), &remote_endpoints_.back());
+ provider_host_ = host->AsWeakPtr();
+ EXPECT_FALSE(
+ context()->GetProviderHost(host->process_id(), host->provider_id()));
+ context()->AddProviderHost(std::move(host));
}
std::unique_ptr<net::URLRequest> CreateRequest(const GURL& request_url,
diff --git a/chromium/content/browser/service_worker/service_worker_browsertest.cc b/chromium/content/browser/service_worker/service_worker_browsertest.cc
index 5e8dc2f47ca..0efabf840a5 100644
--- a/chromium/content/browser/service_worker/service_worker_browsertest.cc
+++ b/chromium/content/browser/service_worker/service_worker_browsertest.cc
@@ -107,8 +107,8 @@ void RunOnIOThreadWithDelay(const base::Closure& closure,
base::RunLoop run_loop;
BrowserThread::PostDelayedTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&RunAndQuit, closure, run_loop.QuitClosure(),
- base::RetainedRef(base::ThreadTaskRunnerHandle::Get())),
+ base::BindOnce(&RunAndQuit, closure, run_loop.QuitClosure(),
+ base::RetainedRef(base::ThreadTaskRunnerHandle::Get())),
delay);
run_loop.Run();
}
@@ -125,9 +125,8 @@ void RunOnIOThread(
base::ThreadTaskRunnerHandle::Get().get(),
FROM_HERE,
run_loop.QuitClosure());
- BrowserThread::PostTask(BrowserThread::IO,
- FROM_HERE,
- base::Bind(closure, quit_on_original_thread));
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+ base::BindOnce(closure, quit_on_original_thread));
run_loop.Run();
}
@@ -190,9 +189,9 @@ class WorkerActivatedObserver
const ServiceWorkerVersion* version = context_->GetLiveVersion(version_id);
if (version->status() == ServiceWorkerVersion::ACTIVATED) {
context_->RemoveObserver(this);
- BrowserThread::PostTask(BrowserThread::UI,
- FROM_HERE,
- base::Bind(&WorkerActivatedObserver::Quit, this));
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&WorkerActivatedObserver::Quit, this));
}
}
void Wait() { run_loop_.Run(); }
@@ -485,8 +484,8 @@ class ConsoleListener : public EmbeddedWorkerInstance::Listener {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&ConsoleListener::OnReportConsoleMessageOnUI,
- base::Unretained(this), message));
+ base::BindOnce(&ConsoleListener::OnReportConsoleMessageOnUI,
+ base::Unretained(this), message));
}
void WaitForConsoleMessages(size_t expected_message_count) {
@@ -587,8 +586,8 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
base::RunLoop install_run_loop;
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&self::InstallOnIOThread, base::Unretained(this),
- install_run_loop.QuitClosure(), &status));
+ base::BindOnce(&self::InstallOnIOThread, base::Unretained(this),
+ install_run_loop.QuitClosure(), &status));
install_run_loop.Run();
ASSERT_EQ(expected_status, status);
@@ -597,8 +596,8 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
base::RunLoop stop_run_loop;
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&self::StopOnIOThread, base::Unretained(this),
- stop_run_loop.QuitClosure(), &status));
+ base::BindOnce(&self::StopOnIOThread, base::Unretained(this),
+ stop_run_loop.QuitClosure(), &status));
stop_run_loop.Run();
ASSERT_EQ(SERVICE_WORKER_OK, status);
}
@@ -610,8 +609,8 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
base::RunLoop run_loop;
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&self::ActivateOnIOThread, base::Unretained(this),
- run_loop.QuitClosure(), &status));
+ base::BindOnce(&self::ActivateOnIOThread, base::Unretained(this),
+ run_loop.QuitClosure(), &status));
run_loop.Run();
ASSERT_EQ(expected_status, status);
}
@@ -628,9 +627,9 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
base::RunLoop fetch_run_loop;
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&self::FetchOnIOThread, base::Unretained(this),
- fetch_run_loop.QuitClosure(), &prepare_result,
- &fetch_result));
+ base::BindOnce(&self::FetchOnIOThread, base::Unretained(this),
+ fetch_run_loop.QuitClosure(), &prepare_result,
+ &fetch_result));
fetch_run_loop.Run();
ASSERT_TRUE(prepare_result);
*result = fetch_result.result;
@@ -704,8 +703,8 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
base::RunLoop start_run_loop;
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&self::StartOnIOThread, base::Unretained(this),
- start_run_loop.QuitClosure(), &status));
+ base::BindOnce(&self::StartOnIOThread, base::Unretained(this),
+ start_run_loop.QuitClosure(), &status));
start_run_loop.Run();
ASSERT_EQ(expected_status, status);
}
@@ -716,8 +715,8 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
base::RunLoop stop_run_loop;
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&self::StopOnIOThread, base::Unretained(this),
- stop_run_loop.QuitClosure(), &status));
+ base::BindOnce(&self::StopOnIOThread, base::Unretained(this),
+ stop_run_loop.QuitClosure(), &status));
stop_run_loop.Run();
ASSERT_EQ(expected_status, status);
}
@@ -729,8 +728,8 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
base::RunLoop store_run_loop;
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&self::StoreOnIOThread, base::Unretained(this),
- store_run_loop.QuitClosure(), &status, version_id));
+ base::BindOnce(&self::StoreOnIOThread, base::Unretained(this),
+ store_run_loop.QuitClosure(), &status, version_id));
store_run_loop.Run();
ASSERT_EQ(expected_status, status);
@@ -746,9 +745,9 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
base::RunLoop run_loop;
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&self::FindRegistrationForIdOnIOThread,
- base::Unretained(this), run_loop.QuitClosure(), &status, id,
- origin));
+ base::BindOnce(&self::FindRegistrationForIdOnIOThread,
+ base::Unretained(this), run_loop.QuitClosure(), &status,
+ id, origin));
run_loop.Run();
ASSERT_EQ(expected_status, status);
}
@@ -789,8 +788,8 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
version_->SetStatus(ServiceWorkerVersion::INSTALLING);
version_->RunAfterStartWorker(
ServiceWorkerMetrics::EventType::INSTALL,
- base::Bind(&self::DispatchInstallEventOnIOThread,
- base::Unretained(this), done, result),
+ base::BindOnce(&self::DispatchInstallEventOnIOThread,
+ base::Unretained(this), done, result),
CreateReceiver(BrowserThread::UI, done, result));
}
@@ -804,8 +803,8 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
mojo::MakeRequest(&ptr_info);
version_->event_dispatcher()->DispatchInstallEvent(
std::move(ptr_info),
- base::Bind(&self::ReceiveInstallEventOnIOThread, base::Unretained(this),
- done, result, request_id));
+ base::BindOnce(&self::ReceiveInstallEventOnIOThread,
+ base::Unretained(this), done, result, request_id));
}
void ReceiveInstallEventOnIOThread(const base::Closure& done,
@@ -844,8 +843,8 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
registration_->SetActiveVersion(version_.get());
version_->RunAfterStartWorker(
ServiceWorkerMetrics::EventType::ACTIVATE,
- base::Bind(&self::DispatchActivateEventOnIOThread,
- base::Unretained(this), done, result),
+ base::BindOnce(&self::DispatchActivateEventOnIOThread,
+ base::Unretained(this), done, result),
CreateReceiver(BrowserThread::UI, done, result));
}
@@ -887,6 +886,7 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
ServiceWorkerFetchEventResult actual_result,
const ServiceWorkerResponse& actual_response,
blink::mojom::ServiceWorkerStreamHandlePtr /* stream */,
+ storage::mojom::BlobPtr /* blob */,
const scoped_refptr<ServiceWorkerVersion>& worker) {
ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
ASSERT_TRUE(fetch_dispatcher_);
@@ -937,8 +937,8 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, StartAndStop) {
base::RunLoop start_run_loop;
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&self::StartOnIOThread, base::Unretained(this),
- start_run_loop.QuitClosure(), &status));
+ base::BindOnce(&self::StartOnIOThread, base::Unretained(this),
+ start_run_loop.QuitClosure(), &status));
start_run_loop.Run();
ASSERT_EQ(SERVICE_WORKER_OK, status);
@@ -947,8 +947,8 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, StartAndStop) {
base::RunLoop stop_run_loop;
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&self::StopOnIOThread, base::Unretained(this),
- stop_run_loop.QuitClosure(), &status));
+ base::BindOnce(&self::StopOnIOThread, base::Unretained(this),
+ stop_run_loop.QuitClosure(), &status));
stop_run_loop.Run();
ASSERT_EQ(SERVICE_WORKER_OK, status);
}
@@ -1121,8 +1121,8 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
base::RunLoop install_run_loop;
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&self::InstallOnIOThread, base::Unretained(this),
- install_run_loop.QuitClosure(), &status));
+ base::BindOnce(&self::InstallOnIOThread, base::Unretained(this),
+ install_run_loop.QuitClosure(), &status));
install_run_loop.Run();
ASSERT_EQ(SERVICE_WORKER_ERROR_EVENT_WAITUNTIL_REJECTED, status);
@@ -1166,8 +1166,8 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, TimeoutStartingWorker) {
&wait_for_load));
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&self::StartOnIOThread, base::Unretained(this),
- start_run_loop.QuitClosure(), &status));
+ base::BindOnce(&self::StartOnIOThread, base::Unretained(this),
+ start_run_loop.QuitClosure(), &status));
load_run_loop.Run();
RunOnIOThread(base::Bind(&EmbeddedWorkerInstance::RemoveListener,
base::Unretained(version_->embedded_worker()),
@@ -1198,8 +1198,8 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, TimeoutWorkerInEvent) {
base::RunLoop start_run_loop;
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&self::StartOnIOThread, base::Unretained(this),
- start_run_loop.QuitClosure(), &status));
+ base::BindOnce(&self::StartOnIOThread, base::Unretained(this),
+ start_run_loop.QuitClosure(), &status));
start_run_loop.Run();
ASSERT_EQ(SERVICE_WORKER_OK, status);
@@ -1207,8 +1207,8 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, TimeoutWorkerInEvent) {
base::RunLoop install_run_loop;
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&self::InstallOnIOThread, base::Unretained(this),
- install_run_loop.QuitClosure(), &status));
+ base::BindOnce(&self::InstallOnIOThread, base::Unretained(this),
+ install_run_loop.QuitClosure(), &status));
// Simulate execution timeout. Use a delay to prevent killing the worker
// before it's started execution.
@@ -1552,12 +1552,6 @@ class ServiceWorkerNavigationPreloadTest : public ServiceWorkerBrowserTest {
ServiceWorkerBrowserTest::SetUpOnMainThread();
}
- void SetUpCommandLine(base::CommandLine* command_line) override {
- command_line->AppendSwitchASCII(
- switches::kEnableFeatures,
- features::kServiceWorkerNavigationPreload.name);
- }
-
protected:
static const std::string kNavigationPreloadHeaderName;
static const std::string kEnableNavigationPreloadScript;
@@ -2389,6 +2383,43 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest, ImportsBustMemcache) {
EXPECT_EQ(kExpectedNumResources, num_resources);
}
+// A listener that waits for the version to stop.
+class StopObserver : public ServiceWorkerVersion::Listener {
+ public:
+ explicit StopObserver(const base::Closure& quit_closure)
+ : quit_closure_(quit_closure) {}
+
+ void OnRunningStateChanged(ServiceWorkerVersion* version) override {
+ if (version->running_status() == EmbeddedWorkerStatus::STOPPED)
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, quit_closure_);
+ }
+
+ private:
+ base::Closure quit_closure_;
+};
+
+IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, RendererCrash) {
+ // Start a worker.
+ StartServerAndNavigateToSetup();
+ RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread,
+ base::Unretained(this),
+ "/service_worker/worker.js"));
+ StartWorker(SERVICE_WORKER_OK);
+
+ // Crash the renderer process. The version should stop.
+ base::RunLoop run_loop;
+ StopObserver observer(run_loop.QuitClosure());
+ RunOnIOThread(base::Bind(&ServiceWorkerVersion::AddListener,
+ base::Unretained(version_.get()), &observer));
+ shell()->web_contents()->GetRenderProcessHost()->Shutdown(
+ content::RESULT_CODE_KILLED, false /* wait */);
+ run_loop.Run();
+
+ EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, version_->running_status());
+ RunOnIOThread(base::Bind(&ServiceWorkerVersion::RemoveListener,
+ base::Unretained(version_.get()), &observer));
+}
+
class ServiceWorkerBlackBoxBrowserTest : public ServiceWorkerBrowserTest {
public:
using self = ServiceWorkerBlackBoxBrowserTest;
@@ -2628,8 +2659,9 @@ class CacheStorageSideDataSizeChecker
void OpenCacheOnIOThread(int* result, const base::Closure& continuation) {
cache_storage_context_->cache_manager()->OpenCache(
- origin_, cache_name_, base::Bind(&self::OnCacheStorageOpenCallback,
- this, result, continuation));
+ origin_, cache_name_,
+ base::BindOnce(&self::OnCacheStorageOpenCallback, this, result,
+ continuation));
}
void OnCacheStorageOpenCallback(
@@ -2644,8 +2676,8 @@ class CacheStorageSideDataSizeChecker
CacheStorageCache* cache = cache_handle->value();
cache->Match(
std::move(scoped_request), CacheStorageCacheQueryParams(),
- base::Bind(&self::OnCacheStorageCacheMatchCallback, this, result,
- continuation, base::Passed(std::move(cache_handle))));
+ base::BindOnce(&self::OnCacheStorageCacheMatchCallback, this, result,
+ continuation, base::Passed(std::move(cache_handle))));
}
void OnCacheStorageCacheMatchCallback(
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 3a9318b83fc..7154406d8da 100644
--- a/chromium/content/browser/service_worker/service_worker_client_utils.cc
+++ b/chromium/content/browser/service_worker/service_worker_client_utils.cc
@@ -94,7 +94,7 @@ class OpenURLObserver : public WebContentsObserver {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(callback_, render_process_id, render_frame_id));
+ base::BindOnce(callback_, render_process_id, render_frame_id));
Observe(nullptr);
base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this);
}
@@ -165,8 +165,8 @@ void DidOpenURLOnUI(const OpenURLCallback& callback,
if (!web_contents) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(callback, ChildProcessHost::kInvalidUniqueID,
- MSG_ROUTING_NONE));
+ base::BindOnce(callback, ChildProcessHost::kInvalidUniqueID,
+ MSG_ROUTING_NONE));
return;
}
@@ -205,8 +205,8 @@ void OpenWindowOnUI(
if (render_process_host->IsForGuestsOnly()) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(callback, ChildProcessHost::kInvalidUniqueID,
- MSG_ROUTING_NONE));
+ base::BindOnce(callback, ChildProcessHost::kInvalidUniqueID,
+ MSG_ROUTING_NONE));
return;
}
@@ -234,8 +234,8 @@ void NavigateClientOnUI(const GURL& url,
if (!rfhi || !web_contents) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(callback, ChildProcessHost::kInvalidUniqueID,
- MSG_ROUTING_NONE));
+ base::BindOnce(callback, ChildProcessHost::kInvalidUniqueID,
+ MSG_ROUTING_NONE));
return;
}
@@ -355,7 +355,7 @@ void OnGetWindowClientsOnUI(
}
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::Bind(callback, base::Passed(&clients)));
+ base::BindOnce(callback, base::Passed(&clients)));
}
struct ServiceWorkerClientInfoSort {
@@ -446,7 +446,7 @@ void GetWindowClients(const base::WeakPtr<ServiceWorkerVersion>& controller,
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(
+ base::BindOnce(
&OnGetWindowClientsOnUI, clients_info, controller->script_url(),
base::Bind(&DidGetWindowClients, controller, options, callback),
base::Passed(&clients)));
@@ -476,7 +476,7 @@ void OpenWindow(const GURL& url,
DCHECK_CURRENTLY_ON(BrowserThread::IO);
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(
+ base::BindOnce(
&OpenWindowOnUI, url, script_url, worker_process_id,
make_scoped_refptr(context->wrapper()), disposition,
base::Bind(&DidNavigate, context, script_url.GetOrigin(), callback)));
@@ -491,7 +491,7 @@ void NavigateClient(const GURL& url,
DCHECK_CURRENTLY_ON(BrowserThread::IO);
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(
+ base::BindOnce(
&NavigateClientOnUI, url, script_url, process_id, frame_id,
base::Bind(&DidNavigate, context, script_url.GetOrigin(), callback)));
}
@@ -523,7 +523,7 @@ void GetClient(ServiceWorkerProviderHost* provider_host,
base::TimeTicks(), provider_host->create_time(),
provider_host->client_type());
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::Bind(callback, client_info));
+ base::BindOnce(callback, client_info));
}
void GetClients(const base::WeakPtr<ServiceWorkerVersion>& controller,
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
new file mode 100644
index 00000000000..b8ac5b41c3b
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_content_settings_proxy_impl.cc
@@ -0,0 +1,51 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/service_worker/service_worker_content_settings_proxy_impl.h"
+
+#include "base/threading/thread.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/content_browser_client.h"
+#include "content/public/common/content_client.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
+
+namespace content {
+
+ServiceWorkerContentSettingsProxyImpl::ServiceWorkerContentSettingsProxyImpl(
+ const GURL& script_url,
+ base::WeakPtr<ServiceWorkerContextCore> context,
+ blink::mojom::WorkerContentSettingsProxyRequest request)
+ : origin_(script_url),
+ context_(context),
+ binding_(this, std::move(request)) {}
+
+ServiceWorkerContentSettingsProxyImpl::
+ ~ServiceWorkerContentSettingsProxyImpl() = default;
+
+void ServiceWorkerContentSettingsProxyImpl::AllowIndexedDB(
+ const base::string16& name,
+ AllowIndexedDBCallback callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ if (origin_.unique()) {
+ std::move(callback).Run(false);
+ return;
+ }
+ // |render_frames| is used to show UI for the frames affected by the
+ // content setting. However, service worker is not necessarily associated
+ // with frames or making the request on behalf of frames,
+ // so just pass an empty |render_frames|.
+ std::vector<std::pair<int, int>> render_frames;
+ std::move(callback).Run(GetContentClient()->browser()->AllowWorkerIndexedDB(
+ origin_.GetURL(), name, context_->wrapper()->resource_context(),
+ render_frames));
+}
+
+void ServiceWorkerContentSettingsProxyImpl::RequestFileSystemAccessSync(
+ RequestFileSystemAccessSyncCallback callback) {
+ mojo::ReportBadMessage(
+ "The FileSystem API is not exposed to service workers "
+ "but somehow a service worker requested access.");
+}
+
+} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_content_settings_proxy_impl.h b/chromium/content/browser/service_worker/service_worker_content_settings_proxy_impl.h
new file mode 100644
index 00000000000..ac195dff926
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_content_settings_proxy_impl.h
@@ -0,0 +1,50 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_CONTENT_SETTINGS_PROXY_IMPL_H_
+#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_CONTENT_SETTINGS_PROXY_IMPL_H_
+
+#include "content/browser/service_worker/service_worker_context_core.h"
+#include "content/browser/service_worker/service_worker_context_wrapper.h"
+#include "content/common/content_export.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "third_party/WebKit/public/web/worker_content_settings_proxy.mojom.h"
+#include "url/origin.h"
+
+namespace content {
+
+class ServiceWorkerContextCore;
+
+// ServiceWorkerContentSettingsProxyImpl passes content settings to its renderer
+// counterpart blink::ServiceWorkerContentSettingsProxy
+// Created on EmbeddedWorkerInstance::SendStartWorker() and connects to the
+// counterpart at the moment.
+// EmbeddedWorkerInstance owns this class, so the lifetime of this class is
+// strongly associated to it.
+class ServiceWorkerContentSettingsProxyImpl final
+ : public blink::mojom::WorkerContentSettingsProxy {
+ public:
+ ServiceWorkerContentSettingsProxyImpl(
+ const GURL& script_url,
+ base::WeakPtr<ServiceWorkerContextCore> context,
+ blink::mojom::WorkerContentSettingsProxyRequest request);
+
+ ~ServiceWorkerContentSettingsProxyImpl() override;
+
+ // blink::mojom::WorkerContentSettingsProxy implementation
+ void AllowIndexedDB(const base::string16& name,
+ AllowIndexedDBCallback callback) override;
+ void RequestFileSystemAccessSync(
+ RequestFileSystemAccessSyncCallback callback) override;
+
+ private:
+
+ const url::Origin origin_;
+ base::WeakPtr<ServiceWorkerContextCore> context_;
+ mojo::Binding<blink::mojom::WorkerContentSettingsProxy> binding_;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_CONTENT_SETTINGS_PROXY_IMPL_H_
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 748b18c9bc2..f7989d1441d 100644
--- a/chromium/content/browser/service_worker/service_worker_context_core.cc
+++ b/chromium/content/browser/service_worker/service_worker_context_core.cc
@@ -23,7 +23,6 @@
#include "content/browser/service_worker/embedded_worker_status.h"
#include "content/browser/service_worker/service_worker_context_core_observer.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
-#include "content/browser/service_worker/service_worker_database_task_manager.h"
#include "content/browser/service_worker/service_worker_dispatcher_host.h"
#include "content/browser/service_worker/service_worker_info.h"
#include "content/browser/service_worker/service_worker_job_coordinator.h"
@@ -237,8 +236,7 @@ bool ServiceWorkerContextCore::ProviderHostIterator::
ServiceWorkerContextCore::ServiceWorkerContextCore(
const base::FilePath& path,
- std::unique_ptr<ServiceWorkerDatabaseTaskManager> database_task_manager,
- const scoped_refptr<base::SingleThreadTaskRunner>& disk_cache_thread,
+ scoped_refptr<base::SequencedTaskRunner> database_task_runner,
storage::QuotaManagerProxy* quota_manager_proxy,
storage::SpecialStoragePolicy* special_storage_policy,
base::WeakPtr<storage::BlobStorageContext> blob_storage_context,
@@ -260,8 +258,8 @@ ServiceWorkerContextCore::ServiceWorkerContextCore(
// These get a WeakPtr from weak_factory_, so must be set after weak_factory_
// is initialized.
storage_ = ServiceWorkerStorage::Create(
- path, AsWeakPtr(), std::move(database_task_manager), disk_cache_thread,
- quota_manager_proxy, special_storage_policy);
+ path, AsWeakPtr(), std::move(database_task_runner), quota_manager_proxy,
+ special_storage_policy);
embedded_worker_registry_ = EmbeddedWorkerRegistry::Create(AsWeakPtr());
job_coordinator_.reset(new ServiceWorkerJobCoordinator(AsWeakPtr()));
}
@@ -314,14 +312,15 @@ ServiceWorkerDispatcherHost* ServiceWorkerContextCore::GetDispatcherHost(
}
void ServiceWorkerContextCore::RemoveDispatcherHost(int process_id) {
- DCHECK(dispatcher_hosts_.find(process_id) != dispatcher_hosts_.end());
- RemoveAllProviderHostsForProcess(process_id);
- embedded_worker_registry_->RemoveProcess(process_id);
+ // Temporary CHECK for debugging https://crbug.com/750267.
+ CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
dispatcher_hosts_.erase(process_id);
}
void ServiceWorkerContextCore::AddProviderHost(
std::unique_ptr<ServiceWorkerProviderHost> host) {
+ // Temporary CHECK for debugging https://crbug.com/750267.
+ CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
int process_id = host->process_id();
int provider_id = host->provider_id();
ProviderMap* map = GetProviderMapForProcess(process_id);
@@ -343,6 +342,8 @@ ServiceWorkerProviderHost* ServiceWorkerContextCore::GetProviderHost(
void ServiceWorkerContextCore::RemoveProviderHost(
int process_id, int provider_id) {
+ // Temporary CHECK for debugging https://crbug.com/750267.
+ CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
ProviderMap* map = GetProviderMapForProcess(process_id);
DCHECK(map);
map->Remove(provider_id);
@@ -350,18 +351,24 @@ void ServiceWorkerContextCore::RemoveProviderHost(
void ServiceWorkerContextCore::RemoveAllProviderHostsForProcess(
int process_id) {
+ // Temporary CHECK for debugging https://crbug.com/750267.
+ CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (providers_->Lookup(process_id))
providers_->Remove(process_id);
}
std::unique_ptr<ServiceWorkerContextCore::ProviderHostIterator>
ServiceWorkerContextCore::GetProviderHostIterator() {
+ // Temporary CHECK for debugging https://crbug.com/750267.
+ CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
return base::WrapUnique(new ProviderHostIterator(
providers_.get(), ProviderHostIterator::ProviderHostPredicate()));
}
std::unique_ptr<ServiceWorkerContextCore::ProviderHostIterator>
ServiceWorkerContextCore::GetClientProviderHostIterator(const GURL& origin) {
+ // Temporary CHECK for debugging https://crbug.com/750267.
+ CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
return base::WrapUnique(new ProviderHostIterator(
providers_.get(), base::Bind(IsSameOriginClientProviderHost, origin)));
}
@@ -374,8 +381,8 @@ void ServiceWorkerContextCore::HasMainFrameProviderHost(
providers_.get(), base::Bind(IsSameOriginWindowProviderHost, origin));
if (provider_host_iterator.IsAtEnd()) {
- base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- base::Bind(callback, false));
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(callback, false));
return;
}
@@ -489,9 +496,8 @@ void ServiceWorkerContextCore::DidGetAllRegistrationsForUnregisterForOrigin(
}
bool* overall_success = new bool(true);
base::Closure barrier = base::BarrierClosure(
- scopes.size(),
- base::Bind(
- &SuccessReportingCallback, base::Owned(overall_success), result));
+ scopes.size(), base::BindOnce(&SuccessReportingCallback,
+ base::Owned(overall_success), result));
for (const GURL& scope : scopes) {
UnregisterServiceWorker(
@@ -499,6 +505,13 @@ void ServiceWorkerContextCore::DidGetAllRegistrationsForUnregisterForOrigin(
}
}
+ServiceWorkerContextCore::ProviderMap*
+ServiceWorkerContextCore::GetProviderMapForProcess(int process_id) {
+ // Temporary CHECK for debugging https://crbug.com/750267.
+ CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ return providers_->Lookup(process_id);
+}
+
void ServiceWorkerContextCore::RegistrationComplete(
const GURL& pattern,
const ServiceWorkerContextCore::RegistrationCallback& callback,
@@ -668,7 +681,8 @@ void ServiceWorkerContextCore::ScheduleDeleteAndStartOver() const {
storage_->Disable();
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
- base::Bind(&ServiceWorkerContextWrapper::DeleteAndStartOver, wrapper_));
+ base::BindOnce(&ServiceWorkerContextWrapper::DeleteAndStartOver,
+ wrapper_));
}
void ServiceWorkerContextCore::DeleteAndStartOver(
@@ -918,15 +932,4 @@ void ServiceWorkerContextCore::OnRegistrationFinishedForCheckHasServiceWorker(
CheckFetchHandlerOfInstalledServiceWorker(callback, registration);
}
-void ServiceWorkerContextCore::BindWorkerFetchContext(
- int render_process_id,
- int service_worker_provider_id,
- mojom::ServiceWorkerWorkerClientAssociatedPtrInfo client_ptr_info) {
- ServiceWorkerProviderHost* provider_host =
- GetProviderHost(render_process_id, service_worker_provider_id);
- if (!provider_host)
- return;
- provider_host->BindWorkerFetchContext(std::move(client_ptr_info));
-}
-
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_context_core.h b/chromium/content/browser/service_worker/service_worker_context_core.h
index 037b04bd129..13b7414350e 100644
--- a/chromium/content/browser/service_worker/service_worker_context_core.h
+++ b/chromium/content/browser/service_worker/service_worker_context_core.h
@@ -13,8 +13,8 @@
#include <vector>
#include "base/callback.h"
+#include "base/containers/id_map.h"
#include "base/files/file_path.h"
-#include "base/id_map.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list_threadsafe.h"
@@ -24,14 +24,12 @@
#include "content/browser/service_worker/service_worker_registration_status.h"
#include "content/browser/service_worker/service_worker_storage.h"
#include "content/common/content_export.h"
-#include "content/common/worker_url_loader_factory_provider.mojom.h"
#include "content/public/browser/service_worker_context.h"
class GURL;
namespace base {
class FilePath;
-class SingleThreadTaskRunner;
}
namespace storage {
@@ -45,7 +43,6 @@ namespace content {
class EmbeddedWorkerRegistry;
class ServiceWorkerContextCoreObserver;
class ServiceWorkerContextWrapper;
-class ServiceWorkerDatabaseTaskManager;
class ServiceWorkerDispatcherHost;
class ServiceWorkerJobCoordinator;
class ServiceWorkerNavigationHandleCore;
@@ -60,7 +57,7 @@ class URLLoaderFactoryGetter;
// is the root of the containment hierarchy for service worker data
// associated with a particular partition.
class CONTENT_EXPORT ServiceWorkerContextCore
- : NON_EXPORTED_BASE(public ServiceWorkerVersion::Listener) {
+ : public ServiceWorkerVersion::Listener {
public:
using BoolCallback = base::Callback<void(bool)>;
using StatusCallback = base::Callback<void(ServiceWorkerStatusCode status)>;
@@ -73,8 +70,8 @@ class CONTENT_EXPORT ServiceWorkerContextCore
int64_t registration_id)>;
using UnregistrationCallback =
base::Callback<void(ServiceWorkerStatusCode status)>;
- using ProviderMap = IDMap<std::unique_ptr<ServiceWorkerProviderHost>>;
- using ProcessToProviderMap = IDMap<std::unique_ptr<ProviderMap>>;
+ using ProviderMap = base::IDMap<std::unique_ptr<ServiceWorkerProviderHost>>;
+ using ProcessToProviderMap = base::IDMap<std::unique_ptr<ProviderMap>>;
using ProviderByClientUUIDMap =
std::map<std::string, ServiceWorkerProviderHost*>;
@@ -117,9 +114,7 @@ class CONTENT_EXPORT ServiceWorkerContextCore
// when IsServicificationEnabled is true.
ServiceWorkerContextCore(
const base::FilePath& user_data_directory,
- std::unique_ptr<ServiceWorkerDatabaseTaskManager>
- database_task_runner_manager,
- const scoped_refptr<base::SingleThreadTaskRunner>& disk_cache_thread,
+ scoped_refptr<base::SequencedTaskRunner> database_task_runner,
storage::QuotaManagerProxy* quota_manager_proxy,
storage::SpecialStoragePolicy* special_storage_policy,
base::WeakPtr<storage::BlobStorageContext> blob_context,
@@ -303,14 +298,6 @@ class CONTENT_EXPORT ServiceWorkerContextCore
// version. The count resets to zero when the worker successfully starts.
int GetVersionFailureCount(int64_t version_id);
- // Binds the ServiceWorkerWorkerClient of a dedicated (or shared) worker to
- // the parent frame's ServiceWorkerProviderHost. (This is used only when
- // off-main-thread-fetch is enabled.)
- void BindWorkerFetchContext(
- int render_process_id,
- int service_worker_provider_id,
- mojom::ServiceWorkerWorkerClientAssociatedPtrInfo client_ptr_info);
-
base::WeakPtr<storage::BlobStorageContext> blob_storage_context() {
return blob_storage_context_;
}
@@ -335,9 +322,7 @@ class CONTENT_EXPORT ServiceWorkerContextCore
ServiceWorkerStatusCode last_failure;
};
- ProviderMap* GetProviderMapForProcess(int process_id) {
- return providers_->Lookup(process_id);
- }
+ ProviderMap* GetProviderMapForProcess(int process_id);
void RegistrationComplete(const GURL& pattern,
const RegistrationCallback& callback,
diff --git a/chromium/content/browser/service_worker/service_worker_context_core_observer.h b/chromium/content/browser/service_worker/service_worker_context_core_observer.h
index 2a607717c42..e8bf1086848 100644
--- a/chromium/content/browser/service_worker/service_worker_context_core_observer.h
+++ b/chromium/content/browser/service_worker/service_worker_context_core_observer.h
@@ -29,6 +29,11 @@ class ServiceWorkerContextCoreObserver {
line_number(line),
column_number(column),
source_url(url) {}
+ ErrorInfo(const ErrorInfo& info)
+ : error_message(info.error_message),
+ line_number(info.line_number),
+ column_number(info.column_number),
+ source_url(info.source_url) {}
const base::string16 error_message;
const int line_number;
const int column_number;
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 13b0f6b9b39..4b3535aa5b9 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
@@ -21,26 +21,6 @@
namespace content {
-namespace {
-
-bool IsInstalled(const ServiceWorkerVersion* version) {
- switch (version->status()) {
- case ServiceWorkerVersion::NEW:
- case ServiceWorkerVersion::INSTALLING:
- return false;
- case ServiceWorkerVersion::INSTALLED:
- case ServiceWorkerVersion::ACTIVATING:
- case ServiceWorkerVersion::ACTIVATED:
- return true;
- case ServiceWorkerVersion::REDUNDANT:
- return false;
- }
- NOTREACHED();
- return false;
-}
-
-} // namespace
-
ServiceWorkerContextRequestHandler::ServiceWorkerContextRequestHandler(
base::WeakPtr<ServiceWorkerContextCore> context,
base::WeakPtr<ServiceWorkerProviderHost> provider_host,
@@ -110,7 +90,8 @@ net::URLRequestJob* ServiceWorkerContextRequestHandler::MaybeCreateJob(
MaybeCreateJobImpl(request, network_delegate, &status);
const bool is_main_script = resource_type_ == RESOURCE_TYPE_SERVICE_WORKER;
ServiceWorkerMetrics::RecordContextRequestHandlerStatus(
- status, IsInstalled(version_.get()), is_main_script);
+ status, ServiceWorkerVersion::IsInstalled(version_->status()),
+ is_main_script);
if (job)
return job;
@@ -171,7 +152,7 @@ net::URLRequestJob* ServiceWorkerContextRequestHandler::MaybeCreateJobImpl(
int resource_id =
version_->script_cache_map()->LookupResourceId(request->url());
if (resource_id != kInvalidServiceWorkerResourceId) {
- if (IsInstalled(version_.get())) {
+ if (ServiceWorkerVersion::IsInstalled(version_->status())) {
// An installed worker is loading a stored script.
if (is_main_script)
version_->embedded_worker()->OnURLJobCreatedForMainScript();
@@ -187,7 +168,7 @@ net::URLRequestJob* ServiceWorkerContextRequestHandler::MaybeCreateJobImpl(
}
// An installed worker is importing a non-stored script.
- if (IsInstalled(version_.get())) {
+ if (ServiceWorkerVersion::IsInstalled(version_->status())) {
DCHECK(!is_main_script);
*out_status = CreateJobStatus::ERROR_UNINSTALLED_SCRIPT_IMPORT;
return nullptr;
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 a4c656cfeed..87d418f020f 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
@@ -90,12 +90,11 @@ class ServiceWorkerContextRequestHandlerTest : public testing::Test {
void SetUpProvider() {
std::unique_ptr<ServiceWorkerProviderHost> host =
CreateProviderHostForServiceWorkerContext(
- helper_->mock_render_process_id(), 1 /* provider_id */,
- true /* is_parent_frame_secure */, context()->AsWeakPtr(),
- &remote_endpoint_);
+ helper_->mock_render_process_id(),
+ true /* is_parent_frame_secure */, version_.get(),
+ context()->AsWeakPtr(), &remote_endpoint_);
provider_host_ = host->AsWeakPtr();
context()->AddProviderHost(std::move(host));
- provider_host_->running_hosted_version_ = version_;
}
std::unique_ptr<net::URLRequest> CreateRequest(const GURL& url) {
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 e11bbdc4352..faf861b8f90 100644
--- a/chromium/content/browser/service_worker/service_worker_context_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_context_unittest.cc
@@ -10,6 +10,7 @@
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
#include "base/time/time.h"
#include "content/browser/browser_thread_impl.h"
#include "content/browser/service_worker/embedded_worker_registry.h"
@@ -21,6 +22,7 @@
#include "content/browser/service_worker/service_worker_registration.h"
#include "content/browser/service_worker/service_worker_storage.h"
#include "content/browser/service_worker/service_worker_test_utils.h"
+#include "content/browser/service_worker/service_worker_version.h"
#include "content/common/service_worker/embedded_worker_messages.h"
#include "content/common/service_worker/service_worker_messages.h"
#include "content/public/test/test_browser_thread_bundle.h"
@@ -178,15 +180,19 @@ class RecordableEmbeddedWorkerInstanceClient
const std::vector<Message>& events() const { return events_; }
protected:
- void StartWorker(const EmbeddedWorkerStartParams& params,
- mojom::ServiceWorkerEventDispatcherRequest request,
- mojom::ServiceWorkerInstalledScriptsInfoPtr scripts_info,
- mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo
- instance_host) override {
+ void StartWorker(
+ const EmbeddedWorkerStartParams& params,
+ mojom::ServiceWorkerEventDispatcherRequest request,
+ mojom::ServiceWorkerInstalledScriptsInfoPtr scripts_info,
+ mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
+ mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info,
+ blink::mojom::WorkerContentSettingsProxyPtr content_settings_proxy)
+ override {
events_.push_back(Message::StartWorker);
EmbeddedWorkerTestHelper::MockEmbeddedWorkerInstanceClient::StartWorker(
params, std::move(request), std::move(scripts_info),
- std::move(instance_host));
+ std::move(instance_host), std::move(provider_info),
+ std::move(content_settings_proxy));
}
void StopWorker() override {
@@ -220,15 +226,13 @@ TEST_F(ServiceWorkerContextTest, Register) {
EXPECT_TRUE(called);
ASSERT_EQ(2UL, helper_->dispatched_events()->size());
- ASSERT_EQ(2UL, client->events().size());
+ ASSERT_EQ(1UL, client->events().size());
EXPECT_EQ(RecordableEmbeddedWorkerInstanceClient::Message::StartWorker,
client->events()[0]);
EXPECT_EQ(EmbeddedWorkerTestHelper::Event::Install,
helper_->dispatched_events()->at(0));
EXPECT_EQ(EmbeddedWorkerTestHelper::Event::Activate,
helper_->dispatched_events()->at(1));
- EXPECT_EQ(RecordableEmbeddedWorkerInstanceClient::Message::StopWorker,
- client->events()[1]);
EXPECT_NE(kInvalidServiceWorkerRegistrationId, registration_id);
@@ -323,15 +327,13 @@ TEST_F(ServiceWorkerContextTest, Register_RejectActivate) {
EXPECT_TRUE(called);
ASSERT_EQ(2UL, helper_->dispatched_events()->size());
- ASSERT_EQ(2UL, client->events().size());
+ ASSERT_EQ(1UL, client->events().size());
EXPECT_EQ(RecordableEmbeddedWorkerInstanceClient::Message::StartWorker,
client->events()[0]);
EXPECT_EQ(EmbeddedWorkerTestHelper::Event::Install,
helper_->dispatched_events()->at(0));
EXPECT_EQ(EmbeddedWorkerTestHelper::Event::Activate,
helper_->dispatched_events()->at(1));
- EXPECT_EQ(RecordableEmbeddedWorkerInstanceClient::Message::StopWorker,
- client->events()[1]);
EXPECT_NE(kInvalidServiceWorkerRegistrationId, registration_id);
@@ -596,13 +598,30 @@ TEST_F(ServiceWorkerContextTest, ProviderHostIterator) {
context()->AsWeakPtr(), &remote_endpoints.back());
host3->SetDocumentUrl(kOrigin1);
- // Host4 (provider_id=4): process_id=2, origin2, for ServiceWorker.
+ // Host4 (provider_id < -1): process_id=2, origin2, for ServiceWorker.
+ // Since the provider host is created via
+ // CreateProviderHostForServiceWorkerContext, the provider_id is not a fixed
+ // number.
+ ServiceWorkerRegistrationOptions registration_opt(
+ GURL("http://www.example.com/test/"));
+ scoped_refptr<ServiceWorkerRegistration> registration =
+ base::MakeRefCounted<ServiceWorkerRegistration>(
+ registration_opt, 1L /* registration_id */,
+ helper_->context()->AsWeakPtr());
+ scoped_refptr<ServiceWorkerVersion> version =
+ base::MakeRefCounted<ServiceWorkerVersion>(
+ registration.get(), GURL("http://www.example.com/test/script_url"),
+ 1L /* version_id */, helper_->context()->AsWeakPtr());
+ helper_->SimulateAddProcessToPattern(
+ GURL("http://www.example.com/test/script_url"), kRenderProcessId2);
remote_endpoints.emplace_back();
std::unique_ptr<ServiceWorkerProviderHost> host4 =
CreateProviderHostForServiceWorkerContext(
- kRenderProcessId2, provider_id++, true /* is_parent_frame_secure */,
+ kRenderProcessId2, true /* is_parent_frame_secure */, version.get(),
context()->AsWeakPtr(), &remote_endpoints.back());
host4->SetDocumentUrl(kOrigin2);
+ const int host4_provider_id = host4->provider_id();
+ EXPECT_LT(host4_provider_id, kInvalidServiceWorkerProviderId);
ServiceWorkerProviderHost* host1_raw = host1.get();
ServiceWorkerProviderHost* host2_raw = host2.get();
@@ -648,12 +667,12 @@ TEST_F(ServiceWorkerContextTest, ProviderHostIterator) {
context()->RemoveProviderHost(kRenderProcessId1, 1);
context()->RemoveProviderHost(kRenderProcessId2, 2);
context()->RemoveProviderHost(kRenderProcessId2, 3);
- context()->RemoveProviderHost(kRenderProcessId2, 4);
+ context()->RemoveProviderHost(kRenderProcessId2, host4_provider_id);
}
class ServiceWorkerContextRecoveryTest
: public ServiceWorkerContextTest,
- public testing::WithParamInterface<bool> {
+ public testing::WithParamInterface<bool /* is_storage_on_disk */> {
public:
ServiceWorkerContextRecoveryTest() {}
virtual ~ServiceWorkerContextRecoveryTest() {}
@@ -681,7 +700,7 @@ TEST_P(ServiceWorkerContextRecoveryTest, DeleteAndStartOver) {
MakeRegisteredCallback(&called, &registration_id));
ASSERT_FALSE(called);
- base::RunLoop().RunUntilIdle();
+ content::RunAllBlockingPoolTasksUntilIdle();
EXPECT_TRUE(called);
context()->storage()->FindRegistrationForId(
@@ -691,11 +710,12 @@ TEST_P(ServiceWorkerContextRecoveryTest, DeleteAndStartOver) {
SERVICE_WORKER_OK,
false /* expect_waiting */,
true /* expect_active */));
- base::RunLoop().RunUntilIdle();
+ content::RunAllBlockingPoolTasksUntilIdle();
- // Next handle ids should be 0 (the next call should return 1).
- EXPECT_EQ(0, context()->GetNewServiceWorkerHandleId());
- EXPECT_EQ(0, context()->GetNewRegistrationHandleId());
+ // Next handle ids should be 1 (the next call should return 2) because
+ // registered worker should have taken ID 0.
+ EXPECT_EQ(1, context()->GetNewServiceWorkerHandleId());
+ EXPECT_EQ(1, context()->GetNewRegistrationHandleId());
context()->ScheduleDeleteAndStartOver();
@@ -705,7 +725,7 @@ TEST_P(ServiceWorkerContextRecoveryTest, DeleteAndStartOver) {
registration_id, pattern.GetOrigin(),
base::Bind(&ExpectRegisteredWorkers, SERVICE_WORKER_ERROR_ABORT,
false /* expect_waiting */, true /* expect_active */));
- base::RunLoop().RunUntilIdle();
+ content::RunAllBlockingPoolTasksUntilIdle();
// The context started over and the storage was re-initialized, so the
// registration should not be found.
@@ -716,7 +736,7 @@ TEST_P(ServiceWorkerContextRecoveryTest, DeleteAndStartOver) {
SERVICE_WORKER_ERROR_NOT_FOUND,
false /* expect_waiting */,
true /* expect_active */));
- base::RunLoop().RunUntilIdle();
+ content::RunAllBlockingPoolTasksUntilIdle();
called = false;
context()->RegisterServiceWorker(
@@ -724,7 +744,7 @@ TEST_P(ServiceWorkerContextRecoveryTest, DeleteAndStartOver) {
MakeRegisteredCallback(&called, &registration_id));
ASSERT_FALSE(called);
- base::RunLoop().RunUntilIdle();
+ content::RunAllBlockingPoolTasksUntilIdle();
EXPECT_TRUE(called);
context()->storage()->FindRegistrationForId(
@@ -734,11 +754,12 @@ TEST_P(ServiceWorkerContextRecoveryTest, DeleteAndStartOver) {
SERVICE_WORKER_OK,
false /* expect_waiting */,
true /* expect_active */));
- base::RunLoop().RunUntilIdle();
+ content::RunAllBlockingPoolTasksUntilIdle();
- // The new context should take over next handle ids.
- EXPECT_EQ(1, context()->GetNewServiceWorkerHandleId());
- EXPECT_EQ(1, context()->GetNewRegistrationHandleId());
+ // The new context should take over next handle ids. ID 2 should have been
+ // taken by the running registration, so the following method calls return 3.
+ EXPECT_EQ(3, context()->GetNewServiceWorkerHandleId());
+ EXPECT_EQ(3, context()->GetNewRegistrationHandleId());
ASSERT_EQ(3u, notifications_.size());
EXPECT_EQ(REGISTRATION_STORED, notifications_[0].type);
@@ -752,6 +773,6 @@ TEST_P(ServiceWorkerContextRecoveryTest, DeleteAndStartOver) {
INSTANTIATE_TEST_CASE_P(ServiceWorkerContextRecoveryTest,
ServiceWorkerContextRecoveryTest,
- testing::Bool());
+ testing::Bool() /* is_storage_on_disk */);
} // namespace content
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 a88d408472a..eac701e7545 100644
--- a/chromium/content/browser/service_worker/service_worker_context_watcher.cc
+++ b/chromium/content/browser/service_worker/service_worker_context_watcher.cc
@@ -42,19 +42,23 @@ void ServiceWorkerContextWatcher::Start() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&ServiceWorkerContextWatcher::GetStoredRegistrationsOnIOThread,
- this));
+ base::BindOnce(
+ &ServiceWorkerContextWatcher::GetStoredRegistrationsOnIOThread,
+ this));
}
void ServiceWorkerContextWatcher::Stop() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ stop_called_ = true;
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&ServiceWorkerContextWatcher::StopOnIOThread, this));
+ base::BindOnce(&ServiceWorkerContextWatcher::StopOnIOThread, this));
}
void ServiceWorkerContextWatcher::GetStoredRegistrationsOnIOThread() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ if (is_stopped_)
+ return;
context_->GetAllRegistrations(base::Bind(
&ServiceWorkerContextWatcher::OnStoredRegistrationsOnIOThread, this));
}
@@ -63,6 +67,8 @@ void ServiceWorkerContextWatcher::OnStoredRegistrationsOnIOThread(
ServiceWorkerStatusCode status,
const std::vector<ServiceWorkerRegistrationInfo>& stored_registrations) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ if (is_stopped_)
+ return;
context_->AddObserver(this);
std::unordered_map<int64_t, std::unique_ptr<ServiceWorkerRegistrationInfo>>
@@ -74,32 +80,41 @@ void ServiceWorkerContextWatcher::OnStoredRegistrationsOnIOThread(
for (const auto& version : context_->GetAllLiveVersionInfo())
StoreVersionInfo(version);
- std::vector<ServiceWorkerRegistrationInfo> registrations;
- registrations.reserve(registration_info_map.size());
+ std::unique_ptr<std::vector<ServiceWorkerRegistrationInfo>> registrations =
+ base::MakeUnique<std::vector<ServiceWorkerRegistrationInfo>>();
+ registrations->reserve(registration_info_map.size());
for (const auto& registration_id_info_pair : registration_info_map)
- registrations.push_back(*registration_id_info_pair.second);
+ registrations->push_back(*registration_id_info_pair.second);
- std::vector<ServiceWorkerVersionInfo> versions;
- versions.reserve(version_info_map_.size());
+ std::unique_ptr<std::vector<ServiceWorkerVersionInfo>> versions =
+ base::MakeUnique<std::vector<ServiceWorkerVersionInfo>>();
+ versions->reserve(version_info_map_.size());
for (auto version_it = version_info_map_.begin();
version_it != version_info_map_.end();) {
- versions.push_back(*version_it->second);
+ versions->push_back(*version_it->second);
if (IsStoppedAndRedundant(*version_it->second))
version_info_map_.erase(version_it++);
else
++version_it;
}
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(registration_callback_, registrations));
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(version_callback_, versions));
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(
+ &ServiceWorkerContextWatcher::RunWorkerRegistrationUpdatedCallback,
+ this, std::move(registrations)));
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(
+ &ServiceWorkerContextWatcher::RunWorkerVersionUpdatedCallback, this,
+ std::move(versions)));
}
void ServiceWorkerContextWatcher::StopOnIOThread() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
context_->RemoveObserver(this);
+ is_stopped_ = true;
}
ServiceWorkerContextWatcher::~ServiceWorkerContextWatcher() {
@@ -132,36 +147,73 @@ void ServiceWorkerContextWatcher::SendRegistrationInfo(
int64_t registration_id,
const GURL& pattern,
ServiceWorkerRegistrationInfo::DeleteFlag delete_flag) {
- std::vector<ServiceWorkerRegistrationInfo> registrations;
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ std::unique_ptr<std::vector<ServiceWorkerRegistrationInfo>> registrations =
+ base::MakeUnique<std::vector<ServiceWorkerRegistrationInfo>>();
ServiceWorkerRegistration* registration =
context_->GetLiveRegistration(registration_id);
if (registration) {
- registrations.push_back(registration->GetInfo());
+ registrations->push_back(registration->GetInfo());
} else {
- registrations.push_back(
+ registrations->push_back(
ServiceWorkerRegistrationInfo(pattern, registration_id, delete_flag));
}
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(registration_callback_, registrations));
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(
+ &ServiceWorkerContextWatcher::RunWorkerRegistrationUpdatedCallback,
+ this, std::move(registrations)));
}
void ServiceWorkerContextWatcher::SendVersionInfo(
const ServiceWorkerVersionInfo& version_info) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- std::vector<ServiceWorkerVersionInfo> versions;
- versions.push_back(version_info);
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(version_callback_, versions));
+ std::unique_ptr<std::vector<ServiceWorkerVersionInfo>> versions =
+ base::MakeUnique<std::vector<ServiceWorkerVersionInfo>>();
+ versions->push_back(version_info);
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(
+ &ServiceWorkerContextWatcher::RunWorkerVersionUpdatedCallback, this,
+ std::move(versions)));
+}
+
+void ServiceWorkerContextWatcher::RunWorkerRegistrationUpdatedCallback(
+ std::unique_ptr<std::vector<ServiceWorkerRegistrationInfo>> registrations) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ if (stop_called_)
+ return;
+ registration_callback_.Run(*registrations.get());
+}
+
+void ServiceWorkerContextWatcher::RunWorkerVersionUpdatedCallback(
+ std::unique_ptr<std::vector<ServiceWorkerVersionInfo>> versions) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ if (stop_called_)
+ return;
+ version_callback_.Run(*versions.get());
+}
+
+void ServiceWorkerContextWatcher::RunWorkerErrorReportedCallback(
+ int64_t registration_id,
+ int64_t version_id,
+ std::unique_ptr<ErrorInfo> error_info) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ if (stop_called_)
+ return;
+ error_callback_.Run(registration_id, version_id, *error_info.get());
}
void ServiceWorkerContextWatcher::OnNewLiveRegistration(int64_t registration_id,
const GURL& pattern) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
SendRegistrationInfo(registration_id, pattern,
ServiceWorkerRegistrationInfo::IS_NOT_DELETED);
}
void ServiceWorkerContextWatcher::OnNewLiveVersion(
const ServiceWorkerVersionInfo& version_info) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
int64_t version_id = version_info.version_id;
auto it = version_info_map_.find(version_id);
if (it != version_info_map_.end()) {
@@ -180,6 +232,7 @@ void ServiceWorkerContextWatcher::OnNewLiveVersion(
void ServiceWorkerContextWatcher::OnRunningStateChanged(
int64_t version_id,
content::EmbeddedWorkerStatus running_status) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
auto it = version_info_map_.find(version_id);
if (it == version_info_map_.end())
return;
@@ -195,6 +248,7 @@ void ServiceWorkerContextWatcher::OnRunningStateChanged(
void ServiceWorkerContextWatcher::OnVersionStateChanged(
int64_t version_id,
content::ServiceWorkerVersion::Status status) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
auto it = version_info_map_.find(version_id);
if (it == version_info_map_.end())
return;
@@ -211,6 +265,7 @@ void ServiceWorkerContextWatcher::OnVersionDevToolsRoutingIdChanged(
int64_t version_id,
int process_id,
int devtools_agent_route_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
auto it = version_info_map_.find(version_id);
if (it == version_info_map_.end())
return;
@@ -230,6 +285,7 @@ void ServiceWorkerContextWatcher::OnMainScriptHttpResponseInfoSet(
int64_t version_id,
base::Time script_response_time,
base::Time script_last_modified) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
auto it = version_info_map_.find(version_id);
if (it == version_info_map_.end())
return;
@@ -243,13 +299,16 @@ void ServiceWorkerContextWatcher::OnErrorReported(int64_t version_id,
int process_id,
int thread_id,
const ErrorInfo& info) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
int64_t registration_id = kInvalidServiceWorkerRegistrationId;
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::Bind(error_callback_, registration_id, version_id, info));
+ base::BindOnce(
+ &ServiceWorkerContextWatcher::RunWorkerErrorReportedCallback, this,
+ registration_id, version_id, base::MakeUnique<ErrorInfo>(info)));
}
void ServiceWorkerContextWatcher::OnReportConsoleMessage(
@@ -257,17 +316,21 @@ void ServiceWorkerContextWatcher::OnReportConsoleMessage(
int process_id,
int thread_id,
const ConsoleMessage& message) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (message.message_level != CONSOLE_MESSAGE_LEVEL_ERROR)
return;
int64_t registration_id = kInvalidServiceWorkerRegistrationId;
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::Bind(error_callback_, registration_id, version_id,
- ErrorInfo(message.message, message.line_number, -1,
- message.source_url)));
+ base::BindOnce(
+ &ServiceWorkerContextWatcher::RunWorkerErrorReportedCallback, this,
+ registration_id, version_id,
+ base::MakeUnique<ErrorInfo>(message.message, message.line_number, -1,
+ message.source_url)));
}
void ServiceWorkerContextWatcher::OnControlleeAdded(
@@ -277,6 +340,7 @@ void ServiceWorkerContextWatcher::OnControlleeAdded(
int route_id,
const base::Callback<WebContents*(void)>& web_contents_getter,
ServiceWorkerProviderType type) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
auto it = version_info_map_.find(version_id);
if (it == version_info_map_.end())
return;
@@ -288,6 +352,7 @@ void ServiceWorkerContextWatcher::OnControlleeAdded(
void ServiceWorkerContextWatcher::OnControlleeRemoved(int64_t version_id,
const std::string& uuid) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
auto it = version_info_map_.find(version_id);
if (it == version_info_map_.end())
return;
@@ -298,12 +363,14 @@ void ServiceWorkerContextWatcher::OnControlleeRemoved(int64_t version_id,
void ServiceWorkerContextWatcher::OnRegistrationStored(int64_t registration_id,
const GURL& pattern) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
SendRegistrationInfo(registration_id, pattern,
ServiceWorkerRegistrationInfo::IS_NOT_DELETED);
}
void ServiceWorkerContextWatcher::OnRegistrationDeleted(int64_t registration_id,
const GURL& pattern) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
SendRegistrationInfo(registration_id, pattern,
ServiceWorkerRegistrationInfo::IS_DELETED);
}
diff --git a/chromium/content/browser/service_worker/service_worker_context_watcher.h b/chromium/content/browser/service_worker/service_worker_context_watcher.h
index 02c41c52d8f..10847d4a1f5 100644
--- a/chromium/content/browser/service_worker/service_worker_context_watcher.h
+++ b/chromium/content/browser/service_worker/service_worker_context_watcher.h
@@ -13,6 +13,7 @@
#include "base/callback.h"
#include "content/browser/service_worker/service_worker_context_core_observer.h"
#include "content/browser/service_worker/service_worker_info.h"
+#include "content/common/content_export.h"
namespace content {
@@ -21,7 +22,7 @@ enum class EmbeddedWorkerStatus;
// Used to monitor the status change of the ServiceWorker registrations and
// versions in the ServiceWorkerContext from UI thread.
-class ServiceWorkerContextWatcher
+class CONTENT_EXPORT ServiceWorkerContextWatcher
: public ServiceWorkerContextCoreObserver,
public base::RefCountedThreadSafe<ServiceWorkerContextWatcher> {
public:
@@ -44,6 +45,8 @@ class ServiceWorkerContextWatcher
private:
friend class base::RefCountedThreadSafe<ServiceWorkerContextWatcher>;
+ friend class ServiceWorkerContextWatcherTest;
+
~ServiceWorkerContextWatcher() override;
void GetStoredRegistrationsOnIOThread();
@@ -65,6 +68,15 @@ class ServiceWorkerContextWatcher
ServiceWorkerRegistrationInfo::DeleteFlag delete_flag);
void SendVersionInfo(const ServiceWorkerVersionInfo& version);
+ void RunWorkerRegistrationUpdatedCallback(
+ std::unique_ptr<std::vector<ServiceWorkerRegistrationInfo>>
+ registrations);
+ void RunWorkerVersionUpdatedCallback(
+ std::unique_ptr<std::vector<ServiceWorkerVersionInfo>> versions);
+ void RunWorkerErrorReportedCallback(int64_t registration_id,
+ int64_t version_id,
+ std::unique_ptr<ErrorInfo> error_info);
+
// ServiceWorkerContextCoreObserver implements
void OnNewLiveRegistration(int64_t registration_id,
const GURL& pattern) override;
@@ -110,6 +122,10 @@ class ServiceWorkerContextWatcher
WorkerRegistrationUpdatedCallback registration_callback_;
WorkerVersionUpdatedCallback version_callback_;
WorkerErrorReportedCallback error_callback_;
+ // Should be used on UI thread only.
+ bool stop_called_ = false;
+ // Should be used on IO thread only.
+ bool is_stopped_ = false;
};
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_context_watcher_unittest.cc b/chromium/content/browser/service_worker/service_worker_context_watcher_unittest.cc
new file mode 100644
index 00000000000..67249fe184f
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_context_watcher_unittest.cc
@@ -0,0 +1,386 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/service_worker/service_worker_context_watcher.h"
+
+#include "base/memory/weak_ptr.h"
+#include "base/run_loop.h"
+#include "base/strings/utf_string_conversions.h"
+#include "content/browser/service_worker/embedded_worker_test_helper.h"
+#include "content/browser/service_worker/service_worker_context_wrapper.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+namespace {
+
+void DidRegisterServiceWorker(int64_t* registration_id_out,
+ ServiceWorkerStatusCode status,
+ const std::string& status_message,
+ int64_t registration_id) {
+ ASSERT_TRUE(registration_id_out);
+ EXPECT_EQ(SERVICE_WORKER_OK, status);
+ *registration_id_out = registration_id;
+}
+
+void DidUnregisterServiceWorker(ServiceWorkerStatusCode* status_out,
+ ServiceWorkerStatusCode status) {
+ ASSERT_TRUE(status_out);
+ *status_out = status;
+}
+
+class WatcherCallback {
+ public:
+ WatcherCallback() : weak_factory_(this) {}
+
+ ~WatcherCallback() {}
+
+ scoped_refptr<ServiceWorkerContextWatcher> StartWatch(
+ scoped_refptr<ServiceWorkerContextWrapper> context) {
+ scoped_refptr<ServiceWorkerContextWatcher> watcher =
+ base::MakeRefCounted<ServiceWorkerContextWatcher>(
+ context,
+ base::Bind(&WatcherCallback::OnRegistrationUpdated,
+ weak_factory_.GetWeakPtr()),
+ base::Bind(&WatcherCallback::OnVersionUpdated,
+ weak_factory_.GetWeakPtr()),
+ base::Bind(&WatcherCallback::OnErrorReported,
+ weak_factory_.GetWeakPtr()));
+ watcher->Start();
+ return watcher;
+ }
+
+ const std::map<int64_t, ServiceWorkerRegistrationInfo>& registrations()
+ const {
+ return registrations_;
+ }
+
+ const std::map<int64_t, std::map<int64_t, ServiceWorkerVersionInfo>>&
+ versions() const {
+ return versions_;
+ }
+ const std::map<
+ int64_t,
+ std::map<int64_t,
+ std::vector<ServiceWorkerContextCoreObserver::ErrorInfo>>>&
+ errors() const {
+ return errors_;
+ }
+
+ int callback_count() const { return callback_count_; };
+
+ private:
+ void OnRegistrationUpdated(
+ const std::vector<ServiceWorkerRegistrationInfo>& registrations) {
+ ++callback_count_;
+ for (const auto& info : registrations) {
+ if (info.delete_flag ==
+ ServiceWorkerRegistrationInfo::DeleteFlag::IS_DELETED) {
+ registrations_.erase(info.registration_id);
+ } else {
+ registrations_[info.registration_id] = info;
+ }
+ }
+ }
+
+ void OnVersionUpdated(const std::vector<ServiceWorkerVersionInfo>& versions) {
+ ++callback_count_;
+ for (const auto& info : versions) {
+ versions_[info.registration_id][info.version_id] = info;
+ }
+ }
+
+ void OnErrorReported(
+ int64_t registration_id,
+ int64_t version_id,
+ const ServiceWorkerContextCoreObserver::ErrorInfo& error_info) {
+ ++callback_count_;
+ errors_[registration_id][version_id].push_back(error_info);
+ }
+
+ std::map<int64_t /* registration_id */, ServiceWorkerRegistrationInfo>
+ registrations_;
+ std::map<int64_t /* registration_id */,
+ std::map<int64_t /* version_id */, ServiceWorkerVersionInfo>>
+ versions_;
+ std::map<int64_t /* registration_id */,
+ std::map<int64_t /* version_id */,
+ std::vector<ServiceWorkerContextCoreObserver::ErrorInfo>>>
+ errors_;
+
+ int callback_count_ = 0;
+
+ base::WeakPtrFactory<WatcherCallback> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(WatcherCallback);
+};
+
+} // namespace
+
+class ServiceWorkerContextWatcherTest : public testing::Test {
+ public:
+ ServiceWorkerContextWatcherTest()
+ : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {}
+
+ void SetUp() override {
+ helper_.reset(new EmbeddedWorkerTestHelper(base::FilePath()));
+ base::RunLoop().RunUntilIdle();
+ }
+
+ void TearDown() override {
+ helper_.reset();
+ base::RunLoop().RunUntilIdle();
+ }
+
+ protected:
+ ServiceWorkerContextCore* context() { return helper_->context(); }
+ ServiceWorkerContextWrapper* context_wrapper() {
+ return helper_->context_wrapper();
+ }
+ int64_t RegisterServiceWorker(const GURL& scope, const GURL& script_url) {
+ int64_t registration_id = kInvalidServiceWorkerRegistrationId;
+ context()->RegisterServiceWorker(
+ script_url, ServiceWorkerRegistrationOptions(scope),
+ nullptr /* provider_host */,
+ base::Bind(&DidRegisterServiceWorker, &registration_id));
+ base::RunLoop().RunUntilIdle();
+ return registration_id;
+ }
+
+ ServiceWorkerStatusCode UnregisterServiceWorker(const GURL& scope) {
+ ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
+ context()->UnregisterServiceWorker(
+ scope, base::Bind(&DidUnregisterServiceWorker, &status));
+ base::RunLoop().RunUntilIdle();
+ return status;
+ }
+
+ void ReportError(
+ scoped_refptr<ServiceWorkerContextWatcher> watcher,
+ int64_t version_id,
+ const ServiceWorkerContextCoreObserver::ErrorInfo& error_info) {
+ watcher->OnErrorReported(version_id, 0 /* process_id */, 0 /* thread_id */,
+ error_info);
+ }
+
+ private:
+ std::unique_ptr<EmbeddedWorkerTestHelper> helper_;
+ TestBrowserThreadBundle browser_thread_bundle_;
+
+ DISALLOW_COPY_AND_ASSIGN(ServiceWorkerContextWatcherTest);
+};
+
+TEST_F(ServiceWorkerContextWatcherTest, NoServiceWorker) {
+ WatcherCallback watcher_callback;
+ scoped_refptr<ServiceWorkerContextWatcher> watcher =
+ watcher_callback.StartWatch(context_wrapper());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(0u, watcher_callback.registrations().size());
+ EXPECT_EQ(0u, watcher_callback.versions().size());
+ EXPECT_EQ(0u, watcher_callback.errors().size());
+ // OnRegistrationUpdated() and OnVersionUpdated() must be called with the
+ // empty initial data.
+ EXPECT_EQ(2, watcher_callback.callback_count());
+ watcher->Stop();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(0u, watcher_callback.registrations().size());
+ EXPECT_EQ(0u, watcher_callback.versions().size());
+ EXPECT_EQ(2, watcher_callback.callback_count());
+}
+
+TEST_F(ServiceWorkerContextWatcherTest, StoredServiceWorkers) {
+ GURL scope_1 = GURL("https://www1.example.com/");
+ GURL script_1 = GURL("https://www1.example.com/worker.js");
+ int64_t registration_id_1 = RegisterServiceWorker(scope_1, script_1);
+ ASSERT_NE(kInvalidServiceWorkerRegistrationId, registration_id_1);
+
+ GURL scope_2 = GURL("https://www2.example.com/");
+ GURL script_2 = GURL("https://www2.example.com/worker.js");
+ int64_t registration_id_2 = RegisterServiceWorker(scope_2, script_2);
+ ASSERT_NE(kInvalidServiceWorkerRegistrationId, registration_id_2);
+
+ WatcherCallback watcher_callback;
+ scoped_refptr<ServiceWorkerContextWatcher> watcher =
+ watcher_callback.StartWatch(context_wrapper());
+ base::RunLoop().RunUntilIdle();
+
+ ASSERT_EQ(2u, watcher_callback.registrations().size());
+ EXPECT_EQ(scope_1,
+ watcher_callback.registrations().at(registration_id_1).pattern);
+ EXPECT_EQ(scope_2,
+ watcher_callback.registrations().at(registration_id_2).pattern);
+ ASSERT_EQ(2u, watcher_callback.versions().size());
+ EXPECT_EQ(script_1, watcher_callback.versions()
+ .at(registration_id_1)
+ .begin()
+ ->second.script_url);
+ EXPECT_EQ(script_2, watcher_callback.versions()
+ .at(registration_id_2)
+ .begin()
+ ->second.script_url);
+ EXPECT_EQ(0u, watcher_callback.errors().size());
+
+ watcher->Stop();
+ base::RunLoop().RunUntilIdle();
+}
+
+TEST_F(ServiceWorkerContextWatcherTest, RegisteredServiceWorker) {
+ GURL scope_1 = GURL("https://www1.example.com/");
+ GURL script_1 = GURL("https://www1.example.com/worker.js");
+ int64_t registration_id_1 = RegisterServiceWorker(scope_1, script_1);
+ ASSERT_NE(kInvalidServiceWorkerRegistrationId, registration_id_1);
+
+ WatcherCallback watcher_callback;
+ scoped_refptr<ServiceWorkerContextWatcher> watcher =
+ watcher_callback.StartWatch(context_wrapper());
+ base::RunLoop().RunUntilIdle();
+ ASSERT_EQ(1u, watcher_callback.registrations().size());
+ EXPECT_EQ(scope_1,
+ watcher_callback.registrations().at(registration_id_1).pattern);
+ ASSERT_EQ(1u, watcher_callback.versions().size());
+ EXPECT_EQ(script_1, watcher_callback.versions()
+ .at(registration_id_1)
+ .begin()
+ ->second.script_url);
+ EXPECT_EQ(0u, watcher_callback.errors().size());
+
+ GURL scope_2 = GURL("https://www2.example.com/");
+ GURL script_2 = GURL("https://www2.example.com/worker.js");
+ int64_t registration_id_2 = RegisterServiceWorker(scope_2, script_2);
+ ASSERT_EQ(2u, watcher_callback.registrations().size());
+ EXPECT_EQ(scope_1,
+ watcher_callback.registrations().at(registration_id_1).pattern);
+ EXPECT_EQ(scope_2,
+ watcher_callback.registrations().at(registration_id_2).pattern);
+ ASSERT_EQ(2u, watcher_callback.versions().size());
+ EXPECT_EQ(script_1, watcher_callback.versions()
+ .at(registration_id_1)
+ .begin()
+ ->second.script_url);
+ EXPECT_EQ(script_2, watcher_callback.versions()
+ .at(registration_id_2)
+ .begin()
+ ->second.script_url);
+ EXPECT_EQ(0u, watcher_callback.errors().size());
+
+ watcher->Stop();
+ base::RunLoop().RunUntilIdle();
+}
+
+TEST_F(ServiceWorkerContextWatcherTest, UnregisteredServiceWorker) {
+ GURL scope_1 = GURL("https://www1.example.com/");
+ GURL script_1 = GURL("https://www1.example.com/worker.js");
+ int64_t registration_id_1 = RegisterServiceWorker(scope_1, script_1);
+ ASSERT_NE(kInvalidServiceWorkerRegistrationId, registration_id_1);
+
+ GURL scope_2 = GURL("https://www2.example.com/");
+ GURL script_2 = GURL("https://www2.example.com/worker.js");
+ int64_t registration_id_2 = RegisterServiceWorker(scope_2, script_2);
+
+ WatcherCallback watcher_callback;
+ scoped_refptr<ServiceWorkerContextWatcher> watcher =
+ watcher_callback.StartWatch(context_wrapper());
+ base::RunLoop().RunUntilIdle();
+
+ ASSERT_EQ(2u, watcher_callback.registrations().size());
+ EXPECT_EQ(scope_1,
+ watcher_callback.registrations().at(registration_id_1).pattern);
+ EXPECT_EQ(scope_2,
+ watcher_callback.registrations().at(registration_id_2).pattern);
+ ASSERT_EQ(2u, watcher_callback.versions().size());
+
+ ASSERT_EQ(SERVICE_WORKER_OK, UnregisterServiceWorker(scope_1));
+
+ ASSERT_EQ(1u, watcher_callback.registrations().size());
+ EXPECT_EQ(scope_2,
+ watcher_callback.registrations().at(registration_id_2).pattern);
+
+ watcher->Stop();
+ base::RunLoop().RunUntilIdle();
+}
+
+TEST_F(ServiceWorkerContextWatcherTest, ErrorReport) {
+ GURL scope = GURL("https://www1.example.com/");
+ GURL script = GURL("https://www1.example.com/worker.js");
+ int64_t registration_id = RegisterServiceWorker(scope, script);
+ ASSERT_NE(kInvalidServiceWorkerRegistrationId, registration_id);
+
+ WatcherCallback watcher_callback;
+ scoped_refptr<ServiceWorkerContextWatcher> watcher =
+ watcher_callback.StartWatch(context_wrapper());
+ base::RunLoop().RunUntilIdle();
+ ASSERT_EQ(1u, watcher_callback.registrations().size());
+ EXPECT_EQ(scope,
+ watcher_callback.registrations().at(registration_id).pattern);
+ ASSERT_EQ(1u, watcher_callback.versions().size());
+ EXPECT_EQ(script, watcher_callback.versions()
+ .at(registration_id)
+ .begin()
+ ->second.script_url);
+ int64_t version_id =
+ watcher_callback.versions().at(registration_id).begin()->first;
+ EXPECT_EQ(0u, watcher_callback.errors().size());
+
+ base::string16 message(base::ASCIIToUTF16("HELLO"));
+ ReportError(
+ watcher, version_id,
+ ServiceWorkerContextCoreObserver::ErrorInfo(message, 0, 0, script));
+ base::RunLoop().RunUntilIdle();
+ ASSERT_EQ(1u, watcher_callback.errors().size());
+ ASSERT_EQ(1u, watcher_callback.errors().at(registration_id).size());
+ ASSERT_EQ(
+ 1u, watcher_callback.errors().at(registration_id).at(version_id).size());
+ EXPECT_EQ(message, watcher_callback.errors()
+ .at(registration_id)
+ .at(version_id)[0]
+ .error_message);
+
+ watcher->Stop();
+ base::RunLoop().RunUntilIdle();
+}
+
+// This test checks that even if ServiceWorkerContextWatcher::Stop() is called
+// quickly after Start() is called, the crash (crbug.com/727877) should not
+// happen.
+TEST_F(ServiceWorkerContextWatcherTest, StopQuickly) {
+ WatcherCallback watcher_callback;
+ scoped_refptr<ServiceWorkerContextWatcher> watcher =
+ watcher_callback.StartWatch(context_wrapper());
+ watcher->Stop();
+
+ int callback_count = watcher_callback.callback_count();
+ GURL scope = GURL("https://www1.example.com/");
+ GURL script = GURL("https://www1.example.com/worker.js");
+ int64_t registration_id = RegisterServiceWorker(scope, script);
+ ASSERT_NE(kInvalidServiceWorkerRegistrationId, registration_id);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(callback_count, watcher_callback.callback_count());
+}
+
+// This test checks that any callbacks should not be executed after
+// ServiceWorkerContextWatcher::Stop() is called.
+TEST_F(ServiceWorkerContextWatcherTest, Race) {
+ GURL scope = GURL("https://www1.example.com/");
+ GURL script = GURL("https://www1.example.com/worker.js");
+ int64_t registration_id = RegisterServiceWorker(scope, script);
+ ASSERT_NE(kInvalidServiceWorkerRegistrationId, registration_id);
+ base::RunLoop().RunUntilIdle();
+
+ WatcherCallback watcher_callback;
+ scoped_refptr<ServiceWorkerContextWatcher> watcher =
+ watcher_callback.StartWatch(context_wrapper());
+ base::RunLoop().RunUntilIdle();
+ watcher->Stop();
+
+ int callback_count = watcher_callback.callback_count();
+ base::string16 message(base::ASCIIToUTF16("HELLO"));
+ ReportError(
+ watcher, 0 /*version_id*/,
+ ServiceWorkerContextCoreObserver::ErrorInfo(message, 0, 0, script));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(callback_count, watcher_callback.callback_count());
+}
+
+} // namespace content
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 639e259b21c..d477baabf74 100644
--- a/chromium/content/browser/service_worker/service_worker_context_wrapper.cc
+++ b/chromium/content/browser/service_worker/service_worker_context_wrapper.cc
@@ -18,6 +18,7 @@
#include "base/logging.h"
#include "base/profiler/scoped_tracker.h"
#include "base/single_thread_task_runner.h"
+#include "base/task_scheduler/post_task.h"
#include "base/threading/sequenced_worker_pool.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/service_worker/embedded_worker_status.h"
@@ -51,7 +52,7 @@ void WorkerStarted(const ServiceWorkerContextWrapper::StatusCallback& callback,
ServiceWorkerStatusCode status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(callback, status));
+ base::BindOnce(callback, status));
}
void StartActiveWorkerOnIO(
@@ -68,8 +69,9 @@ void StartActiveWorkerOnIO(
base::Bind(WorkerStarted, callback));
return;
}
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(callback, SERVICE_WORKER_ERROR_NOT_FOUND));
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(callback, SERVICE_WORKER_ERROR_NOT_FOUND));
}
void SkipWaitingWorkerOnIO(
@@ -110,8 +112,8 @@ void FoundReadyRegistrationForStartActiveWorker(
DCHECK(active_version.get());
active_version->RunAfterStartWorker(
ServiceWorkerMetrics::EventType::EXTERNAL_REQUEST,
- base::Bind(&DidStartWorker, active_version,
- base::Passed(&info_callback)),
+ base::BindOnce(&DidStartWorker, active_version,
+ std::move(info_callback)),
base::Bind(&DidFailStartWorker, base::Passed(&failure_callback)));
} else {
std::move(failure_callback).Run();
@@ -190,14 +192,17 @@ void ServiceWorkerContextWrapper::Init(
DCHECK_CURRENTLY_ON(BrowserThread::UI);
is_incognito_ = user_data_directory.empty();
- base::SequencedWorkerPool* pool = BrowserThread::GetBlockingPool();
- std::unique_ptr<ServiceWorkerDatabaseTaskManager> database_task_manager(
- new ServiceWorkerDatabaseTaskManagerImpl(pool));
- scoped_refptr<base::SingleThreadTaskRunner> disk_cache_thread =
- BrowserThread::GetTaskRunnerForThread(BrowserThread::CACHE);
- InitInternal(user_data_directory, std::move(database_task_manager),
- disk_cache_thread, quota_manager_proxy, special_storage_policy,
- blob_context, loader_factory_getter);
+ // The database task runner is BLOCK_SHUTDOWN in order to support
+ // ClearSessionOnlyOrigins() (called due to the "clear on browser exit"
+ // content setting).
+ // TODO(falken): Only block shutdown for that particular task, when someday
+ // task runners support mixing task shutdown behaviors.
+ scoped_refptr<base::SequencedTaskRunner> database_task_runner =
+ base::CreateSequencedTaskRunnerWithTraits(
+ {base::MayBlock(), base::TaskShutdownBehavior::BLOCK_SHUTDOWN});
+ InitInternal(user_data_directory, std::move(database_task_runner),
+ quota_manager_proxy, special_storage_policy, blob_context,
+ loader_factory_getter);
}
void ServiceWorkerContextWrapper::Shutdown() {
@@ -206,9 +211,8 @@ void ServiceWorkerContextWrapper::Shutdown() {
storage_partition_ = nullptr;
process_manager_->Shutdown();
BrowserThread::PostTask(
- BrowserThread::IO,
- FROM_HERE,
- base::Bind(&ServiceWorkerContextWrapper::ShutdownOnIO, this));
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&ServiceWorkerContextWrapper::ShutdownOnIO, this));
}
void ServiceWorkerContextWrapper::InitializeResourceContext(
@@ -252,9 +256,8 @@ static void FinishRegistrationOnIO(
int64_t registration_id) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
BrowserThread::PostTask(
- BrowserThread::UI,
- FROM_HERE,
- base::Bind(continuation, status == SERVICE_WORKER_OK));
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(continuation, status == SERVICE_WORKER_OK));
}
void ServiceWorkerContextWrapper::RegisterServiceWorker(
@@ -263,18 +266,14 @@ void ServiceWorkerContextWrapper::RegisterServiceWorker(
const ResultCallback& continuation) {
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
BrowserThread::PostTask(
- BrowserThread::IO,
- FROM_HERE,
- base::Bind(&ServiceWorkerContextWrapper::RegisterServiceWorker,
- this,
- pattern,
- script_url,
- continuation));
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&ServiceWorkerContextWrapper::RegisterServiceWorker,
+ this, pattern, script_url, continuation));
return;
}
if (!context_core_) {
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(continuation, false));
+ base::BindOnce(continuation, false));
return;
}
ServiceWorkerRegistrationOptions options(net::SimplifyUrlForRequest(pattern));
@@ -289,9 +288,8 @@ static void FinishUnregistrationOnIO(
ServiceWorkerStatusCode status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
BrowserThread::PostTask(
- BrowserThread::UI,
- FROM_HERE,
- base::Bind(continuation, status == SERVICE_WORKER_OK));
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(continuation, status == SERVICE_WORKER_OK));
}
void ServiceWorkerContextWrapper::UnregisterServiceWorker(
@@ -299,17 +297,14 @@ void ServiceWorkerContextWrapper::UnregisterServiceWorker(
const ResultCallback& continuation) {
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
BrowserThread::PostTask(
- BrowserThread::IO,
- FROM_HERE,
- base::Bind(&ServiceWorkerContextWrapper::UnregisterServiceWorker,
- this,
- pattern,
- continuation));
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&ServiceWorkerContextWrapper::UnregisterServiceWorker,
+ this, pattern, continuation));
return;
}
if (!context_core_) {
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(continuation, false));
+ base::BindOnce(continuation, false));
return;
}
@@ -322,8 +317,8 @@ void ServiceWorkerContextWrapper::UpdateRegistration(const GURL& pattern) {
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&ServiceWorkerContextWrapper::UpdateRegistration, this,
- pattern));
+ base::BindOnce(&ServiceWorkerContextWrapper::UpdateRegistration, this,
+ pattern));
return;
}
if (!context_core_)
@@ -340,13 +335,14 @@ void ServiceWorkerContextWrapper::StartServiceWorker(
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&ServiceWorkerContextWrapper::StartServiceWorker, this,
- pattern, callback));
+ base::BindOnce(&ServiceWorkerContextWrapper::StartServiceWorker, this,
+ pattern, callback));
return;
}
if (!context_core_) {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(callback, SERVICE_WORKER_ERROR_ABORT));
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(callback, SERVICE_WORKER_ERROR_ABORT));
return;
}
context_core_->storage()->FindRegistrationForPattern(
@@ -358,8 +354,8 @@ void ServiceWorkerContextWrapper::SkipWaitingWorker(const GURL& pattern) {
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&ServiceWorkerContextWrapper::SkipWaitingWorker, this,
- pattern));
+ base::BindOnce(&ServiceWorkerContextWrapper::SkipWaitingWorker, this,
+ pattern));
return;
}
if (!context_core_)
@@ -373,8 +369,8 @@ void ServiceWorkerContextWrapper::SetForceUpdateOnPageLoad(
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&ServiceWorkerContextWrapper::SetForceUpdateOnPageLoad, this,
- force_update_on_page_load));
+ base::BindOnce(&ServiceWorkerContextWrapper::SetForceUpdateOnPageLoad,
+ this, force_update_on_page_load));
return;
}
if (!context_core_)
@@ -387,9 +383,8 @@ void ServiceWorkerContextWrapper::GetAllOriginsInfo(
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (!context_core_) {
BrowserThread::PostTask(
- BrowserThread::IO,
- FROM_HERE,
- base::Bind(callback, std::vector<ServiceWorkerUsageInfo>()));
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(callback, std::vector<ServiceWorkerUsageInfo>()));
return;
}
context()->storage()->GetAllRegistrationsInfos(base::Bind(
@@ -427,7 +422,7 @@ void ServiceWorkerContextWrapper::DidCheckHasServiceWorker(
DCHECK_CURRENTLY_ON(BrowserThread::IO);
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(callback, capability));
+ base::BindOnce(callback, capability));
}
void ServiceWorkerContextWrapper::StopAllServiceWorkersForOrigin(
@@ -435,8 +430,9 @@ void ServiceWorkerContextWrapper::StopAllServiceWorkersForOrigin(
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&ServiceWorkerContextWrapper::StopAllServiceWorkersForOrigin,
- this, origin));
+ base::BindOnce(
+ &ServiceWorkerContextWrapper::StopAllServiceWorkersForOrigin, this,
+ origin));
return;
}
if (!context_core_.get()) {
@@ -485,15 +481,13 @@ void ServiceWorkerContextWrapper::DeleteForOrigin(
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&ServiceWorkerContextWrapper::DeleteForOrigin, this, origin,
- result));
+ base::BindOnce(&ServiceWorkerContextWrapper::DeleteForOrigin, this,
+ origin, result));
return;
}
if (!context_core_) {
- BrowserThread::PostTask(
- BrowserThread::IO,
- FROM_HERE,
- base::Bind(result, false));
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+ base::BindOnce(result, false));
return;
}
context()->UnregisterServiceWorkers(
@@ -507,14 +501,14 @@ void ServiceWorkerContextWrapper::CheckHasServiceWorker(
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&ServiceWorkerContextWrapper::CheckHasServiceWorker, this,
- url, other_url, callback));
+ base::BindOnce(&ServiceWorkerContextWrapper::CheckHasServiceWorker,
+ this, url, other_url, callback));
return;
}
if (!context_core_) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(callback, ServiceWorkerCapability::NO_SERVICE_WORKER));
+ base::BindOnce(callback, ServiceWorkerCapability::NO_SERVICE_WORKER));
return;
}
context()->CheckHasServiceWorker(
@@ -529,8 +523,9 @@ void ServiceWorkerContextWrapper::CountExternalRequestsForTest(
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&ServiceWorkerContextWrapper::CountExternalRequestsForTest,
- this, origin, callback));
+ base::BindOnce(
+ &ServiceWorkerContextWrapper::CountExternalRequestsForTest, this,
+ origin, callback));
return;
}
@@ -545,8 +540,9 @@ void ServiceWorkerContextWrapper::CountExternalRequestsForTest(
break;
}
}
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(callback, pending_external_request_count));
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(callback, pending_external_request_count));
}
void ServiceWorkerContextWrapper::ClearAllServiceWorkersForTest(
@@ -554,8 +550,9 @@ void ServiceWorkerContextWrapper::ClearAllServiceWorkersForTest(
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&ServiceWorkerContextWrapper::ClearAllServiceWorkersForTest,
- this, callback));
+ base::BindOnce(
+ &ServiceWorkerContextWrapper::ClearAllServiceWorkersForTest, this,
+ callback));
return;
}
if (!context_core_) {
@@ -602,8 +599,8 @@ void ServiceWorkerContextWrapper::HasMainFrameProviderHost(
const BoolCallback& callback) const {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (!context_core_) {
- base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- base::Bind(callback, false));
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(callback, false));
return;
}
context_core_->HasMainFrameProviderHost(origin, callback);
@@ -711,7 +708,7 @@ void ServiceWorkerContextWrapper::DidFindRegistrationForFindReady(
if (active_version->status() == ServiceWorkerVersion::ACTIVATING) {
// Wait until the version is activated.
- active_version->RegisterStatusChangeCallback(base::Bind(
+ active_version->RegisterStatusChangeCallback(base::BindOnce(
&ServiceWorkerContextWrapper::OnStatusChangedForFindReadyRegistration,
this, callback, std::move(registration)));
return;
@@ -844,8 +841,7 @@ bool ServiceWorkerContextWrapper::OriginHasForeignFetchRegistrations(
void ServiceWorkerContextWrapper::InitInternal(
const base::FilePath& user_data_directory,
- std::unique_ptr<ServiceWorkerDatabaseTaskManager> database_task_manager,
- const scoped_refptr<base::SingleThreadTaskRunner>& disk_cache_thread,
+ scoped_refptr<base::SequencedTaskRunner> database_task_runner,
storage::QuotaManagerProxy* quota_manager_proxy,
storage::SpecialStoragePolicy* special_storage_policy,
ChromeBlobStorageContext* blob_context,
@@ -853,12 +849,12 @@ void ServiceWorkerContextWrapper::InitInternal(
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&ServiceWorkerContextWrapper::InitInternal, this,
- user_data_directory, base::Passed(&database_task_manager),
- disk_cache_thread, base::RetainedRef(quota_manager_proxy),
- base::RetainedRef(special_storage_policy),
- base::RetainedRef(blob_context),
- base::RetainedRef(loader_factory_getter)));
+ base::BindOnce(&ServiceWorkerContextWrapper::InitInternal, this,
+ user_data_directory, std::move(database_task_runner),
+ base::RetainedRef(quota_manager_proxy),
+ base::RetainedRef(special_storage_policy),
+ base::RetainedRef(blob_context),
+ base::RetainedRef(loader_factory_getter)));
return;
}
// TODO(pkasting): Remove ScopedTracker below once crbug.com/477117 is fixed.
@@ -875,9 +871,9 @@ void ServiceWorkerContextWrapper::InitInternal(
? blob_context->context()->AsWeakPtr()
: nullptr;
context_core_.reset(new ServiceWorkerContextCore(
- user_data_directory, std::move(database_task_manager), disk_cache_thread,
- quota_manager_proxy, special_storage_policy, blob_storage_context,
- loader_factory_getter, core_observer_list_.get(), this));
+ user_data_directory, std::move(database_task_runner), quota_manager_proxy,
+ special_storage_policy, blob_storage_context, loader_factory_getter,
+ core_observer_list_.get(), this));
}
void ServiceWorkerContextWrapper::ShutdownOnIO() {
@@ -940,7 +936,7 @@ void ServiceWorkerContextWrapper::StartServiceWorkerForNavigationHint(
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(
+ base::BindOnce(
&ServiceWorkerContextWrapper::StartServiceWorkerForNavigationHintOnIO,
this, document_url,
base::Bind(&ServiceWorkerContextWrapper::
@@ -1020,17 +1016,7 @@ void ServiceWorkerContextWrapper::
DCHECK_CURRENTLY_ON(BrowserThread::IO);
ServiceWorkerMetrics::RecordStartServiceWorkerForNavigationHintResult(result);
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(callback, result));
-}
-
-void ServiceWorkerContextWrapper::BindWorkerFetchContext(
- int render_process_id,
- int service_worker_provider_id,
- mojom::ServiceWorkerWorkerClientAssociatedPtrInfo client_ptr_info) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- context()->BindWorkerFetchContext(render_process_id,
- service_worker_provider_id,
- std::move(client_ptr_info));
+ base::BindOnce(callback, result));
}
ServiceWorkerContextCore* ServiceWorkerContextWrapper::context() {
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 ecce8e1509d..29d3839972e 100644
--- a/chromium/content/browser/service_worker/service_worker_context_wrapper.h
+++ b/chromium/content/browser/service_worker/service_worker_context_wrapper.h
@@ -18,12 +18,10 @@
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_context_core_observer.h"
#include "content/common/content_export.h"
-#include "content/common/worker_url_loader_factory_provider.mojom.h"
#include "content/public/browser/service_worker_context.h"
namespace base {
class FilePath;
-class SingleThreadTaskRunner;
}
namespace storage {
@@ -45,7 +43,7 @@ class URLLoaderFactoryGetter;
// instance is strictly single threaded and is not refcounted, the core object
// is what is used internally in the service worker lib.
class CONTENT_EXPORT ServiceWorkerContextWrapper
- : NON_EXPORTED_BASE(public ServiceWorkerContext),
+ : public ServiceWorkerContext,
public ServiceWorkerContextCoreObserver,
public base::RefCountedThreadSafe<ServiceWorkerContextWrapper> {
public:
@@ -250,14 +248,6 @@ class CONTENT_EXPORT ServiceWorkerContextWrapper
// Must be called from the IO thread.
bool OriginHasForeignFetchRegistrations(const GURL& origin);
- // Binds the ServiceWorkerWorkerClient of a dedicated (or shared) worker to
- // the parent frame's ServiceWorkerProviderHost. (This is used only when
- // off-main-thread-fetch is enabled.)
- void BindWorkerFetchContext(
- int render_process_id,
- int service_worker_provider_id,
- mojom::ServiceWorkerWorkerClientAssociatedPtrInfo client_ptr_info);
-
private:
friend class BackgroundSyncManagerTest;
friend class base::RefCountedThreadSafe<ServiceWorkerContextWrapper>;
@@ -276,8 +266,7 @@ class CONTENT_EXPORT ServiceWorkerContextWrapper
void InitInternal(
const base::FilePath& user_data_directory,
- std::unique_ptr<ServiceWorkerDatabaseTaskManager> database_task_manager,
- const scoped_refptr<base::SingleThreadTaskRunner>& disk_cache_thread,
+ scoped_refptr<base::SequencedTaskRunner> database_task_runner,
storage::QuotaManagerProxy* quota_manager_proxy,
storage::SpecialStoragePolicy* special_storage_policy,
ChromeBlobStorageContext* blob_context,
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 8196d4e580e..19acfff5e20 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
@@ -171,7 +171,7 @@ net::URLRequestJob* ServiceWorkerControlleeRequestHandler::MaybeCreateJob(
resource_context_ = resource_context;
if (is_main_resource_load_)
- PrepareForMainResource(request->url(), request->first_party_for_cookies());
+ PrepareForMainResource(request->url(), request->site_for_cookies());
else
PrepareForSubResource();
@@ -228,7 +228,7 @@ void ServiceWorkerControlleeRequestHandler::MaybeCreateLoader(
resource_context_ = resource_context;
PrepareForMainResource(resource_request.url,
- resource_request.first_party_for_cookies);
+ resource_request.site_for_cookies);
if (url_job_->ShouldFallbackToNetwork()) {
// We're falling back to the next URLLoaderRequestHandler, forward
@@ -243,7 +243,7 @@ void ServiceWorkerControlleeRequestHandler::MaybeCreateLoader(
void ServiceWorkerControlleeRequestHandler::PrepareForMainResource(
const GURL& url,
- const GURL& first_party_for_cookies) {
+ const GURL& site_for_cookies) {
DCHECK(!JobWasCanceled());
DCHECK(context_);
DCHECK(provider_host_);
@@ -261,7 +261,7 @@ void ServiceWorkerControlleeRequestHandler::PrepareForMainResource(
stripped_url_ = net::SimplifyUrlForRequest(url);
provider_host_->SetDocumentUrl(stripped_url_);
- provider_host_->SetTopmostFrameUrl(first_party_for_cookies);
+ provider_host_->SetTopmostFrameUrl(site_for_cookies);
context_->storage()->FindRegistrationForDocument(
stripped_url_, base::Bind(&self::DidLookupRegistrationForMainResource,
weak_factory_.GetWeakPtr()));
@@ -349,7 +349,7 @@ void ServiceWorkerControlleeRequestHandler::
if (active_version.get() &&
active_version->status() == ServiceWorkerVersion::ACTIVATING) {
provider_host_->SetAllowAssociation(false);
- registration->active_version()->RegisterStatusChangeCallback(base::Bind(
+ registration->active_version()->RegisterStatusChangeCallback(base::BindOnce(
&self::OnVersionStatusChanged, weak_factory_.GetWeakPtr(),
base::RetainedRef(registration), base::RetainedRef(active_version)));
TRACE_EVENT_ASYNC_END2(
@@ -451,7 +451,7 @@ void ServiceWorkerControlleeRequestHandler::DidUpdateRegistration(
original_registration->installing_version();
new_version->ReportForceUpdateToDevTools();
new_version->set_skip_waiting(true);
- new_version->RegisterStatusChangeCallback(base::Bind(
+ new_version->RegisterStatusChangeCallback(base::BindOnce(
&self::OnUpdatedVersionStatusChanged, weak_factory_.GetWeakPtr(),
original_registration, new_version));
}
@@ -478,8 +478,8 @@ void ServiceWorkerControlleeRequestHandler::OnUpdatedVersionStatusChanged(
return;
}
version->RegisterStatusChangeCallback(
- base::Bind(&self::OnUpdatedVersionStatusChanged,
- weak_factory_.GetWeakPtr(), registration, version));
+ base::BindOnce(&self::OnUpdatedVersionStatusChanged,
+ weak_factory_.GetWeakPtr(), registration, version));
}
void ServiceWorkerControlleeRequestHandler::PrepareForSubResource() {
@@ -493,8 +493,8 @@ void ServiceWorkerControlleeRequestHandler::PrepareForSubResource() {
// because a permanent failure occurred when trying to start it.
//
// As this is an exceptional case, just error out.
- // TODO(falken): Figure out if |active_version| can change to
- // |controlling_version| and do it or document the findings.
+ // TODO(falken): Figure out if |active_version| can change to |controller| and
+ // do it or document the findings.
if (!provider_host_->active_version()) {
url_job_->FailDueToLostController();
return;
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 c746d25453e..6877783a583 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
@@ -21,7 +21,6 @@
#include "content/public/common/request_context_type.h"
#include "content/public/common/resource_type.h"
#include "content/public/common/service_worker_modes.h"
-#include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerResponseType.h"
#include "url/gurl.h"
namespace net {
@@ -83,8 +82,7 @@ class CONTENT_EXPORT ServiceWorkerControlleeRequestHandler
typedef ServiceWorkerControlleeRequestHandler self;
// For main resource case.
- void PrepareForMainResource(const GURL& url,
- const GURL& first_party_for_cookies);
+ void PrepareForMainResource(const GURL& url, const GURL& site_for_cookies);
void DidLookupRegistrationForMainResource(
ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration);
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 c0a964a3d8c..e7fc0182d85 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
@@ -17,6 +17,7 @@
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_provider_host.h"
#include "content/browser/service_worker/service_worker_registration.h"
+#include "content/browser/service_worker/service_worker_response_type.h"
#include "content/browser/service_worker/service_worker_test_utils.h"
#include "content/browser/service_worker/service_worker_url_request_job.h"
#include "content/common/service_worker/service_worker_types.h"
@@ -253,7 +254,7 @@ TEST_F(ServiceWorkerControlleeRequestHandlerTest, InstallingRegistration) {
EXPECT_EQ(registration_.get(), provider_host_->associated_registration());
EXPECT_EQ(version_.get(), provider_host_->installing_version());
EXPECT_FALSE(version_->HasControllee());
- EXPECT_FALSE(provider_host_->controlling_version());
+ EXPECT_FALSE(provider_host_->controller());
}
// Test to not regress crbug/414118.
@@ -310,14 +311,14 @@ TEST_F(ServiceWorkerControlleeRequestHandlerTest, LostActiveVersion) {
main_test_resources.MaybeCreateJob();
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(version_->HasControllee());
- EXPECT_EQ(version_, provider_host_->controlling_version());
+ EXPECT_EQ(version_, provider_host_->controller());
EXPECT_EQ(version_, provider_host_->active_version());
// Unset the active version.
provider_host_->NotifyControllerLost();
registration_->SetActiveVersion(nullptr);
EXPECT_FALSE(version_->HasControllee());
- EXPECT_FALSE(provider_host_->controlling_version());
+ EXPECT_FALSE(provider_host_->controller());
EXPECT_FALSE(provider_host_->active_version());
// Conduct a subresource load.
@@ -327,9 +328,8 @@ TEST_F(ServiceWorkerControlleeRequestHandlerTest, LostActiveVersion) {
base::RunLoop().RunUntilIdle();
// Verify that the job errored.
- EXPECT_EQ(
- ServiceWorkerURLRequestJob::ResponseType::FAIL_DUE_TO_LOST_CONTROLLER,
- sub_job->response_type_);
+ EXPECT_EQ(ServiceWorkerResponseType::FAIL_DUE_TO_LOST_CONTROLLER,
+ sub_job->response_type_);
}
TEST_F(ServiceWorkerControlleeRequestHandlerTest, FallbackWithNoFetchHandler) {
@@ -355,7 +355,7 @@ TEST_F(ServiceWorkerControlleeRequestHandlerTest, FallbackWithNoFetchHandler) {
EXPECT_TRUE(main_job->ShouldFallbackToNetwork());
EXPECT_FALSE(main_job->ShouldForwardToServiceWorker());
EXPECT_TRUE(version_->HasControllee());
- EXPECT_EQ(version_, provider_host_->controlling_version());
+ EXPECT_EQ(version_, provider_host_->controller());
ServiceWorkerRequestTestResources sub_test_resources(
this, GURL("https://host/scope/doc/subresource"), RESOURCE_TYPE_IMAGE);
diff --git a/chromium/content/browser/service_worker/service_worker_data_pipe_reader.cc b/chromium/content/browser/service_worker/service_worker_data_pipe_reader.cc
index d31543018d3..99207bf4f4f 100644
--- a/chromium/content/browser/service_worker/service_worker_data_pipe_reader.cc
+++ b/chromium/content/browser/service_worker/service_worker_data_pipe_reader.cc
@@ -25,7 +25,7 @@ ServiceWorkerDataPipeReader::ServiceWorkerDataPipeReader(
TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker", "ServiceWorkerDataPipeReader", this,
"Url", owner->request()->url().spec());
streaming_version_->AddStreamingURLRequestJob(owner_);
- binding_.set_connection_error_handler(base::Bind(
+ binding_.set_connection_error_handler(base::BindOnce(
&ServiceWorkerDataPipeReader::OnAborted, base::Unretained(this)));
}
@@ -66,9 +66,8 @@ void ServiceWorkerDataPipeReader::OnHandleGotSignal(MojoResult) {
// |stream_pending_buffer_| is set to the IOBuffer instance provided to
// ReadRawData() by URLRequestJob.
uint32_t size_to_pass = stream_pending_buffer_size_;
- MojoResult mojo_result =
- mojo::ReadDataRaw(stream_.get(), stream_pending_buffer_->data(),
- &size_to_pass, MOJO_READ_DATA_FLAG_NONE);
+ MojoResult mojo_result = stream_->ReadData(
+ stream_pending_buffer_->data(), &size_to_pass, MOJO_READ_DATA_FLAG_NONE);
switch (mojo_result) {
case MOJO_RESULT_OK:
@@ -104,8 +103,8 @@ int ServiceWorkerDataPipeReader::ReadRawData(net::IOBuffer* buf, int buf_size) {
return SyncComplete();
uint32_t size_to_pass = buf_size;
- MojoResult mojo_result = mojo::ReadDataRaw(
- stream_.get(), buf->data(), &size_to_pass, MOJO_READ_DATA_FLAG_NONE);
+ MojoResult mojo_result =
+ stream_->ReadData(buf->data(), &size_to_pass, MOJO_READ_DATA_FLAG_NONE);
switch (mojo_result) {
case MOJO_RESULT_OK:
return size_to_pass;
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 7c4d952da4d..a769dba54bf 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
@@ -160,9 +160,8 @@ TEST_P(ServiceWorkerDataPipeReaderTestP, SyncRead) {
for (int i = 0; i < 1024; ++i) {
expected_response += kTestData;
uint32_t written_bytes = sizeof(kTestData) - 1;
- MojoResult result =
- mojo::WriteDataRaw(data_pipe.producer_handle.get(), kTestData,
- &written_bytes, MOJO_WRITE_DATA_FLAG_NONE);
+ MojoResult result = data_pipe.producer_handle->WriteData(
+ kTestData, &written_bytes, MOJO_WRITE_DATA_FLAG_NONE);
ASSERT_EQ(MOJO_RESULT_OK, result);
EXPECT_EQ(sizeof(kTestData) - 1, written_bytes);
}
@@ -217,9 +216,8 @@ TEST_P(ServiceWorkerDataPipeReaderTestP, SyncAbort) {
for (int i = 0; i < 1024; ++i) {
expected_response += kTestData;
uint32_t written_bytes = sizeof(kTestData) - 1;
- MojoResult result =
- mojo::WriteDataRaw(data_pipe.producer_handle.get(), kTestData,
- &written_bytes, MOJO_WRITE_DATA_FLAG_NONE);
+ MojoResult result = data_pipe.producer_handle->WriteData(
+ kTestData, &written_bytes, MOJO_WRITE_DATA_FLAG_NONE);
ASSERT_EQ(MOJO_RESULT_OK, result);
EXPECT_EQ(sizeof(kTestData) - 1, written_bytes);
}
@@ -290,9 +288,8 @@ TEST_P(ServiceWorkerDataPipeReaderTestP, AsyncRead) {
// Push a portion of data.
uint32_t written_bytes = sizeof(kTestData) - 1;
- MojoResult result =
- mojo::WriteDataRaw(data_pipe.producer_handle.get(), kTestData,
- &written_bytes, MOJO_WRITE_DATA_FLAG_NONE);
+ MojoResult result = data_pipe.producer_handle->WriteData(
+ kTestData, &written_bytes, MOJO_WRITE_DATA_FLAG_NONE);
ASSERT_EQ(MOJO_RESULT_OK, result);
EXPECT_EQ(sizeof(kTestData) - 1, written_bytes);
expected_response += kTestData;
@@ -364,9 +361,8 @@ TEST_P(ServiceWorkerDataPipeReaderTestP, AsyncAbort) {
// Push a portion of data.
uint32_t written_bytes = sizeof(kTestData) - 1;
- MojoResult result =
- mojo::WriteDataRaw(data_pipe.producer_handle.get(), kTestData,
- &written_bytes, MOJO_WRITE_DATA_FLAG_NONE);
+ MojoResult result = data_pipe.producer_handle->WriteData(
+ kTestData, &written_bytes, MOJO_WRITE_DATA_FLAG_NONE);
ASSERT_EQ(MOJO_RESULT_OK, result);
EXPECT_EQ(sizeof(kTestData) - 1, written_bytes);
expected_response += kTestData;
diff --git a/chromium/content/browser/service_worker/service_worker_database.cc b/chromium/content/browser/service_worker/service_worker_database.cc
index 93480c4bc58..608186f6029 100644
--- a/chromium/content/browser/service_worker/service_worker_database.cc
+++ b/chromium/content/browser/service_worker/service_worker_database.cc
@@ -1192,7 +1192,7 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::DestroyDatabase() {
return STATUS_OK;
}
- // Directly delete the database directory instead of leveldb::DestroyDB()
+ // Directly delete the database instead of calling leveldb::DestroyDB()
// because the API does not delete the directory if there are unrelated files.
// (https://code.google.com/p/chromium/issues/detail?id=468926#c24)
Status status = base::DeleteFile(path_, true /* recursive */)
@@ -1220,9 +1220,8 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::LazyOpen(
}
}
- leveldb::Options options;
+ leveldb_env::Options options;
options.create_if_missing = create_if_missing;
- options.reuse_logs = leveldb_env::kDefaultLogReuseOptionValue;
if (IsDatabaseInMemory()) {
env_.reset(leveldb::NewMemEnv(leveldb::Env::Default()));
options.env = env_.get();
diff --git a/chromium/content/browser/service_worker/service_worker_database_task_manager.cc b/chromium/content/browser/service_worker/service_worker_database_task_manager.cc
deleted file mode 100644
index 804941bf4c8..00000000000
--- a/chromium/content/browser/service_worker/service_worker_database_task_manager.cc
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/service_worker/service_worker_database_task_manager.h"
-
-#include "base/memory/ptr_util.h"
-#include "base/sequenced_task_runner.h"
-
-namespace content {
-
-ServiceWorkerDatabaseTaskManagerImpl::ServiceWorkerDatabaseTaskManagerImpl(
- base::SequencedWorkerPool* pool) {
- base::SequencedWorkerPool::SequenceToken token = pool->GetSequenceToken();
- task_runner_ = pool->GetSequencedTaskRunner(token);
- shutdown_blocking_task_runner_ =
- pool->GetSequencedTaskRunnerWithShutdownBehavior(
- token, base::SequencedWorkerPool::BLOCK_SHUTDOWN);
-}
-
-ServiceWorkerDatabaseTaskManagerImpl::~ServiceWorkerDatabaseTaskManagerImpl() {
-}
-
-std::unique_ptr<ServiceWorkerDatabaseTaskManager>
-ServiceWorkerDatabaseTaskManagerImpl::Clone() {
- return base::WrapUnique(new ServiceWorkerDatabaseTaskManagerImpl(
- task_runner_, shutdown_blocking_task_runner_));
-}
-
-base::SequencedTaskRunner*
-ServiceWorkerDatabaseTaskManagerImpl::GetTaskRunner() {
- return task_runner_.get();
-}
-
-base::SequencedTaskRunner*
-ServiceWorkerDatabaseTaskManagerImpl::GetShutdownBlockingTaskRunner() {
- return shutdown_blocking_task_runner_.get();
-}
-
-ServiceWorkerDatabaseTaskManagerImpl::ServiceWorkerDatabaseTaskManagerImpl(
- const scoped_refptr<base::SequencedTaskRunner>& task_runner,
- const scoped_refptr<base::SequencedTaskRunner>&
- shutdown_blocking_task_runner)
- : task_runner_(task_runner),
- shutdown_blocking_task_runner_(shutdown_blocking_task_runner) {
-}
-
-MockServiceWorkerDatabaseTaskManager::MockServiceWorkerDatabaseTaskManager(
- const scoped_refptr<base::SequencedTaskRunner>& task_runner)
- : task_runner_(task_runner) {
-}
-
-MockServiceWorkerDatabaseTaskManager::~MockServiceWorkerDatabaseTaskManager() {
-}
-
-std::unique_ptr<ServiceWorkerDatabaseTaskManager>
-MockServiceWorkerDatabaseTaskManager::Clone() {
- return base::WrapUnique(
- new MockServiceWorkerDatabaseTaskManager(task_runner_));
-}
-
-base::SequencedTaskRunner*
-MockServiceWorkerDatabaseTaskManager::GetTaskRunner() {
- return task_runner_.get();
-}
-
-base::SequencedTaskRunner*
-MockServiceWorkerDatabaseTaskManager::GetShutdownBlockingTaskRunner() {
- return task_runner_.get();
-}
-
-} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_database_task_manager.h b/chromium/content/browser/service_worker/service_worker_database_task_manager.h
deleted file mode 100644
index 5f2e8167dfc..00000000000
--- a/chromium/content/browser/service_worker/service_worker_database_task_manager.h
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_DATABASE_TASK_MANAGER_H_
-#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_DATABASE_TASK_MANAGER_H_
-
-#include <memory>
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/threading/sequenced_worker_pool.h"
-#include "content/common/content_export.h"
-
-namespace base {
-class SequencedTaskRunner;
-}
-
-namespace content {
-
-// Used to sequence ServiceWorkerDatabase tasks. Vends two task runners: one
-// that blocks shutdown and one that doesn't. The task runners use the same
-// sequence token, so no matter which runner you post to, the tasks run in the
-// order they are posted. This lets you post sequenced tasks with mixed shutdown
-// behaviors.
-class ServiceWorkerDatabaseTaskManager {
- public:
- virtual ~ServiceWorkerDatabaseTaskManager() {}
- virtual std::unique_ptr<ServiceWorkerDatabaseTaskManager> Clone() = 0;
- virtual base::SequencedTaskRunner* GetTaskRunner() = 0;
- virtual base::SequencedTaskRunner* GetShutdownBlockingTaskRunner() = 0;
-};
-
-class ServiceWorkerDatabaseTaskManagerImpl
- : public ServiceWorkerDatabaseTaskManager {
- public:
- explicit ServiceWorkerDatabaseTaskManagerImpl(
- base::SequencedWorkerPool* pool);
- ~ServiceWorkerDatabaseTaskManagerImpl() override;
-
- protected:
- std::unique_ptr<ServiceWorkerDatabaseTaskManager> Clone() override;
- base::SequencedTaskRunner* GetTaskRunner() override;
- base::SequencedTaskRunner* GetShutdownBlockingTaskRunner() override;
-
- private:
- ServiceWorkerDatabaseTaskManagerImpl(
- const scoped_refptr<base::SequencedTaskRunner>& task_runner,
- const scoped_refptr<base::SequencedTaskRunner>&
- shutdown_blocking_task_runner);
-
- scoped_refptr<base::SequencedTaskRunner> task_runner_;
- scoped_refptr<base::SequencedTaskRunner> shutdown_blocking_task_runner_;
-
- DISALLOW_COPY_AND_ASSIGN(ServiceWorkerDatabaseTaskManagerImpl);
-};
-
-// Dummy implementation for testing. It vends whatever you give it in the ctor.
-class CONTENT_EXPORT MockServiceWorkerDatabaseTaskManager
- : public NON_EXPORTED_BASE(ServiceWorkerDatabaseTaskManager) {
- public:
- explicit MockServiceWorkerDatabaseTaskManager(
- const scoped_refptr<base::SequencedTaskRunner>& task_runner);
- ~MockServiceWorkerDatabaseTaskManager() override;
-
- protected:
- std::unique_ptr<ServiceWorkerDatabaseTaskManager> Clone() override;
- base::SequencedTaskRunner* GetTaskRunner() override;
- base::SequencedTaskRunner* GetShutdownBlockingTaskRunner() override;
-
- private:
- scoped_refptr<base::SequencedTaskRunner> task_runner_;
-
- DISALLOW_COPY_AND_ASSIGN(MockServiceWorkerDatabaseTaskManager);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_DATABASE_TASK_MANAGER_H_
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 07e8736110e..7b7a8c69f64 100644
--- a/chromium/content/browser/service_worker/service_worker_dispatcher_host.cc
+++ b/chromium/content/browser/service_worker/service_worker_dispatcher_host.cc
@@ -6,7 +6,6 @@
#include <utility>
-#include "base/debug/crash_logging.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
@@ -40,6 +39,7 @@
#include "ipc/ipc_message_macros.h"
#include "net/http/http_util.h"
#include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerError.h"
+#include "third_party/WebKit/public/platform/modules/serviceworker/service_worker_error_type.mojom.h"
#include "url/gurl.h"
using blink::WebServiceWorkerError;
@@ -91,28 +91,36 @@ ServiceWorkerDispatcherHost::ServiceWorkerDispatcherHost(
this),
render_process_id_(render_process_id),
resource_context_(resource_context),
- channel_ready_(false) {}
+ channel_ready_(false),
+ weak_ptr_factory_(this) {}
ServiceWorkerDispatcherHost::~ServiceWorkerDispatcherHost() {
// Temporary CHECK for debugging https://crbug.com/736203.
CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- if (GetContext())
+ if (GetContext() && phase_ == Phase::kAddedToContext)
GetContext()->RemoveDispatcherHost(render_process_id_);
}
void ServiceWorkerDispatcherHost::Init(
ServiceWorkerContextWrapper* context_wrapper) {
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::Bind(&ServiceWorkerDispatcherHost::Init, this,
- base::RetainedRef(context_wrapper)));
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&ServiceWorkerDispatcherHost::Init, this,
+ base::RetainedRef(context_wrapper)));
return;
}
+ // Just speculating that maybe we were destructed before Init() was called on
+ // the IO thread in order to try to fix https://crbug.com/750267.
+ if (phase_ != Phase::kInitial)
+ return;
+
context_wrapper_ = context_wrapper;
if (!GetContext())
return;
GetContext()->AddDispatcherHost(render_process_id_, this);
+ phase_ = Phase::kAddedToContext;
}
void ServiceWorkerDispatcherHost::OnFilterAdded(IPC::Channel* channel) {
@@ -133,8 +141,11 @@ void ServiceWorkerDispatcherHost::OnFilterRemoved() {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
// Don't wait until the destructor to teardown since a new dispatcher host
// for this process might be created before then.
- if (GetContext())
+ if (GetContext() && phase_ == Phase::kAddedToContext) {
GetContext()->RemoveDispatcherHost(render_process_id_);
+ weak_ptr_factory_.InvalidateWeakPtrs();
+ }
+ phase_ = Phase::kRemovedFromContext;
context_wrapper_ = nullptr;
channel_ready_ = false;
}
@@ -218,7 +229,8 @@ void ServiceWorkerDispatcherHost::RegisterServiceWorkerRegistrationHandle(
ServiceWorkerHandle* ServiceWorkerDispatcherHost::FindServiceWorkerHandle(
int provider_id,
int64_t version_id) {
- for (IDMap<std::unique_ptr<ServiceWorkerHandle>>::iterator iter(&handles_);
+ for (base::IDMap<std::unique_ptr<ServiceWorkerHandle>>::iterator iter(
+ &handles_);
!iter.IsAtEnd(); iter.Advance()) {
ServiceWorkerHandle* handle = iter.GetCurrentValue();
DCHECK(handle);
@@ -242,7 +254,6 @@ ServiceWorkerDispatcherHost::GetOrCreateRegistrationHandle(
existing_handle->IncrementRefCount();
return existing_handle;
}
-
std::unique_ptr<ServiceWorkerRegistrationHandle> new_handle(
new ServiceWorkerRegistrationHandle(GetContext()->AsWeakPtr(),
provider_host, registration));
@@ -251,6 +262,11 @@ ServiceWorkerDispatcherHost::GetOrCreateRegistrationHandle(
return new_handle_ptr;
}
+base::WeakPtr<ServiceWorkerDispatcherHost>
+ServiceWorkerDispatcherHost::AsWeakPtr() {
+ return weak_ptr_factory_.GetWeakPtr();
+}
+
void ServiceWorkerDispatcherHost::OnRegisterServiceWorker(
int thread_id,
int request_id,
@@ -266,7 +282,7 @@ void ServiceWorkerDispatcherHost::OnRegisterServiceWorker(
case ProviderStatus::NO_CONTEXT: // fallthrough
case ProviderStatus::DEAD_HOST:
Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
- thread_id, request_id, WebServiceWorkerError::kErrorTypeAbort,
+ thread_id, request_id, blink::mojom::ServiceWorkerErrorType::kAbort,
base::ASCIIToUTF16(kServiceWorkerRegisterErrorPrefix) +
base::ASCIIToUTF16(kShutdownErrorMessage)));
return;
@@ -275,7 +291,8 @@ void ServiceWorkerDispatcherHost::OnRegisterServiceWorker(
return;
case ProviderStatus::NO_URL:
Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
- thread_id, request_id, WebServiceWorkerError::kErrorTypeSecurity,
+ thread_id, request_id,
+ blink::mojom::ServiceWorkerErrorType::kSecurity,
base::ASCIIToUTF16(kServiceWorkerRegisterErrorPrefix) +
base::ASCIIToUTF16(kNoDocumentURLErrorMessage)));
return;
@@ -307,7 +324,7 @@ void ServiceWorkerDispatcherHost::OnRegisterServiceWorker(
base::Bind(&GetWebContents, render_process_id_,
provider_host->frame_id()))) {
Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
- thread_id, request_id, WebServiceWorkerError::kErrorTypeDisabled,
+ thread_id, request_id, blink::mojom::ServiceWorkerErrorType::kDisabled,
base::ASCIIToUTF16(kServiceWorkerRegisterErrorPrefix) +
base::ASCIIToUTF16(kUserDeniedPermissionMessage)));
return;
@@ -337,7 +354,7 @@ void ServiceWorkerDispatcherHost::OnUpdateServiceWorker(
case ProviderStatus::NO_CONTEXT: // fallthrough
case ProviderStatus::DEAD_HOST:
Send(new ServiceWorkerMsg_ServiceWorkerUpdateError(
- thread_id, request_id, WebServiceWorkerError::kErrorTypeAbort,
+ thread_id, request_id, blink::mojom::ServiceWorkerErrorType::kAbort,
base::ASCIIToUTF16(kServiceWorkerUpdateErrorPrefix) +
base::ASCIIToUTF16(kShutdownErrorMessage)));
return;
@@ -346,7 +363,8 @@ void ServiceWorkerDispatcherHost::OnUpdateServiceWorker(
return;
case ProviderStatus::NO_URL:
Send(new ServiceWorkerMsg_ServiceWorkerUpdateError(
- thread_id, request_id, WebServiceWorkerError::kErrorTypeSecurity,
+ thread_id, request_id,
+ blink::mojom::ServiceWorkerErrorType::kSecurity,
base::ASCIIToUTF16(kServiceWorkerUpdateErrorPrefix) +
base::ASCIIToUTF16(kNoDocumentURLErrorMessage)));
return;
@@ -376,7 +394,7 @@ void ServiceWorkerDispatcherHost::OnUpdateServiceWorker(
resource_context_, base::Bind(&GetWebContents, render_process_id_,
provider_host->frame_id()))) {
Send(new ServiceWorkerMsg_ServiceWorkerUpdateError(
- thread_id, request_id, WebServiceWorkerError::kErrorTypeDisabled,
+ thread_id, request_id, blink::mojom::ServiceWorkerErrorType::kDisabled,
base::ASCIIToUTF16(kServiceWorkerUpdateErrorPrefix) +
base::ASCIIToUTF16(kUserDeniedPermissionMessage)));
return;
@@ -386,7 +404,7 @@ void ServiceWorkerDispatcherHost::OnUpdateServiceWorker(
// This can happen if update() is called during initial script evaluation.
// Abort the following steps according to the spec.
Send(new ServiceWorkerMsg_ServiceWorkerUpdateError(
- thread_id, request_id, WebServiceWorkerError::kErrorTypeState,
+ thread_id, request_id, blink::mojom::ServiceWorkerErrorType::kState,
base::ASCIIToUTF16(kServiceWorkerUpdateErrorPrefix) +
base::ASCIIToUTF16(kInvalidStateErrorMessage)));
return;
@@ -416,7 +434,7 @@ void ServiceWorkerDispatcherHost::OnUnregisterServiceWorker(
case ProviderStatus::NO_CONTEXT: // fallthrough
case ProviderStatus::DEAD_HOST:
Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
- thread_id, request_id, WebServiceWorkerError::kErrorTypeAbort,
+ thread_id, request_id, blink::mojom::ServiceWorkerErrorType::kAbort,
base::ASCIIToUTF16(kServiceWorkerUpdateErrorPrefix) +
base::ASCIIToUTF16(kShutdownErrorMessage)));
return;
@@ -426,7 +444,8 @@ void ServiceWorkerDispatcherHost::OnUnregisterServiceWorker(
return;
case ProviderStatus::NO_URL:
Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
- thread_id, request_id, WebServiceWorkerError::kErrorTypeSecurity,
+ thread_id, request_id,
+ blink::mojom::ServiceWorkerErrorType::kSecurity,
base::ASCIIToUTF16(kServiceWorkerUnregisterErrorPrefix) +
base::ASCIIToUTF16(kNoDocumentURLErrorMessage)));
return;
@@ -456,7 +475,7 @@ void ServiceWorkerDispatcherHost::OnUnregisterServiceWorker(
resource_context_, base::Bind(&GetWebContents, render_process_id_,
provider_host->frame_id()))) {
Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
- thread_id, request_id, WebServiceWorkerError::kErrorTypeDisabled,
+ thread_id, request_id, blink::mojom::ServiceWorkerErrorType::kDisabled,
base::ASCIIToUTF16(kUserDeniedPermissionMessage)));
return;
}
@@ -486,7 +505,7 @@ void ServiceWorkerDispatcherHost::OnGetRegistration(
case ProviderStatus::NO_CONTEXT: // fallthrough
case ProviderStatus::DEAD_HOST:
Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
- thread_id, request_id, blink::WebServiceWorkerError::kErrorTypeAbort,
+ thread_id, request_id, blink::mojom::ServiceWorkerErrorType::kAbort,
base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix) +
base::ASCIIToUTF16(kShutdownErrorMessage)));
return;
@@ -496,7 +515,8 @@ void ServiceWorkerDispatcherHost::OnGetRegistration(
return;
case ProviderStatus::NO_URL:
Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
- thread_id, request_id, WebServiceWorkerError::kErrorTypeSecurity,
+ thread_id, request_id,
+ blink::mojom::ServiceWorkerErrorType::kSecurity,
base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix) +
base::ASCIIToUTF16(kNoDocumentURLErrorMessage)));
return;
@@ -522,7 +542,7 @@ void ServiceWorkerDispatcherHost::OnGetRegistration(
resource_context_, base::Bind(&GetWebContents, render_process_id_,
provider_host->frame_id()))) {
Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
- thread_id, request_id, WebServiceWorkerError::kErrorTypeDisabled,
+ thread_id, request_id, blink::mojom::ServiceWorkerErrorType::kDisabled,
base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix) +
base::ASCIIToUTF16(kUserDeniedPermissionMessage)));
return;
@@ -554,7 +574,7 @@ void ServiceWorkerDispatcherHost::OnGetRegistrations(int thread_id,
case ProviderStatus::NO_CONTEXT: // fallthrough
case ProviderStatus::DEAD_HOST:
Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationsError(
- thread_id, request_id, blink::WebServiceWorkerError::kErrorTypeAbort,
+ thread_id, request_id, blink::mojom::ServiceWorkerErrorType::kAbort,
base::ASCIIToUTF16(kServiceWorkerGetRegistrationsErrorPrefix) +
base::ASCIIToUTF16(kShutdownErrorMessage)));
return;
@@ -564,7 +584,8 @@ void ServiceWorkerDispatcherHost::OnGetRegistrations(int thread_id,
return;
case ProviderStatus::NO_URL:
Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationsError(
- thread_id, request_id, WebServiceWorkerError::kErrorTypeSecurity,
+ thread_id, request_id,
+ blink::mojom::ServiceWorkerErrorType::kSecurity,
base::ASCIIToUTF16(kServiceWorkerGetRegistrationsErrorPrefix) +
base::ASCIIToUTF16(kNoDocumentURLErrorMessage)));
return;
@@ -583,7 +604,7 @@ void ServiceWorkerDispatcherHost::OnGetRegistrations(int thread_id,
resource_context_, base::Bind(&GetWebContents, render_process_id_,
provider_host->frame_id()))) {
Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationsError(
- thread_id, request_id, WebServiceWorkerError::kErrorTypeDisabled,
+ thread_id, request_id, blink::mojom::ServiceWorkerErrorType::kDisabled,
base::ASCIIToUTF16(kServiceWorkerGetRegistrationsErrorPrefix) +
base::ASCIIToUTF16(kUserDeniedPermissionMessage)));
return;
@@ -640,7 +661,7 @@ void ServiceWorkerDispatcherHost::OnEnableNavigationPreload(
case ProviderStatus::NO_CONTEXT: // fallthrough
case ProviderStatus::DEAD_HOST:
Send(new ServiceWorkerMsg_EnableNavigationPreloadError(
- thread_id, request_id, WebServiceWorkerError::kErrorTypeAbort,
+ thread_id, request_id, blink::mojom::ServiceWorkerErrorType::kAbort,
std::string(kEnableNavigationPreloadErrorPrefix) +
std::string(kShutdownErrorMessage)));
return;
@@ -650,7 +671,8 @@ void ServiceWorkerDispatcherHost::OnEnableNavigationPreload(
return;
case ProviderStatus::NO_URL:
Send(new ServiceWorkerMsg_EnableNavigationPreloadError(
- thread_id, request_id, WebServiceWorkerError::kErrorTypeSecurity,
+ thread_id, request_id,
+ blink::mojom::ServiceWorkerErrorType::kSecurity,
std::string(kEnableNavigationPreloadErrorPrefix) +
std::string(kNoDocumentURLErrorMessage)));
return;
@@ -667,12 +689,9 @@ void ServiceWorkerDispatcherHost::OnEnableNavigationPreload(
this, bad_message::SWDH_ENABLE_NAVIGATION_PRELOAD_BAD_REGISTRATION_ID);
return;
}
- // The spec discussion consensus is to reject if there is no active worker:
- // https://github.com/w3c/ServiceWorker/issues/920#issuecomment-262212670
- // TODO(falken): Remove this comment when the spec is updated.
if (!registration->active_version()) {
Send(new ServiceWorkerMsg_EnableNavigationPreloadError(
- thread_id, request_id, WebServiceWorkerError::kErrorTypeState,
+ thread_id, request_id, blink::mojom::ServiceWorkerErrorType::kState,
std::string(kEnableNavigationPreloadErrorPrefix) +
std::string(kNoActiveWorkerErrorMessage)));
return;
@@ -691,7 +710,7 @@ void ServiceWorkerDispatcherHost::OnEnableNavigationPreload(
resource_context_, base::Bind(&GetWebContents, render_process_id_,
provider_host->frame_id()))) {
Send(new ServiceWorkerMsg_EnableNavigationPreloadError(
- thread_id, request_id, WebServiceWorkerError::kErrorTypeDisabled,
+ thread_id, request_id, blink::mojom::ServiceWorkerErrorType::kDisabled,
std::string(kEnableNavigationPreloadErrorPrefix) +
std::string(kUserDeniedPermissionMessage)));
return;
@@ -716,7 +735,7 @@ void ServiceWorkerDispatcherHost::OnGetNavigationPreloadState(
case ProviderStatus::NO_CONTEXT: // fallthrough
case ProviderStatus::DEAD_HOST:
Send(new ServiceWorkerMsg_GetNavigationPreloadStateError(
- thread_id, request_id, WebServiceWorkerError::kErrorTypeAbort,
+ thread_id, request_id, blink::mojom::ServiceWorkerErrorType::kAbort,
std::string(kGetNavigationPreloadStateErrorPrefix) +
std::string(kShutdownErrorMessage)));
return;
@@ -726,7 +745,8 @@ void ServiceWorkerDispatcherHost::OnGetNavigationPreloadState(
return;
case ProviderStatus::NO_URL:
Send(new ServiceWorkerMsg_GetNavigationPreloadStateError(
- thread_id, request_id, WebServiceWorkerError::kErrorTypeSecurity,
+ thread_id, request_id,
+ blink::mojom::ServiceWorkerErrorType::kSecurity,
std::string(kGetNavigationPreloadStateErrorPrefix) +
std::string(kNoDocumentURLErrorMessage)));
return;
@@ -758,7 +778,7 @@ void ServiceWorkerDispatcherHost::OnGetNavigationPreloadState(
resource_context_, base::Bind(&GetWebContents, render_process_id_,
provider_host->frame_id()))) {
Send(new ServiceWorkerMsg_GetNavigationPreloadStateError(
- thread_id, request_id, WebServiceWorkerError::kErrorTypeDisabled,
+ thread_id, request_id, blink::mojom::ServiceWorkerErrorType::kDisabled,
std::string(kGetNavigationPreloadStateErrorPrefix) +
std::string(kUserDeniedPermissionMessage)));
return;
@@ -781,7 +801,7 @@ void ServiceWorkerDispatcherHost::OnSetNavigationPreloadHeader(
case ProviderStatus::NO_CONTEXT: // fallthrough
case ProviderStatus::DEAD_HOST:
Send(new ServiceWorkerMsg_SetNavigationPreloadHeaderError(
- thread_id, request_id, WebServiceWorkerError::kErrorTypeAbort,
+ thread_id, request_id, blink::mojom::ServiceWorkerErrorType::kAbort,
std::string(kSetNavigationPreloadHeaderErrorPrefix) +
std::string(kShutdownErrorMessage)));
return;
@@ -791,7 +811,8 @@ void ServiceWorkerDispatcherHost::OnSetNavigationPreloadHeader(
return;
case ProviderStatus::NO_URL:
Send(new ServiceWorkerMsg_SetNavigationPreloadHeaderError(
- thread_id, request_id, WebServiceWorkerError::kErrorTypeSecurity,
+ thread_id, request_id,
+ blink::mojom::ServiceWorkerErrorType::kSecurity,
std::string(kSetNavigationPreloadHeaderErrorPrefix) +
std::string(kNoDocumentURLErrorMessage)));
return;
@@ -809,12 +830,9 @@ void ServiceWorkerDispatcherHost::OnSetNavigationPreloadHeader(
bad_message::SWDH_SET_NAVIGATION_PRELOAD_HEADER_BAD_REGISTRATION_ID);
return;
}
- // The spec discussion consensus is to reject if there is no active worker:
- // https://github.com/w3c/ServiceWorker/issues/920#issuecomment-262212670
- // TODO(falken): Remove this comment when the spec is updated.
if (!registration->active_version()) {
Send(new ServiceWorkerMsg_SetNavigationPreloadHeaderError(
- thread_id, request_id, WebServiceWorkerError::kErrorTypeState,
+ thread_id, request_id, blink::mojom::ServiceWorkerErrorType::kState,
std::string(kSetNavigationPreloadHeaderErrorPrefix) +
std::string(kNoActiveWorkerErrorMessage)));
return;
@@ -841,7 +859,7 @@ void ServiceWorkerDispatcherHost::OnSetNavigationPreloadHeader(
resource_context_, base::Bind(&GetWebContents, render_process_id_,
provider_host->frame_id()))) {
Send(new ServiceWorkerMsg_SetNavigationPreloadHeaderError(
- thread_id, request_id, WebServiceWorkerError::kErrorTypeDisabled,
+ thread_id, request_id, blink::mojom::ServiceWorkerErrorType::kDisabled,
std::string(kSetNavigationPreloadHeaderErrorPrefix) +
std::string(kUserDeniedPermissionMessage)));
return;
@@ -952,9 +970,9 @@ void ServiceWorkerDispatcherHost::OnProviderCreated(
// If no host is found, create one.
if (provider_host == nullptr) {
- GetContext()->AddProviderHost(
- ServiceWorkerProviderHost::Create(render_process_id_, std::move(info),
- GetContext()->AsWeakPtr(), this));
+ GetContext()->AddProviderHost(ServiceWorkerProviderHost::Create(
+ render_process_id_, std::move(info), GetContext()->AsWeakPtr(),
+ AsWeakPtr()));
return;
}
@@ -965,98 +983,25 @@ void ServiceWorkerDispatcherHost::OnProviderCreated(
return;
}
provider_host->CompleteNavigationInitialized(render_process_id_,
- std::move(info), this);
+ std::move(info), AsWeakPtr());
GetContext()->AddProviderHost(std::move(provider_host));
} else {
+ // Provider host for controller should be pre-created on StartWorker in
+ // ServiceWorkerVersion.
+ if (info.type == SERVICE_WORKER_PROVIDER_FOR_CONTROLLER) {
+ bad_message::ReceivedBadMessage(
+ this, bad_message::SWDH_PROVIDER_CREATED_ILLEGAL_TYPE_CONTROLLER);
+ return;
+ }
if (ServiceWorkerUtils::IsBrowserAssignedProviderId(info.provider_id)) {
bad_message::ReceivedBadMessage(
this, bad_message::SWDH_PROVIDER_CREATED_BAD_ID);
return;
}
GetContext()->AddProviderHost(ServiceWorkerProviderHost::Create(
- render_process_id_, std::move(info), GetContext()->AsWeakPtr(), this));
- }
-}
-
-void ServiceWorkerDispatcherHost::OnSetHostedVersionId(
- int provider_id,
- int64_t version_id,
- int embedded_worker_id,
- mojom::URLLoaderFactoryAssociatedRequest request) {
- TRACE_EVENT0("ServiceWorker",
- "ServiceWorkerDispatcherHost::OnSetHostedVersionId");
- if (!GetContext())
- return;
- ServiceWorkerProviderHost* provider_host =
- GetContext()->GetProviderHost(render_process_id_, provider_id);
- if (!provider_host) {
- bad_message::ReceivedBadMessage(
- this, bad_message::SWDH_SET_HOSTED_VERSION_NO_HOST);
- return;
- }
-
- // This provider host must be specialized for a controller.
- if (provider_host->IsProviderForClient()) {
- bad_message::ReceivedBadMessage(
- this, bad_message::SWDH_SET_HOSTED_VERSION_INVALID_HOST);
- return;
+ render_process_id_, std::move(info), GetContext()->AsWeakPtr(),
+ AsWeakPtr()));
}
-
- // A service worker context associated with this provider host was destroyed
- // due to restarting the service worker system etc.
- if (!provider_host->IsContextAlive())
- return;
-
- // We might not be STARTING if the stop sequence was entered (STOPPING) or
- // ended up being detached (STOPPED).
- ServiceWorkerVersion* version = GetContext()->GetLiveVersion(version_id);
- if (!version || version->running_status() != EmbeddedWorkerStatus::STARTING)
- return;
-
- // If the version has a different embedded worker, assume the message is about
- // a detached worker and ignore.
- if (version->embedded_worker()->embedded_worker_id() != embedded_worker_id)
- return;
-
- // A process for the worker must be equal to a process for the provider host.
- if (version->embedded_worker()->process_id() != provider_host->process_id()) {
- // Temporary debugging for https://crbug.com/668633
- base::debug::ScopedCrashKey scope_worker_pid(
- "swdh_set_hosted_version_worker_pid",
- base::IntToString(version->embedded_worker()->process_id()));
- base::debug::ScopedCrashKey scope_provider_host_pid(
- "swdh_set_hosted_version_host_pid",
- base::IntToString(provider_host->process_id()));
- base::debug::ScopedCrashKey scope_worker_restart_count(
- "swdh_set_hosted_version_restart_count",
- base::IntToString(version->embedded_worker()->restart_count()));
- bad_message::ReceivedBadMessage(
- this, bad_message::SWDH_SET_HOSTED_VERSION_PROCESS_MISMATCH);
- return;
- }
-
- provider_host->SetHostedVersion(version);
-
- if (ServiceWorkerUtils::IsServicificationEnabled())
- provider_host->CreateScriptURLLoaderFactory(std::move(request));
-
- // Retrieve the registration associated with |version|. The registration
- // must be alive because the version keeps it during starting worker.
- ServiceWorkerRegistration* registration =
- GetContext()->GetLiveRegistration(version->registration_id());
- DCHECK(registration);
-
- // Set the document URL to the script url in order to allow
- // register/unregister/getRegistration on ServiceWorkerGlobalScope.
- provider_host->SetDocumentUrl(version->script_url());
-
- ServiceWorkerRegistrationObjectInfo info;
- ServiceWorkerVersionAttributes attrs;
- GetRegistrationObjectInfoAndVersionAttributes(provider_host->AsWeakPtr(),
- registration, &info, &attrs);
-
- Send(new ServiceWorkerMsg_AssociateRegistration(kDocumentMainThreadId,
- provider_id, info, attrs));
}
template <typename SourceInfo>
@@ -1085,10 +1030,11 @@ void ServiceWorkerDispatcherHost::DispatchExtendableMessageEventInternal(
worker->RunAfterStartWorker(
ServiceWorkerMetrics::EventType::MESSAGE,
- base::Bind(&ServiceWorkerDispatcherHost::
- DispatchExtendableMessageEventAfterStartWorker,
- this, worker, message, source_origin, sent_message_ports,
- ExtendableMessageEventSource(source_info), timeout, callback),
+ base::BindOnce(&ServiceWorkerDispatcherHost::
+ DispatchExtendableMessageEventAfterStartWorker,
+ this, worker, message, source_origin, sent_message_ports,
+ ExtendableMessageEventSource(source_info), timeout,
+ callback),
base::Bind(
&ServiceWorkerDispatcherHost::DidFailToDispatchExtendableMessageEvent<
SourceInfo>,
@@ -1175,17 +1121,17 @@ ServiceWorkerDispatcherHost::FindRegistrationHandle(int provider_id,
void ServiceWorkerDispatcherHost::GetRegistrationObjectInfoAndVersionAttributes(
base::WeakPtr<ServiceWorkerProviderHost> provider_host,
ServiceWorkerRegistration* registration,
- ServiceWorkerRegistrationObjectInfo* info,
- ServiceWorkerVersionAttributes* attrs) {
+ ServiceWorkerRegistrationObjectInfo* out_info,
+ ServiceWorkerVersionAttributes* out_attrs) {
ServiceWorkerRegistrationHandle* handle =
GetOrCreateRegistrationHandle(provider_host, registration);
- *info = handle->GetObjectInfo();
+ *out_info = handle->GetObjectInfo();
- attrs->installing = provider_host->GetOrCreateServiceWorkerHandle(
+ out_attrs->installing = provider_host->GetOrCreateServiceWorkerHandle(
registration->installing_version());
- attrs->waiting = provider_host->GetOrCreateServiceWorkerHandle(
+ out_attrs->waiting = provider_host->GetOrCreateServiceWorkerHandle(
registration->waiting_version());
- attrs->active = provider_host->GetOrCreateServiceWorkerHandle(
+ out_attrs->active = provider_host->GetOrCreateServiceWorkerHandle(
registration->active_version());
}
@@ -1209,7 +1155,7 @@ void ServiceWorkerDispatcherHost::RegistrationComplete(
if (status != SERVICE_WORKER_OK) {
base::string16 error_message;
- blink::WebServiceWorkerError::ErrorType error_type;
+ blink::mojom::ServiceWorkerErrorType error_type;
GetServiceWorkerRegistrationStatusResponse(status, status_message,
&error_type, &error_message);
Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
@@ -1251,7 +1197,7 @@ void ServiceWorkerDispatcherHost::UpdateComplete(
if (status != SERVICE_WORKER_OK) {
base::string16 error_message;
- blink::WebServiceWorkerError::ErrorType error_type;
+ blink::mojom::ServiceWorkerErrorType error_type;
GetServiceWorkerRegistrationStatusResponse(status, status_message,
&error_type, &error_message);
Send(new ServiceWorkerMsg_ServiceWorkerUpdateError(
@@ -1349,7 +1295,7 @@ void ServiceWorkerDispatcherHost::UnregistrationComplete(
request_id, "Status", status);
if (status != SERVICE_WORKER_OK && status != SERVICE_WORKER_ERROR_NOT_FOUND) {
base::string16 error_message;
- blink::WebServiceWorkerError::ErrorType error_type;
+ blink::mojom::ServiceWorkerErrorType error_type;
GetServiceWorkerRegistrationStatusResponse(status, std::string(),
&error_type, &error_message);
Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
@@ -1384,7 +1330,7 @@ void ServiceWorkerDispatcherHost::GetRegistrationComplete(
if (status != SERVICE_WORKER_OK && status != SERVICE_WORKER_ERROR_NOT_FOUND) {
base::string16 error_message;
- blink::WebServiceWorkerError::ErrorType error_type;
+ blink::mojom::ServiceWorkerErrorType error_type;
GetServiceWorkerRegistrationStatusResponse(status, std::string(),
&error_type, &error_message);
Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
@@ -1429,7 +1375,7 @@ void ServiceWorkerDispatcherHost::GetRegistrationsComplete(
if (status != SERVICE_WORKER_OK) {
base::string16 error_message;
- blink::WebServiceWorkerError::ErrorType error_type;
+ blink::mojom::ServiceWorkerErrorType error_type;
GetServiceWorkerRegistrationStatusResponse(status, std::string(),
&error_type, &error_message);
Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationsError(
@@ -1526,7 +1472,7 @@ void ServiceWorkerDispatcherHost::DidUpdateNavigationPreloadEnabled(
ServiceWorkerStatusCode status) {
if (status != SERVICE_WORKER_OK) {
Send(new ServiceWorkerMsg_EnableNavigationPreloadError(
- thread_id, request_id, WebServiceWorkerError::kErrorTypeUnknown,
+ thread_id, request_id, blink::mojom::ServiceWorkerErrorType::kUnknown,
std::string(kEnableNavigationPreloadErrorPrefix) +
std::string(kDatabaseErrorMessage)));
return;
@@ -1548,7 +1494,7 @@ void ServiceWorkerDispatcherHost::DidUpdateNavigationPreloadHeader(
ServiceWorkerStatusCode status) {
if (status != SERVICE_WORKER_OK) {
Send(new ServiceWorkerMsg_SetNavigationPreloadHeaderError(
- thread_id, request_id, WebServiceWorkerError::kErrorTypeUnknown,
+ thread_id, request_id, blink::mojom::ServiceWorkerErrorType::kUnknown,
std::string(kSetNavigationPreloadHeaderErrorPrefix) +
std::string(kDatabaseErrorMessage)));
return;
diff --git a/chromium/content/browser/service_worker/service_worker_dispatcher_host.h b/chromium/content/browser/service_worker/service_worker_dispatcher_host.h
index 688b0a62985..f4bdb7d2e4e 100644
--- a/chromium/content/browser/service_worker/service_worker_dispatcher_host.h
+++ b/chromium/content/browser/service_worker/service_worker_dispatcher_host.h
@@ -10,7 +10,7 @@
#include <memory>
#include <vector>
-#include "base/id_map.h"
+#include "base/containers/id_map.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
@@ -63,7 +63,8 @@ struct ServiceWorkerVersionAttributes;
//
// This class is bound with mojom::ServiceWorkerDispatcherHost. All
// InterfacePtrs on the same render process are bound to the same
-// content::ServiceWorkerDispatcherHost.
+// content::ServiceWorkerDispatcherHost. This can be overridden only for
+// testing.
class CONTENT_EXPORT ServiceWorkerDispatcherHost
: public BrowserMessageFilter,
public BrowserAssociatedInterface<mojom::ServiceWorkerDispatcherHost>,
@@ -89,19 +90,33 @@ class CONTENT_EXPORT ServiceWorkerDispatcherHost
// be destroyed.
bool Send(IPC::Message* message) override;
- void RegisterServiceWorkerHandle(std::unique_ptr<ServiceWorkerHandle> handle);
- void RegisterServiceWorkerRegistrationHandle(
+ // Virtual for testing.
+ virtual void RegisterServiceWorkerHandle(
+ std::unique_ptr<ServiceWorkerHandle> handle);
+ // Virtual for testing.
+ virtual void RegisterServiceWorkerRegistrationHandle(
std::unique_ptr<ServiceWorkerRegistrationHandle> handle);
ServiceWorkerHandle* FindServiceWorkerHandle(int provider_id,
int64_t version_id);
+ // Gets or creates the registration and version handles appropriate for
+ // representing |registration| inside of |provider_host|. Sets |out_info| and
+ // |out_attrs| accordingly for these handles.
+ void GetRegistrationObjectInfoAndVersionAttributes(
+ base::WeakPtr<ServiceWorkerProviderHost> provider_host,
+ ServiceWorkerRegistration* registration,
+ ServiceWorkerRegistrationObjectInfo* out_info,
+ ServiceWorkerVersionAttributes* out_attrs);
+
// Returns the existing registration handle whose reference count is
// incremented or a newly created one if it doesn't exist.
ServiceWorkerRegistrationHandle* GetOrCreateRegistrationHandle(
base::WeakPtr<ServiceWorkerProviderHost> provider_host,
ServiceWorkerRegistration* registration);
+ base::WeakPtr<ServiceWorkerDispatcherHost> AsWeakPtr();
+
protected:
~ServiceWorkerDispatcherHost() override;
@@ -114,17 +129,16 @@ class CONTENT_EXPORT ServiceWorkerDispatcherHost
ProviderCreatedAndDestroyed);
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDispatcherHostTest,
CleanupOnRendererCrash);
+ FRIEND_TEST_ALL_PREFIXES(BackgroundSyncManagerTest,
+ RegisterWithoutLiveSWRegistration);
using StatusCallback = base::Callback<void(ServiceWorkerStatusCode status)>;
enum class ProviderStatus { OK, NO_CONTEXT, DEAD_HOST, NO_HOST, NO_URL };
+ // Debugging for https://crbug.com/750267
+ enum class Phase { kInitial, kAddedToContext, kRemovedFromContext };
// mojom::ServiceWorkerDispatcherHost implementation
void OnProviderCreated(ServiceWorkerProviderHostInfo info) override;
- void OnSetHostedVersionId(
- int provider_id,
- int64_t version_id,
- int embedded_worker_id,
- mojom::URLLoaderFactoryAssociatedRequest request) override;
// IPC Message handlers
void OnRegisterServiceWorker(int thread_id,
@@ -213,12 +227,6 @@ class CONTENT_EXPORT ServiceWorkerDispatcherHost
int provider_id,
int64_t registration_handle_id);
- void GetRegistrationObjectInfoAndVersionAttributes(
- base::WeakPtr<ServiceWorkerProviderHost> provider_host,
- ServiceWorkerRegistration* registration,
- ServiceWorkerRegistrationObjectInfo* info,
- ServiceWorkerVersionAttributes* attrs);
-
// Callbacks from ServiceWorkerContextCore
void RegistrationComplete(int thread_id,
int provider_id,
@@ -276,17 +284,21 @@ class CONTENT_EXPORT ServiceWorkerDispatcherHost
const int render_process_id_;
ResourceContext* resource_context_;
// Only accessed on the IO thread.
+ Phase phase_ = Phase::kInitial;
+ // Only accessed on the IO thread.
scoped_refptr<ServiceWorkerContextWrapper> context_wrapper_;
- IDMap<std::unique_ptr<ServiceWorkerHandle>> handles_;
+ base::IDMap<std::unique_ptr<ServiceWorkerHandle>> handles_;
using RegistrationHandleMap =
- IDMap<std::unique_ptr<ServiceWorkerRegistrationHandle>>;
+ base::IDMap<std::unique_ptr<ServiceWorkerRegistrationHandle>>;
RegistrationHandleMap registration_handles_;
bool channel_ready_; // True after BrowserMessageFilter::sender_ != NULL.
std::vector<std::unique_ptr<IPC::Message>> pending_messages_;
+ base::WeakPtrFactory<ServiceWorkerDispatcherHost> weak_ptr_factory_;
+
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerDispatcherHost);
};
diff --git a/chromium/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc b/chromium/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc
index 1097f259d7a..84b2601c53d 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
@@ -53,14 +53,14 @@ void SetUpDummyMessagePort(std::vector<MessagePort>* ports) {
}
struct RemoteProviderInfo {
- mojom::ServiceWorkerProviderHostAssociatedPtr host_ptr;
- mojom::ServiceWorkerProviderAssociatedRequest client_request;
+ mojom::ServiceWorkerContainerHostAssociatedPtr host_ptr;
+ mojom::ServiceWorkerContainerAssociatedRequest client_request;
};
RemoteProviderInfo SetupProviderHostInfoPtrs(
ServiceWorkerProviderHostInfo* host_info) {
RemoteProviderInfo remote_info;
- mojom::ServiceWorkerProviderAssociatedPtr browser_side_client_ptr;
+ mojom::ServiceWorkerContainerAssociatedPtr browser_side_client_ptr;
remote_info.client_request =
mojo::MakeIsolatedRequest(&browser_side_client_ptr);
host_info->host_request = mojo::MakeIsolatedRequest(&remote_info.host_ptr);
@@ -123,14 +123,16 @@ class FailToStartWorkerTestHelper : public EmbeddedWorkerTestHelper {
public:
FailToStartWorkerTestHelper() : EmbeddedWorkerTestHelper(base::FilePath()) {}
- void OnStartWorker(int embedded_worker_id,
- int64_t service_worker_version_id,
- const GURL& scope,
- const GURL& script_url,
- bool pause_after_download,
- mojom::ServiceWorkerEventDispatcherRequest request,
- mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo
- instance_host) override {
+ void OnStartWorker(
+ int embedded_worker_id,
+ int64_t service_worker_version_id,
+ const GURL& scope,
+ const GURL& script_url,
+ bool pause_after_download,
+ mojom::ServiceWorkerEventDispatcherRequest request,
+ mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
+ mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info)
+ override {
mojom::EmbeddedWorkerInstanceHostAssociatedPtr instance_host_ptr;
instance_host_ptr.Bind(std::move(instance_host));
instance_host_ptr->OnStopped();
@@ -197,13 +199,6 @@ class ServiceWorkerDispatcherHostTest : public testing::Test {
EXPECT_EQ(SERVICE_WORKER_OK, status);
}
- void SendSetHostedVersionId(int provider_id,
- int64_t version_id,
- int embedded_worker_id) {
- dispatcher_host_->OnSetHostedVersionId(provider_id, version_id,
- embedded_worker_id, nullptr);
- }
-
void SendProviderCreated(ServiceWorkerProviderType type,
const GURL& pattern) {
const int64_t kProviderId = 99;
@@ -218,6 +213,19 @@ class ServiceWorkerDispatcherHostTest : public testing::Test {
helper_->mock_render_process_id(), kProviderId);
}
+ void PrepareProviderForServiceWorkerContext(ServiceWorkerVersion* version,
+ const GURL& pattern) {
+ std::unique_ptr<ServiceWorkerProviderHost> host =
+ CreateProviderHostForServiceWorkerContext(
+ helper_->mock_render_process_id(),
+ true /* is_parent_frame_secure */, version,
+ helper_->context()->AsWeakPtr(), &remote_endpoint_);
+ provider_host_ = host.get();
+ helper_->SimulateAddProcessToPattern(pattern,
+ helper_->mock_render_process_id());
+ context()->AddProviderHost(std::move(host));
+ }
+
void SendRegister(int64_t provider_id, GURL pattern, GURL worker_url) {
ServiceWorkerRegistrationOptions options(pattern);
dispatcher_host_->OnMessageReceived(
@@ -612,13 +620,17 @@ TEST_F(ServiceWorkerDispatcherHostTest, ProviderCreatedAndDestroyed) {
base::Callback<WebContents*(void)>()));
}
- // Deletion of the dispatcher_host should cause providers for that
- // process to get deleted as well.
+ // Deletion of the dispatcher_host should cause provider hosts for
+ // that process to have a null dispatcher host.
dispatcher_host_->OnProviderCreated(std::move(host_info_3));
- EXPECT_TRUE(context()->GetProviderHost(process_id, kProviderId));
+ ServiceWorkerProviderHost* host =
+ context()->GetProviderHost(process_id, kProviderId);
+ EXPECT_TRUE(host->dispatcher_host());
EXPECT_TRUE(dispatcher_host_->HasOneRef());
dispatcher_host_ = nullptr;
- EXPECT_FALSE(context()->GetProviderHost(process_id, kProviderId));
+ host = context()->GetProviderHost(process_id, kProviderId);
+ ASSERT_TRUE(host);
+ EXPECT_FALSE(host->dispatcher_host());
}
TEST_F(ServiceWorkerDispatcherHostTest, GetRegistration_SameOrigin) {
@@ -735,9 +747,17 @@ TEST_F(ServiceWorkerDispatcherHostTest, CleanupOnRendererCrash) {
// Simulate the render process crashing.
dispatcher_host_->OnFilterRemoved();
- // The dispatcher host should clean up the state from the process.
- EXPECT_FALSE(context()->GetProviderHost(process_id, provider_id));
- EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, version_->running_status());
+ // The provider host still exists, since it will clean itself up when its Mojo
+ // connection to the renderer breaks. But it should no longer be using the
+ // dispatcher host.
+ ServiceWorkerProviderHost* host =
+ context()->GetProviderHost(process_id, provider_id);
+ ASSERT_TRUE(host);
+ EXPECT_FALSE(host->dispatcher_host());
+
+ // The EmbeddedWorkerInstance should still think it is running, since it will
+ // clean itself up when its Mojo connection to the renderer breaks.
+ EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
// We should be able to hook up a new dispatcher host although the old object
// is not yet destroyed. This is what the browser does when reusing a crashed
@@ -747,10 +767,8 @@ TEST_F(ServiceWorkerDispatcherHostTest, CleanupOnRendererCrash) {
helper_.get()));
new_dispatcher_host->Init(context_wrapper());
- // To show the new dispatcher can operate, simulate provider creation. Since
- // the old dispatcher cleaned up the old provider host, the new one won't
- // complain.
- ServiceWorkerProviderHostInfo host_info(provider_id, MSG_ROUTING_NONE,
+ // To show the new dispatcher can operate, simulate provider creation.
+ ServiceWorkerProviderHostInfo host_info(provider_id + 1, MSG_ROUTING_NONE,
SERVICE_WORKER_PROVIDER_FOR_WINDOW,
true /* is_parent_frame_secure */);
ServiceWorkerRemoteProviderEndpoint remote_endpoint;
@@ -763,8 +781,8 @@ TEST_F(ServiceWorkerDispatcherHostTest, DispatchExtendableMessageEvent) {
GURL pattern = GURL("http://www.example.com/");
GURL script_url = GURL("http://www.example.com/service_worker.js");
- SendProviderCreated(SERVICE_WORKER_PROVIDER_FOR_CONTROLLER, pattern);
SetUpRegistration(pattern, script_url);
+ PrepareProviderForServiceWorkerContext(version_.get(), pattern);
// Set the running hosted version so that we can retrieve a valid service
// worker object information for the source attribute of the message event.
@@ -841,86 +859,4 @@ TEST_F(ServiceWorkerDispatcherHostTest, DispatchExtendableMessageEvent_Fail) {
EXPECT_EQ(SERVICE_WORKER_ERROR_START_WORKER_FAILED, status);
}
-TEST_F(ServiceWorkerDispatcherHostTest, OnSetHostedVersionId) {
- GURL pattern = GURL("http://www.example.com/");
- GURL script_url = GURL("http://www.example.com/service_worker.js");
-
- Initialize(base::WrapUnique(new FailToStartWorkerTestHelper));
- SendProviderCreated(SERVICE_WORKER_PROVIDER_FOR_CONTROLLER, pattern);
- SetUpRegistration(pattern, script_url);
-
- const int64_t kProviderId = 99; // Dummy value
- bool called;
- ServiceWorkerStatusCode status;
- // StartWorker puts the worker in STARTING state but it will have no
- // process id yet.
- version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
- base::Bind(&SaveStatusCallback, &called, &status));
- EXPECT_NE(version_->embedded_worker()->process_id(),
- provider_host_->process_id());
- // SendSetHostedVersionId should reject because the provider host process id
- // is different. It should call BadMessageReceived because it's not an
- // expected error state.
- SendSetHostedVersionId(kProviderId, version_->version_id(),
- version_->embedded_worker()->embedded_worker_id());
- base::RunLoop().RunUntilIdle();
- EXPECT_FALSE(dispatcher_host_->ipc_sink()->GetUniqueMessageMatching(
- ServiceWorkerMsg_AssociateRegistration::ID));
- EXPECT_EQ(1, dispatcher_host_->bad_messages_received_count_);
-}
-
-TEST_F(ServiceWorkerDispatcherHostTest, OnSetHostedVersionId_DetachedWorker) {
- GURL pattern = GURL("http://www.example.com/");
- GURL script_url = GURL("http://www.example.com/service_worker.js");
-
- Initialize(base::WrapUnique(new FailToStartWorkerTestHelper));
- SendProviderCreated(SERVICE_WORKER_PROVIDER_FOR_CONTROLLER, pattern);
- SetUpRegistration(pattern, script_url);
-
- const int64_t kProviderId = 99; // Dummy value
- bool called;
- ServiceWorkerStatusCode status;
- // StartWorker puts the worker in STARTING state.
- version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
- base::Bind(&SaveStatusCallback, &called, &status));
-
- // SendSetHostedVersionId should bail because the embedded worker is
- // different. It shouldn't call BadMessageReceived because receiving a message
- // for a detached worker is a legitimite possibility.
- int bad_embedded_worker_id =
- version_->embedded_worker()->embedded_worker_id() + 1;
- SendSetHostedVersionId(kProviderId, version_->version_id(),
- bad_embedded_worker_id);
- base::RunLoop().RunUntilIdle();
- EXPECT_FALSE(dispatcher_host_->ipc_sink()->GetUniqueMessageMatching(
- ServiceWorkerMsg_AssociateRegistration::ID));
- EXPECT_EQ(0, dispatcher_host_->bad_messages_received_count_);
-}
-
-TEST_F(ServiceWorkerDispatcherHostTest, ReceivedTimedOutRequestResponse) {
- GURL pattern = GURL("https://www.example.com/");
- GURL script_url = GURL("https://www.example.com/service_worker.js");
-
- SendProviderCreated(SERVICE_WORKER_PROVIDER_FOR_WINDOW, pattern);
- SetUpRegistration(pattern, script_url);
-
- version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
- base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
- base::RunLoop().RunUntilIdle();
-
- // Set the worker status to STOPPING.
- version_->embedded_worker()->Stop();
- EXPECT_EQ(EmbeddedWorkerStatus::STOPPING, version_->running_status());
-
- // Receive a response for a timed out request. The bad message count should
- // not increase.
- const int kFetchEventId = 91; // Dummy value
- dispatcher_host_->OnMessageReceived(ServiceWorkerHostMsg_FetchEventResponse(
- version_->embedded_worker()->embedded_worker_id(), kFetchEventId,
- ServiceWorkerResponse(), base::Time::Now()));
-
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(0, dispatcher_host_->bad_messages_received_count_);
-}
-
} // namespace content
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 b1b96204dc0..4e01ed4df0a 100644
--- a/chromium/content/browser/service_worker/service_worker_fetch_dispatcher.cc
+++ b/chromium/content/browser/service_worker/service_worker_fetch_dispatcher.cc
@@ -29,7 +29,7 @@
#include "content/public/browser/browser_thread.h"
#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/common/content_features.h"
-#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
#include "net/base/request_priority.h"
#include "net/http/http_util.h"
#include "net/log/net_log.h"
@@ -46,7 +46,7 @@ namespace {
// URLLoader implementation and delegates URLLoader calls to the wrapped loader.
class DelegatingURLLoader final : public mojom::URLLoader {
public:
- explicit DelegatingURLLoader(mojom::URLLoaderAssociatedPtr loader)
+ explicit DelegatingURLLoader(mojom::URLLoaderPtr loader)
: binding_(this), loader_(std::move(loader)) {}
~DelegatingURLLoader() override {}
@@ -63,7 +63,7 @@ class DelegatingURLLoader final : public mojom::URLLoader {
// This unretained pointer is safe, because |binding_| is owned by |this|
// and the callback will never be called after |this| is destroyed.
binding_.set_connection_error_handler(
- base::Bind(&DelegatingURLLoader::Cancel, base::Unretained(this)));
+ base::BindOnce(&DelegatingURLLoader::Cancel, base::Unretained(this)));
return loader;
}
@@ -75,7 +75,7 @@ class DelegatingURLLoader final : public mojom::URLLoader {
}
mojo::Binding<mojom::URLLoader> binding_;
- mojom::URLLoaderAssociatedPtr loader_;
+ mojom::URLLoaderPtr loader_;
DISALLOW_COPY_AND_ASSIGN(DelegatingURLLoader);
};
@@ -208,9 +208,10 @@ class DelegatingURLLoaderClient final : public mojom::URLLoaderClient {
if (!worker_id_)
return;
while (!devtools_callbacks.empty()) {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(std::move(devtools_callbacks.front()),
- *worker_id_, devtools_request_id_));
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(std::move(devtools_callbacks.front()), *worker_id_,
+ devtools_request_id_));
devtools_callbacks.pop();
}
}
@@ -286,35 +287,39 @@ ServiceWorkerMetrics::EventType FetchTypeToWaitUntilEventType(
} // namespace
-// Helper to receive the fetch event response even if
-// ServiceWorkerFetchDispatcher has been destroyed.
+// ResponseCallback is owned by the callback that is passed to
+// ServiceWorkerVersion::StartRequest*(), and held in pending_requests_
+// until FinishRequest() is called.
class ServiceWorkerFetchDispatcher::ResponseCallback
: public mojom::ServiceWorkerFetchResponseCallback {
public:
- ResponseCallback(base::WeakPtr<ServiceWorkerFetchDispatcher> fetch_dispatcher,
- ServiceWorkerVersion* version,
- int fetch_event_id)
- : fetch_dispatcher_(fetch_dispatcher),
- version_(version),
- fetch_event_id_(fetch_event_id),
- binding_(this) {}
- ~ResponseCallback() override {}
-
- void Run(int request_id,
- const ServiceWorkerResponse& response,
- base::Time dispatch_event_time) {
- // Legacy IPC callback is only for blob handling.
- DCHECK_EQ(fetch_event_id_, request_id);
- DCHECK(response.blob_uuid.size());
- HandleResponse(response, blink::mojom::ServiceWorkerStreamHandlePtr(),
- SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE,
- dispatch_event_time);
+ ResponseCallback(mojom::ServiceWorkerFetchResponseCallbackRequest request,
+ base::WeakPtr<ServiceWorkerFetchDispatcher> fetch_dispatcher,
+ ServiceWorkerVersion* version)
+ : binding_(this, std::move(request)),
+ fetch_dispatcher_(fetch_dispatcher),
+ version_(version) {}
+
+ ~ResponseCallback() override { DCHECK(fetch_event_id_.has_value()); }
+
+ void set_fetch_event_id(int id) {
+ DCHECK(!fetch_event_id_);
+ fetch_event_id_ = id;
}
// Implements mojom::ServiceWorkerFetchResponseCallback.
void OnResponse(const ServiceWorkerResponse& response,
base::Time dispatch_event_time) override {
- HandleResponse(response, blink::mojom::ServiceWorkerStreamHandlePtr(),
+ HandleResponse(fetch_dispatcher_, version_, fetch_event_id_, response,
+ nullptr /* body_as_stream */, nullptr /* body_as_blob */,
+ SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE,
+ dispatch_event_time);
+ }
+ void OnResponseBlob(const ServiceWorkerResponse& response,
+ storage::mojom::BlobPtr body_as_blob,
+ base::Time dispatch_event_time) override {
+ HandleResponse(fetch_dispatcher_, version_, fetch_event_id_, response,
+ nullptr /* body_as_stream */, std::move(body_as_blob),
SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE,
dispatch_event_time);
}
@@ -322,49 +327,51 @@ class ServiceWorkerFetchDispatcher::ResponseCallback
const ServiceWorkerResponse& response,
blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
base::Time dispatch_event_time) override {
- HandleResponse(response, std::move(body_as_stream),
+ HandleResponse(fetch_dispatcher_, version_, fetch_event_id_, response,
+ std::move(body_as_stream), nullptr /* body_as_blob */,
SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE,
dispatch_event_time);
}
void OnFallback(base::Time dispatch_event_time) override {
HandleResponse(
- ServiceWorkerResponse(), blink::mojom::ServiceWorkerStreamHandlePtr(),
+ fetch_dispatcher_, version_, fetch_event_id_, ServiceWorkerResponse(),
+ nullptr /* body_as_stream */, nullptr /* body_as_blob */,
SERVICE_WORKER_FETCH_EVENT_RESULT_FALLBACK, dispatch_event_time);
}
- mojom::ServiceWorkerFetchResponseCallbackPtr CreateInterfacePtrAndBind() {
- mojom::ServiceWorkerFetchResponseCallbackPtr callback_proxy;
- binding_.Bind(mojo::MakeRequest(&callback_proxy));
- return callback_proxy;
- }
-
private:
- void HandleResponse(const ServiceWorkerResponse& response,
- blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
- ServiceWorkerFetchEventResult fetch_result,
- base::Time dispatch_event_time) {
- // Copy |fetch_dispatcher_| and |fetch_event_id_| for use after |this| is
- // destroyed.
- base::WeakPtr<ServiceWorkerFetchDispatcher> dispatcher(fetch_dispatcher_);
- const int event_id(fetch_event_id_);
- // FinishRequest() will delete |this|.
- if (!version_->FinishRequest(
- fetch_event_id_,
+ // static as version->FinishRequest will remove the calling ResponseCallback
+ // instance.
+ static void HandleResponse(
+ base::WeakPtr<ServiceWorkerFetchDispatcher> fetch_dispatcher,
+ ServiceWorkerVersion* version,
+ base::Optional<int> fetch_event_id,
+ const ServiceWorkerResponse& response,
+ blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
+ storage::mojom::BlobPtr body_as_blob,
+ ServiceWorkerFetchEventResult fetch_result,
+ base::Time dispatch_event_time) {
+ if (!version->FinishRequest(
+ fetch_event_id.value(),
fetch_result == SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE,
dispatch_event_time))
NOTREACHED() << "Should only receive one reply per event";
- // |dispatcher| is null if the URLRequest was killed.
- if (!dispatcher)
+ // |fetch_dispatcher| is null if the URLRequest was killed.
+ if (!fetch_dispatcher)
return;
- dispatcher->DidFinish(event_id, fetch_result, response,
- std::move(body_as_stream));
+ fetch_dispatcher->DidFinish(fetch_event_id.value(), fetch_result, response,
+ std::move(body_as_stream),
+ std::move(body_as_blob));
}
+ mojo::Binding<mojom::ServiceWorkerFetchResponseCallback> binding_;
base::WeakPtr<ServiceWorkerFetchDispatcher> fetch_dispatcher_;
- // Owns |this|.
+ // Owns |this| via pending_requests_.
ServiceWorkerVersion* version_;
- const int fetch_event_id_;
- mojo::Binding<mojom::ServiceWorkerFetchResponseCallback> binding_;
+ // Must be set to a non-nullopt value before the corresponding mojo
+ // handle is passed to the other end (i.e. before any of OnResponse*
+ // is called).
+ base::Optional<int> fetch_event_id_;
DISALLOW_COPY_AND_ASSIGN(ResponseCallback);
};
@@ -435,8 +442,8 @@ void ServiceWorkerFetchDispatcher::Run() {
net_log_.BeginEvent(
net::NetLogEventType::SERVICE_WORKER_WAIT_FOR_ACTIVATION);
version_->RegisterStatusChangeCallback(
- base::Bind(&ServiceWorkerFetchDispatcher::DidWaitForActivation,
- weak_factory_.GetWeakPtr()));
+ base::BindOnce(&ServiceWorkerFetchDispatcher::DidWaitForActivation,
+ weak_factory_.GetWeakPtr()));
return;
}
StartWorker();
@@ -463,8 +470,9 @@ void ServiceWorkerFetchDispatcher::StartWorker() {
net_log_.BeginEvent(net::NetLogEventType::SERVICE_WORKER_START_WORKER);
version_->RunAfterStartWorker(
- GetEventType(), base::Bind(&ServiceWorkerFetchDispatcher::DidStartWorker,
- weak_factory_.GetWeakPtr()),
+ GetEventType(),
+ base::BindOnce(&ServiceWorkerFetchDispatcher::DidStartWorker,
+ weak_factory_.GetWeakPtr()),
base::Bind(&ServiceWorkerFetchDispatcher::DidFailToStartWorker,
weak_factory_.GetWeakPtr()));
}
@@ -489,6 +497,12 @@ void ServiceWorkerFetchDispatcher::DispatchFetchEvent() {
base::Closure prepare_callback = prepare_callback_;
prepare_callback.Run();
+ mojom::ServiceWorkerFetchResponseCallbackPtr mojo_response_callback_ptr;
+ auto response_callback = base::MakeUnique<ResponseCallback>(
+ mojo::MakeRequest(&mojo_response_callback_ptr),
+ weak_factory_.GetWeakPtr(), version_.get());
+ ResponseCallback* response_callback_rawptr = response_callback.get();
+
net_log_.BeginEvent(net::NetLogEventType::SERVICE_WORKER_FETCH_EVENT);
int fetch_event_id;
int event_finish_id;
@@ -496,7 +510,8 @@ void ServiceWorkerFetchDispatcher::DispatchFetchEvent() {
fetch_event_id = version_->StartRequestWithCustomTimeout(
GetEventType(),
base::Bind(&ServiceWorkerFetchDispatcher::DidFailToDispatch,
- weak_factory_.GetWeakPtr()),
+ weak_factory_.GetWeakPtr(),
+ base::Passed(&response_callback)),
*timeout_, ServiceWorkerVersion::CONTINUE_ON_TIMEOUT);
event_finish_id = version_->StartRequestWithCustomTimeout(
FetchTypeToWaitUntilEventType(request_->fetch_type),
@@ -506,21 +521,14 @@ void ServiceWorkerFetchDispatcher::DispatchFetchEvent() {
fetch_event_id = version_->StartRequest(
GetEventType(),
base::Bind(&ServiceWorkerFetchDispatcher::DidFailToDispatch,
- weak_factory_.GetWeakPtr()));
+ weak_factory_.GetWeakPtr(),
+ base::Passed(&response_callback)));
event_finish_id = version_->StartRequest(
FetchTypeToWaitUntilEventType(request_->fetch_type),
base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
}
- std::unique_ptr<ResponseCallback> response_callback =
- base::MakeUnique<ResponseCallback>(weak_factory_.GetWeakPtr(),
- version_.get(), fetch_event_id);
- mojom::ServiceWorkerFetchResponseCallbackPtr response_callback_ptr =
- response_callback->CreateInterfacePtrAndBind();
- version_->RegisterRequestCallback<ServiceWorkerHostMsg_FetchEventResponse>(
- fetch_event_id,
- base::Bind(&ServiceWorkerFetchDispatcher::ResponseCallback::Run,
- base::Passed(&response_callback)));
+ response_callback_rawptr->set_fetch_event_id(fetch_event_id);
if (url_loader_assets_) {
url_loader_assets_->MayBeReportToDevTools(
@@ -536,13 +544,14 @@ void ServiceWorkerFetchDispatcher::DispatchFetchEvent() {
// assets alive while the FetchEvent is ongoing in the service worker.
version_->event_dispatcher()->DispatchFetchEvent(
fetch_event_id, *request_, std::move(preload_handle_),
- std::move(response_callback_ptr),
- base::Bind(&ServiceWorkerFetchDispatcher::OnFetchEventFinished,
- base::Unretained(version_.get()), event_finish_id,
- url_loader_assets_));
+ std::move(mojo_response_callback_ptr),
+ base::BindOnce(&ServiceWorkerFetchDispatcher::OnFetchEventFinished,
+ base::Unretained(version_.get()), event_finish_id,
+ url_loader_assets_));
}
void ServiceWorkerFetchDispatcher::DidFailToDispatch(
+ std::unique_ptr<ResponseCallback> response_callback,
ServiceWorkerStatusCode status) {
EndNetLogEventWithServiceWorkerStatus(
net_log_, net::NetLogEventType::SERVICE_WORKER_FETCH_EVENT, status);
@@ -552,25 +561,27 @@ void ServiceWorkerFetchDispatcher::DidFailToDispatch(
void ServiceWorkerFetchDispatcher::DidFail(ServiceWorkerStatusCode status) {
DCHECK_NE(SERVICE_WORKER_OK, status);
Complete(status, SERVICE_WORKER_FETCH_EVENT_RESULT_FALLBACK,
- ServiceWorkerResponse(),
- blink::mojom::ServiceWorkerStreamHandlePtr());
+ ServiceWorkerResponse(), nullptr /* body_as_stream */,
+ nullptr /* body_as_blob */);
}
void ServiceWorkerFetchDispatcher::DidFinish(
int request_id,
ServiceWorkerFetchEventResult fetch_result,
const ServiceWorkerResponse& response,
- blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream) {
+ blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
+ storage::mojom::BlobPtr body_as_blob) {
net_log_.EndEvent(net::NetLogEventType::SERVICE_WORKER_FETCH_EVENT);
- Complete(SERVICE_WORKER_OK, fetch_result, response,
- std::move(body_as_stream));
+ Complete(SERVICE_WORKER_OK, fetch_result, response, std::move(body_as_stream),
+ std::move(body_as_blob));
}
void ServiceWorkerFetchDispatcher::Complete(
ServiceWorkerStatusCode status,
ServiceWorkerFetchEventResult fetch_result,
const ServiceWorkerResponse& response,
- blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream) {
+ blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
+ storage::mojom::BlobPtr body_as_blob) {
DCHECK(!fetch_callback_.is_null());
did_complete_ = true;
@@ -581,7 +592,7 @@ void ServiceWorkerFetchDispatcher::Complete(
FetchCallback fetch_callback = fetch_callback_;
scoped_refptr<ServiceWorkerVersion> version = version_;
fetch_callback.Run(status, fetch_result, response, std::move(body_as_stream),
- version);
+ std::move(body_as_blob), version);
}
bool ServiceWorkerFetchDispatcher::MaybeStartNavigationPreload(
@@ -597,9 +608,6 @@ bool ServiceWorkerFetchDispatcher::MaybeStartNavigationPreload(
if (!request_->blob_uuid.empty())
return false;
- if (!base::FeatureList::IsEnabled(features::kServiceWorkerNavigationPreload))
- return false;
-
ResourceRequestInfoImpl* original_info =
ResourceRequestInfoImpl::ForRequest(original_request);
ResourceRequesterInfo* requester_info = original_info->requester_info();
@@ -622,7 +630,7 @@ bool ServiceWorkerFetchDispatcher::MaybeStartNavigationPreload(
ResourceRequest request;
request.method = original_request->method();
request.url = original_request->url();
- // TODO(horo): Set first_party_for_cookies to support Same-site Cookies.
+ // TODO(horo): Set site_for_cookies to support Same-site Cookies.
request.request_initiator = original_request->initiator().has_value()
? original_request->initiator()
: url::Origin(original_request->url());
@@ -661,7 +669,7 @@ bool ServiceWorkerFetchDispatcher::MaybeStartNavigationPreload(
std::move(url_loader_client_ptr), std::move(on_response), request);
mojom::URLLoaderClientPtr url_loader_client_ptr_to_pass;
url_loader_client->Bind(&url_loader_client_ptr_to_pass);
- mojom::URLLoaderAssociatedPtr url_loader_associated_ptr;
+ mojom::URLLoaderPtr url_loader_associated_ptr;
url_loader_factory->CreateLoaderAndStart(
mojo::MakeRequest(&url_loader_associated_ptr),
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 fa2a126b80a..aa6029a349c 100644
--- a/chromium/content/browser/service_worker/service_worker_fetch_dispatcher.h
+++ b/chromium/content/browser/service_worker/service_worker_fetch_dispatcher.h
@@ -23,6 +23,7 @@
#include "content/public/common/url_loader_factory.mojom.h"
#include "mojo/public/cpp/system/data_pipe.h"
#include "net/log/net_log_with_source.h"
+#include "storage/public/interfaces/blobs.mojom.h"
namespace net {
class URLRequest;
@@ -40,6 +41,7 @@ class CONTENT_EXPORT ServiceWorkerFetchDispatcher {
ServiceWorkerFetchEventResult,
const ServiceWorkerResponse&,
blink::mojom::ServiceWorkerStreamHandlePtr,
+ storage::mojom::BlobPtr,
const scoped_refptr<ServiceWorkerVersion>&)>;
ServiceWorkerFetchDispatcher(
@@ -73,16 +75,19 @@ class CONTENT_EXPORT ServiceWorkerFetchDispatcher {
void DidStartWorker();
void DidFailToStartWorker(ServiceWorkerStatusCode status);
void DispatchFetchEvent();
- void DidFailToDispatch(ServiceWorkerStatusCode status);
+ void DidFailToDispatch(std::unique_ptr<ResponseCallback> callback,
+ ServiceWorkerStatusCode status);
void DidFail(ServiceWorkerStatusCode status);
void DidFinish(int request_id,
ServiceWorkerFetchEventResult fetch_result,
const ServiceWorkerResponse& response,
- blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream);
+ blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
+ storage::mojom::BlobPtr body_as_blob);
void Complete(ServiceWorkerStatusCode status,
ServiceWorkerFetchEventResult fetch_result,
const ServiceWorkerResponse& response,
- blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream);
+ blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
+ storage::mojom::BlobPtr body_as_blob);
static void OnFetchEventFinished(
ServiceWorkerVersion* version,
diff --git a/chromium/content/browser/service_worker/service_worker_handle.h b/chromium/content/browser/service_worker/service_worker_handle.h
index 9cc393ded29..fd2697b6cfb 100644
--- a/chromium/content/browser/service_worker/service_worker_handle.h
+++ b/chromium/content/browser/service_worker/service_worker_handle.h
@@ -28,7 +28,7 @@ class ServiceWorkerContextCore;
// Has references to the corresponding ServiceWorkerVersion in order to ensure
// that the version is alive while this handle is around.
class CONTENT_EXPORT ServiceWorkerHandle
- : NON_EXPORTED_BASE(public ServiceWorkerVersion::Listener) {
+ : public ServiceWorkerVersion::Listener {
public:
// Creates a handle for a live version. This may return nullptr if any of
// |context|, |provider_host| and |version| is nullptr.
diff --git a/chromium/content/browser/service_worker/service_worker_installed_scripts_sender.cc b/chromium/content/browser/service_worker/service_worker_installed_scripts_sender.cc
index 3a2c1affab2..1a0615d86d7 100644
--- a/chromium/content/browser/service_worker/service_worker_installed_scripts_sender.cc
+++ b/chromium/content/browser/service_worker/service_worker_installed_scripts_sender.cc
@@ -4,20 +4,469 @@
#include "content/browser/service_worker/service_worker_installed_scripts_sender.h"
+#include "base/memory/ref_counted.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_disk_cache.h"
+#include "content/browser/service_worker/service_worker_script_cache_map.h"
+#include "content/browser/service_worker/service_worker_storage.h"
+#include "net/http/http_response_headers.h"
+#include "services/network/public/cpp/net_adapters.h"
+
namespace content {
-ServiceWorkerInstalledScriptsSender::ServiceWorkerInstalledScriptsSender() =
- default;
-ServiceWorkerInstalledScriptsSender::~ServiceWorkerInstalledScriptsSender() =
- default;
+namespace {
+
+class MetaDataSender {
+ public:
+ enum class Status { kSuccess, kFailed };
+
+ MetaDataSender(scoped_refptr<net::IOBufferWithSize> meta_data,
+ mojo::ScopedDataPipeProducerHandle handle)
+ : meta_data_(std::move(meta_data)),
+ bytes_sent_(0),
+ handle_(std::move(handle)),
+ watcher_(FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::AUTOMATIC),
+ weak_factory_(this) {}
+
+ void Start(base::OnceCallback<void(Status)> callback) {
+ callback_ = std::move(callback);
+ watcher_.Watch(
+ handle_.get(), MOJO_HANDLE_SIGNAL_WRITABLE,
+ base::Bind(&MetaDataSender::OnWritable, weak_factory_.GetWeakPtr()));
+ }
+
+ void OnWritable(MojoResult) {
+ // It isn't necessary to handle MojoResult here since WriteDataRaw()
+ // returns an equivalent error.
+ uint32_t size = meta_data_->size() - bytes_sent_;
+ MojoResult rv = handle_->WriteData(meta_data_->data() + bytes_sent_, &size,
+ MOJO_WRITE_DATA_FLAG_NONE);
+ switch (rv) {
+ case MOJO_RESULT_INVALID_ARGUMENT:
+ case MOJO_RESULT_OUT_OF_RANGE:
+ case MOJO_RESULT_BUSY:
+ NOTREACHED();
+ return;
+ case MOJO_RESULT_FAILED_PRECONDITION:
+ OnCompleted(Status::kFailed);
+ return;
+ case MOJO_RESULT_SHOULD_WAIT:
+ return;
+ case MOJO_RESULT_OK:
+ break;
+ default:
+ // mojo::WriteDataRaw() should not return any other values.
+ OnCompleted(Status::kFailed);
+ return;
+ }
+ bytes_sent_ += size;
+ if (meta_data_->size() == bytes_sent_)
+ OnCompleted(Status::kSuccess);
+ }
+
+ void OnCompleted(Status status) {
+ watcher_.Cancel();
+ handle_.reset();
+ std::move(callback_).Run(status);
+ }
+
+ private:
+ base::OnceCallback<void(Status)> callback_;
+
+ scoped_refptr<net::IOBufferWithSize> meta_data_;
+ int64_t bytes_sent_;
+ mojo::ScopedDataPipeProducerHandle handle_;
+ mojo::SimpleWatcher watcher_;
+
+ base::WeakPtrFactory<MetaDataSender> weak_factory_;
+};
+
+} // namespace
+
+// Sender sends a single script to the renderer and calls
+// ServiceWorkerIsntalledScriptsSender::OnFinishSendingScript() when done.
+class ServiceWorkerInstalledScriptsSender::Sender {
+ public:
+ Sender(std::unique_ptr<ServiceWorkerResponseReader> reader,
+ ServiceWorkerInstalledScriptsSender* owner)
+ : reader_(std::move(reader)),
+ owner_(owner),
+ watcher_(FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::MANUAL),
+ weak_factory_(this) {}
+
+ void Start() {
+ scoped_refptr<HttpResponseInfoIOBuffer> info_buf =
+ base::MakeRefCounted<HttpResponseInfoIOBuffer>();
+ reader_->ReadInfo(info_buf.get(), base::Bind(&Sender::OnReadInfoComplete,
+ AsWeakPtr(), info_buf));
+ }
+
+ private:
+ void OnReadInfoComplete(scoped_refptr<HttpResponseInfoIOBuffer> http_info,
+ int result) {
+ DCHECK(owner_);
+ DCHECK(http_info);
+ if (!http_info->http_info) {
+ DCHECK_LT(result, 0);
+ ServiceWorkerMetrics::CountReadResponseResult(
+ ServiceWorkerMetrics::READ_HEADERS_ERROR);
+ CompleteSendIfNeeded(FinishedReason::kNoHttpInfoError);
+ return;
+ }
+
+ 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) {
+ 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) {
+ CompleteSendIfNeeded(FinishedReason::kCreateDataPipeError);
+ return;
+ }
+ meta_data_sender_ = base::MakeUnique<MetaDataSender>(
+ http_info->http_info->metadata, std::move(meta_data_producer));
+ meta_data_sender_->Start(
+ base::BindOnce(&Sender::OnMetaDataSent, AsWeakPtr()));
+ DCHECK_GE(http_info->http_info->metadata->size(), 0);
+ meta_data_size = http_info->http_info->metadata->size();
+ }
+
+ // Start sending body.
+ watcher_.Watch(body_handle_.get(), MOJO_HANDLE_SIGNAL_WRITABLE,
+ base::Bind(&Sender::OnWritableBody, AsWeakPtr()));
+ watcher_.ArmOrNotify();
+
+ scoped_refptr<net::HttpResponseHeaders> headers =
+ http_info->http_info->headers;
+ DCHECK(headers);
+
+ std::string charset;
+ headers->GetCharset(&charset);
+
+ // Create a map of response headers.
+ std::unordered_map<std::string, std::string> header_strings;
+ size_t iter = 0;
+ std::string key;
+ std::string value;
+ // This logic is copied from blink::ResourceResponse::AddHTTPHeaderField.
+ while (headers->EnumerateHeaderLines(&iter, &key, &value)) {
+ if (header_strings.find(key) == header_strings.end()) {
+ header_strings[key] = value;
+ } else {
+ header_strings[key] += ", " + value;
+ }
+ }
+
+ owner_->SendScriptInfoToRenderer(
+ charset, std::move(header_strings), std::move(body_consumer), body_size,
+ std::move(meta_data_consumer), meta_data_size);
+ owner_->OnHttpInfoRead(http_info);
+ }
+
+ void OnWritableBody(MojoResult) {
+ // It isn't necessary to handle MojoResult here since BeginWrite() returns
+ // an equivalent error.
+ DCHECK(!pending_write_);
+ uint32_t num_bytes = 0;
+ MojoResult rv = network::NetToMojoPendingBuffer::BeginWrite(
+ &body_handle_, &pending_write_, &num_bytes);
+ switch (rv) {
+ case MOJO_RESULT_INVALID_ARGUMENT:
+ case MOJO_RESULT_BUSY:
+ NOTREACHED();
+ return;
+ case MOJO_RESULT_FAILED_PRECONDITION:
+ CompleteSendIfNeeded(FinishedReason::kConnectionError);
+ return;
+ case MOJO_RESULT_SHOULD_WAIT:
+ watcher_.ArmOrNotify();
+ return;
+ case MOJO_RESULT_OK:
+ break;
+ }
+
+ scoped_refptr<network::NetToMojoIOBuffer> buffer =
+ base::MakeRefCounted<network::NetToMojoIOBuffer>(pending_write_.get());
+ reader_->ReadData(buffer.get(), num_bytes,
+ base::Bind(&Sender::OnResponseDataRead, AsWeakPtr()));
+ }
+
+ void OnResponseDataRead(int read_bytes) {
+ if (read_bytes < 0) {
+ ServiceWorkerMetrics::CountReadResponseResult(
+ ServiceWorkerMetrics::READ_DATA_ERROR);
+ watcher_.Cancel();
+ body_handle_.reset();
+ CompleteSendIfNeeded(FinishedReason::kResponseReaderError);
+ return;
+ }
+ body_handle_ = pending_write_->Complete(read_bytes);
+ DCHECK(body_handle_.is_valid());
+ pending_write_ = nullptr;
+ ServiceWorkerMetrics::CountReadResponseResult(
+ ServiceWorkerMetrics::READ_OK);
+ if (read_bytes == 0) {
+ // All data has been read.
+ watcher_.Cancel();
+ body_handle_.reset();
+ CompleteSendIfNeeded(FinishedReason::kSuccess);
+ return;
+ }
+ watcher_.ArmOrNotify();
+ }
+
+ void OnMetaDataSent(MetaDataSender::Status status) {
+ meta_data_sender_.reset();
+ if (status != MetaDataSender::Status::kSuccess) {
+ watcher_.Cancel();
+ body_handle_.reset();
+ CompleteSendIfNeeded(FinishedReason::kMetaDataSenderError);
+ return;
+ }
+
+ CompleteSendIfNeeded(FinishedReason::kSuccess);
+ }
+
+ // CompleteSendIfNeeded notifies the end of data transfer to |owner_|, and
+ // |this| will be removed by |owner_| as a result. Errors are notified
+ // immediately, but when the transfer has been succeeded, it's notified when
+ // sending both of body and meta data is finished.
+ void CompleteSendIfNeeded(FinishedReason status) {
+ if (status != FinishedReason::kSuccess) {
+ owner_->OnAbortSendingScript(status);
+ return;
+ }
+ if (!body_handle_.is_valid() && !meta_data_sender_)
+ owner_->OnFinishSendingScript();
+ }
+
+ base::WeakPtr<Sender> AsWeakPtr() { return weak_factory_.GetWeakPtr(); }
+
+ std::unique_ptr<ServiceWorkerResponseReader> reader_;
+ ServiceWorkerInstalledScriptsSender* owner_;
+
+ // For meta data.
+ std::unique_ptr<MetaDataSender> meta_data_sender_;
+
+ // For body.
+ scoped_refptr<network::NetToMojoPendingBuffer> pending_write_;
+ mojo::SimpleWatcher watcher_;
+
+ // Pipes.
+ mojo::ScopedDataPipeProducerHandle meta_data_handle_;
+ mojo::ScopedDataPipeProducerHandle body_handle_;
+
+ base::WeakPtrFactory<Sender> weak_factory_;
+};
+
+ServiceWorkerInstalledScriptsSender::ServiceWorkerInstalledScriptsSender(
+ ServiceWorkerVersion* owner,
+ const GURL& main_script_url,
+ base::WeakPtr<ServiceWorkerContextCore> context)
+ : owner_(owner),
+ main_script_url_(main_script_url),
+ main_script_id_(kInvalidServiceWorkerResourceId),
+ state_(State::kNotStarted),
+ finished_reason_(FinishedReason::kNotFinished),
+ context_(std::move(context)) {}
+
+ServiceWorkerInstalledScriptsSender::~ServiceWorkerInstalledScriptsSender() {}
mojom::ServiceWorkerInstalledScriptsInfoPtr
ServiceWorkerInstalledScriptsSender::CreateInfoAndBind() {
+ DCHECK_EQ(State::kNotStarted, state_);
+
+ std::vector<ServiceWorkerDatabase::ResourceRecord> resources;
+ std::vector<GURL> installed_urls;
+ owner_->script_cache_map()->GetResources(&resources);
+ for (const auto& resource : resources) {
+ installed_urls.emplace_back(resource.url);
+ if (resource.url == main_script_url_)
+ main_script_id_ = resource.resource_id;
+ else
+ imported_scripts_.emplace(resource.resource_id, resource.url);
+ }
+
+ if (installed_urls.empty())
+ return nullptr;
+
auto info = mojom::ServiceWorkerInstalledScriptsInfo::New();
info->manager_request = mojo::MakeRequest(&manager_);
-
- // TODO(shimazu): Read all installed urls and start pushing scripts.
+ info->installed_urls = std::move(installed_urls);
return info;
}
+bool ServiceWorkerInstalledScriptsSender::IsFinished() const {
+ return state_ == State::kFinished;
+}
+
+void ServiceWorkerInstalledScriptsSender::Start() {
+ DCHECK_EQ(State::kNotStarted, state_);
+ // Return if no script has been installed.
+ if (main_script_id_ == kInvalidServiceWorkerResourceId) {
+ Finish(FinishedReason::kSuccess);
+ return;
+ }
+ TRACE_EVENT_NESTABLE_ASYNC_BEGIN1("ServiceWorker",
+ "ServiceWorkerInstalledScriptsSender", this,
+ "main_script_url", main_script_url_.spec());
+ UpdateState(State::kSendingMainScript);
+ StartSendingScript(main_script_id_);
+}
+
+void ServiceWorkerInstalledScriptsSender::StartSendingScript(
+ int64_t resource_id) {
+ DCHECK(!running_sender_);
+ DCHECK(state_ == State::kSendingMainScript ||
+ state_ == State::kSendingImportedScript);
+ auto reader = context_->storage()->CreateResponseReader(resource_id);
+ TRACE_EVENT_NESTABLE_ASYNC_BEGIN1("ServiceWorker", "SendingScript", this,
+ "script_url", CurrentSendingURL().spec());
+ running_sender_ = base::MakeUnique<Sender>(std::move(reader), this);
+ running_sender_->Start();
+}
+
+void ServiceWorkerInstalledScriptsSender::SendScriptInfoToRenderer(
+ std::string encoding,
+ std::unordered_map<std::string, std::string> headers,
+ mojo::ScopedDataPipeConsumerHandle body_handle,
+ uint64_t body_size,
+ mojo::ScopedDataPipeConsumerHandle meta_data_handle,
+ uint64_t meta_data_size) {
+ DCHECK(running_sender_);
+ DCHECK(state_ == State::kSendingMainScript ||
+ state_ == State::kSendingImportedScript);
+ TRACE_EVENT_NESTABLE_ASYNC_INSTANT2(
+ "ServiceWorker", "SendScriptInfoToRenderer", this, "body_size", body_size,
+ "meta_data_size", meta_data_size);
+ auto script_info = mojom::ServiceWorkerScriptInfo::New();
+ script_info->script_url = CurrentSendingURL();
+ script_info->headers = std::move(headers);
+ script_info->encoding = std::move(encoding);
+ script_info->body = std::move(body_handle);
+ script_info->body_size = body_size;
+ script_info->meta_data = std::move(meta_data_handle);
+ script_info->meta_data_size = meta_data_size;
+ manager_->TransferInstalledScript(std::move(script_info));
+}
+
+void ServiceWorkerInstalledScriptsSender::OnHttpInfoRead(
+ scoped_refptr<HttpResponseInfoIOBuffer> http_info) {
+ DCHECK(running_sender_);
+ DCHECK(state_ == State::kSendingMainScript ||
+ state_ == State::kSendingImportedScript);
+ if (state_ == State::kSendingMainScript)
+ owner_->SetMainScriptHttpResponseInfo(*http_info->http_info);
+}
+
+void ServiceWorkerInstalledScriptsSender::OnFinishSendingScript() {
+ DCHECK(running_sender_);
+ DCHECK(state_ == State::kSendingMainScript ||
+ state_ == State::kSendingImportedScript);
+ TRACE_EVENT_NESTABLE_ASYNC_END0("ServiceWorker", "SendingScript", this);
+ running_sender_.reset();
+ if (state_ == State::kSendingMainScript) {
+ // Imported scripts are served after the main script.
+ imported_script_iter_ = imported_scripts_.begin();
+ UpdateState(State::kSendingImportedScript);
+ } else {
+ ++imported_script_iter_;
+ }
+ if (imported_script_iter_ == imported_scripts_.end()) {
+ // All scripts have been sent to the renderer.
+ // ServiceWorkerInstalledScriptsSender's work is done now.
+ DCHECK_EQ(State::kSendingImportedScript, state_);
+ DCHECK(!IsFinished());
+ Finish(FinishedReason::kSuccess);
+ TRACE_EVENT_NESTABLE_ASYNC_END0(
+ "ServiceWorker", "ServiceWorkerInstalledScriptsSender", this);
+ return;
+ }
+ // Start sending the next script.
+ StartSendingScript(imported_script_iter_->first);
+}
+
+void ServiceWorkerInstalledScriptsSender::OnAbortSendingScript(
+ FinishedReason reason) {
+ DCHECK(running_sender_);
+ DCHECK(state_ == State::kSendingMainScript ||
+ state_ == State::kSendingImportedScript);
+ DCHECK_NE(FinishedReason::kSuccess, reason);
+ DCHECK(!IsFinished());
+ TRACE_EVENT_NESTABLE_ASYNC_END1("ServiceWorker",
+ "ServiceWorkerInstalledScriptsSender", this,
+ "FinishedReason", static_cast<int>(reason));
+ Finish(reason);
+
+ switch (reason) {
+ case FinishedReason::kNotFinished:
+ case FinishedReason::kSuccess:
+ NOTREACHED();
+ return;
+ case FinishedReason::kNoHttpInfoError:
+ case FinishedReason::kResponseReaderError:
+ owner_->SetStartWorkerStatusCode(SERVICE_WORKER_ERROR_DISK_CACHE);
+ // Abort the worker by deleting from the registration since the data was
+ // corrupted.
+ if (context_) {
+ ServiceWorkerRegistration* registration =
+ context_->GetLiveRegistration(owner_->registration_id());
+ // This ends up with destructing |this|.
+ registration->DeleteVersion(owner_);
+ }
+ return;
+ case FinishedReason::kCreateDataPipeError:
+ case FinishedReason::kConnectionError:
+ case FinishedReason::kMetaDataSenderError:
+ // Notify the renderer that a connection failure happened. Usually the
+ // failure means the renderer gets killed, and the error handler of
+ // EmbeddedWorkerInstance is invoked soon.
+ manager_.reset();
+ break;
+ }
+}
+
+const GURL& ServiceWorkerInstalledScriptsSender::CurrentSendingURL() {
+ if (state_ == State::kSendingMainScript)
+ return main_script_url_;
+ return imported_script_iter_->second;
+}
+
+void ServiceWorkerInstalledScriptsSender::UpdateState(State state) {
+ DCHECK_NE(State::kFinished, state) << "Use Finish() for state kFinished.";
+
+ switch (state_) {
+ case State::kNotStarted:
+ DCHECK_EQ(State::kSendingMainScript, state);
+ state_ = state;
+ return;
+ case State::kSendingMainScript:
+ DCHECK_EQ(State::kSendingImportedScript, state);
+ state_ = state;
+ return;
+ case State::kSendingImportedScript:
+ case State::kFinished:
+ NOTREACHED();
+ return;
+ }
+}
+
+void ServiceWorkerInstalledScriptsSender::Finish(FinishedReason reason) {
+ DCHECK_NE(State::kFinished, state_);
+ DCHECK_NE(FinishedReason::kNotFinished, reason);
+ state_ = State::kFinished;
+ finished_reason_ = reason;
+}
+
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_installed_scripts_sender.h b/chromium/content/browser/service_worker/service_worker_installed_scripts_sender.h
index 97dd25faec3..697f4241e0c 100644
--- a/chromium/content/browser/service_worker/service_worker_installed_scripts_sender.h
+++ b/chromium/content/browser/service_worker/service_worker_installed_scripts_sender.h
@@ -9,13 +9,33 @@
namespace content {
+struct HttpResponseInfoIOBuffer;
+class ServiceWorkerContextCore;
+class ServiceWorkerVersion;
+
// ServiceWorkerInstalledScriptsSender serves the service worker's installed
// scripts from ServiceWorkerStorage to the renderer through Mojo data pipes.
// ServiceWorkerInstalledScriptsSender is owned by ServiceWorkerVersion. It is
// created for worker startup and lives as long as the worker is running.
-class ServiceWorkerInstalledScriptsSender {
+class CONTENT_EXPORT ServiceWorkerInstalledScriptsSender {
public:
- ServiceWorkerInstalledScriptsSender();
+ // Do not change the order. This is used for UMA.
+ enum class FinishedReason {
+ kNotFinished = 0,
+ kSuccess = 1,
+ kNoHttpInfoError = 2,
+ kCreateDataPipeError = 3,
+ kConnectionError = 4,
+ kResponseReaderError = 5,
+ kMetaDataSenderError = 6,
+ // Add a new type here, then update kMaxValue and enums.xml.
+ kMaxValue = kMetaDataSenderError,
+ };
+
+ ServiceWorkerInstalledScriptsSender(
+ ServiceWorkerVersion* owner,
+ const GURL& main_script_url,
+ base::WeakPtr<ServiceWorkerContextCore> context);
~ServiceWorkerInstalledScriptsSender();
// Creates a Mojo struct (mojom::ServiceWorkerInstalledScriptsInfo) and sets
@@ -23,8 +43,54 @@ class ServiceWorkerInstalledScriptsSender {
// on the renderer.
mojom::ServiceWorkerInstalledScriptsInfoPtr CreateInfoAndBind();
+ // Starts sending installed scripts to the worker.
+ void Start();
+
+ bool IsFinished() const;
+ FinishedReason finished_reason() const { return finished_reason_; }
+
private:
+ class Sender;
+
+ enum class State {
+ kNotStarted,
+ kSendingMainScript,
+ kSendingImportedScript,
+ kFinished,
+ };
+
+ void StartSendingScript(int64_t resource_id);
+
+ // Called from |running_sender_|.
+ void SendScriptInfoToRenderer(
+ std::string encoding,
+ std::unordered_map<std::string, std::string> headers,
+ mojo::ScopedDataPipeConsumerHandle body_handle,
+ uint64_t body_size,
+ mojo::ScopedDataPipeConsumerHandle meta_data_handle,
+ uint64_t meta_data_size);
+ void OnHttpInfoRead(scoped_refptr<HttpResponseInfoIOBuffer> http_info);
+ void OnFinishSendingScript();
+ void OnAbortSendingScript(FinishedReason reason);
+
+ const GURL& CurrentSendingURL();
+
+ void UpdateState(State state);
+ void Finish(FinishedReason reason);
+
+ ServiceWorkerVersion* owner_;
+ const GURL main_script_url_;
+ int main_script_id_;
+
mojom::ServiceWorkerInstalledScriptsManagerPtr manager_;
+ std::unique_ptr<Sender> running_sender_;
+ State state_;
+ FinishedReason finished_reason_;
+ std::map<int64_t /* resource_id */, GURL> imported_scripts_;
+ std::map<int64_t /* resource_id */, GURL>::iterator imported_script_iter_;
+ base::WeakPtr<ServiceWorkerContextCore> context_;
+
+ DISALLOW_COPY_AND_ASSIGN(ServiceWorkerInstalledScriptsSender);
};
} // namespace content
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
new file mode 100644
index 00000000000..9d0d18b4ce6
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_installed_scripts_sender_unittest.cc
@@ -0,0 +1,566 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/service_worker/service_worker_installed_scripts_sender.h"
+
+#include "base/optional.h"
+#include "base/run_loop.h"
+#include "base/stl_util.h"
+#include "base/test/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/public/test/test_browser_thread_bundle.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "net/base/io_buffer.h"
+#include "net/base/test_completion_callback.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+namespace {
+
+void WriteBodyToDiskCache(
+ ServiceWorkerResponseWriter* writer,
+ const std::vector<std::pair<std::string, std::string>>& headers,
+ const std::string& body) {
+ std::unique_ptr<net::HttpResponseInfo> info =
+ base::MakeUnique<net::HttpResponseInfo>();
+ info->request_time = base::Time::Now();
+ info->response_time = base::Time::Now();
+ info->headers =
+ base::MakeRefCounted<net::HttpResponseHeaders>("HTTP/1.0 200 OK\0\0");
+ for (const auto& header : headers)
+ info->headers->AddHeader(header.first + ": " + header.second);
+
+ scoped_refptr<HttpResponseInfoIOBuffer> info_buffer =
+ base::MakeRefCounted<HttpResponseInfoIOBuffer>(info.release());
+ info_buffer->response_data_size = body.size();
+ {
+ net::TestCompletionCallback cb;
+ writer->WriteInfo(info_buffer.get(), cb.callback());
+ int rv = cb.WaitForResult();
+ EXPECT_GE(rv, 0);
+ }
+
+ scoped_refptr<net::IOBuffer> body_buffer =
+ base::MakeRefCounted<net::StringIOBuffer>(body);
+ {
+ net::TestCompletionCallback cb;
+ writer->WriteData(body_buffer.get(), body.size(), cb.callback());
+ int rv = cb.WaitForResult();
+ EXPECT_EQ(body.size(), static_cast<size_t>(rv));
+ }
+}
+
+void WriteMetaDataToDiskCache(ServiceWorkerResponseMetadataWriter* writer,
+ const std::string& meta_data) {
+ scoped_refptr<net::IOBuffer> meta_data_buffer =
+ base::MakeRefCounted<net::StringIOBuffer>(meta_data);
+ base::RunLoop loop;
+ writer->WriteMetadata(
+ meta_data_buffer.get(), meta_data.size(),
+ base::Bind(
+ [](base::Closure closure, int expected, int result) {
+ EXPECT_EQ(expected, result);
+ closure.Run();
+ },
+ loop.QuitClosure(), meta_data.size()));
+ loop.Run();
+}
+
+void ReadDataPipeInternal(mojo::DataPipeConsumerHandle handle,
+ std::string* result,
+ base::OnceClosure quit_closure) {
+ while (true) {
+ uint32_t num_bytes;
+ const void* buffer = nullptr;
+ MojoResult rv =
+ handle.BeginReadData(&buffer, &num_bytes, MOJO_READ_DATA_FLAG_NONE);
+ switch (rv) {
+ case MOJO_RESULT_BUSY:
+ case MOJO_RESULT_INVALID_ARGUMENT:
+ NOTREACHED();
+ return;
+ case MOJO_RESULT_FAILED_PRECONDITION:
+ std::move(quit_closure).Run();
+ return;
+ case MOJO_RESULT_SHOULD_WAIT:
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&ReadDataPipeInternal, handle, result,
+ base::Passed(&quit_closure)));
+ return;
+ case MOJO_RESULT_OK:
+ EXPECT_NE(nullptr, buffer);
+ EXPECT_GT(num_bytes, 0u);
+ uint32_t before_size = result->size();
+ result->append(static_cast<const char*>(buffer), num_bytes);
+ uint32_t read_size = result->size() - before_size;
+ EXPECT_EQ(num_bytes, read_size);
+ rv = handle.EndReadData(read_size);
+ EXPECT_EQ(MOJO_RESULT_OK, rv);
+ break;
+ }
+ }
+ NOTREACHED();
+ return;
+}
+
+std::string ReadDataPipe(mojo::ScopedDataPipeConsumerHandle handle) {
+ EXPECT_TRUE(handle.is_valid());
+ std::string result;
+ base::RunLoop loop;
+ ReadDataPipeInternal(handle.get(), &result, loop.QuitClosure());
+ loop.Run();
+ return result;
+}
+
+} // namespace
+
+class ExpectedScriptInfo {
+ public:
+ ExpectedScriptInfo(
+ int64_t resource_id,
+ const GURL& script_url,
+ const std::vector<std::pair<std::string, std::string>>& headers,
+ const std::string& encoding,
+ const std::string& body,
+ const std::string& meta_data)
+ : resource_id_(resource_id),
+ script_url_(script_url),
+ headers_(headers),
+ encoding_(encoding),
+ body_(body),
+ meta_data_(meta_data) {}
+
+ ServiceWorkerDatabase::ResourceRecord WriteToDiskCache(
+ ServiceWorkerStorage* storage) const {
+ auto body_writer = storage->CreateResponseWriter(resource_id_);
+ WriteBodyToDiskCache(body_writer.get(), headers_, body_);
+ auto metadata_writer = storage->CreateResponseMetadataWriter(resource_id_);
+ WriteMetaDataToDiskCache(metadata_writer.get(), meta_data_);
+ return ServiceWorkerDatabase::ResourceRecord(resource_id_, script_url_,
+ body_.size());
+ }
+
+ void CheckIfIdentical(
+ const mojom::ServiceWorkerScriptInfoPtr& script_info) const {
+ EXPECT_EQ(script_url_, script_info->script_url);
+ EXPECT_EQ(encoding_, script_info->encoding);
+ for (const auto& header : headers_) {
+ EXPECT_TRUE(base::ContainsKey(script_info->headers, header.first));
+ EXPECT_EQ(header.second, script_info->headers[header.first]);
+ script_info->headers.erase(header.first);
+ }
+ EXPECT_EQ(0u, script_info->headers.size());
+ EXPECT_TRUE(script_info->body.is_valid());
+ std::string body = ReadDataPipe(std::move(script_info->body));
+ EXPECT_EQ(body_, body);
+ if (meta_data_.size() == 0) {
+ EXPECT_FALSE(script_info->meta_data.is_valid());
+ EXPECT_EQ(0u, script_info->meta_data_size);
+ } else {
+ EXPECT_TRUE(script_info->meta_data.is_valid());
+ std::string meta_data = ReadDataPipe(std::move(script_info->meta_data));
+ EXPECT_EQ(meta_data_, meta_data);
+ }
+ }
+
+ const GURL& script_url() const { return script_url_; }
+
+ private:
+ const int64_t resource_id_;
+ const GURL script_url_;
+ const std::vector<std::pair<std::string, std::string>> headers_;
+ const std::string encoding_;
+ const std::string body_;
+ const std::string meta_data_;
+};
+
+class MockServiceWorkerInstalledScriptsManager
+ : public mojom::ServiceWorkerInstalledScriptsManager {
+ public:
+ MockServiceWorkerInstalledScriptsManager(
+ std::vector<GURL> installed_urls,
+ mojom::ServiceWorkerInstalledScriptsManagerRequest request)
+ : binding_(this, std::move(request)),
+ installed_urls_(std::move(installed_urls)),
+ next_url_(installed_urls_.begin()) {}
+
+ mojom::ServiceWorkerScriptInfoPtr WaitUntilTransferInstalledScript() {
+ EXPECT_TRUE(incoming_script_info_.is_null());
+ EXPECT_FALSE(transfer_installed_script_waiter_);
+ base::RunLoop loop;
+ transfer_installed_script_waiter_ = loop.QuitClosure();
+ loop.Run();
+ EXPECT_FALSE(incoming_script_info_.is_null());
+ return std::move(incoming_script_info_);
+ }
+
+ void TransferInstalledScript(
+ mojom::ServiceWorkerScriptInfoPtr script_info) override {
+ EXPECT_TRUE(incoming_script_info_.is_null());
+ EXPECT_TRUE(transfer_installed_script_waiter_);
+ EXPECT_EQ(*next_url_, script_info->script_url);
+ incoming_script_info_ = std::move(script_info);
+ if (transfer_installed_script_waiter_)
+ std::move(transfer_installed_script_waiter_).Run();
+ ++next_url_;
+ }
+
+ private:
+ mojo::Binding<mojom::ServiceWorkerInstalledScriptsManager> binding_;
+ // This is in the order to be served.
+ const std::vector<GURL> installed_urls_;
+ std::vector<GURL>::const_iterator next_url_;
+
+ base::OnceClosure transfer_installed_script_waiter_;
+ mojom::ServiceWorkerScriptInfoPtr incoming_script_info_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockServiceWorkerInstalledScriptsManager);
+};
+
+class ServiceWorkerInstalledScriptsSenderTest : public testing::Test {
+ public:
+ ServiceWorkerInstalledScriptsSenderTest()
+ : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {}
+
+ protected:
+ void SetUp() override {
+ helper_ = base::MakeUnique<EmbeddedWorkerTestHelper>(base::FilePath());
+
+ context()->storage()->LazyInitialize(base::Bind(&base::DoNothing));
+ base::RunLoop().RunUntilIdle();
+
+ pattern_ = GURL("http://www.example.com/test/");
+ registration_ = base::MakeRefCounted<ServiceWorkerRegistration>(
+ ServiceWorkerRegistrationOptions(pattern_), 1L, context()->AsWeakPtr());
+ version_ = base::MakeRefCounted<ServiceWorkerVersion>(
+ registration_.get(),
+ GURL("http://www.example.com/test/service_worker.js"),
+ context()->storage()->NewVersionId(), context()->AsWeakPtr());
+ }
+
+ void TearDown() override {
+ version_ = nullptr;
+ registration_ = nullptr;
+ helper_.reset();
+ }
+
+ ServiceWorkerContextCore* context() { return helper_->context(); }
+ ServiceWorkerVersion* version() { return version_.get(); }
+
+ private:
+ TestBrowserThreadBundle thread_bundle_;
+ std::unique_ptr<EmbeddedWorkerTestHelper> helper_;
+
+ GURL pattern_;
+ scoped_refptr<ServiceWorkerRegistration> registration_;
+ scoped_refptr<ServiceWorkerVersion> version_;
+};
+
+using SenderFinishedReason =
+ ServiceWorkerInstalledScriptsSender::FinishedReason;
+
+TEST_F(ServiceWorkerInstalledScriptsSenderTest, SendScripts) {
+ const GURL kMainScriptURL = version()->script_url();
+ std::string long_body = "I'm the script body!";
+ std::string long_meta_data = "I'm the meta data!";
+ long_body.resize(1E6, '!');
+ long_meta_data.resize(1E6, '!');
+ std::map<GURL, ExpectedScriptInfo> kExpectedScriptInfoMap = {
+ {kMainScriptURL,
+ {1,
+ kMainScriptURL,
+ {{"Content-Length", "1000000"},
+ {"Content-Type", "text/javascript; charset=utf-8"},
+ {"TestHeader", "BlahBlah"}},
+ "utf-8",
+ std::move(long_body),
+ std::move(long_meta_data)}},
+ {GURL("https://example.com/imported1"),
+ {2,
+ GURL("https://example.com/imported1"),
+ {{"Content-Length", "22"},
+ {"Content-Type", "text/javascript; charset=euc-jp"},
+ {"TestHeader", "BlahBlah"}},
+ "euc-jp",
+ "I'm imported script 1!",
+ "I'm the meta data for imported script 1!"}},
+ {GURL("https://example.com/imported2"),
+ {3,
+ GURL("https://example.com/imported2"),
+ {{"Content-Length", "0"},
+ {"Content-Type", "text/javascript; charset=shift_jis"},
+ {"TestHeader", "BlahBlah"}},
+ "shift_jis",
+ "",
+ ""}},
+ };
+
+ {
+ std::vector<ServiceWorkerDatabase::ResourceRecord> records;
+ for (const auto& info : kExpectedScriptInfoMap)
+ records.push_back(info.second.WriteToDiskCache(context()->storage()));
+ version()->script_cache_map()->SetResources(records);
+ }
+
+ auto sender = base::MakeUnique<ServiceWorkerInstalledScriptsSender>(
+ version(), kMainScriptURL, context()->AsWeakPtr());
+
+ std::unique_ptr<MockServiceWorkerInstalledScriptsManager> renderer_manager;
+ {
+ mojom::ServiceWorkerInstalledScriptsInfoPtr scripts_info =
+ sender->CreateInfoAndBind();
+ ASSERT_TRUE(scripts_info);
+ ASSERT_EQ(kExpectedScriptInfoMap.size(),
+ scripts_info->installed_urls.size());
+ for (const auto& url : scripts_info->installed_urls)
+ EXPECT_TRUE(base::ContainsKey(kExpectedScriptInfoMap, url));
+ EXPECT_TRUE(scripts_info->manager_request.is_pending());
+ renderer_manager =
+ base::MakeUnique<MockServiceWorkerInstalledScriptsManager>(
+ std::move(scripts_info->installed_urls),
+ std::move(scripts_info->manager_request));
+ }
+ ASSERT_TRUE(renderer_manager);
+
+ sender->Start();
+
+ while (kExpectedScriptInfoMap.size() > 0) {
+ EXPECT_FALSE(sender->IsFinished());
+ EXPECT_EQ(SenderFinishedReason::kNotFinished, sender->finished_reason());
+ auto script_info = renderer_manager->WaitUntilTransferInstalledScript();
+ EXPECT_TRUE(
+ base::ContainsKey(kExpectedScriptInfoMap, script_info->script_url));
+ const auto& info = kExpectedScriptInfoMap.at(script_info->script_url);
+ info.CheckIfIdentical(script_info);
+ kExpectedScriptInfoMap.erase(script_info->script_url);
+ }
+
+ EXPECT_TRUE(sender->IsFinished());
+ EXPECT_EQ(SenderFinishedReason::kSuccess, sender->finished_reason());
+}
+
+TEST_F(ServiceWorkerInstalledScriptsSenderTest, FailedToSendBody) {
+ const GURL kMainScriptURL = version()->script_url();
+ std::string long_body = "I'm the body";
+ long_body.resize(1E6, '!');
+ std::map<GURL, ExpectedScriptInfo> kExpectedScriptInfoMap = {
+ {kMainScriptURL,
+ {1,
+ kMainScriptURL,
+ {{"Content-Length", "1000000"},
+ {"Content-Type", "text/javascript; charset=utf-8"},
+ {"TestHeader", "BlahBlah"}},
+ "utf-8",
+ std::move(long_body),
+ "I'm the meta data!"}},
+ };
+
+ {
+ std::vector<ServiceWorkerDatabase::ResourceRecord> records;
+ for (const auto& info : kExpectedScriptInfoMap)
+ records.push_back(info.second.WriteToDiskCache(context()->storage()));
+ version()->script_cache_map()->SetResources(records);
+ }
+
+ auto sender = base::MakeUnique<ServiceWorkerInstalledScriptsSender>(
+ version(), kMainScriptURL, context()->AsWeakPtr());
+
+ std::unique_ptr<MockServiceWorkerInstalledScriptsManager> renderer_manager;
+ {
+ mojom::ServiceWorkerInstalledScriptsInfoPtr scripts_info =
+ sender->CreateInfoAndBind();
+ ASSERT_TRUE(scripts_info);
+ ASSERT_EQ(kExpectedScriptInfoMap.size(),
+ scripts_info->installed_urls.size());
+ for (const auto& url : scripts_info->installed_urls)
+ EXPECT_TRUE(base::ContainsKey(kExpectedScriptInfoMap, url));
+ EXPECT_TRUE(scripts_info->manager_request.is_pending());
+ renderer_manager =
+ base::MakeUnique<MockServiceWorkerInstalledScriptsManager>(
+ std::move(scripts_info->installed_urls),
+ std::move(scripts_info->manager_request));
+ }
+ ASSERT_TRUE(renderer_manager);
+
+ sender->Start();
+ EXPECT_FALSE(sender->IsFinished());
+ EXPECT_EQ(SenderFinishedReason::kNotFinished, sender->finished_reason());
+
+ {
+ // Reset a data pipe during sending the body.
+ auto script_info = renderer_manager->WaitUntilTransferInstalledScript();
+ EXPECT_TRUE(
+ base::ContainsKey(kExpectedScriptInfoMap, script_info->script_url));
+ script_info->body.reset();
+ kExpectedScriptInfoMap.erase(script_info->script_url);
+ // Wait until the error is triggered on the sender side.
+ base::RunLoop().RunUntilIdle();
+ }
+
+ EXPECT_TRUE(sender->IsFinished());
+ EXPECT_EQ(SenderFinishedReason::kConnectionError, sender->finished_reason());
+}
+
+TEST_F(ServiceWorkerInstalledScriptsSenderTest, FailedToSendMetaData) {
+ const GURL kMainScriptURL = version()->script_url();
+ std::string long_meta_data = "I'm the meta data!";
+ long_meta_data.resize(1E6, '!');
+ std::map<GURL, ExpectedScriptInfo> kExpectedScriptInfoMap = {
+ {kMainScriptURL,
+ {1,
+ kMainScriptURL,
+ {{"Content-Length", "0"},
+ {"Content-Type", "text/javascript; charset=utf-8"},
+ {"TestHeader", "BlahBlah"}},
+ "utf-8",
+ "",
+ std::move(long_meta_data)}},
+ };
+
+ {
+ std::vector<ServiceWorkerDatabase::ResourceRecord> records;
+ for (const auto& info : kExpectedScriptInfoMap)
+ records.push_back(info.second.WriteToDiskCache(context()->storage()));
+ version()->script_cache_map()->SetResources(records);
+ }
+
+ auto sender = base::MakeUnique<ServiceWorkerInstalledScriptsSender>(
+ version(), kMainScriptURL, context()->AsWeakPtr());
+
+ std::unique_ptr<MockServiceWorkerInstalledScriptsManager> renderer_manager;
+ {
+ mojom::ServiceWorkerInstalledScriptsInfoPtr scripts_info =
+ sender->CreateInfoAndBind();
+ ASSERT_TRUE(scripts_info);
+ ASSERT_EQ(kExpectedScriptInfoMap.size(),
+ scripts_info->installed_urls.size());
+ for (const auto& url : scripts_info->installed_urls)
+ EXPECT_TRUE(base::ContainsKey(kExpectedScriptInfoMap, url));
+ EXPECT_TRUE(scripts_info->manager_request.is_pending());
+ renderer_manager =
+ base::MakeUnique<MockServiceWorkerInstalledScriptsManager>(
+ std::move(scripts_info->installed_urls),
+ std::move(scripts_info->manager_request));
+ }
+ ASSERT_TRUE(renderer_manager);
+
+ sender->Start();
+ EXPECT_FALSE(sender->IsFinished());
+ EXPECT_EQ(SenderFinishedReason::kNotFinished, sender->finished_reason());
+
+ {
+ // Reset a data pipe during sending the meta data.
+ auto script_info = renderer_manager->WaitUntilTransferInstalledScript();
+ EXPECT_TRUE(
+ base::ContainsKey(kExpectedScriptInfoMap, script_info->script_url));
+ script_info->meta_data.reset();
+ kExpectedScriptInfoMap.erase(script_info->script_url);
+ // Wait until the error is triggered on the sender side.
+ base::RunLoop().RunUntilIdle();
+ }
+
+ EXPECT_TRUE(sender->IsFinished());
+ EXPECT_EQ(SenderFinishedReason::kMetaDataSenderError,
+ sender->finished_reason());
+}
+
+TEST_F(ServiceWorkerInstalledScriptsSenderTest, Histograms) {
+ const GURL kMainScriptURL = version()->script_url();
+ // Use script bodies small enough to be read by one
+ // ServiceWorkerResponseReader::ReadData(). The number of
+ // ServiceWorker.DiskCache.ReadResponseResult will be two per script (one is
+ // reading the body and the other is saying EOD).
+ std::map<GURL, ExpectedScriptInfo> kExpectedScriptInfoMap = {
+ {kMainScriptURL,
+ {1,
+ kMainScriptURL,
+ {{"Content-Length", "17"},
+ {"Content-Type", "text/javascript; charset=utf-8"},
+ {"TestHeader", "BlahBlah"}},
+ "utf-8",
+ "Small script body",
+ "I'm the meta data!"}},
+ {GURL("https://example.com/imported1"),
+ {2,
+ GURL("https://example.com/imported1"),
+ {{"Content-Length", "21"},
+ {"Content-Type", "text/javascript; charset=euc-jp"},
+ {"TestHeader", "BlahBlah"}},
+ "euc-jp",
+ "Small imported script",
+ "I'm the meta data for imported script 1!"}},
+ };
+
+ {
+ std::vector<ServiceWorkerDatabase::ResourceRecord> records;
+ for (const auto& info : kExpectedScriptInfoMap)
+ records.push_back(info.second.WriteToDiskCache(context()->storage()));
+ version()->script_cache_map()->SetResources(records);
+ }
+
+ auto sender = base::MakeUnique<ServiceWorkerInstalledScriptsSender>(
+ version(), kMainScriptURL, context()->AsWeakPtr());
+
+ std::unique_ptr<MockServiceWorkerInstalledScriptsManager> renderer_manager;
+ {
+ mojom::ServiceWorkerInstalledScriptsInfoPtr scripts_info =
+ sender->CreateInfoAndBind();
+ ASSERT_TRUE(scripts_info);
+ ASSERT_EQ(kExpectedScriptInfoMap.size(),
+ scripts_info->installed_urls.size());
+ for (const auto& url : scripts_info->installed_urls)
+ EXPECT_TRUE(base::ContainsKey(kExpectedScriptInfoMap, url));
+ EXPECT_TRUE(scripts_info->manager_request.is_pending());
+ renderer_manager =
+ base::MakeUnique<MockServiceWorkerInstalledScriptsManager>(
+ std::move(scripts_info->installed_urls),
+ std::move(scripts_info->manager_request));
+ }
+ ASSERT_TRUE(renderer_manager);
+
+ base::HistogramTester histogram_tester;
+ sender->Start();
+
+ while (kExpectedScriptInfoMap.size() > 0) {
+ EXPECT_FALSE(sender->IsFinished());
+ EXPECT_EQ(SenderFinishedReason::kNotFinished, sender->finished_reason());
+ auto script_info = renderer_manager->WaitUntilTransferInstalledScript();
+ EXPECT_TRUE(
+ base::ContainsKey(kExpectedScriptInfoMap, script_info->script_url));
+ const auto& info = kExpectedScriptInfoMap.at(script_info->script_url);
+ info.CheckIfIdentical(script_info);
+ kExpectedScriptInfoMap.erase(script_info->script_url);
+ }
+
+ EXPECT_TRUE(sender->IsFinished());
+ EXPECT_EQ(SenderFinishedReason::kSuccess, sender->finished_reason());
+
+ // The histogram should be recorded when reading the script.
+ // The count should be four: reading the response body of a main script and an
+ // imported script, and the end of reading bodies for the two scripts.
+ histogram_tester.ExpectBucketCount(
+ "ServiceWorker.DiskCache.ReadResponseResult",
+ ServiceWorkerMetrics::ReadResponseResult::READ_OK, 4);
+}
+
+TEST_F(ServiceWorkerInstalledScriptsSenderTest, NoInstalledScript) {
+ // Create a scripts sender for a version that has no installed scripts.
+ const GURL kMainScriptURL = version()->script_url();
+ auto sender = base::MakeUnique<ServiceWorkerInstalledScriptsSender>(
+ version(), kMainScriptURL, context()->AsWeakPtr());
+ EXPECT_FALSE(sender->CreateInfoAndBind());
+ EXPECT_FALSE(sender->IsFinished());
+ EXPECT_EQ(SenderFinishedReason::kNotFinished, sender->finished_reason());
+
+ sender->Start();
+ // Finish immediately because there are no installed scripts.
+ EXPECT_TRUE(sender->IsFinished());
+ EXPECT_EQ(SenderFinishedReason::kSuccess, sender->finished_reason());
+}
+
+} // namespace content
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 6a15cd4f1ad..60146802931 100644
--- a/chromium/content/browser/service_worker/service_worker_internals_ui.cc
+++ b/chromium/content/browser/service_worker/service_worker_internals_ui.cc
@@ -52,10 +52,9 @@ void OperationCompleteCallback(WeakPtr<ServiceWorkerInternalsUI> internals,
int callback_id,
ServiceWorkerStatusCode status) {
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- BrowserThread::PostTask(
- BrowserThread::UI,
- FROM_HERE,
- base::Bind(OperationCompleteCallback, internals, callback_id, status));
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::BindOnce(OperationCompleteCallback, internals,
+ callback_id, status));
return;
}
DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -73,13 +72,9 @@ void CallServiceWorkerVersionMethodWithVersionID(
const ServiceWorkerInternalsUI::StatusCallback& callback) {
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
BrowserThread::PostTask(
- BrowserThread::IO,
- FROM_HERE,
- base::Bind(CallServiceWorkerVersionMethodWithVersionID,
- method,
- context,
- version_id,
- callback));
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(CallServiceWorkerVersionMethodWithVersionID, method,
+ context, version_id, callback));
return;
}
@@ -233,8 +228,8 @@ void DidGetStoredRegistrationsOnIOThread(
DCHECK_CURRENTLY_ON(BrowserThread::IO);
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(callback, context->GetAllLiveRegistrationInfo(),
- context->GetAllLiveVersionInfo(), stored_registrations));
+ base::BindOnce(callback, context->GetAllLiveRegistrationInfo(),
+ context->GetAllLiveVersionInfo(), stored_registrations));
}
void GetRegistrationsOnIOThread(
@@ -455,10 +450,11 @@ void ServiceWorkerInternalsUI::AddContextFromStoragePartition(
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(GetRegistrationsOnIOThread, context,
- base::Bind(DidGetRegistrations, AsWeakPtr(), partition_id,
- context->is_incognito() ? base::FilePath()
- : partition->GetPath())));
+ base::BindOnce(
+ GetRegistrationsOnIOThread, context,
+ base::Bind(DidGetRegistrations, AsWeakPtr(), partition_id,
+ context->is_incognito() ? base::FilePath()
+ : partition->GetPath())));
}
void ServiceWorkerInternalsUI::RemoveObserverFromStoragePartition(
@@ -601,8 +597,8 @@ void ServiceWorkerInternalsUI::UnregisterWithScope(
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&ServiceWorkerInternalsUI::UnregisterWithScope,
- base::Unretained(this), context, scope, callback));
+ base::BindOnce(&ServiceWorkerInternalsUI::UnregisterWithScope,
+ base::Unretained(this), context, scope, callback));
return;
}
diff --git a/chromium/content/browser/service_worker/service_worker_job_coordinator.cc b/chromium/content/browser/service_worker/service_worker_job_coordinator.cc
index 19778d2cfbf..7a504879ff4 100644
--- a/chromium/content/browser/service_worker/service_worker_job_coordinator.cc
+++ b/chromium/content/browser/service_worker/service_worker_job_coordinator.cc
@@ -20,7 +20,7 @@ bool IsRegisterJob(const ServiceWorkerRegisterJobBase& job) {
return job.GetType() == ServiceWorkerRegisterJobBase::REGISTRATION_JOB;
}
-}
+} // namespace
ServiceWorkerJobCoordinator::JobQueue::JobQueue() = default;
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 26f29c9d991..0e2d7ffb050 100644
--- a/chromium/content/browser/service_worker/service_worker_job_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_job_unittest.cc
@@ -20,13 +20,17 @@
#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_disk_cache.h"
+#include "content/browser/service_worker/service_worker_dispatcher_host.h"
+#include "content/browser/service_worker/service_worker_handle.h"
#include "content/browser/service_worker/service_worker_job_coordinator.h"
#include "content/browser/service_worker/service_worker_registration.h"
+#include "content/browser/service_worker/service_worker_registration_handle.h"
#include "content/browser/service_worker/service_worker_registration_status.h"
#include "content/browser/service_worker/service_worker_test_utils.h"
#include "content/common/service_worker/embedded_worker_messages.h"
#include "content/common/service_worker/service_worker_messages.h"
#include "content/common/service_worker/service_worker_utils.h"
+#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "ipc/ipc_test_sink.h"
#include "net/base/io_buffer.h"
@@ -44,6 +48,45 @@ namespace content {
namespace {
+// A dispatcher host that holds on to all registered ServiceWorkerHandles and
+// ServiceWorkerRegistrationHandles.
+class KeepHandlesDispatcherHost : public ServiceWorkerDispatcherHost {
+ public:
+ KeepHandlesDispatcherHost(int render_process_id,
+ ResourceContext* resource_context)
+ : ServiceWorkerDispatcherHost(render_process_id, resource_context) {}
+ void RegisterServiceWorkerHandle(
+ std::unique_ptr<ServiceWorkerHandle> handle) override {
+ handles_.push_back(std::move(handle));
+ }
+ void RegisterServiceWorkerRegistrationHandle(
+ std::unique_ptr<ServiceWorkerRegistrationHandle> handle) override {
+ registration_handles_.push_back(std::move(handle));
+ }
+
+ void RemoveHandles() {
+ handles_.clear();
+ registration_handles_.clear();
+ }
+
+ const std::vector<std::unique_ptr<ServiceWorkerHandle>>& handles() {
+ return handles_;
+ }
+
+ const std::vector<std::unique_ptr<ServiceWorkerRegistrationHandle>>&
+ registration_handles() {
+ return registration_handles_;
+ }
+
+ private:
+ ~KeepHandlesDispatcherHost() override {}
+
+ std::vector<std::unique_ptr<ServiceWorkerHandle>> handles_;
+ std::vector<std::unique_ptr<ServiceWorkerRegistrationHandle>>
+ registration_handles_;
+ DISALLOW_COPY_AND_ASSIGN(KeepHandlesDispatcherHost);
+};
+
void SaveRegistrationCallback(
ServiceWorkerStatusCode expected_status,
bool* called,
@@ -357,11 +400,29 @@ TEST_F(ServiceWorkerJobTest, Register) {
TEST_F(ServiceWorkerJobTest, Unregister) {
GURL pattern("http://www.example.com/");
+ // During registration, handles will be created for hosting the worker's
+ // context. KeepHandlesDispatcherHost will store the handles.
+ scoped_refptr<KeepHandlesDispatcherHost> dispatcher_host =
+ base::MakeRefCounted<KeepHandlesDispatcherHost>(
+ helper_->mock_render_process_id(),
+ helper_->browser_context()->GetResourceContext());
+ helper_->RegisterDispatcherHost(helper_->mock_render_process_id(),
+ dispatcher_host);
+ dispatcher_host->Init(helper_->context_wrapper());
+
scoped_refptr<ServiceWorkerRegistration> registration =
RunRegisterJob(pattern, GURL("http://www.example.com/service_worker.js"));
+ EXPECT_EQ(1UL, dispatcher_host->registration_handles().size());
+ EXPECT_EQ(3UL, dispatcher_host->handles().size());
+
RunUnregisterJob(pattern);
+ // Remove the handles. The only reference to the registration object should be
+ // |registration|.
+ dispatcher_host->RemoveHandles();
+ EXPECT_EQ(0UL, dispatcher_host->registration_handles().size());
+ EXPECT_EQ(0UL, dispatcher_host->handles().size());
ASSERT_TRUE(registration->HasOneRef());
registration = FindRegistrationForPattern(pattern,
@@ -405,12 +466,28 @@ TEST_F(ServiceWorkerJobTest, RegisterNewScript) {
// Make sure that when registering a duplicate pattern+script_url
// combination, that the same registration is used.
TEST_F(ServiceWorkerJobTest, RegisterDuplicateScript) {
+ // During registration, handles will be created for hosting the worker's
+ // context. KeepHandlesDispatcherHost will store the handles.
+ scoped_refptr<KeepHandlesDispatcherHost> dispatcher_host =
+ new KeepHandlesDispatcherHost(
+ helper_->mock_render_process_id(),
+ helper_->browser_context()->GetResourceContext());
+ helper_->RegisterDispatcherHost(helper_->mock_render_process_id(),
+ dispatcher_host);
+ dispatcher_host->Init(helper_->context_wrapper());
+
GURL pattern("http://www.example.com/");
GURL script_url("http://www.example.com/service_worker.js");
scoped_refptr<ServiceWorkerRegistration> old_registration =
RunRegisterJob(pattern, script_url);
+ // Ensure that the registration's handle doesn't have the reference.
+ EXPECT_EQ(1UL, dispatcher_host->registration_handles().size());
+ dispatcher_host->RemoveHandles();
+ EXPECT_EQ(0UL, dispatcher_host->registration_handles().size());
+ ASSERT_TRUE(old_registration->HasOneRef());
+
scoped_refptr<ServiceWorkerRegistration> old_registration_by_pattern =
FindRegistrationForPattern(pattern);
@@ -433,14 +510,16 @@ class FailToStartWorkerTestHelper : public EmbeddedWorkerTestHelper {
public:
FailToStartWorkerTestHelper() : EmbeddedWorkerTestHelper(base::FilePath()) {}
- void OnStartWorker(int embedded_worker_id,
- int64_t service_worker_version_id,
- const GURL& scope,
- const GURL& script_url,
- bool pause_after_download,
- mojom::ServiceWorkerEventDispatcherRequest request,
- mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo
- instance_host) override {
+ void OnStartWorker(
+ int embedded_worker_id,
+ int64_t service_worker_version_id,
+ const GURL& scope,
+ const GURL& script_url,
+ bool pause_after_download,
+ mojom::ServiceWorkerEventDispatcherRequest request,
+ mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
+ mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info)
+ override {
mojom::EmbeddedWorkerInstanceHostAssociatedPtr instance_host_ptr;
instance_host_ptr.Bind(std::move(instance_host));
instance_host_ptr->OnStopped();
@@ -848,8 +927,10 @@ class UpdateJobTestHelper
UpdateJobTestHelper() : EmbeddedWorkerTestHelper(base::FilePath()) {}
~UpdateJobTestHelper() override {
- if (registration_.get())
- registration_->RemoveListener(this);
+ if (observed_registration_.get())
+ observed_registration_->RemoveListener(this);
+ for (auto& version : observed_versions_)
+ version->RemoveListener(this);
}
ServiceWorkerStorage* storage() { return context()->storage(); }
@@ -875,19 +956,21 @@ class UpdateJobTestHelper
EXPECT_TRUE(registration->active_version());
EXPECT_FALSE(registration->installing_version());
EXPECT_FALSE(registration->waiting_version());
- registration_ = registration;
+ observed_registration_ = registration;
return registration;
}
// EmbeddedWorkerTestHelper overrides
- void OnStartWorker(int embedded_worker_id,
- int64_t version_id,
- const GURL& scope,
- const GURL& script,
- bool pause_after_download,
- mojom::ServiceWorkerEventDispatcherRequest request,
- mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo
- instance_host) override {
+ void OnStartWorker(
+ int embedded_worker_id,
+ int64_t version_id,
+ const GURL& scope,
+ const GURL& script,
+ bool pause_after_download,
+ mojom::ServiceWorkerEventDispatcherRequest request,
+ mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
+ mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info)
+ override {
const std::string kMockScriptBody = "mock_script";
const uint64_t kMockScriptSize = 19284;
ServiceWorkerVersion* version = context()->GetLiveVersion(version_id);
@@ -897,6 +980,7 @@ class UpdateJobTestHelper
version != registration->active_version();
ASSERT_TRUE(version);
+ observed_versions_.push_back(make_scoped_refptr(version));
version->AddListener(this);
// Simulate network access.
@@ -940,17 +1024,27 @@ class UpdateJobTestHelper
EmbeddedWorkerTestHelper::CreateHttpResponseInfo());
}
+ started_workers_.insert(embedded_worker_id);
EmbeddedWorkerTestHelper::OnStartWorker(
embedded_worker_id, version_id, scope, script, pause_after_download,
- std::move(request), std::move(instance_host));
+ std::move(request), std::move(instance_host), std::move(provider_info));
+ }
+
+ void OnStopWorker(int embedded_worker_id) override {
+ // Some of our tests don't call the base class in OnStartWorker(), so we
+ // can't call the base class's OnStopWorker() either.
+ auto iter = started_workers_.find(embedded_worker_id);
+ if (iter == started_workers_.end())
+ return;
+ EmbeddedWorkerTestHelper::OnStopWorker(embedded_worker_id);
+ started_workers_.erase(iter);
}
void OnResumeAfterDownload(int embedded_worker_id) override {
if (!force_start_worker_failure_) {
EmbeddedWorkerTestHelper::OnResumeAfterDownload(embedded_worker_id);
} else {
- SimulateWorkerThreadStarted(GetNextThreadId(), embedded_worker_id,
- GetNextProviderId());
+ SimulateWorkerThreadStarted(GetNextThreadId(), embedded_worker_id);
SimulateWorkerScriptEvaluated(embedded_worker_id, false);
}
}
@@ -983,10 +1077,12 @@ class UpdateJobTestHelper
state_change_log_.push_back(entry);
}
- scoped_refptr<ServiceWorkerRegistration> registration_;
+ scoped_refptr<ServiceWorkerRegistration> observed_registration_;
+ std::vector<scoped_refptr<ServiceWorkerVersion>> observed_versions_;
std::vector<AttributeChangeLogEntry> attribute_change_log_;
std::vector<StateChangeLogEntry> state_change_log_;
+ std::set<int /* embedded_worker_id */> started_workers_;
bool update_found_ = false;
bool force_start_worker_failure_ = false;
};
@@ -998,14 +1094,16 @@ class EvictIncumbentVersionHelper : public UpdateJobTestHelper {
EvictIncumbentVersionHelper() {}
~EvictIncumbentVersionHelper() override {}
- void OnStartWorker(int embedded_worker_id,
- int64_t version_id,
- const GURL& scope,
- const GURL& script,
- bool pause_after_download,
- mojom::ServiceWorkerEventDispatcherRequest request,
- mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo
- instance_host) override {
+ void OnStartWorker(
+ int embedded_worker_id,
+ int64_t version_id,
+ const GURL& scope,
+ const GURL& script,
+ bool pause_after_download,
+ mojom::ServiceWorkerEventDispatcherRequest request,
+ mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
+ mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info)
+ override {
ServiceWorkerVersion* version = context()->GetLiveVersion(version_id);
ServiceWorkerRegistration* registration =
context()->GetLiveRegistration(version->registration_id());
@@ -1019,7 +1117,7 @@ class EvictIncumbentVersionHelper : public UpdateJobTestHelper {
}
UpdateJobTestHelper::OnStartWorker(
embedded_worker_id, version_id, scope, script, pause_after_download,
- std::move(request), std::move(instance_host));
+ std::move(request), std::move(instance_host), std::move(provider_info));
}
void OnRegistrationFailed(ServiceWorkerRegistration* registration) override {
@@ -1692,17 +1790,21 @@ class CheckPauseAfterDownloadEmbeddedWorkerInstanceClient
}
protected:
- void StartWorker(const EmbeddedWorkerStartParams& params,
- mojom::ServiceWorkerEventDispatcherRequest request,
- mojom::ServiceWorkerInstalledScriptsInfoPtr scripts_info,
- mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo
- instance_host) override {
+ void StartWorker(
+ const EmbeddedWorkerStartParams& params,
+ mojom::ServiceWorkerEventDispatcherRequest request,
+ mojom::ServiceWorkerInstalledScriptsInfoPtr scripts_info,
+ mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
+ mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info,
+ blink::mojom::WorkerContentSettingsProxyPtr content_settings_proxy)
+ override {
ASSERT_TRUE(next_pause_after_download_.has_value());
EXPECT_EQ(next_pause_after_download_.value(), params.pause_after_download);
num_of_startworker_++;
EmbeddedWorkerTestHelper::MockEmbeddedWorkerInstanceClient::StartWorker(
params, std::move(request), std::move(scripts_info),
- std::move(instance_host));
+ std::move(instance_host), std::move(provider_info),
+ std::move(content_settings_proxy));
}
private:
diff --git a/chromium/content/browser/service_worker/service_worker_metrics.cc b/chromium/content/browser/service_worker/service_worker_metrics.cc
index 8c2756c9a76..7a1abc1394b 100644
--- a/chromium/content/browser/service_worker/service_worker_metrics.cc
+++ b/chromium/content/browser/service_worker/service_worker_metrics.cc
@@ -89,6 +89,10 @@ std::string EventTypeToSuffix(ServiceWorkerMetrics::EventType event_type) {
return "_BACKGROUND_FETCHED";
case ServiceWorkerMetrics::EventType::NAVIGATION_HINT:
return "_NAVIGATION_HINT";
+ case ServiceWorkerMetrics::EventType::CAN_MAKE_PAYMENT:
+ return "_CAN_MAKE_PAYMENT";
+ case ServiceWorkerMetrics::EventType::ABORT_PAYMENT:
+ return "_ABORT_PAYMENT";
case ServiceWorkerMetrics::EventType::NUM_TYPES:
NOTREACHED() << static_cast<int>(event_type);
}
@@ -332,6 +336,10 @@ const char* ServiceWorkerMetrics::EventTypeToString(EventType event_type) {
return "Background Fetched";
case EventType::NAVIGATION_HINT:
return "Navigation Hint";
+ case EventType::CAN_MAKE_PAYMENT:
+ return "Can Make Payment";
+ case ServiceWorkerMetrics::EventType::ABORT_PAYMENT:
+ return "Abort Payment";
case EventType::NUM_TYPES:
break;
}
@@ -475,7 +483,8 @@ void ServiceWorkerMetrics::CountControlledPageLoad(
}
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&RecordURLMetricOnUI, "ServiceWorker.ControlledPageUrl", url));
+ base::BindOnce(&RecordURLMetricOnUI, "ServiceWorker.ControlledPageUrl",
+ url));
}
void ServiceWorkerMetrics::RecordStartWorkerStatus(
@@ -493,16 +502,21 @@ void ServiceWorkerMetrics::RecordStartWorkerStatus(
RecordHistogramEnum(std::string("ServiceWorker.StartWorker.StatusByPurpose") +
EventTypeToSuffix(purpose),
status, SERVICE_WORKER_ERROR_MAX_VALUE);
- UMA_HISTOGRAM_ENUMERATION("ServiceWorker.StartWorker.Purpose",
- static_cast<int>(purpose),
- static_cast<int>(EventType::NUM_TYPES));
+ UMA_HISTOGRAM_ENUMERATION("ServiceWorker.StartWorker.Purpose", purpose,
+ EventType::NUM_TYPES);
if (status == SERVICE_WORKER_ERROR_TIMEOUT) {
UMA_HISTOGRAM_ENUMERATION("ServiceWorker.StartWorker.Timeout.StartPurpose",
- static_cast<int>(purpose),
- static_cast<int>(EventType::NUM_TYPES));
+ purpose, EventType::NUM_TYPES);
}
}
+void ServiceWorkerMetrics::RecordInstalledScriptsSenderStatus(
+ ServiceWorkerInstalledScriptsSender::FinishedReason reason) {
+ UMA_HISTOGRAM_ENUMERATION(
+ "ServiceWorker.StartWorker.InstalledScriptsSender.FinishedReason", reason,
+ ServiceWorkerInstalledScriptsSender::FinishedReason::kMaxValue);
+}
+
void ServiceWorkerMetrics::RecordStartWorkerTime(base::TimeDelta time,
bool is_installed,
StartSituation start_situation,
@@ -723,6 +737,13 @@ void ServiceWorkerMetrics::RecordEventDuration(EventType event,
UMA_HISTOGRAM_MEDIUM_TIMES("ServiceWorker.BackgroundFetchedEvent.Time",
time);
break;
+ case EventType::CAN_MAKE_PAYMENT:
+ UMA_HISTOGRAM_MEDIUM_TIMES("ServiceWorker.CanMakePaymentEvent.Time",
+ time);
+ break;
+ case EventType::ABORT_PAYMENT:
+ UMA_HISTOGRAM_MEDIUM_TIMES("ServiceWorker.AbortPaymentEvent.Time", time);
+ break;
case EventType::NAVIGATION_HINT:
// The navigation hint should not be sent as an event.
@@ -1047,10 +1068,10 @@ void ServiceWorkerMetrics::RecordRuntime(base::TimeDelta time) {
void ServiceWorkerMetrics::RecordUninstalledScriptImport(const GURL& url) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&RecordURLMetricOnUI,
- "ServiceWorker.ContextRequestHandlerStatus."
- "UninstalledScriptImport",
- url));
+ base::BindOnce(&RecordURLMetricOnUI,
+ "ServiceWorker.ContextRequestHandlerStatus."
+ "UninstalledScriptImport",
+ url));
}
void ServiceWorkerMetrics::RecordStartServiceWorkerForNavigationHintResult(
diff --git a/chromium/content/browser/service_worker/service_worker_metrics.h b/chromium/content/browser/service_worker/service_worker_metrics.h
index cd0c8ff7139..f733146891b 100644
--- a/chromium/content/browser/service_worker/service_worker_metrics.h
+++ b/chromium/content/browser/service_worker/service_worker_metrics.h
@@ -13,6 +13,7 @@
#include "base/time/time.h"
#include "content/browser/service_worker/service_worker_context_request_handler.h"
#include "content/browser/service_worker/service_worker_database.h"
+#include "content/browser/service_worker/service_worker_installed_scripts_sender.h"
#include "content/common/service_worker/embedded_worker.mojom.h"
#include "content/common/service_worker/service_worker_types.h"
#include "content/public/browser/service_worker_context.h"
@@ -126,6 +127,8 @@ class ServiceWorkerMetrics {
BACKGROUND_FETCH_FAIL = 25,
BACKGROUND_FETCHED = 26,
NAVIGATION_HINT = 27,
+ CAN_MAKE_PAYMENT = 28,
+ ABORT_PAYMENT = 29,
// Add new events to record here.
NUM_TYPES
};
@@ -269,6 +272,10 @@ class ServiceWorkerMetrics {
EventType purpose,
bool is_installed);
+ // Records the result of sending installed scripts to the renderer.
+ static void RecordInstalledScriptsSenderStatus(
+ ServiceWorkerInstalledScriptsSender::FinishedReason reason);
+
// Records the time taken to successfully start a worker. |is_installed|
// indicates whether the version has been installed.
static void RecordStartWorkerTime(base::TimeDelta time,
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 279461f8e8f..a840a8aa76b 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
@@ -44,7 +44,7 @@ void ServiceWorkerNavigationHandleCore::DidPreCreateProviderHost(
precreated_host_->provider_id(), this);
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(
+ base::BindOnce(
&ServiceWorkerNavigationHandle::DidCreateServiceWorkerProviderHost,
ui_handle_, precreated_host_->provider_id()));
}
diff --git a/chromium/content/browser/service_worker/service_worker_process_manager.cc b/chromium/content/browser/service_worker/service_worker_process_manager.cc
index 8e193da3f6b..ef13976eba4 100644
--- a/chromium/content/browser/service_worker/service_worker_process_manager.cc
+++ b/chromium/content/browser/service_worker/service_worker_process_manager.cc
@@ -90,7 +90,7 @@ void ServiceWorkerProcessManager::Shutdown() {
for (std::map<int, ProcessInfo>::const_iterator it = instance_info_.begin();
it != instance_info_.end(); ++it) {
RenderProcessHost::FromID(it->second.process_id)
- ->DecrementServiceWorkerRefCount();
+ ->DecrementKeepAliveRefCount();
}
}
instance_info_.clear();
@@ -105,12 +105,10 @@ void ServiceWorkerProcessManager::AddProcessReferenceToPattern(
const GURL& pattern, int process_id) {
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
BrowserThread::PostTask(
- BrowserThread::UI,
- FROM_HERE,
- base::Bind(&ServiceWorkerProcessManager::AddProcessReferenceToPattern,
- weak_this_,
- pattern,
- process_id));
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(
+ &ServiceWorkerProcessManager::AddProcessReferenceToPattern,
+ weak_this_, pattern, process_id));
return;
}
@@ -122,13 +120,10 @@ void ServiceWorkerProcessManager::RemoveProcessReferenceFromPattern(
const GURL& pattern, int process_id) {
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
BrowserThread::PostTask(
- BrowserThread::UI,
- FROM_HERE,
- base::Bind(
- &ServiceWorkerProcessManager::RemoveProcessReferenceFromPattern,
- weak_this_,
- pattern,
- process_id));
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(
+ &ServiceWorkerProcessManager::RemoveProcessReferenceFromPattern,
+ weak_this_, pattern, process_id));
return;
}
@@ -190,7 +185,7 @@ ServiceWorkerStatusCode ServiceWorkerProcessManager::AllocateWorkerProcess(
if (can_use_existing_process) {
int process_id = FindAvailableProcess(pattern);
if (process_id != ChildProcessHost::kInvalidUniqueID) {
- RenderProcessHost::FromID(process_id)->IncrementServiceWorkerRefCount();
+ RenderProcessHost::FromID(process_id)->IncrementKeepAliveRefCount();
instance_info_.insert(
std::make_pair(embedded_worker_id, ProcessInfo(process_id)));
out_info->process_id = process_id;
@@ -243,7 +238,7 @@ ServiceWorkerStatusCode ServiceWorkerProcessManager::AllocateWorkerProcess(
instance_info_.insert(
std::make_pair(embedded_worker_id, ProcessInfo(site_instance)));
- rph->IncrementServiceWorkerRefCount();
+ rph->IncrementKeepAliveRefCount();
out_info->process_id = rph->GetID();
out_info->start_situation = start_situation;
return SERVICE_WORKER_OK;
@@ -283,7 +278,7 @@ void ServiceWorkerProcessManager::ReleaseWorkerProcess(int embedded_worker_id) {
<< "Process " << info->second.process_id
<< " was destroyed unexpectedly. Did we actually hold a reference?";
}
- rph->DecrementServiceWorkerRefCount();
+ rph->DecrementKeepAliveRefCount();
instance_info_.erase(info);
}
diff --git a/chromium/content/browser/service_worker/service_worker_process_manager_unittest.cc b/chromium/content/browser/service_worker/service_worker_process_manager_unittest.cc
index 90d65da5ded..a88ece9d5f4 100644
--- a/chromium/content/browser/service_worker/service_worker_process_manager_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_process_manager_unittest.cc
@@ -121,8 +121,8 @@ TEST_F(ServiceWorkerProcessManagerTest,
std::unique_ptr<MockRenderProcessHost> host2(CreateRenderProcessHost());
process_manager_->AddProcessReferenceToPattern(scope1, host1->GetID());
process_manager_->AddProcessReferenceToPattern(scope2, host2->GetID());
- ASSERT_EQ(0u, host1->GetWorkerRefCount());
- ASSERT_EQ(0u, host2->GetWorkerRefCount());
+ ASSERT_EQ(0u, host1->GetKeepAliveRefCount());
+ ASSERT_EQ(0u, host2->GetKeepAliveRefCount());
std::map<int, ServiceWorkerProcessManager::ProcessInfo>& instance_info =
process_manager_->instance_info_;
@@ -138,8 +138,8 @@ TEST_F(ServiceWorkerProcessManagerTest,
EXPECT_EQ(host1->GetID(), process_info.process_id);
EXPECT_EQ(ServiceWorkerMetrics::StartSituation::EXISTING_READY_PROCESS,
process_info.start_situation);
- EXPECT_EQ(1u, host1->GetWorkerRefCount());
- EXPECT_EQ(0u, host2->GetWorkerRefCount());
+ EXPECT_EQ(1u, host1->GetKeepAliveRefCount());
+ EXPECT_EQ(0u, host2->GetKeepAliveRefCount());
EXPECT_EQ(1u, instance_info.size());
std::map<int, ServiceWorkerProcessManager::ProcessInfo>::iterator found =
instance_info.find(kEmbeddedWorkerId1);
@@ -157,8 +157,8 @@ TEST_F(ServiceWorkerProcessManagerTest,
EXPECT_EQ(host1->GetID(), process_info.process_id);
EXPECT_EQ(ServiceWorkerMetrics::StartSituation::EXISTING_READY_PROCESS,
process_info.start_situation);
- EXPECT_EQ(2u, host1->GetWorkerRefCount());
- EXPECT_EQ(0u, host2->GetWorkerRefCount());
+ EXPECT_EQ(2u, host1->GetKeepAliveRefCount());
+ EXPECT_EQ(0u, host2->GetKeepAliveRefCount());
EXPECT_EQ(2u, instance_info.size());
found = instance_info.find(kEmbeddedWorkerId2);
ASSERT_TRUE(found != instance_info.end());
@@ -175,8 +175,8 @@ TEST_F(ServiceWorkerProcessManagerTest,
EXPECT_EQ(host2->GetID(), process_info.process_id);
EXPECT_EQ(ServiceWorkerMetrics::StartSituation::EXISTING_READY_PROCESS,
process_info.start_situation);
- EXPECT_EQ(2u, host1->GetWorkerRefCount());
- EXPECT_EQ(1u, host2->GetWorkerRefCount());
+ EXPECT_EQ(2u, host1->GetKeepAliveRefCount());
+ EXPECT_EQ(1u, host2->GetKeepAliveRefCount());
EXPECT_EQ(3u, instance_info.size());
found = instance_info.find(kEmbeddedWorkerId3);
ASSERT_TRUE(found != instance_info.end());
@@ -184,21 +184,21 @@ TEST_F(ServiceWorkerProcessManagerTest,
// The instance map should be updated by process release.
process_manager_->ReleaseWorkerProcess(kEmbeddedWorkerId3);
- EXPECT_EQ(2u, host1->GetWorkerRefCount());
- EXPECT_EQ(0u, host2->GetWorkerRefCount());
+ EXPECT_EQ(2u, host1->GetKeepAliveRefCount());
+ EXPECT_EQ(0u, host2->GetKeepAliveRefCount());
EXPECT_EQ(2u, instance_info.size());
EXPECT_TRUE(base::ContainsKey(instance_info, kEmbeddedWorkerId1));
EXPECT_TRUE(base::ContainsKey(instance_info, kEmbeddedWorkerId2));
process_manager_->ReleaseWorkerProcess(kEmbeddedWorkerId1);
- EXPECT_EQ(1u, host1->GetWorkerRefCount());
- EXPECT_EQ(0u, host2->GetWorkerRefCount());
+ EXPECT_EQ(1u, host1->GetKeepAliveRefCount());
+ EXPECT_EQ(0u, host2->GetKeepAliveRefCount());
EXPECT_EQ(1u, instance_info.size());
EXPECT_TRUE(base::ContainsKey(instance_info, kEmbeddedWorkerId2));
process_manager_->ReleaseWorkerProcess(kEmbeddedWorkerId2);
- EXPECT_EQ(0u, host1->GetWorkerRefCount());
- EXPECT_EQ(0u, host2->GetWorkerRefCount());
+ EXPECT_EQ(0u, host1->GetKeepAliveRefCount());
+ EXPECT_EQ(0u, host2->GetKeepAliveRefCount());
EXPECT_TRUE(instance_info.empty());
}
@@ -228,7 +228,7 @@ TEST_F(ServiceWorkerProcessManagerTest,
EXPECT_EQ(host->GetID(), process_info.process_id);
EXPECT_EQ(ServiceWorkerMetrics::StartSituation::EXISTING_UNREADY_PROCESS,
process_info.start_situation);
- EXPECT_EQ(1u, host->GetWorkerRefCount());
+ EXPECT_EQ(1u, host->GetKeepAliveRefCount());
EXPECT_EQ(1u, instance_info.size());
std::map<int, ServiceWorkerProcessManager::ProcessInfo>::iterator found =
instance_info.find(kEmbeddedWorkerId);
@@ -237,7 +237,7 @@ TEST_F(ServiceWorkerProcessManagerTest,
// Release the process.
process_manager_->ReleaseWorkerProcess(kEmbeddedWorkerId);
- EXPECT_EQ(0u, host->GetWorkerRefCount());
+ EXPECT_EQ(0u, host->GetKeepAliveRefCount());
EXPECT_TRUE(instance_info.empty());
RenderProcessHostImpl::RemoveFrameWithSite(browser_context_.get(), host.get(),
@@ -269,7 +269,7 @@ TEST_F(ServiceWorkerProcessManagerTest,
EXPECT_NE(host->GetID(), process_info.process_id);
EXPECT_EQ(ServiceWorkerMetrics::StartSituation::NEW_PROCESS,
process_info.start_situation);
- EXPECT_EQ(0u, host->GetWorkerRefCount());
+ EXPECT_EQ(0u, host->GetKeepAliveRefCount());
EXPECT_EQ(1u, instance_info.size());
std::map<int, ServiceWorkerProcessManager::ProcessInfo>::iterator found =
instance_info.find(kEmbeddedWorkerId);
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 34a8c1c2c59..fc29d68210f 100644
--- a/chromium/content/browser/service_worker/service_worker_provider_host.cc
+++ b/chromium/content/browser/service_worker/service_worker_provider_host.cc
@@ -6,11 +6,11 @@
#include <utility>
-#include "base/feature_list.h"
#include "base/guid.h"
#include "base/memory/ptr_util.h"
#include "base/stl_util.h"
#include "base/time/time.h"
+#include "content/browser/service_worker/browser_side_service_worker_event_dispatcher.h"
#include "content/browser/service_worker/embedded_worker_status.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_context_request_handler.h"
@@ -18,6 +18,7 @@
#include "content/browser/service_worker/service_worker_dispatcher_host.h"
#include "content/browser/service_worker/service_worker_handle.h"
#include "content/browser/service_worker/service_worker_registration_handle.h"
+#include "content/browser/service_worker/service_worker_script_url_loader_factory.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_messages.h"
@@ -27,7 +28,6 @@
#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/common/child_process_host.h"
#include "content/public/common/content_client.h"
-#include "content/public/common/content_features.h"
#include "content/public/common/origin_util.h"
#include "content/public/common/resource_request_body.h"
#include "mojo/public/cpp/bindings/strong_associated_binding.h"
@@ -38,10 +38,13 @@ namespace content {
namespace {
-// PlzNavigate
-// Next ServiceWorkerProviderHost ID for navigations, starts at -2 and keeps
-// going down.
-int g_next_navigation_provider_id = -2;
+// Provider host for navigation with PlzNavigate or when service worker's
+// context is created on the browser side. This function provides the next
+// ServiceWorkerProviderHost ID for them, starts at -2 and keeps going down.
+int NextBrowserProvidedProviderId() {
+ static int g_next_browser_provided_provider_id = -2;
+ return g_next_browser_provided_provider_id--;
+}
// A request handler derivative used to handle navigation requests when
// skip_service_worker flag is set. It tracks the document URL and sets the url
@@ -61,16 +64,15 @@ class ServiceWorkerURLTrackingRequestHandler
~ServiceWorkerURLTrackingRequestHandler() override {}
// Called via custom URLRequestJobFactory.
- net::URLRequestJob* MaybeCreateJob(
- net::URLRequest* request,
- net::NetworkDelegate* /* network_delegate */,
- ResourceContext* /* resource_context */) override {
+ net::URLRequestJob* MaybeCreateJob(net::URLRequest* request,
+ net::NetworkDelegate*,
+ ResourceContext*) override {
// |provider_host_| may have been deleted when the request is resumed.
if (!provider_host_)
return nullptr;
const GURL stripped_url = net::SimplifyUrlForRequest(request->url());
provider_host_->SetDocumentUrl(stripped_url);
- provider_host_->SetTopmostFrameUrl(request->first_party_for_cookies());
+ provider_host_->SetTopmostFrameUrl(request->site_for_cookies());
return nullptr;
}
@@ -81,172 +83,20 @@ class ServiceWorkerURLTrackingRequestHandler
void RemoveProviderHost(base::WeakPtr<ServiceWorkerContextCore> context,
int process_id,
int provider_id) {
+ // Temporary CHECK for debugging https://crbug.com/750267.
+ CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
TRACE_EVENT0("ServiceWorker",
"ServiceWorkerProviderHost::RemoveProviderHost");
- if (!context)
- return;
- if (!context->GetProviderHost(process_id, provider_id)) {
- // PlzNavigate: in some cancellation of navigation cases, it is possible
- // for the pre-created host, whose |provider_id| is assigned by the browser
- // process, to have been destroyed before being claimed by the renderer. The
- // provider is then destroyed in the renderer, and no matching host will be
- // found.
- DCHECK(IsBrowserSideNavigationEnabled() &&
- ServiceWorkerUtils::IsBrowserAssignedProviderId(provider_id));
+ if (!context || !context->GetProviderHost(process_id, provider_id)) {
+ // In some cancellation of navigation cases, it is possible for the
+ // pre-created host, whose |provider_id| is assigned by the browser process,
+ // to have been destroyed before being claimed by the renderer. The provider
+ // is then destroyed in the renderer, and no matching host will be found.
return;
}
context->RemoveProviderHost(process_id, provider_id);
}
-// Used by a Service Worker for script loading (for all script loading for now,
-// but to be used only during installation once script streaming lands).
-// For now this is just a proxy loader for the network loader.
-// Eventually this should replace the existing URLRequestJob-based request
-// interception for script loading, namely ServiceWorkerWriteToCacheJob.
-// TODO(kinuko): Implement this. Hook up the existing code in
-// ServiceWorkerContextRequestHandler.
-class ScriptURLLoader : public mojom::URLLoader, public mojom::URLLoaderClient {
- public:
- ScriptURLLoader(
- int32_t routing_id,
- int32_t request_id,
- uint32_t options,
- const ResourceRequest& resource_request,
- mojom::URLLoaderClientPtr client,
- base::WeakPtr<ServiceWorkerContextCore> context,
- base::WeakPtr<ServiceWorkerProviderHost> provider_host,
- base::WeakPtr<storage::BlobStorageContext> blob_storage_context,
- scoped_refptr<URLLoaderFactoryGetter> loader_factory_getter,
- const net::MutableNetworkTrafficAnnotationTag& traffic_annotation)
- : network_client_binding_(this),
- forwarding_client_(std::move(client)),
- provider_host_(provider_host) {
- mojom::URLLoaderClientPtr network_client;
- network_client_binding_.Bind(mojo::MakeRequest(&network_client));
- loader_factory_getter->GetNetworkFactory()->get()->CreateLoaderAndStart(
- mojo::MakeRequest(&network_loader_), routing_id, request_id, options,
- resource_request, std::move(network_client), traffic_annotation);
- }
- ~ScriptURLLoader() override {}
-
- // mojom::URLLoader:
- void FollowRedirect() override { network_loader_->FollowRedirect(); }
- void SetPriority(net::RequestPriority priority,
- int32_t intra_priority_value) override {
- network_loader_->SetPriority(priority, intra_priority_value);
- }
-
- // mojom::URLLoaderClient for simply proxying network:
- void OnReceiveResponse(
- const ResourceResponseHead& response_head,
- const base::Optional<net::SSLInfo>& ssl_info,
- mojom::DownloadedTempFilePtr downloaded_file) override {
- if (provider_host_) {
- // We don't have complete info here, but fill in what we have now.
- // At least we need headers and SSL info.
- net::HttpResponseInfo response_info;
- response_info.headers = response_head.headers;
- if (ssl_info.has_value())
- response_info.ssl_info = *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;
-
- DCHECK(provider_host_->IsHostToRunningServiceWorker());
- provider_host_->running_hosted_version()->SetMainScriptHttpResponseInfo(
- response_info);
- }
- forwarding_client_->OnReceiveResponse(response_head, ssl_info,
- std::move(downloaded_file));
- }
- void OnReceiveRedirect(const net::RedirectInfo& redirect_info,
- const ResourceResponseHead& response_head) override {
- forwarding_client_->OnReceiveRedirect(redirect_info, response_head);
- }
- void OnDataDownloaded(int64_t data_len, int64_t encoded_data_len) override {
- forwarding_client_->OnDataDownloaded(data_len, encoded_data_len);
- }
- void OnUploadProgress(int64_t current_position,
- int64_t total_size,
- OnUploadProgressCallback ack_callback) override {
- forwarding_client_->OnUploadProgress(current_position, total_size,
- std::move(ack_callback));
- }
- void OnReceiveCachedMetadata(const std::vector<uint8_t>& data) override {
- forwarding_client_->OnReceiveCachedMetadata(data);
- }
- void OnTransferSizeUpdated(int32_t transfer_size_diff) override {
- forwarding_client_->OnTransferSizeUpdated(transfer_size_diff);
- }
- void OnStartLoadingResponseBody(
- mojo::ScopedDataPipeConsumerHandle body) override {
- forwarding_client_->OnStartLoadingResponseBody(std::move(body));
- }
- void OnComplete(const ResourceRequestCompletionStatus& status) override {
- forwarding_client_->OnComplete(status);
- }
-
- private:
- mojom::URLLoaderAssociatedPtr network_loader_;
- mojo::Binding<mojom::URLLoaderClient> network_client_binding_;
- mojom::URLLoaderClientPtr forwarding_client_;
- base::WeakPtr<ServiceWorkerProviderHost> provider_host_;
-
- DISALLOW_COPY_AND_ASSIGN(ScriptURLLoader);
-};
-
-// Created per one controller worker for script loading (only during
-// installation, eventually). This is kept alive while
-// ServiceWorkerNetworkProvider in the renderer process is alive.
-// Used only when IsServicificationEnabled is true.
-class ScriptURLLoaderFactory : public mojom::URLLoaderFactory {
- public:
- ScriptURLLoaderFactory(
- base::WeakPtr<ServiceWorkerContextCore> context,
- base::WeakPtr<ServiceWorkerProviderHost> provider_host,
- base::WeakPtr<storage::BlobStorageContext> blob_storage_context,
- scoped_refptr<URLLoaderFactoryGetter> loader_factory_getter)
- : context_(context),
- provider_host_(provider_host),
- blob_storage_context_(blob_storage_context),
- loader_factory_getter_(loader_factory_getter) {}
- ~ScriptURLLoaderFactory() override {}
-
- // mojom::URLLoaderFactory:
- void CreateLoaderAndStart(mojom::URLLoaderAssociatedRequest request,
- int32_t routing_id,
- int32_t request_id,
- uint32_t options,
- const ResourceRequest& resource_request,
- mojom::URLLoaderClientPtr client,
- const net::MutableNetworkTrafficAnnotationTag&
- traffic_annotation) override {
- mojo::MakeStrongAssociatedBinding(
- base::MakeUnique<ScriptURLLoader>(
- routing_id, request_id, options, resource_request,
- std::move(client), context_, provider_host_, blob_storage_context_,
- loader_factory_getter_, traffic_annotation),
- std::move(request));
- }
-
- void SyncLoad(int32_t routing_id,
- int32_t request_id,
- const ResourceRequest& request,
- SyncLoadCallback callback) override {
- NOTREACHED();
- }
-
- private:
- base::WeakPtr<ServiceWorkerContextCore> context_;
- base::WeakPtr<ServiceWorkerProviderHost> provider_host_;
- base::WeakPtr<storage::BlobStorageContext> blob_storage_context_;
- scoped_refptr<URLLoaderFactoryGetter> loader_factory_getter_;
- DISALLOW_COPY_AND_ASSIGN(ScriptURLLoaderFactory);
-};
-
} // anonymous namespace
ServiceWorkerProviderHost::OneShotGetReadyCallback::OneShotGetReadyCallback(
@@ -265,58 +115,45 @@ ServiceWorkerProviderHost::PreCreateNavigationHost(
bool are_ancestors_secure,
const WebContentsGetter& web_contents_getter) {
CHECK(IsBrowserSideNavigationEnabled());
- // Generate a new browser-assigned id for the host.
- int provider_id = g_next_navigation_provider_id--;
auto host = base::WrapUnique(new ServiceWorkerProviderHost(
ChildProcessHost::kInvalidUniqueID,
- ServiceWorkerProviderHostInfo(provider_id, MSG_ROUTING_NONE,
- SERVICE_WORKER_PROVIDER_FOR_WINDOW,
- are_ancestors_secure),
- context, nullptr));
+ ServiceWorkerProviderHostInfo(
+ NextBrowserProvidedProviderId(), MSG_ROUTING_NONE,
+ SERVICE_WORKER_PROVIDER_FOR_WINDOW, are_ancestors_secure),
+ context, nullptr /* dispatcher_host */));
host->web_contents_getter_ = web_contents_getter;
return host;
}
// static
+std::unique_ptr<ServiceWorkerProviderHost>
+ServiceWorkerProviderHost::PreCreateForController(
+ base::WeakPtr<ServiceWorkerContextCore> context) {
+ auto host = base::WrapUnique(new ServiceWorkerProviderHost(
+ ChildProcessHost::kInvalidUniqueID,
+ ServiceWorkerProviderHostInfo(NextBrowserProvidedProviderId(),
+ MSG_ROUTING_NONE,
+ SERVICE_WORKER_PROVIDER_FOR_CONTROLLER,
+ true /* is_parent_frame_secure */),
+ std::move(context), nullptr));
+ return host;
+}
+
+// static
std::unique_ptr<ServiceWorkerProviderHost> ServiceWorkerProviderHost::Create(
int process_id,
ServiceWorkerProviderHostInfo info,
base::WeakPtr<ServiceWorkerContextCore> context,
- ServiceWorkerDispatcherHost* dispatcher_host) {
+ base::WeakPtr<ServiceWorkerDispatcherHost> dispatcher_host) {
return base::WrapUnique(new ServiceWorkerProviderHost(
process_id, std::move(info), context, dispatcher_host));
}
-void ServiceWorkerProviderHost::BindWorkerFetchContext(
- mojom::ServiceWorkerWorkerClientAssociatedPtrInfo client_ptr_info) {
- DCHECK(base::FeatureList::IsEnabled(features::kOffMainThreadFetch));
- mojom::ServiceWorkerWorkerClientAssociatedPtr client;
- client.Bind(std::move(client_ptr_info));
- client.set_connection_error_handler(
- base::Bind(&ServiceWorkerProviderHost::UnregisterWorkerFetchContext,
- base::Unretained(this), client.get()));
-
- if (controlling_version_)
- client->SetControllerServiceWorker(controlling_version_->version_id());
-
- auto result = worker_clients_.insert(
- std::make_pair<mojom::ServiceWorkerWorkerClient*,
- mojom::ServiceWorkerWorkerClientAssociatedPtr>(
- client.get(), std::move(client)));
- DCHECK(result.second);
-}
-
-void ServiceWorkerProviderHost::UnregisterWorkerFetchContext(
- mojom::ServiceWorkerWorkerClient* client) {
- DCHECK(worker_clients_.count(client));
- worker_clients_.erase(client);
-}
-
ServiceWorkerProviderHost::ServiceWorkerProviderHost(
int render_process_id,
ServiceWorkerProviderHostInfo info,
base::WeakPtr<ServiceWorkerContextCore> context,
- ServiceWorkerDispatcherHost* dispatcher_host)
+ base::WeakPtr<ServiceWorkerDispatcherHost> dispatcher_host)
: client_uuid_(base::GenerateGUID()),
create_time_(base::TimeTicks::Now()),
render_process_id_(render_process_id),
@@ -328,38 +165,46 @@ ServiceWorkerProviderHost::ServiceWorkerProviderHost(
binding_(this) {
DCHECK_NE(SERVICE_WORKER_PROVIDER_UNKNOWN, info_.type);
- // PlzNavigate
- CHECK(render_process_id != ChildProcessHost::kInvalidUniqueID ||
- IsBrowserSideNavigationEnabled());
-
if (info_.type == SERVICE_WORKER_PROVIDER_FOR_CONTROLLER) {
- // Actual thread id is set when the service worker context gets started.
+ // Actual |render_process_id| will be set after choosing a process for the
+ // controller, and |render_thread id| will be set when the service worker
+ // context gets started.
+ DCHECK_EQ(ChildProcessHost::kInvalidUniqueID, render_process_id);
render_thread_id_ = kInvalidEmbeddedWorkerThreadId;
+ } else {
+ // PlzNavigate
+ DCHECK(render_process_id != ChildProcessHost::kInvalidUniqueID ||
+ IsBrowserSideNavigationEnabled());
}
+
context_->RegisterProviderHostByClientID(client_uuid_, this);
- // PlzNavigate
- // |provider_| and |binding_| will be bound on CompleteNavigationInitialized.
- if (IsBrowserSideNavigationEnabled()) {
- DCHECK(!info.client_ptr_info.is_valid() && !info.host_request.is_pending());
+ // |client_| and |binding_| will be bound on CompleteNavigationInitialized
+ // (PlzNavigate) or on CompleteStartWorkerPreparation (providers for
+ // controller).
+ if (!info_.client_ptr_info.is_valid() && !info_.host_request.is_pending()) {
+ DCHECK(IsBrowserSideNavigationEnabled() ||
+ info_.type == SERVICE_WORKER_PROVIDER_FOR_CONTROLLER);
return;
}
- provider_.Bind(std::move(info_.client_ptr_info));
+ container_.Bind(std::move(info_.client_ptr_info));
binding_.Bind(std::move(info_.host_request));
- binding_.set_connection_error_handler(base::Bind(
+ binding_.set_connection_error_handler(base::BindOnce(
&RemoveProviderHost, context_, render_process_id, info_.provider_id));
}
ServiceWorkerProviderHost::~ServiceWorkerProviderHost() {
+ // Temporary CHECK for debugging https://crbug.com/750267.
+ CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (context_)
context_->UnregisterProviderHostByClientID(client_uuid_);
// Clear docurl so the deferred activation of a waiting worker
// won't associate the new version with a provider being destroyed.
document_url_ = GURL();
- if (controlling_version_.get())
- controlling_version_->RemoveControllee(this);
+ if (controller_.get())
+ controller_->RemoveControllee(this);
RemoveAllMatchingRegistrations();
@@ -401,9 +246,9 @@ void ServiceWorkerProviderHost::OnVersionAttributesChanged(
if (changed_mask.active_changed() && 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::Bind(
- &ServiceWorkerProviderHost::ReturnRegistrationForReadyIfNeeded,
- AsWeakPtr()));
+ registration->active_version()->RegisterStatusChangeCallback(base::BindOnce(
+ &ServiceWorkerProviderHost::ReturnRegistrationForReadyIfNeeded,
+ AsWeakPtr()));
}
}
@@ -426,7 +271,7 @@ void ServiceWorkerProviderHost::OnSkippedWaiting(
// A client is "using" a registration if it is controlled by the active
// worker of the registration. skipWaiting doesn't cause a client to start
// using the registration.
- if (!controlling_version_)
+ if (!controller_)
return;
ServiceWorkerVersion* active_version = registration->active_version();
DCHECK(active_version);
@@ -450,47 +295,26 @@ void ServiceWorkerProviderHost::SetControllerVersionAttribute(
ServiceWorkerVersion* version,
bool notify_controllerchange) {
CHECK(!version || IsContextSecureForServiceWorker());
- if (version == controlling_version_.get())
+ if (version == controller_.get())
return;
- scoped_refptr<ServiceWorkerVersion> previous_version = controlling_version_;
- controlling_version_ = version;
+ scoped_refptr<ServiceWorkerVersion> previous_version = controller_;
+ controller_ = version;
+
+ // This will drop the message pipes to the client pages as well.
+ controller_event_dispatcher_.reset();
+
if (version) {
version->AddControllee(this);
- for (const auto& pair : worker_clients_) {
- pair.second->SetControllerServiceWorker(version->version_id());
- }
+ controller_event_dispatcher_ =
+ base::MakeUnique<BrowserSideServiceWorkerEventDispatcher>(version);
}
if (previous_version.get())
previous_version->RemoveControllee(this);
- if (!dispatcher_host_)
- return; // Could be NULL in some tests.
-
// SetController message should be sent only for controllees.
DCHECK(IsProviderForClient());
- Send(new ServiceWorkerMsg_SetControllerServiceWorker(
- render_thread_id_, provider_id(), GetOrCreateServiceWorkerHandle(version),
- notify_controllerchange,
- version ? version->used_features() : std::set<uint32_t>()));
-}
-
-void ServiceWorkerProviderHost::SetHostedVersion(
- ServiceWorkerVersion* version) {
- DCHECK(!IsProviderForClient());
- DCHECK_EQ(EmbeddedWorkerStatus::STARTING, version->running_status());
- DCHECK_EQ(render_process_id_, version->embedded_worker()->process_id());
- running_hosted_version_ = version;
-}
-
-void ServiceWorkerProviderHost::CreateScriptURLLoaderFactory(
- mojom::URLLoaderFactoryAssociatedRequest script_loader_factory_request) {
- DCHECK(ServiceWorkerUtils::IsServicificationEnabled());
- mojo::MakeStrongAssociatedBinding(
- base::MakeUnique<ScriptURLLoaderFactory>(
- context_, AsWeakPtr(), context_->blob_storage_context(),
- context_->loader_factory_getter()),
- std::move(script_loader_factory_request));
+ SendSetControllerServiceWorker(version, notify_controllerchange);
}
bool ServiceWorkerProviderHost::IsProviderForClient() const {
@@ -532,7 +356,6 @@ void ServiceWorkerProviderHost::AssociateRegistration(
DCHECK(CanAssociateRegistration(registration));
associated_registration_ = registration;
AddMatchingRegistration(registration);
- SendAssociateRegistrationMessage();
SetControllerVersionAttribute(registration->active_version(),
notify_controllerchange);
}
@@ -541,16 +364,8 @@ void ServiceWorkerProviderHost::DisassociateRegistration() {
queued_events_.clear();
if (!associated_registration_.get())
return;
- associated_registration_ = NULL;
- SetControllerVersionAttribute(NULL, false /* notify_controllerchange */);
-
- if (!dispatcher_host_)
- return;
-
- // Disassociation message should be sent only for controllees.
- DCHECK(IsProviderForClient());
- Send(new ServiceWorkerMsg_DisassociateRegistration(
- render_thread_id_, provider_id()));
+ associated_registration_ = nullptr;
+ SetControllerVersionAttribute(nullptr, false /* notify_controllerchange */);
}
void ServiceWorkerProviderHost::AddMatchingRegistration(
@@ -631,8 +446,7 @@ ServiceWorkerProviderHost::CreateRequestHandler(
return base::MakeUnique<ServiceWorkerContextRequestHandler>(
context_, AsWeakPtr(), blob_storage_context, resource_type);
}
- if (ServiceWorkerUtils::IsMainResourceType(resource_type) ||
- controlling_version()) {
+ if (ServiceWorkerUtils::IsMainResourceType(resource_type) || controller()) {
return base::MakeUnique<ServiceWorkerControlleeRequestHandler>(
context_, AsWeakPtr(), blob_storage_context, request_mode,
credentials_mode, redirect_mode, integrity, resource_type,
@@ -677,7 +491,7 @@ void ServiceWorkerProviderHost::PostMessageToClient(
const base::string16& message,
const std::vector<MessagePort>& sent_message_ports) {
if (!dispatcher_host_)
- return; // Could be NULL in some tests.
+ return;
ServiceWorkerMsg_MessageToDocument_Params params;
params.thread_id = kDocumentMainThreadId;
@@ -690,7 +504,7 @@ void ServiceWorkerProviderHost::PostMessageToClient(
void ServiceWorkerProviderHost::CountFeature(uint32_t feature) {
if (!dispatcher_host_)
- return; // Could be nullptr in some tests.
+ return;
// CountFeature message should be sent only for controllees.
DCHECK(IsProviderForClient());
@@ -738,19 +552,19 @@ ServiceWorkerProviderHost::PrepareForCrossSiteTransfer() {
base::WrapUnique(new ServiceWorkerProviderHost(
process_id(),
ServiceWorkerProviderHostInfo(std::move(info_), binding_.Unbind(),
- provider_.PassInterface()),
- context_, dispatcher_host()));
+ container_.PassInterface()),
+ context_, dispatcher_host_));
for (const GURL& pattern : associated_patterns_)
DecreaseProcessReference(pattern);
RemoveAllMatchingRegistrations();
- if (associated_registration_.get()) {
- if (dispatcher_host_) {
- Send(new ServiceWorkerMsg_DisassociateRegistration(
- render_thread_id_, provider_id()));
- }
+ // Clear the controller from the renderer-side provider, since no one knows
+ // what's going to happen until after cross-site transfer finishes.
+ if (controller_) {
+ SendSetControllerServiceWorker(nullptr,
+ false /* notify_controllerchange */);
}
render_process_id_ = ChildProcessHost::kInvalidUniqueID;
@@ -769,30 +583,37 @@ void ServiceWorkerProviderHost::CompleteCrossSiteTransfer(
render_process_id_ = provisional_host->process_id();
render_thread_id_ = kDocumentMainThreadId;
- dispatcher_host_ = provisional_host->dispatcher_host();
+ dispatcher_host_ = provisional_host->dispatcher_host()
+ ? provisional_host->dispatcher_host()->AsWeakPtr()
+ : nullptr;
info_ = std::move(provisional_host->info_);
// Take the connection over from the provisional host.
- DCHECK(!provider_.is_bound());
+ DCHECK(!container_.is_bound());
DCHECK(!binding_.is_bound());
- provider_.Bind(provisional_host->provider_.PassInterface());
+ container_.Bind(provisional_host->container_.PassInterface());
binding_.Bind(provisional_host->binding_.Unbind());
binding_.set_connection_error_handler(
- base::Bind(&RemoveProviderHost, context_, provisional_host->process_id(),
- provider_id()));
+ base::BindOnce(&RemoveProviderHost, context_,
+ provisional_host->process_id(), provider_id()));
for (const GURL& pattern : associated_patterns_)
IncreaseProcessReference(pattern);
SyncMatchingRegistrations();
- NotifyControllerToAssociatedProvider();
+ // Now that the provider is stable and the connection is established,
+ // send it the SetController IPC if there is a controller.
+ if (controller_) {
+ SendSetControllerServiceWorker(controller_.get(),
+ false /* notify_controllerchange */);
+ }
}
// PlzNavigate
void ServiceWorkerProviderHost::CompleteNavigationInitialized(
int process_id,
ServiceWorkerProviderHostInfo info,
- ServiceWorkerDispatcherHost* dispatcher_host) {
+ base::WeakPtr<ServiceWorkerDispatcherHost> dispatcher_host) {
CHECK(IsBrowserSideNavigationEnabled());
DCHECK_EQ(ChildProcessHost::kInvalidUniqueID, render_process_id_);
DCHECK_EQ(SERVICE_WORKER_PROVIDER_FOR_WINDOW, info_.type);
@@ -802,13 +623,13 @@ void ServiceWorkerProviderHost::CompleteNavigationInitialized(
DCHECK_EQ(info_.provider_id, info.provider_id);
DCHECK_NE(MSG_ROUTING_NONE, info.route_id);
- // Connect with the provider on the renderer.
- DCHECK(!provider_.is_bound());
+ // Connect with the mojom::ServiceWorkerContainer on the renderer.
+ DCHECK(!container_.is_bound());
DCHECK(!binding_.is_bound());
- provider_.Bind(std::move(info.client_ptr_info));
+ container_.Bind(std::move(info.client_ptr_info));
binding_.Bind(std::move(info.host_request));
binding_.set_connection_error_handler(
- base::Bind(&RemoveProviderHost, context_, process_id, provider_id()));
+ base::BindOnce(&RemoveProviderHost, context_, process_id, provider_id()));
info_.route_id = info.route_id;
render_process_id_ = process_id;
dispatcher_host_ = dispatcher_host;
@@ -820,13 +641,78 @@ void ServiceWorkerProviderHost::CompleteNavigationInitialized(
for (auto& key_registration : matching_registrations_)
IncreaseProcessReference(key_registration.second->pattern());
- NotifyControllerToAssociatedProvider();
+ // Now that there is a connection with the renderer-side provider,
+ // send it the SetController IPC.
+ if (controller_) {
+ SendSetControllerServiceWorker(controller_.get(),
+ false /* notify_controllerchange */);
+ }
+}
+
+mojom::ServiceWorkerProviderInfoForStartWorkerPtr
+ServiceWorkerProviderHost::CompleteStartWorkerPreparation(
+ int process_id,
+ scoped_refptr<ServiceWorkerVersion> hosted_version) {
+ DCHECK(context_);
+ DCHECK_EQ(kInvalidEmbeddedWorkerThreadId, render_thread_id_);
+ DCHECK_EQ(ChildProcessHost::kInvalidUniqueID, render_process_id_);
+ DCHECK_EQ(SERVICE_WORKER_PROVIDER_FOR_CONTROLLER, provider_type());
+ DCHECK(!running_hosted_version_);
+
+ DCHECK_NE(ChildProcessHost::kInvalidUniqueID, process_id);
+
+ running_hosted_version_ = std::move(hosted_version);
+
+ ServiceWorkerDispatcherHost* dispatcher_host =
+ context_->GetDispatcherHost(process_id);
+ DCHECK(dispatcher_host);
+ render_process_id_ = process_id;
+ dispatcher_host_ = dispatcher_host->AsWeakPtr();
+
+ // Retrieve the registration associated with |version|. The registration
+ // must be alive because the version keeps it during starting worker.
+ ServiceWorkerRegistration* registration = context_->GetLiveRegistration(
+ running_hosted_version()->registration_id());
+ DCHECK(registration);
+ ServiceWorkerRegistrationObjectInfo info;
+ ServiceWorkerVersionAttributes attrs;
+ dispatcher_host->GetRegistrationObjectInfoAndVersionAttributes(
+ AsWeakPtr(), registration, &info, &attrs);
+
+ // Initialize provider_info.
+ mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info =
+ mojom::ServiceWorkerProviderInfoForStartWorker::New();
+ provider_info->provider_id = provider_id();
+ provider_info->attributes = std::move(attrs);
+ provider_info->registration = std::move(info);
+ provider_info->client_request = mojo::MakeRequest(&container_);
+
+ mojom::URLLoaderFactoryAssociatedPtrInfo script_loader_factory_ptr_info;
+ if (ServiceWorkerUtils::IsServicificationEnabled()) {
+ mojo::MakeStrongAssociatedBinding(
+ base::MakeUnique<ServiceWorkerScriptURLLoaderFactory>(
+ context_, AsWeakPtr(), context_->blob_storage_context(),
+ context_->loader_factory_getter()),
+ mojo::MakeRequest(&script_loader_factory_ptr_info));
+ provider_info->script_loader_factory_ptr_info =
+ std::move(script_loader_factory_ptr_info);
+ }
+
+ binding_.Bind(mojo::MakeRequest(&provider_info->host_ptr_info));
+ binding_.set_connection_error_handler(
+ base::BindOnce(&RemoveProviderHost, context_, process_id, provider_id()));
+
+ // Set the document URL to the script url in order to allow
+ // register/unregister/getRegistration on ServiceWorkerGlobalScope.
+ SetDocumentUrl(running_hosted_version()->script_url());
+
+ return provider_info;
}
void ServiceWorkerProviderHost::SendUpdateFoundMessage(
int registration_handle_id) {
if (!dispatcher_host_)
- return; // Could be nullptr in some tests.
+ return;
if (!IsReadyToSendMessages()) {
queued_events_.push_back(
@@ -846,7 +732,7 @@ void ServiceWorkerProviderHost::SendSetVersionAttributesMessage(
ServiceWorkerVersion* waiting_version,
ServiceWorkerVersion* active_version) {
if (!dispatcher_host_)
- return; // Could be nullptr in some tests.
+ return;
if (!changed_mask.changed())
return;
@@ -899,28 +785,6 @@ void ServiceWorkerProviderHost::SetReadyToSendMessagesToWorker(
queued_events_.clear();
}
-void ServiceWorkerProviderHost::SendAssociateRegistrationMessage() {
- if (!dispatcher_host_)
- return;
-
- ServiceWorkerRegistrationHandle* handle =
- dispatcher_host_->GetOrCreateRegistrationHandle(
- AsWeakPtr(), associated_registration_.get());
-
- ServiceWorkerVersionAttributes attrs;
- attrs.installing = GetOrCreateServiceWorkerHandle(
- associated_registration_->installing_version());
- attrs.waiting = GetOrCreateServiceWorkerHandle(
- associated_registration_->waiting_version());
- attrs.active = GetOrCreateServiceWorkerHandle(
- associated_registration_->active_version());
-
- // Association message should be sent only for controllees.
- DCHECK(IsProviderForClient());
- dispatcher_host_->Send(new ServiceWorkerMsg_AssociateRegistration(
- render_thread_id_, provider_id(), handle->GetObjectInfo(), attrs));
-}
-
void ServiceWorkerProviderHost::SyncMatchingRegistrations() {
DCHECK(context_);
RemoveAllMatchingRegistrations();
@@ -987,18 +851,33 @@ void ServiceWorkerProviderHost::Send(IPC::Message* message) const {
dispatcher_host_->Send(message);
}
-void ServiceWorkerProviderHost::NotifyControllerToAssociatedProvider() {
- if (associated_registration_.get()) {
- SendAssociateRegistrationMessage();
- if (dispatcher_host_ && associated_registration_->active_version()) {
- Send(new ServiceWorkerMsg_SetControllerServiceWorker(
- render_thread_id_, provider_id(),
- GetOrCreateServiceWorkerHandle(
- associated_registration_->active_version()),
- false /* shouldNotifyControllerChange */,
- associated_registration_->active_version()->used_features()));
+void ServiceWorkerProviderHost::SendSetControllerServiceWorker(
+ ServiceWorkerVersion* version,
+ bool notify_controllerchange) {
+ if (!dispatcher_host_)
+ return;
+
+ if (version) {
+ DCHECK(associated_registration_);
+ DCHECK_EQ(associated_registration_->active_version(), version);
+ DCHECK_EQ(controller_.get(), version);
+ }
+
+ ServiceWorkerMsg_SetControllerServiceWorker_Params params;
+ params.thread_id = render_thread_id_;
+ params.provider_id = provider_id();
+ params.object_info = GetOrCreateServiceWorkerHandle(version);
+ params.should_notify_controllerchange = notify_controllerchange;
+ if (version) {
+ params.used_features = version->used_features();
+ if (ServiceWorkerUtils::IsServicificationEnabled()) {
+ params.controller_event_dispatcher =
+ controller_event_dispatcher_->CreateEventDispatcherPtrInfo()
+ .PassHandle()
+ .release();
}
}
+ Send(new ServiceWorkerMsg_SetControllerServiceWorker(params));
}
} // namespace content
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 9f317571c48..b1f0d7c87fe 100644
--- a/chromium/content/browser/service_worker/service_worker_provider_host.h
+++ b/chromium/content/browser/service_worker/service_worker_provider_host.h
@@ -12,7 +12,6 @@
#include <memory>
#include <set>
#include <string>
-#include <unordered_map>
#include <vector>
#include "base/gtest_prod_util.h"
@@ -22,10 +21,10 @@
#include "base/time/time.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_event_dispatcher.mojom.h"
#include "content/common/service_worker/service_worker_provider_host_info.h"
-#include "content/common/service_worker/service_worker_provider_interfaces.mojom.h"
#include "content/common/service_worker/service_worker_types.h"
-#include "content/common/worker_url_loader_factory_provider.mojom.h"
#include "content/public/common/request_context_frame_type.h"
#include "content/public/common/request_context_type.h"
#include "content/public/common/resource_type.h"
@@ -44,6 +43,7 @@ class ServiceWorkerContextCore;
class ServiceWorkerDispatcherHost;
class ServiceWorkerRequestHandler;
class ServiceWorkerVersion;
+class BrowserSideServiceWorkerEventDispatcher;
class WebContents;
// This class is the browser-process representation of a service worker
@@ -59,21 +59,27 @@ class WebContents;
// For providers hosting a running service worker, this class will observe
// resource loads made directly by the service worker.
//
-// A ServiceWorkerProviderHost instance is created when a
-// ServiceWorkerNetworkProvider is created on the renderer process, which
-// happens 1) when a document or worker (i.e., a service worker client) is
-// created, or 2) during service worker startup. Mojo's connection from
-// ServiceWorkerNetworkProvider is established on the creation time, and the
-// instance is destroyed on disconnection from the renderer side.
-// If PlzNavigate is turned on, an instance is pre-created on the browser
+// A ServiceWorkerProviderHost is created in the following situations:
+// 1) When it's for a document or worker (i.e., a service
+// worker client), the provider host is created when
+// ServiceWorkerNetworkProvider is created on the renderer process. Mojo's
+// connection from ServiceWorkerNetworkProvider is established on the creation
+// time.
+// 2) When it's for a running service worker, the provider host is created on
+// the browser process before launching the service worker's thread. Mojo's
+// connection to the renderer is established with the StartWorker message.
+// 3) When PlzNavigate is turned on, an instance is pre-created on the browser
// before ServiceWorkerNetworkProvider is created on the renderer because
// navigation is initiated on the browser side. In that case, establishment of
// Mojo's connection will be deferred until ServiceWorkerNetworkProvider is
// created on the renderer.
+// Destruction of the ServiceWorkerProviderHost instance happens on
+// disconnection of the Mojo's pipe from the renderer side regardless of what
+// the provider is for.
class CONTENT_EXPORT ServiceWorkerProviderHost
- : public NON_EXPORTED_BASE(ServiceWorkerRegistration::Listener),
+ : public ServiceWorkerRegistration::Listener,
public base::SupportsWeakPtr<ServiceWorkerProviderHost>,
- public NON_EXPORTED_BASE(mojom::ServiceWorkerProviderHost) {
+ public mojom::ServiceWorkerContainerHost {
public:
using GetRegistrationForReadyCallback =
base::Callback<void(ServiceWorkerRegistration* reigstration)>;
@@ -92,6 +98,12 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
bool are_ancestors_secure,
const WebContentsGetter& web_contents_getter);
+ // Creates a ServiceWorkerProviderHost for hosting a running service worker.
+ // Information about this provider host is passed down to the service worker
+ // via StartWorker message.
+ static std::unique_ptr<ServiceWorkerProviderHost> PreCreateForController(
+ base::WeakPtr<ServiceWorkerContextCore> context);
+
// Used to create a ServiceWorkerProviderHost when the renderer-side provider
// is created. This ProviderHost will be created for the process specified by
// |process_id|.
@@ -99,7 +111,7 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
int process_id,
ServiceWorkerProviderHostInfo info,
base::WeakPtr<ServiceWorkerContextCore> context,
- ServiceWorkerDispatcherHost* dispatcher_host);
+ base::WeakPtr<ServiceWorkerDispatcherHost> dispatcher_host);
~ServiceWorkerProviderHost() override;
@@ -126,7 +138,7 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
bool IsContextSecureForServiceWorker() const;
bool IsHostToRunningServiceWorker() {
- return running_hosted_version_.get() != NULL;
+ return running_hosted_version_.get() != nullptr;
}
// Returns this provider's controller. The controller is typically the same as
@@ -137,29 +149,31 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
// to an exceptional circumstance (here also it is not "using" the
// registration).
// (3) During algorithms such as the update, skipWaiting(), and claim() steps,
- // the active_version and controlling_version may temporarily differ. For
- // example, to perform skipWaiting(), the registration's active version is
- // updated first and then the provider host's controlling version is updated
- // to match it.
- ServiceWorkerVersion* controlling_version() const {
+ // the active version and controller may temporarily differ. For example, to
+ // perform skipWaiting(), the registration's active version is updated first
+ // and then the provider host's controlling version is updated to match it.
+ ServiceWorkerVersion* controller() const {
// Only clients can have controllers.
- DCHECK(!controlling_version_ || IsProviderForClient());
- return controlling_version_.get();
+ DCHECK(!controller_ || IsProviderForClient());
+ return controller_.get();
}
ServiceWorkerVersion* active_version() const {
- return associated_registration_.get() ?
- associated_registration_->active_version() : NULL;
+ return associated_registration_.get()
+ ? associated_registration_->active_version()
+ : nullptr;
}
ServiceWorkerVersion* waiting_version() const {
- return associated_registration_.get() ?
- associated_registration_->waiting_version() : NULL;
+ return associated_registration_.get()
+ ? associated_registration_->waiting_version()
+ : nullptr;
}
ServiceWorkerVersion* installing_version() const {
- return associated_registration_.get() ?
- associated_registration_->installing_version() : NULL;
+ return associated_registration_.get()
+ ? associated_registration_->installing_version()
+ : nullptr;
}
// Returns the associated registration. The provider host listens to this
@@ -201,15 +215,7 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
// Clears the associated registration and stop listening to it.
void DisassociateRegistration();
- void SetHostedVersion(ServiceWorkerVersion* version);
-
- // Creates a per-controller-worker URLLoaderFactory for script loading.
- // The created factory is kept alive while the controller worker is alive.
- // Used only when IsServicificationEnabled is true.
- void CreateScriptURLLoaderFactory(
- mojom::URLLoaderFactoryAssociatedRequest script_loader_factory_request);
-
- // Returns a handler for a request, the handler may return NULL if
+ // Returns a handler for a request, the handler may return nullptr if
// the request doesn't require special handling.
std::unique_ptr<ServiceWorkerRequestHandler> CreateRequestHandler(
FetchRequestMode request_mode,
@@ -268,7 +274,7 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
std::unique_ptr<ServiceWorkerProviderHost> PrepareForCrossSiteTransfer();
void CompleteCrossSiteTransfer(ServiceWorkerProviderHost* provisional_host);
ServiceWorkerDispatcherHost* dispatcher_host() const {
- return dispatcher_host_;
+ return dispatcher_host_.get();
}
// PlzNavigate
@@ -276,7 +282,17 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
void CompleteNavigationInitialized(
int process_id,
ServiceWorkerProviderHostInfo info,
- ServiceWorkerDispatcherHost* dispatcher_host);
+ base::WeakPtr<ServiceWorkerDispatcherHost> dispatcher_host);
+
+ // Completes initialization of provider hosts for controllers and returns the
+ // value to create ServiceWorkerNetworkProvider on the renderer which will be
+ // connected to this instance.
+ // This instance will keep the reference to |hosted_version|, so please be
+ // careful not to create a reference cycle.
+ mojom::ServiceWorkerProviderInfoForStartWorkerPtr
+ CompleteStartWorkerPreparation(
+ int process_id,
+ scoped_refptr<ServiceWorkerVersion> hosted_version);
// Sends event messages to the renderer. Events for the worker are queued up
// until the worker thread id is known via SetReadyToSendMessagesToWorker().
@@ -307,12 +323,6 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
// cache.
void NotifyControllerLost();
- // Binds the ServiceWorkerWorkerClient of a dedicated (or shared) worker to
- // the parent frame's ServiceWorkerProviderHost. (This is used only when
- // off-main-thread-fetch is enabled.)
- void BindWorkerFetchContext(
- mojom::ServiceWorkerWorkerClientAssociatedPtrInfo client_ptr_info);
-
private:
friend class ForeignFetchRequestHandlerTest;
friend class LinkHeaderServiceWorkerTest;
@@ -343,10 +353,11 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
~OneShotGetReadyCallback();
};
- ServiceWorkerProviderHost(int process_id,
- ServiceWorkerProviderHostInfo info,
- base::WeakPtr<ServiceWorkerContextCore> context,
- ServiceWorkerDispatcherHost* dispatcher_host);
+ ServiceWorkerProviderHost(
+ int process_id,
+ ServiceWorkerProviderHostInfo info,
+ base::WeakPtr<ServiceWorkerContextCore> context,
+ base::WeakPtr<ServiceWorkerDispatcherHost> dispatcher_host);
// ServiceWorkerRegistration::Listener overrides.
void OnVersionAttributesChanged(
@@ -358,9 +369,9 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
ServiceWorkerRegistration* registration) override;
void OnSkippedWaiting(ServiceWorkerRegistration* registration) override;
- // Sets the controller version field to |version| or if |version| is NULL,
- // clears the field. If |notify_controllerchange| is true, instructs the
- // renderer to dispatch a 'controller' change event.
+ // Sets the controller field to |version| or if |version| is nullptr, clears
+ // the field. If |notify_controllerchange| is true, instructs the renderer to
+ // dispatch a 'controller' change event.
void SetControllerVersionAttribute(ServiceWorkerVersion* version,
bool notify_controllerchange);
@@ -381,18 +392,18 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
bool IsReadyToSendMessages() const;
void Send(IPC::Message* message) const;
- // Notifies the information about the controller and associated registration
- // to the provider on the renderer. This is for cross site transfer and
- // browser side navigation which need to decide which process will handle the
- // request later.
- void NotifyControllerToAssociatedProvider();
-
- // Clears the information of the ServiceWorkerWorkerClient of dedicated (or
- // shared) worker, when the connection to the worker is disconnected.
- void UnregisterWorkerFetchContext(mojom::ServiceWorkerWorkerClient*);
-
- std::string client_uuid_;
- base::TimeTicks create_time_;
+ // Sends information about the controller to the providers of the service
+ // worker clients in the renderer. If |notify_controllerchange| is true,
+ // instructs the renderer to dispatch a 'controllerchange' event. If
+ // |version| is non-null, it must be the same as |controller_|. |version| can
+ // be null while |controller_| is non-null in the strange case of cross-site
+ // transfer, which will be removed when the non-PlzNavigate code path is
+ // removed.
+ void SendSetControllerServiceWorker(ServiceWorkerVersion* version,
+ bool notify_controllerchange);
+
+ const std::string client_uuid_;
+ const base::TimeTicks create_time_;
int render_process_id_;
// For provider hosts that are hosting a running service worker, the id of the
@@ -416,36 +427,46 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
scoped_refptr<ServiceWorkerRegistration> associated_registration_;
// Keyed by registration scope URL length.
- typedef std::map<size_t, scoped_refptr<ServiceWorkerRegistration>>
- ServiceWorkerRegistrationMap;
+ using ServiceWorkerRegistrationMap =
+ std::map<size_t, scoped_refptr<ServiceWorkerRegistration>>;
// Contains all living registrations whose pattern this document's URL
// starts with. It is empty if IsContextSecureForServiceWorker() is
// false.
ServiceWorkerRegistrationMap matching_registrations_;
std::unique_ptr<OneShotGetReadyCallback> get_ready_callback_;
- scoped_refptr<ServiceWorkerVersion> controlling_version_;
+ scoped_refptr<ServiceWorkerVersion> controller_;
+ std::unique_ptr<BrowserSideServiceWorkerEventDispatcher>
+ controller_event_dispatcher_;
+
scoped_refptr<ServiceWorkerVersion> running_hosted_version_;
base::WeakPtr<ServiceWorkerContextCore> context_;
- ServiceWorkerDispatcherHost* dispatcher_host_;
+
+ // |dispatcher_host_| can be null in several cases:
+ // 1) In some tests.
+ // 2) PlzNavigate and service worker startup pre-create a
+ // ServiceWorkerProviderHost instance before there is a renderer assigned to
+ // it. The dispatcher host is set once the instance starts hosting a
+ // renderer.
+ // 3) During cross-site transfer.
+ // 4) The dispatcher host can be destructed/removed before the provider host.
+ base::WeakPtr<ServiceWorkerDispatcherHost> dispatcher_host_;
+
bool allow_association_;
- // |provider_| is the renderer-side Mojo endpoint for provider.
- mojom::ServiceWorkerProviderAssociatedPtr provider_;
+ // |container_| is the Mojo endpoint to the renderer-side
+ // ServiceWorkerContainer that |this| is a ServiceWorkerContainerHost for.
+ mojom::ServiceWorkerContainerAssociatedPtr container_;
// |binding_| is the Mojo binding that keeps the connection to the
// renderer-side counterpart (content::ServiceWorkerNetworkProvider). When the
- // connection bound on |binding_| gets killed from the renderer side, this
+ // connection bound on |binding_| gets killed from the renderer side, or the
+ // bound |ServiceWorkerProviderInfoForStartWorker::host_ptr_info| is otherwise
+ // destroyed before being passed to the renderer, this
// content::ServiceWorkerProviderHost will be destroyed.
- mojo::AssociatedBinding<mojom::ServiceWorkerProviderHost> binding_;
+ mojo::AssociatedBinding<mojom::ServiceWorkerContainerHost> binding_;
std::vector<base::Closure> queued_events_;
- // Keeps ServiceWorkerWorkerClient pointers of dedicated or shared workers
- // which are associated with the ServiceWorkerProviderHost.
- std::unordered_map<mojom::ServiceWorkerWorkerClient*,
- mojom::ServiceWorkerWorkerClientAssociatedPtr>
- worker_clients_;
-
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerProviderHost);
};
diff --git a/chromium/content/browser/service_worker/service_worker_provider_host_unittest.cc b/chromium/content/browser/service_worker/service_worker_provider_host_unittest.cc
index f4325c138c3..df6f1cdffed 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
@@ -10,13 +10,16 @@
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/memory/weak_ptr.h"
+#include "base/run_loop.h"
#include "base/threading/thread_task_runner_handle.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_dispatcher_host.h"
#include "content/browser/service_worker/service_worker_register_job.h"
#include "content/browser/service_worker/service_worker_registration.h"
#include "content/browser/service_worker/service_worker_test_utils.h"
#include "content/browser/service_worker/service_worker_version.h"
+#include "content/common/service_worker/service_worker_messages.h"
#include "content/common/url_schemes.h"
#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/common/child_process_host.h"
@@ -29,6 +32,19 @@
namespace content {
+namespace {
+
+// Sets the document URL for |host| and associates it with |registration|.
+// A dumb version of
+// ServiceWorkerControlleeRequestHandler::PrepareForMainResource().
+void SimulateServiceWorkerControlleeRequestHandler(
+ ServiceWorkerProviderHost* host,
+ ServiceWorkerRegistration* registration) {
+ host->SetDocumentUrl(GURL("https://www.example.com/page"));
+ host->AssociateRegistration(registration,
+ false /* notify_controllerchange */);
+}
+
const char kServiceWorkerScheme[] = "i-can-use-service-worker";
class ServiceWorkerTestContentClient : public TestContentClient {
@@ -38,12 +54,13 @@ class ServiceWorkerTestContentClient : public TestContentClient {
}
};
+} // namespace
+
class ServiceWorkerProviderHostTest : public testing::Test {
protected:
ServiceWorkerProviderHostTest()
: thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP),
- next_renderer_provided_id_(1),
- next_browser_provided_id_(-2) {
+ next_renderer_provided_id_(1) {
SetContentClient(&test_content_client_);
}
~ServiceWorkerProviderHostTest() override {}
@@ -69,8 +86,9 @@ class ServiceWorkerProviderHostTest : public testing::Test {
}
void TearDown() override {
- registration1_ = 0;
- registration2_ = 0;
+ registration1_ = nullptr;
+ registration2_ = nullptr;
+ registration3_ = nullptr;
helper_.reset();
SetBrowserClientForTesting(old_content_browser_client_);
// Reset cached security schemes so we don't affect other tests.
@@ -88,8 +106,7 @@ class ServiceWorkerProviderHostTest : public testing::Test {
host = ServiceWorkerProviderHost::PreCreateNavigationHost(
helper_->context()->AsWeakPtr(), true,
base::Callback<WebContents*(void)>());
- ServiceWorkerProviderHostInfo info(next_browser_provided_id_--,
- 1 /* route_id */,
+ ServiceWorkerProviderHostInfo info(host->provider_id(), 1 /* route_id */,
SERVICE_WORKER_PROVIDER_FOR_WINDOW,
true /* is_parent_frame_secure */);
remote_endpoints_.back().BindWithProviderHostInfo(&info);
@@ -133,7 +150,6 @@ class ServiceWorkerProviderHostTest : public testing::Test {
TestContentBrowserClient test_content_browser_client_;
ContentBrowserClient* old_content_browser_client_;
int next_renderer_provided_id_;
- int next_browser_provided_id_;
std::vector<ServiceWorkerRemoteProviderEndpoint> remote_endpoints_;
private:
@@ -351,4 +367,80 @@ TEST_F(ServiceWorkerProviderHostTest, RemoveProvider) {
EXPECT_FALSE(context_->GetProviderHost(process_id, provider_id));
}
+TEST_F(ServiceWorkerProviderHostTest, Controller) {
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kEnableBrowserSideNavigation);
+ // Create a host.
+ std::unique_ptr<ServiceWorkerProviderHost> host =
+ ServiceWorkerProviderHost::PreCreateNavigationHost(
+ helper_->context()->AsWeakPtr(), true /* are_ancestors_secure */,
+ base::Callback<WebContents*(void)>());
+ ServiceWorkerProviderHostInfo info(host->provider_id(), 1 /* route_id */,
+ SERVICE_WORKER_PROVIDER_FOR_WINDOW,
+ true /* is_parent_frame_secure */);
+ remote_endpoints_.emplace_back();
+ remote_endpoints_.back().BindWithProviderHostInfo(&info);
+
+ // 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());
+ registration1_->SetActiveVersion(version);
+ SimulateServiceWorkerControlleeRequestHandler(host.get(),
+ registration1_.get());
+
+ // Finish the navigation.
+ host->CompleteNavigationInitialized(
+ helper_->mock_render_process_id(), std::move(info),
+ helper_->GetDispatcherHostForProcess(helper_->mock_render_process_id())
+ ->AsWeakPtr());
+
+ // The page should be controlled since there was an active version at the
+ // time navigation started. The SetController IPC should have been sent.
+ EXPECT_TRUE(host->active_version());
+ EXPECT_EQ(host->active_version(), host->controller());
+ EXPECT_TRUE(helper_->ipc_sink()->GetUniqueMessageMatching(
+ ServiceWorkerMsg_SetControllerServiceWorker::ID));
+}
+
+TEST_F(ServiceWorkerProviderHostTest, ActiveIsNotController) {
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kEnableBrowserSideNavigation);
+ // Create a host.
+ std::unique_ptr<ServiceWorkerProviderHost> host =
+ ServiceWorkerProviderHost::PreCreateNavigationHost(
+ helper_->context()->AsWeakPtr(), true /* are_ancestors_secure */,
+ base::Callback<WebContents*(void)>());
+ ServiceWorkerProviderHostInfo info(host->provider_id(), 1 /* route_id */,
+ SERVICE_WORKER_PROVIDER_FOR_WINDOW,
+ true /* is_parent_frame_secure */);
+ remote_endpoints_.emplace_back();
+ remote_endpoints_.back().BindWithProviderHostInfo(&info);
+
+ // Associate it with an installing registration 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());
+ registration1_->SetInstallingVersion(version);
+ SimulateServiceWorkerControlleeRequestHandler(host.get(),
+ registration1_.get());
+
+ // Promote the worker to active while navigation is still happening.
+ registration1_->SetActiveVersion(version);
+
+ // Finish the navigation.
+ host->CompleteNavigationInitialized(
+ helper_->mock_render_process_id(), std::move(info),
+ helper_->GetDispatcherHostForProcess(helper_->mock_render_process_id())
+ ->AsWeakPtr());
+
+ // The page should not be controlled since there was no active version at the
+ // time navigation started. Furthermore, no SetController IPC should have been
+ // sent.
+ EXPECT_TRUE(host->active_version());
+ EXPECT_FALSE(host->controller());
+ EXPECT_EQ(nullptr, helper_->ipc_sink()->GetFirstMessageMatching(
+ ServiceWorkerMsg_SetControllerServiceWorker::ID));
+}
+
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_read_from_cache_job.cc b/chromium/content/browser/service_worker/service_worker_read_from_cache_job.cc
index 46835d5ba81..466c55c56f5 100644
--- a/chromium/content/browser/service_worker/service_worker_read_from_cache_job.cc
+++ b/chromium/content/browser/service_worker/service_worker_read_from_cache_job.cc
@@ -53,8 +53,8 @@ ServiceWorkerReadFromCacheJob::~ServiceWorkerReadFromCacheJob() {
void ServiceWorkerReadFromCacheJob::Start() {
TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("ServiceWorker", "ReadInfo", this);
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&ServiceWorkerReadFromCacheJob::StartAsync,
- weak_factory_.GetWeakPtr()));
+ FROM_HERE, base::BindOnce(&ServiceWorkerReadFromCacheJob::StartAsync,
+ weak_factory_.GetWeakPtr()));
}
void ServiceWorkerReadFromCacheJob::Kill() {
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 033232bb40c..856072624b4 100644
--- a/chromium/content/browser/service_worker/service_worker_register_job.cc
+++ b/chromium/content/browser/service_worker/service_worker_register_job.cc
@@ -125,8 +125,8 @@ void ServiceWorkerRegisterJob::AddCallback(
void ServiceWorkerRegisterJob::Start() {
BrowserThread::PostAfterStartupTask(
FROM_HERE, base::ThreadTaskRunnerHandle::Get(),
- base::Bind(&ServiceWorkerRegisterJob::StartImpl,
- weak_factory_.GetWeakPtr()));
+ base::BindOnce(&ServiceWorkerRegisterJob::StartImpl,
+ weak_factory_.GetWeakPtr()));
}
void ServiceWorkerRegisterJob::StartImpl() {
@@ -441,8 +441,8 @@ void ServiceWorkerRegisterJob::InstallAndContinue() {
// "Fire an event named install..."
new_version()->RunAfterStartWorker(
ServiceWorkerMetrics::EventType::INSTALL,
- base::Bind(&ServiceWorkerRegisterJob::DispatchInstallEvent,
- weak_factory_.GetWeakPtr()),
+ base::BindOnce(&ServiceWorkerRegisterJob::DispatchInstallEvent,
+ weak_factory_.GetWeakPtr()),
base::Bind(&ServiceWorkerRegisterJob::OnInstallFailed,
weak_factory_.GetWeakPtr()));
@@ -469,9 +469,9 @@ void ServiceWorkerRegisterJob::DispatchInstallEvent() {
install_methods_receiver->BindInterface(&ptr_info);
new_version()->event_dispatcher()->DispatchInstallEvent(
std::move(ptr_info),
- base::Bind(&ServiceWorkerRegisterJob::OnInstallFinished,
- weak_factory_.GetWeakPtr(), request_id,
- base::Passed(&install_methods_receiver)));
+ base::BindOnce(&ServiceWorkerRegisterJob::OnInstallFinished,
+ weak_factory_.GetWeakPtr(), request_id,
+ base::Passed(&install_methods_receiver)));
}
void ServiceWorkerRegisterJob::OnInstallFinished(
diff --git a/chromium/content/browser/service_worker/service_worker_registration.cc b/chromium/content/browser/service_worker/service_worker_registration.cc
index ca1ca39d302..d5706a8a6bc 100644
--- a/chromium/content/browser/service_worker/service_worker_registration.cc
+++ b/chromium/content/browser/service_worker/service_worker_registration.cc
@@ -211,7 +211,7 @@ void ServiceWorkerRegistration::ClaimClients() {
ServiceWorkerProviderHost* host = it->GetProviderHost();
if (host->IsHostToRunningServiceWorker())
continue;
- if (host->controlling_version() == active_version())
+ if (host->controller() == active_version())
continue;
if (!host->IsContextSecureForServiceWorker())
continue;
@@ -377,8 +377,9 @@ void ServiceWorkerRegistration::ActivateWaitingVersion(bool delay) {
// failures, wait a bit before continuing.
if (delay) {
task_runner_->PostDelayedTask(
- FROM_HERE, base::Bind(&ServiceWorkerRegistration::ContinueActivation,
- this, activating_version),
+ FROM_HERE,
+ base::BindOnce(&ServiceWorkerRegistration::ContinueActivation, this,
+ activating_version),
base::TimeDelta::FromSeconds(1));
} else {
ContinueActivation(std::move(activating_version));
@@ -394,8 +395,8 @@ void ServiceWorkerRegistration::ContinueActivation(
DCHECK_EQ(ServiceWorkerVersion::ACTIVATING, activating_version->status());
activating_version->RunAfterStartWorker(
ServiceWorkerMetrics::EventType::ACTIVATE,
- base::Bind(&ServiceWorkerRegistration::DispatchActivateEvent, this,
- activating_version),
+ base::BindOnce(&ServiceWorkerRegistration::DispatchActivateEvent, this,
+ activating_version),
base::Bind(&ServiceWorkerRegistration::OnActivateEventFinished, this,
activating_version));
}
@@ -410,7 +411,7 @@ void ServiceWorkerRegistration::DeleteVersion(
context_->GetProviderHostIterator();
!it->IsAtEnd(); it->Advance()) {
ServiceWorkerProviderHost* host = it->GetProviderHost();
- if (host->controlling_version() == version)
+ if (host->controller() == version)
host->NotifyControllerLost();
}
diff --git a/chromium/content/browser/service_worker/service_worker_registration.h b/chromium/content/browser/service_worker/service_worker_registration.h
index b48520c074a..ecbe25122cf 100644
--- a/chromium/content/browser/service_worker/service_worker_registration.h
+++ b/chromium/content/browser/service_worker/service_worker_registration.h
@@ -30,12 +30,12 @@ struct ServiceWorkerRegistrationInfo;
// to this class. This is refcounted via ServiceWorkerRegistrationHandle to
// facilitate multiple controllees being associated with the same registration.
class CONTENT_EXPORT ServiceWorkerRegistration
- : public NON_EXPORTED_BASE(base::RefCounted<ServiceWorkerRegistration>),
- public NON_EXPORTED_BASE(ServiceWorkerVersion::Listener) {
+ : public base::RefCounted<ServiceWorkerRegistration>,
+ public ServiceWorkerVersion::Listener {
public:
typedef base::Callback<void(ServiceWorkerStatusCode status)> StatusCallback;
- class Listener {
+ class CONTENT_EXPORT Listener {
public:
virtual void OnVersionAttributesChanged(
ServiceWorkerRegistration* registration,
diff --git a/chromium/content/browser/service_worker/service_worker_registration_handle.h b/chromium/content/browser/service_worker/service_worker_registration_handle.h
index e06b112e1f4..1384604eec1 100644
--- a/chromium/content/browser/service_worker/service_worker_registration_handle.h
+++ b/chromium/content/browser/service_worker/service_worker_registration_handle.h
@@ -12,6 +12,7 @@
#include "base/memory/weak_ptr.h"
#include "content/browser/service_worker/service_worker_registration.h"
#include "content/browser/service_worker/service_worker_version.h"
+#include "content/common/content_export.h"
#include "content/common/service_worker/service_worker_types.h"
namespace content {
@@ -30,10 +31,10 @@ class ServiceWorkerVersion;
//
// Has a reference to the corresponding ServiceWorkerRegistration in order to
// ensure that the registration is alive while this handle is around.
-class ServiceWorkerRegistrationHandle
+class CONTENT_EXPORT ServiceWorkerRegistrationHandle
: public ServiceWorkerRegistration::Listener {
public:
- CONTENT_EXPORT ServiceWorkerRegistrationHandle(
+ ServiceWorkerRegistrationHandle(
base::WeakPtr<ServiceWorkerContextCore> context,
base::WeakPtr<ServiceWorkerProviderHost> provider_host,
ServiceWorkerRegistration* registration);
diff --git a/chromium/content/browser/service_worker/service_worker_registration_status.cc b/chromium/content/browser/service_worker/service_worker_registration_status.cc
index a36727389e7..ed6bc744050 100644
--- a/chromium/content/browser/service_worker/service_worker_registration_status.cc
+++ b/chromium/content/browser/service_worker/service_worker_registration_status.cc
@@ -8,6 +8,7 @@
#include "base/logging.h"
#include "base/strings/utf_string_conversions.h"
+#include "third_party/WebKit/public/platform/modules/serviceworker/service_worker_error_type.mojom.h"
namespace content {
@@ -16,9 +17,9 @@ using blink::WebServiceWorkerError;
void GetServiceWorkerRegistrationStatusResponse(
ServiceWorkerStatusCode status,
const std::string& status_message,
- blink::WebServiceWorkerError::ErrorType* error_type,
+ blink::mojom::ServiceWorkerErrorType* error_type,
base::string16* message) {
- *error_type = WebServiceWorkerError::kErrorTypeUnknown;
+ *error_type = blink::mojom::ServiceWorkerErrorType::kUnknown;
if (!status_message.empty())
*message = base::UTF8ToUTF16(status_message);
else
@@ -33,31 +34,31 @@ void GetServiceWorkerRegistrationStatusResponse(
case SERVICE_WORKER_ERROR_PROCESS_NOT_FOUND:
case SERVICE_WORKER_ERROR_REDUNDANT:
case SERVICE_WORKER_ERROR_DISALLOWED:
- *error_type = WebServiceWorkerError::kErrorTypeInstall;
+ *error_type = blink::mojom::ServiceWorkerErrorType::kInstall;
return;
case SERVICE_WORKER_ERROR_NOT_FOUND:
- *error_type = WebServiceWorkerError::kErrorTypeNotFound;
+ *error_type = blink::mojom::ServiceWorkerErrorType::kNotFound;
return;
case SERVICE_WORKER_ERROR_NETWORK:
- *error_type = WebServiceWorkerError::kErrorTypeNetwork;
+ *error_type = blink::mojom::ServiceWorkerErrorType::kNetwork;
return;
case SERVICE_WORKER_ERROR_SCRIPT_EVALUATE_FAILED:
- *error_type = WebServiceWorkerError::kErrorTypeScriptEvaluateFailed;
+ *error_type = blink::mojom::ServiceWorkerErrorType::kScriptEvaluateFailed;
return;
case SERVICE_WORKER_ERROR_SECURITY:
- *error_type = WebServiceWorkerError::kErrorTypeSecurity;
+ *error_type = blink::mojom::ServiceWorkerErrorType::kSecurity;
return;
case SERVICE_WORKER_ERROR_TIMEOUT:
- *error_type = WebServiceWorkerError::kErrorTypeTimeout;
+ *error_type = blink::mojom::ServiceWorkerErrorType::kTimeout;
return;
case SERVICE_WORKER_ERROR_ABORT:
- *error_type = WebServiceWorkerError::kErrorTypeAbort;
+ *error_type = blink::mojom::ServiceWorkerErrorType::kAbort;
return;
case SERVICE_WORKER_ERROR_ACTIVATE_WORKER_FAILED:
diff --git a/chromium/content/browser/service_worker/service_worker_registration_status.h b/chromium/content/browser/service_worker/service_worker_registration_status.h
index 44e6d923a1e..7f94b26f440 100644
--- a/chromium/content/browser/service_worker/service_worker_registration_status.h
+++ b/chromium/content/browser/service_worker/service_worker_registration_status.h
@@ -15,7 +15,7 @@ namespace content {
void GetServiceWorkerRegistrationStatusResponse(
ServiceWorkerStatusCode status,
const std::string& status_message,
- blink::WebServiceWorkerError::ErrorType* error_type,
+ blink::mojom::ServiceWorkerErrorType* error_type,
base::string16* message);
} // namespace content
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 3f7dd64792e..cab5b64c2a9 100644
--- a/chromium/content/browser/service_worker/service_worker_registration_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_registration_unittest.cc
@@ -266,6 +266,8 @@ class ServiceWorkerActivationTest : public ServiceWorkerRegistrationTest {
helper_->mock_render_process_id(), 1 /* dummy provider_id */,
true /* is_parent_frame_secure */, context()->AsWeakPtr(),
&remote_endpoint_);
+ DCHECK(remote_endpoint_.client_request()->is_pending());
+ DCHECK(remote_endpoint_.host_ptr()->is_bound());
version_1->AddControllee(host_.get());
// Give the active version an in-flight request.
diff --git a/chromium/content/browser/service_worker/service_worker_response_info.cc b/chromium/content/browser/service_worker/service_worker_response_info.cc
index e9b3f63a52e..028e30dada0 100644
--- a/chromium/content/browser/service_worker/service_worker_response_info.cc
+++ b/chromium/content/browser/service_worker/service_worker_response_info.cc
@@ -80,7 +80,7 @@ void ServiceWorkerResponseInfo::OnStartCompleted(
bool was_fetched_via_foreign_fetch,
bool was_fallback_required,
const std::vector<GURL>& url_list_via_service_worker,
- blink::WebServiceWorkerResponseType response_type_via_service_worker,
+ network::mojom::FetchResponseType response_type_via_service_worker,
base::TimeTicks service_worker_start_time,
base::TimeTicks service_worker_ready_time,
bool response_is_in_cache_storage,
@@ -111,7 +111,7 @@ void ServiceWorkerResponseInfo::ResetData() {
was_fallback_required_ = false;
url_list_via_service_worker_.clear();
response_type_via_service_worker_ =
- blink::kWebServiceWorkerResponseTypeDefault;
+ network::mojom::FetchResponseType::kDefault;
// Don't reset |service_worker_start_time_| or |service_worker_ready_time_|
// since it's historical timing information that should persist between job
// restarts.
diff --git a/chromium/content/browser/service_worker/service_worker_response_info.h b/chromium/content/browser/service_worker/service_worker_response_info.h
index 679207c1f4f..ab759f1cef3 100644
--- a/chromium/content/browser/service_worker/service_worker_response_info.h
+++ b/chromium/content/browser/service_worker/service_worker_response_info.h
@@ -10,7 +10,7 @@
#include "base/supports_user_data.h"
#include "content/common/content_export.h"
#include "content/common/service_worker/service_worker_types.h"
-#include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerResponseType.h"
+#include "services/network/public/interfaces/fetch_api.mojom.h"
#include "url/gurl.h"
namespace net {
@@ -39,7 +39,7 @@ class CONTENT_EXPORT ServiceWorkerResponseInfo
bool was_fetched_via_foreign_fetch,
bool was_fallback_required,
const std::vector<GURL>& url_list_via_service_worker,
- blink::WebServiceWorkerResponseType response_type_via_service_worker,
+ network::mojom::FetchResponseType response_type_via_service_worker,
base::TimeTicks service_worker_start_time,
base::TimeTicks service_worker_ready_time,
bool response_is_in_cache_storage,
@@ -76,7 +76,7 @@ class CONTENT_EXPORT ServiceWorkerResponseInfo
const std::vector<GURL>& url_list_via_service_worker() const {
return url_list_via_service_worker_;
}
- blink::WebServiceWorkerResponseType response_type_via_service_worker() const {
+ network::mojom::FetchResponseType response_type_via_service_worker() const {
return response_type_via_service_worker_;
}
base::TimeTicks service_worker_start_time() const {
@@ -100,8 +100,8 @@ class CONTENT_EXPORT ServiceWorkerResponseInfo
bool was_fetched_via_foreign_fetch_ = false;
bool was_fallback_required_ = false;
std::vector<GURL> url_list_via_service_worker_;
- blink::WebServiceWorkerResponseType response_type_via_service_worker_ =
- blink::kWebServiceWorkerResponseTypeDefault;
+ network::mojom::FetchResponseType response_type_via_service_worker_ =
+ network::mojom::FetchResponseType::kDefault;
base::TimeTicks service_worker_start_time_;
base::TimeTicks service_worker_ready_time_;
bool response_is_in_cache_storage_ = false;
diff --git a/chromium/content/browser/service_worker/service_worker_script_url_loader.cc b/chromium/content/browser/service_worker/service_worker_script_url_loader.cc
new file mode 100644
index 00000000000..3e802a23a17
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_script_url_loader.cc
@@ -0,0 +1,114 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/service_worker/service_worker_script_url_loader.h"
+
+#include <memory>
+#include "content/browser/service_worker/service_worker_context_core.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/public/common/resource_response.h"
+#include "storage/browser/blob/blob_storage_context.h"
+
+namespace content {
+
+ServiceWorkerScriptURLLoader::ServiceWorkerScriptURLLoader(
+ int32_t routing_id,
+ int32_t request_id,
+ uint32_t options,
+ const ResourceRequest& resource_request,
+ mojom::URLLoaderClientPtr client,
+ base::WeakPtr<ServiceWorkerContextCore> context,
+ base::WeakPtr<ServiceWorkerProviderHost> provider_host,
+ base::WeakPtr<storage::BlobStorageContext> blob_storage_context,
+ scoped_refptr<URLLoaderFactoryGetter> loader_factory_getter,
+ const net::MutableNetworkTrafficAnnotationTag& traffic_annotation)
+ : network_client_binding_(this),
+ forwarding_client_(std::move(client)),
+ provider_host_(provider_host) {
+ mojom::URLLoaderClientPtr network_client;
+ network_client_binding_.Bind(mojo::MakeRequest(&network_client));
+ loader_factory_getter->GetNetworkFactory()->get()->CreateLoaderAndStart(
+ mojo::MakeRequest(&network_loader_), routing_id, request_id, options,
+ resource_request, std::move(network_client), traffic_annotation);
+}
+
+ServiceWorkerScriptURLLoader::~ServiceWorkerScriptURLLoader() = default;
+
+void ServiceWorkerScriptURLLoader::FollowRedirect() {
+ network_loader_->FollowRedirect();
+}
+
+void ServiceWorkerScriptURLLoader::SetPriority(net::RequestPriority priority,
+ int32_t intra_priority_value) {
+ network_loader_->SetPriority(priority, intra_priority_value);
+}
+
+void ServiceWorkerScriptURLLoader::OnReceiveResponse(
+ const ResourceResponseHead& response_head,
+ const base::Optional<net::SSLInfo>& ssl_info,
+ mojom::DownloadedTempFilePtr downloaded_file) {
+ if (provider_host_) {
+ // We don't have complete info here, but fill in what we have now.
+ // At least we need headers and SSL info.
+ net::HttpResponseInfo response_info;
+ response_info.headers = response_head.headers;
+ if (ssl_info.has_value())
+ response_info.ssl_info = *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;
+
+ DCHECK(provider_host_->IsHostToRunningServiceWorker());
+ provider_host_->running_hosted_version()->SetMainScriptHttpResponseInfo(
+ response_info);
+ }
+ forwarding_client_->OnReceiveResponse(response_head, ssl_info,
+ std::move(downloaded_file));
+}
+
+void ServiceWorkerScriptURLLoader::OnReceiveRedirect(
+ const net::RedirectInfo& redirect_info,
+ const ResourceResponseHead& response_head) {
+ forwarding_client_->OnReceiveRedirect(redirect_info, response_head);
+}
+
+void ServiceWorkerScriptURLLoader::OnDataDownloaded(int64_t data_len,
+ int64_t encoded_data_len) {
+ forwarding_client_->OnDataDownloaded(data_len, encoded_data_len);
+}
+
+void ServiceWorkerScriptURLLoader::OnUploadProgress(
+ int64_t current_position,
+ int64_t total_size,
+ OnUploadProgressCallback ack_callback) {
+ forwarding_client_->OnUploadProgress(current_position, total_size,
+ std::move(ack_callback));
+}
+
+void ServiceWorkerScriptURLLoader::OnReceiveCachedMetadata(
+ const std::vector<uint8_t>& data) {
+ forwarding_client_->OnReceiveCachedMetadata(data);
+}
+
+void ServiceWorkerScriptURLLoader::OnTransferSizeUpdated(
+ int32_t transfer_size_diff) {
+ forwarding_client_->OnTransferSizeUpdated(transfer_size_diff);
+}
+
+void ServiceWorkerScriptURLLoader::OnStartLoadingResponseBody(
+ mojo::ScopedDataPipeConsumerHandle body) {
+ forwarding_client_->OnStartLoadingResponseBody(std::move(body));
+}
+
+void ServiceWorkerScriptURLLoader::OnComplete(
+ const ResourceRequestCompletionStatus& status) {
+ forwarding_client_->OnComplete(status);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_script_url_loader.h b/chromium/content/browser/service_worker/service_worker_script_url_loader.h
new file mode 100644
index 00000000000..3847128e801
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_script_url_loader.h
@@ -0,0 +1,79 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_SCRIPT_URL_LOADER_H_
+#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_SCRIPT_URL_LOADER_H_
+
+#include "base/macros.h"
+#include "content/browser/service_worker/service_worker_provider_host.h"
+#include "content/public/common/resource_request.h"
+#include "content/public/common/url_loader.mojom.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "net/traffic_annotation/network_traffic_annotation.h"
+
+namespace storage {
+class BlobStorageContext;
+} // namespace storage
+
+namespace content {
+
+class ServiceWorkerContextCore;
+class ServiceWorkerProviderHost;
+class URLLoaderFactoryGetter;
+
+// S13nServiceWorker:
+// Used by a Service Worker for script loading only during the installation
+// time. For now this is just a proxy loader for the network loader.
+// Eventually this should replace the existing URLRequestJob-based request
+// interception for script loading, namely ServiceWorkerWriteToCacheJob.
+// TODO(kinuko): Implement this.
+class ServiceWorkerScriptURLLoader : public mojom::URLLoader,
+ public mojom::URLLoaderClient {
+ public:
+ ServiceWorkerScriptURLLoader(
+ int32_t routing_id,
+ int32_t request_id,
+ uint32_t options,
+ const ResourceRequest& resource_request,
+ mojom::URLLoaderClientPtr client,
+ base::WeakPtr<ServiceWorkerContextCore> context,
+ base::WeakPtr<ServiceWorkerProviderHost> provider_host,
+ base::WeakPtr<storage::BlobStorageContext> blob_storage_context,
+ scoped_refptr<URLLoaderFactoryGetter> loader_factory_getter,
+ const net::MutableNetworkTrafficAnnotationTag& traffic_annotation);
+ ~ServiceWorkerScriptURLLoader() override;
+
+ // mojom::URLLoader:
+ void FollowRedirect() override;
+ void SetPriority(net::RequestPriority priority,
+ int32_t intra_priority_value) override;
+
+ // mojom::URLLoaderClient for simply proxying network:
+ void OnReceiveResponse(const ResourceResponseHead& response_head,
+ const base::Optional<net::SSLInfo>& ssl_info,
+ mojom::DownloadedTempFilePtr downloaded_file) override;
+ void OnReceiveRedirect(const net::RedirectInfo& redirect_info,
+ const ResourceResponseHead& response_head) override;
+ void OnDataDownloaded(int64_t data_len, int64_t encoded_data_len) 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 body) override;
+ void OnComplete(const ResourceRequestCompletionStatus& status) override;
+
+ private:
+ mojom::URLLoaderPtr network_loader_;
+ mojo::Binding<mojom::URLLoaderClient> network_client_binding_;
+ mojom::URLLoaderClientPtr forwarding_client_;
+ base::WeakPtr<ServiceWorkerProviderHost> provider_host_;
+
+ DISALLOW_COPY_AND_ASSIGN(ServiceWorkerScriptURLLoader);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_SCRIPT_URL_LOADER_H_
diff --git a/chromium/content/browser/service_worker/service_worker_script_url_loader_factory.cc b/chromium/content/browser/service_worker/service_worker_script_url_loader_factory.cc
new file mode 100644
index 00000000000..271c3b95133
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_script_url_loader_factory.cc
@@ -0,0 +1,130 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/service_worker/service_worker_script_url_loader_factory.h"
+
+#include <memory>
+#include "content/browser/service_worker/service_worker_context_core.h"
+#include "content/browser/service_worker/service_worker_provider_host.h"
+#include "content/browser/service_worker/service_worker_script_url_loader.h"
+#include "content/browser/service_worker/service_worker_version.h"
+#include "content/browser/url_loader_factory_getter.h"
+#include "content/common/service_worker/service_worker_utils.h"
+#include "content/public/common/resource_response.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "storage/browser/blob/blob_storage_context.h"
+
+namespace content {
+
+ServiceWorkerScriptURLLoaderFactory::ServiceWorkerScriptURLLoaderFactory(
+ base::WeakPtr<ServiceWorkerContextCore> context,
+ base::WeakPtr<ServiceWorkerProviderHost> provider_host,
+ base::WeakPtr<storage::BlobStorageContext> blob_storage_context,
+ scoped_refptr<URLLoaderFactoryGetter> loader_factory_getter)
+ : context_(context),
+ provider_host_(provider_host),
+ blob_storage_context_(blob_storage_context),
+ loader_factory_getter_(loader_factory_getter) {}
+
+ServiceWorkerScriptURLLoaderFactory::~ServiceWorkerScriptURLLoaderFactory() =
+ default;
+
+void ServiceWorkerScriptURLLoaderFactory::CreateLoaderAndStart(
+ mojom::URLLoaderRequest request,
+ int32_t routing_id,
+ int32_t request_id,
+ uint32_t options,
+ const ResourceRequest& resource_request,
+ mojom::URLLoaderClientPtr client,
+ const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) {
+ if (!ShouldHandleScriptRequest(resource_request)) {
+ // If the request should not be handled by ServiceWorkerScriptURLLoader,
+ // just fallback to the network. This needs a relaying as we use different
+ // associated message pipes.
+ // TODO(kinuko): Record the reason like what we do with netlog in
+ // ServiceWorkerContextRequestHandler.
+ (*loader_factory_getter_->GetNetworkFactory())
+ ->CreateLoaderAndStart(std::move(request), routing_id, request_id,
+ options, resource_request, std::move(client),
+ traffic_annotation);
+ return;
+ }
+ mojo::MakeStrongBinding(
+ base::MakeUnique<ServiceWorkerScriptURLLoader>(
+ routing_id, request_id, options, resource_request, std::move(client),
+ context_, provider_host_, blob_storage_context_,
+ loader_factory_getter_, traffic_annotation),
+ std::move(request));
+}
+
+void ServiceWorkerScriptURLLoaderFactory::Clone(
+ mojom::URLLoaderFactoryRequest request) {
+ // This method is required to support synchronous requests which are not
+ // performed during installation.
+ NOTREACHED();
+}
+
+bool ServiceWorkerScriptURLLoaderFactory::ShouldHandleScriptRequest(
+ const ResourceRequest& resource_request) {
+ if (!context_ || !provider_host_)
+ return false;
+
+ // We only use the script cache for main script loading and
+ // importScripts(), even if a cached script is xhr'd, we don't
+ // retrieve it from the script cache.
+ if (resource_request.resource_type != RESOURCE_TYPE_SERVICE_WORKER &&
+ resource_request.resource_type != RESOURCE_TYPE_SCRIPT) {
+ // TODO: Record bad message, we shouldn't come here for other
+ // request types.
+ return false;
+ }
+
+ scoped_refptr<ServiceWorkerVersion> version =
+ provider_host_->running_hosted_version();
+
+ // This could happen if browser-side has set the status to redundant but
+ // the worker has not yet stopped. The worker is already doomed so just
+ // reject the request. Handle it specially here because otherwise it'd be
+ // unclear whether "REDUNDANT" should count as installed or not installed
+ // when making decisions about how to handle the request and logging UMA.
+ if (!version || version->status() == ServiceWorkerVersion::REDUNDANT)
+ return false;
+
+ // TODO: Make sure we don't handle the redirected request.
+
+ // If script streaming is enabled, for installed service workers, typically
+ // all the scripts are served via script streaming, so we don't come here.
+ // However, we still come here when the service worker is A) importing a
+ // script that was never installed, or B) loading the same script twice.
+ // For now, return false here to fallback to network. Eventually, A) should
+ // be deprecated (https://crbug.com/719052), and B) should be handled by
+ // script streaming as well, see the TODO in
+ // WebServiceWorkerInstalledScriptsManagerImpl::GetRawScriptData().
+ //
+ // When script streaming is not enabled, we get here even for the main
+ // script. Therefore, ServiceWorkerScriptURLLoader must handle the request
+ // (even though it currently just does a network fetch for now), because it
+ // sets the main script's HTTP Response Info (via
+ // ServiceWorkerVersion::SetMainScriptHttpResponseInfo()) which otherwise
+ // would never be set.
+ if (ServiceWorkerVersion::IsInstalled(version->status()) &&
+ ServiceWorkerUtils::IsScriptStreamingEnabled()) {
+ return false;
+ }
+
+ // TODO: Make sure we come here only for new / unknown scripts
+ // once script streaming manager in the renderer side stops sending
+ // resource requests for the known script URLs, i.e. add DCHECK for
+ // version->script_cache_map()->LookupResourceId(url) ==
+ // kInvalidServiceWorkerResourceId.
+ //
+ // Currently this could be false for the installing worker that imports
+ // the same script twice (e.g. importScripts('dupe.js');
+ // importScripts('dupe.js');).
+
+ // Request should be served by ServiceWorkerScriptURLLoader.
+ return true;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_script_url_loader_factory.h b/chromium/content/browser/service_worker/service_worker_script_url_loader_factory.h
new file mode 100644
index 00000000000..9b0f768e011
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_script_url_loader_factory.h
@@ -0,0 +1,59 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_SCRIPT_URL_LOADER_FACTORY_H_
+#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_SCRIPT_URL_LOADER_FACTORY_H_
+
+#include "base/macros.h"
+#include "content/public/common/url_loader_factory.mojom.h"
+
+namespace storage {
+class BlobStorageContext;
+} // namespace storage
+
+namespace content {
+
+class ServiceWorkerContextCore;
+class ServiceWorkerProviderHost;
+class URLLoaderFactoryGetter;
+
+// S13nServiceWorker:
+// Created per one controller worker for script loading (only during
+// installation, eventually). This is kept alive while
+// ServiceWorkerNetworkProvider in the renderer process is alive.
+// Used only when IsServicificationEnabled is true.
+class ServiceWorkerScriptURLLoaderFactory : public mojom::URLLoaderFactory {
+ public:
+ ServiceWorkerScriptURLLoaderFactory(
+ base::WeakPtr<ServiceWorkerContextCore> context,
+ base::WeakPtr<ServiceWorkerProviderHost> provider_host,
+ base::WeakPtr<storage::BlobStorageContext> blob_storage_context,
+ scoped_refptr<URLLoaderFactoryGetter> loader_factory_getter);
+ ~ServiceWorkerScriptURLLoaderFactory() override;
+
+ // mojom::URLLoaderFactory:
+ void CreateLoaderAndStart(mojom::URLLoaderRequest request,
+ int32_t routing_id,
+ int32_t request_id,
+ uint32_t options,
+ const ResourceRequest& resource_request,
+ mojom::URLLoaderClientPtr client,
+ const net::MutableNetworkTrafficAnnotationTag&
+ traffic_annotation) override;
+ void Clone(mojom::URLLoaderFactoryRequest request) override;
+
+ private:
+ bool ShouldHandleScriptRequest(const ResourceRequest& resource_request);
+
+ base::WeakPtr<ServiceWorkerContextCore> context_;
+ base::WeakPtr<ServiceWorkerProviderHost> provider_host_;
+ base::WeakPtr<storage::BlobStorageContext> blob_storage_context_;
+ scoped_refptr<URLLoaderFactoryGetter> loader_factory_getter_;
+
+ DISALLOW_COPY_AND_ASSIGN(ServiceWorkerScriptURLLoaderFactory);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_SCRIPT_URL_LOADER_FACTORY_H_
diff --git a/chromium/content/browser/service_worker/service_worker_storage.cc b/chromium/content/browser/service_worker/service_worker_storage.cc
index 8d38845d39f..585d157df3f 100644
--- a/chromium/content/browser/service_worker/service_worker_storage.cc
+++ b/chromium/content/browser/service_worker/service_worker_storage.cc
@@ -5,15 +5,15 @@
#include "content/browser/service_worker/service_worker_storage.h"
#include <stddef.h>
+#include <utility>
#include "base/bind_helpers.h"
#include "base/files/file_util.h"
#include "base/memory/ptr_util.h"
#include "base/message_loop/message_loop.h"
#include "base/sequenced_task_runner.h"
-#include "base/single_thread_task_runner.h"
#include "base/task_runner_util.h"
-#include "base/threading/thread_task_runner_handle.h"
+#include "base/task_scheduler/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_disk_cache.h"
@@ -29,6 +29,8 @@
#include "storage/browser/quota/quota_manager_proxy.h"
#include "storage/browser/quota/special_storage_policy.h"
+using std::swap;
+
namespace content {
namespace {
@@ -112,21 +114,19 @@ DidDeleteRegistrationParams::~DidDeleteRegistrationParams() {
ServiceWorkerStorage::~ServiceWorkerStorage() {
ClearSessionOnlyOrigins();
weak_factory_.InvalidateWeakPtrs();
- database_task_manager_->GetTaskRunner()->DeleteSoon(FROM_HERE,
- database_.release());
+ database_task_runner_->DeleteSoon(FROM_HERE, std::move(database_));
}
// static
std::unique_ptr<ServiceWorkerStorage> ServiceWorkerStorage::Create(
const base::FilePath& path,
const base::WeakPtr<ServiceWorkerContextCore>& context,
- std::unique_ptr<ServiceWorkerDatabaseTaskManager> database_task_manager,
- const scoped_refptr<base::SingleThreadTaskRunner>& disk_cache_thread,
+ scoped_refptr<base::SequencedTaskRunner> database_task_runner,
storage::QuotaManagerProxy* quota_manager_proxy,
storage::SpecialStoragePolicy* special_storage_policy) {
- return base::WrapUnique(new ServiceWorkerStorage(
- path, context, std::move(database_task_manager), disk_cache_thread,
- quota_manager_proxy, special_storage_policy));
+ return base::WrapUnique(
+ new ServiceWorkerStorage(path, context, std::move(database_task_runner),
+ quota_manager_proxy, special_storage_policy));
}
// static
@@ -134,8 +134,8 @@ std::unique_ptr<ServiceWorkerStorage> ServiceWorkerStorage::Create(
const base::WeakPtr<ServiceWorkerContextCore>& context,
ServiceWorkerStorage* old_storage) {
return base::WrapUnique(new ServiceWorkerStorage(
- old_storage->path_, context, old_storage->database_task_manager_->Clone(),
- old_storage->disk_cache_thread_, old_storage->quota_manager_proxy_.get(),
+ old_storage->path_, context, old_storage->database_task_runner_,
+ old_storage->quota_manager_proxy_.get(),
old_storage->special_storage_policy_.get()));
}
@@ -180,22 +180,16 @@ void ServiceWorkerStorage::FindRegistrationForDocument(
// To connect this TRACE_EVENT with the callback, TimeTicks is used for
// callback id.
int64_t callback_id = base::TimeTicks::Now().ToInternalValue();
- TRACE_EVENT_ASYNC_BEGIN1(
- "ServiceWorker",
- "ServiceWorkerStorage::FindRegistrationForDocument",
- callback_id,
- "URL", document_url.spec());
- database_task_manager_->GetTaskRunner()->PostTask(
+ TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker",
+ "ServiceWorkerStorage::FindRegistrationForDocument",
+ callback_id, "URL", document_url.spec());
+ database_task_runner_->PostTask(
FROM_HERE,
- base::Bind(
- &FindForDocumentInDB,
- database_.get(),
- base::ThreadTaskRunnerHandle::Get(),
- document_url,
+ base::BindOnce(
+ &FindForDocumentInDB, database_.get(),
+ base::ThreadTaskRunnerHandle::Get(), document_url,
base::Bind(&ServiceWorkerStorage::DidFindRegistrationForDocument,
- weak_factory_.GetWeakPtr(),
- document_url,
- callback,
+ weak_factory_.GetWeakPtr(), document_url, callback,
callback_id)));
}
@@ -226,17 +220,13 @@ void ServiceWorkerStorage::FindRegistrationForPattern(
return;
}
- database_task_manager_->GetTaskRunner()->PostTask(
+ database_task_runner_->PostTask(
FROM_HERE,
- base::Bind(
- &FindForPatternInDB,
- database_.get(),
- base::ThreadTaskRunnerHandle::Get(),
- scope,
+ base::BindOnce(
+ &FindForPatternInDB, database_.get(),
+ base::ThreadTaskRunnerHandle::Get(), scope,
base::Bind(&ServiceWorkerStorage::DidFindRegistrationForPattern,
- weak_factory_.GetWeakPtr(),
- scope,
- callback)));
+ weak_factory_.GetWeakPtr(), scope, callback)));
}
ServiceWorkerRegistration* ServiceWorkerStorage::GetUninstallingRegistration(
@@ -286,16 +276,13 @@ void ServiceWorkerStorage::FindRegistrationForId(
return;
}
- database_task_manager_->GetTaskRunner()->PostTask(
+ database_task_runner_->PostTask(
FROM_HERE,
- base::Bind(&FindForIdInDB,
- database_.get(),
- base::ThreadTaskRunnerHandle::Get(),
- registration_id,
- origin,
- base::Bind(&ServiceWorkerStorage::DidFindRegistrationForId,
- weak_factory_.GetWeakPtr(),
- callback)));
+ base::BindOnce(&FindForIdInDB, database_.get(),
+ base::ThreadTaskRunnerHandle::Get(), registration_id,
+ origin,
+ base::Bind(&ServiceWorkerStorage::DidFindRegistrationForId,
+ weak_factory_.GetWeakPtr(), callback)));
}
void ServiceWorkerStorage::FindRegistrationForIdOnly(
@@ -323,15 +310,12 @@ void ServiceWorkerStorage::FindRegistrationForIdOnly(
return;
}
- database_task_manager_->GetTaskRunner()->PostTask(
+ database_task_runner_->PostTask(
FROM_HERE,
- base::Bind(&FindForIdOnlyInDB,
- database_.get(),
- base::ThreadTaskRunnerHandle::Get(),
- registration_id,
- base::Bind(&ServiceWorkerStorage::DidFindRegistrationForId,
- weak_factory_.GetWeakPtr(),
- callback)));
+ base::BindOnce(&FindForIdOnlyInDB, database_.get(),
+ base::ThreadTaskRunnerHandle::Get(), registration_id,
+ base::Bind(&ServiceWorkerStorage::DidFindRegistrationForId,
+ weak_factory_.GetWeakPtr(), callback)));
}
void ServiceWorkerStorage::GetRegistrationsForOrigin(
@@ -352,8 +336,8 @@ void ServiceWorkerStorage::GetRegistrationsForOrigin(
RegistrationList* registrations = new RegistrationList;
std::vector<ResourceList>* resource_lists = new std::vector<ResourceList>;
- PostTaskAndReplyWithResult(
- database_task_manager_->GetTaskRunner(), FROM_HERE,
+ base::PostTaskAndReplyWithResult(
+ database_task_runner_.get(), FROM_HERE,
base::Bind(&ServiceWorkerDatabase::GetRegistrationsForOrigin,
base::Unretained(database_.get()), origin, registrations,
resource_lists),
@@ -378,8 +362,8 @@ void ServiceWorkerStorage::GetAllRegistrationsInfos(
DCHECK_EQ(INITIALIZED, state_);
RegistrationList* registrations = new RegistrationList;
- PostTaskAndReplyWithResult(
- database_task_manager_->GetTaskRunner(), FROM_HERE,
+ base::PostTaskAndReplyWithResult(
+ database_task_runner_.get(), FROM_HERE,
base::Bind(&ServiceWorkerDatabase::GetAllRegistrations,
base::Unretained(database_.get()), registrations),
base::Bind(&ServiceWorkerStorage::DidGetAllRegistrationsInfos,
@@ -436,17 +420,12 @@ void ServiceWorkerStorage::StoreRegistration(
if (!has_checked_for_stale_resources_)
DeleteStaleResources();
- database_task_manager_->GetTaskRunner()->PostTask(
+ database_task_runner_->PostTask(
FROM_HERE,
- base::Bind(&WriteRegistrationInDB,
- database_.get(),
- base::ThreadTaskRunnerHandle::Get(),
- data,
- resources,
- base::Bind(&ServiceWorkerStorage::DidStoreRegistration,
- weak_factory_.GetWeakPtr(),
- callback,
- data)));
+ base::BindOnce(&WriteRegistrationInDB, database_.get(),
+ base::ThreadTaskRunnerHandle::Get(), data, resources,
+ base::Bind(&ServiceWorkerStorage::DidStoreRegistration,
+ weak_factory_.GetWeakPtr(), callback, data)));
registration->set_is_deleted(false);
}
@@ -462,16 +441,13 @@ void ServiceWorkerStorage::UpdateToActiveState(
return;
}
- PostTaskAndReplyWithResult(
- database_task_manager_->GetTaskRunner(),
- FROM_HERE,
+ base::PostTaskAndReplyWithResult(
+ database_task_runner_.get(), FROM_HERE,
base::Bind(&ServiceWorkerDatabase::UpdateVersionToActive,
- base::Unretained(database_.get()),
- registration->id(),
+ base::Unretained(database_.get()), registration->id(),
registration->pattern().GetOrigin()),
base::Bind(&ServiceWorkerStorage::DidUpdateToActiveState,
- weak_factory_.GetWeakPtr(),
- callback));
+ weak_factory_.GetWeakPtr(), callback));
}
void ServiceWorkerStorage::UpdateLastUpdateCheckTime(
@@ -481,12 +457,11 @@ void ServiceWorkerStorage::UpdateLastUpdateCheckTime(
if (IsDisabled())
return;
- database_task_manager_->GetTaskRunner()->PostTask(
+ database_task_runner_->PostTask(
FROM_HERE,
- base::Bind(
+ base::BindOnce(
base::IgnoreResult(&ServiceWorkerDatabase::UpdateLastCheckTime),
- base::Unretained(database_.get()),
- registration->id(),
+ base::Unretained(database_.get()), registration->id(),
registration->pattern().GetOrigin(),
registration->last_update_check()));
}
@@ -502,8 +477,8 @@ void ServiceWorkerStorage::UpdateNavigationPreloadEnabled(
return;
}
- PostTaskAndReplyWithResult(
- database_task_manager_->GetTaskRunner(), FROM_HERE,
+ base::PostTaskAndReplyWithResult(
+ database_task_runner_.get(), FROM_HERE,
base::Bind(&ServiceWorkerDatabase::UpdateNavigationPreloadEnabled,
base::Unretained(database_.get()), registration_id, origin,
enable),
@@ -521,8 +496,8 @@ void ServiceWorkerStorage::UpdateNavigationPreloadHeader(
return;
}
- PostTaskAndReplyWithResult(
- database_task_manager_->GetTaskRunner(), FROM_HERE,
+ base::PostTaskAndReplyWithResult(
+ database_task_runner_.get(), FROM_HERE,
base::Bind(&ServiceWorkerDatabase::UpdateNavigationPreloadHeader,
base::Unretained(database_.get()), registration_id, origin,
value),
@@ -546,16 +521,13 @@ void ServiceWorkerStorage::DeleteRegistration(int64_t registration_id,
params.origin = origin;
params.callback = callback;
- database_task_manager_->GetTaskRunner()->PostTask(
+ database_task_runner_->PostTask(
FROM_HERE,
- base::Bind(&DeleteRegistrationFromDB,
- database_.get(),
- base::ThreadTaskRunnerHandle::Get(),
- registration_id,
- origin,
- base::Bind(&ServiceWorkerStorage::DidDeleteRegistration,
- weak_factory_.GetWeakPtr(),
- params)));
+ base::BindOnce(&DeleteRegistrationFromDB, database_.get(),
+ base::ThreadTaskRunnerHandle::Get(), registration_id,
+ origin,
+ base::Bind(&ServiceWorkerStorage::DidDeleteRegistration,
+ weak_factory_.GetWeakPtr(), params)));
// The registration should no longer be findable.
pending_deletions_.insert(registration_id);
@@ -592,8 +564,8 @@ void ServiceWorkerStorage::StoreUncommittedResourceId(int64_t resource_id) {
if (!has_checked_for_stale_resources_)
DeleteStaleResources();
- PostTaskAndReplyWithResult(
- database_task_manager_->GetTaskRunner(), FROM_HERE,
+ base::PostTaskAndReplyWithResult(
+ database_task_runner_.get(), FROM_HERE,
base::Bind(&ServiceWorkerDatabase::WriteUncommittedResourceIds,
base::Unretained(database_.get()),
std::set<int64_t>(&resource_id, &resource_id + 1)),
@@ -615,8 +587,8 @@ void ServiceWorkerStorage::DoomUncommittedResources(
if (IsDisabled())
return;
- PostTaskAndReplyWithResult(
- database_task_manager_->GetTaskRunner(), FROM_HERE,
+ base::PostTaskAndReplyWithResult(
+ database_task_runner_.get(), FROM_HERE,
base::Bind(&ServiceWorkerDatabase::PurgeUncommittedResourceIds,
base::Unretained(database_.get()), resource_ids),
base::Bind(&ServiceWorkerStorage::DidPurgeUncommittedResourceIds,
@@ -649,8 +621,8 @@ void ServiceWorkerStorage::StoreUserData(
}
}
- PostTaskAndReplyWithResult(
- database_task_manager_->GetTaskRunner(), FROM_HERE,
+ base::PostTaskAndReplyWithResult(
+ database_task_runner_.get(), FROM_HERE,
base::Bind(&ServiceWorkerDatabase::WriteUserData,
base::Unretained(database_.get()), registration_id, origin,
key_value_pairs),
@@ -685,12 +657,12 @@ void ServiceWorkerStorage::GetUserData(int64_t registration_id,
}
}
- database_task_manager_->GetTaskRunner()->PostTask(
+ database_task_runner_->PostTask(
FROM_HERE,
- base::Bind(&ServiceWorkerStorage::GetUserDataInDB, database_.get(),
- base::ThreadTaskRunnerHandle::Get(), registration_id, keys,
- base::Bind(&ServiceWorkerStorage::DidGetUserData,
- weak_factory_.GetWeakPtr(), callback)));
+ base::BindOnce(&ServiceWorkerStorage::GetUserDataInDB, database_.get(),
+ base::ThreadTaskRunnerHandle::Get(), registration_id, keys,
+ base::Bind(&ServiceWorkerStorage::DidGetUserData,
+ weak_factory_.GetWeakPtr(), callback)));
}
void ServiceWorkerStorage::GetUserDataByKeyPrefix(
@@ -719,13 +691,13 @@ void ServiceWorkerStorage::GetUserDataByKeyPrefix(
return;
}
- database_task_manager_->GetTaskRunner()->PostTask(
+ database_task_runner_->PostTask(
FROM_HERE,
- base::Bind(&ServiceWorkerStorage::GetUserDataByKeyPrefixInDB,
- database_.get(), base::ThreadTaskRunnerHandle::Get(),
- registration_id, key_prefix,
- base::Bind(&ServiceWorkerStorage::DidGetUserData,
- weak_factory_.GetWeakPtr(), callback)));
+ base::BindOnce(&ServiceWorkerStorage::GetUserDataByKeyPrefixInDB,
+ database_.get(), base::ThreadTaskRunnerHandle::Get(),
+ registration_id, key_prefix,
+ base::Bind(&ServiceWorkerStorage::DidGetUserData,
+ weak_factory_.GetWeakPtr(), callback)));
}
void ServiceWorkerStorage::ClearUserData(int64_t registration_id,
@@ -756,8 +728,8 @@ void ServiceWorkerStorage::ClearUserData(int64_t registration_id,
}
}
- PostTaskAndReplyWithResult(
- database_task_manager_->GetTaskRunner(), FROM_HERE,
+ base::PostTaskAndReplyWithResult(
+ database_task_runner_.get(), FROM_HERE,
base::Bind(&ServiceWorkerDatabase::DeleteUserData,
base::Unretained(database_.get()), registration_id, keys),
base::Bind(&ServiceWorkerStorage::DidDeleteUserData,
@@ -788,16 +760,13 @@ void ServiceWorkerStorage::GetUserDataForAllRegistrations(
return;
}
- database_task_manager_->GetTaskRunner()->PostTask(
+ database_task_runner_->PostTask(
FROM_HERE,
- base::Bind(
+ base::BindOnce(
&ServiceWorkerStorage::GetUserDataForAllRegistrationsInDB,
- database_.get(),
- base::ThreadTaskRunnerHandle::Get(),
- key,
+ database_.get(), base::ThreadTaskRunnerHandle::Get(), key,
base::Bind(&ServiceWorkerStorage::DidGetUserDataForAllRegistrations,
- weak_factory_.GetWeakPtr(),
- callback)));
+ weak_factory_.GetWeakPtr(), callback)));
}
void ServiceWorkerStorage::GetUserDataForAllRegistrationsByKeyPrefix(
@@ -824,9 +793,9 @@ void ServiceWorkerStorage::GetUserDataForAllRegistrationsByKeyPrefix(
return;
}
- database_task_manager_->GetTaskRunner()->PostTask(
+ database_task_runner_->PostTask(
FROM_HERE,
- base::Bind(
+ base::BindOnce(
&ServiceWorkerStorage::GetUserDataForAllRegistrationsByKeyPrefixInDB,
database_.get(), base::ThreadTaskRunnerHandle::Get(), key_prefix,
base::Bind(&ServiceWorkerStorage::DidGetUserDataForAllRegistrations,
@@ -842,13 +811,27 @@ bool ServiceWorkerStorage::OriginHasForeignFetchRegistrations(
void ServiceWorkerStorage::DeleteAndStartOver(const StatusCallback& callback) {
Disable();
- // Delete the database on the database thread.
- PostTaskAndReplyWithResult(
- database_task_manager_->GetTaskRunner(), FROM_HERE,
- base::Bind(&ServiceWorkerDatabase::DestroyDatabase,
- base::Unretained(database_.get())),
- base::Bind(&ServiceWorkerStorage::DidDeleteDatabase,
- weak_factory_.GetWeakPtr(), callback));
+ // Will be used in DiskCacheImplDoneWithDisk()
+ delete_and_start_over_callback_ = callback;
+
+ // Won't get a callback about cleanup being done, so call it ourselves.
+ if (!expecting_done_with_disk_on_disable_)
+ DiskCacheImplDoneWithDisk();
+}
+
+void ServiceWorkerStorage::DiskCacheImplDoneWithDisk() {
+ expecting_done_with_disk_on_disable_ = false;
+ if (!delete_and_start_over_callback_.is_null()) {
+ StatusCallback callback;
+ swap(callback, delete_and_start_over_callback_);
+ // Delete the database on the database thread.
+ PostTaskAndReplyWithResult(
+ database_task_runner_.get(), FROM_HERE,
+ base::Bind(&ServiceWorkerDatabase::DestroyDatabase,
+ base::Unretained(database_.get())),
+ base::Bind(&ServiceWorkerStorage::DidDeleteDatabase,
+ weak_factory_.GetWeakPtr(), callback));
+ }
}
int64_t ServiceWorkerStorage::NewRegistrationId() {
@@ -922,18 +905,17 @@ void ServiceWorkerStorage::PurgeResources(const ResourceList& resources) {
ServiceWorkerStorage::ServiceWorkerStorage(
const base::FilePath& path,
base::WeakPtr<ServiceWorkerContextCore> context,
- std::unique_ptr<ServiceWorkerDatabaseTaskManager> database_task_manager,
- const scoped_refptr<base::SingleThreadTaskRunner>& disk_cache_thread,
+ scoped_refptr<base::SequencedTaskRunner> database_task_runner,
storage::QuotaManagerProxy* quota_manager_proxy,
storage::SpecialStoragePolicy* special_storage_policy)
: next_registration_id_(kInvalidServiceWorkerRegistrationId),
next_version_id_(kInvalidServiceWorkerVersionId),
next_resource_id_(kInvalidServiceWorkerResourceId),
state_(UNINITIALIZED),
+ expecting_done_with_disk_on_disable_(false),
path_(path),
context_(context),
- database_task_manager_(std::move(database_task_manager)),
- disk_cache_thread_(disk_cache_thread),
+ database_task_runner_(std::move(database_task_runner)),
quota_manager_proxy_(quota_manager_proxy),
special_storage_policy_(special_storage_policy),
is_purge_pending_(false),
@@ -972,13 +954,12 @@ bool ServiceWorkerStorage::LazyInitialize(const base::Closure& callback) {
}
state_ = INITIALIZING;
- database_task_manager_->GetTaskRunner()->PostTask(
+ database_task_runner_->PostTask(
FROM_HERE,
- base::Bind(&ReadInitialDataFromDB,
- database_.get(),
- base::ThreadTaskRunnerHandle::Get(),
- base::Bind(&ServiceWorkerStorage::DidReadInitialData,
- weak_factory_.GetWeakPtr())));
+ base::BindOnce(&ReadInitialDataFromDB, database_.get(),
+ base::ThreadTaskRunnerHandle::Get(),
+ base::Bind(&ServiceWorkerStorage::DidReadInitialData,
+ weak_factory_.GetWeakPtr())));
return false;
}
@@ -1468,8 +1449,11 @@ ServiceWorkerDiskCache* ServiceWorkerStorage::disk_cache() {
void ServiceWorkerStorage::InitializeDiskCache() {
disk_cache_->set_is_waiting_to_initialize(false);
+ expecting_done_with_disk_on_disable_ = true;
int rv = disk_cache_->InitWithDiskBackend(
- GetDiskCachePath(), kMaxDiskCacheSize, false, disk_cache_thread_,
+ GetDiskCachePath(), kMaxDiskCacheSize, false,
+ base::BindOnce(&ServiceWorkerStorage::DiskCacheImplDoneWithDisk,
+ weak_factory_.GetWeakPtr()),
base::Bind(&ServiceWorkerStorage::OnDiskCacheInitialized,
weak_factory_.GetWeakPtr()));
if (rv != net::ERR_IO_PENDING)
@@ -1538,11 +1522,12 @@ void ServiceWorkerStorage::OnResourcePurged(int64_t id, int rv) {
ServiceWorkerMetrics::RecordPurgeResourceResult(rv);
- database_task_manager_->GetTaskRunner()->PostTask(
+ std::set<int64_t> ids = {id};
+ database_task_runner_->PostTask(
FROM_HERE,
- base::Bind(
+ base::BindOnce(
base::IgnoreResult(&ServiceWorkerDatabase::ClearPurgeableResourceIds),
- base::Unretained(database_.get()), std::set<int64_t>(&id, &id + 1)));
+ base::Unretained(database_.get()), ids));
// Continue purging resources regardless of the previous result.
ContinuePurgingResources();
@@ -1551,13 +1536,12 @@ void ServiceWorkerStorage::OnResourcePurged(int64_t id, int rv) {
void ServiceWorkerStorage::DeleteStaleResources() {
DCHECK(!has_checked_for_stale_resources_);
has_checked_for_stale_resources_ = true;
- database_task_manager_->GetTaskRunner()->PostTask(
+ database_task_runner_->PostTask(
FROM_HERE,
- base::Bind(&ServiceWorkerStorage::CollectStaleResourcesFromDB,
- database_.get(),
- base::ThreadTaskRunnerHandle::Get(),
- base::Bind(&ServiceWorkerStorage::DidCollectStaleResources,
- weak_factory_.GetWeakPtr())));
+ base::BindOnce(&ServiceWorkerStorage::CollectStaleResourcesFromDB,
+ database_.get(), base::ThreadTaskRunnerHandle::Get(),
+ base::Bind(&ServiceWorkerStorage::DidCollectStaleResources,
+ weak_factory_.GetWeakPtr())));
}
void ServiceWorkerStorage::DidCollectStaleResources(
@@ -1585,13 +1569,12 @@ void ServiceWorkerStorage::ClearSessionOnlyOrigins() {
session_only_origins.insert(origin);
}
- database_task_manager_->GetShutdownBlockingTaskRunner()->PostTask(
- FROM_HERE,
- base::Bind(&DeleteAllDataForOriginsFromDB,
- database_.get(),
- session_only_origins));
+ database_task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&DeleteAllDataForOriginsFromDB, database_.get(),
+ session_only_origins));
}
+// static
void ServiceWorkerStorage::CollectStaleResourcesFromDB(
ServiceWorkerDatabase* database,
scoped_refptr<base::SequencedTaskRunner> original_task_runner,
@@ -1602,8 +1585,8 @@ void ServiceWorkerStorage::CollectStaleResourcesFromDB(
if (status != ServiceWorkerDatabase::STATUS_OK) {
original_task_runner->PostTask(
FROM_HERE,
- base::Bind(callback, std::vector<int64_t>(ids.begin(), ids.end()),
- status));
+ base::BindOnce(callback, std::vector<int64_t>(ids.begin(), ids.end()),
+ status));
return;
}
@@ -1611,8 +1594,8 @@ void ServiceWorkerStorage::CollectStaleResourcesFromDB(
if (status != ServiceWorkerDatabase::STATUS_OK) {
original_task_runner->PostTask(
FROM_HERE,
- base::Bind(callback, std::vector<int64_t>(ids.begin(), ids.end()),
- status));
+ base::BindOnce(callback, std::vector<int64_t>(ids.begin(), ids.end()),
+ status));
return;
}
@@ -1620,10 +1603,11 @@ void ServiceWorkerStorage::CollectStaleResourcesFromDB(
status = database->GetPurgeableResourceIds(&ids);
original_task_runner->PostTask(
FROM_HERE,
- base::Bind(callback, std::vector<int64_t>(ids.begin(), ids.end()),
- status));
+ base::BindOnce(callback, std::vector<int64_t>(ids.begin(), ids.end()),
+ status));
}
+// static
void ServiceWorkerStorage::ReadInitialDataFromDB(
ServiceWorkerDatabase* database,
scoped_refptr<base::SequencedTaskRunner> original_task_runner,
@@ -1638,21 +1622,24 @@ void ServiceWorkerStorage::ReadInitialDataFromDB(
&data->next_resource_id);
if (status != ServiceWorkerDatabase::STATUS_OK) {
original_task_runner->PostTask(
- FROM_HERE, base::Bind(callback, base::Passed(std::move(data)), status));
+ FROM_HERE,
+ base::BindOnce(callback, base::Passed(std::move(data)), status));
return;
}
status = database->GetOriginsWithRegistrations(&data->origins);
if (status != ServiceWorkerDatabase::STATUS_OK) {
original_task_runner->PostTask(
- FROM_HERE, base::Bind(callback, base::Passed(std::move(data)), status));
+ FROM_HERE,
+ base::BindOnce(callback, base::Passed(std::move(data)), status));
return;
}
status = database->GetOriginsWithForeignFetchRegistrations(
&data->foreign_fetch_origins);
original_task_runner->PostTask(
- FROM_HERE, base::Bind(callback, base::Passed(std::move(data)), status));
+ FROM_HERE,
+ base::BindOnce(callback, base::Passed(std::move(data)), status));
}
void ServiceWorkerStorage::DeleteRegistrationFromDB(
@@ -1669,8 +1656,9 @@ void ServiceWorkerStorage::DeleteRegistrationFromDB(
registration_id, origin, &deleted_version, &newly_purgeable_resources);
if (status != ServiceWorkerDatabase::STATUS_OK) {
original_task_runner->PostTask(
- FROM_HERE, base::Bind(callback, OriginState::KEEP_ALL, deleted_version,
- std::vector<int64_t>(), status));
+ FROM_HERE,
+ base::BindOnce(callback, OriginState::KEEP_ALL, deleted_version,
+ std::vector<int64_t>(), status));
return;
}
@@ -1680,8 +1668,9 @@ void ServiceWorkerStorage::DeleteRegistrationFromDB(
status = database->GetRegistrationsForOrigin(origin, &registrations, nullptr);
if (status != ServiceWorkerDatabase::STATUS_OK) {
original_task_runner->PostTask(
- FROM_HERE, base::Bind(callback, OriginState::KEEP_ALL, deleted_version,
- std::vector<int64_t>(), status));
+ FROM_HERE,
+ base::BindOnce(callback, OriginState::KEEP_ALL, deleted_version,
+ std::vector<int64_t>(), status));
return;
}
@@ -1698,8 +1687,8 @@ void ServiceWorkerStorage::DeleteRegistrationFromDB(
}
}
original_task_runner->PostTask(
- FROM_HERE, base::Bind(callback, origin_state, deleted_version,
- newly_purgeable_resources, status));
+ FROM_HERE, base::BindOnce(callback, origin_state, deleted_version,
+ newly_purgeable_resources, status));
}
void ServiceWorkerStorage::WriteRegistrationInDB(
@@ -1713,14 +1702,13 @@ void ServiceWorkerStorage::WriteRegistrationInDB(
std::vector<int64_t> newly_purgeable_resources;
ServiceWorkerDatabase::Status status = database->WriteRegistration(
data, resources, &deleted_version, &newly_purgeable_resources);
- original_task_runner->PostTask(FROM_HERE,
- base::Bind(callback,
- data.script.GetOrigin(),
- deleted_version,
- newly_purgeable_resources,
- status));
+ original_task_runner->PostTask(
+ FROM_HERE,
+ base::BindOnce(callback, data.script.GetOrigin(), deleted_version,
+ newly_purgeable_resources, status));
}
+// static
void ServiceWorkerStorage::FindForDocumentInDB(
ServiceWorkerDatabase* database,
scoped_refptr<base::SequencedTaskRunner> original_task_runner,
@@ -1733,10 +1721,8 @@ void ServiceWorkerStorage::FindForDocumentInDB(
if (status != ServiceWorkerDatabase::STATUS_OK) {
original_task_runner->PostTask(
FROM_HERE,
- base::Bind(callback,
- ServiceWorkerDatabase::RegistrationData(),
- ResourceList(),
- status));
+ base::BindOnce(callback, ServiceWorkerDatabase::RegistrationData(),
+ ResourceList(), status));
return;
}
@@ -1754,10 +1740,10 @@ void ServiceWorkerStorage::FindForDocumentInDB(
status = database->ReadRegistration(match, origin, &data, &resources);
original_task_runner->PostTask(
- FROM_HERE,
- base::Bind(callback, data, resources, status));
+ FROM_HERE, base::BindOnce(callback, data, resources, status));
}
+// static
void ServiceWorkerStorage::FindForPatternInDB(
ServiceWorkerDatabase* database,
scoped_refptr<base::SequencedTaskRunner> original_task_runner,
@@ -1770,10 +1756,8 @@ void ServiceWorkerStorage::FindForPatternInDB(
if (status != ServiceWorkerDatabase::STATUS_OK) {
original_task_runner->PostTask(
FROM_HERE,
- base::Bind(callback,
- ServiceWorkerDatabase::RegistrationData(),
- ResourceList(),
- status));
+ base::BindOnce(callback, ServiceWorkerDatabase::RegistrationData(),
+ ResourceList(), status));
return;
}
@@ -1790,10 +1774,10 @@ void ServiceWorkerStorage::FindForPatternInDB(
}
original_task_runner->PostTask(
- FROM_HERE,
- base::Bind(callback, data, resources, status));
+ FROM_HERE, base::BindOnce(callback, data, resources, status));
}
+// static
void ServiceWorkerStorage::FindForIdInDB(
ServiceWorkerDatabase* database,
scoped_refptr<base::SequencedTaskRunner> original_task_runner,
@@ -1805,9 +1789,10 @@ void ServiceWorkerStorage::FindForIdInDB(
ServiceWorkerDatabase::Status status =
database->ReadRegistration(registration_id, origin, &data, &resources);
original_task_runner->PostTask(
- FROM_HERE, base::Bind(callback, data, resources, status));
+ FROM_HERE, base::BindOnce(callback, data, resources, status));
}
+// static
void ServiceWorkerStorage::FindForIdOnlyInDB(
ServiceWorkerDatabase* database,
scoped_refptr<base::SequencedTaskRunner> original_task_runner,
@@ -1819,8 +1804,8 @@ void ServiceWorkerStorage::FindForIdOnlyInDB(
if (status != ServiceWorkerDatabase::STATUS_OK) {
original_task_runner->PostTask(
FROM_HERE,
- base::Bind(callback, ServiceWorkerDatabase::RegistrationData(),
- ResourceList(), status));
+ base::BindOnce(callback, ServiceWorkerDatabase::RegistrationData(),
+ ResourceList(), status));
return;
}
FindForIdInDB(database, original_task_runner, registration_id, origin,
@@ -1837,7 +1822,7 @@ void ServiceWorkerStorage::GetUserDataInDB(
ServiceWorkerDatabase::Status status =
database->ReadUserData(registration_id, keys, &values);
original_task_runner->PostTask(FROM_HERE,
- base::Bind(callback, values, status));
+ base::BindOnce(callback, values, status));
}
void ServiceWorkerStorage::GetUserDataByKeyPrefixInDB(
@@ -1850,7 +1835,7 @@ void ServiceWorkerStorage::GetUserDataByKeyPrefixInDB(
ServiceWorkerDatabase::Status status =
database->ReadUserDataByKeyPrefix(registration_id, key_prefix, &values);
original_task_runner->PostTask(FROM_HERE,
- base::Bind(callback, values, status));
+ base::BindOnce(callback, values, status));
}
void ServiceWorkerStorage::GetUserDataForAllRegistrationsInDB(
@@ -1862,7 +1847,7 @@ void ServiceWorkerStorage::GetUserDataForAllRegistrationsInDB(
ServiceWorkerDatabase::Status status =
database->ReadUserDataForAllRegistrations(key, &user_data);
original_task_runner->PostTask(FROM_HERE,
- base::Bind(callback, user_data, status));
+ base::BindOnce(callback, user_data, status));
}
void ServiceWorkerStorage::GetUserDataForAllRegistrationsByKeyPrefixInDB(
@@ -1875,7 +1860,7 @@ void ServiceWorkerStorage::GetUserDataForAllRegistrationsByKeyPrefixInDB(
database->ReadUserDataForAllRegistrationsByKeyPrefix(key_prefix,
&user_data);
original_task_runner->PostTask(FROM_HERE,
- base::Bind(callback, user_data, status));
+ base::BindOnce(callback, user_data, status));
}
void ServiceWorkerStorage::DeleteAllDataForOriginsFromDB(
@@ -1923,12 +1908,18 @@ void ServiceWorkerStorage::DidDeleteDatabase(
}
DVLOG(1) << "Deleted ServiceWorkerDatabase successfully.";
- // Delete the disk cache on the cache thread.
+ // Delete the disk cache. Use BLOCK_SHUTDOWN to try to avoid things being
+ // half-deleted.
+ // TODO(falken): Investigate if BLOCK_SHUTDOWN is needed, as the next startup
+ // is expected to cleanup the disk cache anyway. Also investigate whether
+ // ClearSessionOnlyOrigins() should try to delete relevant entries from the
+ // disk cache before shutdown.
+
// TODO(nhiroki): What if there is a bunch of files in the cache directory?
// Deleting the directory could take a long time and restart could be delayed.
// We should probably rename the directory and delete it later.
- PostTaskAndReplyWithResult(
- disk_cache_thread_.get(), FROM_HERE,
+ PostTaskWithTraitsAndReplyWithResult(
+ FROM_HERE, {base::MayBlock(), base::TaskShutdownBehavior::BLOCK_SHUTDOWN},
base::Bind(&base::DeleteFile, GetDiskCachePath(), true),
base::Bind(&ServiceWorkerStorage::DidDeleteDiskCache,
weak_factory_.GetWeakPtr(), callback));
diff --git a/chromium/content/browser/service_worker/service_worker_storage.h b/chromium/content/browser/service_worker/service_worker_storage.h
index 77b04af870e..3c526937a1e 100644
--- a/chromium/content/browser/service_worker/service_worker_storage.h
+++ b/chromium/content/browser/service_worker/service_worker_storage.h
@@ -20,7 +20,6 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "content/browser/service_worker/service_worker_database.h"
-#include "content/browser/service_worker/service_worker_database_task_manager.h"
#include "content/browser/service_worker/service_worker_metrics.h"
#include "content/browser/service_worker/service_worker_version.h"
#include "content/common/content_export.h"
@@ -29,7 +28,6 @@
namespace base {
class SequencedTaskRunner;
-class SingleThreadTaskRunner;
}
namespace storage {
@@ -53,7 +51,7 @@ struct ServiceWorkerRegistrationInfo;
// disabled and all subsequent requests are aborted until the context core is
// restarted.
class CONTENT_EXPORT ServiceWorkerStorage
- : NON_EXPORTED_BASE(public ServiceWorkerVersion::Listener) {
+ : public ServiceWorkerVersion::Listener {
public:
typedef std::vector<ServiceWorkerDatabase::ResourceRecord> ResourceList;
typedef base::Callback<void(ServiceWorkerStatusCode status)> StatusCallback;
@@ -82,8 +80,7 @@ class CONTENT_EXPORT ServiceWorkerStorage
static std::unique_ptr<ServiceWorkerStorage> Create(
const base::FilePath& path,
const base::WeakPtr<ServiceWorkerContextCore>& context,
- std::unique_ptr<ServiceWorkerDatabaseTaskManager> database_task_manager,
- const scoped_refptr<base::SingleThreadTaskRunner>& disk_cache_thread,
+ scoped_refptr<base::SequencedTaskRunner> database_task_runner,
storage::QuotaManagerProxy* quota_manager_proxy,
storage::SpecialStoragePolicy* special_storage_policy);
@@ -260,6 +257,8 @@ class CONTENT_EXPORT ServiceWorkerStorage
friend class ServiceWorkerContextRequestHandlerTest;
friend class ServiceWorkerReadFromCacheJobTest;
friend class ServiceWorkerRequestHandlerTest;
+ friend class ServiceWorkerInstalledScriptsSenderTest;
+ friend class ServiceWorkerURLLoaderJobTest;
friend class ServiceWorkerURLRequestJobTest;
friend class ServiceWorkerVersionBrowserTest;
friend class ServiceWorkerVersionTest;
@@ -353,8 +352,7 @@ class CONTENT_EXPORT ServiceWorkerStorage
ServiceWorkerStorage(
const base::FilePath& path,
base::WeakPtr<ServiceWorkerContextCore> context,
- std::unique_ptr<ServiceWorkerDatabaseTaskManager> database_task_manager,
- const scoped_refptr<base::SingleThreadTaskRunner>& disk_cache_thread,
+ scoped_refptr<base::SequencedTaskRunner> database_task_runner,
storage::QuotaManagerProxy* quota_manager_proxy,
storage::SpecialStoragePolicy* special_storage_policy);
@@ -530,9 +528,13 @@ class CONTENT_EXPORT ServiceWorkerStorage
bool IsDisabled() const;
void ScheduleDeleteAndStartOver();
- void DidDeleteDatabase(
- const StatusCallback& callback,
- ServiceWorkerDatabase::Status status);
+
+ // Posted by the underlying cache implementation after it finishes making
+ // disk changes upon its destruction.
+ void DiskCacheImplDoneWithDisk();
+ void DidDeleteDatabase(const StatusCallback& callback,
+ ServiceWorkerDatabase::Status status);
+ // Posted when we finish deleting the cache directory.
void DidDeleteDiskCache(
const StatusCallback& callback,
bool result);
@@ -560,16 +562,28 @@ class CONTENT_EXPORT ServiceWorkerStorage
};
State state_;
+ // non-null between when DeleteAndStartOver() is called and when the
+ // underlying disk cache stops using the disk.
+ StatusCallback delete_and_start_over_callback_;
+
+ // This is set when we know that a call to Disable() will result in
+ // DiskCacheImplDoneWithDisk() eventually called. This might not happen
+ // for many reasons:
+ // 1) A previous call to Disable() may have already triggered that.
+ // 2) We may be using a memory backend.
+ // 3) |disk_cache_| might not have been created yet.
+ // ... so it's easier to keep track of the case when it will happen.
+ bool expecting_done_with_disk_on_disable_;
+
base::FilePath path_;
// The context should be valid while the storage is alive.
base::WeakPtr<ServiceWorkerContextCore> context_;
- // Only accessed using |database_task_manager_|.
+ // |database_| is only accessed using |database_task_runner_|.
std::unique_ptr<ServiceWorkerDatabase> database_;
+ scoped_refptr<base::SequencedTaskRunner> database_task_runner_;
- std::unique_ptr<ServiceWorkerDatabaseTaskManager> database_task_manager_;
- scoped_refptr<base::SingleThreadTaskRunner> disk_cache_thread_;
scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy_;
scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy_;
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 0fd82a15e69..e0c29fb598c 100644
--- a/chromium/content/browser/service_worker/service_worker_storage_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_storage_unittest.cc
@@ -27,10 +27,12 @@
#include "content/public/common/content_client.h"
#include "content/public/common/origin_trial_policy.h"
#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/test_utils.h"
#include "ipc/ipc_message.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/base/test_completion_callback.h"
+#include "net/disk_cache/disk_cache.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_util.h"
#include "net/test/cert_test_util.h"
@@ -311,7 +313,8 @@ class ServiceWorkerStorageTest : public testing::Test {
void TearDown() override {
helper_.reset();
- base::RunLoop().RunUntilIdle();
+ disk_cache::FlushCacheThreadForTesting();
+ content::RunAllBlockingPoolTasksUntilIdle();
}
bool InitUserDataDirectory() {
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 4c8f7390b91..6d41dad444c 100644
--- a/chromium/content/browser/service_worker/service_worker_test_utils.cc
+++ b/chromium/content/browser/service_worker/service_worker_test_utils.cc
@@ -6,7 +6,10 @@
#include <utility>
+#include "content/browser/service_worker/service_worker_dispatcher_host.h"
#include "content/browser/service_worker/service_worker_provider_host.h"
+#include "content/common/service_worker/service_worker_provider.mojom.h"
+#include "content/public/common/child_process_host.h"
namespace content {
@@ -20,12 +23,18 @@ ServiceWorkerRemoteProviderEndpoint::~ServiceWorkerRemoteProviderEndpoint() {}
void ServiceWorkerRemoteProviderEndpoint::BindWithProviderHostInfo(
content::ServiceWorkerProviderHostInfo* info) {
- mojom::ServiceWorkerProviderAssociatedPtr client_ptr;
+ mojom::ServiceWorkerContainerAssociatedPtr client_ptr;
client_request_ = mojo::MakeIsolatedRequest(&client_ptr);
info->client_ptr_info = client_ptr.PassInterface();
info->host_request = mojo::MakeIsolatedRequest(&host_ptr_);
}
+void ServiceWorkerRemoteProviderEndpoint::BindWithProviderInfo(
+ mojom::ServiceWorkerProviderInfoForStartWorkerPtr info) {
+ client_request_ = std::move(info->client_request);
+ host_ptr_.Bind(std::move(info->host_ptr_info));
+}
+
std::unique_ptr<ServiceWorkerProviderHost> CreateProviderHostForWindow(
int process_id,
int provider_id,
@@ -43,16 +52,19 @@ std::unique_ptr<ServiceWorkerProviderHost> CreateProviderHostForWindow(
std::unique_ptr<ServiceWorkerProviderHost>
CreateProviderHostForServiceWorkerContext(
int process_id,
- int provider_id,
bool is_parent_frame_secure,
+ ServiceWorkerVersion* hosted_version,
base::WeakPtr<ServiceWorkerContextCore> context,
ServiceWorkerRemoteProviderEndpoint* output_endpoint) {
- ServiceWorkerProviderHostInfo info(provider_id, MSG_ROUTING_NONE,
- SERVICE_WORKER_PROVIDER_FOR_CONTROLLER,
- is_parent_frame_secure);
- output_endpoint->BindWithProviderHostInfo(&info);
- return ServiceWorkerProviderHost::Create(process_id, std::move(info),
- std::move(context), nullptr);
+ ServiceWorkerProviderHostInfo info(
+ kInvalidServiceWorkerProviderId, MSG_ROUTING_NONE,
+ SERVICE_WORKER_PROVIDER_FOR_CONTROLLER, is_parent_frame_secure);
+ std::unique_ptr<ServiceWorkerProviderHost> host =
+ ServiceWorkerProviderHost::PreCreateForController(std::move(context));
+ mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info =
+ host->CompleteStartWorkerPreparation(process_id, hosted_version);
+ output_endpoint->BindWithProviderInfo(std::move(provider_info));
+ return host;
}
std::unique_ptr<ServiceWorkerProviderHost> CreateProviderHostWithDispatcherHost(
@@ -66,7 +78,8 @@ std::unique_ptr<ServiceWorkerProviderHost> CreateProviderHostWithDispatcherHost(
SERVICE_WORKER_PROVIDER_FOR_WINDOW, true);
output_endpoint->BindWithProviderHostInfo(&info);
return ServiceWorkerProviderHost::Create(process_id, std::move(info),
- std::move(context), dispatcher_host);
+ std::move(context),
+ dispatcher_host->AsWeakPtr());
}
} // 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 2c9a08681db..1f01c945a4a 100644
--- a/chromium/content/browser/service_worker/service_worker_test_utils.h
+++ b/chromium/content/browser/service_worker/service_worker_test_utils.h
@@ -11,7 +11,7 @@
#include "base/callback.h"
#include "base/command_line.h"
#include "base/memory/weak_ptr.h"
-#include "content/common/service_worker/service_worker_provider_interfaces.mojom.h"
+#include "content/common/service_worker/service_worker_provider.mojom.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_switches.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -21,6 +21,7 @@ namespace content {
class ServiceWorkerContextCore;
class ServiceWorkerDispatcherHost;
class ServiceWorkerProviderHost;
+class ServiceWorkerVersion;
struct ServiceWorkerProviderHostInfo;
template <typename Arg>
@@ -58,22 +59,24 @@ class ServiceWorkerRemoteProviderEndpoint {
~ServiceWorkerRemoteProviderEndpoint();
void BindWithProviderHostInfo(ServiceWorkerProviderHostInfo* info);
+ void BindWithProviderInfo(
+ mojom::ServiceWorkerProviderInfoForStartWorkerPtr info);
- mojom::ServiceWorkerProviderHostAssociatedPtr* host_ptr() {
+ mojom::ServiceWorkerContainerHostAssociatedPtr* host_ptr() {
return &host_ptr_;
}
- mojom::ServiceWorkerProviderAssociatedRequest* client_request() {
+ mojom::ServiceWorkerContainerAssociatedRequest* client_request() {
return &client_request_;
}
private:
// Bound with content::ServiceWorkerProviderHost. The provider host will be
// removed asynchronously when this pointer is closed.
- mojom::ServiceWorkerProviderHostAssociatedPtr host_ptr_;
- // This is the other end of ServiceWorkerProviderAssociatedPtr owned by
+ mojom::ServiceWorkerContainerHostAssociatedPtr host_ptr_;
+ // This is the other end of ServiceWorkerContainerAssociatedPtr owned by
// content::ServiceWorkerProviderHost.
- mojom::ServiceWorkerProviderAssociatedRequest client_request_;
+ mojom::ServiceWorkerContainerAssociatedRequest client_request_;
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerRemoteProviderEndpoint);
};
@@ -88,8 +91,8 @@ std::unique_ptr<ServiceWorkerProviderHost> CreateProviderHostForWindow(
std::unique_ptr<ServiceWorkerProviderHost>
CreateProviderHostForServiceWorkerContext(
int process_id,
- int provider_id,
bool is_parent_frame_secure,
+ ServiceWorkerVersion* hosted_version,
base::WeakPtr<ServiceWorkerContextCore> context,
ServiceWorkerRemoteProviderEndpoint* output_endpoint);
diff --git a/chromium/content/browser/service_worker/service_worker_url_loader_job.cc b/chromium/content/browser/service_worker/service_worker_url_loader_job.cc
index 7e10fab80e7..020ca4a32b1 100644
--- a/chromium/content/browser/service_worker/service_worker_url_loader_job.cc
+++ b/chromium/content/browser/service_worker/service_worker_url_loader_job.cc
@@ -31,7 +31,6 @@ ServiceWorkerURLLoaderJob::ServiceWorkerURLLoaderJob(
blob_client_binding_(this),
binding_(this),
weak_factory_(this) {
- DCHECK(ServiceWorkerUtils::IsServicificationEnabled());
}
ServiceWorkerURLLoaderJob::~ServiceWorkerURLLoaderJob() {}
@@ -213,6 +212,7 @@ void ServiceWorkerURLLoaderJob::DidDispatchFetchEvent(
ServiceWorkerFetchEventResult fetch_result,
const ServiceWorkerResponse& response,
blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
+ storage::mojom::BlobPtr body_as_blob,
const scoped_refptr<ServiceWorkerVersion>& version) {
if (!did_navigation_preload_)
fetch_dispatcher_.reset();
@@ -251,51 +251,64 @@ void ServiceWorkerURLLoaderJob::DidDispatchFetchEvent(
// ServiceWorker, we have to check the security level of the responses.
const net::HttpResponseInfo* main_script_http_info =
version->GetMainScriptHttpResponseInfo();
- DCHECK(main_script_http_info);
- ssl_info_ = main_script_http_info->ssl_info;
+ // TODO(kinuko)
+ // Fix this here.
+ if (main_script_http_info)
+ ssl_info_ = main_script_http_info->ssl_info;
std::move(loader_callback_)
- .Run(base::Bind(&ServiceWorkerURLLoaderJob::StartResponse,
- weak_factory_.GetWeakPtr(), response,
- base::Passed(std::move(body_as_stream))));
+ .Run(base::BindOnce(&ServiceWorkerURLLoaderJob::StartResponse,
+ weak_factory_.GetWeakPtr(), response,
+ std::move(body_as_stream), std::move(body_as_blob)));
}
void ServiceWorkerURLLoaderJob::StartResponse(
const ServiceWorkerResponse& response,
blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
+ storage::mojom::BlobPtr body_as_blob,
mojom::URLLoaderRequest request,
mojom::URLLoaderClientPtr client) {
DCHECK(!binding_.is_bound());
binding_.Bind(std::move(request));
- binding_.set_connection_error_handler(
- base::Bind(&ServiceWorkerURLLoaderJob::Cancel, base::Unretained(this)));
+ binding_.set_connection_error_handler(base::BindOnce(
+ &ServiceWorkerURLLoaderJob::Cancel, base::Unretained(this)));
url_loader_client_ = std::move(client);
SaveResponseInfo(response);
SaveResponseHeaders(response.status_code, response.status_text,
response.headers);
- // Ideally, we would always get a data pipe fom SWFetchDispatcher and use
- // this case. See:
- // https://docs.google.com/a/google.com/document/d/1_ROmusFvd8ATwIZa29-P6Ls5yyLjfld0KvKchVfA84Y/edit?usp=drive_web
+ // Handle a stream response body.
if (!body_as_stream.is_null() && body_as_stream->stream.is_valid()) {
CommitResponseHeaders();
url_loader_client_->OnStartLoadingResponseBody(
std::move(body_as_stream->stream));
+ // TODO(falken): Call CommitCompleted() when stream finished.
+ // See https://crbug.com/758455
CommitCompleted(net::OK);
return;
}
+ // Handle a blob response body. Ideally we'd just get a data pipe from
+ // SWFetchDispatcher, and this could be treated the same as a stream response.
+ // |body_as_blob| must be kept around until here to ensure the blob is alive.
+ // See:
+ // https://docs.google.com/a/google.com/document/d/1_ROmusFvd8ATwIZa29-P6Ls5yyLjfld0KvKchVfA84Y/edit?usp=drive_web
if (!response.blob_uuid.empty() && blob_storage_context_) {
std::unique_ptr<storage::BlobDataHandle> blob_data_handle =
blob_storage_context_->GetBlobDataFromUUID(response.blob_uuid);
- mojom::URLLoaderAssociatedRequest request;
+ mojom::URLLoaderRequest request;
mojom::URLLoaderClientPtr client;
blob_client_binding_.Bind(mojo::MakeRequest(&client));
BlobURLLoaderFactory::CreateLoaderAndStart(
std::move(request), resource_request_, std::move(client),
std::move(blob_data_handle), nullptr /* file_system_context */);
+ return;
}
+
+ // The response has no body.
+ CommitResponseHeaders();
+ CommitCompleted(net::OK);
}
// URLLoader implementation----------------------------------------
diff --git a/chromium/content/browser/service_worker/service_worker_url_loader_job.h b/chromium/content/browser/service_worker/service_worker_url_loader_job.h
index ce479ea7a2b..1d292a04211 100644
--- a/chromium/content/browser/service_worker/service_worker_url_loader_job.h
+++ b/chromium/content/browser/service_worker/service_worker_url_loader_job.h
@@ -38,8 +38,8 @@ class ServiceWorkerVersion;
// --enable-network-service and PlzNavigate is enabled.
// This also works as a URLLoaderClient for BlobURLLoader while reading
// the blob content returned by SW.
-class ServiceWorkerURLLoaderJob : public mojom::URLLoader,
- public mojom::URLLoaderClient {
+class CONTENT_EXPORT ServiceWorkerURLLoaderJob : public mojom::URLLoader,
+ public mojom::URLLoaderClient {
public:
using Delegate = ServiceWorkerURLJobWrapper::Delegate;
@@ -97,10 +97,14 @@ class ServiceWorkerURLLoaderJob : public mojom::URLLoader,
ServiceWorkerFetchEventResult fetch_result,
const ServiceWorkerResponse& response,
blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
+ storage::mojom::BlobPtr body_as_blob,
const scoped_refptr<ServiceWorkerVersion>& version);
+ // |body_as_blob| is kept around until BlobDataHandle is created from
+ // blob_uuid just to make sure the blob is kept alive.
void StartResponse(const ServiceWorkerResponse& response,
blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
+ storage::mojom::BlobPtr body_as_blob,
mojom::URLLoaderRequest request,
mojom::URLLoaderClientPtr client);
void AfterRead(scoped_refptr<net::IOBuffer> buffer, int bytes);
diff --git a/chromium/content/browser/service_worker/service_worker_url_loader_job_unittest.cc b/chromium/content/browser/service_worker/service_worker_url_loader_job_unittest.cc
new file mode 100644
index 00000000000..977bfe8df3e
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_url_loader_job_unittest.cc
@@ -0,0 +1,553 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/service_worker/service_worker_url_loader_job.h"
+
+#include "base/run_loop.h"
+#include "content/browser/loader/url_loader_request_handler.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_registration.h"
+#include "content/browser/service_worker/service_worker_version.h"
+#include "content/public/common/resource_response.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/test_url_loader_client.h"
+#include "mojo/common/data_pipe_utils.h"
+#include "net/ssl/ssl_info.h"
+#include "net/test/cert_test_util.h"
+#include "net/test/test_data_directory.h"
+#include "services/network/public/interfaces/fetch_api.mojom.h"
+#include "storage/browser/blob/blob_data_builder.h"
+#include "storage/browser/blob/blob_storage_context.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+namespace {
+
+void ReceiveStartLoaderCallback(StartLoaderCallback* out_callback,
+ StartLoaderCallback callback) {
+ *out_callback = std::move(callback);
+}
+
+} // namespace
+
+// Helper simulates a service worker handling fetch events. The response can be
+// customized via RespondWith* functions.
+class Helper : public EmbeddedWorkerTestHelper {
+ public:
+ Helper() : EmbeddedWorkerTestHelper(base::FilePath()) {}
+ ~Helper() override = default;
+
+ // Tells this helper to respond to fetch events with the specified blob.
+ void RespondWithBlob(const std::string blob_uuid, uint64_t blob_size) {
+ response_mode_ = ResponseMode::kBlob;
+ blob_uuid_ = blob_uuid;
+ blob_size_ = blob_size;
+ }
+
+ // Tells this helper to respond to fetch events with the specified stream.
+ void RespondWithStream(
+ blink::mojom::ServiceWorkerStreamCallbackRequest callback_request,
+ mojo::ScopedDataPipeConsumerHandle consumer_handle) {
+ response_mode_ = ResponseMode::kStream;
+ stream_handle_ = blink::mojom::ServiceWorkerStreamHandle::New();
+ stream_handle_->callback_request = std::move(callback_request);
+ stream_handle_->stream = std::move(consumer_handle);
+ }
+
+ // Tells this helper to respond to fetch events with network fallback.
+ // i.e.,simulate the service worker not calling respondWith().
+ void RespondWithFallback() {
+ response_mode_ = ResponseMode::kFallbackResponse;
+ }
+
+ // Tells this helper to simulate failure to dispatch the fetch event to the
+ // service worker.
+ void FailToDispatchFetchEvent() {
+ response_mode_ = ResponseMode::kFailFetchEventDispatch;
+ }
+
+ // Tells this helper to simulate "early response", where the respondWith()
+ // promise resolves before the waitUntil() promise. In this mode, the
+ // helper sets the response mode to "early response", which simulates the
+ // promise passed to respondWith() resolving before the waitUntil() promise
+ // resolves. In this mode, the helper will respond to fetch events
+ // immediately, but will not finish the fetch event until FinishWaitUntil() is
+ // called.
+ void RespondEarly() { response_mode_ = ResponseMode::kEarlyResponse; }
+ void FinishWaitUntil() {
+ std::move(finish_callback_).Run(SERVICE_WORKER_OK, base::Time::Now());
+ base::RunLoop().RunUntilIdle();
+ }
+
+ protected:
+ void OnFetchEvent(
+ int embedded_worker_id,
+ int fetch_event_id,
+ const ServiceWorkerFetchRequest& request,
+ mojom::FetchEventPreloadHandlePtr preload_handle,
+ mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
+ FetchCallback finish_callback) override {
+ switch (response_mode_) {
+ case ResponseMode::kDefault:
+ EmbeddedWorkerTestHelper::OnFetchEvent(
+ embedded_worker_id, fetch_event_id, request,
+ std::move(preload_handle), std::move(response_callback),
+ std::move(finish_callback));
+ return;
+ case ResponseMode::kBlob:
+ response_callback->OnResponse(
+ ServiceWorkerResponse(
+ base::MakeUnique<std::vector<GURL>>(), 200, "OK",
+ network::mojom::FetchResponseType::kDefault,
+ base::MakeUnique<ServiceWorkerHeaderMap>(), blob_uuid_,
+ blob_size_, nullptr /* blob */,
+ blink::kWebServiceWorkerResponseErrorUnknown, base::Time(),
+ false /* response_is_in_cache_storage */,
+ std::string() /* response_cache_storage_cache_name */,
+ base::MakeUnique<
+ ServiceWorkerHeaderList>() /* cors_exposed_header_names */),
+ base::Time::Now());
+ std::move(finish_callback).Run(SERVICE_WORKER_OK, base::Time::Now());
+ return;
+ case ResponseMode::kStream:
+ response_callback->OnResponseStream(
+ ServiceWorkerResponse(
+ base::MakeUnique<std::vector<GURL>>(), 200, "OK",
+ network::mojom::FetchResponseType::kDefault,
+ base::MakeUnique<ServiceWorkerHeaderMap>(), "" /* blob_uuid */,
+ 0 /* blob_size */, nullptr /* blob */,
+ blink::kWebServiceWorkerResponseErrorUnknown, base::Time(),
+ false /* response_is_in_cache_storage */,
+ std::string() /* response_cache_storage_cache_name */,
+ base::MakeUnique<
+ ServiceWorkerHeaderList>() /* cors_exposed_header_names */),
+ std::move(stream_handle_), base::Time::Now());
+ std::move(finish_callback).Run(SERVICE_WORKER_OK, base::Time::Now());
+ return;
+ case ResponseMode::kFallbackResponse:
+ response_callback->OnFallback(base::Time::Now());
+ std::move(finish_callback).Run(SERVICE_WORKER_OK, base::Time::Now());
+ return;
+ case ResponseMode::kFailFetchEventDispatch:
+ // Simulate failure by stopping the worker before the event finishes.
+ // This causes ServiceWorkerVersion::StartRequest() to call its error
+ // callback, which triggers ServiceWorkerURLLoaderJob's dispatch failed
+ // behavior.
+ SimulateWorkerStopped(embedded_worker_id);
+ // Finish the event by calling |finish_callback|.
+ // This is the Mojo callback for
+ // mojom::ServiceWorkerEventDispatcher::DispatchFetchEvent().
+ // If this is not called, Mojo will complain. In production code,
+ // ServiceWorkerContextClient would call this when it aborts all
+ // callbacks after an unexpected stop.
+ std::move(finish_callback)
+ .Run(SERVICE_WORKER_ERROR_ABORT, base::Time::Now());
+ return;
+ case ResponseMode::kEarlyResponse:
+ finish_callback_ = std::move(finish_callback);
+ response_callback->OnResponse(
+ ServiceWorkerResponse(
+ base::MakeUnique<std::vector<GURL>>(), 200, "OK",
+ network::mojom::FetchResponseType::kDefault,
+ base::MakeUnique<ServiceWorkerHeaderMap>(), "" /* blob_uuid */,
+ 0 /* blob_size */, nullptr /* blob */,
+ blink::kWebServiceWorkerResponseErrorUnknown, base::Time(),
+ false /* response_is_in_cache_storage */,
+ std::string() /* response_cache_storage_cache_name */,
+ base::MakeUnique<
+ ServiceWorkerHeaderList>() /* cors_exposed_header_names */),
+ base::Time::Now());
+ // Now the caller must call FinishWaitUntil() to finish the event.
+ return;
+ }
+ NOTREACHED();
+ }
+
+ private:
+ enum class ResponseMode {
+ kDefault,
+ kBlob,
+ kStream,
+ kFallbackResponse,
+ kFailFetchEventDispatch,
+ kEarlyResponse
+ };
+
+ ResponseMode response_mode_ = ResponseMode::kDefault;
+
+ // For ResponseMode::kBlob.
+ std::string blob_uuid_;
+ uint64_t blob_size_ = 0;
+
+ // For ResponseMode::kStream.
+ blink::mojom::ServiceWorkerStreamHandlePtr stream_handle_;
+
+ // For ResponseMode::kEarlyResponse.
+ FetchCallback finish_callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(Helper);
+};
+
+// ServiceWorkerURLLoaderJobTest is for testing the handling of requests
+// by a service worker via ServiceWorkerURLLoaderJob.
+//
+// Of course, no actual service worker runs in the unit test, it is simulated
+// via EmbeddedWorkerTestHelper receiving IPC messages from the browser and
+// responding as if a service worker is running in the renderer.
+//
+// ServiceWorkerURLLoaderJobTest is also a ServiceWorkerURLLoaderJob::Delegate.
+// In production code, ServiceWorkerControlleeRequestHandler is the Delegate
+// (for non-"foreign fetch" request interceptions). So this class also basically
+// mocks that part of ServiceWorkerControlleeRequestHandler.
+class ServiceWorkerURLLoaderJobTest
+ : public testing::Test,
+ public ServiceWorkerURLLoaderJob::Delegate {
+ public:
+ ServiceWorkerURLLoaderJobTest()
+ : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP),
+ helper_(base::MakeUnique<Helper>()) {}
+ ~ServiceWorkerURLLoaderJobTest() override = default;
+
+ void SetUp() override {
+ // Create an active service worker.
+ storage()->LazyInitialize(base::Bind(&base::DoNothing));
+ base::RunLoop().RunUntilIdle();
+ registration_ = new ServiceWorkerRegistration(
+ ServiceWorkerRegistrationOptions(GURL("https://example.com/")),
+ storage()->NewRegistrationId(), helper_->context()->AsWeakPtr());
+ version_ = new ServiceWorkerVersion(
+ registration_.get(), GURL("https://example.com/service_worker.js"),
+ storage()->NewVersionId(), helper_->context()->AsWeakPtr());
+ std::vector<ServiceWorkerDatabase::ResourceRecord> records;
+ records.push_back(ServiceWorkerDatabase::ResourceRecord(
+ storage()->NewResourceId(), version_->script_url(), 100));
+ version_->script_cache_map()->SetResources(records);
+ version_->set_fetch_handler_existence(
+ ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
+ version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
+ registration_->SetActiveVersion(version_);
+
+ // Make the registration findable via storage functions.
+ registration_->set_last_update_check(base::Time::Now());
+ ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
+ storage()->StoreRegistration(registration_.get(), version_.get(),
+ CreateReceiverOnCurrentThread(&status));
+ base::RunLoop().RunUntilIdle();
+ ASSERT_EQ(SERVICE_WORKER_OK, status);
+ }
+
+ ServiceWorkerStorage* storage() { return helper_->context()->storage(); }
+
+ base::WeakPtr<storage::BlobStorageContext> GetBlobStorageContext() {
+ return blob_context_.AsWeakPtr();
+ }
+
+ // Indicates whether ServiceWorkerURLLoaderJob decided to handle a request,
+ // i.e., it returned a non-null StartLoaderCallback for the request.
+ enum class JobResult {
+ kHandledRequest,
+ kDidNotHandleRequest,
+ };
+
+ // Performs a request. When this returns, |client_| will have information
+ // about the response.
+ JobResult TestRequest() {
+ ResourceRequest request;
+ request.url = GURL("https://www.example.com/");
+ request.method = "GET";
+
+ // Start a ServiceWorkerURLLoaderJob. It should return a
+ // StartLoaderCallback.
+ StartLoaderCallback callback;
+ job_ = base::MakeUnique<ServiceWorkerURLLoaderJob>(
+ base::BindOnce(&ReceiveStartLoaderCallback, &callback), this, request,
+ GetBlobStorageContext());
+ job_->ForwardToServiceWorker();
+ base::RunLoop().RunUntilIdle();
+ if (!callback)
+ return JobResult::kDidNotHandleRequest;
+
+ // Start the loader. It will load |request.url|.
+ mojom::URLLoaderPtr loader;
+ std::move(callback).Run(mojo::MakeRequest(&loader),
+ client_.CreateInterfacePtr());
+ client_.RunUntilComplete();
+
+ return JobResult::kHandledRequest;
+ }
+
+ void ExpectFetchedViaServiceWorker(const ResourceResponseHead& info) {
+ EXPECT_TRUE(info.was_fetched_via_service_worker);
+ EXPECT_FALSE(info.was_fallback_required_by_service_worker);
+ EXPECT_TRUE(info.url_list_via_service_worker.empty());
+ EXPECT_EQ(network::mojom::FetchResponseType::kDefault,
+ info.response_type_via_service_worker);
+ // TODO(falken): start and ready time should be set.
+ EXPECT_TRUE(info.service_worker_start_time.is_null());
+ EXPECT_TRUE(info.service_worker_ready_time.is_null());
+ EXPECT_FALSE(info.is_in_cache_storage);
+ EXPECT_EQ(std::string(), info.cache_storage_cache_name);
+ }
+
+ protected:
+ // ServiceWorkerURLLoaderJob::Delegate --------------------------------------
+ void OnPrepareToRestart() override {}
+
+ ServiceWorkerVersion* GetServiceWorkerVersion(
+ ServiceWorkerMetrics::URLRequestJobResult* result) override {
+ return version_.get();
+ }
+
+ bool RequestStillValid(
+ ServiceWorkerMetrics::URLRequestJobResult* result) override {
+ return true;
+ }
+
+ void MainResourceLoadFailed() override {
+ was_main_resource_load_failed_called_ = true;
+ }
+ // --------------------------------------------------------------------------
+
+ TestBrowserThreadBundle thread_bundle_;
+ std::unique_ptr<Helper> helper_;
+ scoped_refptr<ServiceWorkerRegistration> registration_;
+ scoped_refptr<ServiceWorkerVersion> version_;
+ storage::BlobStorageContext blob_context_;
+ TestURLLoaderClient client_;
+ bool was_main_resource_load_failed_called_ = false;
+ std::unique_ptr<ServiceWorkerURLLoaderJob> job_;
+};
+
+TEST_F(ServiceWorkerURLLoaderJobTest, Basic) {
+ JobResult result = TestRequest();
+ EXPECT_EQ(JobResult::kHandledRequest, result);
+ EXPECT_EQ(net::OK, client_.completion_status().error_code);
+ const ResourceResponseHead& info = client_.response_head();
+ EXPECT_EQ(200, info.headers->response_code());
+ ExpectFetchedViaServiceWorker(info);
+}
+
+TEST_F(ServiceWorkerURLLoaderJobTest, BlobResponse) {
+ // Construct the blob to respond with.
+ const std::string kResponseBody = "Here is sample text for the blob.";
+ auto blob_data = base::MakeUnique<storage::BlobDataBuilder>("blob-id:myblob");
+ blob_data->AppendData(kResponseBody);
+ std::unique_ptr<storage::BlobDataHandle> blob_handle =
+ blob_context_.AddFinishedBlob(blob_data.get());
+ helper_->RespondWithBlob(blob_handle->uuid(), blob_handle->size());
+
+ // Perform the request.
+ JobResult result = TestRequest();
+ EXPECT_EQ(JobResult::kHandledRequest, result);
+ const ResourceResponseHead& info = client_.response_head();
+ EXPECT_EQ(200, info.headers->response_code());
+ ExpectFetchedViaServiceWorker(info);
+
+ // Test the body.
+ std::string response;
+ EXPECT_TRUE(client_.response_body().is_valid());
+ EXPECT_TRUE(mojo::common::BlockingCopyToString(
+ client_.response_body_release(), &response));
+ EXPECT_EQ(kResponseBody, response);
+}
+
+// Tell the helper to respond with a non-existent Blob.
+TEST_F(ServiceWorkerURLLoaderJobTest, NonExistentBlobUUIDResponse) {
+ helper_->RespondWithBlob("blob-id:nothing-is-here", 0);
+
+ // Perform the request.
+ JobResult result = TestRequest();
+ EXPECT_EQ(JobResult::kHandledRequest, result);
+ const ResourceResponseHead& info = client_.response_head();
+ // TODO(falken): Currently our code returns 404 not found (with net::OK), but
+ // the spec seems to say this should act as if a network error has occurred.
+ // See https://crbug.com/732750
+ EXPECT_EQ(404, info.headers->response_code());
+ ExpectFetchedViaServiceWorker(info);
+}
+
+TEST_F(ServiceWorkerURLLoaderJobTest, StreamResponse) {
+ // Construct the Stream to respond with.
+ const char kResponseBody[] = "Here is sample text for the Stream.";
+ blink::mojom::ServiceWorkerStreamCallbackPtr stream_callback;
+ mojo::DataPipe data_pipe;
+ helper_->RespondWithStream(mojo::MakeRequest(&stream_callback),
+ std::move(data_pipe.consumer_handle));
+
+ // Perform the request.
+ JobResult result = TestRequest();
+ EXPECT_EQ(JobResult::kHandledRequest, result);
+ const ResourceResponseHead& info = client_.response_head();
+ EXPECT_EQ(200, info.headers->response_code());
+ ExpectFetchedViaServiceWorker(info);
+
+ // TODO(falken): This should be true since the worker is still streaming the
+ // response body. See https://crbug.com/758455
+ EXPECT_FALSE(version_->HasWork());
+
+ // Write the body stream.
+ 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);
+ stream_callback->OnCompleted();
+ data_pipe.producer_handle.reset();
+ EXPECT_EQ(net::OK, client_.completion_status().error_code);
+
+ // Test the body.
+ std::string response;
+ EXPECT_TRUE(client_.response_body().is_valid());
+ EXPECT_TRUE(mojo::common::BlockingCopyToString(
+ client_.response_body_release(), &response));
+ EXPECT_EQ(kResponseBody, response);
+}
+
+// Test when a stream response body is aborted.
+TEST_F(ServiceWorkerURLLoaderJobTest, StreamResponse_Abort) {
+ // Construct the Stream to respond with.
+ const char kResponseBody[] = "Here is sample text for the Stream.";
+ blink::mojom::ServiceWorkerStreamCallbackPtr stream_callback;
+ mojo::DataPipe data_pipe;
+ helper_->RespondWithStream(mojo::MakeRequest(&stream_callback),
+ std::move(data_pipe.consumer_handle));
+
+ // Perform the request.
+ JobResult result = TestRequest();
+ EXPECT_EQ(JobResult::kHandledRequest, result);
+ const ResourceResponseHead& info = client_.response_head();
+ EXPECT_EQ(200, info.headers->response_code());
+ ExpectFetchedViaServiceWorker(info);
+
+ // Start writing the body stream, then abort 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);
+ stream_callback->OnAborted();
+ data_pipe.producer_handle.reset();
+ // TODO(falken): This should be an error, see https://crbug.com/758455
+ EXPECT_EQ(net::OK, client_.completion_status().error_code);
+
+ // Test the body.
+ std::string response;
+ EXPECT_TRUE(client_.response_body().is_valid());
+ EXPECT_TRUE(mojo::common::BlockingCopyToString(
+ client_.response_body_release(), &response));
+ EXPECT_EQ(kResponseBody, response);
+}
+
+// Test when the job is cancelled while a stream response is being written.
+TEST_F(ServiceWorkerURLLoaderJobTest, StreamResponseAndCancel) {
+ // Construct the Stream to respond with.
+ const char kResponseBody[] = "Here is sample text for the Stream.";
+ blink::mojom::ServiceWorkerStreamCallbackPtr stream_callback;
+ mojo::DataPipe data_pipe;
+ helper_->RespondWithStream(mojo::MakeRequest(&stream_callback),
+ std::move(data_pipe.consumer_handle));
+
+ // Perform the request.
+ JobResult result = TestRequest();
+ EXPECT_EQ(JobResult::kHandledRequest, result);
+ const ResourceResponseHead& info = client_.response_head();
+ EXPECT_EQ(200, info.headers->response_code());
+ ExpectFetchedViaServiceWorker(info);
+
+ // Start writing the body stream, then cancel the job 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(job_->WasCanceled());
+ // TODO(falken): This should be true since the worker is still streaming the
+ // response body. See https://crbug.com/758455
+ EXPECT_FALSE(version_->HasWork());
+ job_->Cancel();
+ EXPECT_TRUE(job_->WasCanceled());
+ EXPECT_FALSE(version_->HasWork());
+
+ // Although ServiceworkerURLLoaderJob resets its URLLoaderClient pointer in
+ // Cancel(), 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(
+ kResponseBody, &written_bytes, MOJO_WRITE_DATA_FLAG_NONE);
+ // TODO(falken): This should probably be an error.
+ EXPECT_EQ(MOJO_RESULT_OK, mojo_result);
+
+ stream_callback->OnAborted();
+
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(data_pipe.consumer_handle.is_valid());
+ // TODO(falken): This should be an error, see https://crbug.com/758455
+ EXPECT_EQ(net::OK, client_.completion_status().error_code);
+}
+
+// Test when the service worker responds with network fallback.
+// i.e., does not call respondWith().
+TEST_F(ServiceWorkerURLLoaderJobTest, FallbackResponse) {
+ helper_->RespondWithFallback();
+
+ // Perform the request.
+ JobResult result = TestRequest();
+ EXPECT_EQ(JobResult::kDidNotHandleRequest, result);
+
+ // The request should not be handled by the job, but it shouldn't be a
+ // failure.
+ EXPECT_FALSE(was_main_resource_load_failed_called_);
+}
+
+// Test when dispatching the fetch event to the service worker failed.
+TEST_F(ServiceWorkerURLLoaderJobTest, FailFetchDispatch) {
+ helper_->FailToDispatchFetchEvent();
+
+ // Perform the request.
+ JobResult result = TestRequest();
+ EXPECT_EQ(JobResult::kDidNotHandleRequest, result);
+ EXPECT_TRUE(was_main_resource_load_failed_called_);
+}
+
+// Test when the respondWith() promise resolves before the waitUntil() promise
+// resolves. The response should be received before the event finishes.
+TEST_F(ServiceWorkerURLLoaderJobTest, EarlyResponse) {
+ helper_->RespondEarly();
+
+ // Perform the request.
+ JobResult result = TestRequest();
+ EXPECT_EQ(JobResult::kHandledRequest, result);
+ const ResourceResponseHead& info = client_.response_head();
+ EXPECT_EQ(200, info.headers->response_code());
+ ExpectFetchedViaServiceWorker(info);
+
+ // Although the response was already received, the event remains outstanding
+ // until waitUntil() resolves.
+ EXPECT_TRUE(version_->HasWork());
+ helper_->FinishWaitUntil();
+ EXPECT_FALSE(version_->HasWork());
+}
+
+// Test asking the job to fallback to network. In production code, this happens
+// when there is no active service worker for the URL, or it must be skipped,
+// etc.
+TEST_F(ServiceWorkerURLLoaderJobTest, FallbackToNetwork) {
+ ResourceRequest request;
+ request.url = GURL("https://www.example.com/");
+ request.method = "GET";
+
+ StartLoaderCallback callback;
+ auto job = base::MakeUnique<ServiceWorkerURLLoaderJob>(
+ base::BindOnce(&ReceiveStartLoaderCallback, &callback), this, request,
+ GetBlobStorageContext());
+ // Ask the job to fallback to network. In production code,
+ // ServiceWorkerControlleeRequestHandler calls FallbackToNetwork() to do this.
+ job->FallbackToNetwork();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(callback);
+}
+
+} // namespace content
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 c1f07885306..777604a8d92 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
@@ -19,11 +19,8 @@
#include "base/guid.h"
#include "base/location.h"
#include "base/numerics/safe_conversions.h"
-#include "base/single_thread_task_runner.h"
#include "base/strings/stringprintf.h"
-#include "base/task_runner.h"
-#include "base/task_runner_util.h"
-#include "base/threading/sequenced_worker_pool.h"
+#include "base/task_scheduler/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "content/browser/resource_context_impl.h"
@@ -39,6 +36,7 @@
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/resource_request_info.h"
#include "content/public/browser/service_worker_context.h"
+#include "content/public/common/content_features.h"
#include "content/public/common/referrer.h"
#include "content/public/common/resource_request_body.h"
#include "net/base/net_errors.h"
@@ -51,6 +49,7 @@
#include "net/log/net_log_with_source.h"
#include "storage/browser/blob/blob_data_builder.h"
#include "storage/browser/blob/blob_data_handle.h"
+#include "storage/browser/blob/blob_impl.h"
#include "storage/browser/blob/blob_storage_context.h"
#include "ui/base/page_transition_types.h"
@@ -121,8 +120,8 @@ net::NetLogEventType RequestJobResultToNetEventType(
return n::FAILED;
}
-std::vector<int64_t> GetFileSizesOnBlockingPool(
- std::vector<base::FilePath> file_paths) {
+// Does file IO. Use with base::MayBlock().
+std::vector<int64_t> GetFileSizes(std::vector<base::FilePath> file_paths) {
std::vector<int64_t> sizes;
sizes.reserve(file_paths.size());
for (const base::FilePath& path : file_paths) {
@@ -158,13 +157,12 @@ class ServiceWorkerURLRequestJob::FileSizeResolver {
phase_ == Phase::SUCCESS);
}
- void Resolve(base::TaskRunner* file_runner,
- const base::Callback<void(bool)>& callback) {
+ void Resolve(base::OnceCallback<void(bool /* success */)> callback) {
DCHECK_EQ(static_cast<int>(Phase::INITIAL), static_cast<int>(phase_));
DCHECK(file_elements_.empty());
phase_ = Phase::WAITING;
body_ = owner_->body_;
- callback_ = callback;
+ callback_ = std::move(callback);
std::vector<base::FilePath> file_paths;
for (ResourceRequestBody::Element& element : *body_->elements_mutable()) {
@@ -179,10 +177,11 @@ class ServiceWorkerURLRequestJob::FileSizeResolver {
return;
}
- PostTaskAndReplyWithResult(
- file_runner, FROM_HERE,
- base::Bind(&GetFileSizesOnBlockingPool, base::Passed(&file_paths)),
- base::Bind(
+ base::PostTaskWithTraitsAndReplyWithResult(
+ FROM_HERE,
+ {base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
+ base::BindOnce(&GetFileSizes, std::move(file_paths)),
+ base::BindOnce(
&ServiceWorkerURLRequestJob::FileSizeResolver::OnFileSizesResolved,
weak_factory_.GetWeakPtr()));
}
@@ -209,8 +208,8 @@ class ServiceWorkerURLRequestJob::FileSizeResolver {
void Complete(bool success) {
DCHECK_EQ(static_cast<int>(Phase::WAITING), static_cast<int>(phase_));
phase_ = success ? Phase::SUCCESS : Phase::FAIL;
- // Destroys |this|, so we use a copy.
- base::ResetAndReturn(&callback_).Run(success);
+ // Destroys |this|.
+ std::move(callback_).Run(success);
}
// Owns and must outlive |this|.
@@ -218,7 +217,7 @@ class ServiceWorkerURLRequestJob::FileSizeResolver {
scoped_refptr<ResourceRequestBody> body_;
std::vector<ResourceRequestBody::Element*> file_elements_;
- base::Callback<void(bool)> callback_;
+ base::OnceCallback<void(bool /* success */)> callback_;
Phase phase_ = Phase::INITIAL;
base::WeakPtrFactory<FileSizeResolver> weak_factory_;
@@ -337,8 +336,7 @@ ServiceWorkerURLRequestJob::ServiceWorkerURLRequestJob(
delegate_(delegate),
response_type_(NOT_DETERMINED),
is_started_(false),
- service_worker_response_type_(
- blink::kWebServiceWorkerResponseTypeDefault),
+ fetch_response_type_(network::mojom::FetchResponseType::kDefault),
client_id_(client_id),
blob_storage_context_(blob_storage_context),
resource_context_(resource_context),
@@ -512,8 +510,8 @@ void ServiceWorkerURLRequestJob::MaybeStartRequest() {
if (is_started_ && response_type_ != NOT_DETERMINED) {
// Start asynchronously.
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&ServiceWorkerURLRequestJob::StartRequest,
- weak_factory_.GetWeakPtr()));
+ FROM_HERE, base::BindOnce(&ServiceWorkerURLRequestJob::StartRequest,
+ weak_factory_.GetWeakPtr()));
}
}
@@ -544,11 +542,9 @@ void ServiceWorkerURLRequestJob::StartRequest() {
if (HasRequestBody()) {
DCHECK(!file_size_resolver_);
file_size_resolver_.reset(new FileSizeResolver(this));
- file_size_resolver_->Resolve(
- BrowserThread::GetBlockingPool(),
- base::Bind(
- &ServiceWorkerURLRequestJob::RequestBodyFileSizesResolved,
- GetWeakPtr()));
+ file_size_resolver_->Resolve(base::BindOnce(
+ &ServiceWorkerURLRequestJob::RequestBodyFileSizesResolved,
+ GetWeakPtr()));
return;
}
@@ -581,6 +577,7 @@ ServiceWorkerURLRequestJob::CreateFetchRequest() {
}
request->blob_uuid = blob_uuid;
request->blob_size = blob_size;
+ request->blob = request_body_blob_handle_;
request->credentials_mode = credentials_mode_;
request->redirect_mode = redirect_mode_;
request->integrity = integrity_;
@@ -614,6 +611,15 @@ void ServiceWorkerURLRequestJob::CreateRequestBodyBlob(std::string* blob_uuid,
blob_storage_context_->AddFinishedBlob(&blob_builder);
*blob_uuid = blob_builder.uuid();
*blob_size = request_body_blob_data_handle_->size();
+
+ if (base::FeatureList::IsEnabled(features::kMojoBlobs)) {
+ storage::mojom::BlobPtr blob_ptr;
+ storage::BlobImpl::Create(base::MakeUnique<storage::BlobDataHandle>(
+ *request_body_blob_data_handle_),
+ MakeRequest(&blob_ptr));
+ request_body_blob_handle_ =
+ base::MakeRefCounted<storage::BlobHandle>(std::move(blob_ptr));
+ }
}
bool ServiceWorkerURLRequestJob::ShouldRecordNavigationMetrics(
@@ -674,6 +680,7 @@ void ServiceWorkerURLRequestJob::DidDispatchFetchEvent(
ServiceWorkerFetchEventResult fetch_result,
const ServiceWorkerResponse& response,
blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
+ storage::mojom::BlobPtr body_as_blob,
const scoped_refptr<ServiceWorkerVersion>& version) {
// Do not clear |fetch_dispatcher_| if it has dispatched a navigation preload
// request to keep the mojom::URLLoader related objects in it, because the
@@ -749,6 +756,8 @@ void ServiceWorkerURLRequestJob::DidDispatchFetchEvent(
}
// Set up a request for reading the blob.
+ // |body_as_blob| must be kept around until we call this to ensure that
+ // it's alive.
if (!response.blob_uuid.empty() && blob_storage_context_) {
SetResponseBodyType(BLOB);
std::unique_ptr<storage::BlobDataHandle> blob_data_handle =
@@ -773,7 +782,7 @@ void ServiceWorkerURLRequestJob::DidDispatchFetchEvent(
void ServiceWorkerURLRequestJob::SetResponse(
const ServiceWorkerResponse& response) {
response_url_list_ = response.url_list;
- service_worker_response_type_ = response.response_type;
+ fetch_response_type_ = response.response_type;
cors_exposed_header_names_ = response.cors_exposed_header_names;
response_time_ = response.response_time;
CreateResponseHeader(response.status_code, response.status_text,
@@ -922,7 +931,7 @@ void ServiceWorkerURLRequestJob::OnStartCompleted() const {
false /* was_fetched_via_foreign_fetch */,
false /* was_fallback_required */,
std::vector<GURL>() /* url_list_via_service_worker */,
- blink::kWebServiceWorkerResponseTypeDefault,
+ network::mojom::FetchResponseType::kDefault,
base::TimeTicks() /* service_worker_start_time */,
base::TimeTicks() /* service_worker_ready_time */,
false /* response_is_in_cache_storage */,
@@ -939,11 +948,10 @@ void ServiceWorkerURLRequestJob::OnStartCompleted() const {
->OnStartCompleted(
true /* was_fetched_via_service_worker */,
fetch_type_ == ServiceWorkerFetchType::FOREIGN_FETCH,
- fall_back_required_, response_url_list_,
- service_worker_response_type_, worker_start_time_,
- worker_ready_time_, response_is_in_cache_storage_,
- response_cache_storage_cache_name_, cors_exposed_header_names_,
- did_navigation_preload_);
+ fall_back_required_, response_url_list_, fetch_response_type_,
+ worker_start_time_, worker_ready_time_,
+ response_is_in_cache_storage_, response_cache_storage_cache_name_,
+ cors_exposed_header_names_, did_navigation_preload_);
break;
}
}
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 8f8c187ffb0..a3b1ad33afd 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
@@ -34,8 +34,8 @@
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_job.h"
#include "net/url_request/url_request_status.h"
+#include "services/network/public/interfaces/fetch_api.mojom.h"
#include "storage/common/blob_storage/blob_storage_constants.h"
-#include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerResponseType.h"
#include "url/gurl.h"
namespace net {
@@ -144,8 +144,6 @@ class CONTENT_EXPORT ServiceWorkerURLRequestJob : public net::URLRequestJob {
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerControlleeRequestHandlerTest,
LostActiveVersion);
- using ResponseType = ServiceWorkerResponseType;
-
enum ResponseBodyType {
UNKNOWN,
BLOB,
@@ -180,6 +178,7 @@ class CONTENT_EXPORT ServiceWorkerURLRequestJob : public net::URLRequestJob {
ServiceWorkerFetchEventResult fetch_result,
const ServiceWorkerResponse& response,
blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
+ storage::mojom::BlobPtr body_as_blob,
const scoped_refptr<ServiceWorkerVersion>& version);
void SetResponse(const ServiceWorkerResponse& response);
@@ -277,7 +276,7 @@ class CONTENT_EXPORT ServiceWorkerURLRequestJob : public net::URLRequestJob {
std::unique_ptr<NavigationPreloadMetrics> nav_preload_metrics_;
- ResponseType response_type_;
+ ServiceWorkerResponseType response_type_;
// True if URLRequestJob::Start() has been called.
bool is_started_;
@@ -288,7 +287,7 @@ class CONTENT_EXPORT ServiceWorkerURLRequestJob : public net::URLRequestJob {
// Headers that have not yet been committed to |http_response_info_|.
scoped_refptr<net::HttpResponseHeaders> http_response_headers_;
std::vector<GURL> response_url_list_;
- blink::WebServiceWorkerResponseType service_worker_response_type_;
+ network::mojom::FetchResponseType fetch_response_type_;
// Used when response type is FORWARD_TO_SERVICE_WORKER.
std::unique_ptr<ServiceWorkerFetchDispatcher> fetch_dispatcher_;
@@ -311,6 +310,7 @@ class CONTENT_EXPORT ServiceWorkerURLRequestJob : public net::URLRequestJob {
// using the userdata mechanism. So we have to keep it not to free the blobs.
scoped_refptr<ResourceRequestBody> body_;
std::unique_ptr<storage::BlobDataHandle> request_body_blob_data_handle_;
+ scoped_refptr<storage::BlobHandle> request_body_blob_handle_;
ServiceWorkerFetchType fetch_type_;
base::Optional<base::TimeDelta> timeout_;
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 439fc02871b..65bba2b2fbb 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
@@ -60,6 +60,7 @@
#include "storage/browser/blob/blob_storage_context.h"
#include "storage/browser/blob/blob_url_request_job.h"
#include "storage/browser/blob/blob_url_request_job_factory.h"
+#include "storage/common/blob_storage/blob_handle.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
@@ -69,10 +70,16 @@ namespace {
const int kProviderID = 100;
const char kTestData[] = "Here is sample text for the blob.";
-class MockHttpProtocolHandler
- : public net::URLRequestJobFactory::ProtocolHandler {
+// A simple ProtocolHandler implementation to create ServiceWorkerURLRequestJob.
+//
+// MockProtocolHandler is basically a mock of
+// ServiceWorkerControlleeRequestHandler. In production code,
+// ServiceWorkerControlleeRequestHandler::MaybeCreateJob() is called by
+// ServiceWorkerRequestInterceptor, a custom URLRequestInterceptor, but for
+// testing it's easier to make the job via ProtocolHandler.
+class MockProtocolHandler : public net::URLRequestJobFactory::ProtocolHandler {
public:
- MockHttpProtocolHandler(
+ MockProtocolHandler(
base::WeakPtr<ServiceWorkerProviderHost> provider_host,
const ResourceContext* resource_context,
base::WeakPtr<storage::BlobStorageContext> blob_storage_context,
@@ -85,7 +92,7 @@ class MockHttpProtocolHandler
resource_type_(RESOURCE_TYPE_MAIN_FRAME),
simulate_navigation_preload_(false) {}
- ~MockHttpProtocolHandler() override {}
+ ~MockProtocolHandler() override = default;
void set_resource_type(ResourceType type) { resource_type_ = type; }
void set_custom_timeout(base::Optional<base::TimeDelta> timeout) {
@@ -95,6 +102,8 @@ class MockHttpProtocolHandler
simulate_navigation_preload_ = true;
}
+ // A simple version of
+ // ServiceWorkerControlleeRequestHandler::MaybeCreateJob().
net::URLRequestJob* MaybeCreateJob(
net::URLRequest* request,
net::NetworkDelegate* network_delegate) const override {
@@ -155,16 +164,37 @@ void SaveStatusCallback(ServiceWorkerStatusCode* out_status,
} // namespace
+// ServiceWorkerURLRequestJobTest is for testing the handling of URL requests by
+// a service worker.
+//
+// To use it, call SetUpWithHelper() in your test. This sets up the service
+// worker and the scaffolding to make the worker handle https URLRequests. (Of
+// course, no actual service worker runs in the unit test, it is simulated via
+// EmbeddedWorkerTestHelper receiving IPC messages from the browser and
+// responding as if a service worker is running in the renderer.) Example:
+//
+// auto request = url_request_context_.CreateRequest(
+// GURL("https://example.com/foo.html"), net::DEFAULT_PRIORITY,
+// &url_request_delegate_, TRAFFIC_ANNOTATION_FOR_TESTS);
+// request->set_method("GET");
+// request->Start();
+// base::RunLoop().RunUntilIdle();
+// // Now the request was handled by a ServiceWorkerURLRequestJob.
+//
+// ServiceWorkerURLRequestJobTest is also a
+// ServiceWorkerURLRequestJob::Delegate. In production code,
+// ServiceWorkerControlleeRequestHandler is the Delegate (for non-"foreign
+// fetch" request interceptions). So this class also basically mocks that part
+// of ServiceWorkerControlleeRequestHandler.
class ServiceWorkerURLRequestJobTest
: public testing::Test,
public ServiceWorkerURLRequestJob::Delegate {
public:
- MockHttpProtocolHandler* handler() { return http_protocol_handler_; }
+ MockProtocolHandler* handler() { return protocol_handler_; }
protected:
ServiceWorkerURLRequestJobTest()
- : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP),
- blob_data_(new storage::BlobDataBuilder("blob-id:myblob")) {}
+ : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {}
~ServiceWorkerURLRequestJobTest() override {}
void SetUp() override {
@@ -172,10 +202,10 @@ class ServiceWorkerURLRequestJobTest
InitializeResourceContext(browser_context_.get());
}
- void SetUpWithHelper(std::unique_ptr<EmbeddedWorkerTestHelper> helper,
- bool set_main_script_http_response_info = true) {
+ void SetUpWithHelper(std::unique_ptr<EmbeddedWorkerTestHelper> helper) {
helper_ = std::move(helper);
+ // Create a registration and service worker version.
registration_ = new ServiceWorkerRegistration(
ServiceWorkerRegistrationOptions(GURL("https://example.com/")), 1L,
helper_->context()->AsWeakPtr());
@@ -200,18 +230,18 @@ class ServiceWorkerURLRequestJobTest
base::RunLoop().RunUntilIdle();
ASSERT_EQ(SERVICE_WORKER_OK, status);
- if (set_main_script_http_response_info) {
- net::HttpResponseInfo http_info;
- http_info.ssl_info.cert =
- net::ImportCertFromFile(net::GetTestCertsDirectory(), "ok_cert.pem");
- EXPECT_TRUE(http_info.ssl_info.is_valid());
- http_info.ssl_info.security_bits = 0x100;
- // SSL3 TLS_DHE_RSA_WITH_AES_256_CBC_SHA
- http_info.ssl_info.connection_status = 0x300039;
- http_info.headers = make_scoped_refptr(new net::HttpResponseHeaders(""));
- version_->SetMainScriptHttpResponseInfo(http_info);
- }
-
+ // Set HTTP response info on the version.
+ net::HttpResponseInfo http_info;
+ http_info.ssl_info.cert =
+ net::ImportCertFromFile(net::GetTestCertsDirectory(), "ok_cert.pem");
+ EXPECT_TRUE(http_info.ssl_info.is_valid());
+ http_info.ssl_info.security_bits = 0x100;
+ // SSL3 TLS_DHE_RSA_WITH_AES_256_CBC_SHA
+ http_info.ssl_info.connection_status = 0x300039;
+ http_info.headers = make_scoped_refptr(new net::HttpResponseHeaders(""));
+ version_->SetMainScriptHttpResponseInfo(http_info);
+
+ // Create a controlled client.
std::unique_ptr<ServiceWorkerProviderHost> provider_host =
CreateProviderHostForWindow(
helper_->mock_render_process_id(), kProviderID,
@@ -223,19 +253,18 @@ class ServiceWorkerURLRequestJobTest
provider_host->AssociateRegistration(registration_.get(),
false /* notify_controllerchange */);
+ // Set up scaffolding for handling URL requests.
ChromeBlobStorageContext* chrome_blob_storage_context =
ChromeBlobStorageContext::GetFor(browser_context_.get());
// Wait for chrome_blob_storage_context to finish initializing.
base::RunLoop().RunUntilIdle();
storage::BlobStorageContext* blob_storage_context =
chrome_blob_storage_context->context();
-
url_request_job_factory_.reset(new net::URLRequestJobFactoryImpl);
- std::unique_ptr<MockHttpProtocolHandler> handler(
- new MockHttpProtocolHandler(provider_host->AsWeakPtr(),
- browser_context_->GetResourceContext(),
- blob_storage_context->AsWeakPtr(), this));
- http_protocol_handler_ = handler.get();
+ std::unique_ptr<MockProtocolHandler> handler(new MockProtocolHandler(
+ provider_host->AsWeakPtr(), browser_context_->GetResourceContext(),
+ blob_storage_context->AsWeakPtr(), this));
+ protocol_handler_ = handler.get();
url_request_job_factory_->SetProtocolHandler("https", std::move(handler));
url_request_job_factory_->SetProtocolHandler(
"blob", CreateMockBlobProtocolHandler(blob_storage_context));
@@ -255,7 +284,7 @@ class ServiceWorkerURLRequestJobTest
const std::string& expected_status_text,
const std::string& expected_response,
bool expect_valid_ssl) {
- EXPECT_TRUE(request_->status().is_success());
+ EXPECT_EQ(net::OK, url_request_delegate_.request_status());
EXPECT_EQ(expected_status_code,
request_->response_headers()->response_code());
EXPECT_EQ(expected_status_text,
@@ -304,41 +333,10 @@ class ServiceWorkerURLRequestJobTest
bool HasWork() { return version_->HasWork(); }
- // ServiceWorkerURLRequestJob::Delegate implementation:
- void OnPrepareToRestart() override { times_prepare_to_restart_invoked_++; }
-
- ServiceWorkerVersion* GetServiceWorkerVersion(
- ServiceWorkerMetrics::URLRequestJobResult* result) override {
- if (!provider_host_) {
- *result = ServiceWorkerMetrics::REQUEST_JOB_ERROR_NO_PROVIDER_HOST;
- return nullptr;
- }
- if (!provider_host_->active_version()) {
- *result = ServiceWorkerMetrics::REQUEST_JOB_ERROR_NO_ACTIVE_VERSION;
- return nullptr;
- }
- return provider_host_->active_version();
- }
-
- bool RequestStillValid(
- ServiceWorkerMetrics::URLRequestJobResult* result) override {
- if (!provider_host_) {
- *result = ServiceWorkerMetrics::REQUEST_JOB_ERROR_NO_PROVIDER_HOST;
- return false;
- }
- return true;
- }
-
- void MainResourceLoadFailed() override {
- CHECK(provider_host_);
- // Detach the controller so subresource requests also skip the worker.
- provider_host_->NotifyControllerLost();
- }
-
// Runs a request where the active worker starts a request in ACTIVATING state
// and fails to reach ACTIVATED.
void RunFailToActivateTest(ResourceType resource_type) {
- http_protocol_handler_->set_resource_type(resource_type);
+ protocol_handler_->set_resource_type(resource_type);
// Start a request with an activating worker.
version_->SetStatus(ServiceWorkerVersion::ACTIVATING);
@@ -355,16 +353,16 @@ class ServiceWorkerURLRequestJobTest
// it might respond synchronously, and the TestDelegate would complain that
// the message loop isn't being run.
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&ServiceWorkerVersion::SetStatus, version_,
- ServiceWorkerVersion::REDUNDANT));
+ FROM_HERE, base::BindOnce(&ServiceWorkerVersion::SetStatus, version_,
+ ServiceWorkerVersion::REDUNDANT));
base::RunLoop().RunUntilIdle();
}
// Starts a navigation request with navigation preload enabled.
void SetUpNavigationPreloadTest(ResourceType resource_type) {
version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
- http_protocol_handler_->set_resource_type(resource_type);
- http_protocol_handler_->set_simulate_navigation_preload();
+ protocol_handler_->set_resource_type(resource_type);
+ protocol_handler_->set_simulate_navigation_preload();
request_ = url_request_context_.CreateRequest(
GURL("https://example.com/foo.html"), net::DEFAULT_PRIORITY,
&url_request_delegate_, TRAFFIC_ANNOTATION_FOR_TESTS);
@@ -378,6 +376,38 @@ class ServiceWorkerURLRequestJobTest
base::RunLoop().RunUntilIdle();
}
+ // ServiceWorkerURLRequestJob::Delegate -------------------------------------
+ void OnPrepareToRestart() override { times_prepare_to_restart_invoked_++; }
+
+ ServiceWorkerVersion* GetServiceWorkerVersion(
+ ServiceWorkerMetrics::URLRequestJobResult* result) override {
+ if (!provider_host_) {
+ *result = ServiceWorkerMetrics::REQUEST_JOB_ERROR_NO_PROVIDER_HOST;
+ return nullptr;
+ }
+ if (!provider_host_->active_version()) {
+ *result = ServiceWorkerMetrics::REQUEST_JOB_ERROR_NO_ACTIVE_VERSION;
+ return nullptr;
+ }
+ return provider_host_->active_version();
+ }
+
+ bool RequestStillValid(
+ ServiceWorkerMetrics::URLRequestJobResult* result) override {
+ if (!provider_host_) {
+ *result = ServiceWorkerMetrics::REQUEST_JOB_ERROR_NO_PROVIDER_HOST;
+ return false;
+ }
+ return true;
+ }
+
+ void MainResourceLoadFailed() override {
+ ASSERT_TRUE(provider_host_);
+ // Detach the controller so subresource requests also skip the worker.
+ provider_host_->NotifyControllerLost();
+ }
+ // ---------------------------------------------------------------------------
+
TestBrowserThreadBundle thread_bundle_;
std::unique_ptr<TestBrowserContext> browser_context_;
@@ -390,14 +420,14 @@ class ServiceWorkerURLRequestJobTest
net::TestDelegate url_request_delegate_;
std::unique_ptr<net::URLRequest> request_;
- std::unique_ptr<storage::BlobDataBuilder> blob_data_;
-
int times_prepare_to_restart_invoked_ = 0;
base::WeakPtr<ServiceWorkerProviderHost> provider_host_;
ServiceWorkerRemoteProviderEndpoint remote_endpoint_;
// Not owned.
- MockHttpProtocolHandler* http_protocol_handler_;
+ // The ProtocolHandler for https requests, which creates a
+ // ServiceWorkerURLRequestJob.
+ MockProtocolHandler* protocol_handler_;
private:
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerURLRequestJobTest);
@@ -415,8 +445,8 @@ TEST_F(ServiceWorkerURLRequestJobTest, Simple) {
ASSERT_TRUE(info);
EXPECT_TRUE(info->was_fetched_via_service_worker());
EXPECT_FALSE(info->was_fallback_required());
- EXPECT_EQ(0u, info->url_list_via_service_worker().size());
- EXPECT_EQ(blink::kWebServiceWorkerResponseTypeDefault,
+ EXPECT_TRUE(info->url_list_via_service_worker().empty());
+ EXPECT_EQ(network::mojom::FetchResponseType::kDefault,
info->response_type_via_service_worker());
EXPECT_FALSE(info->service_worker_start_time().is_null());
EXPECT_FALSE(info->service_worker_ready_time().is_null());
@@ -439,17 +469,17 @@ class DelayHelper : public EmbeddedWorkerTestHelper {
EmbeddedWorkerTestHelper::OnStartWorker(
embedded_worker_id_, service_worker_version_id_, scope_, script_url_,
pause_after_download_, std::move(start_worker_request_),
- std::move(start_worker_instance_host_));
+ std::move(start_worker_instance_host_), std::move(provider_info_));
}
void Respond() {
response_callback_->OnResponse(
ServiceWorkerResponse(
base::MakeUnique<std::vector<GURL>>(), 200, "OK",
- blink::kWebServiceWorkerResponseTypeDefault,
+ network::mojom::FetchResponseType::kDefault,
base::MakeUnique<ServiceWorkerHeaderMap>(), std::string(), 0,
- blink::kWebServiceWorkerResponseErrorUnknown, base::Time(),
- false /* response_is_in_cache_storage */,
+ nullptr /* blob */, blink::kWebServiceWorkerResponseErrorUnknown,
+ base::Time(), false /* response_is_in_cache_storage */,
std::string() /* response_cache_storage_cache_name */,
base::MakeUnique<
ServiceWorkerHeaderList>() /* cors_exposed_header_names */),
@@ -458,14 +488,16 @@ class DelayHelper : public EmbeddedWorkerTestHelper {
}
protected:
- void OnStartWorker(int embedded_worker_id,
- int64_t service_worker_version_id,
- const GURL& scope,
- const GURL& script_url,
- bool pause_after_download,
- mojom::ServiceWorkerEventDispatcherRequest request,
- mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo
- instance_host) override {
+ void OnStartWorker(
+ int embedded_worker_id,
+ int64_t service_worker_version_id,
+ const GURL& scope,
+ const GURL& script_url,
+ bool pause_after_download,
+ mojom::ServiceWorkerEventDispatcherRequest request,
+ mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
+ mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info)
+ override {
embedded_worker_id_ = embedded_worker_id;
service_worker_version_id_ = service_worker_version_id;
scope_ = scope;
@@ -473,6 +505,7 @@ class DelayHelper : public EmbeddedWorkerTestHelper {
pause_after_download_ = pause_after_download;
start_worker_request_ = std::move(request);
start_worker_instance_host_ = std::move(instance_host);
+ provider_info_ = std::move(provider_info);
}
void OnFetchEvent(
@@ -497,6 +530,7 @@ class DelayHelper : public EmbeddedWorkerTestHelper {
mojom::ServiceWorkerEventDispatcherRequest start_worker_request_;
mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo
start_worker_instance_host_;
+ mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info_;
int embedded_worker_id_ = 0;
int fetch_event_id_ = 0;
mojom::ServiceWorkerFetchResponseCallbackPtr response_callback_;
@@ -651,11 +685,13 @@ TEST_F(ServiceWorkerURLRequestJobTest, CustomTimeout) {
version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
// Set mock clock on version_ to check timeout behavior.
- base::SimpleTestTickClock* tick_clock = new base::SimpleTestTickClock();
- tick_clock->SetNowTicks(base::TimeTicks::Now());
- version_->SetTickClockForTesting(base::WrapUnique(tick_clock));
+ {
+ auto tick_clock = base::MakeUnique<base::SimpleTestTickClock>();
+ tick_clock->SetNowTicks(base::TimeTicks::Now());
+ version_->SetTickClockForTesting(std::move(tick_clock));
+ }
- http_protocol_handler_->set_custom_timeout(base::TimeDelta::FromSeconds(5));
+ protocol_handler_->set_custom_timeout(base::TimeDelta::FromSeconds(5));
TestRequest(200, "OK", std::string(), true /* expect_valid_ssl */);
EXPECT_EQ(base::TimeDelta::FromSeconds(5), version_->remaining_timeout());
}
@@ -677,10 +713,10 @@ class ProviderDeleteHelper : public EmbeddedWorkerTestHelper {
response_callback->OnResponse(
ServiceWorkerResponse(
base::MakeUnique<std::vector<GURL>>(), 200, "OK",
- blink::kWebServiceWorkerResponseTypeDefault,
+ network::mojom::FetchResponseType::kDefault,
base::MakeUnique<ServiceWorkerHeaderMap>(), std::string(), 0,
- blink::kWebServiceWorkerResponseErrorUnknown, base::Time(),
- false /* response_is_in_cache_storage */,
+ nullptr /* blob */, blink::kWebServiceWorkerResponseErrorUnknown,
+ base::Time(), false /* response_is_in_cache_storage */,
std::string() /* response_cache_storage_cache_name */,
base::MakeUnique<
ServiceWorkerHeaderList>() /* cors_exposed_header_names */),
@@ -710,7 +746,7 @@ TEST_F(ServiceWorkerURLRequestJobTest, DeletedProviderHostOnFetchEvent) {
EXPECT_TRUE(info->was_fetched_via_service_worker());
EXPECT_FALSE(info->was_fallback_required());
EXPECT_EQ(0u, info->url_list_via_service_worker().size());
- EXPECT_EQ(blink::kWebServiceWorkerResponseTypeDefault,
+ EXPECT_EQ(network::mojom::FetchResponseType::kDefault,
info->response_type_via_service_worker());
EXPECT_FALSE(info->service_worker_start_time().is_null());
EXPECT_FALSE(info->service_worker_ready_time().is_null());
@@ -739,7 +775,7 @@ TEST_F(ServiceWorkerURLRequestJobTest, DeletedProviderHostBeforeFetchEvent) {
EXPECT_TRUE(info->was_fetched_via_service_worker());
EXPECT_FALSE(info->was_fallback_required());
EXPECT_EQ(0u, info->url_list_via_service_worker().size());
- EXPECT_EQ(blink::kWebServiceWorkerResponseTypeDefault,
+ EXPECT_EQ(network::mojom::FetchResponseType::kDefault,
info->response_type_via_service_worker());
EXPECT_TRUE(info->service_worker_start_time().is_null());
EXPECT_TRUE(info->service_worker_ready_time().is_null());
@@ -752,7 +788,7 @@ class BlobResponder : public EmbeddedWorkerTestHelper {
: EmbeddedWorkerTestHelper(base::FilePath()),
blob_uuid_(blob_uuid),
blob_size_(blob_size) {}
- ~BlobResponder() override {}
+ ~BlobResponder() override = default;
protected:
void OnFetchEvent(
@@ -765,8 +801,8 @@ class BlobResponder : public EmbeddedWorkerTestHelper {
response_callback->OnResponse(
ServiceWorkerResponse(
base::MakeUnique<std::vector<GURL>>(), 200, "OK",
- blink::kWebServiceWorkerResponseTypeDefault, MakeHeaders(),
- blob_uuid_, blob_size_,
+ network::mojom::FetchResponseType::kDefault, MakeHeaders(),
+ blob_uuid_, blob_size_, nullptr /* blob */,
blink::kWebServiceWorkerResponseErrorUnknown, base::Time(),
false /* response_is_in_cache_storage */,
std::string() /* response_cache_storage_cache_name */,
@@ -786,17 +822,19 @@ class BlobResponder : public EmbeddedWorkerTestHelper {
TEST_F(ServiceWorkerURLRequestJobTest, BlobResponse) {
ChromeBlobStorageContext* blob_storage_context =
ChromeBlobStorageContext::GetFor(browser_context_.get());
- // Wait for chrome_blob_storage_context to finish initializing.
+ // Wait for blob_storage_context to finish initializing.
base::RunLoop().RunUntilIdle();
std::string expected_response;
expected_response.reserve((sizeof(kTestData) - 1) * 1024);
+
+ auto blob_data = base::MakeUnique<storage::BlobDataBuilder>("blob-id:myblob");
for (int i = 0; i < 1024; ++i) {
- blob_data_->AppendData(kTestData);
+ blob_data->AppendData(kTestData);
expected_response += kTestData;
}
std::unique_ptr<storage::BlobDataHandle> blob_handle =
- blob_storage_context->context()->AddFinishedBlob(blob_data_.get());
+ blob_storage_context->context()->AddFinishedBlob(blob_data.get());
SetUpWithHelper(base::MakeUnique<BlobResponder>(blob_handle->uuid(),
expected_response.size()));
@@ -811,7 +849,7 @@ TEST_F(ServiceWorkerURLRequestJobTest, BlobResponse) {
EXPECT_TRUE(info->was_fetched_via_service_worker());
EXPECT_FALSE(info->was_fallback_required());
EXPECT_EQ(0u, info->url_list_via_service_worker().size());
- EXPECT_EQ(blink::kWebServiceWorkerResponseTypeDefault,
+ EXPECT_EQ(network::mojom::FetchResponseType::kDefault,
info->response_type_via_service_worker());
EXPECT_FALSE(info->service_worker_start_time().is_null());
EXPECT_FALSE(info->service_worker_ready_time().is_null());
@@ -831,7 +869,7 @@ TEST_F(ServiceWorkerURLRequestJobTest, NonExistentBlobUUIDResponse) {
EXPECT_TRUE(info->was_fetched_via_service_worker());
EXPECT_FALSE(info->was_fallback_required());
EXPECT_EQ(0u, info->url_list_via_service_worker().size());
- EXPECT_EQ(blink::kWebServiceWorkerResponseTypeDefault,
+ EXPECT_EQ(network::mojom::FetchResponseType::kDefault,
info->response_type_via_service_worker());
EXPECT_FALSE(info->service_worker_start_time().is_null());
EXPECT_FALSE(info->service_worker_ready_time().is_null());
@@ -863,9 +901,9 @@ class StreamResponder : public EmbeddedWorkerTestHelper {
response_callback->OnResponseStream(
ServiceWorkerResponse(
base::MakeUnique<std::vector<GURL>>(), 200, "OK",
- blink::kWebServiceWorkerResponseTypeDefault, MakeHeaders(), "", 0,
- blink::kWebServiceWorkerResponseErrorUnknown, base::Time(),
- false /* response_is_in_cache_storage */,
+ network::mojom::FetchResponseType::kDefault, MakeHeaders(), "", 0,
+ nullptr /* blob */, blink::kWebServiceWorkerResponseErrorUnknown,
+ base::Time(), false /* response_is_in_cache_storage */,
std::string() /* response_cache_storage_cache_name */,
base::MakeUnique<
ServiceWorkerHeaderList>() /* cors_exposed_header_names */),
@@ -898,9 +936,8 @@ TEST_F(ServiceWorkerURLRequestJobTest, StreamResponse) {
for (int i = 0; i < 1024; ++i) {
expected_response += kTestData;
uint32_t written_bytes = sizeof(kTestData) - 1;
- MojoResult result =
- mojo::WriteDataRaw(data_pipe.producer_handle.get(), kTestData,
- &written_bytes, MOJO_WRITE_DATA_FLAG_NONE);
+ MojoResult result = data_pipe.producer_handle->WriteData(
+ kTestData, &written_bytes, MOJO_WRITE_DATA_FLAG_NONE);
ASSERT_EQ(MOJO_RESULT_OK, result);
EXPECT_EQ(sizeof(kTestData) - 1, written_bytes);
}
@@ -910,7 +947,7 @@ TEST_F(ServiceWorkerURLRequestJobTest, StreamResponse) {
EXPECT_FALSE(HasWork());
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(HasWork());
- EXPECT_TRUE(request_->status().is_success());
+ EXPECT_EQ(net::OK, url_request_delegate_.request_status());
net::HttpResponseHeaders* headers = request_->response_headers();
EXPECT_EQ(200, headers->response_code());
EXPECT_EQ("OK", headers->GetStatusText());
@@ -924,7 +961,7 @@ TEST_F(ServiceWorkerURLRequestJobTest, StreamResponse) {
EXPECT_TRUE(info->was_fetched_via_service_worker());
EXPECT_FALSE(info->was_fallback_required());
EXPECT_EQ(0u, info->url_list_via_service_worker().size());
- EXPECT_EQ(blink::kWebServiceWorkerResponseTypeDefault,
+ EXPECT_EQ(network::mojom::FetchResponseType::kDefault,
info->response_type_via_service_worker());
EXPECT_FALSE(info->service_worker_start_time().is_null());
EXPECT_FALSE(info->service_worker_ready_time().is_null());
@@ -951,9 +988,8 @@ TEST_F(ServiceWorkerURLRequestJobTest, StreamResponse_ConsecutiveRead) {
for (int i = 0; i < 1024; ++i) {
expected_response += kTestData;
uint32_t written_bytes = sizeof(kTestData) - 1;
- MojoResult result =
- mojo::WriteDataRaw(data_pipe.producer_handle.get(), kTestData,
- &written_bytes, MOJO_WRITE_DATA_FLAG_NONE);
+ MojoResult result = data_pipe.producer_handle->WriteData(
+ kTestData, &written_bytes, MOJO_WRITE_DATA_FLAG_NONE);
ASSERT_EQ(MOJO_RESULT_OK, result);
EXPECT_EQ(sizeof(kTestData) - 1, written_bytes);
base::RunLoop().RunUntilIdle();
@@ -961,7 +997,10 @@ TEST_F(ServiceWorkerURLRequestJobTest, StreamResponse_ConsecutiveRead) {
}
stream_callback->OnCompleted();
base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(request_->status().is_success());
+
+ // IO is still pending since |producer_handle| is not yet reset, but the data
+ // should have been received by now.
+ EXPECT_EQ(net::ERR_IO_PENDING, url_request_delegate_.request_status());
EXPECT_EQ(200,
request_->response_headers()->response_code());
EXPECT_EQ("OK",
@@ -975,7 +1014,7 @@ TEST_F(ServiceWorkerURLRequestJobTest, StreamResponse_ConsecutiveRead) {
EXPECT_TRUE(info->was_fetched_via_service_worker());
EXPECT_FALSE(info->was_fallback_required());
EXPECT_EQ(0u, info->url_list_via_service_worker().size());
- EXPECT_EQ(blink::kWebServiceWorkerResponseTypeDefault,
+ EXPECT_EQ(network::mojom::FetchResponseType::kDefault,
info->response_type_via_service_worker());
EXPECT_FALSE(info->service_worker_start_time().is_null());
EXPECT_FALSE(info->service_worker_ready_time().is_null());
@@ -1000,9 +1039,8 @@ TEST_F(ServiceWorkerURLRequestJobTest, StreamResponseAndCancel) {
for (int i = 0; i < 512; ++i) {
uint32_t written_bytes = sizeof(kTestData) - 1;
- MojoResult result =
- mojo::WriteDataRaw(data_pipe.producer_handle.get(), kTestData,
- &written_bytes, MOJO_WRITE_DATA_FLAG_NONE);
+ MojoResult result = data_pipe.producer_handle->WriteData(
+ kTestData, &written_bytes, MOJO_WRITE_DATA_FLAG_NONE);
ASSERT_EQ(MOJO_RESULT_OK, result);
EXPECT_EQ(sizeof(kTestData) - 1, written_bytes);
}
@@ -1012,16 +1050,15 @@ TEST_F(ServiceWorkerURLRequestJobTest, StreamResponseAndCancel) {
// Fail to write the data pipe because it's already canceled.
uint32_t written_bytes = sizeof(kTestData) - 1;
- MojoResult result =
- mojo::WriteDataRaw(data_pipe.producer_handle.get(), kTestData,
- &written_bytes, MOJO_WRITE_DATA_FLAG_NONE);
+ MojoResult result = data_pipe.producer_handle->WriteData(
+ kTestData, &written_bytes, MOJO_WRITE_DATA_FLAG_NONE);
ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result);
stream_callback->OnAborted();
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(data_pipe.consumer_handle.is_valid());
- EXPECT_FALSE(request_->status().is_success());
+ EXPECT_EQ(net::ERR_ABORTED, url_request_delegate_.request_status());
EXPECT_EQ(0, times_prepare_to_restart_invoked_);
ServiceWorkerResponseInfo* info =
@@ -1030,7 +1067,7 @@ TEST_F(ServiceWorkerURLRequestJobTest, StreamResponseAndCancel) {
EXPECT_TRUE(info->was_fetched_via_service_worker());
EXPECT_FALSE(info->was_fallback_required());
EXPECT_EQ(0u, info->url_list_via_service_worker().size());
- EXPECT_EQ(blink::kWebServiceWorkerResponseTypeDefault,
+ EXPECT_EQ(network::mojom::FetchResponseType::kDefault,
info->response_type_via_service_worker());
EXPECT_FALSE(info->service_worker_start_time().is_null());
EXPECT_FALSE(info->service_worker_ready_time().is_null());
@@ -1055,9 +1092,8 @@ TEST_F(ServiceWorkerURLRequestJobTest, StreamResponse_Abort) {
for (int i = 0; i < 1024; ++i) {
expected_response += kTestData;
uint32_t written_bytes = sizeof(kTestData) - 1;
- MojoResult result =
- mojo::WriteDataRaw(data_pipe.producer_handle.get(), kTestData,
- &written_bytes, MOJO_WRITE_DATA_FLAG_NONE);
+ MojoResult result = data_pipe.producer_handle->WriteData(
+ kTestData, &written_bytes, MOJO_WRITE_DATA_FLAG_NONE);
ASSERT_EQ(MOJO_RESULT_OK, result);
EXPECT_EQ(sizeof(kTestData) - 1, written_bytes);
}
@@ -1067,7 +1103,8 @@ TEST_F(ServiceWorkerURLRequestJobTest, StreamResponse_Abort) {
EXPECT_FALSE(HasWork());
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(HasWork());
- EXPECT_FALSE(request_->status().is_success());
+ EXPECT_EQ(net::ERR_CONNECTION_RESET, url_request_delegate_.request_status());
+
net::HttpResponseHeaders* headers = request_->response_headers();
EXPECT_EQ(200, headers->response_code());
EXPECT_EQ("OK", headers->GetStatusText());
@@ -1081,7 +1118,7 @@ TEST_F(ServiceWorkerURLRequestJobTest, StreamResponse_Abort) {
EXPECT_TRUE(info->was_fetched_via_service_worker());
EXPECT_FALSE(info->was_fallback_required());
EXPECT_EQ(0u, info->url_list_via_service_worker().size());
- EXPECT_EQ(blink::kWebServiceWorkerResponseTypeDefault,
+ EXPECT_EQ(network::mojom::FetchResponseType::kDefault,
info->response_type_via_service_worker());
EXPECT_FALSE(info->service_worker_start_time().is_null());
EXPECT_FALSE(info->service_worker_ready_time().is_null());
@@ -1105,20 +1142,16 @@ TEST_F(ServiceWorkerURLRequestJobTest, StreamResponse_AbortBeforeData) {
request_->set_method("GET");
request_->Start();
base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(request_->status().is_io_pending());
-
stream_callback->OnAborted();
base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(request_->status().is_io_pending());
std::string expected_response;
expected_response.reserve((sizeof(kTestData) - 1) * 1024);
for (int i = 0; i < 1024; ++i) {
expected_response += kTestData;
uint32_t written_bytes = sizeof(kTestData) - 1;
- MojoResult result =
- mojo::WriteDataRaw(data_pipe.producer_handle.get(), kTestData,
- &written_bytes, MOJO_WRITE_DATA_FLAG_NONE);
+ MojoResult result = data_pipe.producer_handle->WriteData(
+ kTestData, &written_bytes, MOJO_WRITE_DATA_FLAG_NONE);
ASSERT_EQ(MOJO_RESULT_OK, result);
EXPECT_EQ(sizeof(kTestData) - 1, written_bytes);
base::RunLoop().RunUntilIdle();
@@ -1128,7 +1161,6 @@ TEST_F(ServiceWorkerURLRequestJobTest, StreamResponse_AbortBeforeData) {
data_pipe.producer_handle.reset();
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(net::ERR_CONNECTION_RESET, request_->status().ToNetError());
EXPECT_EQ(net::ERR_CONNECTION_RESET, url_request_delegate_.request_status());
EXPECT_EQ(200,
request_->response_headers()->response_code());
@@ -1143,7 +1175,7 @@ TEST_F(ServiceWorkerURLRequestJobTest, StreamResponse_AbortBeforeData) {
EXPECT_TRUE(info->was_fetched_via_service_worker());
EXPECT_FALSE(info->was_fallback_required());
EXPECT_EQ(0u, info->url_list_via_service_worker().size());
- EXPECT_EQ(blink::kWebServiceWorkerResponseTypeDefault,
+ EXPECT_EQ(network::mojom::FetchResponseType::kDefault,
info->response_type_via_service_worker());
EXPECT_FALSE(info->service_worker_start_time().is_null());
EXPECT_FALSE(info->service_worker_ready_time().is_null());
@@ -1164,18 +1196,11 @@ TEST_F(ServiceWorkerURLRequestJobTest, StreamResponse_AbortAfterData) {
request_->set_method("GET");
request_->Start();
base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(request_->status().is_io_pending());
-
data_pipe.producer_handle.reset();
base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(request_->status().is_io_pending());
-
stream_callback->OnAborted();
base::RunLoop().RunUntilIdle();
- EXPECT_FALSE(request_->status().is_io_pending());
- EXPECT_FALSE(request_->status().is_success());
- EXPECT_EQ(net::ERR_CONNECTION_RESET, request_->status().ToNetError());
EXPECT_EQ(net::ERR_CONNECTION_RESET, url_request_delegate_.request_status());
EXPECT_EQ(200, request_->response_headers()->response_code());
EXPECT_EQ("OK", request_->response_headers()->GetStatusText());
@@ -1188,7 +1213,7 @@ TEST_F(ServiceWorkerURLRequestJobTest, StreamResponse_AbortAfterData) {
EXPECT_TRUE(info->was_fetched_via_service_worker());
EXPECT_FALSE(info->was_fallback_required());
EXPECT_EQ(0u, info->url_list_via_service_worker().size());
- EXPECT_EQ(blink::kWebServiceWorkerResponseTypeDefault,
+ EXPECT_EQ(network::mojom::FetchResponseType::kDefault,
info->response_type_via_service_worker());
EXPECT_FALSE(info->service_worker_start_time().is_null());
EXPECT_FALSE(info->service_worker_ready_time().is_null());
@@ -1212,9 +1237,8 @@ TEST_F(ServiceWorkerURLRequestJobTest, StreamResponse_ConsecutiveReadAndAbort) {
for (int i = 0; i < 512; ++i) {
expected_response += kTestData;
uint32_t written_bytes = sizeof(kTestData) - 1;
- MojoResult result =
- mojo::WriteDataRaw(data_pipe.producer_handle.get(), kTestData,
- &written_bytes, MOJO_WRITE_DATA_FLAG_NONE);
+ MojoResult result = data_pipe.producer_handle->WriteData(
+ kTestData, &written_bytes, MOJO_WRITE_DATA_FLAG_NONE);
ASSERT_EQ(MOJO_RESULT_OK, result);
EXPECT_EQ(sizeof(kTestData) - 1, written_bytes);
@@ -1226,7 +1250,9 @@ TEST_F(ServiceWorkerURLRequestJobTest, StreamResponse_ConsecutiveReadAndAbort) {
base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(request_->status().is_success());
+ // IO is still pending since |producer_handle| is not yet reset, but the data
+ // should have been received by now.
+ EXPECT_EQ(net::ERR_IO_PENDING, url_request_delegate_.request_status());
EXPECT_EQ(200, request_->response_headers()->response_code());
EXPECT_EQ("OK", request_->response_headers()->GetStatusText());
EXPECT_EQ(expected_response, url_request_delegate_.data_received());
@@ -1238,7 +1264,7 @@ TEST_F(ServiceWorkerURLRequestJobTest, StreamResponse_ConsecutiveReadAndAbort) {
EXPECT_TRUE(info->was_fetched_via_service_worker());
EXPECT_FALSE(info->was_fallback_required());
EXPECT_EQ(0u, info->url_list_via_service_worker().size());
- EXPECT_EQ(blink::kWebServiceWorkerResponseTypeDefault,
+ EXPECT_EQ(network::mojom::FetchResponseType::kDefault,
info->response_type_via_service_worker());
EXPECT_FALSE(info->service_worker_start_time().is_null());
EXPECT_FALSE(info->service_worker_ready_time().is_null());
@@ -1278,7 +1304,7 @@ TEST_F(ServiceWorkerURLRequestJobTest, FailFetchDispatch) {
request_->Start();
base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(request_->status().is_success());
+ EXPECT_EQ(net::OK, url_request_delegate_.request_status());
// We should have fallen back to network.
EXPECT_EQ(200, request_->GetResponseCode());
EXPECT_EQ("PASS", url_request_delegate_.data_received());
@@ -1286,7 +1312,7 @@ TEST_F(ServiceWorkerURLRequestJobTest, FailFetchDispatch) {
ServiceWorkerProviderHost* host = helper_->context()->GetProviderHost(
helper_->mock_render_process_id(), kProviderID);
ASSERT_TRUE(host);
- EXPECT_EQ(host->controlling_version(), nullptr);
+ EXPECT_EQ(host->controller(), nullptr);
EXPECT_EQ(1, times_prepare_to_restart_invoked_);
ServiceWorkerResponseInfo* info =
@@ -1302,7 +1328,7 @@ TEST_F(ServiceWorkerURLRequestJobTest, FailToActivate_MainResource) {
// The load should fail and we should have fallen back to network because
// this is a main resource request.
- EXPECT_TRUE(request_->status().is_success());
+ EXPECT_EQ(net::OK, url_request_delegate_.request_status());
EXPECT_EQ(200, request_->GetResponseCode());
EXPECT_EQ("PASS", url_request_delegate_.data_received());
@@ -1310,7 +1336,7 @@ TEST_F(ServiceWorkerURLRequestJobTest, FailToActivate_MainResource) {
ServiceWorkerProviderHost* host = helper_->context()->GetProviderHost(
helper_->mock_render_process_id(), kProviderID);
ASSERT_TRUE(host);
- EXPECT_EQ(host->controlling_version(), nullptr);
+ EXPECT_EQ(host->controller(), nullptr);
}
TEST_F(ServiceWorkerURLRequestJobTest, FailToActivate_Subresource) {
@@ -1319,7 +1345,7 @@ TEST_F(ServiceWorkerURLRequestJobTest, FailToActivate_Subresource) {
// The load should fail and we should not fall back to network because
// this is a subresource request.
- EXPECT_TRUE(request_->status().is_success());
+ EXPECT_EQ(net::OK, url_request_delegate_.request_status());
EXPECT_EQ(500, request_->GetResponseCode());
EXPECT_EQ("Service Worker Response Error",
request_->response_headers()->GetStatusText());
@@ -1328,7 +1354,7 @@ TEST_F(ServiceWorkerURLRequestJobTest, FailToActivate_Subresource) {
ServiceWorkerProviderHost* host = helper_->context()->GetProviderHost(
helper_->mock_render_process_id(), kProviderID);
ASSERT_TRUE(host);
- EXPECT_EQ(host->controlling_version(), version_);
+ EXPECT_EQ(host->controller(), version_);
}
class EarlyResponseHelper : public EmbeddedWorkerTestHelper {
@@ -1352,10 +1378,10 @@ class EarlyResponseHelper : public EmbeddedWorkerTestHelper {
response_callback->OnResponse(
ServiceWorkerResponse(
base::MakeUnique<std::vector<GURL>>(), 200, "OK",
- blink::kWebServiceWorkerResponseTypeDefault,
+ network::mojom::FetchResponseType::kDefault,
base::MakeUnique<ServiceWorkerHeaderMap>(), std::string(), 0,
- blink::kWebServiceWorkerResponseErrorUnknown, base::Time(),
- false /* response_is_in_cache_storage */,
+ nullptr /* blob */, blink::kWebServiceWorkerResponseErrorUnknown,
+ base::Time(), false /* response_is_in_cache_storage */,
std::string() /* response_cache_storage_cache_name */,
base::MakeUnique<
ServiceWorkerHeaderList>() /* cors_exposed_header_names */),
@@ -1384,7 +1410,7 @@ TEST_F(ServiceWorkerURLRequestJobTest, EarlyResponse) {
EXPECT_TRUE(info->was_fetched_via_service_worker());
EXPECT_FALSE(info->was_fallback_required());
EXPECT_EQ(0u, info->url_list_via_service_worker().size());
- EXPECT_EQ(blink::kWebServiceWorkerResponseTypeDefault,
+ EXPECT_EQ(network::mojom::FetchResponseType::kDefault,
info->response_type_via_service_worker());
EXPECT_FALSE(info->service_worker_start_time().is_null());
EXPECT_FALSE(info->service_worker_ready_time().is_null());
diff --git a/chromium/content/browser/service_worker/service_worker_version.cc b/chromium/content/browser/service_worker/service_worker_version.cc
index d387881aecc..bb9f2505cbe 100644
--- a/chromium/content/browser/service_worker/service_worker_version.cc
+++ b/chromium/content/browser/service_worker/service_worker_version.cc
@@ -20,6 +20,7 @@
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "base/time/default_clock.h"
#include "base/time/default_tick_clock.h"
#include "content/browser/bad_message.h"
#include "content/browser/child_process_security_policy_impl.h"
@@ -43,6 +44,7 @@
#include "content/public/common/result_codes.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_response_info.h"
+#include "third_party/WebKit/public/platform/modules/serviceworker/service_worker_error_type.mojom.h"
#include "third_party/WebKit/public/web/WebConsoleMessage.h"
namespace content {
@@ -78,9 +80,10 @@ const char kForceUpdateInfoMessage[] =
"Service Worker was updated because \"Update on reload\" was "
"checked in the DevTools Application panel.";
-void RunSoon(const base::Closure& callback) {
+void RunSoon(base::OnceClosure callback) {
if (!callback.is_null())
- base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, callback);
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+ std::move(callback));
}
template <typename CallbackArray, typename Arg>
@@ -101,11 +104,10 @@ void RunStartWorkerCallback(
}
// A callback adapter to start a |task| after StartWorker.
-void RunTaskAfterStartWorker(
- base::WeakPtr<ServiceWorkerVersion> version,
- const StatusCallback& error_callback,
- const base::Closure& task,
- ServiceWorkerStatusCode status) {
+void RunTaskAfterStartWorker(base::WeakPtr<ServiceWorkerVersion> version,
+ const StatusCallback& error_callback,
+ base::OnceClosure task,
+ ServiceWorkerStatusCode status) {
if (status != SERVICE_WORKER_OK) {
if (!error_callback.is_null())
error_callback.Run(status);
@@ -119,7 +121,7 @@ void RunTaskAfterStartWorker(
error_callback.Run(SERVICE_WORKER_ERROR_START_WORKER_FAILED);
return;
}
- task.Run();
+ std::move(task).Run();
}
void KillEmbeddedWorkerProcess(int process_id, ResultCode code) {
@@ -136,21 +138,6 @@ void ClearTick(base::TimeTicks* time) {
*time = base::TimeTicks();
}
-bool IsInstalled(ServiceWorkerVersion::Status status) {
- switch (status) {
- case ServiceWorkerVersion::NEW:
- case ServiceWorkerVersion::INSTALLING:
- case ServiceWorkerVersion::REDUNDANT:
- return false;
- case ServiceWorkerVersion::INSTALLED:
- case ServiceWorkerVersion::ACTIVATING:
- case ServiceWorkerVersion::ACTIVATED:
- return true;
- }
- NOTREACHED() << "Unexpected status: " << status;
- return false;
-}
-
std::string VersionStatusToString(ServiceWorkerVersion::Status status) {
switch (status) {
case ServiceWorkerVersion::NEW:
@@ -202,6 +189,21 @@ void OnEventDispatcherConnectionError(
}
}
+mojom::ServiceWorkerProviderInfoForStartWorkerPtr
+CompleteProviderHostPreparation(
+ ServiceWorkerVersion* version,
+ std::unique_ptr<ServiceWorkerProviderHost> provider_host,
+ base::WeakPtr<ServiceWorkerContextCore> context,
+ int process_id) {
+ // Caller should ensure |context| is alive when completing StartWorker
+ // preparation.
+ DCHECK(context);
+ auto info =
+ provider_host->CompleteStartWorkerPreparation(process_id, version);
+ context->AddProviderHost(std::move(provider_host));
+ return info;
+}
+
} // namespace
constexpr base::TimeDelta ServiceWorkerVersion::kTimeoutTimerDelay;
@@ -290,7 +292,8 @@ ServiceWorkerVersion::ServiceWorkerVersion(
site_for_uma_(ServiceWorkerMetrics::SiteFromURL(scope_)),
context_(context),
script_cache_map_(this, context),
- tick_clock_(base::WrapUnique(new base::DefaultTickClock)),
+ tick_clock_(base::MakeUnique<base::DefaultTickClock>()),
+ clock_(base::MakeUnique<base::DefaultClock>()),
ping_controller_(new PingController(this)),
weak_factory_(this) {
DCHECK_NE(kInvalidServiceWorkerVersionId, version_id);
@@ -365,10 +368,10 @@ void ServiceWorkerVersion::SetStatus(Status status) {
for (auto& observer : listeners_)
observer.OnVersionStateChanged(this);
- std::vector<base::Closure> callbacks;
+ std::vector<base::OnceClosure> callbacks;
callbacks.swap(status_change_callbacks_);
- for (const auto& callback : callbacks)
- callback.Run();
+ for (auto& callback : callbacks)
+ std::move(callback).Run();
if (status == INSTALLED)
embedded_worker_->OnWorkerVersionInstalled();
@@ -377,8 +380,8 @@ void ServiceWorkerVersion::SetStatus(Status status) {
}
void ServiceWorkerVersion::RegisterStatusChangeCallback(
- const base::Closure& callback) {
- status_change_callbacks_.push_back(callback);
+ base::OnceClosure callback) {
+ status_change_callbacks_.push_back(std::move(callback));
}
ServiceWorkerVersionInfo ServiceWorkerVersion::GetInfo() {
@@ -432,14 +435,14 @@ void ServiceWorkerVersion::StartWorker(ServiceWorkerMetrics::EventType purpose,
RecordStartWorkerResult(purpose, status_, kInvalidTraceId,
is_browser_startup_complete,
SERVICE_WORKER_ERROR_ABORT);
- RunSoon(base::Bind(callback, SERVICE_WORKER_ERROR_ABORT));
+ RunSoon(base::BindOnce(callback, SERVICE_WORKER_ERROR_ABORT));
return;
}
if (is_redundant()) {
RecordStartWorkerResult(purpose, status_, kInvalidTraceId,
is_browser_startup_complete,
SERVICE_WORKER_ERROR_REDUNDANT);
- RunSoon(base::Bind(callback, SERVICE_WORKER_ERROR_REDUNDANT));
+ RunSoon(base::BindOnce(callback, SERVICE_WORKER_ERROR_REDUNDANT));
return;
}
@@ -454,12 +457,13 @@ void ServiceWorkerVersion::StartWorker(ServiceWorkerMetrics::EventType purpose,
RecordStartWorkerResult(purpose, status_, kInvalidTraceId,
is_browser_startup_complete,
SERVICE_WORKER_ERROR_DISALLOWED);
- RunSoon(base::Bind(callback, SERVICE_WORKER_ERROR_DISALLOWED));
+ RunSoon(base::BindOnce(callback, SERVICE_WORKER_ERROR_DISALLOWED));
return;
}
// Ensure the live registration during starting worker so that the worker can
- // get associated with it in SWDispatcherHost::OnSetHostedVersionId().
+ // get associated with it in
+ // ServiceWorkerProviderHost::CompleteStartWorkerPreparation.
context_->storage()->FindRegistrationForId(
registration_id_, scope_.GetOrigin(),
base::Bind(&ServiceWorkerVersion::DidEnsureLiveRegistrationForStartWorker,
@@ -476,13 +480,9 @@ void ServiceWorkerVersion::StopWorker(const StatusCallback& callback) {
switch (running_status()) {
case EmbeddedWorkerStatus::STARTING:
case EmbeddedWorkerStatus::RUNNING:
- // Stop() returns false when it's called before StartWorker message hasn't
- // been sent to the renderer process even though EmbeddedWorkerInstance is
- // stopped properly.
- // TODO(shimazu): Remove this check after Stop() hides the IPC behavior.
- // See also a TODO on EmbeddedWorkerInstance::Stop.
- if (!embedded_worker_->Stop()) {
- RunSoon(base::Bind(callback, SERVICE_WORKER_ERROR_IPC_FAILED));
+ embedded_worker_->Stop();
+ if (running_status() == EmbeddedWorkerStatus::STOPPED) {
+ RunSoon(base::BindOnce(callback, SERVICE_WORKER_OK));
return;
}
stop_callbacks_.push_back(callback);
@@ -491,9 +491,10 @@ void ServiceWorkerVersion::StopWorker(const StatusCallback& callback) {
stop_callbacks_.push_back(callback);
return;
case EmbeddedWorkerStatus::STOPPED:
- RunSoon(base::Bind(callback, SERVICE_WORKER_OK));
+ RunSoon(base::BindOnce(callback, SERVICE_WORKER_OK));
return;
}
+ NOTREACHED();
}
void ServiceWorkerVersion::ScheduleUpdate() {
@@ -551,7 +552,7 @@ int ServiceWorkerVersion::StartRequestWithCustomTimeout(
<< " can only be dispatched to an active worker: " << status();
int request_id = pending_requests_.Add(base::MakeUnique<PendingRequest>(
- error_callback, base::Time::Now(), tick_clock_->NowTicks(), event_type));
+ error_callback, clock_->Now(), tick_clock_->NowTicks(), event_type));
TRACE_EVENT_ASYNC_BEGIN2("ServiceWorker", "ServiceWorkerVersion::Request",
pending_requests_.Lookup(request_id), "Request id",
request_id, "Event type",
@@ -621,7 +622,7 @@ bool ServiceWorkerVersion::FinishExternalRequest(
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, base::Time::Now());
+ return FinishRequest(request_id, true, clock_->Now());
}
// It is possible that the request was cancelled or timed out before and we
@@ -640,16 +641,16 @@ ServiceWorkerVersion::CreateSimpleEventCallback(int request_id) {
void ServiceWorkerVersion::RunAfterStartWorker(
ServiceWorkerMetrics::EventType purpose,
- const base::Closure& task,
+ base::OnceClosure task,
const StatusCallback& error_callback) {
if (running_status() == EmbeddedWorkerStatus::RUNNING) {
DCHECK(start_callbacks_.empty());
- task.Run();
+ std::move(task).Run();
return;
}
StartWorker(purpose,
base::Bind(&RunTaskAfterStartWorker, weak_factory_.GetWeakPtr(),
- error_callback, task));
+ error_callback, base::Passed(std::move(task))));
}
void ServiceWorkerVersion::AddControllee(
@@ -742,8 +743,8 @@ void ServiceWorkerVersion::Doom() {
void ServiceWorkerVersion::SetValidOriginTrialTokens(
const TrialTokenValidator::FeatureToTokensMap& tokens) {
- origin_trial_tokens_ =
- TrialTokenValidator::GetValidTokens(url::Origin(scope()), tokens);
+ origin_trial_tokens_ = TrialTokenValidator::GetValidTokens(
+ url::Origin(scope()), tokens, clock_->Now());
}
void ServiceWorkerVersion::SetDevToolsAttached(bool attached) {
@@ -795,7 +796,7 @@ void ServiceWorkerVersion::SetMainScriptHttpResponseInfo(
// wasn't set in the entry.
if (!origin_trial_tokens_) {
origin_trial_tokens_ = TrialTokenValidator::GetValidTokensFromHeaders(
- url::Origin(scope()), http_info.headers.get());
+ url::Origin(scope()), http_info.headers.get(), clock_->Now());
}
for (auto& observer : listeners_)
@@ -811,6 +812,11 @@ void ServiceWorkerVersion::SetTickClockForTesting(
tick_clock_ = std::move(tick_clock);
}
+void ServiceWorkerVersion::SetClockForTesting(
+ std::unique_ptr<base::Clock> clock) {
+ clock_ = std::move(clock);
+}
+
const net::HttpResponseInfo*
ServiceWorkerVersion::GetMainScriptHttpResponseInfo() {
return main_script_http_info_.get();
@@ -848,6 +854,9 @@ ServiceWorkerVersion::PendingRequest::~PendingRequest() {}
void ServiceWorkerVersion::OnThreadStarted() {
DCHECK_EQ(EmbeddedWorkerStatus::STARTING, running_status());
+ DCHECK(provider_host_);
+ provider_host_->SetReadyToSendMessagesToWorker(
+ embedded_worker()->thread_id());
// Activate ping/pong now that JavaScript execution will start.
ping_controller_->Activate();
}
@@ -1066,6 +1075,21 @@ void ServiceWorkerVersion::CountFeature(uint32_t feature) {
provider_host_by_uuid.second->CountFeature(feature);
}
+bool ServiceWorkerVersion::IsInstalled(ServiceWorkerVersion::Status status) {
+ switch (status) {
+ case ServiceWorkerVersion::NEW:
+ case ServiceWorkerVersion::INSTALLING:
+ case ServiceWorkerVersion::REDUNDANT:
+ return false;
+ case ServiceWorkerVersion::INSTALLED:
+ case ServiceWorkerVersion::ACTIVATING:
+ case ServiceWorkerVersion::ACTIVATED:
+ return true;
+ }
+ NOTREACHED() << "Unexpected status: " << status;
+ return false;
+}
+
void ServiceWorkerVersion::OnOpenNewTab(int request_id, const GURL& url) {
OnOpenWindow(request_id, url, WindowOpenDisposition::NEW_FOREGROUND_TAB);
}
@@ -1084,9 +1108,9 @@ void ServiceWorkerVersion::OnOpenWindow(int request_id,
if (!url.is_valid()) {
DVLOG(1) << "Received unexpected invalid URL from renderer process.";
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(&KillEmbeddedWorkerProcess,
- embedded_worker_->process_id(),
- RESULT_CODE_KILLED_BAD_MESSAGE));
+ base::BindOnce(&KillEmbeddedWorkerProcess,
+ embedded_worker_->process_id(),
+ RESULT_CODE_KILLED_BAD_MESSAGE));
return;
}
@@ -1247,10 +1271,10 @@ void ServiceWorkerVersion::OnNavigateClient(int request_id,
if (!url.is_valid() || !base::IsValidGUID(client_uuid)) {
DVLOG(1) << "Received unexpected invalid URL/UUID from renderer process.";
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&KillEmbeddedWorkerProcess, embedded_worker_->process_id(),
- RESULT_CODE_KILLED_BAD_MESSAGE));
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&KillEmbeddedWorkerProcess,
+ embedded_worker_->process_id(),
+ RESULT_CODE_KILLED_BAD_MESSAGE));
return;
}
@@ -1326,7 +1350,7 @@ void ServiceWorkerVersion::DidSkipWaiting(int request_id) {
void ServiceWorkerVersion::OnClaimClients(int request_id) {
if (status_ != ACTIVATING && status_ != ACTIVATED) {
embedded_worker_->SendMessage(ServiceWorkerMsg_ClaimClientsError(
- request_id, blink::WebServiceWorkerError::kErrorTypeState,
+ request_id, blink::mojom::ServiceWorkerErrorType::kState,
base::ASCIIToUTF16(kClaimClientsStateErrorMesage)));
return;
}
@@ -1341,7 +1365,7 @@ void ServiceWorkerVersion::OnClaimClients(int request_id) {
}
embedded_worker_->SendMessage(ServiceWorkerMsg_ClaimClientsError(
- request_id, blink::WebServiceWorkerError::kErrorTypeAbort,
+ request_id, blink::mojom::ServiceWorkerErrorType::kAbort,
base::ASCIIToUTF16(kClaimClientsShutdownErrorMesage)));
}
@@ -1362,20 +1386,20 @@ void ServiceWorkerVersion::RegisterForeignFetchScopes(
!base::StartsWith(url.path(), scope_path,
base::CompareCase::SENSITIVE)) {
DVLOG(1) << "Received unexpected invalid URL from renderer process.";
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&KillEmbeddedWorkerProcess, embedded_worker_->process_id(),
- RESULT_CODE_KILLED_BAD_MESSAGE));
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&KillEmbeddedWorkerProcess,
+ embedded_worker_->process_id(),
+ RESULT_CODE_KILLED_BAD_MESSAGE));
return;
}
}
for (const url::Origin& url : origins) {
if (url.unique()) {
DVLOG(1) << "Received unexpected unique origin from renderer process.";
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&KillEmbeddedWorkerProcess, embedded_worker_->process_id(),
- RESULT_CODE_KILLED_BAD_MESSAGE));
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&KillEmbeddedWorkerProcess,
+ embedded_worker_->process_id(),
+ RESULT_CODE_KILLED_BAD_MESSAGE));
return;
}
}
@@ -1405,14 +1429,14 @@ void ServiceWorkerVersion::DidEnsureLiveRegistrationForStartWorker(
if (status != SERVICE_WORKER_OK) {
RecordStartWorkerResult(purpose, prestart_status, kInvalidTraceId,
is_browser_startup_complete, status);
- RunSoon(base::Bind(callback, SERVICE_WORKER_ERROR_START_WORKER_FAILED));
+ RunSoon(base::BindOnce(callback, SERVICE_WORKER_ERROR_START_WORKER_FAILED));
return;
}
if (is_redundant()) {
RecordStartWorkerResult(purpose, prestart_status, kInvalidTraceId,
is_browser_startup_complete,
SERVICE_WORKER_ERROR_REDUNDANT);
- RunSoon(base::Bind(callback, SERVICE_WORKER_ERROR_REDUNDANT));
+ RunSoon(base::BindOnce(callback, SERVICE_WORKER_ERROR_REDUNDANT));
return;
}
@@ -1420,7 +1444,7 @@ void ServiceWorkerVersion::DidEnsureLiveRegistrationForStartWorker(
switch (running_status()) {
case EmbeddedWorkerStatus::RUNNING:
- RunSoon(base::Bind(callback, SERVICE_WORKER_OK));
+ RunSoon(base::BindOnce(callback, SERVICE_WORKER_OK));
return;
case EmbeddedWorkerStatus::STARTING:
DCHECK(!start_callbacks_.empty());
@@ -1468,6 +1492,10 @@ void ServiceWorkerVersion::StartWorkerInternal() {
StartTimeoutTimer();
+ std::unique_ptr<ServiceWorkerProviderHost> pending_provider_host =
+ ServiceWorkerProviderHost::PreCreateForController(context());
+ provider_host_ = pending_provider_host->AsWeakPtr();
+
auto params = base::MakeUnique<EmbeddedWorkerStartParams>();
params->service_worker_version_id = version_id_;
params->scope = scope_;
@@ -1476,19 +1504,31 @@ void ServiceWorkerVersion::StartWorkerInternal() {
params->pause_after_download = pause_after_download_;
mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info;
- if (ServiceWorkerUtils::IsScriptStreamingEnabled()) {
+ if (ServiceWorkerUtils::IsScriptStreamingEnabled() &&
+ !pause_after_download_) {
DCHECK(!installed_scripts_sender_);
installed_scripts_sender_ =
- base::MakeUnique<ServiceWorkerInstalledScriptsSender>();
+ base::MakeUnique<ServiceWorkerInstalledScriptsSender>(
+ this, script_url(), context());
installed_scripts_info = installed_scripts_sender_->CreateInfoAndBind();
+ installed_scripts_sender_->Start();
}
+ auto event_dispatcher_request = mojo::MakeRequest(&event_dispatcher_);
+ // TODO(horo): These CHECKs are for debugging crbug.com/759938.
+ CHECK(event_dispatcher_.is_bound());
+ CHECK(event_dispatcher_request.is_pending());
+
embedded_worker_->Start(
- std::move(params), mojo::MakeRequest(&event_dispatcher_),
- std::move(installed_scripts_info),
+ std::move(params),
+ // Unretained is used here because the callback will be owned by
+ // |embedded_worker_| whose owner is |this|.
+ base::BindOnce(&CompleteProviderHostPreparation, base::Unretained(this),
+ base::Passed(&pending_provider_host), context()),
+ std::move(event_dispatcher_request), std::move(installed_scripts_info),
base::Bind(&ServiceWorkerVersion::OnStartSentAndScriptEvaluated,
weak_factory_.GetWeakPtr()));
- event_dispatcher_.set_connection_error_handler(base::Bind(
+ event_dispatcher_.set_connection_error_handler(base::BindOnce(
&OnEventDispatcherConnectionError, embedded_worker_->AsWeakPtr()));
}
@@ -1557,7 +1597,10 @@ void ServiceWorkerVersion::OnTimeoutTimer() {
// Detach the worker. Remove |this| as a listener first; otherwise
// OnStoppedInternal might try to restart before the new worker
- // is created.
+ // is created. Also, protect |this|, since swapping out the
+ // EmbeddedWorkerInstance could destroy our ServiceWorkerProviderHost
+ // which could in turn destroy |this|.
+ scoped_refptr<ServiceWorkerVersion> protect_this(this);
embedded_worker_->RemoveListener(this);
embedded_worker_->Detach();
embedded_worker_ = context_->embedded_worker_registry()->CreateWorker();
@@ -1626,8 +1669,8 @@ void ServiceWorkerVersion::PingWorker() {
DCHECK(running_status() == EmbeddedWorkerStatus::STARTING ||
running_status() == EmbeddedWorkerStatus::RUNNING);
// base::Unretained here is safe because event_dispatcher is owned by |this|.
- event_dispatcher()->Ping(base::Bind(&ServiceWorkerVersion::OnPongFromWorker,
- base::Unretained(this)));
+ event_dispatcher()->Ping(base::BindOnce(
+ &ServiceWorkerVersion::OnPongFromWorker, base::Unretained(this)));
}
void ServiceWorkerVersion::OnPingTimeout() {
@@ -1673,6 +1716,10 @@ void ServiceWorkerVersion::RecordStartWorkerResult(
if (context_ && IsInstalled(prestart_status))
context_->UpdateVersionFailureCount(version_id_, status);
+ if (installed_scripts_sender_) {
+ ServiceWorkerMetrics::RecordInstalledScriptsSenderStatus(
+ installed_scripts_sender_->finished_reason());
+ }
ServiceWorkerMetrics::RecordStartWorkerStatus(status, purpose,
IsInstalled(prestart_status));
@@ -1766,7 +1813,7 @@ void ServiceWorkerVersion::MarkIfStale() {
if (!registration || registration->active_version() != this)
return;
base::TimeDelta time_since_last_check =
- base::Time::Now() - registration->last_update_check();
+ clock_->Now() - registration->last_update_check();
if (time_since_last_check > kServiceWorkerScriptMaxCacheAge)
RestartTick(&stale_time_);
}
@@ -1808,8 +1855,9 @@ void ServiceWorkerVersion::OnStoppedInternal(EmbeddedWorkerStatus old_status) {
// This worker is unresponsive and restart may fail.
should_restart = false;
} else if (old_status == EmbeddedWorkerStatus::STARTING) {
- // This worker unexpectedly stopped because of start failure (e.g., process
- // allocation failure) and restart is likely to fail again.
+ // This worker unexpectedly stopped because start failed. Attempting to
+ // restart on start failure could cause an endless loop of start attempts,
+ // so don't try to restart now.
should_restart = false;
}
@@ -1833,7 +1881,8 @@ void ServiceWorkerVersion::OnStoppedInternal(EmbeddedWorkerStatus old_status) {
// Let all message callbacks fail (this will also fire and clear all
// callbacks for events).
// TODO(kinuko): Consider if we want to add queue+resend mechanism here.
- IDMap<std::unique_ptr<PendingRequest>>::iterator iter(&pending_requests_);
+ base::IDMap<std::unique_ptr<PendingRequest>>::iterator iter(
+ &pending_requests_);
while (!iter.IsAtEnd()) {
TRACE_EVENT_ASYNC_END1("ServiceWorker", "ServiceWorkerVersion::Request",
iter.GetCurrentValue(), "Error", "Worker Stopped");
diff --git a/chromium/content/browser/service_worker/service_worker_version.h b/chromium/content/browser/service_worker/service_worker_version.h
index cd9c7ec34fb..b037d6f9285 100644
--- a/chromium/content/browser/service_worker/service_worker_version.h
+++ b/chromium/content/browser/service_worker/service_worker_version.h
@@ -17,14 +17,15 @@
#include <vector>
#include "base/callback.h"
+#include "base/containers/id_map.h"
#include "base/gtest_prod_util.h"
-#include "base/id_map.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/memory/ref_counted.h"
#include "base/observer_list.h"
#include "base/optional.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "base/time/clock.h"
#include "base/time/tick_clock.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
@@ -66,7 +67,7 @@ struct ServiceWorkerVersionInfo;
// one of them is activated. This class connects the actual script with a
// running worker.
class CONTENT_EXPORT ServiceWorkerVersion
- : NON_EXPORTED_BASE(public base::RefCounted<ServiceWorkerVersion>),
+ : public base::RefCounted<ServiceWorkerVersion>,
public EmbeddedWorkerInstance::Listener {
public:
using StatusCallback = base::Callback<void(ServiceWorkerStatusCode)>;
@@ -196,7 +197,7 @@ class CONTENT_EXPORT ServiceWorkerVersion
// Registers status change callback. (This is for one-off observation,
// the consumer needs to re-register if it wants to continue observing
// status changes)
- void RegisterStatusChangeCallback(const base::Closure& callback);
+ void RegisterStatusChangeCallback(base::OnceClosure callback);
// Starts an embedded worker for this version.
// This returns OK (success) if the worker is already running.
@@ -227,7 +228,7 @@ class CONTENT_EXPORT ServiceWorkerVersion
// this method returns).
// |purpose| is used for UMA.
void RunAfterStartWorker(ServiceWorkerMetrics::EventType purpose,
- const base::Closure& task,
+ base::OnceClosure task,
const StatusCallback& error_callback);
// Call this while the worker is running before dispatching an event to the
@@ -289,15 +290,6 @@ class CONTENT_EXPORT ServiceWorkerVersion
return event_dispatcher_.get();
}
- // This method registers a callback to receive messages sent back from the
- // service worker in response to |request_id|.
- // ResponseMessage is the type of the IPC message that is used for the
- // response, and its first argument MUST be the request_id.
- // Callback registration should be done once for one request_id.
- template <typename ResponseMessage, typename ResponseCallbackType>
- void RegisterRequestCallback(int request_id,
- const ResponseCallbackType& callback);
-
// Adds and removes |provider_host| as a controllee of this ServiceWorker.
void AddControllee(ServiceWorkerProviderHost* provider_host);
void RemoveControllee(ServiceWorkerProviderHost* provider_host);
@@ -308,6 +300,13 @@ class CONTENT_EXPORT ServiceWorkerVersion
return controllee_map_;
}
+ // The provider host hosting this version. Only valid while the version is
+ // running.
+ ServiceWorkerProviderHost* provider_host() {
+ DCHECK(provider_host_);
+ return provider_host_.get();
+ }
+
base::WeakPtr<ServiceWorkerContextCore> context() const { return context_; }
// Adds and removes |request_job| as a dependent job not to stop the
@@ -352,6 +351,8 @@ class CONTENT_EXPORT ServiceWorkerVersion
force_bypass_cache_for_scripts_ = force_bypass_cache_for_scripts;
}
+ // Used for pausing service worker startup in the renderer in order to do the
+ // byte-for-byte check.
bool pause_after_download() const { return pause_after_download_; }
void set_pause_after_download(bool pause_after_download) {
pause_after_download_ = pause_after_download;
@@ -385,6 +386,9 @@ class CONTENT_EXPORT ServiceWorkerVersion
// Used to allow tests to change time for testing.
void SetTickClockForTesting(std::unique_ptr<base::TickClock> tick_clock);
+ // Used to allow tests to change wall clock for testing.
+ void SetClockForTesting(std::unique_ptr<base::Clock> clock);
+
// Returns true if the service worker has work to do: it has pending
// requests, in-progress streaming URLRequestJobs, or pending start callbacks.
bool HasWork() const;
@@ -406,6 +410,8 @@ class CONTENT_EXPORT ServiceWorkerVersion
}
const std::set<uint32_t>& used_features() const { return used_features_; }
+ static bool IsInstalled(ServiceWorkerVersion::Status status);
+
private:
friend class base::RefCounted<ServiceWorkerVersion>;
friend class ServiceWorkerReadFromCacheJobTest;
@@ -434,6 +440,8 @@ class CONTENT_EXPORT ServiceWorkerVersion
TimeoutWorkerInEvent);
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerStallInStoppingTest, DetachThenStart);
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerStallInStoppingTest, DetachThenRestart);
+ FRIEND_TEST_ALL_PREFIXES(ServiceWorkerStallInStoppingTest,
+ DetachThenRestartNoCrash);
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTest,
RegisterForeignFetchScopes);
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTest, RequestNowTimeout);
@@ -465,22 +473,10 @@ class CONTENT_EXPORT ServiceWorkerVersion
ServiceWorkerMetrics::EventType event_type);
~PendingRequest();
- // ------------------------------------------------------------------------
- // For all requests. Set by StartRequest.
- // ------------------------------------------------------------------------
StatusCallback error_callback;
base::Time start_time;
base::TimeTicks start_time_ticks;
ServiceWorkerMetrics::EventType event_type;
-
- // ------------------------------------------------------------------------
- // For IPC message requests.
- // ------------------------------------------------------------------------
- // Set by RegisterRequestCallback. Receives IPC responses to the request via
- // OnMessageReceived.
- std::unique_ptr<EmbeddedWorkerInstance::Listener> listener;
- // True if an IPC message was sent to dispatch the event for this request.
- bool is_dispatched = false;
};
using ServiceWorkerClients = std::vector<ServiceWorkerClientInfo>;
@@ -704,11 +700,11 @@ class CONTENT_EXPORT ServiceWorkerVersion
std::unique_ptr<EmbeddedWorkerInstance> embedded_worker_;
std::vector<StatusCallback> start_callbacks_;
std::vector<StatusCallback> stop_callbacks_;
- std::vector<base::Closure> status_change_callbacks_;
+ std::vector<base::OnceClosure> status_change_callbacks_;
// Holds in-flight requests, including requests due to outstanding push,
// fetch, sync, etc. events.
- IDMap<std::unique_ptr<PendingRequest>> pending_requests_;
+ base::IDMap<std::unique_ptr<PendingRequest>> pending_requests_;
// Container for pending external requests for this service worker.
// (key, value): (request uuid, request id).
@@ -723,6 +719,11 @@ class CONTENT_EXPORT ServiceWorkerVersion
std::set<const ServiceWorkerURLRequestJob*> streaming_url_request_jobs_;
+ // Keeps track of the provider hosting this running service worker for this
+ // version. |provider_host_| is always valid as long as this version is
+ // running.
+ base::WeakPtr<ServiceWorkerProviderHost> provider_host_;
+
std::map<std::string, ServiceWorkerProviderHost*> controllee_map_;
// Will be null while shutting down.
base::WeakPtr<ServiceWorkerContextCore> context_;
@@ -778,6 +779,9 @@ class CONTENT_EXPORT ServiceWorkerVersion
// The clock used to vend tick time.
std::unique_ptr<base::TickClock> tick_clock_;
+ // The clock used for actual (wall clock) time
+ std::unique_ptr<base::Clock> clock_;
+
std::unique_ptr<PingController> ping_controller_;
// Used for recording worker activities (e.g., a ratio of handled events)
@@ -801,19 +805,6 @@ class CONTENT_EXPORT ServiceWorkerVersion
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerVersion);
};
-template <typename ResponseMessage, typename ResponseCallbackType>
-void ServiceWorkerVersion::RegisterRequestCallback(
- int request_id,
- const ResponseCallbackType& callback) {
- PendingRequest* request = pending_requests_.Lookup(request_id);
- DCHECK(request) << "Invalid request id";
- DCHECK(!request->listener) << "Callback was already registered";
- DCHECK(!request->is_dispatched) << "Request already dispatched an IPC event";
- request->listener.reset(
- new EventResponseHandler<ResponseMessage, ResponseCallbackType>(
- embedded_worker()->AsWeakPtr(), request_id, callback));
-}
-
template <typename ResponseMessage, typename CallbackType, typename... Args>
bool ServiceWorkerVersion::EventResponseHandler<
ResponseMessage,
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 a80c58b1ab7..b375e2ce4cf 100644
--- a/chromium/content/browser/service_worker/service_worker_version_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_version_unittest.cc
@@ -78,18 +78,8 @@ void VerifyCalled(bool* called) {
void ObserveStatusChanges(ServiceWorkerVersion* version,
std::vector<ServiceWorkerVersion::Status>* statuses) {
statuses->push_back(version->status());
- version->RegisterStatusChangeCallback(
- base::Bind(&ObserveStatusChanges, base::Unretained(version), statuses));
-}
-
-void ReceiveTestEventResult(int* request_id,
- std::string* data,
- const base::Closure& callback,
- int actual_request_id,
- const std::string& actual_data) {
- *request_id = actual_request_id;
- *data = actual_data;
- callback.Run();
+ version->RegisterStatusChangeCallback(base::BindOnce(
+ &ObserveStatusChanges, base::Unretained(version), statuses));
}
// A specialized listener class to receive test messages from a worker.
@@ -269,14 +259,16 @@ class MessageReceiverDisallowStart : public MessageReceiver {
enum class StartMode { STALL, FAIL, SUCCEED };
- void OnStartWorker(int embedded_worker_id,
- int64_t service_worker_version_id,
- const GURL& scope,
- const GURL& script_url,
- bool pause_after_download,
- mojom::ServiceWorkerEventDispatcherRequest request,
- mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo
- instance_host) override {
+ void OnStartWorker(
+ int embedded_worker_id,
+ int64_t service_worker_version_id,
+ const GURL& scope,
+ const GURL& script_url,
+ bool pause_after_download,
+ mojom::ServiceWorkerEventDispatcherRequest request,
+ mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
+ mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info)
+ override {
switch (mode_) {
case StartMode::STALL:
// Prepare for OnStopWorker().
@@ -295,7 +287,8 @@ class MessageReceiverDisallowStart : public MessageReceiver {
case StartMode::SUCCEED:
MessageReceiver::OnStartWorker(
embedded_worker_id, service_worker_version_id, scope, script_url,
- pause_after_download, std::move(request), std::move(instance_host));
+ pause_after_download, std::move(request), std::move(instance_host),
+ std::move(provider_info));
break;
}
current_mock_instance_index_++;
@@ -542,7 +535,7 @@ TEST_F(ServiceWorkerVersionTest, InstallAndWaitCompletion) {
// Wait for the completion.
bool status_change_called = false;
version_->RegisterStatusChangeCallback(
- base::Bind(&VerifyCalled, &status_change_called));
+ base::BindOnce(&VerifyCalled, &status_change_called));
// Dispatch an install event.
SimulateDispatchEvent(ServiceWorkerMetrics::EventType::INSTALL);
@@ -563,7 +556,7 @@ TEST_F(ServiceWorkerVersionTest, ActivateAndWaitCompletion) {
// Wait for the completion.
bool status_change_called = false;
version_->RegisterStatusChangeCallback(
- base::Bind(&VerifyCalled, &status_change_called));
+ base::BindOnce(&VerifyCalled, &status_change_called));
// Dispatch an activate event.
SimulateDispatchEvent(ServiceWorkerMetrics::EventType::ACTIVATE);
@@ -578,7 +571,7 @@ TEST_F(ServiceWorkerVersionTest, RepeatedlyObserveStatusChanges) {
// Repeatedly observe status changes (the callback re-registers itself).
std::vector<ServiceWorkerVersion::Status> statuses;
- version_->RegisterStatusChangeCallback(base::Bind(
+ version_->RegisterStatusChangeCallback(base::BindOnce(
&ObserveStatusChanges, base::RetainedRef(version_), &statuses));
version_->SetStatus(ServiceWorkerVersion::INSTALLING);
@@ -703,6 +696,11 @@ TEST_F(ServiceWorkerVersionTest, StoppingBeforeDestruct) {
EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, listener.last_status);
+ // Destruct |version_| by releasing all references, including the provider
+ // host's.
+ helper_->context()->RemoveProviderHost(
+ version_->provider_host()->process_id(),
+ version_->provider_host()->provider_id());
version_ = nullptr;
EXPECT_EQ(EmbeddedWorkerStatus::STOPPING, listener.last_status);
}
@@ -787,10 +785,12 @@ TEST_F(ServiceWorkerVersionTest, StaleUpdate_DoNotDeferTimer) {
// Stale time is not deferred.
version_->RunAfterStartWorker(
- ServiceWorkerMetrics::EventType::UNKNOWN, base::Bind(&base::DoNothing),
+ ServiceWorkerMetrics::EventType::UNKNOWN,
+ base::BindOnce(&base::DoNothing),
base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
version_->RunAfterStartWorker(
- ServiceWorkerMetrics::EventType::UNKNOWN, base::Bind(&base::DoNothing),
+ ServiceWorkerMetrics::EventType::UNKNOWN,
+ base::BindOnce(&base::DoNothing),
base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(stale_time, version_->stale_time_);
@@ -1107,9 +1107,9 @@ TEST_F(ServiceWorkerFailToStartTest, RendererCrash) {
EXPECT_EQ(SERVICE_WORKER_ERROR_NETWORK, status);
EXPECT_EQ(EmbeddedWorkerStatus::STARTING, version_->running_status());
- // Simulate renderer crash: remove DispatcherHost like what
- // ServiceWorkerDispatcherHost::OnFilterRemoved does.
- helper_->RegisterDispatcherHost(helper_->mock_render_process_id(), nullptr);
+ // Simulate renderer crash: break EmbeddedWorkerInstance's Mojo connection to
+ // the renderer-side client.
+ helper_->mock_instance_clients()->clear();
base::RunLoop().RunUntilIdle();
// Callback completed.
@@ -1201,7 +1201,7 @@ TEST_F(ServiceWorkerStallInStoppingTest, DetachThenRestart) {
version_->StopWorker(CreateReceiverOnCurrentThread(&status));
EXPECT_EQ(EmbeddedWorkerStatus::STOPPING, version_->running_status());
- // Worker is now stalled in stopping. Add a start worker requset.
+ // Worker is now stalled in stopping. Add a start worker request.
ServiceWorkerStatusCode start_status = SERVICE_WORKER_ERROR_FAILED;
version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
CreateReceiverOnCurrentThread(&start_status));
@@ -1215,7 +1215,6 @@ TEST_F(ServiceWorkerStallInStoppingTest, DetachThenRestart) {
base::RunLoop().RunUntilIdle();
EXPECT_EQ(SERVICE_WORKER_OK, status);
EXPECT_EQ(SERVICE_WORKER_OK, start_status);
- EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
}
TEST_F(ServiceWorkerVersionTest, RegisterForeignFetchScopes) {
@@ -1312,9 +1311,9 @@ TEST_F(ServiceWorkerVersionTest, RendererCrashDuringEvent) {
// Callback has not completed yet.
EXPECT_EQ(SERVICE_WORKER_OK, status);
- // Simulate renderer crash: remove DispatcherHost like what
- // ServiceWorkerDispatcherHost::OnFilterRemoved does.
- helper_->RegisterDispatcherHost(helper_->mock_render_process_id(), nullptr);
+ // Simulate renderer crash: break EmbeddedWorkerInstance's Mojo connection to
+ // the renderer-side client.
+ helper_->mock_instance_clients()->clear();
base::RunLoop().RunUntilIdle();
// Callback completed.
@@ -1326,45 +1325,6 @@ TEST_F(ServiceWorkerVersionTest, RendererCrashDuringEvent) {
base::Time::Now()));
}
-TEST_F(ServiceWorkerVersionTest, RegisterRequestCallback) {
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_NETWORK; // dummy value
-
- // Activate and start worker.
- version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
- version_->StartWorker(ServiceWorkerMetrics::EventType::SYNC,
- CreateReceiverOnCurrentThread(&status));
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(SERVICE_WORKER_OK, status);
- EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
-
- // Start request and dispatch test event.
- scoped_refptr<MessageLoopRunner> runner(new MessageLoopRunner);
- int request_id = version_->StartRequest(
- ServiceWorkerMetrics::EventType::SYNC,
- CreateReceiverOnCurrentThread(&status, runner->QuitClosure()));
- int received_request_id = 0;
- std::string received_data;
- version_->RegisterRequestCallback<TestMsg_TestEventResult>(
- request_id, base::Bind(&ReceiveTestEventResult, &received_request_id,
- &received_data, runner->QuitClosure()));
-
- // Simulate sending reply to event.
- std::string reply("foobar");
- helper_->SimulateSendEventResult(
- version_->embedded_worker()->embedded_worker_id(), request_id, reply);
- runner->Run();
-
- // Verify message callback got called with correct reply.
- EXPECT_EQ(request_id, received_request_id);
- EXPECT_EQ(reply, received_data);
-
- // Should not have timed out, so error callback should not have been
- // called and FinishRequest should return true.
- EXPECT_EQ(SERVICE_WORKER_OK, status);
- EXPECT_TRUE(version_->FinishRequest(request_id, true /* was_handled */,
- base::Time::Now()));
-}
-
TEST_F(ServiceWorkerFailToStartTest, FailingWorkerUsesNewRendererProcess) {
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
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 9edd6ab647b..3dc9ef9aa9c 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
@@ -80,9 +80,6 @@ ServiceWorkerWriteToCacheJob::ServiceWorkerWriteToCacheJob(
resource_id_(resource_id),
incumbent_resource_id_(incumbent_resource_id),
version_(version),
- has_been_killed_(false),
- did_notify_started_(false),
- did_notify_finished_(false),
weak_factory_(this) {
DCHECK(version_);
DCHECK(resource_type_ == RESOURCE_TYPE_SCRIPT ||
@@ -98,8 +95,8 @@ ServiceWorkerWriteToCacheJob::~ServiceWorkerWriteToCacheJob() {
void ServiceWorkerWriteToCacheJob::Start() {
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&ServiceWorkerWriteToCacheJob::StartAsync,
- weak_factory_.GetWeakPtr()));
+ FROM_HERE, base::BindOnce(&ServiceWorkerWriteToCacheJob::StartAsync,
+ weak_factory_.GetWeakPtr()));
}
void ServiceWorkerWriteToCacheJob::StartAsync() {
@@ -114,9 +111,19 @@ void ServiceWorkerWriteToCacheJob::StartAsync() {
return;
}
- cache_writer_.reset(new ServiceWorkerCacheWriter(
- CreateCacheResponseReader(), CreateCacheResponseReader(),
- CreateCacheResponseWriter()));
+ // 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;
+ if (ShouldByteForByteCheck()) {
+ compare_reader =
+ context_->storage()->CreateResponseReader(incumbent_resource_id_);
+ copy_reader =
+ context_->storage()->CreateResponseReader(incumbent_resource_id_);
+ }
+ cache_writer_ = base::MakeUnique<ServiceWorkerCacheWriter>(
+ std::move(compare_reader), std::move(copy_reader),
+ context_->storage()->CreateResponseWriter(resource_id_));
+
version_->script_cache_map()->NotifyStartedCaching(url_, resource_id_);
did_notify_started_ = true;
StartNetRequest();
@@ -209,7 +216,7 @@ void ServiceWorkerWriteToCacheJob::InitNetRequest(
destination: WEBSITE
}
policy {
- cookies_allowed: true
+ cookies_allowed: YES
cookies_store: "user"
setting:
"Users can control this feature via the 'Cookies' setting under "
@@ -226,8 +233,7 @@ void ServiceWorkerWriteToCacheJob::InitNetRequest(
})");
net_request_ = request()->context()->CreateRequest(
request()->url(), request()->priority(), this, traffic_annotation);
- net_request_->set_first_party_for_cookies(
- request()->first_party_for_cookies());
+ net_request_->set_site_for_cookies(request()->site_for_cookies());
net_request_->set_initiator(request()->initiator());
net_request_->SetReferrer(request()->referrer());
net_request_->SetUserData(URLRequestServiceWorkerData::kUserDataKey,
@@ -488,18 +494,9 @@ net::Error ServiceWorkerWriteToCacheJob::NotifyFinishedCaching(
return net_error;
}
-std::unique_ptr<ServiceWorkerResponseReader>
-ServiceWorkerWriteToCacheJob::CreateCacheResponseReader() {
- if (incumbent_resource_id_ == kInvalidServiceWorkerResourceId ||
- !version_->pause_after_download()) {
- return nullptr;
- }
- return context_->storage()->CreateResponseReader(incumbent_resource_id_);
-}
-
-std::unique_ptr<ServiceWorkerResponseWriter>
-ServiceWorkerWriteToCacheJob::CreateCacheResponseWriter() {
- return context_->storage()->CreateResponseWriter(resource_id_);
+bool ServiceWorkerWriteToCacheJob::ShouldByteForByteCheck() const {
+ return incumbent_resource_id_ != kInvalidServiceWorkerResourceId &&
+ version_->pause_after_download();
}
} // 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 290a129251f..6033b20d960 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,24 +132,25 @@ class CONTENT_EXPORT ServiceWorkerWriteToCacheJob
net::Error NotifyFinishedCaching(net::Error net_error,
const std::string& status_message);
- std::unique_ptr<ServiceWorkerResponseReader> CreateCacheResponseReader();
- std::unique_ptr<ServiceWorkerResponseWriter> CreateCacheResponseWriter();
+ // Returns true when the incumbent service worker exists and it's required to
+ // do the byte-for-byte check.
+ bool ShouldByteForByteCheck() const;
- ResourceType resource_type_; // Differentiate main script and imports
+ const ResourceType resource_type_; // Differentiate main script and imports
scoped_refptr<net::IOBuffer> io_buffer_;
int io_buffer_bytes_;
base::WeakPtr<ServiceWorkerContextCore> context_;
- GURL url_;
- int64_t resource_id_;
- int64_t incumbent_resource_id_;
+ const GURL url_;
+ const int64_t resource_id_;
+ const int64_t incumbent_resource_id_;
std::unique_ptr<net::URLRequest> net_request_;
std::unique_ptr<net::HttpResponseInfo> http_info_;
std::unique_ptr<ServiceWorkerResponseWriter> writer_;
scoped_refptr<ServiceWorkerVersion> version_;
std::unique_ptr<ServiceWorkerCacheWriter> cache_writer_;
- bool has_been_killed_;
- bool did_notify_started_;
- bool did_notify_finished_;
+ bool has_been_killed_ = false;
+ bool did_notify_started_ = false;
+ bool did_notify_finished_ = false;
base::WeakPtrFactory<ServiceWorkerWriteToCacheJob> weak_factory_;
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 82ab2fdd20f..86a14a009c2 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
@@ -117,8 +117,8 @@ class SSLCertificateErrorJob : public net::URLRequestTestJob {
weak_factory_(this) {}
void Start() override {
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&SSLCertificateErrorJob::NotifyError,
- weak_factory_.GetWeakPtr()));
+ FROM_HERE, base::BindOnce(&SSLCertificateErrorJob::NotifyError,
+ weak_factory_.GetWeakPtr()));
}
void NotifyError() {
net::SSLInfo info;
@@ -127,8 +127,8 @@ class SSLCertificateErrorJob : public net::URLRequestTestJob {
}
void ContinueDespiteLastError() override {
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&SSLCertificateErrorJob::StartAsync,
- weak_factory_.GetWeakPtr()));
+ FROM_HERE, base::BindOnce(&SSLCertificateErrorJob::StartAsync,
+ weak_factory_.GetWeakPtr()));
}
protected:
@@ -288,16 +288,14 @@ class ServiceWorkerWriteToCacheJobTest : public testing::Test {
base::WeakPtr<ServiceWorkerProviderHost> CreateHostForVersion(
int process_id,
- int provider_id,
const scoped_refptr<ServiceWorkerVersion>& version) {
std::unique_ptr<ServiceWorkerProviderHost> host =
CreateProviderHostForServiceWorkerContext(
- process_id, provider_id, true /* is_parent_frame_secure */,
+ process_id, true /* is_parent_frame_secure */, version.get(),
context()->AsWeakPtr(), &remote_endpoint_);
- base::WeakPtr<ServiceWorkerProviderHost> provider_host = host->AsWeakPtr();
+ base::WeakPtr<ServiceWorkerProviderHost> host_weakptr = host->AsWeakPtr();
context()->AddProviderHost(std::move(host));
- provider_host->running_hosted_version_ = version;
- return provider_host;
+ return host_weakptr;
}
void SetUpScriptRequest(int process_id, int provider_id) {
@@ -327,11 +325,9 @@ class ServiceWorkerWriteToCacheJobTest : public testing::Test {
scoped_refptr<ResourceRequestBody>());
}
- int NextProviderId() { return next_provider_id_++; }
int NextVersionId() { return next_version_id_++; }
void SetUp() override {
- int provider_id = NextProviderId();
helper_.reset(new EmbeddedWorkerTestHelper(base::FilePath()));
// A new unstored registration/version.
@@ -340,8 +336,8 @@ class ServiceWorkerWriteToCacheJobTest : public testing::Test {
version_ =
new ServiceWorkerVersion(registration_.get(), script_url_,
NextVersionId(), context()->AsWeakPtr());
- base::WeakPtr<ServiceWorkerProviderHost> host = CreateHostForVersion(
- helper_->mock_render_process_id(), provider_id, version_);
+ base::WeakPtr<ServiceWorkerProviderHost> host =
+ CreateHostForVersion(helper_->mock_render_process_id(), version_);
ASSERT_TRUE(host);
SetUpScriptRequest(helper_->mock_render_process_id(), host->provider_id());
@@ -391,14 +387,13 @@ class ServiceWorkerWriteToCacheJobTest : public testing::Test {
// to the script |response|. Returns the new version.
scoped_refptr<ServiceWorkerVersion> UpdateScript(
const std::string& response) {
- int provider_id = NextProviderId();
scoped_refptr<ServiceWorkerVersion> new_version =
new ServiceWorkerVersion(registration_.get(), script_url_,
NextVersionId(), context()->AsWeakPtr());
new_version->set_pause_after_download(true);
- base::WeakPtr<ServiceWorkerProviderHost> host = CreateHostForVersion(
- helper_->mock_render_process_id(), provider_id, new_version);
-
+ base::WeakPtr<ServiceWorkerProviderHost> host =
+ CreateHostForVersion(helper_->mock_render_process_id(), new_version);
+ EXPECT_TRUE(host);
SetUpScriptRequest(helper_->mock_render_process_id(), host->provider_id());
mock_protocol_handler_->SetCreateJobCallback(
base::Bind(&CreateResponseJob, response));
@@ -435,7 +430,6 @@ class ServiceWorkerWriteToCacheJobTest : public testing::Test {
std::unique_ptr<EmbeddedWorkerTestHelper> helper_;
scoped_refptr<ServiceWorkerRegistration> registration_;
scoped_refptr<ServiceWorkerVersion> version_;
- base::WeakPtr<ServiceWorkerProviderHost> provider_host_;
std::unique_ptr<net::URLRequestContext> url_request_context_;
std::unique_ptr<net::URLRequestJobFactoryImpl> url_request_job_factory_;
std::unique_ptr<net::URLRequest> request_;
diff --git a/chromium/content/browser/shared_worker/DEPS b/chromium/content/browser/shared_worker/DEPS
new file mode 100644
index 00000000000..b896a7ad062
--- /dev/null
+++ b/chromium/content/browser/shared_worker/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+ "+third_party/WebKit/public/web/worker_content_settings_proxy.mojom.h",
+]
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
new file mode 100644
index 00000000000..38d279b8897
--- /dev/null
+++ b/chromium/content/browser/shared_worker/shared_worker_content_settings_proxy_impl.cc
@@ -0,0 +1,44 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/shared_worker/shared_worker_content_settings_proxy_impl.h"
+
+#include <utility>
+
+#include "content/browser/shared_worker/shared_worker_host.h"
+#include "content/browser/shared_worker/shared_worker_service_impl.h"
+#include "url/gurl.h"
+
+namespace content {
+
+SharedWorkerContentSettingsProxyImpl::SharedWorkerContentSettingsProxyImpl(
+ const GURL& script_url,
+ SharedWorkerHost* owner,
+ blink::mojom::WorkerContentSettingsProxyRequest request)
+ : origin_(script_url), owner_(owner), binding_(this, std::move(request)) {}
+
+SharedWorkerContentSettingsProxyImpl::~SharedWorkerContentSettingsProxyImpl() =
+ default;
+
+void SharedWorkerContentSettingsProxyImpl::AllowIndexedDB(
+ const base::string16& name,
+ AllowIndexedDBCallback callback) {
+ if (!origin_.unique()) {
+ bool result = owner_->AllowIndexedDB(origin_.GetURL(), name);
+ std::move(callback).Run(result);
+ } else {
+ std::move(callback).Run(false);
+ }
+}
+
+void SharedWorkerContentSettingsProxyImpl::RequestFileSystemAccessSync(
+ RequestFileSystemAccessSyncCallback callback) {
+ if (!origin_.unique()) {
+ owner_->AllowFileSystem(origin_.GetURL(), std::move(callback));
+ } else {
+ std::move(callback).Run(false);
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/browser/shared_worker/shared_worker_content_settings_proxy_impl.h b/chromium/content/browser/shared_worker/shared_worker_content_settings_proxy_impl.h
new file mode 100644
index 00000000000..967f28d88f1
--- /dev/null
+++ b/chromium/content/browser/shared_worker/shared_worker_content_settings_proxy_impl.h
@@ -0,0 +1,52 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_SHARED_WORKER_SHARED_WORKER_CONTENT_SETTING_PROXY_IMPL_H_
+#define CONTENT_BROWSER_SHARED_WORKER_SHARED_WORKER_CONTENT_SETTING_PROXY_IMPL_H_
+
+#include "base/callback.h"
+#include "base/strings/string16.h"
+#include "content/common/content_export.h"
+#include "content/public/browser/resource_context.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "third_party/WebKit/public/web/worker_content_settings_proxy.mojom.h"
+#include "url/origin.h"
+
+namespace content {
+
+class SharedWorkerHost;
+
+// SharedWorkerContentSettingsProxyImpl passes content settings to its renderer
+// counterpart blink::SharedWorkerContentSettingsProxy.
+// Created on SharedWorker::Start() and connects to the counterpart
+// at the moment.
+// SharedWorkerHost owns this class, so the lifetime of this class is strongly
+// associated to it.
+class CONTENT_EXPORT SharedWorkerContentSettingsProxyImpl
+ : public blink::mojom::WorkerContentSettingsProxy {
+ public:
+ SharedWorkerContentSettingsProxyImpl(
+ const GURL& script_url,
+ SharedWorkerHost* owner,
+ blink::mojom::WorkerContentSettingsProxyRequest request);
+
+ ~SharedWorkerContentSettingsProxyImpl() override;
+
+ // blink::mojom::WorkerContentSettingsProxy implementation.
+ void AllowIndexedDB(const base::string16& name,
+ AllowIndexedDBCallback callback) override;
+ void RequestFileSystemAccessSync(
+ RequestFileSystemAccessSyncCallback callback) override;
+
+ private:
+ const url::Origin origin_;
+ SharedWorkerHost* owner_;
+ mojo::Binding<blink::mojom::WorkerContentSettingsProxy> binding_;
+
+ DISALLOW_COPY_AND_ASSIGN(SharedWorkerContentSettingsProxyImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_SHARED_WORKER_SHARED_WORKER_CONTENT_SETTING_PROXY_IMPL_H_
diff --git a/chromium/content/browser/shared_worker/shared_worker_host.cc b/chromium/content/browser/shared_worker/shared_worker_host.cc
index c2b9761094f..b560e5fbbb5 100644
--- a/chromium/content/browser/shared_worker/shared_worker_host.cc
+++ b/chromium/content/browser/shared_worker/shared_worker_host.cc
@@ -4,8 +4,11 @@
#include "content/browser/shared_worker/shared_worker_host.h"
+#include <utility>
+
#include "base/metrics/histogram_macros.h"
#include "content/browser/devtools/shared_worker_devtools_manager.h"
+#include "content/browser/shared_worker/shared_worker_content_settings_proxy_impl.h"
#include "content/browser/shared_worker/shared_worker_instance.h"
#include "content/browser/shared_worker/shared_worker_message_filter.h"
#include "content/browser/shared_worker/shared_worker_service_impl.h"
@@ -15,6 +18,7 @@
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/common/content_client.h"
+#include "third_party/WebKit/public/web/worker_content_settings_proxy.mojom.h"
namespace content {
namespace {
@@ -22,11 +26,9 @@ namespace {
void NotifyWorkerReadyForInspection(int worker_process_id,
int worker_route_id) {
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- BrowserThread::PostTask(BrowserThread::UI,
- FROM_HERE,
- base::Bind(NotifyWorkerReadyForInspection,
- worker_process_id,
- worker_route_id));
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::BindOnce(NotifyWorkerReadyForInspection,
+ worker_process_id, worker_route_id));
return;
}
SharedWorkerDevToolsManager::GetInstance()->WorkerReadyForInspection(
@@ -35,10 +37,9 @@ void NotifyWorkerReadyForInspection(int worker_process_id,
void NotifyWorkerDestroyed(int worker_process_id, int worker_route_id) {
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- BrowserThread::PostTask(
- BrowserThread::UI,
- FROM_HERE,
- base::Bind(NotifyWorkerDestroyed, worker_process_id, worker_route_id));
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::BindOnce(NotifyWorkerDestroyed,
+ worker_process_id, worker_route_id));
return;
}
SharedWorkerDevToolsManager::GetInstance()->WorkerDestroyed(
@@ -74,6 +75,10 @@ SharedWorkerHost::~SharedWorkerHost() {
}
void SharedWorkerHost::Start(bool pause_on_start) {
+ blink::mojom::WorkerContentSettingsProxyPtrInfo content_settings;
+ content_settings_ = base::MakeUnique<SharedWorkerContentSettingsProxyImpl>(
+ instance_->url(), this, mojo::MakeRequest(&content_settings));
+
WorkerProcessMsg_CreateWorker_Params params;
params.url = instance_->url();
params.name = instance_->name();
@@ -83,6 +88,7 @@ void SharedWorkerHost::Start(bool pause_on_start) {
params.pause_on_start = pause_on_start;
params.route_id = worker_route_id_;
params.data_saver_enabled = instance_->data_saver_enabled();
+ params.content_settings_handle = content_settings.PassHandle().release();
Send(new WorkerProcessMsg_CreateWorker(params));
for (const FilterInfo& info : filters_)
@@ -189,31 +195,23 @@ void SharedWorkerHost::WorkerConnected(int connection_request_id) {
void SharedWorkerHost::AllowFileSystem(
const GURL& url,
- std::unique_ptr<IPC::Message> reply_msg) {
+ base::OnceCallback<void(bool)> callback) {
GetContentClient()->browser()->AllowWorkerFileSystem(
- url,
- instance_->resource_context(),
- GetRenderFrameIDsForWorker(),
+ url, instance_->resource_context(), GetRenderFrameIDsForWorker(),
base::Bind(&SharedWorkerHost::AllowFileSystemResponse,
- weak_factory_.GetWeakPtr(),
- base::Passed(&reply_msg)));
+ weak_factory_.GetWeakPtr(), base::Passed(&callback)));
}
void SharedWorkerHost::AllowFileSystemResponse(
- std::unique_ptr<IPC::Message> reply_msg,
+ base::OnceCallback<void(bool)> callback,
bool allowed) {
- DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-
- WorkerProcessHostMsg_RequestFileSystemAccessSync::WriteReplyParams(
- reply_msg.get(),
- allowed);
- Send(reply_msg.release());
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ std::move(callback).Run(allowed);
}
-void SharedWorkerHost::AllowIndexedDB(const GURL& url,
- const base::string16& name,
- bool* result) {
- *result = GetContentClient()->browser()->AllowWorkerIndexedDB(
+bool SharedWorkerHost::AllowIndexedDB(const GURL& url,
+ const base::string16& name) {
+ return GetContentClient()->browser()->AllowWorkerIndexedDB(
url, name, instance_->resource_context(), GetRenderFrameIDsForWorker());
}
diff --git a/chromium/content/browser/shared_worker/shared_worker_host.h b/chromium/content/browser/shared_worker/shared_worker_host.h
index bdb06fdfebf..32c70d47316 100644
--- a/chromium/content/browser/shared_worker/shared_worker_host.h
+++ b/chromium/content/browser/shared_worker/shared_worker_host.h
@@ -26,8 +26,9 @@ class Message;
namespace content {
class MessagePort;
-class SharedWorkerMessageFilter;
+class SharedWorkerContentSettingsProxyImpl;
class SharedWorkerInstance;
+class SharedWorkerMessageFilter;
// The SharedWorkerHost is the interface that represents the browser side of
// the browser <-> worker communication channel. This is owned by
@@ -72,10 +73,8 @@ class SharedWorkerHost {
void WorkerScriptLoadFailed();
void WorkerConnected(int connection_request_id);
void AllowFileSystem(const GURL& url,
- std::unique_ptr<IPC::Message> reply_msg);
- void AllowIndexedDB(const GURL& url,
- const base::string16& name,
- bool* result);
+ base::OnceCallback<void(bool)> callback);
+ bool AllowIndexedDB(const GURL& url, const base::string16& name);
// Terminates the given worker, i.e. based on a UI action.
void TerminateWorker();
@@ -120,7 +119,7 @@ class SharedWorkerHost {
void SetConnectionRequestID(SharedWorkerMessageFilter* filter,
int route_id,
int connection_request_id);
- void AllowFileSystemResponse(std::unique_ptr<IPC::Message> reply_msg,
+ void AllowFileSystemResponse(base::OnceCallback<void(bool)> callback,
bool allowed);
// Sends |message| to the SharedWorker.
@@ -146,6 +145,7 @@ class SharedWorkerHost {
// from blink::UseCounter::Feature enum.
std::set<uint32_t> used_features_;
+ std::unique_ptr<SharedWorkerContentSettingsProxyImpl> content_settings_;
base::WeakPtrFactory<SharedWorkerHost> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(SharedWorkerHost);
diff --git a/chromium/content/browser/shared_worker/shared_worker_message_filter.cc b/chromium/content/browser/shared_worker/shared_worker_message_filter.cc
index a2ddef37a15..e2138b16ac0 100644
--- a/chromium/content/browser/shared_worker/shared_worker_message_filter.cc
+++ b/chromium/content/browser/shared_worker/shared_worker_message_filter.cc
@@ -77,10 +77,6 @@ bool SharedWorkerMessageFilter::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_FORWARD(WorkerHostMsg_WorkerConnected,
SharedWorkerServiceImpl::GetInstance(),
SharedWorkerServiceImpl::WorkerConnected)
- IPC_MESSAGE_HANDLER_DELAY_REPLY(
- WorkerProcessHostMsg_RequestFileSystemAccessSync,
- OnRequestFileSystemAccess)
- IPC_MESSAGE_HANDLER(WorkerProcessHostMsg_AllowIndexedDB, OnAllowIndexedDB)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
@@ -99,20 +95,4 @@ void SharedWorkerMessageFilter::OnCreateWorker(
WorkerStoragePartitionId(partition_));
}
-void SharedWorkerMessageFilter::OnRequestFileSystemAccess(
- int worker_route_id,
- const GURL& url,
- IPC::Message* reply_msg) {
- SharedWorkerServiceImpl::GetInstance()->AllowFileSystem(this, worker_route_id,
- url, reply_msg);
-}
-
-void SharedWorkerMessageFilter::OnAllowIndexedDB(int worker_route_id,
- const GURL& url,
- const base::string16& name,
- bool* result) {
- SharedWorkerServiceImpl::GetInstance()->AllowIndexedDB(this, worker_route_id,
- url, name, result);
-}
-
} // namespace content
diff --git a/chromium/content/browser/shared_worker/shared_worker_message_filter.h b/chromium/content/browser/shared_worker/shared_worker_message_filter.h
index 7f657500c8a..fdd564821d9 100644
--- a/chromium/content/browser/shared_worker/shared_worker_message_filter.h
+++ b/chromium/content/browser/shared_worker/shared_worker_message_filter.h
@@ -10,7 +10,6 @@
#include "content/common/content_export.h"
#include "content/public/browser/browser_message_filter.h"
-class GURL;
struct ViewHostMsg_CreateWorker_Params;
struct ViewHostMsg_CreateWorker_Reply;
@@ -43,13 +42,6 @@ class CONTENT_EXPORT SharedWorkerMessageFilter : public BrowserMessageFilter {
// Message handlers.
void OnCreateWorker(const ViewHostMsg_CreateWorker_Params& params,
ViewHostMsg_CreateWorker_Reply* reply);
- void OnRequestFileSystemAccess(int worker_route_id,
- const GURL& url,
- IPC::Message* reply_msg);
- void OnAllowIndexedDB(int worker_route_id,
- const GURL& url,
- const base::string16& name,
- bool* result);
const int render_process_id_;
ResourceContext* const resource_context_;
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 d19cab1de35..7150ea7e286 100644
--- a/chromium/content/browser/shared_worker/shared_worker_service_impl.cc
+++ b/chromium/content/browser/shared_worker/shared_worker_service_impl.cc
@@ -32,7 +32,7 @@ WorkerService* WorkerService::GetInstance() {
bool IsHostAlive(RenderProcessHostImpl* host) {
return host && !host->FastShutdownStarted() &&
- !host->IsWorkerRefCountDisabled();
+ !host->IsKeepAliveRefCountDisabled();
}
namespace {
@@ -63,8 +63,9 @@ class SharedWorkerReserver {
worker_process_id, worker_route_id, is_new_worker, instance));
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&SharedWorkerReserver::TryReserveOnUI, std::move(reserver),
- success_cb, failure_cb, try_increment_worker_ref_count));
+ base::BindOnce(&SharedWorkerReserver::TryReserveOnUI,
+ std::move(reserver), success_cb, failure_cb,
+ try_increment_worker_ref_count));
}
private:
@@ -99,8 +100,8 @@ class SharedWorkerReserver {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(callback, worker_process_id_, worker_route_id_,
- is_new_worker_, pause_on_start));
+ base::BindOnce(callback, worker_process_id_, worker_route_id_,
+ is_new_worker_, pause_on_start));
}
const int worker_process_id_;
@@ -135,37 +136,36 @@ void UpdateWorkerDependencyOnUI(const std::vector<int>& added_ids,
static_cast<RenderProcessHostImpl*>(RenderProcessHost::FromID(id));
if (!IsHostAlive(render_process_host_impl))
continue;
- render_process_host_impl->IncrementSharedWorkerRefCount();
+ render_process_host_impl->IncrementKeepAliveRefCount();
}
for (int id : removed_ids) {
RenderProcessHostImpl* render_process_host_impl =
static_cast<RenderProcessHostImpl*>(RenderProcessHost::FromID(id));
if (!IsHostAlive(render_process_host_impl))
continue;
- render_process_host_impl->DecrementSharedWorkerRefCount();
+ render_process_host_impl->DecrementKeepAliveRefCount();
}
}
void UpdateWorkerDependency(const std::vector<int>& added_ids,
const std::vector<int>& removed_ids) {
BrowserThread::PostTask(
- BrowserThread::UI,
- FROM_HERE,
- base::Bind(&UpdateWorkerDependencyOnUI, added_ids, removed_ids));
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&UpdateWorkerDependencyOnUI, added_ids, removed_ids));
}
void DecrementWorkerRefCount(int process_id) {
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- BrowserThread::PostTask(BrowserThread::UI,
- FROM_HERE,
- base::Bind(&DecrementWorkerRefCount, process_id));
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&DecrementWorkerRefCount, process_id));
return;
}
RenderProcessHostImpl* render_process_host_impl =
static_cast<RenderProcessHostImpl*>(
RenderProcessHost::FromID(process_id));
if (IsHostAlive(render_process_host_impl))
- render_process_host_impl->DecrementSharedWorkerRefCount();
+ render_process_host_impl->DecrementKeepAliveRefCount();
}
bool TryIncrementWorkerRefCount(int worker_process_id) {
@@ -173,7 +173,7 @@ bool TryIncrementWorkerRefCount(int worker_process_id) {
RenderProcessHost::FromID(worker_process_id));
if (!IsHostAlive(render_process))
return false;
- render_process->IncrementSharedWorkerRefCount();
+ render_process->IncrementKeepAliveRefCount();
return true;
}
@@ -443,31 +443,6 @@ void SharedWorkerServiceImpl::WorkerConnected(SharedWorkerMessageFilter* filter,
host->WorkerConnected(connection_request_id);
}
-void SharedWorkerServiceImpl::AllowFileSystem(SharedWorkerMessageFilter* filter,
- int worker_route_id,
- const GURL& url,
- IPC::Message* reply_msg) {
- if (SharedWorkerHost* host =
- FindSharedWorkerHost(filter->render_process_id(), worker_route_id)) {
- host->AllowFileSystem(url, base::WrapUnique(reply_msg));
- } else {
- filter->Send(reply_msg);
- return;
- }
-}
-
-void SharedWorkerServiceImpl::AllowIndexedDB(SharedWorkerMessageFilter* filter,
- int worker_route_id,
- const GURL& url,
- const base::string16& name,
- bool* result) {
- if (SharedWorkerHost* host =
- FindSharedWorkerHost(filter->render_process_id(), worker_route_id))
- host->AllowIndexedDB(url, name, result);
- else
- *result = false;
-}
-
void SharedWorkerServiceImpl::OnSharedWorkerMessageFilterClosing(
SharedWorkerMessageFilter* filter) {
ScopedWorkerDependencyChecker checker(this);
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 8c4513bab2e..b8ae5033093 100644
--- a/chromium/content/browser/shared_worker/shared_worker_service_impl.h
+++ b/chromium/content/browser/shared_worker/shared_worker_service_impl.h
@@ -22,10 +22,6 @@
struct ViewHostMsg_CreateWorker_Params;
-namespace IPC {
-class Message;
-}
-
namespace content {
class MessagePort;
@@ -38,8 +34,7 @@ class WorkerStoragePartitionId;
// The implementation of WorkerService. We try to place workers in an existing
// renderer process when possible.
-class CONTENT_EXPORT SharedWorkerServiceImpl
- : public NON_EXPORTED_BASE(WorkerService) {
+class CONTENT_EXPORT SharedWorkerServiceImpl : public WorkerService {
public:
// Returns the SharedWorkerServiceImpl singleton.
static SharedWorkerServiceImpl* GetInstance();
@@ -78,15 +73,6 @@ class CONTENT_EXPORT SharedWorkerServiceImpl
void WorkerConnected(SharedWorkerMessageFilter* filter,
int connection_request_id,
int worker_route_id);
- void AllowFileSystem(SharedWorkerMessageFilter* filter,
- int worker_route_id,
- const GURL& url,
- IPC::Message* reply_msg);
- void AllowIndexedDB(SharedWorkerMessageFilter* filter,
- int worker_route_id,
- const GURL& url,
- const base::string16& name,
- bool* result);
void OnSharedWorkerMessageFilterClosing(
SharedWorkerMessageFilter* filter);
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 8becd584494..261e9e31ba4 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
@@ -111,7 +111,12 @@ static const int kProcessIDs[] = {100, 101, 102};
static const unsigned long long kDocumentIDs[] = {200, 201, 202};
static const int kRenderFrameRouteIDs[] = {300, 301, 302};
-void BlockingReadFromMessagePort(MessagePort port, base::string16* message) {
+std::vector<uint8_t> StringPieceToVector(base::StringPiece s) {
+ return std::vector<uint8_t>(s.begin(), s.end());
+}
+
+void BlockingReadFromMessagePort(MessagePort port,
+ std::vector<uint8_t>* message) {
base::RunLoop run_loop;
port.SetCallback(run_loop.QuitClosure());
run_loop.Run();
@@ -381,10 +386,11 @@ TEST_F(SharedWorkerServiceImplTest, BasicTest) {
std::set<uint32_t>());
// Verify that |worker_msg_port| corresponds to |connector->local_port()|.
- base::string16 expected_message(base::ASCIIToUTF16("test1"));
- connector->local_port().PostMessage(expected_message,
+ std::vector<uint8_t> expected_message(StringPieceToVector("test1"));
+ connector->local_port().PostMessage(expected_message.data(),
+ expected_message.size(),
std::vector<MessagePort>());
- base::string16 received_message;
+ std::vector<uint8_t> received_message;
BlockingReadFromMessagePort(worker_msg_port, &received_message);
EXPECT_EQ(expected_message, received_message);
@@ -472,10 +478,11 @@ TEST_F(SharedWorkerServiceImplTest, TwoRendererTest) {
std::set<uint32_t>());
// Verify that |worker_msg_port1| corresponds to |connector0->local_port()|.
- base::string16 expected_message1(base::ASCIIToUTF16("test1"));
- connector0->local_port().PostMessage(expected_message1,
+ std::vector<uint8_t> expected_message1(StringPieceToVector("test1"));
+ connector0->local_port().PostMessage(expected_message1.data(),
+ expected_message1.size(),
std::vector<MessagePort>());
- base::string16 received_message1;
+ std::vector<uint8_t> received_message1;
BlockingReadFromMessagePort(worker_msg_port1, &received_message1);
EXPECT_EQ(expected_message1, received_message1);
@@ -544,10 +551,11 @@ TEST_F(SharedWorkerServiceImplTest, TwoRendererTest) {
{feature1, feature2});
// Verify that |worker_msg_port2| corresponds to |connector1->local_port()|.
- base::string16 expected_message2(base::ASCIIToUTF16("test2"));
- connector1->local_port().PostMessage(expected_message2,
+ std::vector<uint8_t> expected_message2(StringPieceToVector("test2"));
+ connector1->local_port().PostMessage(expected_message2.data(),
+ expected_message2.size(),
std::vector<MessagePort>());
- base::string16 received_message2;
+ std::vector<uint8_t> received_message2;
BlockingReadFromMessagePort(worker_msg_port2, &received_message2);
EXPECT_EQ(expected_message2, received_message2);
diff --git a/chromium/content/browser/shared_worker/worker_browsertest.cc b/chromium/content/browser/shared_worker/worker_browsertest.cc
index f991ff4e004..8f439df1870 100644
--- a/chromium/content/browser/shared_worker/worker_browsertest.cc
+++ b/chromium/content/browser/shared_worker/worker_browsertest.cc
@@ -247,7 +247,6 @@ IN_PROC_BROWSER_TEST_F(WorkerTest, WebSocketSharedWorker) {
// Launch WebSocket server.
net::SpawnedTestServer ws_server(net::SpawnedTestServer::TYPE_WS,
- net::SpawnedTestServer::kLocalhost,
net::GetWebSocketTestDataDirectory());
ASSERT_TRUE(ws_server.Start());
diff --git a/chromium/content/browser/site_instance_impl.cc b/chromium/content/browser/site_instance_impl.cc
index 08cb4e3cf76..f7bae497810 100644
--- a/chromium/content/browser/site_instance_impl.cc
+++ b/chromium/content/browser/site_instance_impl.cc
@@ -435,11 +435,11 @@ bool SiteInstanceImpl::DoesSiteRequireDedicatedProcess(
// static
bool SiteInstanceImpl::ShouldLockToOrigin(BrowserContext* browser_context,
+ RenderProcessHost* host,
GURL site_url) {
// Don't lock to origin in --single-process mode, since this mode puts
// cross-site pages into the same process.
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kSingleProcess))
+ if (host->run_renderer_in_process())
return false;
if (!DoesSiteRequireDedicatedProcess(browser_context, site_url))
@@ -504,16 +504,44 @@ void SiteInstanceImpl::LockToOriginIfNeeded() {
// We can get here either when we commit a URL into a SiteInstance that does
// not yet have a site, or when we create a process for a SiteInstance with a
// preassigned site.
+ bool was_unused = process_->IsUnused();
process_->SetIsUsed();
// TODO(nick): When all sites are isolated, this operation provides strong
// protection. If only some sites are isolated, we need additional logic to
// prevent the non-isolated sites from requesting resources for isolated
// sites. https://crbug.com/509125
- if (ShouldLockToOrigin(GetBrowserContext(), site_)) {
+ if (ShouldLockToOrigin(GetBrowserContext(), process_, site_)) {
ChildProcessSecurityPolicyImpl* policy =
ChildProcessSecurityPolicyImpl::GetInstance();
- policy->LockToOrigin(process_->GetID(), site_);
+
+ // Sanity check that this won't try to assign an origin lock to a <webview>
+ // process, which can't be locked.
+ CHECK(!process_->IsForGuestsOnly());
+
+ auto lock_state = policy->CheckOriginLock(process_->GetID(), site_);
+ switch (lock_state) {
+ case ChildProcessSecurityPolicyImpl::CheckOriginLockResult::NO_LOCK: {
+ // TODO(alexmos): Turn this into a CHECK once https://crbug.com/738634
+ // is fixed.
+ DCHECK(was_unused);
+ policy->LockToOrigin(process_->GetID(), site_);
+ break;
+ }
+ case ChildProcessSecurityPolicyImpl::CheckOriginLockResult::
+ HAS_WRONG_LOCK:
+ // We should never attempt to reassign a different origin lock to a
+ // process.
+ CHECK(false);
+ break;
+ case ChildProcessSecurityPolicyImpl::CheckOriginLockResult::
+ HAS_EQUAL_LOCK:
+ // Process already has the right origin lock assigned. This case will
+ // happen for commits to |site_| after the first one.
+ break;
+ default:
+ NOTREACHED();
+ }
}
}
diff --git a/chromium/content/browser/site_instance_impl.h b/chromium/content/browser/site_instance_impl.h
index d5e0207a0c3..5f08f4e8104 100644
--- a/chromium/content/browser/site_instance_impl.h
+++ b/chromium/content/browser/site_instance_impl.h
@@ -162,17 +162,18 @@ class CONTENT_EXPORT SiteInstanceImpl final : public SiteInstance,
static bool DoesSiteRequireDedicatedProcess(BrowserContext* browser_context,
const GURL& url);
- // Returns true if a process for |site_url| should be locked to just that
- // site. Returning 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
+ // Returns true if a process |host| can be locked to a site |site_url|.
+ // Returning 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, 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().
+ // 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().
static bool ShouldLockToOrigin(BrowserContext* browser_context,
+ RenderProcessHost* host,
GURL site_url);
private:
diff --git a/chromium/content/browser/site_per_process_browsertest.cc b/chromium/content/browser/site_per_process_browsertest.cc
index ac63bfb81f8..5651f6c2e9a 100644
--- a/chromium/content/browser/site_per_process_browsertest.cc
+++ b/chromium/content/browser/site_per_process_browsertest.cc
@@ -19,6 +19,7 @@
#include "base/location.h"
#include "base/memory/ptr_util.h"
#include "base/path_service.h"
+#include "base/run_loop.h"
#include "base/sequenced_task_runner.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/pattern.h"
@@ -38,7 +39,6 @@
#include "content/browser/frame_host/navigation_entry_impl.h"
#include "content/browser/frame_host/navigator.h"
#include "content/browser/frame_host/render_frame_proxy_host.h"
-#include "content/browser/frame_host/render_widget_host_view_child_frame.h"
#include "content/browser/gpu/compositor_util.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/renderer_host/cursor_manager.h"
@@ -47,6 +47,7 @@
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_input_event_router.h"
#include "content/browser/renderer_host/render_widget_host_view_aura.h"
+#include "content/browser/renderer_host/render_widget_host_view_child_frame.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"
@@ -76,6 +77,7 @@
#include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test_utils_internal.h"
+#include "content/test/mock_overscroll_observer.h"
#include "ipc/ipc.mojom.h"
#include "ipc/ipc_security_test_util.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
@@ -101,7 +103,10 @@
#include "ui/native_theme/native_theme_features.h"
#if defined(USE_AURA)
+#include "content/browser/renderer_host/overscroll_controller.h"
#include "content/browser/renderer_host/render_widget_host_view_aura.h"
+#include "content/public/browser/overscroll_configuration.h"
+#include "content/test/mock_overscroll_controller_delegate_aura.h"
#endif
#if defined(OS_MACOSX)
@@ -116,6 +121,9 @@
#include "content/browser/android/ime_adapter_android.h"
#include "content/browser/renderer_host/input/touch_selection_controller_client_manager_android.h"
#include "content/browser/renderer_host/render_widget_host_view_android.h"
+#include "content/public/browser/android/child_process_importance.h"
+#include "content/test/mock_overscroll_refresh_handler_android.h"
+#include "ui/events/android/motion_event_android.h"
#include "ui/gfx/geometry/point_f.h"
#endif
@@ -747,6 +755,21 @@ class SitePerProcessFeaturePolicyBrowserTest
}
};
+// SitePerProcessFeaturePolicyDisabledBrowserTest
+
+class SitePerProcessFeaturePolicyDisabledBrowserTest
+ : public SitePerProcessBrowserTest {
+ public:
+ SitePerProcessFeaturePolicyDisabledBrowserTest() {}
+
+ protected:
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ SitePerProcessBrowserTest::SetUpCommandLine(command_line);
+ command_line->AppendSwitchASCII(switches::kDisableBlinkFeatures,
+ "FeaturePolicy");
+ }
+};
+
IN_PROC_BROWSER_TEST_F(SitePerProcessHighDPIBrowserTest,
SubframeLoadsWithCorrectDeviceScaleFactor) {
GURL main_url(embedded_test_server()->GetURL(
@@ -774,14 +797,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessHighDPIBrowserTest,
// Ensure that navigating subframes in --site-per-process mode works and the
// correct documents are committed.
-
-// Crashes on Win only. https://crbug.com/746055
-#if defined(OS_WIN)
-#define MAYBE_CrossSiteIframe DISABLED_CrossSiteIframe
-#else
-#define MAYBE_CrossSiteIframe CrossSiteIframe
-#endif
-IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, MAYBE_CrossSiteIframe) {
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, CrossSiteIframe) {
GURL main_url(embedded_test_server()->GetURL(
"a.com", "/cross_site_iframe_factory.html?a(a,a(a,a(a)))"));
EXPECT_TRUE(NavigateToURL(shell(), main_url));
@@ -1016,14 +1032,16 @@ class FrameRectChangedMessageFilter : public content::BrowserMessageFilter {
private:
~FrameRectChangedMessageFilter() override {}
- void OnFrameRectChanged(const gfx::Rect& rect) {
+ void OnFrameRectChanged(const gfx::Rect& rect,
+ const viz::LocalSurfaceId& local_surface_id) {
content::BrowserThread::PostTask(
content::BrowserThread::UI, FROM_HERE,
base::Bind(&FrameRectChangedMessageFilter::OnFrameRectChangedOnUI, this,
- rect));
+ rect, local_surface_id));
}
- void OnFrameRectChangedOnUI(const gfx::Rect& rect) {
+ void OnFrameRectChangedOnUI(const gfx::Rect& rect,
+ const viz::LocalSurfaceId& local_surface_id) {
last_rect_ = rect;
if (!frame_rect_received_) {
frame_rect_received_ = true;
@@ -1419,6 +1437,220 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, ScrollBubblingFromOOPIFTest) {
DCHECK_EQ(filter->last_rect().y(), 0);
}
+#if defined(USE_AURA) || defined(OS_ANDROID)
+
+// When unconsumed scrolls in a child bubble to the root and start an
+// overscroll gesture, the subsequent gesture scroll update events should be
+// consumed by the root. The child should not be able to scroll during the
+// overscroll gesture.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ RootConsumesScrollDuringOverscrollGesture) {
+ 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();
+ RenderWidgetHostViewBase* rwhv_root = static_cast<RenderWidgetHostViewBase*>(
+ root->current_frame_host()->GetRenderWidgetHost()->GetView());
+ ASSERT_EQ(1U, root->child_count());
+
+ FrameTreeNode* child_node = root->child_at(0);
+
+#if defined(USE_AURA)
+ // The child must be horizontally scrollable.
+ GURL child_url(embedded_test_server()->GetURL("b.com", "/wide_page.html"));
+#elif defined(OS_ANDROID)
+ // The child must be vertically scrollable.
+ GURL child_url(embedded_test_server()->GetURL("b.com", "/tall_page.html"));
+#endif
+ NavigateFrameToURL(child_node, child_url);
+
+ EXPECT_EQ(
+ " Site A ------------ proxies for B\n"
+ " +--Site B ------- proxies for A\n"
+ "Where A = http://a.com/\n"
+ " B = http://b.com/",
+ DepictFrameTree(root));
+
+ RenderWidgetHostViewChildFrame* rwhv_child =
+ static_cast<RenderWidgetHostViewChildFrame*>(
+ child_node->current_frame_host()->GetRenderWidgetHost()->GetView());
+
+ WaitForChildFrameSurfaceReady(child_node->current_frame_host());
+
+ ASSERT_EQ(gfx::Vector2dF(), rwhv_root->GetLastScrollOffset());
+ ASSERT_EQ(gfx::Vector2dF(), rwhv_child->GetLastScrollOffset());
+
+ RenderWidgetHostInputEventRouter* router =
+ static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetInputEventRouter();
+
+ {
+ // Set up the RenderWidgetHostInputEventRouter to send the gesture stream
+ // to the child.
+ const gfx::Rect root_bounds = rwhv_root->GetViewBounds();
+ const gfx::Rect child_bounds = rwhv_child->GetViewBounds();
+ const float page_scale_factor = GetPageScaleFactor(shell());
+ const gfx::Point point_in_child(
+ gfx::ToCeiledInt((child_bounds.x() - root_bounds.x() + 10) *
+ page_scale_factor),
+ gfx::ToCeiledInt((child_bounds.y() - root_bounds.y() + 10) *
+ page_scale_factor));
+ gfx::Point dont_care;
+ ASSERT_EQ(rwhv_child->GetRenderWidgetHost(),
+ router->GetRenderWidgetHostAtPoint(rwhv_root, point_in_child,
+ &dont_care));
+
+ blink::WebTouchEvent touch_event(
+ blink::WebInputEvent::kTouchStart, blink::WebInputEvent::kNoModifiers,
+ blink::WebInputEvent::kTimeStampForTesting);
+ touch_event.touches_length = 1;
+ touch_event.touches[0].state = blink::WebTouchPoint::kStatePressed;
+ touch_event.touches[0].SetPositionInWidget(point_in_child.x(),
+ point_in_child.y());
+ touch_event.unique_touch_event_id = 1;
+ router->RouteTouchEvent(rwhv_root, &touch_event,
+ ui::LatencyInfo(ui::SourceEventType::TOUCH));
+
+ blink::WebGestureEvent gesture_event(
+ blink::WebInputEvent::kGestureTapDown,
+ blink::WebInputEvent::kNoModifiers,
+ blink::WebInputEvent::kTimeStampForTesting);
+ gesture_event.source_device = blink::kWebGestureDeviceTouchscreen;
+ gesture_event.unique_touch_event_id = touch_event.unique_touch_event_id;
+ router->RouteGestureEvent(rwhv_root, &gesture_event,
+ ui::LatencyInfo(ui::SourceEventType::TOUCH));
+ }
+
+#if defined(USE_AURA)
+ RenderWidgetHostViewAura* rwhva =
+ static_cast<RenderWidgetHostViewAura*>(rwhv_root);
+ std::unique_ptr<MockOverscrollControllerDelegateAura>
+ mock_overscroll_delegate =
+ base::MakeUnique<MockOverscrollControllerDelegateAura>(rwhva);
+ rwhva->overscroll_controller()->set_delegate(mock_overscroll_delegate.get());
+ MockOverscrollObserver* mock_overscroll_observer =
+ mock_overscroll_delegate.get();
+#elif defined(OS_ANDROID)
+ RenderWidgetHostViewAndroid* rwhv_android =
+ static_cast<RenderWidgetHostViewAndroid*>(rwhv_root);
+ std::unique_ptr<MockOverscrollRefreshHandlerAndroid> mock_overscroll_handler =
+ base::MakeUnique<MockOverscrollRefreshHandlerAndroid>();
+ rwhv_android->SetOverscrollControllerForTesting(
+ mock_overscroll_handler.get());
+ MockOverscrollObserver* mock_overscroll_observer =
+ mock_overscroll_handler.get();
+#endif // defined(USE_AURA)
+
+ std::unique_ptr<InputEventAckWaiter> gesture_begin_observer_child =
+ base::MakeUnique<InputEventAckWaiter>(
+ blink::WebInputEvent::kGestureScrollBegin);
+ child_node->current_frame_host()
+ ->GetRenderWidgetHost()
+ ->AddInputEventObserver(gesture_begin_observer_child.get());
+ std::unique_ptr<InputEventAckWaiter> gesture_end_observer_child =
+ base::MakeUnique<InputEventAckWaiter>(
+ blink::WebInputEvent::kGestureScrollEnd);
+ child_node->current_frame_host()
+ ->GetRenderWidgetHost()
+ ->AddInputEventObserver(gesture_end_observer_child.get());
+
+#if defined(USE_AURA)
+ const float overscroll_threshold =
+ GetOverscrollConfig(OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START_TOUCHSCREEN);
+#elif defined(OS_ANDROID)
+ const float overscroll_threshold = 0.f;
+#endif
+
+ // First we need our scroll to initiate an overscroll gesture in the root
+ // via unconsumed scrolls in the child.
+ blink::WebGestureEvent gesture_scroll_begin(
+ blink::WebGestureEvent::kGestureScrollBegin,
+ blink::WebInputEvent::kNoModifiers,
+ blink::WebInputEvent::kTimeStampForTesting);
+ gesture_scroll_begin.source_device = blink::kWebGestureDeviceTouchscreen;
+ gesture_scroll_begin.unique_touch_event_id = 1;
+ gesture_scroll_begin.data.scroll_begin.delta_hint_units =
+ blink::WebGestureEvent::ScrollUnits::kPrecisePixels;
+ gesture_scroll_begin.data.scroll_begin.delta_x_hint = 0.f;
+ gesture_scroll_begin.data.scroll_begin.delta_y_hint = 0.f;
+#if defined(USE_AURA)
+ // For aura, we scroll horizontally to activate an overscroll navigation.
+ gesture_scroll_begin.data.scroll_begin.delta_x_hint =
+ overscroll_threshold + 1;
+#elif defined(OS_ANDROID)
+ // For android, we scroll vertically to activate pull-to-refresh.
+ gesture_scroll_begin.data.scroll_begin.delta_y_hint =
+ overscroll_threshold + 1;
+#endif
+ router->RouteGestureEvent(rwhv_root, &gesture_scroll_begin,
+ ui::LatencyInfo(ui::SourceEventType::TOUCH));
+
+ // Make sure the child is indeed receiving the gesture stream.
+ gesture_begin_observer_child->Wait();
+
+ blink::WebGestureEvent gesture_scroll_update(
+ blink::WebGestureEvent::kGestureScrollUpdate,
+ blink::WebInputEvent::kNoModifiers,
+ blink::WebInputEvent::kTimeStampForTesting);
+ gesture_scroll_update.source_device = blink::kWebGestureDeviceTouchscreen;
+ gesture_scroll_update.unique_touch_event_id = 1;
+ gesture_scroll_update.data.scroll_update.delta_units =
+ blink::WebGestureEvent::ScrollUnits::kPrecisePixels;
+ gesture_scroll_update.data.scroll_update.delta_x = 0.f;
+ gesture_scroll_update.data.scroll_update.delta_y = 0.f;
+#if defined(USE_AURA)
+ float* delta = &gesture_scroll_update.data.scroll_update.delta_x;
+#elif defined(OS_ANDROID)
+ float* delta = &gesture_scroll_update.data.scroll_update.delta_y;
+#endif
+ *delta = overscroll_threshold + 1;
+ mock_overscroll_observer->Reset();
+ // This will bring us into an overscroll gesture.
+ router->RouteGestureEvent(rwhv_root, &gesture_scroll_update,
+ ui::LatencyInfo(ui::SourceEventType::TOUCH));
+ // Note that in addition to verifying that we get the overscroll update, it
+ // is necessary to wait before sending the next event to prevent our multiple
+ // GestureScrollUpdates from being coalesced.
+ mock_overscroll_observer->WaitForUpdate();
+
+ // This scroll is in the same direction and so it will contribute to the
+ // overscroll.
+ *delta = 10.0f;
+ mock_overscroll_observer->Reset();
+ router->RouteGestureEvent(rwhv_root, &gesture_scroll_update,
+ ui::LatencyInfo(ui::SourceEventType::TOUCH));
+ mock_overscroll_observer->WaitForUpdate();
+
+ // Now we reverse direction. The child could scroll in this direction, but
+ // since we're in an overscroll gesture, the root should consume it.
+ *delta = -5.0f;
+ mock_overscroll_observer->Reset();
+ router->RouteGestureEvent(rwhv_root, &gesture_scroll_update,
+ ui::LatencyInfo(ui::SourceEventType::TOUCH));
+ mock_overscroll_observer->WaitForUpdate();
+
+ blink::WebGestureEvent gesture_scroll_end(
+ blink::WebGestureEvent::kGestureScrollEnd,
+ blink::WebInputEvent::kNoModifiers,
+ blink::WebInputEvent::kTimeStampForTesting);
+ gesture_scroll_end.source_device = blink::kWebGestureDeviceTouchscreen;
+ gesture_scroll_end.unique_touch_event_id = 1;
+ gesture_scroll_end.data.scroll_end.delta_units =
+ blink::WebGestureEvent::ScrollUnits::kPrecisePixels;
+ mock_overscroll_observer->Reset();
+ router->RouteGestureEvent(rwhv_root, &gesture_scroll_end,
+ ui::LatencyInfo(ui::SourceEventType::TOUCH));
+ mock_overscroll_observer->WaitForEnd();
+
+ // Ensure that the method of providing the child's scroll events to the root
+ // does not leave the child in an invalid state.
+ gesture_end_observer_child->Wait();
+}
+#endif // defined(USE_AURA) || defined(OS_ANDROID)
+
// Test that an ET_SCROLL event sent to an out-of-process iframe correctly
// results in a scroll. This is only handled by RenderWidgetHostViewAura
// and is needed for trackpad scrolling on Chromebooks.
@@ -1892,15 +2124,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
}
// Ensure that OOPIFs are deleted after navigating to a new main frame.
-
-// Crashes on Win only. https://crbug.com/746055
-#if defined(OS_WIN)
-#define MAYBE_CleanupCrossSiteIframe DISABLED_CleanupCrossSiteIframe
-#else
-#define MAYBE_CleanupCrossSiteIframe CleanupCrossSiteIframe
-#endif
-IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
- MAYBE_CleanupCrossSiteIframe) {
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, CleanupCrossSiteIframe) {
GURL main_url(embedded_test_server()->GetURL(
"a.com", "/cross_site_iframe_factory.html?a(a,a(a,a(a)))"));
EXPECT_TRUE(NavigateToURL(shell(), main_url));
@@ -1957,14 +2181,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
}
// Ensure that root frames cannot be detached.
-
-// Crashes on Win only. https://crbug.com/746055
-#if defined(OS_WIN)
-#define MAYBE_RestrictFrameDetach DISABLED_RestrictFrameDetach
-#else
-#define MAYBE_RestrictFrameDetach RestrictFrameDetach
-#endif
-IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, MAYBE_RestrictFrameDetach) {
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, RestrictFrameDetach) {
GURL main_url(embedded_test_server()->GetURL(
"a.com", "/cross_site_iframe_factory.html?a(a,a(a,a(a)))"));
EXPECT_TRUE(NavigateToURL(shell(), main_url));
@@ -2026,13 +2243,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, MAYBE_RestrictFrameDetach) {
DepictFrameTree(root));
}
-// Crashes on Win only. https://crbug.com/746055
-#if defined(OS_WIN)
-#define MAYBE_NavigateRemoteFrame DISABLED_NavigateRemoteFrame
-#else
-#define MAYBE_NavigateRemoteFrame NavigateRemoteFrame
-#endif
-IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, MAYBE_NavigateRemoteFrame) {
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, NavigateRemoteFrame) {
GURL main_url(embedded_test_server()->GetURL(
"a.com", "/cross_site_iframe_factory.html?a(a,a(a,a(a)))"));
EXPECT_TRUE(NavigateToURL(shell(), main_url));
@@ -2495,7 +2706,7 @@ class FailingLoadFactory : public mojom::URLLoaderFactory {
FailingLoadFactory() {}
~FailingLoadFactory() override {}
- void CreateLoaderAndStart(mojom::URLLoaderAssociatedRequest loader,
+ void CreateLoaderAndStart(mojom::URLLoaderRequest loader,
int32_t routing_id,
int32_t request_id,
uint32_t options,
@@ -2505,10 +2716,8 @@ class FailingLoadFactory : public mojom::URLLoaderFactory {
traffic_annotation) override {
new FailingURLLoaderImpl(std::move(client));
}
- void SyncLoad(int32_t routing_id,
- int32_t request_id,
- const ResourceRequest& request,
- SyncLoadCallback callback) override {}
+
+ void Clone(mojom::URLLoaderFactoryRequest request) override { NOTREACHED(); }
};
}
@@ -3238,15 +3447,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// Ensure that when navigating a frame cross-process RenderFrameProxyHosts are
// created in the FrameTree skipping the subtree of the navigating frame.
-
-// Crashes on Win only. https://crbug.com/746055
-#if defined(OS_WIN)
-#define MAYBE_ProxyCreationSkipsSubtree DISABLED_ProxyCreationSkipsSubtree
-#else
-#define MAYBE_ProxyCreationSkipsSubtree ProxyCreationSkipsSubtree
-#endif
IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
- MAYBE_ProxyCreationSkipsSubtree) {
+ ProxyCreationSkipsSubtree) {
GURL main_url(embedded_test_server()->GetURL(
"a.com", "/cross_site_iframe_factory.html?a(a,a(a,a(a)))"));
EXPECT_TRUE(NavigateToURL(shell(), main_url));
@@ -7154,43 +7356,358 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, ParentDetachRemoteChild) {
EXPECT_TRUE(watcher.did_exit_normally());
}
-IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, VisibilityChanged) {
- GURL main_url(
- embedded_test_server()->GetURL("a.com", "/page_with_iframe.html"));
+// TODO(ekaramad): Move this test out of this file when addressing
+// https://crbug.com/754726.
+// This test verifies that RFHImpl::ForEachImmediateLocalRoot works as expected.
+// The frame tree used in the test is:
+// A0
+// / | \
+// A1 B1 A2
+// / \ | / \
+// B2 A3 B3 A4 C2
+// / / / \ \
+// D1 D2 C3 C4 C5
+//
+// As an example, the expected set of immediate local roots for the root node A0
+// should be {B1, B2, C2, D2, C5}. Note that the order is compatible with that
+// of a BFS traversal from root node A0.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, FindImmediateLocalRoots) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com",
+ "/cross_site_iframe_factory.html?a(a(b(d),a(d)),b(b(c,c)),a(a(c),c))"));
EXPECT_TRUE(NavigateToURL(shell(), main_url));
- EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(), main_url);
- GURL cross_site_url =
- embedded_test_server()->GetURL("oopif.com", "/title1.html");
+ // Each entry is of the frame "LABEL:ILR1ILR2..." where ILR stands for
+ // immediate local root.
+ std::string immediate_local_roots[] = {
+ "A0:B1B2C2D2C5", "A1:B2D2", "B1:C3C4", "A2:C2C5", "B2:D1",
+ "A3:D2", "B3:C3C4", "A4:C5", "C2:", "D1:",
+ "D2:", "C3:", "C4:", "C5:"};
+
+ std::map<RenderFrameHostImpl*, std::string>
+ frame_to_immediate_local_roots_map;
+ std::map<RenderFrameHostImpl*, std::string> frame_to_label_map;
+ size_t index = 0;
+ // Map each RenderFrameHostImpl to its label and set of immediate local roots.
+ for (auto* ftn : web_contents()->GetFrameTree()->Nodes()) {
+ std::string roots = immediate_local_roots[index++];
+ frame_to_immediate_local_roots_map[ftn->current_frame_host()] = roots;
+ frame_to_label_map[ftn->current_frame_host()] = roots.substr(0, 2);
+ }
+
+ // For each frame in the tree, verify that ForEachImmediateLocalRoot properly
+ // visits each and only each immediate local root in a BFS traversal order.
+ for (auto* ftn : web_contents()->GetFrameTree()->Nodes()) {
+ RenderFrameHostImpl* current_frame_host = ftn->current_frame_host();
+ std::list<RenderFrameHostImpl*> frame_list;
+ current_frame_host->ForEachImmediateLocalRoot(
+ base::Bind([](std::list<RenderFrameHostImpl*>* ilr_list,
+ RenderFrameHostImpl* rfh) { ilr_list->push_back(rfh); },
+ &frame_list));
+
+ std::string result = frame_to_label_map[current_frame_host];
+ result.append(":");
+ for (auto* ilr_ptr : frame_list)
+ result.append(frame_to_label_map[ilr_ptr]);
+ EXPECT_EQ(frame_to_immediate_local_roots_map[current_frame_host], result);
+ }
+}
+
+// This test verifies that changing the CSS visibility of a cross-origin
+// <iframe> is forwarded to its corresponding RenderWidgetHost and all other
+// RenderWidgetHosts corresponding to the nested cross-origin frame.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, CSSVisibilityChanged) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b(b(c(d(d(a))))))"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
- FrameTreeNode* root = web_contents()->GetFrameTree()->root();
+ // Find all child RenderWidgetHosts.
+ std::vector<RenderWidgetHostImpl*> child_widget_hosts;
+ FrameTreeNode* first_cross_process_child =
+ web_contents()->GetFrameTree()->root()->child_at(0);
+ for (auto* ftn : web_contents()->GetFrameTree()->SubtreeNodes(
+ first_cross_process_child)) {
+ RenderFrameHostImpl* frame_host = ftn->current_frame_host();
+ if (!frame_host->is_local_root())
+ continue;
- TestNavigationObserver observer(shell()->web_contents());
+ child_widget_hosts.push_back(frame_host->GetRenderWidgetHost());
+ }
- NavigateFrameToURL(root->child_at(0), cross_site_url);
- EXPECT_EQ(cross_site_url, observer.last_navigation_url());
- EXPECT_TRUE(observer.last_navigation_succeeded());
+ // Ignoring the root, there is exactly 4 local roots and hence 5
+ // RenderWidgetHosts on the page.
+ EXPECT_EQ(4U, child_widget_hosts.size());
- RenderWidgetHostImpl* render_widget_host =
- root->child_at(0)->current_frame_host()->GetRenderWidgetHost();
- EXPECT_FALSE(render_widget_host->is_hidden());
+ // Initially all the RenderWidgetHosts should be visible.
+ for (size_t index = 0; index < child_widget_hosts.size(); ++index) {
+ EXPECT_FALSE(child_widget_hosts[index]->is_hidden())
+ << "The RWH at distance " << index + 1U
+ << " from root RWH should not be hidden.";
+ }
std::string show_script =
"document.querySelector('iframe').style.visibility = 'visible';";
std::string hide_script =
"document.querySelector('iframe').style.visibility = 'hidden';";
- // Verify that hiding leads to a notification from RenderWidgetHost.
- RenderWidgetHostVisibilityObserver hide_observer(
- root->child_at(0)->current_frame_host()->GetRenderWidgetHost(), false);
+ // Define observers for notifications about hiding child RenderWidgetHosts.
+ std::vector<std::unique_ptr<RenderWidgetHostVisibilityObserver>>
+ hide_widget_host_observers(child_widget_hosts.size());
+ for (size_t index = 0U; index < child_widget_hosts.size(); ++index) {
+ hide_widget_host_observers[index].reset(
+ new RenderWidgetHostVisibilityObserver(child_widget_hosts[index],
+ false));
+ }
+
EXPECT_TRUE(ExecuteScript(shell(), hide_script));
- EXPECT_TRUE(hide_observer.WaitUntilSatisfied());
+ for (size_t index = 0U; index < child_widget_hosts.size(); ++index) {
+ EXPECT_TRUE(hide_widget_host_observers[index]->WaitUntilSatisfied())
+ << "Expected RenderWidgetHost at distance " << index + 1U
+ << " from root RenderWidgetHost to become hidden.";
+ }
+
+ // Define observers for notifications about showing child RenderWidgetHosts.
+ std::vector<std::unique_ptr<RenderWidgetHostVisibilityObserver>>
+ show_widget_host_observers(child_widget_hosts.size());
+ for (size_t index = 0U; index < child_widget_hosts.size(); ++index) {
+ show_widget_host_observers[index].reset(
+ new RenderWidgetHostVisibilityObserver(child_widget_hosts[index],
+ true));
+ }
- // Verify showing leads to a notification as well.
- RenderWidgetHostVisibilityObserver show_observer(
- root->child_at(0)->current_frame_host()->GetRenderWidgetHost(), true);
EXPECT_TRUE(ExecuteScript(shell(), show_script));
- EXPECT_TRUE(show_observer.WaitUntilSatisfied());
+ for (size_t index = 0U; index < child_widget_hosts.size(); ++index) {
+ EXPECT_TRUE(show_widget_host_observers[index]->WaitUntilSatisfied())
+ << "Expected RenderWidgetHost at distance " << index + 1U
+ << " from root RenderWidgetHost to become shown.";
+ }
+}
+
+// A class which counts the number of times a RenderWidgetHostViewChildFrame
+// swaps compositor frames.
+class ChildFrameCompositorFrameSwapCounter {
+ public:
+ explicit ChildFrameCompositorFrameSwapCounter(
+ RenderWidgetHostViewChildFrame* view)
+ : view_(view), weak_factory_(this) {
+ RegisterCallback();
+ }
+
+ ~ChildFrameCompositorFrameSwapCounter() {}
+
+ // Wait until at least |count| new frames are swapped.
+ void WaitForNewFrames(size_t count) {
+ while (counter_ < count) {
+ base::RunLoop loop;
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE, loop.QuitClosure(), TestTimeouts::tiny_timeout());
+ loop.Run();
+ }
+ }
+
+ void ResetCounter() { counter_ = 0; }
+ size_t GetCount() const { return counter_; }
+
+ private:
+ void RegisterCallback() {
+ view_->RegisterFrameSwappedCallback(base::MakeUnique<base::Closure>(
+ base::Bind(&ChildFrameCompositorFrameSwapCounter::OnFrameSwapped,
+ weak_factory_.GetWeakPtr())));
+ }
+ void OnFrameSwapped() {
+ counter_++;
+
+ // Register a new callback as the old one is released now.
+ RegisterCallback();
+ }
+
+ size_t counter_ = 0;
+
+ private:
+ RenderWidgetHostViewChildFrame* view_;
+ base::WeakPtrFactory<ChildFrameCompositorFrameSwapCounter> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(ChildFrameCompositorFrameSwapCounter);
+};
+
+// This test verifies that hiding an OOPIF in CSS will stop generating
+// compositor frames for the OOPIF and any nested OOPIFs inside it. This holds
+// even when the whole page is shown.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ HiddenOOPIFWillNotGenerateCompositorFrames) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/frame_tree/page_with_two_frames.html"));
+ ASSERT_TRUE(NavigateToURL(shell(), main_url));
+ ASSERT_EQ(shell()->web_contents()->GetLastCommittedURL(), main_url);
+
+ GURL cross_site_url_b =
+ embedded_test_server()->GetURL("b.com", "/counter.html");
+
+ FrameTreeNode* root = web_contents()->GetFrameTree()->root();
+
+ NavigateFrameToURL(root->child_at(0), cross_site_url_b);
+
+ NavigateFrameToURL(root->child_at(1), cross_site_url_b);
+
+ // Now inject code in the first frame to create a nested OOPIF.
+ RenderFrameHostCreatedObserver new_frame_created_observer(
+ shell()->web_contents(), 1);
+ ASSERT_TRUE(ExecuteScript(
+ root->child_at(0)->current_frame_host(),
+ "document.body.appendChild(document.createElement('iframe'));"));
+ new_frame_created_observer.Wait();
+
+ GURL cross_site_url_a =
+ embedded_test_server()->GetURL("a.com", "/counter.html");
+
+ // Navigate the nested frame.
+ TestFrameNavigationObserver observer(root->child_at(0)->child_at(0));
+ ASSERT_TRUE(ExecuteScript(
+ root->child_at(0)->current_frame_host(),
+ base::StringPrintf("document.querySelector('iframe').src = '%s';",
+ cross_site_url_a.spec().c_str())));
+ observer.Wait();
+
+ RenderWidgetHostViewChildFrame* first_child_view =
+ static_cast<RenderWidgetHostViewChildFrame*>(
+ root->child_at(0)->current_frame_host()->GetView());
+ RenderWidgetHostViewChildFrame* second_child_view =
+ static_cast<RenderWidgetHostViewChildFrame*>(
+ root->child_at(1)->current_frame_host()->GetView());
+ RenderWidgetHostViewChildFrame* nested_child_view =
+ static_cast<RenderWidgetHostViewChildFrame*>(
+ root->child_at(0)->child_at(0)->current_frame_host()->GetView());
+
+ ChildFrameCompositorFrameSwapCounter first_counter(first_child_view);
+ ChildFrameCompositorFrameSwapCounter second_counter(second_child_view);
+ ChildFrameCompositorFrameSwapCounter third_counter(nested_child_view);
+
+ const size_t kFrameCountLimit = 20u;
+
+ // Wait for a minimum number of compositor frames for the second frame.
+ second_counter.WaitForNewFrames(kFrameCountLimit);
+ ASSERT_LE(kFrameCountLimit, second_counter.GetCount());
+
+ // Now make sure all frames have roughly the counter value in the sense that
+ // no counter value is more than twice any other.
+ float ratio = static_cast<float>(first_counter.GetCount()) /
+ static_cast<float>(second_counter.GetCount());
+ EXPECT_GT(2.5f, ratio + 1 / ratio) << "Ratio is: " << ratio;
+
+ ratio = static_cast<float>(first_counter.GetCount()) /
+ static_cast<float>(third_counter.GetCount());
+ EXPECT_GT(2.5f, ratio + 1 / ratio) << "Ratio is: " << ratio;
+
+ // Make sure all views can become visible.
+ EXPECT_TRUE(first_child_view->CanBecomeVisible());
+ EXPECT_TRUE(second_child_view->CanBecomeVisible());
+ EXPECT_TRUE(nested_child_view->CanBecomeVisible());
+
+ // Hide the first frame and wait for the notification to be posted by its
+ // RenderWidgetHost.
+ RenderWidgetHostVisibilityObserver hide_observer(
+ root->child_at(0)->current_frame_host()->GetRenderWidgetHost(), false);
+
+ // Hide the first frame.
+ ASSERT_TRUE(ExecuteScript(
+ shell(),
+ "document.getElementsByName('frame1')[0].style.visibility = 'hidden'"));
+ ASSERT_TRUE(hide_observer.WaitUntilSatisfied());
+ EXPECT_TRUE(first_child_view->FrameConnectorForTesting()->IsHidden());
+
+ // Verify that only the second view can become visible now.
+ EXPECT_FALSE(first_child_view->CanBecomeVisible());
+ EXPECT_TRUE(second_child_view->CanBecomeVisible());
+ EXPECT_FALSE(nested_child_view->CanBecomeVisible());
+
+ // Now hide and show the WebContents (to simulate a tab switch).
+ shell()->web_contents()->WasHidden();
+ shell()->web_contents()->WasShown();
+
+ first_counter.ResetCounter();
+ second_counter.ResetCounter();
+ third_counter.ResetCounter();
+
+ // We expect the second counter to keep running.
+ second_counter.WaitForNewFrames(kFrameCountLimit);
+ ASSERT_LT(kFrameCountLimit, second_counter.GetCount() + 1u);
+
+ // Verify that the counter for other two frames did not count much.
+ ratio = static_cast<float>(first_counter.GetCount()) /
+ static_cast<float>(second_counter.GetCount());
+ EXPECT_GT(0.5f, ratio) << "Ratio is: " << ratio;
+
+ ratio = static_cast<float>(third_counter.GetCount()) /
+ static_cast<float>(second_counter.GetCount());
+ EXPECT_GT(0.5f, ratio) << "Ratio is: " << ratio;
+}
+
+// This test verifies that navigating a hidden OOPIF to cross-origin will not
+// lead to creating compositor frames for the new OOPIF renderer.
+IN_PROC_BROWSER_TEST_F(
+ SitePerProcessBrowserTest,
+ HiddenOOPIFWillNotGenerateCompositorFramesAfterNavigation) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/frame_tree/page_with_two_frames.html"));
+ ASSERT_TRUE(NavigateToURL(shell(), main_url));
+ ASSERT_EQ(shell()->web_contents()->GetLastCommittedURL(), main_url);
+
+ GURL cross_site_url_b =
+ embedded_test_server()->GetURL("b.com", "/counter.html");
+
+ FrameTreeNode* root = web_contents()->GetFrameTree()->root();
+
+ NavigateFrameToURL(root->child_at(0), cross_site_url_b);
+
+ NavigateFrameToURL(root->child_at(1), cross_site_url_b);
+
+ // Hide the first frame and wait for the notification to be posted by its
+ // RenderWidgetHost.
+ RenderWidgetHostVisibilityObserver hide_observer(
+ root->child_at(0)->current_frame_host()->GetRenderWidgetHost(), false);
+
+ // Hide the first frame.
+ ASSERT_TRUE(ExecuteScript(
+ shell(),
+ "document.getElementsByName('frame1')[0].style.visibility = 'hidden'"));
+ ASSERT_TRUE(hide_observer.WaitUntilSatisfied());
+
+ // Now navigate the first frame to another OOPIF process.
+ TestFrameNavigationObserver navigation_observer(
+ root->child_at(0)->current_frame_host());
+ GURL cross_site_url_c =
+ embedded_test_server()->GetURL("c.com", "/counter.html");
+ ASSERT_TRUE(ExecuteScript(
+ web_contents(),
+ base::StringPrintf("document.getElementsByName('frame1')[0].src = '%s';",
+ cross_site_url_c.spec().c_str())));
+ navigation_observer.Wait();
+
+ // Now investigate compositor frame creation.
+ RenderWidgetHostViewChildFrame* first_child_view =
+ static_cast<RenderWidgetHostViewChildFrame*>(
+ root->child_at(0)->current_frame_host()->GetView());
+
+ RenderWidgetHostViewChildFrame* second_child_view =
+ static_cast<RenderWidgetHostViewChildFrame*>(
+ root->child_at(1)->current_frame_host()->GetView());
+
+ EXPECT_FALSE(first_child_view->CanBecomeVisible());
+
+ ChildFrameCompositorFrameSwapCounter first_counter(first_child_view);
+ ChildFrameCompositorFrameSwapCounter second_counter(second_child_view);
+
+ const size_t kFrameCountLimit = 20u;
+
+ // Wait for a certain number of swapped compositor frames generated for the
+ // second child view. During the same interval the first frame should not have
+ // swapped any compositor frames.
+ second_counter.WaitForNewFrames(kFrameCountLimit);
+ ASSERT_LT(kFrameCountLimit, second_counter.GetCount() + 1u);
+
+ float ratio = static_cast<float>(first_counter.GetCount()) /
+ static_cast<float>(second_counter.GetCount());
+ EXPECT_GT(0.5f, ratio) << "Ratio is: " << ratio;
}
// Verify that sandbox flags inheritance works across multiple levels of
@@ -7348,11 +7865,29 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// Navigate the popup cross-site. This should keep the unique origin and the
// inherited sandbox flags.
GURL c_url(embedded_test_server()->GetURL("c.com", "/title1.html"));
- TestFrameNavigationObserver popup_observer(foo_root);
- EXPECT_TRUE(
- ExecuteScript(foo_root, "location.href = '" + c_url.spec() + "';"));
- popup_observer.Wait();
- EXPECT_EQ(c_url, foo_shell->web_contents()->GetLastCommittedURL());
+ {
+ TestFrameNavigationObserver popup_observer(foo_root);
+ EXPECT_TRUE(
+ ExecuteScript(foo_root, "location.href = '" + c_url.spec() + "';"));
+ popup_observer.Wait();
+ EXPECT_EQ(c_url, foo_shell->web_contents()->GetLastCommittedURL());
+ }
+
+ // Confirm that the popup is still sandboxed, both on browser and renderer
+ // sides.
+ EXPECT_EQ(expected_flags, foo_root->effective_sandbox_flags());
+ EXPECT_EQ("null", GetDocumentOrigin(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
+ // origin and the inherited sandbox flags.
+ {
+ TestFrameNavigationObserver popup_observer(foo_root);
+ EXPECT_TRUE(
+ ExecuteScript(foo_root, "location.href = '" + frame_url.spec() + "';"));
+ popup_observer.Wait();
+ EXPECT_EQ(frame_url, foo_shell->web_contents()->GetLastCommittedURL());
+ }
// Confirm that the popup is still sandboxed, both on browser and renderer
// sides.
@@ -8093,12 +8628,12 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// Prevent b.com process from terminating right away once the subframe
// navigates away from b.com below. This is necessary so that the renderer
// process has time to process the closings of RenderWidget and RenderView,
- // which is where the original bug was triggered. Incrementing worker
- // RefCount will cause RenderProcessHostImpl::Cleanup to forego process
+ // which is where the original bug was triggered. Incrementing the keep alive
+ // ref count will cause RenderProcessHostImpl::Cleanup to forego process
// termination.
RenderProcessHost* subframe_process =
root->child_at(0)->current_frame_host()->GetProcess();
- subframe_process->IncrementSharedWorkerRefCount();
+ subframe_process->IncrementKeepAliveRefCount();
// Navigate the subframe away from b.com. Since this is the last active
// frame in the b.com process, this causes the RenderWidget and RenderView to
@@ -8120,7 +8655,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// process hasn't heard the OnChannelError yet). This race will need to be
// fixed.
- subframe_process->DecrementSharedWorkerRefCount();
+ subframe_process->DecrementKeepAliveRefCount();
}
// Tests that an input event targeted to a out-of-process iframe correctly
@@ -8504,10 +9039,10 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
#endif
// Check that out-of-process frames correctly calculate their ability to enter
-// fullscreen. A frame is allowed enter fullscreen if the allowFullscreen
-// attribute is present in all of its ancestor <iframe> elements. For OOPIF,
-// when a parent frame changes this attribute, the change is replicated to the
-// child frame and its proxies.
+// fullscreen when Feature Policy is disabled. A frame is allowed to enter
+// fullscreen if the allowFullscreen attribute is present in all of its ancestor
+// <iframe> elements. For OOPIF, when a parent frame changes this attribute,
+// the change is replicated to the child frame and its proxies.
//
// The test checks the following cases:
//
@@ -8515,14 +9050,12 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// 2. Attribute injected dynamically via JavaScript
// 3. Multiple levels of nesting (A-embed-B-embed-C)
// 4. Cross-site subframe navigation
-
-// Crashes on Win only. https://crbug.com/746055
-#if defined(OS_WIN)
-#define MAYBE_AllowFullscreen DISABLED_AllowFullscreen
-#else
-#define MAYBE_AllowFullscreen AllowFullscreen
-#endif
-IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, MAYBE_AllowFullscreen) {
+//
+// Note that this is testing deprecated behavior that will eventually be
+// removed, once the Fullscreen spec has been updated to integrate with Feature
+// Policy.
+IN_PROC_BROWSER_TEST_F(SitePerProcessFeaturePolicyDisabledBrowserTest,
+ AllowFullscreen) {
// Load a page with a cross-site <iframe allowFullscreen>.
GURL url_1(embedded_test_server()->GetURL(
"a.com", "/page_with_allowfullscreen_frame.html"));
@@ -9784,74 +10317,6 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
FrameHostMsg_ContextMenu(rfh->GetRoutingID(), ContextMenuParams()));
}
-// Test iframe "allow" attribute is propagated correctly.
-IN_PROC_BROWSER_TEST_F(SitePerProcessFeaturePolicyBrowserTest, AllowedIFrames) {
- GURL url(embedded_test_server()->GetURL("/allowed_frames.html"));
- EXPECT_TRUE(NavigateToURL(shell(), url));
-
- FrameTreeNode* root = web_contents()->GetFrameTree()->root();
-
- // Iframes without "allow" attribute, or an empty "allow" attribute will not
- // have any allowed features propagated.
- EXPECT_TRUE(
- root->child_at(0)->frame_owner_properties().allowed_features.empty());
- EXPECT_TRUE(
- root->child_at(1)->frame_owner_properties().allowed_features.empty());
-
- // Make sure the third frame starts out at the correct cross-site page.
- EXPECT_EQ(embedded_test_server()->GetURL("bar.com", "/title1.html"),
- root->child_at(2)->current_url());
- // Check allowed features are propagated correctly for cross-site iframes.
- EXPECT_EQ(root->child_at(2)->frame_owner_properties().allowed_features.size(),
- 2u);
- EXPECT_EQ(root->child_at(2)->frame_owner_properties().allowed_features[0],
- blink::WebFeaturePolicyFeature::kFullscreen);
- EXPECT_EQ(root->child_at(2)->frame_owner_properties().allowed_features[1],
- blink::WebFeaturePolicyFeature::kVibrate);
-
- // Check allowed features are propagated correctly for same-site iframes.
- EXPECT_EQ(root->child_at(3)->frame_owner_properties().allowed_features.size(),
- 2u);
- EXPECT_EQ(root->child_at(3)->frame_owner_properties().allowed_features[0],
- blink::WebFeaturePolicyFeature::kFullscreen);
- EXPECT_EQ(root->child_at(3)->frame_owner_properties().allowed_features[1],
- blink::WebFeaturePolicyFeature::kVibrate);
-}
-
-// Test dynamic updates to iframe "allow" attribute are propagated correctly.
-IN_PROC_BROWSER_TEST_F(SitePerProcessFeaturePolicyBrowserTest,
- AllowedIFramesDynamic) {
- GURL main_url(embedded_test_server()->GetURL("/allowed_frames.html"));
- EXPECT_TRUE(NavigateToURL(shell(), main_url));
-
- FrameTreeNode* root = web_contents()->GetFrameTree()->root();
-
- // Test for dynamically removing "allow" attribute.
- EXPECT_TRUE(ExecuteScript(
- root, "document.getElementById('child-2').removeAttribute('allow')"));
- EXPECT_TRUE(
- root->child_at(2)->frame_owner_properties().allowed_features.empty());
-
- // Test for dynamically setting "allow" attribute by element.setAttribute.
- EXPECT_TRUE(ExecuteScript(
- root,
- "document.getElementById('child-3').setAttribute('allow', 'payment')"));
- EXPECT_EQ(root->child_at(3)->frame_owner_properties().allowed_features.size(),
- 1u);
- EXPECT_EQ(root->child_at(3)->frame_owner_properties().allowed_features[0],
- blink::WebFeaturePolicyFeature::kPayment);
-
- // Test for dynamically setting "allow" attribute by frame.allow="...".
- EXPECT_TRUE(ExecuteScript(
- root, "document.getElementById('child-3').allow='fullscreen vibrate'"));
- EXPECT_EQ(root->child_at(3)->frame_owner_properties().allowed_features.size(),
- 2u);
- EXPECT_EQ(root->child_at(3)->frame_owner_properties().allowed_features[0],
- blink::WebFeaturePolicyFeature::kFullscreen);
- EXPECT_EQ(root->child_at(3)->frame_owner_properties().allowed_features[1],
- blink::WebFeaturePolicyFeature::kVibrate);
-}
-
// Test iframe container policy is replicated properly to the browser.
IN_PROC_BROWSER_TEST_F(SitePerProcessFeaturePolicyBrowserTest,
ContainerPolicy) {
@@ -10606,17 +11071,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// Check that subframes for the same site rendering in unrelated tabs start
// sharing processes that are already dedicated to that site when over process
// limit. See https://crbug.com/513036.
-
-// Crashes on Win only. https://crbug.com/746055
-#if defined(OS_WIN)
-#define MAYBE_SubframeProcessReuseWhenOverLimit \
- DISABLED_SubframeProcessReuseWhenOverLimit
-#else
-#define MAYBE_SubframeProcessReuseWhenOverLimit \
- SubframeProcessReuseWhenOverLimit
-#endif
IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
- MAYBE_SubframeProcessReuseWhenOverLimit) {
+ SubframeProcessReuseWhenOverLimit) {
// Set the process limit to 1.
RenderProcessHost::SetMaxRendererProcessCount(1);
@@ -10671,6 +11127,89 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
}
#if defined(OS_ANDROID)
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, TestChildProcessImportance) {
+ web_contents()->SetImportance(ChildProcessImportance::MODERATE);
+
+ // Construct root page with one child in different domain.
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b)"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+ FrameTreeNode* root = web_contents()->GetFrameTree()->root();
+ ASSERT_EQ(1u, root->child_count());
+ FrameTreeNode* child = root->child_at(0);
+
+ // Importance should survive initial navigation.
+ EXPECT_EQ(
+ ChildProcessImportance::MODERATE,
+ root->current_frame_host()->GetProcess()->ComputeEffectiveImportance());
+ EXPECT_EQ(
+ ChildProcessImportance::MODERATE,
+ child->current_frame_host()->GetProcess()->ComputeEffectiveImportance());
+
+ // Check setting importance.
+ web_contents()->SetImportance(ChildProcessImportance::NORMAL);
+ EXPECT_EQ(
+ ChildProcessImportance::NORMAL,
+ root->current_frame_host()->GetProcess()->ComputeEffectiveImportance());
+ EXPECT_EQ(
+ ChildProcessImportance::NORMAL,
+ child->current_frame_host()->GetProcess()->ComputeEffectiveImportance());
+ web_contents()->SetImportance(ChildProcessImportance::IMPORTANT);
+ EXPECT_EQ(
+ ChildProcessImportance::IMPORTANT,
+ root->current_frame_host()->GetProcess()->ComputeEffectiveImportance());
+ EXPECT_EQ(
+ ChildProcessImportance::IMPORTANT,
+ child->current_frame_host()->GetProcess()->ComputeEffectiveImportance());
+
+ // Check importance is maintained if child navigates to new domain.
+ int old_child_process_id = child->current_frame_host()->GetProcess()->GetID();
+ GURL url = embedded_test_server()->GetURL("foo.com", "/title2.html");
+ {
+ RenderFrameDeletedObserver deleted_observer(child->current_frame_host());
+ NavigateFrameToURL(root->child_at(0), url);
+ deleted_observer.WaitUntilDeleted();
+ }
+ int new_child_process_id = child->current_frame_host()->GetProcess()->GetID();
+ EXPECT_NE(old_child_process_id, new_child_process_id);
+ EXPECT_EQ(
+ ChildProcessImportance::IMPORTANT,
+ child->current_frame_host()->GetProcess()->ComputeEffectiveImportance());
+
+ // Check importance is maintained if root navigates to new domain.
+ int old_root_process_id = root->current_frame_host()->GetProcess()->GetID();
+ child = nullptr; // Going to navigate root to page without any child.
+ {
+ RenderFrameDeletedObserver deleted_observer(root->current_frame_host());
+ NavigateFrameToURL(root, url);
+ deleted_observer.WaitUntilDeleted();
+ }
+ EXPECT_EQ(0u, root->child_count());
+ int new_root_process_id = root->current_frame_host()->GetProcess()->GetID();
+ EXPECT_NE(old_root_process_id, new_root_process_id);
+ EXPECT_EQ(
+ ChildProcessImportance::IMPORTANT,
+ root->current_frame_host()->GetProcess()->ComputeEffectiveImportance());
+
+ // Check interstitial maintains importance.
+ TestInterstitialDelegate* delegate = new TestInterstitialDelegate;
+ WebContentsImpl* contents_impl =
+ static_cast<WebContentsImpl*>(web_contents());
+ GURL interstitial_url("http://interstitial");
+ InterstitialPageImpl* interstitial = new InterstitialPageImpl(
+ contents_impl, contents_impl, true, interstitial_url, delegate);
+ interstitial->Show();
+ WaitForInterstitialAttach(contents_impl);
+ RenderProcessHost* interstitial_process =
+ interstitial->GetMainFrame()->GetProcess();
+ EXPECT_EQ(ChildProcessImportance::IMPORTANT,
+ interstitial_process->ComputeEffectiveImportance());
+
+ web_contents()->SetImportance(ChildProcessImportance::MODERATE);
+ EXPECT_EQ(ChildProcessImportance::MODERATE,
+ interstitial_process->ComputeEffectiveImportance());
+}
+
// Tests for Android TouchSelectionEditing.
class TouchSelectionControllerClientAndroidSiteIsolationTest
: public SitePerProcessBrowserTest {
@@ -10721,10 +11260,15 @@ class TouchSelectionControllerClientAndroidSiteIsolationTest
ui::MotionEvent::Action action,
gfx::Point point) {
DCHECK(action >= ui::MotionEvent::ACTION_DOWN &&
- action << ui::MotionEvent::ACTION_CANCEL);
- ui::MotionEventGeneric touch(
- action, ui::EventTimeForNow(),
- ui::PointerProperties(point.x(), point.y(), 10));
+ action < ui::MotionEvent::ACTION_CANCEL);
+
+ ui::MotionEventAndroid::Pointer p(0, point.x(), point.y(), 10, 0, 0, 0, 0);
+ JNIEnv* env = base::android::AttachCurrentThread();
+ auto time_ms = (ui::EventTimeForNow() - base::TimeTicks()).InMilliseconds();
+ ui::MotionEventAndroid touch(
+ env, nullptr, 1.f, 0, 0, 0, time_ms,
+ ui::MotionEventAndroid::GetAndroidActionForTesting(action), 1, 0, 0, 0,
+ 0, 0, 0, 0, false, &p, nullptr);
view->OnTouchEvent(touch);
}
};
diff --git a/chromium/content/browser/site_per_process_mac_browsertest.mm b/chromium/content/browser/site_per_process_mac_browsertest.mm
index 20a1de4f974..60f9a66b680 100644
--- a/chromium/content/browser/site_per_process_mac_browsertest.mm
+++ b/chromium/content/browser/site_per_process_mac_browsertest.mm
@@ -223,7 +223,9 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessMacBrowserTest,
child_rwhv->ProcessMouseWheelEvent(scroll_event, ui::LatencyInfo());
// If wheel scroll latching is enabled, no wheel event with phase ended will
- // be sent before a wheel event with momentum phase began.
+ // be sent before a wheel event with momentum phase began. So, no
+ // GestureScrollEnd and no GestureScrollBegin will be generated between
+ // normal scroll and momentum scroll phases.
if (!child_rwhv->wheel_scroll_latching_enabled()) {
// End of non-momentum scrolling.
scroll_event.delta_y = 0.0f;
@@ -231,17 +233,17 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessMacBrowserTest,
scroll_event.momentum_phase = blink::WebMouseWheelEvent::kPhaseNone;
child_rwhv->ProcessMouseWheelEvent(scroll_event, ui::LatencyInfo());
gesture_scroll_end_ack_observer->Wait();
+ gesture_scroll_begin_ack_observer->Reset();
+ gesture_scroll_end_ack_observer->Reset();
}
- gesture_scroll_begin_ack_observer->Reset();
- gesture_scroll_end_ack_observer->Reset();
-
// We now go into a fling.
scroll_event.delta_y = -2.0f;
scroll_event.phase = blink::WebMouseWheelEvent::kPhaseNone;
scroll_event.momentum_phase = blink::WebMouseWheelEvent::kPhaseBegan;
child_rwhv->ProcessMouseWheelEvent(scroll_event, ui::LatencyInfo());
- gesture_scroll_begin_ack_observer->Wait();
+ if (!child_rwhv->wheel_scroll_latching_enabled())
+ gesture_scroll_begin_ack_observer->Wait();
scroll_event.delta_y = -2.0f;
scroll_event.phase = blink::WebMouseWheelEvent::kPhaseNone;
diff --git a/chromium/content/browser/speech/speech_recognition_browsertest.cc b/chromium/content/browser/speech/speech_recognition_browsertest.cc
index b1bf1abfa23..9b11bd5bba8 100644
--- a/chromium/content/browser/speech/speech_recognition_browsertest.cc
+++ b/chromium/content/browser/speech/speech_recognition_browsertest.cc
@@ -161,7 +161,8 @@ class SpeechRecognitionBrowserTest :
audio_bus->FromInterleaved(&audio_buffer.get()[0],
audio_bus->frames(),
audio_params.bits_per_sample() / 8);
- controller->sync_writer()->Write(audio_bus.get(), 0.0, false, 0);
+ controller->sync_writer()->Write(audio_bus.get(), 0.0, false,
+ base::TimeTicks::Now());
}
void FeedAudioController(int duration_ms, bool feed_with_noise) {
diff --git a/chromium/content/browser/speech/speech_recognition_engine.cc b/chromium/content/browser/speech/speech_recognition_engine.cc
index bd99e7ac998..53919a718cd 100644
--- a/chromium/content/browser/speech/speech_recognition_engine.cc
+++ b/chromium/content/browser/speech/speech_recognition_engine.cc
@@ -360,7 +360,7 @@ SpeechRecognitionEngine::ConnectBothStreams(const FSMEventArgs&) {
destination: GOOGLE_OWNED_SERVICE
}
policy {
- cookies_allowed: false
+ cookies_allowed: NO
setting:
"The user must allow the browser to access the microphone in a "
"permission prompt. This is set per site (hostname pattern). In "
@@ -454,7 +454,7 @@ SpeechRecognitionEngine::ConnectBothStreams(const FSMEventArgs&) {
destination: GOOGLE_OWNED_SERVICE
}
policy {
- cookies_allowed: false
+ cookies_allowed: NO
setting:
"The user must allow the browser to access the microphone in a "
"permission prompt. This is set per site (hostname pattern). In "
diff --git a/chromium/content/browser/speech/speech_recognition_manager_impl.h b/chromium/content/browser/speech/speech_recognition_manager_impl.h
index 8c18de8c6cf..7626cfeaa2b 100644
--- a/chromium/content/browser/speech/speech_recognition_manager_impl.h
+++ b/chromium/content/browser/speech/speech_recognition_manager_impl.h
@@ -50,9 +50,9 @@ class SpeechRecognizer;
// corresponding listener (demuxing on the base of their session_id).
// - Relays also recognition results/status/error events of every session to
// the catch-all snoop listener (optionally) provided by the delegate.
-class CONTENT_EXPORT SpeechRecognitionManagerImpl :
- public NON_EXPORTED_BASE(SpeechRecognitionManager),
- public SpeechRecognitionEventListener {
+class CONTENT_EXPORT SpeechRecognitionManagerImpl
+ : public SpeechRecognitionManager,
+ public SpeechRecognitionEventListener {
public:
// Returns the current SpeechRecognitionManagerImpl or NULL if the call is
// issued when it is not created yet or destroyed (by BrowserMainLoop).
diff --git a/chromium/content/browser/speech/speech_recognizer_impl.cc b/chromium/content/browser/speech/speech_recognizer_impl.cc
index 03bc4cbba43..82c3ce55d74 100644
--- a/chromium/content/browser/speech/speech_recognizer_impl.cc
+++ b/chromium/content/browser/speech/speech_recognizer_impl.cc
@@ -290,7 +290,7 @@ void SpeechRecognizerImpl::OnError(AudioInputController* controller,
void SpeechRecognizerImpl::Write(const AudioBus* data,
double volume,
bool key_pressed,
- uint32_t hardware_delay_bytes) {
+ base::TimeTicks capture_time) {
// 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);
@@ -565,8 +565,8 @@ SpeechRecognizerImpl::FSMState SpeechRecognizerImpl::PrepareRecognition(
DCHECK(recognition_engine_.get() != NULL);
DCHECK(!IsCapturingAudio());
GetAudioSystem()->GetInputStreamParameters(
- device_id_, base::Bind(&SpeechRecognizerImpl::OnDeviceInfo,
- weak_ptr_factory_.GetWeakPtr()));
+ device_id_, base::BindOnce(&SpeechRecognizerImpl::OnDeviceInfo,
+ weak_ptr_factory_.GetWeakPtr()));
listener()->OnRecognitionStart(session_id());
return STATE_PREPARING;
diff --git a/chromium/content/browser/speech/speech_recognizer_impl.h b/chromium/content/browser/speech/speech_recognizer_impl.h
index 711b501edf5..f69c48f21ea 100644
--- a/chromium/content/browser/speech/speech_recognizer_impl.h
+++ b/chromium/content/browser/speech/speech_recognizer_impl.h
@@ -35,7 +35,7 @@ class CONTENT_EXPORT SpeechRecognizerImpl
: public SpeechRecognizer,
public media::AudioInputController::EventHandler,
public media::AudioInputController::SyncWriter,
- public NON_EXPORTED_BASE(SpeechRecognitionEngine::Delegate) {
+ public SpeechRecognitionEngine::Delegate {
public:
static const int kAudioSampleRate;
static const media::ChannelLayout kChannelLayout;
@@ -156,7 +156,7 @@ class CONTENT_EXPORT SpeechRecognizerImpl
void Write(const media::AudioBus* data,
double volume,
bool key_pressed,
- uint32_t hardware_delay_bytes) override;
+ base::TimeTicks capture_time) override;
void Close() override;
// SpeechRecognitionEngineDelegate methods.
diff --git a/chromium/content/browser/speech/speech_recognizer_impl_android.cc b/chromium/content/browser/speech/speech_recognizer_impl_android.cc
index 143fa81c764..19bec767ab1 100644
--- a/chromium/content/browser/speech/speech_recognizer_impl_android.cc
+++ b/chromium/content/browser/speech/speech_recognizer_impl_android.cc
@@ -219,9 +219,4 @@ void SpeechRecognizerImplAndroid::OnRecognitionEnd(
listener()->OnRecognitionEnd(session_id());
}
-// static
-bool SpeechRecognizerImplAndroid::RegisterSpeechRecognizer(JNIEnv* env) {
- return RegisterNativesImpl(env);
-}
-
} // namespace content
diff --git a/chromium/content/browser/speech/speech_recognizer_impl_android.h b/chromium/content/browser/speech/speech_recognizer_impl_android.h
index f0a940e6e32..9f12627dcac 100644
--- a/chromium/content/browser/speech/speech_recognizer_impl_android.h
+++ b/chromium/content/browser/speech/speech_recognizer_impl_android.h
@@ -51,8 +51,6 @@ class CONTENT_EXPORT SpeechRecognizerImplAndroid : public SpeechRecognizer {
void OnRecognitionEnd(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj);
- static bool RegisterSpeechRecognizer(JNIEnv* env);
-
private:
enum State {
STATE_IDLE = 0,
diff --git a/chromium/content/browser/speech/speech_recognizer_impl_unittest.cc b/chromium/content/browser/speech/speech_recognizer_impl_unittest.cc
index e91f0677078..7fb87f5a1b6 100644
--- a/chromium/content/browser/speech/speech_recognizer_impl_unittest.cc
+++ b/chromium/content/browser/speech/speech_recognizer_impl_unittest.cc
@@ -197,7 +197,7 @@ class SpeechRecognizerImplTest : public SpeechRecognitionEventListener,
void OnData(media::AudioBus* data) {
auto* writer =
static_cast<AudioInputController::SyncWriter*>(recognizer_.get());
- writer->Write(data, 0.0, false, 0);
+ writer->Write(data, 0.0, false, base::TimeTicks::Now());
}
void WaitForAudioThreadToPostDeviceInfo() {
diff --git a/chromium/content/browser/ssl/ssl_manager.cc b/chromium/content/browser/ssl/ssl_manager.cc
index a4b1b910fa0..1b2e8cef61a 100644
--- a/chromium/content/browser/ssl/ssl_manager.cc
+++ b/chromium/content/browser/ssl/ssl_manager.cc
@@ -27,6 +27,8 @@
#include "content/public/browser/devtools_agent_host.h"
#include "content/public/browser/navigation_details.h"
#include "content/public/browser/ssl_host_state_delegate.h"
+#include "content/public/common/console_message_level.h"
+#include "net/cert/symantec_certs.h"
#include "net/url_request/url_request.h"
namespace content {
@@ -42,6 +44,37 @@ enum SSLGoodCertSeenEvent {
SSL_GOOD_CERT_SEEN_EVENT_MAX = 2
};
+// Should be called on navigation commit. Checks if the navigation described by
+// |details| was a different-page navigation that used a legacy Symantec
+// certificate |cert|, and if so, logs a console warning in |web_contents|.
+void MaybeLogLegacySymantecWarning(
+ const LoadCommittedDetails& details,
+ const scoped_refptr<net::X509Certificate>& cert,
+ const net::HashValueVector& public_key_hashes,
+ content::WebContents* web_contents) {
+ // No need to log on same-page navigations, because the message would be
+ // redundant.
+ if (details.is_same_document)
+ return;
+ if (!net::IsLegacySymantecCert(public_key_hashes))
+ return;
+ std::string content_client_message;
+ GURL url = details.entry->GetURL();
+ bool message_overridden =
+ GetContentClient()->browser()->OverrideLegacySymantecCertConsoleMessage(
+ url, cert, &content_client_message);
+ web_contents->GetMainFrame()->AddMessageToConsole(
+ CONSOLE_MESSAGE_LEVEL_WARNING,
+ message_overridden ? content_client_message
+ : "The certificate used to load " + url.spec() +
+ " uses an SSL certificate that will be "
+ "distrusted in the future. "
+ "Once distrusted, users will be prevented from "
+ "loading this resource. See "
+ "https://g.co/chrome/symantecpkicerts for "
+ "more information.");
+}
+
void OnAllowCertificateWithRecordDecision(
bool record_decision,
const base::Callback<void(bool, content::CertificateRequestResultType)>&
@@ -191,7 +224,13 @@ SSLManager::~SSLManager() {
void SSLManager::DidCommitProvisionalLoad(const LoadCommittedDetails& details) {
NavigationEntryImpl* entry = controller_->GetLastCommittedEntry();
- int content_status_flags = 0;
+ int add_content_status_flags = 0;
+ int remove_content_status_flags = 0;
+
+ MaybeLogLegacySymantecWarning(details, entry->GetSSL().certificate,
+ entry->GetSSL().public_key_hashes,
+ controller_->delegate()->GetWebContents());
+
if (!details.is_main_frame) {
// If it wasn't a main-frame navigation, then carry over content
// status flags. (For example, the mixed content flag shouldn't
@@ -199,13 +238,25 @@ void SSLManager::DidCommitProvisionalLoad(const LoadCommittedDetails& details) {
NavigationEntryImpl* previous_entry =
controller_->GetEntryAtIndex(details.previous_entry_index);
if (previous_entry) {
- content_status_flags = previous_entry->GetSSL().content_status;
+ add_content_status_flags = previous_entry->GetSSL().content_status;
}
+ } else if (!details.is_same_document) {
+ // For main-frame non-same-page navigations, clear content status
+ // flags. These flags are set based on the content on the page, and thus
+ // should reflect the current content, even if the navigation was to an
+ // existing entry that already had content status flags set.
+ remove_content_status_flags = ~0;
+ // Also clear any UserData from the SSLStatus.
+ if (entry)
+ entry->GetSSL().user_data = nullptr;
+ }
+
+ if (!UpdateEntry(entry, add_content_status_flags,
+ remove_content_status_flags)) {
+ // Ensure the WebContents is notified that the SSL state changed when a
+ // load is committed, in case the active navigation entry has changed.
+ NotifyDidChangeVisibleSSLState();
}
- UpdateEntry(entry, content_status_flags, 0);
- // Always notify the WebContents that the SSL state changed when a
- // load is committed, in case the active navigation entry has changed.
- NotifyDidChangeVisibleSSLState();
}
void SSLManager::DidDisplayMixedContent() {
@@ -401,18 +452,18 @@ void SSLManager::OnCertErrorInternal(std::unique_ptr<SSLErrorHandler> handler,
base::Bind(&OnAllowCertificateWithRecordDecision, true, callback));
}
-void SSLManager::UpdateEntry(NavigationEntryImpl* entry,
+bool SSLManager::UpdateEntry(NavigationEntryImpl* entry,
int add_content_status_flags,
int remove_content_status_flags) {
// We don't always have a navigation entry to update, for example in the
// case of the Web Inspector.
if (!entry)
- return;
+ return false;
SSLStatus original_ssl_status = entry->GetSSL(); // Copy!
entry->GetSSL().initialized = true;
- entry->GetSSL().content_status |= add_content_status_flags;
entry->GetSSL().content_status &= ~remove_content_status_flags;
+ entry->GetSSL().content_status |= add_content_status_flags;
SiteInstance* site_instance = entry->site_instance();
// Note that |site_instance| can be NULL here because NavigationEntries don't
@@ -436,8 +487,13 @@ void SSLManager::UpdateEntry(NavigationEntryImpl* entry,
}
}
- if (!entry->GetSSL().Equals(original_ssl_status))
+ if (entry->GetSSL().initialized != original_ssl_status.initialized ||
+ entry->GetSSL().content_status != original_ssl_status.content_status) {
NotifyDidChangeVisibleSSLState();
+ return true;
+ }
+
+ return false;
}
void SSLManager::UpdateLastCommittedEntry(int add_content_status_flags,
diff --git a/chromium/content/browser/ssl/ssl_manager.h b/chromium/content/browser/ssl/ssl_manager.h
index a99dfbd674b..e3a17f55b58 100644
--- a/chromium/content/browser/ssl/ssl_manager.h
+++ b/chromium/content/browser/ssl/ssl_manager.h
@@ -113,14 +113,14 @@ class CONTENT_EXPORT SSLManager {
void OnCertErrorInternal(std::unique_ptr<SSLErrorHandler> handler,
int options_mask);
- // Updates the NavigationEntry's |content_status| flags according to
- // state in |ssl_host_state_delegate|. |add_content_status_flags| and
- // |remove_content_status_flags| are bitmasks of
- // SSLStatus::ContentStatusFlags that will be added or removed from
- // the |content_status| field. (Pass 0 to add/remove no content status
- // flags.) This method will notify the WebContents of an SSL state
- // change if a change was actually made.
- void UpdateEntry(NavigationEntryImpl* entry,
+ // Updates the NavigationEntry's |content_status| flags according to state in
+ // |ssl_host_state_delegate|. |add_content_status_flags| and
+ // |remove_content_status_flags| are bitmasks of SSLStatus::ContentStatusFlags
+ // that will be added or removed from the |content_status| field. (Pass 0 to
+ // add/remove no content status flags.) |remove_content_status_flags| are
+ // removed before |add_content_status_flags| are added. If the final set of
+ // flags changes, this method will notify the WebContents and return true.
+ bool UpdateEntry(NavigationEntryImpl* entry,
int add_content_status_flags,
int remove_content_status_flags);
diff --git a/chromium/content/browser/ssl/ssl_manager_unittest.cc b/chromium/content/browser/ssl/ssl_manager_unittest.cc
index cd910452bce..54fa0b036a2 100644
--- a/chromium/content/browser/ssl/ssl_manager_unittest.cc
+++ b/chromium/content/browser/ssl/ssl_manager_unittest.cc
@@ -6,6 +6,7 @@
#include "base/macros.h"
#include "content/browser/site_instance_impl.h"
+#include "content/common/frame_messages.h"
#include "content/public/browser/ssl_status.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/test/mock_render_process_host.h"
@@ -101,6 +102,64 @@ TEST_F(SSLManagerTest, NotifyVisibleSSLStateChangeOnPasswordAndHttpCreditCard) {
SSLStatus::DISPLAYED_CREDIT_CARD_FIELD_ON_HTTP);
}
+// Returns true if the given |sink| has received a Symantec warning console
+// message, and false otherwise.
+bool FindSymantecConsoleMessage(const IPC::TestSink& sink) {
+ for (size_t i = 0; i < sink.message_count(); i++) {
+ const IPC::Message* message = sink.GetMessageAt(i);
+ if (message->type() != FrameMsg_AddMessageToConsole::ID)
+ continue;
+ std::tuple<ConsoleMessageLevel, std::string> params;
+ FrameMsg_AddMessageToConsole::Read(message, &params);
+ if (std::get<0>(params) == CONSOLE_MESSAGE_LEVEL_WARNING &&
+ std::get<1>(params).find("will be distrusted") != std::string::npos) {
+ return true;
+ }
+ }
+ return false;
+}
+
+TEST_F(SSLManagerTest, SymantecConsoleMessage) {
+ SSLManager manager(
+ static_cast<NavigationControllerImpl*>(&web_contents()->GetController()));
+
+ // Set up a navigation entry with a Symantec public key hash and simulate
+ // navigation to that entry.
+ NavigateAndCommit(GURL("https://example.test"));
+ net::SHA256HashValue symantec_hash_value = {
+ {0xb2, 0xde, 0xf5, 0x36, 0x2a, 0xd3, 0xfa, 0xcd, 0x04, 0xbd, 0x29,
+ 0x04, 0x7a, 0x43, 0x84, 0x4f, 0x76, 0x70, 0x34, 0xea, 0x48, 0x92,
+ 0xf8, 0x0e, 0x56, 0xbe, 0xe6, 0x90, 0x24, 0x3e, 0x25, 0x02}};
+ web_contents()
+ ->GetController()
+ .GetLastCommittedEntry()
+ ->GetSSL()
+ .public_key_hashes.push_back(net::HashValue(symantec_hash_value));
+ process()->sink().ClearMessages();
+ // Navigate to the current entry, which now looks like a Symantec certificate.
+ Reload();
+ // Check that the expected console message was sent to the renderer to log.
+ EXPECT_TRUE(FindSymantecConsoleMessage(process()->sink()));
+
+ // Check that the console message is not logged when the certificate chain
+ // includes an excluded subCA.
+ net::SHA256HashValue google_hash_value = {
+ {0xec, 0x72, 0x29, 0x69, 0xcb, 0x64, 0x20, 0x0a, 0xb6, 0x63, 0x8f,
+ 0x68, 0xac, 0x53, 0x8e, 0x40, 0xab, 0xab, 0x5b, 0x19, 0xa6, 0x48,
+ 0x56, 0x61, 0x04, 0x2a, 0x10, 0x61, 0xc4, 0x61, 0x27, 0x76}};
+ web_contents()
+ ->GetController()
+ .GetLastCommittedEntry()
+ ->GetSSL()
+ .public_key_hashes.push_back(net::HashValue(google_hash_value));
+ process()->sink().ClearMessages();
+ // Navigate to the current entry, which now includes an excluded subCA.
+ Reload();
+ // Check that the expected console message was not sent to the renderer to
+ // log.
+ EXPECT_FALSE(FindSymantecConsoleMessage(process()->sink()));
+}
+
} // namespace
} // namespace content
diff --git a/chromium/content/browser/storage_partition_impl.cc b/chromium/content/browser/storage_partition_impl.cc
index 32a960d4ae6..dcd12d2fd06 100644
--- a/chromium/content/browser/storage_partition_impl.cc
+++ b/chromium/content/browser/storage_partition_impl.cc
@@ -20,17 +20,18 @@
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
#include "content/browser/browser_main_loop.h"
#include "content/browser/browsing_data/storage_partition_http_cache_data_remover.h"
+#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/fileapi/browser_file_system_helper.h"
#include "content/browser/gpu/shader_cache_factory.h"
#include "content/browser/notifications/platform_notification_context_impl.h"
#include "content/common/dom_storage/dom_storage_types.h"
+#include "content/network/network_context.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/dom_storage_context.h"
#include "content/public/browser/indexed_db_context.h"
#include "content/public/browser/local_storage_usage_info.h"
-#include "content/public/browser/network_service_instance.h"
#include "content/public/browser/session_storage_usage_info.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_features.h"
@@ -243,6 +244,38 @@ base::WeakPtr<storage::BlobStorageContext> BlobStorageContextGetter(
} // namespace
+// Class to own the NetworkContext wrapping a storage partitions
+// URLRequestContext, when the ContentBrowserClient doesn't provide a
+// NetworkContext itself.
+//
+// Createdd on the UI thread, but must be initialized and destroyed on the IO
+// thread.
+class StoragePartitionImpl::NetworkContextOwner {
+ public:
+ NetworkContextOwner() { DCHECK_CURRENTLY_ON(BrowserThread::UI); }
+
+ ~NetworkContextOwner() { DCHECK_CURRENTLY_ON(BrowserThread::IO); }
+
+ void Initialize(mojom::NetworkContextRequest network_context_request,
+ scoped_refptr<net::URLRequestContextGetter> context_getter) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ context_getter_ = std::move(context_getter);
+ network_context_ = base::MakeUnique<NetworkContext>(
+ std::move(network_context_request),
+ context_getter_->GetURLRequestContext());
+ }
+
+ private:
+ // Reference to the URLRequestContextGetter for the URLRequestContext used by
+ // NetworkContext. Depending on the embedder's implementation, this may be
+ // needed to keep the URLRequestContext alive until the NetworkContext is
+ // destroyed.
+ scoped_refptr<net::URLRequestContextGetter> context_getter_;
+ std::unique_ptr<mojom::NetworkContext> network_context_;
+
+ DISALLOW_COPY_AND_ASSIGN(NetworkContextOwner);
+};
+
// Static.
int StoragePartitionImpl::GenerateQuotaClientMask(uint32_t remove_mask) {
int quota_client_mask = 0;
@@ -394,11 +427,8 @@ StoragePartitionImpl::StoragePartitionImpl(
StoragePartitionImpl::~StoragePartitionImpl() {
browser_context_ = nullptr;
- // These message loop checks are just to avoid leaks in unittests.
- if (GetDatabaseTracker() &&
- BrowserThread::IsMessageLoopValid(BrowserThread::FILE)) {
- BrowserThread::PostTask(
- BrowserThread::FILE,
+ if (GetDatabaseTracker()) {
+ GetDatabaseTracker()->task_runner()->PostTask(
FROM_HERE,
base::Bind(&storage::DatabaseTracker::Shutdown, GetDatabaseTracker()));
}
@@ -423,6 +453,9 @@ StoragePartitionImpl::~StoragePartitionImpl() {
if (GetPaymentAppContext())
GetPaymentAppContext()->Shutdown();
+
+ BrowserThread::DeleteSoon(BrowserThread::IO, FROM_HERE,
+ std::move(network_context_owner_));
}
// static
@@ -449,7 +482,6 @@ std::unique_ptr<StoragePartitionImpl> StoragePartitionImpl::Create(
partition->quota_manager_ = new storage::QuotaManager(
in_memory, partition_path,
BrowserThread::GetTaskRunnerForThread(BrowserThread::IO).get(),
- BrowserThread::GetTaskRunnerForThread(BrowserThread::DB).get(),
context->GetSpecialStoragePolicy(),
base::Bind(&StoragePartitionImpl::GetQuotaSettings,
partition->weak_factory_.GetWeakPtr()));
@@ -461,10 +493,9 @@ std::unique_ptr<StoragePartitionImpl> StoragePartitionImpl::Create(
partition->filesystem_context_ = CreateFileSystemContext(
context, partition_path, in_memory, quota_manager_proxy.get());
- partition->database_tracker_ = new storage::DatabaseTracker(
+ partition->database_tracker_ = base::MakeRefCounted<storage::DatabaseTracker>(
partition_path, in_memory, context->GetSpecialStoragePolicy(),
- quota_manager_proxy.get(),
- BrowserThread::GetTaskRunnerForThread(BrowserThread::FILE).get());
+ quota_manager_proxy.get());
partition->dom_storage_context_ = new DOMStorageContextWrapper(
BrowserContext::GetConnectorFor(context),
@@ -513,15 +544,11 @@ std::unique_ptr<StoragePartitionImpl> StoragePartitionImpl::Create(
scoped_refptr<ChromeBlobStorageContext> blob_context =
ChromeBlobStorageContext::GetFor(context);
- if (base::FeatureList::IsEnabled(features::kNetworkService)) {
- mojom::NetworkContextParamsPtr context_params =
- mojom::NetworkContextParams::New();
- // TODO: fill this
- // context_params->cache_dir =
- // context_params->cookie_path =
- GetNetworkService()->CreateNetworkContext(
- MakeRequest(&partition->network_context_), std::move(context_params));
+ partition->network_context_ =
+ GetContentClient()->browser()->CreateNetworkContext(
+ context, in_memory, relative_partition_path);
+ if (base::FeatureList::IsEnabled(features::kNetworkService)) {
BlobURLLoaderFactory::BlobContextGetter blob_getter =
base::BindOnce(&BlobStorageContextGetter, blob_context);
partition->blob_url_loader_factory_ = BlobURLLoaderFactory::Create(
@@ -540,6 +567,9 @@ std::unique_ptr<StoragePartitionImpl> StoragePartitionImpl::Create(
blob_context, partition->filesystem_context_);
}
+ partition->appcache_service_->set_url_loader_factory_getter(
+ partition->url_loader_factory_getter_.get());
+
return partition;
}
@@ -556,6 +586,21 @@ StoragePartitionImpl::GetMediaURLRequestContext() {
return media_url_request_context_.get();
}
+mojom::NetworkContext* StoragePartitionImpl::GetNetworkContext() {
+ // Create the NetworkContext as needed, when the network service is disabled.
+ if (!network_context_.get()) {
+ DCHECK(!base::FeatureList::IsEnabled(features::kNetworkService));
+ DCHECK(!network_context_owner_);
+ network_context_owner_ = base::MakeUnique<NetworkContextOwner>();
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&NetworkContextOwner::Initialize,
+ base::Unretained(network_context_owner_.get()),
+ MakeRequest(&network_context_), url_request_context_));
+ }
+ return network_context_.get();
+}
+
storage::QuotaManager* StoragePartitionImpl::GetQuotaManager() {
return quota_manager_.get();
}
@@ -641,6 +686,12 @@ BlobRegistryWrapper* StoragePartitionImpl::GetBlobRegistry() {
void StoragePartitionImpl::OpenLocalStorage(
const url::Origin& origin,
mojo::InterfaceRequest<mojom::LevelDBWrapper> request) {
+ int process_id = bindings_.dispatch_context();
+ if (!ChildProcessSecurityPolicy::GetInstance()->CanAccessDataForOrigin(
+ process_id, origin.GetURL())) {
+ mojo::ReportBadMessage("Access denied for localStorage request");
+ return;
+ }
dom_storage_context_->OpenLocalStorage(origin, std::move(request));
}
@@ -953,8 +1004,9 @@ BrowserContext* StoragePartitionImpl::browser_context() const {
}
void StoragePartitionImpl::Bind(
+ int process_id,
mojo::InterfaceRequest<mojom::StoragePartitionService> request) {
- bindings_.AddBinding(this, std::move(request));
+ bindings_.AddBinding(this, std::move(request), process_id);
}
void StoragePartitionImpl::OverrideQuotaManagerForTesting(
diff --git a/chromium/content/browser/storage_partition_impl.h b/chromium/content/browser/storage_partition_impl.h
index a0df88a7ff3..b5902ac7f70 100644
--- a/chromium/content/browser/storage_partition_impl.h
+++ b/chromium/content/browser/storage_partition_impl.h
@@ -45,9 +45,9 @@ namespace content {
class BlobRegistryWrapper;
class BlobURLLoaderFactory;
-class CONTENT_EXPORT StoragePartitionImpl
+class CONTENT_EXPORT StoragePartitionImpl
: public StoragePartition,
- public NON_EXPORTED_BASE(mojom::StoragePartitionService) {
+ public mojom::StoragePartitionService {
public:
// It is guaranteed that storage partitions are destructed before the
// browser context starts shutting down its corresponding IO thread residents
@@ -73,6 +73,7 @@ class CONTENT_EXPORT StoragePartitionImpl
base::FilePath GetPath() override;
net::URLRequestContextGetter* GetURLRequestContext() override;
net::URLRequestContextGetter* GetMediaURLRequestContext() override;
+ mojom::NetworkContext* GetNetworkContext() override;
storage::QuotaManager* GetQuotaManager() override;
ChromeAppCacheService* GetAppCacheService() override;
storage::FileSystemContext* GetFileSystemContext() override;
@@ -127,10 +128,6 @@ class CONTENT_EXPORT StoragePartitionImpl
const url::Origin& origin,
mojo::InterfaceRequest<mojom::LevelDBWrapper> request) override;
- // Returns the NetworkContext associated with this storage partition. Only
- // used when the network service is enabled.
- mojom::NetworkContext* network_context() { return network_context_.get(); }
-
scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter() {
return url_loader_factory_getter_;
}
@@ -139,12 +136,15 @@ class CONTENT_EXPORT StoragePartitionImpl
BrowserContext* browser_context() const;
// Called by each renderer process once.
- void Bind(mojo::InterfaceRequest<mojom::StoragePartitionService> request);
+ void Bind(int process_id,
+ mojo::InterfaceRequest<mojom::StoragePartitionService> request);
struct DataDeletionHelper;
struct QuotaManagedDataDeletionHelper;
private:
+ class NetworkContextOwner;
+
friend class BackgroundSyncManagerTest;
friend class BackgroundSyncServiceImplTest;
friend class PaymentAppContentUnitTestBase;
@@ -255,9 +255,23 @@ class CONTENT_EXPORT StoragePartitionImpl
scoped_refptr<BlobURLLoaderFactory> blob_url_loader_factory_;
scoped_refptr<BlobRegistryWrapper> blob_registry_;
- mojo::BindingSet<mojom::StoragePartitionService> bindings_;
+ // BindingSet for StoragePartitionService, using the process id as the
+ // binding context type. The process id can subsequently be used during
+ // interface method calls to enforce security checks.
+ mojo::BindingSet<mojom::StoragePartitionService, int> bindings_;
+
+ // This is the NetworkContext used to
+ // make requests for the StoragePartition. When the network service is
+ // enabled, the underlying NetworkContext will be owned by the network
+ // service. When it's disabled, the underlying NetworkContext may either be
+ // provided by the embedder, or is created by the StoragePartition and owned
+ // by |network_context_owner_|.
mojom::NetworkContextPtr network_context_;
+ // When the network service is disabled, a NetworkContext is created on the IO
+ // thread that wraps access to the URLRequestContext.
+ std::unique_ptr<NetworkContextOwner> network_context_owner_;
+
// Raw pointer that should always be valid. The BrowserContext owns the
// StoragePartitionImplMap which then owns StoragePartitionImpl. When the
// BrowserContext is destroyed, |this| will be destroyed too.
diff --git a/chromium/content/browser/storage_partition_impl_browsertest.cc b/chromium/content/browser/storage_partition_impl_browsertest.cc
new file mode 100644
index 00000000000..922e9695884
--- /dev/null
+++ b/chromium/content/browser/storage_partition_impl_browsertest.cc
@@ -0,0 +1,99 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/storage_partition_impl.h"
+
+#include <string>
+
+#include "base/test/scoped_feature_list.h"
+#include "build/build_config.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/common/content_features.h"
+#include "content/public/common/network_service.mojom.h"
+#include "content/public/common/resource_response.h"
+#include "content/public/common/resource_response_info.h"
+#include "content/public/common/url_loader.mojom.h"
+#include "content/public/common/url_loader_factory.mojom.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/test_url_loader_client.h"
+#include "content/shell/browser/shell.h"
+#include "mojo/public/cpp/bindings/interface_request.h"
+#include "net/http/http_response_headers.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace content {
+
+enum class NetworkServiceState {
+ kDisabled,
+ kEnabled,
+};
+
+class StoragePartititionImplBrowsertest
+ : public ContentBrowserTest,
+ public testing::WithParamInterface<NetworkServiceState> {
+ public:
+ StoragePartititionImplBrowsertest() {
+ if (GetParam() == NetworkServiceState::kEnabled)
+ feature_list_.InitAndEnableFeature(features::kNetworkService);
+ }
+ ~StoragePartititionImplBrowsertest() override {}
+
+ private:
+ base::test::ScopedFeatureList feature_list_;
+};
+
+// Make sure that the NetworkContext returned by a StoragePartition works, both
+// with the network service enabled and with it disabled, when one is created
+// that wraps the URLRequestContext created by the BrowserContext.
+IN_PROC_BROWSER_TEST_P(StoragePartititionImplBrowsertest, NetworkContext) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ mojom::URLLoaderFactoryPtr loader_factory;
+ BrowserContext::GetDefaultStoragePartition(
+ shell()->web_contents()->GetBrowserContext())
+ ->GetNetworkContext()
+ ->CreateURLLoaderFactory(mojo::MakeRequest(&loader_factory), 0);
+
+ ResourceRequest request;
+ TestURLLoaderClient client;
+ request.url = embedded_test_server()->GetURL("/set-header?foo: bar");
+ request.method = "GET";
+ mojom::URLLoaderPtr loader;
+ loader_factory->CreateLoaderAndStart(
+ mojo::MakeRequest(&loader), 2, 1, mojom::kURLLoadOptionNone, request,
+ client.CreateInterfacePtr(),
+ net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
+
+ // Just wait until headers are received - if the right headers are received,
+ // no need to read the body.
+ client.RunUntilResponseBodyArrived();
+ ASSERT_TRUE(client.response_head().headers);
+ EXPECT_EQ(200, client.response_head().headers->response_code());
+
+ std::string foo_header_value;
+ ASSERT_TRUE(client.response_head().headers->GetNormalizedHeader(
+ "foo", &foo_header_value));
+ EXPECT_EQ("bar", foo_header_value);
+}
+
+// NetworkServiceState::kEnabled currently DCHECKs on Android, as Android isn't
+// expected to create extra processes.
+#if defined(OS_ANDROID)
+INSTANTIATE_TEST_CASE_P(
+ /* No test prefix */,
+ StoragePartititionImplBrowsertest,
+ ::testing::Values(NetworkServiceState::kDisabled));
+#else // !defined(OS_ANDROID)
+INSTANTIATE_TEST_CASE_P(
+ /* No test prefix */,
+ StoragePartititionImplBrowsertest,
+ ::testing::Values(NetworkServiceState::kDisabled,
+ NetworkServiceState::kEnabled));
+#endif
+
+} // namespace content
diff --git a/chromium/content/browser/storage_partition_impl_map.cc b/chromium/content/browser/storage_partition_impl_map.cc
index c968bf57994..067312ae6f1 100644
--- a/chromium/content/browser/storage_partition_impl_map.cc
+++ b/chromium/content/browser/storage_partition_impl_map.cc
@@ -419,11 +419,6 @@ StoragePartitionImpl* StoragePartitionImplMap::Get(
.release());
}
- protocol_handlers[kChromeDevToolsScheme] =
- linked_ptr<net::URLRequestJobFactory::ProtocolHandler>(
- CreateDevToolsProtocolHandler(
- browser_context_->GetResourceContext()));
-
URLRequestInterceptorScopedVector request_interceptors;
request_interceptors.push_back(
base::MakeUnique<DevToolsURLRequestInterceptor>(browser_context_));
diff --git a/chromium/content/browser/storage_partition_impl_unittest.cc b/chromium/content/browser/storage_partition_impl_unittest.cc
index dbfae0b26eb..16cb6af9e38 100644
--- a/chromium/content/browser/storage_partition_impl_unittest.cc
+++ b/chromium/content/browser/storage_partition_impl_unittest.cc
@@ -107,7 +107,7 @@ class AwaitCompletionHelper {
void Notify() {
if (start_) {
DCHECK(!already_quit_);
- base::MessageLoop::current()->QuitWhenIdle();
+ base::RunLoop::QuitCurrentWhenIdleDeprecated();
start_ = false;
} else {
DCHECK(!already_quit_);
@@ -632,7 +632,6 @@ class StoragePartitionImplTest : public testing::Test {
quota_manager_ = new MockQuotaManager(
browser_context_->IsOffTheRecord(), browser_context_->GetPath(),
BrowserThread::GetTaskRunnerForThread(BrowserThread::IO).get(),
- BrowserThread::GetTaskRunnerForThread(BrowserThread::DB).get(),
browser_context_->GetSpecialStoragePolicy());
}
return quota_manager_.get();
@@ -655,9 +654,7 @@ class StoragePartitionShaderClearTest : public testing::Test {
StoragePartitionShaderClearTest()
: thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
browser_context_(new TestBrowserContext()) {
- InitShaderCacheFactorySingleton(
- base::ThreadTaskRunnerHandle::Get(),
- BrowserThread::GetTaskRunnerForThread(BrowserThread::CACHE));
+ InitShaderCacheFactorySingleton(base::ThreadTaskRunnerHandle::Get());
GetShaderCacheFactorySingleton()->SetCacheInfo(
kDefaultClientId,
BrowserContext::GetDefaultStoragePartition(browser_context())
diff --git a/chromium/content/browser/streams/stream.cc b/chromium/content/browser/streams/stream.cc
index 1714876b890..7c0bc8a930a 100644
--- a/chromium/content/browser/streams/stream.cc
+++ b/chromium/content/browser/streams/stream.cc
@@ -81,7 +81,7 @@ void Stream::Abort() {
// STREAM_ABORTED.
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
- base::Bind(&Stream::OnDataAvailable, weak_ptr_factory_.GetWeakPtr()));
+ base::BindOnce(&Stream::OnDataAvailable, weak_ptr_factory_.GetWeakPtr()));
}
void Stream::AddData(scoped_refptr<net::IOBuffer> buffer, size_t size) {
@@ -128,7 +128,7 @@ void Stream::Finalize(int status) {
// Continue asynchronously.
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
- base::Bind(&Stream::OnDataAvailable, weak_ptr_factory_.GetWeakPtr()));
+ base::BindOnce(&Stream::OnDataAvailable, weak_ptr_factory_.GetWeakPtr()));
}
Stream::StreamState Stream::ReadRawData(net::IOBuffer* buf,
diff --git a/chromium/content/browser/streams/stream_context.cc b/chromium/content/browser/streams/stream_context.cc
index 22e3c0620c7..b23d083c734 100644
--- a/chromium/content/browser/streams/stream_context.cc
+++ b/chromium/content/browser/streams/stream_context.cc
@@ -32,7 +32,7 @@ StreamContext* StreamContext::GetFor(BrowserContext* context) {
if (BrowserThread::IsMessageLoopValid(BrowserThread::IO)) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&StreamContext::InitializeOnIOThread, stream));
+ base::BindOnce(&StreamContext::InitializeOnIOThread, stream));
}
}
diff --git a/chromium/content/browser/streams/stream_handle_impl.cc b/chromium/content/browser/streams/stream_handle_impl.cc
index 22d7be1db3a..03e17b5ef9a 100644
--- a/chromium/content/browser/streams/stream_handle_impl.cc
+++ b/chromium/content/browser/streams/stream_handle_impl.cc
@@ -30,8 +30,8 @@ StreamHandleImpl::StreamHandleImpl(const base::WeakPtr<Stream>& stream)
StreamHandleImpl::~StreamHandleImpl() {
stream_task_runner_->PostTaskAndReply(
- FROM_HERE, base::Bind(&Stream::CloseHandle, stream_),
- base::Bind(&RunCloseListeners, close_listeners_));
+ FROM_HERE, base::BindOnce(&Stream::CloseHandle, stream_),
+ base::BindOnce(&RunCloseListeners, close_listeners_));
}
const GURL& StreamHandleImpl::GetURL() {
diff --git a/chromium/content/browser/streams/stream_url_request_job.cc b/chromium/content/browser/streams/stream_url_request_job.cc
index b9714b1cb1e..5c895f431dc 100644
--- a/chromium/content/browser/streams/stream_url_request_job.cc
+++ b/chromium/content/browser/streams/stream_url_request_job.cc
@@ -82,8 +82,8 @@ void StreamURLRequestJob::OnDataAvailable(Stream* stream) {
void StreamURLRequestJob::Start() {
// Continue asynchronously.
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::Bind(&StreamURLRequestJob::DidStart, weak_factory_.GetWeakPtr()));
+ FROM_HERE, base::BindOnce(&StreamURLRequestJob::DidStart,
+ weak_factory_.GetWeakPtr()));
}
void StreamURLRequestJob::Kill() {
diff --git a/chromium/content/browser/theme_helper_mac.mm b/chromium/content/browser/theme_helper_mac.mm
index 3de483cc6b5..50a8828bc62 100644
--- a/chromium/content/browser/theme_helper_mac.mm
+++ b/chromium/content/browser/theme_helper_mac.mm
@@ -53,6 +53,10 @@ void FillScrollbarThemeParams(
params->preferred_scroller_style =
ThemeHelperMac::GetPreferredScrollerStyle();
params->button_placement = GetButtonPlacement();
+
+ id rubber_band_value = [defaults objectForKey:@"NSScrollViewRubberbanding"];
+ params->scroll_view_rubber_banding =
+ rubber_band_value ? [rubber_band_value boolValue] : YES;
}
void SendSystemColorsChangedMessage(content::mojom::Renderer* renderer) {
@@ -111,6 +115,13 @@ void SendSystemColorsChangedMessage(content::mojom::Renderer* renderer) {
suspensionBehavior:
NSNotificationSuspensionBehaviorDeliverImmediately];
+ [distributedCenter
+ addObserver:self
+ selector:@selector(behaviorPrefsChanged:)
+ name:@"NSScrollViewRubberbanding"
+ object:nil
+ suspensionBehavior:NSNotificationSuspensionBehaviorDeliverImmediately];
+
// In single-process mode, renderers will catch these notifications
// themselves and listening for them here may trigger the DCHECK in Observe().
if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
diff --git a/chromium/content/browser/top_document_isolation_browsertest.cc b/chromium/content/browser/top_document_isolation_browsertest.cc
index cb57f0681e8..be1fa6e4565 100644
--- a/chromium/content/browser/top_document_isolation_browsertest.cc
+++ b/chromium/content/browser/top_document_isolation_browsertest.cc
@@ -6,7 +6,6 @@
#include "base/command_line.h"
#include "base/test/scoped_feature_list.h"
-#include "build/build_config.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"
@@ -134,14 +133,7 @@ IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest, ReturnToTopSite) {
DepictFrameTree(root()));
}
-// Crashes on Win only. https://crbug.com/746063
-#if defined(OS_WIN)
-#define MAYBE_NavigateSubframeToTopSite DISABLED_NavigateSubframeToTopSite
-#else
-#define MAYBE_NavigateSubframeToTopSite NavigateSubframeToTopSite
-#endif
-IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest,
- MAYBE_NavigateSubframeToTopSite) {
+IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest, NavigateSubframeToTopSite) {
if (content::AreAllSitesIsolatedForTesting())
return; // Top Document Isolation is disabled in this mode.
@@ -203,15 +195,8 @@ IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest, NavigateToSubframeSite) {
DepictFrameTree(root()));
}
-// Crashes on Win only. https://crbug.com/746063
-#if defined(OS_WIN)
-#define MAYBE_NavigateToSubframeSiteWithPopup \
- DISABLED_NavigateToSubframeSiteWithPopup
-#else
-#define MAYBE_NavigateToSubframeSiteWithPopup NavigateToSubframeSiteWithPopup
-#endif
IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest,
- MAYBE_NavigateToSubframeSiteWithPopup) {
+ NavigateToSubframeSiteWithPopup) {
if (content::AreAllSitesIsolatedForTesting())
return; // Top Document Isolation is disabled in this mode.
@@ -298,15 +283,8 @@ IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest,
DepictFrameTree(root()));
}
-// Crashes on Win only. https://crbug.com/746063
-#if defined(OS_WIN)
-#define MAYBE_NavigateToSubframeSiteWithPopup2 \
- DISABLED_NavigateToSubframeSiteWithPopup2
-#else
-#define MAYBE_NavigateToSubframeSiteWithPopup2 NavigateToSubframeSiteWithPopup2
-#endif
IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest,
- MAYBE_NavigateToSubframeSiteWithPopup2) {
+ NavigateToSubframeSiteWithPopup2) {
if (content::AreAllSitesIsolatedForTesting())
return; // Top Document Isolation is disabled in this mode.
@@ -421,13 +399,7 @@ IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest,
DepictFrameTree(root()));
}
-// Crashes on Win only. https://crbug.com/746063
-#if defined(OS_WIN)
-#define MAYBE_FrameForSitesInHistory DISABLED_FrameForSitesInHistory
-#else
-#define MAYBE_FrameForSitesInHistory FrameForSitesInHistory
-#endif
-IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest, MAYBE_FrameForSitesInHistory) {
+IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest, FramesForSitesInHistory) {
if (content::AreAllSitesIsolatedForTesting())
return; // Top Document Isolation is disabled in this mode.
diff --git a/chromium/content/browser/tracing/background_memory_tracing_observer.cc b/chromium/content/browser/tracing/background_memory_tracing_observer.cc
index 78c246a13f7..b7a06d2b295 100644
--- a/chromium/content/browser/tracing/background_memory_tracing_observer.cc
+++ b/chromium/content/browser/tracing/background_memory_tracing_observer.cc
@@ -6,9 +6,22 @@
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/memory_dump_request_args.h"
+#include "content/browser/tracing/background_tracing_rule.h"
#include "services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h"
+using base::trace_event::MemoryDumpManager;
+
namespace content {
+namespace {
+const char kEnableHeapProfilerModeName[] = "enable_heap_profiler_mode";
+const char kBackgroundModeName[] = "background";
+
+void GlobalDumpCallback(bool success, uint64_t guid) {
+ // Disable heap profiling after capturing the first memory dump.
+ MemoryDumpManager::GetInstance()->EnableHeapProfiling(
+ base::trace_event::kHeapProfilingModeDisabled);
+}
+} // namespace
// static
BackgroundMemoryTracingObserver*
@@ -21,7 +34,37 @@ BackgroundMemoryTracingObserver::BackgroundMemoryTracingObserver() {}
BackgroundMemoryTracingObserver::~BackgroundMemoryTracingObserver() {}
void BackgroundMemoryTracingObserver::OnScenarioActivated(
- const BackgroundTracingConfigImpl* config) {}
+ const BackgroundTracingConfigImpl* config) {
+ if (!config) {
+ DCHECK(!heap_profiling_enabled_);
+ return;
+ }
+
+ for (const auto& rule : config->rules()) {
+ if (rule->category_preset() != BackgroundTracingConfigImpl::CategoryPreset::
+ BENCHMARK_MEMORY_LIGHT ||
+ !rule->args()) {
+ continue;
+ }
+ std::string mode;
+ if (rule->args()->GetString(kEnableHeapProfilerModeName, &mode) &&
+ mode == kBackgroundModeName) {
+ heap_profiling_enabled_ = true;
+ // TODO(ssid): Add ability to enable profiling on all processes,
+ // crbug.com/700245.
+ MemoryDumpManager::GetInstance()->EnableHeapProfiling(
+ base::trace_event::kHeapProfilingModeNoStack);
+ }
+ }
+}
+
+void BackgroundMemoryTracingObserver::OnScenarioAborted() {
+ if (!heap_profiling_enabled_)
+ return;
+ heap_profiling_enabled_ = false;
+ MemoryDumpManager::GetInstance()->EnableHeapProfiling(
+ base::trace_event::kHeapProfilingModeDisabled);
+}
void BackgroundMemoryTracingObserver::OnTracingEnabled(
BackgroundTracingConfigImpl::CategoryPreset preset) {
@@ -29,12 +72,14 @@ void BackgroundMemoryTracingObserver::OnTracingEnabled(
BackgroundTracingConfigImpl::CategoryPreset::BENCHMARK_MEMORY_LIGHT)
return;
+ memory_instrumentation::MemoryInstrumentation::
+ RequestGlobalDumpAndAppendToTraceCallback callback;
+ if (heap_profiling_enabled_)
+ callback = base::Bind(&GlobalDumpCallback);
memory_instrumentation::MemoryInstrumentation::GetInstance()
->RequestGlobalDumpAndAppendToTrace(
base::trace_event::MemoryDumpType::EXPLICITLY_TRIGGERED,
- base::trace_event::MemoryDumpLevelOfDetail::BACKGROUND,
- memory_instrumentation::MemoryInstrumentation::
- RequestGlobalDumpAndAppendToTraceCallback());
+ base::trace_event::MemoryDumpLevelOfDetail::BACKGROUND, callback);
}
} // namespace content
diff --git a/chromium/content/browser/tracing/background_memory_tracing_observer.h b/chromium/content/browser/tracing/background_memory_tracing_observer.h
index 6533de6c062..26e827f8d27 100644
--- a/chromium/content/browser/tracing/background_memory_tracing_observer.h
+++ b/chromium/content/browser/tracing/background_memory_tracing_observer.h
@@ -15,6 +15,7 @@ class BackgroundMemoryTracingObserver
static BackgroundMemoryTracingObserver* GetInstance();
void OnScenarioActivated(const BackgroundTracingConfigImpl* config) override;
+ void OnScenarioAborted() override;
void OnTracingEnabled(
BackgroundTracingConfigImpl::CategoryPreset preset) override;
@@ -22,6 +23,8 @@ class BackgroundMemoryTracingObserver
BackgroundMemoryTracingObserver();
~BackgroundMemoryTracingObserver() override;
+ bool heap_profiling_enabled_ = false;
+
DISALLOW_COPY_AND_ASSIGN(BackgroundMemoryTracingObserver);
};
diff --git a/chromium/content/browser/tracing/background_tracing_manager_browsertest.cc b/chromium/content/browser/tracing/background_tracing_manager_browsertest.cc
index a9919acf702..cc408bf6a1a 100644
--- a/chromium/content/browser/tracing/background_tracing_manager_browsertest.cc
+++ b/chromium/content/browser/tracing/background_tracing_manager_browsertest.cc
@@ -9,6 +9,7 @@
#include "base/command_line.h"
#include "base/macros.h"
#include "base/metrics/histogram_macros.h"
+#include "base/run_loop.h"
#include "base/strings/pattern.h"
#include "base/trace_event/trace_event.h"
#include "content/browser/tracing/background_tracing_manager_impl.h"
@@ -30,17 +31,18 @@ class TestBackgroundTracingObserver
~TestBackgroundTracingObserver() override;
void OnScenarioActivated(const BackgroundTracingConfigImpl* config) override;
+ void OnScenarioAborted() override;
void OnTracingEnabled(
BackgroundTracingConfigImpl::CategoryPreset preset) override;
private:
- bool was_scenario_activated_;
+ bool is_scenario_active_;
base::Closure tracing_enabled_callback_;
};
TestBackgroundTracingObserver::TestBackgroundTracingObserver(
base::Closure tracing_enabled_callback)
- : was_scenario_activated_(false),
+ : is_scenario_active_(false),
tracing_enabled_callback_(tracing_enabled_callback) {
BackgroundTracingManagerImpl::GetInstance()->AddEnabledStateObserver(this);
}
@@ -49,12 +51,16 @@ TestBackgroundTracingObserver::~TestBackgroundTracingObserver() {
static_cast<BackgroundTracingManagerImpl*>(
BackgroundTracingManager::GetInstance())
->RemoveEnabledStateObserver(this);
- EXPECT_TRUE(was_scenario_activated_);
+ EXPECT_TRUE(is_scenario_active_);
}
void TestBackgroundTracingObserver::OnScenarioActivated(
const BackgroundTracingConfigImpl* config) {
- was_scenario_activated_ = true;
+ is_scenario_active_ = true;
+}
+
+void TestBackgroundTracingObserver::OnScenarioAborted() {
+ is_scenario_active_ = false;
}
void TestBackgroundTracingObserver::OnTracingEnabled(
diff --git a/chromium/content/browser/tracing/background_tracing_manager_impl.cc b/chromium/content/browser/tracing/background_tracing_manager_impl.cc
index 3c1bc45443a..a7305d71f41 100644
--- a/chromium/content/browser/tracing/background_tracing_manager_impl.cc
+++ b/chromium/content/browser/tracing/background_tracing_manager_impl.cc
@@ -140,8 +140,8 @@ bool BackgroundTracingManagerImpl::SetActiveScenario(
} else {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
- base::Bind(&BackgroundTracingManagerImpl::ValidateStartupScenario,
- base::Unretained(this)));
+ base::BindOnce(&BackgroundTracingManagerImpl::ValidateStartupScenario,
+ base::Unretained(this)));
}
std::unique_ptr<const content::BackgroundTracingConfigImpl> config_impl(
@@ -310,8 +310,8 @@ void BackgroundTracingManagerImpl::OnHistogramTrigger(
if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) {
content::BrowserThread::PostTask(
content::BrowserThread::UI, FROM_HERE,
- base::Bind(&BackgroundTracingManagerImpl::OnHistogramTrigger,
- base::Unretained(this), histogram_name));
+ base::BindOnce(&BackgroundTracingManagerImpl::OnHistogramTrigger,
+ base::Unretained(this), histogram_name));
return;
}
@@ -327,8 +327,8 @@ void BackgroundTracingManagerImpl::TriggerNamedEvent(
if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) {
content::BrowserThread::PostTask(
content::BrowserThread::UI, FROM_HERE,
- base::Bind(&BackgroundTracingManagerImpl::TriggerNamedEvent,
- base::Unretained(this), handle, callback));
+ base::BindOnce(&BackgroundTracingManagerImpl::TriggerNamedEvent,
+ base::Unretained(this), handle, callback));
return;
}
@@ -502,8 +502,8 @@ void BackgroundTracingManagerImpl::OnFinalizeComplete() {
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&BackgroundTracingManagerImpl::OnFinalizeComplete,
- base::Unretained(this)));
+ base::BindOnce(&BackgroundTracingManagerImpl::OnFinalizeComplete,
+ base::Unretained(this)));
return;
}
@@ -580,6 +580,9 @@ void BackgroundTracingManagerImpl::AbortScenario() {
tracing_timer_.reset();
content::TracingController::GetInstance()->StopTracing(nullptr);
+
+ for (auto* observer : background_tracing_observers_)
+ observer->OnScenarioAborted();
}
std::string
diff --git a/chromium/content/browser/tracing/background_tracing_manager_impl.h b/chromium/content/browser/tracing/background_tracing_manager_impl.h
index d1625be5bab..43a47049040 100644
--- a/chromium/content/browser/tracing/background_tracing_manager_impl.h
+++ b/chromium/content/browser/tracing/background_tracing_manager_impl.h
@@ -36,6 +36,9 @@ class BackgroundTracingManagerImpl : public BackgroundTracingManager {
virtual void OnScenarioActivated(
const BackgroundTracingConfigImpl* config) = 0;
+ // In case the scenario was aborted before or after tracing was enabled.
+ virtual void OnScenarioAborted() = 0;
+
// Called after tracing is enabled on all processes because the rule was
// triggered.
virtual void OnTracingEnabled(
diff --git a/chromium/content/browser/tracing/background_tracing_rule.cc b/chromium/content/browser/tracing/background_tracing_rule.cc
index 3d339f0c944..624efaa878a 100644
--- a/chromium/content/browser/tracing/background_tracing_rule.cc
+++ b/chromium/content/browser/tracing/background_tracing_rule.cc
@@ -25,6 +25,7 @@ const char kConfigRuleTriggerDelay[] = "trigger_delay";
const char kConfigRuleTriggerChance[] = "trigger_chance";
const char kConfigRuleStopTracingOnRepeatedReactive[] =
"stop_tracing_on_repeated_reactive";
+const char kConfigRuleArgsKey[] = "args";
const char kConfigRuleHistogramNameKey[] = "histogram_name";
const char kConfigRuleHistogramValueOldKey[] = "histogram_value";
@@ -181,8 +182,13 @@ class HistogramRule
if (histogram_lower_value >= histogram_upper_value)
return nullptr;
- return std::unique_ptr<BackgroundTracingRule>(new HistogramRule(
+ std::unique_ptr<BackgroundTracingRule> rule(new HistogramRule(
histogram_name, histogram_lower_value, histogram_upper_value, repeat));
+
+ const base::DictionaryValue* args_dict = nullptr;
+ if (dict->GetDictionary(kConfigRuleArgsKey, &args_dict))
+ rule->SetArgs(*args_dict);
+ return rule;
}
~HistogramRule() override {
@@ -219,7 +225,7 @@ class HistogramRule
content::BrowserThread::PostTask(
content::BrowserThread::UI, FROM_HERE,
- base::Bind(
+ base::BindOnce(
&BackgroundTracingManagerImpl::OnRuleTriggered,
base::Unretained(BackgroundTracingManagerImpl::GetInstance()), this,
BackgroundTracingManager::StartedFinalizingCallback()));
@@ -228,7 +234,7 @@ class HistogramRule
void AbortTracing() {
content::BrowserThread::PostTask(
content::BrowserThread::UI, FROM_HERE,
- base::Bind(
+ base::BindOnce(
&BackgroundTracingManagerImpl::AbortScenario,
base::Unretained(BackgroundTracingManagerImpl::GetInstance())));
}
diff --git a/chromium/content/browser/tracing/background_tracing_rule.h b/chromium/content/browser/tracing/background_tracing_rule.h
index 513480c0e42..9d0a91eb01f 100644
--- a/chromium/content/browser/tracing/background_tracing_rule.h
+++ b/chromium/content/browser/tracing/background_tracing_rule.h
@@ -5,7 +5,11 @@
#ifndef CONTENT_BROWSER_TRACING_BACKGROUND_TRACING_RULE_H_
#define CONTENT_BROWSER_TRACING_BACKGROUND_TRACING_RULE_H_
+#include <memory>
+
#include "base/macros.h"
+#include "base/memory/ptr_util.h"
+#include "base/values.h"
#include "content/browser/tracing/background_tracing_config_impl.h"
#include "content/common/content_export.h"
@@ -49,6 +53,11 @@ class CONTENT_EXPORT BackgroundTracingRule {
static std::unique_ptr<BackgroundTracingRule> CreateRuleFromDict(
const base::DictionaryValue* dict);
+ void SetArgs(const base::DictionaryValue& args) {
+ args_ = args.CreateDeepCopy();
+ }
+ const base::DictionaryValue* args() const { return args_.get(); }
+
private:
DISALLOW_COPY_AND_ASSIGN(BackgroundTracingRule);
@@ -56,6 +65,7 @@ class CONTENT_EXPORT BackgroundTracingRule {
int trigger_delay_;
bool stop_tracing_on_repeated_reactive_;
BackgroundTracingConfigImpl::CategoryPreset category_preset_;
+ std::unique_ptr<base::DictionaryValue> args_;
};
} // namespace content
diff --git a/chromium/content/browser/tracing/etw_tracing_agent_win.cc b/chromium/content/browser/tracing/etw_tracing_agent_win.cc
index b3b56bd9454..8ee34811dbf 100644
--- a/chromium/content/browser/tracing/etw_tracing_agent_win.cc
+++ b/chromium/content/browser/tracing/etw_tracing_agent_win.cc
@@ -31,10 +31,11 @@ const int kEtwBufferSizeInKBytes = 16;
const int kEtwBufferFlushTimeoutInSeconds = 1;
std::string GuidToString(const GUID& guid) {
- return base::StringPrintf("%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
- guid.Data1, guid.Data2, guid.Data3,
- guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3],
- guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
+ return base::StringPrintf("%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
+ guid.Data1, guid.Data2, guid.Data3, guid.Data4[0],
+ guid.Data4[1], guid.Data4[2], guid.Data4[3],
+ guid.Data4[4], guid.Data4[5], guid.Data4[6],
+ guid.Data4[7]);
}
} // namespace
@@ -171,9 +172,9 @@ void EtwTracingAgent::AddSyncEventToBuffer() {
auto value = base::MakeUnique<base::DictionaryValue>();
value->SetString("guid", "ClockSync");
value->SetString("walltime",
- base::StringPrintf("%08X%08X", walltime_in_us.HighPart,
+ base::StringPrintf("%08lX%08lX", walltime_in_us.HighPart,
walltime_in_us.LowPart));
- value->SetString("tick", base::StringPrintf("%08X%08X", now_in_us.HighPart,
+ value->SetString("tick", base::StringPrintf("%08lX%08lX", now_in_us.HighPart,
now_in_us.LowPart));
// Append it to the events buffer.
@@ -187,7 +188,7 @@ void EtwTracingAgent::AppendEventToBuffer(EVENT_TRACE* event) {
LARGE_INTEGER ts_us;
ts_us.QuadPart = event->Header.TimeStamp.QuadPart / 10;
value->SetString(
- "ts", base::StringPrintf("%08X%08X", ts_us.HighPart, ts_us.LowPart));
+ "ts", base::StringPrintf("%08lX%08lX", ts_us.HighPart, ts_us.LowPart));
value->SetString("guid", GuidToString(event->Header.Guid));
diff --git a/chromium/content/browser/tracing/memory_tracing_browsertest.cc b/chromium/content/browser/tracing/memory_tracing_browsertest.cc
index 3733caa2c98..edf052880ed 100644
--- a/chromium/content/browser/tracing/memory_tracing_browsertest.cc
+++ b/chromium/content/browser/tracing/memory_tracing_browsertest.cc
@@ -15,6 +15,7 @@
#include "base/trace_event/memory_dump_request_args.h"
#include "base/trace_event/trace_config_memory_test_util.h"
#include "base/trace_event/trace_log.h"
+#include "build/build_config.h"
#include "content/public/browser/tracing_controller.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test_utils.h"
@@ -55,9 +56,10 @@ class MemoryTracingTest : public ContentBrowserTest {
// the run loop (which is the IN_PROC_BROWSER_TEST_F main thread).
if (!task_runner->RunsTasksInCurrentSequence()) {
task_runner->PostTask(
- FROM_HERE, base::Bind(&MemoryTracingTest::OnGlobalMemoryDumpDone,
- base::Unretained(this), task_runner, closure,
- request_index, success, dump_guid));
+ FROM_HERE,
+ base::BindOnce(&MemoryTracingTest::OnGlobalMemoryDumpDone,
+ base::Unretained(this), task_runner, closure,
+ request_index, success, dump_guid));
return;
}
if (success)
@@ -73,9 +75,10 @@ class MemoryTracingTest : public ContentBrowserTest {
const MemoryDumpLevelOfDetail& level_of_detail,
const base::Closure& closure) {
uint32_t request_index = next_request_index_++;
- base::trace_event::GlobalMemoryDumpCallback callback = base::Bind(
- &MemoryTracingTest::OnGlobalMemoryDumpDone, base::Unretained(this),
- base::ThreadTaskRunnerHandle::Get(), closure, request_index);
+ memory_instrumentation::MemoryInstrumentation::
+ RequestGlobalDumpAndAppendToTraceCallback callback = base::Bind(
+ &MemoryTracingTest::OnGlobalMemoryDumpDone, base::Unretained(this),
+ base::ThreadTaskRunnerHandle::Get(), closure, request_index);
if (from_renderer_thread) {
PostTaskToInProcessRendererAndWait(base::Bind(
&memory_instrumentation::MemoryInstrumentation::
@@ -236,7 +239,8 @@ IN_PROC_BROWSER_TEST_F(SingleProcessMemoryTracingTest, ManyInterleavedDumps) {
// dump requests are queued and carried out after it's finished. Also checks
// that periodic dump requests fail in case there is already a request in the
// queue with the same level of detail.
-IN_PROC_BROWSER_TEST_F(SingleProcessMemoryTracingTest, QueuedDumps) {
+// Flaky failures on all platforms. https://crbug.com/752613
+IN_PROC_BROWSER_TEST_F(SingleProcessMemoryTracingTest, DISABLED_QueuedDumps) {
Navigate(shell());
EnableMemoryTracing();
@@ -302,8 +306,7 @@ IN_PROC_BROWSER_TEST_F(SingleProcessMemoryTracingTest, QueuedDumps) {
#endif // !defined(GOOGLE_CHROME_BUILD)
// Non-deterministic races under TSan. crbug.com/529678
-// Flaky on Linux. crbug.com/709524
-#if defined(THREAD_SANITIZER) || defined(OS_LINUX)
+#if defined(THREAD_SANITIZER)
#define MAYBE_BrowserInitiatedDump DISABLED_BrowserInitiatedDump
#else
#define MAYBE_BrowserInitiatedDump BrowserInitiatedDump
@@ -314,7 +317,14 @@ IN_PROC_BROWSER_TEST_F(MemoryTracingTest, MAYBE_BrowserInitiatedDump) {
Navigate(shell());
EXPECT_CALL(*mock_dump_provider_, OnMemoryDump(_,_)).WillOnce(Return(true));
+#if defined(OS_LINUX)
+ // TODO(ssid): Test for dump success once the on start tracing done callback
+ // is fixed to be called after enable tracing is acked by all processes,
+ // crbug.com/709524. The test still tests if dumping does not crash.
+ EXPECT_CALL(*this, OnMemoryDumpDone(_, _));
+#else
EXPECT_CALL(*this, OnMemoryDumpDone(_, true /* success */));
+#endif
EnableMemoryTracing();
RequestGlobalDumpAndWait(false /* from_renderer_thread */,
diff --git a/chromium/content/browser/tracing/power_tracing_agent.cc b/chromium/content/browser/tracing/power_tracing_agent.cc
index 6276c099cec..3bd378c0a03 100644
--- a/chromium/content/browser/tracing/power_tracing_agent.cc
+++ b/chromium/content/browser/tracing/power_tracing_agent.cc
@@ -40,9 +40,10 @@ void PowerTracingAgent::StartAgentTracing(
const StartAgentTracingCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
- base::Bind(&PowerTracingAgent::FindBattOrOnFileThread,
- base::Unretained(this), callback));
+ BrowserThread::PostTask(
+ BrowserThread::FILE, FROM_HERE,
+ base::BindOnce(&PowerTracingAgent::FindBattOrOnFileThread,
+ base::Unretained(this), callback));
}
void PowerTracingAgent::FindBattOrOnFileThread(
@@ -53,14 +54,14 @@ void PowerTracingAgent::FindBattOrOnFileThread(
if (path.empty()) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(callback, GetTracingAgentName(), false /* success */));
+ base::BindOnce(callback, GetTracingAgentName(), false /* success */));
return;
}
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&PowerTracingAgent::StartAgentTracingOnIOThread,
- base::Unretained(this), path, callback));
+ base::BindOnce(&PowerTracingAgent::StartAgentTracingOnIOThread,
+ base::Unretained(this), path, callback));
}
void PowerTracingAgent::StartAgentTracingOnIOThread(
@@ -84,7 +85,7 @@ void PowerTracingAgent::OnStartTracingComplete(battor::BattOrError error) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(start_tracing_callback_, GetTracingAgentName(), success));
+ base::BindOnce(start_tracing_callback_, GetTracingAgentName(), success));
start_tracing_callback_.Reset();
}
@@ -94,8 +95,8 @@ void PowerTracingAgent::StopAgentTracing(
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&PowerTracingAgent::StopAgentTracingOnIOThread,
- base::Unretained(this), callback));
+ base::BindOnce(&PowerTracingAgent::StopAgentTracingOnIOThread,
+ base::Unretained(this), callback));
}
void PowerTracingAgent::StopAgentTracingOnIOThread(
@@ -105,8 +106,8 @@ void PowerTracingAgent::StopAgentTracingOnIOThread(
if (!battor_agent_) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(callback, GetTracingAgentName(), GetTraceEventLabel(),
- nullptr /* events_str_ptr */));
+ base::BindOnce(callback, GetTracingAgentName(), GetTraceEventLabel(),
+ nullptr /* events_str_ptr */));
return;
}
@@ -124,8 +125,8 @@ void PowerTracingAgent::OnStopTracingComplete(const std::string& trace,
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(stop_tracing_callback_, GetTracingAgentName(),
- GetTraceEventLabel(), result));
+ base::BindOnce(stop_tracing_callback_, GetTracingAgentName(),
+ GetTraceEventLabel(), result));
stop_tracing_callback_.Reset();
battor_agent_.reset();
}
@@ -138,8 +139,8 @@ void PowerTracingAgent::RecordClockSyncMarker(
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&PowerTracingAgent::RecordClockSyncMarkerOnIOThread,
- base::Unretained(this), sync_id, callback));
+ base::BindOnce(&PowerTracingAgent::RecordClockSyncMarkerOnIOThread,
+ base::Unretained(this), sync_id, callback));
}
void PowerTracingAgent::RecordClockSyncMarkerOnIOThread(
@@ -164,12 +165,10 @@ void PowerTracingAgent::OnRecordClockSyncMarkerComplete(
if (error != battor::BATTOR_ERROR_NONE)
issue_start_ts = issue_end_ts = base::TimeTicks();
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(record_clock_sync_marker_callback_,
- record_clock_sync_marker_sync_id_,
- issue_start_ts,
- issue_end_ts));
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::BindOnce(record_clock_sync_marker_callback_,
+ record_clock_sync_marker_sync_id_,
+ issue_start_ts, issue_end_ts));
record_clock_sync_marker_callback_.Reset();
record_clock_sync_marker_sync_id_ = std::string();
diff --git a/chromium/content/browser/tracing/trace_message_filter.cc b/chromium/content/browser/tracing/trace_message_filter.cc
index dcf2ac3883e..e43830c0914 100644
--- a/chromium/content/browser/tracing/trace_message_filter.cc
+++ b/chromium/content/browser/tracing/trace_message_filter.cc
@@ -34,9 +34,9 @@ void TraceMessageFilter::OnChannelClosing() {
if (is_awaiting_buffer_percent_full_ack_)
OnTraceLogStatusReply(base::trace_event::TraceLogStatus());
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&TraceMessageFilter::Unregister, base::RetainedRef(this)));
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&TraceMessageFilter::Unregister,
+ base::RetainedRef(this)));
}
}
@@ -92,7 +92,7 @@ void TraceMessageFilter::OnChildSupportsTracing() {
has_child_ = true;
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&TraceMessageFilter::Register, base::RetainedRef(this)));
+ base::BindOnce(&TraceMessageFilter::Register, base::RetainedRef(this)));
}
void TraceMessageFilter::OnEndTracingAck(
diff --git a/chromium/content/browser/tracing/tracing_controller_browsertest.cc b/chromium/content/browser/tracing/tracing_controller_browsertest.cc
index be5cfe00f8e..7087fef34c7 100644
--- a/chromium/content/browser/tracing/tracing_controller_browsertest.cc
+++ b/chromium/content/browser/tracing/tracing_controller_browsertest.cc
@@ -78,8 +78,8 @@ class TracingControllerTestEndpoint : public TraceDataEndpoint {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(done_callback_, base::Passed(std::move(metadata)),
- base::RetainedRef(chunk_ptr)));
+ base::BindOnce(done_callback_, base::Passed(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 e3b447c9813..59b81fe7b42 100644
--- a/chromium/content/browser/tracing/tracing_controller_impl.cc
+++ b/chromium/content/browser/tracing/tracing_controller_impl.cc
@@ -24,7 +24,6 @@
#include "base/trace_event/trace_event.h"
#include "base/values.h"
#include "build/build_config.h"
-#include "components/tracing/common/process_metrics_memory_dump_provider.h"
#include "content/browser/tracing/file_tracing_provider_impl.h"
#include "content/browser/tracing/trace_message_filter.h"
#include "content/browser/tracing/tracing_ui.h"
@@ -296,8 +295,8 @@ bool TracingControllerImpl::StopTracing(
if (start_tracing_timer_.IsRunning()) {
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE,
- base::Bind(base::IgnoreResult(&TracingControllerImpl::StopTracing),
- base::Unretained(this), trace_data_sink),
+ base::BindOnce(base::IgnoreResult(&TracingControllerImpl::StopTracing),
+ base::Unretained(this), trace_data_sink),
base::TimeDelta::FromMilliseconds(kStopTracingRetryTimeMilliseconds));
return true;
}
@@ -339,10 +338,10 @@ void TracingControllerImpl::StopTracingAfterClockSync() {
// interfering with the process.
base::Closure on_stop_tracing_done_callback = base::Bind(
&TracingControllerImpl::OnStopTracingDone, base::Unretained(this));
- BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
- base::Bind(&TracingControllerImpl::SetDisabledOnFileThread,
- base::Unretained(this),
- on_stop_tracing_done_callback));
+ BrowserThread::PostTask(
+ BrowserThread::FILE, FROM_HERE,
+ base::BindOnce(&TracingControllerImpl::SetDisabledOnFileThread,
+ base::Unretained(this), on_stop_tracing_done_callback));
}
void TracingControllerImpl::OnStopTracingDone() {
@@ -391,8 +390,8 @@ bool TracingControllerImpl::GetTraceBufferUsage(
// child processes.
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&TracingControllerImpl::OnTraceLogStatusReply,
- base::Unretained(this), nullptr, status));
+ base::BindOnce(&TracingControllerImpl::OnTraceLogStatusReply,
+ base::Unretained(this), nullptr, status));
// Notify all child processes.
for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
@@ -410,13 +409,6 @@ void TracingControllerImpl::AddTraceMessageFilter(
TraceMessageFilter* trace_message_filter) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
-#if defined(OS_LINUX)
- // On Linux the browser process dumps process metrics for child process due to
- // sandbox.
- tracing::ProcessMetricsMemoryDumpProvider::RegisterForProcess(
- trace_message_filter->peer_pid());
-#endif
-
trace_message_filters_.insert(trace_message_filter);
if (can_stop_tracing()) {
trace_message_filter->SendBeginTracing(
@@ -428,11 +420,6 @@ void TracingControllerImpl::RemoveTraceMessageFilter(
TraceMessageFilter* trace_message_filter) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-#if defined(OS_LINUX)
- tracing::ProcessMetricsMemoryDumpProvider::UnregisterForProcess(
- trace_message_filter->peer_pid());
-#endif
-
// If a filter is removed while a response from that filter is pending then
// simulate the response. Otherwise the response count will be wrong and the
// completion callback will never be executed.
@@ -442,10 +429,10 @@ void TracingControllerImpl::RemoveTraceMessageFilter(
if (it != pending_stop_tracing_filters_.end()) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&TracingControllerImpl::OnStopTracingAcked,
- base::Unretained(this),
- base::RetainedRef(trace_message_filter),
- std::vector<std::string>()));
+ base::BindOnce(&TracingControllerImpl::OnStopTracingAcked,
+ base::Unretained(this),
+ base::RetainedRef(trace_message_filter),
+ std::vector<std::string>()));
}
}
if (pending_trace_log_status_ack_count_ > 0) {
@@ -454,10 +441,10 @@ void TracingControllerImpl::RemoveTraceMessageFilter(
if (it != pending_trace_log_status_filters_.end()) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&TracingControllerImpl::OnTraceLogStatusReply,
- base::Unretained(this),
- base::RetainedRef(trace_message_filter),
- base::trace_event::TraceLogStatus()));
+ base::BindOnce(&TracingControllerImpl::OnTraceLogStatusReply,
+ base::Unretained(this),
+ base::RetainedRef(trace_message_filter),
+ base::trace_event::TraceLogStatus()));
}
}
trace_message_filters_.erase(trace_message_filter);
@@ -521,7 +508,7 @@ void TracingControllerImpl::OnStopTracingAcked(
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(
+ base::BindOnce(
&TracingControllerImpl::OnStopTracingAcked, base::Unretained(this),
base::RetainedRef(trace_message_filter), known_category_groups));
return;
@@ -604,9 +591,10 @@ void TracingControllerImpl::OnTraceDataCollected(
// OnTraceDataCollected may be called from any browser thread, either by the
// local event trace system or from child processes via TraceMessageFilter.
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(&TracingControllerImpl::OnTraceDataCollected,
- base::Unretained(this), events_str_ptr));
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&TracingControllerImpl::OnTraceDataCollected,
+ base::Unretained(this), events_str_ptr));
return;
}
@@ -635,9 +623,9 @@ void TracingControllerImpl::OnTraceLogStatusReply(
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&TracingControllerImpl::OnTraceLogStatusReply,
- base::Unretained(this),
- base::RetainedRef(trace_message_filter), status));
+ base::BindOnce(&TracingControllerImpl::OnTraceLogStatusReply,
+ base::Unretained(this),
+ base::RetainedRef(trace_message_filter), status));
return;
}
@@ -692,9 +680,9 @@ void TracingControllerImpl::StartAgentTracing(
base::Bind(callback, kChromeTracingAgentName, true);
if (!BrowserThread::PostTask(
BrowserThread::FILE, FROM_HERE,
- base::Bind(&TracingControllerImpl::SetEnabledOnFileThread,
- base::Unretained(this), trace_config,
- on_agent_started))) {
+ base::BindOnce(&TracingControllerImpl::SetEnabledOnFileThread,
+ base::Unretained(this), trace_config,
+ on_agent_started))) {
// BrowserThread::PostTask fails if the threads haven't been created yet,
// so it should be safe to just use TraceLog::SetEnabled directly.
TraceLog::GetInstance()->SetEnabled(trace_config, enabled_tracing_modes_);
@@ -806,7 +794,7 @@ void TracingControllerImpl::AddFilteredMetadata(
it.Advance()) {
if (filter.Run(it.key()))
filtered_metadata->Set(it.key(),
- base::MakeUnique<base::Value>(it.value()));
+ base::MakeUnique<base::Value>(it.value().Clone()));
else
filtered_metadata->SetString(it.key(), "__stripped__");
}
diff --git a/chromium/content/browser/tracing/tracing_controller_impl_data_sinks.cc b/chromium/content/browser/tracing/tracing_controller_impl_data_sinks.cc
index 73cb2388671..fa6b7d7b13d 100644
--- a/chromium/content/browser/tracing/tracing_controller_impl_data_sinks.cc
+++ b/chromium/content/browser/tracing/tracing_controller_impl_data_sinks.cc
@@ -39,8 +39,8 @@ class StringTraceDataEndpoint : public TraceDataEndpoint {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(completion_callback_, base::Passed(std::move(metadata)),
- base::RetainedRef(str)));
+ base::BindOnce(completion_callback_, base::Passed(std::move(metadata)),
+ base::RetainedRef(str)));
}
void ReceiveTraceChunk(std::unique_ptr<std::string> chunk) override {
@@ -67,15 +67,15 @@ class FileTraceDataEndpoint : public TraceDataEndpoint {
void ReceiveTraceChunk(std::unique_ptr<std::string> chunk) override {
BrowserThread::PostTask(
BrowserThread::FILE, FROM_HERE,
- base::Bind(&FileTraceDataEndpoint::ReceiveTraceChunkOnFileThread, this,
- base::Passed(std::move(chunk))));
+ base::BindOnce(&FileTraceDataEndpoint::ReceiveTraceChunkOnFileThread,
+ this, base::Passed(std::move(chunk))));
}
void ReceiveTraceFinalContents(
std::unique_ptr<const base::DictionaryValue>) override {
BrowserThread::PostTask(
BrowserThread::FILE, FROM_HERE,
- base::Bind(&FileTraceDataEndpoint::CloseOnFileThread, this));
+ base::BindOnce(&FileTraceDataEndpoint::CloseOnFileThread, this));
}
private:
@@ -105,7 +105,7 @@ class FileTraceDataEndpoint : public TraceDataEndpoint {
}
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&FileTraceDataEndpoint::FinalizeOnUIThread, this));
+ base::BindOnce(&FileTraceDataEndpoint::FinalizeOnUIThread, this));
}
void FinalizeOnUIThread() { completion_callback_.Run(); }
@@ -194,16 +194,16 @@ class CompressedTraceDataEndpoint : public TraceDataEndpoint {
void ReceiveTraceChunk(std::unique_ptr<std::string> chunk) override {
BrowserThread::PostTask(
BrowserThread::FILE, FROM_HERE,
- base::Bind(&CompressedTraceDataEndpoint::CompressOnFileThread, this,
- base::Passed(std::move(chunk))));
+ base::BindOnce(&CompressedTraceDataEndpoint::CompressOnFileThread, this,
+ base::Passed(std::move(chunk))));
}
void ReceiveTraceFinalContents(
std::unique_ptr<const base::DictionaryValue> metadata) override {
BrowserThread::PostTask(
BrowserThread::FILE, FROM_HERE,
- base::Bind(&CompressedTraceDataEndpoint::CloseOnFileThread, this,
- base::Passed(std::move(metadata))));
+ base::BindOnce(&CompressedTraceDataEndpoint::CloseOnFileThread, this,
+ base::Passed(std::move(metadata))));
}
private:
diff --git a/chromium/content/browser/url_loader_factory_getter.cc b/chromium/content/browser/url_loader_factory_getter.cc
index 67cd6bac5a0..af030c20945 100644
--- a/chromium/content/browser/url_loader_factory_getter.cc
+++ b/chromium/content/browser/url_loader_factory_getter.cc
@@ -14,7 +14,7 @@ URLLoaderFactoryGetter::URLLoaderFactoryGetter() {}
void URLLoaderFactoryGetter::Initialize(StoragePartitionImpl* partition) {
mojom::URLLoaderFactoryPtr network_factory;
- partition->network_context()->CreateURLLoaderFactory(
+ partition->GetNetworkContext()->CreateURLLoaderFactory(
MakeRequest(&network_factory), 0);
mojom::URLLoaderFactoryPtr blob_factory;
@@ -40,13 +40,19 @@ mojom::URLLoaderFactoryPtr* URLLoaderFactoryGetter::GetBlobFactory() {
void URLLoaderFactoryGetter::SetNetworkFactoryForTesting(
mojom::URLLoaderFactoryPtr test_factory) {
- // Since the URLLoaderFactory pointers are bound on the IO thread, and this
- // method is called on the UI thread, we are not able to unbind and return the
- // old value. As such this class keeps two separate pointers, one for test.
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&URLLoaderFactoryGetter::SetTestNetworkFactoryOnIOThread,
- this, test_factory.PassInterface()));
+ if (content::BrowserThread::CurrentlyOn(BrowserThread::IO)) {
+ URLLoaderFactoryGetter::SetTestNetworkFactoryOnIOThread(
+ test_factory.PassInterface());
+ } else {
+ // Since the URLLoaderFactory pointers are bound on the IO thread, and this
+ // method is called on the UI thread, we are not able to unbind and return
+ // the old value. As such this class keeps two separate pointers, one for
+ // test.
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&URLLoaderFactoryGetter::SetTestNetworkFactoryOnIOThread,
+ this, test_factory.PassInterface()));
+ }
}
URLLoaderFactoryGetter::~URLLoaderFactoryGetter() {}
diff --git a/chromium/content/browser/url_loader_factory_getter.h b/chromium/content/browser/url_loader_factory_getter.h
index 128645908ed..cee9f47b060 100644
--- a/chromium/content/browser/url_loader_factory_getter.h
+++ b/chromium/content/browser/url_loader_factory_getter.h
@@ -22,7 +22,7 @@ class URLLoaderFactoryGetter
: public base::RefCountedThreadSafe<URLLoaderFactoryGetter,
BrowserThread::DeleteOnIOThread> {
public:
- URLLoaderFactoryGetter();
+ CONTENT_EXPORT URLLoaderFactoryGetter();
// Initializes this object on the UI thread. The |partition| is used to
// initialize the URLLoaderFactories for the network service and AppCache.
diff --git a/chromium/content/browser/utility_process_host_impl.cc b/chromium/content/browser/utility_process_host_impl.cc
index 7a9069e60e1..fdd9360e9e5 100644
--- a/chromium/content/browser/utility_process_host_impl.cc
+++ b/chromium/content/browser/utility_process_host_impl.cc
@@ -51,19 +51,19 @@ class UtilitySandboxedProcessLauncherDelegate
public:
UtilitySandboxedProcessLauncherDelegate(const base::FilePath& exposed_dir,
bool launch_elevated,
- bool no_sandbox,
+ SandboxType sandbox_type,
const base::EnvironmentMap& env)
: exposed_dir_(exposed_dir),
#if defined(OS_WIN)
- launch_elevated_(launch_elevated)
+ launch_elevated_(launch_elevated),
#elif defined(OS_POSIX)
- env_(env)
-#if !defined(OS_MACOSX) && !defined(OS_ANDROID)
- ,
- no_sandbox_(no_sandbox)
-#endif // !defined(OS_MACOSX) && !defined(OS_ANDROID)
+ env_(env),
#endif // OS_WIN
- {}
+ sandbox_type_(sandbox_type) {
+ DCHECK(sandbox_type_ == SANDBOX_TYPE_NO_SANDBOX ||
+ sandbox_type_ == SANDBOX_TYPE_UTILITY ||
+ sandbox_type_ == SANDBOX_TYPE_NETWORK);
+ }
~UtilitySandboxedProcessLauncherDelegate() override {}
@@ -90,19 +90,17 @@ class UtilitySandboxedProcessLauncherDelegate
#elif defined(OS_POSIX)
-#if !defined(OS_MACOSX) && !defined(OS_ANDROID)
+#if !defined(OS_MACOSX) && !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
ZygoteHandle GetZygote() override {
- if (no_sandbox_ || !exposed_dir_.empty())
+ if (IsUnsandboxedSandboxType(sandbox_type_) || !exposed_dir_.empty())
return nullptr;
return GetGenericZygote();
}
-#endif // !defined(OS_MACOSX) && !defined(OS_ANDROID)
+#endif // !defined(OS_MACOSX) && !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
base::EnvironmentMap GetEnvironment() override { return env_; }
#endif // OS_WIN
- SandboxType GetSandboxType() override {
- return SANDBOX_TYPE_UTILITY;
- }
+ SandboxType GetSandboxType() override { return sandbox_type_; }
private:
base::FilePath exposed_dir_;
@@ -111,10 +109,8 @@ class UtilitySandboxedProcessLauncherDelegate
bool launch_elevated_;
#elif defined(OS_POSIX)
base::EnvironmentMap env_;
-#if !defined(OS_MACOSX) && !defined(OS_ANDROID)
- bool no_sandbox_;
-#endif // !defined(OS_MACOSX) && !defined(OS_ANDROID)
#endif // OS_WIN
+ SandboxType sandbox_type_;
};
UtilityMainThreadFactoryFunction g_utility_main_thread_factory = NULL;
@@ -135,7 +131,7 @@ UtilityProcessHostImpl::UtilityProcessHostImpl(
const scoped_refptr<base::SequencedTaskRunner>& client_task_runner)
: client_(client),
client_task_runner_(client_task_runner),
- no_sandbox_(false),
+ sandbox_type_(SANDBOX_TYPE_UTILITY),
run_elevated_(false),
#if defined(OS_LINUX)
child_flags_(ChildProcessHost::CHILD_ALLOW_SELF),
@@ -170,14 +166,12 @@ void UtilityProcessHostImpl::SetExposedDir(const base::FilePath& dir) {
void UtilityProcessHostImpl::SetSandboxType(SandboxType sandbox_type) {
DCHECK(sandbox_type != SANDBOX_TYPE_INVALID);
-
- // TODO(tsepez): Store sandbox type itself.
- no_sandbox_ = IsUnsandboxedSandboxType(sandbox_type);
+ sandbox_type_ = sandbox_type;
}
#if defined(OS_WIN)
void UtilityProcessHostImpl::ElevatePrivileges() {
- no_sandbox_ = true;
+ sandbox_type_ = SANDBOX_TYPE_NO_SANDBOX;
run_elevated_ = true;
}
#endif
@@ -269,7 +263,7 @@ bool UtilityProcessHostImpl::StartProcess() {
cmd_line->AppendArg(switches::kPrefetchArgumentOther);
#endif // defined(OS_WIN)
- if (no_sandbox_)
+ if (IsUnsandboxedSandboxType(sandbox_type_))
cmd_line->AppendSwitch(switches::kNoSandbox);
// Browser command-line switches to propagate to the utility process.
@@ -284,6 +278,7 @@ bool UtilityProcessHostImpl::StartProcess() {
#endif
switches::kUseFakeDeviceForMediaStream,
switches::kUseFileForFakeVideoCapture,
+ switches::kUtilityStartupDialog,
};
cmd_line->CopySwitchesFrom(browser_command_line, kSwitchNames,
arraysize(kSwitchNames));
@@ -310,7 +305,7 @@ bool UtilityProcessHostImpl::StartProcess() {
#endif
process_->Launch(base::MakeUnique<UtilitySandboxedProcessLauncherDelegate>(
- exposed_dir_, run_elevated_, no_sandbox_, env_),
+ exposed_dir_, run_elevated_, sandbox_type_, env_),
std::move(cmd_line), true);
}
diff --git a/chromium/content/browser/utility_process_host_impl.h b/chromium/content/browser/utility_process_host_impl.h
index 0bf388040cf..ecfc91ceb78 100644
--- a/chromium/content/browser/utility_process_host_impl.h
+++ b/chromium/content/browser/utility_process_host_impl.h
@@ -29,7 +29,7 @@ typedef base::Thread* (*UtilityMainThreadFactoryFunction)(
const InProcessChildThreadParams&);
class CONTENT_EXPORT UtilityProcessHostImpl
- : public NON_EXPORTED_BASE(UtilityProcessHost),
+ : public UtilityProcessHost,
public BrowserChildProcessHostDelegate {
public:
static void RegisterUtilityMainThreadFactory(
@@ -85,8 +85,8 @@ class CONTENT_EXPORT UtilityProcessHostImpl
// Directory opened through the child process sandbox if needed.
base::FilePath exposed_dir_;
- // Whether to launch the child process with switches::kNoSandbox.
- bool no_sandbox_;
+ // Launch the child process with switches that will setup this sandbox type.
+ SandboxType sandbox_type_;
// Whether to launch the child process with elevated privileges.
bool run_elevated_;
diff --git a/chromium/content/browser/wake_lock/wake_lock_browsertest.cc b/chromium/content/browser/wake_lock/wake_lock_browsertest.cc
index 663fe3479c1..86ae40f0088 100644
--- a/chromium/content/browser/wake_lock/wake_lock_browsertest.cc
+++ b/chromium/content/browser/wake_lock/wake_lock_browsertest.cc
@@ -4,6 +4,7 @@
#include "base/command_line.h"
#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
#include "base/test/test_timeouts.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/common/content_switches.h"
@@ -24,7 +25,7 @@ const char kBlinkWakeLockFeature[] = "WakeLock";
void OnHasWakeLock(bool* out, bool has_wakelock) {
*out = has_wakelock;
- base::MessageLoop::current()->QuitNow();
+ base::RunLoop::QuitCurrentDeprecated();
}
} // namespace
diff --git a/chromium/content/browser/web_contents/aura/gesture_nav_simple.cc b/chromium/content/browser/web_contents/aura/gesture_nav_simple.cc
index 97d311e9631..21143fa6c6b 100644
--- a/chromium/content/browser/web_contents/aura/gesture_nav_simple.cc
+++ b/chromium/content/browser/web_contents/aura/gesture_nav_simple.cc
@@ -7,10 +7,14 @@
#include <utility>
#include "base/macros.h"
+#include "base/memory/ptr_util.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/metrics/user_metrics.h"
#include "cc/paint/paint_flags.h"
#include "components/vector_icons/vector_icons.h"
#include "content/browser/frame_host/navigation_controller_impl.h"
#include "content/browser/renderer_host/overscroll_controller.h"
+#include "content/browser/web_contents/aura/types.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/overscroll_configuration.h"
#include "third_party/skia/include/core/SkDrawLooper.h"
@@ -36,7 +40,9 @@ namespace {
// Parameters defining the arrow icon inside the affordance.
const int kArrowSize = 16;
const SkColor kArrowColor = gfx::kGoogleBlue500;
-const uint8_t kArrowInitialOpacity = 0x4D;
+const float kArrowFullOpacity = 1.f;
+const float kArrowInitialOpacity = .3f;
+const float kReloadArrowInitialRotation = -90.f;
// The arrow opacity remains constant until progress reaches this threshold,
// then increases quickly as the progress increases beyond the threshold
@@ -60,10 +66,19 @@ const gfx::Tween::Type kBurstAnimationTweenType = gfx::Tween::EASE_IN;
constexpr auto kRippleBurstAnimationDuration =
base::TimeDelta::FromMilliseconds(160);
-// Offset of the affordance when it is at the maximum distance with content
-// border. Since the affordance is initially out of content bounds, this is the
-// offset of the farther side of the affordance (which equals 128 + 18).
-const int kMaxAffordanceOffset = 146;
+// Offset of the affordance when it is at the activation threshold. Since the
+// affordance is initially out of content bounds, this is the offset of the
+// farther side of the affordance (which equals 128 + 18).
+const int kAffordanceActivationOffset = 146;
+
+// Extra offset of the affordance when it is dragged past the activation
+// threshold.
+const int kAffordanceExtraOffset = 72;
+const gfx::Tween::Type kExtraDragTweenType = gfx::Tween::Type::EASE_OUT;
+
+constexpr float kExtraAffordanceRatio =
+ static_cast<float>(kAffordanceExtraOffset) /
+ static_cast<float>(kAffordanceActivationOffset);
// Parameters defining animation when the affordance is aborted.
const gfx::Tween::Type kAbortAnimationTweenType = gfx::Tween::EASE_IN;
@@ -81,6 +96,97 @@ bool ShouldNavigateBack(const NavigationController& controller,
controller.CanGoBack();
}
+bool ShouldReload(const NavigationController& controller, OverscrollMode mode) {
+ return mode == OVERSCROLL_SOUTH;
+}
+
+NavigationDirection GetDirectionFromMode(OverscrollMode mode) {
+ if (mode == (base::i18n::IsRTL() ? OVERSCROLL_WEST : OVERSCROLL_EAST))
+ return NavigationDirection::BACK;
+ if (mode == (base::i18n::IsRTL() ? OVERSCROLL_EAST : OVERSCROLL_WEST))
+ return NavigationDirection::FORWARD;
+ if (mode == OVERSCROLL_SOUTH)
+ return NavigationDirection::RELOAD;
+ return NavigationDirection::NONE;
+}
+
+// Records UMA historgram and also user action for the cancelled overscroll.
+void RecordCancelled(NavigationDirection direction, OverscrollSource source) {
+ DCHECK_NE(direction, NavigationDirection::NONE);
+ DCHECK_NE(source, OverscrollSource::NONE);
+ UMA_HISTOGRAM_ENUMERATION("Overscroll.Cancelled3",
+ GetUmaNavigationType(direction, source),
+ NAVIGATION_TYPE_COUNT);
+ if (direction == NavigationDirection::BACK)
+ RecordAction(base::UserMetricsAction("Overscroll_Cancelled.Back"));
+ else if (direction == NavigationDirection::FORWARD)
+ RecordAction(base::UserMetricsAction("Overscroll_Cancelled.Forward"));
+ else
+ RecordAction(base::UserMetricsAction("Overscroll_Cancelled.Reload"));
+}
+
+// Responsible for drawing the affordance arrow. Depending on the overscroll
+// mode, it will draw back, forward, or reload arrow.
+class Arrow : public ui::LayerDelegate {
+ public:
+ explicit Arrow(OverscrollMode mode);
+ ~Arrow() override;
+
+ ui::Layer* layer() { return &layer_; }
+
+ private:
+ // ui::LayerDelegate:
+ void OnPaintLayer(const ui::PaintContext& context) override;
+ void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override;
+ void OnDeviceScaleFactorChanged(float device_scale_factor) override;
+
+ const OverscrollMode mode_;
+ ui::Layer layer_;
+
+ DISALLOW_COPY_AND_ASSIGN(Arrow);
+};
+
+Arrow::Arrow(OverscrollMode mode) : mode_(mode), layer_(ui::LAYER_TEXTURED) {
+ DCHECK(mode_ == OVERSCROLL_EAST || mode_ == OVERSCROLL_WEST ||
+ mode_ == OVERSCROLL_SOUTH);
+ gfx::Rect bounds(kArrowSize, kArrowSize);
+ bounds.set_x(kMaxRippleBurstRadius - kArrowSize / 2);
+ bounds.set_y(kMaxRippleBurstRadius - kArrowSize / 2);
+ layer_.SetBounds(bounds);
+ layer_.SetFillsBoundsOpaquely(false);
+ layer_.set_delegate(this);
+}
+
+Arrow::~Arrow() {}
+
+void Arrow::OnPaintLayer(const ui::PaintContext& context) {
+ const gfx::VectorIcon* icon = nullptr;
+ switch (mode_) {
+ case OVERSCROLL_EAST:
+ icon = &vector_icons::kBackArrowIcon;
+ break;
+ case OVERSCROLL_WEST:
+ icon = &vector_icons::kForwardArrowIcon;
+ break;
+ case OVERSCROLL_SOUTH:
+ icon = &vector_icons::kReloadIcon;
+ break;
+ case OVERSCROLL_NORTH:
+ case OVERSCROLL_NONE:
+ NOTREACHED();
+ }
+ const gfx::ImageSkia& image =
+ gfx::CreateVectorIcon(*icon, kArrowSize, kArrowColor);
+
+ ui::PaintRecorder recorder(context, layer_.size());
+ gfx::Canvas* canvas = recorder.canvas();
+ canvas->DrawImageInt(image, 0, 0);
+}
+
+void Arrow::OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) {}
+
+void Arrow::OnDeviceScaleFactorChanged(float device_scale_factor) {}
+
} // namespace
// This class is responsible for creating, painting, and positioning the layer
@@ -89,10 +195,13 @@ class Affordance : public ui::LayerDelegate, public gfx::AnimationDelegate {
public:
Affordance(GestureNavSimple* owner,
OverscrollMode mode,
- const gfx::Rect& content_bounds);
+ const gfx::Rect& content_bounds,
+ float max_drag_progress);
~Affordance() override;
- // Sets progress of affordance drag as a value between 0 and 1.
+ // Sets drag progress. 0 means no progress. 1 means full progress. Values more
+ // than 1 are also allowed for when the user drags beyond the completion
+ // threshold.
void SetDragProgress(float progress);
// Aborts the affordance and animates it back. This will delete |this|
@@ -104,7 +213,7 @@ class Affordance : public ui::LayerDelegate, public gfx::AnimationDelegate {
void Complete();
// Returns the root layer of the affordance.
- ui::Layer* root_layer() const { return root_layer_.get(); }
+ ui::Layer* root_layer() { return &root_layer_; }
// Returns whether the affordance is performing abort or complete animation.
bool IsFinishing() const { return state_ != State::DRAGGING; }
@@ -112,11 +221,22 @@ class Affordance : public ui::LayerDelegate, public gfx::AnimationDelegate {
private:
enum class State { DRAGGING, ABORTING, COMPLETING };
- void UpdateTransform();
+ // Helper function that returns the origin for painted layer according to the
+ // overscroll mode.
+ gfx::Point GetPaintedLayerOrigin(const gfx::Rect& content_bounds) const;
+
+ void UpdatePaintedLayer();
+ void UpdateArrowLayer();
+ void UpdateLayers();
void SchedulePaint();
void SetAbortProgress(float progress);
void SetCompleteProgress(float progress);
+ // Helper function that returns the affordance progress according to the
+ // current values of different progress values (drag progress and abort
+ // progress). 1 means the affordance is at the activation threshold.
+ float GetAffordanceProgress() const;
+
// ui::LayerDelegate:
void OnPaintLayer(const ui::PaintContext& context) override;
void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override;
@@ -131,15 +251,19 @@ class Affordance : public ui::LayerDelegate, public gfx::AnimationDelegate {
const OverscrollMode mode_;
+ // Maximum value for drag progress that can be reached if the user drags
+ // entire width of the page/screen.
+ const float max_drag_progress_;
+
// Root layer of the affordance. This is used to clip the affordance to the
// content bounds.
- std::unique_ptr<ui::Layer> root_layer_;
+ ui::Layer root_layer_;
// Layer that actually paints the affordance.
- std::unique_ptr<ui::Layer> painted_layer_;
+ ui::Layer painted_layer_;
- // Arrow image to be used for the affordance.
- const gfx::Image image_;
+ // The arrow for the affordance.
+ Arrow arrow_;
// Values that determine current state of the affordance.
State state_ = State::DRAGGING;
@@ -154,33 +278,29 @@ class Affordance : public ui::LayerDelegate, public gfx::AnimationDelegate {
Affordance::Affordance(GestureNavSimple* owner,
OverscrollMode mode,
- const gfx::Rect& content_bounds)
+ const gfx::Rect& content_bounds,
+ float max_drag_progress)
: owner_(owner),
mode_(mode),
- root_layer_(base::MakeUnique<ui::Layer>(ui::LAYER_NOT_DRAWN)),
- painted_layer_(base::MakeUnique<ui::Layer>(ui::LAYER_TEXTURED)),
- image_(gfx::CreateVectorIcon(mode == OVERSCROLL_EAST
- ? vector_icons::kBackArrowIcon
- : vector_icons::kForwardArrowIcon,
- kArrowSize,
- kArrowColor)) {
- DCHECK(mode == OVERSCROLL_EAST || mode == OVERSCROLL_WEST);
- DCHECK(!image_.IsEmpty());
-
- root_layer_->SetBounds(content_bounds);
- root_layer_->SetMasksToBounds(true);
-
- painted_layer_->SetFillsBoundsOpaquely(false);
- int x =
- mode_ == OVERSCROLL_EAST
- ? -kMaxRippleBurstRadius - kBackgroundRadius
- : content_bounds.width() - kMaxRippleBurstRadius + kBackgroundRadius;
- int y = std::max(0, content_bounds.height() / 2 - kMaxRippleBurstRadius);
- painted_layer_->SetBounds(
- gfx::Rect(x, y, 2 * kMaxRippleBurstRadius, 2 * kMaxRippleBurstRadius));
- painted_layer_->set_delegate(this);
-
- root_layer_->Add(painted_layer_.get());
+ max_drag_progress_(max_drag_progress),
+ root_layer_(ui::LAYER_NOT_DRAWN),
+ painted_layer_(ui::LAYER_TEXTURED),
+ arrow_(mode) {
+ DCHECK(mode_ == OVERSCROLL_EAST || mode_ == OVERSCROLL_WEST ||
+ mode_ == OVERSCROLL_SOUTH);
+
+ root_layer_.SetBounds(content_bounds);
+ root_layer_.SetMasksToBounds(true);
+
+ painted_layer_.SetFillsBoundsOpaquely(false);
+ gfx::Rect painted_layer_bounds(2 * kMaxRippleBurstRadius,
+ 2 * kMaxRippleBurstRadius);
+ painted_layer_bounds.set_origin(GetPaintedLayerOrigin(content_bounds));
+ painted_layer_.SetBounds(painted_layer_bounds);
+ painted_layer_.set_delegate(this);
+
+ painted_layer_.Add(arrow_.layer());
+ root_layer_.Add(&painted_layer_);
}
Affordance::~Affordance() {}
@@ -188,13 +308,12 @@ Affordance::~Affordance() {}
void Affordance::SetDragProgress(float progress) {
DCHECK_EQ(State::DRAGGING, state_);
DCHECK_LE(0.f, progress);
- DCHECK_GE(1.f, progress);
if (drag_progress_ == progress)
return;
drag_progress_ = progress;
- UpdateTransform();
+ UpdateLayers();
SchedulePaint();
}
@@ -203,33 +322,97 @@ void Affordance::Abort() {
state_ = State::ABORTING;
- animation_.reset(
- new gfx::LinearAnimation(drag_progress_ * kAbortAnimationDuration,
- gfx::LinearAnimation::kDefaultFrameRate, this));
+ animation_ = base::MakeUnique<gfx::LinearAnimation>(
+ GetAffordanceProgress() * kAbortAnimationDuration,
+ gfx::LinearAnimation::kDefaultFrameRate, this);
animation_->Start();
}
void Affordance::Complete() {
DCHECK_EQ(State::DRAGGING, state_);
- DCHECK_EQ(1.f, drag_progress_);
+ DCHECK_LE(1.f, drag_progress_);
state_ = State::COMPLETING;
- animation_.reset(
- new gfx::LinearAnimation(kRippleBurstAnimationDuration,
- gfx::LinearAnimation::kDefaultFrameRate, this));
+ animation_ = base::MakeUnique<gfx::LinearAnimation>(
+ kRippleBurstAnimationDuration, gfx::LinearAnimation::kDefaultFrameRate,
+ this);
animation_->Start();
}
-void Affordance::UpdateTransform() {
- float offset = (1 - abort_progress_) * drag_progress_ * kMaxAffordanceOffset;
+gfx::Point Affordance::GetPaintedLayerOrigin(
+ const gfx::Rect& content_bounds) const {
+ DCHECK_NE(OVERSCROLL_NONE, mode_);
+ gfx::Point origin;
+ if (mode_ == OVERSCROLL_SOUTH) {
+ origin.set_x(
+ std::max(0, content_bounds.width() / 2 - kMaxRippleBurstRadius));
+ origin.set_y(-kMaxRippleBurstRadius - kBackgroundRadius);
+ } else {
+ origin.set_y(
+ std::max(0, content_bounds.height() / 2 - kMaxRippleBurstRadius));
+ if (mode_ == OVERSCROLL_EAST) {
+ origin.set_x(-kMaxRippleBurstRadius - kBackgroundRadius);
+ } else {
+ origin.set_x(content_bounds.width() - kMaxRippleBurstRadius +
+ kBackgroundRadius);
+ }
+ }
+ return origin;
+}
+
+void Affordance::UpdatePaintedLayer() {
+ const float offset = GetAffordanceProgress() * kAffordanceActivationOffset;
+ gfx::Transform transform;
+ if (mode_ == OVERSCROLL_EAST)
+ transform.Translate(offset, 0);
+ else if (mode_ == OVERSCROLL_WEST)
+ transform.Translate(-offset, 0);
+ else
+ transform.Translate(0, offset);
+ painted_layer_.SetTransform(transform);
+}
+
+void Affordance::UpdateArrowLayer() {
+ const float progress = std::min(1.f, GetAffordanceProgress());
gfx::Transform transform;
- transform.Translate(mode_ == OVERSCROLL_EAST ? offset : -offset, 0);
- painted_layer_->SetTransform(transform);
+ if (mode_ == OVERSCROLL_SOUTH) {
+ gfx::Vector2dF offset(kArrowSize / 2.f, kArrowSize / 2.f);
+ transform.Translate(offset);
+ transform.Rotate(kReloadArrowInitialRotation * (1 - progress));
+ transform.Translate(-offset);
+ } else {
+ // Calculate the offset for the arrow relative to its final position.
+ const float offset =
+ (1 - progress) * (-kBackgroundRadius + kArrowSize / 2.f);
+ transform.Translate(
+ gfx::Vector2dF(mode_ == OVERSCROLL_EAST ? offset : -offset, 0));
+ }
+ arrow_.layer()->SetTransform(transform);
+
+ if (mode_ != OVERSCROLL_SOUTH) {
+ // The arrow opacity is fixed before progress reaches
+ // kArrowOpacityProgressThreshold and after that increases linearly to 1;
+ // essentially, making a quick bump at the end.
+ float opacity = kArrowInitialOpacity;
+ if (progress > kArrowOpacityProgressThreshold) {
+ const float max_opacity_bump = kArrowFullOpacity - kArrowInitialOpacity;
+ const float opacity_bump_ratio =
+ std::min(1.f, (progress - kArrowOpacityProgressThreshold) /
+ (1.f - kArrowOpacityProgressThreshold));
+ opacity += opacity_bump_ratio * max_opacity_bump;
+ }
+ arrow_.layer()->SetOpacity(opacity);
+ }
+}
+
+void Affordance::UpdateLayers() {
+ UpdatePaintedLayer();
+ UpdateArrowLayer();
}
void Affordance::SchedulePaint() {
- painted_layer_->SchedulePaint(gfx::Rect(painted_layer_->size()));
+ painted_layer_.SchedulePaint(gfx::Rect(painted_layer_.size()));
}
void Affordance::SetAbortProgress(float progress) {
@@ -241,7 +424,7 @@ void Affordance::SetAbortProgress(float progress) {
return;
abort_progress_ = progress;
- UpdateTransform();
+ UpdateLayers();
SchedulePaint();
}
@@ -254,20 +437,41 @@ void Affordance::SetCompleteProgress(float progress) {
return;
complete_progress_ = progress;
- painted_layer_->SetOpacity(1 - complete_progress_);
+ painted_layer_.SetOpacity(gfx::Tween::CalculateValue(kBurstAnimationTweenType,
+ 1 - complete_progress_));
SchedulePaint();
}
+float Affordance::GetAffordanceProgress() const {
+ // Apply tween on the drag progress.
+ float affordance_progress = drag_progress_;
+ if (drag_progress_ >= 1.f) {
+ float extra_progress = max_drag_progress_ == 1.f
+ ? 1.f
+ : std::min(1.f, (drag_progress_ - 1.f) /
+ (max_drag_progress_ - 1.f));
+ affordance_progress =
+ 1 + gfx::Tween::CalculateValue(kExtraDragTweenType, extra_progress) *
+ kExtraAffordanceRatio;
+ }
+
+ // Apply abort progress, if any.
+ affordance_progress *=
+ 1 - gfx::Tween::CalculateValue(kAbortAnimationTweenType, abort_progress_);
+
+ return affordance_progress;
+}
+
void Affordance::OnPaintLayer(const ui::PaintContext& context) {
- DCHECK(drag_progress_ == 1.f || state_ != State::COMPLETING);
+ DCHECK(drag_progress_ >= 1.f || state_ != State::COMPLETING);
DCHECK(abort_progress_ == 0.f || state_ == State::ABORTING);
DCHECK(complete_progress_ == 0.f || state_ == State::COMPLETING);
- ui::PaintRecorder recorder(context, painted_layer_->size());
+ ui::PaintRecorder recorder(context, painted_layer_.size());
gfx::Canvas* canvas = recorder.canvas();
gfx::PointF center_point(kMaxRippleBurstRadius, kMaxRippleBurstRadius);
- float progress = (1 - abort_progress_) * drag_progress_;
+ float progress = std::min(1.f, GetAffordanceProgress());
// Draw the ripple.
cc::PaintFlags ripple_flags;
@@ -276,9 +480,10 @@ void Affordance::OnPaintLayer(const ui::PaintContext& context) {
ripple_flags.setColor(kRippleColor);
float ripple_radius;
if (state_ == State::COMPLETING) {
- ripple_radius =
- kMaxRippleRadius +
- complete_progress_ * (kMaxRippleBurstRadius - kMaxRippleRadius);
+ const float burst_progress = gfx::Tween::CalculateValue(
+ kBurstAnimationTweenType, complete_progress_);
+ ripple_radius = kMaxRippleRadius +
+ burst_progress * (kMaxRippleBurstRadius - kMaxRippleRadius);
} else {
ripple_radius =
kBackgroundRadius + progress * (kMaxRippleRadius - kBackgroundRadius);
@@ -295,28 +500,6 @@ void Affordance::OnPaintLayer(const ui::PaintContext& context) {
kBgShadowColor);
bg_flags.setLooper(gfx::CreateShadowDrawLooper(shadow));
canvas->DrawCircle(center_point, kBackgroundRadius, bg_flags);
-
- // Draw the arrow.
- float arrow_x = center_point.x() - kArrowSize / 2.f;
- float arrow_y = center_point.y() - kArrowSize / 2.f;
- // Calculate the offset for the arrow relative to its circular background.
- float arrow_x_offset =
- (1 - progress) * (-kBackgroundRadius + kArrowSize / 2.f);
- arrow_x += mode_ == OVERSCROLL_EAST ? arrow_x_offset : -arrow_x_offset;
- // Calculate arrow opacity. Opacity is fixed before progress reaches
- // kArrowOpacityProgressThreshold and after that increases linearly to 1;
- // essentially, making a quick bump at the end.
- uint8_t arrow_opacity = kArrowInitialOpacity;
- if (progress > kArrowOpacityProgressThreshold) {
- const uint8_t max_opacity_bump = 0xFF - kArrowInitialOpacity;
- const float opacity_bump_ratio =
- std::min(1.f, (progress - kArrowOpacityProgressThreshold) /
- (1.f - kArrowOpacityProgressThreshold));
- arrow_opacity +=
- static_cast<uint8_t>(opacity_bump_ratio * max_opacity_bump);
- }
- canvas->DrawImageInt(*image_.ToImageSkia(), static_cast<int>(arrow_x),
- static_cast<int>(arrow_y), arrow_opacity);
}
void Affordance::OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) {}
@@ -333,12 +516,10 @@ void Affordance::AnimationProgressed(const gfx::Animation* animation) {
NOTREACHED();
break;
case State::ABORTING:
- SetAbortProgress(gfx::Tween::CalculateValue(
- kAbortAnimationTweenType, animation->GetCurrentValue()));
+ SetAbortProgress(animation->GetCurrentValue());
break;
case State::COMPLETING:
- SetCompleteProgress(gfx::Tween::CalculateValue(
- kBurstAnimationTweenType, animation->GetCurrentValue()));
+ SetCompleteProgress(animation->GetCurrentValue());
break;
}
}
@@ -348,27 +529,12 @@ void Affordance::AnimationCanceled(const gfx::Animation* animation) {
}
GestureNavSimple::GestureNavSimple(WebContentsImpl* web_contents)
- : web_contents_(web_contents),
- completion_threshold_(0.f) {}
+ : web_contents_(web_contents) {}
GestureNavSimple::~GestureNavSimple() {}
-void GestureNavSimple::AbortGestureAnimation() {
- if (affordance_)
- affordance_->Abort();
-}
-
-void GestureNavSimple::CompleteGestureAnimation() {
- if (affordance_)
- affordance_->Complete();
-}
-
void GestureNavSimple::OnAffordanceAnimationEnded() {
- affordance_.reset();
-}
-
-gfx::Size GestureNavSimple::GetVisibleSize() const {
- return web_contents_->GetNativeView()->bounds().size();
+ affordance_ = nullptr;
}
gfx::Size GestureNavSimple::GetDisplaySize() const {
@@ -380,48 +546,102 @@ gfx::Size GestureNavSimple::GetDisplaySize() const {
bool GestureNavSimple::OnOverscrollUpdate(float delta_x, float delta_y) {
if (!affordance_ || affordance_->IsFinishing())
return false;
- affordance_->SetDragProgress(
- std::min(1.f, std::abs(delta_x) / completion_threshold_));
+ float delta = std::abs(mode_ == OVERSCROLL_SOUTH ? delta_y : delta_x);
+ DCHECK_LE(delta, max_delta_);
+ affordance_->SetDragProgress(delta / completion_threshold_);
return true;
}
void GestureNavSimple::OnOverscrollComplete(OverscrollMode overscroll_mode) {
+ DCHECK_EQ(mode_, overscroll_mode);
+
+ mode_ = OVERSCROLL_NONE;
+ OverscrollSource overscroll_source = source_;
+ source_ = OverscrollSource::NONE;
if (!affordance_ || affordance_->IsFinishing())
return;
- CompleteGestureAnimation();
+ affordance_->Complete();
NavigationControllerImpl& controller = web_contents_->GetController();
- if (ShouldNavigateForward(controller, overscroll_mode))
+ NavigationDirection direction = NavigationDirection::NONE;
+ if (ShouldNavigateForward(controller, overscroll_mode)) {
controller.GoForward();
- else if (ShouldNavigateBack(controller, overscroll_mode))
+ direction = NavigationDirection::FORWARD;
+ } else if (ShouldNavigateBack(controller, overscroll_mode)) {
controller.GoBack();
+ direction = NavigationDirection::BACK;
+ } else if (ShouldReload(controller, overscroll_mode)) {
+ controller.Reload(ReloadType::NORMAL, true);
+ direction = NavigationDirection::RELOAD;
+ }
+
+ if (direction != NavigationDirection::NONE) {
+ UMA_HISTOGRAM_ENUMERATION(
+ "Overscroll.Navigated3",
+ GetUmaNavigationType(direction, overscroll_source),
+ UmaNavigationType::NAVIGATION_TYPE_COUNT);
+ if (direction == NavigationDirection::BACK)
+ RecordAction(base::UserMetricsAction("Overscroll_Navigated.Back"));
+ else if (direction == NavigationDirection::FORWARD)
+ RecordAction(base::UserMetricsAction("Overscroll_Navigated.Forward"));
+ else
+ RecordAction(base::UserMetricsAction("Overscroll_Navigated.Reload"));
+ } else {
+ RecordCancelled(GetDirectionFromMode(overscroll_mode), overscroll_source);
+ }
}
void GestureNavSimple::OnOverscrollModeChange(OverscrollMode old_mode,
OverscrollMode new_mode,
OverscrollSource source) {
+ DCHECK_EQ(mode_, old_mode);
+ if (mode_ == new_mode)
+ return;
+ mode_ = new_mode;
+
NavigationControllerImpl& controller = web_contents_->GetController();
- if (!ShouldNavigateForward(controller, new_mode) &&
- !ShouldNavigateBack(controller, new_mode)) {
- AbortGestureAnimation();
+ if (!ShouldNavigateForward(controller, mode_) &&
+ !ShouldNavigateBack(controller, mode_) &&
+ !ShouldReload(controller, mode_)) {
+ // If there is an overscroll in progress - record its cancellation.
+ if (affordance_ && !affordance_->IsFinishing()) {
+ RecordCancelled(GetDirectionFromMode(old_mode), source_);
+ affordance_->Abort();
+ }
+ source_ = OverscrollSource::NONE;
return;
}
- DCHECK_NE(source, OverscrollSource::NONE);
+ DCHECK_NE(OverscrollSource::NONE, source);
+ source_ = source;
+
+ UMA_HISTOGRAM_ENUMERATION(
+ "Overscroll.Started3",
+ GetUmaNavigationType(GetDirectionFromMode(mode_), source_),
+ UmaNavigationType::NAVIGATION_TYPE_COUNT);
+
+ bool is_vertical = mode_ == OVERSCROLL_SOUTH;
const float start_threshold = GetOverscrollConfig(
- source == OverscrollSource::TOUCHPAD
- ? OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START_TOUCHPAD
- : OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START_TOUCHSCREEN);
- const int width = source == OverscrollSource::TOUCHPAD
- ? GetDisplaySize().width()
- : GetVisibleSize().width();
+ is_vertical ? OVERSCROLL_CONFIG_VERT_THRESHOLD_START
+ : source == OverscrollSource::TOUCHPAD
+ ? OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START_TOUCHPAD
+ : OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START_TOUCHSCREEN);
+ const int size =
+ is_vertical ? GetDisplaySize().height() : GetDisplaySize().width();
completion_threshold_ =
- width * GetOverscrollConfig(OVERSCROLL_CONFIG_HORIZ_THRESHOLD_COMPLETE) -
+ size * GetOverscrollConfig(
+ is_vertical ? OVERSCROLL_CONFIG_VERT_THRESHOLD_COMPLETE
+ : OVERSCROLL_CONFIG_HORIZ_THRESHOLD_COMPLETE) -
start_threshold;
+ DCHECK_LE(0, completion_threshold_);
+
+ max_delta_ = size - start_threshold;
+ DCHECK_LE(0, max_delta_);
aura::Window* window = web_contents_->GetNativeView();
- affordance_ = base::MakeUnique<Affordance>(this, new_mode, window->bounds());
+ affordance_ = base::MakeUnique<Affordance>(
+ this, mode_, window->bounds(), max_delta_ / completion_threshold_);
// Adding the affordance as a child of the content window is not sufficient,
// because it is possible for a new layer to be parented on top of the
@@ -436,7 +656,7 @@ void GestureNavSimple::OnOverscrollModeChange(OverscrollMode old_mode,
base::Optional<float> GestureNavSimple::GetMaxOverscrollDelta() const {
if (affordance_)
- return completion_threshold_;
+ return max_delta_;
return base::nullopt;
}
diff --git a/chromium/content/browser/web_contents/aura/gesture_nav_simple.h b/chromium/content/browser/web_contents/aura/gesture_nav_simple.h
index 70b474f3f1f..999b18715b0 100644
--- a/chromium/content/browser/web_contents/aura/gesture_nav_simple.h
+++ b/chromium/content/browser/web_contents/aura/gesture_nav_simple.h
@@ -27,11 +27,7 @@ class GestureNavSimple : public OverscrollControllerDelegate {
void OnAffordanceAnimationEnded();
private:
- void AbortGestureAnimation();
- void CompleteGestureAnimation();
-
// OverscrollControllerDelegate:
- gfx::Size GetVisibleSize() const override;
gfx::Size GetDisplaySize() const override;
bool OnOverscrollUpdate(float delta_x, float delta_y) override;
void OnOverscrollComplete(OverscrollMode overscroll_mode) override;
@@ -40,9 +36,16 @@ class GestureNavSimple : public OverscrollControllerDelegate {
OverscrollSource source) override;
base::Optional<float> GetMaxOverscrollDelta() const override;
- WebContentsImpl* web_contents_;
+ WebContentsImpl* web_contents_ = nullptr;
+
+ OverscrollMode mode_ = OVERSCROLL_NONE;
+ OverscrollSource source_ = OverscrollSource::NONE;
std::unique_ptr<Affordance> affordance_;
- float completion_threshold_;
+ float completion_threshold_ = 0.f;
+
+ // When an overscroll is active, represents the maximum overscroll delta we
+ // expect in OnOverscrollUpdate().
+ float max_delta_ = 0.f;
DISALLOW_COPY_AND_ASSIGN(GestureNavSimple);
};
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 9ed29e92433..427784094dd 100644
--- a/chromium/content/browser/web_contents/aura/overscroll_navigation_overlay.cc
+++ b/chromium/content/browser/web_contents/aura/overscroll_navigation_overlay.cc
@@ -14,7 +14,6 @@
#include "content/browser/frame_host/navigation_entry_impl.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/web_contents/aura/overscroll_window_delegate.h"
-#include "content/browser/web_contents/aura/uma_navigation_type.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/view_messages.h"
#include "content/public/browser/browser_thread.h"
@@ -48,29 +47,12 @@ bool DoesEntryMatchURL(NavigationEntry* entry, const GURL& url) {
return false;
}
-UmaNavigationType GetUmaNavigationType(
- OverscrollNavigationOverlay::NavigationDirection direction,
- OverscrollSource source) {
- if (direction == OverscrollNavigationOverlay::NONE ||
- source == OverscrollSource::NONE)
- return NAVIGATION_TYPE_NONE;
- if (direction == OverscrollNavigationOverlay::BACK)
- return source == OverscrollSource::TOUCHPAD
- ? UmaNavigationType::BACK_TOUCHPAD
- : UmaNavigationType::BACK_TOUCHSCREEN;
- DCHECK_EQ(direction, OverscrollNavigationOverlay::FORWARD);
- return source == OverscrollSource::TOUCHPAD
- ? UmaNavigationType::FORWARD_TOUCHPAD
- : UmaNavigationType::FORWARD_TOUCHSCREEN;
-}
-
// Records UMA historgram and also user action for the cancelled overscroll.
-void RecordCancelled(OverscrollNavigationOverlay::NavigationDirection direction,
- OverscrollSource source) {
+void RecordCancelled(NavigationDirection direction, OverscrollSource source) {
UMA_HISTOGRAM_ENUMERATION("Overscroll.Cancelled3",
GetUmaNavigationType(direction, source),
NAVIGATION_TYPE_COUNT);
- if (direction == OverscrollNavigationOverlay::BACK)
+ if (direction == NavigationDirection::BACK)
RecordAction(base::UserMetricsAction("Overscroll_Cancelled.Back"));
else
RecordAction(base::UserMetricsAction("Overscroll_Cancelled.Forward"));
@@ -123,7 +105,7 @@ class OverlayDismissAnimator
OverscrollNavigationOverlay::OverscrollNavigationOverlay(
WebContentsImpl* web_contents,
aura::Window* web_contents_window)
- : direction_(NONE),
+ : direction_(NavigationDirection::NONE),
web_contents_(web_contents),
loading_complete_(false),
received_paint_update_(false),
@@ -187,7 +169,7 @@ std::unique_ptr<aura::Window> OverscrollNavigationOverlay::CreateOverlayWindow(
window->SetName("OverscrollOverlay");
web_contents_window_->AddChild(window.get());
aura::Window* event_window = GetMainWindow();
- if (direction_ == FORWARD)
+ if (direction_ == NavigationDirection::FORWARD)
web_contents_window_->StackChildAbove(window.get(), event_window);
else
web_contents_window_->StackChildBelow(window.get(), event_window);
@@ -204,7 +186,8 @@ const gfx::Image OverscrollNavigationOverlay::GetImageForDirection(
NavigationDirection direction) const {
const NavigationControllerImpl& controller = web_contents_->GetController();
const NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry(
- controller.GetEntryAtOffset(direction == FORWARD ? 1 : -1));
+ controller.GetEntryAtOffset(
+ direction == NavigationDirection::FORWARD ? 1 : -1));
if (entry && entry->screenshot().get()) {
std::vector<gfx::ImagePNGRep> image_reps;
@@ -218,7 +201,7 @@ std::unique_ptr<aura::Window> OverscrollNavigationOverlay::CreateFrontWindow(
const gfx::Rect& bounds) {
if (!web_contents_->GetController().CanGoForward())
return nullptr;
- direction_ = FORWARD;
+ direction_ = NavigationDirection::FORWARD;
return CreateOverlayWindow(bounds);
}
@@ -226,7 +209,7 @@ std::unique_ptr<aura::Window> OverscrollNavigationOverlay::CreateBackWindow(
const gfx::Rect& bounds) {
if (!web_contents_->GetController().CanGoBack())
return nullptr;
- direction_ = BACK;
+ direction_ = NavigationDirection::BACK;
return CreateOverlayWindow(bounds);
}
@@ -247,7 +230,7 @@ void OverscrollNavigationOverlay::OnOverscrollCompleting() {
void OverscrollNavigationOverlay::OnOverscrollCompleted(
std::unique_ptr<aura::Window> window) {
- DCHECK(direction_ != NONE);
+ DCHECK_NE(direction_, NavigationDirection::NONE);
aura::Window* main_window = GetMainWindow();
if (!main_window) {
RecordCancelled(direction_, owa_->overscroll_source());
@@ -266,10 +249,12 @@ void OverscrollNavigationOverlay::OnOverscrollCompleted(
// during an overscroll gesture and navigating without history produces a
// crash.
bool navigated = false;
- if (direction_ == FORWARD && web_contents_->GetController().CanGoForward()) {
+ if (direction_ == NavigationDirection::FORWARD &&
+ web_contents_->GetController().CanGoForward()) {
web_contents_->GetController().GoForward();
navigated = true;
- } else if (direction_ == BACK && web_contents_->GetController().CanGoBack()) {
+ } else if (direction_ == NavigationDirection::BACK &&
+ web_contents_->GetController().CanGoBack()) {
web_contents_->GetController().GoBack();
navigated = true;
} else {
@@ -284,14 +269,14 @@ void OverscrollNavigationOverlay::OnOverscrollCompleted(
"Overscroll.Navigated3",
GetUmaNavigationType(direction_, owa_->overscroll_source()),
NAVIGATION_TYPE_COUNT);
- if (direction_ == BACK)
+ if (direction_ == NavigationDirection::BACK)
RecordAction(base::UserMetricsAction("Overscroll_Navigated.Back"));
else
RecordAction(base::UserMetricsAction("Overscroll_Navigated.Forward"));
StartObserving();
}
- direction_ = NONE;
+ direction_ = NavigationDirection::NONE;
StopObservingIfDone();
}
@@ -301,7 +286,7 @@ void OverscrollNavigationOverlay::OnOverscrollCancelled() {
if (!main_window)
return;
main_window->ReleaseCapture();
- direction_ = NONE;
+ direction_ = NavigationDirection::NONE;
StopObservingIfDone();
}
diff --git a/chromium/content/browser/web_contents/aura/overscroll_navigation_overlay.h b/chromium/content/browser/web_contents/aura/overscroll_navigation_overlay.h
index 44739c97382..4f69dde8974 100644
--- a/chromium/content/browser/web_contents/aura/overscroll_navigation_overlay.h
+++ b/chromium/content/browser/web_contents/aura/overscroll_navigation_overlay.h
@@ -8,6 +8,7 @@
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "content/browser/web_contents/aura/overscroll_window_animation.h"
+#include "content/browser/web_contents/aura/types.h"
#include "content/browser/web_contents/web_contents_view_aura.h"
#include "content/common/content_export.h"
#include "content/public/browser/web_contents_observer.h"
@@ -32,8 +33,6 @@ class CONTENT_EXPORT OverscrollNavigationOverlay
: public WebContentsObserver,
public OverscrollWindowAnimation::Delegate {
public:
- enum NavigationDirection { NONE, FORWARD, BACK, NAVIGATION_COUNT };
-
OverscrollNavigationOverlay(WebContentsImpl* web_contents,
aura::Window* web_contents_window);
diff --git a/chromium/content/browser/web_contents/aura/overscroll_navigation_overlay_unittest.cc b/chromium/content/browser/web_contents/aura/overscroll_navigation_overlay_unittest.cc
index 02fc3bc43b4..778ad3772ec 100644
--- a/chromium/content/browser/web_contents/aura/overscroll_navigation_overlay_unittest.cc
+++ b/chromium/content/browser/web_contents/aura/overscroll_navigation_overlay_unittest.cc
@@ -12,7 +12,7 @@
#include "base/test/histogram_tester.h"
#include "base/test/user_action_tester.h"
#include "content/browser/frame_host/navigation_entry_impl.h"
-#include "content/browser/web_contents/aura/uma_navigation_type.h"
+#include "content/browser/web_contents/aura/types.h"
#include "content/browser/web_contents/web_contents_view.h"
#include "content/common/frame_messages.h"
#include "content/common/view_messages.h"
@@ -157,7 +157,7 @@ class OverscrollNavigationOverlayTest : public RenderViewHostImplTestHarness {
kUmaStarted, source == OverscrollSource::TOUCHPAD ? BACK_TOUCHPAD
: BACK_TOUCHSCREEN,
1);
- EXPECT_EQ(GetOverlay()->direction_, OverscrollNavigationOverlay::BACK);
+ EXPECT_EQ(GetOverlay()->direction_, NavigationDirection::BACK);
// Performs BACK navigation, sets image from layer_delegate_ on
// image_delegate_.
GetOverlay()->OnOverscrollCompleting();
@@ -175,7 +175,7 @@ class OverscrollNavigationOverlayTest : public RenderViewHostImplTestHarness {
1);
EXPECT_EQ(1, action_tester()->GetActionCount(kActionNavigatedBack));
} else {
- EXPECT_EQ(GetOverlay()->direction_, OverscrollNavigationOverlay::NONE);
+ EXPECT_EQ(GetOverlay()->direction_, NavigationDirection::NONE);
histogram_tester()->ExpectTotalCount(kUmaStarted, 0);
}
GetOverlay()->owa_->SetOverscrollSourceForTesting(OverscrollSource::NONE);
@@ -320,14 +320,14 @@ TEST_F(OverscrollNavigationOverlayTest, CancelNavigation) {
OverscrollSource::TOUCHSCREEN);
std::unique_ptr<aura::Window> window =
GetOverlay()->CreateBackWindow(GetBackSlideWindowBounds());
- EXPECT_EQ(GetOverlay()->direction_, OverscrollNavigationOverlay::BACK);
+ EXPECT_EQ(GetOverlay()->direction_, NavigationDirection::BACK);
histogram_tester()->ExpectTotalCount(kUmaCancelled, 0);
EXPECT_EQ(0, action_tester()->GetActionCount(kActionCancelledBack));
GetOverlay()->OnOverscrollCancelled();
EXPECT_FALSE(contents()->CrossProcessNavigationPending());
- EXPECT_EQ(GetOverlay()->direction_, OverscrollNavigationOverlay::NONE);
+ EXPECT_EQ(GetOverlay()->direction_, NavigationDirection::NONE);
histogram_tester()->ExpectTotalCount(kUmaCancelled, 1);
histogram_tester()->ExpectBucketCount(kUmaCancelled, BACK_TOUCHSCREEN, 1);
EXPECT_EQ(1, action_tester()->GetActionCount(kActionCancelledBack));
@@ -339,7 +339,7 @@ TEST_F(OverscrollNavigationOverlayTest, ForwardNavigation) {
GetOverlay()->owa_->SetOverscrollSourceForTesting(OverscrollSource::TOUCHPAD);
std::unique_ptr<aura::Window> window =
GetOverlay()->CreateFrontWindow(GetBackSlideWindowBounds());
- EXPECT_EQ(GetOverlay()->direction_, OverscrollNavigationOverlay::FORWARD);
+ EXPECT_EQ(GetOverlay()->direction_, NavigationDirection::FORWARD);
histogram_tester()->ExpectTotalCount(kUmaStarted, 2);
histogram_tester()->ExpectBucketCount(kUmaStarted, FORWARD_TOUCHPAD, 1);
@@ -362,7 +362,7 @@ TEST_F(OverscrollNavigationOverlayTest, ForwardNavigationCancelled) {
OverscrollSource::TOUCHSCREEN);
std::unique_ptr<aura::Window> window =
GetOverlay()->CreateFrontWindow(GetBackSlideWindowBounds());
- EXPECT_EQ(GetOverlay()->direction_, OverscrollNavigationOverlay::FORWARD);
+ EXPECT_EQ(GetOverlay()->direction_, NavigationDirection::FORWARD);
histogram_tester()->ExpectTotalCount(kUmaStarted, 2);
histogram_tester()->ExpectBucketCount(kUmaStarted, FORWARD_TOUCHSCREEN, 1);
@@ -370,7 +370,7 @@ TEST_F(OverscrollNavigationOverlayTest, ForwardNavigationCancelled) {
EXPECT_EQ(0, action_tester()->GetActionCount(kActionCancelledForward));
GetOverlay()->OnOverscrollCancelled();
- EXPECT_EQ(GetOverlay()->direction_, OverscrollNavigationOverlay::NONE);
+ EXPECT_EQ(GetOverlay()->direction_, NavigationDirection::NONE);
histogram_tester()->ExpectTotalCount(kUmaCancelled, 1);
histogram_tester()->ExpectBucketCount(kUmaCancelled, FORWARD_TOUCHSCREEN, 1);
EXPECT_EQ(1, action_tester()->GetActionCount(kActionCancelledForward));
@@ -383,12 +383,12 @@ TEST_F(OverscrollNavigationOverlayTest, CancelAfterSuccessfulNavigation) {
GetOverlay()->owa_->SetOverscrollSourceForTesting(OverscrollSource::TOUCHPAD);
std::unique_ptr<aura::Window> wrapper =
GetOverlay()->CreateBackWindow(GetBackSlideWindowBounds());
- EXPECT_EQ(GetOverlay()->direction_, OverscrollNavigationOverlay::BACK);
+ EXPECT_EQ(GetOverlay()->direction_, NavigationDirection::BACK);
histogram_tester()->ExpectTotalCount(kUmaStarted, 2);
histogram_tester()->ExpectBucketCount(kUmaStarted, BACK_TOUCHPAD, 2);
GetOverlay()->OnOverscrollCancelled();
- EXPECT_EQ(GetOverlay()->direction_, OverscrollNavigationOverlay::NONE);
+ EXPECT_EQ(GetOverlay()->direction_, NavigationDirection::NONE);
histogram_tester()->ExpectTotalCount(kUmaCancelled, 1);
histogram_tester()->ExpectBucketCount(kUmaCancelled, BACK_TOUCHPAD, 1);
EXPECT_EQ(1, action_tester()->GetActionCount(kActionCancelledBack));
@@ -450,7 +450,7 @@ TEST_F(OverscrollNavigationOverlayTest, CloseDuringAnimation) {
GetOverlay()->owa_->OnOverscrollModeChange(OVERSCROLL_NONE, OVERSCROLL_EAST,
OverscrollSource::TOUCHSCREEN);
GetOverlay()->owa_->OnOverscrollComplete(OVERSCROLL_EAST);
- EXPECT_EQ(GetOverlay()->direction_, OverscrollNavigationOverlay::BACK);
+ EXPECT_EQ(GetOverlay()->direction_, NavigationDirection::BACK);
OverscrollTestWebContents* test_web_contents =
static_cast<OverscrollTestWebContents*>(web_contents());
test_web_contents->set_is_being_destroyed(true);
diff --git a/chromium/content/browser/web_contents/aura/overscroll_window_animation.cc b/chromium/content/browser/web_contents/aura/overscroll_window_animation.cc
index d3246764e2c..1508bfe4c79 100644
--- a/chromium/content/browser/web_contents/aura/overscroll_window_animation.cc
+++ b/chromium/content/browser/web_contents/aura/overscroll_window_animation.cc
@@ -49,17 +49,13 @@ void OverscrollWindowAnimation::CancelSlide() {
float OverscrollWindowAnimation::GetTranslationForOverscroll(float delta_x) {
DCHECK(direction_ != SLIDE_NONE);
- const float bounds_width = GetVisibleSize().width();
+ const float bounds_width = GetContentSize().width();
if (direction_ == SLIDE_FRONT)
return std::max(-bounds_width, delta_x);
else
return std::min(bounds_width, delta_x);
}
-gfx::Size OverscrollWindowAnimation::GetVisibleSize() const {
- return delegate_->GetMainWindow()->bounds().size();
-}
-
gfx::Size OverscrollWindowAnimation::GetDisplaySize() const {
return display::Screen::GetScreen()
->GetDisplayNearestView(delegate_->GetMainWindow())
@@ -108,7 +104,7 @@ void OverscrollWindowAnimation::OnOverscrollModeChange(
slide_window_->layer()->GetAnimator()->StopAnimating();
delegate_->GetMainWindow()->layer()->GetAnimator()->StopAnimating();
}
- gfx::Rect slide_window_bounds(GetVisibleSize());
+ gfx::Rect slide_window_bounds(GetContentSize());
if (new_direction == SLIDE_FRONT) {
slide_window_bounds.Offset(base::i18n::IsRTL()
? -slide_window_bounds.width()
@@ -145,7 +141,7 @@ void OverscrollWindowAnimation::OnOverscrollComplete(
if (!is_active())
return;
delegate_->OnOverscrollCompleting();
- int content_width = GetVisibleSize().width();
+ int content_width = GetContentSize().width();
float translate_x;
if ((base::i18n::IsRTL() && direction_ == SLIDE_FRONT) ||
(!base::i18n::IsRTL() && direction_ == SLIDE_BACK)) {
@@ -191,4 +187,8 @@ ui::Layer* OverscrollWindowAnimation::GetBackLayer() const {
return delegate_->GetMainWindow()->layer();
}
+gfx::Size OverscrollWindowAnimation::GetContentSize() const {
+ return delegate_->GetMainWindow()->bounds().size();
+}
+
} // namespace content
diff --git a/chromium/content/browser/web_contents/aura/overscroll_window_animation.h b/chromium/content/browser/web_contents/aura/overscroll_window_animation.h
index 1f72bb8941e..84066f39acd 100644
--- a/chromium/content/browser/web_contents/aura/overscroll_window_animation.h
+++ b/chromium/content/browser/web_contents/aura/overscroll_window_animation.h
@@ -84,7 +84,6 @@ class CONTENT_EXPORT OverscrollWindowAnimation
}
// OverscrollControllerDelegate:
- gfx::Size GetVisibleSize() const override;
gfx::Size GetDisplaySize() const override;
bool OnOverscrollUpdate(float delta_x, float delta_y) override;
void OnOverscrollComplete(OverscrollMode overscroll_mode) override;
@@ -112,6 +111,9 @@ class CONTENT_EXPORT OverscrollWindowAnimation
ui::Layer* GetFrontLayer() const;
ui::Layer* GetBackLayer() const;
+ // Returns the size of the content window.
+ gfx::Size GetContentSize() const;
+
// ui::ImplicitAnimationObserver:
void OnImplicitAnimationsCompleted() override;
diff --git a/chromium/content/browser/web_contents/aura/overscroll_window_delegate.cc b/chromium/content/browser/web_contents/aura/overscroll_window_delegate.cc
index ac5753d147a..5f910bc4d6c 100644
--- a/chromium/content/browser/web_contents/aura/overscroll_window_delegate.cc
+++ b/chromium/content/browser/web_contents/aura/overscroll_window_delegate.cc
@@ -40,7 +40,6 @@ void OverscrollWindowDelegate::StartOverscroll(OverscrollSource source) {
overscroll_mode_ = OVERSCROLL_EAST;
else
overscroll_mode_ = OVERSCROLL_WEST;
- overscroll_source_ = source;
delegate_->OnOverscrollModeChange(old_mode, overscroll_mode_, source);
}
@@ -50,17 +49,13 @@ void OverscrollWindowDelegate::ResetOverscroll() {
delegate_->OnOverscrollModeChange(overscroll_mode_, OVERSCROLL_NONE,
OverscrollSource::NONE);
overscroll_mode_ = OVERSCROLL_NONE;
- overscroll_source_ = OverscrollSource::NONE;
delta_x_ = 0;
}
void OverscrollWindowDelegate::CompleteOrResetOverscroll() {
if (overscroll_mode_ == OVERSCROLL_NONE)
return;
- int width = overscroll_source_ == OverscrollSource::TOUCHPAD
- ? delegate_->GetDisplaySize().width()
- : delegate_->GetVisibleSize().width();
- float ratio = (fabs(delta_x_)) / width;
+ float ratio = (fabs(delta_x_)) / delegate_->GetDisplaySize().width();
if (ratio < complete_threshold_ratio_) {
ResetOverscroll();
return;
diff --git a/chromium/content/browser/web_contents/aura/overscroll_window_delegate.h b/chromium/content/browser/web_contents/aura/overscroll_window_delegate.h
index 251daac83fc..f267b851277 100644
--- a/chromium/content/browser/web_contents/aura/overscroll_window_delegate.h
+++ b/chromium/content/browser/web_contents/aura/overscroll_window_delegate.h
@@ -52,9 +52,6 @@ class CONTENT_EXPORT OverscrollWindowDelegate
// The current overscroll mode.
OverscrollMode overscroll_mode_;
- // The current overscroll source.
- OverscrollSource overscroll_source_;
-
// The latest delta_x scroll update.
float delta_x_;
diff --git a/chromium/content/browser/web_contents/aura/overscroll_window_delegate_unittest.cc b/chromium/content/browser/web_contents/aura/overscroll_window_delegate_unittest.cc
index b94a12e6166..683a6cb1a3e 100644
--- a/chromium/content/browser/web_contents/aura/overscroll_window_delegate_unittest.cc
+++ b/chromium/content/browser/web_contents/aura/overscroll_window_delegate_unittest.cc
@@ -29,7 +29,6 @@ class OverscrollWindowDelegateTest : public aura::test::AuraTestBase,
overscroll_started_(false),
mode_changed_(false),
current_mode_(OVERSCROLL_NONE),
- current_source_(OverscrollSource::NONE),
touch_start_threshold_(content::GetOverscrollConfig(
content::OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START_TOUCHSCREEN)),
touch_complete_threshold_(content::GetOverscrollConfig(
@@ -42,7 +41,6 @@ class OverscrollWindowDelegateTest : public aura::test::AuraTestBase,
overscroll_started_ = false;
mode_changed_ = false;
current_mode_ = OVERSCROLL_NONE;
- current_source_ = OverscrollSource::NONE;
window_.reset(CreateNormalWindow(
0, root_window(), new OverscrollWindowDelegate(this, gfx::Image())));
window_->SetBounds(gfx::Rect(0, 0, kTestWindowWidth, kTestWindowWidth));
@@ -60,10 +58,7 @@ class OverscrollWindowDelegateTest : public aura::test::AuraTestBase,
float touch_start_threshold() { return touch_start_threshold_; }
float touch_complete_threshold() {
- const int width = current_source_ == OverscrollSource::TOUCHPAD
- ? kTestDisplayWidth
- : kTestWindowWidth;
- return width * touch_complete_threshold_;
+ return kTestDisplayWidth * touch_complete_threshold_;
}
protected:
@@ -82,10 +77,6 @@ class OverscrollWindowDelegateTest : public aura::test::AuraTestBase,
private:
// OverscrollControllerDelegate:
- gfx::Size GetVisibleSize() const override {
- return gfx::Size(kTestWindowWidth, kTestWindowWidth);
- }
-
gfx::Size GetDisplaySize() const override {
return gfx::Size(kTestDisplayWidth, kTestDisplayWidth);
}
@@ -103,7 +94,6 @@ class OverscrollWindowDelegateTest : public aura::test::AuraTestBase,
OverscrollSource source) override {
mode_changed_ = true;
current_mode_ = new_mode;
- current_source_ = source;
if (current_mode_ != OVERSCROLL_NONE)
overscroll_started_ = true;
}
@@ -120,7 +110,6 @@ class OverscrollWindowDelegateTest : public aura::test::AuraTestBase,
bool overscroll_started_;
bool mode_changed_;
OverscrollMode current_mode_;
- OverscrollSource current_source_;
// Config defined constants.
const float touch_start_threshold_;
diff --git a/chromium/content/browser/web_contents/aura/types.cc b/chromium/content/browser/web_contents/aura/types.cc
new file mode 100644
index 00000000000..73bcf2b1d96
--- /dev/null
+++ b/chromium/content/browser/web_contents/aura/types.cc
@@ -0,0 +1,31 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/web_contents/aura/types.h"
+
+namespace content {
+
+UmaNavigationType GetUmaNavigationType(NavigationDirection direction,
+ OverscrollSource source) {
+ if (direction == NavigationDirection::NONE ||
+ source == OverscrollSource::NONE) {
+ return NAVIGATION_TYPE_NONE;
+ }
+ if (direction == NavigationDirection::BACK) {
+ return source == OverscrollSource::TOUCHPAD
+ ? UmaNavigationType::BACK_TOUCHPAD
+ : UmaNavigationType::BACK_TOUCHSCREEN;
+ }
+ if (direction == NavigationDirection::FORWARD) {
+ return source == OverscrollSource::TOUCHPAD
+ ? UmaNavigationType::FORWARD_TOUCHPAD
+ : UmaNavigationType::FORWARD_TOUCHSCREEN;
+ }
+ DCHECK_EQ(direction, NavigationDirection::RELOAD);
+ return source == OverscrollSource::TOUCHPAD
+ ? UmaNavigationType::RELOAD_TOUCHPAD
+ : UmaNavigationType::RELOAD_TOUCHSCREEN;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/web_contents/aura/types.h b/chromium/content/browser/web_contents/aura/types.h
new file mode 100644
index 00000000000..7f593d5feb6
--- /dev/null
+++ b/chromium/content/browser/web_contents/aura/types.h
@@ -0,0 +1,38 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_WEB_CONTENTS_AURA_TYPES_H_
+#define CONTENT_BROWSER_WEB_CONTENTS_AURA_TYPES_H_
+
+#include "content/browser/renderer_host/overscroll_controller.h"
+
+namespace content {
+
+enum class NavigationDirection {
+ NONE,
+ FORWARD,
+ BACK,
+ RELOAD,
+ NAVIGATION_COUNT,
+};
+
+// Note that this enum is used to back an UMA histogram, so it should be
+// treated as append-only.
+enum UmaNavigationType {
+ NAVIGATION_TYPE_NONE,
+ FORWARD_TOUCHPAD,
+ BACK_TOUCHPAD,
+ FORWARD_TOUCHSCREEN,
+ BACK_TOUCHSCREEN,
+ RELOAD_TOUCHPAD,
+ RELOAD_TOUCHSCREEN,
+ NAVIGATION_TYPE_COUNT,
+};
+
+UmaNavigationType GetUmaNavigationType(NavigationDirection direction,
+ OverscrollSource source);
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_WEB_CONTENTS_AURA_TYPES_H_
diff --git a/chromium/content/browser/web_contents/aura/uma_navigation_type.h b/chromium/content/browser/web_contents/aura/uma_navigation_type.h
deleted file mode 100644
index 53294b9d919..00000000000
--- a/chromium/content/browser/web_contents/aura/uma_navigation_type.h
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-namespace content {
-
-// Note that this enum is used to back an UMA histogram, so it should be
-// treated as append-only.
-enum UmaNavigationType {
- NAVIGATION_TYPE_NONE,
- FORWARD_TOUCHPAD,
- BACK_TOUCHPAD,
- FORWARD_TOUCHSCREEN,
- BACK_TOUCHSCREEN,
- NAVIGATION_TYPE_COUNT,
-};
-
-} // namespace content
diff --git a/chromium/content/browser/web_contents/web_contents_android.cc b/chromium/content/browser/web_contents/web_contents_android.cc
index 193df403bc3..f45cf9a7a94 100644
--- a/chromium/content/browser/web_contents/web_contents_android.cc
+++ b/chromium/content/browser/web_contents/web_contents_android.cc
@@ -181,11 +181,6 @@ ScopedJavaLocalRef<jobject> FromNativePtr(JNIEnv* env,
return web_contents_android->GetJavaObject();
}
-// static
-bool WebContentsAndroid::Register(JNIEnv* env) {
- return RegisterNativesImpl(env);
-}
-
WebContentsAndroid::WebContentsAndroid(WebContentsImpl* web_contents)
: web_contents_(web_contents),
navigation_controller_(&(web_contents->GetController())),
@@ -343,6 +338,13 @@ void WebContentsAndroid::OnShow(JNIEnv* env, const JavaParamRef<jobject>& obj) {
web_contents_->WasShown();
}
+void WebContentsAndroid::SetImportance(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj,
+ jint importance) {
+ web_contents_->SetImportance(static_cast<ChildProcessImportance>(importance));
+}
+
void WebContentsAndroid::SuspendAllMediaPlayers(
JNIEnv* env,
const JavaParamRef<jobject>& jobj) {
@@ -664,22 +666,14 @@ bool WebContentsAndroid::HasActiveEffectivelyFullscreenVideo(
}
base::android::ScopedJavaLocalRef<jobject>
-WebContentsAndroid::GetCurrentlyPlayingVideoSizes(
+WebContentsAndroid::GetFullscreenVideoSize(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj) {
- const WebContents::VideoSizeMap& sizes =
- web_contents_->GetCurrentlyPlayingVideoSizes();
- DCHECK_GT(sizes.size(), 0u);
-
- ScopedJavaLocalRef<jobject> jsizes = Java_WebContentsImpl_createSizeList(env);
-
- using MapEntry = std::pair<WebContentsObserver::MediaPlayerId, gfx::Size>;
- for (const MapEntry& entry : sizes) {
- Java_WebContentsImpl_createSizeAndAddToList(
- env, jsizes, entry.second.width(), entry.second.height());
- }
+ if (!web_contents_->GetFullscreenVideoSize())
+ return ScopedJavaLocalRef<jobject>(); // Return null.
- return jsizes;
+ gfx::Size size = web_contents_->GetFullscreenVideoSize().value();
+ return Java_WebContentsImpl_createSize(env, size.width(), size.height());
}
ScopedJavaLocalRef<jobject> WebContentsAndroid::GetOrCreateEventForwarder(
diff --git a/chromium/content/browser/web_contents/web_contents_android.h b/chromium/content/browser/web_contents/web_contents_android.h
index f18a3b819bd..b206ce4f3aa 100644
--- a/chromium/content/browser/web_contents/web_contents_android.h
+++ b/chromium/content/browser/web_contents/web_contents_android.h
@@ -31,8 +31,6 @@ class WebContentsImpl;
class CONTENT_EXPORT WebContentsAndroid
: public base::SupportsUserData::Data {
public:
- static bool Register(JNIEnv* env);
-
explicit WebContentsAndroid(WebContentsImpl* web_contents);
~WebContentsAndroid() override;
@@ -86,6 +84,9 @@ class CONTENT_EXPORT WebContentsAndroid
void OnHide(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
void OnShow(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
+ void SetImportance(JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj,
+ jint importance);
void SuspendAllMediaPlayers(JNIEnv* env,
const base::android::JavaParamRef<jobject>& jobj);
void SetAudioMuted(JNIEnv* env,
@@ -208,7 +209,7 @@ class CONTENT_EXPORT WebContentsAndroid
bool HasActiveEffectivelyFullscreenVideo(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj);
- base::android::ScopedJavaLocalRef<jobject> GetCurrentlyPlayingVideoSizes(
+ base::android::ScopedJavaLocalRef<jobject> GetFullscreenVideoSize(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj);
diff --git a/chromium/content/browser/web_contents/web_contents_impl.cc b/chromium/content/browser/web_contents/web_contents_impl.cc
index d927e85156e..b46cec9804d 100644
--- a/chromium/content/browser/web_contents/web_contents_impl.cc
+++ b/chromium/content/browser/web_contents/web_contents_impl.cc
@@ -33,7 +33,6 @@
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
-#include "components/mime_util/mime_util.h"
#include "components/rappor/public/rappor_utils.h"
#include "components/url_formatter/url_formatter.h"
#include "content/browser/accessibility/browser_accessibility_state_impl.h"
@@ -41,6 +40,7 @@
#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"
+#include "content/browser/devtools/protocol/page_handler.h"
#include "content/browser/devtools/render_frame_devtools_agent_host.h"
#include "content/browser/dom_storage/dom_storage_context_wrapper.h"
#include "content/browser/dom_storage/session_storage_namespace_impl.h"
@@ -56,7 +56,6 @@
#include "content/browser/frame_host/navigator_impl.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/frame_host/render_frame_proxy_host.h"
-#include "content/browser/frame_host/render_widget_host_view_child_frame.h"
#include "content/browser/loader/loader_io_thread_notifier.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/manifest/manifest_manager_host.h"
@@ -71,6 +70,7 @@
#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/renderer_host/render_widget_host_view_child_frame.h"
#include "content/browser/renderer_host/text_input_manager.h"
#include "content/browser/screen_orientation/screen_orientation_provider.h"
#include "content/browser/site_instance_impl.h"
@@ -131,6 +131,7 @@
#include "ppapi/features/features.h"
#include "services/metrics/public/cpp/ukm_recorder.h"
#include "services/service_manager/public/cpp/interface_provider.h"
+#include "third_party/WebKit/common/mime_util/mime_util.h"
#include "third_party/WebKit/public/platform/WebSecurityStyle.h"
#include "third_party/WebKit/public/web/WebSandboxFlags.h"
#include "third_party/skia/include/core/SkBitmap.h"
@@ -278,6 +279,30 @@ FrameTreeNode* FindOpener(const WebContents::CreateParams& params) {
return opener_node;
}
+// Ensures that OnDialogClosed is only called once.
+class CloseDialogCallbackWrapper
+ : public base::RefCountedThreadSafe<CloseDialogCallbackWrapper> {
+ public:
+ CloseDialogCallbackWrapper(
+ const base::Callback<void(bool, bool, const base::string16&)> callback)
+ : callback_(callback) {}
+
+ void Run(bool dialog_was_suppressed,
+ bool success,
+ const base::string16& user_input) {
+ if (already_fired_)
+ return;
+ already_fired_ = true;
+ callback_.Run(dialog_was_suppressed, success, user_input);
+ }
+
+ private:
+ friend class base::RefCountedThreadSafe<CloseDialogCallbackWrapper>;
+ ~CloseDialogCallbackWrapper() {}
+ bool already_fired_ = false;
+ base::Callback<void(bool, bool, const base::string16&)> callback_;
+};
+
} // namespace
WebContents* WebContents::Create(const WebContents::CreateParams& params) {
@@ -494,6 +519,7 @@ WebContentsImpl::WebContentsImpl(BrowserContext* browser_context)
did_first_visually_non_empty_paint_(false),
capturer_count_(0),
should_normally_be_visible_(true),
+ should_normally_be_occluded_(false),
did_first_set_visible_(false),
is_being_destroyed_(false),
is_notifying_observers_(false),
@@ -753,8 +779,9 @@ bool WebContentsImpl::OnMessageReceived(RenderViewHostImpl* render_view_host,
}
for (auto& observer : observers_) {
- // TODO(nick, creis): Replace all uses of this variant of OnMessageReceived
- // with the version that takes a RenderFrameHost, and delete it.
+ // TODO(nick, creis): https://crbug.com/758026: Replace all uses of this
+ // variant of OnMessageReceived with the version that takes a
+ // RenderFrameHost, and then delete it.
if (observer.OnMessageReceived(message))
return true;
}
@@ -1025,7 +1052,7 @@ SkColor WebContentsImpl::GetThemeColor() const {
return theme_color_;
}
-void WebContentsImpl::SetAccessibilityMode(AccessibilityMode mode) {
+void WebContentsImpl::SetAccessibilityMode(ui::AXMode mode) {
if (mode == accessibility_mode_)
return;
@@ -1045,8 +1072,8 @@ void WebContentsImpl::SetAccessibilityMode(AccessibilityMode mode) {
}
}
-void WebContentsImpl::AddAccessibilityMode(AccessibilityMode mode) {
- AccessibilityMode new_mode(accessibility_mode_);
+void WebContentsImpl::AddAccessibilityMode(ui::AXMode mode) {
+ ui::AXMode new_mode(accessibility_mode_);
new_mode |= mode;
SetAccessibilityMode(new_mode);
}
@@ -1204,16 +1231,16 @@ void WebContentsImpl::EnableWebContentsOnlyAccessibilityMode() {
for (RenderFrameHost* rfh : GetAllFrames())
ResetAccessibility(rfh);
} else {
- AddAccessibilityMode(kAccessibilityModeWebContentsOnly);
+ AddAccessibilityMode(ui::kAXModeWebContentsOnly);
}
}
bool WebContentsImpl::IsWebContentsOnlyAccessibilityModeForTesting() const {
- return accessibility_mode_ == kAccessibilityModeWebContentsOnly;
+ return accessibility_mode_ == ui::kAXModeWebContentsOnly;
}
bool WebContentsImpl::IsFullAccessibilityModeForTesting() const {
- return accessibility_mode_ == kAccessibilityModeComplete;
+ return accessibility_mode_ == ui::kAXModeComplete;
}
const PageImportanceSignals& WebContentsImpl::GetPageImportanceSignals() const {
@@ -1333,7 +1360,7 @@ void WebContentsImpl::IncrementCapturerCount(const gfx::Size& capture_size) {
}
// Ensure that all views are un-occluded before capture begins.
- WasUnOccluded();
+ DoWasUnOccluded();
}
void WebContentsImpl::DecrementCapturerCount() {
@@ -1349,11 +1376,14 @@ void WebContentsImpl::DecrementCapturerCount() {
const gfx::Size old_size = preferred_size_for_capture_;
preferred_size_for_capture_ = gfx::Size();
OnPreferredSizeChanged(old_size);
- }
- if (IsHidden()) {
- DVLOG(1) << "Executing delayed WasHidden().";
- WasHidden();
+ if (IsHidden()) {
+ DVLOG(1) << "Executing delayed WasHidden().";
+ WasHidden();
+ }
+
+ if (should_normally_be_occluded_)
+ WasOccluded();
}
}
@@ -1384,7 +1414,12 @@ void WebContentsImpl::SetAudioMuted(bool mute) {
for (auto& observer : observers_)
observer.DidUpdateAudioMutingState(mute);
- OnAudioStateChanged(!mute && audio_stream_monitor_.IsCurrentlyAudible());
+ // Notification for UI updates in response to the changed muting state.
+ NotifyNavigationStateChanged(INVALIDATE_TYPE_TAB);
+}
+
+bool WebContentsImpl::IsCurrentlyAudible() {
+ return audio_stream_monitor()->IsCurrentlyAudible();
}
bool WebContentsImpl::IsConnectedToBluetoothDevice() const {
@@ -1448,6 +1483,9 @@ void WebContentsImpl::OnAudioStateChanged(bool is_audible) {
// Notification for UI updates in response to the changed audio state.
NotifyNavigationStateChanged(INVALIDATE_TYPE_TAB);
+
+ if (delegate_)
+ delegate_->OnAudioStateChanged(is_audible);
}
base::TimeTicks WebContentsImpl::GetLastActiveTime() const {
@@ -1465,13 +1503,16 @@ base::TimeTicks WebContentsImpl::GetLastHiddenTime() const {
void WebContentsImpl::WasShown() {
controller_.SetActive(true);
- for (RenderWidgetHostView* view : GetRenderWidgetHostViewsInTree()) {
+ if (auto* view = GetRenderWidgetHostView()) {
view->Show();
#if defined(OS_MACOSX)
view->SetActive(true);
#endif
}
+ if (!ShowingInterstitialPage())
+ SetVisibilityForChildViews(true);
+
SendPageMessage(new PageMsg_WasShown(MSG_ROUTING_NONE));
last_active_time_ = base::TimeTicks::Now();
@@ -1492,9 +1533,12 @@ void WebContentsImpl::WasHidden() {
// removes the |GetRenderViewHost()|; then when we actually destroy the
// window, OnWindowPosChanged() notices and calls WasHidden() (which
// calls us).
- for (RenderWidgetHostView* view : GetRenderWidgetHostViewsInTree())
+ if (auto* view = GetRenderWidgetHostView())
view->Hide();
+ if (!ShowingInterstitialPage())
+ SetVisibilityForChildViews(true);
+
SendPageMessage(new PageMsg_WasHidden(MSG_ROUTING_NONE));
}
@@ -1506,19 +1550,49 @@ void WebContentsImpl::WasHidden() {
should_normally_be_visible_ = false;
}
+#if defined(OS_ANDROID)
+void WebContentsImpl::SetImportance(ChildProcessImportance importance) {
+ // Not calling GetRenderWidgetHostView since importance should be set on both
+ // the interstitial and underlying page.
+ std::set<RenderWidgetHostImpl*> set;
+ if (ShowingInterstitialPage()) {
+ set.insert(
+ static_cast<RenderFrameHostImpl*>(interstitial_page_->GetMainFrame())
+ ->GetRenderWidgetHost());
+ }
+ for (RenderFrameHost* rfh : GetAllFrames())
+ set.insert(static_cast<RenderFrameHostImpl*>(rfh)->GetRenderWidgetHost());
+ for (RenderWidgetHostImpl* host : set) {
+ DCHECK(host);
+ host->SetImportance(importance);
+ }
+ // TODO(boliu): If this is ever used on platforms other than Android, make
+ // sure to also update inner WebContents.
+}
+#endif
+
bool WebContentsImpl::IsVisible() const {
return should_normally_be_visible_;
}
void WebContentsImpl::WasOccluded() {
- if (capturer_count_ > 0)
- return;
+ if (capturer_count_ == 0) {
+ for (RenderWidgetHostView* view : GetRenderWidgetHostViewsInTree())
+ view->WasOccluded();
+ }
- for (RenderWidgetHostView* view : GetRenderWidgetHostViewsInTree())
- view->WasOccluded();
+ should_normally_be_occluded_ = true;
}
void WebContentsImpl::WasUnOccluded() {
+ if (capturer_count_ == 0)
+ DoWasUnOccluded();
+
+ should_normally_be_occluded_ = false;
+}
+
+void WebContentsImpl::DoWasUnOccluded() {
+ // TODO(fdoray): Only call WasUnOccluded on frames in the active viewport.
for (RenderWidgetHostView* view : GetRenderWidgetHostViewsInTree())
view->WasUnOccluded();
}
@@ -1689,10 +1763,9 @@ void WebContentsImpl::Init(const WebContents::CreateParams& params) {
site_instance->GetProcess()->GetNextRoutingID();
}
- GetRenderManager()->Init(site_instance.get(), view_routing_id,
- params.main_frame_routing_id,
- main_frame_widget_routing_id,
- params.renderer_initiated_creation);
+ GetRenderManager()->Init(
+ site_instance.get(), view_routing_id, params.main_frame_routing_id,
+ main_frame_widget_routing_id, params.renderer_initiated_creation);
// blink::FrameTree::setName always keeps |unique_name| empty in case of a
// main frame - let's do the same thing here.
@@ -1978,9 +2051,6 @@ void WebContentsImpl::ReplicatePageFocus(bool is_focused) {
RenderWidgetHostImpl* WebContentsImpl::GetFocusedRenderWidgetHost(
RenderWidgetHostImpl* receiving_widget) {
- if (!SiteIsolationPolicy::AreCrossProcessFramesPossible())
- return receiving_widget;
-
// Events for widgets other than the main frame (e.g., popup menus) should be
// forwarded directly to the widget they arrived on.
if (receiving_widget != GetMainFrame()->GetRenderWidgetHost())
@@ -2335,6 +2405,11 @@ void WebContentsImpl::CreateNewWindow(
}
}
+ // Any new WebContents opened while this WebContents is in fullscreen can be
+ // used to confuse the user, so drop fullscreen.
+ if (IsFullscreenForCurrentTab())
+ ExitFullscreen(true);
+
if (params.opener_suppressed) {
// When the opener is suppressed, the original renderer cannot access the
// new window. As a result, we need to show and navigate the window here.
@@ -2404,8 +2479,8 @@ void WebContentsImpl::CreateNewWidget(int32_t render_process_id,
return;
}
- RenderWidgetHostImpl* widget_host =
- new RenderWidgetHostImpl(this, process, route_id, IsHidden());
+ RenderWidgetHostImpl* widget_host = new RenderWidgetHostImpl(
+ this, process, route_id, std::move(widget), IsHidden());
RenderWidgetHostViewBase* widget_view =
static_cast<RenderWidgetHostViewBase*>(
@@ -2630,7 +2705,7 @@ bool WebContentsImpl::ShouldIgnoreUnresponsiveRenderer() {
return DevToolsAgentHost::IsDebuggerAttached(this);
}
-AccessibilityMode WebContentsImpl::GetAccessibilityMode() const {
+ui::AXMode WebContentsImpl::GetAccessibilityMode() const {
return accessibility_mode_;
}
@@ -2722,6 +2797,15 @@ void WebContentsImpl::OnMoveValidationMessage(
delegate_->MoveValidationMessage(this, anchor_in_root_view);
}
+void WebContentsImpl::SetNotWaitingForResponse() {
+ if (waiting_for_response_ == false)
+ return;
+
+ waiting_for_response_ = false;
+ if (delegate_)
+ delegate_->LoadingStateChanged(this, is_load_to_different_document_);
+}
+
void WebContentsImpl::SendScreenRects() {
for (FrameTreeNode* node : frame_tree_.Nodes()) {
if (node->current_frame_host()->is_local_root())
@@ -2924,6 +3008,13 @@ void WebContentsImpl::AttachInterstitialPage(
GetRenderManager()->SetRWHViewForInnerContents(view);
}
}
+
+#if defined(OS_ANDROID)
+ // Update importance of the interstitial.
+ static_cast<RenderFrameHostImpl*>(interstitial_page_->GetMainFrame())
+ ->GetRenderWidgetHost()
+ ->SetImportance(GetMainFrame()->GetRenderWidgetHost()->importance());
+#endif
}
void WebContentsImpl::DidProceedOnInterstitial() {
@@ -3204,7 +3295,7 @@ bool WebContentsImpl::IsSavable() {
contents_mime_type_ == "application/xhtml+xml" ||
contents_mime_type_ == "text/plain" ||
contents_mime_type_ == "text/css" ||
- mime_util::IsSupportedJavascriptMimeType(contents_mime_type_);
+ blink::IsSupportedJavascriptMimeType(contents_mime_type_);
}
void WebContentsImpl::OnSavePage() {
@@ -3278,7 +3369,7 @@ void WebContentsImpl::SaveFrameWithHeaders(const GURL& url,
destination: WEBSITE
}
policy {
- cookies_allowed: true
+ cookies_allowed: YES
cookies_store: "user"
setting:
"This feature cannot be disabled by settings, but it's is only "
@@ -3370,6 +3461,7 @@ void WebContentsImpl::LoadStateChanged(
void WebContentsImpl::DidGetResourceResponseStart(
const ResourceRequestDetails& details) {
+ SetNotWaitingForResponse();
controller_.ssl_manager()->DidStartResourceResponse(
details.url, details.has_certificate, details.ssl_cert_status);
@@ -3381,12 +3473,6 @@ void WebContentsImpl::DidGetRedirectForResourceRequest(
const ResourceRedirectDetails& details) {
for (auto& observer : observers_)
observer.DidGetRedirectForResourceRequest(details);
-
- // TODO(avi): Remove. http://crbug.com/170921
- NotificationService::current()->Notify(
- NOTIFICATION_RESOURCE_RECEIVED_REDIRECT,
- Source<WebContents>(this),
- Details<const ResourceRedirectDetails>(&details));
}
void WebContentsImpl::NotifyWebContentsFocused(
@@ -3694,11 +3780,9 @@ void WebContentsImpl::DidFailLoadWithError(
RenderFrameHostImpl* render_frame_host,
const GURL& url,
int error_code,
- const base::string16& error_description,
- bool was_ignored_by_handler) {
+ const base::string16& error_description) {
for (auto& observer : observers_) {
- observer.DidFailLoad(render_frame_host, url, error_code, error_description,
- was_ignored_by_handler);
+ observer.DidFailLoad(render_frame_host, url, error_code, error_description);
}
}
@@ -4414,6 +4498,19 @@ void WebContentsImpl::NotifyViewSwapped(RenderViewHost* old_host,
void WebContentsImpl::NotifyFrameSwapped(RenderFrameHost* old_host,
RenderFrameHost* new_host) {
+#if defined(OS_ANDROID)
+ // Try to copy importance from either |old_host| or parent of |new_host|.
+ // If both are null, then this is the very first frame host created from Init.
+ // There is no need to pass importance in this case because there is no chance
+ // for anything to call SetImportance yet.
+ RenderFrameHostImpl* importance_host = static_cast<RenderFrameHostImpl*>(
+ old_host ? old_host : new_host->GetParent());
+ if (importance_host) {
+ static_cast<RenderFrameHostImpl*>(new_host)
+ ->GetRenderWidgetHost()
+ ->SetImportance(importance_host->GetRenderWidgetHost()->importance());
+ }
+#endif
for (auto& observer : observers_)
observer.RenderFrameHostChanged(old_host, new_host);
}
@@ -4437,6 +4534,18 @@ void WebContentsImpl::NotifyNavigationEntryCommitted(
observer.NavigationEntryCommitted(load_details);
}
+void WebContentsImpl::NotifyNavigationEntryChanged(
+ const EntryChangedDetails& change_details) {
+ for (auto& observer : observers_)
+ observer.NavigationEntryChanged(change_details);
+}
+
+void WebContentsImpl::NotifyNavigationListPruned(
+ const PrunedDetails& pruned_details) {
+ for (auto& observer : observers_)
+ observer.NavigationListPruned(pruned_details);
+}
+
void WebContentsImpl::OnAssociatedInterfaceRequest(
RenderFrameHost* render_frame_host,
const std::string& interface_name,
@@ -4446,6 +4555,18 @@ void WebContentsImpl::OnAssociatedInterfaceRequest(
it->second->OnRequestForFrame(render_frame_host, std::move(handle));
}
+void WebContentsImpl::OnInterfaceRequest(
+ RenderFrameHost* render_frame_host,
+ const std::string& interface_name,
+ mojo::ScopedMessagePipeHandle* interface_pipe) {
+ for (auto& observer : observers_) {
+ observer.OnInterfaceRequestFromFrame(render_frame_host, interface_name,
+ interface_pipe);
+ if (!interface_pipe->is_valid())
+ break;
+ }
+}
+
const GURL& WebContentsImpl::GetMainFrameLastCommittedURL() const {
return GetLastCommittedURL();
}
@@ -4503,31 +4624,48 @@ void WebContentsImpl::RunJavaScriptDialog(RenderFrameHost* render_frame_host,
if (IsFullscreenForCurrentTab())
ExitFullscreen(true);
+ base::Callback<void(bool, bool, const base::string16&)> callback =
+ base::Bind(&WebContentsImpl::OnDialogClosed, base::Unretained(this),
+ render_frame_host->GetProcess()->GetID(),
+ render_frame_host->GetRoutingID(), reply_msg);
+
// Suppress JavaScript dialogs when requested. Also suppress messages when
// showing an interstitial as it's shown over the previous page and we don't
// want the hidden page's dialogs to interfere with the interstitial.
- bool suppress_this_message =
- ShowingInterstitialPage() || !delegate_ ||
- delegate_->ShouldSuppressDialogs(this) ||
- !delegate_->GetJavaScriptDialogManager(this);
-
- if (!suppress_this_message) {
- is_showing_javascript_dialog_ = true;
+ bool suppress_this_message = ShowingInterstitialPage() || !delegate_ ||
+ delegate_->ShouldSuppressDialogs(this);
+ if (delegate_)
dialog_manager_ = delegate_->GetJavaScriptDialogManager(this);
+
+ std::vector<protocol::PageHandler*> page_handlers =
+ protocol::PageHandler::EnabledForWebContents(this);
+
+ if (suppress_this_message || (!dialog_manager_ && !page_handlers.size())) {
+ callback.Run(true, false, base::string16());
+ return;
+ }
+
+ scoped_refptr<CloseDialogCallbackWrapper> wrapper =
+ new CloseDialogCallbackWrapper(callback);
+ callback = base::Bind(&CloseDialogCallbackWrapper::Run, wrapper);
+
+ is_showing_javascript_dialog_ = true;
+
+ for (auto* handler : page_handlers) {
+ handler->DidRunJavaScriptDialog(frame_url, message, default_prompt,
+ dialog_type, base::Bind(callback, false));
+ }
+
+ if (dialog_manager_) {
dialog_manager_->RunJavaScriptDialog(
this, frame_url, dialog_type, message, default_prompt,
- base::Bind(&WebContentsImpl::OnDialogClosed, base::Unretained(this),
- render_frame_host->GetProcess()->GetID(),
- render_frame_host->GetRoutingID(), reply_msg, false),
- &suppress_this_message);
+ base::Bind(callback, false), &suppress_this_message);
}
if (suppress_this_message) {
// If we are suppressing messages, just reply as if the user immediately
// pressed "Cancel", passing true to |dialog_was_suppressed|.
- OnDialogClosed(render_frame_host->GetProcess()->GetID(),
- render_frame_host->GetRoutingID(), reply_msg,
- true, false, base::string16());
+ callback.Run(true, false, base::string16());
}
}
@@ -4545,24 +4683,40 @@ void WebContentsImpl::RunBeforeUnloadConfirm(
if (delegate_)
delegate_->WillRunBeforeUnloadConfirm();
- bool suppress_this_message =
- !rfhi->is_active() ||
- ShowingInterstitialPage() || !delegate_ ||
- delegate_->ShouldSuppressDialogs(this) ||
- !delegate_->GetJavaScriptDialogManager(this);
- if (suppress_this_message) {
- rfhi->JavaScriptDialogClosed(reply_msg, true, base::string16());
+ base::Callback<void(bool, bool, const base::string16&)> callback =
+ base::Bind(&WebContentsImpl::OnDialogClosed, base::Unretained(this),
+ render_frame_host->GetProcess()->GetID(),
+ render_frame_host->GetRoutingID(), reply_msg);
+
+ bool suppress_this_message = !rfhi->is_active() ||
+ ShowingInterstitialPage() || !delegate_ ||
+ delegate_->ShouldSuppressDialogs(this);
+ if (delegate_)
+ dialog_manager_ = delegate_->GetJavaScriptDialogManager(this);
+
+ std::vector<protocol::PageHandler*> page_handlers =
+ protocol::PageHandler::EnabledForWebContents(this);
+
+ if (suppress_this_message || (!dialog_manager_ && !page_handlers.size())) {
+ callback.Run(false, true, base::string16());
return;
}
is_showing_before_unload_dialog_ = true;
- dialog_manager_ = delegate_->GetJavaScriptDialogManager(this);
- dialog_manager_->RunBeforeUnloadDialog(
- this, is_reload,
- base::Bind(&WebContentsImpl::OnDialogClosed, base::Unretained(this),
- render_frame_host->GetProcess()->GetID(),
- render_frame_host->GetRoutingID(), reply_msg,
- false));
+
+ scoped_refptr<CloseDialogCallbackWrapper> wrapper =
+ new CloseDialogCallbackWrapper(callback);
+ callback = base::Bind(&CloseDialogCallbackWrapper::Run, wrapper);
+
+ GURL frame_url = rfhi->GetLastCommittedURL();
+ for (auto* handler : page_handlers) {
+ handler->DidRunBeforeUnloadConfirm(frame_url, base::Bind(callback, false));
+ }
+
+ if (dialog_manager_) {
+ dialog_manager_->RunBeforeUnloadDialog(this, is_reload,
+ base::Bind(callback, false));
+ }
}
void WebContentsImpl::RunFileChooser(RenderFrameHost* render_frame_host,
@@ -5543,6 +5697,12 @@ void WebContentsImpl::OnDialogClosed(int render_process_id,
if (rfh) {
rfh->JavaScriptDialogClosed(reply_msg, success, user_input);
+
+ std::vector<protocol::PageHandler*> page_handlers =
+ protocol::PageHandler::EnabledForWebContents(this);
+ for (auto* handler : page_handlers)
+ handler->DidCloseJavaScriptDialog(success, user_input);
+
} else {
// Don't leak the sync IPC reply if the RFH or process is gone.
delete reply_msg;
@@ -5767,9 +5927,12 @@ void WebContentsImpl::MediaResized(
observer.MediaResized(size, id);
}
-const WebContents::VideoSizeMap&
-WebContentsImpl::GetCurrentlyPlayingVideoSizes() {
- return cached_video_sizes_;
+base::Optional<gfx::Size> WebContentsImpl::GetFullscreenVideoSize() {
+ base::Optional<WebContentsObserver::MediaPlayerId> id =
+ media_web_contents_observer_->GetFullscreenVideoMediaPlayerId();
+ if (id && cached_video_sizes_.count(id.value()))
+ return base::Optional<gfx::Size>(cached_video_sizes_[id.value()]);
+ return base::Optional<gfx::Size>();
}
int WebContentsImpl::GetCurrentlyPlayingVideoCount() {
@@ -5932,4 +6095,8 @@ void WebContentsImpl::MediaMutedStatusChanged(
observer.MediaMutedStatusChanged(id, muted);
}
+void WebContentsImpl::SetVisibilityForChildViews(bool visible) {
+ GetMainFrame()->SetVisibilityForChildViews(visible);
+}
+
} // namespace content
diff --git a/chromium/content/browser/web_contents/web_contents_impl.h b/chromium/content/browser/web_contents/web_contents_impl.h
index 65a6fa4b26a..8484f67bdbe 100644
--- a/chromium/content/browser/web_contents/web_contents_impl.h
+++ b/chromium/content/browser/web_contents/web_contents_impl.h
@@ -32,7 +32,6 @@
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_delegate.h"
#include "content/browser/wake_lock/wake_lock_context_host.h"
-#include "content/common/accessibility_mode.h"
#include "content/common/content_export.h"
#include "content/public/browser/color_chooser.h"
#include "content/public/browser/download_url_parameters.h"
@@ -51,12 +50,14 @@
#include "services/device/public/interfaces/wake_lock.mojom.h"
#include "services/metrics/public/cpp/ukm_recorder.h"
#include "third_party/WebKit/public/platform/WebDragOperation.h"
+#include "ui/accessibility/ax_modes.h"
#include "ui/base/page_transition_types.h"
#include "ui/gfx/geometry/rect_f.h"
#include "ui/gfx/geometry/size.h"
#if defined(OS_ANDROID)
#include "content/browser/android/nfc_host.h"
+#include "content/public/browser/android/child_process_importance.h"
#endif
struct ViewHostMsg_DateTimeDialogValue_Params;
@@ -119,15 +120,14 @@ WebContentsView* CreateWebContentsView(
WebContentsViewDelegate* delegate,
RenderViewHostDelegateView** render_view_host_delegate_view);
-class CONTENT_EXPORT WebContentsImpl
- : public NON_EXPORTED_BASE(WebContents),
- public NON_EXPORTED_BASE(RenderFrameHostDelegate),
- public RenderViewHostDelegate,
- public RenderWidgetHostDelegate,
- public RenderFrameHostManager::Delegate,
- public NotificationObserver,
- public NON_EXPORTED_BASE(NavigationControllerDelegate),
- public NON_EXPORTED_BASE(NavigatorDelegate) {
+class CONTENT_EXPORT WebContentsImpl : public WebContents,
+ public RenderFrameHostDelegate,
+ public RenderViewHostDelegate,
+ public RenderWidgetHostDelegate,
+ public RenderFrameHostManager::Delegate,
+ public NotificationObserver,
+ public NavigationControllerDelegate,
+ public NavigatorDelegate {
public:
class FriendWrapper;
@@ -232,18 +232,12 @@ class CONTENT_EXPORT WebContentsImpl
bool should_normally_be_visible() { return should_normally_be_visible_; }
- // Indicate if the window has been occluded, and pass this to the views, only
- // if there is no active capture going on (otherwise it is dropped on the
- // floor).
- void WasOccluded();
- void WasUnOccluded();
-
// Broadcasts the mode change to all frames.
- void SetAccessibilityMode(AccessibilityMode mode);
+ void SetAccessibilityMode(ui::AXMode mode);
// Adds the given accessibility mode to the current accessibility mode
// bitmap.
- void AddAccessibilityMode(AccessibilityMode mode);
+ void AddAccessibilityMode(ui::AXMode mode);
#if !defined(OS_ANDROID)
// Set a temporary zoom level for the frames associated with this WebContents.
@@ -296,6 +290,10 @@ class CONTENT_EXPORT WebContentsImpl
void NotifyManifestUrlChanged(const base::Optional<GURL>& manifest_url);
+#if defined(OS_ANDROID)
+ void SetImportance(ChildProcessImportance importance);
+#endif
+
// WebContents ------------------------------------------------------
WebContentsDelegate* GetDelegate() override;
void SetDelegate(WebContentsDelegate* delegate) override;
@@ -352,6 +350,7 @@ class CONTENT_EXPORT WebContentsImpl
int GetCapturerCount() const override;
bool IsAudioMuted() const override;
void SetAudioMuted(bool mute) override;
+ bool IsCurrentlyAudible() override;
bool IsConnectedToBluetoothDevice() const override;
bool IsCrashed() const override;
void SetIsCrashed(base::TerminationStatus status, int error_code) override;
@@ -366,6 +365,8 @@ class CONTENT_EXPORT WebContentsImpl
void WasShown() override;
void WasHidden() override;
bool IsVisible() const override;
+ void WasOccluded() override;
+ void WasUnOccluded() override;
bool NeedToFireBeforeUnload() override;
void DispatchBeforeUnload() override;
void AttachToOuterWebContentsFrame(
@@ -488,6 +489,10 @@ class CONTENT_EXPORT WebContentsImpl
RenderFrameHost* render_frame_host,
const std::string& interface_name,
mojo::ScopedInterfaceEndpointHandle handle) override;
+ void OnInterfaceRequest(
+ RenderFrameHost* render_frame_host,
+ const std::string& interface_name,
+ mojo::ScopedMessagePipeHandle* interface_pipe) override;
const GURL& GetMainFrameLastCommittedURL() const override;
void RenderFrameCreated(RenderFrameHost* render_frame_host) override;
void RenderFrameDeleted(RenderFrameHost* render_frame_host) override;
@@ -517,7 +522,7 @@ class CONTENT_EXPORT WebContentsImpl
const std::string& encoding) override;
WebContents* GetAsWebContents() override;
bool IsNeverVisible() override;
- AccessibilityMode GetAccessibilityMode() const override;
+ ui::AXMode GetAccessibilityMode() const override;
void AccessibilityEventReceived(
const std::vector<AXEventNotificationDetails>& details) override;
void AccessibilityLocationChangesReceived(
@@ -642,8 +647,7 @@ class CONTENT_EXPORT WebContentsImpl
void DidFailLoadWithError(RenderFrameHostImpl* render_frame_host,
const GURL& url,
int error_code,
- const base::string16& error_description,
- bool was_ignored_by_handler) override;
+ const base::string16& error_description) override;
void DidNavigateMainFramePreCommit(bool navigation_is_within_page) override;
void DidNavigateMainFramePostCommit(
RenderFrameHostImpl* render_frame_host,
@@ -786,6 +790,9 @@ class CONTENT_EXPORT WebContentsImpl
WebContents* GetWebContents() override;
void NotifyNavigationEntryCommitted(
const LoadCommittedDetails& load_details) override;
+ void NotifyNavigationEntryChanged(
+ const EntryChangedDetails& change_details) override;
+ void NotifyNavigationListPruned(const PrunedDetails& pruned_details) override;
// Invoked before a form repost warning is shown.
void NotifyBeforeFormRepostWarningShow() override;
@@ -846,7 +853,7 @@ class CONTENT_EXPORT WebContentsImpl
const WebContentsObserver::MediaPlayerId& id);
int GetCurrentlyPlayingVideoCount() override;
- const VideoSizeMap& GetCurrentlyPlayingVideoSizes() override;
+ base::Optional<gfx::Size> GetFullscreenVideoSize() override;
bool IsFullscreen() override;
MediaWebContentsObserver* media_web_contents_observer() {
@@ -931,10 +938,15 @@ class CONTENT_EXPORT WebContentsImpl
JavaScriptDialogsInMainAndSubframes);
FRIEND_TEST_ALL_PREFIXES(WebContentsImplBrowserTest,
DialogsFromJavaScriptEndFullscreen);
+ FRIEND_TEST_ALL_PREFIXES(WebContentsImplBrowserTest,
+ PopupsFromJavaScriptEndFullscreen);
FRIEND_TEST_ALL_PREFIXES(RenderFrameHostImplBrowserTest,
IframeBeforeUnloadParentHang);
FRIEND_TEST_ALL_PREFIXES(RenderFrameHostImplBrowserTest,
BeforeUnloadDialogRequiresGesture);
+ FRIEND_TEST_ALL_PREFIXES(DevToolsProtocolTest, JavaScriptDialogNotifications);
+ FRIEND_TEST_ALL_PREFIXES(DevToolsProtocolTest, JavaScriptDialogInterop);
+ FRIEND_TEST_ALL_PREFIXES(DevToolsProtocolTest, BeforeUnloadDialog);
// So |find_request_manager_| can be accessed for testing.
friend class FindRequestManagerTest;
@@ -1027,6 +1039,9 @@ class CONTENT_EXPORT WebContentsImpl
// all the unique RenderWidgetHostViews.
std::set<RenderWidgetHostView*> GetRenderWidgetHostViewsInTree();
+ // Calls WasUnOccluded() on all RenderWidgetHostViews in the frame tree.
+ void DoWasUnOccluded();
+
// Called with the result of a DownloadImage() request.
void OnDidDownloadImage(const ImageDownloadCallback& callback,
int id,
@@ -1035,7 +1050,7 @@ class CONTENT_EXPORT WebContentsImpl
const std::vector<SkBitmap>& images,
const std::vector<gfx::Size>& original_image_sizes);
- // Callback function when showing JavaScript dialogs. Takes in a routing ID
+ // Callback function when showing JavaScript dialogs. Takes in a routing ID
// pair to identify the RenderFrameHost that opened the dialog, because it's
// possible for the RenderFrameHost to be deleted by the time this is called.
void OnDialogClosed(int render_process_id,
@@ -1159,9 +1174,9 @@ class CONTENT_EXPORT WebContentsImpl
const gfx::Rect& anchor_in_root_view);
// Called by derived classes to indicate that we're no longer waiting for a
- // response. This won't actually update the throbber, but it will get picked
- // up at the next animation step if the throbber is going.
- void SetNotWaitingForResponse() { waiting_for_response_ = false; }
+ // response. Will inform |delegate_| of the change in status so that it may,
+ // for example, update the throbber.
+ void SetNotWaitingForResponse();
// Inner WebContents Helpers -------------------------------------------------
//
@@ -1304,6 +1319,10 @@ class CONTENT_EXPORT WebContentsImpl
static DownloadUrlParameters::RequestHeadersType ParseDownloadHeaders(
const std::string& headers);
+ // Sets the visibility of immediate child views, i.e. views whose parent view
+ // is that of the main frame.
+ void SetVisibilityForChildViews(bool visible);
+
// Data for core operation ---------------------------------------------------
// Delegate for notifying our owner about stuff. Not owned by us.
@@ -1435,6 +1454,9 @@ class CONTENT_EXPORT WebContentsImpl
// Tracks whether RWHV should be visible once capturer_count_ becomes zero.
bool should_normally_be_visible_;
+ // Tracks whether RWHV should be occluded once |capturer_count_| becomes zero.
+ bool should_normally_be_occluded_;
+
// Tracks whether this WebContents was ever set to be visible. Used to
// facilitate WebContents being loaded in the background by setting
// |should_normally_be_visible_|. Ensures WasShown() will trigger when first
@@ -1596,7 +1618,7 @@ class CONTENT_EXPORT WebContentsImpl
// The accessibility mode for all frames. This is queried when each frame
// is created, and broadcast to all frames when it changes.
- AccessibilityMode accessibility_mode_;
+ ui::AXMode accessibility_mode_;
// Monitors power levels for audio streams associated with this WebContents.
AudioStreamMonitor audio_stream_monitor_;
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 d588e6600f4..cc49d1c2a36 100644
--- a/chromium/content/browser/web_contents/web_contents_impl_browsertest.cc
+++ b/chromium/content/browser/web_contents/web_contents_impl_browsertest.cc
@@ -244,6 +244,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
EXPECT_EQ(&shell()->web_contents()->GetController(),
load_observer.controller_);
}
+
// Test that a renderer-initiated navigation to an invalid URL does not leave
// around a pending entry that could be used in a URL spoof. We test this in
// a browser test because our unit test framework incorrectly calls
@@ -484,13 +485,15 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
base::string16 title = title_watcher.WaitAndGetTitle();
ASSERT_EQ(title, base::ASCIIToUTF16("pushState"));
- // LoadingStateChanged should be called 4 times: start and stop for the
- // initial load of push_state.html, and start and stop for the "navigation"
- // triggered by history.pushState(). However, the start notification for the
- // history.pushState() navigation should set to_different_document to false.
+ // LoadingStateChanged should be called 5 times: start and stop for the
+ // initial load of push_state.html, once for the switch from
+ // IsWaitingForResponse() to !IsWaitingForResponse(), and start and stop for
+ // the "navigation" triggered by history.pushState(). However, the start
+ // notification for the history.pushState() navigation should set
+ // to_different_document to false.
EXPECT_EQ("pushState", shell()->web_contents()->GetLastCommittedURL().ref());
- EXPECT_EQ(4, delegate->loadingStateChangedCount());
- EXPECT_EQ(3, delegate->loadingStateToDifferentDocumentCount());
+ EXPECT_EQ(5, delegate->loadingStateChangedCount());
+ EXPECT_EQ(4, delegate->loadingStateToDifferentDocumentCount());
}
IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
@@ -512,6 +515,55 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
EXPECT_TRUE(new_web_contents_observer.RenderViewCreatedCalled());
}
+namespace {
+
+class DidGetResourceResponseStartObserver : public WebContentsObserver {
+ public:
+ DidGetResourceResponseStartObserver(Shell* shell)
+ : WebContentsObserver(shell->web_contents()), shell_(shell) {
+ shell->web_contents()->SetDelegate(&delegate_);
+ EXPECT_FALSE(shell->web_contents()->IsWaitingForResponse());
+ EXPECT_FALSE(shell->web_contents()->IsLoading());
+ }
+
+ ~DidGetResourceResponseStartObserver() override {}
+
+ void DidGetResourceResponseStart(
+ const ResourceRequestDetails& details) override {
+ EXPECT_FALSE(shell_->web_contents()->IsWaitingForResponse());
+ EXPECT_TRUE(shell_->web_contents()->IsLoading());
+ EXPECT_GT(delegate_.loadingStateChangedCount(), 0);
+ ++resource_response_start_count_;
+ }
+
+ int resource_response_start_count() const {
+ return resource_response_start_count_;
+ }
+
+ private:
+ Shell* shell_;
+ LoadingStateChangedDelegate delegate_;
+ int resource_response_start_count_ = 0;
+
+ DISALLOW_COPY_AND_ASSIGN(DidGetResourceResponseStartObserver);
+};
+
+} // namespace
+
+// Makes sure that the WebContents is no longer marked as waiting for a response
+// after DidGetResourceResponseStart() is called.
+IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
+ DidGetResourceResponseStartUpdatesWaitingState) {
+ DidGetResourceResponseStartObserver observer(shell());
+
+ ASSERT_TRUE(embedded_test_server()->Start());
+ LoadStopNotificationObserver load_observer(
+ &shell()->web_contents()->GetController());
+ NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"));
+ load_observer.Wait();
+ EXPECT_GT(observer.resource_response_start_count(), 0);
+}
+
struct LoadProgressDelegateAndObserver : public WebContentsDelegate,
public WebContentsObserver {
LoadProgressDelegateAndObserver(Shell* shell)
@@ -898,6 +950,31 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, NewNamedWindow) {
}
}
+// Test that HasOriginalOpener() tracks provenance through closed WebContentses.
+IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
+ HasOriginalOpenerTracksThroughClosedWebContents) {
+ const GURL blank_url = GURL("about:blank");
+
+ Shell* shell1 = shell();
+ EXPECT_TRUE(NavigateToURL(shell1, blank_url));
+
+ Shell* shell2 = OpenPopup(shell1, blank_url, "window2");
+ Shell* shell3 = OpenPopup(shell2, blank_url, "window3");
+
+ EXPECT_EQ(shell2->web_contents(),
+ WebContents::FromRenderFrameHost(
+ shell3->web_contents()->GetOriginalOpener()));
+ EXPECT_EQ(shell1->web_contents(),
+ WebContents::FromRenderFrameHost(
+ shell2->web_contents()->GetOriginalOpener()));
+
+ shell2->Close();
+
+ EXPECT_EQ(shell1->web_contents(),
+ WebContents::FromRenderFrameHost(
+ shell3->web_contents()->GetOriginalOpener()));
+}
+
// TODO(clamy): Make the test work on Windows and on Mac. On Mac and Windows,
// there seem to be an issue with the ShellJavascriptDialogManager.
// Flaky on all platforms: https://crbug.com/655628
@@ -990,12 +1067,12 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
namespace {
-class TestJavaScriptDialogManager : public JavaScriptDialogManager,
- public WebContentsDelegate {
+class TestWCDelegateForDialogsAndFullscreen : public JavaScriptDialogManager,
+ public WebContentsDelegate {
public:
- TestJavaScriptDialogManager()
+ TestWCDelegateForDialogsAndFullscreen()
: is_fullscreen_(false), message_loop_runner_(new MessageLoopRunner) {}
- ~TestJavaScriptDialogManager() override {}
+ ~TestWCDelegateForDialogsAndFullscreen() override {}
void Wait() {
message_loop_runner_->Run();
@@ -1025,10 +1102,20 @@ class TestJavaScriptDialogManager : public JavaScriptDialogManager,
return is_fullscreen_;
}
+ void AddNewContents(WebContents* source,
+ WebContents* new_contents,
+ WindowOpenDisposition disposition,
+ const gfx::Rect& initial_rect,
+ bool user_gesture,
+ bool* was_blocked) override {
+ delete new_contents;
+ message_loop_runner_->Quit();
+ }
+
// JavaScriptDialogManager
void RunJavaScriptDialog(WebContents* web_contents,
- const GURL& origin_url,
+ const GURL& alerting_frame_url,
JavaScriptDialogType dialog_type,
const base::string16& message_text,
const base::string16& default_prompt_text,
@@ -1064,7 +1151,7 @@ class TestJavaScriptDialogManager : public JavaScriptDialogManager,
// The MessageLoopRunner used to spin the message loop.
scoped_refptr<MessageLoopRunner> message_loop_runner_;
- DISALLOW_COPY_AND_ASSIGN(TestJavaScriptDialogManager);
+ DISALLOW_COPY_AND_ASSIGN(TestWCDelegateForDialogsAndFullscreen);
};
} // namespace
@@ -1072,8 +1159,8 @@ class TestJavaScriptDialogManager : public JavaScriptDialogManager,
IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
JavaScriptDialogsInMainAndSubframes) {
WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell()->web_contents());
- TestJavaScriptDialogManager dialog_manager;
- wc->SetDelegate(&dialog_manager);
+ TestWCDelegateForDialogsAndFullscreen test_delegate;
+ wc->SetDelegate(&test_delegate);
ASSERT_TRUE(embedded_test_server()->Start());
@@ -1101,15 +1188,15 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
std::string alert_location = "alert(document.location)";
EXPECT_TRUE(
content::ExecuteScript(root->current_frame_host(), alert_location));
- dialog_manager.Wait();
+ test_delegate.Wait();
EXPECT_EQ(GURL("http://a.com/title1.html"),
- GURL(dialog_manager.last_message()).ReplaceComponents(clear_port));
+ GURL(test_delegate.last_message()).ReplaceComponents(clear_port));
// A dialog from the subframe.
EXPECT_TRUE(
content::ExecuteScript(frame->current_frame_host(), alert_location));
- dialog_manager.Wait();
- EXPECT_EQ("about:blank", dialog_manager.last_message());
+ test_delegate.Wait();
+ EXPECT_EQ("about:blank", test_delegate.last_message());
// Navigate the subframe cross-site.
NavigateFrameToURL(frame,
@@ -1119,16 +1206,16 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
// A dialog from the subframe.
EXPECT_TRUE(
content::ExecuteScript(frame->current_frame_host(), alert_location));
- dialog_manager.Wait();
+ test_delegate.Wait();
EXPECT_EQ(GURL("http://b.com/title2.html"),
- GURL(dialog_manager.last_message()).ReplaceComponents(clear_port));
+ GURL(test_delegate.last_message()).ReplaceComponents(clear_port));
// A dialog from the main frame.
EXPECT_TRUE(
content::ExecuteScript(root->current_frame_host(), alert_location));
- dialog_manager.Wait();
+ test_delegate.Wait();
EXPECT_EQ(GURL("http://a.com/title1.html"),
- GURL(dialog_manager.last_message()).ReplaceComponents(clear_port));
+ GURL(test_delegate.last_message()).ReplaceComponents(clear_port));
// Navigate the top frame cross-site; ensure that dialogs work.
NavigateToURL(shell(),
@@ -1136,18 +1223,18 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
EXPECT_TRUE(WaitForLoadStop(wc));
EXPECT_TRUE(
content::ExecuteScript(root->current_frame_host(), alert_location));
- dialog_manager.Wait();
+ test_delegate.Wait();
EXPECT_EQ(GURL("http://c.com/title3.html"),
- GURL(dialog_manager.last_message()).ReplaceComponents(clear_port));
+ GURL(test_delegate.last_message()).ReplaceComponents(clear_port));
// Navigate back; ensure that dialogs work.
wc->GetController().GoBack();
EXPECT_TRUE(WaitForLoadStop(wc));
EXPECT_TRUE(
content::ExecuteScript(root->current_frame_host(), alert_location));
- dialog_manager.Wait();
+ test_delegate.Wait();
EXPECT_EQ(GURL("http://a.com/title1.html"),
- GURL(dialog_manager.last_message()).ReplaceComponents(clear_port));
+ GURL(test_delegate.last_message()).ReplaceComponents(clear_port));
wc->SetDelegate(nullptr);
wc->SetJavaScriptDialogManagerForTesting(nullptr);
@@ -1469,8 +1556,8 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, UserAgentOverride) {
IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
DialogsFromJavaScriptEndFullscreen) {
WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell()->web_contents());
- TestJavaScriptDialogManager dialog_manager;
- wc->SetDelegate(&dialog_manager);
+ TestWCDelegateForDialogsAndFullscreen test_delegate;
+ wc->SetDelegate(&test_delegate);
GURL url("about:blank");
EXPECT_TRUE(NavigateToURL(shell(), url));
@@ -1480,7 +1567,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
EXPECT_TRUE(wc->IsFullscreenForCurrentTab());
std::string script = "alert('hi')";
EXPECT_TRUE(content::ExecuteScript(wc, script));
- dialog_manager.Wait();
+ test_delegate.Wait();
EXPECT_FALSE(wc->IsFullscreenForCurrentTab());
// confirm
@@ -1488,7 +1575,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
EXPECT_TRUE(wc->IsFullscreenForCurrentTab());
script = "confirm('hi')";
EXPECT_TRUE(content::ExecuteScript(wc, script));
- dialog_manager.Wait();
+ test_delegate.Wait();
EXPECT_FALSE(wc->IsFullscreenForCurrentTab());
// prompt
@@ -1496,7 +1583,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
EXPECT_TRUE(wc->IsFullscreenForCurrentTab());
script = "prompt('hi')";
EXPECT_TRUE(content::ExecuteScript(wc, script));
- dialog_manager.Wait();
+ test_delegate.Wait();
EXPECT_FALSE(wc->IsFullscreenForCurrentTab());
// beforeunload
@@ -1511,7 +1598,28 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
script = "window.onbeforeunload=function(e){ return 'x' };";
EXPECT_TRUE(content::ExecuteScript(wc, script));
EXPECT_TRUE(NavigateToURL(shell(), url));
- dialog_manager.Wait();
+ test_delegate.Wait();
+ EXPECT_FALSE(wc->IsFullscreenForCurrentTab());
+
+ wc->SetDelegate(nullptr);
+ wc->SetJavaScriptDialogManagerForTesting(nullptr);
+}
+
+IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
+ PopupsFromJavaScriptEndFullscreen) {
+ WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell()->web_contents());
+ TestWCDelegateForDialogsAndFullscreen test_delegate;
+ wc->SetDelegate(&test_delegate);
+
+ GURL url("about:blank");
+ EXPECT_TRUE(NavigateToURL(shell(), url));
+
+ // popup
+ wc->EnterFullscreenMode(url);
+ EXPECT_TRUE(wc->IsFullscreenForCurrentTab());
+ std::string script = "window.open('', '', 'width=200,height=100')";
+ EXPECT_TRUE(content::ExecuteScript(wc, script));
+ test_delegate.Wait();
EXPECT_FALSE(wc->IsFullscreenForCurrentTab());
wc->SetDelegate(nullptr);
@@ -1556,8 +1664,10 @@ class FormBubbleDelegate : public WebContentsDelegate {
scoped_refptr<MessageLoopRunner> message_loop_runner_;
};
+// TODO(tkent): Remove this test when we remove the browser-side validation
+// bubble implementation. crbug.com/739091
IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
- NavigationHidesFormValidationBubble) {
+ DISABLED_NavigationHidesFormValidationBubble) {
ASSERT_TRUE(embedded_test_server()->Start());
EXPECT_TRUE(NavigateToURL(
shell(), embedded_test_server()->GetURL("a.com", "/title1.html")));
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 059b3c4713c..bb30a920796 100644
--- a/chromium/content/browser/web_contents/web_contents_impl_unittest.cc
+++ b/chromium/content/browser/web_contents/web_contents_impl_unittest.cc
@@ -46,6 +46,7 @@
#include "content/public/common/content_constants.h"
#include "content/public/common/url_constants.h"
#include "content/public/test/mock_render_process_host.h"
+#include "content/public/test/navigation_simulator.h"
#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_utils.h"
#include "content/test/test_content_browser_client.h"
@@ -291,8 +292,7 @@ class TestWebContentsObserver : public WebContentsObserver {
void DidFailLoad(RenderFrameHost* render_frame_host,
const GURL& validated_url,
int error_code,
- const base::string16& error_description,
- bool was_ignored_by_handler) override {
+ const base::string16& error_description) override {
last_url_ = validated_url;
}
@@ -337,11 +337,12 @@ class FakeFullscreenDelegate : public WebContentsDelegate {
DISALLOW_COPY_AND_ASSIGN(FakeFullscreenDelegate);
};
-class FakeValidationMessageDelegate : public WebContentsDelegate {
+class FakeWebContentsDelegate : public WebContentsDelegate {
public:
- FakeValidationMessageDelegate()
- : hide_validation_message_was_called_(false) {}
- ~FakeValidationMessageDelegate() override {}
+ FakeWebContentsDelegate()
+ : hide_validation_message_was_called_(false),
+ loading_state_changed_was_called_(false) {}
+ ~FakeWebContentsDelegate() override {}
void HideValidationMessage(WebContents* web_contents) override {
hide_validation_message_was_called_ = true;
@@ -351,16 +352,28 @@ class FakeValidationMessageDelegate : public WebContentsDelegate {
return hide_validation_message_was_called_;
}
+ void LoadingStateChanged(WebContents* source,
+ bool to_different_document) override {
+ loading_state_changed_was_called_ = true;
+ }
+
+ bool loading_state_changed_was_called() const {
+ return loading_state_changed_was_called_;
+ }
+
private:
bool hide_validation_message_was_called_;
+ bool loading_state_changed_was_called_;
- DISALLOW_COPY_AND_ASSIGN(FakeValidationMessageDelegate);
+ DISALLOW_COPY_AND_ASSIGN(FakeWebContentsDelegate);
};
} // namespace
-// Test to make sure that title updates get stripped of whitespace.
TEST_F(WebContentsImplTest, UpdateTitle) {
+ FakeWebContentsDelegate fake_delegate;
+ contents()->SetDelegate(&fake_delegate);
+
NavigationControllerImpl& cont =
static_cast<NavigationControllerImpl&>(controller());
cont.LoadURL(GURL(url::kAboutBlankURL), Referrer(), ui::PAGE_TRANSITION_TYPED,
@@ -372,10 +385,16 @@ TEST_F(WebContentsImplTest, UpdateTitle) {
main_test_rfh()->SendNavigateWithParams(&params);
+ EXPECT_TRUE(contents()->IsWaitingForResponse());
contents()->UpdateTitle(main_test_rfh(),
base::ASCIIToUTF16(" Lots O' Whitespace\n"),
base::i18n::LEFT_TO_RIGHT);
+ // Make sure that title updates get stripped of whitespace.
EXPECT_EQ(base::ASCIIToUTF16("Lots O' Whitespace"), contents()->GetTitle());
+ EXPECT_FALSE(contents()->IsWaitingForResponse());
+ EXPECT_TRUE(fake_delegate.loading_state_changed_was_called());
+
+ contents()->SetDelegate(nullptr);
}
TEST_F(WebContentsImplTest, UpdateTitleBeforeFirstNavigation) {
@@ -523,13 +542,7 @@ TEST_F(WebContentsImplTest, CrossSiteBoundaries) {
// Navigate to URL. First URL should use first RenderViewHost.
const GURL url("http://www.google.com");
- controller().LoadURL(
- url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
- int entry_id = controller().GetPendingEntry()->GetUniqueID();
- orig_rfh->PrepareForCommit();
- contents()->TestDidNavigateWithSequenceNumber(
- orig_rfh, entry_id, true, url, Referrer(), ui::PAGE_TRANSITION_TYPED,
- false, 0, 0);
+ NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url);
// Keep the number of active frames in orig_rfh's SiteInstance non-zero so
// that orig_rfh doesn't get deleted when it gets swapped out.
@@ -544,7 +557,7 @@ TEST_F(WebContentsImplTest, CrossSiteBoundaries) {
const GURL url2("http://www.yahoo.com");
controller().LoadURL(
url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
- entry_id = controller().GetPendingEntry()->GetUniqueID();
+ int entry_id = controller().GetPendingEntry()->GetUniqueID();
if (IsBrowserSideNavigationEnabled())
orig_rfh->PrepareForCommit();
EXPECT_TRUE(contents()->CrossProcessNavigationPending());
@@ -563,7 +576,7 @@ TEST_F(WebContentsImplTest, CrossSiteBoundaries) {
EXPECT_FALSE(pending_rfh->are_navigations_suspended());
}
- // DidNavigate from the pending page
+ // DidNavigate from the pending page.
contents()->TestDidNavigateWithSequenceNumber(
pending_rfh, entry_id, true, url2, Referrer(), ui::PAGE_TRANSITION_TYPED,
false, 1, 1);
@@ -602,7 +615,7 @@ TEST_F(WebContentsImplTest, CrossSiteBoundaries) {
EXPECT_FALSE(goback_rfh->are_navigations_suspended());
}
- // DidNavigate from the back action
+ // DidNavigate from the back action.
contents()->TestDidNavigateWithSequenceNumber(
goback_rfh, entry_id, false, url2, Referrer(), ui::PAGE_TRANSITION_TYPED,
false, 2, 0);
@@ -1023,10 +1036,7 @@ TEST_F(WebContentsImplTest, CrossSiteComparesAgainstCurrentPage) {
// Simulate a link click in first contents to second site. Doesn't switch
// SiteInstances, because we don't intercept Blink navigations.
- orig_rfh->SendRendererInitiatedNavigationRequest(url2, true);
- orig_rfh->PrepareForCommit();
- contents()->TestDidNavigate(orig_rfh, 0, true, url2,
- ui::PAGE_TRANSITION_TYPED);
+ NavigationSimulator::NavigateAndCommitFromDocument(url2, orig_rfh);
SiteInstance* instance3 = contents()->GetSiteInstance();
EXPECT_EQ(instance1, instance3);
EXPECT_FALSE(contents()->CrossProcessNavigationPending());
@@ -1143,19 +1153,12 @@ TEST_F(WebContentsImplTest, CrossSiteNavigationBackPreempted) {
// Start with a web ui page, which gets a new RVH with WebUI bindings.
GURL url1(std::string(kChromeUIScheme) + "://" +
std::string(kChromeUIGpuHost));
- controller().LoadURL(
- url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
- int entry_id = controller().GetPendingEntry()->GetUniqueID();
+ NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url1);
TestRenderFrameHost* webui_rfh = main_test_rfh();
- webui_rfh->PrepareForCommit();
- contents()->TestDidNavigateWithSequenceNumber(
- webui_rfh, entry_id, true, url1, Referrer(), ui::PAGE_TRANSITION_TYPED,
- false, 0, 0);
NavigationEntry* entry1 = controller().GetLastCommittedEntry();
SiteInstance* instance1 = contents()->GetSiteInstance();
EXPECT_FALSE(contents()->CrossProcessNavigationPending());
- EXPECT_EQ(webui_rfh, main_test_rfh());
EXPECT_EQ(url1, entry1->GetURL());
EXPECT_EQ(instance1,
NavigationEntryImpl::FromNavigationEntry(entry1)->site_instance());
@@ -1163,25 +1166,12 @@ TEST_F(WebContentsImplTest, CrossSiteNavigationBackPreempted) {
// Navigate to new site.
const GURL url2("http://www.google.com");
- controller().LoadURL(
- url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
- entry_id = controller().GetPendingEntry()->GetUniqueID();
- EXPECT_TRUE(contents()->CrossProcessNavigationPending());
- TestRenderFrameHost* google_rfh = contents()->GetPendingMainFrame();
-
- // Simulate beforeunload approval.
- EXPECT_TRUE(webui_rfh->is_waiting_for_beforeunload_ack());
- webui_rfh->PrepareForCommit();
-
- // DidNavigate from the pending page.
- contents()->TestDidNavigateWithSequenceNumber(
- google_rfh, entry_id, true, url2, Referrer(), ui::PAGE_TRANSITION_TYPED,
- false, 1, 1);
+ NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url2);
+ TestRenderFrameHost* google_rfh = main_test_rfh();
NavigationEntry* entry2 = controller().GetLastCommittedEntry();
SiteInstance* instance2 = contents()->GetSiteInstance();
EXPECT_FALSE(contents()->CrossProcessNavigationPending());
- EXPECT_EQ(google_rfh, main_test_rfh());
EXPECT_NE(instance1, instance2);
EXPECT_FALSE(contents()->GetPendingMainFrame());
EXPECT_EQ(url2, entry2->GetURL());
@@ -1191,14 +1181,7 @@ TEST_F(WebContentsImplTest, CrossSiteNavigationBackPreempted) {
// Navigate to third page on same site.
const GURL url3("http://news.google.com");
- controller().LoadURL(
- url3, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
- entry_id = controller().GetPendingEntry()->GetUniqueID();
- EXPECT_FALSE(contents()->CrossProcessNavigationPending());
- main_test_rfh()->PrepareForCommit();
- contents()->TestDidNavigateWithSequenceNumber(
- google_rfh, entry_id, true, url3, Referrer(), ui::PAGE_TRANSITION_TYPED,
- false, 2, 2);
+ NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url3);
NavigationEntry* entry3 = controller().GetLastCommittedEntry();
SiteInstance* instance3 = contents()->GetSiteInstance();
@@ -1618,7 +1601,7 @@ TEST_F(WebContentsImplTest, HistoryNavigationExitsFullscreen) {
}
TEST_F(WebContentsImplTest, TerminateHidesValidationMessage) {
- FakeValidationMessageDelegate fake_delegate;
+ FakeWebContentsDelegate fake_delegate;
contents()->SetDelegate(&fake_delegate);
EXPECT_FALSE(fake_delegate.hide_validation_message_was_called());
@@ -1677,7 +1660,7 @@ TEST_F(WebContentsImplTest,
ShowInterstitialFromBrowserWithNewNavigationDontProceed) {
// Navigate to a page.
GURL url1("http://www.google.com");
- main_test_rfh()->NavigateAndCommitRendererInitiated(true, url1);
+ NavigationSimulator::NavigateAndCommitFromDocument(url1, main_test_rfh());
EXPECT_EQ(1, controller().GetEntryCount());
// Initiate a browser navigation that will trigger the interstitial.
@@ -1729,7 +1712,7 @@ TEST_F(WebContentsImplTest,
ShowInterstitialFromRendererWithNewNavigationDontProceed) {
// Navigate to a page.
GURL url1("http://www.google.com");
- main_test_rfh()->NavigateAndCommitRendererInitiated(true, url1);
+ NavigationSimulator::NavigateAndCommitFromDocument(url1, main_test_rfh());
EXPECT_EQ(1, controller().GetEntryCount());
// Show an interstitial (no pending entry, the interstitial would have been
@@ -1776,7 +1759,7 @@ TEST_F(WebContentsImplTest,
TEST_F(WebContentsImplTest, ShowInterstitialNoNewNavigationDontProceed) {
// Navigate to a page.
GURL url1("http://www.google.com");
- main_test_rfh()->NavigateAndCommitRendererInitiated(true, url1);
+ NavigationSimulator::NavigateAndCommitFromDocument(url1, main_test_rfh());
EXPECT_EQ(1, controller().GetEntryCount());
// Show an interstitial.
@@ -1823,7 +1806,7 @@ TEST_F(WebContentsImplTest,
ShowInterstitialFromBrowserNewNavigationProceed) {
// Navigate to a page.
GURL url1("http://www.google.com");
- main_test_rfh()->NavigateAndCommitRendererInitiated(true, url1);
+ NavigationSimulator::NavigateAndCommitFromDocument(url1, main_test_rfh());
EXPECT_EQ(1, controller().GetEntryCount());
// Initiate a browser navigation that will trigger the interstitial
@@ -1887,7 +1870,7 @@ TEST_F(WebContentsImplTest,
ShowInterstitialFromRendererNewNavigationProceed) {
// Navigate to a page.
GURL url1("http://www.google.com");
- main_test_rfh()->NavigateAndCommitRendererInitiated(true, url1);
+ NavigationSimulator::NavigateAndCommitFromDocument(url1, main_test_rfh());
EXPECT_EQ(1, controller().GetEntryCount());
// Show an interstitial.
@@ -1925,7 +1908,7 @@ TEST_F(WebContentsImplTest,
// Simulate the navigation to the page, that's when the interstitial gets
// hidden.
GURL url3("http://www.thepage.com");
- main_test_rfh()->NavigateAndCommitRendererInitiated(true, url3);
+ NavigationSimulator::NavigateAndCommitFromDocument(url3, main_test_rfh());
EXPECT_FALSE(contents()->ShowingInterstitialPage());
EXPECT_EQ(nullptr, contents()->GetInterstitialPage());
@@ -1945,7 +1928,7 @@ TEST_F(WebContentsImplTest,
TEST_F(WebContentsImplTest, ShowInterstitialNoNewNavigationProceed) {
// Navigate to a page so we have a navigation entry in the controller.
GURL url1("http://www.google.com");
- main_test_rfh()->NavigateAndCommitRendererInitiated(true, url1);
+ NavigationSimulator::NavigateAndCommitFromDocument(url1, main_test_rfh());
EXPECT_EQ(1, controller().GetEntryCount());
// Show an interstitial.
@@ -2004,7 +1987,7 @@ TEST_F(WebContentsImplTest, ShowInterstitialThenNavigate) {
// While interstitial showing, navigate to a new URL.
const GURL url2("http://www.yahoo.com");
- main_test_rfh()->NavigateAndCommitRendererInitiated(true, url2);
+ NavigationSimulator::NavigateAndCommitFromDocument(url2, main_test_rfh());
EXPECT_EQ(TestInterstitialPage::CANCELED, state);
@@ -2016,7 +1999,7 @@ TEST_F(WebContentsImplTest, ShowInterstitialThenNavigate) {
TEST_F(WebContentsImplTest, ShowInterstitialThenGoBack) {
// Navigate to a page so we have a navigation entry in the controller.
GURL url1("http://www.google.com");
- main_test_rfh()->NavigateAndCommitRendererInitiated(true, url1);
+ NavigationSimulator::NavigateAndCommitFromDocument(url1, main_test_rfh());
EXPECT_EQ(1, controller().GetEntryCount());
// Show interstitial.
@@ -2056,7 +2039,7 @@ TEST_F(WebContentsImplTest, ShowInterstitialThenGoBack) {
TEST_F(WebContentsImplTest, ShowInterstitialCrashRendererThenGoBack) {
// Navigate to a page so we have a navigation entry in the controller.
GURL url1("http://www.google.com");
- main_test_rfh()->NavigateAndCommitRendererInitiated(true, url1);
+ NavigationSimulator::NavigateAndCommitFromDocument(url1, main_test_rfh());
EXPECT_EQ(1, controller().GetEntryCount());
NavigationEntry* entry = controller().GetLastCommittedEntry();
@@ -2098,7 +2081,7 @@ TEST_F(WebContentsImplTest, ShowInterstitialCrashRendererThenGoBack) {
TEST_F(WebContentsImplTest, ShowInterstitialCrashRendererThenNavigate) {
// Navigate to a page so we have a navigation entry in the controller.
GURL url1("http://www.google.com");
- main_test_rfh()->NavigateAndCommitRendererInitiated(true, url1);
+ NavigationSimulator::NavigateAndCommitFromDocument(url1, main_test_rfh());
EXPECT_EQ(1, controller().GetEntryCount());
// Show interstitial.
@@ -2178,7 +2161,7 @@ TEST_F(WebContentsImplTest, ShowInterstitialThenCloseAndShutdown) {
TEST_F(WebContentsImplTest, CreateInterstitialForClosingTab) {
// Navigate to a page.
GURL url1("http://www.google.com");
- main_test_rfh()->NavigateAndCommitRendererInitiated(true, url1);
+ NavigationSimulator::NavigateAndCommitFromDocument(url1, main_test_rfh());
EXPECT_EQ(1, controller().GetEntryCount());
// Initiate a browser navigation that will trigger an interstitial.
@@ -2224,7 +2207,7 @@ TEST_F(WebContentsImplTest, CreateInterstitialForClosingTab) {
TEST_F(WebContentsImplTest, TabNavigationDoesntRaceInterstitial) {
// Navigate to a page.
GURL url1("http://www.google.com");
- main_test_rfh()->NavigateAndCommitRendererInitiated(true, url1);
+ NavigationSimulator::NavigateAndCommitFromDocument(url1, main_test_rfh());
EXPECT_EQ(1, controller().GetEntryCount());
// Initiate a browser navigation that will trigger an interstitial.
@@ -2269,7 +2252,7 @@ TEST_F(WebContentsImplTest, TabNavigationDoesntRaceInterstitial) {
TEST_F(WebContentsImplTest, ShowInterstitialProceedMultipleCommands) {
// Navigate to a page so we have a navigation entry in the controller.
GURL url1("http://www.google.com");
- main_test_rfh()->NavigateAndCommitRendererInitiated(true, url1);
+ NavigationSimulator::NavigateAndCommitFromDocument(url1, main_test_rfh());
EXPECT_EQ(1, controller().GetEntryCount());
// Show an interstitial.
@@ -2305,7 +2288,8 @@ TEST_F(WebContentsImplTest, ShowInterstitialProceedMultipleCommands) {
TEST_F(WebContentsImplTest, ShowInterstitialOnInterstitial) {
// Navigate to a page so we have a navigation entry in the controller.
GURL start_url("http://www.google.com");
- main_test_rfh()->NavigateAndCommitRendererInitiated(true, start_url);
+ NavigationSimulator::NavigateAndCommitFromDocument(start_url,
+ main_test_rfh());
EXPECT_EQ(1, controller().GetEntryCount());
// Show an interstitial.
@@ -2360,7 +2344,8 @@ TEST_F(WebContentsImplTest, ShowInterstitialOnInterstitial) {
TEST_F(WebContentsImplTest, ShowInterstitialProceedShowInterstitial) {
// Navigate to a page so we have a navigation entry in the controller.
GURL start_url("http://www.google.com");
- main_test_rfh()->NavigateAndCommitRendererInitiated(true, start_url);
+ NavigationSimulator::NavigateAndCommitFromDocument(start_url,
+ main_test_rfh());
EXPECT_EQ(1, controller().GetEntryCount());
// Show an interstitial.
@@ -2510,7 +2495,7 @@ TEST_F(WebContentsImplTest, InterstitialCrasher) {
RunAllPendingInMessageLoop();
EXPECT_TRUE(deleted);
- // Now try again but this time crash the intersitial after it was shown.
+ // Now try again but this time crash the interstitial after it was shown.
interstitial =
new TestInterstitialPage(contents(), true, url, &state, &deleted);
interstitial->Show();
@@ -2615,7 +2600,7 @@ TEST_F(WebContentsImplTest, NoJSMessageOnInterstitials) {
TEST_F(WebContentsImplTest, CopyStateFromAndPruneSourceInterstitial) {
// Navigate to a page.
GURL url1("http://www.google.com");
- main_test_rfh()->NavigateAndCommitRendererInitiated(true, url1);
+ NavigationSimulator::NavigateAndCommitFromDocument(url1, main_test_rfh());
EXPECT_EQ(1, controller().GetEntryCount());
// Initiate a browser navigation that will trigger the interstitial
@@ -2719,8 +2704,7 @@ TEST_F(WebContentsImplTest, FilterURLs) {
other_contents->NavigateAndCommit(url_normalized);
// Check that an IPC with about:whatever is correctly normalized.
- other_contents->TestDidFailLoadWithError(
- url_from_ipc, 1, base::string16(), false);
+ other_contents->TestDidFailLoadWithError(url_from_ipc, 1, base::string16());
EXPECT_EQ(url_normalized, other_observer.last_url());
}
@@ -2841,20 +2825,34 @@ TEST_F(WebContentsImplTest, CapturerPreventsOcclusion) {
contents()->WasOccluded();
EXPECT_TRUE(view->is_occluded());
- // Add a capturer. This should cause the view to be un-occluded.
+ // Adding a capturer on an occluded WebContents should cause the view to be
+ // unoccluded. Removing the capturer should cause the view to be occluded
+ // again.
+ contents()->IncrementCapturerCount(gfx::Size());
+ EXPECT_FALSE(view->is_occluded());
+
+ contents()->DecrementCapturerCount();
+ EXPECT_TRUE(view->is_occluded());
+
+ // Adding a capturer on an unoccluded WebContents should not change the
+ // occlusion state of the view. Calling WasOccluded() on an unoccluded
+ // WebContents() that has a capturer should not change the occlusion state of
+ // the view. Removing the capturer should cause the view to become occluded.
+ contents()->WasUnOccluded();
+ EXPECT_FALSE(view->is_occluded());
contents()->IncrementCapturerCount(gfx::Size());
EXPECT_FALSE(view->is_occluded());
- // Try to occlude the view. This will fail to propagate because of the
- // active capturer.
contents()->WasOccluded();
EXPECT_FALSE(view->is_occluded());
- // Remove the capturer and try again.
contents()->DecrementCapturerCount();
- EXPECT_FALSE(view->is_occluded());
- contents()->WasOccluded();
EXPECT_TRUE(view->is_occluded());
+
+ // Calling WasUnoccluded() on a WebContents with no capturers should cause the
+ // view to become unoccluded.
+ contents()->WasUnOccluded();
+ EXPECT_FALSE(view->is_occluded());
}
// Tests that GetLastActiveTime starts with a real, non-zero time and updates
@@ -3178,18 +3176,9 @@ TEST_F(WebContentsImplTestWithSiteIsolation, StartStopEventsBalance) {
// Navigate the frame to another URL, which will send again
// DidStartLoading and DidStopLoading messages.
- {
- subframe->SendRendererInitiatedNavigationRequest(foo_url, false);
- subframe->PrepareForCommit();
- if (!IsBrowserSideNavigationEnabled()) {
- subframe->OnMessageReceived(
- FrameHostMsg_DidStartLoading(subframe->GetRoutingID(), true));
- }
- subframe->SendNavigateWithTransition(10, false, foo_url,
- ui::PAGE_TRANSITION_AUTO_SUBFRAME);
- subframe->OnMessageReceived(
- FrameHostMsg_DidStopLoading(subframe->GetRoutingID()));
- }
+ NavigationSimulator::NavigateAndCommitFromDocument(foo_url, subframe);
+ subframe->OnMessageReceived(
+ FrameHostMsg_DidStopLoading(subframe->GetRoutingID()));
// Since the main frame hasn't sent any DidStopLoading messages, it is
// expected that the WebContents is still in loading state.
@@ -3577,7 +3566,7 @@ class TestJavaScriptDialogManager : public JavaScriptDialogManager {
// JavaScriptDialogManager
void RunJavaScriptDialog(WebContents* web_contents,
- const GURL& origin_url,
+ const GURL& alerting_frame_url,
JavaScriptDialogType dialog_type,
const base::string16& message_text,
const base::string16& default_prompt_text,
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 1947cd67273..6e34c386197 100644
--- a/chromium/content/browser/web_contents/web_contents_view_android.cc
+++ b/chromium/content/browser/web_contents/web_contents_view_android.cc
@@ -462,8 +462,7 @@ void WebContentsViewAndroid::TakeFocus(bool reverse) {
web_contents_->GetRenderWidgetHostView()->Focus();
}
-bool WebContentsViewAndroid::OnTouchEvent(const ui::MotionEventAndroid& event,
- bool for_touch_handle) {
+bool WebContentsViewAndroid::OnTouchEvent(const ui::MotionEventAndroid& event) {
if (event.GetAction() == ui::MotionEventAndroid::ACTION_DOWN)
content_view_core_->OnTouchDown(event.GetJavaObject());
return false; // let the children handle the actual 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 dabecf26656..26945c159ae 100644
--- a/chromium/content/browser/web_contents/web_contents_view_android.h
+++ b/chromium/content/browser/web_contents/web_contents_view_android.h
@@ -101,8 +101,7 @@ class WebContentsViewAndroid : public WebContentsView,
void TakeFocus(bool reverse) override;
// ui::ViewClient implementation.
- bool OnTouchEvent(const ui::MotionEventAndroid& event,
- bool for_touch_handle) override;
+ bool OnTouchEvent(const ui::MotionEventAndroid& event) override;
bool OnMouseEvent(const ui::MotionEventAndroid& event) override;
bool OnDragEvent(const ui::DragEventAndroid& event) override;
void OnPhysicalBackingSizeChanged() 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 a99e04390ef..53ad9c8cb39 100644
--- a/chromium/content/browser/web_contents/web_contents_view_aura.cc
+++ b/chromium/content/browser/web_contents/web_contents_view_aura.cc
@@ -94,11 +94,6 @@ namespace {
WebContentsViewAura::RenderWidgetHostViewCreateFunction
g_create_render_widget_host_view = nullptr;
-bool IsScrollEndEffectEnabled() {
- return base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
- switches::kScrollEndEffect) == "1";
-}
-
RenderWidgetHostViewAura* ToRenderWidgetHostViewAura(
RenderWidgetHostView* view) {
if (!view || (RenderViewHostFactory::has_factory() &&
@@ -155,7 +150,7 @@ class WebDragSourceAura : public NotificationObserver {
DISALLOW_COPY_AND_ASSIGN(WebDragSourceAura);
};
-#if (!defined(OS_CHROMEOS) && defined(USE_X11)) || defined(OS_WIN)
+#if defined(USE_X11) || defined(OS_WIN)
// Fill out the OSExchangeData with a file contents, synthesizing a name if
// necessary.
void PrepareDragForFileContents(const DropData& drop_data,
@@ -291,7 +286,7 @@ void PrepareDragData(const DropData& drop_data,
if (!drop_data.download_metadata.empty())
PrepareDragForDownload(drop_data, provider, web_contents);
#endif
-#if (!defined(OS_CHROMEOS) && defined(USE_X11)) || defined(OS_WIN)
+#if defined(USE_X11) || defined(OS_WIN)
// We set the file contents before the URL because the URL also sets file
// contents (to a .URL shortcut). We want to prefer file content data over
// a shortcut so we add it first.
@@ -497,7 +492,7 @@ class WebContentsViewAura::WindowObserver
}
// Overridden WindowTreeHostObserver:
- void OnHostMovedInPixels(const aura::WindowTreeHost* host,
+ void OnHostMovedInPixels(aura::WindowTreeHost* host,
const gfx::Point& new_origin_in_pixels) override {
TRACE_EVENT1("ui",
"WebContentsViewAura::WindowObserver::OnHostMovedInPixels",
@@ -648,12 +643,6 @@ void WebContentsViewAura::CompleteOverscrollNavigation(OverscrollMode mode) {
selection_controller->HideAndDisallowShowingAutomatically();
}
-void WebContentsViewAura::OverscrollUpdateForWebContentsDelegate(
- float delta_y) {
- if (web_contents_->GetDelegate() && IsScrollEndEffectEnabled())
- web_contents_->GetDelegate()->OverscrollUpdate(delta_y);
-}
-
ui::TouchSelectionController* WebContentsViewAura::GetSelectionController()
const {
RenderWidgetHostViewAura* view =
@@ -713,6 +702,7 @@ void GetScreenInfoForWindow(ScreenInfo* results,
results->is_monochrome = display.is_monochrome();
results->device_scale_factor = display.device_scale_factor();
results->color_space = display.color_space();
+ results->color_space.GetICCProfile(&results->icc_profile);
// The Display rotation and the ScreenInfo orientation are not the same
// angle. The former is the physical display rotation while the later is the
@@ -1029,14 +1019,6 @@ void WebContentsViewAura::TakeFocus(bool reverse) {
////////////////////////////////////////////////////////////////////////////////
// WebContentsViewAura, OverscrollControllerDelegate implementation:
-gfx::Size WebContentsViewAura::GetVisibleSize() const {
- RenderWidgetHostView* rwhv = web_contents_->GetRenderWidgetHostView();
- if (!rwhv || !rwhv->IsShowing())
- return gfx::Size();
-
- return rwhv->GetViewBounds().size();
-}
-
gfx::Size WebContentsViewAura::GetDisplaySize() const {
RenderWidgetHostView* rwhv = web_contents_->GetRenderWidgetHostView();
if (!rwhv)
@@ -1048,33 +1030,22 @@ gfx::Size WebContentsViewAura::GetDisplaySize() const {
}
bool WebContentsViewAura::OnOverscrollUpdate(float delta_x, float delta_y) {
- if (current_overscroll_gesture_ == OVERSCROLL_NONE)
+ if (current_overscroll_gesture_ != OVERSCROLL_EAST &&
+ current_overscroll_gesture_ != OVERSCROLL_WEST) {
return false;
-
- if (current_overscroll_gesture_ == OVERSCROLL_NORTH ||
- current_overscroll_gesture_ == OVERSCROLL_SOUTH) {
- OverscrollUpdateForWebContentsDelegate(delta_y);
- return delta_y != 0;
}
+
return navigation_overlay_->relay_delegate()->OnOverscrollUpdate(delta_x,
delta_y);
}
void WebContentsViewAura::OnOverscrollComplete(OverscrollMode mode) {
- if (web_contents_->GetDelegate() &&
- IsScrollEndEffectEnabled() &&
- (mode == OVERSCROLL_NORTH || mode == OVERSCROLL_SOUTH)) {
- web_contents_->GetDelegate()->OverscrollComplete();
- }
CompleteOverscrollNavigation(mode);
}
void WebContentsViewAura::OnOverscrollModeChange(OverscrollMode old_mode,
OverscrollMode new_mode,
OverscrollSource source) {
- if (old_mode == OVERSCROLL_NORTH || old_mode == OVERSCROLL_SOUTH)
- OverscrollUpdateForWebContentsDelegate(0);
-
current_overscroll_gesture_ = new_mode;
navigation_overlay_->relay_delegate()->OnOverscrollModeChange(
old_mode, new_mode, source);
@@ -1188,7 +1159,7 @@ void WebContentsViewAura::OnMouseEvent(ui::MouseEvent* event) {
// Linux window managers like to handle raise-on-click themselves. If we
// raise-on-click manually, this may override user settings that prevent
// focus-stealing.
-#if !defined(USE_X11) || defined (OS_CHROMEOS)
+#if !defined(USE_X11)
web_contents_->GetDelegate()->ActivateContents(web_contents_);
#endif
}
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 bb492884e22..7979b48375e 100644
--- a/chromium/content/browser/web_contents/web_contents_view_aura.h
+++ b/chromium/content/browser/web_contents/web_contents_view_aura.h
@@ -42,7 +42,7 @@ class WebContentsImpl;
class WebDragDestDelegate;
class CONTENT_EXPORT WebContentsViewAura
- : NON_EXPORTED_BASE(public WebContentsView),
+ : public WebContentsView,
public RenderViewHostDelegateView,
public OverscrollControllerDelegate,
public aura::WindowDelegate,
@@ -88,8 +88,6 @@ class CONTENT_EXPORT WebContentsViewAura
// animates in, or the content window animates out).
void CompleteOverscrollNavigation(OverscrollMode mode);
- void OverscrollUpdateForWebContentsDelegate(float delta_y);
-
ui::TouchSelectionController* GetSelectionController() const;
TouchSelectionControllerClientAura* GetSelectionControllerClient() const;
@@ -153,7 +151,6 @@ class CONTENT_EXPORT WebContentsViewAura
#endif
// Overridden from OverscrollControllerDelegate:
- gfx::Size GetVisibleSize() const override;
gfx::Size GetDisplaySize() const override;
bool OnOverscrollUpdate(float delta_x, float delta_y) override;
void OnOverscrollComplete(OverscrollMode overscroll_mode) override;
diff --git a/chromium/content/browser/web_contents/web_contents_view_aura_browsertest.cc b/chromium/content/browser/web_contents/web_contents_view_aura_browsertest.cc
index 99c5e173163..783a11b5673 100644
--- a/chromium/content/browser/web_contents/web_contents_view_aura_browsertest.cc
+++ b/chromium/content/browser/web_contents/web_contents_view_aura_browsertest.cc
@@ -31,7 +31,6 @@
#include "content/public/browser/overscroll_configuration.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_widget_host.h"
-#include "content/public/browser/web_contents_delegate.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test_utils.h"
@@ -61,38 +60,6 @@ void GiveItSomeTime() {
run_loop.Run();
}
-// WebContentsDelegate which tracks vertical overscroll updates.
-class VerticalOverscrollTracker : public content::WebContentsDelegate {
- public:
- VerticalOverscrollTracker() : count_(0), completed_(false) {}
- ~VerticalOverscrollTracker() override {}
-
- int num_overscroll_updates() const {
- return count_;
- }
-
- bool overscroll_completed() const {
- return completed_;
- }
-
- void Reset() {
- count_ = 0;
- completed_ = false;
- }
-
- private:
- bool CanOverscrollContent() const override { return true; }
-
- void OverscrollUpdate(float delta_y) override { ++count_; }
-
- void OverscrollComplete() override { completed_ = true; }
-
- int count_;
- bool completed_;
-
- DISALLOW_COPY_AND_ASSIGN(VerticalOverscrollTracker);
-};
-
} //namespace
@@ -1068,157 +1035,4 @@ IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
}
}
-// Test that vertical overscroll updates are sent only when a user overscrolls
-// vertically. Flaky on several platforms. https://crbug.com/679420
-#if defined(OS_WIN) || defined(OS_CHROMEOS)
-#define MAYBE_VerticalOverscroll DISABLED_VerticalOverscroll
-#else
-#define MAYBE_VerticalOverscroll VerticalOverscroll
-#endif
-
-IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, MAYBE_VerticalOverscroll) {
- base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
- switches::kScrollEndEffect, "1");
-
- ASSERT_NO_FATAL_FAILURE(StartTestWithPage("about:blank"));
- WebContentsImpl* web_contents =
- static_cast<WebContentsImpl*>(shell()->web_contents());
- VerticalOverscrollTracker tracker;
- web_contents->SetDelegate(&tracker);
-
- // This test triggers a large number of animations. Speed them up to ensure
- // the test completes within its time limit.
- ui::ScopedAnimationDurationScaleMode fast_duration_mode(
- ui::ScopedAnimationDurationScaleMode::FAST_DURATION);
-
- aura::Window* content = web_contents->GetContentNativeView();
- ui::EventSink* sink = content->GetHost()->event_sink();
- gfx::Rect bounds = content->GetBoundsInRootWindow();
-
- // Overscroll horizontally.
- {
- int kXStep = bounds.width() / 10;
- gfx::Point location(bounds.right() - kXStep, bounds.y() + 5);
- base::TimeTicks timestamp = ui::EventTimeForNow();
- ui::TouchEvent press(
- ui::ET_TOUCH_PRESSED, location, timestamp,
- ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0));
- ui::EventDispatchDetails details = sink->OnEventFromSource(&press);
- ASSERT_FALSE(details.dispatcher_destroyed);
- WaitAFrame();
- location -= gfx::Vector2d(kXStep, 0);
- timestamp += base::TimeDelta::FromMilliseconds(10);
-
- while (location.x() > bounds.x() + kXStep) {
- ui::TouchEvent inc(
- ui::ET_TOUCH_MOVED, location, timestamp,
- ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0));
- details = sink->OnEventFromSource(&inc);
- ASSERT_FALSE(details.dispatcher_destroyed);
- WaitAFrame();
- location -= gfx::Vector2d(10, 0);
- timestamp += base::TimeDelta::FromMilliseconds(10);
- }
-
- ui::TouchEvent release(
- ui::ET_TOUCH_RELEASED, location, timestamp,
- ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0));
- details = sink->OnEventFromSource(&release);
- ASSERT_FALSE(details.dispatcher_destroyed);
- WaitAFrame();
-
- EXPECT_EQ(0, tracker.num_overscroll_updates());
- EXPECT_FALSE(tracker.overscroll_completed());
- }
-
- // Overscroll vertically.
- {
- tracker.Reset();
-
- int kYStep = bounds.height() / 10;
- gfx::Point location(bounds.x() + 10, bounds.y() + kYStep);
- base::TimeTicks timestamp = ui::EventTimeForNow();
- ui::TouchEvent press(
- ui::ET_TOUCH_PRESSED, location, timestamp,
- ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0));
- ui::EventDispatchDetails details = sink->OnEventFromSource(&press);
- ASSERT_FALSE(details.dispatcher_destroyed);
- WaitAFrame();
- location += gfx::Vector2d(0, kYStep);
- timestamp += base::TimeDelta::FromMilliseconds(10);
-
- while (location.y() < bounds.bottom() - kYStep) {
- ui::TouchEvent inc(
- ui::ET_TOUCH_MOVED, location, timestamp,
- ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0));
- details = sink->OnEventFromSource(&inc);
- ASSERT_FALSE(details.dispatcher_destroyed);
- WaitAFrame();
- location += gfx::Vector2d(0, kYStep);
- timestamp += base::TimeDelta::FromMilliseconds(10);
- }
-
- ui::TouchEvent release(
- ui::ET_TOUCH_RELEASED, location, timestamp,
- ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0));
- details = sink->OnEventFromSource(&release);
- ASSERT_FALSE(details.dispatcher_destroyed);
- WaitAFrame();
-
- EXPECT_LT(0, tracker.num_overscroll_updates());
- EXPECT_TRUE(tracker.overscroll_completed());
- }
-
- // Start out overscrolling vertically, then switch directions and finish
- // overscrolling horizontally.
- {
- tracker.Reset();
-
- int kXStep = bounds.width() / 10;
- int kYStep = bounds.height() / 10;
- gfx::Point location = bounds.origin() + gfx::Vector2d(0, kYStep);
- base::TimeTicks timestamp = ui::EventTimeForNow();
- ui::TouchEvent press(
- ui::ET_TOUCH_PRESSED, location, timestamp,
- ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0));
- ui::EventDispatchDetails details = sink->OnEventFromSource(&press);
- ASSERT_FALSE(details.dispatcher_destroyed);
- WaitAFrame();
- location += gfx::Vector2d(0, kYStep);
- timestamp += base::TimeDelta::FromMilliseconds(10);
-
- for (size_t i = 0; i < 3; ++i) {
- ui::TouchEvent inc(
- ui::ET_TOUCH_MOVED, location, timestamp,
- ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0));
- details = sink->OnEventFromSource(&inc);
- ASSERT_FALSE(details.dispatcher_destroyed);
- WaitAFrame();
- location += gfx::Vector2d(0, kYStep);
- timestamp += base::TimeDelta::FromMilliseconds(10);
- }
-
- while (location.x() < bounds.right() - kXStep) {
- ui::TouchEvent inc(
- ui::ET_TOUCH_MOVED, location, timestamp,
- ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0));
- details = sink->OnEventFromSource(&inc);
- ASSERT_FALSE(details.dispatcher_destroyed);
- WaitAFrame();
- location += gfx::Vector2d(kXStep, 0);
- timestamp += base::TimeDelta::FromMilliseconds(10);
- }
-
- ui::TouchEvent release(
- ui::ET_TOUCH_RELEASED, location, timestamp,
- ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0));
- details = sink->OnEventFromSource(&release);
- ASSERT_FALSE(details.dispatcher_destroyed);
- WaitAFrame();
-
- EXPECT_LT(0, tracker.num_overscroll_updates());
- EXPECT_FALSE(tracker.overscroll_completed());
- }
-}
-
} // namespace content
diff --git a/chromium/content/browser/web_contents/web_contents_view_aura_unittest.cc b/chromium/content/browser/web_contents/web_contents_view_aura_unittest.cc
index 97ad227840e..8cdf310e717 100644
--- a/chromium/content/browser/web_contents/web_contents_view_aura_unittest.cc
+++ b/chromium/content/browser/web_contents/web_contents_view_aura_unittest.cc
@@ -41,30 +41,4 @@ TEST_F(WebContentsViewAuraTest, ScreenInfoColorDepth) {
EXPECT_EQ(8u, screen_info.depth_per_component);
}
-// This test class is used when we want to have the kEnableHDROutput flag on.
-class WebContentsViewAuraHDRTest : public WebContentsViewAuraTest {
- public:
- WebContentsViewAuraHDRTest() = default;
- ~WebContentsViewAuraHDRTest() override = default;
-
- void SetUp() override {
- base::CommandLine* command_line =
- scoped_command_line_.GetProcessCommandLine();
- command_line->AppendSwitch(switches::kEnableHDR);
- WebContentsViewAuraTest::SetUp();
- }
-
- private:
- base::test::ScopedCommandLine scoped_command_line_;
-};
-
-TEST_F(WebContentsViewAuraHDRTest, ScreenInfoColorDepth) {
- WebContentsView* web_contents_view = view();
-
- ScreenInfo screen_info;
- web_contents_view->GetScreenInfo(&screen_info);
- EXPECT_EQ(48u, screen_info.depth);
- EXPECT_EQ(16u, screen_info.depth_per_component);
-}
-
} // namespace content
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 eb309e725c2..e1aca335ede 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
@@ -6,7 +6,7 @@
#include "build/build_config.h"
#include "content/browser/frame_host/render_frame_proxy_host.h"
-#include "content/browser/frame_host/render_widget_host_view_child_frame.h"
+#include "content/browser/renderer_host/render_widget_host_view_child_frame.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/web_contents_view_delegate.h"
#include "ui/gfx/geometry/rect.h"
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 34945ac1317..12675d077c8 100644
--- a/chromium/content/browser/web_contents/web_contents_view_mac.h
+++ b/chromium/content/browser/web_contents/web_contents_view_mac.h
@@ -49,7 +49,6 @@ CONTENT_EXPORT
}
- (void)setMouseDownCanMoveWindow:(BOOL)canMove;
-- (void)setOpaque:(BOOL)opaque;
// Returns the available drag operations. This is a required method for
// NSDraggingSource. It is supposedly deprecated, but the non-deprecated API
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 f256f696455..92b48b71163 100644
--- a/chromium/content/browser/web_contents/web_contents_view_mac.mm
+++ b/chromium/content/browser/web_contents/web_contents_view_mac.mm
@@ -90,6 +90,7 @@ content::ScreenInfo GetNSViewScreenInfo(NSView* view) {
content::ScreenInfo results;
results.device_scale_factor = static_cast<int>(display.device_scale_factor());
results.color_space = display.color_space();
+ results.color_space.GetICCProfile(&results.icc_profile);
results.depth = display.color_depth();
results.depth_per_component = display.depth_per_component();
results.is_monochrome = display.is_monochrome();
@@ -541,16 +542,6 @@ void WebContentsViewMac::CloseTab() {
return mouseDownCanMoveWindow_;
}
-- (void)setOpaque:(BOOL)opaque {
- WebContentsImpl* webContents = [self webContents];
- if (!webContents)
- return;
- RenderWidgetHostViewMac* view = static_cast<RenderWidgetHostViewMac*>(
- webContents->GetRenderWidgetHostView());
- DCHECK(view);
- [view->cocoa_view() setOpaque:opaque];
-}
-
- (void)pasteboard:(NSPasteboard*)sender provideDataForType:(NSString*)type {
[dragSource_ lazyWriteToPasteboard:sender
forType:type];
@@ -687,6 +678,9 @@ void WebContentsViewMac::CloseTab() {
- (void)setFrameSize:(NSSize)newSize {
[super setFrameSize:newSize];
+ if (webContentsView_ && webContentsView_->delegate())
+ webContentsView_->delegate()->SizeChanged(gfx::Size(newSize));
+
// Perform manual layout of subviews, e.g., when the window size changes.
for (NSView* subview in [self subviews])
[subview setFrame:[self bounds]];
diff --git a/chromium/content/browser/web_contents_binding_set_browsertest.cc b/chromium/content/browser/web_contents_binding_set_browsertest.cc
index 63435d11a6b..f3bbbc2121f 100644
--- a/chromium/content/browser/web_contents_binding_set_browsertest.cc
+++ b/chromium/content/browser/web_contents_binding_set_browsertest.cc
@@ -4,6 +4,7 @@
#include "base/macros.h"
#include "base/memory/ptr_util.h"
+#include "base/run_loop.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/web_contents_binding_set.h"
#include "content/public/test/browser_test_utils.h"
diff --git a/chromium/content/browser/webauth/authenticator_impl.cc b/chromium/content/browser/webauth/authenticator_impl.cc
index 4b798fc45f4..bc89ca45d04 100644
--- a/chromium/content/browser/webauth/authenticator_impl.cc
+++ b/chromium/content/browser/webauth/authenticator_impl.cc
@@ -63,7 +63,7 @@ void AuthenticatorImpl::MakeCredential(
// opaque origin
if (caller_origin_.unique()) {
std::move(callback).Run(
- webauth::mojom::AuthenticatorStatus::NOT_ALLOWED_ERROR, NULL);
+ webauth::mojom::AuthenticatorStatus::NOT_ALLOWED_ERROR, nullptr);
return;
}
@@ -79,9 +79,14 @@ void AuthenticatorImpl::MakeCredential(
relying_party_id = options->relying_party->id;
}
- // TODO(kpaulhamus): Check ScopedCredentialParameter's type and
- // algorithmIdentifier after algorithmIdentifier is added to mojom to
- // make sure it is U2F_V2.
+ // Check that at least one of the cryptographic parameters is supported.
+ // Only ES256 is currently supported by U2F_V2.
+ if (!HasValidAlgorithm(options->crypto_parameters)) {
+ std::move(callback).Run(
+ webauth::mojom::AuthenticatorStatus::NOT_SUPPORTED_ERROR, nullptr);
+ return;
+ }
+
client_data.SetString(kTypeKey, kMakeCredentialType);
client_data.SetString(kChallengeKey,
base::StringPiece(reinterpret_cast<const char*>(
@@ -103,4 +108,13 @@ void AuthenticatorImpl::MakeCredential(
nullptr);
}
+bool AuthenticatorImpl::HasValidAlgorithm(
+ const std::vector<webauth::mojom::PublicKeyCredentialParametersPtr>&
+ parameters) {
+ for (const auto& params : parameters) {
+ if (params->algorithm_identifier == -7)
+ return true;
+ }
+ return false;
+}
} // namespace content
diff --git a/chromium/content/browser/webauth/authenticator_impl.h b/chromium/content/browser/webauth/authenticator_impl.h
index 99ae045cc84..6f19c52570c 100644
--- a/chromium/content/browser/webauth/authenticator_impl.h
+++ b/chromium/content/browser/webauth/authenticator_impl.h
@@ -20,8 +20,7 @@ namespace content {
class RenderFrameHost;
// Implementation of the public Authenticator interface.
-class CONTENT_EXPORT AuthenticatorImpl
- : public NON_EXPORTED_BASE(webauth::mojom::Authenticator) {
+class CONTENT_EXPORT AuthenticatorImpl : public webauth::mojom::Authenticator {
public:
static void Create(RenderFrameHost* render_frame_host,
webauth::mojom::AuthenticatorRequest request);
@@ -38,6 +37,10 @@ class CONTENT_EXPORT AuthenticatorImpl
void MakeCredential(webauth::mojom::MakeCredentialOptionsPtr options,
MakeCredentialCallback callback) override;
+ bool HasValidAlgorithm(
+ const std::vector<webauth::mojom::PublicKeyCredentialParametersPtr>&
+ parameters);
+
base::Closure connection_error_handler_;
base::CancelableClosure timeout_callback_;
url::Origin caller_origin_;
@@ -46,4 +49,4 @@ class CONTENT_EXPORT AuthenticatorImpl
} // namespace content
-#endif // CONTENT_BROWSER_WEBAUTH_AUTHENTICATOR_IMPL_H_ \ No newline at end of file
+#endif // CONTENT_BROWSER_WEBAUTH_AUTHENTICATOR_IMPL_H_
diff --git a/chromium/content/browser/webauth/authenticator_impl_unittest.cc b/chromium/content/browser/webauth/authenticator_impl_unittest.cc
index d50dd8d9d56..655a6d00471 100644
--- a/chromium/content/browser/webauth/authenticator_impl_unittest.cc
+++ b/chromium/content/browser/webauth/authenticator_impl_unittest.cc
@@ -34,6 +34,47 @@ using webauth::mojom::PublicKeyCredentialParametersPtr;
const char* kOrigin1 = "https://google.com";
+namespace {
+
+const int32_t algorithm_identifier = -7;
+
+PublicKeyCredentialEntityPtr GetTestPublicKeyCredentialRPEntity() {
+ auto entity = PublicKeyCredentialEntity::New();
+ entity->id = std::string("localhost");
+ entity->name = std::string("TestRP@example.com");
+ return entity;
+}
+
+PublicKeyCredentialEntityPtr GetTestPublicKeyCredentialUserEntity() {
+ auto entity = PublicKeyCredentialEntity::New();
+ entity->display_name = std::string("User A. Name");
+ entity->id = std::string("1098237235409872");
+ entity->name = std::string("username@example.com");
+ entity->icon = GURL("fakeurl2.png");
+ return entity;
+}
+
+std::vector<PublicKeyCredentialParametersPtr>
+GetTestPublicKeyCredentialParameters() {
+ std::vector<PublicKeyCredentialParametersPtr> parameters;
+ auto fake_parameter = PublicKeyCredentialParameters::New();
+ fake_parameter->type = webauth::mojom::PublicKeyCredentialType::PUBLIC_KEY;
+ fake_parameter->algorithm_identifier = algorithm_identifier;
+ parameters.push_back(std::move(fake_parameter));
+ return parameters;
+}
+
+MakeCredentialOptionsPtr GetTestMakeCredentialOptions() {
+ auto options = MakeCredentialOptions::New();
+ std::vector<uint8_t> buffer(32, 0x0A);
+ options->relying_party = GetTestPublicKeyCredentialRPEntity();
+ options->user = GetTestPublicKeyCredentialUserEntity();
+ options->crypto_parameters = GetTestPublicKeyCredentialParameters();
+ options->challenge = std::move(buffer);
+ options->adjusted_timeout = base::TimeDelta::FromMinutes(1);
+ return options;
+}
+
class AuthenticatorImplTest : public content::RenderViewHostTestHarness {
public:
AuthenticatorImplTest() {}
@@ -89,50 +130,16 @@ class TestMakeCredentialCallback {
base::RunLoop run_loop_;
};
-PublicKeyCredentialEntityPtr GetTestPublicKeyCredentialRPEntity() {
- auto entity = PublicKeyCredentialEntity::New();
- entity->id = std::string("localhost");
- entity->name = std::string("TestRP@example.com");
- return entity;
-}
-
-PublicKeyCredentialEntityPtr GetTestPublicKeyCredentialUserEntity() {
- auto entity = PublicKeyCredentialEntity::New();
- entity->display_name = std::string("User A. Name");
- entity->id = std::string("1098237235409872");
- entity->name = std::string("TestRP@example.com");
- entity->icon = GURL("fakeurl2.png");
- return entity;
-}
-
-std::vector<PublicKeyCredentialParametersPtr>
-GetTestPublicKeyCredentialParameters() {
- std::vector<PublicKeyCredentialParametersPtr> parameters;
- auto fake_parameter = PublicKeyCredentialParameters::New();
- fake_parameter->type = webauth::mojom::PublicKeyCredentialType::PUBLIC_KEY;
- parameters.push_back(std::move(fake_parameter));
- return parameters;
-}
-
-MakeCredentialOptionsPtr GetTestMakeCredentialOptions() {
- auto opts = MakeCredentialOptions::New();
- std::vector<uint8_t> buffer(32, 0x0A);
- opts->relying_party = GetTestPublicKeyCredentialRPEntity();
- opts->user = GetTestPublicKeyCredentialUserEntity();
- opts->crypto_parameters = GetTestPublicKeyCredentialParameters();
- opts->challenge = std::move(buffer);
- opts->adjusted_timeout = base::TimeDelta::FromMinutes(1);
- return opts;
-}
+} // namespace
// Test that service returns NOT_IMPLEMENTED on a call to MakeCredential.
TEST_F(AuthenticatorImplTest, MakeCredentialNotImplemented) {
SimulateNavigation(GURL(kOrigin1));
AuthenticatorPtr authenticator = ConnectToAuthenticator();
- MakeCredentialOptionsPtr opts = GetTestMakeCredentialOptions();
+ MakeCredentialOptionsPtr options = GetTestMakeCredentialOptions();
TestMakeCredentialCallback cb;
- authenticator->MakeCredential(std::move(opts), cb.callback());
+ authenticator->MakeCredential(std::move(options), cb.callback());
std::pair<webauth::mojom::AuthenticatorStatus,
webauth::mojom::PublicKeyCredentialInfoPtr>& response =
cb.WaitForCallback();
@@ -146,10 +153,10 @@ TEST_F(AuthenticatorImplTest, MakeCredentialOpaqueOrigin) {
NavigateAndCommit(GURL("data:text/html,opaque"));
AuthenticatorPtr authenticator = ConnectToAuthenticator();
- MakeCredentialOptionsPtr opts = GetTestMakeCredentialOptions();
+ MakeCredentialOptionsPtr options = GetTestMakeCredentialOptions();
TestMakeCredentialCallback cb;
- authenticator->MakeCredential(std::move(opts), cb.callback());
+ authenticator->MakeCredential(std::move(options), cb.callback());
std::pair<webauth::mojom::AuthenticatorStatus,
webauth::mojom::PublicKeyCredentialInfoPtr>& response =
cb.WaitForCallback();
diff --git a/chromium/content/browser/webrtc/webrtc_audio_browsertest.cc b/chromium/content/browser/webrtc/webrtc_audio_browsertest.cc
index dabe2f6de9d..5b66e50b2a3 100644
--- a/chromium/content/browser/webrtc/webrtc_audio_browsertest.cc
+++ b/chromium/content/browser/webrtc/webrtc_audio_browsertest.cc
@@ -61,16 +61,8 @@ class MAYBE_WebRtcAudioBrowserTest : public WebRtcContentBrowserTestBase {
}
};
-// Flaky on Linux. http://crbug.com/733551
-#if defined(OS_LINUX)
-#define MAYBE_CanMakeVideoCallAndThenRenegotiateToAudio \
- DISABLED_CanMakeVideoCallAndThenRenegotiateToAudio
-#else
-#define MAYBE_CanMakeVideoCallAndThenRenegotiateToAudio \
- CanMakeVideoCallAndThenRenegotiateToAudio
-#endif
IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcAudioBrowserTest,
- MAYBE_CanMakeVideoCallAndThenRenegotiateToAudio) {
+ CanMakeVideoCallAndThenRenegotiateToAudio) {
MakeAudioDetectingPeerConnectionCall(
"callAndRenegotiateToAudio({audio: true, video:true}, {audio: true});");
}
diff --git a/chromium/content/browser/webrtc/webrtc_browsertest.cc b/chromium/content/browser/webrtc/webrtc_browsertest.cc
index cc0d2556448..d9ca2c24c75 100644
--- a/chromium/content/browser/webrtc/webrtc_browsertest.cc
+++ b/chromium/content/browser/webrtc/webrtc_browsertest.cc
@@ -151,8 +151,16 @@ IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,
// MSID and bundle attribute from the initial offer to verify that
// video is playing for the call even if the initiating client don't support
// MSID. http://tools.ietf.org/html/draft-alvestrand-rtcweb-msid-02
+// Fails with TSAN. https://crbug.com/756568
+#if defined(THREAD_SANITIZER)
+#define MAYBE_CanSetupAudioAndVideoCallWithoutMsidAndBundle \
+ DISABLED_CanSetupAudioAndVideoCallWithoutMsidAndBundle
+#else
+#define MAYBE_CanSetupAudioAndVideoCallWithoutMsidAndBundle \
+ CanSetupAudioAndVideoCallWithoutMsidAndBundle
+#endif
IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,
- CanSetupAudioAndVideoCallWithoutMsidAndBundle) {
+ MAYBE_CanSetupAudioAndVideoCallWithoutMsidAndBundle) {
MakeTypicalPeerConnectionCall("callWithoutMsidAndBundle();");
}
diff --git a/chromium/content/browser/webrtc/webrtc_capture_from_element_browsertest.cc b/chromium/content/browser/webrtc/webrtc_capture_from_element_browsertest.cc
index 74220174eb3..008ee47fac2 100644
--- a/chromium/content/browser/webrtc/webrtc_capture_from_element_browsertest.cc
+++ b/chromium/content/browser/webrtc/webrtc_capture_from_element_browsertest.cc
@@ -98,7 +98,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcCaptureFromElementBrowserTest,
}
IN_PROC_BROWSER_TEST_F(WebRtcCaptureFromElementBrowserTest,
- DISABLED_VerifyCanvasCaptureWebGLFrames) {
+ VerifyCanvasCaptureWebGLFrames) {
MakeTypicalCall("testCanvasCapture(drawWebGL);", kCanvasCaptureTestHtmlFile);
}
diff --git a/chromium/content/browser/webrtc/webrtc_content_browsertest_base.cc b/chromium/content/browser/webrtc/webrtc_content_browsertest_base.cc
index 91a8a77e89c..e7f817e92d9 100644
--- a/chromium/content/browser/webrtc/webrtc_content_browsertest_base.cc
+++ b/chromium/content/browser/webrtc/webrtc_content_browsertest_base.cc
@@ -5,6 +5,7 @@
#include "content/browser/webrtc/webrtc_content_browsertest_base.h"
#include "base/command_line.h"
+#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
diff --git a/chromium/content/browser/webrtc/webrtc_depth_capture_browsertest.cc b/chromium/content/browser/webrtc/webrtc_depth_capture_browsertest.cc
index 97a8e5ec659..f2936a8bcc0 100644
--- a/chromium/content/browser/webrtc/webrtc_depth_capture_browsertest.cc
+++ b/chromium/content/browser/webrtc/webrtc_depth_capture_browsertest.cc
@@ -93,7 +93,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcTwoDeviceDepthCaptureBrowserTest,
GetDepthStreamAndCameraCalibration) {
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
command_line->AppendSwitchASCII("--enable-blink-features",
- "MediaGetSettings,MediaCaptureDepth");
+ "MediaCaptureDepth");
ASSERT_TRUE(embedded_test_server()->Start());
@@ -118,7 +118,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcTwoDeviceDepthCaptureBrowserTest,
MAYBE_GetBothStreamsAndCheckForFeaturesPresence) {
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
command_line->AppendSwitchASCII("--enable-blink-features",
- "MediaGetSettings,MediaCaptureDepth");
+ "MediaCaptureDepth");
ASSERT_TRUE(embedded_test_server()->Start());
@@ -134,7 +134,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcTwoDeviceDepthCaptureBrowserTest,
GetStreamsByVideoKind) {
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
command_line->AppendSwitchASCII("--enable-blink-features",
- "MediaGetSettings,MediaCaptureDepth");
+ "MediaCaptureDepthVideoKind");
ASSERT_TRUE(embedded_test_server()->Start());
@@ -150,7 +150,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcOneDeviceDepthCaptureBrowserTest,
GetStreamsByVideoKindNoDepth) {
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
command_line->AppendSwitchASCII("--enable-blink-features",
- "MediaGetSettings,MediaCaptureDepth");
+ "MediaCaptureDepthVideoKind");
ASSERT_TRUE(embedded_test_server()->Start());
diff --git a/chromium/content/browser/webrtc/webrtc_eventlog_host_unittest.cc b/chromium/content/browser/webrtc/webrtc_eventlog_host_unittest.cc
index 776c80d58c4..06a39035a2a 100644
--- a/chromium/content/browser/webrtc/webrtc_eventlog_host_unittest.cc
+++ b/chromium/content/browser/webrtc/webrtc_eventlog_host_unittest.cc
@@ -4,6 +4,7 @@
#include "content/browser/webrtc/webrtc_eventlog_host.h"
+#include <set>
#include <tuple>
#include "base/files/file.h"
@@ -11,6 +12,7 @@
#include "base/strings/string_number_conversions.h"
#include "base/task_scheduler/post_task.h"
#include "base/task_scheduler/task_traits.h"
+#include "build/build_config.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/common/media/peer_connection_tracker_messages.h"
#include "content/public/browser/browser_context.h"
@@ -80,6 +82,23 @@ class WebRtcEventlogHostTest : public testing::Test {
IPC::PlatformFileForTransitToFile(std::get<1>(start_params)).Close();
}
+ // This version of the function returns the peer connection ID instead of
+ // validating it.
+ int ReadStartIPCMessageAndCloseFile(const IPC::Message* msg) {
+ EXPECT_TRUE(msg);
+ if (msg) {
+ std::tuple<int, IPC::PlatformFileForTransit> start_params;
+ PeerConnectionTracker_StartEventLog::Read(msg, &start_params);
+ EXPECT_NE(IPC::InvalidPlatformFileForTransit(),
+ std::get<1>(start_params));
+ if (std::get<1>(start_params) != IPC::InvalidPlatformFileForTransit()) {
+ IPC::PlatformFileForTransitToFile(std::get<1>(start_params)).Close();
+ }
+ return std::get<0>(start_params);
+ }
+ return -1;
+ }
+
void ValidateStopIPCMessage(const IPC::Message* msg,
const int peer_connection_id) {
ASSERT_TRUE(msg);
@@ -87,6 +106,18 @@ class WebRtcEventlogHostTest : public testing::Test {
PeerConnectionTracker_StopEventLog::Read(msg, &stop_params);
EXPECT_EQ(peer_connection_id, std::get<0>(stop_params));
}
+
+ // This version of the function returns the peer connection ID instead of
+ // validating it.
+ int ReadStopIPCMessage(const IPC::Message* msg) {
+ EXPECT_TRUE(msg);
+ if (msg) {
+ std::tuple<int> stop_params;
+ PeerConnectionTracker_StopEventLog::Read(msg, &stop_params);
+ return std::get<0>(stop_params);
+ }
+ return -1;
+ }
};
// This test calls StartWebRTCEventLog() and StopWebRTCEventLog() without having
@@ -141,6 +172,7 @@ TEST_F(WebRtcEventlogHostTest, OnePeerConnectionTest) {
// two PeerConnections. It is expected that two IPC messages will be sent for
// each of the Start and Stop calls, and that a file is created for both
// PeerConnections.
+
TEST_F(WebRtcEventlogHostTest, TwoPeerConnectionsTest) {
const int kTestPeerConnectionId1 = 123;
const int kTestPeerConnectionId2 = 321;
@@ -155,10 +187,15 @@ TEST_F(WebRtcEventlogHostTest, TwoPeerConnectionsTest) {
EXPECT_EQ(size_t(2), mock_render_process_host_->sink().message_count());
const IPC::Message* start_msg1 =
mock_render_process_host_->sink().GetMessageAt(0);
- ValidateStartIPCMessageAndCloseFile(start_msg1, kTestPeerConnectionId1);
+ int start_msg1_id = ReadStartIPCMessageAndCloseFile(start_msg1);
const IPC::Message* start_msg2 =
mock_render_process_host_->sink().GetMessageAt(1);
- ValidateStartIPCMessageAndCloseFile(start_msg2, kTestPeerConnectionId2);
+ int start_msg2_id = ReadStartIPCMessageAndCloseFile(start_msg2);
+
+ const std::set<int> expected_ids = {kTestPeerConnectionId1,
+ kTestPeerConnectionId2};
+ std::set<int> actual_start_ids = {start_msg1_id, start_msg2_id};
+ EXPECT_EQ(expected_ids, actual_start_ids);
// Stop logging.
mock_render_process_host_->sink().ClearMessages();
@@ -168,10 +205,13 @@ TEST_F(WebRtcEventlogHostTest, TwoPeerConnectionsTest) {
EXPECT_EQ(size_t(2), mock_render_process_host_->sink().message_count());
const IPC::Message* stop_msg1 =
mock_render_process_host_->sink().GetMessageAt(0);
- ValidateStopIPCMessage(stop_msg1, kTestPeerConnectionId1);
+ int stop_msg1_id = ReadStopIPCMessage(stop_msg1);
const IPC::Message* stop_msg2 =
mock_render_process_host_->sink().GetMessageAt(1);
- ValidateStopIPCMessage(stop_msg2, kTestPeerConnectionId2);
+ int stop_msg2_id = ReadStopIPCMessage(stop_msg2);
+
+ std::set<int> actual_stop_ids = {stop_msg1_id, stop_msg2_id};
+ EXPECT_EQ(expected_ids, actual_stop_ids);
// Clean up the logfiles.
base::FilePath expected_file1 = GetExpectedEventLogFileName(
@@ -189,7 +229,7 @@ TEST_F(WebRtcEventlogHostTest, TwoPeerConnectionsTest) {
// maximum allowed number of IPC messages and log files will be opened, but we
// expect the number of stop IPC messages to be equal to the actual number of
// PeerConnections.
-TEST_F(WebRtcEventlogHostTest, DISABLED_ExceedMaxPeerConnectionsTest) {
+TEST_F(WebRtcEventlogHostTest, ExceedMaxPeerConnectionsTest) {
#if defined(OS_ANDROID)
const int kMaxNumberLogFiles = 3;
#else
@@ -204,12 +244,18 @@ TEST_F(WebRtcEventlogHostTest, DISABLED_ExceedMaxPeerConnectionsTest) {
StartLogging();
// Check that the correct IPC messages were sent.
- ASSERT_EQ(size_t(kMaxNumberLogFiles),
- mock_render_process_host_->sink().message_count());
- for (int i = 0; i < kMaxNumberLogFiles; ++i) {
- const IPC::Message* start_msg =
- mock_render_process_host_->sink().GetMessageAt(i);
- ValidateStartIPCMessageAndCloseFile(start_msg, i);
+ {
+ std::set<int> actual_ids, expected_ids;
+ ASSERT_EQ(size_t(kMaxNumberLogFiles),
+ mock_render_process_host_->sink().message_count());
+ for (int i = 0; i < kMaxNumberLogFiles; ++i) {
+ const IPC::Message* start_msg =
+ mock_render_process_host_->sink().GetMessageAt(i);
+ int id = ReadStartIPCMessageAndCloseFile(start_msg);
+ actual_ids.insert(id);
+ expected_ids.insert(i);
+ }
+ EXPECT_EQ(actual_ids, expected_ids);
}
// Stop logging.
@@ -217,12 +263,18 @@ TEST_F(WebRtcEventlogHostTest, DISABLED_ExceedMaxPeerConnectionsTest) {
StopLogging();
// Check that the correct IPC messages were sent.
- ASSERT_EQ(size_t(kNumberOfPeerConnections),
- mock_render_process_host_->sink().message_count());
- for (int i = 0; i < kNumberOfPeerConnections; ++i) {
- const IPC::Message* stop_msg =
- mock_render_process_host_->sink().GetMessageAt(i);
- ValidateStopIPCMessage(stop_msg, i);
+ {
+ std::set<int> actual_ids, expected_ids;
+ ASSERT_EQ(size_t(kNumberOfPeerConnections),
+ mock_render_process_host_->sink().message_count());
+ for (int i = 0; i < kNumberOfPeerConnections; ++i) {
+ const IPC::Message* stop_msg =
+ mock_render_process_host_->sink().GetMessageAt(i);
+ int id = ReadStopIPCMessage(stop_msg);
+ actual_ids.insert(id);
+ expected_ids.insert(i);
+ }
+ EXPECT_EQ(actual_ids, expected_ids);
}
// Clean up the logfiles.
diff --git a/chromium/content/browser/webrtc/webrtc_getusermedia_browsertest.cc b/chromium/content/browser/webrtc/webrtc_getusermedia_browsertest.cc
index 8f8acbfa140..31b92fb2f73 100644
--- a/chromium/content/browser/webrtc/webrtc_getusermedia_browsertest.cc
+++ b/chromium/content/browser/webrtc/webrtc_getusermedia_browsertest.cc
@@ -712,8 +712,9 @@ IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
// This test calls getUserMedia in an iframe and immediately close the iframe
// in the scope of the success callback.
+// Flaky: crbug.com/727601.
IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
- AudioInIFrameAndCloseInSuccessCb) {
+ DISABLED_AudioInIFrameAndCloseInSuccessCb) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
@@ -1504,4 +1505,39 @@ IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
"failTestAfterTimeout('Got no mute event', 1500);"));
}
+IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest, SrcObjectAddVideoTrack) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+ GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
+ NavigateToURL(shell(), url);
+ ExecuteJavascriptAndWaitForOk("srcObjectAddVideoTrack()");
+}
+
+IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
+ SrcObjectRemoveVideoTrack) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+ GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
+ NavigateToURL(shell(), url);
+ ExecuteJavascriptAndWaitForOk("srcObjectRemoveVideoTrack()");
+}
+
+IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
+ SrcObjectRemoveFirstOfTwoVideoTracks) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+ GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
+ NavigateToURL(shell(), url);
+ ExecuteJavascriptAndWaitForOk("srcObjectRemoveFirstOfTwoVideoTracks()");
+}
+
+// TODO(guidou): Add SrcObjectAddAudioTrack and SrcObjectRemoveAudioTrack tests
+// when a straightforward mechanism to detect the presence/absence of audio in a
+// media element with an assigned MediaStream becomes available.
+
+IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
+ SrcObjectReassignSameObject) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+ GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
+ NavigateToURL(shell(), url);
+ ExecuteJavascriptAndWaitForOk("srcObjectReassignSameObject()");
+}
+
} // namespace content
diff --git a/chromium/content/browser/webrtc/webrtc_internals.cc b/chromium/content/browser/webrtc/webrtc_internals.cc
index 46d187d58eb..6d32bc6155c 100644
--- a/chromium/content/browser/webrtc/webrtc_internals.cc
+++ b/chromium/content/browser/webrtc/webrtc_internals.cc
@@ -25,6 +25,7 @@
#include "services/device/public/interfaces/constants.mojom.h"
#include "services/device/public/interfaces/wake_lock_provider.mojom.h"
#include "services/service_manager/public/cpp/connector.h"
+#include "ui/shell_dialogs/select_file_policy.h"
#if defined(OS_WIN)
#define IntToStringType base::IntToString16
@@ -218,7 +219,7 @@ void WebRTCInternals::OnAddStats(base::ProcessId pid, int lid,
dict->SetInteger("pid", static_cast<int>(pid));
dict->SetInteger("lid", lid);
- dict->Set("reports", base::MakeUnique<base::Value>(value));
+ dict->SetKey("reports", value.Clone());
SendUpdate("addStats", std::move(dict));
}
@@ -293,16 +294,11 @@ void WebRTCInternals::EnableAudioDebugRecordings(
#else
selecting_event_log_ = false;
DCHECK(!select_file_dialog_);
- select_file_dialog_ = ui::SelectFileDialog::Create(this, NULL);
+ select_file_dialog_ = ui::SelectFileDialog::Create(this, nullptr);
select_file_dialog_->SelectFile(
- ui::SelectFileDialog::SELECT_SAVEAS_FILE,
- base::string16(),
- audio_debug_recordings_file_path_,
- NULL,
- 0,
- FILE_PATH_LITERAL(""),
- web_contents->GetTopLevelNativeWindow(),
- NULL);
+ ui::SelectFileDialog::SELECT_SAVEAS_FILE, base::string16(),
+ audio_debug_recordings_file_path_, NULL, 0, base::FilePath::StringType(),
+ web_contents->GetTopLevelNativeWindow(), NULL);
#endif
#endif
}
diff --git a/chromium/content/browser/webrtc/webrtc_internals_message_handler.cc b/chromium/content/browser/webrtc/webrtc_internals_message_handler.cc
index 409fc90ef10..70e5de61657 100644
--- a/chromium/content/browser/webrtc/webrtc_internals_message_handler.cc
+++ b/chromium/content/browser/webrtc/webrtc_internals_message_handler.cc
@@ -109,20 +109,21 @@ void WebRTCInternalsMessageHandler::OnDOMLoadDone(
const base::ListValue* /* unused_list */) {
webrtc_internals_->UpdateObserver(this);
- if (webrtc_internals_->IsAudioDebugRecordingsEnabled()) {
- RenderFrameHost* host = GetWebRTCInternalsHost();
- if (!host)
- return;
-
- std::vector<const base::Value*> args_vector;
- base::string16 script =
- WebUI::GetJavascriptCall("setAudioDebugRecordingsEnabled", args_vector);
- host->ExecuteJavaScript(script);
- }
+ if (webrtc_internals_->IsAudioDebugRecordingsEnabled())
+ ExecuteJavascriptCommand("setAudioDebugRecordingsEnabled", nullptr);
+
+ if (webrtc_internals_->IsEventLogRecordingsEnabled())
+ ExecuteJavascriptCommand("setEventLogRecordingsEnabled", nullptr);
}
void WebRTCInternalsMessageHandler::OnUpdate(const char* command,
const base::Value* args) {
+ ExecuteJavascriptCommand(command, args);
+}
+
+void WebRTCInternalsMessageHandler::ExecuteJavascriptCommand(
+ const char* command,
+ const base::Value* args) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
RenderFrameHost* host = GetWebRTCInternalsHost();
@@ -133,8 +134,8 @@ void WebRTCInternalsMessageHandler::OnUpdate(const char* command,
if (args)
args_vector.push_back(args);
- base::string16 update = WebUI::GetJavascriptCall(command, args_vector);
- host->ExecuteJavaScript(update);
+ base::string16 script = WebUI::GetJavascriptCall(command, args_vector);
+ host->ExecuteJavaScript(script);
}
} // namespace content
diff --git a/chromium/content/browser/webrtc/webrtc_internals_message_handler.h b/chromium/content/browser/webrtc/webrtc_internals_message_handler.h
index d5d21285f9a..b353617d289 100644
--- a/chromium/content/browser/webrtc/webrtc_internals_message_handler.h
+++ b/chromium/content/browser/webrtc/webrtc_internals_message_handler.h
@@ -23,7 +23,7 @@ class WebRTCInternals;
// It delegates all its work to WebRTCInternalsProxy on the IO thread.
class CONTENT_EXPORT WebRTCInternalsMessageHandler
: public WebUIMessageHandler,
- public NON_EXPORTED_BASE(WebRTCInternalsUIObserver) {
+ public WebRTCInternalsUIObserver {
public:
WebRTCInternalsMessageHandler();
~WebRTCInternalsMessageHandler() override;
@@ -52,6 +52,9 @@ class CONTENT_EXPORT WebRTCInternalsMessageHandler
// WebRTCInternalsUIObserver override.
void OnUpdate(const char* command, const base::Value* args) override;
+ // Executes Javascript command.
+ void ExecuteJavascriptCommand(const char* command, const base::Value* args);
+
DISALLOW_COPY_AND_ASSIGN(WebRTCInternalsMessageHandler);
};
diff --git a/chromium/content/browser/webrtc/webrtc_internals_message_handler_unittest.cc b/chromium/content/browser/webrtc/webrtc_internals_message_handler_unittest.cc
index f4e6ef37580..f830440ba53 100644
--- a/chromium/content/browser/webrtc/webrtc_internals_message_handler_unittest.cc
+++ b/chromium/content/browser/webrtc/webrtc_internals_message_handler_unittest.cc
@@ -36,7 +36,7 @@ class WebRTCInternalsMessageHandlerForTest
~WebRTCInternalsMessageHandlerForTest() override {}
};
-class WebRTCInternalsForTest : public NON_EXPORTED_BASE(WebRTCInternals) {
+class WebRTCInternalsForTest : public WebRTCInternals {
public:
WebRTCInternalsForTest() : WebRTCInternals(0, false) {}
~WebRTCInternalsForTest() override {}
diff --git a/chromium/content/browser/webrtc/webrtc_internals_unittest.cc b/chromium/content/browser/webrtc/webrtc_internals_unittest.cc
index 6e4fb8a5faf..ef2c5028bda 100644
--- a/chromium/content/browser/webrtc/webrtc_internals_unittest.cc
+++ b/chromium/content/browser/webrtc/webrtc_internals_unittest.cc
@@ -72,7 +72,7 @@ class MockWakeLock : public device::mojom::WakeLock {
// Derived class for testing only. Allows the tests to have their own instance
// for testing and control the period for which WebRTCInternals will bulk up
// updates (changes down from 500ms to 1ms).
-class WebRTCInternalsForTest : public NON_EXPORTED_BASE(WebRTCInternals) {
+class WebRTCInternalsForTest : public WebRTCInternals {
public:
WebRTCInternalsForTest()
: WebRTCInternals(1, true),
diff --git a/chromium/content/browser/websockets/websocket_impl.cc b/chromium/content/browser/websockets/websocket_impl.cc
index 7019bc5306d..9739cda2d48 100644
--- a/chromium/content/browser/websockets/websocket_impl.cc
+++ b/chromium/content/browser/websockets/websocket_impl.cc
@@ -375,8 +375,8 @@ WebSocketImpl::WebSocketImpl(Delegate* delegate,
frame_id_(frame_id),
handshake_succeeded_(false),
weak_ptr_factory_(this) {
- binding_.set_connection_error_handler(
- base::Bind(&WebSocketImpl::OnConnectionError, base::Unretained(this)));
+ binding_.set_connection_error_handler(base::BindOnce(
+ &WebSocketImpl::OnConnectionError, base::Unretained(this)));
}
WebSocketImpl::~WebSocketImpl() {}
@@ -390,17 +390,15 @@ void WebSocketImpl::AddChannelRequest(
const GURL& socket_url,
const std::vector<std::string>& requested_protocols,
const url::Origin& origin,
- const GURL& first_party_for_cookies,
+ const GURL& site_for_cookies,
const std::string& user_agent_override,
blink::mojom::WebSocketClientPtr client) {
DVLOG(3) << "WebSocketImpl::AddChannelRequest @"
- << reinterpret_cast<void*>(this)
- << " socket_url=\"" << socket_url << "\" requested_protocols=\""
- << base::JoinString(requested_protocols, ", ")
- << "\" origin=\"" << origin
- << "\" first_party_for_cookies=\"" << first_party_for_cookies
- << "\" user_agent_override=\"" << user_agent_override
- << "\"";
+ << reinterpret_cast<void*>(this) << " socket_url=\"" << socket_url
+ << "\" requested_protocols=\""
+ << base::JoinString(requested_protocols, ", ") << "\" origin=\""
+ << origin << "\" site_for_cookies=\"" << site_for_cookies
+ << "\" user_agent_override=\"" << user_agent_override << "\"";
if (client_ || !client) {
bad_message::ReceivedBadMessage(
@@ -415,16 +413,13 @@ void WebSocketImpl::AddChannelRequest(
if (delay_ > base::TimeDelta()) {
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE,
- base::Bind(&WebSocketImpl::AddChannel,
- weak_ptr_factory_.GetWeakPtr(),
- socket_url,
- requested_protocols,
- origin,
- first_party_for_cookies,
- user_agent_override),
+ base::BindOnce(&WebSocketImpl::AddChannel,
+ weak_ptr_factory_.GetWeakPtr(), socket_url,
+ requested_protocols, origin, site_for_cookies,
+ user_agent_override),
delay_);
} else {
- AddChannel(socket_url, requested_protocols, origin, first_party_for_cookies,
+ AddChannel(socket_url, requested_protocols, origin, site_for_cookies,
user_agent_override);
}
}
@@ -500,28 +495,20 @@ void WebSocketImpl::AddChannel(
const GURL& socket_url,
const std::vector<std::string>& requested_protocols,
const url::Origin& origin,
- const GURL& first_party_for_cookies,
+ const GURL& site_for_cookies,
const std::string& user_agent_override) {
- DVLOG(3) << "WebSocketImpl::AddChannel @"
- << reinterpret_cast<void*>(this)
- << " socket_url=\"" << socket_url
- << "\" requested_protocols=\""
- << base::JoinString(requested_protocols, ", ")
- << "\" origin=\"" << origin
- << "\" first_party_for_cookies=\"" << first_party_for_cookies
- << "\" user_agent_override=\"" << user_agent_override
- << "\"";
+ DVLOG(3) << "WebSocketImpl::AddChannel @" << reinterpret_cast<void*>(this)
+ << " socket_url=\"" << socket_url << "\" requested_protocols=\""
+ << base::JoinString(requested_protocols, ", ") << "\" origin=\""
+ << origin << "\" site_for_cookies=\"" << site_for_cookies
+ << "\" user_agent_override=\"" << user_agent_override << "\"";
DCHECK(!channel_);
- StoragePartition* partition = delegate_->GetStoragePartition();
-
std::unique_ptr<net::WebSocketEventInterface> event_interface(
new WebSocketEventHandler(this));
- channel_.reset(
- new net::WebSocketChannel(
- std::move(event_interface),
- partition->GetURLRequestContext()->GetURLRequestContext()));
+ channel_.reset(new net::WebSocketChannel(std::move(event_interface),
+ delegate_->GetURLRequestContext()));
int64_t quota = pending_flow_control_quota_;
pending_flow_control_quota_ = 0;
@@ -539,7 +526,7 @@ void WebSocketImpl::AddChannel(
user_agent_override.c_str());
}
channel_->SendAddChannelRequest(socket_url, requested_protocols, origin,
- first_party_for_cookies, additional_headers);
+ site_for_cookies, additional_headers);
if (quota > 0)
SendFlowControl(quota);
}
diff --git a/chromium/content/browser/websockets/websocket_impl.h b/chromium/content/browser/websockets/websocket_impl.h
index c6da13167ed..da6225b9d48 100644
--- a/chromium/content/browser/websockets/websocket_impl.h
+++ b/chromium/content/browser/websockets/websocket_impl.h
@@ -25,21 +25,20 @@ class Origin;
} // namespace url
namespace net {
+class URLRequestContext;
class WebSocketChannel;
} // namespace net
namespace content {
-class StoragePartition;
// Host of net::WebSocketChannel.
-class CONTENT_EXPORT WebSocketImpl
- : NON_EXPORTED_BASE(public blink::mojom::WebSocket) {
+class CONTENT_EXPORT WebSocketImpl : public blink::mojom::WebSocket {
public:
class Delegate {
public:
virtual ~Delegate() {}
virtual int GetClientProcessId() = 0;
- virtual StoragePartition* GetStoragePartition() = 0;
+ virtual net::URLRequestContext* GetURLRequestContext() = 0;
virtual void OnReceivedResponseFromServer(WebSocketImpl* impl) = 0;
virtual void OnLostConnectionToClient(WebSocketImpl* impl) = 0;
};
@@ -59,7 +58,7 @@ class CONTENT_EXPORT WebSocketImpl
void AddChannelRequest(const GURL& url,
const std::vector<std::string>& requested_protocols,
const url::Origin& origin,
- const GURL& first_party_for_cookies,
+ const GURL& site_for_cookies,
const std::string& user_agent_override,
blink::mojom::WebSocketClientPtr client) override;
void SendFrame(bool fin,
@@ -78,7 +77,7 @@ class CONTENT_EXPORT WebSocketImpl
void AddChannel(const GURL& socket_url,
const std::vector<std::string>& requested_protocols,
const url::Origin& origin,
- const GURL& first_party_for_cookies,
+ const GURL& site_for_cookies,
const std::string& user_agent_override);
Delegate* delegate_;
diff --git a/chromium/content/browser/websockets/websocket_manager.cc b/chromium/content/browser/websockets/websocket_manager.cc
index 081c482ab17..cf8638a4eb5 100644
--- a/chromium/content/browser/websockets/websocket_manager.cc
+++ b/chromium/content/browser/websockets/websocket_manager.cc
@@ -78,36 +78,30 @@ void WebSocketManager::CreateWebSocket(
DCHECK(handle->manager());
}
- BrowserThread::PostTask(
- BrowserThread::IO,
- FROM_HERE,
- base::Bind(&WebSocketManager::DoCreateWebSocket,
- base::Unretained(handle->manager()),
- frame_id,
- base::Passed(&request)));
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&WebSocketManager::DoCreateWebSocket,
+ base::Unretained(handle->manager()),
+ frame_id, base::Passed(&request)));
}
WebSocketManager::WebSocketManager(int process_id,
StoragePartition* storage_partition)
: process_id_(process_id),
- storage_partition_(storage_partition),
num_pending_connections_(0),
num_current_succeeded_connections_(0),
num_previous_succeeded_connections_(0),
num_current_failed_connections_(0),
num_previous_failed_connections_(0),
context_destroyed_(false) {
- if (storage_partition_) {
- url_request_context_getter_ = storage_partition_->GetURLRequestContext();
+ if (storage_partition) {
+ url_request_context_getter_ = storage_partition->GetURLRequestContext();
// 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::Bind(
- &WebSocketManager::ObserveURLRequestContextGetter,
- base::Unretained(this)));
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&WebSocketManager::ObserveURLRequestContextGetter,
+ base::Unretained(this)));
}
}
@@ -199,8 +193,8 @@ int WebSocketManager::GetClientProcessId() {
return process_id_;
}
-StoragePartition* WebSocketManager::GetStoragePartition() {
- return storage_partition_;
+net::URLRequestContext* WebSocketManager::GetURLRequestContext() {
+ return url_request_context_getter_->GetURLRequestContext();
}
void WebSocketManager::OnReceivedResponseFromServer(WebSocketImpl* impl) {
diff --git a/chromium/content/browser/websockets/websocket_manager.h b/chromium/content/browser/websockets/websocket_manager.h
index 3e76c997c55..6a0f0f86148 100644
--- a/chromium/content/browser/websockets/websocket_manager.h
+++ b/chromium/content/browser/websockets/websocket_manager.h
@@ -24,8 +24,8 @@ class StoragePartition;
// WebSocketImpl objects for each WebSocketRequest and throttling the number of
// WebSocketImpl objects in use.
class CONTENT_EXPORT WebSocketManager
- : NON_EXPORTED_BASE(public WebSocketImpl::Delegate),
- NON_EXPORTED_BASE(public net::URLRequestContextGetterObserver) {
+ : public WebSocketImpl::Delegate,
+ public net::URLRequestContextGetterObserver {
public:
// Called on the UI thread:
static void CreateWebSocket(
@@ -60,14 +60,13 @@ class CONTENT_EXPORT WebSocketManager
// WebSocketImpl::Delegate methods:
int GetClientProcessId() override;
- StoragePartition* GetStoragePartition() override;
+ net::URLRequestContext* GetURLRequestContext() override;
void OnReceivedResponseFromServer(WebSocketImpl* impl) override;
void OnLostConnectionToClient(WebSocketImpl* impl) override;
void ObserveURLRequestContextGetter();
int process_id_;
- StoragePartition* storage_partition_;
scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
std::set<WebSocketImpl*> impls_;
diff --git a/chromium/content/browser/webui/OWNERS b/chromium/content/browser/webui/OWNERS
index 7e3290f6d1c..8187af361be 100644
--- a/chromium/content/browser/webui/OWNERS
+++ b/chromium/content/browser/webui/OWNERS
@@ -1,4 +1,4 @@
-dbeam@chromium.org
+dpapad@chromium.org
groby@chromium.org
tommycli@chromium.org
diff --git a/chromium/content/browser/webui/shared_resources_data_source.cc b/chromium/content/browser/webui/shared_resources_data_source.cc
index 86f1cce409e..589c395687b 100644
--- a/chromium/content/browser/webui/shared_resources_data_source.cc
+++ b/chromium/content/browser/webui/shared_resources_data_source.cc
@@ -37,7 +37,9 @@ const char* const kPathAliases[][2] = {
"polymer/v1_0/web-animations-js/"},
{"../../views/resources/default_100_percent/common/", "images/apps/"},
{"../../views/resources/default_200_percent/common/", "images/2x/apps/"},
- {"../../webui/resources/cr_elements/", "cr_elements/"}};
+ {"../../webui/resources/cr_components/", "cr_components/"},
+ {"../../webui/resources/cr_elements/", "cr_elements/"},
+};
const struct {
const char* const path;
diff --git a/chromium/content/browser/webui/url_data_manager_backend.cc b/chromium/content/browser/webui/url_data_manager_backend.cc
index 495f3fe689e..de92dea74ee 100644
--- a/chromium/content/browser/webui/url_data_manager_backend.cc
+++ b/chromium/content/browser/webui/url_data_manager_backend.cc
@@ -653,7 +653,7 @@ scoped_refptr<net::HttpResponseHeaders> URLDataManagerBackend::GetHeaders(
bool URLDataManagerBackend::CheckURLIsValid(const GURL& url) {
std::vector<std::string> additional_schemes;
- DCHECK(url.SchemeIs(kChromeDevToolsScheme) || url.SchemeIs(kChromeUIScheme) ||
+ DCHECK(url.SchemeIs(kChromeUIScheme) ||
(GetContentClient()->browser()->GetAdditionalWebUISchemes(
&additional_schemes),
SchemeIsInSchemes(url.scheme(), additional_schemes)));
@@ -708,46 +708,4 @@ std::vector<std::string> URLDataManagerBackend::GetWebUISchemes() {
return schemes;
}
-namespace {
-
-class DevToolsJobFactory
- : public net::URLRequestJobFactory::ProtocolHandler {
- public:
- explicit DevToolsJobFactory(ResourceContext* resource_context);
- ~DevToolsJobFactory() override;
-
- net::URLRequestJob* MaybeCreateJob(
- net::URLRequest* request,
- net::NetworkDelegate* network_delegate) const override;
-
- private:
- // |resource_context_| and |network_delegate_| are owned by ProfileIOData,
- // which owns this ProtocolHandler.
- ResourceContext* const resource_context_;
-
- DISALLOW_COPY_AND_ASSIGN(DevToolsJobFactory);
-};
-
-DevToolsJobFactory::DevToolsJobFactory(ResourceContext* resource_context)
- : resource_context_(resource_context) {
- DCHECK(resource_context_);
-}
-
-DevToolsJobFactory::~DevToolsJobFactory() {}
-
-net::URLRequestJob*
-DevToolsJobFactory::MaybeCreateJob(
- net::URLRequest* request, net::NetworkDelegate* network_delegate) const {
- return new URLRequestChromeJob(
- request, network_delegate,
- GetURLDataManagerForResourceContext(resource_context_));
-}
-
-} // namespace
-
-net::URLRequestJobFactory::ProtocolHandler* CreateDevToolsProtocolHandler(
- ResourceContext* resource_context) {
- return new DevToolsJobFactory(resource_context);
-}
-
} // namespace content
diff --git a/chromium/content/browser/webui/url_data_manager_backend.h b/chromium/content/browser/webui/url_data_manager_backend.h
index da6464877fc..a6f3ab913fb 100644
--- a/chromium/content/browser/webui/url_data_manager_backend.h
+++ b/chromium/content/browser/webui/url_data_manager_backend.h
@@ -126,10 +126,6 @@ class URLDataManagerBackend : public base::SupportsUserData::Data {
DISALLOW_COPY_AND_ASSIGN(URLDataManagerBackend);
};
-// Creates protocol handler for chrome-devtools://.
-net::URLRequestJobFactory::ProtocolHandler* CreateDevToolsProtocolHandler(
- ResourceContext* resource_context);
-
} // namespace content
#endif // CONTENT_BROWSER_WEBUI_URL_DATA_MANAGER_BACKEND_H_
diff --git a/chromium/content/browser/webui/web_ui_data_source_impl.h b/chromium/content/browser/webui/web_ui_data_source_impl.h
index 2ef7552fd3a..93bdfe942a7 100644
--- a/chromium/content/browser/webui/web_ui_data_source_impl.h
+++ b/chromium/content/browser/webui/web_ui_data_source_impl.h
@@ -25,9 +25,8 @@ namespace content {
// A data source that can help with implementing the common operations
// needed by the chrome WEBUI settings/history/downloads pages.
-class CONTENT_EXPORT WebUIDataSourceImpl
- : public NON_EXPORTED_BASE(URLDataSourceImpl),
- public NON_EXPORTED_BASE(WebUIDataSource) {
+class CONTENT_EXPORT WebUIDataSourceImpl : public URLDataSourceImpl,
+ public WebUIDataSource {
public:
// WebUIDataSource implementation:
void AddString(const std::string& name, const base::string16& value) override;
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 46a0829ea35..e940e5c9395 100644
--- a/chromium/content/browser/webui/web_ui_message_handler_unittest.cc
+++ b/chromium/content/browser/webui/web_ui_message_handler_unittest.cc
@@ -7,6 +7,7 @@
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
+#include "content/public/test/test_web_ui.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
@@ -94,4 +95,64 @@ TEST(WebUIMessageHandlerTest, ExtractStringValue) {
EXPECT_EQ(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() override {
+ // The test handler unusually owns its own TestWebUI, so we make sure to
+ // unbind it from the base class before the derived class is destroyed.
+ set_web_ui(nullptr);
+ }
+
+ void RegisterMessages() override {}
+
+ int on_javascript_allowed_calls() { return on_javascript_allowed_calls_; }
+ int on_javascript_disallowed_calls() {
+ return on_javascript_disallowed_calls_;
+ }
+
+ private:
+ TestWebUI test_web_ui_;
+
+ void OnJavascriptAllowed() override { ++on_javascript_allowed_calls_; }
+ void OnJavascriptDisallowed() override { ++on_javascript_disallowed_calls_; }
+
+ int on_javascript_allowed_calls_;
+ int on_javascript_disallowed_calls_;
+};
+
+TEST(WebUIMessageHandlerTest, AllowAndDisallowJavascript) {
+ TestWebUIMessageHandler handler;
+
+ EXPECT_FALSE(handler.IsJavascriptAllowed());
+ EXPECT_EQ(0, handler.on_javascript_allowed_calls());
+ EXPECT_EQ(0, handler.on_javascript_disallowed_calls());
+
+ handler.AllowJavascriptForTesting();
+ EXPECT_TRUE(handler.IsJavascriptAllowed());
+ EXPECT_EQ(1, handler.on_javascript_allowed_calls());
+ EXPECT_EQ(0, handler.on_javascript_disallowed_calls());
+
+ // Two calls to AllowJavascript don't trigger OnJavascriptAllowed twice.
+ handler.AllowJavascriptForTesting();
+ EXPECT_TRUE(handler.IsJavascriptAllowed());
+ EXPECT_EQ(1, handler.on_javascript_allowed_calls());
+ EXPECT_EQ(0, handler.on_javascript_disallowed_calls());
+
+ handler.DisallowJavascript();
+ EXPECT_FALSE(handler.IsJavascriptAllowed());
+ EXPECT_EQ(1, handler.on_javascript_allowed_calls());
+ EXPECT_EQ(1, handler.on_javascript_disallowed_calls());
+
+ // Two calls to DisallowJavascript don't trigger OnJavascriptDisallowed twice.
+ handler.DisallowJavascript();
+ EXPECT_FALSE(handler.IsJavascriptAllowed());
+ EXPECT_EQ(1, handler.on_javascript_allowed_calls());
+ EXPECT_EQ(1, handler.on_javascript_disallowed_calls());
+}
+
} // namespace content
diff --git a/chromium/content/browser/webui/web_ui_mojo_browsertest.cc b/chromium/content/browser/webui/web_ui_mojo_browsertest.cc
index 7621bc614ce..34777344aa9 100644
--- a/chromium/content/browser/webui/web_ui_mojo_browsertest.cc
+++ b/chromium/content/browser/webui/web_ui_mojo_browsertest.cc
@@ -44,7 +44,7 @@ bool g_got_message = false;
base::FilePath GetFilePathForJSResource(const std::string& path) {
base::ThreadRestrictions::ScopedAllowIO allow_io_from_test_callbacks;
- std::string binding_path = "gen/" + path + ".js";
+ std::string binding_path = "gen/" + path;
#if defined(OS_WIN)
base::ReplaceChars(binding_path, "//", "\\", &binding_path);
#endif
@@ -60,7 +60,7 @@ bool GetResource(const std::string& id,
base::ThreadRestrictions::ScopedAllowIO allow_io_from_test_callbacks;
std::string contents;
- if (base::EndsWith(id, ".mojom", base::CompareCase::SENSITIVE)) {
+ if (base::EndsWith(id, ".mojom.js", base::CompareCase::SENSITIVE)) {
CHECK(base::ReadFileToString(GetFilePathForJSResource(id), &contents))
<< id;
} else {
@@ -120,17 +120,23 @@ class TestWebUIController : public WebUIController {
// TestWebUIController that additionally creates the ping test BrowserTarget
// implementation at the right time.
-class PingTestWebUIController : public TestWebUIController {
+class PingTestWebUIController : public TestWebUIController,
+ public WebContentsObserver {
public:
PingTestWebUIController(WebUI* web_ui, base::RunLoop* run_loop)
- : TestWebUIController(web_ui, run_loop) {}
+ : TestWebUIController(web_ui, run_loop),
+ WebContentsObserver(web_ui->GetWebContents()) {
+ registry_.AddInterface(base::Bind(&PingTestWebUIController::CreateHandler,
+ base::Unretained(this)));
+ }
~PingTestWebUIController() override {}
- // WebUIController overrides:
- void RenderFrameCreated(RenderFrameHost* render_frame_host) override {
- render_frame_host->GetInterfaceRegistry()->AddInterface(
- base::Bind(&PingTestWebUIController::CreateHandler,
- base::Unretained(this)));
+ // WebContentsObserver implementation:
+ void OnInterfaceRequestFromFrame(
+ RenderFrameHost* render_frame_host,
+ const std::string& interface_name,
+ mojo::ScopedMessagePipeHandle* interface_pipe) override {
+ registry_.TryBindInterface(interface_name, interface_pipe);
}
void CreateHandler(mojom::BrowserTargetRequest request) {
@@ -139,6 +145,8 @@ class PingTestWebUIController : public TestWebUIController {
}
private:
+ service_manager::BinderRegistry registry_;
+
DISALLOW_COPY_AND_ASSIGN(PingTestWebUIController);
};
@@ -214,7 +222,7 @@ bool IsGeneratedResourceAvailable(const std::string& resource_path) {
// it from the browser to the page and back.
IN_PROC_BROWSER_TEST_F(WebUIMojoTest, EndToEndPing) {
if (!IsGeneratedResourceAvailable(
- "content/test/data/web_ui_test_mojo_bindings.mojom"))
+ "content/test/data/web_ui_test_mojo_bindings.mojom.js"))
return;
g_got_message = false;
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 99bc1b30899..3c49b85b047 100644
--- a/chromium/content/browser/webui/web_ui_url_loader_factory.cc
+++ b/chromium/content/browser/webui/web_ui_url_loader_factory.cc
@@ -12,6 +12,7 @@
#include "base/memory/ref_counted_memory.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string_piece.h"
+#include "base/task_scheduler/post_task.h"
#include "content/browser/blob_storage/blob_internals_url_loader.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
#include "content/browser/frame_host/frame_tree_node.h"
@@ -93,9 +94,8 @@ void ReadData(scoped_refptr<ResourceResponse> headers,
void* buffer = nullptr;
uint32_t num_bytes = output_size;
- MojoResult result =
- BeginWriteDataRaw(data_pipe.producer_handle.get(), &buffer, &num_bytes,
- MOJO_WRITE_DATA_FLAG_NONE);
+ MojoResult result = data_pipe.producer_handle->BeginWriteData(
+ &buffer, &num_bytes, MOJO_WRITE_DATA_FLAG_NONE);
CHECK_EQ(result, MOJO_RESULT_OK);
CHECK_EQ(num_bytes, output_size);
@@ -105,7 +105,7 @@ void ReadData(scoped_refptr<ResourceResponse> headers,
} else {
memcpy(buffer, bytes->front(), output_size);
}
- result = EndWriteDataRaw(data_pipe.producer_handle.get(), num_bytes);
+ result = data_pipe.producer_handle->EndWriteData(num_bytes);
CHECK_EQ(result, MOJO_RESULT_OK);
client->OnStartLoadingResponseBody(std::move(data_pipe.consumer_handle));
@@ -119,16 +119,14 @@ void DataAvailable(scoped_refptr<ResourceResponse> headers,
mojom::URLLoaderClientPtrInfo client_info,
scoped_refptr<base::RefCountedMemory> bytes) {
// Since the bytes are from the memory mapped resource file, copying the
- // data can lead to disk access.
- // TODO(jam): once http://crbug.com/678155 is fixed, use task scheduler:
- // base::PostTaskWithTraits(
- // FROM_HERE,
- // {base::TaskPriority::USER_BLOCKING,
- // base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
- BrowserThread::PostTask(
- BrowserThread::FILE_USER_BLOCKING, FROM_HERE,
- base::BindOnce(ReadData, headers, replacements, gzipped, source,
- std::move(client_info), bytes));
+ // data can lead to disk access. Needs to be posted to a SequencedTaskRunner
+ // as Mojo requires a SequencedTaskRunnerHandle in scope.
+ base::CreateSequencedTaskRunnerWithTraits(
+ {base::TaskPriority::USER_BLOCKING, base::MayBlock(),
+ base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN})
+ ->PostTask(FROM_HERE,
+ base::BindOnce(ReadData, headers, replacements, gzipped,
+ source, std::move(client_info), bytes));
}
void StartURLLoader(const ResourceRequest& request,
@@ -224,7 +222,7 @@ class WebUIURLLoaderFactory : public mojom::URLLoaderFactory,
}
// mojom::URLLoaderFactory implementation:
- void CreateLoaderAndStart(mojom::URLLoaderAssociatedRequest loader,
+ void CreateLoaderAndStart(mojom::URLLoaderRequest loader,
int32_t routing_id,
int32_t request_id,
uint32_t options,
@@ -234,7 +232,7 @@ class WebUIURLLoaderFactory : public mojom::URLLoaderFactory,
traffic_annotation) override {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (request.url.host_piece() == kChromeUINetworkViewCacheHost) {
- storage_partition_->network_context()->HandleViewCacheRequest(
+ storage_partition_->GetNetworkContext()->HandleViewCacheRequest(
request.url, std::move(client));
return;
}
@@ -268,11 +266,8 @@ class WebUIURLLoaderFactory : public mojom::URLLoaderFactory,
storage_partition_->browser_context()->GetResourceContext()));
}
- void SyncLoad(int32_t routing_id,
- int32_t request_id,
- const ResourceRequest& request,
- SyncLoadCallback callback) override {
- NOTREACHED();
+ void Clone(mojom::URLLoaderFactoryRequest request) override {
+ loader_factory_bindings_.AddBinding(this, std::move(request));
}
// FrameTreeNode::Observer implementation:
diff --git a/chromium/content/browser/zygote_host/zygote_communication_linux.cc b/chromium/content/browser/zygote_host/zygote_communication_linux.cc
index 1c2192cafdc..9160275b97a 100644
--- a/chromium/content/browser/zygote_host/zygote_communication_linux.cc
+++ b/chromium/content/browser/zygote_host/zygote_communication_linux.cc
@@ -15,7 +15,7 @@
#include "base/path_service.h"
#include "base/pickle.h"
#include "base/posix/eintr_wrapper.h"
-#include "base/posix/unix_domain_socket_linux.h"
+#include "base/posix/unix_domain_socket.h"
#include "content/browser/zygote_host/zygote_host_impl_linux.h"
#include "content/common/zygote_commands_linux.h"
#include "content/public/browser/content_browser_client.h"
@@ -84,7 +84,7 @@ ssize_t ZygoteCommunication::ReadReply(void* buf, size_t buf_len) {
pid_t ZygoteCommunication::ForkRequest(
const std::vector<std::string>& argv,
- std::unique_ptr<FileDescriptorInfo> mapping,
+ std::unique_ptr<PosixFileDescriptorInfo> mapping,
const std::string& process_type) {
DCHECK(init_);
@@ -111,7 +111,7 @@ pid_t ZygoteCommunication::ForkRequest(
// First FD to send is peer_sock.
// TODO(morrita): Ideally, this should be part of the mapping so that
- // FileDescriptorInfo can manages its lifetime.
+ // PosixFileDescriptorInfo can manages its lifetime.
fds.push_back(peer_sock.get());
// The rest come from mapping.
diff --git a/chromium/content/browser/zygote_host/zygote_communication_linux.h b/chromium/content/browser/zygote_host/zygote_communication_linux.h
index 2b5340386c7..3add2ea24e8 100644
--- a/chromium/content/browser/zygote_host/zygote_communication_linux.h
+++ b/chromium/content/browser/zygote_host/zygote_communication_linux.h
@@ -17,7 +17,7 @@
#include "base/process/process_handle.h"
#include "base/synchronization/lock.h"
#include "content/common/content_export.h"
-#include "content/public/browser/file_descriptor_info.h"
+#include "content/public/browser/posix_file_descriptor_info.h"
namespace base {
class Pickle;
@@ -38,7 +38,7 @@ class CONTENT_EXPORT ZygoteCommunication {
// Tries to start a process of type indicated by process_type.
// Returns its pid on success, otherwise base::kNullProcessHandle;
pid_t ForkRequest(const std::vector<std::string>& command_line,
- std::unique_ptr<FileDescriptorInfo> mapping,
+ std::unique_ptr<PosixFileDescriptorInfo> mapping,
const std::string& process_type);
void EnsureProcessTerminated(pid_t process);
diff --git a/chromium/content/browser/zygote_host/zygote_host_impl_linux.cc b/chromium/content/browser/zygote_host/zygote_host_impl_linux.cc
index 73ad92f8c2b..5df85c7cb31 100644
--- a/chromium/content/browser/zygote_host/zygote_host_impl_linux.cc
+++ b/chromium/content/browser/zygote_host/zygote_host_impl_linux.cc
@@ -4,11 +4,13 @@
#include "content/browser/zygote_host/zygote_host_impl_linux.h"
+#include <stdlib.h>
#include <sys/socket.h>
+#include <sys/types.h>
#include "base/allocator/allocator_extension.h"
#include "base/files/file_enumerator.h"
-#include "base/posix/unix_domain_socket_linux.h"
+#include "base/posix/unix_domain_socket.h"
#include "base/process/kill.h"
#include "base/process/memory.h"
#include "base/strings/string_number_conversions.h"
@@ -74,6 +76,20 @@ void ZygoteHostImpl::Init(const base::CommandLine& command_line) {
return;
}
+ // Exit early if running as root without --no-sandbox. See crbug.com/638180.
+ // When running as root with the sandbox enabled, the browser process
+ // crashes on zygote initialization. Running as root with the sandbox
+ // is not supported, and if Chrome were able to display UI it would be showing
+ // an error message. With the zygote crashing it doesn't even get to that,
+ // so print an error message on the console.
+ uid_t uid = 0;
+ gid_t gid = 0;
+ if (!sandbox::Credentials::GetRESIds(&uid, &gid) || uid == 0) {
+ LOG(ERROR) << "Running as root without --" << switches::kNoSandbox
+ << " is not supported. See https://crbug.com/638180.";
+ exit(EXIT_FAILURE);
+ }
+
{
std::unique_ptr<sandbox::SetuidSandboxHost> setuid_sandbox_host(
sandbox::SetuidSandboxHost::Create());
@@ -139,25 +155,23 @@ pid_t ZygoteHostImpl::LaunchZygote(base::CommandLine* cmd_line,
CHECK_EQ(0, socketpair(AF_UNIX, SOCK_SEQPACKET, 0, fds));
CHECK(base::UnixDomainSocket::EnableReceiveProcessId(fds[0]));
- base::FileHandleMappingVector fds_to_map;
- fds_to_map.push_back(std::make_pair(fds[1], kZygoteSocketPairFd));
+ base::LaunchOptions options;
+ options.fds_to_remap.push_back(std::make_pair(fds[1], kZygoteSocketPairFd));
// Start up the sandbox host process and get the file descriptor for the
// renderers to talk to it.
const int sfd = RenderSandboxHostLinux::GetInstance()->GetRendererSocket();
- fds_to_map.push_back(std::make_pair(sfd, GetSandboxFD()));
+ options.fds_to_remap.push_back(std::make_pair(sfd, GetSandboxFD()));
- base::LaunchOptions options;
base::ScopedFD dummy_fd;
if (use_suid_sandbox_) {
std::unique_ptr<sandbox::SetuidSandboxHost> sandbox_host(
sandbox::SetuidSandboxHost::Create());
sandbox_host->PrependWrapper(cmd_line);
- sandbox_host->SetupLaunchOptions(&options, &fds_to_map, &dummy_fd);
+ sandbox_host->SetupLaunchOptions(&options, &dummy_fd);
sandbox_host->SetupLaunchEnvironment();
}
- options.fds_to_remap = &fds_to_map;
base::Process process =
use_namespace_sandbox_
? sandbox::NamespaceSandbox::LaunchProcess(*cmd_line, options)